test/case: Add ietf_system/upgrade

Verifies that RAUC bundles can be installed using NETCONF.

We choose to not add this to the "all" suite for now, as the qeneth
topologies do not run with full disk emulation.

To test locally, configure your "make run" instance to use the UEFI
loader, launch `make run`, and then run:

    make INFIX_TESTS=test/case/ietf_system/upgrade.py test-run
This commit is contained in:
Tobias Waldekranz
2023-06-30 15:33:10 +02:00
committed by Joachim Wiberg
parent 4fb09267cf
commit 5be61a7013
8 changed files with 101 additions and 2 deletions
+1
View File
@@ -3,6 +3,7 @@ INFIX_TESTS ?= $(test-dir)/case/all.yaml
test-env = $(test-dir)/env \
-f $(BINARIES_DIR)/infix-x86_64.img \
-p $(BINARIES_DIR)/infix-x86_64.pkg \
$(1) $(2)
test-env-qeneth = $(call test-env,-q $(test-dir)/virt/dual,$(1))
+1
View File
@@ -0,0 +1 @@
/home/wkz/src/github.com/kernelkit/infix/x-netconf/images/infix-x86_64.pkg
+88
View File
@@ -0,0 +1,88 @@
#!/usr/bin/env python3
import concurrent.futures
import functools
import http.server
import os
import socket
import time
import netifaces
import infamy
SRVPORT = 8008
BUNDLEDIR = os.path.join(
os.path.dirname(__file__),
"bundles"
)
PKGPATH = os.path.join(
BUNDLEDIR,
"package"
)
class FileServer(http.server.HTTPServer):
class RequestHandler(http.server.SimpleHTTPRequestHandler):
def log_message(*args, **kwargs):
pass
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 __enter__(self):
self.__tp.submit(self.serve_forever)
def __exit__(self, _, __, ___):
self.shutdown()
self.__tp.shutdown()
with infamy.Test() as test:
with test.step("Initialize"):
env = infamy.Env(infamy.std_topology("1x1"))
if not env.args.package:
print("No package supplied")
test.skip()
try:
os.unlink(PKGPATH)
except FileNotFoundError:
pass
os.symlink(os.path.abspath(env.args.package), PKGPATH)
target = env.attach("target", "mgmt")
_, hport = env.ltop.xlate("host", "tgt")
_, tport = env.ltop.xlate("target", "mgmt")
hip = netifaces.ifaddresses(hport)[netifaces.AF_INET6][0]["addr"]
hip = hip.replace(f"%{hport}", f"%{tport}")
with FileServer(("::", SRVPORT), BUNDLEDIR):
with test.step(f"Start installation of {os.path.basename(env.args.package)}"):
target.call_dict("infix-system", {
"install-bundle": {
"url": f"http://[{hip}]:{SRVPORT}/package",
}
})
with test.step("Wait for upgrade to finish"):
for _ in range(600):
oper = target.get_dict("/system-state/software")
installer = oper["system-state"]["software"]["installer"]
if installer["operation"] == "idle":
if "last-error" in installer:
print("Install failed:", installer["last-error"])
test.fail()
test.succeed()
time.sleep(1)
print("Timeout, last state:", oper)
test.fail()
+1
View File
@@ -10,6 +10,7 @@ RUN apk add --no-cache \
iputils \
libc-dev \
libyang-dev \
linux-headers \
python3-dev \
qemu-img \
qemu-system-x86_64 \
+1
View File
@@ -1,5 +1,6 @@
libyang==2.7.1
netconf_client==2.2.0
netifaces==0.11.0
networkx==3.1
pydot==1.4.2
pyyaml==5.4.1
+8 -2
View File
@@ -2,7 +2,7 @@
set -e
INFIX_TEST=ghcr.io/kernelkit/infix-test:0.4
INFIX_TEST=ghcr.io/kernelkit/infix-test:0.5
extract_yang()
{
@@ -73,6 +73,9 @@ usage: test/env [<OPTS>] -f <IMAGE> -q <QENETH-DIR> <COMMAND> [<ARGS>...]
useful to see how tests will run in a CI setting, where KVM is
typically not available
-p <BUNDLE>
Infix RAUC bundle to use for upgrade tests.
-q <QENETH-DIR>
Directory containing a topology.dot.in, suitable for consumption
by qeneth. A copy of this network is created, and launched. The
@@ -95,7 +98,7 @@ qeneth="$ixdir/qeneth/qeneth"
containerize=yes
[ -c /dev/kvm ] && kvm="--device=/dev/kvm"
while getopts "Cf:hKq:t:" opt; do
while getopts "Cf:hKp:q:t:" opt; do
case ${opt} in
C)
containerize=
@@ -109,6 +112,9 @@ while getopts "Cf:hKq:t:" opt; do
K)
kvm=
;;
p)
INFAMY_ARGS="$INFAMY_ARGS -p $OPTARG"
;;
q)
qenethdir="$OPTARG"
;;
+1
View File
@@ -13,6 +13,7 @@ class ArgumentParser(argparse.ArgumentParser):
self.add_argument("-d", "--debug", default=False, action="store_true")
self.add_argument("-l", "--logical-topology", dest="ltop", default=ltop)
self.add_argument("-p", "--package", default=None)
self.add_argument("-y", "--yangdir", default=None)
self.add_argument("ptop", nargs=1, metavar="topology")