nixos/lxd: add preseed option

Changed files
+150
nixos
modules
virtualisation
tests
+75
nixos/modules/virtualisation/lxd.nix
···
let
cfg = config.virtualisation.lxd;
+
preseedFormat = pkgs.formats.yaml {};
in {
imports = [
(lib.mkRemovedOptionModule [ "virtualisation" "lxd" "zfsPackage" ] "Override zfs in an overlay instead to override it globally")
···
'';
};
+
preseed = lib.mkOption {
+
type = lib.types.nullOr (lib.types.submodule {
+
freeformType = preseedFormat.type;
+
});
+
+
default = null;
+
+
description = lib.mdDoc ''
+
Configuration for LXD preseed, see
+
<https://documentation.ubuntu.com/lxd/en/latest/howto/initialize/#initialize-preseed>
+
for supported values.
+
+
Changes to this will be re-applied to LXD which will overwrite existing entities or create missing ones,
+
but entities will *not* be removed by preseed.
+
'';
+
+
example = lib.literalExpression ''
+
{
+
networks = [
+
{
+
name = "lxdbr0";
+
type = "bridge";
+
config = {
+
"ipv4.address" = "10.0.100.1/24";
+
"ipv4.nat" = "true";
+
};
+
}
+
];
+
profiles = [
+
{
+
name = "default";
+
devices = {
+
eth0 = {
+
name = "eth0";
+
network = "lxdbr0";
+
type = "nic";
+
};
+
root = {
+
path = "/";
+
pool = "default";
+
size = "35GiB";
+
type = "disk";
+
};
+
};
+
}
+
];
+
storage_pools = [
+
{
+
name = "default";
+
driver = "dir";
+
config = {
+
source = "/var/lib/lxd/storage-pools/default";
+
};
+
}
+
];
+
}
+
'';
+
};
+
startTimeout = lib.mkOption {
type = lib.types.int;
default = 600;
···
# explicitly tell it where the actual configuration files are
Environment = lib.mkIf (config.virtualisation.lxc.lxcfs.enable)
"LXD_LXC_TEMPLATE_CONFIG=${pkgs.lxcfs}/share/lxc/config";
+
};
+
};
+
+
systemd.services.lxd-preseed = lib.mkIf (cfg.preseed != null) {
+
description = "LXD initialization with preseed file";
+
wantedBy = ["multi-user.target"];
+
requires = ["lxd.service"];
+
after = ["lxd.service"];
+
+
script = ''
+
${pkgs.coreutils}/bin/cat ${preseedFormat.generate "lxd-preseed.yaml" cfg.preseed} | ${cfg.package}/bin/lxd init --preseed
+
'';
+
+
serviceConfig = {
+
Type = "oneshot";
};
};
+3
nixos/tests/lxd/container.nix
···
# Wait for lxd to settle
machine.succeed("lxd waitready")
+
# no preseed should mean no service
+
machine.fail("systemctl status lxd-preseed.service")
+
machine.succeed("lxd init --minimal")
machine.succeed(
+1
nixos/tests/lxd/default.nix
···
}: {
container = import ./container.nix {inherit system pkgs;};
nftables = import ./nftables.nix {inherit system pkgs;};
+
preseed = import ./preseed.nix {inherit system pkgs;};
ui = import ./ui.nix {inherit system pkgs;};
virtual-machine = import ./virtual-machine.nix { inherit system pkgs; };
}
+71
nixos/tests/lxd/preseed.nix
···
+
import ../make-test-python.nix ({ pkgs, lib, ... } :
+
+
{
+
name = "lxd-preseed";
+
+
meta = {
+
maintainers = with lib.maintainers; [ adamcstephens ];
+
};
+
+
nodes.machine = { lib, ... }: {
+
virtualisation = {
+
diskSize = 4096;
+
+
lxc.lxcfs.enable = true;
+
lxd.enable = true;
+
+
lxd.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 = ''
+
def wait_for_preseed(_) -> bool:
+
_, output = machine.systemctl("is-active lxd-preseed.service")
+
return ("inactive" in output)
+
+
machine.wait_for_unit("sockets.target")
+
machine.wait_for_unit("lxd.service")
+
with machine.nested("Waiting for preseed to complete"):
+
retry(wait_for_preseed)
+
+
with subtest("Verify preseed resources created"):
+
machine.succeed("lxc profile show nixostest_default")
+
machine.succeed("lxc network info nixostestbr0")
+
machine.succeed("lxc storage show nixostest_pool")
+
'';
+
})