diff options
Diffstat (limited to 'nixpkgs/nixos/tests/incus')
-rw-r--r-- | nixpkgs/nixos/tests/incus/container.nix | 105 | ||||
-rw-r--r-- | nixpkgs/nixos/tests/incus/default.nix | 18 | ||||
-rw-r--r-- | nixpkgs/nixos/tests/incus/lxd-to-incus.nix | 110 | ||||
-rw-r--r-- | nixpkgs/nixos/tests/incus/preseed.nix | 62 | ||||
-rw-r--r-- | nixpkgs/nixos/tests/incus/socket-activated.nix | 28 | ||||
-rw-r--r-- | nixpkgs/nixos/tests/incus/ui.nix | 63 | ||||
-rw-r--r-- | nixpkgs/nixos/tests/incus/virtual-machine.nix | 60 |
7 files changed, 446 insertions, 0 deletions
diff --git a/nixpkgs/nixos/tests/incus/container.nix b/nixpkgs/nixos/tests/incus/container.nix new file mode 100644 index 000000000000..0f42d16f133d --- /dev/null +++ b/nixpkgs/nixos/tests/incus/container.nix @@ -0,0 +1,105 @@ +import ../make-test-python.nix ({ pkgs, lib, extra ? {}, ... } : + +let + releases = import ../../release.nix { + configuration = { + # Building documentation makes the test unnecessarily take a longer time: + documentation.enable = lib.mkForce false; + } // extra; + }; + + container-image-metadata = releases.lxdContainerMeta.${pkgs.stdenv.hostPlatform.system}; + container-image-rootfs = releases.lxdContainerImage.${pkgs.stdenv.hostPlatform.system}; +in +{ + name = "incus-container"; + + meta = { + maintainers = lib.teams.lxc.members; + }; + + nodes.machine = { ... }: { + virtualisation = { + # Ensure test VM has enough resources for creating and managing guests + cores = 2; + memorySize = 1024; + diskSize = 4096; + + incus.enable = true; + }; + }; + + testScript = '' + def instance_is_up(_) -> bool: + status, _ = machine.execute("incus exec container --disable-stdin --force-interactive /run/current-system/sw/bin/systemctl -- is-system-running") + return status == 0 + + def set_container(config): + machine.succeed(f"incus config set container {config}") + machine.succeed("incus restart container") + with machine.nested("Waiting for instance to start and be usable"): + retry(instance_is_up) + + machine.wait_for_unit("incus.service") + + # no preseed should mean no service + machine.fail("systemctl status incus-preseed.service") + + machine.succeed("incus admin init --minimal") + + with subtest("Container image can be imported"): + machine.succeed("incus image import ${container-image-metadata}/*/*.tar.xz ${container-image-rootfs}/*/*.tar.xz --alias nixos") + + with subtest("Container can be launched and managed"): + machine.succeed("incus launch nixos container") + with machine.nested("Waiting for instance to start and be usable"): + retry(instance_is_up) + machine.succeed("echo true | incus exec container /run/current-system/sw/bin/bash -") + + with subtest("Container mounts lxcfs overlays"): + machine.succeed("incus exec container mount | grep 'lxcfs on /proc/cpuinfo type fuse.lxcfs'") + machine.succeed("incus exec container mount | grep 'lxcfs on /proc/meminfo type fuse.lxcfs'") + + with subtest("Container CPU limits can be managed"): + set_container("limits.cpu 1") + cpuinfo = machine.succeed("incus exec container grep -- -c ^processor /proc/cpuinfo").strip() + assert cpuinfo == "1", f"Wrong number of CPUs reported from /proc/cpuinfo, want: 1, got: {cpuinfo}" + + set_container("limits.cpu 2") + cpuinfo = machine.succeed("incus exec container grep -- -c ^processor /proc/cpuinfo").strip() + assert cpuinfo == "2", f"Wrong number of CPUs reported from /proc/cpuinfo, want: 2, got: {cpuinfo}" + + with subtest("Container memory limits can be managed"): + set_container("limits.memory 64MB") + meminfo = machine.succeed("incus exec container grep -- MemTotal /proc/meminfo").strip() + meminfo_bytes = " ".join(meminfo.split(' ')[-2:]) + assert meminfo_bytes == "62500 kB", f"Wrong amount of memory reported from /proc/meminfo, want: '62500 kB', got: '{meminfo_bytes}'" + + set_container("limits.memory 128MB") + meminfo = machine.succeed("incus exec container grep -- MemTotal /proc/meminfo").strip() + meminfo_bytes = " ".join(meminfo.split(' ')[-2:]) + assert meminfo_bytes == "125000 kB", f"Wrong amount of memory reported from /proc/meminfo, want: '125000 kB', got: '{meminfo_bytes}'" + + with subtest("lxc-container generator configures plain container"): + # reuse the existing container to save some time + machine.succeed("incus exec container test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf") + + with subtest("lxc-container generator configures nested container"): + machine.execute("incus delete --force container") + machine.succeed("incus launch nixos container --config security.nesting=true") + with machine.nested("Waiting for instance to start and be usable"): + retry(instance_is_up) + + machine.fail("incus exec container test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf") + target = machine.succeed("incus exec container 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" + + with subtest("lxc-container generator configures privileged container"): + machine.execute("incus delete --force container") + machine.succeed("incus launch nixos container --config security.privileged=true") + with machine.nested("Waiting for instance to start and be usable"): + retry(instance_is_up) + + machine.succeed("incus exec container test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf") + ''; +}) diff --git a/nixpkgs/nixos/tests/incus/default.nix b/nixpkgs/nixos/tests/incus/default.nix new file mode 100644 index 000000000000..ff36fe9d6730 --- /dev/null +++ b/nixpkgs/nixos/tests/incus/default.nix @@ -0,0 +1,18 @@ +{ + system ? builtins.currentSystem, + config ? { }, + pkgs ? import ../../.. { inherit system config; }, + handleTestOn, +}: +{ + container-old-init = import ./container.nix { inherit system pkgs; }; + container-new-init = import ./container.nix { inherit system pkgs; extra = { + # Enable new systemd init + boot.initrd.systemd.enable = true; + }; }; + lxd-to-incus = import ./lxd-to-incus.nix { inherit system pkgs; }; + preseed = import ./preseed.nix { inherit system pkgs; }; + socket-activated = import ./socket-activated.nix { inherit system pkgs; }; + ui = import ./ui.nix {inherit system pkgs;}; + virtual-machine = handleTestOn [ "x86_64-linux" ] ./virtual-machine.nix { inherit system pkgs; }; +} diff --git a/nixpkgs/nixos/tests/incus/lxd-to-incus.nix b/nixpkgs/nixos/tests/incus/lxd-to-incus.nix new file mode 100644 index 000000000000..c0fc98c224df --- /dev/null +++ b/nixpkgs/nixos/tests/incus/lxd-to-incus.nix @@ -0,0 +1,110 @@ +import ../make-test-python.nix ( + + { pkgs, lib, ... }: + + let + releases = import ../../release.nix { configuration.documentation.enable = lib.mkForce false; }; + + container-image-metadata = releases.lxdContainerMeta.${pkgs.stdenv.hostPlatform.system}; + container-image-rootfs = releases.lxdContainerImage.${pkgs.stdenv.hostPlatform.system}; + in + { + name = "lxd-to-incus"; + + meta = { + maintainers = lib.teams.lxc.members; + }; + + nodes.machine = + { lib, ... }: + { + virtualisation = { + diskSize = 6144; + cores = 2; + memorySize = 2048; + + lxd.enable = true; + lxd.preseed = { + networks = [ + { + name = "nixostestbr0"; + type = "bridge"; + config = { + "ipv4.address" = "10.0.100.1/24"; + "ipv4.nat" = "true"; + }; + } + ]; + profiles = [ + { + name = "default"; + devices = { + eth0 = { + name = "eth0"; + network = "nixostestbr0"; + type = "nic"; + }; + root = { + path = "/"; + pool = "nixostest_pool"; + size = "35GiB"; + type = "disk"; + }; + }; + } + { + name = "nixos_notdefault"; + devices = { }; + } + ]; + storage_pools = [ + { + name = "nixostest_pool"; + driver = "dir"; + } + ]; + }; + + incus.enable = true; + }; + }; + + testScript = '' + def lxd_wait_for_preseed(_) -> bool: + _, output = machine.systemctl("is-active lxd-preseed.service") + return ("inactive" in output) + + def lxd_instance_is_up(_) -> bool: + status, _ = machine.execute("lxc exec container --disable-stdin --force-interactive /run/current-system/sw/bin/systemctl -- is-system-running") + return status == 0 + + def incus_instance_is_up(_) -> bool: + status, _ = machine.execute("incus exec container --disable-stdin --force-interactive /run/current-system/sw/bin/systemctl -- is-system-running") + return status == 0 + + with machine.nested("initialize lxd and resources"): + machine.wait_for_unit("sockets.target") + machine.wait_for_unit("lxd.service") + retry(lxd_wait_for_preseed) + + machine.succeed("lxc image import ${container-image-metadata}/*/*.tar.xz ${container-image-rootfs}/*/*.tar.xz --alias nixos") + machine.succeed("lxc launch nixos container") + retry(lxd_instance_is_up) + + machine.wait_for_unit("incus.service") + + with machine.nested("run migration"): + machine.succeed("lxd-to-incus --yes") + + with machine.nested("verify resources migrated to incus"): + machine.succeed("incus config show container") + retry(incus_instance_is_up) + machine.succeed("incus exec container -- true") + machine.succeed("incus profile show default | grep nixostestbr0") + machine.succeed("incus profile show default | grep nixostest_pool") + machine.succeed("incus profile show nixos_notdefault") + machine.succeed("incus storage show nixostest_pool") + machine.succeed("incus network show nixostestbr0") + ''; + } +) diff --git a/nixpkgs/nixos/tests/incus/preseed.nix b/nixpkgs/nixos/tests/incus/preseed.nix new file mode 100644 index 000000000000..a488d71f3c92 --- /dev/null +++ b/nixpkgs/nixos/tests/incus/preseed.nix @@ -0,0 +1,62 @@ +import ../make-test-python.nix ({ pkgs, lib, ... } : + +{ + name = "incus-preseed"; + + meta = { + maintainers = lib.teams.lxc.members; + }; + + nodes.machine = { lib, ... }: { + virtualisation = { + incus.enable = true; + + incus.preseed = { + networks = [ + { + name = "nixostestbr0"; + type = "bridge"; + config = { + "ipv4.address" = "10.0.100.1/24"; + "ipv4.nat" = "true"; + }; + } + ]; + profiles = [ + { + name = "nixostest_default"; + devices = { + eth0 = { + name = "eth0"; + network = "nixostestbr0"; + type = "nic"; + }; + root = { + path = "/"; + pool = "default"; + size = "35GiB"; + type = "disk"; + }; + }; + } + ]; + storage_pools = [ + { + name = "nixostest_pool"; + driver = "dir"; + } + ]; + }; + }; + }; + + testScript = '' + machine.wait_for_unit("incus.service") + machine.wait_for_unit("incus-preseed.service") + + with subtest("Verify preseed resources created"): + machine.succeed("incus profile show nixostest_default") + machine.succeed("incus network info nixostestbr0") + machine.succeed("incus storage show nixostest_pool") + ''; +}) diff --git a/nixpkgs/nixos/tests/incus/socket-activated.nix b/nixpkgs/nixos/tests/incus/socket-activated.nix new file mode 100644 index 000000000000..fca536b7054f --- /dev/null +++ b/nixpkgs/nixos/tests/incus/socket-activated.nix @@ -0,0 +1,28 @@ +import ../make-test-python.nix ({ pkgs, lib, ... } : + +{ + name = "incus-socket-activated"; + + meta = { + maintainers = lib.teams.lxc.members; + }; + + nodes.machine = { lib, ... }: { + virtualisation = { + incus.enable = true; + incus.socketActivation = true; + }; + }; + + testScript = '' + machine.wait_for_unit("incus.socket") + + # ensure service is not running by default + machine.fail("systemctl is-active incus.service") + machine.fail("systemctl is-active incus-preseed.service") + + # access the socket and ensure the service starts + machine.succeed("incus list") + machine.wait_for_unit("incus.service") + ''; +}) diff --git a/nixpkgs/nixos/tests/incus/ui.nix b/nixpkgs/nixos/tests/incus/ui.nix new file mode 100644 index 000000000000..24ce1217d8df --- /dev/null +++ b/nixpkgs/nixos/tests/incus/ui.nix @@ -0,0 +1,63 @@ +import ../make-test-python.nix ({ pkgs, lib, ... }: { + name = "incus-ui"; + + meta = { + maintainers = lib.teams.lxc.members; + }; + + nodes.machine = { lib, ... }: { + virtualisation = { + incus.enable = true; + incus.ui.enable = true; + }; + + environment.systemPackages = + let + seleniumScript = pkgs.writers.writePython3Bin "selenium-script" + { + libraries = with pkgs.python3Packages; [ selenium ]; + } '' + from selenium import webdriver + from selenium.webdriver.common.by import By + from selenium.webdriver.firefox.options import Options + from selenium.webdriver.support.ui import WebDriverWait + + options = Options() + options.add_argument("--headless") + service = webdriver.FirefoxService(executable_path="${lib.getExe pkgs.geckodriver}") # noqa: E501 + + driver = webdriver.Firefox(options=options, service=service) + driver.implicitly_wait(10) + driver.get("https://localhost:8443/ui") + + wait = WebDriverWait(driver, 60) + + assert len(driver.find_elements(By.CLASS_NAME, "l-application")) > 0 + assert len(driver.find_elements(By.CLASS_NAME, "l-navigation__drawer")) > 0 + + driver.close() + ''; + in + with pkgs; [ curl firefox-unwrapped geckodriver seleniumScript ]; + }; + + + testScript = '' + machine.wait_for_unit("sockets.target") + machine.wait_for_unit("incus.service") + machine.wait_for_file("/var/lib/incus/unix.socket") + + # Configure incus listen address + machine.succeed("incus config set core.https_address :8443") + machine.succeed("systemctl restart incus") + + # Check that the INCUS_UI environment variable is populated in the systemd unit + machine.succeed("cat /etc/systemd/system/incus.service | grep 'INCUS_UI'") + + # Ensure the endpoint returns an HTML page with 'Incus UI' in the title + machine.succeed("curl -kLs https://localhost:8443/ui | grep '<title>Incus UI</title>'") + + # Ensure the application is actually rendered by the Javascript + machine.succeed("PYTHONUNBUFFERED=1 selenium-script") + ''; +}) diff --git a/nixpkgs/nixos/tests/incus/virtual-machine.nix b/nixpkgs/nixos/tests/incus/virtual-machine.nix new file mode 100644 index 000000000000..c76e4f448f2f --- /dev/null +++ b/nixpkgs/nixos/tests/incus/virtual-machine.nix @@ -0,0 +1,60 @@ +import ../make-test-python.nix ({ pkgs, lib, ... }: + +let + releases = import ../../release.nix { + configuration = { + # Building documentation makes the test unnecessarily take a longer time: + documentation.enable = lib.mkForce false; + + # Our tests require `grep` & friends: + environment.systemPackages = with pkgs; [busybox]; + }; + }; + + vm-image-metadata = releases.lxdVirtualMachineImageMeta.${pkgs.stdenv.hostPlatform.system}; + vm-image-disk = releases.lxdVirtualMachineImage.${pkgs.stdenv.hostPlatform.system}; + + instance-name = "instance1"; +in +{ + name = "incus-virtual-machine"; + + meta = { + maintainers = lib.teams.lxc.members; + }; + + nodes.machine = {...}: { + virtualisation = { + # Ensure test VM has enough resources for creating and managing guests + cores = 2; + memorySize = 1024; + diskSize = 4096; + + incus.enable = true; + }; + }; + + testScript = '' + def instance_is_up(_) -> bool: + status, _ = machine.execute("incus exec ${instance-name} --disable-stdin --force-interactive /run/current-system/sw/bin/systemctl -- is-system-running") + return status == 0 + + machine.wait_for_unit("incus.service") + + machine.succeed("incus admin init --minimal") + + with subtest("virtual-machine image can be imported"): + machine.succeed("incus image import ${vm-image-metadata}/*/*.tar.xz ${vm-image-disk}/nixos.qcow2 --alias nixos") + + with subtest("virtual-machine can be launched and become available"): + machine.succeed("incus launch nixos ${instance-name} --vm --config limits.memory=512MB --config security.secureboot=false") + with machine.nested("Waiting for instance to start and be usable"): + retry(instance_is_up) + + with subtest("lxd-agent is started"): + machine.succeed("incus exec ${instance-name} systemctl is-active lxd-agent") + + with subtest("lxd-agent has a valid path"): + machine.succeed("incus exec ${instance-name} -- bash -c 'true'") + ''; +}) |