Developing lightweight computation at the DSG edge

Commit 02703736 authored by Roger Pueyo Centelles's avatar Roger Pueyo Centelles
Browse files

[qmp-nc] Import lunced and nc packages from Reflection project



Rename them to qmp-ncd (lunced) and qmp-ncgui (nc).
Signed-off-by: default avatarRoger Pueyo Centelles <roger.pueyo@guifi.net>
parent 0d71b049
# Copyright (C) 2014-2018 Routek S.L. - https://www.routek.net
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# The full GNU General Public License is included in this package in
# the file called "COPYING".
#
# Contributors:
# Agustí Moll Garcia <agusti@routek.net>
# Roger Pueyo Centelles <rogerpueyo@routek.net>
#
include $(TOPDIR)/rules.mk
QMP_FEED_DIR?=$(CURDIR)
QMP_GIT_BRANCH?=$(shell git -C $(QMP_FEED_DIR) rev-parse --abbrev-ref HEAD)
QMP_GIT_REV?=$(shell git -C $(QMP_FEED_DIR) rev-parse --short HEAD)
QMP_GIT_DATE?=$(shell git -C $(QMP_FEED_DIR) log -1 --format=%cd --date=format:%Y%m%d)
QMP_GIT_TIME?=$(shell git -C $(QMP_FEED_DIR) log -1 --format=%cd --date=format:%H%M)
QMP_RELEASE?=trunk
QMP_PKGRELEASE=r$(QMP_GIT_DATE)_$(QMP_GIT_TIME)
QMP_CODENAME?=Kalimotxo
QMP_BUILDDATE:=$(shell date +%Y%m%d-%H%M)
PKG_NAME:=qmp-ncd
PKG_VERSION:=$(QMP_RELEASE)-$(QMP_PKGRELEASE)
PKG_RELEASE:=$(QMP_CODENAME)-$(QMP_GIT_REV)
PKG_LICENSE:=GPL-3.0+
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
include $(INCLUDE_DIR)/package.mk
define Package/qmp-ncd
TITLE:=Network Characterization daemon
SECTION:=net
CATEGORY:=qMp
URL:=http://dev.qmp.cat/projects/nc
DEPENDS:=+lua +liblua +libubox-lua +libubus-lua +ubus +iperf3
endef
define Package/qmp-ncd/description
Network Characterization is a tool to monitor nodes in a Community Network, display collected data in a user-friendly manner and perform administrative tasks.
This package provides the daemon, built in Lua, that communicates via Ubus with other processes of the local node and via JSON over HTTP with other nodes in the network.
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
endef
define Build/Configure
endef
define Build/Compile
endef
define Package/qmp-ncd/install
$(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,qmp-ncd))
Lua Network Characterization Daemon (Lunced)
--------------------------------------------
Lunced is an OpenWrt daemon written in Lua for the NC tool of the Confine OC2 project. It provides information to the NC web user interface about the node itself via Ubus and other nodes in the network using JSON over HTTP.
Requirements
------------
Lunced needs the libubox-lua package. You can install it on your node by typing:
opkg update
opkg install libubox-lua
Installation
------------
Copy the contents of the packages/lunced/files folder to the / on your device. Then enable the daemon (/etc/init.d/lunced enable) and start it (/etc/init.d/lunced start).
#!/bin/sh /etc/rc.common
# Copyright (C) 2014 Routek S.L.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
# The full GNU General Public License is included in this distribution in
# the file called "COPYING".
START=92
BIN=/usr/share/lunced/lunced.lua
CONF=/etc/config/lunced
RUNDIR=/var/run/lunced/
THREADS="lunced lunced-remote"
start() {
for i in $THREADS ; do
$BIN $i &
done
}
stop() {
for i in $THREADS ; do
start-stop-daemon -p $RUNDIR$i.pid -K
done
}
restart() {
stop; sleep 2; start
}
-- BMX6 commands
function ipv62uuid(ipv6)
ipv6 = string.gsub(ipv6,":","_")
return(ipv6)
end
function uuid2ipv6(uuid)
uuid = string.gsub(uuid,"_",":")
return(uuid)
end
-- function localIP2uuid(ipv6)
-- return(string.gsub(ipv6,"",""))
-- end
--[[function lunced_bmx6_flushAll()
local flushAll = os.execute('bmx6 -c --flushAll')
return( flushAll )
end--]]
function lunced_bmx6_all()
local all = JSON:decode('{"interfaces":' .. run('bmx6 -c --jshow interfaces') .. ', "links":' .. run('bmx6 -c --jshow links') .. ', "originators":' .. run('bmx6 -c --jshow originators') .. ', "status":' .. run('bmx6 -c --jshow status') .. '}')
return( all )
end
function lunced_bmx6_descriptors()
local descriptors
= JSON:decode(run('first=true; \
json="{\\\"descriptors\\\":["; \
for file in /var/run/bmx6/json/descriptions/*; do \
if [ "$first" == "true" ]; then \
first=false; \
else \
json=$json","; \
fi; \
json=$json`cat $file`; \
done; \
json=$json"]}"; \
echo $json'))
return( descriptors )
end
function lunced_bmx6_interfaces()
local interfaces = JSON:decode(run('bmx6 -c --jshow interfaces'))
return( interfaces )
end
function lunced_bmx6_links()
local links = JSON:decode(run('bmx6 -c --jshow links'))
return( links )
end
function lunced_bmx6_set_metricAlgo(algorithm, rxExpNumerator, rxExpDivisor, txExpNumerator, txExpDivisor)
local bmx6result = run('bmx6 -c --metricAlgo ' .. algorithm .. ' /rxExpNumerator ' .. rxExpNumerator .. ' /rxExpDivisor ' .. rxExpDivisor .. ' /txExpNumerator ' .. txExpNumerator .. ' /txExpDivisor ' .. txExpDivisor)
local result = JSON:decode('{"metricAlgo":"' .. bmx6result .. '"}')
return (result)
end
function lunced_bmx6_options()
local options = JSON:decode(run('cat /tmp/run/bmx6/json/options'))
return( options )
end
function lunced_bmx6_originators()
local originators = JSON:decode(run('bmx6 -c --jshow originators'))
return( originators )
end
function lunced_bmx6_parameters()
local parameters = JSON:decode(run('cat /tmp/run/bmx6/json/parameters'))
return( parameters )
end
function lunced_bmx6_status()
local status = JSON:decode(run('bmx6 -c --jshow status'))
return( status )
end
--[[function lunced_bmx6_version()
local version = JSON:decode(run('bmx6 -c --version'))
return( parameters )
end--]]
function lunced_bmx6_nodes(sI)
local nodes = JSON:decode(run('bmx6 -c --jshow originators'))
local ret_nodes = {}
ret_nodes['nodes'] = {}
for i,v in ipairs(nodes.originators) do
ret_nodes['nodes'][i] = ipv62uuid(v.primaryIp)
end
nodes = nil
return( ret_nodes )
end
function lunced_bmx6_neighbours(sI)
local links = JSON:decode(run('bmx6 -c --jshow links'))
local nodes = JSON:decode(run('bmx6 -c --jshow originators'))
local list_nodes = {}
local ret_nodes = {}
local counter = 1
list_nodes['nodes'] = {}
ret_nodes['nodes'] = {}
if links ~= nil then
for i,v in ipairs(links.links) do
for o,b in ipairs(nodes.originators) do
if v.name == b.name then
list_nodes['nodes'][b.name] = ipv62uuid(b.primaryIp)
end
end
end
counter = 1
for i,v in pairs(list_nodes.nodes) do
ret_nodes['nodes'][counter] = v
counter = counter + 1
end
end
list_nodes = nil
links = nil
nodes = nil
return( ret_nodes )
end
function lunced_bmx6_local(sI)
local ret = {}
if sI.id == nil then
lunced_bmx6_getSelfInfo(sI)
end
ret['id'] = sI['id']
ret['name'] = sI['name']
return (ret)
end
function lunced_bmx6_version(sI)
local ret = {}
if sI.bmx6 == nil then
lunced_bmx6_getSelfInfo(sI)
end
ret['bmx6'] = sI['bmx6']
return (ret)
end
function lunced_bmx6_getSelfInfo(sI)
local myinfo = JSON:decode(run("bmx6 -c --jshow status"))
sI['id'] = ipv62uuid(myinfo.status.primaryIp)
sI['name'] = myinfo.status.name
sI['bmx6'] = myinfo.status.version
myinfo = nil
end
-- Local information
local VERSION="0.4.7.2"
function lunced_local_version()
return ({ version = VERSION})
end
\ No newline at end of file
-- Network test commands
function lunced_nettest_bandwidth( address, parameters )
if parameters == "" then parameters = " " end
parameters = parameters:gsub('%%20', ' ')
local result = run( 'iperf3 -c ' .. address .. ' -J ' .. parameters .. ' & pid=$!; sleep 23 && kill $pid' )
if result == nil then
return JSON:decode('{}')
else
return JSON:decode( string.gsub( result, "nan", 0 ) )
end
end
function lunced_nettest_iperf3( action )
if action == "stop" then
run ('killall -9 iperf3')
local pid = run( 'pidof iperf3' )
if pid == "" then pid = -1 end
local result = JSON:decode('{"pid": ' .. pid ..'}')
return (result)
elseif action == "start" then
run ('iperf3 -sD')
local pid = run( 'pidof iperf3' )
if pid == "" then pid = -1 end
local result = JSON:decode('{"pid": ' .. pid ..'}')
return (result)
elseif action == "restart" then
run ('killall -9 iperf3')
run ('iperf3 -sD')
local pid = run( 'pidof iperf3' )
if pid == "" then pid = -1 end
local result = JSON:decode('{"pid": ' .. pid ..'}')
return (result)
elseif action == "installed" then
local installed = run ('[ -x /usr/bin/iperf3 ] && echo true')
if installed == "" then installed = 'false' end
local result = JSON:decode('{"installed": ' .. installed ..'}')
return (result)
else
local pid = run( 'pidof iperf3' )
if pid == "" then pid = -1 end
local result = JSON:decode('{"pid": ' .. pid ..'}')
return (result)
end
end
function lunced_nettest_ping( address, parameters )
if parameters == "" then parameters = "-c 10" end
parameters = parameters:gsub('%%20', ' ')
local pingresult = run( 'ping6 ' .. parameters .. ' -W 25 -w 25 ' .. address )
local result = JSON:decode('{"ping":"' .. pingresult .. '"}')
return (result)
end
function lunced_nettest_oldping( address, pingCount, pingSize )
local pingresult = run( 'ping6 -c ' .. pingCount .. ' -s ' .. pingSize .. ' -W 180 -w 180 ' .. address )
local result = JSON:decode('{"ping":"' .. pingresult .. '"}')
return (result)
end
\ No newline at end of file
function run(command)
debugMsg ("Try to execute: " .. command)
local handle = io.popen(command)
local result = handle:read("*a")
handle:close()
return result
end
function errorCode(num)
return '{ "error" : "' .. tostring(num) .. '" , "msg" : "' .. errorMessage(num) .. '" }'
end
function debugMsg(msg)
local debug = 0
if debug == 1 then
print (msg)
end
end
function errorMessage(num)
local result = nil
if num == 100 then
result = "The remote node returned did not reply, or replied with null content."
elseif num == 101 then
result = "The remote node is not in the known nodes list."
else
result = "Big error, bro!"
end
return result
end
--Check if node is in the nodes list
function node_in_nodes(node, nodes)
local result = false
for i,v in ipairs(nodes) do
if v == node then
result = true
break
end
end
return result
end
\ No newline at end of file
This diff is collapsed.
#!/usr/bin/env lua
require "ubus"
require "uloop"
require "lunced.tools"
require "lunced.local"
require "lunced.bmx6"
require "lunced.nettest"
JSON = (loadfile "/usr/share/lunced/JSON.lua")()
RUNDIR = "/var/run/lunced"
STATFILE = "/proc/self/stat"
PIDFILE = "lunced.pid"
if arg[1] ~= nil and arg[1] ~= "lunced" then
PIDFILE = "" .. arg[1] .. ".pid"
end
local fstat = assert(io.open(STATFILE, "r"))
local pid = fstat:read("*number")
fstat:close()
os.execute("mkdir -p " .. RUNDIR)
local fpid = assert(io.open( RUNDIR .. "/" .. PIDFILE, "w+"))
io.output(fpid)
io.write(pid)
io.write("\n")
fpid:close()
local selfInfo = {}
uloop.init()
local timeout = 10
local testTimeout = 26
local tries = 2
local testTries = 1
local conn = ubus.connect()
if not conn then
error("Failed to connect to ubus")
end
local lunced_method = {
lunced = {
--[[bmx6FlushAll = {
function(req)
conn:reply(req, lunced_bmx6_flushAll());
debugMsg("Call to function 'bmx6FlushAll'")
end, { }
},--]]
bmx6All = {
function(req)
conn:reply(req, lunced_bmx6_all());
debugMsg("Call to function 'bmx6All'")
end, { }
},
bmx6Descriptors = {
function(req)
conn:reply(req, lunced_bmx6_descriptors());
debugMsg("Call to function 'bmx6Descriptors'")
end, { }
},
bmx6Interfaces = {
function(req)
conn:reply(req, lunced_bmx6_interfaces());
debugMsg("Call to function 'bmx6Interfaces'")
end, { }
},
bmx6Links = {
function(req)
conn:reply(req, lunced_bmx6_links());
debugMsg("Call to function 'bmx6Links'")
end, { }
},
bmx6SetMetricAlgo = {
function(req, msg)
for k,v in pairs(msg) do
if tostring(k) == "algorithm" and v ~= "" then
for l,w in pairs(msg) do
if tostring(l) == "rxExpNumerator" and w ~= "" then
for m,x in pairs(msg) do
if tostring(m) == "rxExpDivisor" and x ~= "" then
for n,y in pairs(msg) do
if tostring(n) == "txExpNumerator" and y ~= "" then
for o,z in pairs(msg) do
if tostring(o) == "txExpDivisor" and z ~= "" then
conn:reply(req, lunced_bmx6_set_metricAlgo(tostring(v), tostring(w), tostring(x), tostring(y), tostring(z) ));
end
end
end
end
end
end
end
end
end
end
debugMsg("Call to function 'bmx6SetMetricAlgo'")
end, {algorithm = ubus.STRING, rxExpNumerator = ubus.STRING, rxExpDivisor = ubus.STRING, txExpNumerator = ubus.STRING, txExpDivisor = ubus.STRING}
},
bmx6Options = {
function(req)
conn:reply(req, lunced_bmx6_options());
debugMsg("Call to function 'bmx6Options'")
end, { }
},
bmx6Originators = {
function(req)
conn:reply(req, lunced_bmx6_originators());
debugMsg("Call to function 'bmx6Originators'")
end, { }
},
bmx6Parameters = {
function(req)
conn:reply(req, lunced_bmx6_parameters());
debugMsg("Call to function 'bmx6Parameters'")
end, { }
},
--[[bmx6Version = {
function(req)
conn:reply(req, lunced_bmx6_version());
debugMsg("Call to function 'bmx6Version'")
end, { }
},--]]
bmx6Status = {
function(req)
conn:reply(req, lunced_bmx6_status());
debugMsg("Call to function 'bmx6Status'")
end, { }
},
listnodes = {
function(req, msg)
-- get nodes
conn:reply(req, lunced_bmx6_nodes(selfInfo));
debugMsg("Call to function 'nodes'")
end, { nodes = ubus.STRING }
},
neighbours = {
function(req)
conn:reply(req, lunced_bmx6_neighbours(selfInfo));
debugMsg("Call to function 'neighbours'")
end, { nodes = ubus.STRING }
},
nettestBandwidth = {
function(req, msg)
local parameters = " "
for k,v in pairs(msg) do
if tostring(k) == "address" and v ~= "" then
for l,w in pairs(msg) do
if tostring(l) == "parameters" and w ~= "" then
parameters = tostring(w)
end
end
debugMsg("Call to function 'nettestBandwidth'")
conn:reply(req, lunced_nettest_bandwidth(tostring(v), parameters));
end
end
end, {address = ubus.STRING, parameters = ubus.STRING}
},
nettestPing = {
function(req, msg)
local parameters = " "
for k,v in pairs(msg) do
if tostring(k) == "address" and v ~= "" then
for l,w in pairs(msg) do
if tostring(l) == "parameters" and w ~= "" then
parameters = tostring(w)
end
end
debugMsg("Call to function 'nettestPing'")
conn:reply(req, lunced_nettest_ping(tostring(v), parameters));
end
end
end, {address = ubus.STRING, parameters = ubus.STRING}
},