ProfitBricks Cloud API mit Python benutzen – Teil 4: VMs importieren

Montag, 7. November 2016, in Application Platform, von Jürgen Buchhammer

ProfitBricks stellt neben der einfach zu bedienenden GUI des Data Center Designers (DCD) eine Cloud API bereit, die nahezu den gleichen Funktionsumfang bietet. So können Aufgaben wie das Erfassen und Ändern verwendeter Ressourcen oder gar das Provisionieren ganzer Data Center automatisiert werden. In den vorangegangenen Teilen dieser Blog-Artikel-Reihe wurde gezeigt, wie man Informationen zu einer virtuellen Umgebung erhalten und virtuelle Ressourcen managen kann.

Dieser Artikel erklärt, wie die ProfitBricks Cloud API die Migration von virtuellen Maschinen verschiedener Virtualisierungslösungen zu ProfitBricks vereinfachen kann.

Wie für die vorangegangenen Artikel steht auch für diesen ein Beispielskript im ProfitBricks GitHub-Repository zur Verfügung.

VM-Formate

Die folgenden Image-Formate können bei ProfitBricks hochgeladen werden:

  • *.vmdk – VMware HDD-Images
  • *.vhd – HyperV HDD-Images
  • *.cow, *.qcow, *.qcow2 – Qemu HDD-Images
  • *.raw – binary HDD-Image
  • *.vpc – VirtualPC HDD-Image
  • *.vdi – VirtualBox HDD-Image

Wenn man virtuelle Maschinen (VM) aus einer anderen virtuellen Umgebung exportiert, enthalten diese Images meistens noch zusätzliche Dateien mit Metadaten. Diese Metadaten beschreiben Eigenschaften der VMs wie RAM oder sogar verbundene Netzwerkkarten.

Neben lösungsspezifischen internen Formaten wurde ein De-Facto-Standard geschaffen: das vom DMTF herausgegebene Open Virtualization Format (OVF). OVF ist ein offener Standard, der zum Beispiel von den folgenden Produkten unterstützt wird (eine ausführlichere Liste findet sich auf Wikipedia):

  • VirtualBox
  • VMware
  • Amazon Elastic Compute Cloud (AWS EC2)
  • IBM Cloud

Ein so genanntes OVF-Paket besteht aus einem Verzeichnis mit einer XML-basierten Beschreibungsdatei (*.ovf), typischerweise einem oder mehreren Disk-Images und eventuell einigen zusätzlichen Dateien. Ein OVF-Paket kann auch als OVA-Paket bereitgestellt  sein, welches einfach nur ein tar-Archiv des Verzeichnisses ist (mit der Dateiendung *.ova).

Im OVF-Format verpackte VMs importieren

In unserem Beispiel verwenden wir die folgenden Dateien:

  • ACME-VM.ovf
  • ACME-VM-disk1.vmdk
  • ACME-VM-disk2.vmdk
  • ACME-VM-disk3.vmdk

Zunächst muss man wissen, dass das Skript pb_importVM.py die VM-Dateien nicht hochlädt. Dieser Schritt muss manuell durchgeführt werden wie in der ProfitBricks Online-Hilfe beschrieben. Beim Hochladen der Image-Dateien an den Ort, wo später die VM erstellt werden soll, ist es wichtig darauf zu achten, dass die Namen der hochgeladenen Images nicht geändert werden.

Sobald das Hochladen beendet ist, kann das Skript pb_importVM.py verwendet werden, um die VM entsprechend der Daten in der Datei ACME-VM.ovf zu erstellen. Das Skript bietet für den Import folgende Optionen:

Man kann die Optionen -D <dcname> und -l <location> verwenden, um ein neues Data Center anzulegen. Die Option -d <datacenterid> erzeugt eine VM in einem bestehenden virtuellen Data Center.

Das Skript parst die spezifizierte Metadaten-Datei und erzeugt die VM in mehreren Schritten ähnlich dem im Teil 3 dieser Artikel-Reihe beschriebenen Ablauf:

  • Data Center erzeugen, sofern notwendig
  • Server erstellen
  • Netzwerkschnittstellen erzeugen
  • Volumes erzeugen
  • Volumes mit Server verbinden

Die Klasse OVFData ist dafür zuständig, die OVF-Datei unter Verwendung des Python-Moduls xml.etree.ElementTree zu parsen und die erforderlichen Informationen zu speichern.

Um eine OVF-Datei zu parsen, muss man lediglich die Methode parse()der Klasse OVFData aufrufen:

Die so gesammelten Daten werden in folgenden Feldern von OVFData gespeichert:

Systemdaten sammeln

Zunächst werden beim Parsen die Systemdaten aus folgenden Teilen der OVF-Datei gesammelt:

VM import - XML-System-Data

Der Name der VM wird aus dem Element <Name> ausgelesen:

Im Element <OperatingSystemSection> wird das Betriebssystem der VM mit Hilfe von ovf:id definiert. Wie diese ID genau auf ein bestimmtes Betriebssystem referenziert, kann man der DMTF-Dokumentation entnehmen. ID 101 referenziert beispielsweise auf Linux 64 Bit. Das zusätzliche Attribut vmw:osType ist eine VMware-Erweiterung von OVF, um den Namen des Betriebssystems einer VM zu beschreiben. Wir verwenden diese Hersteller-spezifischen Erweiterungen nicht, aber OVFData enthält drei Referenzlisten, in denen das Mapping bereits implementiert ist. Diese kann man ebenfalls dazu verwenden, den richtigen licenseType einer VM zu erhalten:

Die Anzahl der CPUs und die Menge an RAM kann man den entsprechenden <Item>-Elementen in <VirtualHardwareSection> entnehmen. Jede Hardware-Kategorie hat einen spezifischen ResourceType, den man in der DMTF-Dokumentation nachsehen kann. Um die Daten zu sammeln, müssen wir nur wissen, dass ResourceType 3 und 4 auf ‘Processor’ bzw. ‘Memory’ mappen. OVFData enthält die entsprechende Referenzliste resourceTypes für Informationszwecke.

Beim Sammeln von Daten auf obige Weise gilt es einiges zu beachten:

  • VMware erlaubt es, in <vmw:CoresPerSocket> die Anzahl der Cores je Prozessor zu definieren, was derzeit noch als Hersteller-spezifische Erweiterung ignoriert wird. Aus diesem Grund kann es passieren, dass die Anzahl der Cores falsch ist.
  • Im Gegensatz dazu wird der CPU-Typ (Intel oder AMD) in der OVF-Datei nicht angegeben.
  • <rasd:AllocationUnits> enthält die Einheit für die Mengen, z. B. ‘byte * 2^20’ für RAM. Das Skript geht derzeit davon aus, dass die Menge an RAM in MB (und für Festplatten in GB) angegeben wird.

Festplatten-Daten sammeln

Der nächste Schritt beim Parsen besteht darin, die Daten für die Festplatten aus folgenden Teilen der OVF-Datei auszulesen:

VM import - XML-Disk-Data

Die exportierten Festplatten-Dateien befinden sich außerhalb der OVF-Datei und werden im <References>-Element aufgelistet. Das ist daher einfach zu parsen:

Das <DiskSection>-Element listet alle virtuellen Festplatten auf und referenziert auf die Dateien im <References>-Element. <Disk> verwendet das Attribut ovf:capacity für die Kapazität der Festplatte, die in diesem Beispiel in GB gemessen wird. Wie zuvor bereits für RAM erwähnt, geht das Skript davon aus, dass die Kapazität in GB angegeben ist. <Disk> definiert auch das Attribut ovf:diskId, das benötigt wird, um eine Festplatte mit einer bestimmten VM in Verbindung zu bringen. (OVF erlaubt auch mehrere VMs in einer OVF-Datei.)

Die Festplatte einer VM kann man dem entsprechenden <Item>-Element in der <VirtualHardwareSection> entnehmen. In diesem Fall müssen wir ResourceType 17 finden. <rasd:HostResource> enthält die Referenz auf die Festplatten in <DiskSection> mit dem konstanten Präfix “ovf/disk” für die referenzierte ID. Die Reihenfolge der Festplatten wird vorgegeben durch <rasd:AddressOnParent>. In diesem Beispiel ist das Eltern-Element ein hier nicht aufgelisteter  SCSI-Controller, den man getrost ignorieren kann.

Im Code müssen nun noch die verschachtelten Referenzierungen aufgelöst werden, um eine sortierte Liste von Festplatten zu erhalten:

Mit dieser Prozedur erhalten wir eine sortierte Liste von Festplatten ähnlich dieser:

Netzwerkdaten sammeln

Der letzte Schritt beim Parsen besteht darin, Netzwerkdaten aus folgenden Teilen einer OVF-Datei zu beziehen:

VM import - XML-Network-Data

<NetworkSection> enthält ausschließlich die Namen verwendeter Netzwerke. Die Netzwerkkarten werden in den <Item>-Elementen mit ResourceType 10 festgelegt. Die <Items> schließen auch eine Referenzierung zum Netzwerk in <rasd:Connection> ein und können über <rasd:AddressOnParent> sortiert werden.

Beim Parsen der Netzwerke wird jedem Netzwerk eine LAN-ID in aufsteigender Reihenfolge hinzugefügt, da die Verwendung eines LAN-Namens bei ProfitBricks kein eindeutiges Kriterium darstellt:

Die LAN-ID des referenzierten Netzwerks wird auch den geparsten Netzwerkkarten hinzugefügt:

Mit dieser Prozedur erhalten wir eine sortierte Liste von Netzwerkkarten ähnlich dieser:

VM erzeugen

Wie bereits erwähnt, wird die VM in mehreren Schritten erstellt. Nach dem Parsen der OVF-Datei wird ein Data Center erzeugt, sofern noch keines vorhanden ist, oder die Location eines vorhandenen Data Centers bestimmt.

Danach werden alle Images geprüft, um ein eindeutiges Image für die Festplatten zu bekommen und dessen ID zu den Festplattendaten hinzuzufügen:

Die verbliebenen Aufgaben sind:

  • den Server zu erzeugen:

  • die NICs zu erzeugen:

  • die Volumes zu erzeugen:

  • die Volumes mit dem Server zu verbinden:

Die daraus resultierende VM sieht dann wie folgt aus:

VMs importieren - Ergebnis

VM konfigurieren

Nachdem die VM importiert worden ist, sollten noch einige Konfigurationen vorgenommen werden.

Wenn die VM nicht erfolgreich bootet, liegt das sehr wahrscheinlich an fehlenden virtio Treibern. Die Tutorials Migrate a VMware Virtual Machine Running Linux to ProfitBricks und Migrate a VMware Virtual Machine Running Windows to ProfitBricks geben eine detaillierte Beschreibung, wie dies behoben werden kann.

Wenn noch weitere VMs importiert werden sollen, muss sichergestellt werden, dass die Namen der hochgeladenen Images eindeutig sind. Wenn es Konflikte gibt, kann man das erreichen, indem die bereits verwendeten Images gelöscht oder die Disk-Images im DCD und in der OVF-Datei umbenannt werden.

Wie in obigem Screenshot ersichtlich, sind die NICs nicht mit anderen Ressourcen verbunden. Es sollten öffentliche und private LANs sowie DHCP-Einstellungen konfiguriert und gegebenenfalls zusätzliche VMs verbunden werden.

Abhängig vom Betriebssystem der VMs kann es aufgrund der geänderten MAC-Adressen erforderlich sein, die NICs im Betriebssystem zu konfigurieren.

Wie schon erwähnt, kann es sein, dass die Anzahl der Cores nicht korrekt ist, weil in der ursprünglichen VM einem Prozessor zwei oder mehrere Cores zugewiesen sind.

Natürlich kann man mit der ProfitBricks-Plattform Cores, RAM und mehr ganz nach Bedarf konfigurieren.

Referenzen und weiterführende Links

Hinterlasse eine Antwort

* Pflichtfeld

© 2012-2017 by ProfitBricks