Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : * Copyright Contributors to the OpenSDN project 4 : */ 5 : 6 : #include "t_ruleparser.h" 7 : #include <boost/python.hpp> 8 : #include <boost/python/object.hpp> 9 : #include <boost/python/handle.hpp> 10 : 11 0 : void t_ruleaction::execute(const RuleMsg& rmsg) { 12 0 : if (actionid_ == "echoaction") { 13 0 : RuleActionEchoResult.append(" "); 14 0 : RuleActionEchoResult.append(actionid_); 15 : 16 0 : std::vector<std::string>::const_iterator iter; 17 0 : for (iter = paramlist_.begin(); iter != paramlist_.end(); iter++) { 18 0 : RuleActionEchoResult.append(" "); 19 0 : RuleActionEchoResult.append((*iter)); 20 : } 21 : } 22 : 23 0 : if (actionid_ == "echoaction.py") { 24 : using namespace boost::python; 25 0 : object main_module = import("__main__"); 26 0 : dict main_namespace = static_cast<dict>(main_module.attr("__dict__")); 27 : 28 0 : char *rpath = getenv("RULEENGPATH"); 29 0 : std::string commandstr; 30 0 : if (rpath != NULL) { 31 0 : commandstr.append(rpath); 32 0 : commandstr.append("/echoaction.py"); 33 : } else { 34 0 : commandstr.append("echoaction.py"); 35 : } 36 : 37 0 : if (access(commandstr.c_str(), R_OK)) { 38 0 : std::cout << "File error: " << commandstr << std::endl; 39 : 40 0 : RuleActionEchoResult.append(" "); 41 0 : RuleActionEchoResult.append(actionid_); 42 : 43 0 : std::vector<std::string>::const_iterator iter; 44 0 : for (iter = paramlist_.begin(); iter != paramlist_.end(); iter++) { 45 0 : RuleActionEchoResult.append(" "); 46 0 : RuleActionEchoResult.append((*iter)); 47 : } 48 : 49 0 : return; 50 : } 51 : 52 0 : boost::python::str command(commandstr); 53 0 : list param_list; 54 0 : std::vector<std::string>::const_iterator iter; 55 0 : for (iter = paramlist_.begin(); iter != paramlist_.end(); iter++) { 56 0 : param_list.append((*iter)); 57 : } 58 0 : main_namespace["paramlist"] = param_list; 59 : 60 0 : std::string cmdouts; 61 0 : object cmdout; 62 : try { 63 0 : cmdout = exec_file(command, main_namespace, main_namespace); 64 0 : } catch(error_already_set const &){ 65 0 : std::string perror_str = parse_python_exception(); 66 0 : std::cout << "Error in Python exec_file: " << perror_str << std::endl; 67 0 : } 68 : 69 : try { 70 0 : if (main_namespace.has_key("actionresult")) 71 0 : cmdouts = extract<std::string>(main_namespace["actionresult"]); 72 : else 73 0 : cmdouts = "actionresultNone"; 74 0 : } catch(error_already_set const &) { 75 0 : std::string perror_str = parse_python_exception(); 76 0 : std::cout << "Error in boost extract: " << perror_str << std::endl; 77 0 : } 78 0 : RuleActionEchoResult.append(" "); 79 0 : RuleActionEchoResult.append(cmdouts); 80 0 : } 81 0 : syslog(LOG_ERR, "%s action called\n", actionid_.c_str()); 82 : } 83 : 84 0 : std::string t_ruleaction::parse_python_exception() { 85 : namespace py = boost::python; 86 : 87 0 : PyObject *type_ptr = NULL, *value_ptr = NULL, *traceback_ptr = NULL; 88 0 : PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr); 89 0 : std::string ret("Unfetchable Python error"); 90 : 91 0 : if(type_ptr != NULL) { 92 0 : py::handle<> h_type(type_ptr); 93 0 : py::str type_pstr(h_type); 94 0 : py::extract<std::string> e_type_pstr(type_pstr); 95 0 : if(e_type_pstr.check()) 96 0 : ret = e_type_pstr(); 97 : else 98 0 : ret = "Unknown exception type"; 99 0 : } 100 : 101 0 : if(value_ptr != NULL) { 102 0 : py::handle<> h_val(value_ptr); 103 0 : py::str a(h_val); 104 0 : py::extract<std::string> returned(a); 105 0 : if(returned.check()) 106 0 : ret += ": " + returned(); 107 : else 108 0 : ret += std::string(": Unparseable Python error: "); 109 0 : } 110 : 111 0 : if(traceback_ptr != NULL){ 112 0 : py::handle<> h_tb(traceback_ptr); 113 0 : py::object tb(py::import("traceback")); 114 0 : py::object fmt_tb(tb.attr("format_tb")); 115 0 : py::object tb_list(fmt_tb(h_tb)); 116 0 : py::object tb_str(py::str("\n").join(tb_list)); 117 0 : py::extract<std::string> returned(tb_str); 118 0 : if(returned.check()) 119 0 : ret += ": " + returned(); 120 : else 121 0 : ret += std::string(": Unparseable Python traceback"); 122 0 : } 123 0 : return ret; 124 0 : } 125 :