source: nscp/modules/PythonScript/PythonScript.cpp @ d7e265d

0.4.00.4.10.4.2
Last change on this file since d7e265d was d7e265d, checked in by Michael Medin <michael@…>, 21 months ago
  • Fixed some issues in the NSCPClient
  • Property mode set to 100644
File size: 12.4 KB
Line 
1/**************************************************************************
2*   Copyright (C) 2004-2007 by Michael Medin <michael@medin.name>         *
3*                                                                         *
4*   This code is part of NSClient++ - http://trac.nakednuns.org/nscp      *
5*                                                                         *
6*   This program is free software; you can redistribute it and/or modify  *
7*   it under the terms of the GNU General Public License as published by  *
8*   the Free Software Foundation; either version 2 of the License, or     *
9*   (at your option) any later version.                                   *
10*                                                                         *
11*   This program is distributed in the hope that it will be useful,       *
12*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14*   GNU General Public License for more details.                          *
15*                                                                         *
16*   You should have received a copy of the GNU General Public License     *
17*   along with this program; if not, write to the                         *
18*   Free Software Foundation, Inc.,                                       *
19*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20***************************************************************************/
21#include "stdafx.h"
22#include "PythonScript.h"
23#include <strEx.h>
24#include <time.h>
25#include <error.hpp>
26#include <file_helpers.hpp>
27
28#include <boost/python.hpp>
29
30#include <settings/client/settings_client.hpp>
31#include <nscapi/functions.hpp>
32
33#include "script_wrapper.hpp"
34
35PythonScript gPythonScript;
36
37PythonScript::PythonScript() {
38}
39PythonScript::~PythonScript() {
40}
41
42namespace sh = nscapi::settings_helper;
43
44bool PythonScript::loadModule() {
45        return false;
46}
47using namespace boost::python;
48
49
50
51BOOST_PYTHON_MODULE(NSCP)
52{
53        class_<script_wrapper::settings_wrapper, boost::shared_ptr<script_wrapper::settings_wrapper> >("Settings", no_init)
54                .def("get",&script_wrapper::settings_wrapper::create)
55                .staticmethod("get")
56                .def("create",&script_wrapper::settings_wrapper::create)
57                .staticmethod("create")
58                .def("get_section", &script_wrapper::settings_wrapper::get_section)
59                .def("get_string", &script_wrapper::settings_wrapper::get_string)
60                .def("set_string", &script_wrapper::settings_wrapper::set_string)
61                .def("get_bool", &script_wrapper::settings_wrapper::get_bool)
62                .def("set_bool", &script_wrapper::settings_wrapper::set_bool)
63                .def("get_int", &script_wrapper::settings_wrapper::get_int)
64                .def("set_int", &script_wrapper::settings_wrapper::set_int)
65                .def("save", &script_wrapper::settings_wrapper::save)
66                .def("register_path", &script_wrapper::settings_wrapper::settings_register_path)
67                .def("register_key", &script_wrapper::settings_wrapper::settings_register_key)
68                ;
69        class_<script_wrapper::function_wrapper, boost::shared_ptr<script_wrapper::function_wrapper> >("Registry", no_init)
70                .def("get",&script_wrapper::function_wrapper::create)
71                .staticmethod("get")
72                .def("create",&script_wrapper::function_wrapper::create)
73                .staticmethod("create")
74                .def("function", &script_wrapper::function_wrapper::register_function)
75                .def("simple_function", &script_wrapper::function_wrapper::register_simple_function)
76                .def("cmdline", &script_wrapper::function_wrapper::register_cmdline)
77                .def("simple_cmdline", &script_wrapper::function_wrapper::register_simple_cmdline)
78                .def("subscription", &script_wrapper::function_wrapper::subscribe_function)
79                .def("simple_subscription", &script_wrapper::function_wrapper::subscribe_simple_function)
80                ;
81        class_<script_wrapper::command_wrapper, boost::shared_ptr<script_wrapper::command_wrapper> >("Core", no_init)
82                .def("get",&script_wrapper::command_wrapper::create)
83                .staticmethod("get")
84                .def("create",&script_wrapper::command_wrapper::create)
85                .staticmethod("create")
86                .def("simple_query", &script_wrapper::command_wrapper::simple_query)
87                .def("query", &script_wrapper::command_wrapper::query)
88                .def("simple_exec", &script_wrapper::command_wrapper::simple_exec)
89                .def("exec", &script_wrapper::command_wrapper::exec)
90                .def("simple_submit", &script_wrapper::command_wrapper::simple_submit)
91                .def("submit", &script_wrapper::command_wrapper::submit)
92                ;
93
94        enum_<script_wrapper::status>("status")
95                .value("CRITICAL", script_wrapper::CRIT)
96                .value("WARNING", script_wrapper::WARN)
97                .value("UNKNOWN", script_wrapper::UNKNOWN)
98                .value("OK", script_wrapper::OK)
99                ;
100        def("log", script_wrapper::log_msg);
101        def("get_alias", script_wrapper::get_alias);
102}
103
104python_script::python_script(const script_container& script)  {
105        _exec(utf8::cvt<std::string>(script.script.string()));
106        callFunction("init", utf8::cvt<std::string>(script.alias));
107}
108python_script::~python_script(){
109        callFunction("shutdown");
110}
111void python_script::callFunction(const std::string& functionName) {
112        try     {
113                object scriptFunction = extract<object>(localDict[functionName]);
114                if( scriptFunction )
115                        scriptFunction();
116        } catch( error_already_set e) {
117                script_wrapper::log_exception();
118        }
119}
120void python_script::callFunction(const std::string& functionName, const std::string &str){
121        try     {
122                object scriptFunction = extract<object>(localDict[functionName]);
123                if(scriptFunction)
124                        scriptFunction(str);
125        } catch(error_already_set e) {
126                script_wrapper::log_exception();
127        }
128}
129void python_script::_exec(const std::string &scriptfile){
130        try     {
131                object main_module = import("__main__");
132                dict globalDict = extract<dict>(main_module.attr("__dict__"));
133                localDict = globalDict.copy();
134
135                PyRun_SimpleString("import cStringIO");
136                PyRun_SimpleString("import sys");
137                PyRun_SimpleString("sys.stderr = cStringIO.StringIO()");
138
139                object ignored = exec_file(scriptfile.c_str(), localDict, localDict);   
140        } catch( error_already_set e) {
141                script_wrapper::log_exception();
142        }
143}
144
145bool PythonScript::loadModuleEx(std::wstring alias, NSCAPI::moduleLoadMode mode) {
146        alias_ = alias;
147        NSC_DEBUG_MSG_STD(_T("LoadEx in PythonScript as ") + alias);
148        try {
149                root_ = get_core()->getBasePath();
150
151                sh::settings_registry settings(get_settings_proxy());
152                settings.set_alias(alias, _T("python"));
153
154                settings.alias().add_path_to_settings()
155                        (_T("LUA SCRIPT SECTION"), _T("Section for the PythonScripts module."))
156
157                        (_T("scripts"), sh::fun_values_path(boost::bind(&PythonScript::loadScript, this, _1, _2)),
158                        _T("LUA SCRIPTS SECTION"), _T("A list of scripts available to run from the PythonScript module."))
159                        ;
160
161                settings.register_all();
162                settings.notify();
163
164                Py_Initialize();
165                try {
166
167                        PyRun_SimpleString("import cStringIO");
168                        PyRun_SimpleString("import sys");
169                        PyRun_SimpleString("sys.stderr = cStringIO.StringIO()");
170
171                        initNSCP();
172
173                        BOOST_FOREACH(script_container &script, scripts_) {
174                                instances_.push_back(boost::shared_ptr<python_script>(new python_script(script)));
175                        }
176
177                } catch( error_already_set e) {
178                        script_wrapper::log_exception();
179                } catch (std::exception &e) {
180                        NSC_LOG_ERROR_STD(_T("Exception: Failed to load python scripts: ") + utf8::cvt<std::wstring>(e.what()));
181                }
182        } catch (...) {
183                NSC_LOG_ERROR_STD(_T("Exception caught: <UNKNOWN EXCEPTION>"));
184                return false;
185        }
186        return true;
187}
188
189boost::optional<boost::filesystem::wpath> PythonScript::find_file(std::wstring file) {
190        std::list<boost::filesystem::wpath> checks;
191        checks.push_back(file);
192        checks.push_back(root_ / _T("scripts") / _T("python") / file);
193        checks.push_back(root_ / _T("scripts") / file);
194        checks.push_back(root_ / _T("python") / file);
195        checks.push_back(root_ / file);
196        BOOST_FOREACH(boost::filesystem::wpath c, checks) {
197                NSC_DEBUG_MSG_STD(_T("Looking for: ") + c.string());
198                if (boost::filesystem::exists(c))
199                        return boost::optional<boost::filesystem::wpath>(c);
200        }
201        NSC_LOG_ERROR(_T("Script not found: ") + file);
202        return boost::optional<boost::filesystem::wpath>();
203}
204
205bool PythonScript::loadScript(std::wstring alias, std::wstring file) {
206        try {
207                if (file.empty()) {
208                        file = alias;
209                        alias = _T("");
210                }
211                boost::optional<boost::filesystem::wpath> ofile = find_file(file);
212                if (!ofile)
213                        return false;
214                script_container::push(scripts_, alias, *ofile);
215                NSC_DEBUG_MSG_STD(_T("Adding script: ") + alias + _T(" (") + ofile->string() + _T(")"));
216                return true;
217        } catch (...) {
218                NSC_LOG_ERROR_STD(_T("Could not find script: (Unknown exception) ") + file);
219        }
220        return false;
221}
222
223
224bool PythonScript::unloadModule() {
225        instances_.clear();
226        //Py_Finalize();
227        return true;
228}
229
230bool PythonScript::hasCommandHandler() {
231        return true;
232}
233bool PythonScript::hasMessageHandler() {
234        return true;
235}
236bool PythonScript::hasNotificationHandler() {
237        return true;
238}
239
240
241
242bool PythonScript::reload(std::wstring &message) {
243        /*
244        bool error = false;
245        commands_.clear();
246        for (script_list::const_iterator cit = scripts_.begin(); cit != scripts_.end() ; ++cit) {
247                try {
248                        (*cit)->reload(this);
249                } catch (script_wrapper::LUAException e) {
250                        error = true;
251                        message += _T("Exception when reloading script: ") + (*cit)->get_script() + _T(": ") + e.getMessage();
252                        NSC_LOG_ERROR_STD(_T("Exception when reloading script: ") + (*cit)->get_script() + _T(": ") + e.getMessage());
253                } catch (...) {
254                        error = true;
255                        message += _T("Unhandeled Exception when reloading script: ") + (*cit)->get_script();
256                        NSC_LOG_ERROR_STD(_T("Unhandeled Exception when reloading script: ") + (*cit)->get_script());
257                }
258        }
259        if (!error)
260                message = _T("LUA scripts Reloaded...");
261        return !error;
262        */
263        return false;
264}
265
266NSCAPI::nagiosReturn PythonScript::commandRAWLineExec(const wchar_t* char_command, const std::string &request, std::string &response) {
267        boost::shared_ptr<script_wrapper::function_wrapper> inst = script_wrapper::function_wrapper::create();
268        std::string cmd = utf8::cvt<std::string>(char_command);
269        if (inst->has_cmdline(cmd)) {
270                return inst->handle_exec(cmd, request, response);
271        }
272        if (inst->has_simple_cmdline(cmd)) {
273                nscapi::functions::decoded_simple_command_data data = nscapi::functions::parse_simple_exec_request(char_command, request);
274                std::wstring result;
275                NSCAPI::nagiosReturn ret = inst->handle_simple_exec(cmd, data.args, result);
276                nscapi::functions::create_simple_exec_response(data.command, ret, result, response);
277                return ret;
278        }
279        return NSCAPI::returnIgnored;
280}
281
282
283NSCAPI::nagiosReturn PythonScript::handleRAWCommand(const wchar_t* command, const std::string &request, std::string &response) {
284        boost::shared_ptr<script_wrapper::function_wrapper> inst = script_wrapper::function_wrapper::create();
285        std::string cmd = utf8::cvt<std::string>(command);
286        if (inst->has_function(cmd)) {
287                return inst->exec(cmd, request, response);
288        }
289        if (inst->has_simple(cmd)) {
290                nscapi::functions::decoded_simple_command_data data = nscapi::functions::parse_simple_query_request(command, request);
291                std::wstring msg, perf;
292                NSCAPI::nagiosReturn ret = inst->exec_simple(cmd, data.args, msg, perf);
293                nscapi::functions::create_simple_query_response(data.command, ret, msg, perf, response);
294                return ret;
295        }
296        NSC_LOG_ERROR_STD(_T("Could not find python commands for: ") + command + _T(" (avalible python commands are: ") + inst->get_commands() + _T(")"));
297        /*
298        if (command == _T("luareload")) {
299                return reload(message)?NSCAPI::returnOK:NSCAPI::returnCRIT;
300        }
301        */
302        return NSCAPI::returnIgnored;
303}
304
305
306NSCAPI::nagiosReturn PythonScript::handleRAWNotification(const std::wstring &channel, const std::wstring &command, NSCAPI::nagiosReturn code, std::string &request) {
307        boost::shared_ptr<script_wrapper::function_wrapper> inst = script_wrapper::function_wrapper::create();
308        std::string cmd = utf8::cvt<std::string>(command);
309        std::string chnl = utf8::cvt<std::string>(channel);
310        if (inst->has_message_handler(chnl)) {
311                return inst->handle_message(chnl, cmd, request);
312        }
313        if (inst->has_simple_message_handler(chnl)) {
314                std::wstring msg, perf;
315                nscapi::functions::parse_simple_query_response(request, msg, perf);
316                return inst->handle_simple_message(chnl, cmd, code, msg, perf);
317        }
318        return NSCAPI::returnIgnored;
319}
320
321NSC_WRAP_DLL();
322NSC_WRAPPERS_MAIN_DEF(gPythonScript);
323NSC_WRAPPERS_IGNORE_MSG_DEF();
324NSC_WRAPPERS_HANDLE_CMD_DEF(gPythonScript);
325NSC_WRAPPERS_CLI_DEF(gPythonScript);
326NSC_WRAPPERS_HANDLE_NOTIFICATION_DEF(gPythonScript);
Note: See TracBrowser for help on using the repository browser.