3
0
Fork 0
forked from mirrors/nixpkgs

* Use vde_switch instead of QEMU's multicast feature to tie QEMU VMs

together into virtual networks.  This has several advantages:

  - It's more secure because the QEMU instances use Unix domain
    sockets to talk to the switch.

  - It doesn't depend on the host's network interfaces.  (Local
    multicast fails if there is no default gateway, so for instance it
    fails if a laptop is not connected to any network.)

  - VDE devices can be connected together to form arbitrary network
    topologies.

  - VDE has a "wirefilter" tool to emulate delays and packet loss,
    which are useful for network testing.

svn path=/nixos/trunk/; revision=25526
This commit is contained in:
Eelco Dolstra 2011-01-12 18:47:23 +00:00
parent fd48855284
commit b3dbcbe249
4 changed files with 51 additions and 51 deletions

View file

@ -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.<vlan> as the multicast address to connect VMs on
# the same vlan, but allow it to be overriden using the
# $QEMU_MCAST_ADDR_<vlan> 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} ";
}

View file

@ -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.<vlan>.$mcastSuffix\n";
for (my $n = 0; $n < 256; $n++) {
$ENV{"QEMU_MCAST_ADDR_$n"} = "$mcastPrefix.$n.$mcastSuffix";
}
my $showGraphics = defined $ENV{'DISPLAY'};

View file

@ -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();
}

View file

@ -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;
};