Virtueller Rauch (Linux-Magazin, Oktober 2011)

Eine VirtualBox-Installation fährt Schnappschüsse virtueller Maschinen in Sekundenschnelle von der Kommandozeile hoch und hilft, beim Browsen die Privatsphäre zu wahren und Perl-Module durch einen Smoke-Test zu schicken.

Wer ständig neue Linux-Distributionen ausprobiert, der bedient Virtualisierer wie VMWare, KVM, Xen, oder VirtualBox wahrscheinlich schon im Schlaf. Aber auch Programmierer, die Code für unterschiedliche Linux-Versionen oder, Gott bewahre, Windows-Versionen entwickeln, wissen lokal verfügbare virtuelle Maschinen für schnelle Tests zu schätzen.

Das Virtualisierungspaket Virtualbox ([2]) ist einfach mittels einer ansprechenden GUI zu bedienen (Abbildung 1) und bequem als Ubuntu-Paket unter der GPLv2-Lizenz verfügbar (Abbildung 2).

Abbildung 1: VirtualBox mit einigen Ubuntu- und Windows-Versionen als Gastsystemen.

Abbildung 2: Synaptik-Listing von Ubuntu-Paketen, die VirtualBox installieren.

Mit Hilfe von Installations-CD/DVDs oder .iso-Dateien legt der User im Virtualisierer schnell eine Handvoll Gastsysteme an, die anschließend auf Knopfdruck in eigenen Fenstern hochfahren. Die Maussteuerung im Gastsystem bedarf einer kurzen Gewöhnungsphase, denn hat das Gastsystem einmal den Maus-Fokus, gibt es ihn nicht mehr her. Der Mauszeiger eckt nun an den Grenzen des Gastsystemfensters an. Um den Fokus des virtuellen Systems zu verlassen, drückt der User eine vordefinierte Taste (voreingestellt ist die rechte (!) ALT-Taste), worauf der Mauszeiger wieder auf dem heimischen Desktop weilt.

Einfrieren und Auftauen

Dank effizient implementierter Schnappschusstechnik frieren VMs Zustände rasch ein und stellen sie später in wenigen Sekunden wieder her. So können Websurfer eine frisch erzeugte Ubuntu-Installation mit geöffnetem Browser für peinliche Webrecherchen nutzen.

Was Google über seine Nutzer weiß, kommt immer dann erschreckend zutage, wenn der User einen Suchbegriff eingibt und die Autocomplete-Funktion peinliche Vervollständigungen vornimmt. Niemand möchte schließlich daran erinnert werden, dass vor einigen Tagen nach "Hämorrhidencreme" oder "Fußpilz" gesucht wurde, ganz zu schweigen vom Einfluss dieser Suchbegriffe auf das Langzeittargeting von Googles personifizierter Werbemaschine.

Der paranoide Pinguinfreund möchte weder die ausgestellten Cookies länger als notwendig behalten noch irgendwelche Spuren in der Browser-History hinterlassen. Da er nicht genau weiß, was der Browser hinter seinem Rücken alles an Caching und sonstiger Datenspeicherei betreibt, liegt es nahe, für sensitive Suchanfragen blitzschnell eine virtuelle Maschine mit eingabebereitem Browser hochzufahren, die Suche durchzuführen und gleich darauf die VM wieder in ihren Ausgangszustand zurückzuversetzen.

Abbildung 3: Diesen peinlichen Suchbegriff wird der Browser beim nächsten Hochfahren der VM vergessen haben.

Das Verfahren ist zwar nicht ganz hundertprozentig wasserdicht, ein James Bond als Gegenspieler könnte auf der virtuellen Festplatte vielleicht noch Datenschnipsel finden, und auch die IP-Addresse des verwendeten Routers taucht in den Google-Logs auf, aber legt die Latte schon merklich höher. Wer mehr Privatsphäre braucht, sollte Tor bemühen und die in einer Einzeldatei liegende VM-Festplatte nach Gebrauch mit dban zerstören.

Kurz nach der Linux-Installation von der DVD öffnet der auf seine Privatsphäre bedachte User also im nagelneuen Gastsystem den Firefox-Browser und zieht vom aktuellen Zustand der VM einen Snapshot (Abbildungen 2 und 3).

Abbildung 4: Der User zieht vom aktuellen Zustand der VM einen Snapshot ...

Abbildung 5: ... der in wenigen Sekunden abgespeichert ist.

Nach Abschluss der geheimen Mission fährt der User die VM herunter und stellt über die "Restore"-Funktion des VirtualBox-Snapshot-Menüs den ursprünglichen Zustand wieder her. Beim nächsten Hochfahren der VM steht wieder ein offener Browser bereit, der sich allerdings an nichts mehr erinnert, ganz so, als wäre ein Zeitsprung in die Vergangenheit erfolgt.

Automatisch als Kommando

Statt sich bei jeder Recherche erst die VirtualBox-GUI hochzufahren und in dessen Menüs herumzuklicken, bietet sich ein Perl-Skript an, das die VM selbständig auswählt und hochfährt. Nach getaner Arbeit drückt der User im Skript die Enter-Taste und die VM fährt herunter und der Startzustand wird wieder hergestellt. Mit dem Programm VBoxManage bietet VirtualBox dankenswerterweise eine Komplettstuerung von der Kommandozeile. Listing 1 zeigt das Perl-Skript, das die VM mit dem Namen "Ubuntu 10.04" und deren vorher manuell angelegten Snapshot "Browse" auswählt (siehe Abbildung 1). Mittels des tap-Kommandos aus dem CPAN-Modul Sysadm::Install setzt es die Shell-Befehle ab. Man könnte das Skript natürlich einfacher als Shell-Skript implementieren, aber erfahrene Perl-Programmierer wissen, dass es nur eine Frage der Zeit ist, bis ein Shell-Skript im Funktionsumfang so weit wächst, bis man es in Perl reimplementiert, weil es sonst nicht mehr zu warten ist.

Das Skript nutzt die Unterkommandos startvm und ctrlvm poweroff, um die VM herauf- und später wieder herunter zu fahren. Den Snapshot restauriert es sowohl am Anfang als auch am Ende des Skripts, um sicher zu stellen, dass die VM auch dann in den Initialzustand hochfährt, falls jemand zwischenzeitlich in im Snapshot-Menü der VirtualBox-GUI herumgefuhrwerkt hat.

Listing 1: browse

    01 #!/usr/local/bin/perl -w
    02 use strict;
    03 use Sysadm::Install qw(:all);
    04 use Log::Log4perl qw(:easy);
    05 
    06 Log::Log4perl->easy_init($DEBUG);
    07 
    08 my $vbm = "VBoxManage";
    09 my $vm  = "Ubuntu 10.04";
    10 
    11 tap $vbm, "snapshot", $vm, "restore", "Browse";
    12 tap $vbm, "startvm", $vm;
    13 
    14 print "Press Enter for shutdown";
    15 <STDIN>;
    16 
    17 tap $vbm, "controlvm", $vm, "poweroff";
    18 tap $vbm, "snapshot", $vm, "restore", "Browse";

Beschränkt vernetzt

VirtualBox-VMs lassen sich aber auch im Headless-Modus völlig ohne Bildschirmausgabe steuern. Ein im unsichtbar laufenden Gastsystem installierter sshd-Dämon erlaubt dem Hostsystem, dort Kommandos auszuführen oder mit dem Gastsystem Dateien auszutauschen.

VirtualBox fährt Gastsysteme allerdings von Haus aus im NAT-(Network Address-Translation)-Modus hoch, weist ihnen eine Adresse im virtuellen 10.x.x.x-Netz zu und kommuniziert mit dem lokalen Netz des Hosts über eine Adressumwandlung, ähnlich wie die meisten Router in Privathaushalten die lokalen Geräte mit ihren 192.168.x.x-Adressen mit dem Internet kommunizieren lassen. Dies funktioniert aus der VM ins lokale Netz ohne Probleme, allerdings dürfen der Host oder Geräte im lokalen Netz keine Verbindung mit der VM aufnehmen. Dies lässt sich über den Dialog "Network Adapters" ändern, der sich hinter dem Symbol mit den zwei Terminals am rechten unteren Rand einer laufenden VM verbirgt (Abbildungen 6 und 7).

Abbildung 6: Ein Rechtsklick auf das Symbol mit den zwei Terminals öffnet den Dialog zum Einstellen des Netzwerk-Adapters.

Abbildung 7: Der Bridged-Adapter im Netzwerk-Dialog erlaubt die Kommunikation zwischen VM und dem Rest der Welt.

Brücke öffnet Firewall

Ändert man die Einstellung "NAT" in "Bridged Mode" um, holt sich die VM eine IP-Adresse im lokalen Netz vom dort laufenden DCHP-Server ab (z.B. 192.168.0.135) und wird somit zum gleichberechtigten Kommunikationspartner. Ein in der VM installierter sshd-Dämon ("sudo apt-get install openssh-server") gewährt dann Clients auf dem Host oder im lokalen Netz, die sich mit "ssh 192.168.0.135" in der VM mit ihrer Userid anmelden, anstandslos Zugriff. Kopiert der User auch noch seinen SSH-Public-Key (z.B. .ssh/id_rsa.pub) in die Datei ~/.ssh/authorized_keys in der VM, geht es sogar ohne Passwort, was für automatisch ablaufende Skripts wichtig ist.

Allerdings ist es gar nicht so einfach, herauszufinden, welche IP sich eine bestimmte VM beim Hochfahren zugelegt hat. VirtualBox bietet eine Methode über die sogenannten "Guestproperties", einer Erweiterung, die der User erst durch Anwahl des Menüeintrags "Devices/Install Guest Additions" einer laufenden VM installieren muss (Abbildung 8). Anschließend lädt die VM eine .iso-Datei vom Internet, mounted sie als CD-Drive in der VM und führt ein auf der CD liegendes Shell-Skript aus, das dort wild anfängt, Kernelmodule zu kompilieren.

Abbildung 8: Wer die "Guest Additions" installiert, bekommt nützliche Utilities für VirtualBox-VMs.

Handbetrieb erforderlich

Bei der von mir verwendeten VirtualBox-Version 3.1.6 funktionierte das Verfahren allerdings nicht, ich musste VBoxGuestAdditions_3.1.6.iso manuell in die VM herunterladen, über ein "mount -o loop" mounten, das Ubuntu-Paket dkms installieren, und dann das Shell-Skript VBoxLinuxAdditions-x86.run ausführen (Abbildung 9). Hierbei ist zu beachten, dass dies nicht mit Ubuntu-11 als Gastsystem funktioniert, wenn das Hostsystem noch Ubuntu-10.04 fährt.

Abbildung 9: Die Installation der "Guest Additions" erfordert einige Handarbeit.

Nach einem Neustart der VM kann dann der Host das Kommando VBoxManage guestproperty enumerate "Ubuntu 10.04" absetzen und erhält in einem Wust von weiteren Informationen die Zeile "Name: /VirtualBox/GuestInfo/Net/0/V4/IP, value: 192.168.0.135", was ihm die von der VM verwendete IP anzeigt. Wer statt "enumerate" ein "get" auf den oben gezeigten GuestInfo-Pfad absetzt, bekommt die IP der laufenden VM direkt übermittelt (Abbildung 10).

Abbildung 10: Die "Guest Properties" zeigen an, welche IP sich eine bestimmte VM vom DHCP-Server geholt hat.

Schornstein raucht

Falls CPAN-Module ihre Abhängigkeiten zu weiteren Modulen ordnungsgemäß angeben, erledigt eine CPAN-Shell die Installation ohne viel Federlesens. Leider vergessen Autoren allerdings manchmal, Module anzugeben, die sich auf ihrem Entwicklungsrechner befinden, aber blanken Perl-Installationen noch nicht beiliegen. Anwenderfrust ist die Folge.

Abhilfe schafft hier eine als VM-Snapshot festgehaltene frische Perl-Installation, die der Modul-Autor mit Hilfe des Skripts cpan-smoke in Listing 2 hochfährt, ihr einen gerade erzeugten CPAN-Distributions-Tarball übergibt und dort eine CPAN-Shell testen lässt, ob sich die neue Version auf einem jungfräulichen System mit CPAN-Anschluss installieren lässt. Läuft die dem Modul beiliegende Testsuite ohne Fehler durch? Dann gilt der sogenannte "Smoke Test" als bestanden und die Chancen stehen gut, dass das Modul sich gut auf ähnlichen Systemen installieren lässt.

Abbildung 11: Ein neuer Snapshot "CPAN Smoke" baut auf den "Guest Additions" auf und verfügt über eine konfigurierte CPAN-Shell.

Zweige im Snapshot-Baum

Hierzu konfiguriert der Entwickler in einer VM mit den "Guest Additions" eine CPAN-Shell, zieht davon einen Snapshot und nennt ihn "CPAN Smoke". Abbildung 11 zeigt, dass im Snapshot-Baum der VM "Ubuntu 10.04" nun zwei Zweige existieren, der anfangs erzeugten Snapshot "Browse" baut auf einer frischen Installation auf und existiert unabhängig von eventuell weiteren auf "CPAN Smoke" aufbauenden Snapshots.

Damit die Installation auch mit der Mini-CPAN-Shell cpanm im lokalen Verzeichnis klappt, hat der Snapshot "CPAN Smoke" das CPAN-Modul local::lib installiert, das in einem Ubuntu-System am besten durch das Kommando

    $ sudo apt-get install liblocal-lib-perl

durch den Package-Manager in die VM gelangt. Das Kommando

    $ eval $(/usr/bin/perl -Mlocal::lib)

in der Shell setzt dann die notwendigen Shell-Variablen für die Installation weiterer Module im lokalen Verzeichnis. So installiert sich auch die Mini-Shell lokal:

    $ cpan App::cpanminus

und anschließend steht das Kommando cpanm zur Installation weiterer Module im $PATH zur Verfügung:

    $ cpanm --version
    cpanm (App::cpanminus) version 1.4008

Wer genau mitverfolgen möchte, wie die Installation von App::cpanminus in einer frisch angelegten Ubuntu-Installation vonstatten geht, kann sich den Durchlauf im Screencast zum September-Perlsnapshot ansehen.

An dieser Stelle wird dann der Snapshot gezogen und "CPAN Smoke" benannt. Ruft man auf dem Host dann cpan-smoke mit einem Tarball eines mit "make tardist" erzeugten CPAN-Tarballs als Argument auf, restauriert das Skript den Snapshot, fährt die VM hoch und wartet bis dessen Netzwerkkonfiguration abgeschlossen ist und es auf ein "ping" reagiert. Das Kommando VBoxHeadless --startvm in Zeile 28 startet die VM ohne jegliche GUI-Ausgabe und wartet im Vordergrund, bis der User das Programm mit CTRL-C abschießt. Das CPAN-Modul Proc::Simple schickt es deshalb in den Hintergrund und merkt sich die PID, damit das am Ende des Skripts ausgelöste END-Snippet ab Zeile 29 seinen kill()-Befehl an das richtige Programm schickt und die kopflose VM herunterfährt.

Steigt Rauch auf?

Dann kopiert Zeile 55 den tarball ins /tmp-Verzeichnis der VM und Zeile 56 startet dort das Kommando cpanm tarball, das sich den Tarball schnappt, entpackt, und "make"-Kommandos zum Testen und zur Installation ausführt. Stößt cpanm auf CPAN-Module, von denen das Modul abhängt, lädt es diese selbständig vom CPAN und installiert diese ebenfalls.

Listing 2: cpan-smoke

    01 #!/usr/local/bin/perl -w
    02 use strict;
    03 use Sysadm::Install qw(:all);
    04 use Proc::Simple;
    05 use Net::Ping;
    06 use Log::Log4perl qw(:easy);
    07 
    08 my( $tarball) = @ARGV;
    09 
    10 die "usage: $0 tarball" if 
    11   !defined $tarball;
    12 
    13 Log::Log4perl->easy_init($ERROR);
    14 
    15 my $vbm    = "VBoxManage";
    16 my $vbh    = "VBoxHeadless";
    17 my $vm     = "Ubuntu 10.04";
    18 my $ippath = 
    19   "/VirtualBox/GuestInfo/Net/0/V4/IP";
    20 my $snap   = "CPAN Smoke";
    21 
    22   # in case it's up in foreground
    23 tap $vbm, "controlvm", $vm, "poweroff";
    24 tap $vbm, "snapshot", 
    25     $vm, "restore", $snap;
    26 
    27 my $proc = Proc::Simple->new();
    28 $proc->start("$vbh --startvm '$vm'");
    29 END {
    30     $proc->kill();
    31 }
    32 
    33 INFO "Waiting for VM to come up";
    34 
    35 while( !$proc->poll() ) {
    36     DEBUG "Waiting for VM process";
    37     sleep 1;
    38 }
    39 
    40 my $ip;
    41 
    42 while( !defined($ip = ip()) ) {
    43     DEBUG "Waiting for IP";
    44     sleep 1;
    45 }
    46 
    47 my $ping = Net::Ping->new();
    48 while( !$ping->ping($ip) ) {
    49     DEBUG "Waiting for Ping";
    50     sleep 1;
    51 }
    52 
    53 INFO "VM is up: $ip";
    54 
    55 tap "scp", $tarball, "$ip:/tmp/$tarball";
    56 sysrun "ssh", $ip, 
    57   qq{eval \$(/usr/bin/perl -Mlocal::lib); 
    58      cpanm /tmp/$tarball};
    59 
    60 tap $vbm, "controlvm", $vm, "poweroff";
    61 tap $vbm, "snapshot", 
    62     $vm, "restore", $snap;
    63 
    64 ###########################################
    65 sub ip {
    66 ###########################################
    67   my($stdout) = tap $vbm, "guestproperty", 
    68                     "get", $vm, $ippath;
    69 
    70   if( $stdout =~ /Value: (.*)/ ) {
    71     return $1;
    72   }
    73 
    74   return undef;
    75 }

Damit die Shell in der VM das Kommando cpanm findet, nach installierten Modulen im lokalen Pfad ~/perl5 sucht und dort neue Module ebenfalls installiert, setzt der ssh-Befehl in Zeile 56 vor dem eigentlichen cpanm-Kommando noch den weiter oben gezeigten eval-Befehl ab, der die erforderlichen Shell-Variablen setzt.

Die Ausgabe des Installationsskripts cpanm landet dank der sysrun-Funktion des Moduls Sysadm::Install auf der Standardausgabe des rufenden Skripts cpan-smoke, wo der sorgfältige Entwickler ablesen, kann wie seine neueste Kreation sich in einer fremden Umgebung schlägt. Falls Rauch aufsteigt, müssen wohl die definierte Abhängigkeiten zu anderen CPAN-Modulen untersucht werden.

Auch im Cloud-Zeitalter, in der VMs wie Amazons EC2 auf dem Internet zur Verfügung stehen, ist eine lokale Virtualisierungslösung wie VirtualBox noch attraktiv. Eine detaillierte Bedienungsanweisung für Neulinge bietet [3], allerdings beschreibt es die fast schon veraltete Version VirtualBox 3.1. Schnell mal 32 Dollar gezahlt und in Minuten auf den Kindle heruntergeladen spart das sauber redigierte Buch gegenüber weniger strukturierten Internetinhalten enorm Zeit.

Infos

[1]

Listings zu diesem Artikel: ftp://www.linux-magazin.de/pub/listings/magazin/2011/10/Perl

[2]

VirtualBox Project Page, http://www.virtualbox.org

[3]

"VirtualBox 3.1: Beginner's Guide", Alfonso V. Romero, Packt Publishing (April 15, 2010), Kindle Edition

Michael Schilli

arbeitet als Software-Engineer bei Yahoo! in Sunnyvale, Kalifornien. Er hat "Goto Perl 5" (deutsch) und "Perl Power" (englisch) für Addison-Wesley geschrieben und ist unter mschilli@perlmeister.com zu erreichen. Seine Homepage: http://perlmeister.com.