VM-Custom-Attribute zwischen vCentern migrieren mit PowerCLI

Bei vCenter-Migrationen oder Cluster-Umzügen gehen benutzerdefinierte Attribute (Custom Attributes) oft verloren, weil sie nicht zum VM-Inventar gehören, sondern als Metadaten am vCenter-Objekt gespeichert sind. Wer hunderte VMs betreut, kann diese nicht händisch nachpflegen. PowerCLI bietet hier eine saubere Automatisierung: Export der Attributdefinitionen und -werte auf dem Quell-vCenter, Erstellung fehlender Attribute auf dem Ziel-vCenter und anschließendes Befüllen der Werte.

Export: Definitionen und Werte sichern

Zuerst wird die Verbindung zum Quell-vCenter hergestellt. Die Attributdefinitionen (Namen, Zieltypen) lassen sich mit Get-CustomAttribute abrufen und in eine CSV schreiben:

Connect-VIServer -Server vc-source.example.com
$attList = Get-CustomAttribute -TargetType VirtualMachine
$attList | Export-Csv ".\exported-attributes.csv" -NoTypeInformation -Encoding UTF8 -Delimiter ";"

Für die eigentlichen Werte iteriert man effizient über alle VMs eines Clusters (oder per Get-VM über den gesamten Bestand) und nutzt den Enumerator der CustomFields-Property:

$valueList = foreach ($vm in (Get-Cluster "CL01" | Get-VM)) {
    foreach ($cf in $vm.CustomFields.GetEnumerator()) {
        [PSCustomObject]@{
            VMname     = $vm.Name
            FieldKey   = $cf.Key
            FieldValue = $cf.Value
        }
    }
}
$valueList | Export-Csv ".\exported-attributes-value.csv" -NoTypeInformation -Encoding UTF8 -Delimiter ";"
Disconnect-VIServer -Server * -Confirm:$false

Der Enumerator vermeidet Index-Zugriffe auf Keys/Values-Arrays und liefert direkt Key-Value-Paare.

Import: Attribute anlegen und Werte setzen

Auf dem Ziel-vCenter werden zunächst die Definitionen eingespielt. Fehlende Attribute werden per New-CustomAttribute angelegt, vorhandene bleiben unberührt:

Connect-VIServer -Server vc-dest.example.com

$data = Import-Csv ".\exported-attributes-value.csv" -Delimiter ";" -Encoding UTF8

$existing = Get-CustomAttribute -TargetType VirtualMachine -ErrorAction SilentlyContinue |
            Select-Object -ExpandProperty Name

$data.FieldKey | Sort-Object -Unique | Where-Object { $_ -notin $existing } | ForEach-Object {
    New-CustomAttribute -Name $_ -TargetType VirtualMachine | Out-Null
    Write-Host "Created attribute: $_"
}

Anschließend werden die Werte VM-weise gesetzt. Leere Werte werden übersprungen, nicht gefundene VMs protokolliert:

foreach ($vmGroup in ($data | Where-Object { $_.FieldValue } | Group-Object VMname)) {
    $vm = Get-VM -Name $vmGroup.Name -ErrorAction SilentlyContinue
    if (-not $vm) {
        Write-Warning "VM not found: $($vmGroup.Name)"
        continue
    }
    foreach ($line in $vmGroup.Group) {
        Set-Annotation -Entity $vm -CustomAttribute $line.FieldKey -Value $line.FieldValue | Out-Null
    }
    Write-Host "Done: $($vm.Name)"
}

Disconnect-VIServer -Server * -Confirm:$false

Set-Annotation ist das moderne Pendant zu Set-CustomField und arbeitet direkt mit dem VM-Objekt, was Performanz und Fehlerbehandlung verbessert. Die Gruppierung nach VM-Namen minimiert Get-VM-Aufrufe.

Praktische Hinweise

Die Skripte sind idempotent: Wiederholter Import ändert nur Werte, die sich unterscheiden, und legt keine doppelten Attribute an. So lässt sich der Prozess gefahrlos in Migrationsfenster oder Automatisierungspipelines einbauen.

Die vollständigen Scripte sind ebenfalls unten zum Download verlinkt.

Referenzen

Das könnte dich auch interessieren

rchlt

© 2026

LinkedIn GitHub PayPal