diff --git a/board/x86_64/board.mk b/board/x86_64/board.mk index eb52a727..8b47a1b8 100644 --- a/board/x86_64/board.mk +++ b/board/x86_64/board.mk @@ -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)) diff --git a/test/case/ietf_system/bundles/not-a-bundle.pkg b/test/case/ietf_system/bundles/not-a-bundle.pkg new file mode 100644 index 00000000..e69de29b diff --git a/test/case/ietf_system/bundles/package b/test/case/ietf_system/bundles/package new file mode 120000 index 00000000..ce024d92 --- /dev/null +++ b/test/case/ietf_system/bundles/package @@ -0,0 +1 @@ +/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/upgrade.py b/test/case/ietf_system/upgrade.py new file mode 100755 index 00000000..831e5ab1 --- /dev/null +++ b/test/case/ietf_system/upgrade.py @@ -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() diff --git a/test/docker/Dockerfile b/test/docker/Dockerfile index 0a64020e..b2f9862b 100644 --- a/test/docker/Dockerfile +++ b/test/docker/Dockerfile @@ -10,6 +10,7 @@ RUN apk add --no-cache \ iputils \ libc-dev \ libyang-dev \ + linux-headers \ python3-dev \ qemu-img \ qemu-system-x86_64 \ diff --git a/test/docker/pip-requirements.txt b/test/docker/pip-requirements.txt index 13364972..447ee7ef 100644 --- a/test/docker/pip-requirements.txt +++ b/test/docker/pip-requirements.txt @@ -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 diff --git a/test/env b/test/env index febbf70e..5d284f37 100755 --- a/test/env +++ b/test/env @@ -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 [] -f -q [...] useful to see how tests will run in a CI setting, where KVM is typically not available + -p + Infix RAUC bundle to use for upgrade tests. + -q 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" ;; diff --git a/test/infamy/env.py b/test/infamy/env.py index 5b57578e..df0eae42 100644 --- a/test/infamy/env.py +++ b/test/infamy/env.py @@ -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")