source: nscp/modules/PythonScript/script_wrapper.cpp @ a14aa07

0.4.00.4.10.4.2
Last change on this file since a14aa07 was a14aa07, checked in by Michael Medin <michael@…>, 21 months ago
  • Fixed several issues in PythonScript
  • PythonScript supports loading multiple instances as well as scripts
  • Added some basic channel test to test.py script (the idea is that this will become "unit tests" eventually)
  • Property mode set to 100644
File size: 17.7 KB
Line 
1#include "stdafx.h"
2
3#include <strEx.h>
4#include "script_wrapper.hpp"
5#include "PythonScript.h"
6
7using namespace boost::python;
8
9boost::shared_ptr<script_wrapper::functions> script_wrapper::functions::instance;
10
11//extern PythonScript gPythonScript;
12
13
14void script_wrapper::log_msg(std::wstring x) {
15        NSC_LOG_ERROR_STD(utf8::cvt<std::wstring>(x));
16}
17/*
18std::string script_wrapper::get_alias() {
19        return utf8::cvt<std::string>(gPythonScript.get_alias());
20}
21*/
22
23void script_wrapper::log_exception() {
24        try {
25                PyErr_Print();
26                boost::python::object sys(boost::python::handle<>(PyImport_ImportModule("sys")));
27                boost::python::object err = sys.attr("stderr");
28                std::string err_text = boost::python::extract<std::string>(err.attr("getvalue")());
29                NSC_LOG_ERROR_STD(utf8::cvt<std::wstring>(err_text));
30                PyErr_Clear();
31        } catch (const std::exception &e) {
32                NSC_LOG_ERROR_STD(_T("Failed to parse error: ") + utf8::cvt<std::wstring>(e.what()));
33                PyErr_Clear();
34        }
35}
36
37void script_wrapper::function_wrapper::subscribe_simple_function(std::string channel, PyObject* callable) {
38        try {
39                core->registerSubmissionListener(plugin_id, utf8::cvt<std::wstring>(channel));
40                boost::python::handle<> h(boost::python::borrowed(callable));
41                //return boost::python::object o(h);
42                functions::get()->simple_handler[channel] = h;
43        } catch (const std::exception &e) {
44                NSC_LOG_ERROR_STD(_T("Failed to subscribe to channel ") + utf8::cvt<std::wstring>(channel) + _T(": ") + utf8::cvt<std::wstring>(e.what()));
45        } catch (...) {
46                NSC_LOG_ERROR_STD(_T("Failed to subscribe to channel ") + utf8::cvt<std::wstring>(channel));
47        }
48}
49void script_wrapper::function_wrapper::subscribe_function(std::string channel, PyObject* callable) {
50        try {
51                core->registerSubmissionListener(plugin_id, utf8::cvt<std::wstring>(channel));
52                boost::python::handle<> h(boost::python::borrowed(callable));
53                functions::get()->normal_handler[channel] = h;
54        } catch (const std::exception &e) {
55                NSC_LOG_ERROR_STD(_T("Failed to subscribe to channel ") + utf8::cvt<std::wstring>(channel) + _T(": ") + utf8::cvt<std::wstring>(e.what()));
56        } catch (...) {
57                NSC_LOG_ERROR_STD(_T("Failed to subscribe to channel ") + utf8::cvt<std::wstring>(channel));
58        }
59}
60
61
62void script_wrapper::function_wrapper::register_simple_function(std::string name, PyObject* callable, std::string desc) {
63        try {
64                core->registerCommand(plugin_id, utf8::cvt<std::wstring>(name), utf8::cvt<std::wstring>(desc));
65                boost::python::handle<> h(boost::python::borrowed(callable));
66                functions::get()->simple_functions[name] = h;
67        } catch (...) {
68                NSC_LOG_ERROR_STD(_T("Failed to register functions: ") + utf8::cvt<std::wstring>(name));
69        }
70}
71void script_wrapper::function_wrapper::register_function(std::string name, PyObject* callable, std::string desc) {
72        try {
73        core->registerCommand(plugin_id, utf8::cvt<std::wstring>(name), utf8::cvt<std::wstring>(desc));
74        boost::python::handle<> h(boost::python::borrowed(callable));
75        functions::get()->normal_functions[name] = h;
76        } catch (...) {
77                NSC_LOG_ERROR_STD(_T("Failed to register functions: ") + utf8::cvt<std::wstring>(name));
78        }
79}
80void script_wrapper::function_wrapper::register_simple_cmdline(std::string name, PyObject* callable) {
81        try {
82                boost::python::handle<> h(boost::python::borrowed(callable));
83                functions::get()->simple_cmdline[name] = h;
84        } catch (...) {
85                NSC_LOG_ERROR_STD(_T("Failed to register command: ") + utf8::cvt<std::wstring>(name));
86        }
87}
88void script_wrapper::function_wrapper::register_cmdline(std::string name, PyObject* callable) {
89        try {
90                boost::python::handle<> h(boost::python::borrowed(callable));
91                functions::get()->normal_cmdline[name] = h;
92        } catch (...) {
93                NSC_LOG_ERROR_STD(_T("Failed to register command: ") + utf8::cvt<std::wstring>(name));
94        }
95}
96int script_wrapper::function_wrapper::handle_query(const std::string cmd, const std::string &request, std::string &response) const {
97        try {
98                functions::function_map_type::iterator it = functions::get()->normal_functions.find(cmd);
99                if (it == functions::get()->normal_functions.end()) {
100                        NSC_LOG_ERROR_STD(_T("Failed to find python function: ") + utf8::cvt<std::wstring>(cmd));
101                        return NSCAPI::returnIgnored;
102                }
103                tuple ret = boost::python::call<tuple>(boost::python::object(it->second).ptr(), cmd, request);
104                if (ret.ptr() == Py_None) {
105                        return NSCAPI::returnUNKNOWN;
106                }
107                int ret_code = NSCAPI::returnUNKNOWN;
108                if (len(ret) > 0)
109                        ret_code = extract<int>(ret[0]);
110                if (len(ret) > 1)
111                        response = extract<std::string>(ret[1]);
112                return ret_code;
113        } catch( error_already_set e) {
114                log_exception();
115                return NSCAPI::returnUNKNOWN;
116        }
117}
118
119int script_wrapper::function_wrapper::handle_simple_query(const std::string cmd, std::list<std::wstring> arguments, std::wstring &msg, std::wstring &perf) const {
120        try {
121                functions::function_map_type::iterator it = functions::get()->simple_functions.find(cmd);
122                if (it == functions::get()->simple_functions.end()) {
123                        NSC_LOG_ERROR_STD(_T("Failed to find python function: ") + utf8::cvt<std::wstring>(cmd));
124                        return NSCAPI::returnIgnored;
125                }
126
127                boost::python::list l;
128                BOOST_FOREACH(std::wstring a, arguments) {
129                        l.append(utf8::cvt<std::string>(a));
130                }
131                tuple ret;
132                try {
133                        ret = boost::python::call<tuple>(boost::python::object(it->second).ptr(), l);
134                } catch( error_already_set e) {
135                        log_exception();
136                        msg = _T("Exception in: ") + utf8::cvt<std::wstring>(cmd);
137                        return NSCAPI::returnUNKNOWN;
138                }
139               
140                if (ret.ptr() == Py_None) {
141                        msg = _T("None");
142                        return NSCAPI::returnUNKNOWN;
143                }
144                int ret_code = NSCAPI::returnUNKNOWN;
145                if (len(ret) > 0)
146                        ret_code = extract<int>(ret[0]);
147                if (len(ret) > 1) {
148                        try {
149                                //boost::python::object o = ret[1];
150                                msg = utf8::cvt<std::wstring>(extract<std::string>(ret[1]));
151                        } catch(const error_already_set &e) {
152                                msg = _T("Failed to convert message");
153                                ret_code = NSCAPI::returnUNKNOWN;
154                        }
155                }
156                if (len(ret) > 2) {
157                        try {
158                                //boost::python::object o = ret[2];
159                                perf = utf8::cvt<std::wstring>(extract<std::string>(ret[2]));
160                        } catch(const error_already_set &e) {
161                                msg = _T("Failed to convert performance data");
162                                ret_code = NSCAPI::returnUNKNOWN;
163                        }
164                }
165                return ret_code;
166        } catch(const error_already_set &e) {
167                log_exception();
168                msg = _T("Failed to convert data for: ") + utf8::cvt<std::wstring>(cmd);
169                return NSCAPI::returnUNKNOWN;
170        } catch(const std::exception &e) {
171                msg = _T("Exception in ") + utf8::cvt<std::wstring>(cmd) + _T(": ") + utf8::cvt<std::wstring>(e.what());
172                return NSCAPI::returnUNKNOWN;
173        }
174}
175
176bool script_wrapper::function_wrapper::has_function(const std::string command) {
177        return functions::get()->normal_functions.find(command) != functions::get()->normal_functions.end();
178}
179bool script_wrapper::function_wrapper::has_simple(const std::string command) {
180        return functions::get()->simple_functions.find(command) != functions::get()->simple_functions.end();
181}
182
183int script_wrapper::function_wrapper::handle_exec(const std::string cmd, const std::string &request, std::string &response) const {
184        try {
185                functions::function_map_type::iterator it = functions::get()->normal_cmdline.find(cmd);
186                if (it == functions::get()->normal_cmdline.end()) {
187                        NSC_LOG_ERROR_STD(_T("Failed to find python function: ") + utf8::cvt<std::wstring>(cmd));
188                        return NSCAPI::returnIgnored;
189                }
190                tuple ret = boost::python::call<tuple>(boost::python::object(it->second).ptr(), cmd, request);
191                if (ret.ptr() == Py_None) {
192                        return NSCAPI::returnUNKNOWN;
193                }
194                int ret_code = NSCAPI::returnUNKNOWN;
195                if (len(ret) > 0)
196                        ret_code = extract<int>(ret[0]);
197                if (len(ret) > 1)
198                        response = extract<std::string>(ret[1]);
199                return ret_code;
200        } catch( error_already_set e) {
201                log_exception();
202                return NSCAPI::returnUNKNOWN;
203        }
204}
205
206int script_wrapper::function_wrapper::handle_simple_exec(const std::string cmd, std::list<std::wstring> arguments, std::wstring &result) const {
207        try {
208                functions::function_map_type::iterator it = functions::get()->simple_cmdline.find(cmd);
209                if (it == functions::get()->simple_cmdline.end()) {
210                        result = _T("Failed to find python function: ") + utf8::cvt<std::wstring>(cmd);
211                        NSC_LOG_ERROR_STD(result);
212                        return NSCAPI::returnIgnored;
213                }
214
215                tuple ret = boost::python::call<tuple>(boost::python::object(it->second).ptr(), convert(arguments));
216                if (ret.ptr() == Py_None) {
217                        result = _T("None");
218                        return NSCAPI::returnUNKNOWN;
219                }
220                int ret_code = NSCAPI::returnUNKNOWN;
221                if (len(ret) > 0)
222                        ret_code = extract<int>(ret[0]);
223                if (len(ret) > 1)
224                        result = utf8::cvt<std::wstring>(extract<std::string>(ret[1]));
225                return ret_code;
226        } catch( error_already_set e) {
227                log_exception();
228                result = _T("Exception in: ") + utf8::cvt<std::wstring>(cmd);
229                return NSCAPI::returnUNKNOWN;
230        }
231}
232
233
234bool script_wrapper::function_wrapper::has_message_handler(const std::string channel) {
235        return functions::get()->normal_handler.find(channel) != functions::get()->normal_handler.end();
236}
237bool script_wrapper::function_wrapper::has_simple_message_handler(const std::string channel) {
238        return functions::get()->simple_handler.find(channel) != functions::get()->simple_handler.end();
239}
240
241int script_wrapper::function_wrapper::handle_message(const std::string channel, const std::string command, std::string &message) const {
242        try {
243                functions::function_map_type::iterator it = functions::get()->normal_handler.find(channel);
244                if (it == functions::get()->normal_handler.end()) {
245                        NSC_LOG_ERROR_STD(_T("Failed to find python handler: ") + utf8::cvt<std::wstring>(channel));
246                        return NSCAPI::returnIgnored;
247                }
248                object ret = boost::python::call<object>(boost::python::object(it->second).ptr(), channel, command, message);
249                if (ret.ptr() == Py_None) {
250                        return NSCAPI::returnUNKNOWN;
251                }
252                return extract<int>(ret);
253        } catch( error_already_set e) {
254                log_exception();
255                return NSCAPI::returnUNKNOWN;
256        }
257}
258script_wrapper::status script_wrapper::nagios_return_to_py(int code) {
259        if (code == NSCAPI::returnOK)
260                return OK;
261        if (code == NSCAPI::returnWARN)
262                return WARN;
263        if (code == NSCAPI::returnCRIT)
264                return CRIT;
265        if (code == NSCAPI::returnUNKNOWN)
266                return UNKNOWN;
267        NSC_LOG_ERROR_STD(_T("Invalid return code: ") + strEx::itos(code));
268        return UNKNOWN;
269}
270int script_wrapper::py_to_nagios_return(status code) {
271        NSCAPI::nagiosReturn c = NSCAPI::returnUNKNOWN;
272        if (code == OK)
273                return NSCAPI::returnOK;
274        if (code == WARN)
275                return NSCAPI::returnWARN;
276        if (code == CRIT)
277                return NSCAPI::returnCRIT;
278        if (code == UNKNOWN)
279                return NSCAPI::returnUNKNOWN;
280        NSC_LOG_ERROR_STD(_T("Invalid return code: ") + strEx::itos(c));
281        return NSCAPI::returnUNKNOWN;
282}
283
284int script_wrapper::function_wrapper::handle_simple_message(const std::string channel, const std::string command, int code, std::wstring &msg, std::wstring &perf) const {
285        try {
286                functions::function_map_type::iterator it = functions::get()->simple_handler.find(channel);
287                if (it == functions::get()->simple_handler.end()) {
288                        NSC_LOG_ERROR_STD(_T("Failed to find python handler: ") + utf8::cvt<std::wstring>(channel));
289                        return NSCAPI::returnIgnored;
290                }
291                object ret = boost::python::call<object>(boost::python::object(it->second).ptr(), channel, command, nagios_return_to_py(code), utf8::cvt<std::string>(msg), utf8::cvt<std::string>(perf));
292                if (ret.ptr() == Py_None) {
293                        return NSCAPI::returnUNKNOWN;
294                }
295                return extract<int>(ret);
296        } catch( error_already_set e) {
297                log_exception();
298                return NSCAPI::returnUNKNOWN;
299        }
300}
301
302
303
304
305
306
307bool script_wrapper::function_wrapper::has_cmdline(const std::string command) {
308        return functions::get()->normal_cmdline.find(command) != functions::get()->normal_cmdline.end();
309}
310bool script_wrapper::function_wrapper::has_simple_cmdline(const std::string command) {
311        return functions::get()->simple_cmdline.find(command) != functions::get()->simple_cmdline.end();
312}
313
314std::wstring script_wrapper::function_wrapper::get_commands() {
315        std::wstring str;
316        BOOST_FOREACH(const functions::function_map_type::value_type& i, functions::get()->normal_functions) {
317                std::wstring tmp = utf8::cvt<std::wstring>(i.first);
318                strEx::append_list(str, tmp, _T(", "));
319        }
320        BOOST_FOREACH(const functions::function_map_type::value_type& i, functions::get()->simple_functions) {
321                std::wstring tmp = utf8::cvt<std::wstring>(i.first);
322                strEx::append_list(str, tmp, _T(", "));
323        }
324        return str;
325}
326
327
328
329std::list<std::wstring> script_wrapper::convert(list lst) {
330        std::list<std::wstring> ret;
331        for (int i = 0;i<len(lst);i++)
332                ret.push_back(utf8::cvt<std::wstring>(extract<std::string>(lst[i])));
333        return ret;
334}
335list script_wrapper::convert(std::list<std::wstring> lst) {
336         list ret;
337         BOOST_FOREACH(std::wstring s, lst) {
338                 ret.append(utf8::cvt<std::string>(s));
339         }
340        return ret;
341}
342void script_wrapper::command_wrapper::simple_submit(std::string channel, std::string command, status code, std::string message, std::string perf) {
343        NSCAPI::nagiosReturn c = NSCAPI::returnUNKNOWN;
344        if (code == OK)
345                c = NSCAPI::returnOK;
346        if (code == WARN)
347                c = NSCAPI::returnWARN;
348        if (code == CRIT)
349                c = NSCAPI::returnCRIT;
350        std::wstring wmessage = utf8::cvt<std::wstring>(message);
351        std::wstring wperf = utf8::cvt<std::wstring>(perf);
352        std::wstring wchannel = utf8::cvt<std::wstring>(channel);
353        std::wstring wcommand = utf8::cvt<std::wstring>(command);
354        core->submit_simple_message(wchannel, wcommand, c, wmessage, wperf);
355}
356void script_wrapper::command_wrapper::submit(std::string channel, std::string command, std::string request) {
357        std::wstring wchannel = utf8::cvt<std::wstring>(channel);
358        std::wstring wcommand = utf8::cvt<std::wstring>(command);
359        core->submit_message(wchannel, wcommand, request);
360}
361
362
363tuple script_wrapper::command_wrapper::simple_query(std::string command, list args) {
364        std::wstring msg, perf;
365        int ret = core->simple_query(utf8::cvt<std::wstring>(command), convert(args), msg, perf);
366        return make_tuple(nagios_return_to_py(ret),utf8::cvt<std::string>(msg), utf8::cvt<std::string>(perf));
367}
368tuple script_wrapper::command_wrapper::query(std::string command, std::string request) {
369        std::string response;
370        int ret = core->query(utf8::cvt<std::wstring>(command), request, response);
371        return make_tuple(ret,response);
372}
373
374object script_wrapper::command_wrapper::simple_exec(std::string command, list args) {
375        try {
376                std::list<std::wstring> result;
377                int ret = core->exec_simple_command(utf8::cvt<std::wstring>(command), convert(args), result);
378                return make_tuple(ret, convert(result));
379        } catch (const std::exception &e) {
380                NSC_LOG_ERROR_STD(_T("Failed to execute ") + utf8::cvt<std::wstring>(command) + _T(": ") + utf8::cvt<std::wstring>(e.what()));
381                return object();
382        } catch (...) {
383                NSC_LOG_ERROR_STD(_T("Failed to execute ") + utf8::cvt<std::wstring>(command));
384                return object();
385        }
386}
387tuple script_wrapper::command_wrapper::exec(std::string command, std::string request) {
388        std::string response;
389        int ret = core->exec_command(utf8::cvt<std::wstring>(command), request, response);
390        return make_tuple(ret, response);
391}
392
393
394std::string script_wrapper::settings_wrapper::get_string(std::string path, std::string key, std::string def) {
395        return utf8::cvt<std::string>(core->getSettingsString(utf8::cvt<std::wstring>(path), utf8::cvt<std::wstring>(key), utf8::cvt<std::wstring>(def)));
396}
397void script_wrapper::settings_wrapper::set_string(std::string path, std::string key, std::string value) {
398        core->SetSettingsString(utf8::cvt<std::wstring>(path), utf8::cvt<std::wstring>(key), utf8::cvt<std::wstring>(value));
399}
400bool script_wrapper::settings_wrapper::get_bool(std::string path, std::string key, bool def) {
401        return core->getSettingsBool(utf8::cvt<std::wstring>(path), utf8::cvt<std::wstring>(key), def);
402}
403void script_wrapper::settings_wrapper::set_bool(std::string path, std::string key, bool value) {
404        core->SetSettingsInt(utf8::cvt<std::wstring>(path), utf8::cvt<std::wstring>(key), value);
405}
406int script_wrapper::settings_wrapper::get_int(std::string path, std::string key, int def) {
407        return core->getSettingsInt(utf8::cvt<std::wstring>(path), utf8::cvt<std::wstring>(key), def);
408}
409void script_wrapper::settings_wrapper::set_int(std::string path, std::string key, int value) {
410        core->SetSettingsInt(utf8::cvt<std::wstring>(path), utf8::cvt<std::wstring>(key), value);
411}
412std::list<std::string> script_wrapper::settings_wrapper::get_section(std::string path) {
413        std::list<std::string> ret;
414        BOOST_FOREACH(std::wstring s, core->getSettingsSection(utf8::cvt<std::wstring>(path))) {
415                ret.push_back(utf8::cvt<std::string>(s));
416        }
417        return ret;
418}
419void script_wrapper::settings_wrapper::save() {
420        core->settings_save();
421}
422
423NSCAPI::settings_type script_wrapper::settings_wrapper::get_type(std::string stype) {
424        if (stype == "string" || stype == "str" || stype == "s")
425                return NSCAPI::key_string;
426        if (stype == "integer" || stype == "int" || stype == "i")
427                return NSCAPI::key_integer;
428        if (stype == "bool" || stype == "b")
429                return NSCAPI::key_bool;
430        NSC_LOG_ERROR_STD(_T("Invalid settings type"));
431        return NSCAPI::key_string;
432}
433void script_wrapper::settings_wrapper::settings_register_key(std::string path, std::string key, std::string stype, std::string title, std::string description, std::string defaultValue) {
434        NSCAPI::settings_type type = get_type(stype);
435        core->settings_register_key(utf8::cvt<std::wstring>(path), utf8::cvt<std::wstring>(key), type, utf8::cvt<std::wstring>(title), utf8::cvt<std::wstring>(description), utf8::cvt<std::wstring>(defaultValue), false);
436}
437void script_wrapper::settings_wrapper::settings_register_path(std::string path, std::string title, std::string description) {
438        core->settings_register_path(utf8::cvt<std::wstring>(path), utf8::cvt<std::wstring>(title), utf8::cvt<std::wstring>(description), false);
439}
Note: See TracBrowser for help on using the repository browser.