From 90baebc2b7dd8e6602d0ea3799bf50c7017876df Mon Sep 17 00:00:00 2001 From: Jan-Tarek Butt Date: Sat, 12 May 2018 17:48:32 +0200 Subject: [PATCH] add gluon-hoodselector: Integrate geolocation mode This MR includs only the VPN MODE of the hoodselector whitch simply set hoods base on their geopositions. Signed-off-by: Jan-Tarek Butt check_site.lua: fix language syntax muss -> must rage -> range at lease -> at least coordiantes -> coordinates realaise -> realised gluon-hoodselector: fix language syntax in hoodselector can not -> can't routers -> router's continure -> continue to next -> to the next TMP -> temporary for current -> for the current continure -> continue with next -> with the next thier -> there provides -> provide possition -> position therfore -> therefore gluon-hoodselector: fix language syntax in util.lua realaise -> realised gluon-hoodselector: fix language syntax and use autoupdate lock mechanism. gluon-hoodselector: fix spelling/grammar gluon-hoodselector: automatically set SECTION and CATEGORY for Gluon packages gluon-hoodselector-add-VPN-MODE: add micrond & libjson-c dependency gluon-hoodselector-add-VPN-MODE: check running hoodselector before loading lua gluon-hoodselector-add-VPN-MODE: remove nixio dependency from hoodselector util Revert "gluon-hoodselector-add-VPN-MODE: check running hoodselector before loading lua" This reverts commit 535b0a1b2fb73e563bf6a44b568a796440bd307f. add luaposix and luabitop to pakage dependency sbin/hoodselector: remove nixio requiemend sbin/hoodselector: load hoods only if necessary gluon-hoodselector: use VPN abstraction layer. the hoodselectore does not need to know about all individual VPN protocols. gluon-hoodselector: Makefile add gluon-mesh-vpn-core as dependency gluon-hoodselector: apply changes of mesh vpn lib gluon-hoodselector: remove outdated comments package/gluon-hoodselector: check_site.lua rm domain seed check thus its already checked by gluon-core package/gluon-hoodselector: util.lua code cleanup and refactoring package/gluon-hoodselector: hoodselector code cleanup and refactoring gluon-hoodselector: util.lua, use taps instead of spaces. Use posix.unistd.access instead of io.open Signed-off-by: Jan-Tarek Butt gluon-hoodselector: hoodselector, use taps instead of spaces. Signed-off-by: Jan-Tarek Butt gluon-hoodselector: check_site.lua: replace hood with domain Signed-off-by: Jan-Tarek Butt gluon-hoodselector: drop VPN mode and rename hood to domain. Furthermore implement geolocator mode as neorayder way Signed-off-by: Jan-Tarek Butt package/gluon-hoodselector: rm duplicated print output Signed-off-by: Jan-Tarek Butt package/gluon-hoodselector util: fix wrong function signature Signed-off-by: Jan-Tarek Butt small typo fixes small typo fixes Update util.lua processes are really restarted now. new (old) problem: nodes will not forget their former ipv6-addresses. watchdog could here with that. gluon-hoodselector util.lua: replace i iterator with _ Signed-off-by: Jan-Tarek Butt Update util.lua now polygons with holes are recognized correctly. also a mix of nested polygons and boxes should be possible as shapes[] package/gluon-hoodselector: hoodselector use gluon-reload for daemon restarts/reloads Signed-off-by: Jan-Tarek Butt package/gluon-hoodselector: util.lua use math-polygon lib and rm restart_services function. Rectengles will be converted into polygons now Signed-off-by: Jan-Tarek Butt package/gluon-hoodselector: Makefile rewrite description update depends list Signed-off-by: Jan-Tarek Butt package/gluon-hoodselector: check_site.lua reduce complexity Signed-off-by: Jan-Tarek Butt package/gluon-hoodselector: use : for gluon_version Val Signed-off-by: Jan-Tarek Butt package/gluon-hoodselector: fix if equal syntax Signed-off-by: Jan-Tarek Butt luasrc/usr/lib/lua/hoodselector/util.lua: check_site.lua simplify checksite script and fix if logic Signed-off-by: Jan-Tarek Butt package/gluon-hoodselector: set space after comma, rm unnecessary error handling Signed-off-by: Jan-Tarek Butt package/gluon-hoodselector: use only brackes on require function no mixup Signed-off-by: Jan-Tarek Butt package/gluon-hoodselector: check_site.lua rm unuse variables and fix non std global function Signed-off-by: Jan-Tarek Butt package/gluon-hoodselector: util.lua rm unuse include Signed-off-by: Jan-Tarek Butt package/gluon-hoodselector: rm comment return nil in function get_geolocation() Signed-off-by: Jan-Tarek Butt package/gluon-hoodselector: Makefile refactor pkg description Signed-off-by: Jan-Tarek Butt --- package/gluon-hoodselector/Makefile | 24 ++++++ package/gluon-hoodselector/check_site.lua | 26 ++++++ .../files/usr/lib/micron.d/hoodselector | 1 + .../luasrc/usr/lib/lua/hoodselector/util.lua | 79 +++++++++++++++++++ .../luasrc/usr/sbin/hoodselector | 56 +++++++++++++ 5 files changed, 186 insertions(+) create mode 100644 package/gluon-hoodselector/Makefile create mode 100644 package/gluon-hoodselector/check_site.lua create mode 100644 package/gluon-hoodselector/files/usr/lib/micron.d/hoodselector create mode 100644 package/gluon-hoodselector/luasrc/usr/lib/lua/hoodselector/util.lua create mode 100755 package/gluon-hoodselector/luasrc/usr/sbin/hoodselector diff --git a/package/gluon-hoodselector/Makefile b/package/gluon-hoodselector/Makefile new file mode 100644 index 00000000..394deeae --- /dev/null +++ b/package/gluon-hoodselector/Makefile @@ -0,0 +1,24 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-hoodselector + +GLUON_VERSION:=3 +PKG_VERSION:=2 + +include ../gluon.mk + +define Package/gluon-hoodselector + TITLE:=Automatically migrate nodes between domains. + DEPENDS:=+luaposix +libgluonutil +lua-math-polygon +libjson-c +gluon-site +micrond +luabitop @GLUON_MULTIDOMAIN + CONFLICTS:=+gluon-config-mode-domain-select +endef + +define Package/gluon-hoodselector/description + Hoodselector automatically detects in which domain the node is + located based on its geolocation settings. Domains require + bounding boxes defined as polygons or rectangles. Hoodselector + selects a domain from the list of known domains and migrate + towards it without requiring a reboot. +endef + +$(eval $(call BuildPackageGluon,gluon-hoodselector)) diff --git a/package/gluon-hoodselector/check_site.lua b/package/gluon-hoodselector/check_site.lua new file mode 100644 index 00000000..81b9e39e --- /dev/null +++ b/package/gluon-hoodselector/check_site.lua @@ -0,0 +1,26 @@ +local function check_lat_lon_range(pos, range, label) + need({'hoodselector', 'shapes'}, function() + if (type(pos) ~= "number") then + return false + end + if pos > range or pos < -range then + return false + end + return true + end, true, label.." must match a range +/-"..range) +end + +if this_domain() ~= need_string(in_site({'default_domain'})) then + for _, shape in pairs(need_table(in_domain({'hoodselector', 'shapes'}))) do + need({'hoodselector', 'shapes'}, function() + if #shape < 2 then + return false + end + for _, v in ipairs(shape) do + check_lat_lon_range(v.lat, 90.0, "lat") + check_lat_lon_range(v.lon, 180.0, "lon") + end + return true + end, true, "needs to have at least 2 coordinates for rectangular shapes.") + end +end diff --git a/package/gluon-hoodselector/files/usr/lib/micron.d/hoodselector b/package/gluon-hoodselector/files/usr/lib/micron.d/hoodselector new file mode 100644 index 00000000..6e793151 --- /dev/null +++ b/package/gluon-hoodselector/files/usr/lib/micron.d/hoodselector @@ -0,0 +1 @@ +*/2 * * * * /usr/sbin/hoodselector diff --git a/package/gluon-hoodselector/luasrc/usr/lib/lua/hoodselector/util.lua b/package/gluon-hoodselector/luasrc/usr/lib/lua/hoodselector/util.lua new file mode 100644 index 00000000..b93097a6 --- /dev/null +++ b/package/gluon-hoodselector/luasrc/usr/lib/lua/hoodselector/util.lua @@ -0,0 +1,79 @@ +local util = require ('gluon.util') +local math_polygon = require('math-polygon') +local json = require ('jsonc') +local uci = require('simple-uci').cursor() +local site = require ('gluon.site') +local logger = require('posix.syslog') +local M = {} + +function M.log(msg) + io.stdout:write(msg..'\n') + logger.openlog(msg, logger.LOG_PID) +end + +function M.get_domains() + local list = {} + for _, domain_path in ipairs(util.glob('/lib/gluon/domains/*.json')) do + table.insert(list, { + domain_code = domain_path:match('([^/]+)%.json$'), + domain = assert(json.load(domain_path)), + }) + end + return list +end + +-- Return the default domain from the domain list. +-- This method can return the following data: +-- * default domain +function M.get_default_domain(jdomains) + for _, domain in pairs(jdomains) do + if domain.domain_code == site.default_domain() then + return domain + end + end +end + +-- Get Geoposition. +-- This method can return the following data: +-- * table {lat, lon} +function M.get_geolocation() + return { + lat = tonumber(uci:get('gluon-node-info', uci:get_first('gluon-node-info', 'location'), 'latitude')), + lon = tonumber(uci:get('gluon-node-info', uci:get_first('gluon-node-info', 'location'), 'longitude')) + } +end + +-- Return domain from the domain list based on geo position or nil if no geo based domain could be +-- determined. +function M.get_domain_by_geo(jdomains, geo) + for _, domain in pairs(jdomains) do + if domain.domain_code ~= site.default_domain() then + -- Keep record of how many nested shapes we are in, e.g. a polyon with holes. + local nesting = 1 + for _, area in pairs(domain.domain.hoodselector.shapes) do + -- Convert rectangle, defined by to points, into polygon + if #area == 2 then + area = math_polygon.two_point_rec_to_poly(area) + end + if (math_polygon.point_in_polygon(area, geo) == 1) then + nesting = nesting * (-1) + end + end + if nesting == -1 then return domain end + end + end + return nil +end + +function M.set_domain_config(domain) + if uci:get('gluon', 'core', 'domain') ~= domain.domain_code then + uci:set('gluon', 'core', 'domain', domain.domain_code) + uci:commit('gluon') + os.execute('gluon-reconfigure') + M.log('Set domain "'..domain.domain.domain_names[domain.domain_code]..'"') + return true + end + return false +end + +return M diff --git a/package/gluon-hoodselector/luasrc/usr/sbin/hoodselector b/package/gluon-hoodselector/luasrc/usr/sbin/hoodselector new file mode 100755 index 00000000..12125da7 --- /dev/null +++ b/package/gluon-hoodselector/luasrc/usr/sbin/hoodselector @@ -0,0 +1,56 @@ +#!/usr/bin/lua + +local bit = require('bit') +local unistd = require('posix.unistd') +local fcntl = require('posix.fcntl') +local hoodutil = require('hoodselector.util') + +-- PID file to ensure the hoodselector isn't running parallel +local lockfile = '/var/lock/hoodselector.lock' +local lockfd, err = fcntl.open(lockfile, bit.bor(fcntl.O_WRONLY, fcntl.O_CREAT), 384) -- mode 0600 + +if not lockfd then + hoodutil.log(err, '\n') + os.exit(1) +end + +local ok, _ = fcntl.fcntl(lockfd, fcntl.F_SETLK, { + l_start = 0, + l_len = 0, + l_type = fcntl.F_WRLCK, + l_whence = unistd.SEEK_SET, +}) + +if not ok then + io.stderr:write(string.format( + "Unable to lock file %s. Make sure there is no other instance of the hoodselector running.\n", + lockfile + )) + os.exit(1) +end + +-- geolocation mode +-- If we have a location we will try to select the domain corresponding to this location. +-- If no domain for the location has been defined or if we can't determine the node's location, +-- we will select the default domain as last fallback instance. +local geo = hoodutil.get_geolocation() +if geo.lat ~= nil and geo.lon ~= nil then + io.stdout:write('Position found. Enter "geolocation mode" ...\n') + local jdomains = hoodutil.get_domains() + local geo_base_domain = hoodutil.get_domain_by_geo(jdomains, geo) + if geo_base_domain ~= nil then + if hoodutil.set_domain_config(geo_base_domain) then + os.execute("gluon-reload") + hoodutil.log('Domain set by geolocation mode.\n') + end + return + end + io.stdout:write('No domain has been defined for the current position. Continue with default domain mode\n') +else + io.stdout:write('No position found. Continue with default domain mode\n') +end + +-- default domain mode +if hoodutil.set_domain_config(hoodutil.get_default_domain(hoodutil.get_domains())) then + os.execute("gluon-reload") +end