139 lines
3.9 KiB
Nix
139 lines
3.9 KiB
Nix
# 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 config.virtualisation.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}
|
|
'';
|
|
}
|
|
)
|
|
];
|
|
};
|
|
}
|