changeset 483:0cc4a309a36b Not done eventrelay

Save not done eventrelay stuff.
author Aleksandr Rybalko <ray@ddteam.net>
date Tue, 16 Oct 2012 13:26:11 +0300
parents b13d24c91eca
children
files profiles/lua_web_ui/files/etc/rc.d/eventrelay profiles/lua_web_ui/files/etc/www/collector.lua profiles/lua_web_ui/files/etc/www/devd.lua profiles/lua_web_ui/files/etc/www/eventrelay.lua profiles/lua_web_ui/files/etc/www/eventrelay.sh profiles/lua_web_ui/files/etc/www/htdocs/Status.status.lua profiles/lua_web_ui/files/etc/www/htdocs/config.dat profiles/lua_web_ui/files/etc/www/htdocs/rest.xml profiles/lua_web_ui/files/etc/www/httpd.lua profiles/lua_web_ui/files/etc/www/lib/conf.lua profiles/lua_web_ui/files/etc/www/lib/utils.lua
diffstat 11 files changed, 411 insertions(+), 87 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/profiles/lua_web_ui/files/etc/rc.d/eventrelay	Tue Oct 16 13:26:11 2012 +0300
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# PROVIDE: eventrelay
+# BEFORE: httpd devd collector
+# REQUIRE: MAIN
+# KEYWORD: nojail shutdown
+
+. /etc/rc.subr
+
+#[ -z "${eventrelay_enable}" ] && eventrelay_enable="YES"
+eventrelay_enable="YES"
+name="eventrelay"
+command="/etc/www/${name}.sh"
+rcvar=`set_rcvar`
+
+conf_file="/etc/${name}.conf"
+pidfile="/var/run/${name}.pid"
+
+command_args="-P ${pidfile} -B ${conf_file} &"
+
+load_rc_config ${name}
+run_rc_command "$1"
--- a/profiles/lua_web_ui/files/etc/www/collector.lua	Tue Oct 16 13:11:48 2012 +0300
+++ b/profiles/lua_web_ui/files/etc/www/collector.lua	Tue Oct 16 13:26:11 2012 +0300
@@ -10,38 +10,18 @@
 host = host or "127.0.0.1";
 port = port or "8";
 
-serverhost = serverhost or "127.0.0.1";
-serverport = serverport or "80";
+-- read_file, tdump, xmldump, exec_output
+dofile('lib/utils.lua');
+
+-- urlEncode/urlDecode
+dofile("lib/urlXxcode.lua");
 
 -- Globals
 r = {};		-- Runtime varibles structure
 rquery = {};
 queue = {};
 local internet_led = nil;
-
---
--- Utility function:  URL encoding function
---
-function urlEncode(str)
-    if (str) then
-        str = string.gsub (str, "\n", "\r\n")
-        str = string.gsub (str, "([^%w ])",
-            function (c) return string.format ("%%%02X", string.byte(c)) end)
-        str = string.gsub (str, " ", "+")
-    end
-    return str
-end
-
-
---
--- Utility function:  URL decode function
---
-function urlDecode(str)
-    str = string.gsub (str, "+", " ")
-    str = string.gsub (str, "%%(%x%x)", function(h) return string.char(tonumber(h,16)) end)
-    str = string.gsub (str, "\r\n", "\n")
-    return str
-end
+local eventrelay = exec_output("kenv -q EVENTRELAY");
 
 -- convert name1=value1&name2=val+ue%2F2
 -- to table {"name1"="value1", "name2"="val ue/2"}
@@ -159,7 +139,7 @@
 end
 
 function call_server(http, q)
-    local query = "http://127.0.0.1:80/event.xml?" .. q;
+    local query = eventrelay .. "?" .. q;
 
     local body, code, headers = http.request(query);
 
--- a/profiles/lua_web_ui/files/etc/www/devd.lua	Tue Oct 16 13:11:48 2012 +0300
+++ b/profiles/lua_web_ui/files/etc/www/devd.lua	Tue Oct 16 13:26:11 2012 +0300
@@ -17,6 +17,11 @@
 -- urlEncode/urlDecode
 dofile("lib/urlXxcode.lua");
 
+-- read_file, tdump, xmldump, exec_output
+dofile('lib/utils.lua');
+
+local eventrelay = exec_output("kenv -q EVENTRELAY");
+
 function tab_to_query(t)
     local ret = "event=devd";
 
@@ -28,7 +33,7 @@
 end
 
 function call_server(config, q)
-    local query = "http://127.0.0.1:80/event.xml?" .. q;
+    local query = eventrelay .. "?" .. q;
 
     local body, code, headers = config.http.request(query);
 
@@ -40,13 +45,6 @@
 
 end
 
-function exec_output(cmd)
-	fp = io.popen(cmd, "r");
-	data = fp:read("*a");
-	fp:close();
-	return data;
-end
-
 function system_event(config, msg)
     -- !system=IFNET subsystem=rt0 type=ATTACH
     -- !system=DEVFS subsystem=CDEV type=CREATE cdev=usb/0.1.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/profiles/lua_web_ui/files/etc/www/eventrelay.lua	Tue Oct 16 13:26:11 2012 +0300
@@ -0,0 +1,137 @@
+#!/usr/bin/lua
+
+package.path = "./?.lua;/etc/www/lib/?.lua;./lib/?.lua";
+package.cpath =
+	"/lib/?.so;/usr/lib/?.so;/usr/lib/lua/?.so;" ..
+	"/lib/lua?.so;/usr/lib/lua?.so;/usr/lib/lua/lua?.so;" ..
+	"/lib/?-core.so;/usr/lib/?-core.so;/usr/lib/lua/?-core.so;" ..
+	"/lib/?/core.so;/usr/lib/?/core.so;/usr/lib/lua/?/core.so;";
+
+-- URL encode/devcode funtions
+dofile("lib/urlXxcode.lua");
+
+-- redirect print to syslog
+dofile("lib/lsyslog.lua");
+
+-- read_file, tdump, xmldump, exec_output
+dofile('lib/utils.lua');
+
+function call_listener(http, listener, q)
+	local query = listener .. "?" .. q;
+
+	-- Pass query to syslog
+	info(query);
+
+	local body, code, headers = http.request(query);
+
+	if code == 200 then
+		return (true);
+	end
+
+	return (nil);
+end
+
+function getopt(args, opts)
+    i=1;
+    while i < table.getn(arg) do
+	if arg[i]:match("^-") then
+	    if arg[i] == "-l" then
+		table.insert(listeners, arg[i+1]);
+	    else
+		    opts[arg[i]] = arg[i+1];
+	    end
+	    i = i + 1;
+	end
+	i = i + 1;
+    end
+    return (opts);
+end
+
+-- main()
+
+syslog_init("eventrelay.lua");
+
+host = os.getenv("EVENT_RELAY_HOST") or "127.0.0.1";
+port = os.getenv("EVENT_RELAY_PORT") or "1";
+
+listeners = {
+	"http://127.0.0.1:80/event.xml",
+	"http://127.0.0.1:8/event.xml",
+};
+
+opts = {};
+opts["-P"] = "/var/run/event-relay.pid";
+
+if arg then
+    opts = getopt(arg, opts);
+end
+
+for k,v in ipairs(listeners) do
+	print("Listener: " .. v);
+end
+
+-- Check pidfile
+dofile("lib/pidfile.lua");
+pidfile(opts["-P"]);
+
+socket = require("socket");
+http = require("socket.http");
+server = assert(socket.bind(host, port));
+server:settimeout(5);
+
+
+while 1 do
+	local method, path, query, major, minor;
+
+	local control = server:accept();
+
+	if control then
+		while 1 do
+    			local data, err = control:receive();
+    			if not err then
+    				local q;
+	    			_, _, method, path, q, major, minor  =
+	    			    string.find(data,
+	    				"([A-Z]+) (.-)/%?(.-) HTTP/(%d).(%d)");
+				if not query and q then
+					query = q;
+					break;
+				end
+    			else
+    				break;
+    			end
+		end
+
+
+		if query then
+			assert(control:send(
+			    "HTTP/1.0 200 OK\r\n" ..
+			    "Server: simple-lua\r\n" ..
+			    "Content-type: text/plain\r\n" ..
+			    "Connection: close\r\n" ..
+			    "\r\n" ..
+			    "OK"
+			));
+		else
+			assert(control:send(
+			    "HTTP/1.0 400 Bad Request\r\n" ..
+			    "Server: simple-lua\r\n" ..
+			    "Content-type: text/plain\r\n" ..
+			    "Connection: close\r\n" ..
+			    "\r\n" ..
+			    "FAIL"
+			));
+			err("Wrong event message received \"" .. tostring(data) .. "\"");
+    		end
+
+		assert(control:close());
+
+		if query then
+			for k,v in ipairs(listeners) do
+				call_listener(http, v, query);
+			end
+		end
+	end
+end
+
+os.exit(0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/profiles/lua_web_ui/files/etc/www/eventrelay.sh	Tue Oct 16 13:26:11 2012 +0300
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+
+cd /etc/www
+
+echo $$ > /var/run/eventrelay.sh.pid
+
+EVENT_RELAY_HOST="127.0.0.1"
+EVENT_RELAY_PORT=1
+export EVENT_RELAY_HOST EVENT_RELAY_PORT
+
+# Must be called w/o path, listeners list will define path per listener
+kenv EVENTRELAY="http://${EVENT_RELAY_HOST}:${EVENT_RELAY_PORT}/"
+
+./eventrelay.lua > /var/log/eventrelay.sh.log 2>&1
+exit 1
+
+while true; do
+    ./eventrelay.lua > /var/log/eventrelay.sh.log 2>&1
+done
+
--- a/profiles/lua_web_ui/files/etc/www/htdocs/Status.status.lua	Tue Oct 16 13:11:48 2012 +0300
+++ b/profiles/lua_web_ui/files/etc/www/htdocs/Status.status.lua	Tue Oct 16 13:26:11 2012 +0300
@@ -22,6 +22,18 @@
     <body class="yui3-skin-sam  yui-skin-sam">
     <h1>LAN configuration</h1>
 
+<div id="Routes" class="yui3-module boxitem">
+    <div class="yui3-hd">
+        <h4>Routes</h4>
+    </div>
+    <div class="yui3-bd">
+    ]] ..
+    "<pre>\n" ..
+    exec_output("netstat -rn") ..
+    "</pre>\n" ..
+    [[
+    </div>
+</div>
 <div id="Static" class="yui3-module boxitem">
     <div class="yui3-hd">
         <h4>Static/DHCP</h4>
--- a/profiles/lua_web_ui/files/etc/www/htdocs/config.dat	Tue Oct 16 13:11:48 2012 +0300
+++ b/profiles/lua_web_ui/files/etc/www/htdocs/config.dat	Tue Oct 16 13:26:11 2012 +0300
@@ -1,10 +1,38 @@
 
 
-if rq.POST["cmd"] == "download_config" then
-	return (xmldump(c:gettree()));
-else
-	return ("Unknow command");
+if type(rq.POST) == "table" then
+	if rq.POST["cmd"] == "download_config" then
+		return (xmldump(c:gettree()) or "nil");
+	end
+elseif type(rq.GET) == "table" then
+	if rq.GET["key"] then
+		local node = c:getNode(rq.GET["key"]);
+		if node then
+			if rq.GET["value"] then
+				-- try to assign the value
+				node:value(rq.GET["value"]);
+			else
+				-- return value
+				return (node:value() or "nil");
+			end
+		else
+			return ("Item \"" .. rq.GET["key"] ..
+			    "\" not found");
+		end
+	elseif rq.GET["dump"] then
+		local node = c:getNode(rq.GET["dump"]);
+		local format = rq.GET["format"] or "xml";
+
+		if node then
+			return (node:dump(format) or "nil");
+		else
+			return ("Item \"" .. rq.GET["dump"] ..
+			    "\" not found");
+		end
+	end
 end
 
+return ("Unknow command");
+
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/profiles/lua_web_ui/files/etc/www/htdocs/rest.xml	Tue Oct 16 13:26:11 2012 +0300
@@ -0,0 +1,109 @@
+--[[
+
+endWithSlash
+	GET	List the URIs and perhaps other details of the collection's members.
+	PUT	Replace the entire collection with another collection.
+	POST	Create a new entry in the collection. The new entry's URL is assigned automatically and is usually returned by the operation.
+	DELETE	Delete the entire collection.
+!endWithSlash
+	GET	Retrieve a representation of the item of the collection, expressed in an appropriate Internet media type.
+	PUT	Replace the item of the collection, or if it doesn't exist, create it.
+	POST	Treat the item as a collection in its own right and create a new entry in it.
+	DELETE	Delete the item of the collection.
+]]
+
+-- read_file, tdump, xmldump
+dofile('lib/utils.lua');
+
+
+function err(...)
+	local str = string.format(...);
+	return ("<error>" .. str .. "</error>");
+end
+
+function path2item(tree, path)
+	local left, newpath = path:match("^([^\/]+)\/(.*)");
+	if not left then
+		if tree[path] then
+			return (tree[path]);
+		end
+	else
+		if not newpath or newpath == "" then
+			return (tree[left]);
+		end
+		if tree[left] then
+			return (path2item(tree[left], newpath));
+		end
+	end
+	return (nil);
+end
+
+function process()
+	if not sys then
+		print("Configuration structure 'sys' is missing");
+	end
+	if not rq then
+		print("Request structure 'rq' is missing");
+	end
+
+    	local item = path2item(sys, rq.path);
+	if not item then
+		return err("Item \"%s\" is not found", rq.path);
+	end
+
+	if rq.path:sub(-1) == '/' then
+	        -- Collection
+	    	if type(item) ~= "table" then
+	    		return err("Element \"%s\" is not a collection", rq.path);
+	    	end
+
+	        if rq.GET then
+			-- List table items.
+			local list = "";
+			for k, v in pairs(item) do
+				list = list .. string.format("<%s>%s</%s>", k, v, k);
+			end
+			return (list);
+	        elseif rq.PUT then
+			-- Replace whole table.
+	        elseif rq.POST then
+			-- Add table item.
+	        elseif rq.DELETE then
+			-- Free table.
+	        else
+	    		return err("Protocol not implemented");
+	    	end
+	else
+		-- Item
+	    	-- if type(item) ~= "table" then
+	    	-- 	return err("Element \"%s\" is not a collection", rq.path);
+	    	-- end
+
+	        if rq.GET then
+			-- Retrieve item value.
+			return (xmldump(item));
+	        elseif rq.PUT then
+			-- Replace item, or if it doesn't exist, create it.
+	        elseif rq.POST then
+			-- Append/Insert new item to table.
+	        elseif rq.DELETE then
+			-- Delete item from table.
+	        else
+	    		return err("Protocol not implemented");
+	    	end
+	end
+
+end
+
+return ([[
+<?xml version="1.0" encoding="utf-8" ?>
+<data>]] ..
+process() ..
+[[
+</data>
+]]);
+
+-- end
+
+-- print(doit());
+
--- a/profiles/lua_web_ui/files/etc/www/httpd.lua	Tue Oct 16 13:11:48 2012 +0300
+++ b/profiles/lua_web_ui/files/etc/www/httpd.lua	Tue Oct 16 13:26:11 2012 +0300
@@ -34,7 +34,7 @@
 -- XML entity handlers
 dofile('lib/handler.lua');
 
--- read_file, tdump, xmldump
+-- read_file, tdump, xmldump, exec_output
 dofile('lib/utils.lua');
 -- Conf object
 dofile('lib/conf.lua');
@@ -111,7 +111,7 @@
 	-- c:getNode("http.host"):value();
 	s = socket.tcp();
 	assert(s:setoption("reuseaddr", true));
-	assert(s:bind("*", c:getNode("http.port"):value()));
+	assert(s:bind("*", c:getNodeValueSafe("http.port", 80)));
 	assert(s:listen(8));
 	assert(s:settimeout(5));
 	config.listener = s;
@@ -120,8 +120,8 @@
 	--   Print some status messages.
 	--
 	print( "\nListening upon:" );
-	print( "  http://" .. c:getNode("http.host"):value() .. ":" ..
-			c:getNode("http.port"):value() .. "/" );
+	print( "  http://" .. c:getNodeValueSafe("http.host", "*") .. ":" ..
+			c:getNodeValueSafe("http.port", 80) .. "/" );
 	print( "\n\n");
 	--[[
 	table.insert(r.tasks.countdown, { count=25, task=
@@ -288,7 +288,8 @@
 	--
 	-- We only handle GET requests.
 	--
-	if ( method ~= "GET" ) and ( method ~= "POST" ) then
+	if ( method ~= "GET" ) and ( method ~= "POST" ) and
+	    ( method ~= "PUT" ) and ( method ~= "DELETE" ) then
 		error = "Method not implemented";
 
 		if ( method == nil ) then
@@ -308,6 +309,7 @@
 	-- Decode the requested path.
 	--
 	path = urlDecode( path );
+	rq.path = path;
 
 	--
 	-- find the Virtual Host which we need for serving, and find the
@@ -517,21 +519,10 @@
 		end
 		return (ret);
 	else
-		node = c:getNode(s);
-		if node then
-			return field(node:value() or "");
-		end
-		return field("");
+		return (field(c:getNodeValueSafe(s, "")));
 	end
 end
 
-function exec_output(cmd)
-	fp = io.popen(cmd, "r");
-	data = fp:read("*a");
-	fp:close();
-	return data;
-end
-
 function queryData(rq)
 	if rq.POST["cmd"] then
 		cmd = rq.POST["cmd"];
@@ -889,8 +880,8 @@
 		configure_mpd_link(c, path, sub, sub);
 		-- Add interface to route select logic
 		r.route:f(sub,
-		    safeValue(c, path .. ".group", "WAN"),
-		    safeValue(c, path .. ".cost", "1000") - 0,
+		    c:getNodeValueSafe(path .. ".group", "WAN"),
+		    c:getNodeValueSafe(path .. ".cost", "1000") - 0,
 		    "down",
 		    "LINKDOWN")
 	    elseif (subtype == "pptp") then
@@ -900,12 +891,12 @@
 		os.execute("sleep 1");
 		configure_mpd_link(c, path, sub, sub);
 		r.route:f(sub,
-		    safeValue(c, path .. ".group", "WAN"),
-		    safeValue(c, path .. ".cost", "1000") - 0,
+		    c:getNodeValueSafe(path .. ".group", "WAN"),
+		    c:getNodeValueSafe(path .. ".cost", "1000") - 0,
 		    "down",
 		    "LINKDOWN")
 	    elseif (subtype == "hw") then
-		local dev = c:getNode(path .. ".device"):value();
+		local dev = c:getNodeValueSafe(path .. ".device", "wan0");
 		local dhcp = c:getNode(path .. ".dhcp");
 		local dhcpenabled = 0;
 		if dhcp and dhcp:attr("enable") == "true" then
@@ -914,8 +905,8 @@
 
 		os.execute(string.format("ifconfig %s up", dev));
 		r.route:f(sub,
-		    safeValue(c, path .. ".group", "WAN"),
-		    safeValue(c, path .. ".cost", "1000") - 0,
+		    c:getNodeValueSafe(path .. ".group", "WAN"),
+		    c:getNodeValueSafe(path .. ".cost", "1000") - 0,
 		    "up",
 		    "LINKDOWN")
 
@@ -929,7 +920,7 @@
     		query = query .. "&dns2=" .. 	urlEncode(c:getNode(path .. ".dns2"):value());
 
 		-- Call collector, to let him know about static config, and assign route+dns's
-		cmdline = "fetch -qo - \"http://127.0.0.1:8/event.xml?" .. query .. "\"";
+		cmdline = "fetch -qo - \"" .. eventrelay .. "?" .. query .. "\"";
     		print("Exec: " .. cmdline);
     		os.execute(cmdline);
 
@@ -1044,11 +1035,11 @@
 	if c:getNode("dhcpd.instances.instance[1]"):attr("enable") == "true" then
 
 		dhcproot = "dhcpd.instances.instance[1].";
-		domain = safeValue(c, dhcproot .. "domain", "zrouter");
-		dltime = safeValue(c, dhcproot .. "default-lease-time", 3600);
-		mltime = safeValue(c, dhcproot .. "max-lease-time");
-		ranges = safeValue(c, dhcproot .. "range.start");
-		rangee = safeValue(c, dhcproot .. "range.end");
+		domain = c:getNodeValueSafe(dhcproot .. "domain", "zrouter");
+		dltime = c:getNodeValueSafe(dhcproot .. "default-lease-time", 3600);
+		mltime = c:getNodeValueSafe(dhcproot .. "max-lease-time");
+		ranges = c:getNodeValueSafe(dhcproot .. "range.start");
+		rangee = c:getNodeValueSafe(dhcproot .. "range.end");
 
 		local_domain = " --domain=" .. domain .."," .. ranges .. "," .. rangee;
 		local_dhcp_range = " --dhcp-range=" .. ranges .. "," .. rangee .. "," .. dltime;
@@ -1073,10 +1064,10 @@
 		driver = "bsd";
 		--        <ieee80211d>1</ieee80211d>
 		--        <country_code>UA</country_code>
-		channel = safeValue(c, aproot .. "channel", 6);
-		country_code = safeValue(c, aproot .. "country_code", "UA");
+		channel = c:getNodeValueSafe(aproot .. "channel", 6);
+		country_code = c:getNodeValueSafe(aproot .. "country_code", "UA");
 		--        <interface>wlan0</interface>
-		interface = safeValue(c, aproot .. "interface", "wlan0");
+		interface = c:getNodeValueSafe(aproot .. "interface", "wlan0");
 
 		commandline = string.format("ifconfig %s down",interface);
 		if os.execute(commandline) ~= 0 then
@@ -1095,18 +1086,18 @@
 		--        <ctrl_interface>/var/run/hostapd</ctrl_interface>
 		--        <ctrl_interface_group>wheel</ctrl_interface_group>
 		--        <ssid>zrouter</ssid>
-		ssid = safeValue(c, aproot .. "ssid", "zrouter");
+		ssid = c:getNodeValueSafe(aproot .. "ssid", "zrouter");
 		--        <!-- Open -->
 		--        <wpa>0</wpa>
-		wpa = safeValue(c, aproot .. "wpa", 3);
+		wpa = c:getNodeValueSafe(aproot .. "wpa", 3);
 		--        <!-- WPA -->
 		--        <!-- <wpa>1</wpa> -->
 		--        <!-- RSN/WPA2 -->
 		-- <!-- <wpa>2</wpa> -->
     		-- <wpa_pairwise>CCMP TKIP</wpa_pairwise>
-		wpa_key_mgmt = safeValue(c, aproot .. "wpa_key_mgmt", "WPA-PSK");
-		wpa_passphrase = safeValue(c, aproot .. "wpa_passphrase", "freebsdmall");
-		wpa_pairwise = safeValue(c, aproot .. "wpa_pairwise", "CCMP");
+		wpa_key_mgmt = c:getNodeValueSafe(aproot .. "wpa_key_mgmt", "WPA-PSK");
+		wpa_passphrase = c:getNodeValueSafe(aproot .. "wpa_passphrase", "freebsdmall");
+		wpa_pairwise = c:getNodeValueSafe(aproot .. "wpa_pairwise", "CCMP");
 		ctrl_interface = "/var/run/hostapd";
 
 		-- # TARGET
@@ -1149,8 +1140,8 @@
 		return;
 	end
 	if c:getNode("igmp.instance[1]"):attr("enable") == "true" then
-		upif   = safeValue(c, aproot .. "up", "wan0");
-		downif = safeValue(c, aproot .. "down", "lan0");
+		upif   = c:getNodeValueSafe(aproot .. "up", "wan0");
+		downif = c:getNodeValueSafe(aproot .. "down", "lan0");
 
 		cmd = "/etc/rc.d/ng_igmpproxy start " .. upif .. " " .. downif;
 
@@ -1160,10 +1151,15 @@
 end
 
 -- Globals
-config = {};	-- Unused now
+sys = {};	-- Full tree of all params
+config = {};	-- Hold HTTPD server params
 c = {}; 	-- XML tree from config.xml
 r = {};		-- Runtime varibles structure
 
+sys.r = r;
+sys.c = c;
+sys.config = config;
+
 r.routes = {};
 r.routes["default"] = "127.0.0.1";
 r.routes["224.0.0.0/4"] = "-iface bridge0"
@@ -1173,6 +1169,8 @@
 r.tasks.onetime  = {}; -- At some time
 r.tasks.countdown= {}; -- when counter expired
 r.ver = {};
+eventrelay = exec_output("kenv -q EVENTRELAY");
+
 
 opts = {};
 opts["-P"] = "/var/run/httpd.pid";
--- a/profiles/lua_web_ui/files/etc/www/lib/conf.lua	Tue Oct 16 13:11:48 2012 +0300
+++ b/profiles/lua_web_ui/files/etc/www/lib/conf.lua	Tue Oct 16 13:26:11 2012 +0300
@@ -66,6 +66,18 @@
     return (Node:new(ret, path));
 end
 
+function Conf:getNodeValueSafe(path, default)
+	node = self:getNode(path);
+	if not node then
+		if default then
+			return default;
+		else
+			return ("");
+		end
+	end
+	return node:value();
+end
+
 --      node = { _name = <Element Name>,
 --              _type = ROOT|ELEMENT|TEXT|COMMENT|PI|DECL|DTD,
 --              _attr = { Node attributes - see callback API },
--- a/profiles/lua_web_ui/files/etc/www/lib/utils.lua	Tue Oct 16 13:11:48 2012 +0300
+++ b/profiles/lua_web_ui/files/etc/www/lib/utils.lua	Tue Oct 16 13:26:11 2012 +0300
@@ -26,7 +26,10 @@
     return XML subtree of table
 ]]
 
-function xmldump(t)
+function xmldump(t, level)
+    if type(t) ~= "table" then
+	return (nil);
+    end
 
     local function xatrdmp(t)
 	local ret = '';
@@ -35,7 +38,7 @@
     	    ret = ret .. string.format(" %s=\"%s\"", tostring(k), tostring(v));
         end
 
-        return ret;
+        return (ret);
     end
 
     local function xdmp(t, l)
@@ -83,15 +86,12 @@
     	elseif t._type == "COMMENT" then
     	    ret = ret ..
     		string.format("%s<!-- %s -->\n", string.rep(" ", l*4), t._text);
---    	else
---    	    print("Parse Error Unknow type \"" .. (t._type or "(nil)") .. "\"");
     	end
 
-	-- print(ret);
-	return ret;
+	return (ret);
     end
 
-    return xdmp(t, -1);
+    return xdmp(t, level or -1);
 end
 
 
@@ -326,3 +326,10 @@
 	return err;
 end
 
+function exec_output(cmd)
+	fp = io.popen(cmd, "r");
+	data = fp:read("*a");
+	fp:close();
+	-- remove CR and LF, but only at the end of data
+	return data:gsub("[\n\r]$", "");
+end