Merge pull request #178290 from andrew-hoff/ahh/qemu-interfaces

nixos/virtualisation: add option for explicitly named network interfaces
This commit is contained in:
Ryan Lahfa 2023-01-25 17:32:53 +01:00 committed by GitHub
commit 8803f1da66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 130 additions and 92 deletions

View File

@ -728,6 +728,15 @@
been fixed to allow more than one plugin in the path. been fixed to allow more than one plugin in the path.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
A new option was added to the virtualisation module that
enables specifying explicitly named network interfaces in QEMU
VMs. The existing <literal>virtualisation.vlans</literal> is
still supported for cases where the name of the network
interface is irrelevant.
</para>
</listitem>
</itemizedlist> </itemizedlist>
</section> </section>
</section> </section>

View File

@ -180,3 +180,5 @@ In addition to numerous new and upgraded packages, this release has the followin
- `nixos-version` now accepts `--configuration-revision` to display more information about the current generation revision - `nixos-version` now accepts `--configuration-revision` to display more information about the current generation revision
- The option `services.nomad.extraSettingsPlugins` has been fixed to allow more than one plugin in the path. - The option `services.nomad.extraSettingsPlugins` has been fixed to allow more than one plugin in the path.
- A new option was added to the virtualisation module that enables specifying explicitly named network interfaces in QEMU VMs. The existing `virtualisation.vlans` is still supported for cases where the name of the network interface is irrelevant.

View File

@ -12,7 +12,9 @@ let
}; };
vlans = map (m: m.virtualisation.vlans) (lib.attrValues config.nodes); vlans = map (m: (
m.virtualisation.vlans ++
(lib.mapAttrsToList (_: v: v.vlan) m.virtualisation.interfaces))) (lib.attrValues config.nodes);
vms = map (m: m.system.build.vm) (lib.attrValues config.nodes); vms = map (m: m.system.build.vm) (lib.attrValues config.nodes);
nodeHostNames = nodeHostNames =

View File

@ -18,24 +18,40 @@ let
networkModule = { config, nodes, pkgs, ... }: networkModule = { config, nodes, pkgs, ... }:
let let
interfacesNumbered = zipLists config.virtualisation.vlans (range 1 255); qemu-common = import ../qemu-common.nix { inherit lib pkgs; };
interfaces = forEach interfacesNumbered ({ fst, snd }:
nameValuePair "eth${toString snd}" { # Convert legacy VLANs to named interfaces and merge with explicit interfaces.
ipv4.addresses = vlansNumbered = forEach (zipLists config.virtualisation.vlans (range 1 255)) (v: {
[{ name = "eth${toString v.snd}";
address = "192.168.${toString fst}.${toString config.virtualisation.test.nodeNumber}"; vlan = v.fst;
assignIP = true;
});
explicitInterfaces = lib.mapAttrsToList (n: v: v // { name = n; }) config.virtualisation.interfaces;
interfaces = vlansNumbered ++ explicitInterfaces;
interfacesNumbered = zipLists interfaces (range 1 255);
# Automatically assign IP addresses to requested interfaces.
assignIPs = lib.filter (i: i.assignIP) interfaces;
ipInterfaces = forEach assignIPs (i:
nameValuePair i.name { ipv4.addresses =
[ { address = "192.168.${toString i.vlan}.${toString config.virtualisation.test.nodeNumber}";
prefixLength = 24; prefixLength = 24;
}]; }];
}); });
qemuOptions = lib.flatten (forEach interfacesNumbered ({ fst, snd }:
qemu-common.qemuNICFlags snd fst.vlan config.virtualisation.test.nodeNumber));
udevRules = forEach interfacesNumbered ({ fst, snd }:
"SUBSYSTEM==\"net\",ACTION==\"add\",ATTR{address}==\"${qemu-common.qemuNicMac fst.vlan config.virtualisation.test.nodeNumber}\",NAME=\"${fst.name}\"");
networkConfig = networkConfig =
{ {
networking.hostName = mkDefault config.virtualisation.test.nodeName; networking.hostName = mkDefault config.virtualisation.test.nodeName;
networking.interfaces = listToAttrs interfaces; networking.interfaces = listToAttrs ipInterfaces;
networking.primaryIPAddress = networking.primaryIPAddress =
optionalString (interfaces != [ ]) (head (head interfaces).value.ipv4.addresses).address; optionalString (ipInterfaces != [ ]) (head (head ipInterfaces).value.ipv4.addresses).address;
# Put the IP addresses of all VMs in this machine's # Put the IP addresses of all VMs in this machine's
# /etc/hosts file. If a machine has multiple # /etc/hosts file. If a machine has multiple
@ -51,16 +67,13 @@ let
"${config.networking.hostName}.${config.networking.domain} " + "${config.networking.hostName}.${config.networking.domain} " +
"${config.networking.hostName}\n")); "${config.networking.hostName}\n"));
virtualisation.qemu.options = virtualisation.qemu.options = qemuOptions;
let qemu-common = import ../qemu-common.nix { inherit lib pkgs; }; boot.initrd.services.udev.rules = concatMapStrings (x: x + "\n") udevRules;
in
flip concatMap interfacesNumbered
({ fst, snd }: qemu-common.qemuNICFlags snd fst config.virtualisation.test.nodeNumber);
}; };
in in
{ {
key = "ip-address"; key = "network-interfaces";
config = networkConfig // { config = networkConfig // {
# Expose the networkConfig items for tests like nixops # Expose the networkConfig items for tests like nixops
# that need to recreate the network config. # that need to recreate the network config.

View File

@ -545,7 +545,8 @@ in
virtualisation.vlans = virtualisation.vlans =
mkOption { mkOption {
type = types.listOf types.ints.unsigned; type = types.listOf types.ints.unsigned;
default = [ 1 ]; default = if config.virtualisation.interfaces == {} then [ 1 ] else [ ];
defaultText = lib.literalExpression ''if config.virtualisation.interfaces == {} then [ 1 ] else [ ]'';
example = [ 1 2 ]; example = [ 1 2 ];
description = description =
lib.mdDoc '' lib.mdDoc ''
@ -560,6 +561,35 @@ in
''; '';
}; };
virtualisation.interfaces = mkOption {
default = {};
example = {
enp1s0.vlan = 1;
};
description = lib.mdDoc ''
Network interfaces to add to the VM.
'';
type = with types; attrsOf (submodule {
options = {
vlan = mkOption {
type = types.ints.unsigned;
description = lib.mdDoc ''
VLAN to which the network interface is connected.
'';
};
assignIP = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Automatically assign an IP address to the network interface using the same scheme as
virtualisation.vlans.
'';
};
};
});
};
virtualisation.writableStore = virtualisation.writableStore =
mkOption { mkOption {
type = types.bool; type = types.bool;

View File

@ -93,18 +93,19 @@ let
name = "Static"; name = "Static";
nodes.router = router; nodes.router = router;
nodes.client = { pkgs, ... }: with pkgs.lib; { nodes.client = { pkgs, ... }: with pkgs.lib; {
virtualisation.vlans = [ 1 2 ]; virtualisation.interfaces.enp1s0.vlan = 1;
virtualisation.interfaces.enp2s0.vlan = 2;
networking = { networking = {
useNetworkd = networkd; useNetworkd = networkd;
useDHCP = false; useDHCP = false;
defaultGateway = "192.168.1.1"; defaultGateway = "192.168.1.1";
defaultGateway6 = "fd00:1234:5678:1::1"; defaultGateway6 = "fd00:1234:5678:1::1";
interfaces.eth1.ipv4.addresses = mkOverride 0 [ interfaces.enp1s0.ipv4.addresses = [
{ address = "192.168.1.2"; prefixLength = 24; } { address = "192.168.1.2"; prefixLength = 24; }
{ address = "192.168.1.3"; prefixLength = 32; } { address = "192.168.1.3"; prefixLength = 32; }
{ address = "192.168.1.10"; prefixLength = 32; } { address = "192.168.1.10"; prefixLength = 32; }
]; ];
interfaces.eth2.ipv4.addresses = mkOverride 0 [ interfaces.enp2s0.ipv4.addresses = [
{ address = "192.168.2.2"; prefixLength = 24; } { address = "192.168.2.2"; prefixLength = 24; }
]; ];
}; };
@ -170,12 +171,12 @@ let
# Disable test driver default config # Disable test driver default config
networking.interfaces = lib.mkForce {}; networking.interfaces = lib.mkForce {};
networking.useNetworkd = networkd; networking.useNetworkd = networkd;
virtualisation.vlans = [ 1 ]; virtualisation.interfaces.enp1s0.vlan = 1;
}; };
testScript = '' testScript = ''
start_all() start_all()
client.wait_for_unit("multi-user.target") client.wait_for_unit("multi-user.target")
client.wait_until_succeeds("ip addr show dev eth1 | grep '192.168.1'") client.wait_until_succeeds("ip addr show dev enp1s0 | grep '192.168.1'")
client.shell_interact() client.shell_interact()
client.succeed("ping -c 1 192.168.1.1") client.succeed("ping -c 1 192.168.1.1")
router.succeed("ping -c 1 192.168.1.1") router.succeed("ping -c 1 192.168.1.1")
@ -187,20 +188,13 @@ let
name = "SimpleDHCP"; name = "SimpleDHCP";
nodes.router = router; nodes.router = router;
nodes.client = { pkgs, ... }: with pkgs.lib; { nodes.client = { pkgs, ... }: with pkgs.lib; {
virtualisation.vlans = [ 1 2 ]; virtualisation.interfaces.enp1s0.vlan = 1;
virtualisation.interfaces.enp2s0.vlan = 2;
networking = { networking = {
useNetworkd = networkd; useNetworkd = networkd;
useDHCP = false; useDHCP = false;
interfaces.eth1 = { interfaces.enp1s0.useDHCP = true;
ipv4.addresses = mkOverride 0 [ ]; interfaces.enp2s0.useDHCP = true;
ipv6.addresses = mkOverride 0 [ ];
useDHCP = true;
};
interfaces.eth2 = {
ipv4.addresses = mkOverride 0 [ ];
ipv6.addresses = mkOverride 0 [ ];
useDHCP = true;
};
}; };
}; };
testScript = { ... }: testScript = { ... }:
@ -211,10 +205,10 @@ let
router.wait_for_unit("network-online.target") router.wait_for_unit("network-online.target")
with subtest("Wait until we have an ip address on each interface"): with subtest("Wait until we have an ip address on each interface"):
client.wait_until_succeeds("ip addr show dev eth1 | grep -q '192.168.1'") client.wait_until_succeeds("ip addr show dev enp1s0 | grep -q '192.168.1'")
client.wait_until_succeeds("ip addr show dev eth1 | grep -q 'fd00:1234:5678:1:'") client.wait_until_succeeds("ip addr show dev enp1s0 | grep -q 'fd00:1234:5678:1:'")
client.wait_until_succeeds("ip addr show dev eth2 | grep -q '192.168.2'") client.wait_until_succeeds("ip addr show dev enp2s0 | grep -q '192.168.2'")
client.wait_until_succeeds("ip addr show dev eth2 | grep -q 'fd00:1234:5678:2:'") client.wait_until_succeeds("ip addr show dev enp2s0 | grep -q 'fd00:1234:5678:2:'")
with subtest("Test vlan 1"): with subtest("Test vlan 1"):
client.wait_until_succeeds("ping -c 1 192.168.1.1") client.wait_until_succeeds("ping -c 1 192.168.1.1")
@ -243,16 +237,15 @@ let
name = "OneInterfaceDHCP"; name = "OneInterfaceDHCP";
nodes.router = router; nodes.router = router;
nodes.client = { pkgs, ... }: with pkgs.lib; { nodes.client = { pkgs, ... }: with pkgs.lib; {
virtualisation.vlans = [ 1 2 ]; virtualisation.interfaces.enp1s0.vlan = 1;
virtualisation.interfaces.enp2s0.vlan = 2;
networking = { networking = {
useNetworkd = networkd; useNetworkd = networkd;
useDHCP = false; useDHCP = false;
interfaces.eth1 = { interfaces.enp1s0 = {
ipv4.addresses = mkOverride 0 [ ];
mtu = 1343; mtu = 1343;
useDHCP = true; useDHCP = true;
}; };
interfaces.eth2.ipv4.addresses = mkOverride 0 [ ];
}; };
}; };
testScript = { ... }: testScript = { ... }:
@ -264,10 +257,10 @@ let
router.wait_for_unit("network.target") router.wait_for_unit("network.target")
with subtest("Wait until we have an ip address on each interface"): with subtest("Wait until we have an ip address on each interface"):
client.wait_until_succeeds("ip addr show dev eth1 | grep -q '192.168.1'") client.wait_until_succeeds("ip addr show dev enp1s0 | grep -q '192.168.1'")
with subtest("ensure MTU is set"): with subtest("ensure MTU is set"):
assert "mtu 1343" in client.succeed("ip link show dev eth1") assert "mtu 1343" in client.succeed("ip link show dev enp1s0")
with subtest("Test vlan 1"): with subtest("Test vlan 1"):
client.wait_until_succeeds("ping -c 1 192.168.1.1") client.wait_until_succeeds("ping -c 1 192.168.1.1")
@ -286,16 +279,15 @@ let
}; };
bond = let bond = let
node = address: { pkgs, ... }: with pkgs.lib; { node = address: { pkgs, ... }: with pkgs.lib; {
virtualisation.vlans = [ 1 2 ]; virtualisation.interfaces.enp1s0.vlan = 1;
virtualisation.interfaces.enp2s0.vlan = 2;
networking = { networking = {
useNetworkd = networkd; useNetworkd = networkd;
useDHCP = false; useDHCP = false;
bonds.bond0 = { bonds.bond0 = {
interfaces = [ "eth1" "eth2" ]; interfaces = [ "enp1s0" "enp2s0" ];
driverOptions.mode = "802.3ad"; driverOptions.mode = "802.3ad";
}; };
interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
interfaces.eth2.ipv4.addresses = mkOverride 0 [ ];
interfaces.bond0.ipv4.addresses = mkOverride 0 interfaces.bond0.ipv4.addresses = mkOverride 0
[ { inherit address; prefixLength = 30; } ]; [ { inherit address; prefixLength = 30; } ];
}; };
@ -326,12 +318,11 @@ let
}; };
bridge = let bridge = let
node = { address, vlan }: { pkgs, ... }: with pkgs.lib; { node = { address, vlan }: { pkgs, ... }: with pkgs.lib; {
virtualisation.vlans = [ vlan ]; virtualisation.interfaces.enp1s0.vlan = vlan;
networking = { networking = {
useNetworkd = networkd; useNetworkd = networkd;
useDHCP = false; useDHCP = false;
interfaces.eth1.ipv4.addresses = mkOverride 0 interfaces.enp1s0.ipv4.addresses = [ { inherit address; prefixLength = 24; } ];
[ { inherit address; prefixLength = 24; } ];
}; };
}; };
in { in {
@ -339,11 +330,12 @@ let
nodes.client1 = node { address = "192.168.1.2"; vlan = 1; }; nodes.client1 = node { address = "192.168.1.2"; vlan = 1; };
nodes.client2 = node { address = "192.168.1.3"; vlan = 2; }; nodes.client2 = node { address = "192.168.1.3"; vlan = 2; };
nodes.router = { pkgs, ... }: with pkgs.lib; { nodes.router = { pkgs, ... }: with pkgs.lib; {
virtualisation.vlans = [ 1 2 ]; virtualisation.interfaces.enp1s0.vlan = 1;
virtualisation.interfaces.enp2s0.vlan = 2;
networking = { networking = {
useNetworkd = networkd; useNetworkd = networkd;
useDHCP = false; useDHCP = false;
bridges.bridge.interfaces = [ "eth1" "eth2" ]; bridges.bridge.interfaces = [ "enp1s0" "enp2s0" ];
interfaces.eth1.ipv4.addresses = mkOverride 0 [ ]; interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
interfaces.eth2.ipv4.addresses = mkOverride 0 [ ]; interfaces.eth2.ipv4.addresses = mkOverride 0 [ ];
interfaces.bridge.ipv4.addresses = mkOverride 0 interfaces.bridge.ipv4.addresses = mkOverride 0
@ -377,7 +369,7 @@ let
nodes.router = router; nodes.router = router;
nodes.client = { pkgs, ... }: with pkgs.lib; { nodes.client = { pkgs, ... }: with pkgs.lib; {
environment.systemPackages = [ pkgs.iptables ]; # to debug firewall rules environment.systemPackages = [ pkgs.iptables ]; # to debug firewall rules
virtualisation.vlans = [ 1 ]; virtualisation.interfaces.enp1s0.vlan = 1;
networking = { networking = {
useNetworkd = networkd; useNetworkd = networkd;
useDHCP = false; useDHCP = false;
@ -385,14 +377,9 @@ let
# reverse path filtering rules for the macvlan interface seem # reverse path filtering rules for the macvlan interface seem
# to be incorrect, causing the test to fail. Disable temporarily. # to be incorrect, causing the test to fail. Disable temporarily.
firewall.checkReversePath = false; firewall.checkReversePath = false;
macvlans.macvlan.interface = "eth1"; macvlans.macvlan.interface = "enp1s0";
interfaces.eth1 = { interfaces.enp1s0.useDHCP = true;
ipv4.addresses = mkOverride 0 [ ]; interfaces.macvlan.useDHCP = true;
useDHCP = true;
};
interfaces.macvlan = {
useDHCP = true;
};
}; };
}; };
testScript = { ... }: testScript = { ... }:
@ -404,7 +391,7 @@ let
router.wait_for_unit("network.target") router.wait_for_unit("network.target")
with subtest("Wait until we have an ip address on each interface"): with subtest("Wait until we have an ip address on each interface"):
client.wait_until_succeeds("ip addr show dev eth1 | grep -q '192.168.1'") client.wait_until_succeeds("ip addr show dev enp1s0 | grep -q '192.168.1'")
client.wait_until_succeeds("ip addr show dev macvlan | grep -q '192.168.1'") client.wait_until_succeeds("ip addr show dev macvlan | grep -q '192.168.1'")
with subtest("Print lots of diagnostic information"): with subtest("Print lots of diagnostic information"):
@ -431,23 +418,22 @@ let
fou = { fou = {
name = "foo-over-udp"; name = "foo-over-udp";
nodes.machine = { ... }: { nodes.machine = { ... }: {
virtualisation.vlans = [ 1 ]; virtualisation.interfaces.enp1s0.vlan = 1;
networking = { networking = {
useNetworkd = networkd; useNetworkd = networkd;
useDHCP = false; useDHCP = false;
interfaces.eth1.ipv4.addresses = mkOverride 0 interfaces.enp1s0.ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ];
[ { address = "192.168.1.1"; prefixLength = 24; } ];
fooOverUDP = { fooOverUDP = {
fou1 = { port = 9001; }; fou1 = { port = 9001; };
fou2 = { port = 9002; protocol = 41; }; fou2 = { port = 9002; protocol = 41; };
fou3 = mkIf (!networkd) fou3 = mkIf (!networkd)
{ port = 9003; local.address = "192.168.1.1"; }; { port = 9003; local.address = "192.168.1.1"; };
fou4 = mkIf (!networkd) fou4 = mkIf (!networkd)
{ port = 9004; local = { address = "192.168.1.1"; dev = "eth1"; }; }; { port = 9004; local = { address = "192.168.1.1"; dev = "enp1s0"; }; };
}; };
}; };
systemd.services = { systemd.services = {
fou3-fou-encap.after = optional (!networkd) "network-addresses-eth1.service"; fou3-fou-encap.after = optional (!networkd) "network-addresses-enp1s0.service";
}; };
}; };
testScript = { ... }: testScript = { ... }:
@ -470,20 +456,20 @@ let
"gue": None, "gue": None,
"family": "inet", "family": "inet",
"local": "192.168.1.1", "local": "192.168.1.1",
"dev": "eth1", "dev": "enp1s0",
} in fous, "fou4 exists" } in fous, "fou4 exists"
''; '';
}; };
sit = let sit = let
node = { address4, remote, address6 }: { pkgs, ... }: with pkgs.lib; { node = { address4, remote, address6 }: { pkgs, ... }: with pkgs.lib; {
virtualisation.vlans = [ 1 ]; virtualisation.interfaces.enp1s0.vlan = 1;
networking = { networking = {
useNetworkd = networkd; useNetworkd = networkd;
useDHCP = false; useDHCP = false;
sits.sit = { sits.sit = {
inherit remote; inherit remote;
local = address4; local = address4;
dev = "eth1"; dev = "enp1s0";
}; };
interfaces.eth1.ipv4.addresses = mkOverride 0 interfaces.eth1.ipv4.addresses = mkOverride 0
[ { address = address4; prefixLength = 24; } ]; [ { address = address4; prefixLength = 24; } ];
@ -685,10 +671,10 @@ let
vlan-ping = let vlan-ping = let
baseIP = number: "10.10.10.${number}"; baseIP = number: "10.10.10.${number}";
vlanIP = number: "10.1.1.${number}"; vlanIP = number: "10.1.1.${number}";
baseInterface = "eth1"; baseInterface = "enp1s0";
vlanInterface = "vlan42"; vlanInterface = "vlan42";
node = number: {pkgs, ... }: with pkgs.lib; { node = number: {pkgs, ... }: with pkgs.lib; {
virtualisation.vlans = [ 1 ]; virtualisation.interfaces.enp1s0.vlan = 1;
networking = { networking = {
#useNetworkd = networkd; #useNetworkd = networkd;
useDHCP = false; useDHCP = false;
@ -785,12 +771,12 @@ let
privacy = { privacy = {
name = "Privacy"; name = "Privacy";
nodes.router = { ... }: { nodes.router = { ... }: {
virtualisation.vlans = [ 1 ]; virtualisation.interfaces.enp1s0.vlan = 1;
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = true; boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = true;
networking = { networking = {
useNetworkd = networkd; useNetworkd = networkd;
useDHCP = false; useDHCP = false;
interfaces.eth1.ipv6.addresses = singleton { interfaces.enp1s0.ipv6.addresses = singleton {
address = "fd00:1234:5678:1::1"; address = "fd00:1234:5678:1::1";
prefixLength = 64; prefixLength = 64;
}; };
@ -812,11 +798,11 @@ let
}; };
}; };
nodes.client_with_privacy = { pkgs, ... }: with pkgs.lib; { nodes.client_with_privacy = { pkgs, ... }: with pkgs.lib; {
virtualisation.vlans = [ 1 ]; virtualisation.interfaces.enp1s0.vlan = 1;
networking = { networking = {
useNetworkd = networkd; useNetworkd = networkd;
useDHCP = false; useDHCP = false;
interfaces.eth1 = { interfaces.enp1s0 = {
tempAddress = "default"; tempAddress = "default";
ipv4.addresses = mkOverride 0 [ ]; ipv4.addresses = mkOverride 0 [ ];
ipv6.addresses = mkOverride 0 [ ]; ipv6.addresses = mkOverride 0 [ ];
@ -825,11 +811,11 @@ let
}; };
}; };
nodes.client = { pkgs, ... }: with pkgs.lib; { nodes.client = { pkgs, ... }: with pkgs.lib; {
virtualisation.vlans = [ 1 ]; virtualisation.interfaces.enp1s0.vlan = 1;
networking = { networking = {
useNetworkd = networkd; useNetworkd = networkd;
useDHCP = false; useDHCP = false;
interfaces.eth1 = { interfaces.enp1s0 = {
tempAddress = "enabled"; tempAddress = "enabled";
ipv4.addresses = mkOverride 0 [ ]; ipv4.addresses = mkOverride 0 [ ];
ipv6.addresses = mkOverride 0 [ ]; ipv6.addresses = mkOverride 0 [ ];
@ -847,9 +833,9 @@ let
with subtest("Wait until we have an ip address"): with subtest("Wait until we have an ip address"):
client_with_privacy.wait_until_succeeds( client_with_privacy.wait_until_succeeds(
"ip addr show dev eth1 | grep -q 'fd00:1234:5678:1:'" "ip addr show dev enp1s0 | grep -q 'fd00:1234:5678:1:'"
) )
client.wait_until_succeeds("ip addr show dev eth1 | grep -q 'fd00:1234:5678:1:'") client.wait_until_succeeds("ip addr show dev enp1s0 | grep -q 'fd00:1234:5678:1:'")
with subtest("Test vlan 1"): with subtest("Test vlan 1"):
client_with_privacy.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::1") client_with_privacy.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::1")
@ -947,7 +933,7 @@ let
), "The IPv6 routing table has not been properly cleaned:\n{}".format(ipv6Residue) ), "The IPv6 routing table has not been properly cleaned:\n{}".format(ipv6Residue)
''; '';
}; };
rename = { rename = if networkd then {
name = "RenameInterface"; name = "RenameInterface";
nodes.machine = { pkgs, ... }: { nodes.machine = { pkgs, ... }: {
virtualisation.vlans = [ 1 ]; virtualisation.vlans = [ 1 ];
@ -955,22 +941,18 @@ let
useNetworkd = networkd; useNetworkd = networkd;
useDHCP = false; useDHCP = false;
}; };
} // systemd.network.links."10-custom_name" = {
(if networkd matchConfig.MACAddress = "52:54:00:12:01:01";
then { systemd.network.links."10-custom_name" = { linkConfig.Name = "custom_name";
matchConfig.MACAddress = "52:54:00:12:01:01"; };
linkConfig.Name = "custom_name"; };
};
}
else { boot.initrd.services.udev.rules = ''
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="52:54:00:12:01:01", KERNEL=="eth*", NAME="custom_name"
'';
});
testScript = '' testScript = ''
machine.succeed("udevadm settle") machine.succeed("udevadm settle")
print(machine.succeed("ip link show dev custom_name")) print(machine.succeed("ip link show dev custom_name"))
''; '';
}; } else {
name = "RenameInterface";
testScript = "";
# even with disabled networkd, systemd.network.links should work # even with disabled networkd, systemd.network.links should work
# (as it's handled by udev, not networkd) # (as it's handled by udev, not networkd)
link = { link = {