mirror of
https://github.com/kernelkit/infix.git
synced 2026-08-01 13:23:01 +02:00
Merge pull request #846 from kernelkit/fix-upgrade-test
Update upgrade test
This commit is contained in:
@@ -1 +0,0 @@
|
||||
/home/wkz/src/github.com/kernelkit/infix/x-netconf/images/infix-x86_64.pkg
|
||||
@@ -19,3 +19,6 @@
|
||||
|
||||
- name: ntp_client
|
||||
case: ntp_client/test.py
|
||||
|
||||
- name: upgrade
|
||||
case: upgrade/test.py
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
<<<
|
||||
|
||||
@@ -4,11 +4,14 @@ Upgrade
|
||||
|
||||
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 @@ BUNDLEDIR = os.path.join(
|
||||
"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()
|
||||
@@ -33,22 +61,55 @@ with infamy.Test() as test:
|
||||
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()
|
||||
|
||||
_, 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}")
|
||||
old_bootorder=bootloader.get_boot_order()
|
||||
print(f"Initial bootorder: {repr(old_bootorder)}")
|
||||
|
||||
with srv.FileServer(("::", SRVPORT), BUNDLEDIR):
|
||||
_, hport = env.ltop.xlate("host", "data")
|
||||
_, tport = env.ltop.xlate("target", "data")
|
||||
|
||||
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",
|
||||
}
|
||||
})
|
||||
|
||||
@@ -61,9 +122,40 @@ with infamy.Test() as test:
|
||||
print("Install failed:", installer["last-error"])
|
||||
test.fail()
|
||||
|
||||
test.succeed()
|
||||
|
||||
break
|
||||
time.sleep(1)
|
||||
else:
|
||||
print("Timeout, last state:", oper)
|
||||
test.fail()
|
||||
|
||||
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)}"
|
||||
|
||||
test.succeed()
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
graph "1x1" {
|
||||
layout="neato";
|
||||
overlap="false";
|
||||
esep="+20";
|
||||
|
||||
node [shape=record, fontname="DejaVu Sans Mono, Book"];
|
||||
edge [color="cornflowerblue", penwidth="2", fontname="DejaVu Serif, Book"];
|
||||
|
||||
host [
|
||||
label="host | { <mgmt> mgmt }",
|
||||
pos="0,12!",
|
||||
kind="controller",
|
||||
];
|
||||
|
||||
target [
|
||||
label="{ <mgmt> mgmt } | target",
|
||||
pos="10,12!",
|
||||
|
||||
kind="infix",
|
||||
];
|
||||
|
||||
host:mgmt -- target:mgmt [kind=mgmt, color=lightgrey]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
../../../infamy/topologies/1x2.dot
|
||||
+31
-13
@@ -5,24 +5,42 @@ import concurrent.futures
|
||||
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
|
||||
|
||||
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 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)
|
||||
|
||||
|
||||
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()
|
||||
|
||||
+4
-3
@@ -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))
|
||||
|
||||
@@ -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')"; \
|
||||
|
||||
Reference in New Issue
Block a user