diff --git a/lib/qemu-flags.nix b/lib/qemu-flags.nix index 7831c8f149ab..5d8e898c534c 100644 --- a/lib/qemu-flags.nix +++ b/lib/qemu-flags.nix @@ -4,12 +4,6 @@ qemuNICFlags = nic: net: machine: "-net nic,vlan=${toString nic},macaddr=52:54:00:12:${toString net}:${toString machine},model=virtio " + - # Use 232.0.1. as the multicast address to connect VMs on - # the same vlan, but allow it to be overriden using the - # $QEMU_MCAST_ADDR_ environment variable. The test driver - # sets this variable to prevent collisions between parallel - # builds. - "-net socket,vlan=${toString nic},mcast=" + - "\${QEMU_MCAST_ADDR_${toString net}:-232.0.1.${toString net}:1234} "; - + "-net vde,vlan=${toString nic},sock=$QEMU_VDE_SOCKET_${toString net} "; + } diff --git a/lib/test-driver/Machine.pm b/lib/test-driver/Machine.pm index 81d96ee81e1a..7b48f26fb820 100644 --- a/lib/test-driver/Machine.pm +++ b/lib/test-driver/Machine.pm @@ -10,16 +10,6 @@ use Cwd; use File::Basename; -# Stuff our PID in the multicast address/port to prevent collissions -# with other NixOS VM networks. See -# http://www.iana.org/assignments/multicast-addresses/. -my $mcastPrefix = "232.18"; -my $mcastSuffix = ($$ >> 8) . ":" . (64000 + ($$ & 0xff)); -print STDERR "using multicast addresses $mcastPrefix..$mcastSuffix\n"; -for (my $n = 0; $n < 256; $n++) { - $ENV{"QEMU_MCAST_ADDR_$n"} = "$mcastPrefix.$n.$mcastSuffix"; -} - my $showGraphics = defined $ENV{'DISPLAY'}; diff --git a/lib/test-driver/test-driver.pl b/lib/test-driver/test-driver.pl index 9f5054f77219..841017ea0a33 100644 --- a/lib/test-driver/test-driver.pl +++ b/lib/test-driver/test-driver.pl @@ -5,6 +5,7 @@ use Machine; use Term::ReadLine; use IO::File; use Logger; +use Cwd; $SIG{PIPE} = 'IGNORE'; # because Unix domain sockets may die unexpectedly @@ -13,6 +14,19 @@ STDERR->autoflush(1); my $log = new Logger; +# Start vde_switch for each network required by the test. +my %vlans; +foreach my $vlan (split / /, $ENV{VLANS} || "") { + next if defined $vlans{$vlan}; + $log->log("starting VDE switch for network $vlan"); + my $socket = Cwd::abs_path "./vde$vlan.ctl"; + system("vde_switch -d -s $socket") == 0 + or die "cannot start vde_switch"; + $ENV{"QEMU_VDE_SOCKET_$vlan"} = $socket; + $vlans{$vlan} = 1; +} + + my %vms; my $context = ""; @@ -83,23 +97,26 @@ sub runTests { # Copy the kernel coverage data for each machine, if the kernel # has been compiled with coverage instrumentation. - foreach my $vm (values %vms) { - my $gcovDir = "/sys/kernel/debug/gcov"; + $log->nest("collecting coverage data", sub { + foreach my $vm (values %vms) { + my $gcovDir = "/sys/kernel/debug/gcov"; - next unless $vm->isUp(); + next unless $vm->isUp(); - my ($status, $out) = $vm->execute("test -e $gcovDir"); - next if $status != 0; + my ($status, $out) = $vm->execute("test -e $gcovDir"); + next if $status != 0; - # Figure out where to put the *.gcda files so that the report - # generator can find the corresponding kernel sources. - my $kernelDir = $vm->mustSucceed("echo \$(dirname \$(readlink -f /var/run/current-system/kernel))/.build/linux-*"); - chomp $kernelDir; - my $coverageDir = "/hostfs" . $vm->stateDir() . "/coverage-data/$kernelDir"; + # Figure out where to put the *.gcda files so that the + # report generator can find the corresponding kernel + # sources. + my $kernelDir = $vm->mustSucceed("echo \$(dirname \$(readlink -f /var/run/current-system/kernel))/.build/linux-*"); + chomp $kernelDir; + my $coverageDir = "/hostfs" . $vm->stateDir() . "/coverage-data/$kernelDir"; - # Copy all the *.gcda files. - $vm->execute("for d in $gcovDir/nix/store/*/.build/linux-*; do for i in \$(cd \$d && find -name '*.gcda'); do echo \$i; mkdir -p $coverageDir/\$(dirname \$i); cp -v \$d/\$i $coverageDir/\$i; done; done"); - } + # Copy all the *.gcda files. + $vm->execute("for d in $gcovDir/nix/store/*/.build/linux-*; do for i in \$(cd \$d && find -name '*.gcda'); do echo \$i; mkdir -p $coverageDir/\$(dirname \$i); cp -v \$d/\$i $coverageDir/\$i; done; done"); + } + }); if ($nrTests != 0) { $log->log("$nrSucceeded out of $nrTests tests succeeded", @@ -118,12 +135,14 @@ sub createDisk { END { - foreach my $vm (values %vms) { - if ($vm->{pid}) { - $log->log("killing " . $vm->{name} . " (pid " . $vm->{pid} . ")"); - kill 9, $vm->{pid}; + $log->nest("cleaning up", sub { + foreach my $vm (values %vms) { + if ($vm->{pid}) { + $log->log("killing " . $vm->{name} . " (pid " . $vm->{pid} . ")"); + kill 9, $vm->{pid}; + } } - } + }); $log->close(); } diff --git a/lib/testing.nix b/lib/testing.nix index 6f66ec72601d..7ed1ba042756 100644 --- a/lib/testing.nix +++ b/lib/testing.nix @@ -27,31 +27,27 @@ rec { cp ${./test-driver/Logger.pm} $libDir/Logger.pm wrapProgram $out/bin/nixos-test-driver \ - --prefix PATH : "${imagemagick}/bin" \ + --prefix PATH : "${pkgs.qemu_kvm}/bin:${pkgs.vde2}/bin:${imagemagick}/bin" \ --prefix PERL5LIB : "${lib.makePerlPath [ perlPackages.TermReadLineGnu perlPackages.XMLWriter ]}:$out/lib/perl5/site_perl" ''; }; # Run an automated test suite in the given virtual network. - # `network' must be the result of a call to the - # `buildVirtualNetwork' function. `tests' is a Perl fragment - # describing the tests. - runTests = network: tests: + # `driver' is the script that runs the network. + runTests = driver: stdenv.mkDerivation { name = "vm-test-run"; requiredSystemFeatures = [ "kvm" ]; - inherit tests; - - buildInputs = [ pkgs.qemu_kvm pkgs.libxslt ]; + buildInputs = [ pkgs.libxslt ]; buildCommand = '' mkdir -p $out/nix-support - LOGFILE=$out/log.xml ${testDriver}/bin/nixos-test-driver ${network}/vms/*/bin/run-*-vm || failed=1 + LOGFILE=$out/log.xml tests="testScript" ${driver}/bin/nixos-test-driver || failed=1 # Generate a pretty-printed log. xsltproc --output $out/log.html ${./test-driver/log2html.xsl} $out/log.xml @@ -138,10 +134,6 @@ rec { then t.testScript { inherit (vms) nodes; } else t.testScript; - test = runTests vms testScript; - - report = makeReport test; - # Generate a convenience wrapper for running the test driver # interactively with the specified network. driver = runCommand "nixos-test-driver" @@ -150,14 +142,19 @@ rec { } '' mkdir -p $out/bin + echo "$testScript" > $out/test-script ln -s ${vms}/bin/* $out/bin/ ln -s ${testDriver}/bin/* $out/bin/ wrapProgram $out/bin/nixos-test-driver \ --add-flags "${vms}/vms/*/bin/run-*-vm" \ --run "testScript=\"\$(cat $out/test-script)\"" \ - --set testScript '"$testScript"' - echo "$testScript" > $out/test-script + --set testScript '"$testScript"' \ + --set VLANS '"${toString (map (m: m.config.virtualisation.vlans) (lib.attrValues vms.nodes))}"' \ ''; # " + + test = runTests driver; + + report = makeReport test; };