Merge master into staging-next
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib) types;
|
||||
inherit (lib) types mkRemovedOptionModule;
|
||||
|
||||
cfg = config.services.tabby;
|
||||
format = pkgs.formats.toml { };
|
||||
@@ -14,12 +14,26 @@ let
|
||||
};
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
(mkRemovedOptionModule [
|
||||
"settings"
|
||||
"indexInterval"
|
||||
] "These options are now managed within the tabby WebGUI")
|
||||
];
|
||||
options = {
|
||||
services.tabby = {
|
||||
enable = lib.mkEnableOption "Self-hosted AI coding assistant using large language models";
|
||||
|
||||
package = lib.mkPackageOption pkgs "tabby" { };
|
||||
|
||||
host = lib.mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
description = ''
|
||||
Specifies the hostname on which the tabby server HTTP interface listens.
|
||||
'';
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = types.port;
|
||||
default = 11029;
|
||||
@@ -92,29 +106,6 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
settings = lib.mkOption {
|
||||
inherit (format) type;
|
||||
default = { };
|
||||
description = ''
|
||||
Tabby scheduler configuration
|
||||
|
||||
See for more details:
|
||||
> https://tabby.tabbyml.com/docs/configuration/#repository-context-for-code-completion
|
||||
'';
|
||||
example = lib.literalExpression ''
|
||||
settings = {
|
||||
repositories = [
|
||||
{ name = "tabby"; git_url = "https://github.com/TabbyML/tabby.git"; }
|
||||
{ name = "CTranslate2"; git_url = "git@github.com:OpenNMT/CTranslate2.git"; }
|
||||
|
||||
# local directory is also supported, but limited by systemd DynamicUser=1
|
||||
# adding local repositories will need to be done manually
|
||||
{ name = "repository_a"; git_url = "file:///var/lib/tabby/repository_a"; }
|
||||
];
|
||||
};
|
||||
'';
|
||||
};
|
||||
|
||||
usageCollection = lib.mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
@@ -125,22 +116,6 @@ in
|
||||
> https://tabby.tabbyml.com/docs/configuration#usage-collection
|
||||
'';
|
||||
};
|
||||
|
||||
indexInterval = lib.mkOption {
|
||||
type = types.str;
|
||||
default = "5hours";
|
||||
example = "5hours";
|
||||
description = ''
|
||||
Run tabby scheduler to generate the index database at this interval.
|
||||
Updates by default every 5 hours. This value applies to
|
||||
`OnUnitInactiveSec`
|
||||
|
||||
The format is described in
|
||||
{manpage}`systemd.time(7)`.
|
||||
|
||||
To disable running `tabby scheduler --now` updates, set to `"never"`
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -148,7 +123,6 @@ in
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment = {
|
||||
etc."tabby/config.toml".source = format.generate "config.toml" cfg.settings;
|
||||
systemPackages = [ tabbyPackage ];
|
||||
};
|
||||
|
||||
@@ -181,31 +155,10 @@ in
|
||||
serviceConfig = lib.mkMerge [
|
||||
serviceUser
|
||||
{
|
||||
ExecStart = "${lib.getExe tabbyPackage} serve --model ${cfg.model} --port ${toString cfg.port} --device ${tabbyPackage.featureDevice}";
|
||||
ExecStart = "${lib.getExe tabbyPackage} serve --model ${cfg.model} --host ${cfg.host} --port ${toString cfg.port} --device ${tabbyPackage.featureDevice}";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
services.tabby-scheduler = lib.mkIf (cfg.indexInterval != "never") {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
description = "Tabby repository indexing service";
|
||||
after = [ "network.target" ];
|
||||
environment = serviceEnv;
|
||||
preStart = "cp -f /etc/tabby/config.toml \${TABBY_ROOT}/config.toml";
|
||||
serviceConfig = lib.mkMerge [
|
||||
serviceUser
|
||||
{
|
||||
# Type = "oneshot";
|
||||
ExecStart = "${lib.getExe tabbyPackage} scheduler --now";
|
||||
}
|
||||
];
|
||||
};
|
||||
timers.tabby-scheduler = lib.mkIf (cfg.indexInterval != "never") {
|
||||
description = "Update timer for tabby-scheduler";
|
||||
partOf = [ "tabby-scheduler.service" ];
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig.OnUnitInactiveSec = cfg.indexInterval;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -108,6 +108,10 @@ let
|
||||
name = "OVMF_VARS.4MB.ms.fd";
|
||||
path = "${pkgs.OVMFFull.fd}/FV/${ovmf-prefix}_VARS.fd";
|
||||
}
|
||||
{
|
||||
name = "seabios.bin";
|
||||
path = "${pkgs.seabios-qemu}/share/seabios/bios.bin";
|
||||
}
|
||||
];
|
||||
|
||||
environment = lib.mkMerge [
|
||||
|
||||
@@ -467,8 +467,8 @@ in {
|
||||
iftop = handleTest ./iftop.nix {};
|
||||
immich = handleTest ./web-apps/immich.nix {};
|
||||
incron = handleTest ./incron.nix {};
|
||||
incus = pkgs.recurseIntoAttrs (handleTest ./incus { inherit handleTestOn; inherit (pkgs) incus; });
|
||||
incus-lts = pkgs.recurseIntoAttrs (handleTest ./incus { inherit handleTestOn; });
|
||||
incus = pkgs.recurseIntoAttrs (handleTest ./incus { lts = false; });
|
||||
incus-lts = pkgs.recurseIntoAttrs (handleTest ./incus { });
|
||||
influxdb = handleTest ./influxdb.nix {};
|
||||
influxdb2 = handleTest ./influxdb2.nix {};
|
||||
initrd-network-openvpn = handleTestOn [ "x86_64-linux" "i686-linux" ] ./initrd-network-openvpn {};
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
extra ? { },
|
||||
name ? "incus-container",
|
||||
incus ? pkgs.incus-lts,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
releases = import ../../release.nix {
|
||||
configuration = lib.recursiveUpdate {
|
||||
# Building documentation makes the test unnecessarily take a longer time:
|
||||
documentation.enable = lib.mkForce false;
|
||||
|
||||
boot.kernel.sysctl."net.ipv4.ip_forward" = "1";
|
||||
} extra;
|
||||
};
|
||||
|
||||
container-image-metadata = "${
|
||||
releases.incusContainerMeta.${pkgs.stdenv.hostPlatform.system}
|
||||
}/tarball/nixos-image-lxc-*-${pkgs.stdenv.hostPlatform.system}.tar.xz";
|
||||
container-image-rootfs = "${
|
||||
releases.incusContainerImage.${pkgs.stdenv.hostPlatform.system}
|
||||
}/nixos-lxc-image-${pkgs.stdenv.hostPlatform.system}.squashfs";
|
||||
in
|
||||
{
|
||||
inherit name;
|
||||
|
||||
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;
|
||||
package = incus;
|
||||
};
|
||||
};
|
||||
networking.nftables.enable = true;
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
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)
|
||||
|
||||
def check_sysctl(instance):
|
||||
with subtest("systemd sysctl settings are applied"):
|
||||
machine.succeed(f"incus exec {instance} -- systemctl status systemd-sysctl")
|
||||
sysctl = machine.succeed(f"incus exec {instance} -- sysctl net.ipv4.ip_forward").strip().split(" ")[-1]
|
||||
assert "1" == sysctl, f"systemd-sysctl configuration not correctly applied, {sysctl} != 1"
|
||||
|
||||
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} ${container-image-rootfs} --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("resource limits"):
|
||||
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("virtual tpm can be configured"):
|
||||
machine.succeed("incus config device add container vtpm tpm path=/dev/tpm0 pathrm=/dev/tpmrm0")
|
||||
machine.succeed("incus exec container -- test -e /dev/tpm0")
|
||||
machine.succeed("incus exec container -- test -e /dev/tpmrm0")
|
||||
machine.succeed("incus config device remove container vtpm")
|
||||
machine.fail("incus exec container -- test -e /dev/tpm0")
|
||||
|
||||
with subtest("lxc-generator"):
|
||||
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")
|
||||
check_sysctl("container")
|
||||
|
||||
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"
|
||||
|
||||
check_sysctl("container")
|
||||
|
||||
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")
|
||||
|
||||
check_sysctl("container")
|
||||
|
||||
with subtest("softDaemonRestart"):
|
||||
with subtest("Instance remains running when softDaemonRestart is enabled and services is stopped"):
|
||||
pid = machine.succeed("incus info container | grep 'PID'").split(":")[1].strip()
|
||||
machine.succeed(f"ps {pid}")
|
||||
machine.succeed("systemctl stop incus")
|
||||
machine.succeed(f"ps {pid}")
|
||||
'';
|
||||
}
|
||||
)
|
||||
@@ -1,29 +1,42 @@
|
||||
{
|
||||
system ? builtins.currentSystem,
|
||||
config ? { },
|
||||
pkgs ? import ../../.. { inherit system config; },
|
||||
handleTestOn,
|
||||
incus ? pkgs.incus-lts,
|
||||
lts ? true,
|
||||
...
|
||||
}:
|
||||
let
|
||||
incusTest = import ./incus-tests.nix;
|
||||
in
|
||||
{
|
||||
container-legacy-init = import ./container.nix {
|
||||
name = "container-legacy-init";
|
||||
inherit incus system pkgs;
|
||||
all = incusTest {
|
||||
inherit lts;
|
||||
allTests = true;
|
||||
};
|
||||
container-systemd-init = import ./container.nix {
|
||||
name = "container-systemd-init";
|
||||
inherit incus system pkgs;
|
||||
extra = {
|
||||
boot.initrd.systemd.enable = true;
|
||||
};
|
||||
|
||||
container = incusTest {
|
||||
inherit lts;
|
||||
instanceContainer = true;
|
||||
};
|
||||
incusd-options = import ./incusd-options.nix { inherit incus system pkgs; };
|
||||
lxd-to-incus = import ./lxd-to-incus.nix { inherit incus system pkgs; };
|
||||
openvswitch = import ./openvswitch.nix { inherit incus system pkgs; };
|
||||
socket-activated = import ./socket-activated.nix { inherit incus system pkgs; };
|
||||
storage = import ./storage.nix { inherit incus system pkgs; };
|
||||
ui = import ./ui.nix { inherit incus system pkgs; };
|
||||
virtual-machine = handleTestOn [ "x86_64-linux" ] ./virtual-machine.nix {
|
||||
inherit incus system pkgs;
|
||||
|
||||
lvm = incusTest {
|
||||
inherit lts;
|
||||
storageLvm = true;
|
||||
};
|
||||
|
||||
lxd-to-incus = import ./lxd-to-incus.nix { };
|
||||
|
||||
openvswitch = incusTest {
|
||||
inherit lts;
|
||||
networkOvs = true;
|
||||
};
|
||||
|
||||
ui = import ./ui.nix { };
|
||||
|
||||
virtual-machine = incusTest {
|
||||
inherit lts;
|
||||
instanceVm = true;
|
||||
};
|
||||
|
||||
zfs = incusTest {
|
||||
inherit lts;
|
||||
storageLvm = true;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,452 @@
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
|
||||
lts ? true,
|
||||
|
||||
allTests ? false,
|
||||
|
||||
featureUser ? allTests,
|
||||
initLegacy ? true,
|
||||
initSystemd ? true,
|
||||
instanceContainer ? allTests,
|
||||
instanceVm ? allTests,
|
||||
networkOvs ? allTests,
|
||||
storageLvm ? allTests,
|
||||
storageZfs ? allTests,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
releases =
|
||||
init:
|
||||
import ../../release.nix {
|
||||
configuration = {
|
||||
# Building documentation makes the test unnecessarily take a longer time:
|
||||
documentation.enable = lib.mkForce false;
|
||||
|
||||
boot.initrd.systemd.enable = init == "systemd";
|
||||
|
||||
# Arbitrary sysctl modification to ensure containers can update sysctl
|
||||
boot.kernel.sysctl."net.ipv4.ip_forward" = "1";
|
||||
};
|
||||
};
|
||||
|
||||
images = init: {
|
||||
container = {
|
||||
metadata =
|
||||
(releases init).incusContainerMeta.${pkgs.stdenv.hostPlatform.system}
|
||||
+ "/tarball/nixos-image-lxc-*-${pkgs.stdenv.hostPlatform.system}.tar.xz";
|
||||
|
||||
rootfs =
|
||||
(releases init).incusContainerImage.${pkgs.stdenv.hostPlatform.system}
|
||||
+ "/nixos-lxc-image-${pkgs.stdenv.hostPlatform.system}.squashfs";
|
||||
};
|
||||
|
||||
virtual-machine = {
|
||||
metadata =
|
||||
(releases init).incusVirtualMachineImageMeta.${pkgs.stdenv.hostPlatform.system} + "/*/*.tar.xz";
|
||||
disk = (releases init).incusVirtualMachineImage.${pkgs.stdenv.hostPlatform.system} + "/nixos.qcow2";
|
||||
};
|
||||
};
|
||||
|
||||
initVariants = lib.optionals initLegacy [ "legacy" ] ++ lib.optionals initSystemd [ "systemd" ];
|
||||
|
||||
canTestVm = instanceVm && pkgs.stdenv.isLinux && pkgs.stdenv.isx86_64;
|
||||
in
|
||||
{
|
||||
name = "incus" + lib.optionalString lts "-lts";
|
||||
|
||||
meta = {
|
||||
maintainers = lib.teams.lxc.members;
|
||||
};
|
||||
|
||||
nodes.machine = {
|
||||
virtualisation = {
|
||||
cores = 2;
|
||||
memorySize = 2048;
|
||||
diskSize = 12 * 1024;
|
||||
emptyDiskImages = [
|
||||
# vdb for zfs
|
||||
2048
|
||||
# vdc for lvm
|
||||
2048
|
||||
];
|
||||
|
||||
incus = {
|
||||
enable = true;
|
||||
package = if lts then pkgs.incus-lts else pkgs.incus;
|
||||
|
||||
preseed = {
|
||||
networks =
|
||||
[
|
||||
{
|
||||
name = "incusbr0";
|
||||
type = "bridge";
|
||||
config = {
|
||||
"ipv4.address" = "10.0.10.1/24";
|
||||
"ipv4.nat" = "true";
|
||||
};
|
||||
}
|
||||
]
|
||||
++ lib.optionals networkOvs [
|
||||
{
|
||||
name = "ovsbr0";
|
||||
type = "bridge";
|
||||
config = {
|
||||
"bridge.driver" = "openvswitch";
|
||||
"ipv4.address" = "10.0.20.1/24";
|
||||
"ipv4.nat" = "true";
|
||||
};
|
||||
}
|
||||
];
|
||||
profiles = [
|
||||
{
|
||||
name = "default";
|
||||
devices = {
|
||||
eth0 = {
|
||||
name = "eth0";
|
||||
network = "incusbr0";
|
||||
type = "nic";
|
||||
};
|
||||
root = {
|
||||
path = "/";
|
||||
pool = "default";
|
||||
size = "35GiB";
|
||||
type = "disk";
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
storage_pools = [
|
||||
{
|
||||
name = "default";
|
||||
driver = "dir";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
vswitch.enable = networkOvs;
|
||||
};
|
||||
|
||||
boot.supportedFilesystems = lib.optionals storageZfs [ "zfs" ];
|
||||
boot.zfs.forceImportRoot = false;
|
||||
|
||||
environment.systemPackages = [ pkgs.parted ];
|
||||
|
||||
networking.hostId = "01234567";
|
||||
networking.firewall.trustedInterfaces = [ "incusbr0" ];
|
||||
|
||||
services.lvm = {
|
||||
boot.thin.enable = storageLvm;
|
||||
dmeventd.enable = storageLvm;
|
||||
};
|
||||
|
||||
networking.nftables.enable = true;
|
||||
|
||||
users.users.testuser = {
|
||||
isNormalUser = true;
|
||||
shell = pkgs.bashInteractive;
|
||||
group = "incus";
|
||||
uid = 1000;
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
import json
|
||||
|
||||
def wait_for_instance(name: str, project: str = "default"):
|
||||
machine.wait_until_succeeds(f"incus exec {name} --disable-stdin --force-interactive --project {project} -- /run/current-system/sw/bin/systemctl is-system-running")
|
||||
|
||||
|
||||
def wait_incus_exec_success(name: str, command: str, timeout: int = 900, project: str = "default"):
|
||||
def check_command(_) -> bool:
|
||||
status, _ = machine.execute(f"incus exec {name} --disable-stdin --force-interactive --project {project} -- {command}")
|
||||
return status == 0
|
||||
|
||||
with machine.nested(f"Waiting for successful exec: {command}"):
|
||||
retry(check_command, timeout)
|
||||
|
||||
|
||||
def set_config(name: str, config: str, restart: bool = False, unset: bool = False):
|
||||
if restart:
|
||||
machine.succeed(f"incus stop {name}")
|
||||
|
||||
if unset:
|
||||
machine.succeed(f"incus config unset {name} {config}")
|
||||
else:
|
||||
machine.succeed(f"incus config set {name} {config}")
|
||||
|
||||
if restart:
|
||||
machine.succeed(f"incus start {name}")
|
||||
wait_for_instance(name)
|
||||
else:
|
||||
# give a moment to settle
|
||||
machine.sleep(1)
|
||||
|
||||
|
||||
def cleanup():
|
||||
# avoid conflict between preseed and cleanup operations
|
||||
machine.wait_for_unit("incus-preseed.service")
|
||||
|
||||
instances = json.loads(machine.succeed("incus list --format json --all-projects"))
|
||||
with subtest("Stopping all running instances"):
|
||||
for instance in [a for a in instances if a['status'] == 'Running']:
|
||||
machine.execute(f"incus stop --force {instance['name']} --project {instance['project']}")
|
||||
machine.execute(f"incus delete --force {instance['name']} --project {instance['project']}")
|
||||
|
||||
|
||||
def check_sysctl(name: str):
|
||||
with subtest("systemd sysctl settings are applied"):
|
||||
machine.succeed(f"incus exec {name} -- systemctl status systemd-sysctl")
|
||||
sysctl = machine.succeed(f"incus exec {name} -- sysctl net.ipv4.ip_forward").strip().split(" ")[-1]
|
||||
assert "1" == sysctl, f"systemd-sysctl configuration not correctly applied, {sysctl} != 1"
|
||||
|
||||
|
||||
with subtest("Wait for startup"):
|
||||
machine.wait_for_unit("incus.service")
|
||||
machine.wait_for_unit("incus-preseed.service")
|
||||
|
||||
|
||||
with subtest("Verify preseed resources created"):
|
||||
machine.succeed("incus profile show default")
|
||||
machine.succeed("incus network info incusbr0")
|
||||
machine.succeed("incus storage show default")
|
||||
|
||||
''
|
||||
+ lib.optionalString instanceContainer (
|
||||
lib.foldl (
|
||||
acc: variant:
|
||||
acc
|
||||
# python
|
||||
+ ''
|
||||
metadata = "${(images variant).container.metadata}"
|
||||
rootfs = "${(images variant).container.rootfs}"
|
||||
alias = "nixos/container/${variant}"
|
||||
variant = "${variant}"
|
||||
|
||||
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"):
|
||||
machine.succeed(f"incus launch {alias} container-{variant}1")
|
||||
wait_for_instance(f"container-{variant}1")
|
||||
|
||||
|
||||
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("virtual 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")
|
||||
machine.succeed(f"incus config device remove container-{variant}1 vtpm")
|
||||
machine.fail(f"incus exec container-{variant}1 -- test -e /dev/tpm0")
|
||||
|
||||
|
||||
with subtest("lxc-generator"):
|
||||
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")
|
||||
|
||||
check_sysctl(f"container-{variant}1")
|
||||
|
||||
with subtest("lxc-container generator configures nested container"):
|
||||
set_config(f"container-{variant}1", "security.nesting=true", restart=True)
|
||||
|
||||
machine.fail(f"incus exec container-{variant}1 test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf")
|
||||
target = machine.succeed(f"incus exec container-{variant}1 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"
|
||||
|
||||
check_sysctl(f"container-{variant}1")
|
||||
|
||||
with subtest("lxc-container generator configures privileged container"):
|
||||
# Create a new instance for a clean state
|
||||
machine.succeed(f"incus launch {alias} container-{variant}2")
|
||||
wait_for_instance(f"container-{variant}2")
|
||||
|
||||
machine.succeed(f"incus exec container-{variant}2 test -- -e /run/systemd/system/service.d/zzz-lxc-service.conf")
|
||||
|
||||
check_sysctl(f"container-{variant}2")
|
||||
|
||||
|
||||
with subtest("Instance 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")
|
||||
|
||||
|
||||
cleanup()
|
||||
''
|
||||
) "" initVariants
|
||||
)
|
||||
+ lib.optionalString canTestVm (
|
||||
(lib.foldl (
|
||||
acc: variant:
|
||||
acc
|
||||
# python
|
||||
+ ''
|
||||
metadata = "${(images variant).virtual-machine.metadata}"
|
||||
disk = "${(images variant).virtual-machine.disk}"
|
||||
alias = "nixos/virtual-machine/${variant}"
|
||||
variant = "${variant}"
|
||||
|
||||
with subtest("virtual-machine image can be imported"):
|
||||
machine.succeed(f"incus image import {metadata} {disk} --alias {alias}")
|
||||
|
||||
|
||||
with subtest("virtual-machine can be created"):
|
||||
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"):
|
||||
machine.succeed(f"incus config device add vm-{variant}1 vtpm tpm path=/dev/tpm0")
|
||||
|
||||
|
||||
with subtest("virtual-machine can be launched and become available"):
|
||||
machine.succeed(f"incus start vm-{variant}1")
|
||||
wait_for_instance(f"vm-{variant}1")
|
||||
|
||||
|
||||
with subtest("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"):
|
||||
machine.succeed(f"incus exec vm-{variant}1 -- bash -c 'true'")
|
||||
|
||||
|
||||
with subtest("Container 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"):
|
||||
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"):
|
||||
pid = machine.succeed(f"incus info vm-{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")
|
||||
|
||||
|
||||
cleanup()
|
||||
''
|
||||
) "" initVariants)
|
||||
+
|
||||
# python
|
||||
''
|
||||
with subtest("Can launch CSM virtual machine"):
|
||||
machine.succeed("incus init csm --vm --empty -c security.csm=true -c security.secureboot=false")
|
||||
machine.succeed("incus start csm")
|
||||
|
||||
|
||||
cleanup()
|
||||
''
|
||||
)
|
||||
+
|
||||
lib.optionalString featureUser # python
|
||||
''
|
||||
with subtest("incus-user allows restricted access for users"):
|
||||
machine.fail("incus project show user-1000")
|
||||
machine.succeed("su - testuser bash -c 'incus list'")
|
||||
# a project is created dynamically for the user
|
||||
machine.succeed("incus project show user-1000")
|
||||
# users shouldn't be able to list storage pools
|
||||
machine.fail("su - testuser bash -c 'incus storage list'")
|
||||
|
||||
|
||||
with subtest("incus-user allows users to launch instances"):
|
||||
machine.succeed("su - testuser bash -c 'incus image import ${(images "systemd").container.metadata} ${(images "systemd").container.rootfs} --alias nixos'")
|
||||
machine.succeed("su - testuser bash -c 'incus launch nixos instance2'")
|
||||
wait_for_instance("instance2", "user-1000")
|
||||
|
||||
cleanup()
|
||||
''
|
||||
+
|
||||
lib.optionalString networkOvs # python
|
||||
''
|
||||
with subtest("Verify openvswitch bridge"):
|
||||
machine.succeed("incus network info ovsbr0")
|
||||
|
||||
|
||||
with subtest("Verify openvswitch bridge"):
|
||||
machine.succeed("ovs-vsctl br-exists ovsbr0")
|
||||
''
|
||||
|
||||
+
|
||||
lib.optionalString storageZfs # python
|
||||
''
|
||||
with subtest("Verify zfs pool created and usable"):
|
||||
machine.succeed(
|
||||
"zpool status",
|
||||
"parted --script /dev/vdb mklabel gpt",
|
||||
"zpool create zfs_pool /dev/vdb",
|
||||
)
|
||||
|
||||
machine.succeed("incus storage create zfs_pool zfs source=zfs_pool/incus")
|
||||
machine.succeed("zfs list zfs_pool/incus")
|
||||
|
||||
machine.succeed("incus storage volume create zfs_pool test_fs --type filesystem")
|
||||
machine.succeed("incus storage volume create zfs_pool test_vol --type block")
|
||||
|
||||
machine.succeed("incus storage show zfs_pool")
|
||||
machine.succeed("incus storage volume list zfs_pool")
|
||||
machine.succeed("incus storage volume show zfs_pool test_fs")
|
||||
machine.succeed("incus storage volume show zfs_pool test_vol")
|
||||
|
||||
machine.succeed("incus create zfs1 --empty --storage zfs_pool")
|
||||
machine.succeed("incus list zfs1")
|
||||
''
|
||||
|
||||
+
|
||||
lib.optionalString storageLvm # python
|
||||
''
|
||||
with subtest("Verify lvm pool created and usable"):
|
||||
machine.succeed("incus storage create lvm_pool lvm source=/dev/vdc lvm.vg_name=incus_pool")
|
||||
machine.succeed("vgs incus_pool")
|
||||
|
||||
machine.succeed("incus storage volume create lvm_pool test_fs --type filesystem")
|
||||
machine.succeed("incus storage volume create lvm_pool test_vol --type block")
|
||||
|
||||
machine.succeed("incus storage show lvm_pool")
|
||||
|
||||
machine.succeed("incus storage volume list lvm_pool")
|
||||
machine.succeed("incus storage volume show lvm_pool test_fs")
|
||||
machine.succeed("incus storage volume show lvm_pool test_vol")
|
||||
|
||||
machine.succeed("incus create lvm1 --empty --storage zfs_pool")
|
||||
machine.succeed("incus list lvm1")
|
||||
'';
|
||||
}
|
||||
)
|
||||
@@ -1,140 +0,0 @@
|
||||
# this is a set of tests for non-default options. typically the default options
|
||||
# will be handled by the other tests
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
incus ? pkgs.incus-lts,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
releases = import ../../release.nix {
|
||||
configuration = {
|
||||
# Building documentation makes the test unnecessarily take a longer time:
|
||||
documentation.enable = lib.mkForce false;
|
||||
};
|
||||
};
|
||||
|
||||
container-image-metadata = "${
|
||||
releases.incusContainerMeta.${pkgs.stdenv.hostPlatform.system}
|
||||
}/tarball/nixos-image-lxc-*-${pkgs.stdenv.hostPlatform.system}.tar.xz";
|
||||
container-image-rootfs = "${
|
||||
releases.incusContainerImage.${pkgs.stdenv.hostPlatform.system}
|
||||
}/nixos-lxc-image-${pkgs.stdenv.hostPlatform.system}.squashfs";
|
||||
in
|
||||
{
|
||||
name = "incusd-options";
|
||||
|
||||
meta = {
|
||||
maintainers = lib.teams.lxc.members;
|
||||
};
|
||||
|
||||
nodes.machine = {
|
||||
virtualisation = {
|
||||
cores = 2;
|
||||
memorySize = 1024;
|
||||
diskSize = 4096;
|
||||
|
||||
incus = {
|
||||
enable = true;
|
||||
package = incus;
|
||||
softDaemonRestart = false;
|
||||
|
||||
preseed = {
|
||||
networks = [
|
||||
{
|
||||
name = "incusbr0";
|
||||
type = "bridge";
|
||||
config = {
|
||||
"ipv4.address" = "10.0.100.1/24";
|
||||
"ipv4.nat" = "true";
|
||||
};
|
||||
}
|
||||
];
|
||||
profiles = [
|
||||
{
|
||||
name = "default";
|
||||
devices = {
|
||||
eth0 = {
|
||||
name = "eth0";
|
||||
network = "incusbr0";
|
||||
type = "nic";
|
||||
};
|
||||
root = {
|
||||
path = "/";
|
||||
pool = "default";
|
||||
size = "35GiB";
|
||||
type = "disk";
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
storage_pools = [
|
||||
{
|
||||
name = "default";
|
||||
driver = "dir";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
networking.nftables.enable = true;
|
||||
|
||||
users.users.testuser = {
|
||||
isNormalUser = true;
|
||||
shell = pkgs.bashInteractive;
|
||||
group = "incus";
|
||||
uid = 1000;
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
def wait_for_instance(name: str, project: str = "default"):
|
||||
def instance_is_up(_) -> bool:
|
||||
status, _ = machine.execute(f"incus exec {name} --disable-stdin --force-interactive --project {project} -- /run/current-system/sw/bin/systemctl is-system-running")
|
||||
return status == 0
|
||||
|
||||
with machine.nested(f"Waiting for instance {name} to start and be usable"):
|
||||
retry(instance_is_up)
|
||||
|
||||
machine.wait_for_unit("incus.service")
|
||||
machine.wait_for_unit("incus-preseed.service")
|
||||
|
||||
with subtest("Container image can be imported"):
|
||||
machine.succeed("incus image import ${container-image-metadata} ${container-image-rootfs} --alias nixos")
|
||||
|
||||
with subtest("Container can be launched and managed"):
|
||||
machine.succeed("incus launch nixos instance1")
|
||||
wait_for_instance("instance1")
|
||||
machine.succeed("echo true | incus exec instance1 /run/current-system/sw/bin/bash -")
|
||||
|
||||
with subtest("Verify preseed resources created"):
|
||||
machine.succeed("incus profile show default")
|
||||
machine.succeed("incus network info incusbr0")
|
||||
machine.succeed("incus storage show default")
|
||||
|
||||
with subtest("Instance is stopped when softDaemonRestart is disabled and services is stopped"):
|
||||
pid = machine.succeed("incus info instance1 | grep 'PID'").split(":")[1].strip()
|
||||
machine.succeed(f"ps {pid}")
|
||||
machine.succeed("systemctl stop incus")
|
||||
machine.fail(f"ps {pid}")
|
||||
|
||||
with subtest("incus-user allows restricted access for users"):
|
||||
machine.fail("incus project show user-1000")
|
||||
machine.succeed("su - testuser bash -c 'incus list'")
|
||||
# a project is created dynamically for the user
|
||||
machine.succeed("incus project show user-1000")
|
||||
# users shouldn't be able to list storage pools
|
||||
machine.fail("su - testuser bash -c 'incus storage list'")
|
||||
|
||||
with subtest("incus-user allows users to launch instances"):
|
||||
machine.succeed("su - testuser bash -c 'incus image import ${container-image-metadata} ${container-image-rootfs} --alias nixos'")
|
||||
machine.succeed("su - testuser bash -c 'incus launch nixos instance2'")
|
||||
wait_for_instance("instance2", "user-1000")
|
||||
'';
|
||||
}
|
||||
)
|
||||
@@ -1,78 +0,0 @@
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
incus ? pkgs.incus-lts,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
name = "incus-openvswitch";
|
||||
|
||||
meta = {
|
||||
maintainers = lib.teams.lxc.members;
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ lib, ... }:
|
||||
{
|
||||
virtualisation = {
|
||||
incus = {
|
||||
enable = true;
|
||||
package = incus;
|
||||
};
|
||||
|
||||
vswitch.enable = true;
|
||||
incus.preseed = {
|
||||
networks = [
|
||||
{
|
||||
name = "nixostestbr0";
|
||||
type = "bridge";
|
||||
config = {
|
||||
"bridge.driver" = "openvswitch";
|
||||
"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";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
networking.nftables.enable = true;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_unit("incus.service")
|
||||
machine.wait_for_unit("incus-preseed.service")
|
||||
|
||||
with subtest("Verify openvswitch bridge"):
|
||||
machine.succeed("incus network info nixostestbr0")
|
||||
|
||||
with subtest("Verify openvswitch bridge"):
|
||||
machine.succeed("ovs-vsctl br-exists nixostestbr0")
|
||||
'';
|
||||
}
|
||||
)
|
||||
@@ -1,41 +0,0 @@
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
incus ? pkgs.incus-lts,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
name = "incus-socket-activated";
|
||||
|
||||
meta = {
|
||||
maintainers = lib.teams.lxc.members;
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ lib, ... }:
|
||||
{
|
||||
virtualisation = {
|
||||
incus = {
|
||||
enable = true;
|
||||
package = incus;
|
||||
socketActivation = true;
|
||||
};
|
||||
};
|
||||
networking.nftables.enable = 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")
|
||||
'';
|
||||
}
|
||||
)
|
||||
@@ -1,84 +0,0 @@
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
incus ? pkgs.incus-lts,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
name = "incus-storage";
|
||||
|
||||
meta = {
|
||||
maintainers = lib.teams.lxc.members;
|
||||
};
|
||||
|
||||
nodes.machine = {
|
||||
boot.supportedFilesystems = [ "zfs" ];
|
||||
boot.zfs.forceImportRoot = false;
|
||||
|
||||
environment.systemPackages = [ pkgs.parted ];
|
||||
|
||||
networking.hostId = "01234567";
|
||||
networking.nftables.enable = true;
|
||||
|
||||
services.lvm = {
|
||||
boot.thin.enable = true;
|
||||
dmeventd.enable = true;
|
||||
};
|
||||
|
||||
virtualisation = {
|
||||
emptyDiskImages = [
|
||||
2048
|
||||
2048
|
||||
];
|
||||
incus = {
|
||||
enable = true;
|
||||
package = incus;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
machine.wait_for_unit("incus.service")
|
||||
|
||||
with subtest("Verify zfs pool created and usable"):
|
||||
machine.succeed(
|
||||
"zpool status",
|
||||
"parted --script /dev/vdb mklabel gpt",
|
||||
"zpool create zfs_pool /dev/vdb",
|
||||
)
|
||||
|
||||
machine.succeed("incus storage create zfs_pool zfs source=zfs_pool/incus")
|
||||
machine.succeed("zfs list zfs_pool/incus")
|
||||
|
||||
machine.succeed("incus storage volume create zfs_pool test_fs --type filesystem")
|
||||
machine.succeed("incus storage volume create zfs_pool test_vol --type block")
|
||||
|
||||
machine.succeed("incus storage show zfs_pool")
|
||||
machine.succeed("incus storage volume list zfs_pool")
|
||||
machine.succeed("incus storage volume show zfs_pool test_fs")
|
||||
machine.succeed("incus storage volume show zfs_pool test_vol")
|
||||
|
||||
machine.succeed("incus create zfs1 --empty --storage zfs_pool")
|
||||
machine.succeed("incus list zfs1")
|
||||
|
||||
with subtest("Verify lvm pool created and usable"):
|
||||
machine.succeed("incus storage create lvm_pool lvm source=/dev/vdc lvm.vg_name=incus_pool")
|
||||
machine.succeed("vgs incus_pool")
|
||||
|
||||
machine.succeed("incus storage volume create lvm_pool test_fs --type filesystem")
|
||||
machine.succeed("incus storage volume create lvm_pool test_vol --type block")
|
||||
|
||||
machine.succeed("incus storage show lvm_pool")
|
||||
|
||||
machine.succeed("incus storage volume list lvm_pool")
|
||||
machine.succeed("incus storage volume show lvm_pool test_fs")
|
||||
machine.succeed("incus storage volume show lvm_pool test_vol")
|
||||
|
||||
machine.succeed("incus create lvm1 --empty --storage zfs_pool")
|
||||
machine.succeed("incus list lvm1")
|
||||
'';
|
||||
}
|
||||
)
|
||||
@@ -1,95 +0,0 @@
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
incus ? pkgs.incus-lts,
|
||||
...
|
||||
}:
|
||||
|
||||
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.incusVirtualMachineImageMeta.${pkgs.stdenv.hostPlatform.system};
|
||||
vm-image-disk = releases.incusVirtualMachineImage.${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;
|
||||
package = incus;
|
||||
};
|
||||
};
|
||||
networking.nftables.enable = true;
|
||||
};
|
||||
|
||||
testScript = # python
|
||||
''
|
||||
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 created"):
|
||||
machine.succeed("incus create nixos ${instance-name} --vm --config limits.memory=512MB --config security.secureboot=false")
|
||||
|
||||
with subtest("virtual tpm can be configured"):
|
||||
machine.succeed("incus config device add ${instance-name} vtpm tpm path=/dev/tpm0")
|
||||
|
||||
with subtest("virtual-machine can be launched and become available"):
|
||||
machine.succeed("incus start ${instance-name}")
|
||||
with machine.nested("Waiting for instance to start and be usable"):
|
||||
retry(instance_is_up)
|
||||
|
||||
with subtest("incus-agent is started"):
|
||||
machine.succeed("incus exec ${instance-name} systemctl is-active incus-agent")
|
||||
|
||||
with subtest("incus-agent has a valid path"):
|
||||
machine.succeed("incus exec ${instance-name} -- bash -c 'true'")
|
||||
|
||||
with subtest("guest supports cpu hotplug"):
|
||||
machine.succeed("incus config set ${instance-name} limits.cpu=1")
|
||||
count = int(machine.succeed("incus exec ${instance-name} -- nproc").strip())
|
||||
assert count == 1, f"Wrong number of CPUs reported, want: 1, got: {count}"
|
||||
|
||||
machine.succeed("incus config set ${instance-name} limits.cpu=2")
|
||||
count = int(machine.succeed("incus exec ${instance-name} -- nproc").strip())
|
||||
assert count == 2, f"Wrong number of CPUs reported, want: 2, got: {count}"
|
||||
|
||||
with subtest("Instance remains running when softDaemonRestart is enabled and services is stopped"):
|
||||
pid = machine.succeed("incus info ${instance-name} | grep 'PID'").split(":")[1].strip()
|
||||
machine.succeed(f"ps {pid}")
|
||||
machine.succeed("systemctl stop incus")
|
||||
machine.succeed(f"ps {pid}")
|
||||
'';
|
||||
}
|
||||
)
|
||||
@@ -13,12 +13,12 @@ let
|
||||
sha256Hash = "sha256-TfUax9c+RSAzg0GKU3yVYsWL72q4DUB0zZiss4flyqY=";
|
||||
};
|
||||
betaVersion = {
|
||||
version = "2024.2.1.8"; # "Android Studio Ladybug | 2024.2.1 RC 1"
|
||||
sha256Hash = "sha256-Kb/1+g9rIuU/pAO1ue5h0+BU7OCE09QqV9XFoiJxBL4=";
|
||||
version = "2024.2.2.12"; # "Android Studio Ladybug Feature Drop | 2024.2.2 RC 2"
|
||||
sha256Hash = "sha256-zfiTjyD2bMIJ+GVQyg7qUT7306roqYsdRkPECZ/Rdnc=";
|
||||
};
|
||||
latestVersion = {
|
||||
version = "2024.3.1.2"; # "Android Studio Meerkat | 2024.3.1 Canary 2"
|
||||
sha256Hash = "sha256-Oy+BrRvySCAhlYAfaFdGMr//bfPJCfXJix7dp5ryTgg=";
|
||||
version = "2024.3.1.6"; # "Android Studio Meerkat | 2024.3.1 Canary 6"
|
||||
sha256Hash = "sha256-2b2Fp5bjCRT/1f4JUkHkA9PBHM2umwQ9nObevcVYFSw=";
|
||||
};
|
||||
in {
|
||||
# Attributes are named by their corresponding release channels
|
||||
|
||||
@@ -63,8 +63,7 @@ buildGoModule rec {
|
||||
|
||||
passthru = {
|
||||
tests = {
|
||||
incus-legacy-init = nixosTests.incus.container-legacy-init;
|
||||
incus-systemd-init = nixosTests.incus.container-systemd-init;
|
||||
incus-lts = nixosTests.incus-lts.container;
|
||||
};
|
||||
|
||||
generator = callPackage ./generator.nix { inherit src version; };
|
||||
|
||||
@@ -124,7 +124,7 @@ buildGoModule rec {
|
||||
;
|
||||
};
|
||||
|
||||
tests = if lts then nixosTests.incus-lts else nixosTests.incus;
|
||||
tests = if lts then nixosTests.incus-lts.all else nixosTests.incus.all;
|
||||
|
||||
ui = callPackage ./ui.nix { };
|
||||
|
||||
|
||||
@@ -85,8 +85,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
passthru = {
|
||||
tests = {
|
||||
incus-legacy-init = nixosTests.incus.container-legacy-init;
|
||||
incus-systemd-init = nixosTests.incus.container-systemd-init;
|
||||
incus-lts = nixosTests.incus-lts.container;
|
||||
lxc = nixosTests.lxc;
|
||||
lxd = nixosTests.lxd.container;
|
||||
};
|
||||
|
||||
@@ -68,8 +68,7 @@ stdenv.mkDerivation rec {
|
||||
|
||||
passthru = {
|
||||
tests = {
|
||||
incus-container-legacy-init = nixosTests.incus.container-legacy-init;
|
||||
incus-container-systemd-init = nixosTests.incus.container-systemd-init;
|
||||
incus-lts = nixosTests.incus-lts.container;
|
||||
};
|
||||
|
||||
updateScript = nix-update-script { };
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "marwaita-red";
|
||||
version = "23";
|
||||
version = "24";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "darkomarko42";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
hash = "sha256-bJjnKM7ceZyCDP+gsN9NfX+t2El6QFHxskAMrCLIM38=";
|
||||
hash = "sha256-21U3Z53v2PDJ7Io9WZypQiZPM4mjTa3z6W+vE9qNouA=";
|
||||
};
|
||||
|
||||
buildInputs = [
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "misskey";
|
||||
|
||||
version = "2024.10.0";
|
||||
version = "2024.11.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "misskey-dev";
|
||||
repo = finalAttrs.pname;
|
||||
rev = finalAttrs.version;
|
||||
hash = "sha256-cQ8JQnnaS6aX2wZdnimTznHj20hJe0CJ4NESybCk9CU=";
|
||||
hash = "sha256-uei5Ojx39kCbS8DCjHZ5PoEAsqJ5vC6SsFqIEIJ16n8=";
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
|
||||
@@ -38,7 +38,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
# https://nixos.org/manual/nixpkgs/unstable/#javascript-pnpm
|
||||
pnpmDeps = pnpm.fetchDeps {
|
||||
inherit (finalAttrs) pname version src;
|
||||
hash = "sha256-oH4raw+zIQKY+mydteKkY0LqW+13u1408ibm30j1Wss=";
|
||||
hash = "sha256-YWZhm5eKjB6JGP45WC3UrIkr7vuBUI4Q3oiK8Lst3dI=";
|
||||
};
|
||||
|
||||
buildPhase = ''
|
||||
|
||||
@@ -58,14 +58,14 @@ in
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "openvino";
|
||||
version = "2024.5.0";
|
||||
version = "2024.6.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "openvinotoolkit";
|
||||
repo = "openvino";
|
||||
rev = "refs/tags/${version}";
|
||||
fetchSubmodules = true;
|
||||
hash = "sha256-qRa6vTwTEWiSH57HThT2oGhJqhHwFLIqNsU1eCSLwLs=";
|
||||
hash = "sha256-GmbRuFM5L60vQNJLCkva1NzBWWKXK674xjMUpME4o4c=";
|
||||
};
|
||||
|
||||
outputs = [
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
|
||||
cmake,
|
||||
ninja,
|
||||
pkg-config,
|
||||
doctest,
|
||||
|
||||
boost,
|
||||
qt6,
|
||||
nlohmann_json,
|
||||
rtmidi,
|
||||
pugixml,
|
||||
minizip,
|
||||
|
||||
nix-update-script,
|
||||
}:
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "powertabeditor";
|
||||
version = "2.0.21";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "powertab";
|
||||
repo = "powertabeditor";
|
||||
tag = finalAttrs.version;
|
||||
hash = "sha256-mYFguVcF7Xb6rXIIMXAUzRYddlvQDRj7zu6on7GGGeA=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
ninja
|
||||
pkg-config
|
||||
doctest
|
||||
qt6.wrapQtAppsHook
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
boost
|
||||
qt6.qtbase
|
||||
qt6.qttools
|
||||
nlohmann_json
|
||||
rtmidi
|
||||
pugixml
|
||||
minizip
|
||||
];
|
||||
|
||||
passthru.updateScript = nix-update-script { };
|
||||
|
||||
meta = {
|
||||
description = "View and edit guitar tablature";
|
||||
homepage = "https://powertab.github.io/";
|
||||
changelog = "https://github.com/powertab/powertabeditor/blob/refs/tags/${finalAttrs.version}/CHANGELOG.md";
|
||||
license = with lib.licenses; [ gpl3Plus ];
|
||||
platforms = with lib.platforms; linux ++ darwin ++ windows;
|
||||
maintainers = with lib.maintainers; [ pluiedev ];
|
||||
mainProgram = "powertabeditor";
|
||||
};
|
||||
})
|
||||
@@ -10,16 +10,16 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "supabase-cli";
|
||||
version = "2.0.6";
|
||||
version = "2.1.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "supabase";
|
||||
repo = "cli";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-g0p4wonFAveezkM9rym1YETPnJW6Zna4agLUzLkZ7cs=";
|
||||
hash = "sha256-lSmB+UC/dJzrK5C9o+11Hq/ZzbJrzofqaqc0JSy9pxE=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-u4zglwqggZAHswdA9re20Pka+d4fzTiN7VEcbD+AN9c=";
|
||||
vendorHash = "sha256-WygbrpE+FIWBs2Q34EAFlOm458vqnuIy+seZb+4Wf+I=";
|
||||
|
||||
ldflags = [
|
||||
"-s"
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
buildGraalvmNativeImage rec {
|
||||
pname = "yamlscript";
|
||||
version = "0.1.86";
|
||||
version = "0.1.87";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://github.com/yaml/yamlscript/releases/download/${version}/yamlscript.cli-${version}-standalone.jar";
|
||||
hash = "sha256-GFLmEowy89eZDB7cEMTHRKfvGNlZ9CTARxAKLH/GuNg=";
|
||||
hash = "sha256-ItliRQzfVrtRdq5txxj2/JV3d7sHoO0m+ofO6cKrUZ4=";
|
||||
};
|
||||
|
||||
executable = "ys";
|
||||
|
||||
@@ -15,18 +15,18 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "wails";
|
||||
version = "2.9.1";
|
||||
version = "2.9.2";
|
||||
|
||||
src =
|
||||
fetchFromGitHub {
|
||||
owner = "wailsapp";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
hash = "sha256-dtfFeNK7ZfqriK4S0/+Wor1hUJv5kgnRWURVqt+RrNU=";
|
||||
hash = "sha256-Ta7PLxy6ElJwR0yz7oMbmwYyPwduYfoSFWhvsPAJTYs=";
|
||||
}
|
||||
+ "/v2";
|
||||
|
||||
vendorHash = "sha256-15Vo4AKmd9qOF0ea1klTlrXJOUs+IHvsNT2rw4R7ZiU=";
|
||||
vendorHash = "sha256-nnc9+iGVJDcRstEEL9O5UU07NcG9yEQ6kMECDTS9LO8=";
|
||||
|
||||
proxyVendor = true;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user