Merge pull request #13585 (nixos-tests-splitup)

This splits a few NixOS tests (namely Chromium, VirtualBox and the
networking tests) into several subtests that are exposed via attributes.

The networking tests were already split up but they didn't expose an
attribute set of available tests but used a function attribute to
specify the resulting test instead.

A new function callSubTests in nixos/release.nix is now responsible for
gathering subtests, which is also used for the installer and boot tests.
The latter is now placed in a tests.boot.* namespace rather than
"polluting" the tests attribute set with its subtest.

aszlig f70ec0de afa7d845

+558 -572
+2 -2
nixos/release-combined.nix
··· 48 (all nixos.ova) 49 50 #(all nixos.tests.containers) 51 - (all nixos.tests.chromium) 52 (all nixos.tests.firefox) 53 (all nixos.tests.firewall) 54 nixos.tests.gnome3.x86_64-linux # FIXME: i686-linux ··· 63 (all nixos.tests.installer.btrfsSimple) 64 (all nixos.tests.installer.btrfsSubvols) 65 (all nixos.tests.installer.btrfsSubvolDefault) 66 - (all nixos.tests.bootBiosCdrom) 67 (all nixos.tests.ipv6) 68 (all nixos.tests.kde4) 69 #(all nixos.tests.lightdm)
··· 48 (all nixos.ova) 49 50 #(all nixos.tests.containers) 51 + (all nixos.tests.chromium.stable) 52 (all nixos.tests.firefox) 53 (all nixos.tests.firewall) 54 nixos.tests.gnome3.x86_64-linux # FIXME: i686-linux ··· 63 (all nixos.tests.installer.btrfsSimple) 64 (all nixos.tests.installer.btrfsSubvols) 65 (all nixos.tests.installer.btrfsSubvolDefault) 66 + (all nixos.tests.boot.biosCdrom) 67 (all nixos.tests.ipv6) 68 (all nixos.tests.kde4) 69 #(all nixos.tests.lightdm)
+25 -37
nixos/release.nix
··· 13 14 forAllSystems = genAttrs supportedSystems; 15 16 - callTest = fn: args: forAllSystems (system: hydraJob (import fn ({ inherit system; } // args))); 17 18 pkgs = import nixpkgs { system = "x86_64-linux"; }; 19 ··· 215 tests.avahi = callTest tests/avahi.nix {}; 216 tests.bittorrent = callTest tests/bittorrent.nix {}; 217 tests.blivet = callTest tests/blivet.nix {}; 218 tests.cadvisor = hydraJob (import tests/cadvisor.nix { system = "x86_64-linux"; }); 219 - tests.chromium = callTest tests/chromium.nix {}; 220 tests.cjdns = callTest tests/cjdns.nix {}; 221 tests.containers = callTest tests/containers.nix {}; 222 tests.docker = hydraJob (import tests/docker.nix { system = "x86_64-linux"; }); ··· 232 tests.gnome3-gdm = callTest tests/gnome3-gdm.nix {}; 233 tests.grsecurity = callTest tests/grsecurity.nix {}; 234 tests.i3wm = callTest tests/i3wm.nix {}; 235 - tests.installer.grub1 = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).grub1.test); 236 - tests.installer.lvm = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).lvm.test); 237 - tests.installer.luksroot = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).luksroot.test); 238 - tests.installer.separateBoot = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).separateBoot.test); 239 - tests.installer.separateBootFat = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).separateBootFat.test); 240 - tests.installer.simple = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).simple.test); 241 - tests.installer.simpleLabels = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).simpleLabels.test); 242 - tests.installer.simpleProvided = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).simpleProvided.test); 243 - tests.installer.swraid = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).swraid.test); 244 - tests.installer.btrfsSimple = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).btrfsSimple.test); 245 - tests.installer.btrfsSubvols = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).btrfsSubvols.test); 246 - tests.installer.btrfsSubvolDefault = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).btrfsSubvolDefault.test); 247 tests.influxdb = callTest tests/influxdb.nix {}; 248 tests.ipv6 = callTest tests/ipv6.nix {}; 249 tests.jenkins = callTest tests/jenkins.nix {}; ··· 262 tests.mysqlReplication = callTest tests/mysql-replication.nix {}; 263 tests.nat.firewall = callTest tests/nat.nix { withFirewall = true; }; 264 tests.nat.standalone = callTest tests/nat.nix { withFirewall = false; }; 265 - tests.networking.networkd.loopback = callTest tests/networking.nix { networkd = true; test = "loopback"; }; 266 - tests.networking.networkd.static = callTest tests/networking.nix { networkd = true; test = "static"; }; 267 - tests.networking.networkd.dhcpSimple = callTest tests/networking.nix { networkd = true; test = "dhcpSimple"; }; 268 - tests.networking.networkd.dhcpOneIf = callTest tests/networking.nix { networkd = true; test = "dhcpOneIf"; }; 269 - tests.networking.networkd.bond = callTest tests/networking.nix { networkd = true; test = "bond"; }; 270 - tests.networking.networkd.bridge = callTest tests/networking.nix { networkd = true; test = "bridge"; }; 271 - tests.networking.networkd.macvlan = callTest tests/networking.nix { networkd = true; test = "macvlan"; }; 272 - tests.networking.networkd.sit = callTest tests/networking.nix { networkd = true; test = "sit"; }; 273 - tests.networking.networkd.vlan = callTest tests/networking.nix { networkd = true; test = "vlan"; }; 274 - tests.networking.scripted.loopback = callTest tests/networking.nix { networkd = false; test = "loopback"; }; 275 - tests.networking.scripted.static = callTest tests/networking.nix { networkd = false; test = "static"; }; 276 - tests.networking.scripted.dhcpSimple = callTest tests/networking.nix { networkd = false; test = "dhcpSimple"; }; 277 - tests.networking.scripted.dhcpOneIf = callTest tests/networking.nix { networkd = false; test = "dhcpOneIf"; }; 278 - tests.networking.scripted.bond = callTest tests/networking.nix { networkd = false; test = "bond"; }; 279 - tests.networking.scripted.bridge = callTest tests/networking.nix { networkd = false; test = "bridge"; }; 280 - tests.networking.scripted.macvlan = callTest tests/networking.nix { networkd = false; test = "macvlan"; }; 281 - tests.networking.scripted.sit = callTest tests/networking.nix { networkd = false; test = "sit"; }; 282 - tests.networking.scripted.vlan = callTest tests/networking.nix { networkd = false; test = "vlan"; }; 283 # TODO: put in networking.nix after the test becomes more complete 284 tests.networkingProxy = callTest tests/networking-proxy.nix {}; 285 tests.nfs3 = callTest tests/nfs.nix { version = 3; }; ··· 299 tests.simple = callTest tests/simple.nix {}; 300 tests.tomcat = callTest tests/tomcat.nix {}; 301 tests.udisks2 = callTest tests/udisks2.nix {}; 302 - tests.virtualbox = hydraJob (import tests/virtualbox.nix { system = "x86_64-linux"; }); 303 tests.xfce = callTest tests/xfce.nix {}; 304 - tests.bootBiosCdrom = forAllSystems (system: hydraJob (import tests/boot.nix { inherit system; }).bootBiosCdrom); 305 - tests.bootBiosUsb = forAllSystems (system: hydraJob (import tests/boot.nix { inherit system; }).bootBiosUsb); 306 - tests.bootUefiCdrom = forAllSystems (system: hydraJob (import tests/boot.nix { inherit system; }).bootUefiCdrom); 307 - tests.bootUefiUsb = forAllSystems (system: hydraJob (import tests/boot.nix { inherit system; }).bootUefiUsb); 308 309 310 /* Build a bunch of typical closures so that Hydra can keep track of
··· 13 14 forAllSystems = genAttrs supportedSystems; 15 16 + importTest = fn: args: system: import fn ({ 17 + inherit system; 18 + } // args); 19 + 20 + callTest = fn: args: forAllSystems (system: hydraJob (importTest fn args system)); 21 + 22 + callSubTests = fn: args: let 23 + discover = attrs: let 24 + subTests = filterAttrs (const (hasAttr "test")) attrs; 25 + in mapAttrs (const (t: hydraJob t.test)) subTests; 26 + 27 + discoverForSystem = system: mapAttrs (_: test: { 28 + ${system} = test; 29 + }) (discover (importTest fn args system)); 30 + 31 + # If the test is only for a particular system, use only the specified 32 + # system instead of generating attributes for all available systems. 33 + in if args ? system then discover (import fn args) 34 + else foldAttrs (a: b: a // b) {} (map discoverForSystem supportedSystems); 35 36 pkgs = import nixpkgs { system = "x86_64-linux"; }; 37 ··· 233 tests.avahi = callTest tests/avahi.nix {}; 234 tests.bittorrent = callTest tests/bittorrent.nix {}; 235 tests.blivet = callTest tests/blivet.nix {}; 236 + tests.boot = callSubTests tests/boot.nix {}; 237 tests.cadvisor = hydraJob (import tests/cadvisor.nix { system = "x86_64-linux"; }); 238 + tests.chromium = callSubTests tests/chromium.nix {}; 239 tests.cjdns = callTest tests/cjdns.nix {}; 240 tests.containers = callTest tests/containers.nix {}; 241 tests.docker = hydraJob (import tests/docker.nix { system = "x86_64-linux"; }); ··· 251 tests.gnome3-gdm = callTest tests/gnome3-gdm.nix {}; 252 tests.grsecurity = callTest tests/grsecurity.nix {}; 253 tests.i3wm = callTest tests/i3wm.nix {}; 254 + tests.installer = callSubTests tests/installer.nix {}; 255 tests.influxdb = callTest tests/influxdb.nix {}; 256 tests.ipv6 = callTest tests/ipv6.nix {}; 257 tests.jenkins = callTest tests/jenkins.nix {}; ··· 270 tests.mysqlReplication = callTest tests/mysql-replication.nix {}; 271 tests.nat.firewall = callTest tests/nat.nix { withFirewall = true; }; 272 tests.nat.standalone = callTest tests/nat.nix { withFirewall = false; }; 273 + tests.networking.networkd = callSubTests tests/networking.nix { networkd = true; }; 274 + tests.networking.scripted = callSubTests tests/networking.nix { networkd = false; }; 275 # TODO: put in networking.nix after the test becomes more complete 276 tests.networkingProxy = callTest tests/networking-proxy.nix {}; 277 tests.nfs3 = callTest tests/nfs.nix { version = 3; }; ··· 291 tests.simple = callTest tests/simple.nix {}; 292 tests.tomcat = callTest tests/tomcat.nix {}; 293 tests.udisks2 = callTest tests/udisks2.nix {}; 294 + tests.virtualbox = callSubTests tests/virtualbox.nix { system = "x86_64-linux"; }; 295 tests.xfce = callTest tests/xfce.nix {}; 296 297 298 /* Build a bunch of typical closures so that Hydra can keep track of
+4 -4
nixos/tests/boot.nix
··· 30 ''; 31 }; 32 in { 33 - bootBiosCdrom = makeBootTest "bios-cdrom" '' 34 cdrom => glob("${iso}/iso/*.iso") 35 ''; 36 - bootBiosUsb = makeBootTest "bios-usb" '' 37 usb => glob("${iso}/iso/*.iso") 38 ''; 39 - bootUefiCdrom = makeBootTest "uefi-cdrom" '' 40 cdrom => glob("${iso}/iso/*.iso"), 41 bios => '${pkgs.OVMF}/FV/OVMF.fd' 42 ''; 43 - bootUefiUsb = makeBootTest "uefi-usb" '' 44 usb => glob("${iso}/iso/*.iso"), 45 bios => '${pkgs.OVMF}/FV/OVMF.fd' 46 '';
··· 30 ''; 31 }; 32 in { 33 + biosCdrom = makeBootTest "bios-cdrom" '' 34 cdrom => glob("${iso}/iso/*.iso") 35 ''; 36 + biosUsb = makeBootTest "bios-usb" '' 37 usb => glob("${iso}/iso/*.iso") 38 ''; 39 + uefiCdrom = makeBootTest "uefi-cdrom" '' 40 cdrom => glob("${iso}/iso/*.iso"), 41 bios => '${pkgs.OVMF}/FV/OVMF.fd' 42 ''; 43 + uefiUsb = makeBootTest "uefi-usb" '' 44 usb => glob("${iso}/iso/*.iso"), 45 bios => '${pkgs.OVMF}/FV/OVMF.fd' 46 '';
+60 -71
nixos/tests/chromium.nix
··· 1 - import ./make-test.nix ( 2 - { pkgs 3 - , channelMap ? { 4 - stable = pkgs.chromium; 5 - #beta = pkgs.chromiumBeta; 6 - #dev = pkgs.chromiumDev; 7 - } 8 - , ... 9 - }: rec { 10 - name = "chromium"; 11 meta = with pkgs.stdenv.lib.maintainers; { 12 maintainers = [ aszlig ]; 13 }; ··· 16 17 machine.imports = [ ./common/x11.nix ]; 18 machine.virtualisation.memorySize = 2047; 19 20 startupHTML = pkgs.writeText "chromium-startup.html" '' 21 <!DOCTYPE html> ··· 105 closeWin; 106 } 107 108 - sub chromiumTest { 109 - my ($channel, $pkg, $code) = @_; 110 - $machine->waitForX; 111 112 - my $url = "file://${startupHTML}"; 113 - my $args = "--user-data-dir=/tmp/chromium-$channel"; 114 - $machine->execute( 115 - "ulimit -c unlimited; ". 116 - "$pkg/bin/chromium $args \"$url\" & disown" 117 - ); 118 - $machine->waitForText(qr/Type to search or enter a URL to navigate/); 119 - $machine->waitUntilSucceeds("${xdo "check-startup" '' 120 - search --sync --onlyvisible --name "startup done" 121 - # close first start help popup 122 - key -delay 1000 Escape 123 - windowfocus --sync 124 - windowactivate --sync 125 - ''}"); 126 127 - createAndWaitForNewWin; 128 - $machine->screenshot($channel."_emptywin"); 129 - closeWin; 130 131 - $machine->screenshot($channel."_startup_done"); 132 133 - subtest("Chromium $channel", $code); 134 135 - $machine->shutdown; 136 - } 137 138 - for (${let 139 - mkArray = name: pkg: "[\"${name}\", \"${pkg}\"]"; 140 - chanArrays = pkgs.lib.mapAttrsToList mkArray channelMap; 141 - in pkgs.lib.concatStringsSep ", " chanArrays}) { 142 - my ($channel, $pkg) = @$_; 143 - chromiumTest $channel, $pkg, sub { 144 - testNewWin "check sandbox", sub { 145 - $machine->succeed("${xdo "type-url" '' 146 - search --sync --onlyvisible --name "new tab" 147 - windowfocus --sync 148 - type --delay 1000 "chrome://sandbox" 149 - ''}"); 150 151 - $machine->succeed("${xdo "submit-url" '' 152 - search --sync --onlyvisible --name "new tab" 153 - windowfocus --sync 154 - key --delay 1000 Return 155 - ''}"); 156 - 157 - $machine->screenshot($channel."_sandbox"); 158 159 - $machine->succeed("${xdo "submit-url" '' 160 - search --sync --onlyvisible --name "sandbox status" 161 - windowfocus --sync 162 - ''}"); 163 - $machine->succeed("${xdo "submit-url" '' 164 - key --delay 1000 Ctrl+a Ctrl+c 165 - ''}"); 166 167 - my $clipboard = $machine->succeed("${pkgs.xclip}/bin/xclip -o"); 168 - die "sandbox not working properly: $clipboard" 169 - unless $clipboard =~ /namespace sandbox.*yes/mi 170 - && $clipboard =~ /pid namespaces.*yes/mi 171 - && $clipboard =~ /network namespaces.*yes/mi 172 - && $clipboard =~ /seccomp.*sandbox.*yes/mi 173 - && $clipboard =~ /you are adequately sandboxed/mi; 174 - }; 175 - }; 176 - } 177 ''; 178 - })
··· 1 + { system ? builtins.currentSystem }: 2 + 3 + with import ../lib/testing.nix { inherit system; }; 4 + with pkgs.lib; 5 + 6 + mapAttrs (channel: chromiumPkg: makeTest rec { 7 + name = "chromium-${channel}"; 8 meta = with pkgs.stdenv.lib.maintainers; { 9 maintainers = [ aszlig ]; 10 }; ··· 13 14 machine.imports = [ ./common/x11.nix ]; 15 machine.virtualisation.memorySize = 2047; 16 + machine.environment.systemPackages = [ chromiumPkg ]; 17 18 startupHTML = pkgs.writeText "chromium-startup.html" '' 19 <!DOCTYPE html> ··· 103 closeWin; 104 } 105 106 + $machine->waitForX; 107 108 + my $url = "file://${startupHTML}"; 109 + my $args = "--user-data-dir=/tmp/chromium-${channel}"; 110 + $machine->execute( 111 + "ulimit -c unlimited; ". 112 + "chromium $args \"$url\" & disown" 113 + ); 114 + $machine->waitForText(qr/Type to search or enter a URL to navigate/); 115 + $machine->waitUntilSucceeds("${xdo "check-startup" '' 116 + search --sync --onlyvisible --name "startup done" 117 + # close first start help popup 118 + key -delay 1000 Escape 119 + windowfocus --sync 120 + windowactivate --sync 121 + ''}"); 122 123 + createAndWaitForNewWin; 124 + $machine->screenshot("empty_windows"); 125 + closeWin; 126 127 + $machine->screenshot("startup_done"); 128 129 + testNewWin "check sandbox", sub { 130 + $machine->succeed("${xdo "type-url" '' 131 + search --sync --onlyvisible --name "new tab" 132 + windowfocus --sync 133 + type --delay 1000 "chrome://sandbox" 134 + ''}"); 135 136 + $machine->succeed("${xdo "submit-url" '' 137 + search --sync --onlyvisible --name "new tab" 138 + windowfocus --sync 139 + key --delay 1000 Return 140 + ''}"); 141 142 + $machine->screenshot("sandbox_info"); 143 144 + $machine->succeed("${xdo "submit-url" '' 145 + search --sync --onlyvisible --name "sandbox status" 146 + windowfocus --sync 147 + ''}"); 148 + $machine->succeed("${xdo "submit-url" '' 149 + key --delay 1000 Ctrl+a Ctrl+c 150 + ''}"); 151 152 + my $clipboard = $machine->succeed("${pkgs.xclip}/bin/xclip -o"); 153 + die "sandbox not working properly: $clipboard" 154 + unless $clipboard =~ /namespace sandbox.*yes/mi 155 + && $clipboard =~ /pid namespaces.*yes/mi 156 + && $clipboard =~ /network namespaces.*yes/mi 157 + && $clipboard =~ /seccomp.*sandbox.*yes/mi 158 + && $clipboard =~ /you are adequately sandboxed/mi; 159 + }; 160 161 + $machine->shutdown; 162 ''; 163 + }) { 164 + stable = pkgs.chromium; 165 + beta = pkgs.chromiumBeta; 166 + dev = pkgs.chromiumDev; 167 + }
+355 -350
nixos/tests/networking.nix
··· 1 - import ./make-test.nix ({ pkgs, networkd, test, ... }: 2 - let 3 - router = { config, pkgs, ... }: 4 - with pkgs.lib; 5 - let 6 - vlanIfs = range 1 (length config.virtualisation.vlans); 7 - in { 8 - virtualisation.vlans = [ 1 2 3 ]; 9 networking = { 10 - useDHCP = false; 11 useNetworkd = networkd; 12 firewall.allowPing = true; 13 - interfaces = mkOverride 0 (listToAttrs (flip map vlanIfs (n: 14 - nameValuePair "eth${toString n}" { 15 - ipAddress = "192.168.${toString n}.1"; 16 - prefixLength = 24; 17 - }))); 18 - }; 19 - services.dhcpd = { 20 - enable = true; 21 - interfaces = map (n: "eth${toString n}") vlanIfs; 22 - extraConfig = '' 23 - option subnet-mask 255.255.255.0; 24 - '' + flip concatMapStrings vlanIfs (n: '' 25 - subnet 192.168.${toString n}.0 netmask 255.255.255.0 { 26 - option broadcast-address 192.168.${toString n}.255; 27 - option routers 192.168.${toString n}.1; 28 - range 192.168.${toString n}.2 192.168.${toString n}.254; 29 - } 30 - ''); 31 }; 32 }; 33 - testCases = { 34 - loopback = { 35 - name = "Loopback"; 36 - machine.networking.useNetworkd = networkd; 37 - testScript = '' 38 startAll; 39 - $machine->waitForUnit("network-interfaces.target"); 40 - $machine->waitForUnit("network.target"); 41 - $machine->succeed("ip addr show lo | grep -q 'inet 127.0.0.1/8 '"); 42 - $machine->succeed("ip addr show lo | grep -q 'inet6 ::1/128 '"); 43 - ''; 44 - }; 45 - static = { 46 - name = "Static"; 47 - nodes.router = router; 48 - nodes.client = { config, pkgs, ... }: with pkgs.lib; { 49 - virtualisation.vlans = [ 1 2 ]; 50 - networking = { 51 - useNetworkd = networkd; 52 - firewall.allowPing = true; 53 - useDHCP = false; 54 - defaultGateway = "192.168.1.1"; 55 - interfaces.eth1.ip4 = mkOverride 0 [ 56 - { address = "192.168.1.2"; prefixLength = 24; } 57 - { address = "192.168.1.3"; prefixLength = 32; } 58 - { address = "192.168.1.10"; prefixLength = 32; } 59 - ]; 60 - interfaces.eth2.ip4 = mkOverride 0 [ 61 - { address = "192.168.2.2"; prefixLength = 24; } 62 - ]; 63 - }; 64 - }; 65 - testScript = { nodes, ... }: 66 - '' 67 - startAll; 68 69 - $client->waitForUnit("network-interfaces.target"); 70 - $client->waitForUnit("network.target"); 71 - $router->waitForUnit("network-interfaces.target"); 72 - $router->waitForUnit("network.target"); 73 74 - # Make sure dhcpcd is not started 75 - $client->fail("systemctl status dhcpcd.service"); 76 77 - # Test vlan 1 78 - $client->waitUntilSucceeds("ping -c 1 192.168.1.1"); 79 - $client->waitUntilSucceeds("ping -c 1 192.168.1.2"); 80 - $client->waitUntilSucceeds("ping -c 1 192.168.1.3"); 81 - $client->waitUntilSucceeds("ping -c 1 192.168.1.10"); 82 83 - $router->waitUntilSucceeds("ping -c 1 192.168.1.1"); 84 - $router->waitUntilSucceeds("ping -c 1 192.168.1.2"); 85 - $router->waitUntilSucceeds("ping -c 1 192.168.1.3"); 86 - $router->waitUntilSucceeds("ping -c 1 192.168.1.10"); 87 88 - # Test vlan 2 89 - $client->waitUntilSucceeds("ping -c 1 192.168.2.1"); 90 - $client->waitUntilSucceeds("ping -c 1 192.168.2.2"); 91 92 - $router->waitUntilSucceeds("ping -c 1 192.168.2.1"); 93 - $router->waitUntilSucceeds("ping -c 1 192.168.2.2"); 94 95 - # Test default gateway 96 - $router->waitUntilSucceeds("ping -c 1 192.168.3.1"); 97 - $client->waitUntilSucceeds("ping -c 1 192.168.3.1"); 98 - ''; 99 - }; 100 - dhcpSimple = { 101 - name = "SimpleDHCP"; 102 - nodes.router = router; 103 - nodes.client = { config, pkgs, ... }: with pkgs.lib; { 104 - virtualisation.vlans = [ 1 2 ]; 105 - networking = { 106 - useNetworkd = networkd; 107 - firewall.allowPing = true; 108 - useDHCP = true; 109 - interfaces.eth1.ip4 = mkOverride 0 [ ]; 110 - interfaces.eth2.ip4 = mkOverride 0 [ ]; 111 - }; 112 }; 113 - testScript = { nodes, ... }: 114 - '' 115 - startAll; 116 117 - $client->waitForUnit("network-interfaces.target"); 118 - $client->waitForUnit("network.target"); 119 - $router->waitForUnit("network-interfaces.target"); 120 - $router->waitForUnit("network.target"); 121 122 - # Wait until we have an ip address on each interface 123 - $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'"); 124 - $client->waitUntilSucceeds("ip addr show dev eth2 | grep -q '192.168.2'"); 125 126 - # Test vlan 1 127 - $client->waitUntilSucceeds("ping -c 1 192.168.1.1"); 128 - $client->waitUntilSucceeds("ping -c 1 192.168.1.2"); 129 130 - $router->waitUntilSucceeds("ping -c 1 192.168.1.1"); 131 - $router->waitUntilSucceeds("ping -c 1 192.168.1.2"); 132 133 - # Test vlan 2 134 - $client->waitUntilSucceeds("ping -c 1 192.168.2.1"); 135 - $client->waitUntilSucceeds("ping -c 1 192.168.2.2"); 136 137 - $router->waitUntilSucceeds("ping -c 1 192.168.2.1"); 138 - $router->waitUntilSucceeds("ping -c 1 192.168.2.2"); 139 - ''; 140 - }; 141 - dhcpOneIf = { 142 - name = "OneInterfaceDHCP"; 143 - nodes.router = router; 144 - nodes.client = { config, pkgs, ... }: with pkgs.lib; { 145 - virtualisation.vlans = [ 1 2 ]; 146 - networking = { 147 - useNetworkd = networkd; 148 - firewall.allowPing = true; 149 - useDHCP = false; 150 - interfaces.eth1 = { 151 - ip4 = mkOverride 0 [ ]; 152 - useDHCP = true; 153 - }; 154 - interfaces.eth2.ip4 = mkOverride 0 [ ]; 155 }; 156 }; 157 - testScript = { nodes, ... }: 158 - '' 159 - startAll; 160 161 - # Wait for networking to come up 162 - $client->waitForUnit("network-interfaces.target"); 163 - $client->waitForUnit("network.target"); 164 - $router->waitForUnit("network-interfaces.target"); 165 - $router->waitForUnit("network.target"); 166 167 - # Wait until we have an ip address on each interface 168 - $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'"); 169 170 - # Test vlan 1 171 - $client->waitUntilSucceeds("ping -c 1 192.168.1.1"); 172 - $client->waitUntilSucceeds("ping -c 1 192.168.1.2"); 173 174 - $router->waitUntilSucceeds("ping -c 1 192.168.1.1"); 175 - $router->waitUntilSucceeds("ping -c 1 192.168.1.2"); 176 177 - # Test vlan 2 178 - $client->waitUntilSucceeds("ping -c 1 192.168.2.1"); 179 - $client->fail("ping -c 1 192.168.2.2"); 180 181 - $router->waitUntilSucceeds("ping -c 1 192.168.2.1"); 182 - $router->fail("ping -c 1 192.168.2.2"); 183 - ''; 184 - }; 185 - bond = let 186 - node = address: { config, pkgs, ... }: with pkgs.lib; { 187 - virtualisation.vlans = [ 1 2 ]; 188 - networking = { 189 - useNetworkd = networkd; 190 - firewall.allowPing = true; 191 - useDHCP = false; 192 - bonds.bond = { 193 - mode = "balance-rr"; 194 - interfaces = [ "eth1" "eth2" ]; 195 - }; 196 - interfaces.eth1.ip4 = mkOverride 0 [ ]; 197 - interfaces.eth2.ip4 = mkOverride 0 [ ]; 198 - interfaces.bond.ip4 = mkOverride 0 199 - [ { inherit address; prefixLength = 30; } ]; 200 }; 201 }; 202 - in { 203 - name = "Bond"; 204 - nodes.client1 = node "192.168.1.1"; 205 - nodes.client2 = node "192.168.1.2"; 206 - testScript = { nodes, ... }: 207 - '' 208 - startAll; 209 210 - # Wait for networking to come up 211 - $client1->waitForUnit("network-interfaces.target"); 212 - $client1->waitForUnit("network.target"); 213 - $client2->waitForUnit("network-interfaces.target"); 214 - $client2->waitForUnit("network.target"); 215 216 - # Test bonding 217 - $client1->waitUntilSucceeds("ping -c 2 192.168.1.1"); 218 - $client1->waitUntilSucceeds("ping -c 2 192.168.1.2"); 219 220 - $client2->waitUntilSucceeds("ping -c 2 192.168.1.1"); 221 - $client2->waitUntilSucceeds("ping -c 2 192.168.1.2"); 222 - ''; 223 - }; 224 - bridge = let 225 - node = { address, vlan }: { config, pkgs, ... }: with pkgs.lib; { 226 - virtualisation.vlans = [ vlan ]; 227 - networking = { 228 - useNetworkd = networkd; 229 - firewall.allowPing = true; 230 - useDHCP = false; 231 - interfaces.eth1.ip4 = mkOverride 0 232 - [ { inherit address; prefixLength = 24; } ]; 233 - }; 234 }; 235 - in { 236 - name = "Bridge"; 237 - nodes.client1 = node { address = "192.168.1.2"; vlan = 1; }; 238 - nodes.client2 = node { address = "192.168.1.3"; vlan = 2; }; 239 - nodes.router = { config, pkgs, ... }: with pkgs.lib; { 240 - virtualisation.vlans = [ 1 2 ]; 241 - networking = { 242 - useNetworkd = networkd; 243 - firewall.allowPing = true; 244 - useDHCP = false; 245 - bridges.bridge.interfaces = [ "eth1" "eth2" ]; 246 - interfaces.eth1.ip4 = mkOverride 0 [ ]; 247 - interfaces.eth2.ip4 = mkOverride 0 [ ]; 248 - interfaces.bridge.ip4 = mkOverride 0 249 - [ { address = "192.168.1.1"; prefixLength = 24; } ]; 250 - }; 251 }; 252 - testScript = { nodes, ... }: 253 - '' 254 - startAll; 255 256 - # Wait for networking to come up 257 - $client1->waitForUnit("network-interfaces.target"); 258 - $client1->waitForUnit("network.target"); 259 - $client2->waitForUnit("network-interfaces.target"); 260 - $client2->waitForUnit("network.target"); 261 - $router->waitForUnit("network-interfaces.target"); 262 - $router->waitForUnit("network.target"); 263 264 - # Test bridging 265 - $client1->waitUntilSucceeds("ping -c 1 192.168.1.1"); 266 - $client1->waitUntilSucceeds("ping -c 1 192.168.1.2"); 267 - $client1->waitUntilSucceeds("ping -c 1 192.168.1.3"); 268 269 - $client2->waitUntilSucceeds("ping -c 1 192.168.1.1"); 270 - $client2->waitUntilSucceeds("ping -c 1 192.168.1.2"); 271 - $client2->waitUntilSucceeds("ping -c 1 192.168.1.3"); 272 273 - $router->waitUntilSucceeds("ping -c 1 192.168.1.1"); 274 - $router->waitUntilSucceeds("ping -c 1 192.168.1.2"); 275 - $router->waitUntilSucceeds("ping -c 1 192.168.1.3"); 276 - ''; 277 - }; 278 - macvlan = { 279 - name = "MACVLAN"; 280 - nodes.router = router; 281 - nodes.client = { config, pkgs, ... }: with pkgs.lib; { 282 - virtualisation.vlans = [ 1 ]; 283 - networking = { 284 - useNetworkd = networkd; 285 - firewall.allowPing = true; 286 - useDHCP = true; 287 - macvlans.macvlan.interface = "eth1"; 288 - interfaces.eth1.ip4 = mkOverride 0 [ ]; 289 - }; 290 }; 291 - testScript = { nodes, ... }: 292 - '' 293 - startAll; 294 295 - # Wait for networking to come up 296 - $client->waitForUnit("network-interfaces.target"); 297 - $client->waitForUnit("network.target"); 298 - $router->waitForUnit("network-interfaces.target"); 299 - $router->waitForUnit("network.target"); 300 301 - # Wait until we have an ip address on each interface 302 - $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'"); 303 - $client->waitUntilSucceeds("ip addr show dev macvlan | grep -q '192.168.1'"); 304 305 - # Print diagnosting information 306 - $router->succeed("ip addr >&2"); 307 - $client->succeed("ip addr >&2"); 308 309 - # Test macvlan creates routable ips 310 - $client->waitUntilSucceeds("ping -c 1 192.168.1.1"); 311 - $client->waitUntilSucceeds("ping -c 1 192.168.1.2"); 312 - $client->waitUntilSucceeds("ping -c 1 192.168.1.3"); 313 314 - $router->waitUntilSucceeds("ping -c 1 192.168.1.1"); 315 - $router->waitUntilSucceeds("ping -c 1 192.168.1.2"); 316 - $router->waitUntilSucceeds("ping -c 1 192.168.1.3"); 317 - ''; 318 - }; 319 - sit = let 320 - node = { address4, remote, address6 }: { config, pkgs, ... }: with pkgs.lib; { 321 - virtualisation.vlans = [ 1 ]; 322 - networking = { 323 - useNetworkd = networkd; 324 - firewall.enable = false; 325 - useDHCP = false; 326 - sits.sit = { 327 - inherit remote; 328 - local = address4; 329 - dev = "eth1"; 330 - }; 331 - interfaces.eth1.ip4 = mkOverride 0 332 - [ { address = address4; prefixLength = 24; } ]; 333 - interfaces.sit.ip6 = mkOverride 0 334 - [ { address = address6; prefixLength = 64; } ]; 335 }; 336 }; 337 - in { 338 - name = "Sit"; 339 - nodes.client1 = node { address4 = "192.168.1.1"; remote = "192.168.1.2"; address6 = "fc00::1"; }; 340 - nodes.client2 = node { address4 = "192.168.1.2"; remote = "192.168.1.1"; address6 = "fc00::2"; }; 341 - testScript = { nodes, ... }: 342 - '' 343 - startAll; 344 345 - # Wait for networking to be configured 346 - $client1->waitForUnit("network-interfaces.target"); 347 - $client1->waitForUnit("network.target"); 348 - $client2->waitForUnit("network-interfaces.target"); 349 - $client2->waitForUnit("network.target"); 350 351 - # Print diagnostic information 352 - $client1->succeed("ip addr >&2"); 353 - $client2->succeed("ip addr >&2"); 354 355 - # Test ipv6 356 - $client1->waitUntilSucceeds("ping6 -c 1 fc00::1"); 357 - $client1->waitUntilSucceeds("ping6 -c 1 fc00::2"); 358 359 - $client2->waitUntilSucceeds("ping6 -c 1 fc00::1"); 360 - $client2->waitUntilSucceeds("ping6 -c 1 fc00::2"); 361 - ''; 362 - }; 363 - vlan = let 364 - node = address: { config, pkgs, ... }: with pkgs.lib; { 365 - #virtualisation.vlans = [ 1 ]; 366 - networking = { 367 - useNetworkd = networkd; 368 - firewall.allowPing = true; 369 - useDHCP = false; 370 - vlans.vlan = { 371 - id = 1; 372 - interface = "eth0"; 373 - }; 374 - interfaces.eth0.ip4 = mkOverride 0 [ ]; 375 - interfaces.eth1.ip4 = mkOverride 0 [ ]; 376 - interfaces.vlan.ip4 = mkOverride 0 377 - [ { inherit address; prefixLength = 24; } ]; 378 }; 379 }; 380 - in { 381 - name = "vlan"; 382 - nodes.client1 = node "192.168.1.1"; 383 - nodes.client2 = node "192.168.1.2"; 384 - testScript = { nodes, ... }: 385 - '' 386 - startAll; 387 388 - # Wait for networking to be configured 389 - $client1->waitForUnit("network-interfaces.target"); 390 - $client1->waitForUnit("network.target"); 391 - $client2->waitForUnit("network-interfaces.target"); 392 - $client2->waitForUnit("network.target"); 393 394 - # Test vlan is setup 395 - $client1->succeed("ip addr show dev vlan >&2"); 396 - $client2->succeed("ip addr show dev vlan >&2"); 397 - ''; 398 - }; 399 - }; 400 - case = testCases.${test}; 401 - in case // { 402 - name = "${case.name}-Networking-${if networkd then "Networkd" else "Scripted"}"; 403 - meta = with pkgs.stdenv.lib.maintainers; { 404 - maintainers = [ wkennington ]; 405 }; 406 - })
··· 1 + { system ? builtins.currentSystem, networkd }: 2 + 3 + with import ../lib/testing.nix { inherit system; }; 4 + with pkgs.lib; 5 + 6 + let 7 + router = { config, pkgs, ... }: 8 + with pkgs.lib; 9 + let 10 + vlanIfs = range 1 (length config.virtualisation.vlans); 11 + in { 12 + virtualisation.vlans = [ 1 2 3 ]; 13 + networking = { 14 + useDHCP = false; 15 + useNetworkd = networkd; 16 + firewall.allowPing = true; 17 + interfaces = mkOverride 0 (listToAttrs (flip map vlanIfs (n: 18 + nameValuePair "eth${toString n}" { 19 + ipAddress = "192.168.${toString n}.1"; 20 + prefixLength = 24; 21 + }))); 22 + }; 23 + services.dhcpd = { 24 + enable = true; 25 + interfaces = map (n: "eth${toString n}") vlanIfs; 26 + extraConfig = '' 27 + option subnet-mask 255.255.255.0; 28 + '' + flip concatMapStrings vlanIfs (n: '' 29 + subnet 192.168.${toString n}.0 netmask 255.255.255.0 { 30 + option broadcast-address 192.168.${toString n}.255; 31 + option routers 192.168.${toString n}.1; 32 + range 192.168.${toString n}.2 192.168.${toString n}.254; 33 + } 34 + ''); 35 + }; 36 + }; 37 + 38 + testCases = { 39 + loopback = { 40 + name = "Loopback"; 41 + machine.networking.useNetworkd = networkd; 42 + testScript = '' 43 + startAll; 44 + $machine->waitForUnit("network-interfaces.target"); 45 + $machine->waitForUnit("network.target"); 46 + $machine->succeed("ip addr show lo | grep -q 'inet 127.0.0.1/8 '"); 47 + $machine->succeed("ip addr show lo | grep -q 'inet6 ::1/128 '"); 48 + ''; 49 + }; 50 + static = { 51 + name = "Static"; 52 + nodes.router = router; 53 + nodes.client = { config, pkgs, ... }: with pkgs.lib; { 54 + virtualisation.vlans = [ 1 2 ]; 55 networking = { 56 useNetworkd = networkd; 57 firewall.allowPing = true; 58 + useDHCP = false; 59 + defaultGateway = "192.168.1.1"; 60 + interfaces.eth1.ip4 = mkOverride 0 [ 61 + { address = "192.168.1.2"; prefixLength = 24; } 62 + { address = "192.168.1.3"; prefixLength = 32; } 63 + { address = "192.168.1.10"; prefixLength = 32; } 64 + ]; 65 + interfaces.eth2.ip4 = mkOverride 0 [ 66 + { address = "192.168.2.2"; prefixLength = 24; } 67 + ]; 68 }; 69 }; 70 + testScript = { nodes, ... }: 71 + '' 72 startAll; 73 74 + $client->waitForUnit("network-interfaces.target"); 75 + $client->waitForUnit("network.target"); 76 + $router->waitForUnit("network-interfaces.target"); 77 + $router->waitForUnit("network.target"); 78 79 + # Make sure dhcpcd is not started 80 + $client->fail("systemctl status dhcpcd.service"); 81 82 + # Test vlan 1 83 + $client->waitUntilSucceeds("ping -c 1 192.168.1.1"); 84 + $client->waitUntilSucceeds("ping -c 1 192.168.1.2"); 85 + $client->waitUntilSucceeds("ping -c 1 192.168.1.3"); 86 + $client->waitUntilSucceeds("ping -c 1 192.168.1.10"); 87 88 + $router->waitUntilSucceeds("ping -c 1 192.168.1.1"); 89 + $router->waitUntilSucceeds("ping -c 1 192.168.1.2"); 90 + $router->waitUntilSucceeds("ping -c 1 192.168.1.3"); 91 + $router->waitUntilSucceeds("ping -c 1 192.168.1.10"); 92 93 + # Test vlan 2 94 + $client->waitUntilSucceeds("ping -c 1 192.168.2.1"); 95 + $client->waitUntilSucceeds("ping -c 1 192.168.2.2"); 96 97 + $router->waitUntilSucceeds("ping -c 1 192.168.2.1"); 98 + $router->waitUntilSucceeds("ping -c 1 192.168.2.2"); 99 100 + # Test default gateway 101 + $router->waitUntilSucceeds("ping -c 1 192.168.3.1"); 102 + $client->waitUntilSucceeds("ping -c 1 192.168.3.1"); 103 + ''; 104 + }; 105 + dhcpSimple = { 106 + name = "SimpleDHCP"; 107 + nodes.router = router; 108 + nodes.client = { config, pkgs, ... }: with pkgs.lib; { 109 + virtualisation.vlans = [ 1 2 ]; 110 + networking = { 111 + useNetworkd = networkd; 112 + firewall.allowPing = true; 113 + useDHCP = true; 114 + interfaces.eth1.ip4 = mkOverride 0 [ ]; 115 + interfaces.eth2.ip4 = mkOverride 0 [ ]; 116 }; 117 + }; 118 + testScript = { nodes, ... }: 119 + '' 120 + startAll; 121 122 + $client->waitForUnit("network-interfaces.target"); 123 + $client->waitForUnit("network.target"); 124 + $router->waitForUnit("network-interfaces.target"); 125 + $router->waitForUnit("network.target"); 126 127 + # Wait until we have an ip address on each interface 128 + $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'"); 129 + $client->waitUntilSucceeds("ip addr show dev eth2 | grep -q '192.168.2'"); 130 131 + # Test vlan 1 132 + $client->waitUntilSucceeds("ping -c 1 192.168.1.1"); 133 + $client->waitUntilSucceeds("ping -c 1 192.168.1.2"); 134 135 + $router->waitUntilSucceeds("ping -c 1 192.168.1.1"); 136 + $router->waitUntilSucceeds("ping -c 1 192.168.1.2"); 137 138 + # Test vlan 2 139 + $client->waitUntilSucceeds("ping -c 1 192.168.2.1"); 140 + $client->waitUntilSucceeds("ping -c 1 192.168.2.2"); 141 142 + $router->waitUntilSucceeds("ping -c 1 192.168.2.1"); 143 + $router->waitUntilSucceeds("ping -c 1 192.168.2.2"); 144 + ''; 145 + }; 146 + dhcpOneIf = { 147 + name = "OneInterfaceDHCP"; 148 + nodes.router = router; 149 + nodes.client = { config, pkgs, ... }: with pkgs.lib; { 150 + virtualisation.vlans = [ 1 2 ]; 151 + networking = { 152 + useNetworkd = networkd; 153 + firewall.allowPing = true; 154 + useDHCP = false; 155 + interfaces.eth1 = { 156 + ip4 = mkOverride 0 [ ]; 157 + useDHCP = true; 158 }; 159 + interfaces.eth2.ip4 = mkOverride 0 [ ]; 160 }; 161 + }; 162 + testScript = { nodes, ... }: 163 + '' 164 + startAll; 165 166 + # Wait for networking to come up 167 + $client->waitForUnit("network-interfaces.target"); 168 + $client->waitForUnit("network.target"); 169 + $router->waitForUnit("network-interfaces.target"); 170 + $router->waitForUnit("network.target"); 171 172 + # Wait until we have an ip address on each interface 173 + $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'"); 174 175 + # Test vlan 1 176 + $client->waitUntilSucceeds("ping -c 1 192.168.1.1"); 177 + $client->waitUntilSucceeds("ping -c 1 192.168.1.2"); 178 179 + $router->waitUntilSucceeds("ping -c 1 192.168.1.1"); 180 + $router->waitUntilSucceeds("ping -c 1 192.168.1.2"); 181 182 + # Test vlan 2 183 + $client->waitUntilSucceeds("ping -c 1 192.168.2.1"); 184 + $client->fail("ping -c 1 192.168.2.2"); 185 186 + $router->waitUntilSucceeds("ping -c 1 192.168.2.1"); 187 + $router->fail("ping -c 1 192.168.2.2"); 188 + ''; 189 + }; 190 + bond = let 191 + node = address: { config, pkgs, ... }: with pkgs.lib; { 192 + virtualisation.vlans = [ 1 2 ]; 193 + networking = { 194 + useNetworkd = networkd; 195 + firewall.allowPing = true; 196 + useDHCP = false; 197 + bonds.bond = { 198 + mode = "balance-rr"; 199 + interfaces = [ "eth1" "eth2" ]; 200 }; 201 + interfaces.eth1.ip4 = mkOverride 0 [ ]; 202 + interfaces.eth2.ip4 = mkOverride 0 [ ]; 203 + interfaces.bond.ip4 = mkOverride 0 204 + [ { inherit address; prefixLength = 30; } ]; 205 }; 206 + }; 207 + in { 208 + name = "Bond"; 209 + nodes.client1 = node "192.168.1.1"; 210 + nodes.client2 = node "192.168.1.2"; 211 + testScript = { nodes, ... }: 212 + '' 213 + startAll; 214 215 + # Wait for networking to come up 216 + $client1->waitForUnit("network-interfaces.target"); 217 + $client1->waitForUnit("network.target"); 218 + $client2->waitForUnit("network-interfaces.target"); 219 + $client2->waitForUnit("network.target"); 220 221 + # Test bonding 222 + $client1->waitUntilSucceeds("ping -c 2 192.168.1.1"); 223 + $client1->waitUntilSucceeds("ping -c 2 192.168.1.2"); 224 225 + $client2->waitUntilSucceeds("ping -c 2 192.168.1.1"); 226 + $client2->waitUntilSucceeds("ping -c 2 192.168.1.2"); 227 + ''; 228 + }; 229 + bridge = let 230 + node = { address, vlan }: { config, pkgs, ... }: with pkgs.lib; { 231 + virtualisation.vlans = [ vlan ]; 232 + networking = { 233 + useNetworkd = networkd; 234 + firewall.allowPing = true; 235 + useDHCP = false; 236 + interfaces.eth1.ip4 = mkOverride 0 237 + [ { inherit address; prefixLength = 24; } ]; 238 }; 239 + }; 240 + in { 241 + name = "Bridge"; 242 + nodes.client1 = node { address = "192.168.1.2"; vlan = 1; }; 243 + nodes.client2 = node { address = "192.168.1.3"; vlan = 2; }; 244 + nodes.router = { config, pkgs, ... }: with pkgs.lib; { 245 + virtualisation.vlans = [ 1 2 ]; 246 + networking = { 247 + useNetworkd = networkd; 248 + firewall.allowPing = true; 249 + useDHCP = false; 250 + bridges.bridge.interfaces = [ "eth1" "eth2" ]; 251 + interfaces.eth1.ip4 = mkOverride 0 [ ]; 252 + interfaces.eth2.ip4 = mkOverride 0 [ ]; 253 + interfaces.bridge.ip4 = mkOverride 0 254 + [ { address = "192.168.1.1"; prefixLength = 24; } ]; 255 }; 256 + }; 257 + testScript = { nodes, ... }: 258 + '' 259 + startAll; 260 261 + # Wait for networking to come up 262 + $client1->waitForUnit("network-interfaces.target"); 263 + $client1->waitForUnit("network.target"); 264 + $client2->waitForUnit("network-interfaces.target"); 265 + $client2->waitForUnit("network.target"); 266 + $router->waitForUnit("network-interfaces.target"); 267 + $router->waitForUnit("network.target"); 268 269 + # Test bridging 270 + $client1->waitUntilSucceeds("ping -c 1 192.168.1.1"); 271 + $client1->waitUntilSucceeds("ping -c 1 192.168.1.2"); 272 + $client1->waitUntilSucceeds("ping -c 1 192.168.1.3"); 273 274 + $client2->waitUntilSucceeds("ping -c 1 192.168.1.1"); 275 + $client2->waitUntilSucceeds("ping -c 1 192.168.1.2"); 276 + $client2->waitUntilSucceeds("ping -c 1 192.168.1.3"); 277 278 + $router->waitUntilSucceeds("ping -c 1 192.168.1.1"); 279 + $router->waitUntilSucceeds("ping -c 1 192.168.1.2"); 280 + $router->waitUntilSucceeds("ping -c 1 192.168.1.3"); 281 + ''; 282 + }; 283 + macvlan = { 284 + name = "MACVLAN"; 285 + nodes.router = router; 286 + nodes.client = { config, pkgs, ... }: with pkgs.lib; { 287 + virtualisation.vlans = [ 1 ]; 288 + networking = { 289 + useNetworkd = networkd; 290 + firewall.allowPing = true; 291 + useDHCP = true; 292 + macvlans.macvlan.interface = "eth1"; 293 + interfaces.eth1.ip4 = mkOverride 0 [ ]; 294 }; 295 + }; 296 + testScript = { nodes, ... }: 297 + '' 298 + startAll; 299 300 + # Wait for networking to come up 301 + $client->waitForUnit("network-interfaces.target"); 302 + $client->waitForUnit("network.target"); 303 + $router->waitForUnit("network-interfaces.target"); 304 + $router->waitForUnit("network.target"); 305 306 + # Wait until we have an ip address on each interface 307 + $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'"); 308 + $client->waitUntilSucceeds("ip addr show dev macvlan | grep -q '192.168.1'"); 309 310 + # Print diagnosting information 311 + $router->succeed("ip addr >&2"); 312 + $client->succeed("ip addr >&2"); 313 314 + # Test macvlan creates routable ips 315 + $client->waitUntilSucceeds("ping -c 1 192.168.1.1"); 316 + $client->waitUntilSucceeds("ping -c 1 192.168.1.2"); 317 + $client->waitUntilSucceeds("ping -c 1 192.168.1.3"); 318 319 + $router->waitUntilSucceeds("ping -c 1 192.168.1.1"); 320 + $router->waitUntilSucceeds("ping -c 1 192.168.1.2"); 321 + $router->waitUntilSucceeds("ping -c 1 192.168.1.3"); 322 + ''; 323 + }; 324 + sit = let 325 + node = { address4, remote, address6 }: { config, pkgs, ... }: with pkgs.lib; { 326 + virtualisation.vlans = [ 1 ]; 327 + networking = { 328 + useNetworkd = networkd; 329 + firewall.enable = false; 330 + useDHCP = false; 331 + sits.sit = { 332 + inherit remote; 333 + local = address4; 334 + dev = "eth1"; 335 }; 336 + interfaces.eth1.ip4 = mkOverride 0 337 + [ { address = address4; prefixLength = 24; } ]; 338 + interfaces.sit.ip6 = mkOverride 0 339 + [ { address = address6; prefixLength = 64; } ]; 340 }; 341 + }; 342 + in { 343 + name = "Sit"; 344 + nodes.client1 = node { address4 = "192.168.1.1"; remote = "192.168.1.2"; address6 = "fc00::1"; }; 345 + nodes.client2 = node { address4 = "192.168.1.2"; remote = "192.168.1.1"; address6 = "fc00::2"; }; 346 + testScript = { nodes, ... }: 347 + '' 348 + startAll; 349 350 + # Wait for networking to be configured 351 + $client1->waitForUnit("network-interfaces.target"); 352 + $client1->waitForUnit("network.target"); 353 + $client2->waitForUnit("network-interfaces.target"); 354 + $client2->waitForUnit("network.target"); 355 356 + # Print diagnostic information 357 + $client1->succeed("ip addr >&2"); 358 + $client2->succeed("ip addr >&2"); 359 360 + # Test ipv6 361 + $client1->waitUntilSucceeds("ping6 -c 1 fc00::1"); 362 + $client1->waitUntilSucceeds("ping6 -c 1 fc00::2"); 363 364 + $client2->waitUntilSucceeds("ping6 -c 1 fc00::1"); 365 + $client2->waitUntilSucceeds("ping6 -c 1 fc00::2"); 366 + ''; 367 + }; 368 + vlan = let 369 + node = address: { config, pkgs, ... }: with pkgs.lib; { 370 + #virtualisation.vlans = [ 1 ]; 371 + networking = { 372 + useNetworkd = networkd; 373 + firewall.allowPing = true; 374 + useDHCP = false; 375 + vlans.vlan = { 376 + id = 1; 377 + interface = "eth0"; 378 }; 379 + interfaces.eth0.ip4 = mkOverride 0 [ ]; 380 + interfaces.eth1.ip4 = mkOverride 0 [ ]; 381 + interfaces.vlan.ip4 = mkOverride 0 382 + [ { inherit address; prefixLength = 24; } ]; 383 }; 384 + }; 385 + in { 386 + name = "vlan"; 387 + nodes.client1 = node "192.168.1.1"; 388 + nodes.client2 = node "192.168.1.2"; 389 + testScript = { nodes, ... }: 390 + '' 391 + startAll; 392 393 + # Wait for networking to be configured 394 + $client1->waitForUnit("network-interfaces.target"); 395 + $client1->waitForUnit("network.target"); 396 + $client2->waitForUnit("network-interfaces.target"); 397 + $client2->waitForUnit("network.target"); 398 399 + # Test vlan is setup 400 + $client1->succeed("ip addr show dev vlan >&2"); 401 + $client2->succeed("ip addr show dev vlan >&2"); 402 + ''; 403 }; 404 + }; 405 + 406 + in mapAttrs (const (attrs: makeTest (attrs // { 407 + name = "${attrs.name}-Networking-${if networkd then "Networkd" else "Scripted"}"; 408 + meta = with pkgs.stdenv.lib.maintainers; { 409 + maintainers = [ wkennington ]; 410 + }; 411 + }))) testCases
+112 -108
nixos/tests/virtualbox.nix
··· 1 - { debug ? false, ... } @ args: 2 3 - import ./make-test.nix ({ pkgs, ... }: with pkgs.lib; let 4 5 testVMConfig = vmName: attrs: { config, pkgs, ... }: let 6 guestAdditions = pkgs.linuxPackages.virtualboxGuestAdditions; 7 ··· 314 test2.vmScript = dhcpScript; 315 }; 316 317 - in { 318 - name = "virtualbox"; 319 - meta = with pkgs.stdenv.lib.maintainers; { 320 - maintainers = [ aszlig wkennington ]; 321 - }; 322 323 - machine = { pkgs, lib, config, ... }: { 324 - imports = let 325 - mkVMConf = name: val: val.machine // { key = "${name}-config"; }; 326 - vmConfigs = mapAttrsToList mkVMConf vboxVMs; 327 - in [ ./common/user-account.nix ./common/x11.nix ] ++ vmConfigs; 328 - virtualisation.memorySize = 2048; 329 - virtualisation.virtualbox.host.enable = true; 330 - users.extraUsers.alice.extraGroups = let 331 - inherit (config.virtualisation.virtualbox.host) enableHardening; 332 - in lib.mkIf enableHardening (lib.singleton "vboxusers"); 333 - }; 334 335 - testScript = '' 336 - sub ru ($) { 337 - my $esc = $_[0] =~ s/'/'\\${"'"}'/gr; 338 - return "su - alice -c '$esc'"; 339 - } 340 341 - sub vbm { 342 - $machine->succeed(ru("VBoxManage ".$_[0])); 343 - }; 344 345 - ${concatStrings (mapAttrsToList (_: getAttr "testSubs") vboxVMs)} 346 347 - $machine->waitForX; 348 349 - ${mkLog "$HOME/.config/VirtualBox/VBoxSVC.log" "HOST-SVC"} 350 351 - createVM_simple; 352 353 - subtest "simple-gui", sub { 354 - $machine->succeed(ru "VirtualBox &"); 355 - $machine->waitForWindow(qr/Oracle VM VirtualBox Manager/); 356 - $machine->sleep(5); 357 - $machine->screenshot("gui_manager_started"); 358 - $machine->sendKeys("ret"); 359 - $machine->screenshot("gui_manager_sent_startup"); 360 - waitForStartup_simple (sub { 361 - $machine->sendKeys("ret"); 362 - }); 363 - $machine->screenshot("gui_started"); 364 - waitForVMBoot_simple; 365 - $machine->screenshot("gui_booted"); 366 - shutdownVM_simple; 367 - $machine->sleep(5); 368 - $machine->screenshot("gui_stopped"); 369 - $machine->sendKeys("ctrl-q"); 370 - $machine->sleep(5); 371 - $machine->screenshot("gui_manager_stopped"); 372 }; 373 374 - cleanup_simple; 375 376 - subtest "simple-cli", sub { 377 - vbm("startvm simple"); 378 - waitForStartup_simple; 379 - $machine->screenshot("cli_started"); 380 - waitForVMBoot_simple; 381 - $machine->screenshot("cli_booted"); 382 - shutdownVM_simple; 383 - }; 384 385 - subtest "privilege-escalation", sub { 386 $machine->fail("test -e '/root/VirtualBox VMs'"); 387 $machine->fail("test -e '/root/.config/VirtualBox'"); 388 $machine->succeed("test -e '/home/alice/VirtualBox VMs'"); 389 - }; 390 391 - destroyVM_simple; 392 393 - sub removeUUIDs { 394 - return join("\n", grep { $_ !~ /^UUID:/ } split(/\n/, $_[0]))."\n"; 395 - } 396 397 - subtest "host-usb-permissions", sub { 398 - my $userUSB = removeUUIDs vbm("list usbhost"); 399 - print STDERR $userUSB; 400 - my $rootUSB = removeUUIDs $machine->succeed("VBoxManage list usbhost"); 401 - print STDERR $rootUSB; 402 403 - die "USB host devices differ for root and normal user" 404 - if $userUSB ne $rootUSB; 405 - die "No USB host devices found" if $userUSB =~ /<none>/; 406 - }; 407 408 - subtest "systemd-detect-virt", sub { 409 - createVM_detectvirt; 410 - vbm("startvm detectvirt"); 411 - waitForStartup_detectvirt; 412 - waitForVMBoot_detectvirt; 413 - shutdownVM_detectvirt; 414 - my $result = $machine->succeed("cat '$detectvirt_sharepath/result'"); 415 - chomp $result; 416 - destroyVM_detectvirt; 417 - die "systemd-detect-virt returned \"$result\" instead of \"oracle\"" 418 - if $result ne "oracle"; 419 - }; 420 421 - subtest "net-hostonlyif", sub { 422 - createVM_test1; 423 - createVM_test2; 424 425 - vbm("startvm test1"); 426 - waitForStartup_test1; 427 - waitForVMBoot_test1; 428 429 - vbm("startvm test2"); 430 - waitForStartup_test2; 431 - waitForVMBoot_test2; 432 433 - $machine->screenshot("net_booted"); 434 435 - my $test1IP = waitForIP_test1 1; 436 - my $test2IP = waitForIP_test2 1; 437 438 - $machine->succeed("echo '$test2IP' | netcat -c '$test1IP' 1234"); 439 - $machine->succeed("echo '$test1IP' | netcat -c '$test2IP' 1234"); 440 - 441 - $machine->waitUntilSucceeds("netcat -c '$test1IP' 5678 >&2"); 442 - $machine->waitUntilSucceeds("netcat -c '$test2IP' 5678 >&2"); 443 444 - shutdownVM_test1; 445 - shutdownVM_test2; 446 447 - destroyVM_test1; 448 - destroyVM_test2; 449 - }; 450 ''; 451 - }) args
··· 1 + { system ? builtins.currentSystem, debug ? false }: 2 3 + with import ../lib/testing.nix { inherit system; }; 4 + with pkgs.lib; 5 6 + let 7 testVMConfig = vmName: attrs: { config, pkgs, ... }: let 8 guestAdditions = pkgs.linuxPackages.virtualboxGuestAdditions; 9 ··· 316 test2.vmScript = dhcpScript; 317 }; 318 319 + mkVBoxTest = name: testScript: makeTest { 320 + name = "virtualbox-${name}"; 321 322 + machine = { lib, config, ... }: { 323 + imports = let 324 + mkVMConf = name: val: val.machine // { key = "${name}-config"; }; 325 + vmConfigs = mapAttrsToList mkVMConf vboxVMs; 326 + in [ ./common/user-account.nix ./common/x11.nix ] ++ vmConfigs; 327 + virtualisation.memorySize = 2048; 328 + virtualisation.virtualbox.host.enable = true; 329 + users.extraUsers.alice.extraGroups = let 330 + inherit (config.virtualisation.virtualbox.host) enableHardening; 331 + in lib.mkIf enableHardening (lib.singleton "vboxusers"); 332 + }; 333 334 + testScript = '' 335 + sub ru ($) { 336 + my $esc = $_[0] =~ s/'/'\\${"'"}'/gr; 337 + return "su - alice -c '$esc'"; 338 + } 339 + 340 + sub vbm { 341 + $machine->succeed(ru("VBoxManage ".$_[0])); 342 + }; 343 344 + sub removeUUIDs { 345 + return join("\n", grep { $_ !~ /^UUID:/ } split(/\n/, $_[0]))."\n"; 346 + } 347 348 + ${concatStrings (mapAttrsToList (_: getAttr "testSubs") vboxVMs)} 349 350 + $machine->waitForX; 351 352 + ${mkLog "$HOME/.config/VirtualBox/VBoxSVC.log" "HOST-SVC"} 353 354 + ${testScript} 355 + ''; 356 357 + meta = with pkgs.stdenv.lib.maintainers; { 358 + maintainers = [ aszlig wkennington ]; 359 }; 360 + }; 361 362 + in mapAttrs mkVBoxTest { 363 + simple-gui = '' 364 + createVM_simple; 365 + $machine->succeed(ru "VirtualBox &"); 366 + $machine->waitForWindow(qr/Oracle VM VirtualBox Manager/); 367 + $machine->sleep(5); 368 + $machine->screenshot("gui_manager_started"); 369 + $machine->sendKeys("ret"); 370 + $machine->screenshot("gui_manager_sent_startup"); 371 + waitForStartup_simple (sub { 372 + $machine->sendKeys("ret"); 373 + }); 374 + $machine->screenshot("gui_started"); 375 + waitForVMBoot_simple; 376 + $machine->screenshot("gui_booted"); 377 + shutdownVM_simple; 378 + $machine->sleep(5); 379 + $machine->screenshot("gui_stopped"); 380 + $machine->sendKeys("ctrl-q"); 381 + $machine->sleep(5); 382 + $machine->screenshot("gui_manager_stopped"); 383 + ''; 384 385 + simple-cli = '' 386 + createVM_simple; 387 + vbm("startvm simple"); 388 + waitForStartup_simple; 389 + $machine->screenshot("cli_started"); 390 + waitForVMBoot_simple; 391 + $machine->screenshot("cli_booted"); 392 393 + $machine->nest("Checking for privilege escalation", sub { 394 $machine->fail("test -e '/root/VirtualBox VMs'"); 395 $machine->fail("test -e '/root/.config/VirtualBox'"); 396 $machine->succeed("test -e '/home/alice/VirtualBox VMs'"); 397 + }); 398 399 + shutdownVM_simple; 400 + ''; 401 402 + host-usb-permissions = '' 403 + my $userUSB = removeUUIDs vbm("list usbhost"); 404 + print STDERR $userUSB; 405 + my $rootUSB = removeUUIDs $machine->succeed("VBoxManage list usbhost"); 406 + print STDERR $rootUSB; 407 408 + die "USB host devices differ for root and normal user" 409 + if $userUSB ne $rootUSB; 410 + die "No USB host devices found" if $userUSB =~ /<none>/; 411 + ''; 412 413 + systemd-detect-virt = '' 414 + createVM_detectvirt; 415 + vbm("startvm detectvirt"); 416 + waitForStartup_detectvirt; 417 + waitForVMBoot_detectvirt; 418 + shutdownVM_detectvirt; 419 + my $result = $machine->succeed("cat '$detectvirt_sharepath/result'"); 420 + chomp $result; 421 + destroyVM_detectvirt; 422 + die "systemd-detect-virt returned \"$result\" instead of \"oracle\"" 423 + if $result ne "oracle"; 424 + ''; 425 426 + net-hostonlyif = '' 427 + createVM_test1; 428 + createVM_test2; 429 430 + vbm("startvm test1"); 431 + waitForStartup_test1; 432 + waitForVMBoot_test1; 433 434 + vbm("startvm test2"); 435 + waitForStartup_test2; 436 + waitForVMBoot_test2; 437 438 + $machine->screenshot("net_booted"); 439 440 + my $test1IP = waitForIP_test1 1; 441 + my $test2IP = waitForIP_test2 1; 442 443 + $machine->succeed("echo '$test2IP' | netcat -c '$test1IP' 1234"); 444 + $machine->succeed("echo '$test1IP' | netcat -c '$test2IP' 1234"); 445 446 + $machine->waitUntilSucceeds("netcat -c '$test1IP' 5678 >&2"); 447 + $machine->waitUntilSucceeds("netcat -c '$test2IP' 5678 >&2"); 448 449 + shutdownVM_test1; 450 + shutdownVM_test2; 451 452 + destroyVM_test1; 453 + destroyVM_test2; 454 ''; 455 + }