From 45225c04ce1210f45d512b682ddcb15b69a8d0ab Mon Sep 17 00:00:00 2001 From: "Adam C. Stephens" Date: Sat, 25 Apr 2026 15:01:12 -0400 Subject: [PATCH] nixosTests.incus: add test of container channel setup --- nixos/tests/incus/default.nix | 9 ++ nixos/tests/incus/incus-tests-module.nix | 102 ++++++++++++----------- 2 files changed, 64 insertions(+), 47 deletions(-) diff --git a/nixos/tests/incus/default.nix b/nixos/tests/incus/default.nix index a09e4e8c3ace..af33c6c78316 100644 --- a/nixos/tests/incus/default.nix +++ b/nixos/tests/incus/default.nix @@ -45,6 +45,15 @@ in }; }; + channel = incusRunTest { + name = "channel"; + + instances.c1 = { + type = "container"; + copyChannel = true; + }; + }; + # used in lxc tests to verify container functionality container = incusRunTest { name = "container"; diff --git a/nixos/tests/incus/incus-tests-module.nix b/nixos/tests/incus/incus-tests-module.nix index 8d8752fde81f..69b0d3c13825 100644 --- a/nixos/tests/incus/incus-tests-module.nix +++ b/nixos/tests/incus/incus-tests-module.nix @@ -60,6 +60,11 @@ in default = { }; }; + copyChannel = lib.mkEnableOption '' + copy channel in test image. disabled by default as it forces image + rebuilds excessively. enable to validate channel things. + ''; + testScript = lib.mkOption { type = lib.types.str; description = "final script provided to test runner"; @@ -104,7 +109,7 @@ in documentation.enable = lib.mkForce false; documentation.nixos.enable = lib.mkForce false; # including a channel forces images to be rebuilt on any changes - system.installer.channel.enable = lib.mkForce false; + system.installer.channel.enable = lib.mkForce config.copyChannel; environment.etc."nix/registry.json".text = lib.mkForce "{}"; @@ -170,64 +175,67 @@ in # # container specific # - + - lib.optionalString (config.type == "container") - # python - '' - with subtest("[${image_id}] switch-to-configuration updates /sbin/init via installBootLoader"): - # Remove /sbin/init so we can verify installBootLoader recreates it - server.succeed(f"incus exec {instance_name} -- rm -f /sbin/init") - server.fail(f"incus exec {instance_name} -- test -e /sbin/init") + + lib.optionalString (config.type == "container") ( + # python + '' + with subtest("[${image_id}] switch-to-configuration updates /sbin/init via installBootLoader"): + # Remove /sbin/init so we can verify installBootLoader recreates it + server.succeed(f"incus exec {instance_name} -- rm -f /sbin/init") + server.fail(f"incus exec {instance_name} -- test -e /sbin/init") - server.succeed( - f"incus exec {instance_name} -- /run/current-system/bin/switch-to-configuration switch" - ) + server.succeed( + f"incus exec {instance_name} -- /run/current-system/bin/switch-to-configuration switch" + ) - # Verify installBootLoader recreated /sbin/init pointing to the system's init - server.succeed(f"incus exec {instance_name} -- test -x /sbin/init") - target = server.succeed(f"incus exec {instance_name} -- readlink -f /sbin/init").strip() - current = server.succeed(f"incus exec {instance_name} -- readlink -f /run/current-system/init").strip() - assert target == current, f"/sbin/init -> {target}, expected {current}" + # Verify installBootLoader recreated /sbin/init pointing to the system's init + server.succeed(f"incus exec {instance_name} -- test -x /sbin/init") + target = server.succeed(f"incus exec {instance_name} -- readlink -f /sbin/init").strip() + current = server.succeed(f"incus exec {instance_name} -- readlink -f /run/current-system/init").strip() + assert target == current, f"/sbin/init -> {target}, expected {current}" - # TODO troubleshoot VM hot memory resizing which was introduced in 6.12 - with subtest("[${image_id}] memory limits can be hotplug changed"): - server.set_instance_config(instance_name, "limits.memory 512MB") - # can't use lsmem since it sees the host's memory size - server.wait_instance_exec_success(instance_name, "grep 'MemTotal:[[:space:]]*500000 kB' /proc/meminfo", timeout=1) + # TODO troubleshoot VM hot memory resizing which was introduced in 6.12 + with subtest("[${image_id}] memory limits can be hotplug changed"): + server.set_instance_config(instance_name, "limits.memory 512MB") + # can't use lsmem since it sees the host's memory size + server.wait_instance_exec_success(instance_name, "grep 'MemTotal:[[:space:]]*500000 kB' /proc/meminfo", timeout=1) - # verify the patched container systemd generator from `pkgs.distrobuilder.generator` - with subtest("[${image_id}] lxc-generator compatibility"): - with subtest("[${image_id}] lxc-container generator configures plain container"): - # default container is plain - server.succeed(f"incus exec {instance_name} test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf") + # verify the patched container systemd generator from `pkgs.distrobuilder.generator` + with subtest("[${image_id}] lxc-generator compatibility"): + with subtest("[${image_id}] lxc-container generator configures plain container"): + # default container is plain + server.succeed(f"incus exec {instance_name} test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf") - server.check_instance_sysctl(instance_name) + server.check_instance_sysctl(instance_name) - with subtest("[${image_id}] lxc-container generator configures nested container"): - server.set_instance_config(instance_name, "security.nesting=true", restart=True) + with subtest("[${image_id}] lxc-container generator configures nested container"): + server.set_instance_config(instance_name, "security.nesting=true", restart=True) - server.fail(f"incus exec {instance_name} test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf") - target = server.succeed(f"incus exec {instance_name} readlink -- -f /run/systemd/system/systemd-binfmt.service").strip() - assert target == "/dev/null", "lxc generator did not correctly mask /run/systemd/system/systemd-binfmt.service" + server.fail(f"incus exec {instance_name} test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf") + target = server.succeed(f"incus exec {instance_name} readlink -- -f /run/systemd/system/systemd-binfmt.service").strip() + assert target == "/dev/null", "lxc generator did not correctly mask /run/systemd/system/systemd-binfmt.service" - server.check_instance_sysctl(instance_name) + server.check_instance_sysctl(instance_name) - with subtest("[${image_id}] lxcfs"): - with subtest("[${image_id}] mounts lxcfs overlays"): - server.succeed(f"incus exec {instance_name} mount | grep 'lxcfs on /proc/cpuinfo type fuse.lxcfs'") - server.succeed(f"incus exec {instance_name} mount | grep 'lxcfs on /proc/meminfo type fuse.lxcfs'") + with subtest("[${image_id}] lxcfs"): + with subtest("[${image_id}] mounts lxcfs overlays"): + server.succeed(f"incus exec {instance_name} mount | grep 'lxcfs on /proc/cpuinfo type fuse.lxcfs'") + server.succeed(f"incus exec {instance_name} mount | grep 'lxcfs on /proc/meminfo type fuse.lxcfs'") - with subtest("[${image_id}] supports per-instance lxcfs"): - server.succeed(f"incus stop {instance_name}") - server.fail(f"pgrep -a lxcfs | grep 'incus/devices/{instance_name}/lxcfs'") + with subtest("[${image_id}] supports per-instance lxcfs"): + server.succeed(f"incus stop {instance_name}") + server.fail(f"pgrep -a lxcfs | grep 'incus/devices/{instance_name}/lxcfs'") - server.succeed("incus config set instances.lxcfs.per_instance=true") - - server.succeed(f"incus start {instance_name}") - server.wait_for_instance(instance_name) - server.succeed(f"pgrep -a lxcfs | grep 'incus/devices/{instance_name}/lxcfs'") - '' + server.succeed("incus config set instances.lxcfs.per_instance=true") + server.succeed(f"incus start {instance_name}") + server.wait_for_instance(instance_name) + server.succeed(f"pgrep -a lxcfs | grep 'incus/devices/{instance_name}/lxcfs'") + '' + + lib.optionalString (config.copyChannel) '' + with subtest("[${image_id}] channel copied correctly"): + server.succeed(f"incus exec {instance_name} -- systemctl status nix-channel-init.service") + '' + ) # # virtual-machine specific #