move manman to site
This commit is contained in:
		
							parent
							
								
									6f81325a79
								
							
						
					
					
						commit
						59482e53da
					
				| @ -1,13 +0,0 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-config-mode-manman-sync | ||||
| PKG_VERSION:=2 | ||||
| 
 | ||||
| include ../gluon.mk | ||||
| 
 | ||||
| define Package/gluon-config-mode-manman-sync | ||||
|   TITLE:=Sync location data from manman | ||||
|   DEPENDS:=+gluon-config-mode-core +gluon-manman-sync | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackageGluon,gluon-config-mode-manman-sync)) | ||||
| @ -1,36 +0,0 @@ | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: \n" | ||||
| "POT-Creation-Date: \n" | ||||
| "PO-Revision-Date: 2021-12-15 07:33+0100\n" | ||||
| "Last-Translator: Maciej Krüger <maciej@xeredo.it>\n" | ||||
| "Language-Team: German\n" | ||||
| "Language: de\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||||
| "X-Generator: Poedit 3.0\n" | ||||
| 
 | ||||
| msgid "Enable ManMan sync" | ||||
| msgstr "ManMan synchronisierung aktivieren" | ||||
| 
 | ||||
| msgid "ManMan location" | ||||
| msgstr "ManMan Standort" | ||||
| 
 | ||||
| msgid "ManMan node (optional)" | ||||
| msgstr "ManMan Knoten (optional)" | ||||
| 
 | ||||
| msgid "Required if multiple nodes in location" | ||||
| msgstr "Erforderlich wenn mehrere Knoten am Standort" | ||||
| 
 | ||||
| msgid "" | ||||
| "Sync configuration from ManMan " | ||||
| "by entering ManMan location and node name here.<br>" | ||||
| "This will automatically keep name, location and ips " | ||||
| "in sync with the values specified in ManMan." | ||||
| msgstr "" | ||||
| "Synchronisiere die Konfiguration aus ManMan, indem du hier den ManMan " | ||||
| "Standort-Namen und, optional, Knoten-Namen eingibst.\n" | ||||
| "Dadurch werden Name, Standort und IP-Addressen automatisch mit den in " | ||||
| "ManMan angegebenen Werten synchronisiert." | ||||
| @ -1,11 +0,0 @@ | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PACKAGE VERSION\n" | ||||
| "PO-Revision-Date: 2015-08-12 23:30+0100\n" | ||||
| "Last-Translator:Tobias Bernot <tqbs@airmail.cc>\n" | ||||
| "Language-Team: French\n" | ||||
| "Language: fr\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||||
| @ -1,21 +0,0 @@ | ||||
| msgid "" | ||||
| msgstr "Content-Type: text/plain; charset=UTF-8" | ||||
| 
 | ||||
| msgid "Enable ManMan sync" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "ManMan location" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "ManMan node (optional)" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Required if multiple nodes in location" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "" | ||||
| "Sync configuration from ManMan " | ||||
| "by entering ManMan location and node name here.<br>" | ||||
| "This will automatically keep name, location and ips " | ||||
| "in sync with the values specified in ManMan." | ||||
| msgstr "" | ||||
| @ -1,17 +0,0 @@ | ||||
| local site_i18n = i18n 'gluon-site' | ||||
| 
 | ||||
| local uci = require('simple-uci').cursor() | ||||
| 
 | ||||
| local msg | ||||
| 
 | ||||
| if uci:get_bool('gluon-manman-sync', 'sync', 'enabled') then | ||||
| 	msg = site_i18n._translate('gluon-config-mode:manman') | ||||
| else | ||||
| 	msg = site_i18n._translate('gluon-config-mode:no-manman') | ||||
| end | ||||
| 
 | ||||
| if not msg then return end | ||||
| 
 | ||||
| renderer.render_string(msg, { | ||||
| 	location_id = uci:get('gluon-manman-sync', 'sync', 'location_id') | ||||
| }) | ||||
| @ -1,46 +0,0 @@ | ||||
| return function(form, uci) | ||||
| 	local pkg_i18n = i18n 'gluon-config-mode-manman-sync' | ||||
| 
 | ||||
| 	local msg = pkg_i18n.translate( | ||||
| 		'Sync configuration from ManMan ' .. | ||||
| 			'by entering ManMan location and node name here.<br>' .. | ||||
| 		'This will automatically keep name, location and ips ' .. | ||||
| 			'in sync with the values specified in ManMan.' | ||||
| 	) | ||||
| 
 | ||||
| 	local s = form:section(Section, nil, msg) | ||||
| 
 | ||||
| 	local o | ||||
| 
 | ||||
| 	local manman = s:option(Flag, 'manman_sync', pkg_i18n.translate('Enable ManMan sync')) | ||||
| 	manman.default = uci:get_bool('gluon-manman-sync', 'sync', 'enabled') | ||||
| 	function manman:write(data) | ||||
| 		uci:set('gluon-manman-sync', 'sync', 'enabled', data) | ||||
| 	end | ||||
| 
 | ||||
| 	local id = s:option(Value, 'manman_location', pkg_i18n.translate('ManMan location')) | ||||
| 	id:depends(manman, true) | ||||
| 	id.default = uci:get('gluon-manman-sync', 'sync', 'location') | ||||
| 	id.datatype = 'maxlength(16)' | ||||
| 	function id:write(data) | ||||
| 		-- clear ID, gets fetched from manman-sync | ||||
| 		uci:set('gluon-manman-sync', 'sync', 'location_id', nil) | ||||
| 
 | ||||
| 		uci:set('gluon-manman-sync', 'sync', 'location', data) | ||||
| 	end | ||||
| 
 | ||||
| 	local id = s:option(Value, 'manman_node', pkg_i18n.translate('ManMan node (optional)'), pkg_i18n.translate('Required if multiple nodes in location')) | ||||
| 	id:depends(manman, true) | ||||
| 	id.default = uci:get('gluon-manman-sync', 'sync', 'node') | ||||
| 	id.datatype = 'maxlength(16)' | ||||
| 	function id:write(data) | ||||
| 		-- clear ID, gets fetched from manman-sync | ||||
| 		uci:set('gluon-manman-sync', 'sync', 'node_id', nil) | ||||
| 
 | ||||
| 		uci:set('gluon-manman-sync', 'sync', 'node', data) | ||||
| 	end | ||||
| 
 | ||||
| 	function s:write() | ||||
| 		uci:save('gluon-manman-sync') | ||||
| 	end | ||||
| end | ||||
| @ -1,24 +0,0 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-manman-sync | ||||
| PKG_VERSION:=1 | ||||
| 
 | ||||
| include ../gluon.mk | ||||
| 
 | ||||
| define Package/gluon-manman-sync | ||||
|   DEPENDS:=+gluon-core +micrond +luci-lib-ip +luci-lib-httpclient +gluon-lib-ecdsa | ||||
|   TITLE:=Sync configuration with data from manman | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-manman-sync/install | ||||
| 	$(Gluon/Build/Install) | ||||
| 
 | ||||
| 	# httpclient depends on util depends on template.parser & sys.zoneinfo which is from +luci-base | ||||
| 	# +luci-base is quite big and unnesesarry. stubbing the files is enough to make it work. | ||||
| 	$(INSTALL_DIR) $(1)/usr/lib/lua/luci/template | ||||
| 	touch $(1)/usr/lib/lua/luci/template/parser.lua | ||||
| 	$(INSTALL_DIR) $(1)/usr/lib/lua/luci/sys | ||||
| 	touch $(1)/usr/lib/lua/luci/sys/zoneinfo.lua | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackageGluon,gluon-manman-sync)) | ||||
| @ -1,2 +0,0 @@ | ||||
| -- need_array_of(in_site({'manman', 'api'}), string(), false) | ||||
| need_string(in_site({'manman', 'key'}), false) | ||||
| @ -1,14 +0,0 @@ | ||||
| package gluon-manman-sync | ||||
| 
 | ||||
| config sync 'sync' | ||||
| 	option enabled '0' | ||||
|   option location_id '' | ||||
| 	option node '' | ||||
|   option last_data_hash '' | ||||
|   option last_data '' | ||||
| 
 | ||||
| config rollback 'rollback' | ||||
|   option success '1' | ||||
|   option checked_at '' | ||||
|   option previous_hash '' | ||||
|   option new_hash '' | ||||
| @ -1,21 +0,0 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| -- Setup a cron for manman-sync if enabled | ||||
| 
 | ||||
| local uci = require('simple-uci').cursor() | ||||
| 
 | ||||
| local urandom = io.open('/dev/urandom', 'r') | ||||
| local seed1, seed2 = urandom:read(2):byte(1, 2) | ||||
| math.randomseed(seed1*0x100 + seed2) | ||||
| urandom:close() | ||||
| 
 | ||||
| -- Perform sync at a random time each hour | ||||
| local minute = math.random(0, 59) | ||||
| 
 | ||||
| local f = io.open('/usr/lib/micron.d/manman-sync', 'w') | ||||
| -- Only setup cron if enabled | ||||
| -- Write file regardless to clear old cron | ||||
| if uci:get_bool('gluon-manman-sync', 'sync', 'enabled') then | ||||
|   f:write(string.format('%i * * * * /usr/bin/manman-sync sync\n', minute)) | ||||
| end | ||||
| f:close() | ||||
| @ -1,422 +0,0 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local uci = require('simple-uci').cursor() | ||||
| local ip = require 'luci.ip' -- luci-lib-ip | ||||
| local fetch = require 'luci.httpclient' | ||||
| local json = require 'luci.jsonc' | ||||
| local ecdsa = require 'gluon.ecdsa' | ||||
| local site = require 'gluon.site' | ||||
| 
 | ||||
| local pretty_hostname = require 'pretty_hostname' | ||||
| local hostname = pretty_hostname.get(uci) | ||||
| 
 | ||||
| local manapi = site.manman.api() | ||||
| local mankey = site.manman.key() | ||||
| 
 | ||||
| -- CLI lib from olsrd-cli (TODO: move to it's own lib package) | ||||
| -- DO NOT EDIT HERE, JUST COPY FROM THERE | ||||
| 
 | ||||
| function printf(...) | ||||
| 	print(string.format(...)) | ||||
| end | ||||
| 
 | ||||
| -- Print contents of `tbl`, with indentation. | ||||
| -- `indent` sets the initial level of indentation. | ||||
| -- src https://gist.github.com/xytis/5361405 | ||||
| function tprint (tbl, indent) | ||||
|   if not indent then indent = 0 end | ||||
|   for k, v in pairs(tbl) do | ||||
|     formatting = string.rep('  ', indent) .. k .. ': ' | ||||
|     if type(v) == 'table' then | ||||
|       print(formatting) | ||||
|       tprint(v, indent + 1) | ||||
|     else | ||||
|       print(formatting .. tostring(v)) | ||||
|     end | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| -- src https://stackoverflow.com/a/24823383/3990041 | ||||
| function table.slice(tbl, first, last, step) | ||||
|   local sliced = {} | ||||
| 
 | ||||
|   for i = first or 1, last or #tbl, step or 1 do | ||||
|     sliced[#sliced+1] = tbl[i] | ||||
|   end | ||||
| 
 | ||||
|   return sliced | ||||
| end | ||||
| 
 | ||||
| -- CLI lib | ||||
| 
 | ||||
| function exec_cmd(args, sub) | ||||
| 	if sub[args[1]] == nil then | ||||
| 		return cmd_err('does not exist') | ||||
| 	else | ||||
| 		local cmd = sub[args[1]] | ||||
| 		if cmd[3] ~= nil and #args > 1 then | ||||
| 			exec_cmd(table.slice(args, 2), cmd[3]) | ||||
| 		else | ||||
| 			cmd[1](unpack(table.slice(args, 2))) | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
| 
 | ||||
| function list_cmd(level, sub) | ||||
| 	for key, cmd in pairs(sub) do | ||||
| 		printf('%s%s: %s', string.rep('  ', level), key, cmd[2]) | ||||
| 		if cmd[3] ~= nil then | ||||
| 			list_cmd(level + 1, cmd[3]) | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
| 
 | ||||
| function show_help() | ||||
| 	printf('Usage: %s <command>', arg[0]) | ||||
| 	list_cmd(1, sub) | ||||
| end | ||||
| 
 | ||||
| function cmd_err(msg, no_show_help) | ||||
| 	-- since argv0 is at... well... 0... even though this is lua... | ||||
| 	--- ...slice just returns arg without argv0 as the for starts at 1 | ||||
| 	printf('Error: Command "%s" %s', table.concat(table.slice(arg), ' '), msg) | ||||
| 	if not no_show_help then | ||||
| 		printf('') | ||||
| 		show_help() | ||||
| 	end | ||||
| 	os.exit(2) | ||||
| end | ||||
| 
 | ||||
| function dummy() | ||||
| 	cmd_err('requires a subcommand') | ||||
| end | ||||
| 
 | ||||
| -- /// | ||||
| 
 | ||||
| -- NOTE: these will have mesh_ appended for static-ip | ||||
| local mappings = { | ||||
|   wifi = 'radio0', | ||||
|   tunnel = 'vpn', | ||||
|   eth = 'other', | ||||
|   lan = 'other', | ||||
|   wan = 'uplink', | ||||
|   single = 'uplink', | ||||
| } | ||||
| 
 | ||||
| -- https://stackoverflow.com/a/1647577/3990041 | ||||
| function string:split(pat) | ||||
|   pat = pat or '%s+' | ||||
|   local st, g = 1, self:gmatch("()("..pat..")") | ||||
|   local function getter(segs, seps, sep, cap1, ...) | ||||
|     st = sep and seps + #sep | ||||
|     return self:sub(segs, (seps or 0) - 1), cap1 or sep, ... | ||||
|   end | ||||
|   return function() if st then return getter(st, g()) end end | ||||
| end | ||||
| 
 | ||||
| -- https://gist.github.com/Uradamus/10323382 | ||||
| local function shuffle(tbl) | ||||
|   for i = #tbl, 2, -1 do | ||||
|     local j = math.random(i) | ||||
|     tbl[i], tbl[j] = tbl[j], tbl[i] | ||||
|   end | ||||
|   return tbl | ||||
| end | ||||
| 
 | ||||
| local function fetch_signed_json(remote, url) | ||||
|   print('GET ' .. url) | ||||
| 
 | ||||
|   local code, res, result = fetch.request_raw(remote .. url) | ||||
| 
 | ||||
|   if code < 1 then | ||||
|     print('E: failed to fetch') | ||||
|     return 1 | ||||
|   end | ||||
| 
 | ||||
|   if code == 404 then | ||||
|     print('E: location does not exist') | ||||
|     return 2 | ||||
|   end | ||||
| 
 | ||||
|   if code ~= 200 then | ||||
|     print('E: got status code ' .. code) | ||||
|     return 1 | ||||
|   end | ||||
| 
 | ||||
|   -- cloudflare's reverse proxies send http chunked responses with chunk sizes | ||||
|   -- for whatever reasons the chunk size gets smashed into the result | ||||
|   -- this is a hack to fish it out, it is irrelevant on unaffected reverse proxies | ||||
|   local j_start = result:find('{') | ||||
|   local j_end = (result:reverse()):find("}") | ||||
|   result = string.sub(result, j_start, (1 - j_end) > 0 and (1 - j_end) or nil) | ||||
| 
 | ||||
|   local sig = res.headers['x-ecdsa'] | ||||
|   local ts = res.headers['x-ecdsa-ts'] | ||||
| 
 | ||||
|   if not sig or not ts then | ||||
|     print('E: provided response is not signed') | ||||
|     return 1 | ||||
|   end | ||||
| 
 | ||||
|   local data = ts .. '@' .. result | ||||
|   if not ecdsa.verify(data, sig, mankey) then | ||||
|     print('E: signature invalid or not signed with expected key') | ||||
|     return 1 | ||||
|   end | ||||
| 
 | ||||
|   local obj = json.parse(result) | ||||
| 
 | ||||
|   if obj == nil then | ||||
|     print('E: failed to parse json data') | ||||
|     return 1 | ||||
|   end | ||||
| 
 | ||||
|   return false, obj | ||||
| end | ||||
| 
 | ||||
| local function do_manman_sync() | ||||
|   if not uci:get('gluon-manman-sync', 'sync', 'location_id') and not uci:get('gluon-manman-sync', 'sync', 'location') then | ||||
|     print('E: manman location missing') | ||||
|     return 2 | ||||
|   end | ||||
| 
 | ||||
|   -- check manman reachability, abort if not reachable | ||||
| 
 | ||||
|   local working_remote | ||||
| 
 | ||||
|   for _, remote in ipairs(shuffle(manapi)) do | ||||
|     if not working_remote then -- don't try other remotes if we got one that works | ||||
|       print('Trying remote ' .. remote) | ||||
| 
 | ||||
|       local success, a, b, c = pcall(function() return fetch.request_raw(remote .. '/') end) | ||||
|       if not success then | ||||
|         print('E: couldnt reach manman: ' .. a) | ||||
|       else | ||||
|         if a ~= 200 then | ||||
|           print('E: couldnt reach manman - unexpected fetch result', a, b, c) | ||||
|         else | ||||
|           working_remote = remote | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   if not working_remote then | ||||
|     print('E: couldnt reach any manapi server, giving up') | ||||
|     return 1 | ||||
|   end | ||||
| 
 | ||||
|   -- try to fetch data | ||||
|   print('Fetching manman data...') | ||||
|   local location_id = uci:get('gluon-manman-sync', 'sync', 'location_id') | ||||
|   local location = uci:get('gluon-manman-sync', 'sync', 'location') | ||||
| 
 | ||||
|   if not location_id and location then | ||||
|     local err, resp = fetch_signed_json(working_remote, '/find_location_by_name/' .. location) | ||||
|     if err then | ||||
|       return err | ||||
|     end | ||||
| 
 | ||||
|     if not resp.id then | ||||
|       printf('E: location %s is invalid (404)', location) | ||||
|       return 2 | ||||
|     end | ||||
| 
 | ||||
|     uci:set('gluon-manman-sync', 'sync', 'location_id', resp.id) | ||||
|     location_id = resp.id | ||||
|   end | ||||
| 
 | ||||
|   local err, location = fetch_signed_json(working_remote, '/location/show/' .. location_id) | ||||
|   if err then | ||||
|     return err | ||||
|   end | ||||
| 
 | ||||
|   print('Syncing with location ' .. location.location.name) | ||||
| 
 | ||||
|   uci:set('gluon-manman-sync', 'sync', 'location', location.location.name) | ||||
| 
 | ||||
|   if uci:get('gluon-manman-sync', 'sync', 'last_data') and json.stringify(location) == uci:get('gluon-manman-sync', 'sync', 'last_data') then | ||||
|     print('Nothing changed, skipping sync') | ||||
|     return 0 | ||||
|   end | ||||
| 
 | ||||
|   local local_router_id | ||||
|   for id, _ in string.split(hostname, '-') do | ||||
|     if id then | ||||
|       local_router_id = id | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   local local_node_name = uci:get('gluon-manman-sync', 'sync', 'node') or local_router_id | ||||
|   local local_node = uci:get('gluon-manman-sync', 'sync', 'node_id') or local_router_id | ||||
|   local node | ||||
|   local should_hostname | ||||
| 
 | ||||
|   if #location.nodes > 1 then | ||||
|     for _, potential_node in ipairs(location.nodes) do | ||||
|       if (local_node ~= nil and tostring(potential_node.id) == local_node) or (local_node_name ~= nil and potential_node.name == local_node_name) then | ||||
|         node = potential_node | ||||
|         should_hostname = location.location.name .. '-' .. node.name | ||||
|       end | ||||
|     end | ||||
|   else | ||||
|     node = location.nodes[1] | ||||
|     should_hostname = location.location.name | ||||
|   end | ||||
| 
 | ||||
|   -- save node data to update name and persist ID | ||||
|   uci:set('gluon-manman-sync', 'sync', 'node_id', node.id) | ||||
|   uci:set('gluon-manman-sync', 'sync', 'node', node.name) | ||||
| 
 | ||||
|   if node == nil then | ||||
|     print('E: unable to find matching node (selector "' .. node .. '")') | ||||
|     return 2 | ||||
|   end | ||||
| 
 | ||||
|   print('Syncing data for node ' .. node.name) | ||||
| 
 | ||||
|   if hostname ~= should_hostname then | ||||
|     print('Renaming node to ' .. should_hostname) | ||||
|     pretty_hostname.set(uci, should_hostname) | ||||
|   end | ||||
| 
 | ||||
|   local owner = uci:get_first('gluon-node-info', 'owner') | ||||
|   uci:set('gluon-node-info', owner, 'contact', location.administrator.email) | ||||
|   local _location = uci:get_first('gluon-node-info', 'location') | ||||
|   uci:set('gluon-node-info', _location, 'share_location', '1') | ||||
|   uci:set('gluon-node-info', _location, 'latitude', location.location.lat) | ||||
|   uci:set('gluon-node-info', _location, 'longitude', location.location.long) | ||||
| 
 | ||||
|   -- check if anything changed since last time | ||||
|   -- if yes, apply changes and do gluon-reload | ||||
| 
 | ||||
|   local has_changes = false | ||||
| 
 | ||||
|   -- Use this when changing something that needs a reload and/or rollback (not the hostname) | ||||
|   local function set(a, b, c, d, isbool) | ||||
|     local curval | ||||
| 
 | ||||
|     if isbool then | ||||
|       curval = uci:get_bool(a, b, c) | ||||
|     else | ||||
|       curval = uci:get(a, b, c) | ||||
|     end | ||||
| 
 | ||||
|     if curval ~= d then | ||||
|       uci:set(a, b, c, d) | ||||
|       print('  Value', a, b, c, 'changed to', d, 'was', curval) | ||||
|       has_changes = true | ||||
|     else | ||||
|       print('  Value', a, b, c, 'unchanged', d) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   local has_tunnel = false | ||||
| 
 | ||||
|   for _, net in ipairs(node.interfaces) do | ||||
|     local net_name = net.name | ||||
|     if net_name == 'tunnel' or net_name == 'vpn' or net_name == 'mesh_vpn' then | ||||
|       has_tunnel = true | ||||
|     end | ||||
|     local net_mapped = mappings[net_name] or net_name | ||||
|     if not string.find(net_mapped, '_') then | ||||
|       net_mapped = 'mesh_' .. net_mapped | ||||
|     end | ||||
| 
 | ||||
|     local cidr = ip.new(net.ip, net.netmask):string() | ||||
| 
 | ||||
|     print('Syncing ' .. net_name .. ' as ' .. net_mapped .. ' to ' .. cidr) | ||||
|     set('gluon-static-ip', net_mapped, 'ip4', cidr) | ||||
|   end | ||||
| 
 | ||||
|   print('Syncing mesh vpn: ' .. (has_tunnel and 'on' or 'off')) | ||||
|   set('gluon', 'mesh_vpn', 'enabled', has_tunnel, true) | ||||
| 
 | ||||
|   uci:set('gluon-manman-sync', 'sync', 'last_data', json.stringify(location)) | ||||
| 
 | ||||
|   uci:save('system') | ||||
|   uci:save('gluon') | ||||
|   uci:save('gluon-manman-sync') | ||||
|   uci:save('gluon-static-ip') | ||||
|   uci:save('gluon-node-info') | ||||
|   os.execute('exec uci commit') | ||||
| 
 | ||||
|   if has_changes then | ||||
|     print('Applying changes...') | ||||
|     os.execute('exec gluon-reconfigure') | ||||
|     os.execute('exec gluon-reload') | ||||
|   else | ||||
|     print('No settings changes, no reason to reload') | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| local function maybe_sync() | ||||
|   if uci:get_bool('gluon-manman-sync', 'sync', 'enabled') then | ||||
|     do_manman_sync() | ||||
|   else | ||||
|     print('manman-sync not enabled, skipping') | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| local function enable_sync(location, node) | ||||
|   if not uci:get('gluon-manman-sync', 'sync', 'location') and not uci:get('gluon-manman-sync', 'sync', 'location_id') and not location then | ||||
|     cmd_err('requires at least a location (No location was found in config)', true) | ||||
|   end | ||||
| 
 | ||||
|   if location then | ||||
|     printf('Config location %s', location) | ||||
|     uci:set('gluon-manman-sync', 'sync', 'location', location) | ||||
| 		-- clear ID, gets fetched from manman-sync | ||||
| 		uci:set('gluon-manman-sync', 'sync', 'location_id', nil) | ||||
|   end | ||||
| 
 | ||||
|   if node then | ||||
|     printf('Config node %s', node) | ||||
|     uci:set('gluon-manman-sync', 'sync', 'node', node) | ||||
| 		-- clear ID, gets fetched from manman-sync | ||||
| 		uci:set('gluon-manman-sync', 'sync', 'node_id', nil) | ||||
|   end | ||||
| 
 | ||||
|   if not uci:get_bool('gluon-manman-sync', 'sync', 'enabled') then | ||||
|     uci:set('gluon-manman-sync', 'sync', 'enabled', true) | ||||
|     print('Enabled sync.') | ||||
|     print('Trigger with manman-sync sync') | ||||
|   else | ||||
|     print('Sync already enabled.') | ||||
|   end | ||||
| 
 | ||||
|   uci:save('gluon-manman-sync') | ||||
| end | ||||
| 
 | ||||
| local function disable_sync() | ||||
|   if uci:get_bool('gluon-manman-sync', 'sync', 'enabled') then | ||||
|     uci:set('gluon-manman-sync', 'sync', 'enabled', false) | ||||
|     print('Disabled sync.') | ||||
|     uci:save('gluon-manman-sync') | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| local function show_info() | ||||
|   tprint({ | ||||
|     enabled = uci:get_bool('gluon-manman-sync', 'sync', 'enabled'), | ||||
|     location = string.format('%s (id %s)', | ||||
|       uci:get('gluon-manman-sync', 'sync', 'location') or '[none]', | ||||
|       uci:get('gluon-manman-sync', 'sync', 'location_id') or '[will autodetect]' | ||||
|     ), | ||||
|     node = string.format('%s (id %s)', | ||||
|       uci:get('gluon-manman-sync', 'sync', 'node') or '[none - use only available or error]', | ||||
|       uci:get('gluon-manman-sync', 'sync', 'node_id') or '[will autodetect]' | ||||
|     ), | ||||
|   }) | ||||
| end | ||||
| 
 | ||||
| sub = { | ||||
| 	info = { show_info, 'Show manman-sync configuration' }, | ||||
| 	help = { show_help, 'Show help' }, | ||||
|   sync = { maybe_sync, 'Trigger a manman-sync' }, | ||||
|   force_sync = { do_manman_sync, 'Trigger a manman-sync, despite being disabled' }, | ||||
|   enable = { enable_sync, 'Enable sync. [<location>] [<node>]' }, | ||||
|   disable = { disable_sync, 'Disable sync.' } | ||||
| } | ||||
| 
 | ||||
| exec_cmd(table.slice(arg), sub) | ||||
| @ -1,6 +0,0 @@ | ||||
| all: respondd.so | ||||
| 
 | ||||
| CFLAGS += -Wall | ||||
| 
 | ||||
| respondd.so: respondd.c | ||||
| 	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -luci | ||||
| @ -1,78 +0,0 @@ | ||||
| /*
 | ||||
|   Copyright (c) 2016, Matthias Schiffer <mschiffer@universe-factory.net> | ||||
|   All rights reserved. | ||||
| 
 | ||||
|   Redistribution and use in source and binary forms, with or without | ||||
|   modification, are permitted provided that the following conditions are met: | ||||
| 
 | ||||
|     1. Redistributions of source code must retain the above copyright notice, | ||||
|        this list of conditions and the following disclaimer. | ||||
|     2. Redistributions in binary form must reproduce the above copyright notice, | ||||
|        this list of conditions and the following disclaimer in the documentation | ||||
|        and/or other materials provided with the distribution. | ||||
| 
 | ||||
|   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
|   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||
|   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
|   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
|   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
|   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||
|   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
|   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| #include <respondd.h> | ||||
| 
 | ||||
| #include <json-c/json.h> | ||||
| #include <libgluonutil.h> | ||||
| 
 | ||||
| #include <uci.h> | ||||
| 
 | ||||
| #include <string.h> | ||||
| 
 | ||||
| 
 | ||||
| static struct json_object * get_autoupdater(void) { | ||||
| 	struct uci_context *ctx = uci_alloc_context(); | ||||
| 	if (!ctx) | ||||
| 		return NULL; | ||||
| 	ctx->flags &= ~UCI_FLAG_STRICT; | ||||
| 
 | ||||
| 	struct uci_package *p; | ||||
| 	if (uci_load(ctx, "gluon-manman-sync", &p)) | ||||
| 		goto error; | ||||
| 
 | ||||
| 	struct uci_section *s = uci_lookup_section(ctx, p, "sync"); | ||||
| 	if (!s) | ||||
| 		goto error; | ||||
| 
 | ||||
| 	struct json_object *ret = json_object_new_object(); | ||||
| 
 | ||||
| 	json_object_object_add(ret, "location_id", gluonutil_wrap_string(uci_lookup_option_string(ctx, s, "location_id"))); | ||||
| 
 | ||||
| 	const char *enabled = uci_lookup_option_string(ctx, s, "enabled"); | ||||
| 	json_object_object_add(ret, "enabled", json_object_new_boolean(enabled && !strcmp(enabled, "1"))); | ||||
| 
 | ||||
| 	uci_free_context(ctx); | ||||
| 
 | ||||
| 	return ret; | ||||
| 
 | ||||
|  error: | ||||
| 	uci_free_context(ctx); | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static struct json_object * respondd_provider_nodeinfo(void) { | ||||
| 	struct json_object *ret = json_object_new_object(); | ||||
| 	json_object_object_add(ret, "manman", get_autoupdater()); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| const struct respondd_provider_info respondd_providers[] = { | ||||
| 	{"nodeinfo", respondd_provider_nodeinfo}, | ||||
| 	{} | ||||
| }; | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user