Merge pull request #19128 from kampfschlaefer/fix_device_wait_in_containers
Fix device wait in containers
This commit is contained in:
commit
89e4d72fc8
@ -46,6 +46,23 @@ in
|
|||||||
systemd.services =
|
systemd.services =
|
||||||
let
|
let
|
||||||
|
|
||||||
|
deviceDependency = dev:
|
||||||
|
if (config.boot.isContainer == false)
|
||||||
|
then
|
||||||
|
# Trust udev when not in the container
|
||||||
|
[ (subsystemDevice dev) ]
|
||||||
|
else
|
||||||
|
# When in the container, check whether the interface is built from other definitions
|
||||||
|
if (hasAttr dev cfg.bridges) ||
|
||||||
|
(hasAttr dev cfg.bonds) ||
|
||||||
|
(hasAttr dev cfg.macvlans) ||
|
||||||
|
(hasAttr dev cfg.sits) ||
|
||||||
|
(hasAttr dev cfg.vlans) ||
|
||||||
|
(hasAttr dev cfg.vswitches) ||
|
||||||
|
(hasAttr dev cfg.wlanInterfaces)
|
||||||
|
then [ "${dev}-netdev.service" ]
|
||||||
|
else [];
|
||||||
|
|
||||||
networkLocalCommands = {
|
networkLocalCommands = {
|
||||||
after = [ "network-setup.service" ];
|
after = [ "network-setup.service" ];
|
||||||
bindsTo = [ "network-setup.service" ];
|
bindsTo = [ "network-setup.service" ];
|
||||||
@ -120,8 +137,8 @@ in
|
|||||||
# order before network-setup because the routes that are configured
|
# order before network-setup because the routes that are configured
|
||||||
# there may need ip addresses configured
|
# there may need ip addresses configured
|
||||||
before = [ "network-setup.service" ];
|
before = [ "network-setup.service" ];
|
||||||
bindsTo = [ (subsystemDevice i.name) ];
|
bindsTo = deviceDependency i.name;
|
||||||
after = [ (subsystemDevice i.name) "network-pre.target" ];
|
after = [ "network-pre.target" ] ++ (deviceDependency i.name);
|
||||||
serviceConfig.Type = "oneshot";
|
serviceConfig.Type = "oneshot";
|
||||||
serviceConfig.RemainAfterExit = true;
|
serviceConfig.RemainAfterExit = true;
|
||||||
path = [ pkgs.iproute ];
|
path = [ pkgs.iproute ];
|
||||||
@ -179,7 +196,7 @@ in
|
|||||||
|
|
||||||
createBridgeDevice = n: v: nameValuePair "${n}-netdev"
|
createBridgeDevice = n: v: nameValuePair "${n}-netdev"
|
||||||
(let
|
(let
|
||||||
deps = map subsystemDevice v.interfaces;
|
deps = concatLists (map deviceDependency v.interfaces);
|
||||||
in
|
in
|
||||||
{ description = "Bridge Interface ${n}";
|
{ description = "Bridge Interface ${n}";
|
||||||
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
|
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
|
||||||
@ -220,7 +237,7 @@ in
|
|||||||
|
|
||||||
createVswitchDevice = n: v: nameValuePair "${n}-netdev"
|
createVswitchDevice = n: v: nameValuePair "${n}-netdev"
|
||||||
(let
|
(let
|
||||||
deps = map subsystemDevice v.interfaces;
|
deps = concatLists (map deviceDependency v.interfaces);
|
||||||
ofRules = pkgs.writeText "vswitch-${n}-openFlowRules" v.openFlowRules;
|
ofRules = pkgs.writeText "vswitch-${n}-openFlowRules" v.openFlowRules;
|
||||||
in
|
in
|
||||||
{ description = "Open vSwitch Interface ${n}";
|
{ description = "Open vSwitch Interface ${n}";
|
||||||
@ -253,7 +270,7 @@ in
|
|||||||
|
|
||||||
createBondDevice = n: v: nameValuePair "${n}-netdev"
|
createBondDevice = n: v: nameValuePair "${n}-netdev"
|
||||||
(let
|
(let
|
||||||
deps = map subsystemDevice v.interfaces;
|
deps = concatLists (map deviceDependency v.interfaces);
|
||||||
in
|
in
|
||||||
{ description = "Bond Interface ${n}";
|
{ description = "Bond Interface ${n}";
|
||||||
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
|
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
|
||||||
@ -291,7 +308,7 @@ in
|
|||||||
|
|
||||||
createMacvlanDevice = n: v: nameValuePair "${n}-netdev"
|
createMacvlanDevice = n: v: nameValuePair "${n}-netdev"
|
||||||
(let
|
(let
|
||||||
deps = [ (subsystemDevice v.interface) ];
|
deps = deviceDependency v.interface;
|
||||||
in
|
in
|
||||||
{ description = "Vlan Interface ${n}";
|
{ description = "Vlan Interface ${n}";
|
||||||
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
|
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
|
||||||
@ -316,7 +333,7 @@ in
|
|||||||
|
|
||||||
createSitDevice = n: v: nameValuePair "${n}-netdev"
|
createSitDevice = n: v: nameValuePair "${n}-netdev"
|
||||||
(let
|
(let
|
||||||
deps = optional (v.dev != null) (subsystemDevice v.dev);
|
deps = optional (v.dev != null) (deviceDependency v.dev);
|
||||||
in
|
in
|
||||||
{ description = "6-to-4 Tunnel Interface ${n}";
|
{ description = "6-to-4 Tunnel Interface ${n}";
|
||||||
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
|
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
|
||||||
@ -344,7 +361,7 @@ in
|
|||||||
|
|
||||||
createVlanDevice = n: v: nameValuePair "${n}-netdev"
|
createVlanDevice = n: v: nameValuePair "${n}-netdev"
|
||||||
(let
|
(let
|
||||||
deps = [ (subsystemDevice v.interface) ];
|
deps = deviceDependency v.interface;
|
||||||
in
|
in
|
||||||
{ description = "Vlan Interface ${n}";
|
{ description = "Vlan Interface ${n}";
|
||||||
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
|
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
|
||||||
|
@ -310,9 +310,9 @@ in
|
|||||||
generate a random 32-bit ID using the following commands:
|
generate a random 32-bit ID using the following commands:
|
||||||
|
|
||||||
<literal>cksum /etc/machine-id | while read c rest; do printf "%x" $c; done</literal>
|
<literal>cksum /etc/machine-id | while read c rest; do printf "%x" $c; done</literal>
|
||||||
|
|
||||||
(this derives it from the machine-id that systemd generates) or
|
(this derives it from the machine-id that systemd generates) or
|
||||||
|
|
||||||
<literal>head -c4 /dev/urandom | od -A none -t x4</literal>
|
<literal>head -c4 /dev/urandom | od -A none -t x4</literal>
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -972,12 +972,17 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
} // (listToAttrs (flip map interfaces (i:
|
} // (listToAttrs (flip map interfaces (i:
|
||||||
|
let
|
||||||
|
deviceDependency = if config.boot.isContainer
|
||||||
|
then []
|
||||||
|
else [ (subsystemDevice i.name) ];
|
||||||
|
in
|
||||||
nameValuePair "network-link-${i.name}"
|
nameValuePair "network-link-${i.name}"
|
||||||
{ description = "Link configuration of ${i.name}";
|
{ description = "Link configuration of ${i.name}";
|
||||||
wantedBy = [ "network-interfaces.target" ];
|
wantedBy = [ "network-interfaces.target" ];
|
||||||
before = [ "network-interfaces.target" ];
|
before = [ "network-interfaces.target" ];
|
||||||
bindsTo = [ (subsystemDevice i.name) ];
|
bindsTo = deviceDependency;
|
||||||
after = [ (subsystemDevice i.name) "network-pre.target" ];
|
after = [ "network-pre.target" ] ++ deviceDependency;
|
||||||
path = [ pkgs.iproute ];
|
path = [ pkgs.iproute ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
|
@ -227,6 +227,7 @@ in rec {
|
|||||||
tests.containers-bridge = callTest tests/containers-bridge.nix {};
|
tests.containers-bridge = callTest tests/containers-bridge.nix {};
|
||||||
tests.containers-imperative = callTest tests/containers-imperative.nix {};
|
tests.containers-imperative = callTest tests/containers-imperative.nix {};
|
||||||
tests.containers-extra_veth = callTest tests/containers-extra_veth.nix {};
|
tests.containers-extra_veth = callTest tests/containers-extra_veth.nix {};
|
||||||
|
tests.containers-physical_interfaces = callTest tests/containers-physical_interfaces.nix {};
|
||||||
tests.docker = hydraJob (import tests/docker.nix { system = "x86_64-linux"; });
|
tests.docker = hydraJob (import tests/docker.nix { system = "x86_64-linux"; });
|
||||||
tests.dnscrypt-proxy = callTest tests/dnscrypt-proxy.nix { system = "x86_64-linux"; };
|
tests.dnscrypt-proxy = callTest tests/dnscrypt-proxy.nix { system = "x86_64-linux"; };
|
||||||
tests.ecryptfs = callTest tests/ecryptfs.nix {};
|
tests.ecryptfs = callTest tests/ecryptfs.nix {};
|
||||||
|
133
nixos/tests/containers-physical_interfaces.nix
Normal file
133
nixos/tests/containers-physical_interfaces.nix
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
|
||||||
|
import ./make-test.nix ({ pkgs, ...} : {
|
||||||
|
name = "containers-physical_interfaces";
|
||||||
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
|
maintainers = [ kampfschlaefer ];
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes = {
|
||||||
|
server = { config, pkgs, ... }:
|
||||||
|
{
|
||||||
|
virtualisation.memorySize = 256;
|
||||||
|
virtualisation.vlans = [ 1 ];
|
||||||
|
|
||||||
|
containers.server = {
|
||||||
|
privateNetwork = true;
|
||||||
|
interfaces = [ "eth1" ];
|
||||||
|
|
||||||
|
config = {
|
||||||
|
networking.interfaces.eth1 = {
|
||||||
|
ip4 = [ { address = "10.10.0.1"; prefixLength = 24; } ];
|
||||||
|
};
|
||||||
|
networking.firewall.enable = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
bridged = { config, pkgs, ... }: {
|
||||||
|
virtualisation.memorySize = 128;
|
||||||
|
virtualisation.vlans = [ 1 ];
|
||||||
|
|
||||||
|
containers.bridged = {
|
||||||
|
privateNetwork = true;
|
||||||
|
interfaces = [ "eth1" ];
|
||||||
|
|
||||||
|
config = {
|
||||||
|
networking.bridges.br0.interfaces = [ "eth1" ];
|
||||||
|
networking.interfaces.br0 = {
|
||||||
|
ip4 = [ { address = "10.10.0.2"; prefixLength = 24; } ];
|
||||||
|
};
|
||||||
|
networking.firewall.enable = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
bonded = { config, pkgs, ... }: {
|
||||||
|
virtualisation.memorySize = 128;
|
||||||
|
virtualisation.vlans = [ 1 ];
|
||||||
|
|
||||||
|
containers.bonded = {
|
||||||
|
privateNetwork = true;
|
||||||
|
interfaces = [ "eth1" ];
|
||||||
|
|
||||||
|
config = {
|
||||||
|
networking.bonds.bond0 = {
|
||||||
|
interfaces = [ "eth1" ];
|
||||||
|
mode = "active-backup";
|
||||||
|
};
|
||||||
|
networking.interfaces.bond0 = {
|
||||||
|
ip4 = [ { address = "10.10.0.3"; prefixLength = 24; } ];
|
||||||
|
};
|
||||||
|
networking.firewall.enable = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
bridgedbond = { config, pkgs, ... }: {
|
||||||
|
virtualisation.memorySize = 128;
|
||||||
|
virtualisation.vlans = [ 1 ];
|
||||||
|
|
||||||
|
containers.bridgedbond = {
|
||||||
|
privateNetwork = true;
|
||||||
|
interfaces = [ "eth1" ];
|
||||||
|
|
||||||
|
config = {
|
||||||
|
networking.bonds.bond0 = {
|
||||||
|
interfaces = [ "eth1" ];
|
||||||
|
mode = "active-backup";
|
||||||
|
};
|
||||||
|
networking.bridges.br0.interfaces = [ "bond0" ];
|
||||||
|
networking.interfaces.br0 = {
|
||||||
|
ip4 = [ { address = "10.10.0.4"; prefixLength = 24; } ];
|
||||||
|
};
|
||||||
|
networking.firewall.enable = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testScript = ''
|
||||||
|
startAll;
|
||||||
|
|
||||||
|
subtest "prepare server", sub {
|
||||||
|
$server->waitForUnit("default.target");
|
||||||
|
$server->succeed("ip link show dev eth1 >&2");
|
||||||
|
};
|
||||||
|
|
||||||
|
subtest "simple physical interface", sub {
|
||||||
|
$server->succeed("nixos-container start server");
|
||||||
|
$server->waitForUnit("container\@server");
|
||||||
|
$server->succeed("systemctl -M server list-dependencies network-addresses-eth1.service >&2");
|
||||||
|
|
||||||
|
# The other tests will ping this container on its ip. Here we just check
|
||||||
|
# that the device is present in the container.
|
||||||
|
$server->succeed("nixos-container run server -- ip a show dev eth1 >&2");
|
||||||
|
};
|
||||||
|
|
||||||
|
subtest "physical device in bridge in container", sub {
|
||||||
|
$bridged->waitForUnit("default.target");
|
||||||
|
$bridged->succeed("nixos-container start bridged");
|
||||||
|
$bridged->waitForUnit("container\@bridged");
|
||||||
|
$bridged->succeed("systemctl -M bridged list-dependencies network-addresses-br0.service >&2");
|
||||||
|
$bridged->succeed("systemctl -M bridged status -n 30 -l network-addresses-br0.service");
|
||||||
|
$bridged->succeed("nixos-container run bridged -- ping -w 10 -c 1 -n 10.10.0.1");
|
||||||
|
};
|
||||||
|
|
||||||
|
subtest "physical device in bond in container", sub {
|
||||||
|
$bonded->waitForUnit("default.target");
|
||||||
|
$bonded->succeed("nixos-container start bonded");
|
||||||
|
$bonded->waitForUnit("container\@bonded");
|
||||||
|
$bonded->succeed("systemctl -M bonded list-dependencies network-addresses-bond0 >&2");
|
||||||
|
$bonded->succeed("systemctl -M bonded status -n 30 -l network-addresses-bond0 >&2");
|
||||||
|
$bonded->succeed("nixos-container run bonded -- ping -w 10 -c 1 -n 10.10.0.1");
|
||||||
|
};
|
||||||
|
|
||||||
|
subtest "physical device in bond in bridge in container", sub {
|
||||||
|
$bridgedbond->waitForUnit("default.target");
|
||||||
|
$bridgedbond->succeed("nixos-container start bridgedbond");
|
||||||
|
$bridgedbond->waitForUnit("container\@bridgedbond");
|
||||||
|
$bridgedbond->succeed("systemctl -M bridgedbond list-dependencies network-addresses-br0.service >&2");
|
||||||
|
$bridgedbond->succeed("systemctl -M bridgedbond status -n 30 -l network-addresses-br0.service");
|
||||||
|
$bridgedbond->succeed("nixos-container run bridgedbond -- ping -w 10 -c 1 -n 10.10.0.1");
|
||||||
|
};
|
||||||
|
'';
|
||||||
|
})
|
Loading…
x
Reference in New Issue
Block a user