Logo faq-o-matic.net
Logo faq-o-matic.net

Hyper-V-VM als Vorlage ex- und importieren

von veröffentlicht am5. April 2017, 07:37 Uhr Kurzlink und Zitatlink einblenden
Kategorie Kategorie: PowerShell, Virtualisierung, Windows   Translate with Google Translate Translate EN   Die angezeigte Seite drucken

Hyper-V bringt kein System zum Verwalten von VM-Vorlagen mit. Mit separaten Produkten (z.B. System Center Virtual Machine Manager oder 5Nine Manager) lässt sich so eine Funktion ergänzen. Man kann sie aber für “kleine Zwecke” auch mit Bordmitteln ersetzen.

Viele Admins behelfen sich, indem sie einfach den wichtigsten Teil einer VM als Basis-Vorlage speichern, nämlich die virtuelle Festplatte. Der Weg ist simpel: Man installiert eine VM und konfiguriert das Gast-Betriebssystem so, wie man es braucht. Als letzten Schritt führt man sysprep aus, beendet die VM und legt die VHD(X)-Datei schreibgeschützt an eine separate Stelle. Die VM kann man dann löschen (oder gleich als erste neue VM auf Basis der Vorlage verwenden). Braucht man nun eine VM auf Grundlage des erzeugten Templates, so definiert man eine neue VM und kopiert die Vorlagen-VHDX an die passende Stelle.

Dies lässt sich noch erweitern, indem man auch die eigentliche VM als Vorlage speichert. Dadurch hat man dann auch gleich die virtuelle Hardware vordefiniert und spart sich den manuellen Schritt, die VM-Hülle neu einzurichten. Dabei hilft eine Funktion, die es schon seit der ersten Hyper-V-Version von Windows Server 2008 gibt, die seit einigen Jahren aber in Vergessenheit geraten ist. Hyper-V ermöglicht nämlich den VM-Export ohne virtuelle Festplatte, also nur die Konfiguration der VM. Früher gab es diese Funktion im grafischen Hyper-V Manager, doch seit einigen Jahren ist sie nur noch programmatisch erreichbar.

Hier kommt eine PowerShell-Lösung ins Spiel, die ich im Folgenden vorstelle.

Der folgende Artikel im TechNet-Wiki beschreibt, wie man eine Hyper-V-VM “config-only” exportiert. Das dortige Skript nutzt WMI, um diesen Export auszuführen.

[Hyper-V: Export VM Config-Only Using PowerShell – TechNet Articles – United States (English) – TechNet Wiki]
https://social.technet.microsoft.com/wiki/contents/articles/1350.hyper-v-export-vm-config-only-using-powershell.aspx

Ich habe das Skript etwas erweitert, um es komfortabler zu machen:

#################
# Export-VMConfigOnly.ps1
# exports only a VM's configuration without the virtual hard disk files
# based on http://social.technet.microsoft.com/wiki/contents/articles/1350.hyper-v-export-vm-config-only-using-powershell.aspx
# Nils Kaczenski, faq-o-matic.net, 2016-12-21
#################

$SourceVM = Read-Host 'Specify the name of the VM to export'
$expDir = Read-Host 'Specify the target root path for the export (VM name will be appended)'

$ns = 'root\virtualization\v2'

$expDir = $expDir + $SourceVM
if( -Not (Test-Path -Path $expDir ) )
{
    New-Item -ItemType directory -Path $expDir | Out-Null
}
 
#Get VM Object
$vm = gwmi -n $ns Msvm_ComputerSystem | ?{$_.ElementName -eq $SourceVM} 
 
#Get export setting object
$exp = @($vm.GetRelated('Msvm_VirtualSystemExportSettingData'))[0]
 
#If you dont want to copy the VHDs and AVHDs
$exp.CopyVmStorage = $false
 
#If you dont want to copy the Saved state
$exp.CopyVmRuntimeInformation = $false
 
#Get VMMS object
$vmms = gwmi -n $ns Msvm_VirtualSystemManagementService
 
#Perform Export
$out = $vmms.ExportSystemDefinition($vm.Path.Path, $expDir, $exp.GetText(1))
 
#Perform Job handling if necessary
if ($out.ReturnValue -eq 4096)
{
       $task = [Wmi]$out.Job;
       while($task.JobState -eq 3 -or $task.JobState -eq 4)
       {
              $task.Get();
              sleep 1;
       }
       if ($task.JobState -ne 7)
       {
              "Error exporting VM " + $task.ErrorDescription;
       }            
       else
       {
              "Export completed successfully..."
       }     
      
}
elseif ($out.ReturnValue -ne 0)
{
       "Export failed with error : " + $out.ReturnValue;
}
else
{
       "Export completed successfully."
} 

Skript: Export-VMConfigOnly.ps1, exportiert nur die Konfiguration einer VM

Den so erzeugten Export kann man nun als VM-Vorlage verwenden. Um auch diesen Vorgang komfortabler zu machen, habe ich ein zweites Skript gebaut. Es fragt nach der Konfigurationsdatei der Vorlage und nach dem Namen für die neue VM. Die Vorlage selbst muss man nicht über den oben gezeigten Export erzeugen, prinzipiell eignet sich auch eine vorhandene oder eine schlicht kopierte VM. Der Kniff besteht nun darin, dass das Skript prüft, ob zu der angegebenen Vorlagen-VM virtuelle Festplatten gehören. Ist dies nicht der Fall, so entfernt es aus der neuen VM die Verweise auf die VHD(X)-Dateien, sodass die reine Hülle übrig bleibt. Im letzten Schritt kopiert man nun die Sysprep-VHD(X)-Dateien an die passende Stelle und bindet sie in die VM ein.

#############
# Import-VMFromTemplate.ps1
# Imports a VM by copying the original data and renaming the object afterwards
# thus, the original VM (which may have been exported) serves as a template
# if the export folder does not contain VHD or VHDX files all disks will be removed from the imported VM!
# Nils Kaczenski, faq-o-matic.net, 2016-12-21
#############

$SourceVM = Read-Host 'Enter the path of the source VM config file (XML or VMCX)'
$SourceVM = $SourceVM.Replace('"','') # remove quotes as Test-Path doesn't like them
if( -Not (Test-Path -PathType Leaf $SourceVM) )
{
    'File not found. Exiting script.'
    return
}

$TargetVMName = Read-Host 'Enter the name of the new VM to be created'
$TargetVMPath = Read-Host 'Enter the root path to store the new VM (VM name will be appended)'
$TargetVMPath = $TargetVMPath + '\' + $TargetVMName

# create the target folder if it does not exist
if( -Not (Test-Path -Path $TargetVMPath ) )
{
    New-Item -ItemType directory -Path $TargetVMPath | Out-Null
}


$NewVM = Import-VM -Path $SourceVM -Copy -VirtualMachinePath $TargetVMPath -GenerateNewId
Rename-VM $NewVM -NewName $TargetVMName
"VM imported as $NewVM"

# check if the export contains Virtual Hard Disks
$SourceVHDPath = (Get-Item $SourceVM).Directory.Parent.FullName + '\Virtual Hard Disks\*.vhd*'
if (!(Test-Path $SourceVHDPath)) { 
    # no, it does not - thus remove VHD bindings from the VM
    Get-VMHardDiskDrive $NewVM | Remove-VMHardDiskDrive
    'VM virtual hard disks have been removed as there were none in the export data.'
}

$NewVM | fl *

Skript: Import-VMFromTemplate.ps1, importiert die Konfiguration einer VM

Hier der Download:

Download: Import-VMFromTemplate  Import-VMFromTemplate (1,9 KiB, 903-mal heruntergeladen, letzte Änderung am 20. März 2017)

© 2005-2023 bei faq-o-matic.net. Alle Rechte an den Texten liegen bei deren Autorinnen und Autoren.

Jede Wiederveröffentlichung der Texte oder von Auszügen daraus - egal ob kommerziell oder nicht - bedarf der ausdrücklichen Genehmigung durch die jeweiligen Urheberinnen oder Urheber.

Das Impressum findet sich unter: http://www.faq-o-matic.net/impressum/

Danke, dass du faq-o-matic.net nutzt. Du hast ein einfaches Blog sehr glücklich gemacht!