Skip to content

Commit

Permalink
Merge pull request #846 from kernelkit/fix-upgrade-test
Browse files Browse the repository at this point in the history
Update upgrade test
  • Loading branch information
mattiaswal authored Dec 5, 2024
2 parents 1f231c2 + f023304 commit 1db039d
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 51 deletions.
1 change: 0 additions & 1 deletion test/case/ietf_system/bundles/package

This file was deleted.

3 changes: 3 additions & 0 deletions test/case/ietf_system/ietf_system.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@

- name: ntp_client
case: ntp_client/test.py

- name: upgrade
case: upgrade/test.py
4 changes: 4 additions & 0 deletions test/case/ietf_system/upgrade/Readme.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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


<<<
Expand Down
114 changes: 103 additions & 11 deletions test/case/ietf_system/upgrade/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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].strip()

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].strip()

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()
Expand All @@ -33,22 +61,55 @@
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()
print(f"Initial bootorder: {repr(old_bootorder)}")

_, hport = env.ltop.xlate("host", "mgmt")
_, tport = env.ltop.xlate("target", "mgmt")
hip = netifaces.ifaddresses(hport)[netifaces.AF_INET6][0]["addr"]
hip = hip.replace(f"%{hport}", f"%{tport}")
_, hport = env.ltop.xlate("host", "data")
_, tport = env.ltop.xlate("target", "data")

with srv.FileServer(("::", SRVPORT), BUNDLEDIR):
netns = infamy.IsolatedMacVlan(hport).start()
netns.addip("192.168.0.1")

target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": tport,
"ipv4": {
"address": [
{
"ip": "192.168.0.2",
"prefix-length": 24
}
]
}
}
]
}
}
})
netns.must_reach("192.168.0.2")
with srv.FileServer(netns, "192.168.0.1", SRVPORT, BUNDLEDIR):
with test.step("Start installation of selected package"):
print(f"Installing {os.path.basename(env.args.package)}")

target.call_dict("infix-system", {
"install-bundle": {
"url": f"http://[{hip}]:{SRVPORT}/package",
"url": f"http://192.168.0.1:{SRVPORT}/package",
}
})

Expand All @@ -61,9 +122,40 @@
print("Install failed:", installer["last-error"])
test.fail()

test.succeed()

break
time.sleep(1)
else:
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"):
order = bootloader.get_boot_order()
assert order == old_bootorder, f"Unexpected bootorder: {repr(order)}"

print("Timeout, last state:", oper)
test.fail()
test.succeed()
23 changes: 0 additions & 23 deletions test/case/ietf_system/upgrade/topology.dot

This file was deleted.

1 change: 1 addition & 0 deletions test/case/ietf_system/upgrade/topology.dot
44 changes: 31 additions & 13 deletions test/infamy/file_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,42 @@
import functools
import http.server
import socket
from infamy.util import until


class FileServer(http.server.HTTPServer):
class FileServer:
"""Open web server on (address, port) serving files from directory"""
class RequestHandler(http.server.SimpleHTTPRequestHandler):
def log_message(self, *args, **kwargs):
pass
def __init__(self, netns, address, port, directory):
self.address = address
self.port = port
self.directory = directory
self.netns = netns
self.process = None
self.check_addres = None


def start(self):
"""start HTTP file server"""
cmd = f"httpd -p {self.address}:{self.port} -f -h {self.directory}"
self.process = self.netns.popen(cmd.split(" "))
if self.address == "[::]":
check_address = "::1"
elif self.address == "0.0.0.0":
check_address = "127.0.0.1"
else:
check_address=self.address
cmd = f"nc -z {check_address} {self.port}".split()
until(lambda: self.netns.run(cmd).returncode == 0)

address_family = socket.AF_INET6

def __init__(self, server_address, directory):
rh = functools.partial(FileServer.RequestHandler, directory=directory)
self.__tp = concurrent.futures.ThreadPoolExecutor(max_workers=1)
super().__init__(server_address, rh)
def stop(self):
"""Stop HTTP file server"""
if self.process:
self.process.terminate()
self.process.wait()
self.process = None

def __enter__(self):
self.__tp.submit(self.serve_forever)
self.start()

def __exit__(self, _, __, ___):
self.shutdown()
self.__tp.shutdown()
self.stop()
7 changes: 4 additions & 3 deletions test/test.mk
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,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))

Expand All @@ -26,10 +27,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')"; \
Expand Down

0 comments on commit 1db039d

Please sign in to comment.