From 5c046474a32d44b59d725f0e671cf48eae86c834 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Sat, 17 Aug 2019 19:15:58 +0200 Subject: [PATCH 01/21] tests-scheduler first draft --- packages/tests-scheduler/Makefile | 47 ++++++ .../files/bin/tests-scheduler-at.lua | 156 ++++++++++++++++++ .../files/bin/tests-scheduler-probe.lua | 111 +++++++++++++ .../files/etc/config/tests-scheduler | 11 ++ .../etc/uci-defaults/50_tests-scheduler-probe | 12 ++ .../etc/uci-defaults/51_tests-scheduler-at | 15 ++ 6 files changed, 352 insertions(+) create mode 100644 packages/tests-scheduler/Makefile create mode 100644 packages/tests-scheduler/files/bin/tests-scheduler-at.lua create mode 100644 packages/tests-scheduler/files/bin/tests-scheduler-probe.lua create mode 100644 packages/tests-scheduler/files/etc/config/tests-scheduler create mode 100644 packages/tests-scheduler/files/etc/uci-defaults/50_tests-scheduler-probe create mode 100644 packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at diff --git a/packages/tests-scheduler/Makefile b/packages/tests-scheduler/Makefile new file mode 100644 index 000000000..42e316849 --- /dev/null +++ b/packages/tests-scheduler/Makefile @@ -0,0 +1,47 @@ +# +# Copyright (C) 2019 Ilario Gelmetti +# +# This is free software, licensed under the GNU General Public License v3. +# + +include $(TOPDIR)/rules.mk + +GIT_COMMIT_DATE:=$(shell git log -n 1 --pretty=%ad --date=short . ) +GIT_COMMIT_TSTAMP:=$(shell git log -n 1 --pretty=%at . ) + +PKG_NAME:=tests-scheduler +PKG_VERSION=$(GIT_COMMIT_DATE)-$(GIT_COMMIT_TSTAMP) + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) + CATEGORY:=LiMe + TITLE:=Tests scheduler at peak and night time + MAINTAINER:=Ilario Gelmetti + URL:=https://libremesh.org + DEPENDS:=+at + PKGARCH:=all +endef + +define Package/$(PKG_NAME)/config +endef + +define Package/$(PKG_NAME)/description + Monitors the number of clients of the network for each hour, + uses this information for scheduling tests at the peak time and/or at the night time. +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/install + $(INSTALL_DIR) $(1)/bin/ + $(INSTALL_DIR) $(1)/etc/uci-defaults/ + $(INSTALL_DIR) $(1)/etc/config/ + $(INSTALL_BIN) ./files/bin/test-scheduler-at.lua $(1)/bin/tests-scheduler-at + $(INSTALL_BIN) ./files/bin/test-scheduler-probe.lua $(1)/bin/tests-scheduler-probe + $(INSTALL_BIN) ./files/etc/uci-defaults/* $(1)/etc/uci-defaults + $(INSTALL_CONF) ./files/etc/config/tests-scheduler $(1)/etc/config/ +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/packages/tests-scheduler/files/bin/tests-scheduler-at.lua b/packages/tests-scheduler/files/bin/tests-scheduler-at.lua new file mode 100644 index 000000000..640071d15 --- /dev/null +++ b/packages/tests-scheduler/files/bin/tests-scheduler-at.lua @@ -0,0 +1,156 @@ +#!/usr/bin/lua + +local JSON = require("luci.jsonc") + +local libuci_loaded, libuci = pcall(require, "uci") + +local function config_uci_get(option) + local result + if libuci_loaded then + result = libuci:cursor():get("tests-scheduler","at",option) + else + result = nil + end + return result +end + +local peakTestsList = config_uci_get(peak_test) or {arg[1]} + +local nightTestsList = config_uci_get(night_test) or {arg[2]} + +local dataFile = config_uci_get(data_file) or "/tmp/tests-scheduler-probe-data" + +-- see if the file exists +function file_exists(file) + local f = io.open(file, "rb") + if f then f:close() end + return f ~= nil +end + +-- get all lines from a file, returns an empty +-- list/table if the file does not exist +function lines_from(file) + if not file_exists(file) then return {} end + local lines = {} + for line in io.lines(file) do + lines[#lines + 1] = line + end + return lines +end + + +local function do_split(str,pat) + local tbl = {} + str:gsub(pat, function(x) tbl[#tbl+1]=x end) + return tbl +end + +local function max(t) + if #t == 0 then return nil, nil end + local key, value = 1, tonumber(t[1]) + for i = 2, #t do + temp = tonumber(t[i]) + if value < temp then + key, value = i, temp + end + end + return key, value +end + +local function min(t) + if #t == 0 then return nil, nil end + local key, value = 1, tonumber(t[1]) + for i = 2, #t do + temp = tonumber(t[i]) + if value > temp then + key, value = i, temp + end + end + return key, value +end + +local data = lines_from(dataFile) +local complete = true +for _,val in pairs(data) do + if not tonumber(val) then + complete = false + break + end +end + +if complete then + io.stderr:write("Found enough data in "..dataFile..", continuing.\n") + local peakHour1,_ = max(data) + local peakHour = peakHour1 - 1 + for _,peakCommand in pairs(peakTestsList) do + local peakAt = "echo '"..peakCommand.."' | at -Mv "..peakHour..":30 2>&1" + local handlePeakAt = io.popen(peakAt, 'r') + local peakAtRaw = handlePeakAt:read("*a") + handlePeakAt:close() + local peakAtTime = do_split(peakAtRaw,"%C+")[1] + print(peakAtTime.."\t"..peakCommand) + end + if nightTestsList then + local datatemp = data + local nightHours = {} + for i = 1,6 do + nightHour1,_ = min(datatemp) + nightHours[i] = nightHour1 - 1 + datatemp[nightHour1] = math.huge + end + + local getCommand = "shared-state get tests-scheduler-night" + local handleAllTimesJson = io.popen(getCommand, "r") + local allTimesJson = handleAllTimesJson:read("*a") + handleAllTimesJson:close() + local allTimes = {} + for _,value in pairs(JSON.parse(allTimeJson)) do + allTimes[#allTimes + 1] = tonumber(value.data) + end + + local hitsHours = {0,0,0,0,0,0} + for _,val in pairs(allTimes) do + for i = 1,6 do + local valHour = int(val/60) + if valHour == nightHours[i] then + hitsHours[i] = hitsHours[i] + 1 + break + end + end + end + + local minHourIndex,_ = min(hitsHours) + local nightHour = nightHours[minHourIndex] + + local hits5minute = {0,0,0,0,0,0,0,0,0,0,0,0} + for _,val in pairs(allTimes) do + local valHour = int(val/60) + if valHour == nightHour then + local val5minute = 1 + int((val%60)/5) + hits5minute[val5minute] = hits5minute[val5minute] + 1 + end + end + + local min5minute1,_ = min(hits5minute) + local min5minute = min5minute1 - 1 + local nightMinute = min5minute * 5 + math.random(0,4) + local myTime = nightHour * 60 + nightMinute + local myTimeTable = {} + local hostname = io.input("/proc/sys/kernel/hostname"):read("*line") + myTimeTable[hostname] = myTime + io.popen("shared-state insert tests-scheduler-night", "w"):write(JSON.stringify(myTimeTable)) + for _,nightCommand in pairs(nightTestsList) do + local nightAt = "echo '"..nightCommand.."' | at -Mv "..nightHour..":"..nightMinute.." 2>&1" + local handleNightAt = io.popen(nightAt, 'r') + local nightAtRaw = handleNightAt:read("*a") + handleNightAt:close() + local nightAtTime = do_split(nightAtRaw,"%C+")[1] + print(nightAtTime.."\t"..nightCommand) + end + end +else + io.stderr:write("Data from at least one whole day is needed in "..dataFile..", stopping.\n") + os.exit(1) +end + + diff --git a/packages/tests-scheduler/files/bin/tests-scheduler-probe.lua b/packages/tests-scheduler/files/bin/tests-scheduler-probe.lua new file mode 100644 index 000000000..e12daaa55 --- /dev/null +++ b/packages/tests-scheduler/files/bin/tests-scheduler-probe.lua @@ -0,0 +1,111 @@ +#!/usr/bin/lua + +local libuci_loaded, libuci = pcall(require, "uci") + +local function config_uci_get(option) + local result + if libuci_loaded then + result = libuci:cursor():get("tests-scheduler","probe",option) + else + result = nil + end + return result +end + +local defaultTestsList = { + "ip neigh show nud reachable", + "ping6 -n -c 2 ff02::1%br-lan", + "batctl tl" + } + +local temp = config_uci_get(test) +local testsList = type(temp) == "table" and temp or defaultTestsList + +-- stability indicates how much of the previous measurement data +-- (which could be from the previous day) is going to be considered +-- 0 means that just the very last is used, avoid using 1 +-- consider that more than one measurement is performed each hour +local stability = tonumber(config_uci_get(stability)) or 0.9 + +local dataFile = config_uci_get(data_file) or "/tmp/tests-scheduler-probe-data" + +local function do_test(test) + io.stderr:write("Command: "..test.."\n") + local handle = io.popen(test, 'r') + local output = handle:read("*a") + local rc = {handle:close()} + local _,count = output:gsub('\n', '\n') + local exitCode = tonumber(rc[3]) + return count, exitCode +end + +local function do_sum(arr, length) + return length == 1 and arr[1] or arr[length] + do_sum(arr, length -1) +end + +local function do_tests_serie() + local results = {} + local i = 1 + while testsList[i] do + local test = tostring(testsList[i]) + local testResult,exitCode = do_test(test) + if exitCode == 0 then + io.stderr:write("Result: "..tostring(testResult).."\n") + results[#results + 1] = testResult + else + io.stderr:write("Failed with exit code "..exitCode.."\n") + end + i = i + 1 + end + local sum = do_sum(results, #results) + return sum +end + +-- see if the file exists +function file_exists(file) + local f = io.open(file, "rb") + if f then f:close() end + return f ~= nil +end + +-- get all lines from a file, returns an empty +-- list/table if the file does not exist +function lines_from(file) + if not file_exists(file) then return {} end + local lines = {} + for line in io.lines(file) do + lines[#lines + 1] = line + end + return lines +end + +local function calculate_all_data() + data = lines_from(dataFile) + local hour = os.date("*t")["hour"] + local hour1 = hour + 1 + newResult = do_tests_serie() + for i = 1,24 do + if not data[i] then + data[i] = "" + end + end + data[hour1] = tonumber(data[hour1]) and + data[hour1] * stability + newResult * (1 - stability) or + newResult + return data,hour,newResult,data[hour1] +end + +local function save_data(data, file) + -- empty the file + io.open(file,"w"):close() + local handle = io.open(file,"a") + io.output(handle) + for _,val in pairs(data) do + io.write(val.."\n") + end + io.close(handle) +end + +local data,hour,result,cumulativeResult = calculate_all_data() +save_data(data, dataFile) +io.stdout:write(hour.."\t"..result.."\t"..cumulativeResult.."\n") diff --git a/packages/tests-scheduler/files/etc/config/tests-scheduler b/packages/tests-scheduler/files/etc/config/tests-scheduler new file mode 100644 index 000000000..af8bcd229 --- /dev/null +++ b/packages/tests-scheduler/files/etc/config/tests-scheduler @@ -0,0 +1,11 @@ +config probe 'probe' + list test 'ip neigh show nud reachable' + list test 'ping6 -n -c 2 ff02::1%br-lan' + list test 'batctl tl' + option stability 0.9 + option data_file '/tmp/tests-scheduler-probe-data' + +config at 'at' + option data_file '/tmp/tests-scheduler-probe-data' + list peak_test 'lime-report | gzip -c >> /tmp/tests-peak.gz' + list night_test '(date && bandwidth-test) >> /tmp/tests-night' diff --git a/packages/tests-scheduler/files/etc/uci-defaults/50_tests-scheduler-probe b/packages/tests-scheduler/files/etc/uci-defaults/50_tests-scheduler-probe new file mode 100644 index 000000000..3a195043b --- /dev/null +++ b/packages/tests-scheduler/files/etc/uci-defaults/50_tests-scheduler-probe @@ -0,0 +1,12 @@ +#!/bin/sh + +unique_append() +{ + grep -qF "$1" "$2" || echo "$1" >> "$2" +} + +unique_append \ + '*/15 * * * * ((/bin/tests-scheduler-probe)&)'\ + /etc/crontabs/root + +exit 0 diff --git a/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at b/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at new file mode 100644 index 000000000..aa7b5e55f --- /dev/null +++ b/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at @@ -0,0 +1,15 @@ +#!/bin/sh + +hour=$(awk 'BEGIN{srand();print int(rand()*24)}') +minute=$(awk 'BEGIN{srand();print int(rand()*60)}') + +unique_append() +{ + grep -qF "$1" "$2" || echo "$minute $hour $1" >> "$2" +} + +unique_append \ + '* * * ((/bin/tests-scheduler-at; shared-state sync tests-scheduler-night)&)'\ + /etc/crontabs/root + +exit 0 From d78d66ad095665a6021a6cb30680a82d5fc889c1 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Sat, 14 Sep 2019 19:41:21 +0200 Subject: [PATCH 02/21] tests-scheduler-probe remove broken exit code management and fix strings --- .../files/bin/tests-scheduler-probe.lua | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/tests-scheduler/files/bin/tests-scheduler-probe.lua b/packages/tests-scheduler/files/bin/tests-scheduler-probe.lua index e12daaa55..6d6450010 100644 --- a/packages/tests-scheduler/files/bin/tests-scheduler-probe.lua +++ b/packages/tests-scheduler/files/bin/tests-scheduler-probe.lua @@ -18,25 +18,24 @@ local defaultTestsList = { "batctl tl" } -local temp = config_uci_get(test) +local temp = config_uci_get("test") local testsList = type(temp) == "table" and temp or defaultTestsList -- stability indicates how much of the previous measurement data -- (which could be from the previous day) is going to be considered -- 0 means that just the very last is used, avoid using 1 -- consider that more than one measurement is performed each hour -local stability = tonumber(config_uci_get(stability)) or 0.9 +local stability = tonumber(config_uci_get("stability")) or 0.9 -local dataFile = config_uci_get(data_file) or "/tmp/tests-scheduler-probe-data" +local dataFile = config_uci_get("data_file") or "/tmp/tests-scheduler-probe-data" local function do_test(test) io.stderr:write("Command: "..test.."\n") local handle = io.popen(test, 'r') local output = handle:read("*a") - local rc = {handle:close()} + handle:close() local _,count = output:gsub('\n', '\n') - local exitCode = tonumber(rc[3]) - return count, exitCode + return count end local function do_sum(arr, length) @@ -48,12 +47,12 @@ local function do_tests_serie() local i = 1 while testsList[i] do local test = tostring(testsList[i]) - local testResult,exitCode = do_test(test) - if exitCode == 0 then + local testResult = tonumber(do_test(test)) + if testResult > 0 then io.stderr:write("Result: "..tostring(testResult).."\n") results[#results + 1] = testResult else - io.stderr:write("Failed with exit code "..exitCode.."\n") + io.stderr:write("Failed or no output\n") end i = i + 1 end From eb622be45c7d13949e139c36c6ba73205c4f7085 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Sat, 14 Sep 2019 19:57:25 +0200 Subject: [PATCH 03/21] tests-scheduler-probe refine results using grep --- packages/tests-scheduler/files/bin/tests-scheduler-probe.lua | 4 ++-- packages/tests-scheduler/files/etc/config/tests-scheduler | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/tests-scheduler/files/bin/tests-scheduler-probe.lua b/packages/tests-scheduler/files/bin/tests-scheduler-probe.lua index 6d6450010..026043632 100644 --- a/packages/tests-scheduler/files/bin/tests-scheduler-probe.lua +++ b/packages/tests-scheduler/files/bin/tests-scheduler-probe.lua @@ -14,8 +14,8 @@ end local defaultTestsList = { "ip neigh show nud reachable", - "ping6 -n -c 2 ff02::1%br-lan", - "batctl tl" + "ping6 -n -c 2 ff02::1%br-lan | grep '(DUP!)'", + "batctl tl | grep '(0x'" } local temp = config_uci_get("test") diff --git a/packages/tests-scheduler/files/etc/config/tests-scheduler b/packages/tests-scheduler/files/etc/config/tests-scheduler index af8bcd229..313ed44c8 100644 --- a/packages/tests-scheduler/files/etc/config/tests-scheduler +++ b/packages/tests-scheduler/files/etc/config/tests-scheduler @@ -1,7 +1,7 @@ config probe 'probe' list test 'ip neigh show nud reachable' - list test 'ping6 -n -c 2 ff02::1%br-lan' - list test 'batctl tl' + list test 'ping6 -n -c 2 ff02::1%br-lan | grep "(DUP!)"' + list test 'batctl tl | grep "(0x"' option stability 0.9 option data_file '/tmp/tests-scheduler-probe-data' From 84253b9fa4cb938e0a1db642e0e5757161cedfa1 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Sun, 13 Oct 2019 17:19:02 +0200 Subject: [PATCH 04/21] tests-scheduler fixed typo in Makefile --- packages/tests-scheduler/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/tests-scheduler/Makefile b/packages/tests-scheduler/Makefile index 42e316849..9820dbb8b 100644 --- a/packages/tests-scheduler/Makefile +++ b/packages/tests-scheduler/Makefile @@ -38,8 +38,8 @@ define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/bin/ $(INSTALL_DIR) $(1)/etc/uci-defaults/ $(INSTALL_DIR) $(1)/etc/config/ - $(INSTALL_BIN) ./files/bin/test-scheduler-at.lua $(1)/bin/tests-scheduler-at - $(INSTALL_BIN) ./files/bin/test-scheduler-probe.lua $(1)/bin/tests-scheduler-probe + $(INSTALL_BIN) ./files/bin/tests-scheduler-at.lua $(1)/bin/tests-scheduler-at + $(INSTALL_BIN) ./files/bin/tests-scheduler-probe.lua $(1)/bin/tests-scheduler-probe $(INSTALL_BIN) ./files/etc/uci-defaults/* $(1)/etc/uci-defaults $(INSTALL_CONF) ./files/etc/config/tests-scheduler $(1)/etc/config/ endef From 2e934582b86e7e8e32f189984d42c627b5360ab2 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Sun, 13 Oct 2019 19:06:37 +0200 Subject: [PATCH 05/21] tests-scheduler-at various fixes --- .../files/bin/tests-scheduler-at.lua | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/tests-scheduler/files/bin/tests-scheduler-at.lua b/packages/tests-scheduler/files/bin/tests-scheduler-at.lua index 640071d15..57a6cc255 100644 --- a/packages/tests-scheduler/files/bin/tests-scheduler-at.lua +++ b/packages/tests-scheduler/files/bin/tests-scheduler-at.lua @@ -14,11 +14,11 @@ local function config_uci_get(option) return result end -local peakTestsList = config_uci_get(peak_test) or {arg[1]} +local peakTestsList = config_uci_get("peak_test") or {arg[1]} -local nightTestsList = config_uci_get(night_test) or {arg[2]} +local nightTestsList = config_uci_get("night_test") or {arg[2]} -local dataFile = config_uci_get(data_file) or "/tmp/tests-scheduler-probe-data" +local dataFile = config_uci_get("data_file") or "/tmp/tests-scheduler-probe-data" -- see if the file exists function file_exists(file) @@ -88,7 +88,7 @@ if complete then local peakAtRaw = handlePeakAt:read("*a") handlePeakAt:close() local peakAtTime = do_split(peakAtRaw,"%C+")[1] - print(peakAtTime.."\t"..peakCommand) + print("Scheduled time:\t"..peakAtTime.."\tCommand:\t"..peakCommand) end if nightTestsList then local datatemp = data @@ -104,14 +104,15 @@ if complete then local allTimesJson = handleAllTimesJson:read("*a") handleAllTimesJson:close() local allTimes = {} - for _,value in pairs(JSON.parse(allTimeJson)) do + for _,value in pairs(JSON.parse(allTimesJson)) do allTimes[#allTimes + 1] = tonumber(value.data) end local hitsHours = {0,0,0,0,0,0} for _,val in pairs(allTimes) do for i = 1,6 do - local valHour = int(val/60) + local valHourFract = val / 60 + local valHour = valHourFract - (valHourFract % 1) if valHour == nightHours[i] then hitsHours[i] = hitsHours[i] + 1 break @@ -124,7 +125,8 @@ if complete then local hits5minute = {0,0,0,0,0,0,0,0,0,0,0,0} for _,val in pairs(allTimes) do - local valHour = int(val/60) + local valHourFract = val / 60 + local valHour = valHourFract - (valHourFract % 1) if valHour == nightHour then local val5minute = 1 + int((val%60)/5) hits5minute[val5minute] = hits5minute[val5minute] + 1 @@ -139,8 +141,11 @@ if complete then local hostname = io.input("/proc/sys/kernel/hostname"):read("*line") myTimeTable[hostname] = myTime io.popen("shared-state insert tests-scheduler-night", "w"):write(JSON.stringify(myTimeTable)) - for _,nightCommand in pairs(nightTestsList) do - local nightAt = "echo '"..nightCommand.."' | at -Mv "..nightHour..":"..nightMinute.." 2>&1" + for index,nightCommand in ipairs(nightTestsList) do + local nightMinuteIdx = nightMinute + index - 1 + local nightMinuteIdxPad = string.format("%02d", nightMinuteIdx) + local nightAt = "echo '"..nightCommand.."' | at -Mv "..nightHour..":".. + nightMinuteIdxPad.." 2>&1" local handleNightAt = io.popen(nightAt, 'r') local nightAtRaw = handleNightAt:read("*a") handleNightAt:close() From 6724a7475c159cbe21c4c14c9e04c7fbf247acf9 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Sun, 13 Oct 2019 19:39:03 +0200 Subject: [PATCH 06/21] tests-scheduler move from LiMe to Utilities category --- packages/tests-scheduler/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/tests-scheduler/Makefile b/packages/tests-scheduler/Makefile index 9820dbb8b..37fcd0e64 100644 --- a/packages/tests-scheduler/Makefile +++ b/packages/tests-scheduler/Makefile @@ -15,9 +15,9 @@ PKG_VERSION=$(GIT_COMMIT_DATE)-$(GIT_COMMIT_TSTAMP) include $(INCLUDE_DIR)/package.mk define Package/$(PKG_NAME) - CATEGORY:=LiMe + CATEGORY:=Utilities TITLE:=Tests scheduler at peak and night time - MAINTAINER:=Ilario Gelmetti + MAINTAINER:=Ilario Gelmetti URL:=https://libremesh.org DEPENDS:=+at PKGARCH:=all From be2c5db2e5e585fdb6c2ce4034f6579771a8e38b Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Mon, 14 Oct 2019 19:07:28 +0200 Subject: [PATCH 07/21] tests-scheduler improvements --- .../files/bin/tests-scheduler-at.lua | 174 +++++++++--------- .../files/etc/config/tests-scheduler | 3 +- .../init.d/tests-scheduler-probe-data-persist | 25 +++ .../etc/uci-defaults/51_tests-scheduler-at | 2 +- 4 files changed, 120 insertions(+), 84 deletions(-) create mode 100755 packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist diff --git a/packages/tests-scheduler/files/bin/tests-scheduler-at.lua b/packages/tests-scheduler/files/bin/tests-scheduler-at.lua index 57a6cc255..ccd419d06 100644 --- a/packages/tests-scheduler/files/bin/tests-scheduler-at.lua +++ b/packages/tests-scheduler/files/bin/tests-scheduler-at.lua @@ -1,6 +1,7 @@ #!/usr/bin/lua local JSON = require("luci.jsonc") +local utils = require("lime.utils") local libuci_loaded, libuci = pcall(require, "uci") @@ -20,7 +21,7 @@ local nightTestsList = config_uci_get("night_test") or {arg[2]} local dataFile = config_uci_get("data_file") or "/tmp/tests-scheduler-probe-data" --- see if the file exists +-- check if a file exists function file_exists(file) local f = io.open(file, "rb") if f then f:close() end @@ -29,16 +30,15 @@ end -- get all lines from a file, returns an empty -- list/table if the file does not exist -function lines_from(file) +function lines_from_tonumber(file) if not file_exists(file) then return {} end local lines = {} for line in io.lines(file) do - lines[#lines + 1] = line + lines[#lines + 1] = tonumber(line) or "missing" end return lines end - local function do_split(str,pat) local tbl = {} str:gsub(pat, function(x) tbl[#tbl+1]=x end) @@ -69,93 +69,103 @@ local function min(t) return key, value end -local data = lines_from(dataFile) -local complete = true +local data = lines_from_tonumber(dataFile) + for _,val in pairs(data) do - if not tonumber(val) then - complete = false - break + if val == "missing" then + io.stderr:write("Data from at least one whole day is needed in ".. + dataFile..", stopping.\n") + os.exit(1) end end -if complete then - io.stderr:write("Found enough data in "..dataFile..", continuing.\n") - local peakHour1,_ = max(data) - local peakHour = peakHour1 - 1 - for _,peakCommand in pairs(peakTestsList) do - local peakAt = "echo '"..peakCommand.."' | at -Mv "..peakHour..":30 2>&1" - local handlePeakAt = io.popen(peakAt, 'r') - local peakAtRaw = handlePeakAt:read("*a") - handlePeakAt:close() - local peakAtTime = do_split(peakAtRaw,"%C+")[1] - print("Scheduled time:\t"..peakAtTime.."\tCommand:\t"..peakCommand) - end - if nightTestsList then - local datatemp = data - local nightHours = {} - for i = 1,6 do - nightHour1,_ = min(datatemp) - nightHours[i] = nightHour1 - 1 - datatemp[nightHour1] = math.huge - end +io.stderr:write("Found enough data in "..dataFile..", continuing.\n") - local getCommand = "shared-state get tests-scheduler-night" - local handleAllTimesJson = io.popen(getCommand, "r") - local allTimesJson = handleAllTimesJson:read("*a") - handleAllTimesJson:close() - local allTimes = {} - for _,value in pairs(JSON.parse(allTimesJson)) do - allTimes[#allTimes + 1] = tonumber(value.data) - end +local peakHour1,_ = max(data) +local peakHour = peakHour1 - 1 - local hitsHours = {0,0,0,0,0,0} - for _,val in pairs(allTimes) do - for i = 1,6 do - local valHourFract = val / 60 - local valHour = valHourFract - (valHourFract % 1) - if valHour == nightHours[i] then - hitsHours[i] = hitsHours[i] + 1 - break - end - end - end - - local minHourIndex,_ = min(hitsHours) - local nightHour = nightHours[minHourIndex] - - local hits5minute = {0,0,0,0,0,0,0,0,0,0,0,0} - for _,val in pairs(allTimes) do - local valHourFract = val / 60 - local valHour = valHourFract - (valHourFract % 1) - if valHour == nightHour then - local val5minute = 1 + int((val%60)/5) - hits5minute[val5minute] = hits5minute[val5minute] + 1 - end - end +if not peakTestsList then + io.stderr:write("No tests configured to be run at the peak time.\n") +end + +for index,peakCommand in ipairs(peakTestsList) do + local peakMinute = (index * 5) % 60 + local peakMinutePad = string.format("%02d", peakMinute) + local peakAt = "echo '"..peakCommand.."' | at -Mv "..peakHour..":".. + peakMinutePad.." 2>&1" + local handlePeakAt = io.popen(peakAt, 'r') + local peakAtRaw = handlePeakAt:read("*a") + handlePeakAt:close() + local peakAtTime = do_split(peakAtRaw,"%C+")[1] + utils.log("Scheduled time:\t"..peakAtTime.."\tCommand:\t"..peakCommand) +end - local min5minute1,_ = min(hits5minute) - local min5minute = min5minute1 - 1 - local nightMinute = min5minute * 5 + math.random(0,4) - local myTime = nightHour * 60 + nightMinute - local myTimeTable = {} - local hostname = io.input("/proc/sys/kernel/hostname"):read("*line") - myTimeTable[hostname] = myTime - io.popen("shared-state insert tests-scheduler-night", "w"):write(JSON.stringify(myTimeTable)) - for index,nightCommand in ipairs(nightTestsList) do - local nightMinuteIdx = nightMinute + index - 1 - local nightMinuteIdxPad = string.format("%02d", nightMinuteIdx) - local nightAt = "echo '"..nightCommand.."' | at -Mv "..nightHour..":".. - nightMinuteIdxPad.." 2>&1" - local handleNightAt = io.popen(nightAt, 'r') - local nightAtRaw = handleNightAt:read("*a") - handleNightAt:close() - local nightAtTime = do_split(nightAtRaw,"%C+")[1] - print(nightAtTime.."\t"..nightCommand) +if not nightTestsList then + io.stderr:write("No tests configured to be run at the night time.\n") + os.exit(0) +end + +local datatemp = data +local nightHours = {} + +for i = 1,6 do + nightHour1,_ = min(datatemp) + nightHours[i] = nightHour1 - 1 + datatemp[nightHour1] = math.huge +end + +local getCommand = "shared-state get tests-scheduler-night" +local handleAllTimesJson = io.popen(getCommand, "r") +local allTimesJson = handleAllTimesJson:read("*a") +handleAllTimesJson:close() +local allTimes = {} +for _,value in pairs(JSON.parse(allTimesJson)) do + allTimes[#allTimes + 1] = tonumber(value.data) +end + +local hitsHours = {0,0,0,0,0,0} +for _,val in pairs(allTimes) do + for i = 1,6 do + local valHourFract = val / 60 + local valHour = valHourFract - (valHourFract % 1) + if valHour == nightHours[i] then + hitsHours[i] = hitsHours[i] + 1 + break end end -else - io.stderr:write("Data from at least one whole day is needed in "..dataFile..", stopping.\n") - os.exit(1) end +local minHourIndex,_ = min(hitsHours) +local nightHour = nightHours[minHourIndex] + +local hits5minute = {0,0,0,0,0,0,0,0,0,0,0,0} +for _,val in pairs(allTimes) do + local valHourFract = val / 60 + local valHour = valHourFract - (valHourFract % 1) + if valHour == nightHour then + local val5minuteFract = (val % 60) / 5 + local val5minute = val5minuteFract - (val5minuteFract % 1) + hits5minute[val5minute + 1] = hits5minute[val5minute + 1] + 1 + end +end +local min5minute1,_ = min(hits5minute) +local min5minute = min5minute1 - 1 +local nightMinute = min5minute * 5 +local myTime = nightHour * 60 + nightMinute +local myTimeTable = {} +local hostname = io.input("/proc/sys/kernel/hostname"):read("*line") +myTimeTable[hostname] = myTime +io.popen("shared-state insert tests-scheduler-night", "w"):write(JSON.stringify(myTimeTable)) +local randomStart = math.random(0,4) +for index,nightCommand in ipairs(nightTestsList) do + local nightMinuteIdx = nightMinute + ((index + randomStart) % 5) + local nightMinuteIdxPad = string.format("%02d", nightMinuteIdx) + local nightAt = "echo '"..nightCommand.."' | at -Mv "..nightHour..":".. + nightMinuteIdxPad.." 2>&1" + local handleNightAt = io.popen(nightAt, 'r') + local nightAtRaw = handleNightAt:read("*a") + handleNightAt:close() + local nightAtTime = do_split(nightAtRaw,"%C+")[1] + utils.log("Scheduled time:\t"..nightAtTime.."\tCommand:\t"..nightCommand) +end diff --git a/packages/tests-scheduler/files/etc/config/tests-scheduler b/packages/tests-scheduler/files/etc/config/tests-scheduler index 313ed44c8..5c47c48e2 100644 --- a/packages/tests-scheduler/files/etc/config/tests-scheduler +++ b/packages/tests-scheduler/files/etc/config/tests-scheduler @@ -2,8 +2,9 @@ config probe 'probe' list test 'ip neigh show nud reachable' list test 'ping6 -n -c 2 ff02::1%br-lan | grep "(DUP!)"' list test 'batctl tl | grep "(0x"' - option stability 0.9 + option stability 0.95 option data_file '/tmp/tests-scheduler-probe-data' + option persist_to_flash true config at 'at' option data_file '/tmp/tests-scheduler-probe-data' diff --git a/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist b/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist new file mode 100755 index 000000000..7e2cfebef --- /dev/null +++ b/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist @@ -0,0 +1,25 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2019 Ilario Gelmetti +USE_PROCD=1 +START=45 +STOP=01 +BACKUPFILE=/etc/tests-scheduler/tests-scheduler-probe-data-persist +FRESHFILE=/tmp/tests-scheduler-probe-data +CONFIGURATION=tests-scheduler + +start_service() { + config_load "${CONFIGURATION}" + local persist_to_flash + config_get persist_to_flash probe persist_to_flash + procd_open_instance + procd_set_param respawn + procd_set_param command [[ $persist_to_flash == "true" ]] && [[ -e $BACKUPFILE ]] && cp $BACKUPFILE $FRESHFILE + procd_set_param file /etc/config/tests-scheduler + procd_set_param stdout 1 + procd_set_param stderr 1 + procd_close_instance +} + +stop_service() { + [[ -e $FRESHFILE ]] && cp $FRESHFILE $BACKUPFILE +} diff --git a/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at b/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at index aa7b5e55f..375594c9d 100644 --- a/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at +++ b/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at @@ -9,7 +9,7 @@ unique_append() } unique_append \ - '* * * ((/bin/tests-scheduler-at; shared-state sync tests-scheduler-night)&)'\ + '* * * ((/bin/tests-scheduler-at; shared-state sync tests-scheduler-night &> /dev/null)&)'\ /etc/crontabs/root exit 0 From 28fe838aff4865c5a7ac9a52496f4fdb5ec1164a Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Mon, 14 Oct 2019 21:58:19 +0200 Subject: [PATCH 08/21] install also init.d for persist --- packages/tests-scheduler/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/tests-scheduler/Makefile b/packages/tests-scheduler/Makefile index 37fcd0e64..afd65a025 100644 --- a/packages/tests-scheduler/Makefile +++ b/packages/tests-scheduler/Makefile @@ -41,6 +41,7 @@ define Package/$(PKG_NAME)/install $(INSTALL_BIN) ./files/bin/tests-scheduler-at.lua $(1)/bin/tests-scheduler-at $(INSTALL_BIN) ./files/bin/tests-scheduler-probe.lua $(1)/bin/tests-scheduler-probe $(INSTALL_BIN) ./files/etc/uci-defaults/* $(1)/etc/uci-defaults + $(INSTALL_BIN) ./files/etc/init.d/* $(1)/etc/init.d $(INSTALL_CONF) ./files/etc/config/tests-scheduler $(1)/etc/config/ endef From 65b62588e1139f712ffdd0ed9b206bdd9cd26619 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Mon, 14 Oct 2019 22:04:13 +0200 Subject: [PATCH 09/21] fix in Makefile --- packages/tests-scheduler/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/tests-scheduler/Makefile b/packages/tests-scheduler/Makefile index afd65a025..0537fef5b 100644 --- a/packages/tests-scheduler/Makefile +++ b/packages/tests-scheduler/Makefile @@ -38,6 +38,7 @@ define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/bin/ $(INSTALL_DIR) $(1)/etc/uci-defaults/ $(INSTALL_DIR) $(1)/etc/config/ + $(INSTALL_DIR) $(1)/etc/init.d/ $(INSTALL_BIN) ./files/bin/tests-scheduler-at.lua $(1)/bin/tests-scheduler-at $(INSTALL_BIN) ./files/bin/tests-scheduler-probe.lua $(1)/bin/tests-scheduler-probe $(INSTALL_BIN) ./files/etc/uci-defaults/* $(1)/etc/uci-defaults From e48a526c28364d2a72aded00195bbff160fca030 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Mon, 14 Oct 2019 22:55:40 +0200 Subject: [PATCH 10/21] added logrotate to tests-scheduler --- packages/tests-scheduler/Makefile | 4 +++- packages/tests-scheduler/files/etc/config/tests-scheduler | 4 ++-- .../files/etc/logrotate.d/tests-peak-lime-report | 5 +++++ 3 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 packages/tests-scheduler/files/etc/logrotate.d/tests-peak-lime-report diff --git a/packages/tests-scheduler/Makefile b/packages/tests-scheduler/Makefile index 0537fef5b..134b9fdc2 100644 --- a/packages/tests-scheduler/Makefile +++ b/packages/tests-scheduler/Makefile @@ -19,7 +19,7 @@ define Package/$(PKG_NAME) TITLE:=Tests scheduler at peak and night time MAINTAINER:=Ilario Gelmetti URL:=https://libremesh.org - DEPENDS:=+at + DEPENDS:=+at +logrotate PKGARCH:=all endef @@ -39,10 +39,12 @@ define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/etc/uci-defaults/ $(INSTALL_DIR) $(1)/etc/config/ $(INSTALL_DIR) $(1)/etc/init.d/ + $(INSTALL_DIR) $(1)/etc/logrotate.d/ $(INSTALL_BIN) ./files/bin/tests-scheduler-at.lua $(1)/bin/tests-scheduler-at $(INSTALL_BIN) ./files/bin/tests-scheduler-probe.lua $(1)/bin/tests-scheduler-probe $(INSTALL_BIN) ./files/etc/uci-defaults/* $(1)/etc/uci-defaults $(INSTALL_BIN) ./files/etc/init.d/* $(1)/etc/init.d + $(INSTALL_BIN) ./files/etc/logrotate.d/* $(1)/etc/logrotate.d $(INSTALL_CONF) ./files/etc/config/tests-scheduler $(1)/etc/config/ endef diff --git a/packages/tests-scheduler/files/etc/config/tests-scheduler b/packages/tests-scheduler/files/etc/config/tests-scheduler index 5c47c48e2..deb0303ee 100644 --- a/packages/tests-scheduler/files/etc/config/tests-scheduler +++ b/packages/tests-scheduler/files/etc/config/tests-scheduler @@ -8,5 +8,5 @@ config probe 'probe' config at 'at' option data_file '/tmp/tests-scheduler-probe-data' - list peak_test 'lime-report | gzip -c >> /tmp/tests-peak.gz' - list night_test '(date && bandwidth-test) >> /tmp/tests-night' + list peak_test 'lime-report >> /tmp/tests-peak-lime-report' + list night_test '(date && bandwidth-test) >> /tmp/tests-night-bandwidth-test' diff --git a/packages/tests-scheduler/files/etc/logrotate.d/tests-peak-lime-report b/packages/tests-scheduler/files/etc/logrotate.d/tests-peak-lime-report new file mode 100644 index 000000000..cda9c82cb --- /dev/null +++ b/packages/tests-scheduler/files/etc/logrotate.d/tests-peak-lime-report @@ -0,0 +1,5 @@ +/tmp/tests-peak-lime-report { + compress + rotate 5 + size 100k +} From b53e8912189d3645882a674d591f4ba3369ba9a1 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Mon, 14 Oct 2019 23:34:40 +0200 Subject: [PATCH 11/21] create persist dir in Makefile --- packages/tests-scheduler/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/tests-scheduler/Makefile b/packages/tests-scheduler/Makefile index 134b9fdc2..32d2f7830 100644 --- a/packages/tests-scheduler/Makefile +++ b/packages/tests-scheduler/Makefile @@ -40,6 +40,7 @@ define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/etc/config/ $(INSTALL_DIR) $(1)/etc/init.d/ $(INSTALL_DIR) $(1)/etc/logrotate.d/ + $(INSTALL_DIR) $(1)/etc/tests-scheduler/ $(INSTALL_BIN) ./files/bin/tests-scheduler-at.lua $(1)/bin/tests-scheduler-at $(INSTALL_BIN) ./files/bin/tests-scheduler-probe.lua $(1)/bin/tests-scheduler-probe $(INSTALL_BIN) ./files/etc/uci-defaults/* $(1)/etc/uci-defaults From 039ce6eb80b375f6b789c71ea9cd92f61d2b340b Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Tue, 15 Oct 2019 11:27:23 +0200 Subject: [PATCH 12/21] check existence of backup directory --- .../files/etc/init.d/tests-scheduler-probe-data-persist | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist b/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist index 7e2cfebef..057a3150f 100755 --- a/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist +++ b/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist @@ -3,7 +3,8 @@ USE_PROCD=1 START=45 STOP=01 -BACKUPFILE=/etc/tests-scheduler/tests-scheduler-probe-data-persist +BACKUPDIR=/etc/tests-scheduler +BACKUPFILE=$BACKUPDIR/tests-scheduler-probe-data-persist FRESHFILE=/tmp/tests-scheduler-probe-data CONFIGURATION=tests-scheduler @@ -21,5 +22,5 @@ start_service() { } stop_service() { - [[ -e $FRESHFILE ]] && cp $FRESHFILE $BACKUPFILE + [[ -e $FRESHFILE ]] && [[ -d $BACKUPDIR ]] && cp $FRESHFILE $BACKUPFILE } From 4d3a95c6ad2a3d10b78adf4fb3eb46147b384f09 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Tue, 15 Oct 2019 11:28:36 +0200 Subject: [PATCH 13/21] check configuration option --- .../files/etc/init.d/tests-scheduler-probe-data-persist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist b/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist index 057a3150f..132437bcf 100755 --- a/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist +++ b/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist @@ -22,5 +22,5 @@ start_service() { } stop_service() { - [[ -e $FRESHFILE ]] && [[ -d $BACKUPDIR ]] && cp $FRESHFILE $BACKUPFILE + [[ $persist_to_flash == "true" ]] && [[ -e $FRESHFILE ]] && [[ -d $BACKUPDIR ]] && cp $FRESHFILE $BACKUPFILE } From 25adae4e081275f68cb775011cbdf04fffe6348b Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Tue, 15 Oct 2019 11:55:40 +0200 Subject: [PATCH 14/21] fix configuration usage in init file --- .../files/etc/init.d/tests-scheduler-probe-data-persist | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist b/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist index 132437bcf..478c7931e 100755 --- a/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist +++ b/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist @@ -14,7 +14,7 @@ start_service() { config_get persist_to_flash probe persist_to_flash procd_open_instance procd_set_param respawn - procd_set_param command [[ $persist_to_flash == "true" ]] && [[ -e $BACKUPFILE ]] && cp $BACKUPFILE $FRESHFILE + procd_set_param command $persist_to_flash && [[ -e $BACKUPFILE ]] && cp $BACKUPFILE $FRESHFILE procd_set_param file /etc/config/tests-scheduler procd_set_param stdout 1 procd_set_param stderr 1 @@ -22,5 +22,8 @@ start_service() { } stop_service() { - [[ $persist_to_flash == "true" ]] && [[ -e $FRESHFILE ]] && [[ -d $BACKUPDIR ]] && cp $FRESHFILE $BACKUPFILE + config_load "${CONFIGURATION}" + local persist_to_flash + config_get persist_to_flash probe persist_to_flash + $persist_to_flash && [[ -e $FRESHFILE ]] && [[ -d $BACKUPDIR ]] && cp $FRESHFILE $BACKUPFILE } From 1aa1b962fc2450f98a76a970c1e86d7871902e81 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Wed, 16 Oct 2019 22:49:25 +0200 Subject: [PATCH 15/21] split tests to separate package and other changes --- packages/tests-scheduler-lime/Makefile | 48 +++++++++++++++++++ .../etc/logrotate.d/tests-peak-lime-report | 0 .../nightHooks.d/10-bandwidth-test | 2 + .../peakHooks.d/10-lime-report | 2 + packages/tests-scheduler/Makefile | 6 +-- .../files/bin/tests-scheduler-at.lua | 14 +++--- .../files/etc/config/tests-scheduler | 7 +-- .../init.d/tests-scheduler-probe-data-persist | 21 ++++++-- 8 files changed, 80 insertions(+), 20 deletions(-) create mode 100644 packages/tests-scheduler-lime/Makefile rename packages/{tests-scheduler => tests-scheduler-lime}/files/etc/logrotate.d/tests-peak-lime-report (100%) create mode 100644 packages/tests-scheduler-lime/files/etc/tests-scheduler/nightHooks.d/10-bandwidth-test create mode 100644 packages/tests-scheduler-lime/files/etc/tests-scheduler/peakHooks.d/10-lime-report diff --git a/packages/tests-scheduler-lime/Makefile b/packages/tests-scheduler-lime/Makefile new file mode 100644 index 000000000..309e3d7d5 --- /dev/null +++ b/packages/tests-scheduler-lime/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (C) 2019 Ilario Gelmetti +# +# This is free software, licensed under the GNU General Public License v3. +# + +include $(TOPDIR)/rules.mk + +GIT_COMMIT_DATE:=$(shell git log -n 1 --pretty=%ad --date=short . ) +GIT_COMMIT_TSTAMP:=$(shell git log -n 1 --pretty=%at . ) + +PKG_NAME:=tests-scheduler-lime +PKG_VERSION=$(GIT_COMMIT_DATE)-$(GIT_COMMIT_TSTAMP) + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) + CATEGORY:=LiMe + TITLE:=LibreMesh tests for tests-scheduler + MAINTAINER:=Ilario Gelmetti + URL:=https://libremesh.org + DEPENDS:=+logrotate +lime-report +bandwidth-test + PKGARCH:=all +endef + +define Package/$(PKG_NAME)/config +endef + +define Package/$(PKG_NAME)/description + Schedules a few tests which gather useful information for debugging + a LibreMesh network. + The scheduling is done using the tests-scheduler package and can be run + at the network usage peak time or at the night time. +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/install + $(INSTALL_DIR) $(1)/etc/logrotate.d/ + $(INSTALL_DIR) $(1)/etc/tests-scheduler/nightHooks.d/ + $(INSTALL_DIR) $(1)/etc/tests-scheduler/peakHooks.d/ + $(INSTALL_BIN) ./files/etc/logrotate.d/* $(1)/etc/logrotate.d + $(INSTALL_BIN) ./files/etc/tests-scheduler/nightHooks.d/* $(1)/etc/tests-scheduler/nightHooks.d/ + $(INSTALL_BIN) ./files/etc/tests-scheduler/peakHooks.d/* $(1)/etc/tests-scheduler/peakHooks.d/ +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/packages/tests-scheduler/files/etc/logrotate.d/tests-peak-lime-report b/packages/tests-scheduler-lime/files/etc/logrotate.d/tests-peak-lime-report similarity index 100% rename from packages/tests-scheduler/files/etc/logrotate.d/tests-peak-lime-report rename to packages/tests-scheduler-lime/files/etc/logrotate.d/tests-peak-lime-report diff --git a/packages/tests-scheduler-lime/files/etc/tests-scheduler/nightHooks.d/10-bandwidth-test b/packages/tests-scheduler-lime/files/etc/tests-scheduler/nightHooks.d/10-bandwidth-test new file mode 100644 index 000000000..431c9e74c --- /dev/null +++ b/packages/tests-scheduler-lime/files/etc/tests-scheduler/nightHooks.d/10-bandwidth-test @@ -0,0 +1,2 @@ +#!/bin/sh +(date && bandwidth-test) >> /tmp/tests-night-bandwidth-test diff --git a/packages/tests-scheduler-lime/files/etc/tests-scheduler/peakHooks.d/10-lime-report b/packages/tests-scheduler-lime/files/etc/tests-scheduler/peakHooks.d/10-lime-report new file mode 100644 index 000000000..fd26dc2f4 --- /dev/null +++ b/packages/tests-scheduler-lime/files/etc/tests-scheduler/peakHooks.d/10-lime-report @@ -0,0 +1,2 @@ +#!/bin/sh +lime-report >> /tmp/tests-peak-lime-report diff --git a/packages/tests-scheduler/Makefile b/packages/tests-scheduler/Makefile index 32d2f7830..c60dda305 100644 --- a/packages/tests-scheduler/Makefile +++ b/packages/tests-scheduler/Makefile @@ -19,7 +19,7 @@ define Package/$(PKG_NAME) TITLE:=Tests scheduler at peak and night time MAINTAINER:=Ilario Gelmetti URL:=https://libremesh.org - DEPENDS:=+at +logrotate + DEPENDS:=+at PKGARCH:=all endef @@ -37,15 +37,13 @@ endef define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/bin/ $(INSTALL_DIR) $(1)/etc/uci-defaults/ - $(INSTALL_DIR) $(1)/etc/config/ $(INSTALL_DIR) $(1)/etc/init.d/ - $(INSTALL_DIR) $(1)/etc/logrotate.d/ + $(INSTALL_DIR) $(1)/etc/config/ $(INSTALL_DIR) $(1)/etc/tests-scheduler/ $(INSTALL_BIN) ./files/bin/tests-scheduler-at.lua $(1)/bin/tests-scheduler-at $(INSTALL_BIN) ./files/bin/tests-scheduler-probe.lua $(1)/bin/tests-scheduler-probe $(INSTALL_BIN) ./files/etc/uci-defaults/* $(1)/etc/uci-defaults $(INSTALL_BIN) ./files/etc/init.d/* $(1)/etc/init.d - $(INSTALL_BIN) ./files/etc/logrotate.d/* $(1)/etc/logrotate.d $(INSTALL_CONF) ./files/etc/config/tests-scheduler $(1)/etc/config/ endef diff --git a/packages/tests-scheduler/files/bin/tests-scheduler-at.lua b/packages/tests-scheduler/files/bin/tests-scheduler-at.lua index ccd419d06..a3433fad9 100644 --- a/packages/tests-scheduler/files/bin/tests-scheduler-at.lua +++ b/packages/tests-scheduler/files/bin/tests-scheduler-at.lua @@ -8,16 +8,16 @@ local libuci_loaded, libuci = pcall(require, "uci") local function config_uci_get(option) local result if libuci_loaded then - result = libuci:cursor():get("tests-scheduler","at",option) + result = libuci:cursor():get("tests-scheduler","probe",option) else result = nil end return result end -local peakTestsList = config_uci_get("peak_test") or {arg[1]} +--local peakTestsList = config_uci_get("peak_test") or {arg[1]} -local nightTestsList = config_uci_get("night_test") or {arg[2]} +--local nightTestsList = config_uci_get("night_test") or {arg[2]} local dataFile = config_uci_get("data_file") or "/tmp/tests-scheduler-probe-data" @@ -156,10 +156,12 @@ local myTime = nightHour * 60 + nightMinute local myTimeTable = {} local hostname = io.input("/proc/sys/kernel/hostname"):read("*line") myTimeTable[hostname] = myTime -io.popen("shared-state insert tests-scheduler-night", "w"):write(JSON.stringify(myTimeTable)) -local randomStart = math.random(0,4) +local handle = io.popen("shared-state insert tests-scheduler-night", "w") +handle:write(JSON.stringify(myTimeTable)) +handle:close() + for index,nightCommand in ipairs(nightTestsList) do - local nightMinuteIdx = nightMinute + ((index + randomStart) % 5) + local nightMinuteIdx = (nightMinute + index - 1) % 60 local nightMinuteIdxPad = string.format("%02d", nightMinuteIdx) local nightAt = "echo '"..nightCommand.."' | at -Mv "..nightHour..":".. nightMinuteIdxPad.." 2>&1" diff --git a/packages/tests-scheduler/files/etc/config/tests-scheduler b/packages/tests-scheduler/files/etc/config/tests-scheduler index deb0303ee..9831f6f56 100644 --- a/packages/tests-scheduler/files/etc/config/tests-scheduler +++ b/packages/tests-scheduler/files/etc/config/tests-scheduler @@ -4,9 +4,6 @@ config probe 'probe' list test 'batctl tl | grep "(0x"' option stability 0.95 option data_file '/tmp/tests-scheduler-probe-data' + option backup_dir '/etc/tests-scheduler' + option backup_filename 'tests-scheduler-probe-data-backup' option persist_to_flash true - -config at 'at' - option data_file '/tmp/tests-scheduler-probe-data' - list peak_test 'lime-report >> /tmp/tests-peak-lime-report' - list night_test '(date && bandwidth-test) >> /tmp/tests-night-bandwidth-test' diff --git a/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist b/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist index 478c7931e..533ffa371 100755 --- a/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist +++ b/packages/tests-scheduler/files/etc/init.d/tests-scheduler-probe-data-persist @@ -3,18 +3,22 @@ USE_PROCD=1 START=45 STOP=01 -BACKUPDIR=/etc/tests-scheduler -BACKUPFILE=$BACKUPDIR/tests-scheduler-probe-data-persist -FRESHFILE=/tmp/tests-scheduler-probe-data CONFIGURATION=tests-scheduler start_service() { config_load "${CONFIGURATION}" local persist_to_flash + local data_file + local backup_dir + local backup_filename config_get persist_to_flash probe persist_to_flash + config_get data_file probe data_file + config_get backup_dir probe backup_dir + config_get backup_filename probe backup_filename + procd_open_instance procd_set_param respawn - procd_set_param command $persist_to_flash && [[ -e $BACKUPFILE ]] && cp $BACKUPFILE $FRESHFILE + procd_set_param command $persist_to_flash && [[ -e $backup_dir/$backup_filename ]] && cp $backup_dir/$backup_filename $data_file procd_set_param file /etc/config/tests-scheduler procd_set_param stdout 1 procd_set_param stderr 1 @@ -24,6 +28,13 @@ start_service() { stop_service() { config_load "${CONFIGURATION}" local persist_to_flash + local data_file + local backup_dir + local backup_filename config_get persist_to_flash probe persist_to_flash - $persist_to_flash && [[ -e $FRESHFILE ]] && [[ -d $BACKUPDIR ]] && cp $FRESHFILE $BACKUPFILE + config_get data_file probe data_file + config_get backup_dir probe backup_dir + config_get backup_filename probe backup_filename + + $persist_to_flash && [[ -e $data_file ]] && [[ -d $backup_dir ]] && cp $data_file $backup_dir/$backup_filename } From 8ed6c32fd9d28188a38f9da7390a9aa5e09b253e Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Thu, 17 Oct 2019 00:41:28 +0200 Subject: [PATCH 16/21] replace tests from config with hooks --- .../files/bin/tests-scheduler-at.lua | 49 +++++++++---------- .../files/etc/config/tests-scheduler | 4 ++ 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/packages/tests-scheduler/files/bin/tests-scheduler-at.lua b/packages/tests-scheduler/files/bin/tests-scheduler-at.lua index a3433fad9..1eca688c9 100644 --- a/packages/tests-scheduler/files/bin/tests-scheduler-at.lua +++ b/packages/tests-scheduler/files/bin/tests-scheduler-at.lua @@ -2,24 +2,20 @@ local JSON = require("luci.jsonc") local utils = require("lime.utils") +local fs = require("nixio.fs") +local libuci = require("uci") -local libuci_loaded, libuci = pcall(require, "uci") - -local function config_uci_get(option) +result = libuci:cursor():get("tests-scheduler","probe",option) +local function config_uci_get(sectionname, option) local result - if libuci_loaded then - result = libuci:cursor():get("tests-scheduler","probe",option) - else - result = nil - end + result = libuci:cursor():get("tests-scheduler",sectionname,option) return result end ---local peakTestsList = config_uci_get("peak_test") or {arg[1]} - ---local nightTestsList = config_uci_get("night_test") or {arg[2]} +local dataFile = arg[1] or config_uci_get("probe","data_file") +local peakHooksDir = arg[2] or config_uci_get("at","peak_hooks_dir") +local nightHooksDir = arg[3] or config_uci_get("at","night_hooks_dir") -local dataFile = config_uci_get("data_file") or "/tmp/tests-scheduler-probe-data" -- check if a file exists function file_exists(file) @@ -84,26 +80,27 @@ io.stderr:write("Found enough data in "..dataFile..", continuing.\n") local peakHour1,_ = max(data) local peakHour = peakHour1 - 1 -if not peakTestsList then - io.stderr:write("No tests configured to be run at the peak time.\n") -end - -for index,peakCommand in ipairs(peakTestsList) do - local peakMinute = (index * 5) % 60 +local peakDirFun = fs.dir(peakHooksDir) or {} +local peakIndex = 0 +for hook in fs.dir(peakHooksDir) do + local peakMinute = (peakIndex * 5) % 60 local peakMinutePad = string.format("%02d", peakMinute) - local peakAt = "echo '"..peakCommand.."' | at -Mv "..peakHour..":".. + local peakAt = "echo '"..peakHooksDir.."/"..hook.."' | at -Mv "..peakHour..":".. peakMinutePad.." 2>&1" local handlePeakAt = io.popen(peakAt, 'r') local peakAtRaw = handlePeakAt:read("*a") handlePeakAt:close() local peakAtTime = do_split(peakAtRaw,"%C+")[1] - utils.log("Scheduled time:\t"..peakAtTime.."\tCommand:\t"..peakCommand) + utils.log("Scheduled time:\t"..peakAtTime.."\tCommand:\t"..peakHooksDir.."/"..hook) + peakIndex = peakIndex + 1 end -if not nightTestsList then +local nightDirFun = fs.dir(nightHooksDir) or {} +if not nightDirFun(1) then io.stderr:write("No tests configured to be run at the night time.\n") os.exit(0) end +local nightDirFun = fs.dir(nightHooksDir) or {} local datatemp = data local nightHours = {} @@ -160,14 +157,16 @@ local handle = io.popen("shared-state insert tests-scheduler-night", "w") handle:write(JSON.stringify(myTimeTable)) handle:close() -for index,nightCommand in ipairs(nightTestsList) do - local nightMinuteIdx = (nightMinute + index - 1) % 60 +local nightIndex = 0 +for hook in nightDirFun do + local nightMinuteIdx = (nightMinute + nightIndex) % 60 local nightMinuteIdxPad = string.format("%02d", nightMinuteIdx) - local nightAt = "echo '"..nightCommand.."' | at -Mv "..nightHour..":".. + local nightAt = "echo '"..nightHooksDir.."/"..hook.."' | at -Mv "..nightHour..":".. nightMinuteIdxPad.." 2>&1" local handleNightAt = io.popen(nightAt, 'r') local nightAtRaw = handleNightAt:read("*a") handleNightAt:close() local nightAtTime = do_split(nightAtRaw,"%C+")[1] - utils.log("Scheduled time:\t"..nightAtTime.."\tCommand:\t"..nightCommand) + utils.log("Scheduled time:\t"..nightAtTime.."\tCommand:\t"..nightHooksDir.."/"..hook) + nightIndex = nightIndex + 1 end diff --git a/packages/tests-scheduler/files/etc/config/tests-scheduler b/packages/tests-scheduler/files/etc/config/tests-scheduler index 9831f6f56..4fd747b30 100644 --- a/packages/tests-scheduler/files/etc/config/tests-scheduler +++ b/packages/tests-scheduler/files/etc/config/tests-scheduler @@ -7,3 +7,7 @@ config probe 'probe' option backup_dir '/etc/tests-scheduler' option backup_filename 'tests-scheduler-probe-data-backup' option persist_to_flash true +config at 'at' + option peak_hooks_dir '/etc/tests-scheduler/peakHooks.d' + option night_hooks_dir '/etc/tests-scheduler/nightHooks.d' + From 4b4d9e6c0c1e8028be4a781a3712099556863cfc Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Thu, 17 Oct 2019 12:02:11 +0200 Subject: [PATCH 17/21] improvements --- .../etc/logrotate.d/tests-peak-lime-report | 1 + .../files/bin/tests-scheduler-at.lua | 31 ++++++++++++------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/tests-scheduler-lime/files/etc/logrotate.d/tests-peak-lime-report b/packages/tests-scheduler-lime/files/etc/logrotate.d/tests-peak-lime-report index cda9c82cb..5339cfab9 100644 --- a/packages/tests-scheduler-lime/files/etc/logrotate.d/tests-peak-lime-report +++ b/packages/tests-scheduler-lime/files/etc/logrotate.d/tests-peak-lime-report @@ -1,4 +1,5 @@ /tmp/tests-peak-lime-report { + daily compress rotate 5 size 100k diff --git a/packages/tests-scheduler/files/bin/tests-scheduler-at.lua b/packages/tests-scheduler/files/bin/tests-scheduler-at.lua index 1eca688c9..b291decd7 100644 --- a/packages/tests-scheduler/files/bin/tests-scheduler-at.lua +++ b/packages/tests-scheduler/files/bin/tests-scheduler-at.lua @@ -4,8 +4,9 @@ local JSON = require("luci.jsonc") local utils = require("lime.utils") local fs = require("nixio.fs") local libuci = require("uci") +local SharedState = require("shared-state") +require("nixio.util") -result = libuci:cursor():get("tests-scheduler","probe",option) local function config_uci_get(sectionname, option) local result result = libuci:cursor():get("tests-scheduler",sectionname,option) @@ -16,7 +17,6 @@ local dataFile = arg[1] or config_uci_get("probe","data_file") local peakHooksDir = arg[2] or config_uci_get("at","peak_hooks_dir") local nightHooksDir = arg[3] or config_uci_get("at","night_hooks_dir") - -- check if a file exists function file_exists(file) local f = io.open(file, "rb") @@ -95,20 +95,19 @@ for hook in fs.dir(peakHooksDir) do peakIndex = peakIndex + 1 end -local nightDirFun = fs.dir(nightHooksDir) or {} +local nightDirFun = fs.dir(nightHooksDir) or os.exit(0) if not nightDirFun(1) then io.stderr:write("No tests configured to be run at the night time.\n") os.exit(0) end -local nightDirFun = fs.dir(nightHooksDir) or {} +local nightDirFun = fs.dir(nightHooksDir) -local datatemp = data local nightHours = {} for i = 1,6 do - nightHour1,_ = min(datatemp) + nightHour1,_ = min(data) nightHours[i] = nightHour1 - 1 - datatemp[nightHour1] = math.huge + data[nightHour1] = math.huge end local getCommand = "shared-state get tests-scheduler-night" @@ -150,12 +149,20 @@ local min5minute1,_ = min(hits5minute) local min5minute = min5minute1 - 1 local nightMinute = min5minute * 5 local myTime = nightHour * 60 + nightMinute -local myTimeTable = {} local hostname = io.input("/proc/sys/kernel/hostname"):read("*line") -myTimeTable[hostname] = myTime -local handle = io.popen("shared-state insert tests-scheduler-night", "w") -handle:write(JSON.stringify(myTimeTable)) -handle:close() +local timeToLive = 24*60 + +nixio.openlog("shared-state") +local sharedState = SharedState("tests-scheduler-night", nixio.syslog) +sharedState.lock() +sharedState.load() +sharedState.insert(hostname, myTime, timeToLive) +sharedState.save() +sharedState.unlock() +nixio.closelog() +--local handle = io.popen("shared-state insert tests-scheduler-night", "w") +--handle:write(JSON.stringify(myTimeTable)) +--handle:close() local nightIndex = 0 for hook in nightDirFun do From c4690deb0513c3fab77a483e9e858061f3c544b5 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Sun, 20 Oct 2019 17:55:29 +0200 Subject: [PATCH 18/21] tests-scheduler create hooks dirs --- packages/tests-scheduler/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/tests-scheduler/Makefile b/packages/tests-scheduler/Makefile index c60dda305..37a6f23a1 100644 --- a/packages/tests-scheduler/Makefile +++ b/packages/tests-scheduler/Makefile @@ -39,7 +39,8 @@ define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/etc/uci-defaults/ $(INSTALL_DIR) $(1)/etc/init.d/ $(INSTALL_DIR) $(1)/etc/config/ - $(INSTALL_DIR) $(1)/etc/tests-scheduler/ + $(INSTALL_DIR) $(1)/etc/tests-scheduler/peakHooks.d/ + $(INSTALL_DIR) $(1)/etc/tests-scheduler/nightHooks.d/ $(INSTALL_BIN) ./files/bin/tests-scheduler-at.lua $(1)/bin/tests-scheduler-at $(INSTALL_BIN) ./files/bin/tests-scheduler-probe.lua $(1)/bin/tests-scheduler-probe $(INSTALL_BIN) ./files/etc/uci-defaults/* $(1)/etc/uci-defaults From 0ee98367bb748a62ef85b7174df8b2686fcfc804 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Sun, 20 Oct 2019 19:47:29 +0200 Subject: [PATCH 19/21] tests-scheduler-lime depends from tests-scheduler --- packages/tests-scheduler-lime/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tests-scheduler-lime/Makefile b/packages/tests-scheduler-lime/Makefile index 309e3d7d5..2573fd341 100644 --- a/packages/tests-scheduler-lime/Makefile +++ b/packages/tests-scheduler-lime/Makefile @@ -19,7 +19,7 @@ define Package/$(PKG_NAME) TITLE:=LibreMesh tests for tests-scheduler MAINTAINER:=Ilario Gelmetti URL:=https://libremesh.org - DEPENDS:=+logrotate +lime-report +bandwidth-test + DEPENDS:=+logrotate +lime-report +bandwidth-test +tests-scheduler PKGARCH:=all endef From c6bc20e61037b291be5ac47526054bcedbe4fc69 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Mon, 21 Oct 2019 00:32:10 +0200 Subject: [PATCH 20/21] sync before scheduling --- .../files/etc/uci-defaults/51_tests-scheduler-at | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at b/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at index 375594c9d..0c2beb708 100644 --- a/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at +++ b/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at @@ -9,7 +9,7 @@ unique_append() } unique_append \ - '* * * ((/bin/tests-scheduler-at; shared-state sync tests-scheduler-night &> /dev/null)&)'\ + '* * * ((shared-state sync tests-scheduler-night &> /dev/null; /bin/tests-scheduler-at; shared-state sync tests-scheduler-night &> /dev/null)&)'\ /etc/crontabs/root exit 0 From 21d9b47ef0073db339ceba9b342aac0ffe9128e2 Mon Sep 17 00:00:00 2001 From: Ilario Gelmetti Date: Mon, 21 Oct 2019 15:46:26 +0200 Subject: [PATCH 21/21] better randomization of cron time --- .../files/etc/uci-defaults/51_tests-scheduler-at | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at b/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at index 0c2beb708..d269304a0 100644 --- a/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at +++ b/packages/tests-scheduler/files/etc/uci-defaults/51_tests-scheduler-at @@ -1,7 +1,7 @@ #!/bin/sh -hour=$(awk 'BEGIN{srand();print int(rand()*24)}') -minute=$(awk 'BEGIN{srand();print int(rand()*60)}') +hour=$(awk -v seed=$RANDOM 'BEGIN{srand(seed);print int(rand()*24)}') +minute=$(awk -v seed=$RANDOM 'BEGIN{srand(seed);print int(rand()*60)}') unique_append() {