ソースを参照

ffho-autoupdater-wifi-fallback: huge set of bugfixes an improvements

/etc/config/autoupdater-wifi-fallback
  - just provide a config example

/lib/gluon/upgrade/510-autoupdater-wifi-fallback
  - if ther is no config, copy enable state from autoupdater
  - there is no need for setting the wireless config here
  - set a cron job to execute the wifi-fallback 10 minutes after the autoupdater

/usr/lib/lua/autoupdater-wifi-fallback/util.lua
  - improve get_available_wifi_networks()
    - use iwinfo, so there is no need to use io.poppen()
    - match the SSID to someting containing "Freifunk" (case-insensitive)
  - removed unused functions
    - get_site_macs()
    - is_in_fallback_mode()
    - neighbours()
    - interfaces()
    - get_wifi_neighbours()

/usr/lib/micron.d/autoupdater-wifi-fallback removed
  - the cron job is now prepared by /lib/gluon/upgrade/510-autoupdater-wifi-fallback

/usr/sbin/autoupdater-wifi-fallback
  - don't get min_update_secs from the config, just declare it here
  - remove the debug output
  - parse_args()
    - add new arg -b for feature use
    - add error message
  - preflight_check()
    - do not exit, just return true or false
    - do not check the fastd socket, it exists if fastd is running and does not belong to an established connection
  - connectivity_check()
    - was called check_connectivity() bevore, renamed to be similar to preflight_check()
    - do not check your wifi neighbours, they may have no connection too
    - some little code improvements
  - switch_to_falback_mode(wifiNetwork, radio)
    - we need the radio, too, to connect to the wifiNetwork
    - delete all wifi-ifaces, we will restore them later, don't worry
    - setup config for fallback wifi-iface
    - iw dev <dev> connect -w <ssid>, is not working any more, so we install wpa-suplicant-mini
    - revert the wireless directly after connecting to the AP
  - revert_to_standard_mode()
    - the config is allready restored, so just reinitialize the network
  - is_in_fallback_mode()
    - deleted
    - there is no reason to check this here
  - again no need to check the fastd socket
  - improve unreachable_since, execute os.time() only one time
  - as already mentioned, we need the corresponding radio, to connect to wifiNetwork

ffho-autoupdater-wifi-fallback-legacy: new
  - migration package to migrate from old version to the new one
  - deletes the obsolete config after an upgrade
Karsten Böddeker 8 年 前
コミット
4c71154229

+ 43 - 0
ffho/ffho-autoupdater-wifi-fallback-legacy/Makefile

@@ -0,0 +1,43 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ffho-autoupdater-wifi-fallback-legacy
+PKG_VERSION:=1
+PKG_RELEASE:=$(GLUON_VERSION).$(GLUON_SITE_CODE)-$(GLUON_RELEASE).$(GLUON_CONFIG_VERSION)
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ffho-autoupdater-wifi-fallback-legacy
+  SECTION:=ffho
+  CATEGORY:=Gluon
+  TITLE:=Toolset of scripts for migration of ffho-autoupdater-wifi-fallback.
+  DEPENDS:=+ffho-autoupdater-wifi-fallback
+  MAINTAINER:=Freifunk Hochstift <maschinenraum@paderborn.freifunk.net>
+  URL:=https://git.c3pb.de/freifunk-pb/ffho-packages
+  SOURCE:=git@git.c3pb.de:freifunk-pb/ffho-packages.git
+endef
+
+define Package/ffho-autoupdater-wifi-fallback-legacy/description
+	A collection of scripts that fix and cleanup configurations off
+	ffho-autoupdater-wifi-fallback on a node when upgrading the firmware.
+endef
+
+define Build/Prepare
+	mkdir -p $(PKG_BUILD_DIR)
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+endef
+
+define Package/ffho-autoupdater-wifi-fallback-legacy/preinst
+endef
+
+define Package/ffho-autoupdater-wifi-fallback-legacy/install
+  $(CP) ./files/* $(1)/
+endef
+
+$(eval $(call BuildPackage,ffho-autoupdater-wifi-fallback-legacy))

+ 7 - 0
ffho/ffho-autoupdater-wifi-fallback-legacy/files/lib/gluon/upgrade/505-autoupdater-wifi-fallback-legacy

@@ -0,0 +1,7 @@
+#!/usr/bin/lua
+local uci = require('luci.model.uci').cursor()
+
+if uci:get('autoupdater-wifi-fallback','settings') and uci:get('autoupdater-wifi-fallback','settings','min_uptime_secs') then
+  uci:delete('autoupdater-wifi-fallback','settings')
+  uci:save('autoupdater-wifi-fallback')
+end

+ 1 - 1
ffho/ffho-autoupdater-wifi-fallback/Makefile

@@ -10,7 +10,7 @@ include $(GLUONDIR)/include/package.mk
 define Package/ffho-autoupdater-wifi-fallback
   SECTION:=admin
   CATEGORY:=Administration
-  DEPENDS:=+wireless-tools +autoupdater
+  DEPENDS:=+iwinfo +wpa-supplicant-mini +gluon-autoupdater
   TITLE:=Implements switching to fallback mode if we are cut off from the mesh
 endef
 

+ 2 - 3
ffho/ffho-autoupdater-wifi-fallback/files/etc/config/autoupdater-wifi-fallback

@@ -1,3 +1,2 @@
-config autoupdater-wifi-fallback settings
-	option enabled 1
-	option min_uptime_secs 3600
+#config autoupdater-wifi-fallback settings
+#	option enabled 1

+ 22 - 23
ffho/ffho-autoupdater-wifi-fallback/files/lib/gluon/upgrade/510-autoupdater-wifi-fallback

@@ -1,34 +1,23 @@
 #!/usr/bin/lua
 
 local uci = require 'luci.model.uci'.cursor()
-local site = require 'gluon.site_config'
 local util = require 'gluon.util'
 local fs = require('nixio.fs')
-local sysctl = require 'gluon.sysctl'
 
-local radios = {}
-
-uci:foreach('wireless', 'wifi-device',
-  function(s)
-    table.insert(radios, s['.name'])
-  end
-)
+local enabled = uci:get('autoupdater','settings','enabled')
+if uci:get('autoupdater-wifi-fallback', 'settings') then
+  enabled = uci:get_bool('autoupdater-wifi-fallback', 'settings', 'enabled') and 1 or 0
+  uci:delete('autoupdater-wifi-fallback', 'settings')
+end
 
-for _, radio in ipairs(radios) do
-  uci:delete('wireless', 'fallback')
-  uci:section('wireless', 'wifi-iface', 'fallback',
+uci:section('autoupdater-wifi-fallback','autoupdater-wifi-fallback','settings',
   {
-    device = radio,
-    network = 'fallback',
-    mode = 'sta',
-    ssid = site.wifi24.ap.ssid,
-    disabled = 1,
-    macaddr = util.generate_mac(3, 10),
-    ifname = 'fallback',
-    encryption = 'none',
+    enabled = enabled,
   }
 )
-end
+
+uci:delete('wireless', 'fallback')
+
 uci:delete('network','fallback')
 uci:section('network', 'interface', 'fallback',
   {
@@ -36,7 +25,17 @@ uci:section('network', 'interface', 'fallback',
   }
 )
 
-uci:save('wireless')
+uci:save('autoupdater-wifi-fallback')
 uci:save('network')
-uci:commit('wireless')
+uci:save('wireless')
+
+uci:commit('autoupdater-wifi-fallback')
 uci:commit('network')
+uci:commit('wireless')
+
+local minute = tonumber(fs.readfile('/usr/lib/micron.d/autoupdater'):match('^([0-9][0-9]?)%s'))
+minute = (minute + 10) % 60
+
+local f = io.open('/usr/lib/micron.d/autoupdater-wifi-fallback', 'w')
+f:write(string.format('%i * * * * /usr/sbin/autoupdater-wifi-fallback\n', minute))
+f:close()

+ 18 - 66
ffho/ffho-autoupdater-wifi-fallback/files/usr/lib/lua/autoupdater-wifi-fallback/util.lua

@@ -1,18 +1,25 @@
 #!/usr/bin/lua
-
 local uci = require('luci.model.uci').cursor()
-local site = require 'gluon.site_config'
-local json = require 'luci.jsonc'
-local util = require("luci.util")
+local iwinfo = require "iwinfo"
 
 function get_available_wifi_networks()
-  local interfaces = util.split(util.trim(util.exec("iw dev | grep Interface | cut -d' ' -f2")))
-  for _, ifname in ipairs(interfaces) do
-    for line in io.popen(string.format("iw dev %s scan 2>/dev/null", ifname)):lines() do
-      net = line:match(".+.freifunk.net.*")
-      if net then
-	netname = net:sub(8)
-	return netname
+  local radios = {}
+
+  uci:foreach('wireless', 'wifi-device',
+    function(s)
+      table.insert(radios, s['.name'])
+    end
+  )
+  for _, radio in ipairs(radios) do
+    local wifitype = iwinfo.type(radio)
+    local iw = iwinfo[wifitype]
+    if iw then
+      local list = iw.scanlist(radio)
+      for _, net in ipairs(list) do
+        local ssid = net.ssid:match('.*[Ff][Rr][Ee][Ii][Ff][Uu][Nn][Kk].*')
+        if ssid then
+          return radio, ssid
+        end
       end
     end
   end
@@ -32,58 +39,3 @@ function get_update_hosts()
   end
   return hosts
 end
-
-function get_site_macs()
-  local macs = {}
-  local interfaces = util.split(util.trim(util.exec(string.format("iw dev mesh0 scan | grep -B10 %s | grep BSS | cut -f2 -d' ' | cut -f1 -d'('", site.wifi24.ap.ssid))))
-  for _, mac in ipairs(interfaces) do
-    table.insert(macs, mac)
-  end
-
-  return macs
-end
-
-function is_in_fallback_mode()
-  if uci:get('wireless', 'fallback', 'disabled') == '0' then
-    return true
-  end
-  return false
-end
-
-function neighbours(iface)
-  local stations = {}
-  for k, v in pairs(iface.iw.assoclist(iface.ifname)) do
-    table.insert(stations,k:lower())
-  end
-
-  return stations
-end
-
-function interfaces()
-  local interfaces = {}
-  for _, line in ipairs(util.split(util.exec('batctl if'))) do
-    local ifname = line:match('^(.-): active')
-    if ifname ~= nil then
-      pcall(function()
-        local address = util.trim(fs.readfile('/sys/class/net/' .. ifname .. '/address'))
-        local wifitype = iwinfo.type(ifname)
-        if wifitype ~= nil then
-          interfaces[address] = { ifname = ifname, iw = iwinfo[wifitype] }
-        end
-      end)
-    end
-  end
-
-  return interfaces
-end
-
-function get_wifi_neighbours()
-  local wifi = {}
-  for address, iface in pairs(interfaces()) do
-    wifi[address] = { neighbours = neighbours(iface) }
-  end
-  
-  if next(wifi) then
-    return wifi
-  end
-end

+ 0 - 1
ffho/ffho-autoupdater-wifi-fallback/files/usr/lib/micron.d/autoupdater-wifi-fallback

@@ -1 +0,0 @@
-29 * * * * /usr/sbin/autoupdater-wifi-fallback

+ 68 - 87
ffho/ffho-autoupdater-wifi-fallback/files/usr/sbin/autoupdater-wifi-fallback

@@ -2,72 +2,62 @@
 local fs = require('nixio.fs')
 local uci = require('luci.model.uci').cursor()
 local site = require 'gluon.site_config'
-local iwinfo = require 'iwinfo'
-local configname = 'autoupdater-wifi-fallback'
 local util = require 'luci.util'
-local settings = uci:get_all(configname, 'settings')
 local ut = require('autoupdater-wifi-fallback.util')
-local debug = true
+local gluon = require 'gluon.util'
 
--- parse arguments
+local configname = 'autoupdater-wifi-fallback'
 local force = false
+local min_uptime_secs = 3600
+
+local function parse_args()
 local i = 1
-while arg[i] do
-  if arg[i] == '-f' then
-    print("I will do what you want")
-    force = true
+  while arg[i] do
+    if arg[i] == '-f' then
+      force = true
+    elseif arg[i] == '-b' then
+      i=i+1
+
+      if not arg[i] then
+        io.stderr:write("Error parsing command line: expected branch name\n")
+        os.exit(1)
+      end
+
+      branch_name = arg[i]
+    else
+      io.stderr:write("Error parsing command line: unexpected argument '" .. arg[i] .. "'\n")
+      os.exit(1)
+    end
+    i = i+1
   end
-  i = i+1
 end
 
--- preflight checks
-
-if not force then
-  if settings.enabled ~= '1' or uci:get('autoupdater','settings','enabled') ~= '1' then
-    if debug then io.stderr:write('connectivity checks or autoupdater are disabled.\n') end
-    os.exit(0)
+local function preflight_check()
+  if not uci:get_bool(configname,'settings','enabled') then
+    return false
   end
-  
-  if fs.stat("/tmp/run/fastd.mesh_vpn.socket", "type") == "socket" then
-    if debug then io.stderr:write('we have a valid socket for fastd. no fallback required.\n') end
-    os.exit(0)
+  if not uci:get_bool('autoupdater','settings','enabled') then
+    return false
   end
-  
-  if tonumber(fs.readfile('/proc/uptime'):match('^([^ ]+) ')) < tonumber(settings.min_uptime_secs) then
-    if debug then io.stderr:write('we just booted. check skipped.\n') end
-    os.exit(0)
+  if tonumber(fs.readfile('/proc/uptime'):match('^([^ ]+) ')) < min_uptime_secs then
+    return false
   end
+
+  return true
 end
 
-local function check_connectivity()
-  local f = io.open("/sys/kernel/debug/batman_adv/bat0/gateways","r")
-  if f ~= nil then
-    f:close()
-    local wifi = get_wifi_neighbours()
-    if wifi ~= nil then
-      for key, interface in ipairs(wifi) do                                          
-        if os.execute(string.format("batctl ping -t5 -c1 %s > /dev/null 2>&1", interface)) == 0 then
-              return true
-        end
-      end
-    end 
-    
-    local list = io.lines("/sys/kernel/debug/batman_adv/bat0/gateways")
-    for line in list do
-      local gateway_mac = line:match("^=?>? +([0-9a-f:]+)")
-      if gateway_mac ~= nil then
-        if os.execute(string.format("batctl ping -t5 -c1 %s > /dev/null 2>&1", gateway_mac)) == 0 then
-          return true
-        end
+local function connectivity_check()
+  for line in io.lines("/sys/kernel/debug/batman_adv/bat0/gateways") do
+    local gateway_mac = line:match("^=?>? +([0-9a-f:]+)")
+    if gateway_mac then
+      if os.execute("batctl ping -t5 -c1 " .. gateway_mac .. " > /dev/null 2>&1") == 0 then
+        return true
       end
     end
   end
-
   
   -- connectivity check against updateserver
-  local updateHosts = get_update_hosts()
-  while #updateHosts > 0 do
-    host = table.remove(updateHosts)
+  for _, host in ipairs(get_update_hosts()) do
     if os.execute("ping -w2 -c1 " .. host .. " > /dev/null 2>&1") == 0 then
       return true
     end
@@ -77,69 +67,60 @@ local function check_connectivity()
 end
 
 local function run_autoupdater()
-  -- TODO:should be called with -f !
   os.execute("/usr/sbin/autoupdater -f")
 end
 
-local function switch_to_fallback_mode(wifiNetwork)
-  print("I will connect to: " .. wifiNetwork)
-  local disabled_radios = {'fallback'}
-  uci:foreach('wireless', 'wifi-iface',
-        function(s)
-          uci:set('wireless', s['.name'], 'disabled', '1')
-        end
+local function switch_to_fallback_mode(wifiNetwork, radio)
+  print("connect to: " .. wifiNetwork .. " on " .. radio)
+  uci:delete_all('wireless', 'wifi-iface')
+  uci:section('wireless', 'wifi-iface', 'fallback',
+    {
+      device = radio,
+      network = 'fallback',
+      mode = 'managed',
+      disabled = 0,
+      macaddr = gluon.generate_mac(3, 10),
+      ifname = 'fallback',
+      encryption = 'none',
+      ssid = wifiNetwork,
+    }
   )
-  
-  uci:set('wireless', 'fallback', 'ssid', wifiNetwork) 
-  uci:set('wireless', 'fallback', 'disabled', 0)
+  uci:set('wireless', radio, 'disabled', 0)
   uci:save('wireless')
 
   io.popen("wifi")
   os.execute("sleep 5")
-  os.execute("iw dev fallback connect -w " .. wifiNetwork)
   os.execute("echo \"2\" > /proc/sys/net/ipv6/conf/fallback/accept_ra")
+  uci:revert('wireless')
   os.execute("sleep 20")
 end
 
-local function revert_to_standard_mode(restart_network)
+local function revert_to_standard_mode()
   print("Going back to standard config")
-  uci:revert('wireless')
-  uci:save('wireless')
-  if restart_network then
-    os.execute("/etc/init.d/network restart")
-    os.execute("sleep 30")
-  end
+  os.execute("/etc/init.d/network restart")
+  os.execute("sleep 30")
 end
 
-if is_in_fallback_mode() then
-    revert_to_standard_mode(false)
-    run_autoupdater()
-    -- if there really is a firmware update, we should not reach this point
-    os.execute("/etc/init.d/network restart")
-    os.exit(0)
-end
+parse_args()
 
-if not check_connectivity() then
+if (force or preflight_check()) and not connectivity_check() then
   local offset = 2 * 3600
-  if fs.stat("/tmp/run/fastd.mesh_vpn.socket", "type") == "socket" then offset = 4 * 3600 end
-  local unreachable_since = settings.unreachable_since
-  if unreachable_since == nil then 
-    uci:set(configname, 'settings', 'unreachable_since', os.time())
-    unreachable_since = os.time()
+  local unreachable_since = os.time()
+  if not uci:get('autoupdater-wifi-fallback', 'settings', 'unreachable_since') then
+    uci:set(configname, 'settings', 'unreachable_since', unreachable_since)
   else
-    uci:set(configname, 'settings', 'last_run', os.time())
+    uci:set(configname, 'settings', 'last_run', unreachable_since)
+    unreachable_since = uci:get(configname, 'settings', 'unreachable_since')
   end
   uci:save(configname)
   
-  if tonumber(unreachable_since) + offset < os.time() or force then
-    wifiNetwork = get_available_wifi_networks()
+  if force or tonumber(unreachable_since) + offset < os.time() then
+    local radio, wifiNetwork = get_available_wifi_networks()
     if wifiNetwork then
-      switch_to_fallback_mode(wifiNetwork)
-
+      switch_to_fallback_mode(wifiNetwork, radio)
       run_autoupdater()
-      
       -- this is only reached if no updated happened
-      revert_to_standard_mode(true)
+      revert_to_standard_mode()
     end
   end
 else