luci-app-vnstat2: add application
This adds an application for vnStat version 2. Signed-off-by: Jan Hoffmann <jan@3e8.eu>
This commit is contained in:
parent
d844caf137
commit
1750433bc1
6 changed files with 356 additions and 0 deletions
13
applications/luci-app-vnstat2/Makefile
Normal file
13
applications/luci-app-vnstat2/Makefile
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# This is free software, licensed under the Apache License, Version 2.0
|
||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
LUCI_TITLE:=LuCI Support for vnStat 2
|
||||||
|
LUCI_DEPENDS:=+luci-lib-jsonc +vnstat2 +vnstati2
|
||||||
|
|
||||||
|
PKG_LICENSE:=Apache-2.0
|
||||||
|
PKG_MAINTAINER:=Jan Hoffmann <jan@3e8.eu>
|
||||||
|
|
||||||
|
include ../../luci.mk
|
||||||
|
|
||||||
|
# call BuildPackage - OpenWrt buildroot signature
|
|
@ -0,0 +1,109 @@
|
||||||
|
// This is free software, licensed under the Apache License, Version 2.0
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
'require fs';
|
||||||
|
'require ui';
|
||||||
|
'require uci';
|
||||||
|
'require form';
|
||||||
|
'require tools.widgets as widgets';
|
||||||
|
|
||||||
|
return L.view.extend({
|
||||||
|
handleDeleteModal: function(m, iface, ev) {
|
||||||
|
L.showModal(_('Delete interface <em>%h</em>').format(iface), [
|
||||||
|
E('p', _('The interface will be removed from the database permanently. This cannot be undone.')),
|
||||||
|
E('div', { 'class': 'right' }, [
|
||||||
|
E('div', {
|
||||||
|
'class': 'btn',
|
||||||
|
'click': L.hideModal
|
||||||
|
}, _('Cancel')),
|
||||||
|
' ',
|
||||||
|
E('div', {
|
||||||
|
'class': 'btn cbi-button-negative',
|
||||||
|
'click': ui.createHandlerFn(this, 'handleDelete', m, iface)
|
||||||
|
}, _('Delete'))
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleDelete: function(m, iface, ev) {
|
||||||
|
return fs.exec('/usr/bin/vnstat', ['--remove', '-i', iface, '--force'])
|
||||||
|
.then(L.bind(m.render, m))
|
||||||
|
.catch(function(e) {
|
||||||
|
ui.addNotification(null, E('p', e.message));
|
||||||
|
})
|
||||||
|
.finally(L.hideModal);
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
var m, s, o;
|
||||||
|
|
||||||
|
m = new form.Map('vnstat', _('vnStat'), _('vnStat is a network traffic monitor for Linux that keeps a log of network traffic for the selected interface(s).'));
|
||||||
|
|
||||||
|
s = m.section(form.TypedSection, 'vnstat', _('Interfaces'));
|
||||||
|
s.anonymous = true;
|
||||||
|
s.addremove = false;
|
||||||
|
|
||||||
|
o = s.option(widgets.DeviceSelect, 'interface', _('Monitor interfaces'), _('The selected interfaces are automatically added to the vnStat database upon startup.'));
|
||||||
|
o.rmempty = true;
|
||||||
|
o.multiple = true;
|
||||||
|
o.noaliases = true;
|
||||||
|
o.nobridges = false;
|
||||||
|
o.noinactive = false;
|
||||||
|
o.nocreate = false;
|
||||||
|
|
||||||
|
|
||||||
|
o = s.option(form.DummyValue, '_database');
|
||||||
|
|
||||||
|
o.load = function(section_id) {
|
||||||
|
return fs.exec('/usr/bin/vnstat', ['--json', 'f', '1']).then(L.bind(function(result) {
|
||||||
|
var databaseInterfaces = [];
|
||||||
|
if (result.code == 0) {
|
||||||
|
var vnstatData = JSON.parse(result.stdout);
|
||||||
|
for (var i = 0; i < vnstatData.interfaces.length; i++) {
|
||||||
|
databaseInterfaces.push(vnstatData.interfaces[i].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var configInterfaces = uci.get_first('vnstat', 'vnstat', 'interface') || [];
|
||||||
|
|
||||||
|
this.interfaces = databaseInterfaces.filter(function(iface) {
|
||||||
|
return configInterfaces.indexOf(iface) == -1;
|
||||||
|
});
|
||||||
|
}, this));
|
||||||
|
};
|
||||||
|
|
||||||
|
o.render = L.bind(function(view, section_id) {
|
||||||
|
var table = E('div', { 'class': 'table' }, [
|
||||||
|
E('div', { 'class': 'tr table-titles' }, [
|
||||||
|
E('div', { 'class': 'th' }, _('Interface')),
|
||||||
|
E('div', { 'class': 'th right' }, _('Delete'))
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
|
||||||
|
var rows = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < this.interfaces.length; i++) {
|
||||||
|
rows.push([
|
||||||
|
this.interfaces[i],
|
||||||
|
E('button', {
|
||||||
|
'class': 'btn cbi-button-remove',
|
||||||
|
'click': ui.createHandlerFn(view, 'handleDeleteModal', m, this.interfaces[i])
|
||||||
|
}, [ _('Delete…') ])
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
cbi_update_table(table, rows, E('em', _('No unconfigured interfaces found in database.')));
|
||||||
|
|
||||||
|
return E([], [
|
||||||
|
E('h3', _('Unconfigured interfaces')),
|
||||||
|
E('div', { 'class': 'cbi-section-descr' },
|
||||||
|
_('These interfaces are present in the vnStat database, but are not configured above.')),
|
||||||
|
table
|
||||||
|
]);
|
||||||
|
}, o, this);
|
||||||
|
|
||||||
|
|
||||||
|
return m.render();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
50
applications/luci-app-vnstat2/luasrc/controller/vnstat2.lua
Normal file
50
applications/luci-app-vnstat2/luasrc/controller/vnstat2.lua
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
module("luci.controller.vnstat2", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
if not nixio.fs.access("/etc/config/vnstat") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
entry({"admin", "status", "vnstat2"}, alias("admin", "status", "vnstat2", "graphs"), _("vnStat Traffic Monitor"), 90)
|
||||||
|
entry({"admin", "status", "vnstat2", "graphs"}, template("vnstat2/graphs"), _("Graphs"), 1)
|
||||||
|
entry({"admin", "status", "vnstat2", "config"}, view("vnstat2/config"), _("Configuration"), 2)
|
||||||
|
entry({"admin", "status", "vnstat2", "graph"}, call("action_graph"), nil, 3)
|
||||||
|
end
|
||||||
|
|
||||||
|
function action_graph()
|
||||||
|
local util = require "luci.util"
|
||||||
|
|
||||||
|
local param = luci.http.formvalue
|
||||||
|
|
||||||
|
local iface = param("iface")
|
||||||
|
local style = param("style")
|
||||||
|
|
||||||
|
if not iface or not style then
|
||||||
|
luci.http.status(404, "Not Found")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local style_valid = false
|
||||||
|
for _, v in ipairs({"s", "t", "5", "h", "d", "m", "y"}) do
|
||||||
|
if v == style then
|
||||||
|
style_valid = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not style_valid then
|
||||||
|
luci.http.status(404, "Not Found")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
luci.http.prepare_content("image/png")
|
||||||
|
|
||||||
|
local cmd = "vnstati -i %s -%s -o -" % {
|
||||||
|
util.shellquote(iface),
|
||||||
|
util.shellquote(style)
|
||||||
|
}
|
||||||
|
|
||||||
|
local image = io.popen(cmd)
|
||||||
|
luci.http.write(image:read("*a"))
|
||||||
|
image:close()
|
||||||
|
end
|
55
applications/luci-app-vnstat2/luasrc/view/vnstat2/graphs.htm
Normal file
55
applications/luci-app-vnstat2/luasrc/view/vnstat2/graphs.htm
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<%#
|
||||||
|
This is free software, licensed under the Apache License, Version 2.0
|
||||||
|
-%>
|
||||||
|
|
||||||
|
<%-
|
||||||
|
|
||||||
|
local util = require "luci.util"
|
||||||
|
local json = require "luci.jsonc"
|
||||||
|
|
||||||
|
|
||||||
|
local ifaces = {}
|
||||||
|
|
||||||
|
local data = util.exec("vnstat --json f 1 2>/dev/null")
|
||||||
|
local content = json.parse(data)
|
||||||
|
if type(content) == "table" then
|
||||||
|
for _, iface in pairs(content["interfaces"]) do
|
||||||
|
table.insert(ifaces, iface["name"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function render_section(style, title)
|
||||||
|
%><div class="cbi-section" data-tab="<%=style%>" data-tab-title="<%=title%>"><%
|
||||||
|
|
||||||
|
for _, iface in ipairs(ifaces) do
|
||||||
|
%><p><img src="<%=url("admin/status/vnstat2/graph")%>?iface=<%=iface%>&style=<%=style%>" alt="" style="max-width:100%" /></p><%
|
||||||
|
end
|
||||||
|
|
||||||
|
%></div><%
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-%>
|
||||||
|
|
||||||
|
<%+header%>
|
||||||
|
|
||||||
|
<h2 name="content"><%:vnStat Graphs%></h2>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<%
|
||||||
|
if #ifaces == 0 then
|
||||||
|
%><p><em><%:No monitored interfaces have been found. Go to the configuration to enable monitoring for one or more interfaces.%></em></p><%
|
||||||
|
else
|
||||||
|
render_section("s", translate("Summary"))
|
||||||
|
render_section("t", translate("Top"))
|
||||||
|
render_section("5", translate("5 Minute"))
|
||||||
|
render_section("h", translate("Hourly"))
|
||||||
|
render_section("d", translate("Daily"))
|
||||||
|
render_section("m", translate("Monthly"))
|
||||||
|
render_section("y", translate("Yearly"))
|
||||||
|
end
|
||||||
|
%>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%+footer%>
|
117
applications/luci-app-vnstat2/po/templates/vnstat2.pot
Normal file
117
applications/luci-app-vnstat2/po/templates/vnstat2.pot
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
msgid ""
|
||||||
|
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/luasrc/view/vnstat2/graphs.htm:46
|
||||||
|
msgid "5 Minute"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:18
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/luasrc/controller/vnstat2.lua:10
|
||||||
|
msgid "Configuration"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/luasrc/view/vnstat2/graphs.htm:48
|
||||||
|
msgid "Daily"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:23
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:80
|
||||||
|
msgid "Delete"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:12
|
||||||
|
msgid "Delete interface <em>%h</em>"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:92
|
||||||
|
msgid "Delete…"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/luasrc/controller/vnstat2.lua:9
|
||||||
|
msgid "Graphs"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/luasrc/view/vnstat2/graphs.htm:47
|
||||||
|
msgid "Hourly"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:79
|
||||||
|
msgid "Interface"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:43
|
||||||
|
msgid "Interfaces"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:47
|
||||||
|
msgid "Monitor interfaces"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/luasrc/view/vnstat2/graphs.htm:49
|
||||||
|
msgid "Monthly"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/luasrc/view/vnstat2/graphs.htm:42
|
||||||
|
msgid ""
|
||||||
|
"No monitored interfaces have been found. Go to the configuration to enable "
|
||||||
|
"monitoring for one or more interfaces."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:96
|
||||||
|
msgid "No unconfigured interfaces found in database."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/luasrc/view/vnstat2/graphs.htm:44
|
||||||
|
msgid "Summary"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:13
|
||||||
|
msgid ""
|
||||||
|
"The interface will be removed from the database permanently. This cannot be "
|
||||||
|
"undone."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:47
|
||||||
|
msgid ""
|
||||||
|
"The selected interfaces are automatically added to the vnStat database upon "
|
||||||
|
"startup."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:101
|
||||||
|
msgid ""
|
||||||
|
"These interfaces are present in the vnStat database, but are not configured "
|
||||||
|
"above."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/luasrc/view/vnstat2/graphs.htm:45
|
||||||
|
msgid "Top"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:99
|
||||||
|
msgid "Unconfigured interfaces"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/luasrc/view/vnstat2/graphs.htm:50
|
||||||
|
msgid "Yearly"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:41
|
||||||
|
msgid "vnStat"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/luasrc/view/vnstat2/graphs.htm:37
|
||||||
|
msgid "vnStat Graphs"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/luasrc/controller/vnstat2.lua:8
|
||||||
|
msgid "vnStat Traffic Monitor"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: applications/luci-app-vnstat2/htdocs/luci-static/resources/view/vnstat2/config.js:41
|
||||||
|
msgid ""
|
||||||
|
"vnStat is a network traffic monitor for Linux that keeps a log of network "
|
||||||
|
"traffic for the selected interface(s)."
|
||||||
|
msgstr ""
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"luci-app-vnstat2": {
|
||||||
|
"description": "Grant access to LuCI app vnstat2",
|
||||||
|
"write": {
|
||||||
|
"file": {
|
||||||
|
"/usr/bin/vnstat": [ "exec" ]
|
||||||
|
},
|
||||||
|
"uci": [ "vnstat" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue