incus: fix instance unclean shutdown, add per-instance lxcfs support (#373920)
This commit is contained in:
@@ -38,6 +38,7 @@ let
|
||||
libnvidia-container
|
||||
libxfs
|
||||
lvm2
|
||||
lxcfs
|
||||
minio
|
||||
minio-client
|
||||
nftables
|
||||
@@ -121,6 +122,7 @@ let
|
||||
environment = lib.mkMerge [
|
||||
{
|
||||
INCUS_EDK2_PATH = ovmf;
|
||||
INCUS_LXC_HOOK = "${cfg.lxcPackage}/share/lxc/hooks";
|
||||
INCUS_LXC_TEMPLATE_CONFIG = "${pkgs.lxcfs}/share/lxc/config";
|
||||
INCUS_USBIDS_PATH = "${pkgs.hwdata}/share/hwdata/usb.ids";
|
||||
PATH = lib.mkForce serverBinPath;
|
||||
@@ -401,6 +403,7 @@ in
|
||||
"incus.socket"
|
||||
];
|
||||
requires = [ "incus.socket" ];
|
||||
wantedBy = config.systemd.services.incus.wantedBy;
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${incus-startup} start";
|
||||
|
||||
@@ -190,7 +190,7 @@ import ../make-test-python.nix (
|
||||
|
||||
def cleanup():
|
||||
# avoid conflict between preseed and cleanup operations
|
||||
machine.wait_for_unit("incus-preseed.service")
|
||||
machine.execute("systemctl kill incus-preseed.service")
|
||||
|
||||
instances = json.loads(machine.succeed("incus list --format json --all-projects"))
|
||||
with subtest("Stopping all running instances"):
|
||||
@@ -228,39 +228,41 @@ import ../make-test-python.nix (
|
||||
alias = "nixos/container/${variant}"
|
||||
variant = "${variant}"
|
||||
|
||||
with subtest("Container image can be imported"):
|
||||
with subtest("container image can be imported"):
|
||||
machine.succeed(f"incus image import {metadata} {rootfs} --alias {alias}")
|
||||
|
||||
|
||||
with subtest("Container can be launched and managed"):
|
||||
with subtest("container can be launched and managed"):
|
||||
machine.succeed(f"incus launch {alias} container-{variant}1")
|
||||
wait_for_instance(f"container-{variant}1")
|
||||
|
||||
|
||||
with subtest("Container mounts lxcfs overlays"):
|
||||
with subtest("container mounts lxcfs overlays"):
|
||||
machine.succeed(f"incus exec container-{variant}1 mount | grep 'lxcfs on /proc/cpuinfo type fuse.lxcfs'")
|
||||
machine.succeed(f"incus exec container-{variant}1 mount | grep 'lxcfs on /proc/meminfo type fuse.lxcfs'")
|
||||
|
||||
|
||||
with subtest("resource limits"):
|
||||
with subtest("Container CPU limits can be managed"):
|
||||
set_config(f"container-{variant}1", "limits.cpu 1", restart=True)
|
||||
wait_incus_exec_success(f"container-{variant}1", "nproc | grep '^1$'", timeout=15)
|
||||
|
||||
with subtest("Container CPU limits can be hotplug changed"):
|
||||
set_config(f"container-{variant}1", "limits.cpu 2")
|
||||
wait_incus_exec_success(f"container-{variant}1", "nproc | grep '^2$'", timeout=15)
|
||||
|
||||
with subtest("Container memory limits can be managed"):
|
||||
set_config(f"container-{variant}1", "limits.memory 128MB", restart=True)
|
||||
wait_incus_exec_success(f"container-{variant}1", "grep 'MemTotal:[[:space:]]*125000 kB' /proc/meminfo", timeout=15)
|
||||
|
||||
with subtest("Container memory limits can be hotplug changed"):
|
||||
set_config(f"container-{variant}1", "limits.memory 256MB")
|
||||
wait_incus_exec_success(f"container-{variant}1", "grep 'MemTotal:[[:space:]]*250000 kB' /proc/meminfo", timeout=15)
|
||||
with subtest("container CPU limits can be managed"):
|
||||
set_config(f"container-{variant}1", "limits.cpu 1", restart=True)
|
||||
wait_incus_exec_success(f"container-{variant}1", "nproc | grep '^1$'", timeout=15)
|
||||
|
||||
|
||||
with subtest("virtual tpm can be configured"):
|
||||
with subtest("container CPU limits can be hotplug changed"):
|
||||
set_config(f"container-{variant}1", "limits.cpu 2")
|
||||
wait_incus_exec_success(f"container-{variant}1", "nproc | grep '^2$'", timeout=15)
|
||||
|
||||
|
||||
with subtest("container memory limits can be managed"):
|
||||
set_config(f"container-{variant}1", "limits.memory 128MB", restart=True)
|
||||
wait_incus_exec_success(f"container-{variant}1", "grep 'MemTotal:[[:space:]]*125000 kB' /proc/meminfo", timeout=15)
|
||||
|
||||
|
||||
with subtest("container memory limits can be hotplug changed"):
|
||||
set_config(f"container-{variant}1", "limits.memory 256MB")
|
||||
wait_incus_exec_success(f"container-{variant}1", "grep 'MemTotal:[[:space:]]*250000 kB' /proc/meminfo", timeout=15)
|
||||
|
||||
|
||||
with subtest("container software tpm can be configured"):
|
||||
machine.succeed(f"incus config device add container-{variant}1 vtpm tpm path=/dev/tpm0 pathrm=/dev/tpmrm0")
|
||||
machine.succeed(f"incus exec container-{variant}1 -- test -e /dev/tpm0")
|
||||
machine.succeed(f"incus exec container-{variant}1 -- test -e /dev/tpmrm0")
|
||||
@@ -268,7 +270,7 @@ import ../make-test-python.nix (
|
||||
machine.fail(f"incus exec container-{variant}1 -- test -e /dev/tpm0")
|
||||
|
||||
|
||||
with subtest("lxc-generator"):
|
||||
with subtest("container lxc-generator compatibility"):
|
||||
with subtest("lxc-container generator configures plain container"):
|
||||
# default container is plain
|
||||
machine.succeed(f"incus exec container-{variant}1 test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf")
|
||||
@@ -293,14 +295,36 @@ import ../make-test-python.nix (
|
||||
|
||||
check_sysctl(f"container-{variant}2")
|
||||
|
||||
with subtest("container supports per-instance lxcfs"):
|
||||
machine.succeed(f"incus stop container-{variant}1")
|
||||
machine.fail(f"pgrep -a lxcfs | grep 'incus/devices/container-{variant}1/lxcfs'")
|
||||
|
||||
with subtest("Instance remains running when softDaemonRestart is enabled and service is stopped"):
|
||||
machine.succeed("incus config set instances.lxcfs.per_instance=true")
|
||||
|
||||
machine.succeed(f"incus start container-{variant}1")
|
||||
wait_for_instance(f"container-{variant}1")
|
||||
machine.succeed(f"pgrep -a lxcfs | grep 'incus/devices/container-{variant}1/lxcfs'")
|
||||
|
||||
|
||||
with subtest("container can successfully restart"):
|
||||
machine.succeed(f"incus restart container-{variant}1")
|
||||
wait_for_instance(f"container-{variant}1")
|
||||
|
||||
|
||||
with subtest("container remains running when softDaemonRestart is enabled and service is stopped"):
|
||||
pid = machine.succeed(f"incus info container-{variant}1 | grep 'PID'").split(":")[1].strip()
|
||||
machine.succeed(f"ps {pid}")
|
||||
machine.succeed("systemctl stop incus")
|
||||
machine.succeed(f"ps {pid}")
|
||||
machine.succeed("systemctl start incus")
|
||||
|
||||
with subtest("containers stop with incus-startup.service"):
|
||||
pid = machine.succeed(f"incus info container-{variant}1 | grep 'PID'").split(":")[1].strip()
|
||||
machine.succeed(f"ps {pid}")
|
||||
machine.succeed("systemctl stop incus-startup.service")
|
||||
machine.wait_until_fails(f"ps {pid}", timeout=120)
|
||||
machine.succeed("systemctl start incus-startup.service")
|
||||
|
||||
|
||||
cleanup()
|
||||
''
|
||||
@@ -325,7 +349,7 @@ import ../make-test-python.nix (
|
||||
machine.succeed(f"incus create {alias} vm-{variant}1 --vm --config limits.memory=512MB --config security.secureboot=false")
|
||||
|
||||
|
||||
with subtest("virtual tpm can be configured"):
|
||||
with subtest("virtual-machine software tpm can be configured"):
|
||||
machine.succeed(f"incus config device add vm-{variant}1 vtpm tpm path=/dev/tpm0")
|
||||
|
||||
|
||||
@@ -334,25 +358,30 @@ import ../make-test-python.nix (
|
||||
wait_for_instance(f"vm-{variant}1")
|
||||
|
||||
|
||||
with subtest("incus-agent is started"):
|
||||
with subtest("virtual-machine incus-agent is started"):
|
||||
machine.succeed(f"incus exec vm-{variant}1 systemctl is-active incus-agent")
|
||||
|
||||
|
||||
with subtest("incus-agent has a valid path"):
|
||||
with subtest("virtual-machine incus-agent has a valid path"):
|
||||
machine.succeed(f"incus exec vm-{variant}1 -- bash -c 'true'")
|
||||
|
||||
|
||||
with subtest("Container CPU limits can be managed"):
|
||||
with subtest("virtual-machine CPU limits can be managed"):
|
||||
set_config(f"vm-{variant}1", "limits.cpu 1", restart=True)
|
||||
wait_incus_exec_success(f"vm-{variant}1", "nproc | grep '^1$'", timeout=90)
|
||||
|
||||
|
||||
with subtest("Container CPU limits can be hotplug changed"):
|
||||
with subtest("virtual-machine CPU limits can be hotplug changed"):
|
||||
set_config(f"vm-{variant}1", "limits.cpu 2")
|
||||
wait_incus_exec_success(f"vm-{variant}1", "nproc | grep '^2$'", timeout=15)
|
||||
|
||||
|
||||
with subtest("Instance remains running when softDaemonRestart is enabled and service is stopped"):
|
||||
with subtest("virtual-machine can successfully restart"):
|
||||
machine.succeed(f"incus restart vm-{variant}1")
|
||||
wait_for_instance(f"vm-{variant}1")
|
||||
|
||||
|
||||
with subtest("virtual-machine remains running when softDaemonRestart is enabled and service is stopped"):
|
||||
pid = machine.succeed(f"incus info vm-{variant}1 | grep 'PID'").split(":")[1].strip()
|
||||
machine.succeed(f"ps {pid}")
|
||||
machine.succeed("systemctl stop incus")
|
||||
@@ -360,13 +389,21 @@ import ../make-test-python.nix (
|
||||
machine.succeed("systemctl start incus")
|
||||
|
||||
|
||||
with subtest("virtual-machines stop with incus-startup.service"):
|
||||
pid = machine.succeed(f"incus info vm-{variant}1 | grep 'PID'").split(":")[1].strip()
|
||||
machine.succeed(f"ps {pid}")
|
||||
machine.succeed("systemctl stop incus-startup.service")
|
||||
machine.wait_until_fails(f"ps {pid}", timeout=120)
|
||||
machine.succeed("systemctl start incus-startup.service")
|
||||
|
||||
|
||||
cleanup()
|
||||
''
|
||||
) "" initVariants)
|
||||
+
|
||||
# python
|
||||
''
|
||||
with subtest("Can launch CSM virtual machine"):
|
||||
with subtest("virtual-machine can launch CSM (BIOS)"):
|
||||
machine.succeed("incus init csm --vm --empty -c security.csm=true -c security.secureboot=false")
|
||||
machine.succeed("incus start csm")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user