Skip to content

Instantly share code, notes, and snippets.

@tomohulk
Last active June 17, 2024 22:14
Show Gist options
  • Save tomohulk/9809a53a62eff4154af6f9fec851d1bd to your computer and use it in GitHub Desktop.
Save tomohulk/9809a53a62eff4154af6f9fec851d1bd to your computer and use it in GitHub Desktop.
Move Hyper-V Clustered VM to new Cluster with different Virtual Switch Names.
function Move-ClusteredVM {
[CmdletBinding(DefaultParameterSetName = "__AllParameterSets")]
[OutputType()]
param (
[Parameter(Mandatory = $true, ParameterSetName = "ByName", ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[String[]]
$Name,
[Parameter(Mandatory = $true, ParameterSetName = "ByVM", ValueFromPipeline = $true)]
[Microsoft.HyperV.PowerShell.VirtualMachine[]]
$VM,
[Parameter()]
[String]
$DestinationHost,
[Parameter(Mandatory = $true)]
[String]
$DestinationStoragePath,
[Parameter(Mandatory = $true)]
[String]
$DestinationClusterName,
[Parameter(Mandatory = $true)]
[String]
$SwitchName
)
begin {}
process {
if ($PSCmdlet.ParameterSetName -eq "ByName") {
foreach ($nameValue in $Name) {
$VM += Get-VM -Name $nameValue
}
}
foreach ($vmValue in $VM) {
# Remove the current VM Resource Group.
Remove-ClusterGroup -VMId $vmValue.Id -RemoveResources -Force
# Append the VM Name to the destination storage path if not provided.
if (-not $DestinationStoragePath.EndsWith($vmValue.Name)) {
$DestinationStoragePath = Join-Path -Path $DestinationStoragePath -ChildPath $vmValue.Name
}
# Find best host for VM placement if DestinationHost is not provided (simply put, place the VM on the host with the least ammount of VMs running)
if (-not $PSBoundParameters.ContainsKey("DestinationHost")) {
$DestinationHost = Get-CLusterGroup -Cluster $DestinationClusterName | Where-Object { $_.GroupType -eq "VirtualMachine" } | Group-Object -Property OwnerNode | Sort-Object Count | Select-Object -First 1 -ExpandProperty Name
}
# Generate a Compatability Report and correct the Virtual Switch Name for the new Hosts.
$compatabilityReport = Compare-VM -VM $vmValue -DestinationHost $DestinationHost -DestinationStoragePath $DestinationStoragePath
$compatabilityReport.VM.NetworkAdapters | ForEach-Object { Connect-VMNetworkAdapter -VMNetworkAdapter $_ -SwitchName $SwitchName }
# If the VM has Snapshots, update the Virtual Switch connection.
$vmSnapshot = Get-VMSnapshot -VM $vmValue
if ($null -ne ($vmSnapshot)) {
foreach ($vmSnapshotValue in $vmSnapshot) {
$vmSnapshotValue.NetworkAdapters | ForEach-Object { Connect-VMNetworkAdapter -VMNetworkAdapter $_ -SwitchName $SwitchName}
}
}
# Move the VM to the new host.
Move-VM -CompatibilityReport $compatabilityReport
# Add the VM to the new Cluster.
Add-ClusterVirtualMachineRole -VMName $vmValue.Name -Name ("SCVMM {0} Resources" -f $vmValue.Name) -Cluster $DestinationClusterName
}
}
end {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment