diff --git a/scripts/callbacks/system/shutdown.lua b/scripts/callbacks/system/shutdown.lua index e0415413ab..55c52f6d2a 100644 --- a/scripts/callbacks/system/shutdown.lua +++ b/scripts/callbacks/system/shutdown.lua @@ -17,6 +17,7 @@ require "lua_utils" -- NOTE: required by alert_utils local alert_utils = require "alert_utils" local recipients = require "recipients" local recipients_instance = recipients:create() +local user_scripts = require "user_scripts" local periodicity = 3 local now = os.time() @@ -32,4 +33,7 @@ end recipients_instance:process_notifications(now, now + 3 --[[ deadline ]], 3 --[[ periodicity ]], true) +-- Unload all user scripts +user_scripts.loadUnloadUserScripts(false --[[ unload --]]) + recovery_utils.mark_clean_shutdown() diff --git a/scripts/lua/modules/plugins_utils.lua b/scripts/lua/modules/plugins_utils.lua index 582f51fe21..47992f7238 100644 --- a/scripts/lua/modules/plugins_utils.lua +++ b/scripts/lua/modules/plugins_utils.lua @@ -234,11 +234,6 @@ end local function load_plugin_file(full_path) local res = dofile(full_path) - if res and res.onLoad then - -- Execute method onload, if available - res.onLoad() - end - return res end @@ -403,7 +398,11 @@ local function load_plugin_alert_endpoints(plugin) -- Execute the alert endpoint and call its method onLoad, if present local fname_path = os_utils.fixPath(endpoints_path .. "/" .. fname) local endpoint = load_plugin_file(fname_path) - + + if endpoint and endpoint.onLoad then + endpoint.onLoad() + end + if not file_utils.copy_file(fname, endpoints_path, RUNTIME_PATHS.alert_endpoints) then return false end @@ -620,7 +619,7 @@ function plugins_utils.loadPlugins(community_plugins_only) -- Reload user scripts with their configurations local user_scripts = require "user_scripts" - user_scripts.reloadUserScripts() + user_scripts.loadUnloadUserScripts(true --[[ load --]]) return(true) end diff --git a/scripts/lua/modules/user_scripts.lua b/scripts/lua/modules/user_scripts.lua index b837d4d8c9..a743e3ebcd 100644 --- a/scripts/lua/modules/user_scripts.lua +++ b/scripts/lua/modules/user_scripts.lua @@ -752,7 +752,9 @@ end -- @brief Reload user scripts with their existing configurations. -- Method called as part of plugins reload (during startup or when plugins are reloaded) -function user_scripts.reloadUserScripts() +-- @param is_load Boolean, indicating whether callback onLoad/onUnload should be called +-- @return nil +function user_scripts.loadUnloadUserScripts(is_load) -- Read all existing configsets. -- NOTE: A user script can have more than one configuration associated, each -- one identified with an id. For example, hosts have multiple configurations, @@ -767,12 +769,23 @@ function user_scripts.reloadUserScripts() for name, script in pairsByKeys(scripts.modules) do for confid, config in pairs(configsets) do - -- Call user script method onUpdateConfig for + -- Call user script callbacks for -- each available configuration existing for the user script - if script and script.onUpdateConfig then - script.onUpdateConfig(confid, config.config[subdir.id][script.key]) + for hook, hook_config in pairs(config.config[subdir.id][script.key]) do + -- For each configuration there are multiple hooks. + -- Some hooks can be enabled, whereas some other hooks can be disabled: + -- methods onLoad/onUnload are only called for hooks that are enabled. + if script and hook_config.enabled then + -- onLoad/onUnload methods are ONLY called for user scripts that are enabled + if is_load and script.onLoad then + -- This is a load operation + script.onLoad(hook, hook_config) + elseif not is_load and script.onUnload then + -- This is an unload operation + script.onUnload(hook, hook_config) + end + end end - end end end @@ -1035,14 +1048,32 @@ function user_scripts.updateScriptConfig(confid, script_key, subdir, new_config) local config = configsets[confid].config config[subdir] = config[subdir] or {} - config[subdir][script_key] = applied_config - -- If callback `onUpdateConfig` is implemented for the user script, - -- call it with the newly applied configuration as parameter - if script and script.onUpdateConfig then - script.onUpdateConfig(confid, applied_config) + if script then + local prev_config = config[subdir][script_key] + + -- Perform hook callbacks for config changes, or enable/disable + for hook, hook_config in pairs(prev_config) do + local hook_applied_config = applied_config[hook] + + if hook_applied_config then + if script.onDisable and hook_config.enabled and not hook_applied_config.enabled then + -- Hook previously disabled has been enabled + script.onDisable(hook, hook_applied_config) + elseif script.onEnable and not hook_config.enabled and hook_applied_config.enabled then + -- Hook previously enabled has now been disabled + script.onEnable(hook, hook_applied_config) + elseif script.onUpdateConfig and not table.compare(hook_config, applied_config[hook]) then + -- Configuration for the hook has changed + script.onUpdateConfig(hook, hook_applied_config) + end + end + end end + -- Set the new configuration + config[subdir][script_key] = applied_config + return saveConfigsets(configsets) end @@ -1069,15 +1100,21 @@ function user_scripts.toggleScript(confid, script_key, subdir, enable) return false end - for _, hook in pairs(config) do - hook.enabled = enable - end + for hook, hook_config in pairs(config) do + -- Remember the previous toggle + local prev_hook_config = hook_config.enabled + -- Save the new toggle + hook_config.enabled = enable + + if script.onDisable and prev_hook_config and not enable then + -- Hook has been enabled for the user script + script.onDisable(hook, hook_config) + elseif script.onEnable and not prev_hook_config and enable then + -- Hook has been disabled for the user script + script.onEnable(hook, hook_config) + end + - - -- If callback `onUpdateConfig` is implemented for the user script, - -- call it with the (toggled) configuration and configuration id - if script and script.onUpdateConfig then - script.onUpdateConfig(confid, config) end return saveConfigsets(configsets) diff --git a/scripts/plugins/examples/example/user_scripts/flow/example.lua b/scripts/plugins/examples/example/user_scripts/flow/example.lua index d4eea08d9e..06c10181c8 100644 --- a/scripts/plugins/examples/example/user_scripts/flow/example.lua +++ b/scripts/plugins/examples/example/user_scripts/flow/example.lua @@ -83,9 +83,41 @@ local script = { -- ################################################################# -- @brief See host/example.lua -function script.onUpdateConfig(confid, config) - print("on update:" .. script.key.. " confid: "..confid.."\n") - tprint(config) +function script.onLoad(hook, hook_config) + tprint("loading: "..hook) + -- tprint(hook_config) +end + +-- ################################################################# + +-- @brief See host/example.lua +function script.onUnload(hook, hook_config) + tprint("unloading: "..hook) + -- tprint(hook_config) +end + +-- ################################################################# + +-- @brief See host/example.lua +function script.onEnable(hook, hook_config) + tprint("[+] enabling: "..hook) + -- tprint(hook_config) +end + +-- ################################################################# + +-- @brief See host/example.lua +function script.onDisable(hook, hook_config) + tprint("[-] disabling: "..hook) + -- tprint(hook_config) +end + +-- ################################################################# + +-- @brief See host/example.lua +function script.onUpdateConfig(hook, hook_config) + tprint("[~] config change: "..hook) + -- tprint(hook_config) end -- ################################################################# diff --git a/scripts/plugins/examples/example/user_scripts/host/example.lua b/scripts/plugins/examples/example/user_scripts/host/example.lua index b8596618cc..78e08e55a8 100644 --- a/scripts/plugins/examples/example/user_scripts/host/example.lua +++ b/scripts/plugins/examples/example/user_scripts/host/example.lua @@ -71,23 +71,57 @@ local script = { -- ################################################################# --- @brief Called when the plugin containing the user script is loaded/reloaded +-- @brief Called, for every enabled hook, upon ntopng startup or upon plugins reload at runtime +-- @param hook The name of the enabled hook (e.g., min, hour) +-- @param hook_config A Lua table with the hook configuration -- @return nil -function script.onLoad() +function script.onLoad(hook, hook_config) + tprint("loading: "..hook) + -- tprint(hook_config) end -- ################################################################# --- @brief Called when the plugin containing the user script is loaded/reloaded --- or when the user script configuration changes (e.g., is on/off toggled or --- configuration parameters are changed). --- When the plugin is loaded/reloaded, this method is called with all the --- available existing configurations. --- @param confid An integer configuration id --- @param config A lua table with the configuration parameters for `confid` -function script.onUpdateConfig(confid, config) - print("on update:" .. script.key.. " confid: "..confid.."\n") - tprint(config) +-- @brief Called, for every enabled hook, upon ntopng termination +-- @param hook The name of the enabled hook (e.g., min, hour) +-- @param hook_config A Lua table with the hook configuration +-- @return nil +function script.onUnload(hook, hook_config) + tprint("unloading: "..hook) + -- tprint(hook_config) +end + +-- ################################################################# + +-- @brief Called when a user script hook is enabled +-- @param hook The name of the enabled hook (e.g., min, hour) +-- @param hook_config A Lua table with the hook configuration for the enabled hook +-- @return nil +function script.onEnable(hook, hook_config) + tprint("[+] enabling: "..hook) + -- tprint(hook_config) +end + +-- ################################################################# + +-- @brief Called when a user script hook is disabled +-- @param hook The name of the disabled hook (e.g., min, hour) +-- @param hook_config A Lua table with the hook configuration for the disabled hook +-- @return nil +function script.onDisable(hook, hook_config) + tprint("[-] disabling: "..hook) + -- tprint(hook_config) +end + +-- ################################################################# + +-- @brief Called when the configuration for an enabled user script hook has changed +-- @param hook The name of the hook (e.g., min, hour) for which the configuration has changed +-- @param hook_config A Lua table with the new (changed) configuration +-- @return nil +function script.onUpdateConfig(hook, hook_config) + tprint("[~] config change: "..hook) + -- tprint(hook_config) end -- #################################################################