Jednym z nietypowych wymagań w środowiskach DR (Disaster Recovery) jest możliwość szybkiego przeniesienia dysków VMDK między maszynami wirtualnymi — bez niszczenia danych, bez klonowania, bez długich okien serwisowych. W tym artykule pokażę zestaw skryptów PowerCLI, które pozwalają zautomatyzować ten proces w całości: od przygotowania mapowania CSV, przez migrację dysków, aż po walidację wyników. Nie jest to może najlepszy sposób na DR ale jest to jeden z wielu kroków i potrzebne to było na potrzeby opracowania DRu dla z jednej aplikacji klenta i jak wspomnialem wczesniej to tylko jeden z kroków.
Kod dostępny jest na GitHubie: github.com/sebastiangrugel/PowerCLI — VMDK-reattachment
Problem — po co w ogóle przepinać VMDK?
W typowym scenariuszu failover/failback mamy dwie maszyny wirtualne:
- VM-PROD01 — maszyna produkcyjna z dyskami z danymi
- VM-DR01 — maszyna DR, która ma własny dysk systemowy, ale w stanie normalnym nie ma podpiętych dysków z danymi
Gdy ogłaszamy failover, chcemy:
- Odpiąć dyski danych od VM-PROD01 (bez kasowania pliku VMDK)
- Podpiąć te same dyski do VM-DR01 na konkretnych pozycjach SCSI
- Uruchomić VM-DR01 — system widzi dyski tak, jakby zawsze tam były
Po zakończeniu awarii — failback: operacja odwrotna, te same skrypty, zmienione tylko parametry -source i -target.
Kluczowe ograniczenie vSphere: nie można po prostu „przeciągnąć” dysku w GUI na konkretną pozycję SCSI:UNIT. Wysokopoziomowe cmdlety PowerCLI (Add-HardDisk) nie pozwalają wybrać konkretnego slotu. Jedynym sposobem jest bezpośrednie użycie VIM API przez ReconfigVM_Task — dokładnie to robią poniższe skrypty.
Wymagania wstępne
# Zainstaluj moduł PowerCLI (jednorazowo)
Install-Module VMware.PowerCLI -Scope CurrentUser
# Połącz się z vCenter przed uruchomieniem jakiegokolwiek skryptu
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false
Connect-VIServer -Server vcenter.twojadomena.local -User administrator@vsphere.local -Password <haslo>
# Weryfikacja połączenia
$global:DefaultVIServer
Wszystkie skrypty wymagają aktywnej sesji $global:DefaultVIServer.
Architektura rozwiązania
Zestaw składa się z czterech skryptów, które współpracują ze sobą:
| Skrypt | Rola |
|---|---|
export-vm-disk-config.ps1 |
Generuje plik CSV z aktualnego układu dysków maszyny wirtualnej |
reattaching-vmdk-v2.ps1 |
Główny skrypt migracji — odpina dyski ze źródła i podpina do celu wg CSV |
cmd-validation.ps1 |
Waliduje stan obu VM względem CSV — wynik pass/fail per dysk |
create-test-disks.ps1 |
Tworzy testowe dyski z losowym rozmieszczeniem SCSI (do testów laboratoryjnych) |
Format CSV — centralny element łączący wszystkie skrypty:
Source VM vSphere Controller,Source VM vSphere UNIT,Target VM vSphere Controller,Target VM vSphere UNIT
0,1,0,1
1,0,1,0
2,13,2,13
Każda kolumna to numer magistrali SCSI (0–3) oraz numer jednostki na tej magistrali. vSphere wewnętrznie używa ControllerKey = 1000 + BusNumber — np. SCSI bus 2 to klucz 1002. Unit 7 jest zawsze zarezerwowany przez vSphere jako SCSI initiator i nigdy nie powinien pojawić się w CSV.
Skrypt 1 — export-vm-disk-config.ps1
Zanim przepiszesz cokolwiek ręcznie, użyj tego skryptu do wygenerowania CSV bezpośrednio z aktualnego układu dysków maszyny produkcyjnej.
Parametry
| Parametr | Wymagany | Domyślnie | Opis |
|---|---|---|---|
-vmName |
Tak | — | Nazwa maszyny wirtualnej |
-outputCsvPath |
Nie | .\reattaching-vmdk-configuration.csv |
Ścieżka do wygenerowanego pliku CSV |
-excludeBootDisk |
Nie | $true |
Pomija dysk systemowy SCSI 0:0 |
Użycie
# Generuj CSV z VM-PROD01 (dysk startowy pomijany domyślnie)
.\export-vm-disk-config.ps1 -vmName VM-PROD01
# Własna ścieżka wyjściowa
.\export-vm-disk-config.ps1 -vmName VM-PROD01 -outputCsvPath .\prod-layout.csv
Przykładowy output
VM : VM-PROD01 | Power: PoweredOff
Output : .\reattaching-vmdk-configuration.csv
Boot disk : excluded (SCSI0:0)
Disk inventory on VM-PROD01:
Name CapacityGB SCSI Bus Unit Include UUID
Hard disk 1 0.00 0 0 SKIP (boot) 6000C296-32ce-bfdf-...
Hard disk 2 2.00 0 1 YES 6000C29d-e5de-223b-...
Hard disk 3 2.00 1 0 YES 6000C295-e19a-e4df-...
...
Exported : 18 disk(s)
Skipped : 1 disk(s) (boot disk excluded)
Wygenerowany CSV ustawia source = target (ta sama pozycja). Jeśli na maszynie DR dyski mają lądować na innych slotach — edytujesz kolumny Target ręcznie przed migracją.
Uwaga techniczna: ścieżka zaczynająca się od \filename.csv (bez litery dysku) jest przez PowerShell interpretowana jako korzeń dysku (np. E:\filename.csv). Skrypt wykrywa ten przypadek i kotwi ścieżkę do bieżącego katalogu roboczego.
Skrypt 2 — reattaching-vmdk-v2.ps1
Serce całego rozwiązania. Przepina dyski VMDK między maszynami wirtualnymi zgodnie z mapowaniem w CSV, używając bezpośrednio VIM API.
Parametry
| Parametr | Wymagany | Opis |
|---|---|---|
-source |
Tak | Nazwa VM, z której odpinaemy dyski |
-target |
Tak | Nazwa VM, do której podpinamy dyski |
-csvPath |
Tak | Ścieżka do pliku CSV z mapowaniem |
Użycie
# Failover: przenieś dyski z produkcji na DR
.\reattaching-vmdk-v2.ps1 -source VM-PROD01 -target VM-DR01 -csvPath .\reattaching-vmdk-configuration.csv
# Failback: przywróć dyski z DR na produkcję
.\reattaching-vmdk-v2.ps1 -source VM-DR01 -target VM-PROD01 -csvPath .\reattaching-vmdk-configuration.csv
Przepływ wykonania krok po kroku
- Rozwiązuje obie maszyny wirtualne (
Get-VM) - Wyświetla aktualny stan obu VM — kontrolery SCSI, dyski, UUID
- Pokazuje planowane mapowania z CSV
- Pyta o potwierdzenie: Proceed with disk migration? (yes/no)
- Robi snapshot typów kontrolerów SCSI na źródle (potrzebne do odtworzenia po migracji)
- Tworzy brakujące kontrolery SCSI na maszynie docelowej
- Dla każdego wiersza CSV: lokalizuje dysk na źródle → odpina → podpina do celu na wskazanej pozycji
- Odtwarza kontrolery SCSI na źródle (vSphere automatycznie usuwa puste kontrolery gdy odpiął się ostatni dysk)
- Wyświetla stan obu VM po migracji
- Na końcu drukuje łączny czas wykonania (minuty i sekundy)
Przykładowy output
Log : E:\Scripts\VMDK-reattachment\log\log_20260529_143022.log
Resolving VMs...
Source : VM-PROD01
Target : VM-DR01
=== Pre-run State ===
...
Proceed with disk migration? (yes/no): yes
Required SCSI controllers on target: 0, 1, 2
SCSI controller BusNumber=1 already present on VM-DR01.
Creating SCSI controller BusNumber=2 (ParaVirtualSCSIController) on VM-DR01...
-> Done.
Processing disk mappings...
[VM-PROD01 SCSI0:1] -> [VM-DR01 SCSI0:1]
Path : [DatastoreNFS01] VM-PROD01/VM-PROD01_1.vmdk (2 GB)
Detaching from VM-PROD01...
Attaching to VM-DR01 at SCSI0:1...
OK.
Restoring vacated SCSI controllers on source (VM-PROD01)...
BusNumber=1 was auto-removed — recreating as ParaVirtualSCSIController...
-> Done.
=== Post-run State ===
...
Completed in 2 min 14 sec.
Kluczowe aspekty techniczne
Dlaczego VIM API zamiast cmdletów PowerCLI? Wysoko-poziomowe polecenie Add-HardDisk nie pozwala wybrać konkretnego ControllerKey i UnitNumber. Jedynym sposobem jest bezpośrednie wywołanie ReconfigVM_Task przez $vmView.ReconfigVM_Task($vmConfigSpec).
Dlaczego $null = Get-Task | Wait-Task? Wait-Task zwraca obiekt zrekonfigurowanej maszyny wirtualnej. Bez przechwycenia go do $null obiekt trafia do strumienia wyjściowego PowerShell i psuje kolejne wywołania Format-Table.
Automatyczne usuwanie pustych kontrolerów przez vSphere: gdy ostatni dysk opuszcza kontroler SCSI, vSphere go usuwa. Skrypt śledzi typy kontrolerów przed migracją ($sourceControllerMap) i odtwarza je po zakończeniu.
Logowanie: każde uruchomienie tworzy plik logu w katalogu log\ obok skryptu:
log\log_20260529_143022.log
Log zawiera dosłownie wszystko co widać na ekranie — tabele pre/post, postęp per dysk, ostrzeżenia i błędy.
Skrypt 3 — cmd-validation.ps1
Skrypt walidacyjny do uruchomienia przed i po migracji. Generuje trójsekcyjny raport z kolorowymi wskaźnikami [OK] / [!!] / [??].
Parametry
| Parametr | Wymagany | Domyślnie | Opis |
|---|---|---|---|
-vmA |
Nie | VM-PROD01 |
VM referencyjna (source of truth) |
-vmB |
Nie | VM-DR01 |
VM sprawdzana |
-csvPath |
Nie | .\reattaching-vmdk-configuration.csv |
Oczekiwane mapowanie dysków |
Użycie
# Domyślne: VM-PROD01 vs VM-DR01
.\cmd-validation.ps1
# Własne VM
.\cmd-validation.ps1 -vmA VM-PROD01 -vmB VM-DR01 -csvPath .\my-mapping.csv
Sekcja 1 — Porównanie kontrolerów SCSI
Sprawdza czy oba VM mają te same typy kontrolerów SCSI na każdym numerze magistrali:
===== SCSI Controller Comparison =====
BUS VM-PROD01 (Reference) VM-DR01 (Check) Result
SCSI0 VirtualLsiLogicSASController VirtualLsiLogicSASController [OK]
SCSI1 ParaVirtualSCSIController ParaVirtualSCSIController [OK]
SCSI2 ParaVirtualSCSIController (missing) [!!]
Controllers: 2 passed, 2 failed
Sekcja 2 — Walidacja mapowania dysków z CSV
Dla każdego wiersza CSV sprawdza trzy warunki na maszynie sprawdzanej:
| Kolumna | Co sprawdza |
|---|---|
Ctrl |
Czy wymagany kontroler SCSI istnieje na VM docelowej? |
Disk |
Czy na oczekiwanej pozycji docelowej jest dysk? |
UUID |
Czy UUID dysku na pozycji docelowej odpowiada UUID z pozycji źródłowej? |
===== Disk Mapping Validation =====
# Src Pos Tgt Pos UUID @ Src (VM-PROD01) Ctrl Disk UUID @ Tgt (VM-DR01) UUID Result
1 SCSI0:1 SCSI0:1 6000C29d-e5de-223b~ [OK] [OK] 6000C29d-e5de-223b~ [OK] [OK]
2 SCSI1:0 SCSI1:0 6000C295-e19a-e4df~ [OK] [OK] 6000C295-e19a-e4df~ [OK] [OK]
3 SCSI2:13 SCSI2:13 6000C297-7841-f11a~ [!!] [!!] (no disk at tgt) [!!] [!!]
Disk mappings: 2 passed, 1 failed
Wskazówka: po udanej migracji z PROD na DR — pozycje źródłowe na PROD będą puste ([??] w kolumnie UUID). To normalne — dyski opuściły źródło.
Sekcja 3 — Cross-reference UUID
Lista wszystkich UUID dysków z obu VM z ich aktualną pozycją. Jeśli ten sam UUID pojawi się na obu maszynach jednocześnie — jest flagowany jako [??] Both VMs. Dysk VMDK nie może być bezpiecznie podpięty do dwóch VM równocześnie.
===== UUID Cross-Reference =====
UUID VM-PROD01 Pos VM-DR01 Pos Location
6000C296-32ce-bfdf-ae61-9cea6f0f6c64 SCSI0:0 - VM-PROD01 only
6000C29d-e5de-223b-558a-d810baccc697 - SCSI0:1 VM-DR01 only
6000C295-e19a-e4df-bf59-f56917997538 - SCSI1:0 VM-DR01 only
Legenda
| Wskaźnik | Znaczenie |
|---|---|
[OK] (zielony) |
Sprawdzenie zaliczone |
[!!] (czerwony) |
Błąd — wymagana interwencja |
[??] (żółty) |
Niejednoznaczne — sprawdź ręcznie |
Skrypt 4 — create-test-disks.ps1
Narzędzie laboratoryjne. Tworzy N dysków VMDK na wskazanej VM z losowym rozmieszczeniem na istniejących kontrolerach SCSI, a następnie generuje gotowy CSV dla skryptu migracyjnego.
Parametry
| Parametr | Wymagany | Domyślnie | Opis |
|---|---|---|---|
-vmName |
Tak | — | Nazwa VM, na której tworzysz dyski |
-datastore |
Tak | — | Nazwa datastore, na którym tworzysz pliki VMDK |
-diskCount |
Nie | 15 |
Liczba dysków do utworzenia |
-diskSizeGB |
Nie | 1 |
Rozmiar każdego dysku w GB |
-outputCsvPath |
Nie | .\reattaching-vmdk-configuration.csv |
Ścieżka do wygenerowanego CSV |
Użycie
# Utwórz 15 dysków po 1 GB z losowym rozmieszczeniem SCSI
.\create-test-disks.ps1 -vmName VM-PROD01 -datastore DatastoreNFS01
# Własne parametry
.\create-test-disks.ps1 -vmName VM-PROD01 -datastore DatastoreNFS01 -diskCount 10 -diskSizeGB 2
Przykładowy output
VM : VM-PROD01
Datastore : DatastoreNFS01
Disks : 15 x 1 GB
Available SCSI controllers:
Name Type BusNumber
SCSI controller 0 VirtualLsiLogicSASController 0
SCSI controller 1 ParaVirtualSCSIController 1
...
Creating 15 disks with random controller assignment...
Disk 1 -> SCSI2:3
Created: SCSI2:3 | [DatastoreNFS01] VM-PROD01/VM-PROD01_1.vmdk
Disk 2 -> SCSI0:5
Created: SCSI0:5 | [DatastoreNFS01] VM-PROD01/VM-PROD01_2.vmdk
...
CSV written to : .\reattaching-vmdk-configuration.csv (15 rows)
Use with : .\reattaching-vmdk-v2.ps1 -source VM-PROD01 -target <targetVM> -csvPath .\reattaching-vmdk-configuration.csv
Każdy kontroler obsługuje do 15 dysków (sloty 0–15 minus zarezerwowany slot 7). Przy 4 kontrolerach maksimum to 60 dysków.
Typowe workflow
Workflow 1 — Failover PROD → DR
# 1. Sprawdź aktualny stan przed migracją
.\cmd-validation.ps1 -vmA VM-PROD01 -vmB VM-DR01
# 2. Uruchom migrację
.\reattaching-vmdk-v2.ps1 -source VM-PROD01 -target VM-DR01 -csvPath .\reattaching-vmdk-configuration.csv
# 3. Zwaliduj wynik
.\cmd-validation.ps1 -vmA VM-PROD01 -vmB VM-DR01
Workflow 2 — Failback DR → PROD
# Ten sam CSV, zamienione argumenty -source i -target
.\reattaching-vmdk-v2.ps1 -source VM-DR01 -target VM-PROD01 -csvPath .\reattaching-vmdk-configuration.csv
.\cmd-validation.ps1 -vmA VM-DR01 -vmB VM-PROD01
Workflow 3 — Generowanie CSV z istniejącego układu dysków
# Eksportuj aktualny układ dysków VM-PROD01
.\export-vm-disk-config.ps1 -vmName VM-PROD01
# Przejrzyj wygenerowany CSV, następnie uruchom migrację
.\reattaching-vmdk-v2.ps1 -source VM-PROD01 -target VM-DR01 -csvPath .\reattaching-vmdk-configuration.csv
Workflow 4 — Testy laboratoryjne
# Utwórz 15 losowych dysków testowych na VM-PROD01
.\create-test-disks.ps1 -vmName VM-PROD01 -datastore DatastoreNFS01
# Przenieś na VM-DR01
.\reattaching-vmdk-v2.ps1 -source VM-PROD01 -target VM-DR01 -csvPath .\reattaching-vmdk-configuration.csv
# Zwaliduj
.\cmd-validation.ps1
# Cofnij
.\reattaching-vmdk-v2.ps1 -source VM-DR01 -target VM-PROD01 -csvPath .\reattaching-vmdk-configuration.csv
Podsumowanie
Zestaw czterech skryptów rozwiązuje problem, z którym GUI vSphere sobie nie radzi przynajmniej w kontrolowany sposób gdzie łatwo o błąd przy większej licznie dysków. Precyzyjne przenoszenie dysków VMDK między maszynami wirtualnymi na konkretne pozycje SCSI:UNIT, bez kasowania danych, z pełną walidacją przed i po operacji.
Kilka rzeczy, które warto zapamiętać:
- Dysk systemowy (SCSI 0:0) nigdy nie trafia do CSV — nie można go odpiąć od działającej lub zatrzymanej VM
- Unit 7 jest zawsze zarezerwowany przez vSphere — nie używaj go w CSV
- vSphere automatycznie usuwa puste kontrolery SCSI — skrypt je odtwarza po migracji zachowując oryginalny typ
- Każde uruchomienie migracji zapisuje pełny log do katalogu
log\— zawsze masz zapis tego co się stało - Walidacja UUID (
cmd-validation.ps1) jest najsilniejszą weryfikacją poprawności migracji — sprawdza nie tylko pozycję, ale tożsamość konkretnego pliku VMDK
Kod dostępny jest na GitHubie: github.com/sebastiangrugel/PowerCLI — VMDK-reattachment. Jeśli masz pytania lub natrafiłeś na przypadek brzegowy, którego skrypty nie obsługują daj znać.
Informacje o nowych artykułach, świecie wirtualizacji i "cloud computingu" prosto na Twojego maila:
Dodam Cię do listy mailowej, z której możesz wypisać się w dowolnym momencie (jeden klik.) | Polityka Prywatności
















