Merge pull request #19128 from kampfschlaefer/fix_device_wait_in_containers

Fix device wait in containers
This commit is contained in:
Jörg Thalheim 2016-10-10 11:40:31 +02:00 committed by GitHub
commit 89e4d72fc8
4 changed files with 168 additions and 12 deletions

View File

@ -46,6 +46,23 @@ in
systemd.services =
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 = {
after = [ "network-setup.service" ];
bindsTo = [ "network-setup.service" ];
@ -120,8 +137,8 @@ in
# order before network-setup because the routes that are configured
# there may need ip addresses configured
before = [ "network-setup.service" ];
bindsTo = [ (subsystemDevice i.name) ];
after = [ (subsystemDevice i.name) "network-pre.target" ];
bindsTo = deviceDependency i.name;
after = [ "network-pre.target" ] ++ (deviceDependency i.name);
serviceConfig.Type = "oneshot";
serviceConfig.RemainAfterExit = true;
path = [ pkgs.iproute ];
@ -179,7 +196,7 @@ in
createBridgeDevice = n: v: nameValuePair "${n}-netdev"
(let
deps = map subsystemDevice v.interfaces;
deps = concatLists (map deviceDependency v.interfaces);
in
{ description = "Bridge Interface ${n}";
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
@ -220,7 +237,7 @@ in
createVswitchDevice = n: v: nameValuePair "${n}-netdev"
(let
deps = map subsystemDevice v.interfaces;
deps = concatLists (map deviceDependency v.interfaces);
ofRules = pkgs.writeText "vswitch-${n}-openFlowRules" v.openFlowRules;
in
{ description = "Open vSwitch Interface ${n}";
@ -253,7 +270,7 @@ in
createBondDevice = n: v: nameValuePair "${n}-netdev"
(let
deps = map subsystemDevice v.interfaces;
deps = concatLists (map deviceDependency v.interfaces);
in
{ description = "Bond Interface ${n}";
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
@ -291,7 +308,7 @@ in
createMacvlanDevice = n: v: nameValuePair "${n}-netdev"
(let
deps = [ (subsystemDevice v.interface) ];
deps = deviceDependency v.interface;
in
{ description = "Vlan Interface ${n}";
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
@ -316,7 +333,7 @@ in
createSitDevice = n: v: nameValuePair "${n}-netdev"
(let
deps = optional (v.dev != null) (subsystemDevice v.dev);
deps = optional (v.dev != null) (deviceDependency v.dev);
in
{ description = "6-to-4 Tunnel Interface ${n}";
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
@ -344,7 +361,7 @@ in
createVlanDevice = n: v: nameValuePair "${n}-netdev"
(let
deps = [ (subsystemDevice v.interface) ];
deps = deviceDependency v.interface;
in
{ description = "Vlan Interface ${n}";
wantedBy = [ "network-setup.service" (subsystemDevice n) ];

View File

@ -310,9 +310,9 @@ in
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>
(this derives it from the machine-id that systemd generates) or
<literal>head -c4 /dev/urandom | od -A none -t x4</literal>
'';
};
@ -972,12 +972,17 @@ in
'';
};
} // (listToAttrs (flip map interfaces (i:
let
deviceDependency = if config.boot.isContainer
then []
else [ (subsystemDevice i.name) ];
in
nameValuePair "network-link-${i.name}"
{ description = "Link configuration of ${i.name}";
wantedBy = [ "network-interfaces.target" ];
before = [ "network-interfaces.target" ];
bindsTo = [ (subsystemDevice i.name) ];
after = [ (subsystemDevice i.name) "network-pre.target" ];
bindsTo = deviceDependency;
after = [ "network-pre.target" ] ++ deviceDependency;
path = [ pkgs.iproute ];
serviceConfig = {
Type = "oneshot";

View File

@ -227,6 +227,7 @@ in rec {
tests.containers-bridge = callTest tests/containers-bridge.nix {};
tests.containers-imperative = callTest tests/containers-imperative.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.dnscrypt-proxy = callTest tests/dnscrypt-proxy.nix { system = "x86_64-linux"; };
tests.ecryptfs = callTest tests/ecryptfs.nix {};

View 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");
};
'';
})