diff options
author | Ted Trask <ttrask01@yahoo.com> | 2008-09-06 15:11:19 +0000 |
---|---|---|
committer | Ted Trask <ttrask01@yahoo.com> | 2008-09-06 15:11:19 +0000 |
commit | 56a1ef7ebe6ae60bd4722f979ec50684221d94fb (patch) | |
tree | fb3a45b6e1550386d9981027ba68229861dc272d | |
parent | a02de2a0986b0b4b1f16a56d68488db0c32443b1 (diff) | |
download | acf-alpine-baselayout-56a1ef7ebe6ae60bd4722f979ec50684221d94fb.tar.bz2 acf-alpine-baselayout-56a1ef7ebe6ae60bd4722f979ec50684221d94fb.tar.xz |
Added dynamic network activity page to health controller.
git-svn-id: svn://svn.alpinelinux.org/acf/alpine-baselayout/trunk@1452 ab2d0c66-481e-0410-8bed-d214d4d58bed
-rw-r--r-- | alpine-baselayout.roles | 2 | ||||
-rw-r--r-- | health-controller.lua | 17 | ||||
-rw-r--r-- | health-model.lua | 25 | ||||
-rw-r--r-- | health-networkstats-ajax.lsp | 10 | ||||
-rw-r--r-- | health-networkstats-html.lsp | 115 | ||||
-rw-r--r-- | health.menu | 1 | ||||
-rw-r--r-- | syslog-model.lua | 3 |
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 |