Tags: VHD, Hyper-V, PowerShell
Wenn man im Hyper-V Manager eine virtuelle Maschine löscht, dann wird nur die Konfiguration entfernt und die virtuellen Datenträger bleiben erhalten. Wenn man diese nicht gleich manuell beseitigt, dann sammeln sich verwaiste VHDs an. Wenn man den Überblick verloren hat, welche virtuellen Festplatten noch einer VM zugeordnet sind, dann kann man das mit PowerShell herausfinden.
Ein Vorzug von VMs besteht darin, dass man virtuelle Datenträger sehr einfach erstellen und (während der Laufzeit) hinzufügen kann. Ebenso einfach lassen sich wieder von der virtuellen Maschine trennen. Geraten sie danach in Vergessenheit, können sie aufgrund der zumeist üppigen Dateigröße viel Speicherplatz blockieren.
Hyper-V Manager zeigt VHDs pro VM
Der Hyper-V Manager zeigt für einzelne VMs an, welche VHDs mit ihnen verknüpft sind. Eine umgekehrte Sicht, aus der zu erkennen wäre, welche virtuellen Datenträger welcher VM zugeordnet sind, bietet er nicht.
Diese Informationen könnte man erhalten, indem man die im XML-Format vorliegenden Konfigurationsdateien ausliest und die Angaben zu virtuellen Datenträgern ausfiltert. Einfacher geht es jedoch mit dem Cmdlet Get-VMHardDiskDrive, das die VHDs einer oder mehrerer VMs auflistet.
Die folgende Lösung des Problems liest die Namen aller virtuellen Datenträger von sämtlichen auf einem Host existierenden VMs in eine Variable ein und vergleicht sie anschließend mit jenen VHDs, die Get-ChildItem im Verzeichnissystem findet. Zur Ausführung der Befehle muss man PowerShell mit administrativen Rechten starten.
Verwendete VMs auflisten
Im ersten Schritt erfasst der Befehl mit Get-VM alle VMs auf dem lokalen Host, ermittelt dann deren VHDs und extrahiert daraus deren Dateinamen inklusive Pfadangabe. Sie werden in der Variable $VM-VHDs gespeichert:
$VMVHDs = Get-VM | Get-VMHardDiskDrive | Select path | %{$_.path}
Anschließend benötigen wir zum Vergleich die Liste aller auf der Platte vorhandenen virtuellen Datenträger. Das Beispiel hier führt Get-ChildItem (bzw. dessen Alias gci) im VHD-Standardverzeichnis von Hyper-V aus. Dieses lässt sich mit folgendem Aufruf ermitteln und in der Variablen $vhdpath ablegen:
$vhdpath = Get-VMHost | Select virtualharddiskpath
Der nächste Befehl speichert die Dateinamen der VHDs, die Get-ChildItem findet, inklusive Pfadangabe in der Variablen $VHDs:
$VHDs = gci $vhdpath.VirtualHardDiskPath -Filter *.vhd? | %{$_.fullname}
Listen vergleichen
Schließlich bleibt nur noch die Aufgabe, die beiden Listen zu vergleichen. Dies lässt sich recht einfach mit Hilfe von Compare bewerkstelligen:
Compare $VMVHDs $VHDs | fl
Die Ausgabe des Befehls zeigt nur VHDs, die nicht in beiden Listen vorkommen. Das sind also solche, die von VMs verwendet werden, aber außerhalb des Standardverzeichnisses liegen oder (versehentlich) gelöscht wurden.
In diesem Fall zeigt der Pfeil des SideIndicator von Compare nach links, weil sie nur in der Liste von $VMVHDs vorkommen. Bei einem solchen Ergebnis könnte man den Aufruf von gci um weitere VHD-Verzeichnisse ergänzen, um zusätzliche Speicherorte zu berücksichtigen.
Umgekehrt liegen verwaiste VHDs vor wenn, der SideIndicator zur Variablen $VHDs, also nach rechts zeigt. Das bedeutet, dass sie Einträge enthält, die in der Liste der verwendeten VHDs nicht vorkommen.
Täglich Know-how für IT-Pros mit unserem Newsletter
Verwandte Beiträge
- VHDs auslesen mit PowerShell: Größe, Speicherort, Typ, Fragmentierung
- VMs in Hyper-V mit PowerShell erstellen und konfigurieren
- Virtuelle Maschine vollständig mit PowerShell erstellen (am Beispiel von Azure Stack HCI)
- Windows-Features offline in einer virtuellen Maschine installieren
- Virtuelle Maschinen unter Hyper-V von Generation 1 auf 2 konvertieren
Weitere Links