source: nscp/modules/PythonScript/PythonScript.cpp @ 39c73cd

0.4.00.4.10.4.2
Last change on this file since 39c73cd was 39c73cd, checked in by Michael Medin <michael@…>, 23 months ago

2011-08-13 MickeM

  • Added support for command line execution to PythonScript module
  • Readded support for specifying module on command line with --client mode
  • Fixed some issues with the NRPEClient module


2011-08-12 MickeM

  • Finnished (rough) adding back command line exec (with modern API)
  • Fixed so installer uses correct name for dll:s (now Server not Listsener)
  • Property mode set to 100644
File size: 11.5 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> >("Functions", 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("register", &script_wrapper::function_wrapper::register_function)
75                .def("register_simple", &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("subscribe", &script_wrapper::function_wrapper::subscribe_function)
79                .def("subscribe_simple", &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}
102
103python_script::python_script(const script_container& script)  {
104        _exec(utf8::cvt<std::string>(script.script.string()));
105        callFunction("init", utf8::cvt<std::string>(script.alias));
106}
107python_script::~python_script(){
108        callFunction("shutdown");
109}
110void python_script::callFunction(const std::string& functionName) {
111        try     {
112                object scriptFunction = extract<object>(localDict[functionName]);
113                if( scriptFunction )
114                        scriptFunction();
115        } catch( error_already_set e) {
116                script_wrapper::log_exception();
117        }
118}
119void python_script::callFunction(const std::string& functionName, const std::string &str){
120        try     {
121                object scriptFunction = extract<object>(localDict[functionName]);
122                if(scriptFunction)
123                        scriptFunction(str);
124        } catch(error_already_set e) {
125                script_wrapper::log_exception();
126        }
127}
128void python_script::_exec(const std::string &scriptfile){
129        try     {
130                object main_module = import("__main__");
131                dict globalDict = extract<dict>(main_module.attr("__dict__"));
132                localDict = globalDict.copy();
133
134                PyRun_SimpleString("import cStringIO");
135                PyRun_SimpleString("import sys");
136                PyRun_SimpleString("sys.stderr = cStringIO.StringIO()");
137
138                object ignored = exec_file(scriptfile.c_str(), localDict, localDict);   
139        } catch( error_already_set e) {
140                script_wrapper::log_exception();
141        }
142}
143
144bool PythonScript::loadModuleEx(std::wstring alias, NSCAPI::moduleLoadMode mode) {
145        NSC_DEBUG_MSG_STD(_T("LoadEx in PythonScript as ") + alias);
146        try {
147                root_ = get_core()->getBasePath();
148
149                sh::settings_registry settings(get_settings_proxy());
150                settings.set_alias(alias, _T("python"));
151
152                settings.alias().add_path_to_settings()
153                        (_T("LUA SCRIPT SECTION"), _T("Section for the PythonScripts module."))
154
155                        (_T("scripts"), sh::fun_values_path(boost::bind(&PythonScript::loadScript, this, _1, _2)),
156                        _T("LUA SCRIPTS SECTION"), _T("A list of scripts available to run from the PythonScript module."))
157                        ;
158
159                settings.register_all();
160                settings.notify();
161
162                Py_Initialize();
163                try {
164
165                        PyRun_SimpleString("import cStringIO");
166                        PyRun_SimpleString("import sys");
167                        PyRun_SimpleString("sys.stderr = cStringIO.StringIO()");
168
169                        initNSCP();
170
171                        BOOST_FOREACH(script_container &script, scripts_) {
172                                instances_.push_back(boost::shared_ptr<python_script>(new python_script(script)));
173                        }
174
175                } catch( error_already_set e) {
176                        script_wrapper::log_exception();
177                } catch (std::exception &e) {
178                        NSC_LOG_ERROR_STD(_T("Exception: Failed to load python scripts: ") + utf8::cvt<std::wstring>(e.what()));
179                }
180        } catch (...) {
181                NSC_LOG_ERROR_STD(_T("Exception caught: <UNKNOWN EXCEPTION>"));
182                return false;
183        }
184        return true;
185}
186
187boost::optional<boost::filesystem::wpath> PythonScript::find_file(std::wstring file) {
188        std::list<boost::filesystem::wpath> checks;
189        checks.push_back(file);
190        checks.push_back(root_ / _T("scripts") / _T("python") / file);
191        checks.push_back(root_ / _T("scripts") / file);
192        checks.push_back(root_ / _T("python") / file);
193        checks.push_back(root_ / file);
194        BOOST_FOREACH(boost::filesystem::wpath c, checks) {
195                NSC_DEBUG_MSG_STD(_T("Looking for: ") + c.string());
196                if (boost::filesystem::exists(c))
197                        return boost::optional<boost::filesystem::wpath>(c);
198        }
199        NSC_LOG_ERROR(_T("Script not found: ") + file);
200        return boost::optional<boost::filesystem::wpath>();
201}
202
203bool PythonScript::loadScript(std::wstring alias, std::wstring file) {
204        try {
205                if (file.empty()) {
206                        file = alias;
207                        alias = _T("");
208                }
209                boost::optional<boost::filesystem::wpath> ofile = find_file(file);
210                if (!ofile)
211                        return false;
212                script_container::push(scripts_, alias, *ofile);
213                NSC_DEBUG_MSG_STD(_T("Adding script: ") + alias + _T(" (") + ofile->string() + _T(")"));
214                return true;
215        } catch (...) {
216                NSC_LOG_ERROR_STD(_T("Could not find script: (Unknown exception) ") + file);
217        }
218        return false;
219}
220
221
222bool PythonScript::unloadModule() {
223        instances_.clear();
224        //Py_Finalize();
225        return true;
226}
227
228bool PythonScript::hasCommandHandler() {
229        return true;
230}
231bool PythonScript::hasMessageHandler() {
232        return false;
233}
234
235
236bool PythonScript::reload(std::wstring &message) {
237        /*
238        bool error = false;
239        commands_.clear();
240        for (script_list::const_iterator cit = scripts_.begin(); cit != scripts_.end() ; ++cit) {
241                try {
242                        (*cit)->reload(this);
243                } catch (script_wrapper::LUAException e) {
244                        error = true;
245                        message += _T("Exception when reloading script: ") + (*cit)->get_script() + _T(": ") + e.getMessage();
246                        NSC_LOG_ERROR_STD(_T("Exception when reloading script: ") + (*cit)->get_script() + _T(": ") + e.getMessage());
247                } catch (...) {
248                        error = true;
249                        message += _T("Unhandeled Exception when reloading script: ") + (*cit)->get_script();
250                        NSC_LOG_ERROR_STD(_T("Unhandeled Exception when reloading script: ") + (*cit)->get_script());
251                }
252        }
253        if (!error)
254                message = _T("LUA scripts Reloaded...");
255        return !error;
256        */
257        return false;
258}
259
260NSCAPI::nagiosReturn PythonScript::commandRAWLineExec(const wchar_t* char_command, const std::string &request, std::string &response) {
261        boost::shared_ptr<script_wrapper::function_wrapper> inst = script_wrapper::function_wrapper::create();
262        std::string cmd = utf8::cvt<std::string>(char_command);
263        if (inst->has_cmdline(cmd)) {
264                return inst->exec_cmdline(cmd, request, response);
265        }
266        if (inst->has_simple_cmdline(cmd)) {
267                nscapi::functions::decoded_simple_command_data data = nscapi::functions::process_simple_command_line_exec_request(char_command, request);
268                std::wstring result;
269                NSCAPI::nagiosReturn ret = inst->exec_simple_cmdline(cmd, data.args, result);
270                return nscapi::functions::process_simple_command_line_exec_result(data.command, ret, result, response);
271        }
272        return NSCAPI::returnIgnored;
273}
274
275
276NSCAPI::nagiosReturn PythonScript::handleRAWCommand(const wchar_t* command, const std::string &request, std::string &response) {
277        boost::shared_ptr<script_wrapper::function_wrapper> inst = script_wrapper::function_wrapper::create();
278        std::string cmd = utf8::cvt<std::string>(command);
279        if (inst->has_function(cmd)) {
280                return inst->exec(cmd, request, response);
281        }
282        if (inst->has_simple(cmd)) {
283                nscapi::functions::decoded_simple_command_data data = nscapi::functions::process_simple_command_request(command, request);
284                std::wstring msg, perf;
285                NSCAPI::nagiosReturn ret = inst->exec_simple(cmd, data.args, msg, perf);
286                return nscapi::functions::process_simple_command_result(data.command, ret, msg, perf, response);
287        }
288        NSC_LOG_ERROR_STD(_T("Could not find python commands for: ") + command + _T(" (avalible python commands are: ") + inst->get_commands() + _T(")"));
289        /*
290        if (command == _T("luareload")) {
291                return reload(message)?NSCAPI::returnOK:NSCAPI::returnCRIT;
292        }
293        */
294        return NSCAPI::returnIgnored;
295}
296
297NSC_WRAP_DLL();
298NSC_WRAPPERS_MAIN_DEF(gPythonScript);
299NSC_WRAPPERS_IGNORE_MSG_DEF();
300NSC_WRAPPERS_HANDLE_CMD_DEF(gPythonScript);
301NSC_WRAPPERS_CLI_DEF(gPythonScript);
Note: See TracBrowser for help on using the repository browser.