source: nscp/modules/LUAScript/script_wrapper.hpp @ 53be5c8

0.4.10.4.2
Last change on this file since 53be5c8 was 53be5c8, checked in by Michael Medin <michael@…>, 10 months ago
  • LUAScript: Improved lua scripting module a lot
  • LUAScript: Added protocol buffer support to lua scripts
  • tests: Rewrote (halfway there) test_nrpe python script as a lua script.
  • CheckEventLog: Fixed command name when submitting real-time "no action checks"
  • Property mode set to 100644
File size: 16.3 KB
Line 
1#pragma once
2
3#include <map>
4
5#include <boost/enable_shared_from_this.hpp>
6#include <boost/shared_ptr.hpp>
7#include <boost/optional.hpp>
8
9#include "lua_wrappers.hpp"
10
11#include <scripts/functions.hpp>
12#include <nscapi/nscapi_core_helper.hpp>
13
14#ifdef HAVE_LUA_PB
15#include <Plugin.pb-lua.h>
16#endif
17namespace script_wrapper {
18
19        typedef lua_wrappers::lua_wrapper lua_wrapper;
20        typedef lua_wrappers::lua_script_instance script_instance;
21        typedef lua_wrappers::lua_instance_manager instance_manager;
22
23
24        class base_script_object : boost::noncopyable {
25        private:
26                instance_manager::script_instance_type instance;
27
28        public:
29                base_script_object(lua_State *L) {
30                        instance = instance_manager::get_script(L);
31                }
32                instance_manager::script_instance_type get_instance() {
33                        if (!instance)
34                                throw lua_wrappers::LUAException("Invalid instance");
35                        return instance;
36                }
37        };
38
39        class core_wrapper : public base_script_object {
40        public:
41                core_wrapper(lua_State *L) : base_script_object(L) {
42                        NSC_DEBUG_MSG(_T("get: "));
43                }
44
45                static const char className[];
46                static const Luna<core_wrapper>::RegType methods[];
47
48                int simple_query(lua_State *L) {
49                        lua_wrappers::lua_wrapper lua(L);
50                        try {
51                                int nargs = lua.size();
52                                if (nargs == 0)
53                                        return lua.error("nscp.execute requires at least 1 argument!");
54                                const unsigned int argLen = nargs-1;
55                                std::list<std::wstring> arguments;
56                                for (unsigned int i=argLen; i>0; i--) {
57                                        if (lua.is_table()) {
58                                                std::list<std::wstring> table = lua.pop_array();
59                                                arguments.insert(arguments.begin(), table.begin(), table.end());
60                                        } else {
61                                                arguments.push_front(lua.pop_string());
62                                        }
63                                }
64                                std::wstring command = lua.pop_string();
65                                std::wstring message;
66                                std::wstring perf;
67                                NSCAPI::nagiosReturn ret = nscapi::core_helper::simple_query(command, arguments, message, perf);
68                                lua.push_code(ret);
69                                lua.push_string(message);
70                                lua.push_string(perf);
71                                return lua.size();
72                        } catch (...) {
73                                return lua.error("Unknown exception in: simple_query");
74                        }
75                }
76                int query(lua_State *L) {
77                        lua_wrappers::lua_wrapper lua(L);
78                        try {
79                                int nargs = lua.size();
80                                if (nargs != 2)
81                                        return lua.error("nscp.query requires 2 arguments!");
82                                std::string data = utf8::cvt<std::string>(lua.pop_string());
83                                std::wstring command = lua.pop_string();
84                                std::string response;
85                                NSCAPI::nagiosReturn ret = nscapi::plugin_singleton->get_core()->query(command, data, response);
86                                lua.push_code(ret);
87                                lua.push_raw_string(response);
88                                return lua.size();
89                        } catch (...) {
90                                return lua.error("Unknown exception in: simple_query");
91                        }
92                }
93                int simple_exec(lua_State *L) {
94                        lua_wrappers::lua_wrapper lua(L);
95                        try {
96                                int nargs = lua.size();
97                                std::wstring target = lua.wstring(1);
98                                std::wstring command = lua.wstring(2);
99                                std::list<std::wstring> arguments = lua.checkarray(3);
100                                std::list<std::wstring> result;
101                                NSCAPI::nagiosReturn ret = nscapi::core_helper::exec_simple_command(target, command, arguments, result);
102                                lua.push_code(ret);
103                                lua.push_array(result);
104                                return 2;
105                        } catch (...) {
106                                return lua.error("Unknown exception in: simple_query");
107                        }
108                }
109                int exec(lua_State *L) {
110                        lua_wrappers::lua_wrapper lua(L);
111                        NSC_LOG_ERROR_STD(_T("Unsupported API called: exec"));
112                        return lua.error("Unsupported API called: exec");
113                }
114                int simple_submit(lua_State *L) {
115                        lua_wrappers::lua_wrapper lua(L);
116                        try {
117                                int nargs = lua.size();
118                                std::wstring channel = lua.wstring(1);
119                                std::wstring command = lua.wstring(2);
120                                NSCAPI::nagiosReturn code = lua.get_code(3);
121                                std::wstring message = lua.wstring(4);
122                                std::wstring perf = lua.wstring(5);
123                                std::wstring result;
124                                NSCAPI::nagiosReturn ret = nscapi::core_helper::submit_simple_message(channel, command, code, message, perf, result);
125                                lua.push_code(ret);
126                                lua.push_string(result);
127                                return 2;
128                        } catch (...) {
129                                return lua.error("Unknown exception in: simple_query");
130                        }
131                }
132                int submit(lua_State *L) {
133                        lua_wrappers::lua_wrapper lua(L);
134                        NSC_LOG_ERROR_STD(_T("Unsupported API called: submit"));
135                        return lua.error("Unsupported API called: submit");
136                }
137                int reload(lua_State *L) {
138                        lua_wrappers::lua_wrapper lua(L);
139                        if (lua.size() > 1)
140                                return lua.error("Incorrect syntax: reload([<module>]);");
141                        std::wstring module = _T("module");
142                        if (lua.size() == 1)
143                                module = lua.pop_string();
144                        get_instance()->get_core()->reload(module);
145                        return 0;
146                }
147        };
148
149        const char core_wrapper::className[] = "Core";
150        const Luna<core_wrapper>::RegType core_wrapper::methods[] = {
151                { "simple_query", &core_wrapper::simple_query },
152                { "query", &core_wrapper::query },
153                { "simple_exec", &core_wrapper::simple_exec },
154                { "exec", &core_wrapper::exec },
155                { "simple_submit", &core_wrapper::simple_submit },
156                { "submit", &core_wrapper::submit },
157                { "reload", &core_wrapper::reload },
158                { 0 }
159        };
160
161        class registry_wrapper : public base_script_object {
162        private:
163
164        public:
165
166                registry_wrapper(lua_State *L) : base_script_object(L) {}
167
168                static const char className[];
169                static const Luna<registry_wrapper>::RegType methods[];
170
171                boost::optional<int> read_registration(lua_wrapper &lua, std::wstring &command, int &funref, std::wstring &description) {
172                        std::wstring funname;
173                        if (lua.size() != 2 && lua.size() != 3)
174                                return lua.error("Invalid number of arguments: " + strEx::s::xtos(lua.size()) + " expected 2 or 3");
175                        if (lua.size() > 2 && !lua.pop_string(description))
176                                return lua.error("Invalid description");
177                        if (lua.pop_string(funname)) {
178                                lua.getglobal(funname);
179                        }
180                        if (!lua.pop_function(funref))
181                                return lua.error("Invalid function");
182                        if (!lua.pop_string(command))
183                                return lua.error("Invalid command");
184                        return boost::optional<int>();
185                }
186                int register_function(lua_State *L) {
187                        // void = (cmd, function, desc)
188                        std::wstring command, description;
189                        int funref = 0;
190                        lua_wrapper lua(L);
191                        boost::optional<int> error = read_registration(lua, command, funref, description);
192                        if (error)
193                                return *error;
194
195                        if (description.empty())
196                                description = _T("Lua script: ") + command;
197                        get_instance()->get_core()->registerCommand(get_instance()->get_plugin_id(), command, description);
198                        get_instance()->get_registry()->register_query(command, get_instance(), funref, false);
199                        return 0;
200                }
201                int register_simple_function(lua_State *L) {
202                        // void = (cmd, function, desc)
203                        std::wstring command, description;
204                        int funref = 0;
205                        lua_wrapper lua(L);
206                        boost::optional<int> error = read_registration(lua, command, funref, description);
207                        if (error)
208                                return *error;
209
210                        if (description.empty())
211                                description = _T("Lua script: ") + command;
212                        get_instance()->get_core()->registerCommand(get_instance()->get_plugin_id(), command, description);
213                        get_instance()->get_registry()->register_query(command, get_instance(), funref, true);
214                        return 0;
215                }
216                int register_cmdline(lua_State *L) {
217                        lua_wrappers::lua_wrapper lua(L);
218                        NSC_LOG_ERROR_STD(_T("Unsupported API called: exec"));
219                        return lua.error("Unsupported API called: exec");
220                }
221                int register_simple_cmdline(lua_State *L) {
222                        lua_wrapper lua(L);
223                        std::wstring name;
224                        if (lua.is_string()) {
225                                name = lua.pop_string();
226                                lua_getglobal(L, utf8::cvt<std::string>(name).c_str());
227                        }
228                        if (!lua.is_function())
229                                return lua.error("Invalid argument not a function: " + utf8::cvt<std::string>(name));
230
231                        int func_ref = luaL_ref(L, LUA_REGISTRYINDEX);
232
233                        if (func_ref == 0)
234                                return lua.error("Invalid function: " + utf8::cvt<std::string>(name));
235                        std::wstring script = lua.pop_string();
236                        get_instance()->get_registry()->register_exec(script, get_instance(), func_ref);
237                        return 0;
238                }
239                int subscription(lua_State *L) {
240                        lua_wrappers::lua_wrapper lua(L);
241                        NSC_LOG_ERROR_STD(_T("Unsupported API called: exec"));
242                        return lua.error("Unsupported API called: exec");
243                }
244                int simple_subscription(lua_State *L) {
245                        lua_wrapper lua(L);
246                        std::wstring name;
247                        if (lua.is_string()) {
248                                name = lua.pop_string();
249                                lua_getglobal(L, utf8::cvt<std::string>(name).c_str());
250                        }
251                        if (!lua.is_function())
252                                return lua.error("Invalid argument not a function: " + utf8::cvt<std::string>(name));
253
254                        int func_ref = luaL_ref(L, LUA_REGISTRYINDEX);
255
256                        if (func_ref == 0)
257                                return lua.error("Invalid function: " + utf8::cvt<std::string>(name));
258                        std::wstring channel = lua.pop_string();
259                        get_instance()->get_core()->registerSubmissionListener(get_instance()->get_plugin_id(), channel);
260                        get_instance()->get_registry()->register_subscription(channel, get_instance(), func_ref);
261                        return 0;
262                }
263        };
264
265        const char registry_wrapper::className[] = "Registry";
266        const Luna<registry_wrapper>::RegType registry_wrapper::methods[] = {
267                { "query", &registry_wrapper::register_function },
268                { "simple_query", &registry_wrapper::register_simple_function },
269                { "cmdline", &registry_wrapper::register_cmdline },
270                { "simple_cmdline", &registry_wrapper::register_simple_cmdline },
271                { "subscription", &registry_wrapper::subscription },
272                { "simple_subscription", &registry_wrapper::simple_subscription },
273                { 0 }
274        };
275
276
277
278        class settings_wrapper : public base_script_object {
279        public:
280
281                settings_wrapper(lua_State *L) : base_script_object(L) {
282                        NSC_DEBUG_MSG(_T("create"));
283                }
284
285                static const char className[];
286                static const Luna<settings_wrapper>::RegType methods[];
287
288                int get_section(lua_State *L) {
289                        lua_wrapper lua(L);
290                        std::wstring v = lua.op_wstring(1);
291                        try {
292                                lua.push_array(get_instance()->get_core()->getSettingsSection(v));
293                        } catch (...) {
294                                return lua.error("Unknown exception getting section");
295                        }
296                        return 1;
297                }
298                int get_string(lua_State *L) {
299                        lua_wrapper lua(L);
300                        std::wstring s = lua.wstring(1);
301                        std::wstring k = lua.wstring(2);
302                        std::wstring v = lua.op_wstring(3);
303                        lua.push_string(get_instance()->get_core()->getSettingsString(s, k, v));
304                        return 1;
305                }
306                int set_string(lua_State *L) {
307                        lua_wrapper lua(L);
308                        std::wstring s = lua.wstring(1);
309                        std::wstring k = lua.wstring(2);
310                        std::wstring v = lua.wstring(3);
311                        get_instance()->get_core()->SetSettingsString(s, k, v);
312                        return 0;
313                }
314                int get_bool(lua_State *L) {
315                        lua_wrapper lua(L);
316                        std::wstring s = lua.wstring(1);
317                        std::wstring k = lua.wstring(2);
318                        bool v = lua.checkbool(3);
319                        lua.push_boolean(get_instance()->get_core()->getSettingsInt(s, k, v?1:0)==1);
320                        return 1;
321                }
322                int set_bool(lua_State *L) {
323                        lua_wrapper lua(L);
324                        std::wstring s = lua.wstring(1);
325                        std::wstring k = lua.wstring(2);
326                        bool v = lua.checkbool(3);
327                        get_instance()->get_core()->SetSettingsInt(s, k, v?1:0);
328                        return 0;
329                }
330                int get_int(lua_State *L) {
331                        lua_wrapper lua(L);
332                        std::wstring s = lua.wstring(1);
333                        std::wstring k = lua.wstring(2);
334                        int v = lua.checkint(3);
335                        lua.push_int(get_instance()->get_core()->getSettingsInt(s, k, v));
336                        return 1;
337                }
338                int set_int(lua_State *L) {
339                        lua_wrapper lua(L);
340                        std::wstring s = lua.wstring(1);
341                        std::wstring k = lua.wstring(2);
342                        int v = lua.checkint(3);
343                        get_instance()->get_core()->SetSettingsInt(s, k, v);
344                        return 0;
345                }
346                int save(lua_State *L) {
347                        get_instance()->get_core()->settings_save();
348                        return 0;
349                }
350                int register_path(lua_State *L) {
351                        lua_wrapper lua(L);
352                        std::wstring path = lua.wstring(1);
353                        std::wstring title = lua.wstring(1);
354                        std::wstring description = lua.wstring(1);
355                        get_instance()->get_core()->settings_register_path(path, title, description, false);
356                        return 0;
357                }
358                NSCAPI::settings_type script_wrapper::settings_wrapper::get_type(std::string stype) {
359                        if (stype == "string" || stype == "str" || stype == "s")
360                                return NSCAPI::key_string;
361                        if (stype == "integer" || stype == "int" || stype == "i")
362                                return NSCAPI::key_integer;
363                        if (stype == "bool" || stype == "b")
364                                return NSCAPI::key_bool;
365                        NSC_LOG_ERROR_STD(_T("Invalid settings type"));
366                        return NSCAPI::key_string;
367                }
368
369                int register_key(lua_State *L) {
370                        lua_wrapper lua(L);
371                        std::wstring path = lua.wstring(1);
372                        std::wstring key = lua.wstring(1);
373                        std::string stype = lua.string(1);
374                        NSCAPI::settings_type type = get_type(stype);
375                        std::wstring title = lua.wstring(1);
376                        std::wstring description = lua.wstring(1);
377                        std::wstring defaultValue = lua.wstring(1);
378                        get_instance()->get_core()->settings_register_key(path, key, type, title, description, defaultValue, false);
379                        return 0;
380                }
381               
382        };
383
384        const char settings_wrapper::className[] = "Settings";
385        const Luna<settings_wrapper>::RegType settings_wrapper::methods[] = {
386                { "get_section", &settings_wrapper::get_section },
387                { "get_string", &settings_wrapper::get_string },
388                { "set_string", &settings_wrapper::set_string },
389                { "get_bool", &settings_wrapper::get_bool },
390                { "set_bool", &settings_wrapper::set_bool },
391                { "get_int", &settings_wrapper::get_int },
392                { "set_int", &settings_wrapper::set_int },
393                { "save", &settings_wrapper::save },
394                { "register_path", &settings_wrapper::register_path },
395                { "register_key", &settings_wrapper::register_key },
396                { 0 }
397        };
398
399        class nsclient_wrapper {
400        public:
401
402                static int execute (lua_State *L) {
403                        core_wrapper core(L);
404                        return core.simple_query(L);
405                }
406
407                static int register_command(lua_State *L) {
408                        registry_wrapper registry(L);
409                        return registry.register_simple_function(L);
410                }
411
412                static int getSetting (lua_State *L) {
413                        settings_wrapper sw(L);
414                        return sw.get_string(L);
415                }
416                static int getSection (lua_State *L) {
417                        settings_wrapper sw(L);
418                        return sw.get_section(L);
419                }
420                static int info (lua_State *L) {
421                        return log_any(L, NSCAPI::log_level::info);
422                }
423                static int error (lua_State *L) {
424                        return log_any(L, NSCAPI::log_level::error);
425                }
426                static int log_any(lua_State *L, int mode) {
427                        lua_wrapper lua(L);
428                        lua_wrapper::stack_trace trace = lua.get_stack_trace();
429                        int nargs = lua.size();
430                        std::wstring str;
431                        for (int i=0;i<nargs;i++) {
432                                str += lua.pop_string();
433                        }
434                        GET_CORE()->log(mode, utf8::cvt<std::string>(trace.first), trace.second, str);
435                        return 0;
436                }
437
438                static const luaL_Reg my_funcs[];
439
440                static void luaopen(lua_State *L) {
441                        luaL_register(L, "nscp", my_funcs);
442                        lua_pop(L, 1);
443                        Luna<core_wrapper>::Register(L);
444                        Luna<registry_wrapper>::Register(L);
445                        Luna<settings_wrapper>::Register(L);
446#ifdef HAVE_LUA_PB
447                        GET_CORE()->log(NSCAPI::log_level::error, "test", 123, "Loading lua pb");
448                        lua_protobuf_Plugin_open(L);
449#endif
450                }
451
452        };
453        const luaL_Reg nsclient_wrapper::my_funcs[] = {
454                {"execute", execute},
455                {"info", info},
456                {"print", info},
457                {"error", error},
458                {"register", register_command},
459                {"getSetting", getSetting},
460                {"getSection", getSection},
461                {NULL, NULL}
462        };
463
464        class lua_script : public script_instance, public boost::enable_shared_from_this<lua_script>  {
465                lua_script(nscapi::core_wrapper* core, const int plugin_id, boost::shared_ptr<lua_wrappers::lua_registry> registry, const std::string alias, const std::string script)
466                        : script_instance(core, plugin_id, registry, alias, script) {}
467        public:
468
469                static boost::shared_ptr<lua_script> create_instance(nscapi::core_wrapper* core, const int plugin_id, boost::shared_ptr<lua_wrappers::lua_registry> registry, const std::wstring alias, const std::wstring script) {
470                        boost::shared_ptr<lua_script> instance(new lua_script(core, plugin_id, registry, utf8::cvt<std::string>(alias), utf8::cvt<std::string>(script)));
471                        if (instance) {
472                                instance->init();
473                                instance->load();
474                        }
475                        return instance;
476                }
477                void init() {
478                        lua_wrappers::lua_instance_manager::set_script(get_lua_state(), shared_from_this());
479                }
480
481                void load() {
482                        lua_wrappers::lua_wrapper lua(get_lua_state());
483                        lua.openlibs();
484                        nsclient_wrapper::luaopen(get_lua_state());
485                        if (lua.loadfile(get_script()) != 0)
486                                throw lua_wrappers::LUAException(_T("Failed to load script: ") + get_wscript() + _T(": ") + lua.pop_string());
487                        if (lua.pcall(0, 0, 0) != 0)
488                                throw lua_wrappers::LUAException(_T("Failed to execute script: ") + get_wscript() + _T(": ") + lua.pop_string());
489                }
490                std::wstring get_wscript() const {
491                        return utf8::cvt<std::wstring>(get_script());
492                }
493                void unload() {}
494                void reload() {
495                        unload();
496                        load();
497                }
498        };
499}
Note: See TracBrowser for help on using the repository browser.