none
Shared Nothing Migration von VMs mit Powershell RRS feed

  • Frage

  • Hallo zusammen,

    wir haben gerade einen größeren Umzug unserer HyperV Landschaft geplant und dazu könnte ich eure Hilfe brauchen.

    Folgendes ist gegeben:

    -Single HyperV mit den derzeit wichtigsten VMs online, Rest offline (insgesamt rund 100 VMs)

    -2 Node HyperV Failovercluster mit neuem iSCSI Volume als Storage für die VMs

    -Aktuell liegen alle VMs auch auf einem iSCSI Volume, allerdings ist die Ordnerstruktur nicht komplett konsistent.

    -Alle VMs liegen in einem Ordner mit dem Namen der VM, manche haben allerdings auch ein (-1) oder ähnliches im Ordnernamen.

    -In den jeweiligen VM Ordnern wird es noch inkonsistenter. Manche VHDs liegen direkt im VM Ordner, manche haben einen eigenen Unterordner. Manchmal existiert im Ordner der VM nochmal ein Ordner mit dem gleichen Namen und erst darin befinden sich die Dateien der VM.

    -Ich suche jetzt nach einer Möglichkeit per Powershell unsere VMs von dem Single HyperV auf den Cluster zu verschieben und dabei dann auch eine konsistente Ordnerstruktur zu schaffen.

    -Etwa so: Jede VM in einem Ordner welcher den Namen der VM hat, danach einen Unterordner für jeweils das Konfig File, die VHDs, die Snapshots, und die Smartpages.

    Ich hab mich schon ein bisschen umgeschaut und eigentlich sollte das ganze ja per Powershell zu machen sein. Allerdings bin ich bei weitem kein Powershell Guru und die Vorlagen welche ich gefunden habe sind entweder nicht ganz passend oder funktionieren generell nicht für mich.

    Könnte mir von euch jemand behilflich sein und mir wenigstens einen Hinweis geben?

    Vielen Dank

    Joe

    Donnerstag, 15. März 2018 09:33

Antworten

  • Hi,

    zur Shared Nothing Live Migration findest Du hier was:

    https://www.windowspro.de/marcel-kueppers/hyper-v-shared-nothing-live-migration-ohne-cluster

    Zu dem Cmdlet Move-VM steht alles hier:

    https://technet.microsoft.com/de-de/library/hh848547.aspx?f=255&MSPPError=-2147217396

    Für einen Export findest Du hier das Cmdlet:

    https://technet.microsoft.com/de-de/library/hh848491.aspx

    Äquivalent Import:

    https://technet.microsoft.com/de-de/library/hh848495.aspx

    Bei einer Live Migration musst Du die unterschiedlichen Prozessor-Versionen beachten. VHD(X) und die Config werden dann auf den CSV´s abgelegt und VM´s HA konfiguriert.

    Gruß,
    Marcel

    https://www.windowspro.de/marcel-kueppers

    I write here only in private interest

    Disclaimer: This posting is provided AS IS with no warranties or guarantees, and confers no rights.

    Donnerstag, 15. März 2018 09:59
  • Hi,

    vielen Dank für die schnelle Antwort. Ich hätte da aber noch zwei Fragen:

    1. Was ist generell zu bevorzugen? Der Move Befehl oder ein Export gefolgt von einem Import?

    Ich bevorzuge die unterbrechungsfreie LM.

    2. Ich habe mir diesen Befehl mal aus dem verlinkten Technet Artikel herausgesucht und näher angesehen:

    PS C:\> Move-VM "Test VM" remoteServer –VirtualMachinePath D:\TestVM\Config –SnapshotFilePath D:\TestVM\Snapshots –SmartPagingFilePath D:\TestVM\SmartPaging –IncludeStorage –VHDs @(@{"SourceFilePath" = "C:\TestVM\Disk1.VHDX"; "DestinationFilePath" = "D:\TestVM\Disks\Disk1.VHDX"}, @{"SourceFilePath" = "C:\TestVM\Disk2.VHDX"; "DestinationFilePath" = "D:\TestVM\Disks\Disk2.VHDX"})

    Ich denke das geht schon in die Richtung was ich suche. Allerdings verstehe ich insbesondere den letzten Teil noch nicht komplett. Also ab -VHDs. Könntest du mir das noch einmal näher erläutern?

    -Vhds<System.Collections.Hashtable[]>

    Specifies an array of hashtables that contain locations for each individual virtual hard disk to be moved. Each hashtable should have two entries. The first entry specifies the current location of the virtual hard disk to move, and has a key of SourceFilePath. The second entry specifies the new location for the virtual hard disk, and has a key of DestinationFilePath. The virtual hard disk name must be identical in both entries.



    https://www.windowspro.de/marcel-kueppers

    I write here only in private interest

    Disclaimer: This posting is provided AS IS with no warranties or guarantees, and confers no rights.

    Donnerstag, 15. März 2018 12:59

Alle Antworten

  • Hi,

    zur Shared Nothing Live Migration findest Du hier was:

    https://www.windowspro.de/marcel-kueppers/hyper-v-shared-nothing-live-migration-ohne-cluster

    Zu dem Cmdlet Move-VM steht alles hier:

    https://technet.microsoft.com/de-de/library/hh848547.aspx?f=255&MSPPError=-2147217396

    Für einen Export findest Du hier das Cmdlet:

    https://technet.microsoft.com/de-de/library/hh848491.aspx

    Äquivalent Import:

    https://technet.microsoft.com/de-de/library/hh848495.aspx

    Bei einer Live Migration musst Du die unterschiedlichen Prozessor-Versionen beachten. VHD(X) und die Config werden dann auf den CSV´s abgelegt und VM´s HA konfiguriert.

    Gruß,
    Marcel

    https://www.windowspro.de/marcel-kueppers

    I write here only in private interest

    Disclaimer: This posting is provided AS IS with no warranties or guarantees, and confers no rights.

    Donnerstag, 15. März 2018 09:59
  • Hi,

    vielen Dank für die schnelle Antwort. Ich hätte da aber noch zwei Fragen:

    1. Was ist generell zu bevorzugen? Der Move Befehl oder ein Export gefolgt von einem Import?

    2. Ich habe mir diesen Befehl mal aus dem verlinkten Technet Artikel herausgesucht und näher angesehen:

    PS C:\> Move-VM "Test VM" remoteServer –VirtualMachinePath D:\TestVM\Config –SnapshotFilePath D:\TestVM\Snapshots –SmartPagingFilePath D:\TestVM\SmartPaging –IncludeStorage –VHDs @(@{"SourceFilePath" = "C:\TestVM\Disk1.VHDX"; "DestinationFilePath" = "D:\TestVM\Disks\Disk1.VHDX"}, @{"SourceFilePath" = "C:\TestVM\Disk2.VHDX"; "DestinationFilePath" = "D:\TestVM\Disks\Disk2.VHDX"})

    Ich denke das geht schon in die Richtung was ich suche. Allerdings verstehe ich insbesondere den letzten Teil noch nicht komplett. Also ab -VHDs. Könntest du mir das noch einmal näher erläutern?

    Wenn ich das ganze dann nicht nur für eine VM machen möchte sondern für alle 100 könnte das ungefähr so aussehen?

    $RunVMs = Get-VM –ComputerName Server1 | Where-Object {$_.State –eq 'Running'} | select Name
    
    Move-VM $RunVMs remoteServer –VirtualMachinePath D:\$RunVMs\Config –SnapshotFilePath D:\$RunVMs\Snapshots –SmartPagTingFilePath D:\$RunVMs\SmartPaging –IncludeStorage –VHDs @(@{"SourceFilePath" = "C:\$RunVMs\Disk1.VHDX"; "DestinationFilePath" = "D:\$RunVMs\Disks\Disk1.VHDX"}, @{"SourceFilePath" = "C:\$RunVMs\Disk2.VHDX"; "DestinationFilePath" = "D:\$RunVMs\Disks\Disk2.VHDX"})

    Wäre jetzt halt nur für die laufenden VMs und ich bin mir auch nicht ganz sicher ob das so passt. Gerade bei dem VHD Teil bin ich unsicher, weil ich den SourcePath ja normalerweise aus dem Konfig File auslesen müsste. Die Pfade sind ja leider unterschiedlich und auch die Anzahl der VHDs ist unterschiedlich.

    Hättest du noch einen Tipp für mich?

    Vielen Dank

    Joe

    Donnerstag, 15. März 2018 11:13
  • Hi,

    vielen Dank für die schnelle Antwort. Ich hätte da aber noch zwei Fragen:

    1. Was ist generell zu bevorzugen? Der Move Befehl oder ein Export gefolgt von einem Import?

    Ich bevorzuge die unterbrechungsfreie LM.

    2. Ich habe mir diesen Befehl mal aus dem verlinkten Technet Artikel herausgesucht und näher angesehen:

    PS C:\> Move-VM "Test VM" remoteServer –VirtualMachinePath D:\TestVM\Config –SnapshotFilePath D:\TestVM\Snapshots –SmartPagingFilePath D:\TestVM\SmartPaging –IncludeStorage –VHDs @(@{"SourceFilePath" = "C:\TestVM\Disk1.VHDX"; "DestinationFilePath" = "D:\TestVM\Disks\Disk1.VHDX"}, @{"SourceFilePath" = "C:\TestVM\Disk2.VHDX"; "DestinationFilePath" = "D:\TestVM\Disks\Disk2.VHDX"})

    Ich denke das geht schon in die Richtung was ich suche. Allerdings verstehe ich insbesondere den letzten Teil noch nicht komplett. Also ab -VHDs. Könntest du mir das noch einmal näher erläutern?

    -Vhds<System.Collections.Hashtable[]>

    Specifies an array of hashtables that contain locations for each individual virtual hard disk to be moved. Each hashtable should have two entries. The first entry specifies the current location of the virtual hard disk to move, and has a key of SourceFilePath. The second entry specifies the new location for the virtual hard disk, and has a key of DestinationFilePath. The virtual hard disk name must be identical in both entries.



    https://www.windowspro.de/marcel-kueppers

    I write here only in private interest

    Disclaimer: This posting is provided AS IS with no warranties or guarantees, and confers no rights.

    Donnerstag, 15. März 2018 12:59
  • Okay dann hab ich den letzten Part von diesem Befehl auch kapiert. Bleibt noch das Thema wie ich das Variabel für alle VMs bekomme.

    So wie ich es oben geschrieben habe wird es denke ich nicht gehen, ich brauche eine "Foreach" Schleife. Allerdings wie schon gesagt, bin kein großer Powershell Experte.

    Da könnte ich noch einmal Hilfe gebrauchen.

    Vielen Dank

    Joe

    Donnerstag, 15. März 2018 14:12
  • Hallo zusammen,

    ich hab den ganzen gestrigen Tag und den heutigen Morgen damit verbracht mir Powershell Scripte anzusehen und mir die von mir benötigten Teile rauszusuchen. Dabei herausgekommen ist folgendes:

    # Erstellt einen Workflow "Invoke-ParallelLiveMigration"
    Workflow Invoke-ParallelLiveMigrate
    
    {
    # Legt die Parameter für den Workflow fest
     Param (
    
    [parameter(Mandatory=$true)][String[]] $VMListe, # Parameter für ein Array mit allen VM Namen
    
    [parameter(Mandatory=$true)][String] $QuellHost, # Parameter für den Quellhost
    
    [parameter(Mandatory=$true)][String] $ZielHost, # Parameter für den Zielhost
    
    [parameter(Mandatory=$true)][String] $Zielspeicher # Parameter für den Zielspeicher
    
    )
    
    ForEach -Parallel ($VMName in $VMListe)# Für jeden VM-Namen im Array wird eine Variable "$VMName" erstellt
    
        {
    
        $VMZiel = Join-Path -Path $Zielspeicher -ChildPath $VMName # Erstellt eine Variable "$VMZiel" aus dem Zielspeicher und dem VM-Namen
        $SmartpagePath = Join-Path -Path $VMZiel -Childpath "SmartPage"# Erstellt die Variable für den Smartpage Pfad
        $SnapshotPath = Join-Path -Path $VMZiel -Childpath "Snapshot" # Erstellt die Variable für den Snapshot Pfad
        $ConfigPath = Join-Path -Path $VMZiel -Childpath "VM-Config" # Erstellt die Variable für den Konfig Pfad
        $VHDPath = Join-Path -Path $VMZiel -Childpath "VHDs" # Erstellt die Variable für den VHD Pfad
    
        Get-VM $VMName | select -expand HardDrives | ForEach { # Nutzt die Variable "$VMName" um die VM-Konfig auszulesen und die VHDs zu selektieren. Diese werden dann an die Foreach Schleife übergeben
            
            # Der Pfad zur VHD wird ausgelesen, aufgesplittet und nur der Dateiname in die Variable "$VHDDatei" übergeben
            $VHDDatei = $_.Path | Split-Path -Leaf 
            
            # Aus dem Pfad zum VHD Speicher und dem VHD-Dateinamen wird die Variable "$Zielpfad" für den Zielpfad der VHD generiert
            $Zielpfad = Join-Path $VHDPath $Datei
    
            # Erzeugt eine Variable "$Hash" und setzt die Werte für SourceFilePath und DestinationFilePath
            $Hash = @{"SourceFilePath" = "$($_.path)"; "DestinationFilePath" = "$Zielpfad"}
            }
    
          # Verschiebt die VM auf den neuen Host in einen Ordner mit dem Namen der VM und speichert die Dateien in seperaten Unterordnern ab
          Move-VM -ComputerName $Quellhost -Name $VMName -DestinationHost $Zielhost –VirtualMachinePath $ConfigPath –SnapshotFilePath $SnapshotPath –SmartPagingFilePath $SmartpagePath –IncludeStorage –VHDs $Hash -WhatIf
    
    # Gibt aus welche VM gerade verschoben wird
    InlineScript {Write-Host "Kopiere $VMName von $Quellhost nach $Zielhost" -foregroundcolor Cyan}
    }
    }

    Aktuell scheine ich aber noch ein Problem zu haben das das Script beim Aufruf des Befehls "Get-VM $VMName" keine korrekte Ausgabe bekommt und somit auch alle anderen Variablen nicht funktionieren.

    Wenn ich die Zeilen einzeln ausführe funktioniert alles, wenn ich das Script komplett laufen lassen bekomme ich folgenden Fehler:

    Split-Path : Das Argument kann nicht an den Parameter "Path" gebunden werden, da es NULL ist.
    In Invoke-ParallelLiveMigrate:26 Zeichen:26
    + 
        + CategoryInfo          : InvalidData: (:) [Split-Path], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.SplitPathCommand
        + PSComputerName        : [localhost]
     
    Join-Path : Das Argument kann nicht an den Parameter "Path" gebunden werden, da es NULL ist.
    In Invoke-ParallelLiveMigrate:26 Zeichen:26
    + 
        + CategoryInfo          : InvalidData: (:) [Join-Path], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.JoinPathCommand
        + PSComputerName        : [localhost]
     
    Microsoft.PowerShell.Utility\Write-Error : Das Argument für den Parameter "Vhds" kann nicht überprüft werden. Das Argument ist NULL oder leer. Geben Sie ein Argument an, das nicht NULL oder leer ist, und führen Sie den Befehl erneut aus.
    In Invoke-ParallelLiveMigrate:39 Zeichen:39
    + 
        + CategoryInfo          : NotSpecified: (:) [Write-Error], RemoteException
        + FullyQualifiedErrorId : System.Management.Automation.RemoteException,Microsoft.PowerShell.Commands.WriteErrorCommand
        + PSComputerName        : [localhost]

    Wenn ich mich nicht täusche hängt das hiermit zusammen:

    Get-VM : Von Hyper-V wurde kein virtueller Computer mit dem Namen "@{Name=Test}" gefunden.
    In Invoke-ParallelLiveMigrate:25 Zeichen:25
    + 
        + CategoryInfo          : InvalidArgument: (@{Name=Test}:String) [Get-VM], VirtualizationException
        + FullyQualifiedErrorId : InvalidParameter,Microsoft.HyperV.PowerShell.Commands.GetVM
        + PSComputerName        : [localhost]

    Könnte mir das jemand erklären, bzw. kennt jemand eine Lösung?

    Vielen Dank,

    Gruß

    Joe

    Freitag, 16. März 2018 12:34