From aefaae0c9d96d723a6d5da6336054e0112271756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6gler?= Date: Mon, 1 Apr 2024 17:24:42 +0200 Subject: [PATCH 1/3] nixos/tests/machinectl: auto-format test --- nixos/tests/systemd-machinectl.nix | 275 ++++++++++++++--------------- 1 file changed, 137 insertions(+), 138 deletions(-) diff --git a/nixos/tests/systemd-machinectl.nix b/nixos/tests/systemd-machinectl.nix index 02b4d9c590b5..ba37045b1b0e 100644 --- a/nixos/tests/systemd-machinectl.nix +++ b/nixos/tests/systemd-machinectl.nix @@ -1,149 +1,148 @@ import ./make-test-python.nix ({ pkgs, ... }: - let +let - container = { - # We re-use the NixOS container option ... - boot.isContainer = true; - # ... and revert unwanted defaults - networking.useHostResolvConf = false; + container = { + # We re-use the NixOS container option ... + boot.isContainer = true; + # ... and revert unwanted defaults + networking.useHostResolvConf = false; - # use networkd to obtain systemd network setup - networking.useNetworkd = true; - networking.useDHCP = false; + # use networkd to obtain systemd network setup + networking.useNetworkd = true; + networking.useDHCP = false; - # systemd-nspawn expects /sbin/init - boot.loader.initScript.enable = true; + # systemd-nspawn expects /sbin/init + boot.loader.initScript.enable = true; - imports = [ ../modules/profiles/minimal.nix ]; + imports = [ ../modules/profiles/minimal.nix ]; + }; + + containerSystem = (import ../lib/eval-config.nix { + inherit (pkgs) system; + modules = [ container ]; + }).config.system.build.toplevel; + + containerName = "container"; + containerRoot = "/var/lib/machines/${containerName}"; + +in +{ + name = "systemd-machinectl"; + + nodes.machine = { lib, ... }: { + # use networkd to obtain systemd network setup + networking.useNetworkd = true; + networking.useDHCP = false; + + # do not try to access cache.nixos.org + nix.settings.substituters = lib.mkForce [ ]; + + # auto-start container + systemd.targets.machines.wants = [ "systemd-nspawn@${containerName}.service" ]; + + virtualisation.additionalPaths = [ containerSystem ]; + + systemd.tmpfiles.rules = [ + "d /var/lib/machines/shared-decl 0755 root root - -" + ]; + systemd.nspawn.shared-decl = { + execConfig = { + Boot = false; + Parameters = "${containerSystem}/init"; + }; + filesConfig = { + BindReadOnly = "/nix/store"; + }; }; - containerSystem = (import ../lib/eval-config.nix { - inherit (pkgs) system; - modules = [ container ]; - }).config.system.build.toplevel; - - containerName = "container"; - containerRoot = "/var/lib/machines/${containerName}"; - - in - { - name = "systemd-machinectl"; - - nodes.machine = { lib, ... }: { - # use networkd to obtain systemd network setup - networking.useNetworkd = true; - networking.useDHCP = false; - - # do not try to access cache.nixos.org - nix.settings.substituters = lib.mkForce [ ]; - - # auto-start container - systemd.targets.machines.wants = [ "systemd-nspawn@${containerName}.service" ]; - - virtualisation.additionalPaths = [ containerSystem ]; - - systemd.tmpfiles.rules = [ - "d /var/lib/machines/shared-decl 0755 root root - -" + systemd.services."systemd-nspawn@${containerName}" = { + serviceConfig.Environment = [ + # Disable tmpfs for /tmp + "SYSTEMD_NSPAWN_TMPFS_TMP=0" ]; - systemd.nspawn.shared-decl = { - execConfig = { - Boot = false; - Parameters = "${containerSystem}/init"; - }; - filesConfig = { - BindReadOnly = "/nix/store"; - }; - }; - - systemd.services."systemd-nspawn@${containerName}" = { - serviceConfig.Environment = [ - # Disable tmpfs for /tmp - "SYSTEMD_NSPAWN_TMPFS_TMP=0" - ]; - overrideStrategy = "asDropin"; - }; - - # open DHCP for container - networking.firewall.extraCommands = '' - ${pkgs.iptables}/bin/iptables -A nixos-fw -i ve-+ -p udp -m udp --dport 67 -j nixos-fw-accept - ''; + overrideStrategy = "asDropin"; }; - testScript = '' - start_all() - machine.wait_for_unit("default.target"); - - # Test machinectl start stop of shared-decl - machine.succeed("machinectl start shared-decl"); - machine.wait_until_succeeds("systemctl -M shared-decl is-active default.target"); - machine.succeed("machinectl stop shared-decl"); - - # create containers root - machine.succeed("mkdir -p ${containerRoot}"); - - # start container with shared nix store by using same arguments as for systemd-nspawn@.service - machine.succeed("systemd-run systemd-nspawn --machine=${containerName} --network-veth -U --bind-ro=/nix/store ${containerSystem}/init") - machine.wait_until_succeeds("systemctl -M ${containerName} is-active default.target"); - - # Test machinectl stop - machine.succeed("machinectl stop ${containerName}"); - - # Install container - # Workaround for nixos-install - machine.succeed("chmod o+rx /var/lib/machines"); - machine.succeed("nixos-install --root ${containerRoot} --system ${containerSystem} --no-channel-copy --no-root-passwd"); - - # Allow systemd-nspawn to apply user namespace on immutable files - machine.succeed("chattr -i ${containerRoot}/var/empty"); - - # Test machinectl start - machine.succeed("machinectl start ${containerName}"); - machine.wait_until_succeeds("systemctl -M ${containerName} is-active default.target"); - - # Test nss_mymachines without nscd - machine.succeed('LD_LIBRARY_PATH="/run/current-system/sw/lib" getent -s hosts:mymachines hosts ${containerName}'); - - # Test nss_mymachines via nscd - machine.succeed("getent hosts ${containerName}"); - - # Test systemd-nspawn network configuration to container - machine.succeed("networkctl --json=short status ve-${containerName} | ${pkgs.jq}/bin/jq -e '.OperationalState == \"routable\"'"); - - # Test systemd-nspawn network configuration to host - machine.succeed("machinectl shell ${containerName} /run/current-system/sw/bin/networkctl --json=short status host0 | ${pkgs.jq}/bin/jq -r '.OperationalState == \"routable\"'"); - - # Test systemd-nspawn network configuration - machine.succeed("ping -n -c 1 ${containerName}"); - - # Test systemd-nspawn uses a user namespace - machine.succeed("test $(machinectl status ${containerName} | grep 'UID Shift: ' | wc -l) = 1") - - # Test systemd-nspawn reboot - machine.succeed("machinectl shell ${containerName} /run/current-system/sw/bin/reboot"); - machine.wait_until_succeeds("systemctl -M ${containerName} is-active default.target"); - - # Test machinectl reboot - machine.succeed("machinectl reboot ${containerName}"); - machine.wait_until_succeeds("systemctl -M ${containerName} is-active default.target"); - - # Restart machine - machine.shutdown() - machine.start() - machine.wait_for_unit("default.target"); - - # Test auto-start - machine.succeed("machinectl show ${containerName}") - - # Test machinectl stop - machine.succeed("machinectl stop ${containerName}"); - machine.wait_until_succeeds("test $(systemctl is-active systemd-nspawn@${containerName}) = inactive"); - - # Test tmpfs for /tmp - machine.fail("mountpoint /tmp"); - - # Show to to delete the container - machine.succeed("chattr -i ${containerRoot}/var/empty"); - machine.succeed("rm -rf ${containerRoot}"); + # open DHCP for container + networking.firewall.extraCommands = '' + ${pkgs.iptables}/bin/iptables -A nixos-fw -i ve-+ -p udp -m udp --dport 67 -j nixos-fw-accept ''; - } -) + }; + + testScript = '' + start_all() + machine.wait_for_unit("default.target"); + + # Test machinectl start stop of shared-decl + machine.succeed("machinectl start shared-decl"); + machine.wait_until_succeeds("systemctl -M shared-decl is-active default.target"); + machine.succeed("machinectl stop shared-decl"); + + # create containers root + machine.succeed("mkdir -p ${containerRoot}"); + + # start container with shared nix store by using same arguments as for systemd-nspawn@.service + machine.succeed("systemd-run systemd-nspawn --machine=${containerName} --network-veth -U --bind-ro=/nix/store ${containerSystem}/init") + machine.wait_until_succeeds("systemctl -M ${containerName} is-active default.target"); + + # Test machinectl stop + machine.succeed("machinectl stop ${containerName}"); + + # Install container + # Workaround for nixos-install + machine.succeed("chmod o+rx /var/lib/machines"); + machine.succeed("nixos-install --root ${containerRoot} --system ${containerSystem} --no-channel-copy --no-root-passwd"); + + # Allow systemd-nspawn to apply user namespace on immutable files + machine.succeed("chattr -i ${containerRoot}/var/empty"); + + # Test machinectl start + machine.succeed("machinectl start ${containerName}"); + machine.wait_until_succeeds("systemctl -M ${containerName} is-active default.target"); + + # Test nss_mymachines without nscd + machine.succeed('LD_LIBRARY_PATH="/run/current-system/sw/lib" getent -s hosts:mymachines hosts ${containerName}'); + + # Test nss_mymachines via nscd + machine.succeed("getent hosts ${containerName}"); + + # Test systemd-nspawn network configuration to container + machine.succeed("networkctl --json=short status ve-${containerName} | ${pkgs.jq}/bin/jq -e '.OperationalState == \"routable\"'"); + + # Test systemd-nspawn network configuration to host + machine.succeed("machinectl shell ${containerName} /run/current-system/sw/bin/networkctl --json=short status host0 | ${pkgs.jq}/bin/jq -r '.OperationalState == \"routable\"'"); + + # Test systemd-nspawn network configuration + machine.succeed("ping -n -c 1 ${containerName}"); + + # Test systemd-nspawn uses a user namespace + machine.succeed("test $(machinectl status ${containerName} | grep 'UID Shift: ' | wc -l) = 1") + + # Test systemd-nspawn reboot + machine.succeed("machinectl shell ${containerName} /run/current-system/sw/bin/reboot"); + machine.wait_until_succeeds("systemctl -M ${containerName} is-active default.target"); + + # Test machinectl reboot + machine.succeed("machinectl reboot ${containerName}"); + machine.wait_until_succeeds("systemctl -M ${containerName} is-active default.target"); + + # Restart machine + machine.shutdown() + machine.start() + machine.wait_for_unit("default.target"); + + # Test auto-start + machine.succeed("machinectl show ${containerName}") + + # Test machinectl stop + machine.succeed("machinectl stop ${containerName}"); + machine.wait_until_succeeds("test $(systemctl is-active systemd-nspawn@${containerName}) = inactive"); + + # Test tmpfs for /tmp + machine.fail("mountpoint /tmp"); + + # Show to to delete the container + machine.succeed("chattr -i ${containerRoot}/var/empty"); + machine.succeed("rm -rf ${containerRoot}"); + ''; +}) From 20e50bbb9263092b383fa1ee8e4f856e6b90ebd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6gler?= Date: Mon, 1 Apr 2024 17:57:30 +0200 Subject: [PATCH 2/3] nixos/tests/machinectl: add import-tar test --- nixos/tests/systemd-machinectl.nix | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/nixos/tests/systemd-machinectl.nix b/nixos/tests/systemd-machinectl.nix index ba37045b1b0e..78c1e6af42ce 100644 --- a/nixos/tests/systemd-machinectl.nix +++ b/nixos/tests/systemd-machinectl.nix @@ -25,6 +25,25 @@ let containerName = "container"; containerRoot = "/var/lib/machines/${containerName}"; + containerTarball = pkgs.callPackage ../lib/make-system-tarball.nix { + storeContents = [ + { + object = containerSystem; + symlink = "/nix/var/nix/profiles/system"; + } + ]; + + contents = [ + { + source = containerSystem + "/etc/os-release"; + target = "/etc/os-release"; + } + { + source = containerSystem + "/init"; + target = "/sbin/init"; + } + ]; + }; in { name = "systemd-machinectl"; @@ -40,7 +59,7 @@ in # auto-start container systemd.targets.machines.wants = [ "systemd-nspawn@${containerName}.service" ]; - virtualisation.additionalPaths = [ containerSystem ]; + virtualisation.additionalPaths = [ containerSystem containerTarball ]; systemd.tmpfiles.rules = [ "d /var/lib/machines/shared-decl 0755 root root - -" @@ -144,5 +163,13 @@ in # Show to to delete the container machine.succeed("chattr -i ${containerRoot}/var/empty"); machine.succeed("rm -rf ${containerRoot}"); + + # Test import tarball, start, stop and remove + machine.succeed("machinectl import-tar ${containerTarball}/tarball/*.tar* ${containerName}"); + machine.succeed("machinectl start ${containerName}"); + machine.wait_until_succeeds("systemctl -M ${containerName} is-active default.target"); + machine.succeed("machinectl stop ${containerName}"); + machine.wait_until_succeeds("test $(systemctl is-active systemd-nspawn@${containerName}) = inactive"); + machine.succeed("machinectl remove ${containerName}"); ''; }) From ff16d4597f7d74a1c16f10b680124d25189d41f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6gler?= Date: Mon, 1 Apr 2024 20:09:11 +0200 Subject: [PATCH 3/3] nixos/test/machinectl: set stateVersion --- nixos/tests/systemd-machinectl.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nixos/tests/systemd-machinectl.nix b/nixos/tests/systemd-machinectl.nix index 78c1e6af42ce..9d761c6d4d8b 100644 --- a/nixos/tests/systemd-machinectl.nix +++ b/nixos/tests/systemd-machinectl.nix @@ -1,7 +1,7 @@ import ./make-test-python.nix ({ pkgs, ... }: let - container = { + container = { config, ... }: { # We re-use the NixOS container option ... boot.isContainer = true; # ... and revert unwanted defaults @@ -15,6 +15,8 @@ let boot.loader.initScript.enable = true; imports = [ ../modules/profiles/minimal.nix ]; + + system.stateVersion = config.system.nixos.version; }; containerSystem = (import ../lib/eval-config.nix {