From 363806e89ba1e638b0459a2eb8b30bad8189d370 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 18 Jun 2010 19:31:02 +0000 Subject: [PATCH] * To establish the connection to the root shell in the guest, let the guest connect to a Unix domain socket on the host rather than the other way around. The former is a QEMU feature (guestfwd to a socket) while the latter requires a patch (which we can now get rid of). svn path=/nixos/branches/boot-order/; revision=22331 --- lib/test-driver/Machine.pm | 50 +++++++++++------------- lib/test-driver/test-driver.pl | 3 -- modules/testing/test-instrumentation.nix | 10 ++--- modules/virtualisation/qemu-vm.nix | 2 +- 4 files changed, 26 insertions(+), 39 deletions(-) diff --git a/lib/test-driver/Machine.pm b/lib/test-driver/Machine.pm index b5989d54076..c18e0e33162 100644 --- a/lib/test-driver/Machine.pm +++ b/lib/test-driver/Machine.pm @@ -2,7 +2,6 @@ package Machine; use strict; use threads; -use Thread::Queue; use Socket; use IO::Handle; use POSIX qw(dup2); @@ -51,7 +50,6 @@ sub new { booted => 0, pid => 0, connected => 0, - connectedQueue => Thread::Queue->new(), socket => undef, stateDir => "$tmpDir/$name", monitor => undef, @@ -101,6 +99,14 @@ sub start { bind($monitorS, sockaddr_un($monitorPath)) or die "cannot bind monitor socket: $!"; listen($monitorS, 1) or die; + # Create a Unix domain socket to which the root shell in the guest will connect. + my $shellPath = $self->{stateDir} . "/shell"; + unlink $shellPath; + my $shellS; + socket($shellS, PF_UNIX, SOCK_STREAM, 0) or die; + bind($shellS, sockaddr_un($shellPath)) or die "cannot bind shell socket: $!"; + listen($shellS, 1) or die; + # Start the VM. my $pid = fork(); die if $pid == -1; @@ -108,13 +114,15 @@ sub start { if ($pid == 0) { close $serialP; close $monitorS; + close $shellS; open NUL, "{stateDir}; $ENV{USE_TMPDIR} = 1; - $ENV{QEMU_OPTS} = "-nographic -no-reboot -redir tcp:65535::514 -monitor unix:./monitor"; + $ENV{QEMU_OPTS} = "-nographic -no-reboot -monitor unix:./monitor -chardev socket,id=shell,path=./shell"; + $ENV{QEMU_NET_OPTS} = "guestfwd=tcp:10.0.2.6:23-chardev:shell"; $ENV{QEMU_KERNEL_PARAMS} = "hostTmpDir=$ENV{TMPDIR}"; chdir $self->{stateDir} or die; exec $self->{startCommand}; @@ -132,16 +140,20 @@ sub start { chomp; s/\r$//; print STDERR $self->name, "# $_\n"; - $self->{connectedQueue}->enqueue(1) if $_ eq "===UP==="; } - # If the child dies, wake up connect(). - $self->{connectedQueue}->enqueue(1); } - # Wait until QEMU connects to the monitor. eval { local $SIG{CHLD} = sub { die "QEMU died prematurely\n"; }; + + # Wait until QEMU connects to the monitor. accept($self->{monitor}, $monitorS) or die; + + # Wait until QEMU connects to the root shell socket. QEMU + # does so immediately; this doesn't mean that the root shell + # has connected yet inside the guest. + accept($self->{socket}, $shellS) or die; + $self->{socket}->autoflush(1); }; die "$@" if $@; @@ -197,27 +209,9 @@ sub connect { $self->start; - # Wait until the processQemuOutput thread signals that the machine - # is up. - retry sub { - return 1 if $self->{connectedQueue}->dequeue_nb(); - }; - - retry sub { - $self->log("trying to connect"); - my $socket = new IO::Handle; - $self->{socket} = $socket; - socket($socket, PF_UNIX, SOCK_STREAM, 0) or die; - connect($socket, sockaddr_un($self->{stateDir} . "/65535.socket")) or die; - $socket->autoflush(1); - print $socket "echo hello\n" or next; - flush $socket; - my $line = readline($socket); - chomp $line; - return 1 if $line eq "hello"; - }; - - $self->log("connected"); + my $line = readline $self->{socket} or die; + $self->log("connected to guest root shell"); + $self->{connected} = 1; } diff --git a/lib/test-driver/test-driver.pl b/lib/test-driver/test-driver.pl index 98666d6c775..ad1af5a6fbf 100644 --- a/lib/test-driver/test-driver.pl +++ b/lib/test-driver/test-driver.pl @@ -74,6 +74,3 @@ END { runTests; - - -print STDERR "DONE\n"; diff --git a/modules/testing/test-instrumentation.nix b/modules/testing/test-instrumentation.nix index 84671028ba0..2515edf6192 100644 --- a/modules/testing/test-instrumentation.nix +++ b/modules/testing/test-instrumentation.nix @@ -13,6 +13,7 @@ let '' #! ${pkgs.perl}/bin/perl $SIG{CHLD} = 'DEFAULT'; + print "\n"; exec "/bin/sh"; ''; @@ -25,12 +26,6 @@ in jobs.backdoor = { startOn = "started network-interfaces"; - preStart = - '' - echo "guest running" > /dev/ttyS0 - echo "===UP===" > dev/ttyS0 - ''; - script = '' export USER=root @@ -39,7 +34,8 @@ in export GCOV_PREFIX=/tmp/coverage-data source /etc/profile cd /tmp - exec ${pkgs.socat}/bin/socat tcp-listen:514,fork exec:${rootShell} 2> /dev/ttyS0 + echo "connecting to host..." > /dev/ttyS0 + exec ${pkgs.socat}/bin/socat tcp:10.0.2.6:23 exec:${rootShell} 2> /dev/ttyS0 ''; }; diff --git a/modules/virtualisation/qemu-vm.nix b/modules/virtualisation/qemu-vm.nix index 46462bbc6cc..e054b537d43 100644 --- a/modules/virtualisation/qemu-vm.nix +++ b/modules/virtualisation/qemu-vm.nix @@ -134,7 +134,7 @@ let -m ${toString config.virtualisation.memorySize} \ -net nic,vlan=0,model=virtio \ -chardev socket,id=samba,path=./samba \ - -net user,vlan=0,guestfwd=tcp:10.0.2.4:139-chardev:samba \ + -net user,vlan=0,guestfwd=tcp:10.0.2.4:139-chardev:samba''${QEMU_NET_OPTS:+,$QEMU_NET_OPTS} \ -drive file=$NIX_DISK_IMAGE,if=virtio,boot=on,cache=writeback,werror=report \ -kernel ${config.system.build.toplevel}/kernel \ -initrd ${config.system.build.toplevel}/initrd \