mirror of
https://github.com/ntop/ntopng.git
synced 2026-05-03 01:10:10 +00:00
Use new user scripts config and gui
The user scripts configuration can now be configured from the "User Scripts" entry under the cog icon. It allows the creation of multiple configuration presets to be applied to hosts, networks and interfaces.
This commit is contained in:
parent
538ebc741a
commit
d037f9a9a4
18 changed files with 533 additions and 542 deletions
272
attic/scripts/lua/modules/alert_utils.lua
Normal file
272
attic/scripts/lua/modules/alert_utils.lua
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
function drawAlertSourceSettings(entity_type, alert_source, delete_button_msg, delete_confirm_msg, page_name, page_params, alt_name, show_entity, options)
|
||||
options = options or {}
|
||||
local tab = _GET["tab"] or "min"
|
||||
local ts_utils = require("ts_utils")
|
||||
local ifid = interface.getId()
|
||||
local entity_value = alert_source
|
||||
local subdir = entity_type
|
||||
|
||||
if interface.isPcapDumpInterface() then
|
||||
if entity_type == "interface" then
|
||||
tab = "flows"
|
||||
else
|
||||
return
|
||||
end
|
||||
else
|
||||
local function printTab(tab, content, sel_tab)
|
||||
if(tab == sel_tab) then print("\t<li class='nav-item active show'>") else print("\t<li class='nav-item'>") end
|
||||
print("<a class='nav-link' href=\""..ntop.getHttpPrefix().."/lua/"..page_name.."?page=callbacks&tab="..tab)
|
||||
for param, value in pairs(page_params) do
|
||||
print("&"..param.."="..value)
|
||||
end
|
||||
print("\">"..content.."</a></li>\n")
|
||||
end
|
||||
|
||||
print('<ul class="nav nav-tabs">')
|
||||
|
||||
for k, granularity in pairsByField(alert_consts.alerts_granularities, "granularity_id", asc) do
|
||||
local l = i18n(granularity.i18n_title)
|
||||
local resolution = granularity.granularity_seconds
|
||||
|
||||
if (not options.remote_host) or resolution <= 60 then
|
||||
--~ l = '<i class="fas fa-cog" aria-hidden="true"></i> '..l
|
||||
printTab(k, l, tab)
|
||||
end
|
||||
end
|
||||
|
||||
if(entity_type == "interface") then
|
||||
local l = i18n("flows")
|
||||
printTab("flows", l, tab)
|
||||
end
|
||||
|
||||
if tab ~= "flows" then
|
||||
local granularity_label = alertEngineLabel(alertEngine(tab))
|
||||
|
||||
print(
|
||||
template.gen("modal_confirm_dialog.html", {
|
||||
dialog={
|
||||
id = "deleteAlertSourceSettings",
|
||||
action = "deleteAlertSourceSettings()",
|
||||
title = i18n("show_alerts.delete_alerts_configuration"),
|
||||
message = i18n(delete_confirm_msg, {granularity=granularity_label}) .. " <span style='white-space: nowrap;'>" .. ternary(alt_name ~= nil, alt_name, alert_source).."</span>?",
|
||||
confirm = i18n("delete")
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
print(
|
||||
template.gen("modal_confirm_dialog.html", {
|
||||
dialog={
|
||||
id = "deleteGlobalAlertConfig",
|
||||
action = "deleteGlobalAlertConfig()",
|
||||
title = i18n("show_alerts.delete_alerts_configuration"),
|
||||
message = i18n("show_alerts.delete_config_message", {conf = entity_type, granularity=granularity_label}).."?",
|
||||
confirm = i18n("delete")
|
||||
}
|
||||
})
|
||||
)
|
||||
end
|
||||
print('</ul>')
|
||||
end -- !isPcapDumpInterface
|
||||
|
||||
if((tab == "flows") and (entity_type == "interface")) then
|
||||
local flow_callbacks_utils = require "flow_callbacks_utils"
|
||||
flow_callbacks_utils.print_callbacks_config()
|
||||
else
|
||||
local available_modules = user_scripts.load(interface.getId(), user_scripts.script_types.traffic_element, entity_type)
|
||||
local no_modules_available = table.len(available_modules.modules) == 0
|
||||
|
||||
if((_POST["to_delete"] ~= nil) and (_POST["SaveAlerts"] == nil)) then
|
||||
if _POST["to_delete"] == "local" then
|
||||
user_scripts.deleteSpecificConfiguration(subdir, available_modules, tab, entity_value)
|
||||
else
|
||||
user_scripts.deleteGlobalConfiguration(subdir, available_modules, tab, options.remote_host)
|
||||
end
|
||||
elseif(not table.empty(_POST)) then
|
||||
user_scripts.handlePOST(subdir, available_modules, tab, entity_value, options.remote_host)
|
||||
end
|
||||
|
||||
local label
|
||||
|
||||
if entity_type == "host" then
|
||||
if options.remote_host then
|
||||
label = i18n("remote_hosts")
|
||||
else
|
||||
label = i18n("alerts_thresholds_config.active_local_hosts")
|
||||
end
|
||||
else
|
||||
label = firstToUpper(entity_type) .. "s"
|
||||
end
|
||||
|
||||
print [[
|
||||
</ul>
|
||||
<form method="post">
|
||||
<br>
|
||||
<table id="user" class="table table-bordered table-striped" style="clear: both"> <tbody>
|
||||
<tr><th width"40%">]] print(i18n("alerts_thresholds_config.threshold_type")) print[[</th>]]
|
||||
if(tab == "min") then
|
||||
print[[<th class="text-center" width=5%>]] print(i18n("chart")) print[[</th>]]
|
||||
end
|
||||
print[[<th width=20%>]] print(i18n("alerts_thresholds_config.thresholds_single_source", {source=firstToUpper(entity_type),alt_name=ternary(alt_name ~= nil, alt_name, alert_source)})) print[[</th><th width=20%>]] print(i18n("alerts_thresholds_config.common_thresholds_local_sources", {source=label}))
|
||||
print[[</th><th style="text-align: center;">]] print(i18n("flow_callbacks.callback_latest_run")) print[[</th></tr>]]
|
||||
print('<input id="csrf" name="csrf" type="hidden" value="'..ntop.getRandomCSRFValue()..'" />\n')
|
||||
|
||||
if no_modules_available then
|
||||
if areAlertsEnabled() then
|
||||
print[[<tr><td colspan=5>]] print(i18n("flow_callbacks.no_callbacks_available")) print[[.</td></tr>]]
|
||||
else
|
||||
print[[<tr><td colspan=5>]] print(i18n("flow_callbacks.no_callbacks_available_disabled_alerts", {url = ntop.getHttpPrefix().."/lua/admin/prefs.lua?tab=alerts"})) print[[.</td></tr>]]
|
||||
end
|
||||
else
|
||||
local benchmarks = user_scripts.getLastBenchmark(ifid, entity_type)
|
||||
|
||||
for mod_k, user_script in pairsByKeys(available_modules.modules, asc) do
|
||||
local key = user_script.key
|
||||
local gui_conf = user_script.gui
|
||||
local show_input = true
|
||||
|
||||
if user_script.granularity then
|
||||
-- check if the check is performed and thus has to
|
||||
-- be configured at this granularity
|
||||
show_input = false
|
||||
|
||||
for _, gran in pairs(user_script.granularity) do
|
||||
if gran == tab then
|
||||
show_input = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if(user_script.local_only and options.remote_host) then
|
||||
show_input = false
|
||||
end
|
||||
|
||||
if not gui_conf or not show_input then
|
||||
goto next_module
|
||||
end
|
||||
|
||||
local url = ''
|
||||
|
||||
if(user_script.plugin.edition == "community") then
|
||||
local path = string.sub(user_script.source_path, string.len(ntop.getDirs().scriptdir)+1)
|
||||
url = '<A HREF="/lua/code_viewer.lua?lua_script_path='..path..'"><i class="fas fa-lg fa-binoculars"></i></A>'
|
||||
end
|
||||
|
||||
print("<tr><td><b>".. (i18n(gui_conf.i18n_title) or gui_conf.i18n_title) .. " " .. url .."</b><br>")
|
||||
print("<small>".. (i18n(gui_conf.i18n_description) or gui_conf.i18n_description) .."</small>\n")
|
||||
|
||||
if(tab == "min") then
|
||||
print("<td class='text-center'>")
|
||||
if ts_utils.exists("elem_user_script:duration", {ifid=ifid, user_script=mod_k, subdir=entity_type}) then
|
||||
print('<a href="'.. ntop.getHttpPrefix() ..'/lua/user_script_details.lua?ifid='..ifid..'&user_script='..
|
||||
mod_k..'&subdir='..entity_type..'"><i class="fas fa-chart-area fa-lg"></i></a>')
|
||||
end
|
||||
end
|
||||
|
||||
for _, prefix in pairs({"", "global_"}) do
|
||||
if user_script.gui.input_builder then
|
||||
local k = prefix..key
|
||||
local is_global = (prefix == "global_")
|
||||
local conf
|
||||
|
||||
print("</td><td>")
|
||||
|
||||
if is_global then
|
||||
conf = user_scripts.getGlobalConfiguration(user_script, tab, options.remote_host)
|
||||
else
|
||||
conf = user_scripts.getConfiguration(user_script, tab, entity_value, options.remote_host)
|
||||
end
|
||||
|
||||
if(conf ~= nil) then
|
||||
-- TODO remove after implementing the new gui
|
||||
local value = ternary(user_script.gui.post_handler == user_scripts.checkbox_post_handler, conf.enabled, conf.script_conf)
|
||||
|
||||
print(user_script.gui.input_builder(user_script.gui or {}, k, value))
|
||||
end
|
||||
end
|
||||
end
|
||||
print("</td><td align='center'>\n")
|
||||
|
||||
local script_benchmark = benchmarks[mod_k]
|
||||
|
||||
if script_benchmark and (script_benchmark[tab] or script_benchmark["all"]) then
|
||||
local hook = ternary(script_benchmark[tab], tab, "all")
|
||||
|
||||
if script_benchmark[hook]["tot_elapsed"] then
|
||||
if script_benchmark[hook]["tot_num_calls"] > 1 then
|
||||
print(i18n("flow_callbacks.callback_function_duration_fmt_long",
|
||||
{num_calls = format_utils.formatValue(script_benchmark[hook]["tot_num_calls"]),
|
||||
time = format_utils.secondsToTime(script_benchmark[hook]["tot_elapsed"]),
|
||||
speed = format_utils.formatValue(round(script_benchmark[hook]["avg_speed"], 0))}))
|
||||
else
|
||||
print(i18n("flow_callbacks.callback_function_duration_fmt_short",
|
||||
{time = format_utils.secondsToTime(script_benchmark[hook]["tot_elapsed"])}))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
print("</td></tr>\n")
|
||||
::next_module::
|
||||
end
|
||||
end
|
||||
|
||||
print [[</tbody> </table>]]
|
||||
|
||||
if not no_modules_available then
|
||||
print[[
|
||||
<input type="hidden" name="SaveAlerts" value="">
|
||||
|
||||
<button class="btn btn-primary" style="float:right; margin-right:1em;" disabled="disabled" type="submit">]] print(i18n("save_configuration")) print[[</button>
|
||||
</form>
|
||||
|
||||
<button type="button" class="btn btn-secondary" data-toggle="modal" data-target="#deleteGlobalAlertConfig" style="float:right; margin-right:1em;"> ]] print(i18n("show_alerts.delete_config_btn",{conf=firstToUpper(entity_type)})) print[[</button>
|
||||
<button type="button" class="btn btn-secondary" data-toggle="modal" data-target="#deleteAlertSourceSettings" style="float:right; margin-right:1em;"> ]] print(delete_button_msg) print[[</button>
|
||||
]]
|
||||
end
|
||||
|
||||
print("<div style='margin-top:4em;'><b>" .. i18n("alerts_thresholds_config.notes") .. ":</b><ul>")
|
||||
|
||||
print("<li>" .. i18n("alerts_thresholds_config.note_control_threshold_checks_periods") .. "</li>")
|
||||
print("<li>" .. i18n("alerts_thresholds_config.note_thresholds_expressed_as_delta") .. "</li>")
|
||||
print("<li>" .. i18n("alerts_thresholds_config.note_consecutive_checks") .. "</li>")
|
||||
|
||||
if (entity_type == "host") then
|
||||
print("<li>" .. i18n("alerts_thresholds_config.note_checks_on_active_hosts") .. "</li>")
|
||||
end
|
||||
|
||||
print("<li>" .. i18n("alerts_thresholds_config.note_create_custom_scripts", {url = "https://github.com/ntop/ntopng/blob/dev/doc/README.alerts.md"}) .. "</li>")
|
||||
print("<li>" .. i18n("flow_callbacks.note_add_custom_scripts", {url = ntop.getHttpPrefix().."/lua/directories.lua", product=ntop.getInfo()["product"]}) .. "</li>")
|
||||
print("<li>" .. i18n("flow_callbacks.note_scripts_list", {url = ntop.getHttpPrefix().."/lua/user_scripts_overview.lua", product=ntop.getInfo()["product"]}) .. "</li>")
|
||||
|
||||
print("</ul></div>")
|
||||
|
||||
print[[
|
||||
<script>
|
||||
function deleteAlertSourceSettings() {
|
||||
var params = {};
|
||||
|
||||
params.to_delete = "local";
|
||||
params.csrf = "]] print(ntop.getRandomCSRFValue()) print[[";
|
||||
|
||||
var form = paramsToForm('<form method="post"></form>', params);
|
||||
form.appendTo('body').submit();
|
||||
}
|
||||
|
||||
function deleteGlobalAlertConfig() {
|
||||
var params = {};
|
||||
|
||||
params.to_delete = "global";
|
||||
params.csrf = "]] print(ntop.getRandomCSRFValue()) print[[";
|
||||
|
||||
var form = paramsToForm('<form method="post"></form>', params);
|
||||
form.appendTo('body').submit();
|
||||
}
|
||||
|
||||
aysHandleForm("form", {
|
||||
handle_tabs: true,
|
||||
});
|
||||
</script>
|
||||
]]
|
||||
end
|
||||
end
|
||||
239
attic/scripts/lua/modules/flow_callbacks_utils.lua
Normal file
239
attic/scripts/lua/modules/flow_callbacks_utils.lua
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
--
|
||||
-- (C) 2014-19 - ntop.org
|
||||
--
|
||||
|
||||
local dirs = ntop.getDirs()
|
||||
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
|
||||
local alerts_api = require "alerts_api"
|
||||
local format_utils = require "format_utils"
|
||||
local user_scripts = require "user_scripts"
|
||||
local ts_utils = require("ts_utils")
|
||||
|
||||
local flow_callbacks_utils = {}
|
||||
|
||||
local ifid = interface.getId()
|
||||
|
||||
-- ##############################################
|
||||
|
||||
local function printStatsCols(total_stats, cur_elapsed, cur_num_calls, cur_avg_speed)
|
||||
print("<td align='center'>".. format_utils.secondsToTime(cur_elapsed) .." (" .. string.format("%.1f", cur_elapsed * 100 / total_stats.tot_elapsed) .. "%)</td>")
|
||||
print("<td align='center'>".. format_utils.formatValue(cur_num_calls) .." (" .. string.format("%.1f", cur_num_calls * 100 / total_stats.tot_num_calls) .. "%)</td>")
|
||||
print("<td align='center'>".. format_utils.formatValue(round(cur_avg_speed, 0)) .."</td>")
|
||||
end
|
||||
|
||||
-- ##############################################
|
||||
|
||||
local function print_callbacks_config_table(descr, expert_view)
|
||||
print[[<table id="callbacks_config_table" class="table table-bordered table-striped">]]
|
||||
print[[<tr>]]
|
||||
print[[<th width=40%>]] print(i18n("flow_callbacks.callback")) print[[</th>]]
|
||||
print[[<th style="text-align: center;" width="5%">]] print(i18n("chart")) print[[</th>]]
|
||||
print[[<th width="20%">]] print(i18n("flow_callbacks.callback_config")) print[[</th>]]
|
||||
if(expert_view) then
|
||||
print[[<th>]] print(i18n("flow_callbacks.callback_function")) print[[</th>]]
|
||||
end
|
||||
print[[<th style="text-align: center;">]] print(i18n("flow_callbacks.last_duration")) print[[</th>]]
|
||||
print[[<th style="text-align: center;">]] print(i18n("flow_callbacks.last_num_calls")) print[[</th>]]
|
||||
print[[<th style="text-align: center;">]] print(i18n("flow_callbacks.last_calls_per_sec")) print[[</th>]]
|
||||
print[[</tr>]]
|
||||
|
||||
print('<input id="csrf" name="csrf" type="hidden" value="'..ntop.getRandomCSRFValue()..'" />\n')
|
||||
|
||||
local total_stats = {
|
||||
tot_elapsed = 0,
|
||||
tot_num_calls = 0,
|
||||
}
|
||||
|
||||
local benchmarks = user_scripts.getLastBenchmark(ifid, "flow")
|
||||
|
||||
-- A user module link is currently required for the total
|
||||
local total_user_module = nil
|
||||
|
||||
for mod_k, user_script in pairsByKeys(descr.modules, asc) do
|
||||
local hooks_benchmarks = benchmarks[mod_k] or {}
|
||||
|
||||
-- Calculate the total stats
|
||||
for _, mod_benchmark in pairs(hooks_benchmarks) do
|
||||
total_stats.tot_elapsed = total_stats.tot_elapsed + mod_benchmark["tot_elapsed"]
|
||||
total_stats.tot_num_calls = total_stats.tot_num_calls + mod_benchmark["tot_num_calls"]
|
||||
end
|
||||
end
|
||||
|
||||
for mod_k, user_script in pairsByKeys(descr.modules, asc) do
|
||||
local hooks_benchmarks = benchmarks[mod_k] or {}
|
||||
local num_hooks = table.len(hooks_benchmarks)
|
||||
local title
|
||||
local description
|
||||
local rowspan = ""
|
||||
|
||||
if(not total_user_module) then
|
||||
total_user_module = mod_k
|
||||
end
|
||||
|
||||
if(user_script.gui) then
|
||||
title = i18n(user_script.gui.i18n_title) or user_script.gui.i18n_title
|
||||
description = i18n(user_script.gui.i18n_description) or user_script.gui.i18n_description
|
||||
else
|
||||
title = user_script.key
|
||||
description = ""
|
||||
end
|
||||
|
||||
if(expert_view and (num_hooks > 0)) then
|
||||
rowspan = string.format(' rowspan="%d"', num_hooks)
|
||||
end
|
||||
|
||||
local url = ''
|
||||
|
||||
if(user_script.edition == "community") then
|
||||
local path = string.sub(user_script.source_path, string.len(ntop.getDirs().scriptdir)+1)
|
||||
url = '<A HREF="/lua/code_viewer.lua?lua_script_path='.. path ..'"><i class="fas fa-lg fa-binoculars"></i></A>'
|
||||
end
|
||||
print("<tr><td ".. rowspan .."><b>".. title .." "..url.."</b><br>")
|
||||
print("<small>"..description.."</small></td>")
|
||||
|
||||
print("<td ".. rowspan .." class='text-center'>")
|
||||
|
||||
if(ts_utils.exists("flow_user_script:duration", {ifid=ifid, user_script=mod_k, subdir="flow"})) then
|
||||
print('<a href="'.. ntop.getHttpPrefix() ..'/lua/user_script_details.lua?ifid='..ifid..'&user_script='..mod_k..'&subdir=flow"><i class="fas fa-chart-area fa-lg" data-original-title="" title=""></i></a>')
|
||||
end
|
||||
|
||||
print("</td>")
|
||||
|
||||
print("<td ".. rowspan ..">")
|
||||
if(user_script.gui and user_script.gui.input_builder) then
|
||||
local conf = user_scripts.getConfiguration(user_script)
|
||||
local k = user_script.key
|
||||
|
||||
-- TODO remove after implementing the new gui
|
||||
local value = ternary(user_script.gui.post_handler == user_scripts.checkbox_post_handler, conf.enabled, conf.script_conf)
|
||||
|
||||
print(user_script.gui.input_builder(user_script.gui or {}, k, value))
|
||||
else
|
||||
print('<a href="'.. ntop.getHttpPrefix() ..'/lua/admin/prefs.lua?tab=alerts"><i class="fas fa-flask fa-lg"></i></a>')
|
||||
end
|
||||
print("</td>")
|
||||
|
||||
if(expert_view) then
|
||||
if(num_hooks > 0) then
|
||||
local ctr = 0
|
||||
|
||||
for mod_fn, mod_benchmark in pairsByKeys(hooks_benchmarks, asc) do
|
||||
print("<td>".. mod_fn .."</td>")
|
||||
|
||||
local avg_speed = (mod_benchmark["tot_num_calls"] / mod_benchmark["tot_elapsed"])
|
||||
|
||||
printStatsCols(total_stats, mod_benchmark["tot_elapsed"], mod_benchmark["tot_num_calls"], avg_speed)
|
||||
ctr = ctr + 1
|
||||
|
||||
if(ctr ~= num_hooks) then
|
||||
print("</tr><tr>")
|
||||
end
|
||||
end
|
||||
else
|
||||
print("<td></td><td></td><td></td><td></td>")
|
||||
end
|
||||
else
|
||||
if(num_hooks > 0) then
|
||||
-- Accumulate the stats for each hook
|
||||
local total_duration = 0
|
||||
local num_calls = 0
|
||||
|
||||
for mod_fn, mod_benchmark in pairsByKeys(hooks_benchmarks, asc) do
|
||||
total_duration = total_duration + mod_benchmark["tot_elapsed"]
|
||||
num_calls = num_calls + mod_benchmark["tot_num_calls"]
|
||||
end
|
||||
|
||||
local avg_speed = (num_calls / total_duration)
|
||||
|
||||
printStatsCols(total_stats, total_duration, num_calls, avg_speed)
|
||||
else
|
||||
print("<td></td><td></td><td></td>")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local avg_speed = (total_stats.tot_num_calls / total_stats.tot_elapsed)
|
||||
|
||||
-- Print total stats
|
||||
print("</tr><tr><td><b>" .. i18n("total") .. "</b></td><td class='text-center'>")
|
||||
if(ts_utils.exists("flow_user_script:total_stats", {ifid=ifid, subdir="flow"})) then
|
||||
print('<a href="'.. ntop.getHttpPrefix() ..'/lua/user_script_details.lua?ifid='..ifid..'&subdir=flow&user_script='.. total_user_module ..'&ts_schema=custom:flow_user_script:total_stats"><i class="fas fa-chart-area fa-lg"></i></a>')
|
||||
end
|
||||
print("<td>")
|
||||
if(expert_view) then
|
||||
print("<td></td>")
|
||||
end
|
||||
|
||||
print("</tr>")
|
||||
print[[</table>]]
|
||||
end
|
||||
|
||||
-- #################################
|
||||
|
||||
function flow_callbacks_utils.print_callbacks_config()
|
||||
local show_advanced_prefs = false
|
||||
|
||||
if(_GET["show_advanced_prefs"] == "1") then
|
||||
show_advanced_prefs = true
|
||||
end
|
||||
|
||||
local ifid = interface.getId()
|
||||
local descr = user_scripts.load(ifid, user_scripts.script_types.flow, "flow")
|
||||
|
||||
print [[
|
||||
|
||||
<br>]]
|
||||
|
||||
if table.len(_POST) > 0 then
|
||||
user_scripts.handlePOST("flow", descr)
|
||||
end
|
||||
|
||||
print[[<form id="flow-callbacks-config" class="form-inline" method="post">]]
|
||||
print_callbacks_config_table(descr, show_advanced_prefs)
|
||||
print[[<input type=hidden name="show_advanced_prefs" value="]]if show_advanced_prefs then print("true") else print("false") end print[["/>]]
|
||||
print[[<button class="btn btn-primary" style="float:right; margin-right:1em; margin-left:auto" type="submit">]] print(i18n("save_configuration")) print[[</button>]]
|
||||
print[[</form>]]
|
||||
print[[
|
||||
|
||||
<form data-ays-ignore="true">
|
||||
<input type=hidden name="page" value="callbacks" />
|
||||
<input type=hidden name="tab" value="flows" />
|
||||
<input type=hidden name="ifid" value="]] print(string.format("%d", ifid)) print[[" />
|
||||
<input type=hidden name="show_advanced_prefs" value="]]if show_advanced_prefs then print("0") else print("1") end print[["/>
|
||||
|
||||
<div class="btn-group btn-toggle">
|
||||
]]
|
||||
|
||||
local cls_on = "btn btn-sm"
|
||||
local cls_off = cls_on
|
||||
|
||||
if show_advanced_prefs then
|
||||
cls_on = cls_on..' btn-primary active'
|
||||
cls_off = cls_off..' btn-secondary'
|
||||
else
|
||||
cls_on = cls_on..' btn-secondary'
|
||||
cls_off = cls_off..' btn-primary active'
|
||||
end
|
||||
|
||||
print('<button type="submit" class="'..cls_on..'">'..i18n("prefs.expert_view")..'</button>')
|
||||
print('<button type="submit" class="'..cls_off..'">'..i18n("prefs.simple_view")..'</button>')
|
||||
|
||||
print[[
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
]]
|
||||
|
||||
print("<div style='margin-top:4em;'><b>" .. i18n("flow_callbacks.notes") .. ":</b><ul>")
|
||||
|
||||
print("<li>" .. i18n("flow_callbacks.note_flow_lifecycle") .. "</li>")
|
||||
|
||||
print("<li>" .. i18n("flow_callbacks.note_create_custom_scripts", {url = "https://github.com/ntop/ntopng/blob/dev/doc/README.developers.flow_lua_callbacks.md"}) .. "</li>")
|
||||
print("<li>" .. i18n("flow_callbacks.note_add_custom_scripts", {url = ntop.getHttpPrefix().."/lua/directories.lua", product=ntop.getInfo()["product"]}) .. "</li>")
|
||||
|
||||
print("</ul></div>")
|
||||
end
|
||||
|
||||
return flow_callbacks_utils
|
||||
182
attic/scripts/lua/modules/user_scripts.lua
Normal file
182
attic/scripts/lua/modules/user_scripts.lua
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
-- ##############################################
|
||||
|
||||
-- @brief Get the default configuration for the given user script
|
||||
-- and granularity.
|
||||
-- @param user_script a user_script returned by user_scripts.load
|
||||
-- @param granularity_str the target granularity
|
||||
-- @return a table with the default configuration
|
||||
function user_scripts.getDefaultConfig(user_script, granularity_str)
|
||||
local conf = {script_conf = {}, enabled = user_script.default_enabled}
|
||||
|
||||
if((user_script.default_values ~= nil) and (user_script.default_values[granularity_str] ~= nil)) then
|
||||
-- granularity specific default
|
||||
conf.script_conf = user_script.default_values[granularity_str] or {}
|
||||
else
|
||||
conf.script_conf = user_script.default_value or {}
|
||||
end
|
||||
|
||||
return(conf)
|
||||
end
|
||||
|
||||
-- ##############################################
|
||||
|
||||
local function getConfigurationKey(subdir)
|
||||
-- NOTE: strings needed by user_scripts.deleteConfigurations
|
||||
-- NOTE: The configuration must not be saved under a specific ifid, since we
|
||||
-- allow global interfaces configurations
|
||||
return(string.format("ntopng.prefs.user_scripts.conf.%s", subdir))
|
||||
end
|
||||
|
||||
-- ##############################################
|
||||
|
||||
-- Get the user scripts configuration
|
||||
-- @param subdir: the subdir
|
||||
-- @return a table
|
||||
-- {[hook] = {entity_value -> {enabled=true, script_conf = {a = 1}, }, ..., default -> {enabled=false, script_conf = {}, }}, ...}
|
||||
-- @note debug with: redis-cli get ntopng.prefs.user_scripts.conf.interface | python -m json.tool
|
||||
local function loadConfiguration(subdir)
|
||||
local key = getConfigurationKey(subdir)
|
||||
local value = ntop.getPref(key)
|
||||
|
||||
if(not isEmptyString(value)) then
|
||||
value = json.decode(value) or {}
|
||||
else
|
||||
value = {}
|
||||
end
|
||||
|
||||
return(value)
|
||||
end
|
||||
|
||||
-- ##############################################
|
||||
|
||||
-- Save the user scripts configuration.
|
||||
-- @param subdir: the subdir
|
||||
-- @param config: the configuration to save
|
||||
local function saveConfiguration(subdir, config)
|
||||
local key = getConfigurationKey(subdir)
|
||||
|
||||
if(table.empty(config)) then
|
||||
ntop.delCache(key)
|
||||
else
|
||||
local value = json.encode(config)
|
||||
ntop.setPref(key, value)
|
||||
end
|
||||
|
||||
-- Reload the periodic scripts as the configuration has changed
|
||||
ntop.reloadPeriodicScripts()
|
||||
end
|
||||
|
||||
-- ##############################################
|
||||
|
||||
function user_scripts.deleteConfigurations()
|
||||
deleteCachePattern(getConfigurationKey("*"))
|
||||
end
|
||||
|
||||
-- ##############################################
|
||||
|
||||
-- This needs to be called whenever the available_modules.conf changes
|
||||
-- It updates the single scripts config
|
||||
local function reload_scripts_config(available_modules)
|
||||
local scripts_conf = available_modules.conf
|
||||
|
||||
for _, script in pairs(available_modules.modules) do
|
||||
script.conf = scripts_conf[script.key] or {}
|
||||
end
|
||||
end
|
||||
|
||||
-- ##############################################
|
||||
|
||||
local function delete_script_conf(scripts_conf, key, hook, conf_key)
|
||||
if(scripts_conf[key] and scripts_conf[key][hook]) then
|
||||
scripts_conf[key][hook][conf_key] = nil
|
||||
|
||||
-- Cleanup empty tables
|
||||
if table.empty(scripts_conf[key][hook]) then
|
||||
scripts_conf[key][hook] = nil
|
||||
|
||||
if table.empty(scripts_conf[key]) then
|
||||
scripts_conf[key] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- ##############################################
|
||||
|
||||
function user_scripts.handlePOST(subdir, available_modules, hook, entity_value, remote_host)
|
||||
if(table.empty(_POST)) then
|
||||
return
|
||||
end
|
||||
|
||||
hook = hook or NON_TRAFFIC_ELEMENT_CONF_KEY
|
||||
entity_value = entity_value or NON_TRAFFIC_ELEMENT_ENTITY
|
||||
|
||||
local scripts_conf = available_modules.conf
|
||||
|
||||
for _, user_script in pairs(available_modules.modules) do
|
||||
-- There are 3 different configurations:
|
||||
-- - specific_config: the configuration specific of an host/interface/network
|
||||
-- - global_config: the configuration specific for all the (local/remote) hosts, interfaces, networks
|
||||
-- - default_config: the default configuration, specified by the user script
|
||||
-- They follow the follwing priorities:
|
||||
-- [lower] specific_config > global_config > default [upper]
|
||||
--
|
||||
-- Moreover:
|
||||
-- - specific_config is only set if it differs from the global_config
|
||||
-- - global_config is only set if it differs from the default_config
|
||||
--
|
||||
|
||||
-- This is used to represent the previous config in order of priority in order
|
||||
-- to determine if the current config differs from its default.
|
||||
local upper_config = user_scripts.getDefaultConfig(user_script, hook)
|
||||
|
||||
-- NOTE: we must process the global_config before the specific_config
|
||||
for _, prefix in ipairs({"global_", ""}) do
|
||||
local k = prefix .. user_script.key
|
||||
local is_global = (prefix == "global_")
|
||||
local enabled_k = "enabled_" .. k
|
||||
local is_enabled = _POST[enabled_k]
|
||||
local conf_key = ternary(is_global, get_global_conf_key(remote_host), entity_value)
|
||||
local script_conf = nil
|
||||
|
||||
if(user_script.gui and (user_script.gui.post_handler ~= nil)) then
|
||||
script_conf = user_script.gui.post_handler(k)
|
||||
end
|
||||
|
||||
if(is_enabled == nil) then
|
||||
-- TODO remove this after changing the gui to support a separate on/off field
|
||||
-- For backward compatibility, an empty configuration means that the script is disabled
|
||||
|
||||
if(user_script.gui and (user_script.gui.post_handler ~= nil) and (subdir ~= "flow")) then
|
||||
is_enabled = not table.empty(script_conf)
|
||||
else
|
||||
is_enabled = user_script.default_enabled
|
||||
end
|
||||
else
|
||||
is_enabled = (is_enabled == "on")
|
||||
end
|
||||
|
||||
local cur_config = {
|
||||
enabled = is_enabled,
|
||||
script_conf = script_conf,
|
||||
}
|
||||
|
||||
if(not table.compare(upper_config, cur_config)) then
|
||||
-- Configuration differs
|
||||
scripts_conf[user_script.key] = scripts_conf[user_script.key] or {}
|
||||
scripts_conf[user_script.key][hook] = scripts_conf[user_script.key][hook] or {}
|
||||
scripts_conf[user_script.key][hook][conf_key] = cur_config
|
||||
else
|
||||
-- Use the default
|
||||
delete_script_conf(scripts_conf, user_script.key, hook, conf_key)
|
||||
end
|
||||
|
||||
-- Needed for specific_config vs global_config comparison
|
||||
upper_config = cur_config
|
||||
end
|
||||
end
|
||||
|
||||
reload_scripts_config(available_modules)
|
||||
saveConfiguration(subdir, scripts_conf)
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue