From 288f2027c96a0342ff703a7d1ba08df142274ccf Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Tue, 17 Oct 2023 15:55:15 -0300 Subject: [PATCH 001/102] hook test --- .../shared-state-mesh_wide_upgrade/Makefile | 23 +++++++++++ .../hooks/mesh_wide_upgrade/report_status | 25 ++++++++++++ .../shared-state-publish_mesh_wide_upgrade | 1 + .../shared-state_mesh_wide_upgrade_cron | 9 +++++ .../shared-state-publish_mesh_wide_upgrade | 38 +++++++++++++++++++ 5 files changed, 96 insertions(+) create mode 100644 packages/shared-state-mesh_wide_upgrade/Makefile create mode 100644 packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/report_status create mode 120000 packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade create mode 100755 packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/shared-state_mesh_wide_upgrade_cron create mode 100755 packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade diff --git a/packages/shared-state-mesh_wide_upgrade/Makefile b/packages/shared-state-mesh_wide_upgrade/Makefile new file mode 100644 index 000000000..2af45f95f --- /dev/null +++ b/packages/shared-state-mesh_wide_upgrade/Makefile @@ -0,0 +1,23 @@ +# +# Copyright (C) 2023 Javier Jorge +# Copyright (C) 2023 Asociación Civil Altermundi +# This is free software, licensed under the GNU Affero General Public License v3. +# + +include ../../libremesh.mk + +define Package/$(PKG_NAME) + SECTION:=lime + CATEGORY:=LibreMesh + TITLE:=Mesh wide upgrade module for shared-state + MAINTAINER:= Javier + DEPENDS:=+lua +luci-lib-jsonc +ubus-lime-utils \ + +lime-system +ubus-lime-location shared-state + PKGARCH:=all +endef + +define Package/$(PKG_NAME)/description + Syncronize node information to achieve mesh wide firmware upgrades +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/report_status b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/report_status new file mode 100644 index 000000000..19bd7b55f --- /dev/null +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/report_status @@ -0,0 +1,25 @@ +#!/usr/bin/lua + +--! LibreMesh +--! Copyright (C) 2019 Gioacchino Mazzurco +--! +--! This program is free software: you can redistribute it and/or modify +--! it under the terms of the GNU Affero General Public License as +--! published by the Free Software Foundation, either version 3 of the +--! License, or (at your option) any later version. +--! +--! This program is distributed in the hope that it will be useful, +--! but WITHOUT ANY WARRANTY; without even the implied warranty of +--! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +--! GNU Affero General Public License for more details. +--! +--! You should have received a copy of the GNU Affero General Public License +--! along with this program. If not, see . + +local JSON = require("luci.jsonc") +local utils = require "lime.utils" + +for key,value in pairs(JSON.parse(io.stdin:read("*all")) ) do + utils.log("hoock +++++ ",value.data, key) +end + diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade new file mode 120000 index 000000000..ee2664e94 --- /dev/null +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade @@ -0,0 +1 @@ +../../../usr/bin/shared-state-publish_mesh_wide_upgrade \ No newline at end of file diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/shared-state_mesh_wide_upgrade_cron b/packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/shared-state_mesh_wide_upgrade_cron new file mode 100755 index 000000000..7ee1858f2 --- /dev/null +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/shared-state_mesh_wide_upgrade_cron @@ -0,0 +1,9 @@ +#!/bin/sh +unique_append() +{ + grep -qF "$1" "$2" || echo "$1" >> "$2" +} + +unique_append \ + '*/5 * * * * ((sleep $(($RANDOM % 120)); shared-state sync mesh_wide_upgrade &> /dev/null)&)'\ + /etc/crontabs/root diff --git a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade new file mode 100755 index 000000000..6bb1d9109 --- /dev/null +++ b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade @@ -0,0 +1,38 @@ +#!/usr/bin/lua + +--! LibreMesh +--! Copyright (C) 2023 Javier Jorge +--! Copyright (C) 2023 Asociación Civil Altermundi +--! +--! This program is free software: you can redistribute it and/or modify +--! it under the terms of the GNU Affero General Public License as +--! published by the Free Software Foundation, either version 3 of the +--! License, or (at your option) any later version. +--! +--! This program is distributed in the hope that it will be useful, +--! but WITHOUT ANY WARRANTY; without even the implied warranty of +--! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +--! GNU Affero General Public License for more details. +--! +--! You should have received a copy of the GNU Affero General Public License +--! along with this program. If not, see . + +local JSON = require("luci.jsonc") +local network = require ("lime.network") +local location = require("lime.location") +local utils = require('lime.utils') +local config = require("lime.config") + +local hostname = utils.hostname() +function get_node_info() + return { + transaction_hash= "", + state= "downloading", + error= 0, + safe_upgrade_status= "", + eup_STATUS= "" + } +end + +local result = { [hostname] = get_node_info() } +io.popen("shared-state insert mesh_wide_upgrade", "w"):write(JSON.stringify(result)) From 1f96c5d098897634ed5f5ac3fcabc896ce3af47d Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Tue, 17 Oct 2023 16:32:50 -0300 Subject: [PATCH 002/102] added hook execution permision --- .../files/etc/shared-state/hooks/mesh_wide_upgrade/report_status | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/report_status diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/report_status b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/report_status old mode 100644 new mode 100755 From 75fb96aceb93bdbee0fad75be0a3fe559c726e2f Mon Sep 17 00:00:00 2001 From: selankon Date: Wed, 18 Oct 2023 15:39:34 +0200 Subject: [PATCH 003/102] Create lime-mesh-upgrade package --- packages/lime-mesh-upgrade/Makefile | 27 +++++++++++++++++ .../files/usr/lib/lua/lime-mesh-upgrade.lua | 9 ++++++ .../usr/libexec/rpcd/lime-mesh-upgrade.lua | 29 +++++++++++++++++++ .../usr/share/rpcd/acl.d/lime-utils.json | 16 ++++++++++ 4 files changed, 81 insertions(+) create mode 100644 packages/lime-mesh-upgrade/Makefile create mode 100644 packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua create mode 100755 packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua create mode 100644 packages/lime-mesh-upgrade/files/usr/share/rpcd/acl.d/lime-utils.json diff --git a/packages/lime-mesh-upgrade/Makefile b/packages/lime-mesh-upgrade/Makefile new file mode 100644 index 000000000..a5f033f6c --- /dev/null +++ b/packages/lime-mesh-upgrade/Makefile @@ -0,0 +1,27 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=lime-mesh-upgrade +PKG_VERSION=$(GIT_COMMIT_DATE)-$(GIT_COMMIT_TSTAMP) +GIT_COMMIT_DATE:=$(shell git log -n 1 --pretty=%ad --date=short . ) +GIT_COMMIT_TSTAMP:=$(shell git log -n 1 --pretty=%at . ) + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) + CATEGORY:=LibreMesh + MAINTAINER:=selankon + SUBMENU:=3. Applications + TITLE:=LibreMesh mesh wide firmware upgrade + DEPENDS:= +lua +libubus-lua +sysupgrade +wget +lime.utils + PKGARCH:=all +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/install + $(INSTALL_DIR) $(1)/ + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua new file mode 100644 index 000000000..397f3ea6d --- /dev/null +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -0,0 +1,9 @@ +#!/usr/bin/env lua + +local mesh_upgrade = {} + +function mesh_upgrade.became_master_node(urls) + -- todo +end + +return mesh_upgrade \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua new file mode 100755 index 000000000..c1c7e79af --- /dev/null +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua @@ -0,0 +1,29 @@ +#!/usr/bin/env lua + +--[[ + Copyright (C) 2013-2023 LibreMesh.org + This is free software, licensed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 + + Copyright 2023 Selankon +]] -- +local json = require 'luci.jsonc' +local mesh_upgrade = require 'lime-mesh-upgrade' + +local function became_master_node(msg) + local result = mesh_upgrade.became_master_node(msg) + return utils.printJson(result) +end + +local methods = { + became_master_node = {}, +} + +if arg[1] == 'list' then utils.printJson(methods) end + +if arg[1] == 'call' then + local msg = utils.rpcd_readline() + msg = json.parse(msg) + if arg[2] == 'became_master_node' then became_master_node(msg) + else utils.printJson({ error = "Method not found" }) + end +end diff --git a/packages/lime-mesh-upgrade/files/usr/share/rpcd/acl.d/lime-utils.json b/packages/lime-mesh-upgrade/files/usr/share/rpcd/acl.d/lime-utils.json new file mode 100644 index 000000000..a32b1c406 --- /dev/null +++ b/packages/lime-mesh-upgrade/files/usr/share/rpcd/acl.d/lime-utils.json @@ -0,0 +1,16 @@ +{ + "lime-app": { + "description": "lime-app public access", + "read": { + "ubus": { + "lime-utils": [ "*" ], + "system": [ "board" ] + } + }, + "write": { + "ubus": { + "lime-utils": [ "*" ] + } + } + } +} \ No newline at end of file From 863c0760195d8c208b29dfc46f3892da4fd0fb9d Mon Sep 17 00:00:00 2001 From: javierbrk Date: Wed, 18 Oct 2023 12:58:25 -0300 Subject: [PATCH 004/102] removed_files_from_other_commit --- .../shared-state-babel_links_info/Makefile | 23 ---------- .../bin/shared-state-publish_babel_links_info | 44 ------------------- 2 files changed, 67 deletions(-) delete mode 100644 packages/shared-state-babel_links_info/Makefile delete mode 100755 packages/shared-state-babel_links_info/files/usr/bin/shared-state-publish_babel_links_info diff --git a/packages/shared-state-babel_links_info/Makefile b/packages/shared-state-babel_links_info/Makefile deleted file mode 100644 index 3fca60520..000000000 --- a/packages/shared-state-babel_links_info/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (C) 2023 Javier Jorge -# Copyright (C) 2023 Asociación Civil Altermundi -# This is free software, licensed under the GNU Affero General Public License v3. -# - -include ../../libremesh.mk - -define Package/$(PKG_NAME) - SECTION:=lime - CATEGORY:=LibreMesh - TITLE:=Babel links information module for shared-state - MAINTAINER:= Javier - DEPENDS:=+lua +luci-lib-jsonc +ubus-lime-utils \ - +lime-system +ubus-lime-location shared-state - PKGARCH:=all -endef - -define Package/$(PKG_NAME)/description - Syncronize Babel links information beween nodes. -endef - -$(eval $(call BuildPackage,$(PKG_NAME))) \ No newline at end of file diff --git a/packages/shared-state-babel_links_info/files/usr/bin/shared-state-publish_babel_links_info b/packages/shared-state-babel_links_info/files/usr/bin/shared-state-publish_babel_links_info deleted file mode 100755 index 48301e0b0..000000000 --- a/packages/shared-state-babel_links_info/files/usr/bin/shared-state-publish_babel_links_info +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/lua - ---! LibreMesh ---! Copyright (C) 2019 Gioacchino Mazzurco ---! Copyright (C) 2019 Javier Jorge ---! ---! This program is free software: you can redistribute it and/or modify ---! it under the terms of the GNU Affero General Public License as ---! published by the Free Software Foundation, either version 3 of the ---! License, or (at your option) any later version. ---! ---! This program is distributed in the hope that it will be useful, ---! but WITHOUT ANY WARRANTY; without even the implied warranty of ---! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ---! GNU Affero General Public License for more details. ---! ---! You should have received a copy of the GNU Affero General Public License ---! along with this program. If not, see . - -local JSON = require("luci.jsonc") -local node_status = require ("lime.node_status") -local network = require ("lime.network") -local iwinfo = require "iwinfo" - - -function get_wifi_links_info() - local stations = node_status.get_stations() - local links = {} - for _, station in ipairs(stations) do - macparts = network.get_mac(station.iface) - src_macaddr = table.concat(macparts,":") - local station_stats = node_status.get_station_stats(station) - local freq = iwinfo.nl80211.frequency(station.iface) - table.insert(links, {src_mac=src_macaddr ,dst_mac=station.station_mac, - signal=station_stats.signal,chains=station_stats.chains,iface=station.iface, - rx_rate=station_stats.rx_rate,tx_rate=station_stats.tx_rate,freq=freq } ) - end - return links -end - -local hostname = io.input("/proc/sys/kernel/hostname"):read("*line") -local result = { [hostname] = get_wifi_links_info() } -io.popen("shared-state insert wifi_links_info", "w"):write(JSON.stringify(result)) - From f259854924d892736571040bf130c3e461d3e4f8 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Wed, 18 Oct 2023 16:16:03 -0300 Subject: [PATCH 005/102] nuevo modelo de datos --- .../shared-state-mesh_wide_upgrade/Makefile | 2 +- .../{report_status => start_upgrade} | 13 ++++++++-- .../shared-state-publish_mesh_wide_upgrade | 25 +++++++++++-------- 3 files changed, 27 insertions(+), 13 deletions(-) rename packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/{report_status => start_upgrade} (53%) diff --git a/packages/shared-state-mesh_wide_upgrade/Makefile b/packages/shared-state-mesh_wide_upgrade/Makefile index 2af45f95f..4afd9099a 100644 --- a/packages/shared-state-mesh_wide_upgrade/Makefile +++ b/packages/shared-state-mesh_wide_upgrade/Makefile @@ -12,7 +12,7 @@ define Package/$(PKG_NAME) TITLE:=Mesh wide upgrade module for shared-state MAINTAINER:= Javier DEPENDS:=+lua +luci-lib-jsonc +ubus-lime-utils \ - +lime-system +ubus-lime-location shared-state + +lime-system shared-state PKGARCH:=all endef diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/report_status b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade similarity index 53% rename from packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/report_status rename to packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade index 19bd7b55f..143a0cbdd 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/report_status +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -19,7 +19,16 @@ local JSON = require("luci.jsonc") local utils = require "lime.utils" -for key,value in pairs(JSON.parse(io.stdin:read("*all")) ) do - utils.log("hoock +++++ ",value.data, key) +--if already involved in an upgrade transaction do nothing +for node,s_s_data in pairs(JSON.parse(io.stdin:read("*all")) ) do + --if any node has started an upgrade process and start one too + --fetch the info from the master node publication + if s_s_data.data.master_node == node then + utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "starting upgrade from"'..s_s_data.data.repo_url.." "..node ) + --start the upgrade process referencing the original upgrade publication + --start_upgrade(s_s_data.timestamp,s_s_data.id,sate="started",s_s_data.data.master_node) + end + utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "hoock +++++ "'..s_s_data.data.." "..node ) + utils.log("hook started ",s_s_data.data, node) end diff --git a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade index 6bb1d9109..f56c79986 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade @@ -18,21 +18,26 @@ --! along with this program. If not, see . local JSON = require("luci.jsonc") -local network = require ("lime.network") -local location = require("lime.location") local utils = require('lime.utils') -local config = require("lime.config") local hostname = utils.hostname() -function get_node_info() +function report_upgrade_status() return { - transaction_hash= "", - state= "downloading", - error= 0, - safe_upgrade_status= "", - eup_STATUS= "" + type= "upgrade", + data={ + firmware_ver="xxxx", + repo_url="http://10.13.0.1/lros/api/v1/", + state="downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", + error="CODE", + safe_upgrade_status="", + eup_STATUS="", + }, + timestamp=231354654, + id="", + state="started/aborted/finished", + master_node="" } end -local result = { [hostname] = get_node_info() } +local result = { [hostname] = report_upgrade_status() } io.popen("shared-state insert mesh_wide_upgrade", "w"):write(JSON.stringify(result)) From e9aadbdf2fe203715f494a268ba9f8f25999f924 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Fri, 20 Oct 2023 16:33:15 -0300 Subject: [PATCH 006/102] wip ... --- .../files/usr/etc/config/mesh-upgrade | 8 ++++++ .../files/usr/lib/lua/lime-mesh-upgrade.lua | 8 ++++++ .../hooks/mesh_wide_upgrade/start_upgrade | 26 ++++++++++++------- .../shared-state-publish_mesh_wide_upgrade | 1 + 4 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade diff --git a/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade b/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade new file mode 100644 index 000000000..f1052b83c --- /dev/null +++ b/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade @@ -0,0 +1,8 @@ +config mesh-upgrade 'main' + option id '1' + option repo_url 'http://10.13.156.241:8000/web_test/releases/api/' # TODO: provide a saner default + option upgrade_state 'downloading' + option error 'CODE' + option timestamp '231354654' + option transaction_state="started", + option master_node="primero" \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 397f3ea6d..6a0422361 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -6,4 +6,12 @@ function mesh_upgrade.became_master_node(urls) -- todo end +function mesh_upgrade.upgrade_in_progress() + return uci:get('mesh_upgrade', 'main', 'transaction_state') == 'started' +end + +function mendmesh_upgrade.start(upgrade_data) +end + + return mesh_upgrade \ No newline at end of file diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade index 143a0cbdd..b32cbe689 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -18,17 +18,23 @@ local JSON = require("luci.jsonc") local utils = require "lime.utils" +local mesh_upgrade = require "lime.mesh-upgrade" + --if already involved in an upgrade transaction do nothing -for node,s_s_data in pairs(JSON.parse(io.stdin:read("*all")) ) do - --if any node has started an upgrade process and start one too - --fetch the info from the master node publication - if s_s_data.data.master_node == node then - utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "starting upgrade from"'..s_s_data.data.repo_url.." "..node ) - --start the upgrade process referencing the original upgrade publication - --start_upgrade(s_s_data.timestamp,s_s_data.id,sate="started",s_s_data.data.master_node) +if not mesh_upgrade.upgrade_in_progress() then + for node, s_s_data in pairs(JSON.parse(io.stdin:read("*all"))) do + --if any node has started an upgrade process and start one too + --fetch the info from the master node publication + if s_s_data.data.master_node == node then + mesh_upgrade.start(s_s_data.data) + utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "starting upgrade from"' .. + s_s_data.data.repo_url .. " " .. node) + --start the upgrade process referencing the original upgrade publication + --start_upgrade(s_s_data.timestamp,s_s_data.id,sate="started",s_s_data.data.master_node) + end + utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "hoock +++++ "' .. + JSON.stringify(s_s_data.data) .. " " .. node) + utils.log("hook started ", JSON.stringify(s_s_data.data), node) end - utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "hoock +++++ "'..s_s_data.data.." "..node ) - utils.log("hook started ",s_s_data.data, node) end - diff --git a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade index f56c79986..83748e5be 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade @@ -22,6 +22,7 @@ local utils = require('lime.utils') local hostname = utils.hostname() function report_upgrade_status() + --todo: get data from libmeshupgrade and send return { type= "upgrade", data={ From 49d4e23c692ba48ec00a335721448343278580d0 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 23 Oct 2023 11:22:14 -0300 Subject: [PATCH 007/102] add uci interface --- .../files/usr/etc/config/mesh-upgrade | 5 +- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 63 ++++++++++++++++++- .../hooks/mesh_wide_upgrade/start_upgrade | 7 ++- .../shared-state-publish_mesh_wide_upgrade | 18 +----- 4 files changed, 73 insertions(+), 20 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade b/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade index f1052b83c..6fc9939e6 100644 --- a/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade @@ -1,8 +1,11 @@ config mesh-upgrade 'main' option id '1' + option firmware_ver "xxxx" option repo_url 'http://10.13.156.241:8000/web_test/releases/api/' # TODO: provide a saner default option upgrade_state 'downloading' + option safe_upgrade_status '' + option eup_STATUS '' option error 'CODE' option timestamp '231354654' - option transaction_state="started", + option transaction_state="aborted", option master_node="primero" \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 6a0422361..d6aab146c 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -1,6 +1,8 @@ #!/usr/bin/env lua +local libuci = require "uci" local mesh_upgrade = {} +local uci = libuci.cursor() function mesh_upgrade.became_master_node(urls) -- todo @@ -10,8 +12,65 @@ function mesh_upgrade.upgrade_in_progress() return uci:get('mesh_upgrade', 'main', 'transaction_state') == 'started' end -function mendmesh_upgrade.start(upgrade_data) +function mesh_upgrade.abort() + uci:set('mesh_upgrade', 'main', 'transaction_state', 'aborted') + -- stop and delete everything + -- trigger a shared state publish +end + +function mesh_upgrade.start(upgrade_data) + if (type(upgrade_data.id) == "number") and + string.match(upgrade_data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil + --perform aditional checks + then + uci:set('mesh_upgrade', 'main', 'id', upgrade_data.id) + uci:set('mesh_upgrade', 'main', 'repo_url', upgrade_data.data.repo_url) + uci:set('mesh_upgrade', 'main', 'firmware_ver', upgrade_data.data.firmware_ver) + uci:set('mesh_upgrade', 'main', 'upgrade_state', 'starting') + uci:set('mesh_upgrade', 'main', 'error', 0) + uci:set('mesh_upgrade', 'main', 'timestamp', upgrade_data.timestamp) + uci:set('mesh_upgrade', 'main', 'master_node', upgrade_data.master_node) + uci:set('mesh_upgrade', 'main', 'transaction_state', 'started') + uci:save('mesh_upgrade') + uci:commit('mesh_upgrade') + --trigger a shared state publish + else + utils.log("upgrade not started input data errors") + print("upgrade not started input data errors") + end +end + +-- +-- { +-- type= "upgrade", +-- data={ +-- firmware_ver="xxxx", +-- repo_url="http://10.13.0.1/lros/api/v1/", +-- upgrde_state="starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", +-- error="CODE", +-- safe_upgrade_status="", +-- eup_STATUS="", +-- }, +-- timestamp=231354654, +-- id="", +-- transaction_state="started/aborted/finished", +-- master_node="" +-- } +-- +function mesh_upgrade.get_status() + local upgrade_data = {} + upgrade_data.type= "upgrade" + upgrade_data.id = uci:get('mesh_upgrade', 'main', 'id') + upgrade_data.data.firmware_ver = uci:get('mesh_upgrade', 'main', 'firmware_ver') + upgrade_data.data.repo_url = uci:get('mesh_upgrade', 'main', 'repo_url') + upgrade_data.data.upgrade_state = uci:get('mesh_upgrade', 'main', 'upgrade_state') + upgrade_data.data.error = uci:get('mesh_upgrade', 'main', 'error') + upgrade_data.data.safe_upgrade_status=uci:get('mesh_upgrade', 'main', 'safe_upgrade_status') + upgrade_data.data.eup_STATUS=uci:get('mesh_upgrade', 'main', 'eup_STATUS') + upgrade_data.timestamp = uci:get('mesh_upgrade', 'main', 'timestamp') + upgrade_data.master_node = uci:get('mesh_upgrade', 'main', 'master_node') + upgrade_data.transaction_state = uci:get('mesh_upgrade', 'main', 'transaction_state') end -return mesh_upgrade \ No newline at end of file +return mesh_upgrade diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade index b32cbe689..3e773d1b1 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -24,8 +24,8 @@ local mesh_upgrade = require "lime.mesh-upgrade" --if already involved in an upgrade transaction do nothing if not mesh_upgrade.upgrade_in_progress() then for node, s_s_data in pairs(JSON.parse(io.stdin:read("*all"))) do - --if any node has started an upgrade process and start one too - --fetch the info from the master node publication + --if any node has started an upgrade process and start one too? + --fetch the info from the master node publication? if s_s_data.data.master_node == node then mesh_upgrade.start(s_s_data.data) utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "starting upgrade from"' .. @@ -37,4 +37,7 @@ if not mesh_upgrade.upgrade_in_progress() then JSON.stringify(s_s_data.data) .. " " .. node) utils.log("hook started ", JSON.stringify(s_s_data.data), node) end +else + utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "already started an upgrade process"') + utils.log("already started an upgrade process") end diff --git a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade index 83748e5be..1368949b4 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade @@ -19,25 +19,13 @@ local JSON = require("luci.jsonc") local utils = require('lime.utils') +local mesh_upgrade = require "lime.mesh-upgrade" + local hostname = utils.hostname() function report_upgrade_status() --todo: get data from libmeshupgrade and send - return { - type= "upgrade", - data={ - firmware_ver="xxxx", - repo_url="http://10.13.0.1/lros/api/v1/", - state="downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", - error="CODE", - safe_upgrade_status="", - eup_STATUS="", - }, - timestamp=231354654, - id="", - state="started/aborted/finished", - master_node="" - } + return mesh_upgrade.get_status() end local result = { [hostname] = report_upgrade_status() } From 0d82acfe2bc869c673131505d24353ce9382f4ab Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 23 Oct 2023 13:05:34 -0300 Subject: [PATCH 008/102] removed dependencies --- packages/lime-mesh-upgrade/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lime-mesh-upgrade/Makefile b/packages/lime-mesh-upgrade/Makefile index a5f033f6c..5ea56307a 100644 --- a/packages/lime-mesh-upgrade/Makefile +++ b/packages/lime-mesh-upgrade/Makefile @@ -12,7 +12,7 @@ define Package/$(PKG_NAME) MAINTAINER:=selankon SUBMENU:=3. Applications TITLE:=LibreMesh mesh wide firmware upgrade - DEPENDS:= +lua +libubus-lua +sysupgrade +wget +lime.utils + DEPENDS:= +lua +libubus-lua +wget PKGARCH:=all endef From 7895145f475511277bc6adf791cc2c5f551c3aa6 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 23 Oct 2023 15:12:09 -0300 Subject: [PATCH 009/102] testing uci files --- .../files/usr/etc/config/mesh-upgrade | 6 +- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 14 ++++- .../tests/test_lime-mesh-upgrade.lua | 57 +++++++++++++++++++ tests/utils.lua | 2 +- 4 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua diff --git a/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade b/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade index 6fc9939e6..aeaf3ffc5 100644 --- a/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade @@ -7,5 +7,7 @@ config mesh-upgrade 'main' option eup_STATUS '' option error 'CODE' option timestamp '231354654' - option transaction_state="aborted", - option master_node="primero" \ No newline at end of file + option transaction_state 'aborted' + option master_node 'primero' + #option notset "" + \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index d6aab146c..9ad779648 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -2,28 +2,35 @@ local libuci = require "uci" local mesh_upgrade = {} -local uci = libuci.cursor() + function mesh_upgrade.became_master_node(urls) -- todo end function mesh_upgrade.upgrade_in_progress() + local uci = libuci.cursor() return uci:get('mesh_upgrade', 'main', 'transaction_state') == 'started' end function mesh_upgrade.abort() + local uci = libuci.cursor() uci:set('mesh_upgrade', 'main', 'transaction_state', 'aborted') + uci:save('mesh_upgrade') + uci:commit('mesh_upgrade') -- stop and delete everything -- trigger a shared state publish end function mesh_upgrade.start(upgrade_data) + local uci = libuci.cursor() if (type(upgrade_data.id) == "number") and - string.match(upgrade_data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil + string.match(upgrade_data.data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil --perform aditional checks then - uci:set('mesh_upgrade', 'main', 'id', upgrade_data.id) + print (uci:set('mesh_upgrade', 'main')) + print (uci:set('mesh_upgrade', 'main', "mesh_upgrade")) + print (uci:set('mesh_upgrade', 'main', 'id', upgrade_data.id)) uci:set('mesh_upgrade', 'main', 'repo_url', upgrade_data.data.repo_url) uci:set('mesh_upgrade', 'main', 'firmware_ver', upgrade_data.data.firmware_ver) uci:set('mesh_upgrade', 'main', 'upgrade_state', 'starting') @@ -59,6 +66,7 @@ end -- function mesh_upgrade.get_status() local upgrade_data = {} + upgrade_data.data={} upgrade_data.type= "upgrade" upgrade_data.id = uci:get('mesh_upgrade', 'main', 'id') upgrade_data.data.firmware_ver = uci:get('mesh_upgrade', 'main', 'firmware_ver') diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua new file mode 100644 index 000000000..76f80cd05 --- /dev/null +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -0,0 +1,57 @@ +local config = require 'lime.config' +local network = require 'lime.network' +local wireless = require 'lime.wireless' +local utils = require 'lime.utils' +local test_utils = require 'tests.utils' +local lime_mesh_upgrade = require 'lime-mesh-upgrade' +local json = require 'luci.jsonc' + + +-- disable logging in config module +config.log = function() end + +local uci + +local upgrade_data = +{ + type= "upgrade", + data={ + firmware_ver="xxxx", + repo_url="http://10.13.0.1/lros/api/v1/", + upgrde_state="starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", + error="CODE", + safe_upgrade_status="", + eup_STATUS="", + }, + timestamp=231354654, + id=21, + transaction_state="started/aborted/finished", + master_node="" +} + +describe('LiMe mesh upgrade', function() + it('test config', function() + print("pruebaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2") + print (uci:set('mesh_upgrade', 'main', "mesh_upgrade")) + print ("test") + lime_mesh_upgrade.start(upgrade_data) + utils.printJson(lime_mesh_upgrade.get_status()) + + + end) + + it('test config 2', function() + print("pruebaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaa2") + end) + + before_each('', function() + print("pruebaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1") + uci = test_utils.setup_test_uci() + end) + + after_each('', function() + print("pruebaaaaaaaaaaaaaaaaaaaaaaaaaa3") + + test_utils.teardown_test_uci(uci) + end) +end) \ No newline at end of file diff --git a/tests/utils.lua b/tests/utils.lua index ed64806fa..f10cced1f 100644 --- a/tests/utils.lua +++ b/tests/utils.lua @@ -9,7 +9,7 @@ utils.assert = assert UCI_CONFIG_FILES = { "6relayd", "babeld", "batman-adv", "check-date", "dhcp", "dropbear", "fstab", "firewall", - "libremap", "lime", "lime-app", "location", + "libremap", "lime", "lime-app", "location", "mesh-upgrade", "luci", "network", "pirania", "rpcd", "shared-state", "system", "ucitrack", "uhttpd", "wireless", "deferable-reboot", config.UCI_AUTOGEN_NAME, config.UCI_NODE_NAME, config.UCI_COMMUNITY_NAME, config.UCI_DEFAULTS_NAME From f98ac086584b0722cea01fc986c9656481f6f3b0 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 23 Oct 2023 15:31:15 -0300 Subject: [PATCH 010/102] fixed underscore typo --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 55 ++++++++++--------- .../tests/test_lime-mesh-upgrade.lua | 2 +- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 9ad779648..fc13cdf38 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -1,4 +1,3 @@ -#!/usr/bin/env lua local libuci = require "uci" local mesh_upgrade = {} @@ -10,14 +9,14 @@ end function mesh_upgrade.upgrade_in_progress() local uci = libuci.cursor() - return uci:get('mesh_upgrade', 'main', 'transaction_state') == 'started' + return uci:get('mesh-upgrade', 'main', 'transaction_state') == 'started' end function mesh_upgrade.abort() local uci = libuci.cursor() - uci:set('mesh_upgrade', 'main', 'transaction_state', 'aborted') - uci:save('mesh_upgrade') - uci:commit('mesh_upgrade') + uci:set('mesh-upgrade', 'main', 'transaction_state', 'aborted') + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') -- stop and delete everything -- trigger a shared state publish end @@ -28,18 +27,18 @@ function mesh_upgrade.start(upgrade_data) string.match(upgrade_data.data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil --perform aditional checks then - print (uci:set('mesh_upgrade', 'main')) - print (uci:set('mesh_upgrade', 'main', "mesh_upgrade")) - print (uci:set('mesh_upgrade', 'main', 'id', upgrade_data.id)) - uci:set('mesh_upgrade', 'main', 'repo_url', upgrade_data.data.repo_url) - uci:set('mesh_upgrade', 'main', 'firmware_ver', upgrade_data.data.firmware_ver) - uci:set('mesh_upgrade', 'main', 'upgrade_state', 'starting') - uci:set('mesh_upgrade', 'main', 'error', 0) - uci:set('mesh_upgrade', 'main', 'timestamp', upgrade_data.timestamp) - uci:set('mesh_upgrade', 'main', 'master_node', upgrade_data.master_node) - uci:set('mesh_upgrade', 'main', 'transaction_state', 'started') - uci:save('mesh_upgrade') - uci:commit('mesh_upgrade') + uci:set('mesh-upgrade', 'main')) + uci:set('mesh-upgrade', 'main', "mesh_upgrade")) + uci:set('mesh-upgrade', 'main', 'id', upgrade_data.id)) + uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.data.repo_url) + uci:set('mesh-upgrade', 'main', 'firmware_ver', upgrade_data.data.firmware_ver) + uci:set('mesh-upgrade', 'main', 'upgrade_state', 'starting') + uci:set('mesh-upgrade', 'main', 'error', 0) + uci:set('mesh-upgrade', 'main', 'timestamp', upgrade_data.timestamp) + uci:set('mesh-upgrade', 'main', 'master_node', upgrade_data.master_node) + uci:set('mesh-upgrade', 'main', 'transaction_state', 'started') + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') --trigger a shared state publish else utils.log("upgrade not started input data errors") @@ -65,19 +64,21 @@ end -- } -- function mesh_upgrade.get_status() + local uci = libuci.cursor() local upgrade_data = {} upgrade_data.data={} upgrade_data.type= "upgrade" - upgrade_data.id = uci:get('mesh_upgrade', 'main', 'id') - upgrade_data.data.firmware_ver = uci:get('mesh_upgrade', 'main', 'firmware_ver') - upgrade_data.data.repo_url = uci:get('mesh_upgrade', 'main', 'repo_url') - upgrade_data.data.upgrade_state = uci:get('mesh_upgrade', 'main', 'upgrade_state') - upgrade_data.data.error = uci:get('mesh_upgrade', 'main', 'error') - upgrade_data.data.safe_upgrade_status=uci:get('mesh_upgrade', 'main', 'safe_upgrade_status') - upgrade_data.data.eup_STATUS=uci:get('mesh_upgrade', 'main', 'eup_STATUS') - upgrade_data.timestamp = uci:get('mesh_upgrade', 'main', 'timestamp') - upgrade_data.master_node = uci:get('mesh_upgrade', 'main', 'master_node') - upgrade_data.transaction_state = uci:get('mesh_upgrade', 'main', 'transaction_state') + upgrade_data.id = uci:get('mesh-upgrade', 'main', 'id') + upgrade_data.data.firmware_ver = uci:get('mesh-upgrade', 'main', 'firmware_ver') + upgrade_data.data.repo_url = uci:get('mesh-upgrade', 'main', 'repo_url') + upgrade_data.data.upgrade_state = uci:get('mesh-upgrade', 'main', 'upgrade_state') + upgrade_data.data.error = uci:get('mesh-upgrade', 'main', 'error') + upgrade_data.data.safe_upgrade_status=uci:get('mesh-upgrade', 'main', 'safe_upgrade_status') + upgrade_data.data.eup_STATUS=uci:get('mesh-upgrade', 'main', 'eup_STATUS') + upgrade_data.timestamp = uci:get('mesh-upgrade', 'main', 'timestamp') + upgrade_data.master_node = uci:get('mesh-upgrade', 'main', 'master_node') + upgrade_data.transaction_state = uci:get('mesh-upgrade', 'main', 'transaction_state') + return upgrade_data end diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 76f80cd05..123deaeef 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -32,7 +32,7 @@ local upgrade_data = describe('LiMe mesh upgrade', function() it('test config', function() print("pruebaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2") - print (uci:set('mesh_upgrade', 'main', "mesh_upgrade")) + print (uci:set('mesh-upgrade', 'main', "mesh-upgrade")) print ("test") lime_mesh_upgrade.start(upgrade_data) utils.printJson(lime_mesh_upgrade.get_status()) From 76057333cb51351c9c0c11cebdd268a4b4a2e94f Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 23 Oct 2023 15:37:39 -0300 Subject: [PATCH 011/102] test --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 7 +++---- .../lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua | 2 -- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index fc13cdf38..dce239796 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -27,12 +27,11 @@ function mesh_upgrade.start(upgrade_data) string.match(upgrade_data.data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil --perform aditional checks then - uci:set('mesh-upgrade', 'main')) - uci:set('mesh-upgrade', 'main', "mesh_upgrade")) - uci:set('mesh-upgrade', 'main', 'id', upgrade_data.id)) + print (uci:set('mesh-upgrade', 'main', "mesh-upgrade")) + print(uci:set('mesh-upgrade', 'main', 'id', upgrade_data.id)) uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.data.repo_url) uci:set('mesh-upgrade', 'main', 'firmware_ver', upgrade_data.data.firmware_ver) - uci:set('mesh-upgrade', 'main', 'upgrade_state', 'starting') + print(uci:set('mesh-upgrade', 'main', 'upgrade_state', 'starting')) uci:set('mesh-upgrade', 'main', 'error', 0) uci:set('mesh-upgrade', 'main', 'timestamp', upgrade_data.timestamp) uci:set('mesh-upgrade', 'main', 'master_node', upgrade_data.master_node) diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 123deaeef..a8b272279 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -36,8 +36,6 @@ describe('LiMe mesh upgrade', function() print ("test") lime_mesh_upgrade.start(upgrade_data) utils.printJson(lime_mesh_upgrade.get_status()) - - end) it('test config 2', function() From 62b6f12d2ebfb3b23a217b0d3cb0968232144f18 Mon Sep 17 00:00:00 2001 From: selankon Date: Wed, 25 Oct 2023 15:39:02 +0200 Subject: [PATCH 012/102] Implement set_up_firmware_repository --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 53 ++++++++++++++++--- .../usr/libexec/rpcd/lime-mesh-upgrade.lua | 6 +-- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index dce239796..eb7c90070 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -1,18 +1,56 @@ +#!/usr/bin/env lua + local libuci = require "uci" +local eupgrade = require 'eupgrade' local mesh_upgrade = {} +function mesh_upgrade.set_workdir(workdir) + if not utils.file_exists(workdir) then + os.execute('mkdir -p ' .. workdir) + end + if fs.stat(workdir, "type") ~= "dir" then + error("Can't configure workdir " .. workdir) + end + mesh_upgrade.WORKDIR = workdir + --mup.DOWNLOAD_INFO_CACHE_FILE = mup.WORKDIR .. '/download_status' + mesh_upgrade.FIRMWARE_LATEST_JSON = mup.WORKDIR .. "/firmware_latest_mesh_wide.json" + --mup.FIRMWARE_LATEST_JSON_SIGNATURE = mup.FIRMWARE_LATEST_JSON .. '.sig' +end + +mesh_upgrade.set_workdir("/tmp/mesh_upgrade") -function mesh_upgrade.became_master_node(urls) - -- todo +-- This function will download latest librerouter os firmware and expose it as +-- a local repository in order to be used for other nodes +function mesh_upgrade.set_up_firmware_repository() + -- 1. Check if new version is available and download it demonized using eupgrade + local cached_only = false + local latest_data = eupgrade.is_new_version_available(cached_only) + if latest_data then + utils.execute_daemonized("eupgrade-download") + else + ret = {status = 'error', message = 'New version is not availabe'} + end + + -- 2. Create local repository json data + --latest_data = json.parse(latest_json) + local upgrade_url = eupgrade.get_upgrade_api_url() + for _, im in pairs(latest_data['images']) do + im['download-urls'] = string.gsub(im['download-urls'], upgrade_url, "test") + end + -- todo(kon): implement create signature + utils.write_file(mesh_upgrade.FIRMWARE_LATEST_JSON, latest_data) end -function mesh_upgrade.upgrade_in_progress() +-- Shared state functions + +-- Validate if the upgrade is already started +function mesh_upgrade.mesh_upgrade_is_started() local uci = libuci.cursor() return uci:get('mesh-upgrade', 'main', 'transaction_state') == 'started' end -function mesh_upgrade.abort() +function mesh_upgrade.mesh_upgrade_abort() local uci = libuci.cursor() uci:set('mesh-upgrade', 'main', 'transaction_state', 'aborted') uci:save('mesh-upgrade') @@ -21,7 +59,9 @@ function mesh_upgrade.abort() -- trigger a shared state publish end -function mesh_upgrade.start(upgrade_data) +-- It set up the information of where to download the new firmware. +-- Called by a shared state hook +function mesh_upgrade.set_mesh_upgrade_info(upgrade_data) local uci = libuci.cursor() if (type(upgrade_data.id) == "number") and string.match(upgrade_data.data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil @@ -62,7 +102,7 @@ end -- master_node="" -- } -- -function mesh_upgrade.get_status() +function mesh_upgrade.get_mesh_upgrade_status() local uci = libuci.cursor() local upgrade_data = {} upgrade_data.data={} @@ -80,5 +120,4 @@ function mesh_upgrade.get_status() return upgrade_data end - return mesh_upgrade diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua index c1c7e79af..4fa9969d5 100755 --- a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua @@ -9,8 +9,8 @@ local json = require 'luci.jsonc' local mesh_upgrade = require 'lime-mesh-upgrade' -local function became_master_node(msg) - local result = mesh_upgrade.became_master_node(msg) +local function set_up_firmware_repository(msg) + local result = mesh_upgrade.set_up_firmware_repository(msg) return utils.printJson(result) end @@ -23,7 +23,7 @@ if arg[1] == 'list' then utils.printJson(methods) end if arg[1] == 'call' then local msg = utils.rpcd_readline() msg = json.parse(msg) - if arg[2] == 'became_master_node' then became_master_node(msg) + if arg[2] == 'set_up_firmware_repository' then set_up_firmware_repository(msg) else utils.printJson({ error = "Method not found" }) end end From d7d3d304726daf719cec1a354ffcdd900d1879c9 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Tue, 31 Oct 2023 13:40:34 -0300 Subject: [PATCH 013/102] mesh upgrade lib: improves tests, creates states as constants --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 94 ++++++++++++------- .../tests/test_lime-mesh-upgrade.lua | 31 +++--- .../hooks/mesh_wide_upgrade/start_upgrade | 9 +- 3 files changed, 86 insertions(+), 48 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index eb7c90070..28074c4b1 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -2,23 +2,50 @@ local libuci = require "uci" local eupgrade = require 'eupgrade' +local config = require "lime.config" -local mesh_upgrade = {} -function mesh_upgrade.set_workdir(workdir) - if not utils.file_exists(workdir) then - os.execute('mkdir -p ' .. workdir) - end - if fs.stat(workdir, "type") ~= "dir" then - error("Can't configure workdir " .. workdir) - end - mesh_upgrade.WORKDIR = workdir - --mup.DOWNLOAD_INFO_CACHE_FILE = mup.WORKDIR .. '/download_status' - mesh_upgrade.FIRMWARE_LATEST_JSON = mup.WORKDIR .. "/firmware_latest_mesh_wide.json" - --mup.FIRMWARE_LATEST_JSON_SIGNATURE = mup.FIRMWARE_LATEST_JSON .. '.sig' -end -mesh_upgrade.set_workdir("/tmp/mesh_upgrade") +local mesh_upgrade = { + --posible tranactin states + transaction_states = { + NO_TRANSACTION="no_transaction", + STARTED = "started", --ther is a transaction in progress + ABORTED = "aborted", + FINISHED = "finished" + }, + --psible upgrade states enumeration + upgrade_states = { + DOWNLOADING= "downloading", + READY_FOR_UPGRADE="ready_for_upgrade", + UPGRADE_SCHELUDED="upgrade_scheluded", + CONFIRMATION_PENDING="confirmation_pending", + CONFIRMED="confirmed", + UPDATED="updated", + ERROR= "error" + }, + -- list of possible errors + errors = + { + DOWNLOAD_FAILED="download failed", + CONFIRMATION_TIME_OUT="confirmation timeout" + } +} + +-- function mesh_upgrade.set_workdir(workdir) +-- if not utils.file_exists(workdir) then +-- os.execute('mkdir -p ' .. workdir) +-- end +-- if fs.stat(workdir, "type") ~= "dir" then +-- error("Can't configure workdir " .. workdir) +-- end +-- mesh_upgrade.WORKDIR = workdir +-- --mup.DOWNLOAD_INFO_CACHE_FILE = mup.WORKDIR .. '/download_status' +-- mesh_upgrade.FIRMWARE_LATEST_JSON = mup.WORKDIR .. "/firmware_latest_mesh_wide.json" +-- --mup.FIRMWARE_LATEST_JSON_SIGNATURE = mup.FIRMWARE_LATEST_JSON .. '.sig' +-- end + +-- mesh_upgrade.set_workdir("/tmp/mesh_upgrade") -- This function will download latest librerouter os firmware and expose it as -- a local repository in order to be used for other nodes @@ -29,7 +56,7 @@ function mesh_upgrade.set_up_firmware_repository() if latest_data then utils.execute_daemonized("eupgrade-download") else - ret = {status = 'error', message = 'New version is not availabe'} + ret = { status = 'error', message = 'New version is not availabe' } end -- 2. Create local repository json data @@ -44,41 +71,44 @@ end -- Shared state functions --- Validate if the upgrade is already started +-- Validate if the upgrade has already started function mesh_upgrade.mesh_upgrade_is_started() local uci = libuci.cursor() return uci:get('mesh-upgrade', 'main', 'transaction_state') == 'started' + --todo: what happens if a mesh_upgrade has started more than an hour ago ? should this node abort it ? end function mesh_upgrade.mesh_upgrade_abort() local uci = libuci.cursor() - uci:set('mesh-upgrade', 'main', 'transaction_state', 'aborted') + uci:set('mesh-upgrade', 'main', 'transaction_state', mesh_upgrade.transaction_states.ABORTED) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') -- stop and delete everything -- trigger a shared state publish end --- It set up the information of where to download the new firmware. --- Called by a shared state hook +-- set download information for the new firmware from master node +-- Called by a shared state hook in non master nodes function mesh_upgrade.set_mesh_upgrade_info(upgrade_data) - local uci = libuci.cursor() + local uci = config.get_uci_cursor() if (type(upgrade_data.id) == "number") and string.match(upgrade_data.data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil - --perform aditional checks + --perform aditional checks then - print (uci:set('mesh-upgrade', 'main', "mesh-upgrade")) - print(uci:set('mesh-upgrade', 'main', 'id', upgrade_data.id)) + uci:get('mesh-upgrade', 'main','repo_url') + uci:set('mesh-upgrade', 'main', "mesh-upgrade") + uci:set('mesh-upgrade', 'main', 'id', upgrade_data.id) uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.data.repo_url) uci:set('mesh-upgrade', 'main', 'firmware_ver', upgrade_data.data.firmware_ver) - print(uci:set('mesh-upgrade', 'main', 'upgrade_state', 'starting')) + uci:set('mesh-upgrade', 'main', 'upgrade_state', mesh_upgrade.upgrade_states.starting) uci:set('mesh-upgrade', 'main', 'error', 0) uci:set('mesh-upgrade', 'main', 'timestamp', upgrade_data.timestamp) uci:set('mesh-upgrade', 'main', 'master_node', upgrade_data.master_node) - uci:set('mesh-upgrade', 'main', 'transaction_state', 'started') + uci:set('mesh-upgrade', 'main', 'transaction_state', mesh_upgrade.transaction_states.STARTED) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') - --trigger a shared state publish + --wait for the download to be ready to trigger the shared state upgrade. + --trigger firmware download from master_node url else utils.log("upgrade not started input data errors") print("upgrade not started input data errors") @@ -94,7 +124,7 @@ end -- upgrde_state="starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", -- error="CODE", -- safe_upgrade_status="", --- eup_STATUS="", +-- eup_STATUS="",eup.STATUS_DEFAULT = 'not-initiated' eup.STATUS_DOWNLOADING = 'downloading' eup.STATUS_DOWNLOADED = 'downloaded' eup.STATUS_DOWNLOAD_FAILED = 'download-failed' -- }, -- timestamp=231354654, -- id="", @@ -103,17 +133,17 @@ end -- } -- function mesh_upgrade.get_mesh_upgrade_status() - local uci = libuci.cursor() + local uci = config.get_uci_cursor() local upgrade_data = {} - upgrade_data.data={} - upgrade_data.type= "upgrade" + upgrade_data.data = {} + upgrade_data.type = "upgrade" upgrade_data.id = uci:get('mesh-upgrade', 'main', 'id') upgrade_data.data.firmware_ver = uci:get('mesh-upgrade', 'main', 'firmware_ver') upgrade_data.data.repo_url = uci:get('mesh-upgrade', 'main', 'repo_url') upgrade_data.data.upgrade_state = uci:get('mesh-upgrade', 'main', 'upgrade_state') upgrade_data.data.error = uci:get('mesh-upgrade', 'main', 'error') - upgrade_data.data.safe_upgrade_status=uci:get('mesh-upgrade', 'main', 'safe_upgrade_status') - upgrade_data.data.eup_STATUS=uci:get('mesh-upgrade', 'main', 'eup_STATUS') + upgrade_data.data.safe_upgrade_status = uci:get('mesh-upgrade', 'main', 'safe_upgrade_status') + upgrade_data.data.eup_STATUS = uci:get('mesh-upgrade', 'main', 'eup_STATUS') upgrade_data.timestamp = uci:get('mesh-upgrade', 'main', 'timestamp') upgrade_data.master_node = uci:get('mesh-upgrade', 'main', 'master_node') upgrade_data.transaction_state = uci:get('mesh-upgrade', 'main', 'transaction_state') diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index a8b272279..0e068c636 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -8,7 +8,9 @@ local json = require 'luci.jsonc' -- disable logging in config module -config.log = function() end +config.log = function(text) + print (text) + end local uci @@ -26,29 +28,36 @@ local upgrade_data = timestamp=231354654, id=21, transaction_state="started/aborted/finished", - master_node="" + master_node="prmiero" } describe('LiMe mesh upgrade', function() - it('test config', function() - print("pruebaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2") - print (uci:set('mesh-upgrade', 'main', "mesh-upgrade")) - print ("test") - lime_mesh_upgrade.start(upgrade_data) - utils.printJson(lime_mesh_upgrade.get_status()) + it('test set mesh config', function() + local status = lime_mesh_upgrade.get_mesh_upgrade_status() + utils.printJson(status) + assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.NO_TRANSACTION) + lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data) + status = lime_mesh_upgrade.get_mesh_upgrade_status() + utils.printJson(status) + + assert.is.equal(status.master_node, lime_mesh_upgrade.upgrade_states.STARTING) + assert.is.equal(status.data.repo_url,upgrade_data.data.repo_url ) + + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.STARTING) + assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) end) it('test config 2', function() - print("pruebaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaa2") + config.log("pruebaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaa2") end) before_each('', function() - print("pruebaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1") + config.log("pruebaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1") uci = test_utils.setup_test_uci() end) after_each('', function() - print("pruebaaaaaaaaaaaaaaaaaaaaaaaaaa3") + config.log("pruebaaaaaaaaaaaaaaaaaaaaaaaaaa3") test_utils.teardown_test_uci(uci) end) diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade index 3e773d1b1..c9e94a4fa 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -22,15 +22,14 @@ local mesh_upgrade = require "lime.mesh-upgrade" --if already involved in an upgrade transaction do nothing -if not mesh_upgrade.upgrade_in_progress() then +if not mesh_upgrade.mesh_upgrade_is_started() then for node, s_s_data in pairs(JSON.parse(io.stdin:read("*all"))) do --if any node has started an upgrade process and start one too? - --fetch the info from the master node publication? + --only fetch the info from the master node publication? if s_s_data.data.master_node == node then - mesh_upgrade.start(s_s_data.data) - utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "starting upgrade from"' .. + mesh_upgrade.set_mesh_upgrade_info(s_s_data.data) + utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from"' .. s_s_data.data.repo_url .. " " .. node) - --start the upgrade process referencing the original upgrade publication --start_upgrade(s_s_data.timestamp,s_s_data.id,sate="started",s_s_data.data.master_node) end utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "hoock +++++ "' .. From 2504b60d2f95fd656b292c12826afb60f6109478 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Tue, 31 Oct 2023 14:41:20 -0300 Subject: [PATCH 014/102] save configurations to uci and make tests pass --- .../files/usr/etc/config/mesh-upgrade | 16 ++++++------ .../files/usr/lib/lua/lime-mesh-upgrade.lua | 24 +++++++++--------- .../tests/test_lime-mesh-upgrade.lua | 25 ++++++++++++------- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade b/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade index aeaf3ffc5..9a689517d 100644 --- a/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade @@ -1,13 +1,13 @@ config mesh-upgrade 'main' - option id '1' - option firmware_ver "xxxx" - option repo_url 'http://10.13.156.241:8000/web_test/releases/api/' # TODO: provide a saner default - option upgrade_state 'downloading' + option id '' + option firmware_ver '' + option repo_url '' + option upgrade_state '' option safe_upgrade_status '' option eup_STATUS '' - option error 'CODE' - option timestamp '231354654' - option transaction_state 'aborted' - option master_node 'primero' + option error '0' + option timestamp '0' + option transaction_state 'no_transaction' + option master_node '' #option notset "" \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 28074c4b1..5e3657eed 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -1,21 +1,18 @@ #!/usr/bin/env lua - -local libuci = require "uci" local eupgrade = require 'eupgrade' local config = require "lime.config" - - local mesh_upgrade = { --posible tranactin states transaction_states = { NO_TRANSACTION="no_transaction", - STARTED = "started", --ther is a transaction in progress + STARTED = "started", --there is a transaction in progress ABORTED = "aborted", FINISHED = "finished" }, --psible upgrade states enumeration upgrade_states = { + STARTING="starting", DOWNLOADING= "downloading", READY_FOR_UPGRADE="ready_for_upgrade", UPGRADE_SCHELUDED="upgrade_scheluded", @@ -73,13 +70,13 @@ end -- Validate if the upgrade has already started function mesh_upgrade.mesh_upgrade_is_started() - local uci = libuci.cursor() + local uci = config.get_uci_cursor() return uci:get('mesh-upgrade', 'main', 'transaction_state') == 'started' --todo: what happens if a mesh_upgrade has started more than an hour ago ? should this node abort it ? end function mesh_upgrade.mesh_upgrade_abort() - local uci = libuci.cursor() + local uci = config.get_uci_cursor() uci:set('mesh-upgrade', 'main', 'transaction_state', mesh_upgrade.transaction_states.ABORTED) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') @@ -93,14 +90,14 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data) local uci = config.get_uci_cursor() if (type(upgrade_data.id) == "number") and string.match(upgrade_data.data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil - --perform aditional checks - then + --perform aditional checks + then uci:get('mesh-upgrade', 'main','repo_url') uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:set('mesh-upgrade', 'main', 'id', upgrade_data.id) uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.data.repo_url) uci:set('mesh-upgrade', 'main', 'firmware_ver', upgrade_data.data.firmware_ver) - uci:set('mesh-upgrade', 'main', 'upgrade_state', mesh_upgrade.upgrade_states.starting) + uci:set('mesh-upgrade', 'main', 'upgrade_state', mesh_upgrade.upgrade_states.STARTING) uci:set('mesh-upgrade', 'main', 'error', 0) uci:set('mesh-upgrade', 'main', 'timestamp', upgrade_data.timestamp) uci:set('mesh-upgrade', 'main', 'master_node', upgrade_data.master_node) @@ -110,8 +107,7 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data) --wait for the download to be ready to trigger the shared state upgrade. --trigger firmware download from master_node url else - utils.log("upgrade not started input data errors") - print("upgrade not started input data errors") + config.log("upgrade not started input data errors") end end @@ -147,6 +143,10 @@ function mesh_upgrade.get_mesh_upgrade_status() upgrade_data.timestamp = uci:get('mesh-upgrade', 'main', 'timestamp') upgrade_data.master_node = uci:get('mesh-upgrade', 'main', 'master_node') upgrade_data.transaction_state = uci:get('mesh-upgrade', 'main', 'transaction_state') + if(upgrade_data.transaction_state==nil) then + uci:set('mesh-upgrade', 'main', 'transaction_state', mesh_upgrade.transaction_states.NO_TRANSACTION) + upgrade_data.transaction_state = uci:get('mesh-upgrade', 'main', 'transaction_state') + end return upgrade_data end diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 0e068c636..7b57a9e70 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -32,33 +32,40 @@ local upgrade_data = } describe('LiMe mesh upgrade', function() - it('test set mesh config', function() + + it('test set mesh config fresh start', function() local status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.NO_TRANSACTION) + assert.is.equal(lime_mesh_upgrade.mesh_upgrade_is_started(),false) + end) + + + it('test set mesh config', function() + + config.log("test set mesh config.... ") lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data) status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) - - assert.is.equal(status.master_node, lime_mesh_upgrade.upgrade_states.STARTING) + assert.is.equal(status.master_node, upgrade_data.master_node) assert.is.equal(status.data.repo_url,upgrade_data.data.repo_url ) - - assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.STARTING) + assert.is.equal(status.data.upgrade_state, lime_mesh_upgrade.upgrade_states.STARTING) assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) + end) it('test config 2', function() - config.log("pruebaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaa2") + config.log("") end) before_each('', function() - config.log("pruebaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1") uci = test_utils.setup_test_uci() + config.log (uci:set('mesh-upgrade', 'main', "mesh-upgrade")) + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') end) after_each('', function() - config.log("pruebaaaaaaaaaaaaaaaaaaaaaaaaaa3") - test_utils.teardown_test_uci(uci) end) end) \ No newline at end of file From 076fdd56c3d434b4cf8e1180d8f1dc720e5e9e7d Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Mon, 13 Nov 2023 12:32:20 -0300 Subject: [PATCH 015/102] add inform_download_location and trigger_sheredstate_upgrade --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 93 +++++++++++++------ .../tests/test_lime-mesh-upgrade.lua | 13 +-- 2 files changed, 64 insertions(+), 42 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 5e3657eed..aeeed489c 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -1,31 +1,33 @@ #!/usr/bin/env lua + local eupgrade = require 'eupgrade' local config = require "lime.config" +local utils = require "lime.utils" +network = require("lime.network") local mesh_upgrade = { - --posible tranactin states + -- posible tranactin states transaction_states = { - NO_TRANSACTION="no_transaction", - STARTED = "started", --there is a transaction in progress + NO_TRANSACTION = "no_transaction", + STARTED = "started", -- there is a transaction in progress ABORTED = "aborted", FINISHED = "finished" }, - --psible upgrade states enumeration + -- psible upgrade states enumeration upgrade_states = { - STARTING="starting", - DOWNLOADING= "downloading", - READY_FOR_UPGRADE="ready_for_upgrade", - UPGRADE_SCHELUDED="upgrade_scheluded", - CONFIRMATION_PENDING="confirmation_pending", - CONFIRMED="confirmed", - UPDATED="updated", - ERROR= "error" + STARTING = "starting", + DOWNLOADING = "downloading", + READY_FOR_UPGRADE = "ready_for_upgrade", + UPGRADE_SCHELUDED = "upgrade_scheluded", + CONFIRMATION_PENDING = "confirmation_pending", + CONFIRMED = "confirmed", + UPDATED = "updated", + ERROR = "error" }, -- list of possible errors - errors = - { - DOWNLOAD_FAILED="download failed", - CONFIRMATION_TIME_OUT="confirmation timeout" + errors = { + DOWNLOAD_FAILED = "download failed", + CONFIRMATION_TIME_OUT = "confirmation timeout" } } @@ -53,11 +55,14 @@ function mesh_upgrade.set_up_firmware_repository() if latest_data then utils.execute_daemonized("eupgrade-download") else - ret = { status = 'error', message = 'New version is not availabe' } + ret = { + status = 'error', + message = 'New version is not availabe' + } end -- 2. Create local repository json data - --latest_data = json.parse(latest_json) + -- latest_data = json.parse(latest_json) local upgrade_url = eupgrade.get_upgrade_api_url() for _, im in pairs(latest_data['images']) do im['download-urls'] = string.gsub(im['download-urls'], upgrade_url, "test") @@ -66,13 +71,37 @@ function mesh_upgrade.set_up_firmware_repository() utils.write_file(mesh_upgrade.FIRMWARE_LATEST_JSON, latest_data) end --- Shared state functions +-- Shared state functions -- +---------------------------- + +function mesh_upgrade.inform_download_location(version) + if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED then + ipv4, ipv6 = network.primary_address() + mesh_upgrade.set_masternode_mesh_upgrade_info({ + type = "upgrade", + data = { + firmware_ver = version, + repo_url = "http://" .. ipv4.. "/lros/api/v1/", + upgrde_state = mesh_upgrade.upgrade_states.READY_FOR_UPGRADE, + error = 0, + safe_upgrade_status = "", + eup_STATUS = eupgrade.STATUS_DOWNLOADED + }, + timestamp = os.time(), + id = 21, -- todo: create a unique hash + transaction_state = mesh_upgrade.transaction_states.STARTED, + master_node = utils.hostname() + }) + else + config.log("eupgrade STATUS is not 'DOWNLOADED'") + end +end -- Validate if the upgrade has already started function mesh_upgrade.mesh_upgrade_is_started() local uci = config.get_uci_cursor() - return uci:get('mesh-upgrade', 'main', 'transaction_state') == 'started' - --todo: what happens if a mesh_upgrade has started more than an hour ago ? should this node abort it ? + return uci:get('mesh-upgrade', 'main', 'transaction_state') == mesh_upgrade.transaction_states.STARTED + -- todo: what happens if a mesh_upgrade has started more than an hour ago ? should this node abort it ? end function mesh_upgrade.mesh_upgrade_abort() @@ -84,15 +113,19 @@ function mesh_upgrade.mesh_upgrade_abort() -- trigger a shared state publish end +-- This line will genereate recursive dependencies like in pirania pakcage +function mesh_upgrade.trigger_sheredstate_upgrade() + utils.execute_daemonized("/etc/shared-state/publishers/endshared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") +end + -- set download information for the new firmware from master node -- Called by a shared state hook in non master nodes function mesh_upgrade.set_mesh_upgrade_info(upgrade_data) local uci = config.get_uci_cursor() - if (type(upgrade_data.id) == "number") and - string.match(upgrade_data.data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil - --perform aditional checks - then - uci:get('mesh-upgrade', 'main','repo_url') + if (type(upgrade_data.id) == "number") and string.match(upgrade_data.data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= + nil -- perform aditional checks + then + uci:get('mesh-upgrade', 'main', 'repo_url') uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:set('mesh-upgrade', 'main', 'id', upgrade_data.id) uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.data.repo_url) @@ -104,8 +137,8 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data) uci:set('mesh-upgrade', 'main', 'transaction_state', mesh_upgrade.transaction_states.STARTED) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') - --wait for the download to be ready to trigger the shared state upgrade. - --trigger firmware download from master_node url + -- wait for the download to be ready to trigger the shared state upgrade. + -- trigger firmware download from master_node url else config.log("upgrade not started input data errors") end @@ -129,7 +162,7 @@ end -- } -- function mesh_upgrade.get_mesh_upgrade_status() - local uci = config.get_uci_cursor() + local uci = config.get_uci_cursor() local upgrade_data = {} upgrade_data.data = {} upgrade_data.type = "upgrade" @@ -143,7 +176,7 @@ function mesh_upgrade.get_mesh_upgrade_status() upgrade_data.timestamp = uci:get('mesh-upgrade', 'main', 'timestamp') upgrade_data.master_node = uci:get('mesh-upgrade', 'main', 'master_node') upgrade_data.transaction_state = uci:get('mesh-upgrade', 'main', 'transaction_state') - if(upgrade_data.transaction_state==nil) then + if (upgrade_data.transaction_state == nil) then uci:set('mesh-upgrade', 'main', 'transaction_state', mesh_upgrade.transaction_states.NO_TRANSACTION) upgrade_data.transaction_state = uci:get('mesh-upgrade', 'main', 'transaction_state') end diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 7b57a9e70..16b69d11d 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -1,11 +1,7 @@ local config = require 'lime.config' -local network = require 'lime.network' -local wireless = require 'lime.wireless' local utils = require 'lime.utils' local test_utils = require 'tests.utils' local lime_mesh_upgrade = require 'lime-mesh-upgrade' -local json = require 'luci.jsonc' - -- disable logging in config module config.log = function(text) @@ -33,16 +29,14 @@ local upgrade_data = describe('LiMe mesh upgrade', function() - it('test set mesh config fresh start', function() + it('test get mesh config fresh start', function() local status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.NO_TRANSACTION) assert.is.equal(lime_mesh_upgrade.mesh_upgrade_is_started(),false) end) - it('test set mesh config', function() - config.log("test set mesh config.... ") lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data) status = lime_mesh_upgrade.get_mesh_upgrade_status() @@ -51,11 +45,6 @@ describe('LiMe mesh upgrade', function() assert.is.equal(status.data.repo_url,upgrade_data.data.repo_url ) assert.is.equal(status.data.upgrade_state, lime_mesh_upgrade.upgrade_states.STARTING) assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) - - end) - - it('test config 2', function() - config.log("") end) before_each('', function() From b7dd972deaa32cdd5667ab532eaa9152db4d0478 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 13 Nov 2023 17:09:23 -0300 Subject: [PATCH 016/102] incorporates eupgrade and improves testing also Adds the following methods: start_node_download(url) state() change_state() --- .../eupgrade/files/usr/lib/lua/eupgrade.lua | 4 + .../files/usr/lib/lua/lime-mesh-upgrade.lua | 126 ++++++++++++------ .../tests/test_lime-mesh-upgrade.lua | 36 ++++- .../hooks/mesh_wide_upgrade/start_upgrade | 4 +- 4 files changed, 126 insertions(+), 44 deletions(-) diff --git a/packages/eupgrade/files/usr/lib/lua/eupgrade.lua b/packages/eupgrade/files/usr/lib/lua/eupgrade.lua index 8fa86e1b9..d8dd957b7 100644 --- a/packages/eupgrade/files/usr/lib/lua/eupgrade.lua +++ b/packages/eupgrade/files/usr/lib/lua/eupgrade.lua @@ -36,6 +36,10 @@ function eup.get_upgrade_api_url() return uci:get('eupgrade', 'main', 'api_url') or '' end +function eup.set_upgrade_api_url(url) + return uci:set('eupgrade', 'main', 'api_url',url) +end + function eup._check_signature(file_path, signature_path) local cmd = string.format("usign -q -V -P /etc/opkg/keys -x %s -m %s", signature_path, file_path) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index aeeed489c..e9526453c 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -3,7 +3,8 @@ local eupgrade = require 'eupgrade' local config = require "lime.config" local utils = require "lime.utils" -network = require("lime.network") +local network = require("lime.network") + local mesh_upgrade = { -- posible tranactin states @@ -15,6 +16,7 @@ local mesh_upgrade = { }, -- psible upgrade states enumeration upgrade_states = { + DEFAULT = "not upgrading", STARTING = "starting", DOWNLOADING = "downloading", READY_FOR_UPGRADE = "ready_for_upgrade", @@ -31,20 +33,8 @@ local mesh_upgrade = { } } --- function mesh_upgrade.set_workdir(workdir) --- if not utils.file_exists(workdir) then --- os.execute('mkdir -p ' .. workdir) --- end --- if fs.stat(workdir, "type") ~= "dir" then --- error("Can't configure workdir " .. workdir) --- end --- mesh_upgrade.WORKDIR = workdir --- --mup.DOWNLOAD_INFO_CACHE_FILE = mup.WORKDIR .. '/download_status' --- mesh_upgrade.FIRMWARE_LATEST_JSON = mup.WORKDIR .. "/firmware_latest_mesh_wide.json" --- --mup.FIRMWARE_LATEST_JSON_SIGNATURE = mup.FIRMWARE_LATEST_JSON .. '.sig' --- end - --- mesh_upgrade.set_workdir("/tmp/mesh_upgrade") +--shoud epgrade be disabled ? +eupgrade.set_workdir("/tmp/mesh_upgrade") -- This function will download latest librerouter os firmware and expose it as -- a local repository in order to be used for other nodes @@ -74,14 +64,40 @@ end -- Shared state functions -- ---------------------------- +--function to be called by nodes to start download from master. +function mesh_upgrade.start_node_download(url) + local uci = config.get_uci_cursor() + eupgrade.set_upgrade_api_url(url) + local cached_only = false + --download new firmware if necessary + local latest_data = eupgrade.is_new_version_available(cached_only) + if latest_data then + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) + local image = eupgrade.download_firmware(latest_data) + uci:set('mesh-upgrade', 'main', 'eup_STATUS', eupgrade.get_download_status()) + if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED then + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) + else + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR) + --todo: how to handle this error + end + else + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR) + end + mesh_upgrade.trigger_sheredstate_publish() +end + +--this function will be called by the master node to inform that the firmware is available +--also will force shared state data refresh function mesh_upgrade.inform_download_location(version) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED then + --TODO: setup uhttpd to serve workdir location ipv4, ipv6 = network.primary_address() - mesh_upgrade.set_masternode_mesh_upgrade_info({ + mesh_upgrade.set_mesh_upgrade_info({ type = "upgrade", data = { firmware_ver = version, - repo_url = "http://" .. ipv4.. "/lros/api/v1/", + repo_url = "http://" .. ipv4 .. "/lros/api/v1/", upgrde_state = mesh_upgrade.upgrade_states.READY_FOR_UPGRADE, error = 0, safe_upgrade_status = "", @@ -91,17 +107,22 @@ function mesh_upgrade.inform_download_location(version) id = 21, -- todo: create a unique hash transaction_state = mesh_upgrade.transaction_states.STARTED, master_node = utils.hostname() - }) + }, mesh_upgrade.upgrade_states.READY_FOR_UPGRADE, mesh_upgrade.transaction_states.STARTED) else config.log("eupgrade STATUS is not 'DOWNLOADED'") end end -- Validate if the upgrade has already started -function mesh_upgrade.mesh_upgrade_is_started() +function mesh_upgrade.started() local uci = config.get_uci_cursor() return uci:get('mesh-upgrade', 'main', 'transaction_state') == mesh_upgrade.transaction_states.STARTED - -- todo: what happens if a mesh_upgrade has started more than an hour ago ? should this node abort it ? + -- todo: what happens if a mesh_upgrade has started more than an hour ago ? should this node abort it ? +end + +function mesh_upgrade.state() + local uci = config.get_uci_cursor() + return uci:get('mesh-upgrade', 'main', 'upgrade_state') or mesh_upgrade.upgrade_states.DEFAULT end function mesh_upgrade.mesh_upgrade_abort() @@ -114,33 +135,58 @@ function mesh_upgrade.mesh_upgrade_abort() end -- This line will genereate recursive dependencies like in pirania pakcage -function mesh_upgrade.trigger_sheredstate_upgrade() - utils.execute_daemonized("/etc/shared-state/publishers/endshared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") +function mesh_upgrade.trigger_sheredstate_publish() + utils.execute_daemonized( + "/etc/shared-state/publishers/endshared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") +end + +--! changes the state of the upgrade and verifies that state transition is possible. +function mesh_upgrade.change_state(newstate, errortype) + local uci = config.get_uci_cursor() + if newstate == mesh_upgrade.upgrade_states.STARTING and (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DEFAULT or mesh_upgrade.state() == mesh_upgrade.upgrade_states.ERROR or mesh_upgrade.state() == mesh_upgrade.upgrade_states.UPDATED) then + -- trigger firmware download from master_node url + uci:set('mesh-upgrade', 'main', 'upgrade_state', newstate) + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') + return true + end + --todo: verify other states + -- lets allow all types of state changes. + uci:set('mesh-upgrade', 'main', 'upgrade_state', newstate) + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') + return false end -- set download information for the new firmware from master node -- Called by a shared state hook in non master nodes -function mesh_upgrade.set_mesh_upgrade_info(upgrade_data) +function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state, transaction_state) local uci = config.get_uci_cursor() if (type(upgrade_data.id) == "number") and string.match(upgrade_data.data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= - nil -- perform aditional checks + nil -- perform aditional checks then - uci:get('mesh-upgrade', 'main', 'repo_url') - uci:set('mesh-upgrade', 'main', "mesh-upgrade") - uci:set('mesh-upgrade', 'main', 'id', upgrade_data.id) - uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.data.repo_url) - uci:set('mesh-upgrade', 'main', 'firmware_ver', upgrade_data.data.firmware_ver) - uci:set('mesh-upgrade', 'main', 'upgrade_state', mesh_upgrade.upgrade_states.STARTING) - uci:set('mesh-upgrade', 'main', 'error', 0) - uci:set('mesh-upgrade', 'main', 'timestamp', upgrade_data.timestamp) - uci:set('mesh-upgrade', 'main', 'master_node', upgrade_data.master_node) - uci:set('mesh-upgrade', 'main', 'transaction_state', mesh_upgrade.transaction_states.STARTED) - uci:save('mesh-upgrade') - uci:commit('mesh-upgrade') - -- wait for the download to be ready to trigger the shared state upgrade. - -- trigger firmware download from master_node url + if (mesh_upgrade.change_state(upgrade_state)) then + uci:get('mesh-upgrade', 'main', 'repo_url') + uci:set('mesh-upgrade', 'main', "mesh-upgrade") + uci:set('mesh-upgrade', 'main', 'id', upgrade_data.id) + uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.data.repo_url) + uci:set('mesh-upgrade', 'main', 'firmware_ver', upgrade_data.data.firmware_ver) + --uci:set('mesh-upgrade', 'main', 'upgrade_state', upgrade_state) already done in change state + uci:set('mesh-upgrade', 'main', 'error', 0) + uci:set('mesh-upgrade', 'main', 'timestamp', os.time()) + uci:set('mesh-upgrade', 'main', 'master_node', upgrade_data.master_node) + uci:set('mesh-upgrade', 'main', 'transaction_state', transaction_state or mesh_upgrade.transaction_states + .STARTED) + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') + -- trigger shared state data refresh + mesh_upgrade.trigger_sheredstate_publish() + mesh_upgrade.start_node_download(upgrade_data.data.repo_url) + else + config.log("invalid state change ") + end else - config.log("upgrade not started input data errors") + config.log("upgrade failed due input data errors") end end @@ -161,6 +207,8 @@ end -- master_node="" -- } -- + +--! Read status from UCI function mesh_upgrade.get_mesh_upgrade_status() local uci = config.get_uci_cursor() local upgrade_data = {} diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 16b69d11d..a55ab18f6 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -2,6 +2,8 @@ local config = require 'lime.config' local utils = require 'lime.utils' local test_utils = require 'tests.utils' local lime_mesh_upgrade = require 'lime-mesh-upgrade' +eupgrade = require 'eupgrade' + -- disable logging in config module config.log = function(text) @@ -27,23 +29,51 @@ local upgrade_data = master_node="prmiero" } +local latest_release_data = [[ +{ + "metadata-version": 1, + "images": [ + { + "name": "test-board-upgrade.sh", + "type": "installer", + "download-urls": [ + "../20.xx/targets/ar71xx/generic/test-board-upgrade.sh", + ], + "sha256": "fbd95fce091ea10cfa05cfb0ef870da43124ac7c1402890eb8f03b440c57d7b5" + } + ], + "board": "test-board", + "version": "LibreMesh 20.10", + "release-info-url": "https://libremesh.org/news/" +} +]] + + describe('LiMe mesh upgrade', function() it('test get mesh config fresh start', function() local status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.NO_TRANSACTION) - assert.is.equal(lime_mesh_upgrade.mesh_upgrade_is_started(),false) + assert.is.equal(lime_mesh_upgrade.started(),false) end) it('test set mesh config', function() config.log("test set mesh config.... ") - lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data) + + stub(eupgrade, '_get_board_name', function () return 'test-board' end) + stub(eupgrade, '_get_current_fw_version', function () return 'LibreMesh 19.05' end) + stub(eupgrade, '_check_signature', function () return true end) + stub(utils, 'http_client_get', function () return latest_release_data end) + assert.is.equal('LibreMesh 20.10', eupgrade.is_new_version_available()['version']) + + lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data,lime_mesh_upgrade.upgrade_states.STARTING) status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) assert.is.equal(status.master_node, upgrade_data.master_node) assert.is.equal(status.data.repo_url,upgrade_data.data.repo_url ) - assert.is.equal(status.data.upgrade_state, lime_mesh_upgrade.upgrade_states.STARTING) + assert.is.equal(status.data.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) + assert.is.equal(status.data.eup_STATUS, eupgrade.STATUS_DOWNLOAD_FAILED) assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) end) diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade index c9e94a4fa..c0481ad35 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -27,10 +27,10 @@ if not mesh_upgrade.mesh_upgrade_is_started() then --if any node has started an upgrade process and start one too? --only fetch the info from the master node publication? if s_s_data.data.master_node == node then - mesh_upgrade.set_mesh_upgrade_info(s_s_data.data) + + mesh_upgrade.set_mesh_upgrade_info(s_s_data.data,mesh_upgrade.upgrade_states.STARTING) utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from"' .. s_s_data.data.repo_url .. " " .. node) - --start_upgrade(s_s_data.timestamp,s_s_data.id,sate="started",s_s_data.data.master_node) end utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "hoock +++++ "' .. JSON.stringify(s_s_data.data) .. " " .. node) From ac7c5950e157c37152b7de84f16b988986c8345a Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 27 Nov 2023 16:32:46 -0300 Subject: [PATCH 017/102] enables testing with real repo information --- .../eupgrade/files/usr/lib/lua/eupgrade.lua | 5 +- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 11 +- .../tests/test_lime-mesh-upgrade.lua | 109 ++++++++++++++++-- 3 files changed, 115 insertions(+), 10 deletions(-) diff --git a/packages/eupgrade/files/usr/lib/lua/eupgrade.lua b/packages/eupgrade/files/usr/lib/lua/eupgrade.lua index d8dd957b7..23cf2611e 100644 --- a/packages/eupgrade/files/usr/lib/lua/eupgrade.lua +++ b/packages/eupgrade/files/usr/lib/lua/eupgrade.lua @@ -37,7 +37,10 @@ function eup.get_upgrade_api_url() end function eup.set_upgrade_api_url(url) - return uci:set('eupgrade', 'main', 'api_url',url) + status = uci:set('eupgrade', 'main', 'api_url',url) + uci:save('eupgrade') + uci:commit('eupgrade') + return status end function eup._check_signature(file_path, signature_path) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index e9526453c..b7f155ee3 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -68,12 +68,21 @@ end function mesh_upgrade.start_node_download(url) local uci = config.get_uci_cursor() eupgrade.set_upgrade_api_url(url) + status = uci:set('eupgrade', 'main', 'api_url',url) + uci:save('eupgrade') + uci:commit('eupgrade') local cached_only = false --download new firmware if necessary + config.log("is_new_version_available ") + local latest_data = eupgrade.is_new_version_available(cached_only) if latest_data then + config.log("start_node_download ") mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) + config.log("downloading") + local image = eupgrade.download_firmware(latest_data) + uci:set('mesh-upgrade', 'main', 'eup_STATUS', eupgrade.get_download_status()) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) @@ -137,7 +146,7 @@ end -- This line will genereate recursive dependencies like in pirania pakcage function mesh_upgrade.trigger_sheredstate_publish() utils.execute_daemonized( - "/etc/shared-state/publishers/endshared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") + "/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") end --! changes the state of the upgrade and verifies that state transition is possible. diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index a55ab18f6..02ff121f3 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -4,6 +4,8 @@ local test_utils = require 'tests.utils' local lime_mesh_upgrade = require 'lime-mesh-upgrade' eupgrade = require 'eupgrade' +utils.enable_logging() + -- disable logging in config module config.log = function(text) @@ -17,7 +19,7 @@ local upgrade_data = type= "upgrade", data={ firmware_ver="xxxx", - repo_url="http://10.13.0.1/lros/api/v1/", + repo_url="http://repo.librerouter.org/lros/api/v1/latest/", upgrde_state="starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", error="CODE", safe_upgrade_status="", @@ -29,7 +31,7 @@ local upgrade_data = master_node="prmiero" } -local latest_release_data = [[ +local latest_release_data_sample = [[ { "metadata-version": 1, "images": [ @@ -48,25 +50,56 @@ local latest_release_data = [[ } ]] +local latest_release_data_real = [[ +{ + "metadata-version": 1, + "images": [ + { + "name": "upgrade-lr-1.5.sh", + "type": "installer", + "download-urls": [ + "http://repo.librerouter.org/lros/releases/1.5/targets/ath79/generic/upgrade-lr-1.5.sh" + ], + "sha256": "cec8920f93055cc57cfde1f87968e33ca5215b2df88611684195077402079acb" + }, + { + "name": "firmware.bin", + "type": "sysupgrade", + "download-urls": [ + "http://repo.librerouter.org/lros/releases/1.5/targets/ath79/generic/librerouteros-1.5-r0+11434-e93615c947-ath79-generic-librerouter_librerouter-v1-squashfs-sysupgrade.bin" + ], + "sha256": "2da0abb549d6178a7978b357be3493d5aff5c07b993ea0962575fa61bef18c27" + } + ], + "board": "librerouter,librerouter-v1", + "version": "LibreRouterOs 1.5 r0+11434-e93615c947", + "release-info-url": "https://foro.librerouter.org/t/lanzamiento-librerouteros-1-5/337" +} + +]] +local latest_release_data_real_sig = [[ +untrusted comment: signed by key 47513b83fbc579cd +RWRHUTuD+8V5zSCR6+HGnzSU8qhf1d8K8PqOCo/OYLFAXBeiICUXV33BY3o1ihDWcGbFTBLh8jidfhSkWQev5NoT1PTOTOLvZwc= +]] describe('LiMe mesh upgrade', function() it('test get mesh config fresh start', function() + config.log("\n test set mesh config.... \n") local status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.NO_TRANSACTION) assert.is.equal(lime_mesh_upgrade.started(),false) end) - it('test set mesh config', function() - config.log("test set mesh config.... ") - + it('test set mesh config and get status', function() stub(eupgrade, '_get_board_name', function () return 'test-board' end) stub(eupgrade, '_get_current_fw_version', function () return 'LibreMesh 19.05' end) stub(eupgrade, '_check_signature', function () return true end) - stub(utils, 'http_client_get', function () return latest_release_data end) + stub(utils, 'http_client_get', function () return latest_release_data_sample end) + stub(eupgrade, '_file_sha256', function () return 'fbd95fc091ea10cfa05cfb0ef870da43124ac7c1402890eb8f03b440c57d7b5' end) + assert.is.equal('LibreMesh 20.10', eupgrade.is_new_version_available()['version']) - lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data,lime_mesh_upgrade.upgrade_states.STARTING) status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) @@ -75,16 +108,76 @@ describe('LiMe mesh upgrade', function() assert.is.equal(status.data.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) assert.is.equal(status.data.eup_STATUS, eupgrade.STATUS_DOWNLOAD_FAILED) assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) + -- assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.ABORTED) + --TODO: javi en caso de falla ... reintentar ? abortar ? + end) + it('test set mesh config start download and assert status ready_for_upgrade', function() + stub(eupgrade, '_get_board_name', function () return 'test-board' end) + stub(eupgrade, '_get_current_fw_version', function () return 'LibreMesh 19.05' end) + stub(eupgrade, '_check_signature', function () return true end) + stub(utils, 'http_client_get', function () return latest_release_data_sample end) + stub(eupgrade, '_file_sha256', function () return 'fbd95fce091ea10cfa05cfb0ef870da43124ac7c1402890eb8f03b440c57d7b5' end) + + assert.is.equal('LibreMesh 20.10', eupgrade.is_new_version_available()['version']) + lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data,lime_mesh_upgrade.upgrade_states.STARTING) + status = lime_mesh_upgrade.get_mesh_upgrade_status() + utils.printJson(status) + assert.is.equal(status.master_node, upgrade_data.master_node) + assert.is.equal(status.data.repo_url,upgrade_data.data.repo_url ) + assert.is.equal(status.data.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) + assert.is.equal(status.data.eup_STATUS, eupgrade.STATUS_DOWNLOADED) + assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) + end) + + it('test set mesh config start download and assert status ready_for_upgrade', function() + stub(eupgrade, '_get_board_name', function () return 'librerouter-v1' end) + stub(eupgrade, '_get_current_fw_version', function () return 'LibreMesh 19.05' end) + stub(eupgrade, '_check_signature', function () return true end) + stub(eupgrade, '_file_sha256', function () return 'cec8920f93055cc57cfde1f87968e33ca5215b2df88611684195077402079acb' end) + --todo: javi este netodo no seria necesario que sea stub porque deberia tomar la url del set upgrade api pero no toma el config uci + stub(eupgrade, 'get_upgrade_api_url', function () return 'http://repo.librerouter.org/lros/api/v1/' end) + stub(utils, 'http_client_get', + function (url,to,file) + config.log("http_client_get "..url .. " "..to.. (args or "")) + if url == "http://repo.librerouter.org/lros/releases/1.5/targets/ath79/generic/upgrade-lr-1.5.sh" then + return true + end + if url == "http://repo.librerouter.org/lros/api/v1/latest/librerouter-v1.json.sig" then + return latest_release_data_real + end + if url == "http://repo.librerouter.org/lros/api/v1/latest/librerouter-v1.json" then + return latest_release_data_real_sig + end + config.log("http_client_get "..url .. " "..to.. (args or "")) + config.log("http_client_get "..url .. " "..to.. (args or "")) + config.log("http_client_get "..url .. " "..to.. (args or "")) + config.log("http_client_get "..url .. " "..to.. (args or "")) + config.log("http_client_get "..url .. " "..to.. (args or "")) + + return true + end) + --assert.is.equal('LibreRouterOs 1.5 r0+11434-e93615c947', eupgrade.is_new_version_available()['version']) + lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data,lime_mesh_upgrade.upgrade_states.STARTING) + status = lime_mesh_upgrade.get_mesh_upgrade_status() + utils.printJson(status) + assert.is.equal(status.master_node, upgrade_data.master_node) + assert.is.equal(status.data.repo_url,upgrade_data.data.repo_url ) + assert.is.equal(status.data.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) + assert.is.equal(status.data.eup_STATUS, eupgrade.STATUS_DOWNLOADED) + assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) end) before_each('', function() + snapshot = assert:snapshot() uci = test_utils.setup_test_uci() - config.log (uci:set('mesh-upgrade', 'main', "mesh-upgrade")) + uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:save('mesh-upgrade') uci:commit('mesh-upgrade') end) after_each('', function() + snapshot:revert() test_utils.teardown_test_uci(uci) + test_utils.teardown_test_dir() end) end) \ No newline at end of file From e373d28dd5fce89da6b613a6424b293bf38fc13e Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Tue, 28 Nov 2023 08:45:15 -0300 Subject: [PATCH 018/102] ads safeupgrade --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 57 ++++++++++++------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index e9526453c..f85dc525c 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -1,11 +1,11 @@ #!/usr/bin/env lua local eupgrade = require 'eupgrade' +local upgrade = require 'upgrade' local config = require "lime.config" local utils = require "lime.utils" local network = require("lime.network") - local mesh_upgrade = { -- posible tranactin states transaction_states = { @@ -20,7 +20,7 @@ local mesh_upgrade = { STARTING = "starting", DOWNLOADING = "downloading", READY_FOR_UPGRADE = "ready_for_upgrade", - UPGRADE_SCHELUDED = "upgrade_scheluded", + UPGRADE_SCHEDULED = "upgrade_scheluded", CONFIRMATION_PENDING = "confirmation_pending", CONFIRMED = "confirmed", UPDATED = "updated", @@ -30,10 +30,13 @@ local mesh_upgrade = { errors = { DOWNLOAD_FAILED = "download failed", CONFIRMATION_TIME_OUT = "confirmation timeout" - } + }, + fw_path = "", + su_timeout = 600, + MASTERNODE_ENDPOINT = "/lros/api/v1/" } ---shoud epgrade be disabled ? +-- shoud epgrade be disabled ? eupgrade.set_workdir("/tmp/mesh_upgrade") -- This function will download latest librerouter os firmware and expose it as @@ -64,22 +67,23 @@ end -- Shared state functions -- ---------------------------- ---function to be called by nodes to start download from master. +-- function to be called by nodes to start download from master. function mesh_upgrade.start_node_download(url) local uci = config.get_uci_cursor() eupgrade.set_upgrade_api_url(url) local cached_only = false - --download new firmware if necessary + -- download new firmware if necessary local latest_data = eupgrade.is_new_version_available(cached_only) if latest_data then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) - local image = eupgrade.download_firmware(latest_data) + local image = {} + image, mesh_upgrade.fw_path = eupgrade.download_firmware(latest_data) uci:set('mesh-upgrade', 'main', 'eup_STATUS', eupgrade.get_download_status()) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) else mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR) - --todo: how to handle this error + -- todo: how to handle this error end else mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR) @@ -87,17 +91,21 @@ function mesh_upgrade.start_node_download(url) mesh_upgrade.trigger_sheredstate_publish() end ---this function will be called by the master node to inform that the firmware is available ---also will force shared state data refresh +-- this function will be called by the master node to inform that the firmware is available +-- also will force shared state data refresh +-- curl -6 'http://[fe80::a8aa:aaff:fe0d:feaa%lime_br0]/fw/resolv.conf' +-- curl -6 'http://[fd0d:fe46:8ce8::1]/lros/api/v1/' + function mesh_upgrade.inform_download_location(version) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED then - --TODO: setup uhttpd to serve workdir location + -- TODO: setup uhttpd to serve workdir location ipv4, ipv6 = network.primary_address() mesh_upgrade.set_mesh_upgrade_info({ type = "upgrade", data = { firmware_ver = version, - repo_url = "http://" .. ipv4 .. "/lros/api/v1/", + repo_url = "http://" .. ipv4 .. mesh_upgrade.MASTERNODE_ENDPOINT, + repo_url_v6 = "http://[" .. ipv6 .. "]".. mesh_upgrade.MASTERNODE_ENDPOINT, upgrde_state = mesh_upgrade.upgrade_states.READY_FOR_UPGRADE, error = 0, safe_upgrade_status = "", @@ -140,17 +148,19 @@ function mesh_upgrade.trigger_sheredstate_publish() "/etc/shared-state/publishers/endshared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") end ---! changes the state of the upgrade and verifies that state transition is possible. +-- ! changes the state of the upgrade and verifies that state transition is possible. function mesh_upgrade.change_state(newstate, errortype) local uci = config.get_uci_cursor() - if newstate == mesh_upgrade.upgrade_states.STARTING and (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DEFAULT or mesh_upgrade.state() == mesh_upgrade.upgrade_states.ERROR or mesh_upgrade.state() == mesh_upgrade.upgrade_states.UPDATED) then + if newstate == mesh_upgrade.upgrade_states.STARTING and + (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DEFAULT or mesh_upgrade.state() == + mesh_upgrade.upgrade_states.ERROR or mesh_upgrade.state() == mesh_upgrade.upgrade_states.UPDATED) then -- trigger firmware download from master_node url uci:set('mesh-upgrade', 'main', 'upgrade_state', newstate) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') return true end - --todo: verify other states + -- todo: verify other states -- lets allow all types of state changes. uci:set('mesh-upgrade', 'main', 'upgrade_state', newstate) uci:save('mesh-upgrade') @@ -171,12 +181,12 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state, transac uci:set('mesh-upgrade', 'main', 'id', upgrade_data.id) uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.data.repo_url) uci:set('mesh-upgrade', 'main', 'firmware_ver', upgrade_data.data.firmware_ver) - --uci:set('mesh-upgrade', 'main', 'upgrade_state', upgrade_state) already done in change state + -- uci:set('mesh-upgrade', 'main', 'upgrade_state', upgrade_state) already done in change state uci:set('mesh-upgrade', 'main', 'error', 0) uci:set('mesh-upgrade', 'main', 'timestamp', os.time()) uci:set('mesh-upgrade', 'main', 'master_node', upgrade_data.master_node) - uci:set('mesh-upgrade', 'main', 'transaction_state', transaction_state or mesh_upgrade.transaction_states - .STARTED) + uci:set('mesh-upgrade', 'main', 'transaction_state', + transaction_state or mesh_upgrade.transaction_states.STARTED) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') -- trigger shared state data refresh @@ -208,7 +218,7 @@ end -- } -- ---! Read status from UCI +-- ! Read status from UCI function mesh_upgrade.get_mesh_upgrade_status() local uci = config.get_uci_cursor() local upgrade_data = {} @@ -231,4 +241,13 @@ function mesh_upgrade.get_mesh_upgrade_status() return upgrade_data end +function mesh_upgrade.start_safe_upgrade() + if mesh_upgrade.change_state( mesh_upgrade.upgrade_states.UPGRADE_SCHELUDED) and utils.file_exists(mesh_upgrade.fw_path) then + upgrade.firmware_upgrade() + else + utils.log ("not able to start upgrade invalid state or firmware not found") + mesh_upgrade.change_state( mesh_upgrade.upgrade_states.ERROR) + end +end + return mesh_upgrade From e86639dadfb4ac011547b45647a0ddd0186a7b52 Mon Sep 17 00:00:00 2001 From: selankon Date: Wed, 29 Nov 2023 15:20:29 +0100 Subject: [PATCH 019/102] Implement create local repository json data --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 74 +++++++++++++++---- .../tests/test_lime-mesh-upgrade.lua | 56 ++++++++++---- 2 files changed, 101 insertions(+), 29 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index e9526453c..bfbc602d4 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -4,6 +4,8 @@ local eupgrade = require 'eupgrade' local config = require "lime.config" local utils = require "lime.utils" local network = require("lime.network") +local fs = require("nixio.fs") +local json = require 'luci.jsonc' local mesh_upgrade = { @@ -30,16 +32,41 @@ local mesh_upgrade = { errors = { DOWNLOAD_FAILED = "download failed", CONFIRMATION_TIME_OUT = "confirmation timeout" - } + }, } ---shoud epgrade be disabled ? -eupgrade.set_workdir("/tmp/mesh_upgrade") +-- Get the base url for the firmware repository in this node +function mesh_upgrade.get_repo_base_url() + ipv4, ipv6 = network.primary_address() + return "http://" .. ipv4 .. mesh_upgrade.FIRMWARE_REPO_PATH +end --- This function will download latest librerouter os firmware and expose it as --- a local repository in order to be used for other nodes -function mesh_upgrade.set_up_firmware_repository() - -- 1. Check if new version is available and download it demonized using eupgrade +-- Create a work directory if nor exist +function mesh_upgrade._configure_workdir(workdir) + if not utils.file_exists(workdir) then + os.execute('mkdir -p ' .. workdir) + end + if fs.stat(workdir, "type") ~= "dir" then + error("Can't configure workdir " .. workdir) + end +end + +function mesh_upgrade.set_workdir(workdir) + mesh_upgrade._configure_workdir(workdir) + mesh_upgrade.WORKDIR = workdir + mesh_upgrade.LATEST_JSON_FILE_NAME = "firmware_latest_mesh_wide.json" -- latest json with local lan url file name + mesh_upgrade.LATEST_JSON_PATH = mesh_upgrade.WORKDIR .. mesh_upgrade.LATEST_JSON_FILE_NAME -- latest json full path +end +mesh_upgrade.set_workdir("/tmp/mesh_upgrade") + +function mesh_upgrade.set_http_dir(uhttp_folder, http_path) + mesh_upgrade.FIRMWARE_REPO_PATH = http_path -- url path for firmwares + mesh_upgrade.FIRMWARE_HTTP_PATH = uhttp_folder .. mesh_upgrade.FIRMWARE_REPO_PATH -- Path to expose the firmware + --mesh_upgrade._configure_workdir(mesh_upgrade.FIRMWARE_HTTP_PATH) +end +mesh_upgrade.set_http_dir("/www", "/lros/") + +function mesh_upgrade.start_eupgrade_download() local cached_only = false local latest_data = eupgrade.is_new_version_available(cached_only) if latest_data then @@ -50,15 +77,33 @@ function mesh_upgrade.set_up_firmware_repository() message = 'New version is not availabe' } end + return latest_data +end - -- 2. Create local repository json data - -- latest_data = json.parse(latest_json) - local upgrade_url = eupgrade.get_upgrade_api_url() +function mesh_upgrade.create_local_latest_json(latest_data) for _, im in pairs(latest_data['images']) do - im['download-urls'] = string.gsub(im['download-urls'], upgrade_url, "test") + --im['download-urls'] = string.gsub(im['download-urls'], upgrade_url, "test") + im['download-urls'] = {mesh_upgrade.get_repo_base_url() .. im['name']} end - -- todo(kon): implement create signature - utils.write_file(mesh_upgrade.FIRMWARE_LATEST_JSON, latest_data) + -- todo(kon): implement create SHA signature + utils.write_file(mesh_upgrade.LATEST_JSON_PATH, json.stringify(latest_data)) +end + +-- This function will download latest librerouter os firmware and expose it as +-- a local repository in order to be used for other nodes +function mesh_upgrade.set_up_firmware_repository() + -- 1. Check if new version is available and download it demonized using eupgrade + local latest_data = mesh_upgrade.start_eupgrade_download() + + -- 2. Create local repository json data + mesh_upgrade.create_local_latest_json(latest_data) + + -- 3. Expose eupgrade folder to uhttp + local images_folder = eupgrade.WORKDIR + --os.execute("ln -s " .. images_folder .. "/* " .. mesh_upgrade.FIRMWARE_HTTP_PATH ) + + -- 4. Update the shared state + -- mesh_upgrade.inform_download_location end -- Shared state functions -- @@ -92,12 +137,11 @@ end function mesh_upgrade.inform_download_location(version) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED then --TODO: setup uhttpd to serve workdir location - ipv4, ipv6 = network.primary_address() mesh_upgrade.set_mesh_upgrade_info({ type = "upgrade", data = { firmware_ver = version, - repo_url = "http://" .. ipv4 .. "/lros/api/v1/", + repo_url = mesh_upgrade.get_repo_base_url(), upgrde_state = mesh_upgrade.upgrade_states.READY_FOR_UPGRADE, error = 0, safe_upgrade_status = "", diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index a55ab18f6..a4c6cbd63 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -1,7 +1,12 @@ local config = require 'lime.config' -local utils = require 'lime.utils' -local test_utils = require 'tests.utils' local lime_mesh_upgrade = require 'lime-mesh-upgrade' +local network = require("lime.network") + +local utils = require "lime.utils" +local test_utils = require "tests.utils" +local eup = require "eupgrade" +local json = require 'luci.jsonc' + eupgrade = require 'eupgrade' @@ -26,7 +31,7 @@ local upgrade_data = timestamp=231354654, id=21, transaction_state="started/aborted/finished", - master_node="prmiero" + master_node="primero" } local latest_release_data = [[ @@ -34,26 +39,35 @@ local latest_release_data = [[ "metadata-version": 1, "images": [ { - "name": "test-board-upgrade.sh", + "name": "upgrade-lr-1.5.sh", "type": "installer", "download-urls": [ - "../20.xx/targets/ar71xx/generic/test-board-upgrade.sh", + "http://repo.librerouter.org/lros/releases/1.5/targets/ath79/generic/upgrade-lr-1.5.sh" + ], + "sha256": "cec8920f93055cc57cfde1f87968e33ca5215b2df88611684195077402079acb" + }, + { + "name": "firmware.bin", + "type": "sysupgrade", + "download-urls": [ + "http://repo.librerouter.org/lros/releases/1.5/targets/ath79/generic/librerouteros-1.5-r0+11434-e93615c947-ath79-generic-librerouter_librerouter-v1-squashfs-sysupgrade.bin" ], - "sha256": "fbd95fce091ea10cfa05cfb0ef870da43124ac7c1402890eb8f03b440c57d7b5" + "sha256": "2da0abb549d6178a7978b357be3493d5aff5c07b993ea0962575fa61bef18c27" } ], "board": "test-board", - "version": "LibreMesh 20.10", - "release-info-url": "https://libremesh.org/news/" -} + "version": "LibreRouterOs 1.5", + "release-info-url": "https://foro.librerouter.org/t/lanzamiento-librerouteros-1-5/337" +} ]] +local api_url = 'http://repo.librerouter.org/lros/releases/' + describe('LiMe mesh upgrade', function() it('test get mesh config fresh start', function() local status = lime_mesh_upgrade.get_mesh_upgrade_status() - utils.printJson(status) assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.NO_TRANSACTION) assert.is.equal(lime_mesh_upgrade.started(),false) end) @@ -62,14 +76,13 @@ describe('LiMe mesh upgrade', function() config.log("test set mesh config.... ") stub(eupgrade, '_get_board_name', function () return 'test-board' end) - stub(eupgrade, '_get_current_fw_version', function () return 'LibreMesh 19.05' end) + stub(eupgrade, '_get_current_fw_version', function () return 'LibreMesh 1.4' end) stub(eupgrade, '_check_signature', function () return true end) stub(utils, 'http_client_get', function () return latest_release_data end) - assert.is.equal('LibreMesh 20.10', eupgrade.is_new_version_available()['version']) - + assert.is.equal('LibreRouterOs 1.5', eupgrade.is_new_version_available()['version']) + lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data,lime_mesh_upgrade.upgrade_states.STARTING) status = lime_mesh_upgrade.get_mesh_upgrade_status() - utils.printJson(status) assert.is.equal(status.master_node, upgrade_data.master_node) assert.is.equal(status.data.repo_url,upgrade_data.data.repo_url ) assert.is.equal(status.data.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) @@ -77,7 +90,20 @@ describe('LiMe mesh upgrade', function() assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) end) + it('test set_up_firmware_repository download the files correctly and fix the url on json', function() + stub(network, 'primary_address', function () return '10.13.0.1', 'ipv6' end) + lime_mesh_upgrade.create_local_latest_json(json.parse(latest_release_data)) + local latest = json.parse(utils.read_file(lime_mesh_upgrade.LATEST_JSON_PATH)) + local repo_url = lime_mesh_upgrade.FIRMWARE_REPO_PATH + for _, im in pairs(latest['images']) do + for a, url in pairs(im['download-urls']) do + assert(string.find(url, repo_url)) + end + end + end) + before_each('', function() + snapshot = assert:snapshot() uci = test_utils.setup_test_uci() config.log (uci:set('mesh-upgrade', 'main', "mesh-upgrade")) uci:save('mesh-upgrade') @@ -85,6 +111,8 @@ describe('LiMe mesh upgrade', function() end) after_each('', function() + snapshot:revert() test_utils.teardown_test_uci(uci) + test_utils.teardown_test_dir() end) end) \ No newline at end of file From 12c1ad21c72034bfd27e5019e3408ca071e535ed Mon Sep 17 00:00:00 2001 From: selankon Date: Wed, 29 Nov 2023 16:50:46 +0100 Subject: [PATCH 020/102] Implement share firmware images --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 17 +++++++++-------- .../tests/test_lime-mesh-upgrade.lua | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index bfbc602d4..5ea575f36 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -35,6 +35,8 @@ local mesh_upgrade = { }, } +mesh_upgrade.FIRMWARE_REPO_PATH = '/lros' -- path url for firmwares + -- Get the base url for the firmware repository in this node function mesh_upgrade.get_repo_base_url() ipv4, ipv6 = network.primary_address() @@ -59,12 +61,6 @@ function mesh_upgrade.set_workdir(workdir) end mesh_upgrade.set_workdir("/tmp/mesh_upgrade") -function mesh_upgrade.set_http_dir(uhttp_folder, http_path) - mesh_upgrade.FIRMWARE_REPO_PATH = http_path -- url path for firmwares - mesh_upgrade.FIRMWARE_HTTP_PATH = uhttp_folder .. mesh_upgrade.FIRMWARE_REPO_PATH -- Path to expose the firmware - --mesh_upgrade._configure_workdir(mesh_upgrade.FIRMWARE_HTTP_PATH) -end -mesh_upgrade.set_http_dir("/www", "/lros/") function mesh_upgrade.start_eupgrade_download() local cached_only = false @@ -89,6 +85,12 @@ function mesh_upgrade.create_local_latest_json(latest_data) utils.write_file(mesh_upgrade.LATEST_JSON_PATH, json.stringify(latest_data)) end +function mesh_upgrade.share_firmware_packages(dest) + local images_folder = eupgrade.WORKDIR + mesh_upgrade._configure_workdir(dest) + os.execute("ln -s " .. images_folder .. "/* " .. dest ) +end + -- This function will download latest librerouter os firmware and expose it as -- a local repository in order to be used for other nodes function mesh_upgrade.set_up_firmware_repository() @@ -99,8 +101,7 @@ function mesh_upgrade.set_up_firmware_repository() mesh_upgrade.create_local_latest_json(latest_data) -- 3. Expose eupgrade folder to uhttp - local images_folder = eupgrade.WORKDIR - --os.execute("ln -s " .. images_folder .. "/* " .. mesh_upgrade.FIRMWARE_HTTP_PATH ) + mesh_upgrade.share_firmware_packages('/www' .. mesh_upgrade.FIRMWARE_REPO_PATH) -- 4. Update the shared state -- mesh_upgrade.inform_download_location diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index a4c6cbd63..3f6b60379 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -102,6 +102,24 @@ describe('LiMe mesh upgrade', function() end end) + it('test that link properly the files downloaded by eupgrade to desired destination', function() + -- Create some dummy files + local files = {"file1", "file2", "file3"} + local dest = "/tmp/www" .. lime_mesh_upgrade.FIRMWARE_REPO_PATH + -- Delete previous links if exist + os.execute("rm -rf " .. dest) + for _, f in pairs(files) do + utils.write_file(eupgrade.WORKDIR .. "/" .. f, "dummy") + end + lime_mesh_upgrade.share_firmware_packages(dest) + -- Check if all files exist in the destination folder + for _, f in pairs(files) do + local file_path = dest .. "/" .. f + local file_exists = utils.file_exists(file_path) -- You may need to implement or use an existing file_exists function + assert(file_exists, "File not found: " .. file_path) + end + end) + before_each('', function() snapshot = assert:snapshot() uci = test_utils.setup_test_uci() From d285f99e051d29ebe1e9ee2ee5a055db55089878 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Thu, 30 Nov 2023 12:06:56 -0300 Subject: [PATCH 021/102] adds real unit test and fix start_node_download --- .../files/etc/config/mesh-upgrade | 13 ++ .../files/usr/lib/lua/lime-mesh-upgrade.lua | 20 ++- .../tests/test_lime-mesh-upgrade.lua | 147 +++++++++++------- .../hooks/mesh_wide_upgrade/start_upgrade | 4 +- .../shared-state-publish_mesh_wide_upgrade | 4 +- 5 files changed, 116 insertions(+), 72 deletions(-) create mode 100644 packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade diff --git a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade new file mode 100644 index 000000000..9a689517d --- /dev/null +++ b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade @@ -0,0 +1,13 @@ +config mesh-upgrade 'main' + option id '' + option firmware_ver '' + option repo_url '' + option upgrade_state '' + option safe_upgrade_status '' + option eup_STATUS '' + option error '0' + option timestamp '0' + option transaction_state 'no_transaction' + option master_node '' + #option notset "" + \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index ffef535b3..2cfae8a1c 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -1,7 +1,6 @@ #!/usr/bin/env lua local eupgrade = require 'eupgrade' -local upgrade = require 'upgrade' local config = require "lime.config" local utils = require "lime.utils" local network = require("lime.network") @@ -71,14 +70,17 @@ end function mesh_upgrade.start_node_download(url) local uci = config.get_uci_cursor() eupgrade.set_upgrade_api_url(url) - status = uci:set('eupgrade', 'main', 'api_url',url) - uci:save('eupgrade') - uci:commit('eupgrade') local cached_only = false --download new firmware if necessary - config.log("is_new_version_available ") + config.log("is_new_version_available " .. url) + local url2 = eupgrade.get_upgrade_api_url() + config.log("is_new_version_available " .. url2) + + local latest_data, message = eupgrade.is_new_version_available(cached_only) + utils.printJson(latest_data) + print(message) + config.log("start_node_download from ") - local latest_data = eupgrade.is_new_version_available(cached_only) if latest_data then config.log("start_node_download ") mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) @@ -96,6 +98,8 @@ function mesh_upgrade.start_node_download(url) -- todo: how to handle this error end else + config.log("Error ... no latest data available") + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR) end mesh_upgrade.trigger_sheredstate_publish() @@ -175,7 +179,7 @@ function mesh_upgrade.change_state(newstate, errortype) uci:set('mesh-upgrade', 'main', 'upgrade_state', newstate) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') - return false + return true end -- set download information for the new firmware from master node @@ -253,7 +257,7 @@ end function mesh_upgrade.start_safe_upgrade() if mesh_upgrade.change_state( mesh_upgrade.upgrade_states.UPGRADE_SCHELUDED) and utils.file_exists(mesh_upgrade.fw_path) then - upgrade.firmware_upgrade() + --perform safe upgrade else utils.log ("not able to start upgrade invalid state or firmware not found") mesh_upgrade.change_state( mesh_upgrade.upgrade_states.ERROR) diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 02ff121f3..10aca8ae2 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -2,33 +2,31 @@ local config = require 'lime.config' local utils = require 'lime.utils' local test_utils = require 'tests.utils' local lime_mesh_upgrade = require 'lime-mesh-upgrade' -eupgrade = require 'eupgrade' +local eupgrade = require 'eupgrade' utils.enable_logging() - -- disable logging in config module config.log = function(text) - print (text) - end + print(text) +end local uci -local upgrade_data = -{ - type= "upgrade", - data={ - firmware_ver="xxxx", - repo_url="http://repo.librerouter.org/lros/api/v1/latest/", - upgrde_state="starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", - error="CODE", - safe_upgrade_status="", - eup_STATUS="", +local upgrade_data = { + type = "upgrade", + data = { + firmware_ver = "xxxx", + repo_url = "http://repo.librerouter.org/lros/api/v1/latest/", + upgrde_state = "starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", + error = "CODE", + safe_upgrade_status = "", + eup_STATUS = "" }, - timestamp=231354654, - id=21, - transaction_state="started/aborted/finished", - master_node="prmiero" + timestamp = 231354654, + id = 21, + transaction_state = "started/aborted/finished", + master_node = "prmiero" } local latest_release_data_sample = [[ @@ -89,79 +87,108 @@ describe('LiMe mesh upgrade', function() local status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.NO_TRANSACTION) - assert.is.equal(lime_mesh_upgrade.started(),false) + assert.is.equal(lime_mesh_upgrade.started(), false) end) it('test set mesh config and get status', function() - stub(eupgrade, '_get_board_name', function () return 'test-board' end) - stub(eupgrade, '_get_current_fw_version', function () return 'LibreMesh 19.05' end) - stub(eupgrade, '_check_signature', function () return true end) - stub(utils, 'http_client_get', function () return latest_release_data_sample end) - stub(eupgrade, '_file_sha256', function () return 'fbd95fc091ea10cfa05cfb0ef870da43124ac7c1402890eb8f03b440c57d7b5' end) + stub(eupgrade, '_get_board_name', function() + return 'test-board' + end) + stub(eupgrade, '_get_current_fw_version', function() + return 'LibreMesh 19.05' + end) + stub(eupgrade, '_check_signature', function() + return true + end) + stub(utils, 'http_client_get', function() + return latest_release_data_sample + end) + stub(eupgrade, '_file_sha256', function() + return 'fbd95fc091ea10cfa05cfb0ef870da43124ac7c1402890eb8f03b440c57d7b5' + end) assert.is.equal('LibreMesh 20.10', eupgrade.is_new_version_available()['version']) - lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data,lime_mesh_upgrade.upgrade_states.STARTING) + lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data, lime_mesh_upgrade.upgrade_states.STARTING) status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) assert.is.equal(status.master_node, upgrade_data.master_node) - assert.is.equal(status.data.repo_url,upgrade_data.data.repo_url ) + assert.is.equal(status.data.repo_url, upgrade_data.data.repo_url) assert.is.equal(status.data.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) assert.is.equal(status.data.eup_STATUS, eupgrade.STATUS_DOWNLOAD_FAILED) assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) -- assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.ABORTED) - --TODO: javi en caso de falla ... reintentar ? abortar ? + -- TODO: javi en caso de falla ... reintentar ? abortar ? end) it('test set mesh config start download and assert status ready_for_upgrade', function() - stub(eupgrade, '_get_board_name', function () return 'test-board' end) - stub(eupgrade, '_get_current_fw_version', function () return 'LibreMesh 19.05' end) - stub(eupgrade, '_check_signature', function () return true end) - stub(utils, 'http_client_get', function () return latest_release_data_sample end) - stub(eupgrade, '_file_sha256', function () return 'fbd95fce091ea10cfa05cfb0ef870da43124ac7c1402890eb8f03b440c57d7b5' end) + stub(eupgrade, '_get_board_name', function() + return 'test-board' + end) + stub(eupgrade, '_get_current_fw_version', function() + return 'LibreMesh 19.05' + end) + stub(eupgrade, '_check_signature', function() + return true + end) + stub(utils, 'http_client_get', function() + return latest_release_data_sample + end) + stub(eupgrade, '_file_sha256', function() + return 'fbd95fce091ea10cfa05cfb0ef870da43124ac7c1402890eb8f03b440c57d7b5' + end) assert.is.equal('LibreMesh 20.10', eupgrade.is_new_version_available()['version']) - lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data,lime_mesh_upgrade.upgrade_states.STARTING) + lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data, lime_mesh_upgrade.upgrade_states.STARTING) status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) assert.is.equal(status.master_node, upgrade_data.master_node) - assert.is.equal(status.data.repo_url,upgrade_data.data.repo_url ) + assert.is.equal(status.data.repo_url, upgrade_data.data.repo_url) assert.is.equal(status.data.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) assert.is.equal(status.data.eup_STATUS, eupgrade.STATUS_DOWNLOADED) assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) end) it('test set mesh config start download and assert status ready_for_upgrade', function() - stub(eupgrade, '_get_board_name', function () return 'librerouter-v1' end) - stub(eupgrade, '_get_current_fw_version', function () return 'LibreMesh 19.05' end) - stub(eupgrade, '_check_signature', function () return true end) - stub(eupgrade, '_file_sha256', function () return 'cec8920f93055cc57cfde1f87968e33ca5215b2df88611684195077402079acb' end) - --todo: javi este netodo no seria necesario que sea stub porque deberia tomar la url del set upgrade api pero no toma el config uci - stub(eupgrade, 'get_upgrade_api_url', function () return 'http://repo.librerouter.org/lros/api/v1/' end) - stub(utils, 'http_client_get', - function (url,to,file) - config.log("http_client_get "..url .. " "..to.. (args or "")) - if url == "http://repo.librerouter.org/lros/releases/1.5/targets/ath79/generic/upgrade-lr-1.5.sh" then - return true - end - if url == "http://repo.librerouter.org/lros/api/v1/latest/librerouter-v1.json.sig" then + stub(eupgrade, '_get_board_name', function() + return 'librerouter-v1' + end) + stub(eupgrade, '_get_current_fw_version', function() + return 'LibreMesh 19.05' + end) + stub(eupgrade, '_check_signature', function() + return true + end) + stub(eupgrade, '_file_sha256', function() + return 'cec8920f93055cc57cfde1f87968e33ca5215b2df88611684195077402079acb' + end) + -- todo: javi este netodo no seria necesario que sea stub porque deberia tomar la url del set upgrade api pero no toma el config uci + stub(eupgrade, 'get_upgrade_api_url', function() + return 'http://repo.librerouter.org/lros/api/v1/' + end) + stub(utils, 'http_client_get', function(url, to, file) + config.log("http_client_get " .. url .. " " .. to .. (args or "")) + if url == "http://repo.librerouter.org/lros/releases/1.5/targets/ath79/generic/upgrade-lr-1.5.sh" then + return true + end + if url == "http://repo.librerouter.org/lros/api/v1/latest/librerouter-v1.json.sig" then + return latest_release_data_real_sig + end + if url == "http://repo.librerouter.org/lros/api/v1/latest/librerouter-v1.json" then return latest_release_data_real end - if url == "http://repo.librerouter.org/lros/api/v1/latest/librerouter-v1.json" then - return latest_release_data_real_sig - end - config.log("http_client_get "..url .. " "..to.. (args or "")) - config.log("http_client_get "..url .. " "..to.. (args or "")) - config.log("http_client_get "..url .. " "..to.. (args or "")) - config.log("http_client_get "..url .. " "..to.. (args or "")) - config.log("http_client_get "..url .. " "..to.. (args or "")) + config.log("http_client_get " .. url .. " " .. to .. (args or "")) + config.log("http_client_get " .. url .. " " .. to .. (args or "")) + config.log("http_client_get " .. url .. " " .. to .. (args or "")) + config.log("http_client_get " .. url .. " " .. to .. (args or "")) + config.log("http_client_get " .. url .. " " .. to .. (args or "")) - return true + return true end) - --assert.is.equal('LibreRouterOs 1.5 r0+11434-e93615c947', eupgrade.is_new_version_available()['version']) - lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data,lime_mesh_upgrade.upgrade_states.STARTING) + -- assert.is.equal('LibreRouterOs 1.5 r0+11434-e93615c947', eupgrade.is_new_version_available()['version']) + lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data, lime_mesh_upgrade.upgrade_states.STARTING) status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) assert.is.equal(status.master_node, upgrade_data.master_node) - assert.is.equal(status.data.repo_url,upgrade_data.data.repo_url ) + assert.is.equal(status.data.repo_url, upgrade_data.data.repo_url) assert.is.equal(status.data.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) assert.is.equal(status.data.eup_STATUS, eupgrade.STATUS_DOWNLOADED) assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) @@ -180,4 +207,4 @@ describe('LiMe mesh upgrade', function() test_utils.teardown_test_uci(uci) test_utils.teardown_test_dir() end) -end) \ No newline at end of file +end) diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade index c0481ad35..1427eec85 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -18,11 +18,11 @@ local JSON = require("luci.jsonc") local utils = require "lime.utils" -local mesh_upgrade = require "lime.mesh-upgrade" +local mesh_upgrade = require "lime-mesh-upgrade" --if already involved in an upgrade transaction do nothing -if not mesh_upgrade.mesh_upgrade_is_started() then +if not mesh_upgrade.started() then for node, s_s_data in pairs(JSON.parse(io.stdin:read("*all"))) do --if any node has started an upgrade process and start one too? --only fetch the info from the master node publication? diff --git a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade index 1368949b4..cef531948 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade @@ -19,13 +19,13 @@ local JSON = require("luci.jsonc") local utils = require('lime.utils') -local mesh_upgrade = require "lime.mesh-upgrade" +local mesh_upgrade = require "lime-mesh-upgrade" local hostname = utils.hostname() function report_upgrade_status() --todo: get data from libmeshupgrade and send - return mesh_upgrade.get_status() + return mesh_upgrade.get_mesh_upgrade_status() end local result = { [hostname] = report_upgrade_status() } From b905783cfe7e9a165a15353e72b632abbf1c17ae Mon Sep 17 00:00:00 2001 From: selankon Date: Thu, 30 Nov 2023 17:06:46 +0100 Subject: [PATCH 022/102] Add test --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 2 +- .../lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 5ea575f36..6e6de9881 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -81,8 +81,8 @@ function mesh_upgrade.create_local_latest_json(latest_data) --im['download-urls'] = string.gsub(im['download-urls'], upgrade_url, "test") im['download-urls'] = {mesh_upgrade.get_repo_base_url() .. im['name']} end - -- todo(kon): implement create SHA signature utils.write_file(mesh_upgrade.LATEST_JSON_PATH, json.stringify(latest_data)) + -- For the moment mesh upgrade will ignore the latest json signature on de master nodes end function mesh_upgrade.share_firmware_packages(dest) diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 3f6b60379..a7363396d 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -90,6 +90,13 @@ describe('LiMe mesh upgrade', function() assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) end) + it('test custom latest json file is created', function() + stub(network, 'primary_address', function () return '10.13.0.1', 'ipv6' end) + lime_mesh_upgrade.create_local_latest_json(json.parse(latest_release_data)) + local filexists = utils.file_exists(lime_mesh_upgrade.LATEST_JSON_PATH) + assert(filexists, "File not found: " .. lime_mesh_upgrade.LATEST_JSON_PATH) + end) + it('test set_up_firmware_repository download the files correctly and fix the url on json', function() stub(network, 'primary_address', function () return '10.13.0.1', 'ipv6' end) lime_mesh_upgrade.create_local_latest_json(json.parse(latest_release_data)) @@ -115,7 +122,7 @@ describe('LiMe mesh upgrade', function() -- Check if all files exist in the destination folder for _, f in pairs(files) do local file_path = dest .. "/" .. f - local file_exists = utils.file_exists(file_path) -- You may need to implement or use an existing file_exists function + local file_exists = utils.file_exists(file_path) assert(file_exists, "File not found: " .. file_path) end end) From 85f7f95b142d8573e1eb0a69e03d95bddb7ca7d4 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Thu, 30 Nov 2023 15:52:40 -0300 Subject: [PATCH 023/102] merge commits and use alternative eupgrade infra adds new methods to eupgrade like "is_meshupgrade_enabled" and "set_custom_api_url" fixes some reduntant methods call --- .../eupgrade/files/usr/lib/lua/eupgrade.lua | 26 +++++++++++++++---- packages/eupgrade/tests/test_eupgrade.lua | 17 +++++++++++- .../files/usr/etc/config/mesh-upgrade | 13 ---------- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 7 +++-- .../tests/test_lime-mesh-upgrade.lua | 1 - 5 files changed, 40 insertions(+), 24 deletions(-) delete mode 100644 packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade diff --git a/packages/eupgrade/files/usr/lib/lua/eupgrade.lua b/packages/eupgrade/files/usr/lib/lua/eupgrade.lua index 23cf2611e..79a656563 100644 --- a/packages/eupgrade/files/usr/lib/lua/eupgrade.lua +++ b/packages/eupgrade/files/usr/lib/lua/eupgrade.lua @@ -2,6 +2,7 @@ local utils = require "lime.utils" local json = require "luci.jsonc" local libuci = require "uci" local fs = require("nixio.fs") +local config = require "lime.config" local eup = {} @@ -32,12 +33,27 @@ function eup.is_enabled() return uci:get('eupgrade', 'main', 'enabled') == '1' end +function eup.is_meshupgrade_enabled() + if uci:get('eupgrade', 'main', 'custom_api_url') == nil then + return false + else + return true + end +end + function eup.get_upgrade_api_url() - return uci:get('eupgrade', 'main', 'api_url') or '' + return uci:get('eupgrade', 'main', 'custom_api_url') or uci:get('eupgrade', 'main', 'api_url') or '' end -function eup.set_upgrade_api_url(url) - status = uci:set('eupgrade', 'main', 'api_url',url) +function eup.set_custom_api_url(url) + status = uci:set('eupgrade', 'main', 'custom_api_url',url) + uci:save('eupgrade') + uci:commit('eupgrade') + return status +end + +function eup.remove_custom_api_url() + status = uci:delete('eupgrade', 'main', 'custom_api_url') uci:save('eupgrade') uci:commit('eupgrade') return status @@ -93,8 +109,8 @@ function eup.is_new_version_available(cached_only) message = "Can't download signature " .. sig_url utils.log(message) end - - if eup._check_signature(eup.FIRMWARE_LATEST_JSON, eup.FIRMWARE_LATEST_JSON_SIGNATURE) then + -- this will skip json signature verification when altenative url is set + if eup._check_signature(eup.FIRMWARE_LATEST_JSON, eup.FIRMWARE_LATEST_JSON_SIGNATURE) or eup.is_meshupgrade_enabled() then utils.log("Good signature of firmware_latest.json") return latest_data else diff --git a/packages/eupgrade/tests/test_eupgrade.lua b/packages/eupgrade/tests/test_eupgrade.lua index 7a92961bf..0a1832bab 100644 --- a/packages/eupgrade/tests/test_eupgrade.lua +++ b/packages/eupgrade/tests/test_eupgrade.lua @@ -48,7 +48,7 @@ describe('eupgrade tests #eupgrade', function() assert.is.equal('LibreMesh 20.10', eup.is_new_version_available()['version']) end) - it('test is_new_version_available latest version is not the same as current version', function() + it('test is_new_version_available but signature fails', function() stub(eup, '_get_board_name', function () return 'test-board' end) stub(eup, '_get_current_fw_version', function () return 'LibreMesh 19.05' end) stub(eup, '_check_signature', function () return false end) @@ -58,6 +58,21 @@ describe('eupgrade tests #eupgrade', function() assert.is.equal("Bad signature of firmware_latest.json", message) end) + -- it('test is_new_version_available signature fails, but it does not mather since an alternative url has been set', function() + -- stub(eup, '_get_board_name', function () return 'test-board' end) + -- stub(eup, '_get_current_fw_version', function () return 'LibreMesh 19.05' end) + -- stub(eup, '_check_signature', function () return false end) + -- stub(utils, 'http_client_get', function () return latest_release_data end) + -- print("1",tostring(eup.get_upgrade_api_url())) + -- eup.set_custom_api_url("http://localhost") + -- assert.is_true(eup.is_meshupgrade_enabled()) + -- print("2",eup.get_upgrade_api_url()) + -- assert.is.equal('LibreMesh 20.10', eup.is_new_version_available()['version']) + -- eup.remove_custom_api_url() + -- print("3",eup.get_upgrade_api_url()) + + -- end) + it('test is_new_version_available unable to download info', function() stub(eup, '_get_board_name', function () return 'test-board' end) stub(eup, '_get_current_fw_version', function () return 'LibreMesh 19.05' end) diff --git a/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade b/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade deleted file mode 100644 index 9a689517d..000000000 --- a/packages/lime-mesh-upgrade/files/usr/etc/config/mesh-upgrade +++ /dev/null @@ -1,13 +0,0 @@ -config mesh-upgrade 'main' - option id '' - option firmware_ver '' - option repo_url '' - option upgrade_state '' - option safe_upgrade_status '' - option eup_STATUS '' - option error '0' - option timestamp '0' - option transaction_state 'no_transaction' - option master_node '' - #option notset "" - \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index ea847a450..fbd36876e 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -117,6 +117,7 @@ end -- function to be called by nodes to start download from master. function mesh_upgrade.start_node_download(url) + eupgrade.set_workdir("/tmp/mesh_upgrade") local uci = config.get_uci_cursor() eupgrade.set_custom_api_url(url) local cached_only = false @@ -134,13 +135,11 @@ function mesh_upgrade.start_node_download(url) config.log("start_node_download ") mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) config.log("downloading") - - local image = eupgrade.download_firmware(latest_data) - local image = {} image, mesh_upgrade.fw_path = eupgrade.download_firmware(latest_data) uci:set('mesh-upgrade', 'main', 'eup_STATUS', eupgrade.get_download_status()) - if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED then + if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED and image ~= nil then + utils.printJson(image) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) else mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR) diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 13eaf8012..a1c053c23 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -202,7 +202,6 @@ describe('LiMe mesh upgrade', function() return true end) - -- assert.is.equal('LibreRouterOs 1.5 r0+11434-e93615c947', eupgrade.is_new_version_available()['version']) lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data, lime_mesh_upgrade.upgrade_states.STARTING) status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) From d220532c7e14fc44f844aada41ab9a23d35a826f Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 1 Dec 2023 16:16:04 +0100 Subject: [PATCH 024/102] Ensure local latest json sharing --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 13 +++++-------- .../tests/test_lime-mesh-upgrade.lua | 7 +++++++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index fbd36876e..6a138799f 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -39,9 +39,6 @@ local mesh_upgrade = { -- shoud epgrade be disabled ? --eupgrade.set_workdir("/tmp/mesh_upgrade") - -mesh_upgrade.FIRMWARE_REPO_PATH = '/lros' -- path url for firmwares - -- Get the base url for the firmware repository in this node function mesh_upgrade.get_repo_base_url() ipv4, ipv6 = network.primary_address() @@ -62,7 +59,9 @@ function mesh_upgrade.set_workdir(workdir) mesh_upgrade._configure_workdir(workdir) mesh_upgrade.WORKDIR = workdir mesh_upgrade.LATEST_JSON_FILE_NAME = "firmware_latest_mesh_wide.json" -- latest json with local lan url file name - mesh_upgrade.LATEST_JSON_PATH = mesh_upgrade.WORKDIR .. mesh_upgrade.LATEST_JSON_FILE_NAME -- latest json full path + mesh_upgrade.LATEST_JSON_PATH = mesh_upgrade.WORKDIR .. "/" .. mesh_upgrade.LATEST_JSON_FILE_NAME -- latest json full path + mesh_upgrade.FIRMWARE_REPO_PATH = 'lros' -- path url for firmwares + mesh_upgrade.FIRMWARE_SHARED_FOLDER = '/www/' .. mesh_upgrade.FIRMWARE_REPO_PATH end mesh_upgrade.set_workdir("/tmp/mesh_upgrade") @@ -94,6 +93,7 @@ function mesh_upgrade.share_firmware_packages(dest) local images_folder = eupgrade.WORKDIR mesh_upgrade._configure_workdir(dest) os.execute("ln -s " .. images_folder .. "/* " .. dest ) + os.execute("ln -s " .. mesh_upgrade.LATEST_JSON_PATH .. " " .. dest ) end -- This function will download latest librerouter os firmware and expose it as @@ -106,10 +106,7 @@ function mesh_upgrade.set_up_firmware_repository() mesh_upgrade.create_local_latest_json(latest_data) -- 3. Expose eupgrade folder to uhttp - mesh_upgrade.share_firmware_packages('/www' .. mesh_upgrade.FIRMWARE_REPO_PATH) - - -- 4. Update the shared state - -- mesh_upgrade.inform_download_location + mesh_upgrade.share_firmware_packages() end -- Shared state functions -- diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index a1c053c23..26d78775c 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -240,6 +240,9 @@ describe('LiMe mesh upgrade', function() for _, f in pairs(files) do utils.write_file(eupgrade.WORKDIR .. "/" .. f, "dummy") end + -- Create latest json file also + utils.write_file(lime_mesh_upgrade.LATEST_JSON_PATH, "dummy") + -- Create the links lime_mesh_upgrade.share_firmware_packages(dest) -- Check if all files exist in the destination folder for _, f in pairs(files) do @@ -247,6 +250,10 @@ describe('LiMe mesh upgrade', function() local file_exists = utils.file_exists(file_path) assert(file_exists, "File not found: " .. file_path) end + -- Check that the local json file is also there + local json_link = dest .. "/" .. lime_mesh_upgrade.LATEST_JSON_FILE_NAME + local file_exists = utils.file_exists(json_link) + assert(file_exists, "File not found: " .. json_link) end) before_each('', function() From d2f00aa1002c6cb2bc6b0123ff74bd583568e88f Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 1 Dec 2023 16:21:30 +0100 Subject: [PATCH 025/102] Implement become_master_node --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 33 ++++++++++++++++++- .../usr/libexec/rpcd/lime-mesh-upgrade.lua | 9 ++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 6a138799f..3e82e73be 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -109,6 +109,38 @@ function mesh_upgrade.set_up_firmware_repository() mesh_upgrade.share_firmware_packages() end +-- Function that check if tihs node have all things needed to became a master node +-- Then, call update shared state with the proper info +function mesh_upgrade.become_master_node() + -- todo(kon): check if master node is already set or we are on mesh_upgrade status + local download_status = eupgrade.get_download_status() + -- Check if there are a new version available (cached only) + local latest = eup.is_new_version_available(true) + if not latest then + return { code = "NO_NEW_VERSION", error = "No new version is available"} + end + -- Check download is completed + if download_status == eupgrade.STATUS_DEFAULT then + return { code = download_status, error = "Firmware download not started" } + elseif download_status == eup.STATUS_DOWNLOADING then + return { code = download_status, error = "Firmware is downloading"} + elseif download_status == eup.STATUS_DOWNLOAD_FAILED then + return { code = download_status, error = "Firmware download failed"} + end + -- Check if local json file exists + if not utils.file_exists(mesh_upgrade.LATEST_JSON_PATH) then + return { code = "NO_LOCAL_JSON", error = "Local json file not found"} + end + -- Check firmware packages are shared properly + -- we could check if the shared folder is empty or not and what files are present. Not needed imho + if not utils.file_exists(mesh_upgrade.FIRMWARE_SHARED_FOLDER) then + return { code = "NO_SHARED_FOLDER", error = "Shared folder not found"} + end + -- If we get here is supposed that everything is ready to be a master node + mesh_upgrade.inform_download_location(latest['version']) + return { code = "SUCCESS"} +end + -- Shared state functions -- ---------------------------- @@ -154,7 +186,6 @@ end -- also will force shared state data refresh -- curl -6 'http://[fe80::a8aa:aaff:fe0d:feaa%lime_br0]/fw/resolv.conf' -- curl -6 'http://[fd0d:fe46:8ce8::1]/lros/api/v1/' - function mesh_upgrade.inform_download_location(version) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED then --TODO: setup uhttpd to serve workdir location diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua index 4fa9969d5..2595b6232 100755 --- a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua @@ -14,8 +14,14 @@ local function set_up_firmware_repository(msg) return utils.printJson(result) end +local function become_master_node(msg) + local result = mesh_upgrade.become_master_node(msg) + return utils.printJson(result) +end + local methods = { - became_master_node = {}, + set_up_firmware_repository = {}, + become_master_node = {}, } if arg[1] == 'list' then utils.printJson(methods) end @@ -24,6 +30,7 @@ if arg[1] == 'call' then local msg = utils.rpcd_readline() msg = json.parse(msg) if arg[2] == 'set_up_firmware_repository' then set_up_firmware_repository(msg) + elseif arg[2] == 'become_master_node' then become_master_node(msg) else utils.printJson({ error = "Method not found" }) end end From c58fdad83966e84804ba79a4db2c06f8ebe7db40 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 1 Dec 2023 16:23:44 +0100 Subject: [PATCH 026/102] Fix eup to eupgrade --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 3e82e73be..14c52a74a 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -115,16 +115,16 @@ function mesh_upgrade.become_master_node() -- todo(kon): check if master node is already set or we are on mesh_upgrade status local download_status = eupgrade.get_download_status() -- Check if there are a new version available (cached only) - local latest = eup.is_new_version_available(true) + local latest = eupgrade.is_new_version_available(true) if not latest then return { code = "NO_NEW_VERSION", error = "No new version is available"} end -- Check download is completed if download_status == eupgrade.STATUS_DEFAULT then return { code = download_status, error = "Firmware download not started" } - elseif download_status == eup.STATUS_DOWNLOADING then + elseif download_status == eupgrade.STATUS_DOWNLOADING then return { code = download_status, error = "Firmware is downloading"} - elseif download_status == eup.STATUS_DOWNLOAD_FAILED then + elseif download_status == eupgrade.STATUS_DOWNLOAD_FAILED then return { code = download_status, error = "Firmware download failed"} end -- Check if local json file exists From e04af02217d452559e9c825aa21fa6e3b4722e81 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Fri, 1 Dec 2023 15:39:03 -0300 Subject: [PATCH 027/102] updates the downloaded list of files adds a destination to share fw files changes firmware repo fixes get_repo_base_url() --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 14c52a74a..3dac532fc 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -41,8 +41,8 @@ local mesh_upgrade = { -- Get the base url for the firmware repository in this node function mesh_upgrade.get_repo_base_url() - ipv4, ipv6 = network.primary_address() - return "http://" .. ipv4 .. mesh_upgrade.FIRMWARE_REPO_PATH + local ipv4, ipv6 = network.primary_address() + return "http://" .. ipv4:host():string() .. mesh_upgrade.FIRMWARE_REPO_PATH end -- Create a work directory if nor exist @@ -60,7 +60,7 @@ function mesh_upgrade.set_workdir(workdir) mesh_upgrade.WORKDIR = workdir mesh_upgrade.LATEST_JSON_FILE_NAME = "firmware_latest_mesh_wide.json" -- latest json with local lan url file name mesh_upgrade.LATEST_JSON_PATH = mesh_upgrade.WORKDIR .. "/" .. mesh_upgrade.LATEST_JSON_FILE_NAME -- latest json full path - mesh_upgrade.FIRMWARE_REPO_PATH = 'lros' -- path url for firmwares + mesh_upgrade.FIRMWARE_REPO_PATH = '/lros/' -- path url for firmwares mesh_upgrade.FIRMWARE_SHARED_FOLDER = '/www/' .. mesh_upgrade.FIRMWARE_REPO_PATH end mesh_upgrade.set_workdir("/tmp/mesh_upgrade") @@ -90,6 +90,9 @@ function mesh_upgrade.create_local_latest_json(latest_data) end function mesh_upgrade.share_firmware_packages(dest) + if dest == nil then + dest = "/www" .. mesh_upgrade.FIRMWARE_REPO_PATH + end local images_folder = eupgrade.WORKDIR mesh_upgrade._configure_workdir(dest) os.execute("ln -s " .. images_folder .. "/* " .. dest ) @@ -136,6 +139,8 @@ function mesh_upgrade.become_master_node() if not utils.file_exists(mesh_upgrade.FIRMWARE_SHARED_FOLDER) then return { code = "NO_SHARED_FOLDER", error = "Shared folder not found"} end + --reshare downloaded files + mesh_upgrade.share_firmware_packages() -- If we get here is supposed that everything is ready to be a master node mesh_upgrade.inform_download_location(latest['version']) return { code = "SUCCESS"} From 532ad422915a6b617b6b6bb40aeb5b13107512cd Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Tue, 5 Dec 2023 15:42:27 -0300 Subject: [PATCH 028/102] fixes paths and urls to work with eupgrade creates links in new latest folder share_firmware_packages after download has finished successfully adds a test script for the masternode improves startupgrade hoock log information --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 71 ++++++++++--------- .../files/usr/lib/lua/testmaster.lua | 33 +++++++++ .../hooks/mesh_wide_upgrade/start_upgrade | 16 ++--- 3 files changed, 78 insertions(+), 42 deletions(-) create mode 100644 packages/lime-mesh-upgrade/files/usr/lib/lua/testmaster.lua diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 3dac532fc..b463c6d8c 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -1,4 +1,5 @@ #!/usr/bin/env lua + local eupgrade = require 'eupgrade' local config = require "lime.config" local utils = require "lime.utils" @@ -46,7 +47,7 @@ function mesh_upgrade.get_repo_base_url() end -- Create a work directory if nor exist -function mesh_upgrade._configure_workdir(workdir) +function mesh_upgrade._create_workdir(workdir) if not utils.file_exists(workdir) then os.execute('mkdir -p ' .. workdir) end @@ -56,11 +57,11 @@ function mesh_upgrade._configure_workdir(workdir) end function mesh_upgrade.set_workdir(workdir) - mesh_upgrade._configure_workdir(workdir) + mesh_upgrade._create_workdir(workdir) mesh_upgrade.WORKDIR = workdir - mesh_upgrade.LATEST_JSON_FILE_NAME = "firmware_latest_mesh_wide.json" -- latest json with local lan url file name + mesh_upgrade.LATEST_JSON_FILE_NAME = eupgrade._get_board_name()..".json" -- latest json with local lan url file name mesh_upgrade.LATEST_JSON_PATH = mesh_upgrade.WORKDIR .. "/" .. mesh_upgrade.LATEST_JSON_FILE_NAME -- latest json full path - mesh_upgrade.FIRMWARE_REPO_PATH = '/lros/' -- path url for firmwares + mesh_upgrade.FIRMWARE_REPO_PATH = '/lros/' -- path url for firmwares mesh_upgrade.FIRMWARE_SHARED_FOLDER = '/www/' .. mesh_upgrade.FIRMWARE_REPO_PATH end mesh_upgrade.set_workdir("/tmp/mesh_upgrade") @@ -94,9 +95,11 @@ function mesh_upgrade.share_firmware_packages(dest) dest = "/www" .. mesh_upgrade.FIRMWARE_REPO_PATH end local images_folder = eupgrade.WORKDIR - mesh_upgrade._configure_workdir(dest) - os.execute("ln -s " .. images_folder .. "/* " .. dest ) - os.execute("ln -s " .. mesh_upgrade.LATEST_JSON_PATH .. " " .. dest ) + mesh_upgrade._create_workdir(dest) + --json file has to be placed in a url that ends with latest + mesh_upgrade._create_workdir(dest.."/latest") + os.execute("ln -s " .. images_folder .. "/* " .. dest) + os.execute("ln -s " .. mesh_upgrade.LATEST_JSON_PATH .. " " .. dest.. "/latest") end -- This function will download latest librerouter os firmware and expose it as @@ -104,12 +107,16 @@ end function mesh_upgrade.set_up_firmware_repository() -- 1. Check if new version is available and download it demonized using eupgrade local latest_data = mesh_upgrade.start_eupgrade_download() + if latest_data then + -- 2. Create local repository json data + mesh_upgrade.create_local_latest_json(latest_data) + -- 3. Expose eupgrade folder to uhttp + -- mesh_upgrade.share_firmware_packages() + -- do not do it here since the download may fail. + else + utils.log("no new version available") + end - -- 2. Create local repository json data - mesh_upgrade.create_local_latest_json(latest_data) - - -- 3. Expose eupgrade folder to uhttp - mesh_upgrade.share_firmware_packages() end -- Function that check if tihs node have all things needed to became a master node @@ -130,6 +137,9 @@ function mesh_upgrade.become_master_node() elseif download_status == eupgrade.STATUS_DOWNLOAD_FAILED then return { code = download_status, error = "Firmware download failed"} end + -- 3. Expose eupgrade folder to uhttp (this is the best place to do it since + -- all the files are present) + mesh_upgrade.share_firmware_packages() -- Check if local json file exists if not utils.file_exists(mesh_upgrade.LATEST_JSON_PATH) then return { code = "NO_LOCAL_JSON", error = "Local json file not found"} @@ -139,8 +149,6 @@ function mesh_upgrade.become_master_node() if not utils.file_exists(mesh_upgrade.FIRMWARE_SHARED_FOLDER) then return { code = "NO_SHARED_FOLDER", error = "Shared folder not found"} end - --reshare downloaded files - mesh_upgrade.share_firmware_packages() -- If we get here is supposed that everything is ready to be a master node mesh_upgrade.inform_download_location(latest['version']) return { code = "SUCCESS"} @@ -151,24 +159,17 @@ end -- function to be called by nodes to start download from master. function mesh_upgrade.start_node_download(url) - eupgrade.set_workdir("/tmp/mesh_upgrade") local uci = config.get_uci_cursor() eupgrade.set_custom_api_url(url) local cached_only = false - --download new firmware if necessary - config.log("is_new_version_available " .. url) local url2 = eupgrade.get_upgrade_api_url() - config.log("is_new_version_available " .. url2) - local latest_data, message = eupgrade.is_new_version_available(cached_only) - utils.printJson(latest_data) - print(message) - config.log("start_node_download from ") + utils.log("start_node_download from "..url2) if latest_data then - config.log("start_node_download ") + utils.log("start_node_download ") mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) - config.log("downloading") + utils.log("downloading") local image = {} image, mesh_upgrade.fw_path = eupgrade.download_firmware(latest_data) uci:set('mesh-upgrade', 'main', 'eup_STATUS', eupgrade.get_download_status()) @@ -180,7 +181,7 @@ function mesh_upgrade.start_node_download(url) -- todo: how to handle this error end else - config.log("Error ... no latest data available") + utils.log("Error ... no latest data available") mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR) end @@ -210,7 +211,7 @@ function mesh_upgrade.inform_download_location(version) master_node = utils.hostname() }, mesh_upgrade.upgrade_states.READY_FOR_UPGRADE, mesh_upgrade.transaction_states.STARTED) else - config.log("eupgrade STATUS is not 'DOWNLOADED'") + utils.log("eupgrade STATUS is not 'DOWNLOADED'") end end @@ -265,11 +266,10 @@ end -- Called by a shared state hook in non master nodes function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state, transaction_state) local uci = config.get_uci_cursor() - if (type(upgrade_data.id) == "number") and string.match(upgrade_data.data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= - nil -- perform aditional checks + if string.match(upgrade_data.data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil -- perform aditional checks then + utils.log("seting up repo download info ") if (mesh_upgrade.change_state(upgrade_state)) then - uci:get('mesh-upgrade', 'main', 'repo_url') uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:set('mesh-upgrade', 'main', 'id', upgrade_data.id) uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.data.repo_url) @@ -284,12 +284,14 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state, transac uci:commit('mesh-upgrade') -- trigger shared state data refresh mesh_upgrade.trigger_sheredstate_publish() - mesh_upgrade.start_node_download(upgrade_data.data.repo_url) + if (upgrade_state == mesh_upgrade.upgrade_states.STARTING) then + mesh_upgrade.start_node_download(upgrade_data.data.repo_url) + end else - config.log("invalid state change ") + utils.log("invalid state change ") end else - config.log("upgrade failed due input data errors") + utils.log("upgrade failed due input data errors") end end @@ -335,8 +337,9 @@ function mesh_upgrade.get_mesh_upgrade_status() end function mesh_upgrade.start_safe_upgrade() - if mesh_upgrade.change_state( mesh_upgrade.upgrade_states.UPGRADE_SCHELUDED) and utils.file_exists(mesh_upgrade.fw_path) then - --perform safe upgrade + if mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHELUDED) and + utils.file_exists(mesh_upgrade.fw_path) then + -- perform safe upgrade else utils.log ("not able to start upgrade invalid state or firmware not found") mesh_upgrade.change_state( mesh_upgrade.upgrade_states.ERROR) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/testmaster.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/testmaster.lua new file mode 100644 index 000000000..b7099899d --- /dev/null +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/testmaster.lua @@ -0,0 +1,33 @@ +local lime_mesh_upgrade = require 'lime-mesh-upgrade' +local eupgrade = require 'eupgrade' + +local network = require("lime.network") +print (tostring(network.primary_address())) + +print(tostring(eupgrade.get_upgrade_api_url())) + +local utils = require "lime.utils" +os.execute('echo librerouter-v1 > /tmp/sysinfo/board_name') + + +print(eupgrade._get_board_name()) + +eupgrade.set_custom_api_url('http://repo.librerouter.org/lros/api/v1/') +print(tostring(eupgrade.get_upgrade_api_url())) + +print(tostring(eupgrade.is_new_version_available())) +lime_mesh_upgrade.set_up_firmware_repository() +utils.printJson(lime_mesh_upgrade.become_master_node()) + +os.execute("sleep " .. tonumber(6)) + +utils.printJson(lime_mesh_upgrade.become_master_node()) + +os.execute("sleep " .. tonumber(6)) + +utils.printJson(lime_mesh_upgrade.become_master_node()) + +os.execute("sleep " .. tonumber(20)) + +utils.printJson(lime_mesh_upgrade.become_master_node()) + diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade index 1427eec85..6c40009a6 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -19,22 +19,22 @@ local JSON = require("luci.jsonc") local utils = require "lime.utils" local mesh_upgrade = require "lime-mesh-upgrade" - +local hostname = utils.hostname() --if already involved in an upgrade transaction do nothing if not mesh_upgrade.started() then for node, s_s_data in pairs(JSON.parse(io.stdin:read("*all"))) do --if any node has started an upgrade process and start one too? --only fetch the info from the master node publication? - if s_s_data.data.master_node == node then - + if node ~= hostname and s_s_data.data.master_node == node then + utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from "' .. + s_s_data.data.data.repo_url .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) + mesh_upgrade.set_mesh_upgrade_info(s_s_data.data,mesh_upgrade.upgrade_states.STARTING) - utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from"' .. - s_s_data.data.repo_url .. " " .. node) + else + utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "status "' .. + JSON.stringify(s_s_data.data) .. " from node " .. node) end - utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "hoock +++++ "' .. - JSON.stringify(s_s_data.data) .. " " .. node) - utils.log("hook started ", JSON.stringify(s_s_data.data), node) end else utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "already started an upgrade process"') From e0458b78c5eca676d0f76fcff3b476afaf4ee12e Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Tue, 5 Dec 2023 16:00:59 -0300 Subject: [PATCH 029/102] helps network module return the write ip format defines the boardname file --- .../tests/test_lime-mesh-upgrade.lua | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 26d78775c..a65ea96c0 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -1,4 +1,9 @@ local config = require 'lime.config' + +os.execute('mkdir /tmp/sysinfo/') +os.execute('echo librerouter-v1 > /tmp/sysinfo/board_name') + + local lime_mesh_upgrade = require 'lime-mesh-upgrade' local network = require("lime.network") local utils = require "lime.utils" @@ -213,14 +218,31 @@ describe('LiMe mesh upgrade', function() end) it('test custom latest json file is created', function() - stub(network, 'primary_address', function () return '10.13.0.1', 'ipv6' end) + + config.set('network', 'lime') + config.set('network', 'main_ipv4_address', '10.%N1.0.0/16') + config.set('network', 'main_ipv6_address', 'fd%N1:%N2%N3:%N4%N5::/64') + config.set('network', 'protocols', {'lan'}) + config.set('wifi', 'lime') + config.set('wifi', 'ap_ssid', 'LibreMesh.org') + uci:commit('lime') + + --stub(network, 'primary_address', function () return '10.13.0.1', 'ipv6' end) + lime_mesh_upgrade.create_local_latest_json(json.parse(latest_release_data)) local filexists = utils.file_exists(lime_mesh_upgrade.LATEST_JSON_PATH) assert(filexists, "File not found: " .. lime_mesh_upgrade.LATEST_JSON_PATH) end) it('test set_up_firmware_repository download the files correctly and fix the url on json', function() - stub(network, 'primary_address', function () return '10.13.0.1', 'ipv6' end) + config.set('network', 'lime') + config.set('network', 'main_ipv4_address', '10.%N1.0.0/16') + config.set('network', 'main_ipv6_address', 'fd%N1:%N2%N3:%N4%N5::/64') + config.set('network', 'protocols', {'lan'}) + config.set('wifi', 'lime') + config.set('wifi', 'ap_ssid', 'LibreMesh.org') + uci:commit('lime') + lime_mesh_upgrade.create_local_latest_json(json.parse(latest_release_data)) local latest = json.parse(utils.read_file(lime_mesh_upgrade.LATEST_JSON_PATH)) local repo_url = lime_mesh_upgrade.FIRMWARE_REPO_PATH @@ -251,7 +273,7 @@ describe('LiMe mesh upgrade', function() assert(file_exists, "File not found: " .. file_path) end -- Check that the local json file is also there - local json_link = dest .. "/" .. lime_mesh_upgrade.LATEST_JSON_FILE_NAME + local json_link = dest .. "latest/" .. lime_mesh_upgrade.LATEST_JSON_FILE_NAME local file_exists = utils.file_exists(json_link) assert(file_exists, "File not found: " .. json_link) end) From e1fafc825a12b35780c94fe01a24c9706a06a5d5 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Thu, 4 Jan 2024 16:40:50 -0300 Subject: [PATCH 030/102] discards signature check on meshupgrade --- packages/eupgrade/files/usr/lib/lua/eupgrade.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eupgrade/files/usr/lib/lua/eupgrade.lua b/packages/eupgrade/files/usr/lib/lua/eupgrade.lua index 79a656563..31188f61e 100644 --- a/packages/eupgrade/files/usr/lib/lua/eupgrade.lua +++ b/packages/eupgrade/files/usr/lib/lua/eupgrade.lua @@ -84,7 +84,7 @@ end function eup.is_new_version_available(cached_only) --! if 'latest' files are present is because there is a new version if utils.file_exists(eup.FIRMWARE_LATEST_JSON) and utils.file_exists(eup.FIRMWARE_LATEST_JSON_SIGNATURE) then - if eup._check_signature(eup.FIRMWARE_LATEST_JSON, eup.FIRMWARE_LATEST_JSON_SIGNATURE) then + if eup._check_signature(eup.FIRMWARE_LATEST_JSON, eup.FIRMWARE_LATEST_JSON_SIGNATURE) or eup.is_meshupgrade_enabled() then return json.parse(utils.read_file(eup.FIRMWARE_LATEST_JSON)) end end From 46fe6f2fd151950c0391c3c8c3c4b6a5f35ec7ed Mon Sep 17 00:00:00 2001 From: selankon Date: Tue, 9 Jan 2024 16:25:47 +0100 Subject: [PATCH 031/102] Create shared state acl.d --- .../usr/share/rpcd/acl.d/shared-state.json | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 packages/shared-state/files/usr/share/rpcd/acl.d/shared-state.json diff --git a/packages/shared-state/files/usr/share/rpcd/acl.d/shared-state.json b/packages/shared-state/files/usr/share/rpcd/acl.d/shared-state.json new file mode 100644 index 000000000..9b14ed8ff --- /dev/null +++ b/packages/shared-state/files/usr/share/rpcd/acl.d/shared-state.json @@ -0,0 +1,28 @@ +{ + "root": { + "description": "Shared state data root ubus interface", + "read": { + "ubus": { + "shared-state": ["insertIntoSharedStateMultiWriter"] + } + }, + "write": { + "ubus": { + "shared-state": ["insertIntoSharedStateMultiWriter"] + } + } + }, + "lime-app": { + "description": "Get shared state data from ubus", + "read": { + "ubus": { + "shared-state": [ "*" ] + } + }, + "write": { + "ubus": { + "shared-state": [ "*" ] + } + } + } +} From 84ae8ebf9ad8f1da37dea8b669e0454edda21700 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Thu, 11 Jan 2024 19:54:45 -0300 Subject: [PATCH 032/102] removes transaction concept --- .../files/etc/config/mesh-upgrade | 10 +- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 233 +++++++++--------- .../files/usr/lib/lua/testmaster.lua | 33 --- .../tests/test_lime-mesh-upgrade.lua | 69 +++--- .../hooks/mesh_wide_upgrade/start_upgrade | 7 +- .../shared-state-publish_mesh_wide_upgrade | 1 - 6 files changed, 167 insertions(+), 186 deletions(-) delete mode 100644 packages/lime-mesh-upgrade/files/usr/lib/lua/testmaster.lua diff --git a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade index 9a689517d..22a0198e7 100644 --- a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade @@ -1,13 +1,9 @@ config mesh-upgrade 'main' - option id '' option firmware_ver '' + option candidate_fw '' option repo_url '' - option upgrade_state '' - option safe_upgrade_status '' - option eup_STATUS '' + option upgrade_state 'DEFAULT' option error '0' option timestamp '0' - option transaction_state 'no_transaction' - option master_node '' - #option notset "" + option master_node 'false' \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index b463c6d8c..c15e42af4 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -8,7 +8,7 @@ local fs = require("nixio.fs") local json = require 'luci.jsonc' local mesh_upgrade = { - -- posible tranactin states + -- posible transaction states are derived from upgrade states transaction_states = { NO_TRANSACTION = "no_transaction", STARTED = "started", -- there is a transaction in progress @@ -17,28 +17,31 @@ local mesh_upgrade = { }, -- psible upgrade states enumeration upgrade_states = { - DEFAULT = "not upgrading", + DEFAULT = "not upgrading", -- When no transaction has started STARTING = "starting", DOWNLOADING = "downloading", READY_FOR_UPGRADE = "ready_for_upgrade", UPGRADE_SCHEDULED = "upgrade_scheluded", CONFIRMATION_PENDING = "confirmation_pending", CONFIRMED = "confirmed", - UPDATED = "updated", ERROR = "error" }, + -- list of possible errors errors = { DOWNLOAD_FAILED = "download failed", - CONFIRMATION_TIME_OUT = "confirmation timeout" + NO_LATEST_AVAILABLE = "no latest data available", + CONFIRMATION_TIME_OUT = "confirmation timeout", + ABORTED = "aborted" + }, fw_path = "", su_timeout = 600, MASTERNODE_ENDPOINT = "/lros/api/v1/" } --- shoud epgrade be disabled ? ---eupgrade.set_workdir("/tmp/mesh_upgrade") +-- should epgrade be disabled ? +-- eupgrade.set_workdir("/tmp/mesh_upgrade") -- Get the base url for the firmware repository in this node function mesh_upgrade.get_repo_base_url() @@ -59,13 +62,13 @@ end function mesh_upgrade.set_workdir(workdir) mesh_upgrade._create_workdir(workdir) mesh_upgrade.WORKDIR = workdir - mesh_upgrade.LATEST_JSON_FILE_NAME = eupgrade._get_board_name()..".json" -- latest json with local lan url file name + mesh_upgrade.LATEST_JSON_FILE_NAME = eupgrade._get_board_name() .. ".json" -- latest json with local lan url file name mesh_upgrade.LATEST_JSON_PATH = mesh_upgrade.WORKDIR .. "/" .. mesh_upgrade.LATEST_JSON_FILE_NAME -- latest json full path mesh_upgrade.FIRMWARE_REPO_PATH = '/lros/' -- path url for firmwares mesh_upgrade.FIRMWARE_SHARED_FOLDER = '/www/' .. mesh_upgrade.FIRMWARE_REPO_PATH end -mesh_upgrade.set_workdir("/tmp/mesh_upgrade") +mesh_upgrade.set_workdir("/tmp/mesh_upgrade") function mesh_upgrade.start_eupgrade_download() local cached_only = false @@ -83,7 +86,7 @@ end function mesh_upgrade.create_local_latest_json(latest_data) for _, im in pairs(latest_data['images']) do - --im['download-urls'] = string.gsub(im['download-urls'], upgrade_url, "test") + -- im['download-urls'] = string.gsub(im['download-urls'], upgrade_url, "test") im['download-urls'] = {mesh_upgrade.get_repo_base_url() .. im['name']} end utils.write_file(mesh_upgrade.LATEST_JSON_PATH, json.stringify(latest_data)) @@ -91,15 +94,15 @@ function mesh_upgrade.create_local_latest_json(latest_data) end function mesh_upgrade.share_firmware_packages(dest) - if dest == nil then + if dest == nil then dest = "/www" .. mesh_upgrade.FIRMWARE_REPO_PATH end local images_folder = eupgrade.WORKDIR mesh_upgrade._create_workdir(dest) - --json file has to be placed in a url that ends with latest - mesh_upgrade._create_workdir(dest.."/latest") + -- json file has to be placed in a url that ends with latest + mesh_upgrade._create_workdir(dest .. "/latest") os.execute("ln -s " .. images_folder .. "/* " .. dest) - os.execute("ln -s " .. mesh_upgrade.LATEST_JSON_PATH .. " " .. dest.. "/latest") + os.execute("ln -s " .. mesh_upgrade.LATEST_JSON_PATH .. " " .. dest .. "/latest") end -- This function will download latest librerouter os firmware and expose it as @@ -116,7 +119,6 @@ function mesh_upgrade.set_up_firmware_repository() else utils.log("no new version available") end - end -- Function that check if tihs node have all things needed to became a master node @@ -127,44 +129,72 @@ function mesh_upgrade.become_master_node() -- Check if there are a new version available (cached only) local latest = eupgrade.is_new_version_available(true) if not latest then - return { code = "NO_NEW_VERSION", error = "No new version is available"} + return { + code = "NO_NEW_VERSION", + error = "No new version is available" + } end -- Check download is completed if download_status == eupgrade.STATUS_DEFAULT then - return { code = download_status, error = "Firmware download not started" } + return { + code = download_status, + error = "Firmware download not started" + } elseif download_status == eupgrade.STATUS_DOWNLOADING then - return { code = download_status, error = "Firmware is downloading"} + return { + code = download_status, + error = "Firmware is downloading" + } elseif download_status == eupgrade.STATUS_DOWNLOAD_FAILED then - return { code = download_status, error = "Firmware download failed"} + return { + code = download_status, + error = "Firmware download failed" + } end -- 3. Expose eupgrade folder to uhttp (this is the best place to do it since -- all the files are present) mesh_upgrade.share_firmware_packages() -- Check if local json file exists if not utils.file_exists(mesh_upgrade.LATEST_JSON_PATH) then - return { code = "NO_LOCAL_JSON", error = "Local json file not found"} + return { + code = "NO_LOCAL_JSON", + error = "Local json file not found" + } end -- Check firmware packages are shared properly -- we could check if the shared folder is empty or not and what files are present. Not needed imho if not utils.file_exists(mesh_upgrade.FIRMWARE_SHARED_FOLDER) then - return { code = "NO_SHARED_FOLDER", error = "Shared folder not found"} + return { + code = "NO_SHARED_FOLDER", + error = "Shared folder not found" + } end -- If we get here is supposed that everything is ready to be a master node mesh_upgrade.inform_download_location(latest['version']) - return { code = "SUCCESS"} + return { + code = "SUCCESS" + } end -- Shared state functions -- ---------------------------- +function mesh_upgrade.report_error(error) + local uci = config.get_uci_cursor() + uci:set('mesh-upgrade', 'main', 'error', error) + uci:set('mesh-upgrade', 'main', 'timestamp', os.time()) + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') + -- trigger shared state data refresh + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR) +end -- function to be called by nodes to start download from master. function mesh_upgrade.start_node_download(url) - local uci = config.get_uci_cursor() eupgrade.set_custom_api_url(url) local cached_only = false local url2 = eupgrade.get_upgrade_api_url() local latest_data, message = eupgrade.is_new_version_available(cached_only) - utils.log("start_node_download from "..url2) + utils.log("start_node_download from " .. url2) if latest_data then utils.log("start_node_download ") @@ -172,20 +202,17 @@ function mesh_upgrade.start_node_download(url) utils.log("downloading") local image = {} image, mesh_upgrade.fw_path = eupgrade.download_firmware(latest_data) - uci:set('mesh-upgrade', 'main', 'eup_STATUS', eupgrade.get_download_status()) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED and image ~= nil then utils.printJson(image) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) else - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR) - -- todo: how to handle this error + utils.log("Error ... download failed") + mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) end else utils.log("Error ... no latest data available") - - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR) + mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) end - mesh_upgrade.trigger_sheredstate_publish() end -- this function will be called by the master node to inform that the firmware is available @@ -194,22 +221,16 @@ end -- curl -6 'http://[fd0d:fe46:8ce8::1]/lros/api/v1/' function mesh_upgrade.inform_download_location(version) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED then - --TODO: setup uhttpd to serve workdir location + -- TODO: setup uhttpd to serve workdir location mesh_upgrade.set_mesh_upgrade_info({ - type = "upgrade", - data = { - firmware_ver = version, - repo_url = mesh_upgrade.get_repo_base_url(), - upgrde_state = mesh_upgrade.upgrade_states.READY_FOR_UPGRADE, - error = 0, - safe_upgrade_status = "", - eup_STATUS = eupgrade.STATUS_DOWNLOADED - }, - timestamp = os.time(), - id = 21, -- todo: create a unique hash - transaction_state = mesh_upgrade.transaction_states.STARTED, - master_node = utils.hostname() - }, mesh_upgrade.upgrade_states.READY_FOR_UPGRADE, mesh_upgrade.transaction_states.STARTED) + candidate_fw = version, + repo_url = mesh_upgrade.get_repo_base_url(), + upgrde_state = mesh_upgrade.upgrade_states.READY_FOR_UPGRADE, + error = "", + master_node = true, + board_name = eupgrade._get_board_name(), + current_fw = eupgrade._get_current_fw_version() + }, mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) else utils.log("eupgrade STATUS is not 'DOWNLOADED'") end @@ -218,8 +239,14 @@ end -- Validate if the upgrade has already started function mesh_upgrade.started() local uci = config.get_uci_cursor() - return uci:get('mesh-upgrade', 'main', 'transaction_state') == mesh_upgrade.transaction_states.STARTED - -- todo: what happens if a mesh_upgrade has started more than an hour ago ? should this node abort it ? + local status = uci:get('mesh-upgrade', 'main', 'transaction_state') + if status == mesh_upgrade.upgrade_states.STARTING or status == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING or + status == mesh_upgrade.upgrade_states.CONFIRMED or status == mesh_upgrade.upgrade_states.DOWNLOADING or status == + mesh_upgrade.upgrade_states.READY_FOR_UPGRADE or status == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then + return true + end + return false + -- todo(javi): what happens if a mesh_upgrade has started more than an hour ago ? should this node abort it ? end function mesh_upgrade.state() @@ -228,12 +255,9 @@ function mesh_upgrade.state() end function mesh_upgrade.mesh_upgrade_abort() - local uci = config.get_uci_cursor() - uci:set('mesh-upgrade', 'main', 'transaction_state', mesh_upgrade.transaction_states.ABORTED) - uci:save('mesh-upgrade') - uci:commit('mesh-upgrade') - -- stop and delete everything - -- trigger a shared state publish + mesh_upgrade.report_error(mesh_upgrade.errors.ABORTED) + -- todo(javi): stop and delete everything + end -- This line will genereate recursive dependencies like in pirania pakcage @@ -245,48 +269,49 @@ end -- ! changes the state of the upgrade and verifies that state transition is possible. function mesh_upgrade.change_state(newstate, errortype) local uci = config.get_uci_cursor() - if newstate == mesh_upgrade.upgrade_states.STARTING and - (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DEFAULT or mesh_upgrade.state() == + if newstate == mesh_upgrade.upgrade_states.STARTING then + if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DEFAULT or mesh_upgrade.state() == mesh_upgrade.upgrade_states.ERROR or mesh_upgrade.state() == mesh_upgrade.upgrade_states.UPDATED) then - -- trigger firmware download from master_node url - uci:set('mesh-upgrade', 'main', 'upgrade_state', newstate) - uci:save('mesh-upgrade') - uci:commit('mesh-upgrade') - return true + else + return false + end end - -- todo: verify other states - -- lets allow all types of state changes. + -- todo(javi): verify other states and return false if it is not possible + + -- lets allow all types of state changes. uci:set('mesh-upgrade', 'main', 'upgrade_state', newstate) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') + mesh_upgrade.trigger_sheredstate_publish() return true end +function mesh_upgrade.become_bot_node(upgrade_data) + upgrade_data.master_node = false + mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.STARTING) + if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.STARTING) then + mesh_upgrade.start_node_download(upgrade_data.repo_url) + end +end + -- set download information for the new firmware from master node --- Called by a shared state hook in non master nodes -function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state, transaction_state) +-- Called by a shared state hook in bot nodes +function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state) local uci = config.get_uci_cursor() - if string.match(upgrade_data.data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil -- perform aditional checks + if string.match(upgrade_data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil -- todo (javi): perform aditional checks then utils.log("seting up repo download info ") if (mesh_upgrade.change_state(upgrade_state)) then uci:set('mesh-upgrade', 'main', "mesh-upgrade") - uci:set('mesh-upgrade', 'main', 'id', upgrade_data.id) - uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.data.repo_url) - uci:set('mesh-upgrade', 'main', 'firmware_ver', upgrade_data.data.firmware_ver) - -- uci:set('mesh-upgrade', 'main', 'upgrade_state', upgrade_state) already done in change state - uci:set('mesh-upgrade', 'main', 'error', 0) + uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.repo_url) + uci:set('mesh-upgrade', 'main', 'candidate_fw', upgrade_data.candidate_fw) + uci:set('mesh-upgrade', 'main', 'error', "") uci:set('mesh-upgrade', 'main', 'timestamp', os.time()) - uci:set('mesh-upgrade', 'main', 'master_node', upgrade_data.master_node) - uci:set('mesh-upgrade', 'main', 'transaction_state', - transaction_state or mesh_upgrade.transaction_states.STARTED) + uci:set('mesh-upgrade', 'main', 'master_node', tostring(upgrade_data.master_node)) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') -- trigger shared state data refresh mesh_upgrade.trigger_sheredstate_publish() - if (upgrade_state == mesh_upgrade.upgrade_states.STARTING) then - mesh_upgrade.start_node_download(upgrade_data.data.repo_url) - end else utils.log("invalid state change ") end @@ -295,54 +320,42 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state, transac end end --- --- { --- type= "upgrade", --- data={ --- firmware_ver="xxxx", --- repo_url="http://10.13.0.1/lros/api/v1/", --- upgrde_state="starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", --- error="CODE", --- safe_upgrade_status="", --- eup_STATUS="",eup.STATUS_DEFAULT = 'not-initiated' eup.STATUS_DOWNLOADING = 'downloading' eup.STATUS_DOWNLOADED = 'downloaded' eup.STATUS_DOWNLOAD_FAILED = 'download-failed' --- }, --- timestamp=231354654, --- id="", --- transaction_state="started/aborted/finished", --- master_node="" --- } --- +function mesh_upgrade.toboolean(str) + if str == "true" then + return true + end + return false +end -- ! Read status from UCI function mesh_upgrade.get_mesh_upgrade_status() local uci = config.get_uci_cursor() local upgrade_data = {} - upgrade_data.data = {} - upgrade_data.type = "upgrade" - upgrade_data.id = uci:get('mesh-upgrade', 'main', 'id') - upgrade_data.data.firmware_ver = uci:get('mesh-upgrade', 'main', 'firmware_ver') - upgrade_data.data.repo_url = uci:get('mesh-upgrade', 'main', 'repo_url') - upgrade_data.data.upgrade_state = uci:get('mesh-upgrade', 'main', 'upgrade_state') - upgrade_data.data.error = uci:get('mesh-upgrade', 'main', 'error') - upgrade_data.data.safe_upgrade_status = uci:get('mesh-upgrade', 'main', 'safe_upgrade_status') - upgrade_data.data.eup_STATUS = uci:get('mesh-upgrade', 'main', 'eup_STATUS') - upgrade_data.timestamp = uci:get('mesh-upgrade', 'main', 'timestamp') - upgrade_data.master_node = uci:get('mesh-upgrade', 'main', 'master_node') - upgrade_data.transaction_state = uci:get('mesh-upgrade', 'main', 'transaction_state') - if (upgrade_data.transaction_state == nil) then - uci:set('mesh-upgrade', 'main', 'transaction_state', mesh_upgrade.transaction_states.NO_TRANSACTION) - upgrade_data.transaction_state = uci:get('mesh-upgrade', 'main', 'transaction_state') + upgrade_data.candidate_fw = uci:get('mesh-upgrade', 'main', 'candidate_fw') + upgrade_data.repo_url = uci:get('mesh-upgrade', 'main', 'repo_url') + upgrade_data.upgrade_state = uci:get('mesh-upgrade', 'main', 'upgrade_state') + if (upgrade_data.upgrade_state == nil) then + uci:set('mesh-upgrade', 'main', 'transaction_state', mesh_upgrade.upgrade_states.DEFAULT) + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') + upgrade_data.upgrade_state = uci:get('mesh-upgrade', 'main', 'transaction_state') end + upgrade_data.error = uci:get('mesh-upgrade', 'main', 'error') + upgrade_data.timestamp = uci:get('mesh-upgrade', 'main', 'timestamp') + upgrade_data.master_node = mesh_upgrade.toboolean(uci:get('mesh-upgrade', 'main', 'master_node')) + upgrade_data.board_name = eupgrade._get_board_name() + upgrade_data.current_fw = eupgrade._get_current_fw_version() return upgrade_data end function mesh_upgrade.start_safe_upgrade() if mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHELUDED) and utils.file_exists(mesh_upgrade.fw_path) then - -- perform safe upgrade + -- perform safe upgrade + return true else - utils.log ("not able to start upgrade invalid state or firmware not found") - mesh_upgrade.change_state( mesh_upgrade.upgrade_states.ERROR) + utils.log("not able to start upgrade invalid state or firmware not found") + return false end end diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/testmaster.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/testmaster.lua deleted file mode 100644 index b7099899d..000000000 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/testmaster.lua +++ /dev/null @@ -1,33 +0,0 @@ -local lime_mesh_upgrade = require 'lime-mesh-upgrade' -local eupgrade = require 'eupgrade' - -local network = require("lime.network") -print (tostring(network.primary_address())) - -print(tostring(eupgrade.get_upgrade_api_url())) - -local utils = require "lime.utils" -os.execute('echo librerouter-v1 > /tmp/sysinfo/board_name') - - -print(eupgrade._get_board_name()) - -eupgrade.set_custom_api_url('http://repo.librerouter.org/lros/api/v1/') -print(tostring(eupgrade.get_upgrade_api_url())) - -print(tostring(eupgrade.is_new_version_available())) -lime_mesh_upgrade.set_up_firmware_repository() -utils.printJson(lime_mesh_upgrade.become_master_node()) - -os.execute("sleep " .. tonumber(6)) - -utils.printJson(lime_mesh_upgrade.become_master_node()) - -os.execute("sleep " .. tonumber(6)) - -utils.printJson(lime_mesh_upgrade.become_master_node()) - -os.execute("sleep " .. tonumber(20)) - -utils.printJson(lime_mesh_upgrade.become_master_node()) - diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index a65ea96c0..b6a015bee 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -23,20 +23,13 @@ end local uci local upgrade_data = { - type = "upgrade", - data = { - firmware_ver = "xxxx", + candidate_fw = "xxxx", repo_url = "http://repo.librerouter.org/lros/api/v1/latest/", upgrde_state = "starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", error = "CODE", - safe_upgrade_status = "", - eup_STATUS = "" - }, - timestamp=231354654, - id=21, - transaction_state="started/aborted/finished", - master_node="primero" -} + master_node="true", + current_fw="LibreRouterOs 1.5 r0+11434-e93615c947", + board_name = "qemu-standard-pc-i440fx-piix-1996"} local latest_release_data = [[ { @@ -103,8 +96,14 @@ describe('LiMe mesh upgrade', function() it('test get mesh config fresh start', function() config.log("\n test set mesh config.... \n") + stub(eupgrade, '_get_board_name', function() + return 'test-board' + end) + stub(eupgrade, '_get_current_fw_version', function() + return 'LibreMesh 19.05' + end) local status = lime_mesh_upgrade.get_mesh_upgrade_status() - assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.NO_TRANSACTION) + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.DEFAULT) assert.is.equal(lime_mesh_upgrade.started(), false) end) @@ -126,22 +125,30 @@ describe('LiMe mesh upgrade', function() end) assert.is.equal('LibreRouterOs 1.5', eupgrade.is_new_version_available()['version']) - lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data, lime_mesh_upgrade.upgrade_states.STARTING) stub(eupgrade, '_get_board_name', function () return 'test-board' end) stub(eupgrade, '_get_current_fw_version', function () return 'LibreMesh 1.4' end) stub(eupgrade, '_check_signature', function () return true end) stub(utils, 'http_client_get', function () return latest_release_data end) assert.is.equal('LibreRouterOs 1.5', eupgrade.is_new_version_available()['version']) - lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data,lime_mesh_upgrade.upgrade_states.STARTING) + lime_mesh_upgrade.report_error(lime_mesh_upgrade.errors.CONFIRMATION_TIME_OUT) status = lime_mesh_upgrade.get_mesh_upgrade_status() - assert.is.equal(status.master_node, upgrade_data.master_node) - assert.is.equal(status.data.repo_url, upgrade_data.data.repo_url) - assert.is.equal(status.data.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) - assert.is.equal(status.data.eup_STATUS, eupgrade.STATUS_DOWNLOAD_FAILED) - assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) - -- assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.ABORTED) - -- TODO: javi en caso de falla ... reintentar ? abortar ? + assert.is.equal(status.error, lime_mesh_upgrade.errors.CONFIRMATION_TIME_OUT) + + lime_mesh_upgrade.mesh_upgrade_abort() + status = lime_mesh_upgrade.get_mesh_upgrade_status() + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) + assert.is.equal(status.error, lime_mesh_upgrade.errors.ABORTED) + + lime_mesh_upgrade.become_bot_node(upgrade_data) + status = lime_mesh_upgrade.get_mesh_upgrade_status() + assert.is.Not(status.master_node, false) + assert.is.equal(status.repo_url, upgrade_data.repo_url) + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) + assert.is.equal(status.error, lime_mesh_upgrade.errors.DOWNLOAD_FAILED) + --assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) + --assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.ABORTED) + --TODO: javi en caso de falla ... reintentar ? abortar ? end) it('test set mesh config start download and assert status ready_for_upgrade', function() stub(eupgrade, '_get_board_name', function() @@ -161,14 +168,14 @@ describe('LiMe mesh upgrade', function() end) assert.is.equal('LibreRouterOs 1.5', eupgrade.is_new_version_available()['version']) - lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data, lime_mesh_upgrade.upgrade_states.STARTING) + lime_mesh_upgrade.become_bot_node(upgrade_data) status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) assert.is.equal(status.master_node, upgrade_data.master_node) - assert.is.equal(status.data.repo_url, upgrade_data.data.repo_url) - assert.is.equal(status.data.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) - assert.is.equal(status.data.eup_STATUS, eupgrade.STATUS_DOWNLOADED) - assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) + assert.is.equal(status.repo_url, upgrade_data.repo_url) + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) + --assert.is.equal(status.data.eup_STATUS, eupgrade.STATUS_DOWNLOADED) + --assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) end) it('test set mesh config start download and assert status ready_for_upgrade', function() @@ -207,14 +214,14 @@ describe('LiMe mesh upgrade', function() return true end) - lime_mesh_upgrade.set_mesh_upgrade_info(upgrade_data, lime_mesh_upgrade.upgrade_states.STARTING) + lime_mesh_upgrade.become_bot_node(upgrade_data) status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) assert.is.equal(status.master_node, upgrade_data.master_node) - assert.is.equal(status.data.repo_url, upgrade_data.data.repo_url) - assert.is.equal(status.data.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) - assert.is.equal(status.data.eup_STATUS, eupgrade.STATUS_DOWNLOADED) - assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) + assert.is.equal(status.repo_url, upgrade_data.repo_url) + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) + --assert.is.equal(status.eup_STATUS, eupgrade.STATUS_DOWNLOADED) + --assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) end) it('test custom latest json file is created', function() diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade index 6c40009a6..2bcd25408 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -26,14 +26,13 @@ if not mesh_upgrade.started() then for node, s_s_data in pairs(JSON.parse(io.stdin:read("*all"))) do --if any node has started an upgrade process and start one too? --only fetch the info from the master node publication? - if node ~= hostname and s_s_data.data.master_node == node then + if node ~= hostname and s_s_data.data.master_node then utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from "' .. s_s_data.data.data.repo_url .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) - - mesh_upgrade.set_mesh_upgrade_info(s_s_data.data,mesh_upgrade.upgrade_states.STARTING) + mesh_upgrade.become_bot_node(s_s_data.data) else utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "status "' .. - JSON.stringify(s_s_data.data) .. " from node " .. node) + JSON.stringify(s_s_data.data) .. " from node " .. node) end end else diff --git a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade index cef531948..b9ad56594 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade @@ -24,7 +24,6 @@ local mesh_upgrade = require "lime-mesh-upgrade" local hostname = utils.hostname() function report_upgrade_status() - --todo: get data from libmeshupgrade and send return mesh_upgrade.get_mesh_upgrade_status() end From cfb0306416c361dc36a4cbf89165a9179a5aff01 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Tue, 16 Jan 2024 10:15:45 -0300 Subject: [PATCH 033/102] fixes ready for upgrade simulation for x86 --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 57 +++++++++++++++---- .../hooks/mesh_wide_upgrade/start_upgrade | 2 +- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index c15e42af4..3e2b8248e 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -17,7 +17,7 @@ local mesh_upgrade = { }, -- psible upgrade states enumeration upgrade_states = { - DEFAULT = "not upgrading", -- When no transaction has started + DEFAULT = "not_upgrading", -- When no upgrade has started, after reboot STARTING = "starting", DOWNLOADING = "downloading", READY_FOR_UPGRADE = "ready_for_upgrade", @@ -127,15 +127,20 @@ function mesh_upgrade.become_master_node() -- todo(kon): check if master node is already set or we are on mesh_upgrade status local download_status = eupgrade.get_download_status() -- Check if there are a new version available (cached only) + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) local latest = eupgrade.is_new_version_available(true) if not latest then + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DEFAULT) return { code = "NO_NEW_VERSION", error = "No new version is available" } end + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) -- Check download is completed if download_status == eupgrade.STATUS_DEFAULT then + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR,mesh_upgrade.errors.DOWNLOAD_FAILED) + return { code = download_status, error = "Firmware download not started" @@ -146,6 +151,7 @@ function mesh_upgrade.become_master_node() error = "Firmware is downloading" } elseif download_status == eupgrade.STATUS_DOWNLOAD_FAILED then + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR,mesh_upgrade.errors.DOWNLOAD_FAILED) return { code = download_status, error = "Firmware download failed" @@ -156,6 +162,8 @@ function mesh_upgrade.become_master_node() mesh_upgrade.share_firmware_packages() -- Check if local json file exists if not utils.file_exists(mesh_upgrade.LATEST_JSON_PATH) then + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR,mesh_upgrade.errors.NO_LATEST_AVAILABLE) + return { code = "NO_LOCAL_JSON", error = "Local json file not found" @@ -202,9 +210,13 @@ function mesh_upgrade.start_node_download(url) utils.log("downloading") local image = {} image, mesh_upgrade.fw_path = eupgrade.download_firmware(latest_data) + utils.log(image) + utils.log(mesh_upgrade.fw_path) + utils.log(latest_data) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED and image ~= nil then utils.printJson(image) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) + mesh_upgrade.trigger_sheredstate_publish() else utils.log("Error ... download failed") mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) @@ -238,13 +250,13 @@ end -- Validate if the upgrade has already started function mesh_upgrade.started() - local uci = config.get_uci_cursor() - local status = uci:get('mesh-upgrade', 'main', 'transaction_state') + status = mesh_upgrade.state() if status == mesh_upgrade.upgrade_states.STARTING or status == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING or status == mesh_upgrade.upgrade_states.CONFIRMED or status == mesh_upgrade.upgrade_states.DOWNLOADING or status == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE or status == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then return true end + utils.log(" started returned false !!! ") return false -- todo(javi): what happens if a mesh_upgrade has started more than an hour ago ? should this node abort it ? end @@ -269,10 +281,30 @@ end -- ! changes the state of the upgrade and verifies that state transition is possible. function mesh_upgrade.change_state(newstate, errortype) local uci = config.get_uci_cursor() + utils.log("changing from " .. mesh_upgrade.state() .. " to " .. newstate) if newstate == mesh_upgrade.upgrade_states.STARTING then if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DEFAULT or mesh_upgrade.state() == mesh_upgrade.upgrade_states.ERROR or mesh_upgrade.state() == mesh_upgrade.upgrade_states.UPDATED) then + utils.log("ok to start") + else + utils.log("invalid state change not able to start") + + return false + end + end + if newstate == mesh_upgrade.upgrade_states.DOWNLOADING then + if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.STARTING) then + utils.log("ok to download") + else + utils.log("invalid statechange not able to star t") + return false + end + end + if newstate == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then + if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DOWNLOADING) then + utils.log("ok to be ready") else + utils.log("invalid statechange no able to be ready") return false end end @@ -282,15 +314,20 @@ function mesh_upgrade.change_state(newstate, errortype) uci:set('mesh-upgrade', 'main', 'upgrade_state', newstate) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') - mesh_upgrade.trigger_sheredstate_publish() return true end function mesh_upgrade.become_bot_node(upgrade_data) - upgrade_data.master_node = false - mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.STARTING) - if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.STARTING) then - mesh_upgrade.start_node_download(upgrade_data.repo_url) + if mesh_upgrade.started() then + utils.log("already a bot node") + else + utils.log("transfoming into a bot node") + upgrade_data.master_node = false + mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.STARTING) + if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.STARTING) then + mesh_upgrade.trigger_sheredstate_publish() + mesh_upgrade.start_node_download(upgrade_data.repo_url) + end end end @@ -300,7 +337,7 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state) local uci = config.get_uci_cursor() if string.match(upgrade_data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil -- todo (javi): perform aditional checks then - utils.log("seting up repo download info ") + utils.log("seting up repo download info to " .. upgrade_state .. " actual " .. mesh_upgrade.state()) if (mesh_upgrade.change_state(upgrade_state)) then uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.repo_url) @@ -342,7 +379,7 @@ function mesh_upgrade.get_mesh_upgrade_status() end upgrade_data.error = uci:get('mesh-upgrade', 'main', 'error') upgrade_data.timestamp = uci:get('mesh-upgrade', 'main', 'timestamp') - upgrade_data.master_node = mesh_upgrade.toboolean(uci:get('mesh-upgrade', 'main', 'master_node')) + upgrade_data.master_node = mesh_upgrade.toboolean(uci:get('mesh-upgrade', 'main', 'master_node')) upgrade_data.board_name = eupgrade._get_board_name() upgrade_data.current_fw = eupgrade._get_current_fw_version() return upgrade_data diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade index 2bcd25408..086010906 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -28,7 +28,7 @@ if not mesh_upgrade.started() then --only fetch the info from the master node publication? if node ~= hostname and s_s_data.data.master_node then utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from "' .. - s_s_data.data.data.repo_url .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) + s_s_data.data.repo_url .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) mesh_upgrade.become_bot_node(s_s_data.data) else utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "status "' .. From a6467f77f44b7b43251fe90ebb415686c64aa374 Mon Sep 17 00:00:00 2001 From: selankon Date: Mon, 22 Jan 2024 16:46:29 +0100 Subject: [PATCH 034/102] Refactor set_up_local_repository --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 27 ++++++------------- .../usr/libexec/rpcd/lime-mesh-upgrade.lua | 6 ++--- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 3e2b8248e..5d8d739f5 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -70,20 +70,6 @@ end mesh_upgrade.set_workdir("/tmp/mesh_upgrade") -function mesh_upgrade.start_eupgrade_download() - local cached_only = false - local latest_data = eupgrade.is_new_version_available(cached_only) - if latest_data then - utils.execute_daemonized("eupgrade-download") - else - ret = { - status = 'error', - message = 'New version is not availabe' - } - end - return latest_data -end - function mesh_upgrade.create_local_latest_json(latest_data) for _, im in pairs(latest_data['images']) do -- im['download-urls'] = string.gsub(im['download-urls'], upgrade_url, "test") @@ -107,17 +93,20 @@ end -- This function will download latest librerouter os firmware and expose it as -- a local repository in order to be used for other nodes -function mesh_upgrade.set_up_firmware_repository() +function mesh_upgrade.set_up_local_repository() -- 1. Check if new version is available and download it demonized using eupgrade - local latest_data = mesh_upgrade.start_eupgrade_download() + local cached_only = false + local latest_data = eupgrade.is_new_version_available(cached_only) if latest_data then -- 2. Create local repository json data mesh_upgrade.create_local_latest_json(latest_data) - -- 3. Expose eupgrade folder to uhttp - -- mesh_upgrade.share_firmware_packages() - -- do not do it here since the download may fail. + utils.execute_daemonized("eupgrade-download") else utils.log("no new version available") + return { + status = 'error', + message = 'New version is not availabe' + } end end diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua index 2595b6232..b57ba8116 100755 --- a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua @@ -9,8 +9,8 @@ local json = require 'luci.jsonc' local mesh_upgrade = require 'lime-mesh-upgrade' -local function set_up_firmware_repository(msg) - local result = mesh_upgrade.set_up_firmware_repository(msg) +local function set_up_local_repository(msg) + local result = mesh_upgrade.set_up_local_repository(msg) return utils.printJson(result) end @@ -29,7 +29,7 @@ if arg[1] == 'list' then utils.printJson(methods) end if arg[1] == 'call' then local msg = utils.rpcd_readline() msg = json.parse(msg) - if arg[2] == 'set_up_firmware_repository' then set_up_firmware_repository(msg) + if arg[2] == 'set_up_local_repository' then set_up_local_repository(msg) elseif arg[2] == 'become_master_node' then become_master_node(msg) else utils.printJson({ error = "Method not found" }) end From 5f2938c4579b6ce61280e113ede9757d6c9f9135 Mon Sep 17 00:00:00 2001 From: selankon Date: Mon, 22 Jan 2024 17:15:30 +0100 Subject: [PATCH 035/102] Eliminate divisive language --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 25 +++++++++---------- .../usr/libexec/rpcd/lime-mesh-upgrade.lua | 6 ++--- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 5d8d739f5..91806ee72 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -37,7 +37,6 @@ local mesh_upgrade = { }, fw_path = "", su_timeout = 600, - MASTERNODE_ENDPOINT = "/lros/api/v1/" } -- should epgrade be disabled ? @@ -76,7 +75,7 @@ function mesh_upgrade.create_local_latest_json(latest_data) im['download-urls'] = {mesh_upgrade.get_repo_base_url() .. im['name']} end utils.write_file(mesh_upgrade.LATEST_JSON_PATH, json.stringify(latest_data)) - -- For the moment mesh upgrade will ignore the latest json signature on de master nodes + -- For the moment mesh upgrade will ignore the latest json signature on de main nodes end function mesh_upgrade.share_firmware_packages(dest) @@ -110,10 +109,10 @@ function mesh_upgrade.set_up_local_repository() end end --- Function that check if tihs node have all things needed to became a master node +-- Function that check if tihs node have all things needed to became a main node -- Then, call update shared state with the proper info -function mesh_upgrade.become_master_node() - -- todo(kon): check if master node is already set or we are on mesh_upgrade status +function mesh_upgrade.become_main_node() + -- todo(kon): check if main node is already set or we are on mesh_upgrade status local download_status = eupgrade.get_download_status() -- Check if there are a new version available (cached only) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) @@ -166,7 +165,7 @@ function mesh_upgrade.become_master_node() error = "Shared folder not found" } end - -- If we get here is supposed that everything is ready to be a master node + -- If we get here is supposed that everything is ready to be a main node mesh_upgrade.inform_download_location(latest['version']) return { code = "SUCCESS" @@ -185,7 +184,7 @@ function mesh_upgrade.report_error(error) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR) end --- function to be called by nodes to start download from master. +-- function to be called by nodes to start download from main. function mesh_upgrade.start_node_download(url) eupgrade.set_custom_api_url(url) local cached_only = false @@ -216,7 +215,7 @@ function mesh_upgrade.start_node_download(url) end end --- this function will be called by the master node to inform that the firmware is available +-- this function will be called by the main node to inform that the firmware is available -- also will force shared state data refresh -- curl -6 'http://[fe80::a8aa:aaff:fe0d:feaa%lime_br0]/fw/resolv.conf' -- curl -6 'http://[fd0d:fe46:8ce8::1]/lros/api/v1/' @@ -228,7 +227,7 @@ function mesh_upgrade.inform_download_location(version) repo_url = mesh_upgrade.get_repo_base_url(), upgrde_state = mesh_upgrade.upgrade_states.READY_FOR_UPGRADE, error = "", - master_node = true, + main_node = true, board_name = eupgrade._get_board_name(), current_fw = eupgrade._get_current_fw_version() }, mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) @@ -311,7 +310,7 @@ function mesh_upgrade.become_bot_node(upgrade_data) utils.log("already a bot node") else utils.log("transfoming into a bot node") - upgrade_data.master_node = false + upgrade_data.main_node = false mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.STARTING) if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.STARTING) then mesh_upgrade.trigger_sheredstate_publish() @@ -320,7 +319,7 @@ function mesh_upgrade.become_bot_node(upgrade_data) end end --- set download information for the new firmware from master node +-- set download information for the new firmware from main node -- Called by a shared state hook in bot nodes function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state) local uci = config.get_uci_cursor() @@ -333,7 +332,7 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state) uci:set('mesh-upgrade', 'main', 'candidate_fw', upgrade_data.candidate_fw) uci:set('mesh-upgrade', 'main', 'error', "") uci:set('mesh-upgrade', 'main', 'timestamp', os.time()) - uci:set('mesh-upgrade', 'main', 'master_node', tostring(upgrade_data.master_node)) + uci:set('mesh-upgrade', 'main', 'main_node', tostring(upgrade_data.main_node)) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') -- trigger shared state data refresh @@ -368,7 +367,7 @@ function mesh_upgrade.get_mesh_upgrade_status() end upgrade_data.error = uci:get('mesh-upgrade', 'main', 'error') upgrade_data.timestamp = uci:get('mesh-upgrade', 'main', 'timestamp') - upgrade_data.master_node = mesh_upgrade.toboolean(uci:get('mesh-upgrade', 'main', 'master_node')) + upgrade_data.main_node = mesh_upgrade.toboolean(uci:get('mesh-upgrade', 'main', 'main_node')) upgrade_data.board_name = eupgrade._get_board_name() upgrade_data.current_fw = eupgrade._get_current_fw_version() return upgrade_data diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua index b57ba8116..c8303145b 100755 --- a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua @@ -14,8 +14,8 @@ local function set_up_local_repository(msg) return utils.printJson(result) end -local function become_master_node(msg) - local result = mesh_upgrade.become_master_node(msg) +local function become_main_node(msg) + local result = mesh_upgrade.become_main_node(msg) return utils.printJson(result) end @@ -30,7 +30,7 @@ if arg[1] == 'call' then local msg = utils.rpcd_readline() msg = json.parse(msg) if arg[2] == 'set_up_local_repository' then set_up_local_repository(msg) - elseif arg[2] == 'become_master_node' then become_master_node(msg) + elseif arg[2] == 'become_main_node' then become_main_node(msg) else utils.printJson({ error = "Method not found" }) end end From 95e3e77fafcbde7b44071073e78ce33dea5e5f40 Mon Sep 17 00:00:00 2001 From: selankon Date: Tue, 23 Jan 2024 12:34:56 +0100 Subject: [PATCH 036/102] Split become_main_node 1. become_main_node - Start download - Create latest json 2. get_main_node_status - Get status of the main node eupgrade process 3. start_firmware_upgrade_transaction - Linkea los archivos al uhttp - Comprueba q este todo ok - llama a inform_download_location de shared state --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 37 ++++++++++--------- .../usr/libexec/rpcd/lime-mesh-upgrade.lua | 22 +++++++---- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 91806ee72..68cd41023 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -92,21 +92,10 @@ end -- This function will download latest librerouter os firmware and expose it as -- a local repository in order to be used for other nodes -function mesh_upgrade.set_up_local_repository() - -- 1. Check if new version is available and download it demonized using eupgrade - local cached_only = false - local latest_data = eupgrade.is_new_version_available(cached_only) - if latest_data then - -- 2. Create local repository json data - mesh_upgrade.create_local_latest_json(latest_data) - utils.execute_daemonized("eupgrade-download") - else - utils.log("no new version available") - return { - status = 'error', - message = 'New version is not availabe' - } - end +function mesh_upgrade.start_main_node_repository(latest_data) + -- Create local repository json data + mesh_upgrade.create_local_latest_json(latest_data) + utils.execute_daemonized("eupgrade-download") end -- Function that check if tihs node have all things needed to became a main node @@ -116,28 +105,36 @@ function mesh_upgrade.become_main_node() local download_status = eupgrade.get_download_status() -- Check if there are a new version available (cached only) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) - local latest = eupgrade.is_new_version_available(true) + -- 1. Check if new version is available and download it demonized using eupgrade + local latest = eupgrade.is_new_version_available(false) if not latest then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DEFAULT) + utils.log("no new version available") return { code = "NO_NEW_VERSION", error = "No new version is available" } end + -- 2. Start local repository and download latest firmware + mesh_upgrade.start_main_node_repository(latest) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) +end + +function mesh_upgrade.get_main_node_status() -- Check download is completed if download_status == eupgrade.STATUS_DEFAULT then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR,mesh_upgrade.errors.DOWNLOAD_FAILED) - return { code = download_status, error = "Firmware download not started" } + elseif download_status == eupgrade.STATUS_DOWNLOADING then return { code = download_status, error = "Firmware is downloading" } + elseif download_status == eupgrade.STATUS_DOWNLOAD_FAILED then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR,mesh_upgrade.errors.DOWNLOAD_FAILED) return { @@ -145,7 +142,11 @@ function mesh_upgrade.become_main_node() error = "Firmware download failed" } end - -- 3. Expose eupgrade folder to uhttp (this is the best place to do it since +end + +function mesh_upgrade.start_firmware_upgrade_transaction() + -- todo(kon): do all needed checks also with the main node state etc.. + -- Expose eupgrade folder to uhttp (this is the best place to do it since -- all the files are present) mesh_upgrade.share_firmware_packages() -- Check if local json file exists diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua index c8303145b..466fe8c16 100755 --- a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua @@ -9,19 +9,26 @@ local json = require 'luci.jsonc' local mesh_upgrade = require 'lime-mesh-upgrade' -local function set_up_local_repository(msg) - local result = mesh_upgrade.set_up_local_repository(msg) - return utils.printJson(result) -end local function become_main_node(msg) local result = mesh_upgrade.become_main_node(msg) return utils.printJson(result) end +local function get_main_node_status(msg) + local result = mesh_upgrade.get_main_node_status(msg) + return utils.printJson(result) +end + +local function start_firmware_upgrade_transaction(msg) + local result = mesh_upgrade.start_firmware_upgrade_transaction(msg) + return utils.printJson(result) +end + local methods = { - set_up_firmware_repository = {}, become_master_node = {}, + get_main_node_status = {}, + start_firmware_upgrade_transaction = {}, } if arg[1] == 'list' then utils.printJson(methods) end @@ -29,8 +36,9 @@ if arg[1] == 'list' then utils.printJson(methods) end if arg[1] == 'call' then local msg = utils.rpcd_readline() msg = json.parse(msg) - if arg[2] == 'set_up_local_repository' then set_up_local_repository(msg) - elseif arg[2] == 'become_main_node' then become_main_node(msg) + if arg[2] == 'become_main_node' then become_main_node(msg) + elseif arg[2] == 'get_main_node_status' then get_main_node_status(msg) + elseif arg[2] == 'start_firmware_upgrade_transaction' then start_firmware_upgrade_transaction(msg) else utils.printJson({ error = "Method not found" }) end end From ba73b058efd7dee967aad82b4d8387342d245f57 Mon Sep 17 00:00:00 2001 From: selankon Date: Tue, 23 Jan 2024 15:24:46 +0100 Subject: [PATCH 037/102] Fix main node status function --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 68cd41023..392369f39 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -15,7 +15,7 @@ local mesh_upgrade = { ABORTED = "aborted", FINISHED = "finished" }, - -- psible upgrade states enumeration + -- posible upgrade states enumeration upgrade_states = { DEFAULT = "not_upgrading", -- When no upgrade has started, after reboot STARTING = "starting", @@ -102,7 +102,6 @@ end -- Then, call update shared state with the proper info function mesh_upgrade.become_main_node() -- todo(kon): check if main node is already set or we are on mesh_upgrade status - local download_status = eupgrade.get_download_status() -- Check if there are a new version available (cached only) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) -- 1. Check if new version is available and download it demonized using eupgrade @@ -117,29 +116,35 @@ function mesh_upgrade.become_main_node() end -- 2. Start local repository and download latest firmware mesh_upgrade.start_main_node_repository(latest) - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) end function mesh_upgrade.get_main_node_status() + local download_status = eupgrade.get_download_status() -- Check download is completed if download_status == eupgrade.STATUS_DEFAULT then - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR,mesh_upgrade.errors.DOWNLOAD_FAILED) + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DEFAULT) return { - code = download_status, - error = "Firmware download not started" + code = mesh_upgrade.upgrade_states.DEFAULT, } elseif download_status == eupgrade.STATUS_DOWNLOADING then + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) + return { + code = mesh_upgrade.upgrade_states.STARTING, + } + + elseif download_status == eupgrade.DOWNLOADED then + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADED) return { - code = download_status, - error = "Firmware is downloading" + code = mesh_upgrade.upgrade_states.DOWNLOADED, } elseif download_status == eupgrade.STATUS_DOWNLOAD_FAILED then - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR,mesh_upgrade.errors.DOWNLOAD_FAILED) + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR, mesh_upgrade.errors.DOWNLOAD_FAILED) return { - code = download_status, - error = "Firmware download failed" + code = mesh_upgrade.upgrade_states.ERROR, + error = mesh_upgrade.errors.DOWNLOAD_FAILED } end end From 4aa81e8532df519cecc6d6bb93397250419e1483 Mon Sep 17 00:00:00 2001 From: selankon Date: Tue, 23 Jan 2024 16:13:07 +0100 Subject: [PATCH 038/102] Fix get_main_node_status and improve redeability --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 64 +++++++++---------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 392369f39..cabb8f976 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -10,21 +10,21 @@ local json = require 'luci.jsonc' local mesh_upgrade = { -- posible transaction states are derived from upgrade states transaction_states = { - NO_TRANSACTION = "no_transaction", - STARTED = "started", -- there is a transaction in progress - ABORTED = "aborted", - FINISHED = "finished" + NO_TRANSACTION = "NO_TRANSACTION", + STARTED = "STARTED", -- there is a transaction in progress + ABORTED = "ABORTED", + FINISHED = "FINISHED" }, -- posible upgrade states enumeration upgrade_states = { - DEFAULT = "not_upgrading", -- When no upgrade has started, after reboot - STARTING = "starting", - DOWNLOADING = "downloading", - READY_FOR_UPGRADE = "ready_for_upgrade", - UPGRADE_SCHEDULED = "upgrade_scheluded", - CONFIRMATION_PENDING = "confirmation_pending", - CONFIRMED = "confirmed", - ERROR = "error" + DEFAULT = "DEFAULT", -- When no upgrade has started, after reboot + STARTING = "STARTING", + DOWNLOADING = "DOWNLOADING", + READY_FOR_UPGRADE = "READY_FOR_UPGRADE", + UPGRADE_SCHEDULED = "UPGRADE_SCHEDULED", + CONFIRMATION_PENDING = "CONFIRMATION_PENDING", + CONFIRMED = "CONFIRMED", + ERROR = "ERROR" }, -- list of possible errors @@ -102,6 +102,7 @@ end -- Then, call update shared state with the proper info function mesh_upgrade.become_main_node() -- todo(kon): check if main node is already set or we are on mesh_upgrade status + -- todo(kon): dont start again if status is started and eupgrade is downloaded for example -- Check if there are a new version available (cached only) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) -- 1. Check if new version is available and download it demonized using eupgrade @@ -119,34 +120,23 @@ function mesh_upgrade.become_main_node() mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) end +-- Return eupgrade status for this node and update mesh upgrade status accordingly function mesh_upgrade.get_main_node_status() local download_status = eupgrade.get_download_status() + -- Check download is completed if download_status == eupgrade.STATUS_DEFAULT then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DEFAULT) - return { - code = mesh_upgrade.upgrade_states.DEFAULT, - } - elseif download_status == eupgrade.STATUS_DOWNLOADING then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) - return { - code = mesh_upgrade.upgrade_states.STARTING, - } - - elseif download_status == eupgrade.DOWNLOADED then - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADED) - return { - code = mesh_upgrade.upgrade_states.DOWNLOADED, - } - + elseif download_status == eupgrade.STATUS_DOWNLOADED then + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) elseif download_status == eupgrade.STATUS_DOWNLOAD_FAILED then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR, mesh_upgrade.errors.DOWNLOAD_FAILED) - return { - code = mesh_upgrade.upgrade_states.ERROR, - error = mesh_upgrade.errors.DOWNLOAD_FAILED - } end + return { + code = download_status, + } end function mesh_upgrade.start_firmware_upgrade_transaction() @@ -171,6 +161,7 @@ function mesh_upgrade.start_firmware_upgrade_transaction() error = "Shared folder not found" } end + local latest = eupgrade.is_new_version_available(true) -- If we get here is supposed that everything is ready to be a main node mesh_upgrade.inform_download_location(latest['version']) return { @@ -274,11 +265,16 @@ end -- ! changes the state of the upgrade and verifies that state transition is possible. function mesh_upgrade.change_state(newstate, errortype) + -- If the state is the same just return + if newstate == mesh_upgrade.state() then return false end + local uci = config.get_uci_cursor() utils.log("changing from " .. mesh_upgrade.state() .. " to " .. newstate) if newstate == mesh_upgrade.upgrade_states.STARTING then - if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DEFAULT or mesh_upgrade.state() == - mesh_upgrade.upgrade_states.ERROR or mesh_upgrade.state() == mesh_upgrade.upgrade_states.UPDATED) then + if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DEFAULT or + mesh_upgrade.state() == mesh_upgrade.upgrade_states.ERROR or + mesh_upgrade.state() == mesh_upgrade.upgrade_states.UPDATED) + then utils.log("ok to start") else utils.log("invalid state change not able to start") @@ -290,7 +286,7 @@ function mesh_upgrade.change_state(newstate, errortype) if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.STARTING) then utils.log("ok to download") else - utils.log("invalid statechange not able to star t") + utils.log("invalid state change not able to downloading") return false end end @@ -298,7 +294,7 @@ function mesh_upgrade.change_state(newstate, errortype) if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DOWNLOADING) then utils.log("ok to be ready") else - utils.log("invalid statechange no able to be ready") + utils.log("invalid state change no able to be ready") return false end end From ce16017359a75af1230519dc4021d91a43d52c85 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Tue, 23 Jan 2024 15:07:57 -0300 Subject: [PATCH 039/102] improves state changes --- .../files/etc/config/mesh-upgrade | 2 +- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 78 +++++++++++++++---- 2 files changed, 62 insertions(+), 18 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade index 22a0198e7..e6fe03b6f 100644 --- a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade @@ -2,7 +2,7 @@ config mesh-upgrade 'main' option firmware_ver '' option candidate_fw '' option repo_url '' - option upgrade_state 'DEFAULT' + option upgrade_state 'not_upgrading' option error '0' option timestamp '0' option master_node 'false' diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 3e2b8248e..ab70e36e2 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -105,7 +105,7 @@ function mesh_upgrade.share_firmware_packages(dest) os.execute("ln -s " .. mesh_upgrade.LATEST_JSON_PATH .. " " .. dest .. "/latest") end --- This function will download latest librerouter os firmware and expose it as +-- This function will download latest firmware and expose it as -- a local repository in order to be used for other nodes function mesh_upgrade.set_up_firmware_repository() -- 1. Check if new version is available and download it demonized using eupgrade @@ -139,7 +139,7 @@ function mesh_upgrade.become_master_node() mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) -- Check download is completed if download_status == eupgrade.STATUS_DEFAULT then - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR,mesh_upgrade.errors.DOWNLOAD_FAILED) + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR, mesh_upgrade.errors.DOWNLOAD_FAILED) return { code = download_status, @@ -151,7 +151,7 @@ function mesh_upgrade.become_master_node() error = "Firmware is downloading" } elseif download_status == eupgrade.STATUS_DOWNLOAD_FAILED then - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR,mesh_upgrade.errors.DOWNLOAD_FAILED) + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR, mesh_upgrade.errors.DOWNLOAD_FAILED) return { code = download_status, error = "Firmware download failed" @@ -162,7 +162,7 @@ function mesh_upgrade.become_master_node() mesh_upgrade.share_firmware_packages() -- Check if local json file exists if not utils.file_exists(mesh_upgrade.LATEST_JSON_PATH) then - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR,mesh_upgrade.errors.NO_LATEST_AVAILABLE) + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR, mesh_upgrade.errors.NO_LATEST_AVAILABLE) return { code = "NO_LOCAL_JSON", @@ -196,7 +196,7 @@ function mesh_upgrade.report_error(error) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR) end --- function to be called by nodes to start download from master. +-- function to be called by BOT nodes to start download from master. function mesh_upgrade.start_node_download(url) eupgrade.set_custom_api_url(url) local cached_only = false @@ -291,20 +291,39 @@ function mesh_upgrade.change_state(newstate, errortype) return false end - end - if newstate == mesh_upgrade.upgrade_states.DOWNLOADING then + elseif newstate == mesh_upgrade.upgrade_states.DOWNLOADING then if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.STARTING) then - utils.log("ok to download") + utils.log("ok DOWNLOADING") else - utils.log("invalid statechange not able to star t") + utils.log("invalid statechange not able to move to DOWNLOADING") return false end - end - if newstate == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then + elseif newstate == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DOWNLOADING) then - utils.log("ok to be ready") + utils.log("ok READY_FOR_UPGRADE") + else + utils.log("invalid statechange not able to move to READY_FOR_UPGRADE") + return false + end + elseif newstate == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then + if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) then + utils.log("ok UPGRADE_SCHEDULED") + else + utils.log("invalid statechange no able to UPGRADE_SCHEDULED") + return false + end + elseif newstate == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then + if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) then + utils.log("ok CONFIRMATION_PENDING") else - utils.log("invalid statechange no able to be ready") + utils.log("invalid statechange no able to CONFIRMATION_PENDING") + return false + end + elseif newstate == mesh_upgrade.upgrade_states.UPDATED then + if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING) then + utils.log("ok UPDATED") + else + utils.log("invalid statechange no able to UPDATED ") return false end end @@ -325,7 +344,6 @@ function mesh_upgrade.become_bot_node(upgrade_data) upgrade_data.master_node = false mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.STARTING) if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.STARTING) then - mesh_upgrade.trigger_sheredstate_publish() mesh_upgrade.start_node_download(upgrade_data.repo_url) end end @@ -386,9 +404,12 @@ function mesh_upgrade.get_mesh_upgrade_status() end function mesh_upgrade.start_safe_upgrade() - if mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHELUDED) and - utils.file_exists(mesh_upgrade.fw_path) then - -- perform safe upgrade + if mesh_upgrade.state() == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE and utils.file_exists(mesh_upgrade.fw_path) then + -- perform safe upgrade preserving config and rebooting after 600 sec if + -- no confirmation is received + utils.execute_daemonized("safe-upgrade upgrade --reboot-safety-timeout=600 " .. mesh_upgrade.fw_path) + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHELUDED) + mesh_upgrade.trigger_sheredstate_publish() return true else utils.log("not able to start upgrade invalid state or firmware not found") @@ -396,4 +417,27 @@ function mesh_upgrade.start_safe_upgrade() end end +-- This command requires that the configuration be preserverd across upgrade, +-- maybe this change achieves this objetive + +-- diff --git a/packages/lime-system/files/etc/config/lime-defaults b/packages/lime-system/files/etc/config/lime-defaults +-- index 5f5c4a31..8d55d949 100644 +-- --- a/packages/lime-system/files/etc/config/lime-defaults +-- +++ b/packages/lime-system/files/etc/config/lime-defaults +-- @@ -8,7 +8,7 @@ +-- config lime system +-- option hostname 'LiMe-%M4%M5%M6' +-- option domain 'thisnode.info' +-- - option keep_on_upgrade 'libremesh dropbear minimum-essential /etc/sysupgrade.conf' +-- + option keep_on_upgrade 'libremesh dropbear minimum-essential /etc/sysupgrade.conf /etc/config/mesh-upgrade' +-- option root_password_policy 'DO_NOTHING' +-- option root_password_secret '' +-- option deferable_reboot_uptime_s '97200' +function mesh_upgrade.confirm() + if mesh_upgrade.state() == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then + utils.execute_daemonized("safe-upgrade confirm") + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPDATED) + end +end + return mesh_upgrade From 380013542b7898baefa40bf2b2ecae81ca360337 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Tue, 23 Jan 2024 17:58:25 -0300 Subject: [PATCH 040/102] fixes start upgrade script and adds some gaurds --- .../files/etc/config/mesh-upgrade | 2 +- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 30 +++++++++++++++---- .../hooks/mesh_wide_upgrade/start_upgrade | 7 +++-- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade index e6fe03b6f..8681d45b9 100644 --- a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade @@ -2,7 +2,7 @@ config mesh-upgrade 'main' option firmware_ver '' option candidate_fw '' option repo_url '' - option upgrade_state 'not_upgrading' + option upgrade_state '' option error '0' option timestamp '0' option master_node 'false' diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 8478f24bc..20985d4f5 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -143,6 +143,14 @@ function mesh_upgrade.start_firmware_upgrade_transaction() -- todo(kon): do all needed checks also with the main node state etc.. -- Expose eupgrade folder to uhttp (this is the best place to do it since -- all the files are present) + local latest = eupgrade.is_new_version_available(true) + if not latest then + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DEFAULT) + return { + code = "NO_NEW_VERSION", + error = "No new version is available" + } + end mesh_upgrade.share_firmware_packages() -- Check if local json file exists if not utils.file_exists(mesh_upgrade.LATEST_JSON_PATH) then @@ -161,9 +169,9 @@ function mesh_upgrade.start_firmware_upgrade_transaction() error = "Shared folder not found" } end - local latest = eupgrade.is_new_version_available(true) -- If we get here is supposed that everything is ready to be a main node mesh_upgrade.inform_download_location(latest['version']) + mesh_upgrade.trigger_sheredstate_publish() return { code = "SUCCESS" } @@ -289,7 +297,8 @@ function mesh_upgrade.change_state(newstate, errortype) return false end elseif newstate == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then - if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DOWNLOADING) then + if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DOWNLOADING or + mesh_upgrade.state() == mesh_upgrade.upgrade_states.STARTING) then utils.log("ok READY_FOR_UPGRADE") else utils.log("invalid statechange not able to move to READY_FOR_UPGRADE") @@ -397,13 +406,18 @@ function mesh_upgrade.start_safe_upgrade() if mesh_upgrade.state() == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE and utils.file_exists(mesh_upgrade.fw_path) then -- perform safe upgrade preserving config and rebooting after 600 sec if -- no confirmation is received - utils.execute_daemonized("safe-upgrade upgrade --reboot-safety-timeout=600 " .. mesh_upgrade.fw_path) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHELUDED) mesh_upgrade.trigger_sheredstate_publish() - return true + utils.execute_daemonized("safe-upgrade upgrade --reboot-safety-timeout=600 " .. mesh_upgrade.fw_path) + return { + code = "SUCCESS" + } else utils.log("not able to start upgrade invalid state or firmware not found") - return false + return { + code = "NOT_ABLE_TO_START_UPGRADE", + error = "Firmware not found" + } end end @@ -425,8 +439,12 @@ end -- option deferable_reboot_uptime_s '97200' function mesh_upgrade.confirm() if mesh_upgrade.state() == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then - utils.execute_daemonized("safe-upgrade confirm") + local shell_output = utils.unsafe_shell("safe-upgrade confirm") mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPDATED) + utils.log(shell_output) + return { + code = "SUCCESS" + } end end diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade index 086010906..d7b42464a 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -23,15 +23,16 @@ local hostname = utils.hostname() --if already involved in an upgrade transaction do nothing if not mesh_upgrade.started() then + utils.log("starting an upgrade process") for node, s_s_data in pairs(JSON.parse(io.stdin:read("*all"))) do --if any node has started an upgrade process and start one too? --only fetch the info from the master node publication? - if node ~= hostname and s_s_data.data.master_node then - utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from "' .. + if node ~= hostname and s_s_data.data.main_node then + utils.unsafe_shell('logger -p startupgrade.hock -t "mesh upgrade" "mesh upgrade detected upgrade from "' .. s_s_data.data.repo_url .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) mesh_upgrade.become_bot_node(s_s_data.data) else - utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "status "' .. + utils.unsafe_shell('logger -p startupgrade.hock -t "mesh upgrade" "status "' .. JSON.stringify(s_s_data.data) .. " from node " .. node) end end From eae0613b5ea1a660432d1801005d85cd0f9a788b Mon Sep 17 00:00:00 2001 From: selankon Date: Wed, 24 Jan 2024 11:40:36 +0100 Subject: [PATCH 041/102] Try to fix mesh upgrade rpcd --- .../{lime-mesh-upgrade.lua => lime-mesh-upgrade} | 8 +++++++- .../usr/share/rpcd/acl.d/lime-mesh-upgrade.json | 15 +++++++++++++++ .../files/usr/share/rpcd/acl.d/lime-utils.json | 16 ---------------- 3 files changed, 22 insertions(+), 17 deletions(-) rename packages/lime-mesh-upgrade/files/usr/libexec/rpcd/{lime-mesh-upgrade.lua => lime-mesh-upgrade} (84%) create mode 100644 packages/lime-mesh-upgrade/files/usr/share/rpcd/acl.d/lime-mesh-upgrade.json delete mode 100644 packages/lime-mesh-upgrade/files/usr/share/rpcd/acl.d/lime-utils.json diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade similarity index 84% rename from packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua rename to packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade index 466fe8c16..e773c1db2 100755 --- a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade @@ -8,7 +8,12 @@ ]] -- local json = require 'luci.jsonc' local mesh_upgrade = require 'lime-mesh-upgrade' +local ubus = require "ubus" +local conn = ubus.connect() +if not conn then + error("Failed to connect to ubus") +end local function become_main_node(msg) local result = mesh_upgrade.become_main_node(msg) @@ -34,11 +39,12 @@ local methods = { if arg[1] == 'list' then utils.printJson(methods) end if arg[1] == 'call' then + utils.printJson({ error = "Method not foundsss" }) local msg = utils.rpcd_readline() msg = json.parse(msg) if arg[2] == 'become_main_node' then become_main_node(msg) elseif arg[2] == 'get_main_node_status' then get_main_node_status(msg) elseif arg[2] == 'start_firmware_upgrade_transaction' then start_firmware_upgrade_transaction(msg) - else utils.printJson({ error = "Method not found" }) + else utils.printJson({ error = "Method not foundsss" }) end end diff --git a/packages/lime-mesh-upgrade/files/usr/share/rpcd/acl.d/lime-mesh-upgrade.json b/packages/lime-mesh-upgrade/files/usr/share/rpcd/acl.d/lime-mesh-upgrade.json new file mode 100644 index 000000000..dfeb8a36c --- /dev/null +++ b/packages/lime-mesh-upgrade/files/usr/share/rpcd/acl.d/lime-mesh-upgrade.json @@ -0,0 +1,15 @@ +{ + "lime-app": { + "description": "lime-mesh-upgrade public access", + "read": { + "ubus": { + "lime-mesh-upgrade": [ "*" ] + } + }, + "write": { + "ubus": { + "lime-mesh-upgrade": [ "*" ] + } + } + } +} \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/files/usr/share/rpcd/acl.d/lime-utils.json b/packages/lime-mesh-upgrade/files/usr/share/rpcd/acl.d/lime-utils.json deleted file mode 100644 index a32b1c406..000000000 --- a/packages/lime-mesh-upgrade/files/usr/share/rpcd/acl.d/lime-utils.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "lime-app": { - "description": "lime-app public access", - "read": { - "ubus": { - "lime-utils": [ "*" ], - "system": [ "board" ] - } - }, - "write": { - "ubus": { - "lime-utils": [ "*" ] - } - } - } -} \ No newline at end of file From 72fdde156d40d20c262a8cb0d52894d066ca8e07 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Wed, 24 Jan 2024 11:08:50 -0300 Subject: [PATCH 042/102] lime-mesh-upgrade: enable ubus list and methods call --- .../files/usr/libexec/rpcd/lime-mesh-upgrade | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade index e773c1db2..c1d0ee48b 100755 --- a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade @@ -31,20 +31,33 @@ local function start_firmware_upgrade_transaction(msg) end local methods = { - become_master_node = {}, - get_main_node_status = {}, - start_firmware_upgrade_transaction = {}, + become_main_node = { + data_type = 'value' + }, + get_main_node_status = { + data_type = 'value' + }, + start_firmware_upgrade_transaction = { + data_type = 'value' + } } -if arg[1] == 'list' then utils.printJson(methods) end +if arg[1] == 'list' then + utils.printJson(methods) +end if arg[1] == 'call' then - utils.printJson({ error = "Method not foundsss" }) local msg = utils.rpcd_readline() msg = json.parse(msg) - if arg[2] == 'become_main_node' then become_main_node(msg) - elseif arg[2] == 'get_main_node_status' then get_main_node_status(msg) - elseif arg[2] == 'start_firmware_upgrade_transaction' then start_firmware_upgrade_transaction(msg) - else utils.printJson({ error = "Method not foundsss" }) + if arg[2] == 'become_main_node' then + become_main_node(msg) + elseif arg[2] == 'get_main_node_status' then + get_main_node_status(msg) + elseif arg[2] == 'start_firmware_upgrade_transaction' then + start_firmware_upgrade_transaction(msg) + else + utils.printJson({ + error = "Method not foundsss" + }) end end From 775633a73ef41284dc3885b93f5a60fa6a5e3d87 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Fri, 26 Jan 2024 11:49:33 -0300 Subject: [PATCH 043/102] lime_mesh_upgrade: fixes test failure --- .../tests/latest/librerouter-v1.json | 24 +++++++++++++++++++ .../tests/latest/librerouter-v1.json.sig | 2 ++ .../tests/test_lime-mesh-upgrade.lua | 8 +++---- .../hooks/mesh_wide_upgrade/start_upgrade | 4 ++-- 4 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 packages/lime-mesh-upgrade/tests/latest/librerouter-v1.json create mode 100644 packages/lime-mesh-upgrade/tests/latest/librerouter-v1.json.sig diff --git a/packages/lime-mesh-upgrade/tests/latest/librerouter-v1.json b/packages/lime-mesh-upgrade/tests/latest/librerouter-v1.json new file mode 100644 index 000000000..946007c86 --- /dev/null +++ b/packages/lime-mesh-upgrade/tests/latest/librerouter-v1.json @@ -0,0 +1,24 @@ +{ + "metadata-version": 1, + "images": [ + { + "name": "upgrade-lr-1.5.sh", + "type": "installer", + "download-urls": [ + "http://10.13.0.2:8080/librerouteros-1.5-r0+11434-e93615c947-ath79-generic-librerouter_librerouter-v1-squashfs-sysupgrade.bin" + ], + "sha256": "2da0abb549d6178a7978b357be3493d5aff5c07b993ea0962575fa61bef18c27" + }, + { + "name": "firmware.bin", + "type": "sysupgrade", + "download-urls": [ + "http://10.13.0.2:8080/librerouteros-1.5-r0+11434-e93615c947-ath79-generic-librerouter_librerouter-v1-squashfs-sysupgrade.bin" + ], + "sha256": "2da0abb549d6178a7978b357be3493d5aff5c07b993ea0962575fa61bef18c27" + } + ], + "board": "test-board", + "version": "LibreRouterOs 1.5", + "release-info-url": "https://foro.librerouter.org/t/lanzamiento-librerouteros-1-5/337" +} \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/tests/latest/librerouter-v1.json.sig b/packages/lime-mesh-upgrade/tests/latest/librerouter-v1.json.sig new file mode 100644 index 000000000..ada590cbc --- /dev/null +++ b/packages/lime-mesh-upgrade/tests/latest/librerouter-v1.json.sig @@ -0,0 +1,2 @@ +untrusted comment: signed by key 47513b83fbc579cd +RWRHUTuD+8V5zSCR6+HGnzSU8qhf1d8K8PqOCo/OYLFAXBeiICUXV33BY3o1ihDWcGbFTBLh8jidfhSkWQev5NoT1PTOTOLvZwc= \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index b6a015bee..61b8c1785 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -27,7 +27,7 @@ local upgrade_data = { repo_url = "http://repo.librerouter.org/lros/api/v1/latest/", upgrde_state = "starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", error = "CODE", - master_node="true", + main_node="true", current_fw="LibreRouterOs 1.5 r0+11434-e93615c947", board_name = "qemu-standard-pc-i440fx-piix-1996"} @@ -142,7 +142,7 @@ describe('LiMe mesh upgrade', function() lime_mesh_upgrade.become_bot_node(upgrade_data) status = lime_mesh_upgrade.get_mesh_upgrade_status() - assert.is.Not(status.master_node, false) + assert.is.Not(status.main_node, false) assert.is.equal(status.repo_url, upgrade_data.repo_url) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) assert.is.equal(status.error, lime_mesh_upgrade.errors.DOWNLOAD_FAILED) @@ -171,7 +171,7 @@ describe('LiMe mesh upgrade', function() lime_mesh_upgrade.become_bot_node(upgrade_data) status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) - assert.is.equal(status.master_node, upgrade_data.master_node) + assert.is.equal(status.main_node, upgrade_data.main_node) assert.is.equal(status.repo_url, upgrade_data.repo_url) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) --assert.is.equal(status.data.eup_STATUS, eupgrade.STATUS_DOWNLOADED) @@ -217,7 +217,7 @@ describe('LiMe mesh upgrade', function() lime_mesh_upgrade.become_bot_node(upgrade_data) status = lime_mesh_upgrade.get_mesh_upgrade_status() utils.printJson(status) - assert.is.equal(status.master_node, upgrade_data.master_node) + assert.is.equal(status.main_node, upgrade_data.main_node) assert.is.equal(status.repo_url, upgrade_data.repo_url) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) --assert.is.equal(status.eup_STATUS, eupgrade.STATUS_DOWNLOADED) diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade index d7b42464a..e89b8e9b0 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -28,11 +28,11 @@ if not mesh_upgrade.started() then --if any node has started an upgrade process and start one too? --only fetch the info from the master node publication? if node ~= hostname and s_s_data.data.main_node then - utils.unsafe_shell('logger -p startupgrade.hock -t "mesh upgrade" "mesh upgrade detected upgrade from "' .. + utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from "' .. s_s_data.data.repo_url .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) mesh_upgrade.become_bot_node(s_s_data.data) else - utils.unsafe_shell('logger -p startupgrade.hock -t "mesh upgrade" "status "' .. + utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "status "' .. JSON.stringify(s_s_data.data) .. " from node " .. node) end end From e3ac277c04e4a1d3453411fea6789ca27776d989 Mon Sep 17 00:00:00 2001 From: selankon Date: Mon, 29 Jan 2024 11:34:55 +0100 Subject: [PATCH 044/102] mesh-upgrade: delete unnecessary logs And other minor improvements about readability. --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 85 ++++++------------- .../files/usr/libexec/rpcd/lime-mesh-upgrade | 6 +- 2 files changed, 31 insertions(+), 60 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 20985d4f5..23e79fd43 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -109,7 +109,6 @@ function mesh_upgrade.become_main_node() local latest = eupgrade.is_new_version_available(false) if not latest then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DEFAULT) - utils.log("no new version available") return { code = "NO_NEW_VERSION", error = "No new version is available" @@ -118,6 +117,9 @@ function mesh_upgrade.become_main_node() -- 2. Start local repository and download latest firmware mesh_upgrade.start_main_node_repository(latest) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) + return { + code = "SUCCESS", + } end -- Return eupgrade status for this node and update mesh upgrade status accordingly @@ -236,8 +238,6 @@ function mesh_upgrade.inform_download_location(version) board_name = eupgrade._get_board_name(), current_fw = eupgrade._get_current_fw_version() }, mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) - else - utils.log("eupgrade STATUS is not 'DOWNLOADED'") end end @@ -245,11 +245,10 @@ end function mesh_upgrade.started() status = mesh_upgrade.state() if status == mesh_upgrade.upgrade_states.STARTING or status == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING or - status == mesh_upgrade.upgrade_states.CONFIRMED or status == mesh_upgrade.upgrade_states.DOWNLOADING or status == - mesh_upgrade.upgrade_states.READY_FOR_UPGRADE or status == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then + status == mesh_upgrade.upgrade_states.CONFIRMED or status == mesh_upgrade.upgrade_states.DOWNLOADING or status == + mesh_upgrade.upgrade_states.READY_FOR_UPGRADE or status == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then return true end - utils.log(" started returned false !!! ") return false -- todo(javi): what happens if a mesh_upgrade has started more than an hour ago ? should this node abort it ? end @@ -268,66 +267,38 @@ end -- This line will genereate recursive dependencies like in pirania pakcage function mesh_upgrade.trigger_sheredstate_publish() utils.execute_daemonized( - "/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") + "/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") end -- ! changes the state of the upgrade and verifies that state transition is possible. -function mesh_upgrade.change_state(newstate, errortype) +function mesh_upgrade.change_state(newstate) -- If the state is the same just return if newstate == mesh_upgrade.state() then return false end local uci = config.get_uci_cursor() - utils.log("changing from " .. mesh_upgrade.state() .. " to " .. newstate) - if newstate == mesh_upgrade.upgrade_states.STARTING then - if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DEFAULT or - mesh_upgrade.state() == mesh_upgrade.upgrade_states.ERROR or - mesh_upgrade.state() == mesh_upgrade.upgrade_states.UPDATED) - then - utils.log("ok to start") - else - utils.log("invalid state change not able to start") - - return false - end - elseif newstate == mesh_upgrade.upgrade_states.DOWNLOADING then - if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.STARTING) then - utils.log("ok DOWNLOADING") - else - utils.log("invalid statechange not able to move to DOWNLOADING") - return false - end - elseif newstate == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then - if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.DOWNLOADING or - mesh_upgrade.state() == mesh_upgrade.upgrade_states.STARTING) then - utils.log("ok READY_FOR_UPGRADE") - else - utils.log("invalid statechange not able to move to READY_FOR_UPGRADE") - return false - end - elseif newstate == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then - if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) then - utils.log("ok UPGRADE_SCHEDULED") - else - utils.log("invalid statechange no able to UPGRADE_SCHEDULED") - return false - end - elseif newstate == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then - if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) then - utils.log("ok CONFIRMATION_PENDING") - else - utils.log("invalid statechange no able to CONFIRMATION_PENDING") - return false - end - elseif newstate == mesh_upgrade.upgrade_states.UPDATED then - if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING) then - utils.log("ok UPDATED") - else - utils.log("invalid statechange no able to UPDATED ") - return false - end + if newstate == mesh_upgrade.upgrade_states.STARTING and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.DEFAULT and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.ERROR and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.UPDATED then + return false + elseif newstate == mesh_upgrade.upgrade_states.DOWNLOADING and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.STARTING then + return false + elseif newstate == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.DOWNLOADING and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.STARTING then + return false + elseif newstate == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then + return false + elseif newstate == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then + return false + elseif newstate == mesh_upgrade.upgrade_states.UPDATED and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then + return false end -- todo(javi): verify other states and return false if it is not possible - -- lets allow all types of state changes. uci:set('mesh-upgrade', 'main', 'upgrade_state', newstate) uci:save('mesh-upgrade') diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade index c1d0ee48b..7d8091afa 100755 --- a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade @@ -32,13 +32,13 @@ end local methods = { become_main_node = { - data_type = 'value' + no_params = 0 }, get_main_node_status = { - data_type = 'value' + no_params = 0 }, start_firmware_upgrade_transaction = { - data_type = 'value' + no_params = 0 } } From 724abf8603ff53cbb13a11ebe9d815d90fddba64 Mon Sep 17 00:00:00 2001 From: selankon Date: Mon, 29 Jan 2024 11:35:06 +0100 Subject: [PATCH 045/102] mesh-upgrade: add test --- .../tests/test_lime-mesh-upgrade.lua | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index b6a015bee..c5bc26e32 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -25,7 +25,7 @@ local uci local upgrade_data = { candidate_fw = "xxxx", repo_url = "http://repo.librerouter.org/lros/api/v1/latest/", - upgrde_state = "starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", + upgrade_state = "starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", error = "CODE", master_node="true", current_fw="LibreRouterOs 1.5 r0+11434-e93615c947", @@ -150,6 +150,20 @@ describe('LiMe mesh upgrade', function() --assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.ABORTED) --TODO: javi en caso de falla ... reintentar ? abortar ? end) + + it('test become main node changes the state to STARTING', function() + stub(eupgrade, 'is_new_version_available', function() + return json.parse(latest_release_data) + end) + stub(lime_mesh_upgrade, 'start_main_node_repository', function() end) + stub(eupgrade, '_get_current_fw_version', function() end) + local res = lime_mesh_upgrade.become_main_node() + assert.is.equal(res.code, 'SUCCESS') + local status = lime_mesh_upgrade.get_mesh_upgrade_status() + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.STARTING) + end) + + it('test set mesh config start download and assert status ready_for_upgrade', function() stub(eupgrade, '_get_board_name', function() return 'test-board' @@ -249,7 +263,7 @@ describe('LiMe mesh upgrade', function() config.set('wifi', 'lime') config.set('wifi', 'ap_ssid', 'LibreMesh.org') uci:commit('lime') - + lime_mesh_upgrade.create_local_latest_json(json.parse(latest_release_data)) local latest = json.parse(utils.read_file(lime_mesh_upgrade.LATEST_JSON_PATH)) local repo_url = lime_mesh_upgrade.FIRMWARE_REPO_PATH From 08402bd3b883a3d43f1ea34e2b4356f5ed5f7586 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 29 Jan 2024 11:46:44 -0300 Subject: [PATCH 046/102] lime-mesh-upgrade: fiexes json file name --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 17 ++++++++++------- ...-v1.json => librerouter-librerouter-v1.json} | 5 +++-- ....sig => librerouter-librerouter-v1.json.sig} | 0 3 files changed, 13 insertions(+), 9 deletions(-) rename packages/lime-mesh-upgrade/tests/latest/{librerouter-v1.json => librerouter-librerouter-v1.json} (71%) rename packages/lime-mesh-upgrade/tests/latest/{librerouter-v1.json.sig => librerouter-librerouter-v1.json.sig} (100%) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 20985d4f5..992dc5894 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -61,7 +61,7 @@ end function mesh_upgrade.set_workdir(workdir) mesh_upgrade._create_workdir(workdir) mesh_upgrade.WORKDIR = workdir - mesh_upgrade.LATEST_JSON_FILE_NAME = eupgrade._get_board_name() .. ".json" -- latest json with local lan url file name + mesh_upgrade.LATEST_JSON_FILE_NAME = utils.slugify(eupgrade._get_board_name()) .. ".json" -- latest json with local lan url file name mesh_upgrade.LATEST_JSON_PATH = mesh_upgrade.WORKDIR .. "/" .. mesh_upgrade.LATEST_JSON_FILE_NAME -- latest json full path mesh_upgrade.FIRMWARE_REPO_PATH = '/lros/' -- path url for firmwares mesh_upgrade.FIRMWARE_SHARED_FOLDER = '/www/' .. mesh_upgrade.FIRMWARE_REPO_PATH @@ -74,8 +74,11 @@ function mesh_upgrade.create_local_latest_json(latest_data) -- im['download-urls'] = string.gsub(im['download-urls'], upgrade_url, "test") im['download-urls'] = {mesh_upgrade.get_repo_base_url() .. im['name']} end + + utils.log(json.stringify(latest_data)) utils.write_file(mesh_upgrade.LATEST_JSON_PATH, json.stringify(latest_data)) -- For the moment mesh upgrade will ignore the latest json signature on de main nodes + -- todo: add signature file with a valid signature... or review the signing process. end function mesh_upgrade.share_firmware_packages(dest) @@ -195,17 +198,17 @@ function mesh_upgrade.start_node_download(url) local cached_only = false local url2 = eupgrade.get_upgrade_api_url() local latest_data, message = eupgrade.is_new_version_available(cached_only) - utils.log("start_node_download from " .. url2) + utils.log("start_node_download from " .. url2 ) if latest_data then utils.log("start_node_download ") mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) utils.log("downloading") local image = {} - image, mesh_upgrade.fw_path = eupgrade.download_firmware(latest_data) - utils.log(image) - utils.log(mesh_upgrade.fw_path) - utils.log(latest_data) + image = eupgrade.download_firmware(latest_data) + utils.printJson(image) + --utils.log(mesh_upgrade.fw_path) + --utils.log(latest_data) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED and image ~= nil then utils.printJson(image) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) @@ -215,7 +218,7 @@ function mesh_upgrade.start_node_download(url) mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) end else - utils.log("Error ... no latest data available") + utils.log("Error ... no latest data available" .. message) mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) end end diff --git a/packages/lime-mesh-upgrade/tests/latest/librerouter-v1.json b/packages/lime-mesh-upgrade/tests/latest/librerouter-librerouter-v1.json similarity index 71% rename from packages/lime-mesh-upgrade/tests/latest/librerouter-v1.json rename to packages/lime-mesh-upgrade/tests/latest/librerouter-librerouter-v1.json index 946007c86..e1b65839d 100644 --- a/packages/lime-mesh-upgrade/tests/latest/librerouter-v1.json +++ b/packages/lime-mesh-upgrade/tests/latest/librerouter-librerouter-v1.json @@ -5,7 +5,8 @@ "name": "upgrade-lr-1.5.sh", "type": "installer", "download-urls": [ - "http://10.13.0.2:8080/librerouteros-1.5-r0+11434-e93615c947-ath79-generic-librerouter_librerouter-v1-squashfs-sysupgrade.bin" + "http://10.13.0.2:8080/librerouteros-1.5-r0+11434-e93615c947-ath79-generic-librerouter_librerouter-v1-squashfs-sysupgrade.bin", + "http://10.234.77.12:8080/librerouteros-1.5-r0+11434-e93615c947-ath79-generic-librerouter_librerouter-v1-squashfs-sysupgrade.bin" ], "sha256": "2da0abb549d6178a7978b357be3493d5aff5c07b993ea0962575fa61bef18c27" }, @@ -13,7 +14,7 @@ "name": "firmware.bin", "type": "sysupgrade", "download-urls": [ - "http://10.13.0.2:8080/librerouteros-1.5-r0+11434-e93615c947-ath79-generic-librerouter_librerouter-v1-squashfs-sysupgrade.bin" + "http://10.234.77.12:8080/librerouteros-1.5-r0+11434-e93615c947-ath79-generic-librerouter_librerouter-v1-squashfs-sysupgrade.bin" ], "sha256": "2da0abb549d6178a7978b357be3493d5aff5c07b993ea0962575fa61bef18c27" } diff --git a/packages/lime-mesh-upgrade/tests/latest/librerouter-v1.json.sig b/packages/lime-mesh-upgrade/tests/latest/librerouter-librerouter-v1.json.sig similarity index 100% rename from packages/lime-mesh-upgrade/tests/latest/librerouter-v1.json.sig rename to packages/lime-mesh-upgrade/tests/latest/librerouter-librerouter-v1.json.sig From 426db52ee15d8567eadc01394c11449c350d42be Mon Sep 17 00:00:00 2001 From: javierbrk Date: Tue, 30 Jan 2024 11:19:20 -0300 Subject: [PATCH 047/102] lime-mesh-upgrade: fixes "invalid argument" and file permissions --- .../eupgrade/files/usr/lib/lua/eupgrade.lua | 3 - .../files/usr/lib/lua/lime-mesh-upgrade.lua | 60 +++++++++++-------- .../files/usr/libexec/rpcd/lime-mesh-upgrade | 6 +- 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/packages/eupgrade/files/usr/lib/lua/eupgrade.lua b/packages/eupgrade/files/usr/lib/lua/eupgrade.lua index 31188f61e..fcee623a1 100644 --- a/packages/eupgrade/files/usr/lib/lua/eupgrade.lua +++ b/packages/eupgrade/files/usr/lib/lua/eupgrade.lua @@ -107,15 +107,12 @@ function eup.is_new_version_available(cached_only) local sig_url = url .. ".sig" if not utils.http_client_get(sig_url, 10, eup.FIRMWARE_LATEST_JSON_SIGNATURE) then message = "Can't download signature " .. sig_url - utils.log(message) end -- this will skip json signature verification when altenative url is set if eup._check_signature(eup.FIRMWARE_LATEST_JSON, eup.FIRMWARE_LATEST_JSON_SIGNATURE) or eup.is_meshupgrade_enabled() then - utils.log("Good signature of firmware_latest.json") return latest_data else message = "Bad signature of firmware_latest.json" - utils.log(message) end end end diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 241a63f5a..673597a1f 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -51,7 +51,7 @@ end -- Create a work directory if nor exist function mesh_upgrade._create_workdir(workdir) if not utils.file_exists(workdir) then - os.execute('mkdir -p ' .. workdir) + os.execute('mkdir -p ' .. workdir .. " >/dev/null") end if fs.stat(workdir, "type") ~= "dir" then error("Can't configure workdir " .. workdir) @@ -75,7 +75,6 @@ function mesh_upgrade.create_local_latest_json(latest_data) im['download-urls'] = {mesh_upgrade.get_repo_base_url() .. im['name']} end - utils.log(json.stringify(latest_data)) utils.write_file(mesh_upgrade.LATEST_JSON_PATH, json.stringify(latest_data)) -- For the moment mesh upgrade will ignore the latest json signature on de main nodes -- todo: add signature file with a valid signature... or review the signing process. @@ -89,8 +88,13 @@ function mesh_upgrade.share_firmware_packages(dest) mesh_upgrade._create_workdir(dest) -- json file has to be placed in a url that ends with latest mesh_upgrade._create_workdir(dest .. "/latest") - os.execute("ln -s " .. images_folder .. "/* " .. dest) - os.execute("ln -s " .. mesh_upgrade.LATEST_JSON_PATH .. " " .. dest .. "/latest") + os.execute("ln -s " .. images_folder .. "/* " .. dest.. " >/dev/null") + --utils.unsafe_shell("ln -s " .. images_folder .. "/* " .. dest .. " >/dev/null") + os.execute("ln -s " .. mesh_upgrade.LATEST_JSON_PATH .. " " .. dest .. "/latest >/dev/null") + os.execute("chmod -R 664 ".. dest .." >/dev/null") + os.execute("chmod -R 664 ".. mesh_upgrade.WORKDIR .." >/dev/null") + os.execute("chmod -R 664 ".. images_folder .." >/dev/null") + end -- This function will download latest firmware and expose it as @@ -98,12 +102,16 @@ end function mesh_upgrade.start_main_node_repository(latest_data) -- Create local repository json data mesh_upgrade.create_local_latest_json(latest_data) - utils.execute_daemonized("eupgrade-download") + utils.execute_daemonized("eupgrade-download >/dev/null") end --- Function that check if tihs node have all things needed to became a main node --- Then, call update shared state with the proper info -function mesh_upgrade.become_main_node() +--- Function that check if tihs node have all things needed to became a main node +--- Then, call update shared state with the proper info +-- @url optional new url to get the firmware for local repo +function mesh_upgrade.become_main_node(url) + if url then + eupgrade.set_custom_api_url(url) + end -- todo(kon): check if main node is already set or we are on mesh_upgrade status -- todo(kon): dont start again if status is started and eupgrade is downloaded for example -- Check if there are a new version available (cached only) @@ -122,6 +130,7 @@ function mesh_upgrade.become_main_node() mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) return { code = "SUCCESS", + error = "" } end @@ -178,7 +187,8 @@ function mesh_upgrade.start_firmware_upgrade_transaction() mesh_upgrade.inform_download_location(latest['version']) mesh_upgrade.trigger_sheredstate_publish() return { - code = "SUCCESS" + code = "SUCCESS", + error = "" } end @@ -200,27 +210,27 @@ function mesh_upgrade.start_node_download(url) local cached_only = false local url2 = eupgrade.get_upgrade_api_url() local latest_data, message = eupgrade.is_new_version_available(cached_only) - utils.log("start_node_download from " .. url2 ) + --utils.log("start_node_download from " .. url2 ) if latest_data then - utils.log("start_node_download ") + --utils.log("start_node_download ") mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) - utils.log("downloading") + --utils.log("downloading") local image = {} image = eupgrade.download_firmware(latest_data) - utils.printJson(image) - --utils.log(mesh_upgrade.fw_path) - --utils.log(latest_data) + --utils.printJson(image) + ----utils.log(mesh_upgrade.fw_path) + ----utils.log(latest_data) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED and image ~= nil then - utils.printJson(image) + --utils.printJson(image) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) mesh_upgrade.trigger_sheredstate_publish() else - utils.log("Error ... download failed") + --utils.log("Error ... download failed") mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) end else - utils.log("Error ... no latest data available" .. message) + --utils.log("Error ... no latest data available" .. message) mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) end end @@ -311,9 +321,9 @@ end function mesh_upgrade.become_bot_node(upgrade_data) if mesh_upgrade.started() then - utils.log("already a bot node") + --utils.log("already a bot node") else - utils.log("transfoming into a bot node") + --utils.log("transfoming into a bot node") upgrade_data.main_node = false mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.STARTING) if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.STARTING) then @@ -328,7 +338,7 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state) local uci = config.get_uci_cursor() if string.match(upgrade_data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil -- todo (javi): perform aditional checks then - utils.log("seting up repo download info to " .. upgrade_state .. " actual " .. mesh_upgrade.state()) + --utils.log("seting up repo download info to " .. upgrade_state .. " actual " .. mesh_upgrade.state()) if (mesh_upgrade.change_state(upgrade_state)) then uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.repo_url) @@ -341,10 +351,10 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state) -- trigger shared state data refresh mesh_upgrade.trigger_sheredstate_publish() else - utils.log("invalid state change ") + --utils.log("invalid state change ") end else - utils.log("upgrade failed due input data errors") + --utils.log("upgrade failed due input data errors") end end @@ -387,7 +397,7 @@ function mesh_upgrade.start_safe_upgrade() code = "SUCCESS" } else - utils.log("not able to start upgrade invalid state or firmware not found") + --utils.log("not able to start upgrade invalid state or firmware not found") return { code = "NOT_ABLE_TO_START_UPGRADE", error = "Firmware not found" @@ -415,7 +425,7 @@ function mesh_upgrade.confirm() if mesh_upgrade.state() == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then local shell_output = utils.unsafe_shell("safe-upgrade confirm") mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPDATED) - utils.log(shell_output) + --utils.log(shell_output) return { code = "SUCCESS" } diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade index 7d8091afa..66473c516 100755 --- a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade @@ -16,7 +16,7 @@ if not conn then end local function become_main_node(msg) - local result = mesh_upgrade.become_main_node(msg) + local result = mesh_upgrade.become_main_node(msg.url) return utils.printJson(result) end @@ -26,13 +26,13 @@ local function get_main_node_status(msg) end local function start_firmware_upgrade_transaction(msg) - local result = mesh_upgrade.start_firmware_upgrade_transaction(msg) + local result = mesh_upgrade.start_firmware_upgrade_transaction() return utils.printJson(result) end local methods = { become_main_node = { - no_params = 0 + url = 'value' }, get_main_node_status = { no_params = 0 From 088c26f3af8bd78f9512a6d16186efe5619add79 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Tue, 30 Jan 2024 12:53:33 -0300 Subject: [PATCH 048/102] lime-mesh-upgrade: fixes tests bug related to file permission --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 673597a1f..04c82b3fd 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -73,8 +73,7 @@ function mesh_upgrade.create_local_latest_json(latest_data) for _, im in pairs(latest_data['images']) do -- im['download-urls'] = string.gsub(im['download-urls'], upgrade_url, "test") im['download-urls'] = {mesh_upgrade.get_repo_base_url() .. im['name']} - end - + end utils.write_file(mesh_upgrade.LATEST_JSON_PATH, json.stringify(latest_data)) -- For the moment mesh upgrade will ignore the latest json signature on de main nodes -- todo: add signature file with a valid signature... or review the signing process. @@ -89,12 +88,10 @@ function mesh_upgrade.share_firmware_packages(dest) -- json file has to be placed in a url that ends with latest mesh_upgrade._create_workdir(dest .. "/latest") os.execute("ln -s " .. images_folder .. "/* " .. dest.. " >/dev/null") - --utils.unsafe_shell("ln -s " .. images_folder .. "/* " .. dest .. " >/dev/null") os.execute("ln -s " .. mesh_upgrade.LATEST_JSON_PATH .. " " .. dest .. "/latest >/dev/null") - os.execute("chmod -R 664 ".. dest .." >/dev/null") - os.execute("chmod -R 664 ".. mesh_upgrade.WORKDIR .." >/dev/null") - os.execute("chmod -R 664 ".. images_folder .." >/dev/null") - + os.execute("chmod -R 777 ".. dest .." >/dev/null") + os.execute("chmod -R 777 ".. mesh_upgrade.WORKDIR .." >/dev/null") + os.execute("chmod -R 777 ".. images_folder .." >/dev/null") end -- This function will download latest firmware and expose it as From 2f942aa445ba0ba81d2258753100f45c28ccb902 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Tue, 30 Jan 2024 15:28:45 -0300 Subject: [PATCH 049/102] lime-mesh-upgrade: improves testing and fixes small issues --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 7 +- .../tests/test_lime-mesh-upgrade.lua | 246 ++++++++---------- 2 files changed, 105 insertions(+), 148 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 04c82b3fd..485d502a3 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -81,7 +81,7 @@ end function mesh_upgrade.share_firmware_packages(dest) if dest == nil then - dest = "/www" .. mesh_upgrade.FIRMWARE_REPO_PATH + dest = mesh_upgrade.FIRMWARE_SHARED_FOLDER end local images_folder = eupgrade.WORKDIR mesh_upgrade._create_workdir(dest) @@ -228,7 +228,7 @@ function mesh_upgrade.start_node_download(url) end else --utils.log("Error ... no latest data available" .. message) - mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) + mesh_upgrade.report_error(mesh_upgrade.errors.NO_LATEST_AVAILABLE) end end @@ -318,9 +318,8 @@ end function mesh_upgrade.become_bot_node(upgrade_data) if mesh_upgrade.started() then - --utils.log("already a bot node") + else - --utils.log("transfoming into a bot node") upgrade_data.main_node = false mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.STARTING) if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.STARTING) then diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 3f225a6dd..4d531122b 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -1,8 +1,10 @@ local config = require 'lime.config' +local eupgrade = require 'eupgrade' -os.execute('mkdir /tmp/sysinfo/') -os.execute('echo librerouter-v1 > /tmp/sysinfo/board_name') - +local boardname = 'librerouter-v1' +stub(eupgrade, '_get_board_name', function() + return boardname +end) local lime_mesh_upgrade = require 'lime-mesh-upgrade' local network = require("lime.network") @@ -10,26 +12,17 @@ local utils = require "lime.utils" local test_utils = require "tests.utils" local eup = require "eupgrade" local json = require 'luci.jsonc' - -eupgrade = require 'eupgrade' - -utils.enable_logging() - --- disable logging in config module -config.log = function(text) - print(text) -end - local uci local upgrade_data = { - candidate_fw = "xxxx", - repo_url = "http://repo.librerouter.org/lros/api/v1/latest/", - upgrade_state = "starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", - error = "CODE", - main_node="true", - current_fw="LibreRouterOs 1.5 r0+11434-e93615c947", - board_name = "qemu-standard-pc-i440fx-piix-1996"} + candidate_fw = "xxxx", + repo_url = "http://repo.librerouter.org/lros/api/v1/latest/", + upgrade_state = "starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", + error = "CODE", + main_node = "true", + current_fw = "LibreRouterOs 1.5 r0+11434-e93615c947", + board_name = "qemu-standard-pc-i440fx-piix-1996" +} local latest_release_data = [[ { @@ -58,119 +51,62 @@ local latest_release_data = [[ } ]] -local latest_release_data_real = [[ -{ - "metadata-version": 1, - "images": [ - { - "name": "upgrade-lr-1.5.sh", - "type": "installer", - "download-urls": [ - "http://repo.librerouter.org/lros/releases/1.5/targets/ath79/generic/upgrade-lr-1.5.sh" - ], - "sha256": "cec8920f93055cc57cfde1f87968e33ca5215b2df88611684195077402079acb" - }, - { - "name": "firmware.bin", - "type": "sysupgrade", - "download-urls": [ - "http://repo.librerouter.org/lros/releases/1.5/targets/ath79/generic/librerouteros-1.5-r0+11434-e93615c947-ath79-generic-librerouter_librerouter-v1-squashfs-sysupgrade.bin" - ], - "sha256": "2da0abb549d6178a7978b357be3493d5aff5c07b993ea0962575fa61bef18c27" - } - ], - "board": "librerouter,librerouter-v1", - "version": "LibreRouterOs 1.5 r0+11434-e93615c947", - "release-info-url": "https://foro.librerouter.org/t/lanzamiento-librerouteros-1-5/337" -} - -]] -local latest_release_data_real_sig = [[ -untrusted comment: signed by key 47513b83fbc579cd -RWRHUTuD+8V5zSCR6+HGnzSU8qhf1d8K8PqOCo/OYLFAXBeiICUXV33BY3o1ihDWcGbFTBLh8jidfhSkWQev5NoT1PTOTOLvZwc= -]] -local api_url = 'http://repo.librerouter.org/lros/releases/' - - describe('LiMe mesh upgrade', function() it('test get mesh config fresh start', function() + local fw_version = 'LibreMesh 19.02' config.log("\n test set mesh config.... \n") - stub(eupgrade, '_get_board_name', function() - return 'test-board' - end) + stub(eupgrade, '_get_current_fw_version', function() - return 'LibreMesh 19.05' + return fw_version end) local status = lime_mesh_upgrade.get_mesh_upgrade_status() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.DEFAULT) + assert.is.equal(status.main_node, false) + assert.is.equal(status.current_fw, fw_version) + assert.is.equal(status.board_name, boardname) assert.is.equal(lime_mesh_upgrade.started(), false) end) - it('test set mesh config and get status', function() - stub(eupgrade, '_get_board_name', function() - return 'test-board' - end) + it('test set error ', function() stub(eupgrade, '_get_current_fw_version', function() return 'LibreMesh 19.05' end) - stub(eupgrade, '_check_signature', function() - return true - end) - stub(utils, 'http_client_get', function() - return latest_release_data - end) - stub(eupgrade, '_file_sha256', function() - return 'fbd95fc091ea10cfa05cfb0ef870da43124ac7c1402890eb8f03b440c57d7b5' - end) - - assert.is.equal('LibreRouterOs 1.5', eupgrade.is_new_version_available()['version']) - stub(eupgrade, '_get_board_name', function () return 'test-board' end) - stub(eupgrade, '_get_current_fw_version', function () return 'LibreMesh 1.4' end) - stub(eupgrade, '_check_signature', function () return true end) - stub(utils, 'http_client_get', function () return latest_release_data end) - assert.is.equal('LibreRouterOs 1.5', eupgrade.is_new_version_available()['version']) - lime_mesh_upgrade.report_error(lime_mesh_upgrade.errors.CONFIRMATION_TIME_OUT) status = lime_mesh_upgrade.get_mesh_upgrade_status() assert.is.equal(status.error, lime_mesh_upgrade.errors.CONFIRMATION_TIME_OUT) + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) + end) + it('test abort ', function() + stub(eupgrade, '_get_current_fw_version', function() + return 'LibreMesh 19.05' + end) lime_mesh_upgrade.mesh_upgrade_abort() status = lime_mesh_upgrade.get_mesh_upgrade_status() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) assert.is.equal(status.error, lime_mesh_upgrade.errors.ABORTED) + end) + it('test set upgrade info and fail NO_LATEST_AVAILABLE', function() + stub(eupgrade, '_check_signature', function() + return true + end) + stub(eupgrade, '_file_sha256', function() + return 'fbd95fc091ea10cfa05cfb0ef870da43124ac7c1402890eb8f03b440c57d7b5' + end) + stub(eupgrade, '_get_current_fw_version', function() + return 'LibreMesh 1.4' + end) lime_mesh_upgrade.become_bot_node(upgrade_data) status = lime_mesh_upgrade.get_mesh_upgrade_status() - assert.is.Not(status.main_node, false) + assert.is.equal(status.main_node, false) assert.is.equal(status.repo_url, upgrade_data.repo_url) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) - assert.is.equal(status.error, lime_mesh_upgrade.errors.DOWNLOAD_FAILED) - --assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) - --assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.ABORTED) - --TODO: javi en caso de falla ... reintentar ? abortar ? - end) - - it('test become main node changes the state to STARTING', function() - stub(eupgrade, 'is_new_version_available', function() - return json.parse(latest_release_data) - end) - stub(lime_mesh_upgrade, 'start_main_node_repository', function() end) - stub(eupgrade, '_get_current_fw_version', function() end) - local res = lime_mesh_upgrade.become_main_node() - assert.is.equal(res.code, 'SUCCESS') - local status = lime_mesh_upgrade.get_mesh_upgrade_status() - assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.STARTING) + assert.is.equal(status.error, lime_mesh_upgrade.errors.NO_LATEST_AVAILABLE) end) - - it('test set mesh config start download and assert status ready_for_upgrade', function() - stub(eupgrade, '_get_board_name', function() - return 'test-board' - end) - stub(eupgrade, '_get_current_fw_version', function() - return 'LibreMesh 19.05' - end) + it('test set upgrade info and fail to download', function() stub(eupgrade, '_check_signature', function() return true end) @@ -178,68 +114,57 @@ describe('LiMe mesh upgrade', function() return latest_release_data end) stub(eupgrade, '_file_sha256', function() - return 'cec8920f93055cc57cfde1f87968e33ca5215b2df88611684195077402079acb' + return 'fbd95fc091ea10cfa05cfb0ef870da43124ac7c1402890eb8f03b440c57d7b5' + end) + stub(eupgrade, '_get_current_fw_version', function() + return 'LibreMesh 1.4' end) - assert.is.equal('LibreRouterOs 1.5', eupgrade.is_new_version_available()['version']) lime_mesh_upgrade.become_bot_node(upgrade_data) status = lime_mesh_upgrade.get_mesh_upgrade_status() - utils.printJson(status) - assert.is.equal(status.main_node, upgrade_data.main_node) + assert.is.equal(status.main_node, false) assert.is.equal(status.repo_url, upgrade_data.repo_url) - assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) - --assert.is.equal(status.data.eup_STATUS, eupgrade.STATUS_DOWNLOADED) - --assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) + assert.is.equal(status.error, lime_mesh_upgrade.errors.DOWNLOAD_FAILED) end) - it('test set mesh config start download and assert status ready_for_upgrade', function() - stub(eupgrade, '_get_board_name', function() - return 'librerouter-v1' - end) + it('test become botnode and assert status ready_for_upgrade', function() stub(eupgrade, '_get_current_fw_version', function() return 'LibreMesh 19.05' end) stub(eupgrade, '_check_signature', function() return true end) + stub(utils, 'http_client_get', function() + return latest_release_data + end) stub(eupgrade, '_file_sha256', function() return 'cec8920f93055cc57cfde1f87968e33ca5215b2df88611684195077402079acb' end) - -- todo: javi este netodo no seria necesario que sea stub porque deberia tomar la url del set upgrade api pero no toma el config uci - stub(eupgrade, 'get_upgrade_api_url', function() - return 'http://repo.librerouter.org/lros/api/v1/' - end) - stub(utils, 'http_client_get', function(url, to, file) - config.log("http_client_get " .. url .. " " .. to .. (args or "")) - if url == "http://repo.librerouter.org/lros/releases/1.5/targets/ath79/generic/upgrade-lr-1.5.sh" then - return true - end - if url == "http://repo.librerouter.org/lros/api/v1/latest/librerouter-v1.json.sig" then - return latest_release_data_real_sig - end - if url == "http://repo.librerouter.org/lros/api/v1/latest/librerouter-v1.json" then - return latest_release_data_real - end - config.log("http_client_get " .. url .. " " .. to .. (args or "")) - config.log("http_client_get " .. url .. " " .. to .. (args or "")) - config.log("http_client_get " .. url .. " " .. to .. (args or "")) - config.log("http_client_get " .. url .. " " .. to .. (args or "")) - config.log("http_client_get " .. url .. " " .. to .. (args or "")) - return true - end) + assert.is.equal('LibreRouterOs 1.5', eupgrade.is_new_version_available()['version']) lime_mesh_upgrade.become_bot_node(upgrade_data) status = lime_mesh_upgrade.get_mesh_upgrade_status() - utils.printJson(status) assert.is.equal(status.main_node, upgrade_data.main_node) assert.is.equal(status.repo_url, upgrade_data.repo_url) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) - --assert.is.equal(status.eup_STATUS, eupgrade.STATUS_DOWNLOADED) - --assert.is.equal(status.transaction_state, lime_mesh_upgrade.transaction_states.STARTED) end) - it('test custom latest json file is created', function() + it('test become main node changes the state to STARTING', function() + stub(eupgrade, 'is_new_version_available', function() + return json.parse(latest_release_data) + end) + stub(lime_mesh_upgrade, 'start_main_node_repository', function() + end) + stub(eupgrade, '_get_current_fw_version', function() + end) + local res = lime_mesh_upgrade.become_main_node() + assert.is.equal(res.code, 'SUCCESS') + local status = lime_mesh_upgrade.get_mesh_upgrade_status() + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.STARTING) + end) + it('test custom latest json file is created', function() config.set('network', 'lime') config.set('network', 'main_ipv4_address', '10.%N1.0.0/16') config.set('network', 'main_ipv6_address', 'fd%N1:%N2%N3:%N4%N5::/64') @@ -247,9 +172,6 @@ describe('LiMe mesh upgrade', function() config.set('wifi', 'lime') config.set('wifi', 'ap_ssid', 'LibreMesh.org') uci:commit('lime') - - --stub(network, 'primary_address', function () return '10.13.0.1', 'ipv6' end) - lime_mesh_upgrade.create_local_latest_json(json.parse(latest_release_data)) local filexists = utils.file_exists(lime_mesh_upgrade.LATEST_JSON_PATH) assert(filexists, "File not found: " .. lime_mesh_upgrade.LATEST_JSON_PATH) @@ -299,12 +221,48 @@ describe('LiMe mesh upgrade', function() assert(file_exists, "File not found: " .. json_link) end) + it('test become main node change state to READY_FOR_UPGRADE', function() + config.set('network', 'lime') + config.set('network', 'main_ipv4_address', '10.1.1.0/16') + config.set('network', 'main_ipv6_address', 'fd%N1:%N2%N3:%N4%N5::/64') + config.set('network', 'protocols', {'lan'}) + config.set('wifi', 'lime') + config.set('wifi', 'ap_ssid', 'LibreMesh.org') + uci:commit('lime') + + stub(eupgrade, 'is_new_version_available', function() + return json.parse(latest_release_data) + end) + stub(lime_mesh_upgrade, 'start_main_node_repository', function() + end) + stub(eupgrade, '_get_current_fw_version', function() + + end) + local dest = "/tmp/www" .. lime_mesh_upgrade.FIRMWARE_REPO_PATH + -- Delete previous links if exist + os.execute("rm -rf /tmp/www/lros/") + lime_mesh_upgrade.FIRMWARE_SHARED_FOLDER = "/tmp/" + local res = lime_mesh_upgrade.become_main_node('http://repo.librerouter.org/lros/api/v1/') + assert.is.equal(res.code, 'SUCCESS') + local status = lime_mesh_upgrade.get_mesh_upgrade_status() + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.STARTING) + lime_mesh_upgrade.start_firmware_upgrade_transaction() + status = lime_mesh_upgrade.get_mesh_upgrade_status() + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) + assert.is.equal(status.candidate_fw, json.parse(latest_release_data).version) + assert.is.equal(status.board_name, boardname) + assert.is.equal(status.main_node,true) + assert.is.equal(status.main_node,true) + assert.is.equal(status.repo_url,'http://10.1.1.0/lros/') + end) + before_each('', function() snapshot = assert:snapshot() uci = test_utils.setup_test_uci() uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:save('mesh-upgrade') uci:commit('mesh-upgrade') + end) after_each('', function() From 3d8205f1ac02b8c3ebbaf0ce151f778cc437cf17 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Tue, 30 Jan 2024 15:41:54 -0300 Subject: [PATCH 050/102] lime-mesh-upgrade: removes unused requirements --- packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 4d531122b..c18df617c 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -7,10 +7,8 @@ stub(eupgrade, '_get_board_name', function() end) local lime_mesh_upgrade = require 'lime-mesh-upgrade' -local network = require("lime.network") local utils = require "lime.utils" local test_utils = require "tests.utils" -local eup = require "eupgrade" local json = require 'luci.jsonc' local uci From 084b24c909effccffe61222f25a18c4c54e178a6 Mon Sep 17 00:00:00 2001 From: selankon Date: Thu, 1 Feb 2024 16:39:51 +0100 Subject: [PATCH 051/102] mesh-upgrade: refactor to implement get_mesh_upgrade_node_status --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 34 +++++++++++-------- .../files/usr/libexec/rpcd/lime-mesh-upgrade | 20 ++++++----- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 485d502a3..9a28d7ebd 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -131,25 +131,31 @@ function mesh_upgrade.become_main_node(url) } end --- Return eupgrade status for this node and update mesh upgrade status accordingly -function mesh_upgrade.get_main_node_status() +-- Update the state witth an error if eupgrade download failed +function mesh_upgrade.check_eupgrade_download_failed() local download_status = eupgrade.get_download_status() + local upgrade_state = mesh_upgrade.state() - -- Check download is completed - if download_status == eupgrade.STATUS_DEFAULT then - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DEFAULT) - elseif download_status == eupgrade.STATUS_DOWNLOADING then - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) - elseif download_status == eupgrade.STATUS_DOWNLOADED then - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) - elseif download_status == eupgrade.STATUS_DOWNLOAD_FAILED then - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR, mesh_upgrade.errors.DOWNLOAD_FAILED) + if upgrade_state == mesh_upgrade.upgrade_states.STARTING + and download_status == eupgrade.STATUS_DOWNLOAD_FAILED then + mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) end - return { - code = download_status, - } end +-- Function that return the uci data for mesh-upgrade +function mesh_upgrade.get_mesh_upgrade_node_status() + local uci = config.get_uci_cursor() + mesh_upgrade.check_eupgrade_download_failed() + local status = {} + status['timestamp'] = uci:get('mesh-upgrade', 'main', 'timestamp') + status['master_node'] = uci:get('mesh-upgrade', 'main', 'master_node') + status['error'] = uci:get('mesh-upgrade', 'main', 'error') + status['transaction_state'] = uci:get('mesh-upgrade', 'main', 'transaction_state') + status['upgrade_state'] = mesh_upgrade.state() + return status +end + + function mesh_upgrade.start_firmware_upgrade_transaction() -- todo(kon): do all needed checks also with the main node state etc.. -- Expose eupgrade folder to uhttp (this is the best place to do it since diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade index 66473c516..1dd60a744 100755 --- a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade @@ -20,13 +20,15 @@ local function become_main_node(msg) return utils.printJson(result) end -local function get_main_node_status(msg) - local result = mesh_upgrade.get_main_node_status(msg) +local function start_firmware_upgrade_transaction(msg) + local result = mesh_upgrade.start_firmware_upgrade_transaction() return utils.printJson(result) end -local function start_firmware_upgrade_transaction(msg) - local result = mesh_upgrade.start_firmware_upgrade_transaction() +-- It gets the mesh upgrade status for this node +-- Shortcut to get the status without await the shared state synchronization +local function get_mesh_upgrade_node_status(msg) + local result = mesh_upgrade.get_mesh_upgrade_node_status(msg) return utils.printJson(result) end @@ -34,10 +36,10 @@ local methods = { become_main_node = { url = 'value' }, - get_main_node_status = { + start_firmware_upgrade_transaction = { no_params = 0 }, - start_firmware_upgrade_transaction = { + get_mesh_upgrade_node_status = { no_params = 0 } } @@ -51,13 +53,13 @@ if arg[1] == 'call' then msg = json.parse(msg) if arg[2] == 'become_main_node' then become_main_node(msg) - elseif arg[2] == 'get_main_node_status' then - get_main_node_status(msg) elseif arg[2] == 'start_firmware_upgrade_transaction' then start_firmware_upgrade_transaction(msg) + elseif arg[2] == 'get_mesh_upgrade_node_status' then + get_mesh_upgrade_node_status(msg) else utils.printJson({ - error = "Method not foundsss" + error = "Method not found" }) end end From f920940e2327310642491cb91238586079879fe5 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Thu, 1 Feb 2024 13:28:45 -0300 Subject: [PATCH 052/102] lime_mesh_upgrade: adds fwpath --- .../files/etc/config/mesh-upgrade | 3 +- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 131 +++++++++++------- .../tests/test_lime-mesh-upgrade.lua | 29 ++++ 3 files changed, 115 insertions(+), 48 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade index 8681d45b9..37251a399 100644 --- a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade @@ -1,9 +1,10 @@ config mesh-upgrade 'main' option firmware_ver '' option candidate_fw '' + option fw_path '' option repo_url '' option upgrade_state '' option error '0' option timestamp '0' - option master_node 'false' + option main_node 'false' \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 485d502a3..f04c8528d 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -32,7 +32,8 @@ local mesh_upgrade = { DOWNLOAD_FAILED = "download failed", NO_LATEST_AVAILABLE = "no latest data available", CONFIRMATION_TIME_OUT = "confirmation timeout", - ABORTED = "aborted" + ABORTED = "aborted", + FW_FILE_NOT_FOUND = "firmware file not found" }, fw_path = "", @@ -51,19 +52,28 @@ end -- Create a work directory if nor exist function mesh_upgrade._create_workdir(workdir) if not utils.file_exists(workdir) then - os.execute('mkdir -p ' .. workdir .. " >/dev/null") + os.execute('mkdir -p ' .. workdir .. " >/dev/null") end if fs.stat(workdir, "type") ~= "dir" then error("Can't configure workdir " .. workdir) end end +function mesh_upgrade.get_fw_path() + local uci = config.get_uci_cursor() + return uci:get('mesh-upgrade', 'main', 'fw_path') or " " +end + function mesh_upgrade.set_workdir(workdir) mesh_upgrade._create_workdir(workdir) mesh_upgrade.WORKDIR = workdir - mesh_upgrade.LATEST_JSON_FILE_NAME = utils.slugify(eupgrade._get_board_name()) .. ".json" -- latest json with local lan url file name - mesh_upgrade.LATEST_JSON_PATH = mesh_upgrade.WORKDIR .. "/" .. mesh_upgrade.LATEST_JSON_FILE_NAME -- latest json full path - mesh_upgrade.FIRMWARE_REPO_PATH = '/lros/' -- path url for firmwares + mesh_upgrade.LATEST_JSON_FILE_NAME = utils.slugify(eupgrade._get_board_name()) .. + ".json" -- latest json with local lan url file name + mesh_upgrade.LATEST_JSON_PATH = mesh_upgrade.WORKDIR .. + "/" .. + mesh_upgrade.LATEST_JSON_FILE_NAME -- latest json full path + mesh_upgrade.FIRMWARE_REPO_PATH = + '/lros/' -- path url for firmwares mesh_upgrade.FIRMWARE_SHARED_FOLDER = '/www/' .. mesh_upgrade.FIRMWARE_REPO_PATH end @@ -72,11 +82,11 @@ mesh_upgrade.set_workdir("/tmp/mesh_upgrade") function mesh_upgrade.create_local_latest_json(latest_data) for _, im in pairs(latest_data['images']) do -- im['download-urls'] = string.gsub(im['download-urls'], upgrade_url, "test") - im['download-urls'] = {mesh_upgrade.get_repo_base_url() .. im['name']} - end + im['download-urls'] = { mesh_upgrade.get_repo_base_url() .. im['name'] } + end utils.write_file(mesh_upgrade.LATEST_JSON_PATH, json.stringify(latest_data)) -- For the moment mesh upgrade will ignore the latest json signature on de main nodes - -- todo: add signature file with a valid signature... or review the signing process. + -- todo: add signature file with a valid signature... or review the signing process. end function mesh_upgrade.share_firmware_packages(dest) @@ -87,11 +97,11 @@ function mesh_upgrade.share_firmware_packages(dest) mesh_upgrade._create_workdir(dest) -- json file has to be placed in a url that ends with latest mesh_upgrade._create_workdir(dest .. "/latest") - os.execute("ln -s " .. images_folder .. "/* " .. dest.. " >/dev/null") + os.execute("ln -s " .. images_folder .. "/* " .. dest .. " >/dev/null") os.execute("ln -s " .. mesh_upgrade.LATEST_JSON_PATH .. " " .. dest .. "/latest >/dev/null") - os.execute("chmod -R 777 ".. dest .." >/dev/null") - os.execute("chmod -R 777 ".. mesh_upgrade.WORKDIR .." >/dev/null") - os.execute("chmod -R 777 ".. images_folder .." >/dev/null") + os.execute("chmod -R 777 " .. dest .. " >/dev/null") + os.execute("chmod -R 777 " .. mesh_upgrade.WORKDIR .. " >/dev/null") + os.execute("chmod -R 777 " .. images_folder .. " >/dev/null") end -- This function will download latest firmware and expose it as @@ -104,7 +114,7 @@ end --- Function that check if tihs node have all things needed to became a main node --- Then, call update shared state with the proper info --- @url optional new url to get the firmware for local repo +-- @url optional new url to get the firmware for local repo function mesh_upgrade.become_main_node(url) if url then eupgrade.set_custom_api_url(url) @@ -143,10 +153,11 @@ function mesh_upgrade.get_main_node_status() elseif download_status == eupgrade.STATUS_DOWNLOADED then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) elseif download_status == eupgrade.STATUS_DOWNLOAD_FAILED then - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR, mesh_upgrade.errors.DOWNLOAD_FAILED) + mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) end return { code = download_status, + error = "" } end @@ -154,6 +165,13 @@ function mesh_upgrade.start_firmware_upgrade_transaction() -- todo(kon): do all needed checks also with the main node state etc.. -- Expose eupgrade folder to uhttp (this is the best place to do it since -- all the files are present) + local download_status = eupgrade.get_download_status() + if download_status ~= eupgrade.STATUS_DOWNLOADED then + return { + code = "NO_FIRMWARE_AVAILABLE", + error = "No new firmware file downloaded" + } + end local latest = eupgrade.is_new_version_available(true) if not latest then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DEFAULT) @@ -189,6 +207,15 @@ function mesh_upgrade.start_firmware_upgrade_transaction() } end +function mesh_upgrade.set_fw_path(image) + mesh_upgrade.fw_path = eupgrade.WORKDIR .. "/" .. image['name'] + local uci = config.get_uci_cursor() + uci:set('mesh-upgrade', 'main', 'fw_path', mesh_upgrade.fw_path) + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') + print(mesh_upgrade.fw_path) +end + -- Shared state functions -- ---------------------------- function mesh_upgrade.report_error(error) @@ -215,13 +242,11 @@ function mesh_upgrade.start_node_download(url) --utils.log("downloading") local image = {} image = eupgrade.download_firmware(latest_data) - --utils.printJson(image) - ----utils.log(mesh_upgrade.fw_path) - ----utils.log(latest_data) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED and image ~= nil then --utils.printJson(image) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) mesh_upgrade.trigger_sheredstate_publish() + mesh_upgrade.set_fw_path(image) else --utils.log("Error ... download failed") mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) @@ -255,8 +280,8 @@ end function mesh_upgrade.started() status = mesh_upgrade.state() if status == mesh_upgrade.upgrade_states.STARTING or status == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING or - status == mesh_upgrade.upgrade_states.CONFIRMED or status == mesh_upgrade.upgrade_states.DOWNLOADING or status == - mesh_upgrade.upgrade_states.READY_FOR_UPGRADE or status == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then + status == mesh_upgrade.upgrade_states.CONFIRMED or status == mesh_upgrade.upgrade_states.DOWNLOADING or status == + mesh_upgrade.upgrade_states.READY_FOR_UPGRADE or status == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then return true end return false @@ -270,14 +295,13 @@ end function mesh_upgrade.mesh_upgrade_abort() mesh_upgrade.report_error(mesh_upgrade.errors.ABORTED) - -- todo(javi): stop and delete everything - + -- todo(javi): stop and delete everything end -- This line will genereate recursive dependencies like in pirania pakcage function mesh_upgrade.trigger_sheredstate_publish() utils.execute_daemonized( - "/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") + "/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") end -- ! changes the state of the upgrade and verifies that state transition is possible. @@ -287,25 +311,25 @@ function mesh_upgrade.change_state(newstate) local uci = config.get_uci_cursor() if newstate == mesh_upgrade.upgrade_states.STARTING and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.DEFAULT and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.ERROR and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.UPDATED then + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.DEFAULT and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.ERROR and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.UPDATED then return false elseif newstate == mesh_upgrade.upgrade_states.DOWNLOADING and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.STARTING then + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.STARTING then return false elseif newstate == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.DOWNLOADING and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.STARTING then + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.DOWNLOADING and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.STARTING then return false elseif newstate == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then return false elseif newstate == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then return false elseif newstate == mesh_upgrade.upgrade_states.UPDATED and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then return false end -- todo(javi): verify other states and return false if it is not possible @@ -367,15 +391,20 @@ function mesh_upgrade.get_mesh_upgrade_status() local upgrade_data = {} upgrade_data.candidate_fw = uci:get('mesh-upgrade', 'main', 'candidate_fw') upgrade_data.repo_url = uci:get('mesh-upgrade', 'main', 'repo_url') - upgrade_data.upgrade_state = uci:get('mesh-upgrade', 'main', 'upgrade_state') + upgrade_data.upgrade_state = uci:get('mesh-upgrade', 'main', 'upgrade_state') if (upgrade_data.upgrade_state == nil) then - uci:set('mesh-upgrade', 'main', 'transaction_state', mesh_upgrade.upgrade_states.DEFAULT) + uci:set('mesh-upgrade', 'main', 'upgrade_state', mesh_upgrade.upgrade_states.DEFAULT) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') - upgrade_data.upgrade_state = uci:get('mesh-upgrade', 'main', 'transaction_state') end + if (state == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) then + if (tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) > 1) then + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.CONFIRMATION_PENDING) + end + end + upgrade_data.upgrade_state = uci:get('mesh-upgrade', 'main', 'upgrade_state') upgrade_data.error = uci:get('mesh-upgrade', 'main', 'error') - upgrade_data.timestamp = uci:get('mesh-upgrade', 'main', 'timestamp') + upgrade_data.timestamp = tonumber(uci:get('mesh-upgrade', 'main', 'timestamp')) upgrade_data.main_node = mesh_upgrade.toboolean(uci:get('mesh-upgrade', 'main', 'main_node')) upgrade_data.board_name = eupgrade._get_board_name() upgrade_data.current_fw = eupgrade._get_current_fw_version() @@ -383,20 +412,28 @@ function mesh_upgrade.get_mesh_upgrade_status() end function mesh_upgrade.start_safe_upgrade() - if mesh_upgrade.state() == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE and utils.file_exists(mesh_upgrade.fw_path) then - -- perform safe upgrade preserving config and rebooting after 600 sec if - -- no confirmation is received - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHELUDED) - mesh_upgrade.trigger_sheredstate_publish() - utils.execute_daemonized("safe-upgrade upgrade --reboot-safety-timeout=600 " .. mesh_upgrade.fw_path) - return { - code = "SUCCESS" - } + if mesh_upgrade.state() == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then + if utils.file_exists(mesh_upgrade.get_fw_path()) then + -- perform safe upgrade preserving config and rebooting after 600 sec if + -- no confirmation is received + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHELUDED) + mesh_upgrade.trigger_sheredstate_publish() + utils.execute_daemonized("safe-upgrade upgrade --reboot-safety-timeout=600 " .. mesh_upgrade.get_fw_path()) + return { + code = "SUCCESS" + } + else + --utils.log("not able to start upgrade invalid state or firmware not found") + mesh_upgrade.report_error(mesh_upgrade.errors.FW_FILE_NOT_FOUND) + return { + code = "NOT_ABLE_TO_START_UPGRADE", + error = "Firmware not found" + } + end else - --utils.log("not able to start upgrade invalid state or firmware not found") return { - code = "NOT_ABLE_TO_START_UPGRADE", - error = "Firmware not found" + code = "NOT_READY_FOR_UPGRADE", + error = "Not READY FOR UPGRADE" } end end diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 4d531122b..4f49647bf 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -150,6 +150,35 @@ describe('LiMe mesh upgrade', function() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) end) + it('test get fw path', function() + + local fw_path = lime_mesh_upgrade.get_fw_path() + assert.is.equal(fw_path, " ") + + stub(eupgrade, '_get_current_fw_version', function() + return 'LibreMesh 19.05' + end) + stub(eupgrade, '_check_signature', function() + return true + end) + stub(utils, 'http_client_get', function() + return latest_release_data + end) + stub(eupgrade, '_file_sha256', function() + return 'cec8920f93055cc57cfde1f87968e33ca5215b2df88611684195077402079acb' + end) + + lime_mesh_upgrade.become_bot_node(upgrade_data) + status = lime_mesh_upgrade.get_mesh_upgrade_status() + assert.is.equal(status.main_node, upgrade_data.main_node) + assert.is.equal(status.repo_url, upgrade_data.repo_url) + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) + + local fw_path = lime_mesh_upgrade.get_fw_path() + assert.is.equal(fw_path, '/tmp/eupgrades/upgrade-lr-1.5.sh') + + end) + it('test become main node changes the state to STARTING', function() stub(eupgrade, 'is_new_version_available', function() return json.parse(latest_release_data) From b27caa55ebbbfae88bbe877441e97039f927f977 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Thu, 1 Feb 2024 16:56:44 -0300 Subject: [PATCH 053/102] lime-mesh-upgrade: add eupgrade status and more rpc --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 18 ++++++++++++--- .../files/usr/libexec/rpcd/lime-mesh-upgrade | 23 ++++++++++++++++++- .../tests/test_lime-mesh-upgrade.lua | 21 ++++++++--------- .../shared-state-publish_mesh_wide_upgrade | 2 +- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 93f6eeb0c..d4f51a718 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -110,6 +110,7 @@ function mesh_upgrade.start_main_node_repository(latest_data) -- Create local repository json data mesh_upgrade.create_local_latest_json(latest_data) utils.execute_daemonized("eupgrade-download >/dev/null") + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) end --- Function that check if tihs node have all things needed to became a main node @@ -146,7 +147,7 @@ function mesh_upgrade.check_eupgrade_download_failed() local download_status = eupgrade.get_download_status() local upgrade_state = mesh_upgrade.state() - if upgrade_state == mesh_upgrade.upgrade_states.STARTING + if upgrade_state == mesh_upgrade.upgrade_states.DOWNLOADING and download_status == eupgrade.STATUS_DOWNLOAD_FAILED then mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) end @@ -158,6 +159,7 @@ function mesh_upgrade.start_firmware_upgrade_transaction() -- all the files are present) local download_status = eupgrade.get_download_status() if download_status ~= eupgrade.STATUS_DOWNLOADED then + mesh_upgrade.check_eupgrade_download_failed() return { code = "NO_FIRMWARE_AVAILABLE", error = "No new firmware file downloaded" @@ -171,6 +173,7 @@ function mesh_upgrade.start_firmware_upgrade_transaction() error = "No new version is available" } end + mesh_upgrade.set_fw_path(latest['images'][1]) mesh_upgrade.share_firmware_packages() -- Check if local json file exists if not utils.file_exists(mesh_upgrade.LATEST_JSON_PATH) then @@ -380,7 +383,6 @@ end function mesh_upgrade.get_node_status() local uci = config.get_uci_cursor() local upgrade_data = {} - mesh_upgrade.check_eupgrade_download_failed() upgrade_data.candidate_fw = uci:get('mesh-upgrade', 'main', 'candidate_fw') upgrade_data.repo_url = uci:get('mesh-upgrade', 'main', 'repo_url') upgrade_data.upgrade_state = uci:get('mesh-upgrade', 'main', 'upgrade_state') @@ -389,6 +391,10 @@ function mesh_upgrade.get_node_status() uci:save('mesh-upgrade') uci:commit('mesh-upgrade') end + if (state == mesh_upgrade.upgrade_states.DOWNLOADING) then + mesh_upgrade.check_eupgrade_download_failed() + end + upgrade_data.eupgradestate = eupgrade.get_download_status() if (state == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) then if (tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) > 1) then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.CONFIRMATION_PENDING) @@ -408,6 +414,7 @@ function mesh_upgrade.start_safe_upgrade() if utils.file_exists(mesh_upgrade.get_fw_path()) then -- perform safe upgrade preserving config and rebooting after 600 sec if -- no confirmation is received + -- todo: javier first veryfy image mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHELUDED) mesh_upgrade.trigger_sheredstate_publish() utils.execute_daemonized("safe-upgrade upgrade --reboot-safety-timeout=600 " .. mesh_upgrade.get_fw_path()) @@ -447,13 +454,18 @@ end -- option root_password_secret '' -- option deferable_reboot_uptime_s '97200' function mesh_upgrade.confirm() - if mesh_upgrade.state() == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then + if mesh_upgrade.get_node_status().upgrade_state == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then local shell_output = utils.unsafe_shell("safe-upgrade confirm") mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPDATED) --utils.log(shell_output) return { code = "SUCCESS" } + else + return { + code = "NOT_READY_TO_CONFIRM", + error = "NOT_READY_TO_CONFIRM" + } end end diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade index 532c030b0..6066e76c8 100755 --- a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade @@ -28,7 +28,17 @@ end -- It gets the mesh upgrade status for this node -- Shortcut to get the status without await the shared state synchronization local function get_mesh_upgrade_node_status(msg) - local result = mesh_upgrade.get_node_status(msg) + local result = mesh_upgrade.get_node_status() + return utils.printJson(result) +end + +local function start_safe_upgrade(msg) + local result = mesh_upgrade.start_safe_upgrade() + return utils.printJson(result) +end +-- to be called after successfully reboot +local function confirm(msg) + local result = mesh_upgrade.confirm() return utils.printJson(result) end @@ -41,7 +51,14 @@ local methods = { }, get_mesh_upgrade_node_status = { no_params = 0 + }, + start_safe_upgrade = { + no_params = 0 + }, + confirm_boot_partition = { + no_params = 0 } + } if arg[1] == 'list' then @@ -57,6 +74,10 @@ if arg[1] == 'call' then start_firmware_upgrade_transaction(msg) elseif arg[2] == 'get_mesh_upgrade_node_status' then get_mesh_upgrade_node_status(msg) + elseif arg[2] == 'start_safe_upgrade' then + start_safe_upgrade(msg) + elseif arg[2] == 'confirm_boot_partition' then + confirm(msg) else utils.printJson({ error = "Method not found" diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 4f49647bf..ca5223de1 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -60,7 +60,7 @@ describe('LiMe mesh upgrade', function() stub(eupgrade, '_get_current_fw_version', function() return fw_version end) - local status = lime_mesh_upgrade.get_mesh_upgrade_status() + local status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.DEFAULT) assert.is.equal(status.main_node, false) assert.is.equal(status.current_fw, fw_version) @@ -73,7 +73,7 @@ describe('LiMe mesh upgrade', function() return 'LibreMesh 19.05' end) lime_mesh_upgrade.report_error(lime_mesh_upgrade.errors.CONFIRMATION_TIME_OUT) - status = lime_mesh_upgrade.get_mesh_upgrade_status() + status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.error, lime_mesh_upgrade.errors.CONFIRMATION_TIME_OUT) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) end) @@ -83,7 +83,7 @@ describe('LiMe mesh upgrade', function() return 'LibreMesh 19.05' end) lime_mesh_upgrade.mesh_upgrade_abort() - status = lime_mesh_upgrade.get_mesh_upgrade_status() + status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) assert.is.equal(status.error, lime_mesh_upgrade.errors.ABORTED) end) @@ -99,7 +99,7 @@ describe('LiMe mesh upgrade', function() return 'LibreMesh 1.4' end) lime_mesh_upgrade.become_bot_node(upgrade_data) - status = lime_mesh_upgrade.get_mesh_upgrade_status() + status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.main_node, false) assert.is.equal(status.repo_url, upgrade_data.repo_url) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) @@ -121,7 +121,7 @@ describe('LiMe mesh upgrade', function() end) assert.is.equal('LibreRouterOs 1.5', eupgrade.is_new_version_available()['version']) lime_mesh_upgrade.become_bot_node(upgrade_data) - status = lime_mesh_upgrade.get_mesh_upgrade_status() + status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.main_node, false) assert.is.equal(status.repo_url, upgrade_data.repo_url) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) @@ -144,7 +144,7 @@ describe('LiMe mesh upgrade', function() assert.is.equal('LibreRouterOs 1.5', eupgrade.is_new_version_available()['version']) lime_mesh_upgrade.become_bot_node(upgrade_data) - status = lime_mesh_upgrade.get_mesh_upgrade_status() + status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.main_node, upgrade_data.main_node) assert.is.equal(status.repo_url, upgrade_data.repo_url) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) @@ -169,11 +169,10 @@ describe('LiMe mesh upgrade', function() end) lime_mesh_upgrade.become_bot_node(upgrade_data) - status = lime_mesh_upgrade.get_mesh_upgrade_status() + status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.main_node, upgrade_data.main_node) assert.is.equal(status.repo_url, upgrade_data.repo_url) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) - local fw_path = lime_mesh_upgrade.get_fw_path() assert.is.equal(fw_path, '/tmp/eupgrades/upgrade-lr-1.5.sh') @@ -189,7 +188,7 @@ describe('LiMe mesh upgrade', function() end) local res = lime_mesh_upgrade.become_main_node() assert.is.equal(res.code, 'SUCCESS') - local status = lime_mesh_upgrade.get_mesh_upgrade_status() + local status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.STARTING) end) @@ -273,10 +272,10 @@ describe('LiMe mesh upgrade', function() lime_mesh_upgrade.FIRMWARE_SHARED_FOLDER = "/tmp/" local res = lime_mesh_upgrade.become_main_node('http://repo.librerouter.org/lros/api/v1/') assert.is.equal(res.code, 'SUCCESS') - local status = lime_mesh_upgrade.get_mesh_upgrade_status() + local status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.STARTING) lime_mesh_upgrade.start_firmware_upgrade_transaction() - status = lime_mesh_upgrade.get_mesh_upgrade_status() + status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) assert.is.equal(status.candidate_fw, json.parse(latest_release_data).version) assert.is.equal(status.board_name, boardname) diff --git a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade index b9ad56594..5da94eed9 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade @@ -24,7 +24,7 @@ local mesh_upgrade = require "lime-mesh-upgrade" local hostname = utils.hostname() function report_upgrade_status() - return mesh_upgrade.get_mesh_upgrade_status() + return mesh_upgrade.get_node_status() end local result = { [hostname] = report_upgrade_status() } From 4be266e392787e2bf65d0f3ccffa928414a24184 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 2 Feb 2024 14:37:07 +0100 Subject: [PATCH 054/102] mesh-upgrade: refactor for name consistency --- .../files/usr/libexec/rpcd/lime-mesh-upgrade | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade index 6066e76c8..f7e1c1a02 100755 --- a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade @@ -27,7 +27,7 @@ end -- It gets the mesh upgrade status for this node -- Shortcut to get the status without await the shared state synchronization -local function get_mesh_upgrade_node_status(msg) +local function get_node_status(msg) local result = mesh_upgrade.get_node_status() return utils.printJson(result) end @@ -49,7 +49,7 @@ local methods = { start_firmware_upgrade_transaction = { no_params = 0 }, - get_mesh_upgrade_node_status = { + get_node_status = { no_params = 0 }, start_safe_upgrade = { @@ -72,8 +72,8 @@ if arg[1] == 'call' then become_main_node(msg) elseif arg[2] == 'start_firmware_upgrade_transaction' then start_firmware_upgrade_transaction(msg) - elseif arg[2] == 'get_mesh_upgrade_node_status' then - get_mesh_upgrade_node_status(msg) + elseif arg[2] == 'get_node_status' then + get_node_status(msg) elseif arg[2] == 'start_safe_upgrade' then start_safe_upgrade(msg) elseif arg[2] == 'confirm_boot_partition' then From e66d0714591395be7e99e601d63cd76fdcf39cc7 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 2 Feb 2024 14:55:48 +0100 Subject: [PATCH 055/102] mesh-upgrade: return eupgrade status on check_eupgrade_download_failed On this way we can avoid succesive calls to eupgrade.getDownloadStatus --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index d4f51a718..e75161a18 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -143,6 +143,7 @@ function mesh_upgrade.become_main_node(url) end -- Update the state witth an error if eupgrade download failed +-- It returns the download status function mesh_upgrade.check_eupgrade_download_failed() local download_status = eupgrade.get_download_status() local upgrade_state = mesh_upgrade.state() @@ -151,15 +152,15 @@ function mesh_upgrade.check_eupgrade_download_failed() and download_status == eupgrade.STATUS_DOWNLOAD_FAILED then mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) end + return download_status end function mesh_upgrade.start_firmware_upgrade_transaction() -- todo(kon): do all needed checks also with the main node state etc.. -- Expose eupgrade folder to uhttp (this is the best place to do it since -- all the files are present) - local download_status = eupgrade.get_download_status() + local download_status = mesh_upgrade.check_eupgrade_download_failed() if download_status ~= eupgrade.STATUS_DOWNLOADED then - mesh_upgrade.check_eupgrade_download_failed() return { code = "NO_FIRMWARE_AVAILABLE", error = "No new firmware file downloaded" @@ -385,16 +386,13 @@ function mesh_upgrade.get_node_status() local upgrade_data = {} upgrade_data.candidate_fw = uci:get('mesh-upgrade', 'main', 'candidate_fw') upgrade_data.repo_url = uci:get('mesh-upgrade', 'main', 'repo_url') + upgrade_data.eupgradestate = mesh_upgrade.check_eupgrade_download_failed() upgrade_data.upgrade_state = uci:get('mesh-upgrade', 'main', 'upgrade_state') if (upgrade_data.upgrade_state == nil) then uci:set('mesh-upgrade', 'main', 'upgrade_state', mesh_upgrade.upgrade_states.DEFAULT) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') end - if (state == mesh_upgrade.upgrade_states.DOWNLOADING) then - mesh_upgrade.check_eupgrade_download_failed() - end - upgrade_data.eupgradestate = eupgrade.get_download_status() if (state == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) then if (tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) > 1) then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.CONFIRMATION_PENDING) From d7ea20fea1c51768e54c221de2d4871c2b9b6252 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 2 Feb 2024 14:57:35 +0100 Subject: [PATCH 056/102] mesh-upgrade: prevent mesh_upgrade.state nill state --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index e75161a18..68413eefd 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -285,7 +285,14 @@ end function mesh_upgrade.state() local uci = config.get_uci_cursor() - return uci:get('mesh-upgrade', 'main', 'upgrade_state') or mesh_upgrade.upgrade_states.DEFAULT + local upgrade_state = uci:get('mesh-upgrade', 'main', 'upgrade_state') + if (upgrade_state == nil) then + uci:set('mesh-upgrade', 'main', 'upgrade_state', mesh_upgrade.upgrade_states.DEFAULT) + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') + return mesh_upgrade.upgrade_states.DEFAULT + end + return upgrade_state end function mesh_upgrade.mesh_upgrade_abort() @@ -387,12 +394,7 @@ function mesh_upgrade.get_node_status() upgrade_data.candidate_fw = uci:get('mesh-upgrade', 'main', 'candidate_fw') upgrade_data.repo_url = uci:get('mesh-upgrade', 'main', 'repo_url') upgrade_data.eupgradestate = mesh_upgrade.check_eupgrade_download_failed() - upgrade_data.upgrade_state = uci:get('mesh-upgrade', 'main', 'upgrade_state') - if (upgrade_data.upgrade_state == nil) then - uci:set('mesh-upgrade', 'main', 'upgrade_state', mesh_upgrade.upgrade_states.DEFAULT) - uci:save('mesh-upgrade') - uci:commit('mesh-upgrade') - end + upgrade_data.upgrade_state = mesh_upgrade.state() if (state == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) then if (tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) > 1) then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.CONFIRMATION_PENDING) From 49c74494acb4d1c78337d684621c3ef2816a4207 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 2 Feb 2024 16:16:30 +0100 Subject: [PATCH 057/102] mesh-upgrade: deprecate STARTING state And implement main node status --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 82 ++++++++++++------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 68413eefd..4bb6adaa0 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -18,7 +18,6 @@ local mesh_upgrade = { -- posible upgrade states enumeration upgrade_states = { DEFAULT = "DEFAULT", -- When no upgrade has started, after reboot - STARTING = "STARTING", DOWNLOADING = "DOWNLOADING", READY_FOR_UPGRADE = "READY_FOR_UPGRADE", UPGRADE_SCHEDULED = "UPGRADE_SCHEDULED", @@ -26,7 +25,12 @@ local mesh_upgrade = { CONFIRMED = "CONFIRMED", ERROR = "ERROR" }, - + -- Master node specific states + main_node_states = { + NO = "NO", + STARTING = "STARTING", + MAIN_NODE = "MAIN_NODE" + }, -- list of possible errors errors = { DOWNLOAD_FAILED = "download failed", @@ -123,7 +127,6 @@ function mesh_upgrade.become_main_node(url) -- todo(kon): check if main node is already set or we are on mesh_upgrade status -- todo(kon): dont start again if status is started and eupgrade is downloaded for example -- Check if there are a new version available (cached only) - --mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) -- 1. Check if new version is available and download it demonized using eupgrade local latest = eupgrade.is_new_version_available(false) if not latest then @@ -135,7 +138,8 @@ function mesh_upgrade.become_main_node(url) end -- 2. Start local repository and download latest firmware mesh_upgrade.start_main_node_repository(latest) - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.STARTING) + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) + mesh_upgrade.change_main_node_state(mesh_upgrade.main_node_states.STARTING) return { code = "SUCCESS", error = "" @@ -257,14 +261,15 @@ end -- curl -6 'http://[fe80::a8aa:aaff:fe0d:feaa%lime_br0]/fw/resolv.conf' -- curl -6 'http://[fd0d:fe46:8ce8::1]/lros/api/v1/' function mesh_upgrade.inform_download_location(version) - if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED then + if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED + and mesh_upgrade.mesh_upgrade.main_node_state() == mesh_upgrade.main_node_states.STARTING then -- TODO: setup uhttpd to serve workdir location mesh_upgrade.set_mesh_upgrade_info({ candidate_fw = version, repo_url = mesh_upgrade.get_repo_base_url(), upgrde_state = mesh_upgrade.upgrade_states.READY_FOR_UPGRADE, error = "", - main_node = true, + main_node = mesh_upgrade.main_node_states.MAIN_NODE, board_name = eupgrade._get_board_name(), current_fw = eupgrade._get_current_fw_version() }, mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) @@ -274,11 +279,7 @@ end -- Validate if the upgrade has already started function mesh_upgrade.started() status = mesh_upgrade.state() - if status == mesh_upgrade.upgrade_states.STARTING or status == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING or - status == mesh_upgrade.upgrade_states.CONFIRMED or status == mesh_upgrade.upgrade_states.DOWNLOADING or status == - mesh_upgrade.upgrade_states.READY_FOR_UPGRADE or status == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then - return true - end + if status == mesh_upgrade.upgrade_states.DEFAULT then return false end return false -- todo(javi): what happens if a mesh_upgrade has started more than an hour ago ? should this node abort it ? end @@ -295,6 +296,18 @@ function mesh_upgrade.state() return upgrade_state end +function mesh_upgrade.main_node_state() + local uci = config.get_uci_cursor() + local main_node_state = uci:get('mesh-upgrade', 'main', 'main_node') + if (main_node_state == nil) then + uci:set('mesh-upgrade', 'main', 'main_node', mesh_upgrade.main_node_states.NO) + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') + return mesh_upgrade.main_node_states.NO + end + return main_node_state +end + function mesh_upgrade.mesh_upgrade_abort() mesh_upgrade.report_error(mesh_upgrade.errors.ABORTED) -- todo(javi): stop and delete everything @@ -306,23 +319,36 @@ function mesh_upgrade.trigger_sheredstate_publish() "/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") end +function mesh_upgrade.change_main_node_state(newstate) + local main_node_state = mesh_upgrade.main_node_state() + if newstate == main_node_state then return false end + + if newstate == mesh_upgrade.main_node_states.STARTING and + main_node_state ~= mesh_upgrade.main_node_states.NO then + return false + elseif newstate == mesh_upgrade.main_node_states.MAIN_NODE and + main_node_state ~= mesh_upgrade.main_node_states.STARTING then + return false + end + uci:set('mesh-upgrade', 'main', 'main_node', newstate) + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') + return true +end + -- ! changes the state of the upgrade and verifies that state transition is possible. function mesh_upgrade.change_state(newstate) -- If the state is the same just return if newstate == mesh_upgrade.state() then return false end local uci = config.get_uci_cursor() - if newstate == mesh_upgrade.upgrade_states.STARTING and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.DEFAULT and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.ERROR and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.UPDATED then - return false - elseif newstate == mesh_upgrade.upgrade_states.DOWNLOADING and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.STARTING then + if newstate == mesh_upgrade.upgrade_states.DOWNLOADING and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.DEFAULT and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.ERROR and + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.UPDATED then return false elseif newstate == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.DOWNLOADING and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.STARTING then + mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.DOWNLOADING then return false elseif newstate == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED and mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then @@ -343,15 +369,11 @@ function mesh_upgrade.change_state(newstate) end function mesh_upgrade.become_bot_node(upgrade_data) - if mesh_upgrade.started() then + if mesh_upgrade.started() then return end - else - upgrade_data.main_node = false - mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.STARTING) - if (mesh_upgrade.state() == mesh_upgrade.upgrade_states.STARTING) then - mesh_upgrade.start_node_download(upgrade_data.repo_url) - end - end + upgrade_data.main_node = false + mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.DOWNLOADING) + mesh_upgrade.start_node_download(upgrade_data.repo_url) end -- set download information for the new firmware from main node @@ -367,7 +389,7 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state) uci:set('mesh-upgrade', 'main', 'candidate_fw', upgrade_data.candidate_fw) uci:set('mesh-upgrade', 'main', 'error', "") uci:set('mesh-upgrade', 'main', 'timestamp', os.time()) - uci:set('mesh-upgrade', 'main', 'main_node', tostring(upgrade_data.main_node)) + uci:set('mesh-upgrade', 'main', 'main_node', upgrade_data.main_node) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') -- trigger shared state data refresh @@ -403,7 +425,7 @@ function mesh_upgrade.get_node_status() upgrade_data.upgrade_state = uci:get('mesh-upgrade', 'main', 'upgrade_state') upgrade_data.error = uci:get('mesh-upgrade', 'main', 'error') upgrade_data.timestamp = tonumber(uci:get('mesh-upgrade', 'main', 'timestamp')) - upgrade_data.main_node = mesh_upgrade.toboolean(uci:get('mesh-upgrade', 'main', 'main_node')) + upgrade_data.main_node = mesh_upgrade.main_node_state() upgrade_data.board_name = eupgrade._get_board_name() upgrade_data.current_fw = eupgrade._get_current_fw_version() return upgrade_data From e9e5dd942b19bc69d8270214974c8cfd15df35b3 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 2 Feb 2024 16:18:43 +0100 Subject: [PATCH 058/102] mesh-upgrade: improve code --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 4bb6adaa0..94fe02cd8 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -338,26 +338,27 @@ end -- ! changes the state of the upgrade and verifies that state transition is possible. function mesh_upgrade.change_state(newstate) + local actual_state = mesh_upgrade.state() -- If the state is the same just return - if newstate == mesh_upgrade.state() then return false end + if newstate == actual_state then return false end local uci = config.get_uci_cursor() if newstate == mesh_upgrade.upgrade_states.DOWNLOADING and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.DEFAULT and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.ERROR and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.UPDATED then + actual_state ~= mesh_upgrade.upgrade_states.DEFAULT and + actual_state ~= mesh_upgrade.upgrade_states.ERROR and + actual_state ~= mesh_upgrade.upgrade_states.UPDATED then return false elseif newstate == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.DOWNLOADING then + actual_state ~= mesh_upgrade.upgrade_states.DOWNLOADING then return false elseif newstate == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then + actual_state ~= mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then return false elseif newstate == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then + actual_state ~= mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then return false elseif newstate == mesh_upgrade.upgrade_states.UPDATED and - mesh_upgrade.state() ~= mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then + actual_state ~= mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then return false end -- todo(javi): verify other states and return false if it is not possible From d98467454a447fee2db65907b946c3f22c143e9d Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 2 Feb 2024 16:29:14 +0100 Subject: [PATCH 059/102] mesh-upgrade: upgrade mesh_upgrade main node initial state --- packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade | 2 +- .../lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade index 37251a399..3679eb214 100644 --- a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade @@ -6,5 +6,5 @@ config mesh-upgrade 'main' option upgrade_state '' option error '0' option timestamp '0' - option main_node 'false' + option main_node 'NO' \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 94fe02cd8..e0107ce4b 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -372,7 +372,7 @@ end function mesh_upgrade.become_bot_node(upgrade_data) if mesh_upgrade.started() then return end - upgrade_data.main_node = false + upgrade_data.main_node = mesh_upgrade.main_node_states.NO mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.DOWNLOADING) mesh_upgrade.start_node_download(upgrade_data.repo_url) end From 889b46d41c7da7bb6d67bb57ac50dbbd5abe43e4 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 2 Feb 2024 16:36:51 +0100 Subject: [PATCH 060/102] mesh-upgrade: fix wrong uci cursor --- .../lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index e0107ce4b..15799892e 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -330,6 +330,8 @@ function mesh_upgrade.change_main_node_state(newstate) main_node_state ~= mesh_upgrade.main_node_states.STARTING then return false end + + local uci = config.get_uci_cursor() uci:set('mesh-upgrade', 'main', 'main_node', newstate) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') @@ -342,7 +344,6 @@ function mesh_upgrade.change_state(newstate) -- If the state is the same just return if newstate == actual_state then return false end - local uci = config.get_uci_cursor() if newstate == mesh_upgrade.upgrade_states.DOWNLOADING and actual_state ~= mesh_upgrade.upgrade_states.DEFAULT and actual_state ~= mesh_upgrade.upgrade_states.ERROR and @@ -363,6 +364,7 @@ function mesh_upgrade.change_state(newstate) end -- todo(javi): verify other states and return false if it is not possible -- lets allow all types of state changes. + local uci = config.get_uci_cursor() uci:set('mesh-upgrade', 'main', 'upgrade_state', newstate) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') From 0a9e85124f2230c8205cfc2c456b0d4c1b847e48 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 2 Feb 2024 16:39:48 +0100 Subject: [PATCH 061/102] mesh-upgrade: prevent start mesh wide transaction If main node not started --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 15799892e..203a4ac76 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -163,6 +163,12 @@ function mesh_upgrade.start_firmware_upgrade_transaction() -- todo(kon): do all needed checks also with the main node state etc.. -- Expose eupgrade folder to uhttp (this is the best place to do it since -- all the files are present) + if mesh_upgrade.main_node_state() ~= mesh_upgrade.main_node_states.STARTING then + return { + code = "BAD_NODE_STATE", + error = "This node main state status is not starting" + } + end local download_status = mesh_upgrade.check_eupgrade_download_failed() if download_status ~= eupgrade.STATUS_DOWNLOADED then return { From 183a13191626d4c5e882a431a7198ba8f4e12b3a Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 5 Feb 2024 15:04:22 -0300 Subject: [PATCH 062/102] mesh-upgrade: fixes tests and incorporates config persistence --- .../lib/upgrade/keep.d/lime-mesh-upgrade | 1 + .../tests/test_lime-mesh-upgrade.lua | 68 ++++++++++++++++--- .../hooks/mesh_wide_upgrade/start_upgrade | 2 +- 3 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 packages/lime-mesh-upgrade/files/lib/upgrade/keep.d/lime-mesh-upgrade diff --git a/packages/lime-mesh-upgrade/files/lib/upgrade/keep.d/lime-mesh-upgrade b/packages/lime-mesh-upgrade/files/lib/upgrade/keep.d/lime-mesh-upgrade new file mode 100644 index 000000000..12034c27f --- /dev/null +++ b/packages/lime-mesh-upgrade/files/lib/upgrade/keep.d/lime-mesh-upgrade @@ -0,0 +1 @@ +/etc/config/mesh-upgrade diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index ca5223de1..f00728d25 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -62,7 +62,7 @@ describe('LiMe mesh upgrade', function() end) local status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.DEFAULT) - assert.is.equal(status.main_node, false) + assert.is.equal(status.main_node, lime_mesh_upgrade.main_node_states.NO) assert.is.equal(status.current_fw, fw_version) assert.is.equal(status.board_name, boardname) assert.is.equal(lime_mesh_upgrade.started(), false) @@ -100,7 +100,7 @@ describe('LiMe mesh upgrade', function() end) lime_mesh_upgrade.become_bot_node(upgrade_data) status = lime_mesh_upgrade.get_node_status() - assert.is.equal(status.main_node, false) + assert.is.equal(status.main_node, lime_mesh_upgrade.main_node_states.NO) assert.is.equal(status.repo_url, upgrade_data.repo_url) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) assert.is.equal(status.error, lime_mesh_upgrade.errors.NO_LATEST_AVAILABLE) @@ -122,7 +122,7 @@ describe('LiMe mesh upgrade', function() assert.is.equal('LibreRouterOs 1.5', eupgrade.is_new_version_available()['version']) lime_mesh_upgrade.become_bot_node(upgrade_data) status = lime_mesh_upgrade.get_node_status() - assert.is.equal(status.main_node, false) + assert.is.equal(status.main_node, lime_mesh_upgrade.main_node_states.NO) assert.is.equal(status.repo_url, upgrade_data.repo_url) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) assert.is.equal(status.error, lime_mesh_upgrade.errors.DOWNLOAD_FAILED) @@ -189,7 +189,8 @@ describe('LiMe mesh upgrade', function() local res = lime_mesh_upgrade.become_main_node() assert.is.equal(res.code, 'SUCCESS') local status = lime_mesh_upgrade.get_node_status() - assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.STARTING) + assert.is.equal(status.main_node, lime_mesh_upgrade.main_node_states.STARTING) + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.DOWNLOADING) end) it('test custom latest json file is created', function() @@ -273,24 +274,75 @@ describe('LiMe mesh upgrade', function() local res = lime_mesh_upgrade.become_main_node('http://repo.librerouter.org/lros/api/v1/') assert.is.equal(res.code, 'SUCCESS') local status = lime_mesh_upgrade.get_node_status() - assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.STARTING) + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.DOWNLOADING) lime_mesh_upgrade.start_firmware_upgrade_transaction() status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) assert.is.equal(status.candidate_fw, json.parse(latest_release_data).version) assert.is.equal(status.board_name, boardname) - assert.is.equal(status.main_node,true) - assert.is.equal(status.main_node,true) + assert.is.equal(status.main_node,lime_mesh_upgrade.main_node_states.MAIN_NODE) assert.is.equal(status.repo_url,'http://10.1.1.0/lros/') end) + it('test start_safe_upgrade default timeouts', function() + + stub(utils, 'execute_daemonized', function () + end) + + stub(lime_mesh_upgrade, 'state', function() + return lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE + end) + + stub(utils, 'file_exists', function() + return true + end) + + stub(utils, 'file_exists', function() + return true + end) + + stub(lime_mesh_upgrade, 'get_fw_path', function() + return "/tmp/foo.bar" + end) + + lime_mesh_upgrade.start_safe_upgrade() + assert.is.equal(lime_mesh_upgrade.su_confirm_timeout,600) + assert.is.equal(lime_mesh_upgrade.su_start_time_out,60) + assert.stub.spy(utils.execute_daemonized).was.called.with("sleep 60; safe-upgrade upgrade --reboot-safety-timeout=600 /tmp/foo.bar") + end) + + it('test start_safe_upgrade different timeouts', function() + stub(utils, 'execute_daemonized', function () + end) + + stub(lime_mesh_upgrade, 'state', function() + return lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE + end) + + stub(utils, 'file_exists', function() + return true + end) + + stub(utils, 'file_exists', function() + return true + end) + + stub(lime_mesh_upgrade, 'get_fw_path', function() + return "/tmp/foo.bar" + end) + + lime_mesh_upgrade.start_safe_upgrade(10,100) + assert.is.equal(lime_mesh_upgrade.su_confirm_timeout,100) + assert.is.equal(lime_mesh_upgrade.su_start_time_out,10) + assert.stub.spy(utils.execute_daemonized).was.called.with("sleep 10; safe-upgrade upgrade --reboot-safety-timeout=100 /tmp/foo.bar") + end) + before_each('', function() snapshot = assert:snapshot() uci = test_utils.setup_test_uci() uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:save('mesh-upgrade') uci:commit('mesh-upgrade') - end) after_each('', function() diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade index e89b8e9b0..e09373d79 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -27,7 +27,7 @@ if not mesh_upgrade.started() then for node, s_s_data in pairs(JSON.parse(io.stdin:read("*all"))) do --if any node has started an upgrade process and start one too? --only fetch the info from the master node publication? - if node ~= hostname and s_s_data.data.main_node then + if node ~= hostname and s_s_data.data.main_node == mesh_upgrade.main_node_states.MAIN_NODE then utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from "' .. s_s_data.data.repo_url .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) mesh_upgrade.become_bot_node(s_s_data.data) From d65a96a5ad9850f38b18e7bec6cdc98c0a7a6bb5 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Tue, 6 Feb 2024 07:36:05 -0300 Subject: [PATCH 063/102] mesh-upgrade: prserve mesh config and set su_timeouts --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 74 +++++++++++++------ 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 203a4ac76..035d21952 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -41,7 +41,8 @@ local mesh_upgrade = { }, fw_path = "", - su_timeout = 600, + su_confirm_timeout = 600, + su_start_time_out = 60, } -- should epgrade be disabled ? @@ -218,7 +219,6 @@ function mesh_upgrade.set_fw_path(image) uci:set('mesh-upgrade', 'main', 'fw_path', mesh_upgrade.fw_path) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') - print(mesh_upgrade.fw_path) end -- Shared state functions -- @@ -239,7 +239,7 @@ function mesh_upgrade.start_node_download(url) local cached_only = false local url2 = eupgrade.get_upgrade_api_url() local latest_data, message = eupgrade.is_new_version_available(cached_only) - --utils.log("start_node_download from " .. url2 ) + --utils.log("start_node_download from " .. url2) if latest_data then --utils.log("start_node_download ") @@ -268,7 +268,7 @@ end -- curl -6 'http://[fd0d:fe46:8ce8::1]/lros/api/v1/' function mesh_upgrade.inform_download_location(version) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED - and mesh_upgrade.mesh_upgrade.main_node_state() == mesh_upgrade.main_node_states.STARTING then + and mesh_upgrade.main_node_state() == mesh_upgrade.main_node_states.STARTING then -- TODO: setup uhttpd to serve workdir location mesh_upgrade.set_mesh_upgrade_info({ candidate_fw = version, @@ -286,7 +286,7 @@ end function mesh_upgrade.started() status = mesh_upgrade.state() if status == mesh_upgrade.upgrade_states.DEFAULT then return false end - return false + return true -- todo(javi): what happens if a mesh_upgrade has started more than an hour ago ? should this node abort it ? end @@ -330,10 +330,10 @@ function mesh_upgrade.change_main_node_state(newstate) if newstate == main_node_state then return false end if newstate == mesh_upgrade.main_node_states.STARTING and - main_node_state ~= mesh_upgrade.main_node_states.NO then + main_node_state ~= mesh_upgrade.main_node_states.NO then return false elseif newstate == mesh_upgrade.main_node_states.MAIN_NODE and - main_node_state ~= mesh_upgrade.main_node_states.STARTING then + main_node_state ~= mesh_upgrade.main_node_states.STARTING then return false end @@ -351,21 +351,21 @@ function mesh_upgrade.change_state(newstate) if newstate == actual_state then return false end if newstate == mesh_upgrade.upgrade_states.DOWNLOADING and - actual_state ~= mesh_upgrade.upgrade_states.DEFAULT and - actual_state ~= mesh_upgrade.upgrade_states.ERROR and - actual_state ~= mesh_upgrade.upgrade_states.UPDATED then + actual_state ~= mesh_upgrade.upgrade_states.DEFAULT and + actual_state ~= mesh_upgrade.upgrade_states.ERROR and + actual_state ~= mesh_upgrade.upgrade_states.UPDATED then return false elseif newstate == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE and - actual_state ~= mesh_upgrade.upgrade_states.DOWNLOADING then + actual_state ~= mesh_upgrade.upgrade_states.DOWNLOADING then return false elseif newstate == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED and - actual_state ~= mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then + actual_state ~= mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then return false elseif newstate == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING and - actual_state ~= mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then + actual_state ~= mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then return false elseif newstate == mesh_upgrade.upgrade_states.UPDATED and - actual_state ~= mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then + actual_state ~= mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then return false end -- todo(javi): verify other states and return false if it is not possible @@ -378,11 +378,15 @@ function mesh_upgrade.change_state(newstate) end function mesh_upgrade.become_bot_node(upgrade_data) - if mesh_upgrade.started() then return end - - upgrade_data.main_node = mesh_upgrade.main_node_states.NO - mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.DOWNLOADING) - mesh_upgrade.start_node_download(upgrade_data.repo_url) + if mesh_upgrade.started() then + --utils.log("started") + return + else + --utils.log("not started") + upgrade_data.main_node = mesh_upgrade.main_node_states.NO + mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.DOWNLOADING) + mesh_upgrade.start_node_download(upgrade_data.repo_url) + end end -- set download information for the new firmware from main node @@ -440,20 +444,42 @@ function mesh_upgrade.get_node_status() return upgrade_data end -function mesh_upgrade.start_safe_upgrade() +function mesh_upgrade.start_safe_upgrade(su_start_time_out, su_confirm_timeout) + mesh_upgrade.su_start_time_out = su_start_time_out or mesh_upgrade.su_start_time_out + mesh_upgrade.su_confirm_timeout = su_confirm_timeout or mesh_upgrade.su_confirm_timeout + if mesh_upgrade.state() == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then if utils.file_exists(mesh_upgrade.get_fw_path()) then -- perform safe upgrade preserving config and rebooting after 600 sec if -- no confirmation is received -- todo: javier first veryfy image + + -- just preserve meshconfig + --os.execute("tar cfz ".. mesh_upgrade.WORKDIR.."/mesh_upgrade_cfg.tgz -C / etc/config/mesh-upgrade") + + -- perform a full config backup including mesh_upgrade config file needed for the next image + -- surprisingly this does not presrve nodename + -- os.execute("sysupgrade -b ".. mesh_upgrade.WORKDIR.."/mesh_upgrade_cfg.tgz") + + config = require("lime.config") + local keep = config.get("system", "keep_on_upgrade", "") + keep = keep .. " lime-mesh-upgrade" + config.set("system", "keep_on_upgrade", keep) --use set but not commit, so this configuration wont be preserved. + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHELUDED) mesh_upgrade.trigger_sheredstate_publish() - utils.execute_daemonized("safe-upgrade upgrade --reboot-safety-timeout=600 " .. mesh_upgrade.get_fw_path()) + --this must be executed after a safe upgrade timeout to enable all nodes to start_safe_upgrade + utils.execute_daemonized("sleep " .. + mesh_upgrade.su_start_time_out .. + "; safe-upgrade upgrade --reboot-safety-timeout=" .. + mesh_upgrade.su_confirm_timeout .. " " .. mesh_upgrade.get_fw_path()) + return { - code = "SUCCESS" + code = "SUCCESS", + error = "" } else - --utils.log("not able to start upgrade invalid state or firmware not found") + ----utils.log("not able to start upgrade invalid state or firmware not found") mesh_upgrade.report_error(mesh_upgrade.errors.FW_FILE_NOT_FOUND) return { code = "NOT_ABLE_TO_START_UPGRADE", @@ -488,7 +514,7 @@ function mesh_upgrade.confirm() if mesh_upgrade.get_node_status().upgrade_state == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then local shell_output = utils.unsafe_shell("safe-upgrade confirm") mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPDATED) - --utils.log(shell_output) + ----utils.log(shell_output) return { code = "SUCCESS" } From 85b4bbbee105d53919bc6496aa8f2a23a3e46a62 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Thu, 22 Feb 2024 17:15:12 -0300 Subject: [PATCH 064/102] mesh-upgrade: adds retry on error and abort --- .../files/etc/config/mesh-upgrade | 1 + .../files/usr/lib/lua/lime-mesh-upgrade.lua | 65 +++++++++++++------ .../files/usr/libexec/rpcd/lime-mesh-upgrade | 10 +++ .../tests/test_lime-mesh-upgrade.lua | 1 + 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade index 3679eb214..2acd09301 100644 --- a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade @@ -7,4 +7,5 @@ config mesh-upgrade 'main' option error '0' option timestamp '0' option main_node 'NO' + option retry_count '0' \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 035d21952..bbcb57caa 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -33,16 +33,17 @@ local mesh_upgrade = { }, -- list of possible errors errors = { - DOWNLOAD_FAILED = "download failed", - NO_LATEST_AVAILABLE = "no latest data available", - CONFIRMATION_TIME_OUT = "confirmation timeout", + DOWNLOAD_FAILED = "download_failed", + NO_LATEST_AVAILABLE = "no_latest_data_available", + CONFIRMATION_TIME_OUT = "confirmation_timeout", ABORTED = "aborted", - FW_FILE_NOT_FOUND = "firmware file not found" + FW_FILE_NOT_FOUND = "firmware_file_not_found" }, fw_path = "", su_confirm_timeout = 600, su_start_time_out = 60, + max_retry_conunt = 4 } -- should epgrade be disabled ? @@ -189,7 +190,7 @@ function mesh_upgrade.start_firmware_upgrade_transaction() mesh_upgrade.share_firmware_packages() -- Check if local json file exists if not utils.file_exists(mesh_upgrade.LATEST_JSON_PATH) then - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR, mesh_upgrade.errors.NO_LATEST_AVAILABLE) + mesh_upgrade.report_error(mesh_upgrade.errors.NO_LATEST_AVAILABLE) return { code = "NO_LOCAL_JSON", @@ -226,10 +227,8 @@ end function mesh_upgrade.report_error(error) local uci = config.get_uci_cursor() uci:set('mesh-upgrade', 'main', 'error', error) - uci:set('mesh-upgrade', 'main', 'timestamp', os.time()) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') - -- trigger shared state data refresh mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ERROR) end @@ -275,17 +274,24 @@ function mesh_upgrade.inform_download_location(version) repo_url = mesh_upgrade.get_repo_base_url(), upgrde_state = mesh_upgrade.upgrade_states.READY_FOR_UPGRADE, error = "", + timestamp = os.time(), main_node = mesh_upgrade.main_node_states.MAIN_NODE, board_name = eupgrade._get_board_name(), current_fw = eupgrade._get_current_fw_version() }, mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) + -- trigger shared state data refresh + mesh_upgrade.trigger_sheredstate_publish() end end -- Validate if the upgrade has already started function mesh_upgrade.started() status = mesh_upgrade.state() - if status == mesh_upgrade.upgrade_states.DEFAULT then return false end + if status == mesh_upgrade.upgrade_states.DEFAULT or + --if an error has ocurred then there is no transaction + status == mesh_upgrade.upgrade_states.ERROR then + return false + end return true -- todo(javi): what happens if a mesh_upgrade has started more than an hour ago ? should this node abort it ? end @@ -316,13 +322,22 @@ end function mesh_upgrade.mesh_upgrade_abort() mesh_upgrade.report_error(mesh_upgrade.errors.ABORTED) + mesh_upgrade.change_main_node_state(mesh_upgrade.main_node_states.NO) + local uci = config.get_uci_cursor() + uci:set('mesh-upgrade', 'main', 'retry_count', 0) + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') -- todo(javi): stop and delete everything + return { + code = "SUCCESS", + error = "" + } end -- This line will genereate recursive dependencies like in pirania pakcage function mesh_upgrade.trigger_sheredstate_publish() utils.execute_daemonized( - "/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") + "sleep 1;/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") end function mesh_upgrade.change_main_node_state(newstate) @@ -377,15 +392,26 @@ function mesh_upgrade.change_state(newstate) return true end +--this function will retry max_retry_conunt tymes in case of error function mesh_upgrade.become_bot_node(upgrade_data) if mesh_upgrade.started() then - --utils.log("started") return else - --utils.log("not started") upgrade_data.main_node = mesh_upgrade.main_node_states.NO - mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.DOWNLOADING) - mesh_upgrade.start_node_download(upgrade_data.repo_url) + actual_state = mesh_upgrade.get_node_status() + if actual_state.timestamp == upgrade_data.timestamp and + actual_state.repo_url == upgrade_data.repo_url then + upgrade_data.retry_count = actual_state.retry_count + 1 + else + upgrade_data.retry_count = 0 + end + + if upgrade_data.retry_count < mesh_upgrade.max_retry_conunt then + mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.DOWNLOADING) + mesh_upgrade.start_node_download(upgrade_data.repo_url) + -- trigger shared state data refresh + mesh_upgrade.trigger_sheredstate_publish() + end end end @@ -401,12 +427,12 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state) uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.repo_url) uci:set('mesh-upgrade', 'main', 'candidate_fw', upgrade_data.candidate_fw) uci:set('mesh-upgrade', 'main', 'error', "") - uci:set('mesh-upgrade', 'main', 'timestamp', os.time()) + uci:set('mesh-upgrade', 'main', 'retry_count', upgrade_data.retry_count or 0) + --timestamp is used as id ... every node must have the same one + uci:set('mesh-upgrade', 'main', 'timestamp', upgrade_data.timestamp) uci:set('mesh-upgrade', 'main', 'main_node', upgrade_data.main_node) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') - -- trigger shared state data refresh - mesh_upgrade.trigger_sheredstate_publish() else --utils.log("invalid state change ") end @@ -437,6 +463,7 @@ function mesh_upgrade.get_node_status() end upgrade_data.upgrade_state = uci:get('mesh-upgrade', 'main', 'upgrade_state') upgrade_data.error = uci:get('mesh-upgrade', 'main', 'error') + upgrade_data.retry_count = tonumber(uci:get('mesh-upgrade', 'main', 'retry_count')) upgrade_data.timestamp = tonumber(uci:get('mesh-upgrade', 'main', 'timestamp')) upgrade_data.main_node = mesh_upgrade.main_node_state() upgrade_data.board_name = eupgrade._get_board_name() @@ -470,9 +497,9 @@ function mesh_upgrade.start_safe_upgrade(su_start_time_out, su_confirm_timeout) mesh_upgrade.trigger_sheredstate_publish() --this must be executed after a safe upgrade timeout to enable all nodes to start_safe_upgrade utils.execute_daemonized("sleep " .. - mesh_upgrade.su_start_time_out .. - "; safe-upgrade upgrade --reboot-safety-timeout=" .. - mesh_upgrade.su_confirm_timeout .. " " .. mesh_upgrade.get_fw_path()) + mesh_upgrade.su_start_time_out .. + "; safe-upgrade upgrade --reboot-safety-timeout=" .. + mesh_upgrade.su_confirm_timeout .. " " .. mesh_upgrade.get_fw_path()) return { code = "SUCCESS", diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade index f7e1c1a02..aac80457c 100755 --- a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade @@ -42,6 +42,11 @@ local function confirm(msg) return utils.printJson(result) end +local function abort(msg) + local result = mesh_upgrade.mesh_upgrade_abort() + return utils.printJson(result) +end + local methods = { become_main_node = { url = 'value' @@ -57,6 +62,9 @@ local methods = { }, confirm_boot_partition = { no_params = 0 + }, + abort = { + no_params = 0 } } @@ -78,6 +86,8 @@ if arg[1] == 'call' then start_safe_upgrade(msg) elseif arg[2] == 'confirm_boot_partition' then confirm(msg) + elseif arg[2] == 'abort' then + abort(msg) else utils.printJson({ error = "Method not found" diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index f00728d25..f0bad6481 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -20,6 +20,7 @@ local upgrade_data = { upgrade_state = "starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", error = "CODE", main_node = "true", + timestamp=02, current_fw = "LibreRouterOs 1.5 r0+11434-e93615c947", board_name = "qemu-standard-pc-i440fx-piix-1996" } From d85b950fae5812d65d93f9af3ed6301488c255bb Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Thu, 7 Mar 2024 14:39:08 -0300 Subject: [PATCH 065/102] mesh_upgrade: fixes typos and add tests for confirm --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 51 ++++++++----- .../tests/test_lime-mesh-upgrade.lua | 76 +++++++++++++------ 2 files changed, 81 insertions(+), 46 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index bbcb57caa..f765e2e55 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -55,7 +55,7 @@ function mesh_upgrade.get_repo_base_url() return "http://" .. ipv4:host():string() .. mesh_upgrade.FIRMWARE_REPO_PATH end --- Create a work directory if nor exist +-- Create a work directory if doesn't exist function mesh_upgrade._create_workdir(workdir) if not utils.file_exists(workdir) then os.execute('mkdir -p ' .. workdir .. " >/dev/null") @@ -65,11 +65,26 @@ function mesh_upgrade._create_workdir(workdir) end end +-- Gets local downloaded firmware's path function mesh_upgrade.get_fw_path() local uci = config.get_uci_cursor() - return uci:get('mesh-upgrade', 'main', 'fw_path') or " " + local path = uci:get('mesh-upgrade', 'main', 'fw_path') + if path ~= nil and utils.file_exists(path) then + return path + else + return " " + end end +function mesh_upgrade.set_fw_path(image) + mesh_upgrade.fw_path = eupgrade.WORKDIR .. "/" .. image['name'] + local uci = config.get_uci_cursor() + uci:set('mesh-upgrade', 'main', 'fw_path', mesh_upgrade.fw_path) + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') +end + + function mesh_upgrade.set_workdir(workdir) mesh_upgrade._create_workdir(workdir) mesh_upgrade.WORKDIR = workdir @@ -214,14 +229,6 @@ function mesh_upgrade.start_firmware_upgrade_transaction() } end -function mesh_upgrade.set_fw_path(image) - mesh_upgrade.fw_path = eupgrade.WORKDIR .. "/" .. image['name'] - local uci = config.get_uci_cursor() - uci:set('mesh-upgrade', 'main', 'fw_path', mesh_upgrade.fw_path) - uci:save('mesh-upgrade') - uci:commit('mesh-upgrade') -end - -- Shared state functions -- ---------------------------- function mesh_upgrade.report_error(error) @@ -337,7 +344,9 @@ end -- This line will genereate recursive dependencies like in pirania pakcage function mesh_upgrade.trigger_sheredstate_publish() utils.execute_daemonized( - "sleep 1;/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") + "sleep 1; \ + shared-state bleach mesh_wide_upgrade; \ + /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") end function mesh_upgrade.change_main_node_state(newstate) @@ -456,7 +465,7 @@ function mesh_upgrade.get_node_status() upgrade_data.repo_url = uci:get('mesh-upgrade', 'main', 'repo_url') upgrade_data.eupgradestate = mesh_upgrade.check_eupgrade_download_failed() upgrade_data.upgrade_state = mesh_upgrade.state() - if (state == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) then + if (upgrade_data.upgrade_state == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) then if (tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) > 1) then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.CONFIRMATION_PENDING) end @@ -493,7 +502,7 @@ function mesh_upgrade.start_safe_upgrade(su_start_time_out, su_confirm_timeout) keep = keep .. " lime-mesh-upgrade" config.set("system", "keep_on_upgrade", keep) --use set but not commit, so this configuration wont be preserved. - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHELUDED) + mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) mesh_upgrade.trigger_sheredstate_publish() --this must be executed after a safe upgrade timeout to enable all nodes to start_safe_upgrade utils.execute_daemonized("sleep " .. @@ -540,17 +549,17 @@ end function mesh_upgrade.confirm() if mesh_upgrade.get_node_status().upgrade_state == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then local shell_output = utils.unsafe_shell("safe-upgrade confirm") - mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPDATED) - ----utils.log(shell_output) - return { - code = "SUCCESS" - } - else - return { + if mesh_upgrade.change_state(mesh_upgrade.upgrade_states.CONFIRMED) then + return { + code = "SUCCESS" + } + end + end + return { code = "NOT_READY_TO_CONFIRM", error = "NOT_READY_TO_CONFIRM" } - end + end return mesh_upgrade diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 8a79ab5fc..b144d4579 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -6,8 +6,15 @@ stub(eupgrade, '_get_board_name', function() return boardname end) -local lime_mesh_upgrade = require 'lime-mesh-upgrade' +confirm_remaining = -1 + +stub(utils, 'unsafe_shell', function(command) + print(command) + return confirm_remaining +end) + local utils = require "lime.utils" +local lime_mesh_upgrade = require 'lime-mesh-upgrade' local test_utils = require "tests.utils" local json = require 'luci.jsonc' local uci @@ -18,7 +25,7 @@ local upgrade_data = { upgrade_state = "starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", error = "CODE", main_node = "true", - timestamp=02, + timestamp = 02, current_fw = "LibreRouterOs 1.5 r0+11434-e93615c947", board_name = "qemu-standard-pc-i440fx-piix-1996" } @@ -54,8 +61,6 @@ describe('LiMe mesh upgrade', function() it('test get mesh config fresh start', function() local fw_version = 'LibreMesh 19.02' - config.log("\n test set mesh config.... \n") - stub(eupgrade, '_get_current_fw_version', function() return fw_version end) @@ -153,7 +158,7 @@ describe('LiMe mesh upgrade', function() local fw_path = lime_mesh_upgrade.get_fw_path() assert.is.equal(fw_path, " ") - + stub(eupgrade, '_get_current_fw_version', function() return 'LibreMesh 19.05' end) @@ -166,6 +171,9 @@ describe('LiMe mesh upgrade', function() stub(eupgrade, '_file_sha256', function() return 'cec8920f93055cc57cfde1f87968e33ca5215b2df88611684195077402079acb' end) + stub(utils, 'file_exists', function() + return true + end) lime_mesh_upgrade.become_bot_node(upgrade_data) status = lime_mesh_upgrade.get_node_status() @@ -174,7 +182,7 @@ describe('LiMe mesh upgrade', function() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) local fw_path = lime_mesh_upgrade.get_fw_path() assert.is.equal(fw_path, '/tmp/eupgrades/upgrade-lr-1.5.sh') - + end) it('test become main node changes the state to STARTING', function() @@ -279,21 +287,13 @@ describe('LiMe mesh upgrade', function() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) assert.is.equal(status.candidate_fw, json.parse(latest_release_data).version) assert.is.equal(status.board_name, boardname) - assert.is.equal(status.main_node,lime_mesh_upgrade.main_node_states.MAIN_NODE) - assert.is.equal(status.repo_url,'http://10.1.1.0/lros/') + assert.is.equal(status.main_node, lime_mesh_upgrade.main_node_states.MAIN_NODE) + assert.is.equal(status.repo_url, 'http://10.1.1.0/lros/') end) it('test start_safe_upgrade default timeouts', function() - stub(utils, 'execute_daemonized', function () - end) - - stub(lime_mesh_upgrade, 'state', function() - return lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE - end) - - stub(utils, 'file_exists', function() - return true + stub(utils, 'execute_daemonized', function() end) stub(utils, 'file_exists', function() @@ -304,14 +304,38 @@ describe('LiMe mesh upgrade', function() return "/tmp/foo.bar" end) + local fw_version = 'LibreMesh 19.02' + stub(eupgrade, '_get_current_fw_version', function() + return fw_version + end) + uci:set('mesh-upgrade', 'main', "mesh-upgrade") + uci:set('mesh-upgrade', 'main', "upgrade_state", "READY_FOR_UPGRADE") + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') + local status = lime_mesh_upgrade.get_node_status() + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) + + --should be called from rpcd lime_mesh_upgrade.start_safe_upgrade() - assert.is.equal(lime_mesh_upgrade.su_confirm_timeout,600) - assert.is.equal(lime_mesh_upgrade.su_start_time_out,60) - assert.stub.spy(utils.execute_daemonized).was.called.with("sleep 60; safe-upgrade upgrade --reboot-safety-timeout=600 /tmp/foo.bar") + status = lime_mesh_upgrade.get_node_status() + assert.stub.spy(utils.execute_daemonized).was.called.with( + "sleep 60; safe-upgrade upgrade --reboot-safety-timeout=600 /tmp/foo.bar") + assert.is.equal(lime_mesh_upgrade.su_confirm_timeout, 600) + assert.is.equal(lime_mesh_upgrade.su_start_time_out, 60) + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) + + --after reboot confirm confirm_remaining will be grater than 0 + confirm_remaining = 10 + status = lime_mesh_upgrade.get_node_status() + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.CONFIRMATION_PENDING) + + lime_mesh_upgrade.confirm() + status = lime_mesh_upgrade.get_node_status() + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.CONFIRMED) end) it('test start_safe_upgrade different timeouts', function() - stub(utils, 'execute_daemonized', function () + stub(utils, 'execute_daemonized', function() end) stub(lime_mesh_upgrade, 'state', function() @@ -330,16 +354,18 @@ describe('LiMe mesh upgrade', function() return "/tmp/foo.bar" end) - lime_mesh_upgrade.start_safe_upgrade(10,100) - assert.is.equal(lime_mesh_upgrade.su_confirm_timeout,100) - assert.is.equal(lime_mesh_upgrade.su_start_time_out,10) - assert.stub.spy(utils.execute_daemonized).was.called.with("sleep 10; safe-upgrade upgrade --reboot-safety-timeout=100 /tmp/foo.bar") + lime_mesh_upgrade.start_safe_upgrade(10, 100) + assert.is.equal(lime_mesh_upgrade.su_confirm_timeout, 100) + assert.is.equal(lime_mesh_upgrade.su_start_time_out, 10) + assert.stub.spy(utils.execute_daemonized).was.called.with( + "sleep 10; safe-upgrade upgrade --reboot-safety-timeout=100 /tmp/foo.bar") end) before_each('', function() snapshot = assert:snapshot() uci = test_utils.setup_test_uci() uci:set('mesh-upgrade', 'main', "mesh-upgrade") + uci:set('mesh-upgrade', 'main', "upgrade_state", "DEFAULT") uci:save('mesh-upgrade') uci:commit('mesh-upgrade') end) From 50242d26f338a5f24ac8b8e2fff6abc965703adc Mon Sep 17 00:00:00 2001 From: javierbrk Date: Fri, 1 Mar 2024 15:45:47 -0300 Subject: [PATCH 066/102] lime-mesh-upgrade: add ipv4 in node status --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 2 ++ .../tests/test_lime-mesh-upgrade.lua | 22 +++++++------------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index f765e2e55..08595fd99 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -477,6 +477,8 @@ function mesh_upgrade.get_node_status() upgrade_data.main_node = mesh_upgrade.main_node_state() upgrade_data.board_name = eupgrade._get_board_name() upgrade_data.current_fw = eupgrade._get_current_fw_version() + local ipv4, ipv6 = network.primary_address() + upgrade_data.node_ip = ipv4:host():string() return upgrade_data end diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index b144d4579..7e4088a53 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -201,26 +201,12 @@ describe('LiMe mesh upgrade', function() end) it('test custom latest json file is created', function() - config.set('network', 'lime') - config.set('network', 'main_ipv4_address', '10.%N1.0.0/16') - config.set('network', 'main_ipv6_address', 'fd%N1:%N2%N3:%N4%N5::/64') - config.set('network', 'protocols', {'lan'}) - config.set('wifi', 'lime') - config.set('wifi', 'ap_ssid', 'LibreMesh.org') - uci:commit('lime') lime_mesh_upgrade.create_local_latest_json(json.parse(latest_release_data)) local filexists = utils.file_exists(lime_mesh_upgrade.LATEST_JSON_PATH) assert(filexists, "File not found: " .. lime_mesh_upgrade.LATEST_JSON_PATH) end) it('test set_up_firmware_repository download the files correctly and fix the url on json', function() - config.set('network', 'lime') - config.set('network', 'main_ipv4_address', '10.%N1.0.0/16') - config.set('network', 'main_ipv6_address', 'fd%N1:%N2%N3:%N4%N5::/64') - config.set('network', 'protocols', {'lan'}) - config.set('wifi', 'lime') - config.set('wifi', 'ap_ssid', 'LibreMesh.org') - uci:commit('lime') lime_mesh_upgrade.create_local_latest_json(json.parse(latest_release_data)) local latest = json.parse(utils.read_file(lime_mesh_upgrade.LATEST_JSON_PATH)) @@ -367,6 +353,14 @@ describe('LiMe mesh upgrade', function() uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:set('mesh-upgrade', 'main', "upgrade_state", "DEFAULT") uci:save('mesh-upgrade') + config.set('network', 'lime') + config.set('network', 'main_ipv4_address', '10.%N1.0.0/16') + config.set('network', 'main_ipv6_address', 'fd%N1:%N2%N3:%N4%N5::/64') + config.set('network', 'protocols', {'lan'}) + config.set('wifi', 'lime') + config.set('wifi', 'ap_ssid', 'LibreMesh.org') + uci:commit('lime') + uci:commit('mesh-upgrade') end) From 5e60e13e87dc3226d4518720b6e25b7b81845b91 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Tue, 12 Mar 2024 14:19:18 -0300 Subject: [PATCH 067/102] lime-mesh-upgrade: adds rpc parameters to start_s_u --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 18 +++- .../files/usr/libexec/rpcd/lime-mesh-upgrade | 5 +- .../tests/test_rpcd_lime_mesh_upgrade.lua | 83 +++++++++++++++++++ 3 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 08595fd99..621ce539b 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -329,11 +329,12 @@ end function mesh_upgrade.mesh_upgrade_abort() mesh_upgrade.report_error(mesh_upgrade.errors.ABORTED) - mesh_upgrade.change_main_node_state(mesh_upgrade.main_node_states.NO) + --mesh_upgrade.change_main_node_state(mesh_upgrade.main_node_states.NO) local uci = config.get_uci_cursor() uci:set('mesh-upgrade', 'main', 'retry_count', 0) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') + mesh_upgrade.trigger_sheredstate_publish() -- todo(javi): stop and delete everything return { code = "SUCCESS", @@ -404,6 +405,12 @@ end --this function will retry max_retry_conunt tymes in case of error function mesh_upgrade.become_bot_node(upgrade_data) if mesh_upgrade.started() then + if actual_state.timestamp == upgrade_data.timestamp and + upgrade_data.upgrade_state == mesh_upgrade.upgrade_states.ERROR and + upgrade_data.error == mesh_upgrade.errors.ABORTED then + mesh_upgrade.mesh_upgrade_abort() + end + return else upgrade_data.main_node = mesh_upgrade.main_node_states.NO @@ -482,8 +489,8 @@ function mesh_upgrade.get_node_status() return upgrade_data end -function mesh_upgrade.start_safe_upgrade(su_start_time_out, su_confirm_timeout) - mesh_upgrade.su_start_time_out = su_start_time_out or mesh_upgrade.su_start_time_out +function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) + mesh_upgrade.su_start_time_out = su_start_delay or mesh_upgrade.su_start_time_out mesh_upgrade.su_confirm_timeout = su_confirm_timeout or mesh_upgrade.su_confirm_timeout if mesh_upgrade.state() == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then @@ -514,7 +521,10 @@ function mesh_upgrade.start_safe_upgrade(su_start_time_out, su_confirm_timeout) return { code = "SUCCESS", - error = "" + error = "", + su_start_delay = mesh_upgrade.su_start_time_out, + su_confirm_timeout = mesh_upgrade.su_confirm_timeout + } else ----utils.log("not able to start upgrade invalid state or firmware not found") diff --git a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade index aac80457c..d7b783a37 100755 --- a/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade @@ -33,7 +33,7 @@ local function get_node_status(msg) end local function start_safe_upgrade(msg) - local result = mesh_upgrade.start_safe_upgrade() + local result = mesh_upgrade.start_safe_upgrade(msg.start_delay ,msg.confirm_timeout) return utils.printJson(result) end -- to be called after successfully reboot @@ -58,7 +58,8 @@ local methods = { no_params = 0 }, start_safe_upgrade = { - no_params = 0 + confirm_timeout = 0, + start_delay = 0, }, confirm_boot_partition = { no_params = 0 diff --git a/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua b/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua new file mode 100644 index 000000000..84744d905 --- /dev/null +++ b/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua @@ -0,0 +1,83 @@ +local test_utils = require "tests.utils" +local json = require("luci.jsonc") +local eupgrade = require 'eupgrade' + + +local testFileName = "packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade" +local limeRpc = test_utils.load_lua_file_as_function(testFileName) +local rpcdCall = test_utils.rpcd_call + + + +describe('general rpc testing', function() + before_each('', function() + local boardname = 'librerouter-v1' + stub(eupgrade, '_get_board_name', function() + return boardname + end) + lime_mesh_upgrade = require 'lime-mesh-upgrade' + + snapshot = assert:snapshot() + uci = test_utils.setup_test_uci() + uci:set('mesh-upgrade', 'main', "mesh-upgrade") + uci:set('mesh-upgrade', 'main', "upgrade_state", "DEFAULT") + uci:save('mesh-upgrade') + config.set('network', 'lime') + config.set('network', 'main_ipv4_address', '10.%N1.0.0/16') + config.set('network', 'main_ipv6_address', 'fd%N1:%N2%N3:%N4%N5::/64') + config.set('network', 'protocols', { 'lan' }) + config.set('wifi', 'lime') + config.set('wifi', 'ap_ssid', 'LibreMesh.org') + uci:commit('lime') + + uci:commit('mesh-upgrade') + end) + + after_each('', function() + end) + + it('test list methods', function() + local response = rpcdCall(limeRpc, { 'list' }) + assert.is.equal("value", response.become_main_node.url) + assert.is.equal(0, response.start_safe_upgrade.confirm_timeout) + assert.is.equal(0, response.abort.no_params) + assert.is.equal(0, response.start_firmware_upgrade_transaction.no_params) + assert.is.equal(0, response.get_node_status.no_params) + + end) + + it('test start_safe_upgrade different timeouts', function() + stub(utils, 'execute_daemonized', function() + end) + + + stub(lime_mesh_upgrade, 'state', function() + return lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE + end) + + stub(utils, 'file_exists', function() + return true + end) + + stub(utils, 'file_exists', function() + return true + end) + + stub(lime_mesh_upgrade, 'get_fw_path', function() + return "/tmp/foo.bar" + end) + + local response = rpcdCall(limeRpc, { 'call', 'start_safe_upgrade'}, '{}') + assert.are.equal(response.code, "SUCCESS") + assert.are.equal(response.su_confirm_timeout, 600) + assert.are.equal(response.su_start_delay, 60) + local response = rpcdCall(limeRpc, { 'call', 'start_safe_upgrade'}, '{"confirm_timeout":15, "start_delay":150}') + assert.are.equal(response.code, "SUCCESS") + assert.are.equal(response.su_confirm_timeout, 15) + assert.are.equal(response.su_start_delay, 150) + local response = rpcdCall(limeRpc, { 'call', 'start_safe_upgrade'}, '{}') + assert.are.equal(response.code, "SUCCESS") + assert.are.equal(response.su_confirm_timeout, 15) + assert.are.equal(response.su_start_delay, 150) + end) +end) From 88c500f8646ed10f38a4fdfd97e7b9ed68f31a14 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Thu, 21 Mar 2024 09:40:01 -0300 Subject: [PATCH 068/102] mesh-upgrade: error if filenot found --- .../lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 621ce539b..79a63a74c 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -475,6 +475,8 @@ function mesh_upgrade.get_node_status() if (upgrade_data.upgrade_state == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) then if (tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) > 1) then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.CONFIRMATION_PENDING) + elseif utils.file_exists(mesh_upgrade.get_fw_path()) == false then + mesh_upgrade.report_error(mesh_upgrade.errors.FW_FILE_NOT_FOUND) end end upgrade_data.upgrade_state = uci:get('mesh-upgrade', 'main', 'upgrade_state') From a306df701c76fdd0106a28f5eaeb7d6740ea3499 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Thu, 28 Sep 2023 13:57:15 -0300 Subject: [PATCH 069/102] added test case, removed luci dependency --- packages/shared-state-mesh_wide_upgrade/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/shared-state-mesh_wide_upgrade/Makefile b/packages/shared-state-mesh_wide_upgrade/Makefile index 4afd9099a..fbaddab34 100644 --- a/packages/shared-state-mesh_wide_upgrade/Makefile +++ b/packages/shared-state-mesh_wide_upgrade/Makefile @@ -1,5 +1,6 @@ # -# Copyright (C) 2023 Javier Jorge +# Copyright (c) 2023 Javier Jorge +# Copyright (c) 2023 Instituto Nacional de Tecnología Industrial # Copyright (C) 2023 Asociación Civil Altermundi # This is free software, licensed under the GNU Affero General Public License v3. # From d99480d9c84a98c47cd8765bc50446e9e67f307f Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Thu, 28 Sep 2023 14:19:02 -0300 Subject: [PATCH 070/102] added ubus dependency --- packages/shared-state-mesh_wide_upgrade/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared-state-mesh_wide_upgrade/Makefile b/packages/shared-state-mesh_wide_upgrade/Makefile index fbaddab34..37e280e9f 100644 --- a/packages/shared-state-mesh_wide_upgrade/Makefile +++ b/packages/shared-state-mesh_wide_upgrade/Makefile @@ -13,7 +13,7 @@ define Package/$(PKG_NAME) TITLE:=Mesh wide upgrade module for shared-state MAINTAINER:= Javier DEPENDS:=+lua +luci-lib-jsonc +ubus-lime-utils \ - +lime-system shared-state + +libubus-lua shared-state PKGARCH:=all endef From a00e9e5006c75c3d5ffff5ed404f1899ddc169cd Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Thu, 28 Sep 2023 14:41:53 -0300 Subject: [PATCH 071/102] use random-numgen --- packages/shared-state-mesh_wide_upgrade/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared-state-mesh_wide_upgrade/Makefile b/packages/shared-state-mesh_wide_upgrade/Makefile index 37e280e9f..4a1dc0e27 100644 --- a/packages/shared-state-mesh_wide_upgrade/Makefile +++ b/packages/shared-state-mesh_wide_upgrade/Makefile @@ -13,7 +13,7 @@ define Package/$(PKG_NAME) TITLE:=Mesh wide upgrade module for shared-state MAINTAINER:= Javier DEPENDS:=+lua +luci-lib-jsonc +ubus-lime-utils \ - +libubus-lua shared-state + +libubus-lua +random-numgen shared-state PKGARCH:=all endef From 88e61e8b6e4ff1218f07d635dfce153bfd7f2fef Mon Sep 17 00:00:00 2001 From: javierbrk Date: Fri, 1 Mar 2024 12:44:03 -0300 Subject: [PATCH 072/102] shared-state-async: add babel links information support --- packages/shared-state-mesh_wide_upgrade/Makefile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/shared-state-mesh_wide_upgrade/Makefile b/packages/shared-state-mesh_wide_upgrade/Makefile index 4a1dc0e27..5caf7061b 100644 --- a/packages/shared-state-mesh_wide_upgrade/Makefile +++ b/packages/shared-state-mesh_wide_upgrade/Makefile @@ -8,12 +8,11 @@ include ../../libremesh.mk define Package/$(PKG_NAME) - SECTION:=lime CATEGORY:=LibreMesh - TITLE:=Mesh wide upgrade module for shared-state - MAINTAINER:= Javier + TITLE:=Babel links module for shared-state + MAINTAINER:=Asociación Civil Altermundi DEPENDS:=+lua +luci-lib-jsonc +ubus-lime-utils \ - +libubus-lua +random-numgen shared-state + +libubus-lua +random-numgen shared-state-async PKGARCH:=all endef From 0bedc8a1e7968b9a0e4fafccec4f7455bef9552d Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 25 Mar 2024 17:17:57 -0300 Subject: [PATCH 073/102] mesh-upgrade: adds makefile dependencies --- packages/lime-mesh-upgrade/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/lime-mesh-upgrade/Makefile b/packages/lime-mesh-upgrade/Makefile index 5ea56307a..1ee456963 100644 --- a/packages/lime-mesh-upgrade/Makefile +++ b/packages/lime-mesh-upgrade/Makefile @@ -10,9 +10,8 @@ include $(INCLUDE_DIR)/package.mk define Package/$(PKG_NAME) CATEGORY:=LibreMesh MAINTAINER:=selankon - SUBMENU:=3. Applications TITLE:=LibreMesh mesh wide firmware upgrade - DEPENDS:= +lua +libubus-lua +wget + DEPENDS:= +lua +libubus-lua +wget +safe-upgrade +shared-state-mesh_wide_upgrade PKGARCH:=all endef From d6445364e84d3bc232048d9ad6e9a8cb76f17dfe Mon Sep 17 00:00:00 2001 From: javierbrk Date: Tue, 26 Mar 2024 14:50:17 -0300 Subject: [PATCH 074/102] mesh-upgrade: abort --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 104 ++++++++++-------- .../tests/test_lime-mesh-upgrade.lua | 3 +- .../hooks/mesh_wide_upgrade/start_upgrade | 21 +++- 3 files changed, 82 insertions(+), 46 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 79a63a74c..0a89304a7 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -23,7 +23,8 @@ local mesh_upgrade = { UPGRADE_SCHEDULED = "UPGRADE_SCHEDULED", CONFIRMATION_PENDING = "CONFIRMATION_PENDING", CONFIRMED = "CONFIRMED", - ERROR = "ERROR" + ERROR = "ERROR", + ABORTED = "ABORTED" }, -- Master node specific states main_node_states = { @@ -36,7 +37,7 @@ local mesh_upgrade = { DOWNLOAD_FAILED = "download_failed", NO_LATEST_AVAILABLE = "no_latest_data_available", CONFIRMATION_TIME_OUT = "confirmation_timeout", - ABORTED = "aborted", + -- ABORTED = "aborted", FW_FILE_NOT_FOUND = "firmware_file_not_found" }, @@ -84,7 +85,6 @@ function mesh_upgrade.set_fw_path(image) uci:commit('mesh-upgrade') end - function mesh_upgrade.set_workdir(workdir) mesh_upgrade._create_workdir(workdir) mesh_upgrade.WORKDIR = workdir @@ -156,11 +156,16 @@ function mesh_upgrade.become_main_node(url) -- 2. Start local repository and download latest firmware mesh_upgrade.start_main_node_repository(latest) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) - mesh_upgrade.change_main_node_state(mesh_upgrade.main_node_states.STARTING) + if mesh_upgrade.change_main_node_state(mesh_upgrade.main_node_states.STARTING) then return { code = "SUCCESS", error = "" } + end + return { + code = "NO_NEW_VERSION", + error = "No new version is available" + } end -- Update the state witth an error if eupgrade download failed @@ -296,7 +301,9 @@ function mesh_upgrade.started() status = mesh_upgrade.state() if status == mesh_upgrade.upgrade_states.DEFAULT or --if an error has ocurred then there is no transaction - status == mesh_upgrade.upgrade_states.ERROR then + status == mesh_upgrade.upgrade_states.ERROR or + status == mesh_upgrade.upgrade_states.ABORTED + then return false end return true @@ -328,14 +335,15 @@ function mesh_upgrade.main_node_state() end function mesh_upgrade.mesh_upgrade_abort() - mesh_upgrade.report_error(mesh_upgrade.errors.ABORTED) - --mesh_upgrade.change_main_node_state(mesh_upgrade.main_node_states.NO) - local uci = config.get_uci_cursor() - uci:set('mesh-upgrade', 'main', 'retry_count', 0) - uci:save('mesh-upgrade') - uci:commit('mesh-upgrade') - mesh_upgrade.trigger_sheredstate_publish() - -- todo(javi): stop and delete everything + if mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ABORTED) then + --mesh_upgrade.change_main_node_state(mesh_upgrade.main_node_states.NO) + local uci = config.get_uci_cursor() + uci:set('mesh-upgrade', 'main', 'retry_count', 0) + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') + mesh_upgrade.trigger_sheredstate_publish() + -- todo(javi): stop and delete everything + end return { code = "SUCCESS", error = "" @@ -354,10 +362,10 @@ function mesh_upgrade.change_main_node_state(newstate) local main_node_state = mesh_upgrade.main_node_state() if newstate == main_node_state then return false end - if newstate == mesh_upgrade.main_node_states.STARTING and - main_node_state ~= mesh_upgrade.main_node_states.NO then - return false - elseif newstate == mesh_upgrade.main_node_states.MAIN_NODE and + -- if newstate == mesh_upgrade.main_node_states.STARTING and + -- main_node_state ~= mesh_upgrade.main_node_states.NO then + -- return false + if newstate == mesh_upgrade.main_node_states.MAIN_NODE and main_node_state ~= mesh_upgrade.main_node_states.STARTING then return false end @@ -378,7 +386,8 @@ function mesh_upgrade.change_state(newstate) if newstate == mesh_upgrade.upgrade_states.DOWNLOADING and actual_state ~= mesh_upgrade.upgrade_states.DEFAULT and actual_state ~= mesh_upgrade.upgrade_states.ERROR and - actual_state ~= mesh_upgrade.upgrade_states.UPDATED then + actual_state ~= mesh_upgrade.upgrade_states.UPDATED and + actual_state ~= mesh_upgrade.upgrade_states.ABORTED then return false elseif newstate == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE and actual_state ~= mesh_upgrade.upgrade_states.DOWNLOADING then @@ -403,30 +412,37 @@ function mesh_upgrade.change_state(newstate) end --this function will retry max_retry_conunt tymes in case of error -function mesh_upgrade.become_bot_node(upgrade_data) +function mesh_upgrade.become_bot_node(main_node_upgrade_data) + if main_node_upgrade_data.upgrade_state == mesh_upgrade.upgrade_states.ABORTED then + utils.log("main node has aborted") + mesh_upgrade.mesh_upgrade_abort() + return + end + if mesh_upgrade.started() then - if actual_state.timestamp == upgrade_data.timestamp and - upgrade_data.upgrade_state == mesh_upgrade.upgrade_states.ERROR and - upgrade_data.error == mesh_upgrade.errors.ABORTED then - mesh_upgrade.mesh_upgrade_abort() - end - + utils.log("node has already started") return else - upgrade_data.main_node = mesh_upgrade.main_node_states.NO + utils.log("node has not started") + + main_node_upgrade_data.main_node = mesh_upgrade.main_node_states.NO actual_state = mesh_upgrade.get_node_status() - if actual_state.timestamp == upgrade_data.timestamp and - actual_state.repo_url == upgrade_data.repo_url then - upgrade_data.retry_count = actual_state.retry_count + 1 + if actual_state.timestamp == main_node_upgrade_data.timestamp and + actual_state.repo_url == main_node_upgrade_data.repo_url then + main_node_upgrade_data.retry_count = actual_state.retry_count + 1 else - upgrade_data.retry_count = 0 + main_node_upgrade_data.retry_count = 0 end - - if upgrade_data.retry_count < mesh_upgrade.max_retry_conunt then - mesh_upgrade.set_mesh_upgrade_info(upgrade_data, mesh_upgrade.upgrade_states.DOWNLOADING) - mesh_upgrade.start_node_download(upgrade_data.repo_url) - -- trigger shared state data refresh - mesh_upgrade.trigger_sheredstate_publish() + + if main_node_upgrade_data.retry_count < mesh_upgrade.max_retry_conunt then + if (mesh_upgrade.set_mesh_upgrade_info(main_node_upgrade_data, mesh_upgrade.upgrade_states.DOWNLOADING)) then + mesh_upgrade.start_node_download(main_node_upgrade_data.repo_url) + -- trigger shared state data refresh + mesh_upgrade.trigger_sheredstate_publish() + end + else + utils.log("max retry_count has been reached") + end end end @@ -437,7 +453,7 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state) local uci = config.get_uci_cursor() if string.match(upgrade_data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil -- todo (javi): perform aditional checks then - --utils.log("seting up repo download info to " .. upgrade_state .. " actual " .. mesh_upgrade.state()) + utils.log("seting up repo download info to " .. upgrade_state .. " actual " .. mesh_upgrade.state()) if (mesh_upgrade.change_state(upgrade_state)) then uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.repo_url) @@ -449,11 +465,14 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state) uci:set('mesh-upgrade', 'main', 'main_node', upgrade_data.main_node) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') + return true else --utils.log("invalid state change ") + return false end else --utils.log("upgrade failed due input data errors") + return false end end @@ -475,7 +494,7 @@ function mesh_upgrade.get_node_status() if (upgrade_data.upgrade_state == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) then if (tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) > 1) then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.CONFIRMATION_PENDING) - elseif utils.file_exists(mesh_upgrade.get_fw_path()) == false then + elseif utils.file_exists(mesh_upgrade.get_fw_path()) == false then mesh_upgrade.report_error(mesh_upgrade.errors.FW_FILE_NOT_FOUND) end end @@ -524,7 +543,7 @@ function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) return { code = "SUCCESS", error = "", - su_start_delay = mesh_upgrade.su_start_time_out, + su_start_delay = mesh_upgrade.su_start_time_out, su_confirm_timeout = mesh_upgrade.su_confirm_timeout } @@ -570,10 +589,9 @@ function mesh_upgrade.confirm() end end return { - code = "NOT_READY_TO_CONFIRM", - error = "NOT_READY_TO_CONFIRM" - } - + code = "NOT_READY_TO_CONFIRM", + error = "NOT_READY_TO_CONFIRM" + } end return mesh_upgrade diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 7e4088a53..13f4e9df3 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -88,8 +88,7 @@ describe('LiMe mesh upgrade', function() end) lime_mesh_upgrade.mesh_upgrade_abort() status = lime_mesh_upgrade.get_node_status() - assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) - assert.is.equal(status.error, lime_mesh_upgrade.errors.ABORTED) + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ABORTED) end) it('test set upgrade info and fail NO_LATEST_AVAILABLE', function() diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade index e09373d79..aed13bb89 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -21,13 +21,16 @@ local utils = require "lime.utils" local mesh_upgrade = require "lime-mesh-upgrade" local hostname = utils.hostname() +local indata = io.stdin:read("*all") --if already involved in an upgrade transaction do nothing if not mesh_upgrade.started() then utils.log("starting an upgrade process") - for node, s_s_data in pairs(JSON.parse(io.stdin:read("*all"))) do + for node, s_s_data in pairs(JSON.parse(indata)) do --if any node has started an upgrade process and start one too? --only fetch the info from the master node publication? if node ~= hostname and s_s_data.data.main_node == mesh_upgrade.main_node_states.MAIN_NODE then + utils.log("starting an upgrade process") + utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from "' .. s_s_data.data.repo_url .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) mesh_upgrade.become_bot_node(s_s_data.data) @@ -37,6 +40,22 @@ if not mesh_upgrade.started() then end end else + --if started check that a main node has not aborted + for node, s_s_data in pairs(JSON.parse(indata)) do + utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from "' .. + s_s_data.data.main_node .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) + utils.log('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from "' .. + s_s_data.data.main_node .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) + + if node ~= hostname and + s_s_data.data.main_node == mesh_upgrade.main_node_states.MAIN_NODE and + s_s_data.data.upgrade_state == mesh_upgrade.upgrade_states.ABORTED + then + mesh_upgrade.mesh_upgrade_abort() + utils.log("aborting, main has aborted") + utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "aborting, main has aborted"') + end + end utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "already started an upgrade process"') utils.log("already started an upgrade process") end From 2e8824864db38d7f7425f89af18ddb9a055a7eb5 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Tue, 26 Mar 2024 16:48:22 -0300 Subject: [PATCH 075/102] mesh-upgrade: reports time and abort scheduled upgrade --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 10 +++++++++- .../lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 0a89304a7..6c7a0034d 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -44,7 +44,8 @@ local mesh_upgrade = { fw_path = "", su_confirm_timeout = 600, su_start_time_out = 60, - max_retry_conunt = 4 + max_retry_conunt = 4, + safeupgrade_start_mark=0 } -- should epgrade be disabled ? @@ -343,6 +344,10 @@ function mesh_upgrade.mesh_upgrade_abort() uci:commit('mesh-upgrade') mesh_upgrade.trigger_sheredstate_publish() -- todo(javi): stop and delete everything + -- kill posible safe upgrade command + utils.unsafe_shell("kill $(ps| grep 'sh -c (( sleep " .. + mesh_upgrade.su_start_time_out .. + "; safe-upgrade upgrade'| awk '{print $1}')") end return { code = "SUCCESS", @@ -507,6 +512,8 @@ function mesh_upgrade.get_node_status() upgrade_data.current_fw = eupgrade._get_current_fw_version() local ipv4, ipv6 = network.primary_address() upgrade_data.node_ip = ipv4:host():string() + upgrade_data.safeupgrade_start_remining= (mesh_upgrade.su_start_time_out- (utils.uptime_s()-mesh_upgrade.safeupgrade_start_mark)>0 and mesh_upgrade.su_start_time_out- (utils.uptime_s()-mesh_upgrade.safeupgrade_start_mark) or -1) + upgrade_data.confirm_remining= tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) return upgrade_data end @@ -533,6 +540,7 @@ function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) config.set("system", "keep_on_upgrade", keep) --use set but not commit, so this configuration wont be preserved. mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) + mesh_upgrade.safeupgrade_start_mark=utils.uptime_s() mesh_upgrade.trigger_sheredstate_publish() --this must be executed after a safe upgrade timeout to enable all nodes to start_safe_upgrade utils.execute_daemonized("sleep " .. diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 13f4e9df3..60f909467 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -307,6 +307,8 @@ describe('LiMe mesh upgrade', function() "sleep 60; safe-upgrade upgrade --reboot-safety-timeout=600 /tmp/foo.bar") assert.is.equal(lime_mesh_upgrade.su_confirm_timeout, 600) assert.is.equal(lime_mesh_upgrade.su_start_time_out, 60) + assert(status.safeupgrade_start_remining<60 and status.safeupgrade_start_remining>10) + assert.is.equal(status.confirm_remining,-1) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) --after reboot confirm confirm_remaining will be grater than 0 From 79e6411a996a6b26ed1d5d71f6c88fded4d1fa24 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Wed, 27 Mar 2024 14:09:52 -0300 Subject: [PATCH 076/102] mesh-upgrade: fixes became main node error --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 6c7a0034d..83198cda1 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -164,8 +164,8 @@ function mesh_upgrade.become_main_node(url) } end return { - code = "NO_NEW_VERSION", - error = "No new version is available" + code = "NO_ABLE_TO_BECOME_MAIN_NODE", + error = "Not able to start main node repository or change to starting" } end @@ -365,7 +365,7 @@ end function mesh_upgrade.change_main_node_state(newstate) local main_node_state = mesh_upgrade.main_node_state() - if newstate == main_node_state then return false end + --if newstate == main_node_state then return false end -- if newstate == mesh_upgrade.main_node_states.STARTING and -- main_node_state ~= mesh_upgrade.main_node_states.NO then From 9734b3b72877032abf6fdc73e75d905a97b5f928 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Wed, 3 Apr 2024 13:29:07 -0300 Subject: [PATCH 077/102] mesh-upgrade: check image is valid and add timing --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 83198cda1..0ede2cbd9 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -38,14 +38,15 @@ local mesh_upgrade = { NO_LATEST_AVAILABLE = "no_latest_data_available", CONFIRMATION_TIME_OUT = "confirmation_timeout", -- ABORTED = "aborted", - FW_FILE_NOT_FOUND = "firmware_file_not_found" + FW_FILE_NOT_FOUND = "firmware_file_not_found", + INVALID_FW_FILE = "invalid_firmware_file" }, fw_path = "", su_confirm_timeout = 600, su_start_time_out = 60, max_retry_conunt = 4, - safeupgrade_start_mark=0 + safeupgrade_start_mark = 0 } -- should epgrade be disabled ? @@ -158,10 +159,10 @@ function mesh_upgrade.become_main_node(url) mesh_upgrade.start_main_node_repository(latest) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) if mesh_upgrade.change_main_node_state(mesh_upgrade.main_node_states.STARTING) then - return { - code = "SUCCESS", - error = "" - } + return { + code = "SUCCESS", + error = "" + } end return { code = "NO_ABLE_TO_BECOME_MAIN_NODE", @@ -199,6 +200,8 @@ function mesh_upgrade.start_firmware_upgrade_transaction() error = "No new firmware file downloaded" } end + --this is redundant but there is an scenario when download information is + --outdated and this check is necesary local latest = eupgrade.is_new_version_available(true) if not latest then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DEFAULT) @@ -346,8 +349,8 @@ function mesh_upgrade.mesh_upgrade_abort() -- todo(javi): stop and delete everything -- kill posible safe upgrade command utils.unsafe_shell("kill $(ps| grep 'sh -c (( sleep " .. - mesh_upgrade.su_start_time_out .. - "; safe-upgrade upgrade'| awk '{print $1}')") + mesh_upgrade.su_start_time_out .. + "; safe-upgrade upgrade'| awk '{print $1}')") end return { code = "SUCCESS", @@ -512,8 +515,8 @@ function mesh_upgrade.get_node_status() upgrade_data.current_fw = eupgrade._get_current_fw_version() local ipv4, ipv6 = network.primary_address() upgrade_data.node_ip = ipv4:host():string() - upgrade_data.safeupgrade_start_remining= (mesh_upgrade.su_start_time_out- (utils.uptime_s()-mesh_upgrade.safeupgrade_start_mark)>0 and mesh_upgrade.su_start_time_out- (utils.uptime_s()-mesh_upgrade.safeupgrade_start_mark) or -1) - upgrade_data.confirm_remining= tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) + upgrade_data.safeupgrade_start_remining = (mesh_upgrade.su_start_time_out - (utils.uptime_s() - mesh_upgrade.safeupgrade_start_mark) > 0 and mesh_upgrade.su_start_time_out - (utils.uptime_s() - mesh_upgrade.safeupgrade_start_mark) or -1) + upgrade_data.confirm_remining = tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) return upgrade_data end @@ -523,15 +526,22 @@ function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) if mesh_upgrade.state() == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then if utils.file_exists(mesh_upgrade.get_fw_path()) then + + -- veryfy the image before starting + if os.execute("sysupgrade --test " .. mesh_upgrade.get_fw_path()) ~= 0 then + mesh_upgrade.report_error(mesh_upgrade.errors.INVALID_FW_FILE) + return { + code = "NOT_ABLE_TO_START_UPGRADE", + error = "Firmware not valid" + } + end + -- perform safe upgrade preserving config and rebooting after 600 sec if -- no confirmation is received - -- todo: javier first veryfy image - - -- just preserve meshconfig - --os.execute("tar cfz ".. mesh_upgrade.WORKDIR.."/mesh_upgrade_cfg.tgz -C / etc/config/mesh-upgrade") -- perform a full config backup including mesh_upgrade config file needed for the next image -- surprisingly this does not presrve nodename + -- os.execute("sysupgrade -b ".. mesh_upgrade.WORKDIR.."/mesh_upgrade_cfg.tgz") config = require("lime.config") @@ -540,7 +550,7 @@ function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) config.set("system", "keep_on_upgrade", keep) --use set but not commit, so this configuration wont be preserved. mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) - mesh_upgrade.safeupgrade_start_mark=utils.uptime_s() + mesh_upgrade.safeupgrade_start_mark = utils.uptime_s() mesh_upgrade.trigger_sheredstate_publish() --this must be executed after a safe upgrade timeout to enable all nodes to start_safe_upgrade utils.execute_daemonized("sleep " .. From 14323cbf4f783849ba054ee83b26f6e6fa4349a3 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 15 Apr 2024 11:05:31 -0300 Subject: [PATCH 078/102] mesh-upgrade: fix ipv4 address, add support for sharedstate async --- packages/lime-mesh-upgrade/Makefile | 4 +- .../files/etc/config/mesh-upgrade | 2 + .../files/usr/lib/lua/lime-mesh-upgrade.lua | 32 ++++++---- .../tests/test_lime-mesh-upgrade.lua | 56 +++++++++++++---- .../tests/test_rpcd_lime_mesh_upgrade.lua | 60 +++++++++++++----- .../hooks/mesh_wide_upgrade/start_upgrade | 61 ------------------ .../shared-state_mesh_wide_upgrade_cron | 11 +++- .../shared-state-publish_mesh_wide_upgrade | 2 +- .../hooks/mesh_wide_upgrade/start_upgrade | 63 +++++++++++++++++++ 9 files changed, 188 insertions(+), 103 deletions(-) delete mode 100755 packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade create mode 100755 packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade diff --git a/packages/lime-mesh-upgrade/Makefile b/packages/lime-mesh-upgrade/Makefile index 1ee456963..079f898ba 100644 --- a/packages/lime-mesh-upgrade/Makefile +++ b/packages/lime-mesh-upgrade/Makefile @@ -11,7 +11,9 @@ define Package/$(PKG_NAME) CATEGORY:=LibreMesh MAINTAINER:=selankon TITLE:=LibreMesh mesh wide firmware upgrade - DEPENDS:= +lua +libubus-lua +wget +safe-upgrade +shared-state-mesh_wide_upgrade + DEPENDS:= +lua +libubus-lua +wget +safe-upgrade + +!shared-state-async:shared-state-mesh_wide_upgrade + +shared-state-async:shared-state-mesh_wide_upgrade-async PKGARCH:=all endef diff --git a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade index 2acd09301..0a0bb9bd8 100644 --- a/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade +++ b/packages/lime-mesh-upgrade/files/etc/config/mesh-upgrade @@ -8,4 +8,6 @@ config mesh-upgrade 'main' option timestamp '0' option main_node 'NO' option retry_count '0' + option safeupgrade_start_mark '0' + option su_start_time_out '0' \ No newline at end of file diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 0ede2cbd9..699b5c685 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -54,8 +54,9 @@ local mesh_upgrade = { -- Get the base url for the firmware repository in this node function mesh_upgrade.get_repo_base_url() - local ipv4, ipv6 = network.primary_address() - return "http://" .. ipv4:host():string() .. mesh_upgrade.FIRMWARE_REPO_PATH + local uci = config.get_uci_cursor() + local ipv4 = uci:get("network", "lan", "ipaddr") + return "http://" .. ipv4 .. mesh_upgrade.FIRMWARE_REPO_PATH end -- Create a work directory if doesn't exist @@ -279,8 +280,6 @@ end -- this function will be called by the main node to inform that the firmware is available -- also will force shared state data refresh --- curl -6 'http://[fe80::a8aa:aaff:fe0d:feaa%lime_br0]/fw/resolv.conf' --- curl -6 'http://[fd0d:fe46:8ce8::1]/lros/api/v1/' function mesh_upgrade.inform_download_location(version) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED and mesh_upgrade.main_node_state() == mesh_upgrade.main_node_states.STARTING then @@ -362,8 +361,7 @@ end function mesh_upgrade.trigger_sheredstate_publish() utils.execute_daemonized( "sleep 1; \ - shared-state bleach mesh_wide_upgrade; \ - /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state sync mesh_wide_upgrade") + /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") end function mesh_upgrade.change_main_node_state(newstate) @@ -510,11 +508,16 @@ function mesh_upgrade.get_node_status() upgrade_data.error = uci:get('mesh-upgrade', 'main', 'error') upgrade_data.retry_count = tonumber(uci:get('mesh-upgrade', 'main', 'retry_count')) upgrade_data.timestamp = tonumber(uci:get('mesh-upgrade', 'main', 'timestamp')) + mesh_upgrade.safeupgrade_start_mark = tonumber(uci:get('mesh-upgrade', 'main', 'safeupgrade_start_mark')) or 0 + upgrade_data.safeupgrade_start_mark = mesh_upgrade.safeupgrade_start_mark + + mesh_upgrade.su_start_time_out = tonumber(uci:get('mesh-upgrade', 'main', 'su_start_time_out')) or mesh_upgrade.su_start_time_out + upgrade_data.su_start_time_out = mesh_upgrade.su_start_time_out + upgrade_data.main_node = mesh_upgrade.main_node_state() upgrade_data.board_name = eupgrade._get_board_name() upgrade_data.current_fw = eupgrade._get_current_fw_version() - local ipv4, ipv6 = network.primary_address() - upgrade_data.node_ip = ipv4:host():string() + upgrade_data.node_ip = uci:get("network", "lan", "ipaddr") upgrade_data.safeupgrade_start_remining = (mesh_upgrade.su_start_time_out - (utils.uptime_s() - mesh_upgrade.safeupgrade_start_mark) > 0 and mesh_upgrade.su_start_time_out - (utils.uptime_s() - mesh_upgrade.safeupgrade_start_mark) or -1) upgrade_data.confirm_remining = tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) return upgrade_data @@ -532,7 +535,7 @@ function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) mesh_upgrade.report_error(mesh_upgrade.errors.INVALID_FW_FILE) return { code = "NOT_ABLE_TO_START_UPGRADE", - error = "Firmware not valid" + error = "Invalid Firmware" } end @@ -544,13 +547,20 @@ function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) -- os.execute("sysupgrade -b ".. mesh_upgrade.WORKDIR.."/mesh_upgrade_cfg.tgz") - config = require("lime.config") + --config = require("lime.config") local keep = config.get("system", "keep_on_upgrade", "") keep = keep .. " lime-mesh-upgrade" config.set("system", "keep_on_upgrade", keep) --use set but not commit, so this configuration wont be preserved. mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) mesh_upgrade.safeupgrade_start_mark = utils.uptime_s() + local uci = config.get_uci_cursor() + uci:set('mesh-upgrade', 'main', 'safeupgrade_start_mark',mesh_upgrade.safeupgrade_start_mark) + uci:set('mesh-upgrade', 'main', 'su_start_time_out',mesh_upgrade.su_start_time_out) + uci:set('mesh-upgrade', 'main', 'su_confirm_timeout',mesh_upgrade.su_confirm_timeout) + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') + mesh_upgrade.trigger_sheredstate_publish() --this must be executed after a safe upgrade timeout to enable all nodes to start_safe_upgrade utils.execute_daemonized("sleep " .. @@ -561,7 +571,7 @@ function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) return { code = "SUCCESS", error = "", - su_start_delay = mesh_upgrade.su_start_time_out, + su_start_time_out = mesh_upgrade.su_start_time_out, su_confirm_timeout = mesh_upgrade.su_confirm_timeout } diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 60f909467..4939acbfc 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -14,7 +14,7 @@ stub(utils, 'unsafe_shell', function(command) end) local utils = require "lime.utils" -local lime_mesh_upgrade = require 'lime-mesh-upgrade' +local lime_mesh_upgrade = {} local test_utils = require "tests.utils" local json = require 'luci.jsonc' local uci @@ -284,6 +284,10 @@ describe('LiMe mesh upgrade', function() stub(utils, 'file_exists', function() return true end) + + stub(os, 'execute', function() + return 0 + end) stub(lime_mesh_upgrade, 'get_fw_path', function() return "/tmp/foo.bar" @@ -300,13 +304,20 @@ describe('LiMe mesh upgrade', function() local status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) + assert.is.equal(lime_mesh_upgrade.su_confirm_timeout, 600) + assert.is.equal(lime_mesh_upgrade.su_start_time_out, 60) --should be called from rpcd - lime_mesh_upgrade.start_safe_upgrade() - status = lime_mesh_upgrade.get_node_status() + local response = lime_mesh_upgrade.start_safe_upgrade() + assert.is.equal(response.code,"SUCCESS") + assert.is.equal(response.su_confirm_timeout,600) + assert.is.equal(response.su_start_time_out,60) assert.stub.spy(utils.execute_daemonized).was.called.with( - "sleep 60; safe-upgrade upgrade --reboot-safety-timeout=600 /tmp/foo.bar") + "sleep 60; safe-upgrade upgrade --reboot-safety-timeout=600 /tmp/foo.bar") + + status = lime_mesh_upgrade.get_node_status() + assert.is.equal(lime_mesh_upgrade.su_confirm_timeout, 600) - assert.is.equal(lime_mesh_upgrade.su_start_time_out, 60) + assert.is.equal(status.su_start_time_out, 60) assert(status.safeupgrade_start_remining<60 and status.safeupgrade_start_remining>10) assert.is.equal(status.confirm_remining,-1) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) @@ -325,31 +336,43 @@ describe('LiMe mesh upgrade', function() stub(utils, 'execute_daemonized', function() end) - stub(lime_mesh_upgrade, 'state', function() - return lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE - end) - stub(utils, 'file_exists', function() return true end) - - stub(utils, 'file_exists', function() - return true + + stub(os, 'execute', function() + return 0 end) stub(lime_mesh_upgrade, 'get_fw_path', function() return "/tmp/foo.bar" end) - lime_mesh_upgrade.start_safe_upgrade(10, 100) + local fw_version = 'LibreMesh 19.02' + stub(eupgrade, '_get_current_fw_version', function() + return fw_version + end) + uci:set('mesh-upgrade', 'main', "mesh-upgrade") + uci:set('mesh-upgrade', 'main', "upgrade_state", "READY_FOR_UPGRADE") + uci:save('mesh-upgrade') + uci:commit('mesh-upgrade') + + local response = lime_mesh_upgrade.start_safe_upgrade(10, 100) + assert.is.equal(response.code,"SUCCESS") + + assert.is.equal(response.su_confirm_timeout, 100) + assert.is.equal(lime_mesh_upgrade.su_confirm_timeout, 100) assert.is.equal(lime_mesh_upgrade.su_start_time_out, 10) + assert.stub.spy(utils.execute_daemonized).was.called.with( "sleep 10; safe-upgrade upgrade --reboot-safety-timeout=100 /tmp/foo.bar") end) before_each('', function() snapshot = assert:snapshot() + lime_mesh_upgrade = require 'lime-mesh-upgrade' + uci = test_utils.setup_test_uci() uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:set('mesh-upgrade', 'main', "upgrade_state", "DEFAULT") @@ -360,6 +383,13 @@ describe('LiMe mesh upgrade', function() config.set('network', 'protocols', {'lan'}) config.set('wifi', 'lime') config.set('wifi', 'ap_ssid', 'LibreMesh.org') + + uci = config.get_uci_cursor() + uci:set('network', 'lan', 'interface') + uci:set('network', 'lan', 'ipaddr', '10.5.0.5') + uci:set('network', 'lan', 'ip6addr', 'fd0d:fe46:8ce8::ab:cd00/64') + uci:commit('network') + uci:commit('lime') uci:commit('mesh-upgrade') diff --git a/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua b/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua index 84744d905..54f6d9d5c 100644 --- a/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua @@ -1,16 +1,23 @@ local test_utils = require "tests.utils" local json = require("luci.jsonc") local eupgrade = require 'eupgrade' +local libuci = require 'uci' +local uci local testFileName = "packages/lime-mesh-upgrade/files/usr/libexec/rpcd/lime-mesh-upgrade" -local limeRpc = test_utils.load_lua_file_as_function(testFileName) +local limeRpc local rpcdCall = test_utils.rpcd_call - - describe('general rpc testing', function() + local snapshot -- to revert luassert stubs and spies + before_each('', function() + limeRpc = test_utils.load_lua_file_as_function(testFileName) + + snapshot = assert:snapshot() + uci = test_utils.setup_test_uci() + local boardname = 'librerouter-v1' stub(eupgrade, '_get_board_name', function() return boardname @@ -18,7 +25,6 @@ describe('general rpc testing', function() lime_mesh_upgrade = require 'lime-mesh-upgrade' snapshot = assert:snapshot() - uci = test_utils.setup_test_uci() uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:set('mesh-upgrade', 'main', "upgrade_state", "DEFAULT") uci:save('mesh-upgrade') @@ -29,11 +35,13 @@ describe('general rpc testing', function() config.set('wifi', 'lime') config.set('wifi', 'ap_ssid', 'LibreMesh.org') uci:commit('lime') - uci:commit('mesh-upgrade') end) after_each('', function() + snapshot:revert() + test_utils.teardown_test_uci(uci) + test_utils.teardown_test_dir() end) it('test list methods', function() @@ -49,7 +57,10 @@ describe('general rpc testing', function() it('test start_safe_upgrade different timeouts', function() stub(utils, 'execute_daemonized', function() end) - + + stub(os, 'execute', function() + return 0 + end) stub(lime_mesh_upgrade, 'state', function() return lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE @@ -59,25 +70,44 @@ describe('general rpc testing', function() return true end) - stub(utils, 'file_exists', function() - return true - end) - stub(lime_mesh_upgrade, 'get_fw_path', function() return "/tmp/foo.bar" end) local response = rpcdCall(limeRpc, { 'call', 'start_safe_upgrade'}, '{}') - assert.are.equal(response.code, "SUCCESS") - assert.are.equal(response.su_confirm_timeout, 600) - assert.are.equal(response.su_start_delay, 60) + assert.are.equal("SUCCESS", response.code ) + assert.are.equal(600,response.su_confirm_timeout) + assert.are.equal(60,response.su_start_time_out) local response = rpcdCall(limeRpc, { 'call', 'start_safe_upgrade'}, '{"confirm_timeout":15, "start_delay":150}') assert.are.equal(response.code, "SUCCESS") assert.are.equal(response.su_confirm_timeout, 15) - assert.are.equal(response.su_start_delay, 150) + assert.are.equal(response.su_start_time_out, 150) local response = rpcdCall(limeRpc, { 'call', 'start_safe_upgrade'}, '{}') assert.are.equal(response.code, "SUCCESS") assert.are.equal(response.su_confirm_timeout, 15) - assert.are.equal(response.su_start_delay, 150) + assert.are.equal(response.su_start_time_out, 150) + end) + + + + it('test start_safe_upgrade invalid firmware file', function() + stub(utils, 'execute_daemonized', function() + end) + + stub(lime_mesh_upgrade, 'state', function() + return lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE + end) + + stub(utils, 'file_exists', function() + return true + end) + + stub(lime_mesh_upgrade, 'get_fw_path', function() + return "/tmp/foo.bar" + end) + + local response = rpcdCall(limeRpc, { 'call', 'start_safe_upgrade'}, '{}') + assert.are.equal("NOT_ABLE_TO_START_UPGRADE", response.code ) + assert.are.equal("Invalid Firmware", response.error ) end) end) diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade deleted file mode 100755 index aed13bb89..000000000 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/lua - ---! LibreMesh ---! Copyright (C) 2019 Gioacchino Mazzurco ---! ---! This program is free software: you can redistribute it and/or modify ---! it under the terms of the GNU Affero General Public License as ---! published by the Free Software Foundation, either version 3 of the ---! License, or (at your option) any later version. ---! ---! This program is distributed in the hope that it will be useful, ---! but WITHOUT ANY WARRANTY; without even the implied warranty of ---! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ---! GNU Affero General Public License for more details. ---! ---! You should have received a copy of the GNU Affero General Public License ---! along with this program. If not, see . - -local JSON = require("luci.jsonc") -local utils = require "lime.utils" -local mesh_upgrade = require "lime-mesh-upgrade" -local hostname = utils.hostname() - -local indata = io.stdin:read("*all") ---if already involved in an upgrade transaction do nothing -if not mesh_upgrade.started() then - utils.log("starting an upgrade process") - for node, s_s_data in pairs(JSON.parse(indata)) do - --if any node has started an upgrade process and start one too? - --only fetch the info from the master node publication? - if node ~= hostname and s_s_data.data.main_node == mesh_upgrade.main_node_states.MAIN_NODE then - utils.log("starting an upgrade process") - - utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from "' .. - s_s_data.data.repo_url .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) - mesh_upgrade.become_bot_node(s_s_data.data) - else - utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "status "' .. - JSON.stringify(s_s_data.data) .. " from node " .. node) - end - end -else - --if started check that a main node has not aborted - for node, s_s_data in pairs(JSON.parse(indata)) do - utils.unsafe_shell('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from "' .. - s_s_data.data.main_node .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) - utils.log('logger -p daemon.info -t "mesh upgrade" "mesh upgrade detected upgrade from "' .. - s_s_data.data.main_node .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) - - if node ~= hostname and - s_s_data.data.main_node == mesh_upgrade.main_node_states.MAIN_NODE and - s_s_data.data.upgrade_state == mesh_upgrade.upgrade_states.ABORTED - then - mesh_upgrade.mesh_upgrade_abort() - utils.log("aborting, main has aborted") - utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "aborting, main has aborted"') - end - end - utils.unsafe_shell('logger -p daemon.info -t "messwideupgrade" "already started an upgrade process"') - utils.log("already started an upgrade process") -end diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/shared-state_mesh_wide_upgrade_cron b/packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/shared-state_mesh_wide_upgrade_cron index 7ee1858f2..47b647012 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/shared-state_mesh_wide_upgrade_cron +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/shared-state_mesh_wide_upgrade_cron @@ -1,9 +1,18 @@ #!/bin/sh + unique_append() { grep -qF "$1" "$2" || echo "$1" >> "$2" } +uci set shared-state.mesh_wide_upgrade=dataType +uci set shared-state.mesh_wide_upgrade.name='mesh_wide_upgrade' +uci set shared-state.mesh_wide_upgrade.scope='community' +uci set shared-state.mesh_wide_upgrade.ttl='2400' +uci set shared-state.mesh_wide_upgrade.update_interval='30' +uci commit shared-state + unique_append \ - '*/5 * * * * ((sleep $(($RANDOM % 120)); shared-state sync mesh_wide_upgrade &> /dev/null)&)'\ + '*/30 * * * * ((sleep $(($RANDOM % 120)); shared-state-publish_mesh_wide_upgrade &> /dev/null)&)' \ /etc/crontabs/root + diff --git a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade index 5da94eed9..7b7ce8f37 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade @@ -28,4 +28,4 @@ function report_upgrade_status() end local result = { [hostname] = report_upgrade_status() } -io.popen("shared-state insert mesh_wide_upgrade", "w"):write(JSON.stringify(result)) +io.popen("shared-state-async insert mesh_wide_upgrade", "w"):write(JSON.stringify(result)) diff --git a/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade new file mode 100755 index 000000000..142521b96 --- /dev/null +++ b/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -0,0 +1,63 @@ +#!/usr/bin/lua + +--! LibreMesh +--! Copyright (C) 2019 Gioacchino Mazzurco +--! +--! This program is free software: you can redistribute it and/or modify +--! it under the terms of the GNU Affero General Public License as +--! published by the Free Software Foundation, either version 3 of the +--! License, or (at your option) any later version. +--! +--! This program is distributed in the hope that it will be useful, +--! but WITHOUT ANY WARRANTY; without even the implied warranty of +--! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +--! GNU Affero General Public License for more details. +--! +--! You should have received a copy of the GNU Affero General Public License +--! along with this program. If not, see . + +local JSON = require("luci.jsonc") +local utils = require "lime.utils" +local mesh_upgrade = require "lime-mesh-upgrade" +local hostname = utils.hostname() + +utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "************************************* "') + +local indata = io.stdin:read("*all") +utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "'.. indata .. ' fin"' ) +utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "************************************* "') + +--if already involved in an upgrade transaction do nothing +if not mesh_upgrade.started() then + utils.log("async: starting an upgrade process") + for node, s_s_data in pairs(JSON.parse(indata)) do + --if any node has started an upgrade process and start one too? + --only fetch the info from the master node publication? + if node ~= hostname and s_s_data.main_node == mesh_upgrade.main_node_states.MAIN_NODE then + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "mesh upgrade detected upgrade from ' .. + s_s_data.repo_url .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data)..'"') + mesh_upgrade.become_bot_node(s_s_data) + else + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "status "' .. + JSON.stringify(s_s_data) .. " from node " .. node) + end + end +else + --if started check that a main node has not aborted + for node, s_s_data in pairs(JSON.parse(indata)) do + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "mesh upgrade detected upgrade from "' .. + s_s_data.main_node .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "mesh upgrade detected upgrade from "' .. + s_s_data.main_node .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) + + if node ~= hostname and + s_s_data.main_node == mesh_upgrade.main_node_states.MAIN_NODE and + s_s_data.upgrade_state == mesh_upgrade.upgrade_states.ABORTED + then + mesh_upgrade.mesh_upgrade_abort() + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "aborting, main has aborted"') + end + end + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "already started an upgrade process"') + utils.log("already started an upgrade process") +end \ No newline at end of file From e9f334fde0031f586927b97deb08c0baa8d423c5 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 15 Apr 2024 11:20:53 -0300 Subject: [PATCH 079/102] mesh-upgrade: fix makefile dependencies --- packages/lime-mesh-upgrade/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lime-mesh-upgrade/Makefile b/packages/lime-mesh-upgrade/Makefile index 079f898ba..d05809461 100644 --- a/packages/lime-mesh-upgrade/Makefile +++ b/packages/lime-mesh-upgrade/Makefile @@ -12,8 +12,8 @@ define Package/$(PKG_NAME) MAINTAINER:=selankon TITLE:=LibreMesh mesh wide firmware upgrade DEPENDS:= +lua +libubus-lua +wget +safe-upgrade - +!shared-state-async:shared-state-mesh_wide_upgrade - +shared-state-async:shared-state-mesh_wide_upgrade-async + +shared-state-mesh_wide_upgrade + PKGARCH:=all endef From fad984b6b67077e91ae12a6c6299b5da09f1fbb0 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 15 Apr 2024 15:32:37 -0300 Subject: [PATCH 080/102] mesh-upgrade: fixes ip test failure --- packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 4939acbfc..651648def 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -273,7 +273,7 @@ describe('LiMe mesh upgrade', function() assert.is.equal(status.candidate_fw, json.parse(latest_release_data).version) assert.is.equal(status.board_name, boardname) assert.is.equal(status.main_node, lime_mesh_upgrade.main_node_states.MAIN_NODE) - assert.is.equal(status.repo_url, 'http://10.1.1.0/lros/') + assert.is.equal(status.repo_url, 'http://10.5.0.5/lros/') end) it('test start_safe_upgrade default timeouts', function() From 7c62efd15bf42557a37882af1de2ad9b96d9f287 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 15 Apr 2024 16:41:05 -0300 Subject: [PATCH 081/102] mesh-upgrade: fixes makefile error --- packages/lime-mesh-upgrade/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lime-mesh-upgrade/Makefile b/packages/lime-mesh-upgrade/Makefile index d05809461..3654094d5 100644 --- a/packages/lime-mesh-upgrade/Makefile +++ b/packages/lime-mesh-upgrade/Makefile @@ -11,7 +11,7 @@ define Package/$(PKG_NAME) CATEGORY:=LibreMesh MAINTAINER:=selankon TITLE:=LibreMesh mesh wide firmware upgrade - DEPENDS:= +lua +libubus-lua +wget +safe-upgrade + DEPENDS:= +lua +libubus-lua +wget +safe-upgrade \ +shared-state-mesh_wide_upgrade PKGARCH:=all From 0db996553fc2c5eb07b34e734ca573957dccf1ad Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 15 Apr 2024 16:47:33 -0300 Subject: [PATCH 082/102] mesh-upgrade:deleted unnecesary file --- .../publishers/shared-state-publish_mesh_wide_upgrade | 1 - 1 file changed, 1 deletion(-) delete mode 120000 packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade deleted file mode 120000 index ee2664e94..000000000 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade +++ /dev/null @@ -1 +0,0 @@ -../../../usr/bin/shared-state-publish_mesh_wide_upgrade \ No newline at end of file From c39be29349d32cce86fd5aaf90be8030979efee5 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Tue, 16 Apr 2024 18:13:04 -0300 Subject: [PATCH 083/102] mesh_upgrade: implements delayed insert --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 16 ++++- .../tests/test_lime-mesh-upgrade.lua | 59 ++++++++++++++++++- .../tests/test_rpcd_lime_mesh_upgrade.lua | 11 ++++ 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 699b5c685..726000b16 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -287,7 +287,7 @@ function mesh_upgrade.inform_download_location(version) mesh_upgrade.set_mesh_upgrade_info({ candidate_fw = version, repo_url = mesh_upgrade.get_repo_base_url(), - upgrde_state = mesh_upgrade.upgrade_states.READY_FOR_UPGRADE, + upgrade_state = mesh_upgrade.upgrade_states.READY_FOR_UPGRADE, error = "", timestamp = os.time(), main_node = mesh_upgrade.main_node_states.MAIN_NODE, @@ -359,9 +359,19 @@ end -- This line will genereate recursive dependencies like in pirania pakcage function mesh_upgrade.trigger_sheredstate_publish() - utils.execute_daemonized( - "sleep 1; \ + --utils.execute_daemonized( + -- "sleep 1; \ + -- /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") + -- minimum renewal time is 30s if not able to renew info just wait + utils.unsafe_shell("/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade") + local status = json.parse(utils.unsafe_shell("shared-state-async get mesh_wide_upgrade")) + if status and next(status) ~= nil and status[utils.hostname()].upgrade_state ~= mesh_upgrade.state() then + utils.execute_daemonized("sleep 30; \ /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") + else + utils.execute_daemonized("sleep 1; shared-state-async sync mesh_wide_upgrade") + end + end function mesh_upgrade.change_main_node_state(newstate) diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 651648def..f5d663b4f 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -6,11 +6,55 @@ stub(eupgrade, '_get_board_name', function() return boardname end) +local mesh_wide_sample = [[ + { + "LiMe-8a50aa": { + "eupgradestate": "not-initiated", + "confirm_remining": -1, + "safeupgrade_start_remining": -1, + "safeupgrade_start_mark": 0, + "upgrade_state": "UPGRADE_SCHEDULED", + "current_fw": "LibreRouterOs 23.05-SNAPSHOT r1+1-48c81b80b2", + "main_node": "NO", + "node_ip": "10.13.80.170", + "board_name": "librerouter,librerouter-v1", + "su_start_time_out": 0, + "timestamp": 0, + "error": "0", + "retry_count": 0 + }, + "LiMe-a51ed1": { + "repo_url": "http://10.13.80.170/lros/", + "confirm_remining": -1, + "candidate_fw": "LibreRouterOs r23744", + "safeupgrade_start_remining": -1, + "safeupgrade_start_mark": 0, + "retry_count": 0, + "upgrade_state": "ERROR", + "current_fw": "LibreRouterOs 23.05-SNAPSHOT r1+1-48c81b80b2", + "main_node": "NO", + "node_ip": "10.13.30.209", + "board_name": "librerouter,librerouter-v1", + "su_start_time_out": 0, + "timestamp": 1713282042, + "error": "no_latest_data_available", + "eupgradestate": "not-initiated" + } + } + +]] + confirm_remaining = -1 stub(utils, 'unsafe_shell', function(command) + if command == "safe-upgrade confirm-remaining" then + return confirm_remaining + elseif command == "shared-state-async get mesh_wide_upgrade" then + return mesh_wide_sample + end print(command) return confirm_remaining + end) local utils = require "lime.utils" @@ -83,12 +127,19 @@ describe('LiMe mesh upgrade', function() end) it('test abort ', function() + stub(utils, 'execute_daemonized', function() + end) stub(eupgrade, '_get_current_fw_version', function() return 'LibreMesh 19.05' end) + stub(utils, 'hostname', function() + return "LiMe-8a50aa" + end) lime_mesh_upgrade.mesh_upgrade_abort() status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ABORTED) + assert.stub.spy(utils.execute_daemonized).was.called.with("sleep 30; \ + /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") end) it('test set upgrade info and fail NO_LATEST_AVAILABLE', function() @@ -315,7 +366,10 @@ describe('LiMe mesh upgrade', function() "sleep 60; safe-upgrade upgrade --reboot-safety-timeout=600 /tmp/foo.bar") status = lime_mesh_upgrade.get_node_status() - + + assert.stub.spy(utils.execute_daemonized).was.called.with( + "sleep 1; shared-state-async sync mesh_wide_upgrade") + assert.is.equal(lime_mesh_upgrade.su_confirm_timeout, 600) assert.is.equal(status.su_start_time_out, 60) assert(status.safeupgrade_start_remining<60 and status.safeupgrade_start_remining>10) @@ -371,6 +425,9 @@ describe('LiMe mesh upgrade', function() before_each('', function() snapshot = assert:snapshot() + stub(utils, 'hostname', function() + return "LiMe-8a50aa" + end) lime_mesh_upgrade = require 'lime-mesh-upgrade' uci = test_utils.setup_test_uci() diff --git a/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua b/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua index 54f6d9d5c..97c8f7a10 100644 --- a/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua @@ -18,6 +18,17 @@ describe('general rpc testing', function() snapshot = assert:snapshot() uci = test_utils.setup_test_uci() + stub(utils, 'unsafe_shell', function(command) + if command == "safe-upgrade confirm-remaining" then + return confirm_remaining + elseif command == "shared-state-async get mesh_wide_upgrade" then + return "{}" + end + print(command) + return confirm_remaining + + end) + local boardname = 'librerouter-v1' stub(eupgrade, '_get_board_name', function() return boardname From 98ba39920d863e180607f4bacd1d1da463fd4c4a Mon Sep 17 00:00:00 2001 From: javierbrk Date: Fri, 19 Apr 2024 07:10:25 -0300 Subject: [PATCH 084/102] mesh-upgrade: fixes deadlock in publish --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 34 ++++++++----------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 726000b16..1fd8cb6b8 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -62,7 +62,7 @@ end -- Create a work directory if doesn't exist function mesh_upgrade._create_workdir(workdir) if not utils.file_exists(workdir) then - os.execute('mkdir -p ' .. workdir .. " >/dev/null") + os.execute('mkdir -p ' .. workdir .. " >/dev/null 2>&1") end if fs.stat(workdir, "type") ~= "dir" then error("Can't configure workdir " .. workdir) @@ -121,11 +121,11 @@ function mesh_upgrade.share_firmware_packages(dest) mesh_upgrade._create_workdir(dest) -- json file has to be placed in a url that ends with latest mesh_upgrade._create_workdir(dest .. "/latest") - os.execute("ln -s " .. images_folder .. "/* " .. dest .. " >/dev/null") - os.execute("ln -s " .. mesh_upgrade.LATEST_JSON_PATH .. " " .. dest .. "/latest >/dev/null") - os.execute("chmod -R 777 " .. dest .. " >/dev/null") - os.execute("chmod -R 777 " .. mesh_upgrade.WORKDIR .. " >/dev/null") - os.execute("chmod -R 777 " .. images_folder .. " >/dev/null") + os.execute("ln -s " .. images_folder .. "/* " .. dest .. " >/dev/null 2>&1") + os.execute("ln -s " .. mesh_upgrade.LATEST_JSON_PATH .. " " .. dest .. "/latest >/dev/null 2>&1") + os.execute("chmod -R 777 " .. dest .. " >/dev/null 2>&1") + os.execute("chmod -R 777 " .. mesh_upgrade.WORKDIR .. " >/dev/null 2>&1") + os.execute("chmod -R 777 " .. images_folder .. " >/dev/null 2>&1") end -- This function will download latest firmware and expose it as @@ -133,7 +133,7 @@ end function mesh_upgrade.start_main_node_repository(latest_data) -- Create local repository json data mesh_upgrade.create_local_latest_json(latest_data) - utils.execute_daemonized("eupgrade-download >/dev/null") + utils.execute_daemonized("eupgrade-download >/dev/null 2>&1") mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) end @@ -359,19 +359,13 @@ end -- This line will genereate recursive dependencies like in pirania pakcage function mesh_upgrade.trigger_sheredstate_publish() - --utils.execute_daemonized( - -- "sleep 1; \ - -- /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") - -- minimum renewal time is 30s if not able to renew info just wait - utils.unsafe_shell("/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade") - local status = json.parse(utils.unsafe_shell("shared-state-async get mesh_wide_upgrade")) - if status and next(status) ~= nil and status[utils.hostname()].upgrade_state ~= mesh_upgrade.state() then - utils.execute_daemonized("sleep 30; \ + utils.execute_daemonized( + "sleep 1; \ + /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") + --minimum renewal time is 30s if not able to renew info just wait, if firts fails the seccond success, + -- if the first succesds the seccond will fail. Sadly merge will output 0 so both times will make sync. + utils.execute_daemonized("sleep 30; \ /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") - else - utils.execute_daemonized("sleep 1; shared-state-async sync mesh_wide_upgrade") - end - end function mesh_upgrade.change_main_node_state(newstate) @@ -469,7 +463,7 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state) local uci = config.get_uci_cursor() if string.match(upgrade_data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil -- todo (javi): perform aditional checks then - utils.log("seting up repo download info to " .. upgrade_state .. " actual " .. mesh_upgrade.state()) + --utils.log("seting up repo download info to " .. upgrade_state .. " actual " .. mesh_upgrade.state()) if (mesh_upgrade.change_state(upgrade_state)) then uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.repo_url) From 58a3feabc0cc42427aa41e36169711fa96092454 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Fri, 19 Apr 2024 07:15:03 -0300 Subject: [PATCH 085/102] mesh-upgrade: cleans log comments --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 1fd8cb6b8..5f05faceb 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -255,25 +255,18 @@ function mesh_upgrade.start_node_download(url) local cached_only = false local url2 = eupgrade.get_upgrade_api_url() local latest_data, message = eupgrade.is_new_version_available(cached_only) - --utils.log("start_node_download from " .. url2) - if latest_data then - --utils.log("start_node_download ") mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) - --utils.log("downloading") local image = {} image = eupgrade.download_firmware(latest_data) if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED and image ~= nil then - --utils.printJson(image) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) mesh_upgrade.trigger_sheredstate_publish() mesh_upgrade.set_fw_path(image) else - --utils.log("Error ... download failed") mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) end else - --utils.log("Error ... no latest data available" .. message) mesh_upgrade.report_error(mesh_upgrade.errors.NO_LATEST_AVAILABLE) end end @@ -463,7 +456,6 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state) local uci = config.get_uci_cursor() if string.match(upgrade_data.repo_url, "https?://[%w-_%.%?%.:/%+=&]+") ~= nil -- todo (javi): perform aditional checks then - --utils.log("seting up repo download info to " .. upgrade_state .. " actual " .. mesh_upgrade.state()) if (mesh_upgrade.change_state(upgrade_state)) then uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:set('mesh-upgrade', 'main', 'repo_url', upgrade_data.repo_url) @@ -477,11 +469,9 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state) uci:commit('mesh-upgrade') return true else - --utils.log("invalid state change ") return false end else - --utils.log("upgrade failed due input data errors") return false end end @@ -566,7 +556,7 @@ function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) uci:commit('mesh-upgrade') mesh_upgrade.trigger_sheredstate_publish() - --this must be executed after a safe upgrade timeout to enable all nodes to start_safe_upgrade + --upgrade must be executed after a safe upgrade timeout to enable all nodes to start_safe_upgrade utils.execute_daemonized("sleep " .. mesh_upgrade.su_start_time_out .. "; safe-upgrade upgrade --reboot-safety-timeout=" .. @@ -580,7 +570,6 @@ function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) } else - ----utils.log("not able to start upgrade invalid state or firmware not found") mesh_upgrade.report_error(mesh_upgrade.errors.FW_FILE_NOT_FOUND) return { code = "NOT_ABLE_TO_START_UPGRADE", From d2ae110530c4556b5432c90c492b64899d12e29c Mon Sep 17 00:00:00 2001 From: javierbrk Date: Fri, 19 Apr 2024 12:20:11 -0300 Subject: [PATCH 086/102] mesh-upgrade: adds readme message --- packages/lime-mesh-upgrade/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 packages/lime-mesh-upgrade/README.md diff --git a/packages/lime-mesh-upgrade/README.md b/packages/lime-mesh-upgrade/README.md new file mode 100644 index 000000000..a1579a845 --- /dev/null +++ b/packages/lime-mesh-upgrade/README.md @@ -0,0 +1,13 @@ +# Mesh upgrade +This package can help you upgrade the firmware of all the routers in a network from a single node. + +## Description and steps +1- A node must become main node, the main node will fetch the firmware for all the others. And expose it in the local network. +2- The main node announces the new firmware over shared-state-async +3- Other nodes with this package will get the news and try to download the firmware. +4- Once all the nodes have the firmware in their tmp folder the main node user will be able to schedule the safe upgrade of all the nodes (this last step is done synchronously). +5- After the specified time (60s default) all the nodes will start the safe upgrade process and the nodes will reboot. +6- The nodes will report that the new firmware has to be confirmed. +7- The main node user will verify that everything is in place an press the confirm button. +8- If the firmware is not confirmed after 600 seconds the routers will go back to the previous firmware. + From d14626f9c7fde3eada648da77f62244cbfd8b8ac Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Fri, 19 Apr 2024 14:43:43 -0300 Subject: [PATCH 087/102] mesh-upgrade: fix ability to start a new upgrade after confirmation --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 159 +++++++++--------- .../tests/test_lime-mesh-upgrade.lua | 46 ++++- 2 files changed, 121 insertions(+), 84 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 5f05faceb..c0dcecb9b 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -91,13 +91,9 @@ end function mesh_upgrade.set_workdir(workdir) mesh_upgrade._create_workdir(workdir) mesh_upgrade.WORKDIR = workdir - mesh_upgrade.LATEST_JSON_FILE_NAME = utils.slugify(eupgrade._get_board_name()) .. - ".json" -- latest json with local lan url file name - mesh_upgrade.LATEST_JSON_PATH = mesh_upgrade.WORKDIR .. - "/" .. - mesh_upgrade.LATEST_JSON_FILE_NAME -- latest json full path - mesh_upgrade.FIRMWARE_REPO_PATH = - '/lros/' -- path url for firmwares + mesh_upgrade.LATEST_JSON_FILE_NAME = utils.slugify(eupgrade._get_board_name()) .. ".json" -- latest json with local lan url file name + mesh_upgrade.LATEST_JSON_PATH = mesh_upgrade.WORKDIR .. "/" .. mesh_upgrade.LATEST_JSON_FILE_NAME -- latest json full path + mesh_upgrade.FIRMWARE_REPO_PATH = '/lros/' -- path url for firmwares mesh_upgrade.FIRMWARE_SHARED_FOLDER = '/www/' .. mesh_upgrade.FIRMWARE_REPO_PATH end @@ -106,7 +102,7 @@ mesh_upgrade.set_workdir("/tmp/mesh_upgrade") function mesh_upgrade.create_local_latest_json(latest_data) for _, im in pairs(latest_data['images']) do -- im['download-urls'] = string.gsub(im['download-urls'], upgrade_url, "test") - im['download-urls'] = { mesh_upgrade.get_repo_base_url() .. im['name'] } + im['download-urls'] = {mesh_upgrade.get_repo_base_url() .. im['name']} end utils.write_file(mesh_upgrade.LATEST_JSON_PATH, json.stringify(latest_data)) -- For the moment mesh upgrade will ignore the latest json signature on de main nodes @@ -177,8 +173,7 @@ function mesh_upgrade.check_eupgrade_download_failed() local download_status = eupgrade.get_download_status() local upgrade_state = mesh_upgrade.state() - if upgrade_state == mesh_upgrade.upgrade_states.DOWNLOADING - and download_status == eupgrade.STATUS_DOWNLOAD_FAILED then + if upgrade_state == mesh_upgrade.upgrade_states.DOWNLOADING and download_status == eupgrade.STATUS_DOWNLOAD_FAILED then mesh_upgrade.report_error(mesh_upgrade.errors.DOWNLOAD_FAILED) end return download_status @@ -201,8 +196,8 @@ function mesh_upgrade.start_firmware_upgrade_transaction() error = "No new firmware file downloaded" } end - --this is redundant but there is an scenario when download information is - --outdated and this check is necesary + -- this is redundant but there is an scenario when download information is + -- outdated and this check is necesary local latest = eupgrade.is_new_version_available(true) if not latest then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DEFAULT) @@ -274,8 +269,8 @@ end -- this function will be called by the main node to inform that the firmware is available -- also will force shared state data refresh function mesh_upgrade.inform_download_location(version) - if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED - and mesh_upgrade.main_node_state() == mesh_upgrade.main_node_states.STARTING then + if eupgrade.get_download_status() == eupgrade.STATUS_DOWNLOADED and mesh_upgrade.main_node_state() == + mesh_upgrade.main_node_states.STARTING then -- TODO: setup uhttpd to serve workdir location mesh_upgrade.set_mesh_upgrade_info({ candidate_fw = version, @@ -295,11 +290,10 @@ end -- Validate if the upgrade has already started function mesh_upgrade.started() status = mesh_upgrade.state() - if status == mesh_upgrade.upgrade_states.DEFAULT or - --if an error has ocurred then there is no transaction - status == mesh_upgrade.upgrade_states.ERROR or - status == mesh_upgrade.upgrade_states.ABORTED - then + if status == mesh_upgrade.upgrade_states.DEFAULT or -- if an error has ocurred then there is no transaction + status == mesh_upgrade.upgrade_states.ERROR or + status == mesh_upgrade.upgrade_states.ABORTED or + status == mesh_upgrade.upgrade_states.CONFIRMED then return false end return true @@ -332,7 +326,7 @@ end function mesh_upgrade.mesh_upgrade_abort() if mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ABORTED) then - --mesh_upgrade.change_main_node_state(mesh_upgrade.main_node_states.NO) + -- mesh_upgrade.change_main_node_state(mesh_upgrade.main_node_states.NO) local uci = config.get_uci_cursor() uci:set('mesh-upgrade', 'main', 'retry_count', 0) uci:save('mesh-upgrade') @@ -340,9 +334,8 @@ function mesh_upgrade.mesh_upgrade_abort() mesh_upgrade.trigger_sheredstate_publish() -- todo(javi): stop and delete everything -- kill posible safe upgrade command - utils.unsafe_shell("kill $(ps| grep 'sh -c (( sleep " .. - mesh_upgrade.su_start_time_out .. - "; safe-upgrade upgrade'| awk '{print $1}')") + utils.unsafe_shell("kill $(ps| grep 'sh -c (( sleep " .. mesh_upgrade.su_start_time_out .. + "; safe-upgrade upgrade'| awk '{print $1}')") end return { code = "SUCCESS", @@ -352,10 +345,9 @@ end -- This line will genereate recursive dependencies like in pirania pakcage function mesh_upgrade.trigger_sheredstate_publish() - utils.execute_daemonized( - "sleep 1; \ + utils.execute_daemonized("sleep 1; \ /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") - --minimum renewal time is 30s if not able to renew info just wait, if firts fails the seccond success, + -- minimum renewal time is 30s if not able to renew info just wait, if firts fails the seccond success, -- if the first succesds the seccond will fail. Sadly merge will output 0 so both times will make sync. utils.execute_daemonized("sleep 30; \ /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") @@ -363,13 +355,12 @@ end function mesh_upgrade.change_main_node_state(newstate) local main_node_state = mesh_upgrade.main_node_state() - --if newstate == main_node_state then return false end + -- if newstate == main_node_state then return false end -- if newstate == mesh_upgrade.main_node_states.STARTING and -- main_node_state ~= mesh_upgrade.main_node_states.NO then -- return false - if newstate == mesh_upgrade.main_node_states.MAIN_NODE and - main_node_state ~= mesh_upgrade.main_node_states.STARTING then + if newstate == mesh_upgrade.main_node_states.MAIN_NODE and main_node_state ~= mesh_upgrade.main_node_states.STARTING then return false end @@ -384,25 +375,25 @@ end function mesh_upgrade.change_state(newstate) local actual_state = mesh_upgrade.state() -- If the state is the same just return - if newstate == actual_state then return false end + if newstate == actual_state then + return false + end - if newstate == mesh_upgrade.upgrade_states.DOWNLOADING and - actual_state ~= mesh_upgrade.upgrade_states.DEFAULT and - actual_state ~= mesh_upgrade.upgrade_states.ERROR and - actual_state ~= mesh_upgrade.upgrade_states.UPDATED and + if newstate == mesh_upgrade.upgrade_states.DOWNLOADING and actual_state ~= mesh_upgrade.upgrade_states.DEFAULT and + actual_state ~= mesh_upgrade.upgrade_states.ERROR and actual_state ~= mesh_upgrade.upgrade_states.CONFIRMED and actual_state ~= mesh_upgrade.upgrade_states.ABORTED then return false - elseif newstate == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE and - actual_state ~= mesh_upgrade.upgrade_states.DOWNLOADING then + elseif newstate == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE and actual_state ~= + mesh_upgrade.upgrade_states.DOWNLOADING then return false - elseif newstate == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED and - actual_state ~= mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then + elseif newstate == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED and actual_state ~= + mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then return false - elseif newstate == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING and - actual_state ~= mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then + elseif newstate == mesh_upgrade.upgrade_states.CONFIRMATION_PENDING and actual_state ~= + mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED then return false - elseif newstate == mesh_upgrade.upgrade_states.UPDATED and - actual_state ~= mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then + elseif newstate == mesh_upgrade.upgrade_states.CONFIRMED and actual_state ~= + mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then return false end -- todo(javi): verify other states and return false if it is not possible @@ -414,40 +405,43 @@ function mesh_upgrade.change_state(newstate) return true end ---this function will retry max_retry_conunt tymes in case of error +-- this function will retry max_retry_conunt tymes in case of error +-- It will only fetch new information if main node has aborted or main node is +-- ready for upgraade function mesh_upgrade.become_bot_node(main_node_upgrade_data) if main_node_upgrade_data.upgrade_state == mesh_upgrade.upgrade_states.ABORTED then utils.log("main node has aborted") mesh_upgrade.mesh_upgrade_abort() return - end - - if mesh_upgrade.started() then - utils.log("node has already started") - return - else - utils.log("node has not started") - - main_node_upgrade_data.main_node = mesh_upgrade.main_node_states.NO - actual_state = mesh_upgrade.get_node_status() - if actual_state.timestamp == main_node_upgrade_data.timestamp and - actual_state.repo_url == main_node_upgrade_data.repo_url then - main_node_upgrade_data.retry_count = actual_state.retry_count + 1 + elseif main_node_upgrade_data.upgrade_state == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then + if mesh_upgrade.started() then + utils.log("node has already started") + return else - main_node_upgrade_data.retry_count = 0 - end - - if main_node_upgrade_data.retry_count < mesh_upgrade.max_retry_conunt then - if (mesh_upgrade.set_mesh_upgrade_info(main_node_upgrade_data, mesh_upgrade.upgrade_states.DOWNLOADING)) then - mesh_upgrade.start_node_download(main_node_upgrade_data.repo_url) - -- trigger shared state data refresh - mesh_upgrade.trigger_sheredstate_publish() + utils.log("node has not started") + local actual_state = mesh_upgrade.get_node_status() + if actual_state.timestamp == main_node_upgrade_data.timestamp and actual_state.repo_url == + main_node_upgrade_data.repo_url then + main_node_upgrade_data.retry_count = actual_state.retry_count + 1 + else + main_node_upgrade_data.retry_count = 0 end - else - utils.log("max retry_count has been reached") + if main_node_upgrade_data.retry_count < mesh_upgrade.max_retry_conunt then + utils.log("seting upgrade info") + main_node_upgrade_data.main_node = mesh_upgrade.main_node_states.NO + if (mesh_upgrade.set_mesh_upgrade_info(main_node_upgrade_data, mesh_upgrade.upgrade_states.DOWNLOADING)) then + mesh_upgrade.start_node_download(main_node_upgrade_data.repo_url) + -- trigger shared state data refresh + mesh_upgrade.trigger_sheredstate_publish() + end + else + utils.log("max retry_count has been reached") + end end end + utils.log("Main node is not ready for upgrade") + end -- set download information for the new firmware from main node @@ -462,7 +456,7 @@ function mesh_upgrade.set_mesh_upgrade_info(upgrade_data, upgrade_state) uci:set('mesh-upgrade', 'main', 'candidate_fw', upgrade_data.candidate_fw) uci:set('mesh-upgrade', 'main', 'error', "") uci:set('mesh-upgrade', 'main', 'retry_count', upgrade_data.retry_count or 0) - --timestamp is used as id ... every node must have the same one + -- timestamp is used as id ... every node must have the same one uci:set('mesh-upgrade', 'main', 'timestamp', upgrade_data.timestamp) uci:set('mesh-upgrade', 'main', 'main_node', upgrade_data.main_node) uci:save('mesh-upgrade') @@ -505,14 +499,18 @@ function mesh_upgrade.get_node_status() mesh_upgrade.safeupgrade_start_mark = tonumber(uci:get('mesh-upgrade', 'main', 'safeupgrade_start_mark')) or 0 upgrade_data.safeupgrade_start_mark = mesh_upgrade.safeupgrade_start_mark - mesh_upgrade.su_start_time_out = tonumber(uci:get('mesh-upgrade', 'main', 'su_start_time_out')) or mesh_upgrade.su_start_time_out + mesh_upgrade.su_start_time_out = tonumber(uci:get('mesh-upgrade', 'main', 'su_start_time_out')) or + mesh_upgrade.su_start_time_out upgrade_data.su_start_time_out = mesh_upgrade.su_start_time_out upgrade_data.main_node = mesh_upgrade.main_node_state() upgrade_data.board_name = eupgrade._get_board_name() upgrade_data.current_fw = eupgrade._get_current_fw_version() upgrade_data.node_ip = uci:get("network", "lan", "ipaddr") - upgrade_data.safeupgrade_start_remining = (mesh_upgrade.su_start_time_out - (utils.uptime_s() - mesh_upgrade.safeupgrade_start_mark) > 0 and mesh_upgrade.su_start_time_out - (utils.uptime_s() - mesh_upgrade.safeupgrade_start_mark) or -1) + upgrade_data.safeupgrade_start_remining = (mesh_upgrade.su_start_time_out - + (utils.uptime_s() - mesh_upgrade.safeupgrade_start_mark) > 0 and + mesh_upgrade.su_start_time_out - + (utils.uptime_s() - mesh_upgrade.safeupgrade_start_mark) or -1) upgrade_data.confirm_remining = tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) return upgrade_data end @@ -523,7 +521,7 @@ function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) if mesh_upgrade.state() == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then if utils.file_exists(mesh_upgrade.get_fw_path()) then - + -- veryfy the image before starting if os.execute("sysupgrade --test " .. mesh_upgrade.get_fw_path()) ~= 0 then mesh_upgrade.report_error(mesh_upgrade.errors.INVALID_FW_FILE) @@ -538,29 +536,28 @@ function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) -- perform a full config backup including mesh_upgrade config file needed for the next image -- surprisingly this does not presrve nodename - + -- os.execute("sysupgrade -b ".. mesh_upgrade.WORKDIR.."/mesh_upgrade_cfg.tgz") - --config = require("lime.config") + -- config = require("lime.config") local keep = config.get("system", "keep_on_upgrade", "") keep = keep .. " lime-mesh-upgrade" - config.set("system", "keep_on_upgrade", keep) --use set but not commit, so this configuration wont be preserved. + config.set("system", "keep_on_upgrade", keep) -- use set but not commit, so this configuration wont be preserved. mesh_upgrade.change_state(mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) mesh_upgrade.safeupgrade_start_mark = utils.uptime_s() local uci = config.get_uci_cursor() - uci:set('mesh-upgrade', 'main', 'safeupgrade_start_mark',mesh_upgrade.safeupgrade_start_mark) - uci:set('mesh-upgrade', 'main', 'su_start_time_out',mesh_upgrade.su_start_time_out) - uci:set('mesh-upgrade', 'main', 'su_confirm_timeout',mesh_upgrade.su_confirm_timeout) + uci:set('mesh-upgrade', 'main', 'safeupgrade_start_mark', mesh_upgrade.safeupgrade_start_mark) + uci:set('mesh-upgrade', 'main', 'su_start_time_out', mesh_upgrade.su_start_time_out) + uci:set('mesh-upgrade', 'main', 'su_confirm_timeout', mesh_upgrade.su_confirm_timeout) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') mesh_upgrade.trigger_sheredstate_publish() - --upgrade must be executed after a safe upgrade timeout to enable all nodes to start_safe_upgrade - utils.execute_daemonized("sleep " .. - mesh_upgrade.su_start_time_out .. - "; safe-upgrade upgrade --reboot-safety-timeout=" .. - mesh_upgrade.su_confirm_timeout .. " " .. mesh_upgrade.get_fw_path()) + -- upgrade must be executed after a safe upgrade timeout to enable all nodes to start_safe_upgrade + utils.execute_daemonized("sleep " .. mesh_upgrade.su_start_time_out .. + "; safe-upgrade upgrade --reboot-safety-timeout=" .. + mesh_upgrade.su_confirm_timeout .. " " .. mesh_upgrade.get_fw_path()) return { code = "SUCCESS", diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index f5d663b4f..079e66ed8 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -66,7 +66,7 @@ local uci local upgrade_data = { candidate_fw = "xxxx", repo_url = "http://repo.librerouter.org/lros/api/v1/latest/", - upgrade_state = "starting,downloading|ready_for_upgrade|upgrade_scheluded|confirmation_pending|~~confirmed~~|updated|error", + upgrade_state = "READY_FOR_UPGRADE", error = "CODE", main_node = "true", timestamp = 02, @@ -198,12 +198,51 @@ describe('LiMe mesh upgrade', function() assert.is.equal('LibreRouterOs 1.5', eupgrade.is_new_version_available()['version']) lime_mesh_upgrade.become_bot_node(upgrade_data) - status = lime_mesh_upgrade.get_node_status() + local status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.main_node, upgrade_data.main_node) assert.is.equal(status.repo_url, upgrade_data.repo_url) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) end) + it('test become botnode and assert status ready_for_upgrade', function() + stub(eupgrade, '_get_current_fw_version', function() + return 'LibreMesh 19.05' + end) + stub(eupgrade, '_check_signature', function() + return true + end) + stub(utils, 'http_client_get', function() + return latest_release_data + end) + stub(eupgrade, '_file_sha256', function() + return 'cec8920f93055cc57cfde1f87968e33ca5215b2df88611684195077402079acb' + end) + + uci = test_utils.setup_test_uci() + uci:set('mesh-upgrade', 'main', "mesh-upgrade") + uci:set('mesh-upgrade', 'main', "upgrade_state", "UPGRADE_SCHEDULED") + uci:save('mesh-upgrade') + utils.log("about to become bot node") + assert.is.equal('LibreRouterOs 1.5', eupgrade.is_new_version_available()['version']) + lime_mesh_upgrade.become_bot_node(upgrade_data) + local status = lime_mesh_upgrade.get_node_status() + assert.is.equal(status.main_node, upgrade_data.main_node) + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) + + utils.log("about to become bot node seccond time") + uci = test_utils.setup_test_uci() + uci:set('mesh-upgrade', 'main', "mesh-upgrade") + uci:set('mesh-upgrade', 'main', "upgrade_state", "CONFIRMED") + uci:save('mesh-upgrade') + + lime_mesh_upgrade.become_bot_node(upgrade_data) + local status = lime_mesh_upgrade.get_node_status() + assert.is.equal(status.main_node, upgrade_data.main_node) + --assert.is.equal(status.repo_url, upgrade_data.repo_url) + assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.READY_FOR_UPGRADE) + + end) + it('test get fw path', function() local fw_path = lime_mesh_upgrade.get_fw_path() @@ -368,7 +407,8 @@ describe('LiMe mesh upgrade', function() status = lime_mesh_upgrade.get_node_status() assert.stub.spy(utils.execute_daemonized).was.called.with( - "sleep 1; shared-state-async sync mesh_wide_upgrade") + "sleep 1; \ + /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") assert.is.equal(lime_mesh_upgrade.su_confirm_timeout, 600) assert.is.equal(status.su_start_time_out, 60) From 7210e05b506c27d70fee33ef581e9bb98542d4d0 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 22 Apr 2024 10:58:09 -0300 Subject: [PATCH 088/102] shared-state: remove cached possibly corrupted files from eupgrade --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 1 + .../share/shared-state/hooks/mesh_wide_upgrade/start_upgrade | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index c0dcecb9b..ebc878350 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -333,6 +333,7 @@ function mesh_upgrade.mesh_upgrade_abort() uci:commit('mesh-upgrade') mesh_upgrade.trigger_sheredstate_publish() -- todo(javi): stop and delete everything + os.execute("rm ".. eupgrade.WORKDIR .." -r >/dev/null 2>&1") -- kill posible safe upgrade command utils.unsafe_shell("kill $(ps| grep 'sh -c (( sleep " .. mesh_upgrade.su_start_time_out .. "; safe-upgrade upgrade'| awk '{print $1}')") diff --git a/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade index 142521b96..502aa6c7c 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -21,12 +21,7 @@ local utils = require "lime.utils" local mesh_upgrade = require "lime-mesh-upgrade" local hostname = utils.hostname() -utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "************************************* "') - local indata = io.stdin:read("*all") -utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "'.. indata .. ' fin"' ) -utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "************************************* "') - --if already involved in an upgrade transaction do nothing if not mesh_upgrade.started() then utils.log("async: starting an upgrade process") From 9b761d821a0443715aa493ebaf059996d20d4df7 Mon Sep 17 00:00:00 2001 From: selankon Date: Mon, 6 May 2024 10:31:11 +0200 Subject: [PATCH 089/102] mesh-upgrade: create link of publish_mesh_upgrade --- .../publishers/shared-state-publish_mesh_wide_upgrade | 1 + 1 file changed, 1 insertion(+) create mode 120000 packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade new file mode 120000 index 000000000..ee2664e94 --- /dev/null +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade @@ -0,0 +1 @@ +../../../usr/bin/shared-state-publish_mesh_wide_upgrade \ No newline at end of file From 2828bbd9cee9875c0600ccf6083d408ae74eadec Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Tue, 7 May 2024 13:59:32 -0300 Subject: [PATCH 090/102] shared-state-async: avoid removing eupgrade staff --- .../lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index ebc878350..e5df8bd40 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -333,7 +333,7 @@ function mesh_upgrade.mesh_upgrade_abort() uci:commit('mesh-upgrade') mesh_upgrade.trigger_sheredstate_publish() -- todo(javi): stop and delete everything - os.execute("rm ".. eupgrade.WORKDIR .." -r >/dev/null 2>&1") + --os.execute("rm ".. eupgrade.WORKDIR .." -r >/dev/null 2>&1") -- kill posible safe upgrade command utils.unsafe_shell("kill $(ps| grep 'sh -c (( sleep " .. mesh_upgrade.su_start_time_out .. "; safe-upgrade upgrade'| awk '{print $1}')") From 1f5cc43ab762eec1991da735be0caa470352d128 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Fri, 10 May 2024 12:54:15 -0300 Subject: [PATCH 091/102] shared-state-asymc: add simple general check --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 88 ++++++++++++++++--- .../tests/test_lime-mesh-upgrade.lua | 4 +- .../hooks/mesh_wide_upgrade/start_upgrade | 7 +- 3 files changed, 84 insertions(+), 15 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index e5df8bd40..f7f4042ca 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -290,13 +290,7 @@ end -- Validate if the upgrade has already started function mesh_upgrade.started() status = mesh_upgrade.state() - if status == mesh_upgrade.upgrade_states.DEFAULT or -- if an error has ocurred then there is no transaction - status == mesh_upgrade.upgrade_states.ERROR or - status == mesh_upgrade.upgrade_states.ABORTED or - status == mesh_upgrade.upgrade_states.CONFIRMED then - return false - end - return true + return mesh_upgrade.is_active(status) -- todo(javi): what happens if a mesh_upgrade has started more than an hour ago ? should this node abort it ? end @@ -324,14 +318,16 @@ function mesh_upgrade.main_node_state() return main_node_state end -function mesh_upgrade.mesh_upgrade_abort() +function mesh_upgrade.mesh_upgrade_abort(silent_abortion) if mesh_upgrade.change_state(mesh_upgrade.upgrade_states.ABORTED) then -- mesh_upgrade.change_main_node_state(mesh_upgrade.main_node_states.NO) local uci = config.get_uci_cursor() uci:set('mesh-upgrade', 'main', 'retry_count', 0) uci:save('mesh-upgrade') uci:commit('mesh-upgrade') - mesh_upgrade.trigger_sheredstate_publish() + if silent_abortion == nil or silent_abortion == false then + mesh_upgrade.trigger_sheredstate_publish() + end -- todo(javi): stop and delete everything --os.execute("rm ".. eupgrade.WORKDIR .." -r >/dev/null 2>&1") -- kill posible safe upgrade command @@ -410,7 +406,10 @@ end -- It will only fetch new information if main node has aborted or main node is -- ready for upgraade function mesh_upgrade.become_bot_node(main_node_upgrade_data) - if main_node_upgrade_data.upgrade_state == mesh_upgrade.upgrade_states.ABORTED then + local actual_state = mesh_upgrade.get_node_status() + -- only abort if my main node has aborted + if main_node_upgrade_data.upgrade_state == mesh_upgrade.upgrade_states.ABORTED and + main_node_upgrade_data.timestamp == actual_state.timestamp then utils.log("main node has aborted") mesh_upgrade.mesh_upgrade_abort() return @@ -420,7 +419,7 @@ function mesh_upgrade.become_bot_node(main_node_upgrade_data) return else utils.log("node has not started") - local actual_state = mesh_upgrade.get_node_status() + if actual_state.timestamp == main_node_upgrade_data.timestamp and actual_state.repo_url == main_node_upgrade_data.repo_url then main_node_upgrade_data.retry_count = actual_state.retry_count + 1 @@ -437,7 +436,6 @@ function mesh_upgrade.become_bot_node(main_node_upgrade_data) end else utils.log("max retry_count has been reached") - end end end @@ -613,4 +611,70 @@ function mesh_upgrade.confirm() } end +-- An active node is involved in a transaction +function mesh_upgrade.is_active(status) + if status == mesh_upgrade.upgrade_states.DEFAULT or -- if an error has ocurred then there is no transaction + status == mesh_upgrade.upgrade_states.ERROR or + status == mesh_upgrade.upgrade_states.ABORTED or + status == mesh_upgrade.upgrade_states.CONFIRMED then + return false + end + return true +end + +function mesh_upgrade.verify_network_consistency (network_state) + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "verifying" ') + local actual_status = mesh_upgrade.get_node_status() + + local main_node = "" + for node, s_s_data in pairs(network_state) do + --if any node has started an upgrade process and start one too? + --only fetch the info from the master node publication? + if s_s_data.main_node == mesh_upgrade.main_node_states.MAIN_NODE then + if mesh_upgrade.is_active(s_s_data.upgrade_state) then + if main_node == "" then + main_node = node + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "there is one main node '..main_node..' , ok"') + else + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "there are two active main nodes '.. node ..' and '..main_node..' , aborting"') + mesh_upgrade.mesh_upgrade_abort() + return + end + else + --there is an inactive main node + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "there is an inactive main node '.. node ..' "') + if mesh_upgrade.started() and network_state[node].timestamp == actual_status.timestamp then + -- i should abort too + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "i should abort we share timestamps"') + mesh_upgrade.mesh_upgrade_abort() + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "i should not abort dont share timestamps"') + end + + end + end + end + --there is only one main node + if main_node ~= "" then + if not mesh_upgrade.started() and main_node ~= utils.hostname() then + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "' ..utils.hostname()' become' ..main_node..' _bot_node "') + mesh_upgrade.become_bot_node(network_state[main_node]) + else + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "already started a transaction "') + if network_state[main_node].timestamp == actual_status.timestamp then + --"ok" + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "main node and bot node timestamp are equal"') + else + --I am in a transaction and main node is in an other + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "main node and bot node timestamp are different"') + mesh_upgrade.mesh_upgrade_abort(true) + --this will lead to a doble write to shared state. + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "main node and bot node timestamp are different"') + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" " become_bot_node "') + mesh_upgrade.become_bot_node(network_state[main_node]) + end + end + end +end + + return mesh_upgrade diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 079e66ed8..de42b21cc 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -227,7 +227,7 @@ describe('LiMe mesh upgrade', function() lime_mesh_upgrade.become_bot_node(upgrade_data) local status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.main_node, upgrade_data.main_node) - assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) + --assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ERROR) utils.log("about to become bot node seccond time") uci = test_utils.setup_test_uci() @@ -412,7 +412,7 @@ describe('LiMe mesh upgrade', function() assert.is.equal(lime_mesh_upgrade.su_confirm_timeout, 600) assert.is.equal(status.su_start_time_out, 60) - assert(status.safeupgrade_start_remining<60 and status.safeupgrade_start_remining>10) + assert(status.safeupgrade_start_remining<61 and status.safeupgrade_start_remining>1) assert.is.equal(status.confirm_remining,-1) assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) diff --git a/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade index 502aa6c7c..51a2408d9 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -22,7 +22,11 @@ local mesh_upgrade = require "lime-mesh-upgrade" local hostname = utils.hostname() local indata = io.stdin:read("*all") +utils.printJson(JSON.parse(indata)) +mesh_upgrade.verify_network_consistency(JSON.parse(indata)) + --if already involved in an upgrade transaction do nothing +--[[ if not mesh_upgrade.started() then utils.log("async: starting an upgrade process") for node, s_s_data in pairs(JSON.parse(indata)) do @@ -55,4 +59,5 @@ else end utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "already started an upgrade process"') utils.log("already started an upgrade process") -end \ No newline at end of file +end +]]-- From ba6e26ca2dc1339e9627def6e8bb5ae343708146 Mon Sep 17 00:00:00 2001 From: "javier.jorge" Date: Thu, 16 May 2024 22:09:42 +0300 Subject: [PATCH 092/102] fixes verify_network_consistency apend bug --- .../lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index f7f4042ca..68fed6456 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -656,7 +656,7 @@ function mesh_upgrade.verify_network_consistency (network_state) --there is only one main node if main_node ~= "" then if not mesh_upgrade.started() and main_node ~= utils.hostname() then - utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "' ..utils.hostname()' become' ..main_node..' _bot_node "') + utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "' ..utils.hostname()..' become' ..main_node..' _bot_node "') mesh_upgrade.become_bot_node(network_state[main_node]) else utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "already started a transaction "') From 7d366fc484512d765c8737a920d508fff5fbb516 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 9 Sep 2024 18:19:59 -0300 Subject: [PATCH 093/102] f_mesh_up: move publisher to new location --- .../publishers/shared-state-publish_mesh_wide_upgrade | 1 - .../publishers}/shared-state-publish_mesh_wide_upgrade | 0 2 files changed, 1 deletion(-) delete mode 120000 packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade rename packages/shared-state-mesh_wide_upgrade/files/usr/{bin => share/shared-state/publishers}/shared-state-publish_mesh_wide_upgrade (100%) diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade b/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade deleted file mode 120000 index ee2664e94..000000000 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade +++ /dev/null @@ -1 +0,0 @@ -../../../usr/bin/shared-state-publish_mesh_wide_upgrade \ No newline at end of file diff --git a/packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade b/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/publishers/shared-state-publish_mesh_wide_upgrade similarity index 100% rename from packages/shared-state-mesh_wide_upgrade/files/usr/bin/shared-state-publish_mesh_wide_upgrade rename to packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/publishers/shared-state-publish_mesh_wide_upgrade From a03cc220fea262e755d4ad421a2a202d7909faab Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 9 Sep 2024 18:23:06 -0300 Subject: [PATCH 094/102] f_mesh_up: rename uci default file --- ...e_cron => shared-state_mesh_wide_upgrade_register} | 11 ----------- 1 file changed, 11 deletions(-) rename packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/{shared-state_mesh_wide_upgrade_cron => shared-state_mesh_wide_upgrade_register} (60%) diff --git a/packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/shared-state_mesh_wide_upgrade_cron b/packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/shared-state_mesh_wide_upgrade_register similarity index 60% rename from packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/shared-state_mesh_wide_upgrade_cron rename to packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/shared-state_mesh_wide_upgrade_register index 47b647012..a37f54e2e 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/shared-state_mesh_wide_upgrade_cron +++ b/packages/shared-state-mesh_wide_upgrade/files/etc/uci-defaults/shared-state_mesh_wide_upgrade_register @@ -1,18 +1,7 @@ #!/bin/sh - -unique_append() -{ - grep -qF "$1" "$2" || echo "$1" >> "$2" -} - uci set shared-state.mesh_wide_upgrade=dataType uci set shared-state.mesh_wide_upgrade.name='mesh_wide_upgrade' uci set shared-state.mesh_wide_upgrade.scope='community' uci set shared-state.mesh_wide_upgrade.ttl='2400' uci set shared-state.mesh_wide_upgrade.update_interval='30' uci commit shared-state - -unique_append \ - '*/30 * * * * ((sleep $(($RANDOM % 120)); shared-state-publish_mesh_wide_upgrade &> /dev/null)&)' \ - /etc/crontabs/root - From 32b40a1bc972d7760d8ed9af24e94580bc51bf8d Mon Sep 17 00:00:00 2001 From: javierbrk Date: Fri, 13 Sep 2024 11:20:07 -0300 Subject: [PATCH 095/102] f_mu: fixes #1125 by checking that safe upgrade is ready --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 25 +++++++++++++++---- .../tests/test_lime-mesh-upgrade.lua | 6 +++++ .../tests/test_rpcd_lime_mesh_upgrade.lua | 4 +++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 68fed6456..5aac67bab 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -39,8 +39,8 @@ local mesh_upgrade = { CONFIRMATION_TIME_OUT = "confirmation_timeout", -- ABORTED = "aborted", FW_FILE_NOT_FOUND = "firmware_file_not_found", - INVALID_FW_FILE = "invalid_firmware_file" - + INVALID_FW_FILE = "invalid_firmware_file", + SAFE_UPGRADE_NOT_BOOTSTRAPED= "safe upgrade not working" }, fw_path = "", su_confirm_timeout = 600, @@ -179,6 +179,18 @@ function mesh_upgrade.check_eupgrade_download_failed() return download_status end + +function mesh_upgrade.check_safeupgrade_is_working() + local result = os.execute("safe-upgrade bootstrap") + local exit_code = result and (result / 256) or result + if exit_code == 121 then + -- this means that safeupgrade has been bootrsaped and is ready to work + return true + end + mesh_upgrade.report_error(mesh_upgrade.errors.SAFE_UPGRADE_NOT_BOOTSTRAPED) + return false +end + function mesh_upgrade.start_firmware_upgrade_transaction() -- todo(kon): do all needed checks also with the main node state etc.. -- Expose eupgrade folder to uhttp (this is the best place to do it since @@ -478,14 +490,16 @@ end -- ! Read status from UCI function mesh_upgrade.get_node_status() + mesh_upgrade.check_safeupgrade_is_working() local uci = config.get_uci_cursor() local upgrade_data = {} upgrade_data.candidate_fw = uci:get('mesh-upgrade', 'main', 'candidate_fw') upgrade_data.repo_url = uci:get('mesh-upgrade', 'main', 'repo_url') upgrade_data.eupgradestate = mesh_upgrade.check_eupgrade_download_failed() upgrade_data.upgrade_state = mesh_upgrade.state() + local safe_upgrade_confirm_remaining = tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) if (upgrade_data.upgrade_state == mesh_upgrade.upgrade_states.UPGRADE_SCHEDULED) then - if (tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) > 1) then + if (safe_upgrade_confirm_remaining and safe_upgrade_confirm_remaining > 1) then mesh_upgrade.change_state(mesh_upgrade.upgrade_states.CONFIRMATION_PENDING) elseif utils.file_exists(mesh_upgrade.get_fw_path()) == false then mesh_upgrade.report_error(mesh_upgrade.errors.FW_FILE_NOT_FOUND) @@ -510,7 +524,7 @@ function mesh_upgrade.get_node_status() (utils.uptime_s() - mesh_upgrade.safeupgrade_start_mark) > 0 and mesh_upgrade.su_start_time_out - (utils.uptime_s() - mesh_upgrade.safeupgrade_start_mark) or -1) - upgrade_data.confirm_remining = tonumber(utils.unsafe_shell("safe-upgrade confirm-remaining")) + upgrade_data.confirm_remining = safe_upgrade_confirm_remaining return upgrade_data end @@ -518,7 +532,8 @@ function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) mesh_upgrade.su_start_time_out = su_start_delay or mesh_upgrade.su_start_time_out mesh_upgrade.su_confirm_timeout = su_confirm_timeout or mesh_upgrade.su_confirm_timeout - if mesh_upgrade.state() == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE then + if mesh_upgrade.state() == mesh_upgrade.upgrade_states.READY_FOR_UPGRADE and + mesh_upgrade.check_safeupgrade_is_working() then if utils.file_exists(mesh_upgrade.get_fw_path()) then -- veryfy the image before starting diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index de42b21cc..99ee4409f 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -57,6 +57,8 @@ stub(utils, 'unsafe_shell', function(command) end) + + local utils = require "lime.utils" local lime_mesh_upgrade = {} local test_utils = require "tests.utils" @@ -470,6 +472,10 @@ describe('LiMe mesh upgrade', function() end) lime_mesh_upgrade = require 'lime-mesh-upgrade' + stub(lime_mesh_upgrade, 'check_safeupgrade_is_working', function(command) + return true + end) + uci = test_utils.setup_test_uci() uci:set('mesh-upgrade', 'main', "mesh-upgrade") uci:set('mesh-upgrade', 'main', "upgrade_state", "DEFAULT") diff --git a/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua b/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua index 97c8f7a10..45ba3abdc 100644 --- a/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_rpcd_lime_mesh_upgrade.lua @@ -34,6 +34,10 @@ describe('general rpc testing', function() return boardname end) lime_mesh_upgrade = require 'lime-mesh-upgrade' + stub(lime_mesh_upgrade, 'check_safeupgrade_is_working', function(command) + return true + end) + snapshot = assert:snapshot() uci:set('mesh-upgrade', 'main', "mesh-upgrade") From 937c645e89174ef00e64f838ddb6010475165de6 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Fri, 13 Sep 2024 11:25:18 -0300 Subject: [PATCH 096/102] f_mu: fixes publisher relocation --- .../lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 5aac67bab..6e99289c7 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -355,11 +355,11 @@ end -- This line will genereate recursive dependencies like in pirania pakcage function mesh_upgrade.trigger_sheredstate_publish() utils.execute_daemonized("sleep 1; \ - /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") + /usr/share/shared-state/publishers/shared-state-publish_mesh_wide_upgrade") -- minimum renewal time is 30s if not able to renew info just wait, if firts fails the seccond success, -- if the first succesds the seccond will fail. Sadly merge will output 0 so both times will make sync. utils.execute_daemonized("sleep 30; \ - /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") + /usr/share/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") end function mesh_upgrade.change_main_node_state(newstate) From 26fc404e96ef153c14ce6de02156fb80f150440c Mon Sep 17 00:00:00 2001 From: javierbrk Date: Fri, 13 Sep 2024 11:29:38 -0300 Subject: [PATCH 097/102] f_mu: fix tests after publisher relocation --- packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua index 99ee4409f..612e5260c 100644 --- a/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/tests/test_lime-mesh-upgrade.lua @@ -141,7 +141,7 @@ describe('LiMe mesh upgrade', function() status = lime_mesh_upgrade.get_node_status() assert.is.equal(status.upgrade_state, lime_mesh_upgrade.upgrade_states.ABORTED) assert.stub.spy(utils.execute_daemonized).was.called.with("sleep 30; \ - /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") + /usr/share/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") end) it('test set upgrade info and fail NO_LATEST_AVAILABLE', function() @@ -409,8 +409,8 @@ describe('LiMe mesh upgrade', function() status = lime_mesh_upgrade.get_node_status() assert.stub.spy(utils.execute_daemonized).was.called.with( - "sleep 1; \ - /etc/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") + "sleep 30; \ + /usr/share/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") assert.is.equal(lime_mesh_upgrade.su_confirm_timeout, 600) assert.is.equal(status.su_start_time_out, 60) From 2f9794a21098c075d7f3c1c96fcf3a91faa7b8b7 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Fri, 13 Sep 2024 11:40:51 -0300 Subject: [PATCH 098/102] f_mu: fix ubus print error in get status --- .../lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 6e99289c7..91b6788b7 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -181,7 +181,7 @@ end function mesh_upgrade.check_safeupgrade_is_working() - local result = os.execute("safe-upgrade bootstrap") + local result = os.execute("safe-upgrade bootstrap >/dev/null 2>&1") local exit_code = result and (result / 256) or result if exit_code == 121 then -- this means that safeupgrade has been bootrsaped and is ready to work From c338195ab96560ef3a926706a6be3a686449cbc2 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 23 Sep 2024 09:37:29 -0300 Subject: [PATCH 099/102] f_mu: removes wget dependency --- packages/lime-mesh-upgrade/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lime-mesh-upgrade/Makefile b/packages/lime-mesh-upgrade/Makefile index 3654094d5..2d63794df 100644 --- a/packages/lime-mesh-upgrade/Makefile +++ b/packages/lime-mesh-upgrade/Makefile @@ -11,7 +11,7 @@ define Package/$(PKG_NAME) CATEGORY:=LibreMesh MAINTAINER:=selankon TITLE:=LibreMesh mesh wide firmware upgrade - DEPENDS:= +lua +libubus-lua +wget +safe-upgrade \ + DEPENDS:= +lua +libubus-lua +safe-upgrade \ +shared-state-mesh_wide_upgrade PKGARCH:=all From 7fd8d38ec97c0af171b74b541e77f1de56794ba0 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 25 Nov 2024 17:17:41 -0300 Subject: [PATCH 100/102] f_mu: comments cleanup --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 21 ++--------- .../hooks/mesh_wide_upgrade/start_upgrade | 37 ------------------- 2 files changed, 3 insertions(+), 55 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 91b6788b7..16aa9c9ce 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -101,7 +101,6 @@ mesh_upgrade.set_workdir("/tmp/mesh_upgrade") function mesh_upgrade.create_local_latest_json(latest_data) for _, im in pairs(latest_data['images']) do - -- im['download-urls'] = string.gsub(im['download-urls'], upgrade_url, "test") im['download-urls'] = {mesh_upgrade.get_repo_base_url() .. im['name']} end utils.write_file(mesh_upgrade.LATEST_JSON_PATH, json.stringify(latest_data)) @@ -133,15 +132,13 @@ function mesh_upgrade.start_main_node_repository(latest_data) mesh_upgrade.change_state(mesh_upgrade.upgrade_states.DOWNLOADING) end ---- Function that check if tihs node have all things needed to became a main node +--- Function that check if this node is able to became a main node --- Then, call update shared state with the proper info -- @url optional new url to get the firmware for local repo function mesh_upgrade.become_main_node(url) if url then eupgrade.set_custom_api_url(url) end - -- todo(kon): check if main node is already set or we are on mesh_upgrade status - -- todo(kon): dont start again if status is started and eupgrade is downloaded for example -- Check if there are a new version available (cached only) -- 1. Check if new version is available and download it demonized using eupgrade local latest = eupgrade.is_new_version_available(false) @@ -167,7 +164,7 @@ function mesh_upgrade.become_main_node(url) } end --- Update the state witth an error if eupgrade download failed +-- Update the state with an error if eupgrade download failed -- It returns the download status function mesh_upgrade.check_eupgrade_download_failed() local download_status = eupgrade.get_download_status() @@ -192,9 +189,6 @@ function mesh_upgrade.check_safeupgrade_is_working() end function mesh_upgrade.start_firmware_upgrade_transaction() - -- todo(kon): do all needed checks also with the main node state etc.. - -- Expose eupgrade folder to uhttp (this is the best place to do it since - -- all the files are present) if mesh_upgrade.main_node_state() ~= mesh_upgrade.main_node_states.STARTING then return { code = "BAD_NODE_STATE", @@ -340,8 +334,6 @@ function mesh_upgrade.mesh_upgrade_abort(silent_abortion) if silent_abortion == nil or silent_abortion == false then mesh_upgrade.trigger_sheredstate_publish() end - -- todo(javi): stop and delete everything - --os.execute("rm ".. eupgrade.WORKDIR .." -r >/dev/null 2>&1") -- kill posible safe upgrade command utils.unsafe_shell("kill $(ps| grep 'sh -c (( sleep " .. mesh_upgrade.su_start_time_out .. "; safe-upgrade upgrade'| awk '{print $1}')") @@ -364,11 +356,6 @@ end function mesh_upgrade.change_main_node_state(newstate) local main_node_state = mesh_upgrade.main_node_state() - -- if newstate == main_node_state then return false end - - -- if newstate == mesh_upgrade.main_node_states.STARTING and - -- main_node_state ~= mesh_upgrade.main_node_states.NO then - -- return false if newstate == mesh_upgrade.main_node_states.MAIN_NODE and main_node_state ~= mesh_upgrade.main_node_states.STARTING then return false end @@ -405,8 +392,6 @@ function mesh_upgrade.change_state(newstate) mesh_upgrade.upgrade_states.CONFIRMATION_PENDING then return false end - -- todo(javi): verify other states and return false if it is not possible - -- lets allow all types of state changes. local uci = config.get_uci_cursor() uci:set('mesh-upgrade', 'main', 'upgrade_state', newstate) uci:save('mesh-upgrade') @@ -414,7 +399,7 @@ function mesh_upgrade.change_state(newstate) return true end --- this function will retry max_retry_conunt tymes in case of error +-- this function will retry max_retry_conunt times in case of error -- It will only fetch new information if main node has aborted or main node is -- ready for upgraade function mesh_upgrade.become_bot_node(main_node_upgrade_data) diff --git a/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade b/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade index 51a2408d9..264ca007c 100755 --- a/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade +++ b/packages/shared-state-mesh_wide_upgrade/files/usr/share/shared-state/hooks/mesh_wide_upgrade/start_upgrade @@ -24,40 +24,3 @@ local hostname = utils.hostname() local indata = io.stdin:read("*all") utils.printJson(JSON.parse(indata)) mesh_upgrade.verify_network_consistency(JSON.parse(indata)) - ---if already involved in an upgrade transaction do nothing ---[[ -if not mesh_upgrade.started() then - utils.log("async: starting an upgrade process") - for node, s_s_data in pairs(JSON.parse(indata)) do - --if any node has started an upgrade process and start one too? - --only fetch the info from the master node publication? - if node ~= hostname and s_s_data.main_node == mesh_upgrade.main_node_states.MAIN_NODE then - utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "mesh upgrade detected upgrade from ' .. - s_s_data.repo_url .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data)..'"') - mesh_upgrade.become_bot_node(s_s_data) - else - utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "status "' .. - JSON.stringify(s_s_data) .. " from node " .. node) - end - end -else - --if started check that a main node has not aborted - for node, s_s_data in pairs(JSON.parse(indata)) do - utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "mesh upgrade detected upgrade from "' .. - s_s_data.main_node .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) - utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "mesh upgrade detected upgrade from "' .. - s_s_data.main_node .. " and masternode node " .. node .. " with this data " .. JSON.stringify(s_s_data.data)) - - if node ~= hostname and - s_s_data.main_node == mesh_upgrade.main_node_states.MAIN_NODE and - s_s_data.upgrade_state == mesh_upgrade.upgrade_states.ABORTED - then - mesh_upgrade.mesh_upgrade_abort() - utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "aborting, main has aborted"') - end - end - utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "already started an upgrade process"') - utils.log("already started an upgrade process") -end -]]-- From 160a2a4e37fa65d9e75f2f4606a604c622c32dba Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 25 Nov 2024 17:22:19 -0300 Subject: [PATCH 101/102] f_mu: fix spelling errors --- .../files/usr/lib/lua/lime-mesh-upgrade.lua | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua index 16aa9c9ce..9d71540de 100644 --- a/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua +++ b/packages/lime-mesh-upgrade/files/usr/lib/lua/lime-mesh-upgrade.lua @@ -8,14 +8,14 @@ local fs = require("nixio.fs") local json = require 'luci.jsonc' local mesh_upgrade = { - -- posible transaction states are derived from upgrade states + -- possible transaction states are derived from upgrade states transaction_states = { NO_TRANSACTION = "NO_TRANSACTION", STARTED = "STARTED", -- there is a transaction in progress ABORTED = "ABORTED", FINISHED = "FINISHED" }, - -- posible upgrade states enumeration + -- possible upgrade states enumeration upgrade_states = { DEFAULT = "DEFAULT", -- When no upgrade has started, after reboot DOWNLOADING = "DOWNLOADING", @@ -334,7 +334,7 @@ function mesh_upgrade.mesh_upgrade_abort(silent_abortion) if silent_abortion == nil or silent_abortion == false then mesh_upgrade.trigger_sheredstate_publish() end - -- kill posible safe upgrade command + -- kill possible safe upgrade command utils.unsafe_shell("kill $(ps| grep 'sh -c (( sleep " .. mesh_upgrade.su_start_time_out .. "; safe-upgrade upgrade'| awk '{print $1}')") end @@ -344,12 +344,12 @@ function mesh_upgrade.mesh_upgrade_abort(silent_abortion) } end --- This line will genereate recursive dependencies like in pirania pakcage +-- This line will generate recursive dependencies like in pirania package function mesh_upgrade.trigger_sheredstate_publish() utils.execute_daemonized("sleep 1; \ /usr/share/shared-state/publishers/shared-state-publish_mesh_wide_upgrade") - -- minimum renewal time is 30s if not able to renew info just wait, if firts fails the seccond success, - -- if the first succesds the seccond will fail. Sadly merge will output 0 so both times will make sync. + -- minimum renewal time is 30s if not able to renew info just wait, if flirts fails the second success, + -- if the first succeeds the second will fail. Sadly merge will output 0 so both times will make sync. utils.execute_daemonized("sleep 30; \ /usr/share/shared-state/publishers/shared-state-publish_mesh_wide_upgrade && shared-state-async sync mesh_wide_upgrade") end @@ -534,7 +534,7 @@ function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) -- no confirmation is received -- perform a full config backup including mesh_upgrade config file needed for the next image - -- surprisingly this does not presrve nodename + -- surprisingly this does not preserve nodename -- os.execute("sysupgrade -b ".. mesh_upgrade.WORKDIR.."/mesh_upgrade_cfg.tgz") @@ -580,8 +580,8 @@ function mesh_upgrade.start_safe_upgrade(su_start_delay, su_confirm_timeout) end end --- This command requires that the configuration be preserverd across upgrade, --- maybe this change achieves this objetive +-- This command requires that the configuration be preserved across upgrade, +-- maybe this change achieves this objective -- diff --git a/packages/lime-system/files/etc/config/lime-defaults b/packages/lime-system/files/etc/config/lime-defaults -- index 5f5c4a31..8d55d949 100644 @@ -613,7 +613,7 @@ end -- An active node is involved in a transaction function mesh_upgrade.is_active(status) - if status == mesh_upgrade.upgrade_states.DEFAULT or -- if an error has ocurred then there is no transaction + if status == mesh_upgrade.upgrade_states.DEFAULT or -- if an error has occurred then there is no transaction status == mesh_upgrade.upgrade_states.ERROR or status == mesh_upgrade.upgrade_states.ABORTED or status == mesh_upgrade.upgrade_states.CONFIRMED then @@ -667,7 +667,7 @@ function mesh_upgrade.verify_network_consistency (network_state) --I am in a transaction and main node is in an other utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "main node and bot node timestamp are different"') mesh_upgrade.mesh_upgrade_abort(true) - --this will lead to a doble write to shared state. + --this will lead to a double write to shared state. utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" "main node and bot node timestamp are different"') utils.unsafe_shell('logger -p daemon.info -t "async: mesh upgrade" " become_bot_node "') mesh_upgrade.become_bot_node(network_state[main_node]) From f54b79a54b7c8e2a5a2c3659b7d71f252ddcbe22 Mon Sep 17 00:00:00 2001 From: javierbrk Date: Mon, 25 Nov 2024 17:28:15 -0300 Subject: [PATCH 102/102] f_mu: fix makefile description --- packages/shared-state-mesh_wide_upgrade/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/shared-state-mesh_wide_upgrade/Makefile b/packages/shared-state-mesh_wide_upgrade/Makefile index 5caf7061b..ec98704b2 100644 --- a/packages/shared-state-mesh_wide_upgrade/Makefile +++ b/packages/shared-state-mesh_wide_upgrade/Makefile @@ -9,7 +9,7 @@ include ../../libremesh.mk define Package/$(PKG_NAME) CATEGORY:=LibreMesh - TITLE:=Babel links module for shared-state + TITLE:=Shared-state mesh upgrade information module MAINTAINER:=Asociación Civil Altermundi DEPENDS:=+lua +luci-lib-jsonc +ubus-lime-utils \ +libubus-lua +random-numgen shared-state-async @@ -17,7 +17,7 @@ define Package/$(PKG_NAME) endef define Package/$(PKG_NAME)/description - Syncronize node information to achieve mesh wide firmware upgrades + Synchronize node information to achieve mesh wide firmware upgrades endef $(eval $(call BuildPackage,$(PKG_NAME)))