summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--alpine-baselayout.roles2
-rw-r--r--health-controller.lua17
-rw-r--r--health-model.lua25
-rw-r--r--health-networkstats-ajax.lsp10
-rw-r--r--health-networkstats-html.lsp115
-rw-r--r--health.menu1
-rw-r--r--syslog-model.lua3
7 files changed, 170 insertions, 3 deletions
diff --git a/alpine-baselayout.roles b/alpine-baselayout.roles
index 993f050..adc0e41 100644
--- a/alpine-baselayout.roles
+++ b/alpine-baselayout.roles
@@ -1,5 +1,5 @@
CREATE=interfaces:create,interfaces:editintfile
-READ=health:storage,health:proc,health:network,health:modules,interfaces:status,interfaces:read,logfiles:status,logfiles:view,logfiles:download,logfiles:tail,syslog:status,syslog:loginfo
+READ=health:storage,health:proc,health:network,health:modules,health:networkstats,interfaces:status,interfaces:read,logfiles:status,logfiles:view,logfiles:download,logfiles:tail,syslog:status,syslog:loginfo
UPDATE=interfaces:update,interfaces:ifup,interfaces:ifdown,skins:update,skins:read,syslog:startstop,syslog:config,syslog:expert
DELETE=interfaces:delete,logfiles:delete
ALL=health:system,hostname:read
diff --git a/health-controller.lua b/health-controller.lua
index 6ebc00e..ef08301 100644
--- a/health-controller.lua
+++ b/health-controller.lua
@@ -23,3 +23,20 @@ end
proc = function (self )
return self.model:get_proc()
end
+
+networkstats = function(self)
+ local retval = self.model.get_networkstats()
+ if self.clientdata.viewtype then
+ self.conf.viewtype = "ajax"
+ else
+ local intf = self:new("alpine-baselayout/interfaces")
+ local interfaces = intf.model.get_addresses()
+ intf:destroy()
+ for i,intf in ipairs(interfaces.value) do
+ if retval.value[intf.interface] then
+ retval.value[intf.interface].ipaddr = intf.ipaddr
+ end
+ end
+ end
+ return retval
+end
diff --git a/health-model.lua b/health-model.lua
index 0646f5e..854e2cc 100644
--- a/health-model.lua
+++ b/health-model.lua
@@ -94,3 +94,28 @@ get_proc = function (self)
proc.memory = cfe({ value=fs.read_file("/proc/meminfo"), label="Memory" })
return cfe({ type="group", value=proc })
end
+
+get_networkstats = function ()
+ local stats = cfe({ type="structure", value={}, label="Network Stats", timestamp=os.time() })
+ local result = querycmd("/bin/ip -s link show")
+ -- parse the result
+ local i=0
+ local intf = ""
+ for line in string.gmatch(result, "[^\n]*\n?") do
+ if i==0 then
+ intf = string.match(line, "^%x+:%s+(%w+):")
+ if not intf or intf == "" then
+ break
+ end
+ stats.value[intf] = {}
+ elseif i==3 then
+ local bytes, packets = string.match(line, "^%s+(%d+)%s+(%d+)")
+ stats.value[intf].RX = {bytes=bytes, packets=packets}
+ elseif i==5 then
+ local bytes, packets = string.match(line, "^%s+(%d+)%s+(%d+)")
+ stats.value[intf].TX = {bytes=bytes, packets=packets}
+ end
+ i=(i+1)%6
+ end
+ return stats
+end
diff --git a/health-networkstats-ajax.lsp b/health-networkstats-ajax.lsp
new file mode 100644
index 0000000..e8d176e
--- /dev/null
+++ b/health-networkstats-ajax.lsp
@@ -0,0 +1,10 @@
+<% local view, viewlibrary, page_info = ... %>
+<%
+ require("json")
+%>
+Status: 200 OK
+Content-Type: "application/json"
+<% io.write("\n") %>
+<%
+ print(json.encode(view))
+%>
diff --git a/health-networkstats-html.lsp b/health-networkstats-html.lsp
new file mode 100644
index 0000000..e994afb
--- /dev/null
+++ b/health-networkstats-html.lsp
@@ -0,0 +1,115 @@
+<% local view, viewlibrary, page_info = ... %>
+<% require("viewfunctions") %>
+<% require("json") %>
+
+<style type="text/css">
+ #chart table {
+ width: auto;
+ }
+</style>
+<!--[if IE]><script type="text/javascript" src="/js/excanvas.js"></script><![endif]-->
+<script type="text/javascript" src="/js/jquery-latest.js"></script>
+<script type="text/javascript" src="/js/jquery.flot.js"></script>
+<script type="text/javascript">
+ var interval = 1000;
+ var duration = 60000;
+ var lastdata = <%= json.encode(view) %>;
+ var chartdata = <% -- Generate the data structure in Lua and then convert to json
+ local chartdata = {}
+ local i=0
+ for intf in pairs(view.value) do
+ chartdata[intf.."RX"] = {label=intf.." RX", data={}, color=i}
+ chartdata[intf.."TX"] = {label=intf.." TX", data={}, color=i+1}
+ i = i+2
+ end
+ io.write( json.encode(chartdata) ) %>;
+ var ID
+ function DrawChart(){
+ var data = [];
+ $("body").find("input:checked").each(function() {
+ data.push(chartdata[$(this).attr("name")]);
+ });
+ var timestamp = 0;
+ $.each(chartdata, function(key,val){
+ if (val.data.length > 0){
+ timestamp=val.data[0][0];
+ return false;
+ }
+ });
+ if (timestamp == 0 && lastdata != null) timestamp = lastdata.timestamp*1000;
+ $.plot(
+ $("#chart"), data, {legend:{position:"ne", backgroundOpacity:0}, xaxis:{mode:"time", timeformat:"%H:%M:%S", min:timestamp, max:timestamp+duration}, yaxis:{min:0}});
+ }
+ function Update(){
+ $.getJSON(
+ '<%= page_info.script .. page_info.prefix .. page_info.controller .. "/" .. page_info.action %>',
+ {viewtype:'json'},
+ function(data) {
+ if (lastdata != null){
+ if (data.timestamp <= lastdata.timestamp) return false;
+ var timestamp = data.timestamp * 1000;
+ var multiplier = 1 / (data.timestamp - lastdata.timestamp);
+ var shiftcount = null;
+ $.each(lastdata.value, function(key,val){
+ chartdata[key+"RX"].data.push([timestamp, (data.value[key].RX.bytes - lastdata.value[key].RX.bytes)*multiplier]);
+ chartdata[key+"TX"].data.push([timestamp, (data.value[key].TX.bytes - lastdata.value[key].TX.bytes)*multiplier]);
+ if (shiftcount == null) {
+ shiftcount = 0;
+ $.each(chartdata[key+"RX"].data, function(key,val){
+ if (val[0] < timestamp-duration)
+ shiftcount += 1;
+ else
+ return false;
+ });
+ }
+ for (i=0; i<shiftcount; i++){
+ chartdata[key+"RX"].data.shift();
+ chartdata[key+"TX"].data.shift();
+ }
+ });
+ }
+ lastdata = data;
+ DrawChart();
+ }
+ );
+ }
+ function Start(){
+ lastdata = null;
+ $.each(chartdata, function(key,val){
+ val.data = [];
+ });
+ Update();
+ ID = window.setInterval("Update()", interval);
+ $("#Start").attr("disabled","disabled");
+ $("#Stop").removeAttr("disabled");
+ }
+ function Stop(){
+ window.clearInterval(ID);
+ $("#Stop").attr("disabled","disabled");
+ $("#Start").removeAttr("disabled");
+ }
+ $(function (){
+ $(":checkbox").click(DrawChart);
+ $("#Start").click(Start);
+ $("#Stop").click(Stop);
+ DrawChart();
+ Start();
+ });
+</script>
+
+<H1>Network Statistics</H1>
+<div id="chart" style="WIDTH: 600px; HEIGHT: 300px"></div>
+<DL>
+<DT>Display Options</DT>
+<% for intf,val in pairs(view.value) do
+ local ipaddr = ""
+ if val.ipaddr then ipaddr = " ("..val.ipaddr..")" end %>
+ <DD><input type="checkbox" name=<%= intf.."RX" %> checked="checked"><%= intf.." RX"..ipaddr %></input></DD>
+ <DD><input type="checkbox" name=<%= intf.."TX" %> checked="checked"><%= intf.." TX"..ipaddr %></input></DD>
+<% end %>
+<DT>Start / Stop</DT>
+<DD>
+<input TYPE="button" ID="Start" VALUE="Start">
+<input TYPE="button" ID="Stop" VALUE="Stop">
+</DD>
+</DL>
diff --git a/health.menu b/health.menu
index ab57366..a595728 100644
--- a/health.menu
+++ b/health.menu
@@ -2,5 +2,6 @@
System 01General_health System system
System 01General_health Storage storage
System 01General_health Network network
+System 01General_health Network_Activity networkstats
System 01General_health Modules modules
System 01General_health Proc proc
diff --git a/syslog-model.lua b/syslog-model.lua
index 273cc27..25969fe 100644
--- a/syslog-model.lua
+++ b/syslog-model.lua
@@ -202,8 +202,7 @@ end
function update_filedetails (filedetails)
-- Validation before writing
- filedetails.value.filecontent.value = format.dostounix(filedetails.value.filecontent.value)
- filedetails.value.filecontent.value = filedetails.value.filecontent.value:gsub("\n+$", "")
+ filedetails.value.filecontent.value = string.gsub(format.dostounix(filedetails.value.filecontent.value), "\n+$", "")
local configcontent = getopts.getoptsfromfile(filedetails.value.filecontent.value, "", "SYSLOGD_OPTS", true) or {}
local config = makeconfig(configcontent)
local success, errtxt