From 13c34cfb6fe455dfbb18139a1a7158d65c76113f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= <lazzer@gmail.com>
Date: Fri, 29 Nov 2024 13:36:26 +0100
Subject: [PATCH] Update upgrade test

---
 test/case/ietf_system/bundles/package         |  1 -
 test/case/ietf_system/ietf_system.yaml        |  3 +
 test/case/ietf_system/upgrade/Readme.adoc     |  4 +
 .../{ => upgrade}/bundles/not-a-bundle.pkg    |  0
 test/case/ietf_system/upgrade/test.py         | 84 +++++++++++++++++--
 test/test.mk                                  |  7 +-
 6 files changed, 88 insertions(+), 11 deletions(-)
 delete mode 120000 test/case/ietf_system/bundles/package
 rename test/case/ietf_system/{ => upgrade}/bundles/not-a-bundle.pkg (100%)

diff --git a/test/case/ietf_system/bundles/package b/test/case/ietf_system/bundles/package
deleted file mode 120000
index ce024d927..000000000
--- a/test/case/ietf_system/bundles/package
+++ /dev/null
@@ -1 +0,0 @@
-/home/wkz/src/github.com/kernelkit/infix/x-netconf/images/infix-x86_64.pkg
\ No newline at end of file
diff --git a/test/case/ietf_system/ietf_system.yaml b/test/case/ietf_system/ietf_system.yaml
index d5c31b36e..b317fc078 100644
--- a/test/case/ietf_system/ietf_system.yaml
+++ b/test/case/ietf_system/ietf_system.yaml
@@ -16,3 +16,6 @@
 
 - name: ssh_key_authentication
   case: ssh_key_authentication/test.py
+
+- name: upgrade
+  case: upgrade/test.py
diff --git a/test/case/ietf_system/upgrade/Readme.adoc b/test/case/ietf_system/upgrade/Readme.adoc
index 032efc36e..b295c8197 100644
--- a/test/case/ietf_system/upgrade/Readme.adoc
+++ b/test/case/ietf_system/upgrade/Readme.adoc
@@ -18,6 +18,10 @@ endif::topdoc[]
 . Set up topology and attach to target DUT
 . Start installation of selected package
 . Wait for upgrade to finish
+. Verify boot order has changed and reboot
+. Verify that the partition is the booted
+. Restore boot order to original configured
+. Verify the boot order is the orignal configured
 
 
 <<<
diff --git a/test/case/ietf_system/bundles/not-a-bundle.pkg b/test/case/ietf_system/upgrade/bundles/not-a-bundle.pkg
similarity index 100%
rename from test/case/ietf_system/bundles/not-a-bundle.pkg
rename to test/case/ietf_system/upgrade/bundles/not-a-bundle.pkg
diff --git a/test/case/ietf_system/upgrade/test.py b/test/case/ietf_system/upgrade/test.py
index 24d457375..35da96306 100755
--- a/test/case/ietf_system/upgrade/test.py
+++ b/test/case/ietf_system/upgrade/test.py
@@ -4,11 +4,14 @@
 
 Verify it is possible to upgrade.
 """
+# NOTE: THIS TEST IS HARDCODED TO NETCONF
+# There is a bug somewhere in the restconf-code (infamy or rousette)
 import os
 import time
 import netifaces
 import infamy
 import infamy.file_server as srv
+from infamy.util import wait_boot, until
 
 SRVPORT = 8008
 
@@ -17,11 +20,36 @@
     "bundles"
 )
 
+bootloader=None
 PKGPATH = os.path.join(
     BUNDLEDIR,
     "package"
 )
 
+class Uboot:
+    def __init__(self, ssh):
+        self.ssh=ssh
+
+    def get_boot_order(self):
+        order=self.ssh.runsh("sudo fw_printenv BOOT_ORDER").stdout.split("=")
+        return order[1]
+
+    def set_boot_order(self, order):
+        return self.ssh.run(f"sudo fw_setenv BOOT_ORDER '{order}'".split()).returncode
+
+class Grub:
+    def __init__(self, ssh):
+        self.ssh = ssh
+
+    def get_boot_order(self):
+        lines=self.ssh.runsh("grub-editenv /mnt/aux/grub/grubenv list").stdout.split("\n")
+        for line in lines:
+            if "ORDER" in line:
+                return line.split("=")[1]
+
+    def set_boot_order(self, order):
+        return self.ssh.run(f"sudo grub-editenv /mnt/aux/grub/grubenv set ORDER='{order}'".split()).returncode
+
 with infamy.Test() as test:
     with test.step("Set up topology and attach to target DUT"):
         env = infamy.Env()
@@ -33,9 +61,20 @@
             os.unlink(PKGPATH)
         except FileNotFoundError:
             pass
+        #os.unlink(PKGPATH)
         os.symlink(os.path.abspath(env.args.package), PKGPATH)
 
-        target = env.attach("target", "mgmt")
+        target = env.attach("target", "mgmt", "netconf")
+        target_ssh = env.attach("target", "mgmt", "ssh")
+        if target_ssh.run("test -e /sys/firmware/devicetree/base/chosen/u-boot,version".split()).returncode == 0:
+            bootloader=Uboot(target_ssh)
+        elif target_ssh.run("test -e /mnt/aux/grub/grubenv".split()).returncode == 0:
+            bootloader=Grub(target_ssh)
+        else:
+            print("No supported bootloader found")
+            test.skip()
+
+        old_bootorder=bootloader.get_boot_order()
 
         _, hport = env.ltop.xlate("host", "mgmt")
         _, tport = env.ltop.xlate("target", "mgmt")
@@ -43,7 +82,6 @@
         hip = hip.replace(f"%{hport}", f"%{tport}")
 
     with srv.FileServer(("::", SRVPORT), BUNDLEDIR):
-
         with test.step("Start installation of selected package"):
             print(f"Installing {os.path.basename(env.args.package)}")
             target.call_dict("infix-system", {
@@ -53,7 +91,7 @@
             })
 
         with test.step("Wait for upgrade to finish"):
-            for _ in range(600):
+            for left in range(600):
                 oper = target.get_dict("/system-state/software")
                 installer = oper["system-state"]["software"]["installer"]
                 if installer["operation"] == "idle":
@@ -61,9 +99,41 @@
                         print("Install failed:", installer["last-error"])
                         test.fail()
 
-                    test.succeed()
-
+                    break
+                time.sleep(1)
+                if left >= 600:
+                    print("Timeout, last state:", oper)
+                    test.fail()
                 time.sleep(1)
 
-            print("Timeout, last state:", oper)
-            test.fail()
+            with test.step("Verify boot order has changed and reboot"):
+                assert(old_bootorder != bootloader.get_boot_order())
+                target.reboot()
+
+                if not wait_boot(target, env):
+                    test.fail()
+                target = env.attach("target", "mgmt", "netconf")
+
+
+        with test.step("Verify that the partition is the booted"):
+            should_boot=bootloader.get_boot_order().split()[0]
+            oper = target.get_dict("/system-state/software")
+            booted = oper["system-state"]["software"]["booted"]
+            print(f"Should boot: {should_boot}, booted: {booted}")
+            assert(booted == should_boot)
+
+        with test.step("Restore boot order to original configured"):
+            print(f"Restore boot order to {old_bootorder}")
+            if bootloader.set_boot_order(old_bootorder) != 0:
+                test.fail()
+            target = env.attach("target", "mgmt", "netconf")
+            target.reboot()
+            if not wait_boot(target, env):
+                test.fail()
+            target = env.attach("target", "mgmt", "netconf")
+
+        with test.step("Verify the boot order is the orignal configured"):
+            # Wait for sshd to start.
+            until(lambda: old_bootorder == bootloader.get_boot_order(), attempts=200)
+
+    test.succeed()
diff --git a/test/test.mk b/test/test.mk
index 5ac145556..ddef0ae3b 100644
--- a/test/test.mk
+++ b/test/test.mk
@@ -22,7 +22,8 @@ mode-run    := -t $(BINARIES_DIR)/qemu.dot
 mode        := $(mode-$(TEST_MODE))
 
 INFIX_IMAGE_ID := $(call qstrip,$(INFIX_IMAGE_ID))
-binaries-$(ARCH) := $(addprefix $(INFIX_IMAGE_ID),.img -disk.img .pkg)
+binaries-$(ARCH) := $(addprefix $(INFIX_IMAGE_ID),.img -disk.img)
+pkg-$(ARCH)      := -p $(O)/images/$(addprefix $(INFIX_IMAGE_ID),.pkg)
 binaries-x86_64  += OVMF.fd
 binaries := $(foreach bin,$(binaries-$(ARCH)),-f $(BINARIES_DIR)/$(bin))
 
@@ -32,10 +33,10 @@ export INFAMY_ARGS := --transport=netconf
 endif
 
 test:
-	$(test-dir)/env -r $(base) $(mode) $(binaries) $(ninepm) $(TESTS)
+	$(test-dir)/env -r $(base) $(mode) $(binaries) $(pkg-$(ARCH)) $(ninepm) $(TESTS)
 
 test-sh:
-	$(test-dir)/env $(base) $(mode) $(binaries) -i /bin/sh
+	$(test-dir)/env $(base) $(mode) $(binaries) $(pkg-$(ARCH)) -i /bin/sh
 
 test-spec:
 	@esc_infix_name="$(echo $(INFIX_NAME) | sed 's/\//\\\//g')"; \