nixos/virtualisation: factor out common networking options between qemu-vm and nspawn-container
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
# This module defines networking options for virtual machines and containers.
|
||||
# It is intended to be used with systemd-nspawn containers and QEMU virtual machines.
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
inherit (lib) types;
|
||||
|
||||
interfaceType = types.submodule (
|
||||
{ name, ... }:
|
||||
{
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = ''
|
||||
Interface name
|
||||
'';
|
||||
};
|
||||
|
||||
vlan = lib.mkOption {
|
||||
type = types.ints.unsigned;
|
||||
description = ''
|
||||
VLAN to which the network interface is connected.
|
||||
'';
|
||||
};
|
||||
|
||||
assignIP = lib.mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Automatically assign an IP address to the network interface using the same scheme as
|
||||
virtualisation.vlans.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
cfg = config.virtualisation;
|
||||
|
||||
# Convert legacy VLANs to named interfaces.
|
||||
vlansNumbered = lib.listToAttrs (
|
||||
lib.forEach (lib.zipLists cfg.vlans (lib.range 1 255)) (
|
||||
v:
|
||||
let
|
||||
name = "eth${toString v.snd}";
|
||||
in
|
||||
lib.nameValuePair name {
|
||||
inherit name;
|
||||
vlan = v.fst;
|
||||
assignIP = true;
|
||||
}
|
||||
)
|
||||
);
|
||||
in
|
||||
{
|
||||
options = {
|
||||
networking.primaryIPAddress = lib.mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
internal = true;
|
||||
description = "Primary IP address used in /etc/hosts.";
|
||||
};
|
||||
|
||||
networking.primaryIPv6Address = lib.mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
internal = true;
|
||||
description = "Primary IPv6 address used in /etc/hosts.";
|
||||
};
|
||||
|
||||
virtualisation.vlans = lib.mkOption {
|
||||
type = types.listOf types.ints.unsigned;
|
||||
default = if cfg.interfaces == { } then [ 1 ] else [ ];
|
||||
defaultText = lib.literalExpression ''if cfg.interfaces == {} then [ 1 ] else [ ]'';
|
||||
example = [
|
||||
1
|
||||
2
|
||||
];
|
||||
description = ''
|
||||
Virtual networks to which the container or VM is connected. Each number «N» in
|
||||
this list causes the container to have a virtual Ethernet interface
|
||||
attached to a separate virtual network on which it will be assigned IP
|
||||
address `192.168.«N».«M»`, where «M» is the index of this container in
|
||||
the list of containers.
|
||||
'';
|
||||
};
|
||||
|
||||
virtualisation.interfaces = lib.mkOption {
|
||||
default = { };
|
||||
example = {
|
||||
enp1s0.vlan = 1;
|
||||
};
|
||||
description = ''
|
||||
Extra network interfaces to add to the container or VM in addition to the ones
|
||||
created by {option}`virtualisation.vlans`.
|
||||
'';
|
||||
type = types.attrsOf interfaceType;
|
||||
};
|
||||
|
||||
virtualisation.allInterfaces = lib.mkOption {
|
||||
type = types.attrsOf interfaceType;
|
||||
readOnly = true;
|
||||
description = ''
|
||||
All network interfaces for the container or VM. Combines
|
||||
{option}`virtualisation.vlans` and {option}`virtualisation.interfaces`.
|
||||
'';
|
||||
default = vlansNumbered // cfg.interfaces;
|
||||
};
|
||||
};
|
||||
config = {
|
||||
assertions = [
|
||||
(
|
||||
let
|
||||
conflictingKeys = lib.intersectAttrs vlansNumbered cfg.interfaces;
|
||||
in
|
||||
{
|
||||
assertion = conflictingKeys == { };
|
||||
message = ''
|
||||
`virtualisation.vlans` and `virtualisation.interfaces` have conflicting keys: ${lib.concatStringsSep "," (lib.attrNames conflictingKeys)}
|
||||
'';
|
||||
}
|
||||
)
|
||||
(
|
||||
let
|
||||
allInterfaceNames =
|
||||
(lib.mapAttrsToList (k: i: i.name) vlansNumbered)
|
||||
++ (lib.mapAttrsToList (k: i: i.name) cfg.interfaces);
|
||||
in
|
||||
{
|
||||
assertion = lib.allUnique allInterfaceNames;
|
||||
message = ''
|
||||
`virtualisation.vlans` and `virtualisation.interfaces` have conflicting interface names: ${lib.concatStringsSep "," allInterfaceNames}
|
||||
'';
|
||||
}
|
||||
)
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -19,106 +19,11 @@
|
||||
let
|
||||
inherit (lib) types;
|
||||
cfg = config.virtualisation;
|
||||
|
||||
interfaceType = types.submodule (
|
||||
{ name, ... }:
|
||||
{
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = ''
|
||||
Interface name
|
||||
'';
|
||||
};
|
||||
|
||||
vlan = lib.mkOption {
|
||||
type = types.ints.unsigned;
|
||||
description = ''
|
||||
VLAN to which the network interface is connected.
|
||||
'';
|
||||
};
|
||||
|
||||
assignIP = lib.mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Automatically assign an IP address to the network interface using the same scheme as
|
||||
virtualisation.vlans.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
# Convert legacy VLANs to named interfaces.
|
||||
vlansNumbered = lib.listToAttrs (
|
||||
lib.forEach (lib.zipLists cfg.vlans (lib.range 1 255)) (
|
||||
v:
|
||||
let
|
||||
name = "eth${toString v.snd}";
|
||||
in
|
||||
lib.nameValuePair name {
|
||||
inherit name;
|
||||
vlan = v.fst;
|
||||
assignIP = true;
|
||||
}
|
||||
)
|
||||
);
|
||||
in
|
||||
{
|
||||
imports = [ ../guest-networking-options.nix ];
|
||||
|
||||
options = {
|
||||
networking.primaryIPAddress = lib.mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
internal = true;
|
||||
description = "Primary IP address used in /etc/hosts.";
|
||||
};
|
||||
|
||||
networking.primaryIPv6Address = lib.mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
internal = true;
|
||||
description = "Primary IPv6 address used in /etc/hosts.";
|
||||
};
|
||||
|
||||
virtualisation.vlans = lib.mkOption {
|
||||
type = types.listOf types.ints.unsigned;
|
||||
default = if cfg.interfaces == { } then [ 1 ] else [ ];
|
||||
defaultText = lib.literalExpression ''if cfg.interfaces == {} then [ 1 ] else [ ]'';
|
||||
example = [
|
||||
1
|
||||
2
|
||||
];
|
||||
description = ''
|
||||
Virtual networks to which the container is connected. Each number «N» in
|
||||
this list causes the container to have a virtual Ethernet interface
|
||||
attached to a separate virtual network on which it will be assigned IP
|
||||
address `192.168.«N».«M»`, where «M» is the index of this container in
|
||||
the list of containers.
|
||||
'';
|
||||
};
|
||||
|
||||
virtualisation.interfaces = lib.mkOption {
|
||||
default = { };
|
||||
example = {
|
||||
enp1s0.vlan = 1;
|
||||
};
|
||||
description = ''
|
||||
Network interfaces to add to the container.
|
||||
'';
|
||||
type = types.attrsOf interfaceType;
|
||||
};
|
||||
|
||||
virtualisation.allInterfaces = lib.mkOption {
|
||||
type = types.attrsOf interfaceType;
|
||||
readOnly = true;
|
||||
description = ''
|
||||
All network interfaces for the container. Combines
|
||||
{option}`virtualisation.vlans` and {option}`virtualisation.interfaces`.
|
||||
'';
|
||||
default = vlansNumbered // cfg.interfaces;
|
||||
};
|
||||
|
||||
virtualisation.cmdline = lib.mkOption {
|
||||
type = types.listOf types.str;
|
||||
@@ -163,33 +68,6 @@ in
|
||||
};
|
||||
|
||||
config = {
|
||||
assertions = [
|
||||
(
|
||||
let
|
||||
conflictingKeys = lib.intersectAttrs vlansNumbered cfg.interfaces;
|
||||
in
|
||||
{
|
||||
assertion = conflictingKeys == { };
|
||||
message = ''
|
||||
`virtualisation.vlans` and `virtualisation.interfaces` have conflicting keys: ${lib.concatStringsSep "," (lib.attrNames conflictingKeys)}
|
||||
'';
|
||||
}
|
||||
)
|
||||
(
|
||||
let
|
||||
allInterfaceNames =
|
||||
(lib.mapAttrsToList (k: i: i.name) vlansNumbered)
|
||||
++ (lib.mapAttrsToList (k: i: i.name) cfg.interfaces);
|
||||
in
|
||||
{
|
||||
assertion = lib.allUnique allInterfaceNames;
|
||||
message = ''
|
||||
`virtualisation.vlans` and `virtualisation.interfaces` have conflicting interface names: ${lib.concatStringsSep "," allInterfaceNames}
|
||||
'';
|
||||
}
|
||||
)
|
||||
];
|
||||
|
||||
boot.isNspawnContainer = true;
|
||||
|
||||
# Needed since nixpkgs 7fb2f407c01b017737eafc26b065d7f56434a992 removed the getty unit by default.
|
||||
|
||||
@@ -360,58 +360,12 @@ let
|
||||
copyChannel = false;
|
||||
OVMF = cfg.efi.OVMF;
|
||||
};
|
||||
|
||||
interfaceType = types.submodule (
|
||||
{ name, ... }:
|
||||
{
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = ''
|
||||
Interface name
|
||||
'';
|
||||
};
|
||||
|
||||
vlan = mkOption {
|
||||
type = types.ints.unsigned;
|
||||
description = ''
|
||||
VLAN to which the network interface is connected.
|
||||
'';
|
||||
};
|
||||
|
||||
assignIP = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Automatically assign an IP address to the network interface using the same scheme as
|
||||
virtualisation.vlans.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
# Convert legacy VLANs to named interfaces.
|
||||
vlansNumbered = lib.listToAttrs (
|
||||
lib.forEach (lib.zipLists cfg.vlans (lib.range 1 255)) (
|
||||
v:
|
||||
let
|
||||
name = "eth${toString v.snd}";
|
||||
in
|
||||
lib.nameValuePair name {
|
||||
inherit name;
|
||||
vlan = v.fst;
|
||||
assignIP = true;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
../profiles/qemu-guest.nix
|
||||
./disk-size-option.nix
|
||||
./guest-networking-options.nix
|
||||
(mkRenamedOptionModule
|
||||
[
|
||||
"virtualisation"
|
||||
@@ -726,48 +680,6 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
virtualisation.vlans = mkOption {
|
||||
type = types.listOf types.ints.unsigned;
|
||||
default = if config.virtualisation.interfaces == { } then [ 1 ] else [ ];
|
||||
defaultText = lib.literalExpression ''if config.virtualisation.interfaces == {} then [ 1 ] else [ ]'';
|
||||
example = [
|
||||
1
|
||||
2
|
||||
];
|
||||
description = ''
|
||||
Virtual networks to which the VM is connected. Each
|
||||
number «N» in this list causes
|
||||
the VM to have a virtual Ethernet interface attached to a
|
||||
separate virtual network on which it will be assigned IP
|
||||
address
|
||||
`192.168.«N».«M»`,
|
||||
where «M» is the index of this VM
|
||||
in the list of VMs.
|
||||
'';
|
||||
};
|
||||
|
||||
virtualisation.interfaces = mkOption {
|
||||
default = { };
|
||||
example = {
|
||||
enp1s0.vlan = 1;
|
||||
};
|
||||
description = ''
|
||||
Extra network interfaces to add to the VM in addition to the ones
|
||||
created by {option}`virtualisation.vlans`.
|
||||
'';
|
||||
type = types.attrsOf interfaceType;
|
||||
};
|
||||
|
||||
virtualisation.allInterfaces = mkOption {
|
||||
type = types.attrsOf interfaceType;
|
||||
readOnly = true;
|
||||
description = ''
|
||||
All network interfaces for the VM. Combines
|
||||
{option}`virtualisation.vlans` and {option}`virtualisation.interfaces`.
|
||||
'';
|
||||
default = vlansNumbered // cfg.interfaces;
|
||||
};
|
||||
|
||||
virtualisation.writableStore = mkOption {
|
||||
type = types.bool;
|
||||
default = cfg.mountHostNixStore;
|
||||
@@ -790,20 +702,6 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
networking.primaryIPAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
internal = true;
|
||||
description = "Primary IP address used in /etc/hosts.";
|
||||
};
|
||||
|
||||
networking.primaryIPv6Address = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
internal = true;
|
||||
description = "Primary IPv6 address used in /etc/hosts.";
|
||||
};
|
||||
|
||||
virtualisation.host.pkgs = mkOption {
|
||||
type = options.nixpkgs.pkgs.type;
|
||||
default = pkgs;
|
||||
@@ -1286,30 +1184,6 @@ in
|
||||
)
|
||||
)
|
||||
++ [
|
||||
(
|
||||
let
|
||||
conflictingKeys = lib.intersectAttrs vlansNumbered cfg.interfaces;
|
||||
in
|
||||
{
|
||||
assertion = conflictingKeys == { };
|
||||
message = ''
|
||||
`virtualisation.vlans` and `virtualisation.interfaces` have conflicting keys: ${lib.concatStringsSep "," (lib.attrNames conflictingKeys)}
|
||||
'';
|
||||
}
|
||||
)
|
||||
(
|
||||
let
|
||||
allInterfaceNames =
|
||||
(lib.mapAttrsToList (k: i: i.name) vlansNumbered)
|
||||
++ (lib.mapAttrsToList (k: i: i.name) cfg.interfaces);
|
||||
in
|
||||
{
|
||||
assertion = lib.allUnique allInterfaceNames;
|
||||
message = ''
|
||||
`virtualisation.vlans` and `virtualisation.interfaces` have conflicting interface names: ${lib.concatStringsSep "," allInterfaceNames}
|
||||
'';
|
||||
}
|
||||
)
|
||||
{
|
||||
assertion = pkgs.stdenv.hostPlatform.is32bit -> cfg.memorySize < 2047;
|
||||
message = ''
|
||||
|
||||
Reference in New Issue
Block a user