Tags: VHD, Hyper-V, PowerShell
Die x86-Virtualisierung erlaubt das Anlegen von virtuellen Maschinen mit wenigen Mausklicks. Entsprechend schnell vermehrt sich in vielen Umgebungen die Zahl der virtuellen Laufwerke. PowerShell kann helfen, den Überblick über die vorhandenen VHD(X)-Dateien zu bewahren.
Ein unkontrolliertes Wachstum von VMs stellt unter anderem ein Storage-Problem dar, wenn die virtuellen Maschinen nicht mehr genutzt werden, aber ihre Laufwerke weiterhin Platz belegen. Besonders schwer sind solche Platzverschwender zu entdecken, wenn VHD(X)-Dateien verwaist sind, also zu keiner VM mehr gehören (siehe dazu: Nicht verwendete VHDs in Hyper-V finden mit PowerShell).
Liste von VHDs abrufen
Auch unabhängig von solchen Zombie-VHDs ist es interessant zu wissen, wie viele VHDs die Speichersysteme bevölkern, wie viel Platz sie belegen und über welche Verzeichnisse sie verstreut sind.
Für die meisten Abfragen benötigt man erst eine Liste aller VHD(X). Diese könnte man natürlich bekommen, indem man die Standardverzeichnisse für Hyper-V mit Get-ChildItem ausliest. Aber nachdem gerade auch VHDs an unerwarteten Orten entdeckt werden sollen, empfiehlt sich der Einsatz von Cmdlets aus dem Modul Hyper-V, die ihre Daten aus der VM-Konfiguration extrahieren.
Dazu gibt man im ersten Schritt folgenden Befehl ein:
$VHDs = Get-VM | select VMID | Get-VHD
Er ermittelt mit Get-VM alle VMs auf dem aktuellen Host (einen Remote-Host könnte man über den Parameter -ComputerName angeben) und ruft anhand ihrer IDs mit Get-VHD die Liste der ihnen zugeordneten virtuellen Laufwerke ab. Der Befehl
($VHDs).count
informiert anschließend darüber, wie viele (A)VHD(X)-Dateien insgesamt gefunden wurden.
VHD-Verzeichnisse anzeigen
Will man nun wissen, ob sich VMs entgegen der Best Practices für Hyper-V noch im Standardverzeichnis (also auf dem Systemlaufwerk im Profil des Users Public) befinden, dann kann man dies auf folgende Weise überprüfen:
$VHDs | ? Path -like "C:\Users\Public\*" | select Path
Dieses Kommando verwendet das Alias "?" für Where-Object, um Tipparbeit zu sparen. Es gibt den vollständigen Pfad inklusive Dateiname für alle VHD(X) aus, die sich unterhalb von C:\Users\Public befinden.
Möchte man eine Übersicht über alle Verzeichnisse bekommen, in denen sich virtuelle Laufwerke befinden, dann hilft dieser Aufruf:
($VHDs | select path).path -replace "[^\\]*\.a?vhdx?","" | sort -Uniq
Die Ergebnisse dürften auf vielen Rechnern einige Überraschungen bergen, besonders dann, wenn man die Import- und Exportfunktion für VMs häufig nutzt.
Die Eigenschaft Path enthält auch den Dateinamen der VHD(X), den man aber nicht gebrauchen kann, wenn man nur eine Liste der Verzeichnisse haben möchte. Der reguläre Ausdruck nach dem replace-Operator entfernt ihn deshalb. Der Aufruf von sort -uniq eliminiert Dubletten, so dass jeder Pfad nur einmal in der Liste vorkommt.
Platzverbrauch von VHDs berechnen
Eine sicher interessante Information ist jene über den Platzverbrauch der virtuellen Laufwerke. Möchte man wissen, wie viele GB von den VHD(X) insgesamt belegt werden, dann lässt sich das mit
$VHDs | %{$FS += $_.FileSize}; $FS/1GB
herausfinden. Dieser Befehl iteriert über alle Elemente von $VHDs, summiert die Dateigrößen der einzelnen virtuellen Laufwerke in der Variablen $FS auf und rechnet sie schließlich in GB um.
Will man die Abfrage auf jene VHD(X) reduzieren, die inaktiven VMs zugeordnet sind und daher aktuell nicht verwendet werden, dann modifiziert man den Aufruf folgendermaßen:
$VHDs | ? Attached -eq $false | %{$FS += $_.FileSize}; $FS/1GB
Verwendet man die Variable $FS nachfolgend in weiteren Befehlen, dann ist daran zu denken, dass man sie vorher durch
$FS = 0
zurücksetzt.
VHDs nach Größe sortieren
Eine Übersicht über die größten Verbraucher von Speicherplatz erhält man, wenn man die Liste der VHD(X) nach Größe sortiert anzeigt:
$VHDs | sort -Des -Prop FileSize | select Path, @{Name="GByte";Expression={$_.FileSize/1GB}}
VHD von VHDX unterscheiden
Das Cmdlet Get-VHD liefert noch weitere Daten über virtuelle Laufwerke, die man sich zunutze machen kann. So möchte man vielleicht wissen, welche VMs noch VHDs anstatt des neueren und leistungsfähigeren VHDX-Formats verwenden. Dies ließe sich zwar auch über die Dateiendung herausfinden, aber diese Methode ist zuverlässiger:
$VHDs | ? VHDFormat -eq "VHD"
Dynamische, fixe oder differenzielle VHD?
Eine weitere aufschlussreiche Information ist der VHD-Typ. Wenn man etwa VMs von einer Testumgebung auf produktive Systeme übernommen hat und dort nur VHDs fester Größe verwenden will, dann kann man sich anzeigen lassen, ob auf die Konvertierung einzelner Laufwerke vergessen wurde:
$VHDs | ? VhdType -eq "Dynamic"| Select Path
Fragmentierung analysieren
Schließlich informiert eine dafür vorgesehene Eigenschaft über den Grad der Fragmentierung von VHDs, so dass man Hinweise darauf bekommt, wo eine Defragmentierung erforderlich ist:
$VHDs | select Path, FragmentationPercentage | Out-GridView
Dieser Aufruf schickt die Ausgabe an das Cmdlet Out-GridView, das die Daten in einer Tabelle auf der grafischen Oberfläche anzeigt und sie damit besser konsumierbar macht. Wenn das Komprimieren von VHD(X) notwendig sein sollte, dann findet sich die zuständige Funktion im Hyper-V Manager unter Datenträger bearbeiten.
Täglich Know-how für IT-Pros mit unserem Newsletter
Verwandte Beiträge
- Ungenutzte VHDX in Hyper-V finden mit PowerShell
- 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