Sonntag, 16. September 2018

Virtuelle Maschinen erzeugen und administrieren mit Powershell

Kennt Ihr das? Hilfe Texte stimmen nicht, Beschreibungen funktionieren nicht? Das Thema Powershell und VM ist auch damit ganz schlimm gebeutelt.

VM anlegen

Man kann eine leere VM anlegen, das ergibt ein relativ mageres Ergebnis:
1GB RAM, Generation 1, keine Disk.
New-VM –Name 'Test1'
Will man in etwa das Ergebnis, was der Hyper-V Manager Wizard nur mit der Eingabe "Name" erzeugt, muss man es so machen:
$vm = 'Test2'
New-VM –Name $vm –NewVHDPath "$vm.vhdx" -NewVHDSizeBytes 127GB
Bisher haben wir VMs der Generation 1 erzeugt.
Viel mehr als im nächsten Befehl, kann man bei New-VM gar nicht angeben.
$vm = 'Test3'
New-VM –Name $vm -Generation 2 –MemoryStartupBytes 4GB –NewVHDPath "$vm.vhdx" -NewVHDSizeBytes 32GB
Alles weitere muss man mit Set-VM* Befehlen machen.

Startmedien - DVD Laufwerk

Das wichtigste dabei (und nicht ganz einfach wie man denkt) wäre ja die Angabe von Start- bzw. Installationsmedien. Kaum noch existieren wirklich optische Laufwerke, das Handling am Hyper-V Server wäre extrem unpraktisch. Man kann ohne weiteres ISO oder VHD Images einbinden, aber nur wenn sie lokal auf dem Hyper-V Server liegen. Microsoft hat eine sehr eigenartige Sicherheit eingebaut, wenn es um den Zugriff auf ein Image geht, welches auf einem Server liegt.
Auch die hier beschriebenen Wege funktionieren bei mir nur in der manuellen Art für VMs der Generation 1!

Mein Resumé: Startmedien gehen nur lokal

Mag sein es funktioniert in AD Umgebungen, ich habe es in einer Workgroup versucht, und wirklich viel experimentiert, ich bekomme es nicht hin! Man kann auf dem Hyper-V Host ein Image mounten und sich einen Überblick von den Laufwerksbuchstaben ausgeben lassen.
Mount-DiskImage -ImagePath \\omv1\shares\ISO\de_windows_7_All_with_sp1_x64_.iso
Get-Volume|? DriveType -eq CD-ROM

Für VMs der Generation 1 kann man nun im Hyper-V Manager das physische Laufwerk auswählen und zuweisen. (Mit Set-VMDvdDrive kann man nur echte DVD Laufwerke zuweisen)

Bei VMs der Generation 2 kann man nur mit lokalen ISO Images arbeiten!
Mann muss zunächst ein DVD Laufwerk hinzufügen.
Add-VMDvdDrive -VMName $vm -Path D:\ISO\Name.iso
Mit Set-VMDvdDrive kann man lokale ISO Images zuweisen und ändern.

Konfiguration Netzwerk, Bootreihenfolge und Prozessor

Damit der Startvorgang nicht am PXE Boot "verhungert" sollte man noch die Boot Reihenfolge festlegen
$VMDVD=Get-VMDvdDrive -VMName $vm
Set-VMFirmware -VMName $vm -FirstBootDevice $VMDVD
Oder man legt die Reihenfolge neu fest, die neue vhdx Datei kann sowieso nicht booten, er sollte in dem Fall beim ersten Mal von der DVD starten
$VMHDD=Get-VMHardDiskDrive -VMName $vm
Set-VMFirmware -VMName $vm -BootOrder $VMHDD, $VMDVD
Will man den (einzigen) Netzwerk Adapter noch mit dem (einzigen) virtuellen, externen Switch verbinden, kann man das so machen
Connect-VMNetworkAdapter -VMName $vm -SwitchName (Get-VMSwitch|? Switchtype -eq External).Name
Während wir den mindest RAM bei der Einrichtung festgelegt haben, hat die VM bisher nur einen Prozessor. Man kann so alle verfügbaren Prozessoren zuweisen
Set-VMProcessor -VMName $vm -Count (Get-VMHost).LogicalProcessorCount

Zusammenfassung

Hier ein Template/Script für eine neue VM, Der VM Name kann als Parameter übergeben werden oder wird abgefragt (Mandatory=$true).
In der ersten und zweiten Zeile werden alle Parameter gesetzt. Ich habe deshalb auf übermäßig viele Variablen verzichtet.
<#
.SYNOPSIS 
    Das Script erstellt eine neue virtuelle Maschine
.DESCRIPTION 
    Das Script erstellt eine neue virtuelle Maschine
.EXAMPLE 
    CreateVM Name 
.NOTES 
    Generation 2, 32 GB HDD, 4 GB RAM, alle Prozessoren
#>
#region Params
param(
    [Parameter(Position=0, Mandatory=$true,HelpMessage="Name der VM",ValueFromPipeline=$false)]
    [System.String]
    $vm=""
)
#endregion 

New-VM –Name $vm -Generation 2 –MemoryStartupBytes 4GB –NewVHDPath "$vm.vhdx" -NewVHDSizeBytes 32GB
Add-VMDvdDrive -VMName $vm 
$VMDVD=Get-VMDvdDrive -VMName $vm
$VMHDD=Get-VMHardDiskDrive -VMName $vm
Set-VMFirmware -VMName $vm -BootOrder $VMHDD, $VMDVD
Connect-VMNetworkAdapter -VMName $vm -SwitchName (Get-VMSwitch|? Switchtype -eq External).Name
Set-VMProcessor -VMName $vm -Count (Get-VMHost).LogicalProcessorCount

Für die DVD habe ich mal noch einen "Würgaround" gefunden.
Dieser Mehrzeiler schaut nach, ob die ISO Datei im lokalen Pfad schon existiert und kopiert diese ansonsten dahin.
$DVD = "name.iso"
$Ziel = 'D:\ISO\'
$Quelle = '\\omv1\shares\iso\'
$Diff = Compare-Object -ReferenceObject (gci -Path $Ziel) -DifferenceObject (gci -Path $Quelle)
Copy-Item -Path (($Diff|? InputObject -like $DVD).InputObject).FullName -Destination $Ziel
# DVD einlegen
Set-VMDvdDrive -VMName $vm -Path $Ziel$DVD

Damit das lokale Verzeichnis nicht vermüllt, kann man ja von Zeit zu Zeit die ISOs entfernen, die nicht mehr eingebunden sind.
$Ziel = 'D:\ISO\'
$InUse = (Get-VMDvdDrive -VMName *|? Path -like $Ziel*).Path
$Exist = (gci -Path $Ziel).Fullname
$Diff = Compare-Object -ReferenceObject $Exist -DifferenceObject $InUse
Remove-Item ($Diff|? SideIndicator -eq '<=').InputObject -confirm

Aufräumen

Dieser Einzeiler löscht alle VMs und deren virtuelle HDDs, deren Name mit Test beginnt.
Jeder Löschvorgang verlangt nach Bestätigung! Bitte genau hinschauen, ich übernehme keine Verantwortung!
Ich hoffe, dass ich in einem Jahr noch weiß, wie dieser Einzeiler funktioniert.
% ist das Kürzel für ForEach, $_ Ist das aktuelle Element der Schleife
-process enthält den Ausführungsteil(, beide Befehlsteile werden in getrennten Schleifen abgearbeitet.)
-InputObject die Eingabe
% -process {Remove-Item (Get-VMHardDiskDrive -VMName $_.name).Path -Confirm ; Remove-VM -VMName $_.name} -inputobject (Get-VM -VMName Test*)

Informationen

Man kann sich relativ schnell einen Überblick über die Cmdlets verschaffen und detaillierte Hilfe abrufen. (Leider stimmt auch in den Hilfetexten nicht alles)
Get-Help Hyper-V
Get-Help Set-VM*

Keine Kommentare:

Kommentar veröffentlichen