[{"data":1,"prerenderedAt":2192},["ShallowReactive",2],{"post:\u002F2026\u002F06\u002F10\u002Fhyper-v-migrating-vms-off-an-aging-cluster-without-downtime\u002F":3},{"post":4,"newer":2149,"older":2161,"related":2169,"series":2190},{"id":5,"title":6,"body":7,"canonical":2131,"categories":2132,"date":2134,"description":2135,"extension":2136,"featured":2137,"hero":2138,"image":2138,"meta":2139,"navigation":246,"path":2140,"readingTime":146,"seo":2141,"series":2138,"seriesOrder":2138,"sites":2142,"source":2138,"stem":2143,"tags":2144,"updated":2138,"url":2147,"__hash__":2148},"blog\u002Fblog\u002F2026\u002F06\u002F10\u002Fhyper-v-migrating-vms-off-an-aging-cluster-without-downtime.md","Hyper-V: Migrating VMs Off an Aging Cluster Without Downtime",{"type":8,"value":9,"toc":2121},"minimark",[10,14,19,35,42,45,49,60,64,67,76,80,95,770,785,808,812,825,2005,2008,2016,2024,2028,2031,2035,2041,2045,2117],[11,12,13],"p",{},"An aging Hyper-V cluster doesn't announce that it's time to go. It just accumulates small warning signs — a host that takes longer to fail over than it used to, firmware updates the vendor no longer tests against the current build, storage that's a generation behind what the newer hosts get — until replacing it stops being optional. The workloads on it are still production, though, and \"just schedule a maintenance window\" gets harder to justify every year as more of the business runs around the clock. Moving VMs to a new cluster without downtime is possible, but it's a different operation than the failover most admins are used to, and it has its own set of surprises.",[15,16,18],"h2",{"id":17},"why-we-couldnt-just-fail-over","Why We Couldn't Just Fail Over",[11,20,21,22,26,27,30,31,34],{},"A normal Hyper-V cluster failover or live migration moves a VM between nodes that share the same cluster, the same Cluster Shared Volumes and the same cluster database. Moving to a new cluster entirely is a different animal. There's no shared CSV between the old cluster and the new one, so this is a shared-nothing live migration: Hyper-V copies the VM's memory and streams its virtual disks across the network to the destination host while the VM keeps running on the source. ",[23,24,25],"code",{},"Move-VM"," does this when you pass ",[23,28,29],{},"-IncludeStorage"," and a ",[23,32,33],{},"-DestinationStoragePath","; without them it assumes the storage is already reachable from the destination.",[11,36,37,38,41],{},"Two things about clustered VMs are not obvious. First, Microsoft's older cluster migration guidance says plainly that you cannot live migrate a highly available VM to a new failover cluster; its supported path, the Copy Cluster Roles wizard, moves the role and then remaps the same LUNs to the new cluster with a brief outage. To get a zero-downtime move you take the VM out of the old cluster's control first (remove its clustered role, which leaves the VM itself running and registered in Hyper-V on its owner node), live migrate it with its storage to a node of the new cluster, then make it highly available again there with ",[23,39,40],{},"Add-ClusterVirtualMachineRole",". For the minutes the copy takes, the VM is not protected by either cluster, which is one more reason to move them one at a time.",[11,43,44],{},"Second, if you were hoping to avoid all of this, Cluster OS Rolling Upgrade only helps when you keep the hardware: it upgrades the OS one node at a time, one Windows Server version per pass. Replacing the hosts means migrating.",[15,46,48],{"id":47},"configuration-versions-were-the-first-surprise","Configuration Versions Were the First Surprise",[11,50,51,52,55,56,59],{},"The VM configuration version decides which hosts a VM can run on at all, and new hosts drop old versions. Windows Server 2022 runs configuration versions 8.0 through 10.0, and Windows Server 2025 runs 8.0 through 12.0. Anything still at 5.0 (created on Windows Server 2012 R2) or at 6.2 to 7.1 and never upgraded cannot run on either, so it cannot live migrate there. ",[23,53,54],{},"Update-VMVersion"," fixes that, but it needs the VM shut down and it cannot be undone: after the upgrade the VM can't go back to a host that doesn't support the new version. That meant a short, scheduled restart for a handful of old VMs before the zero-downtime part could even begin, and it's why I now run ",[23,57,58],{},"Get-VM | Format-Table Name, Version"," against every old cluster long before the new hardware arrives.",[15,61,63],{"id":62},"cpu-compatibility-was-the-second","CPU Compatibility Was the Second",[11,65,66],{},"The old cluster's hosts and the new cluster's hosts were bought years apart, which meant different CPU generations with different instruction sets exposed to the guest. Hyper-V checks the processor features a running VM can see against the destination before a live migration, and cancels the move if they don't match. Processor compatibility mode fixes that by presenting a reduced feature set, but it has to be turned on while the VM is shut down, so it goes in the same maintenance slot as any configuration-version upgrade, not mid-move. It doesn't help across vendors either: even with it enabled you can't live migrate from an Intel host to an AMD host. Microsoft recommends turning it on only for the migration and off again afterwards, because it hides the newer instructions from the guest. Windows Server 2025 adds a dynamic mode that calculates the common feature set across a cluster's nodes automatically, for VMs at configuration version 10.0 or later.",[11,68,69,72,73,75],{},[23,70,71],{},"Compare-VM"," is the tool that catches both problems before they turn into a failed migration in front of an audience. It builds the same compatibility report ",[23,74,25],{}," would, without moving anything, and lists every incompatibility with a message and ID.",[15,77,79],{"id":78},"authentication-and-bandwidth","Authentication and Bandwidth",[11,81,82,83,86,87,90,91,94],{},"Shared-nothing moves started from a management machine need Kerberos constrained delegation: each host's computer account trusted to delegate ",[23,84,85],{},"Microsoft Virtual System Migration Service"," (for the VM) and ",[23,88,89],{},"cifs"," (for the storage) to the other side, set with \"Use any authentication protocol\". CredSSP avoids the delegation but only works if you're signed in to the source host, and it stops working entirely once hosts run Windows Server 2025, which enables Credential Guard by default on domain members. Microsoft's Scale-Out File Server deployment guide ships a delegation script built on ",[23,92,93],{},"msDS-AllowedToDelegateTo","; this is the same idea for an old-cluster-to-new-cluster move, run once with the ActiveDirectory module as a Domain Admin:",[96,97,102],"pre",{"className":98,"code":99,"language":100,"meta":101,"style":101},"language-powershell shiki shiki-themes github-dark","\u003C#\n.SYNOPSIS\n    Grants Kerberos constrained delegation for live migration and storage moves between two sets of Hyper-V hosts.\n.DESCRIPTION\n    For every source and destination host pair, adds the Microsoft Virtual System Migration Service and cifs\n    SPNs of the other host to msDS-AllowedToDelegateTo and enables protocol transition (\"Use any\n    authentication protocol\"), in both directions. Hosts need a new Kerberos ticket (a restart is simplest)\n    before the change takes effect.\n.PARAMETER SourceHosts\n    Hyper-V hosts in the old cluster.\n.PARAMETER DestinationHosts\n    Hyper-V hosts in the new cluster.\n.EXAMPLE\n    .\\Set-MigrationDelegation.ps1 -SourceHosts 'old-hv01', 'old-hv02' -DestinationHosts 'new-hv01', 'new-hv02'\n.NOTES\n    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n    Version : 1.0 (2026-06-10)\n    Requires: ActiveDirectory module, Domain Admins\n#>\n\n[CmdletBinding()]\nparam (\n    [Parameter(Mandatory = $true)]\n    [string[]]$SourceHosts,\n\n    [Parameter(Mandatory = $true)]\n    [string[]]$DestinationHosts\n)\n\nImport-Module -Name ActiveDirectory\n\n$pairs = foreach ($source in $SourceHosts) {\n    foreach ($destination in $DestinationHosts) {\n        [PSCustomObject]@{ From = $source; To = $destination }\n        [PSCustomObject]@{ From = $destination; To = $source }\n    }\n}\n\nforeach ($pair in $pairs) {\n    $target = Get-ADComputer -Identity $pair.To\n    $services = @(\n        \"Microsoft Virtual System Migration Service\u002F$($target.Name)\",\n        \"Microsoft Virtual System Migration Service\u002F$($target.DNSHostName)\",\n        \"cifs\u002F$($target.Name)\",\n        \"cifs\u002F$($target.DNSHostName)\"\n    )\n\n    $computer = Get-ADComputer -Identity $pair.From -Properties 'msDS-AllowedToDelegateTo'\n    $missing = $services | Where-Object { $computer.'msDS-AllowedToDelegateTo' -notcontains $_ }\n\n    if ($missing) {\n        Set-ADComputer -Identity $computer -Add @{ 'msDS-AllowedToDelegateTo' = [string[]]$missing }\n        Write-Output \"$($pair.From): added delegation to $($pair.To)\"\n    }\n\n    Set-ADAccountControl -Identity $computer -TrustedToAuthForDelegation $true\n}\n","powershell","",[23,103,104,113,124,130,138,144,150,156,162,173,179,189,195,203,209,217,223,229,235,241,248,261,270,295,309,314,331,341,347,352,364,369,390,404,432,455,461,467,472,486,502,516,539,557,575,591,597,602,626,658,663,672,705,737,742,747,765],{"__ignoreMap":101},[105,106,109],"span",{"class":107,"line":108},"line",1,[105,110,112],{"class":111},"sAwPA","\u003C#\n",[105,114,116,120],{"class":107,"line":115},2,[105,117,119],{"class":118},"sDLfK",".",[105,121,123],{"class":122},"snl16","SYNOPSIS\n",[105,125,127],{"class":107,"line":126},3,[105,128,129],{"class":111},"    Grants Kerberos constrained delegation for live migration and storage moves between two sets of Hyper-V hosts.\n",[105,131,133,135],{"class":107,"line":132},4,[105,134,119],{"class":118},[105,136,137],{"class":122},"DESCRIPTION\n",[105,139,141],{"class":107,"line":140},5,[105,142,143],{"class":111},"    For every source and destination host pair, adds the Microsoft Virtual System Migration Service and cifs\n",[105,145,147],{"class":107,"line":146},6,[105,148,149],{"class":111},"    SPNs of the other host to msDS-AllowedToDelegateTo and enables protocol transition (\"Use any\n",[105,151,153],{"class":107,"line":152},7,[105,154,155],{"class":111},"    authentication protocol\"), in both directions. Hosts need a new Kerberos ticket (a restart is simplest)\n",[105,157,159],{"class":107,"line":158},8,[105,160,161],{"class":111},"    before the change takes effect.\n",[105,163,165,167,170],{"class":107,"line":164},9,[105,166,119],{"class":118},[105,168,169],{"class":122},"PARAMETER",[105,171,172],{"class":122}," SourceHosts\n",[105,174,176],{"class":107,"line":175},10,[105,177,178],{"class":111},"    Hyper-V hosts in the old cluster.\n",[105,180,182,184,186],{"class":107,"line":181},11,[105,183,119],{"class":118},[105,185,169],{"class":122},[105,187,188],{"class":122}," DestinationHosts\n",[105,190,192],{"class":107,"line":191},12,[105,193,194],{"class":111},"    Hyper-V hosts in the new cluster.\n",[105,196,198,200],{"class":107,"line":197},13,[105,199,119],{"class":118},[105,201,202],{"class":122},"EXAMPLE\n",[105,204,206],{"class":107,"line":205},14,[105,207,208],{"class":111},"    .\\Set-MigrationDelegation.ps1 -SourceHosts 'old-hv01', 'old-hv02' -DestinationHosts 'new-hv01', 'new-hv02'\n",[105,210,212,214],{"class":107,"line":211},15,[105,213,119],{"class":118},[105,215,216],{"class":122},"NOTES\n",[105,218,220],{"class":107,"line":219},16,[105,221,222],{"class":111},"    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n",[105,224,226],{"class":107,"line":225},17,[105,227,228],{"class":111},"    Version : 1.0 (2026-06-10)\n",[105,230,232],{"class":107,"line":231},18,[105,233,234],{"class":111},"    Requires: ActiveDirectory module, Domain Admins\n",[105,236,238],{"class":107,"line":237},19,[105,239,240],{"class":111},"#>\n",[105,242,244],{"class":107,"line":243},20,[105,245,247],{"emptyLinePlaceholder":246},true,"\n",[105,249,251,255,258],{"class":107,"line":250},21,[105,252,254],{"class":253},"s95oV","[",[105,256,257],{"class":118},"CmdletBinding",[105,259,260],{"class":253},"()]\n",[105,262,264,267],{"class":107,"line":263},22,[105,265,266],{"class":122},"param",[105,268,269],{"class":253}," (\n",[105,271,273,276,279,282,286,289,292],{"class":107,"line":272},23,[105,274,275],{"class":253},"    [",[105,277,278],{"class":118},"Parameter",[105,280,281],{"class":253},"(",[105,283,285],{"class":284},"s9osk","Mandatory",[105,287,288],{"class":122}," =",[105,290,291],{"class":118}," $true",[105,293,294],{"class":253},")]\n",[105,296,298,300,303,306],{"class":107,"line":297},24,[105,299,275],{"class":253},[105,301,302],{"class":122},"string",[105,304,305],{"class":253},"[]]$SourceHosts",[105,307,308],{"class":122},",\n",[105,310,312],{"class":107,"line":311},25,[105,313,247],{"emptyLinePlaceholder":246},[105,315,317,319,321,323,325,327,329],{"class":107,"line":316},26,[105,318,275],{"class":253},[105,320,278],{"class":118},[105,322,281],{"class":253},[105,324,285],{"class":284},[105,326,288],{"class":122},[105,328,291],{"class":118},[105,330,294],{"class":253},[105,332,334,336,338],{"class":107,"line":333},27,[105,335,275],{"class":253},[105,337,302],{"class":122},[105,339,340],{"class":253},"[]]$DestinationHosts\n",[105,342,344],{"class":107,"line":343},28,[105,345,346],{"class":253},")\n",[105,348,350],{"class":107,"line":349},29,[105,351,247],{"emptyLinePlaceholder":246},[105,353,355,358,361],{"class":107,"line":354},30,[105,356,357],{"class":118},"Import-Module",[105,359,360],{"class":122}," -",[105,362,363],{"class":253},"Name ActiveDirectory\n",[105,365,367],{"class":107,"line":366},31,[105,368,247],{"emptyLinePlaceholder":246},[105,370,372,375,378,381,384,387],{"class":107,"line":371},32,[105,373,374],{"class":253},"$pairs ",[105,376,377],{"class":122},"=",[105,379,380],{"class":122}," foreach",[105,382,383],{"class":253}," ($source ",[105,385,386],{"class":122},"in",[105,388,389],{"class":253}," $SourceHosts) {\n",[105,391,393,396,399,401],{"class":107,"line":392},33,[105,394,395],{"class":122},"    foreach",[105,397,398],{"class":253}," ($destination ",[105,400,386],{"class":122},[105,402,403],{"class":253}," $DestinationHosts) {\n",[105,405,407,410,413,416,419,422,424,427,429],{"class":107,"line":406},34,[105,408,409],{"class":253},"        [",[105,411,412],{"class":122},"PSCustomObject",[105,414,415],{"class":253},"]",[105,417,418],{"class":122},"@",[105,420,421],{"class":253},"{ From ",[105,423,377],{"class":122},[105,425,426],{"class":253}," $source; To ",[105,428,377],{"class":122},[105,430,431],{"class":253}," $destination }\n",[105,433,435,437,439,441,443,445,447,450,452],{"class":107,"line":434},35,[105,436,409],{"class":253},[105,438,412],{"class":122},[105,440,415],{"class":253},[105,442,418],{"class":122},[105,444,421],{"class":253},[105,446,377],{"class":122},[105,448,449],{"class":253}," $destination; To ",[105,451,377],{"class":122},[105,453,454],{"class":253}," $source }\n",[105,456,458],{"class":107,"line":457},36,[105,459,460],{"class":253},"    }\n",[105,462,464],{"class":107,"line":463},37,[105,465,466],{"class":253},"}\n",[105,468,470],{"class":107,"line":469},38,[105,471,247],{"emptyLinePlaceholder":246},[105,473,475,478,481,483],{"class":107,"line":474},39,[105,476,477],{"class":122},"foreach",[105,479,480],{"class":253}," ($pair ",[105,482,386],{"class":122},[105,484,485],{"class":253}," $pairs) {\n",[105,487,489,492,494,497,499],{"class":107,"line":488},40,[105,490,491],{"class":253},"    $target ",[105,493,377],{"class":122},[105,495,496],{"class":118}," Get-ADComputer",[105,498,360],{"class":122},[105,500,501],{"class":253},"Identity $pair.To\n",[105,503,505,508,510,513],{"class":107,"line":504},41,[105,506,507],{"class":253},"    $services ",[105,509,377],{"class":122},[105,511,512],{"class":122}," @",[105,514,515],{"class":253},"(\n",[105,517,519,523,526,528,531,534,537],{"class":107,"line":518},42,[105,520,522],{"class":521},"sU2Wk","        \"Microsoft Virtual System Migration Service\u002F",[105,524,525],{"class":122},"$",[105,527,281],{"class":521},[105,529,530],{"class":253},"$target.Name",[105,532,533],{"class":521},")",[105,535,536],{"class":521},"\"",[105,538,308],{"class":122},[105,540,542,544,546,548,551,553,555],{"class":107,"line":541},43,[105,543,522],{"class":521},[105,545,525],{"class":122},[105,547,281],{"class":521},[105,549,550],{"class":253},"$target.DNSHostName",[105,552,533],{"class":521},[105,554,536],{"class":521},[105,556,308],{"class":122},[105,558,560,563,565,567,569,571,573],{"class":107,"line":559},44,[105,561,562],{"class":521},"        \"cifs\u002F",[105,564,525],{"class":122},[105,566,281],{"class":521},[105,568,530],{"class":253},[105,570,533],{"class":521},[105,572,536],{"class":521},[105,574,308],{"class":122},[105,576,578,580,582,584,586,588],{"class":107,"line":577},45,[105,579,562],{"class":521},[105,581,525],{"class":122},[105,583,281],{"class":521},[105,585,550],{"class":253},[105,587,533],{"class":521},[105,589,590],{"class":521},"\"\n",[105,592,594],{"class":107,"line":593},46,[105,595,596],{"class":253},"    )\n",[105,598,600],{"class":107,"line":599},47,[105,601,247],{"emptyLinePlaceholder":246},[105,603,605,608,610,612,614,617,620,623],{"class":107,"line":604},48,[105,606,607],{"class":253},"    $computer ",[105,609,377],{"class":122},[105,611,496],{"class":118},[105,613,360],{"class":122},[105,615,616],{"class":253},"Identity $pair.From ",[105,618,619],{"class":122},"-",[105,621,622],{"class":253},"Properties ",[105,624,625],{"class":521},"'msDS-AllowedToDelegateTo'\n",[105,627,629,632,634,637,640,643,646,649,652,655],{"class":107,"line":628},49,[105,630,631],{"class":253},"    $missing ",[105,633,377],{"class":122},[105,635,636],{"class":253}," $services ",[105,638,639],{"class":122},"|",[105,641,642],{"class":118}," Where-Object",[105,644,645],{"class":253}," { $computer.",[105,647,648],{"class":521},"'msDS-AllowedToDelegateTo'",[105,650,651],{"class":122}," -notcontains",[105,653,654],{"class":118}," $_",[105,656,657],{"class":253}," }\n",[105,659,661],{"class":107,"line":660},50,[105,662,247],{"emptyLinePlaceholder":246},[105,664,666,669],{"class":107,"line":665},51,[105,667,668],{"class":122},"    if",[105,670,671],{"class":253}," ($missing) {\n",[105,673,675,678,680,683,685,688,690,693,695,697,700,702],{"class":107,"line":674},52,[105,676,677],{"class":118},"        Set-ADComputer",[105,679,360],{"class":122},[105,681,682],{"class":253},"Identity $computer ",[105,684,619],{"class":122},[105,686,687],{"class":253},"Add ",[105,689,418],{"class":122},[105,691,692],{"class":253},"{ ",[105,694,648],{"class":521},[105,696,288],{"class":122},[105,698,699],{"class":253}," [",[105,701,302],{"class":122},[105,703,704],{"class":253},"[]]$missing }\n",[105,706,708,711,714,716,718,721,723,726,728,730,733,735],{"class":107,"line":707},53,[105,709,710],{"class":118},"        Write-Output",[105,712,713],{"class":521}," \"",[105,715,525],{"class":122},[105,717,281],{"class":521},[105,719,720],{"class":253},"$pair.From",[105,722,533],{"class":521},[105,724,725],{"class":521},": added delegation to ",[105,727,525],{"class":122},[105,729,281],{"class":521},[105,731,732],{"class":253},"$pair.To",[105,734,533],{"class":521},[105,736,590],{"class":521},[105,738,740],{"class":107,"line":739},54,[105,741,460],{"class":253},[105,743,745],{"class":107,"line":744},55,[105,746,247],{"emptyLinePlaceholder":246},[105,748,750,753,755,757,759,762],{"class":107,"line":749},56,[105,751,752],{"class":118},"    Set-ADAccountControl",[105,754,360],{"class":122},[105,756,682],{"class":253},[105,758,619],{"class":122},[105,760,761],{"class":253},"TrustedToAuthForDelegation ",[105,763,764],{"class":118},"$true\n",[105,766,768],{"class":107,"line":767},57,[105,769,466],{"class":253},[11,771,772,773,776,777,780,781,784],{},"Then, on every source and destination host, turn on live migrations outside the cluster with ",[23,774,775],{},"Enable-VMMigration"," (off by default), allow the migration network with ",[23,778,779],{},"Add-VMMigrationNetwork",", and set ",[23,782,783],{},"Set-VMHost -VirtualMachineMigrationAuthenticationType Kerberos",". Remember that live migration traffic isn't encrypted on the wire, so keep it on a trusted, isolated network.",[11,786,787,788,791,792,795,796,799,800,803,804,807],{},"Bandwidth is the other half. A shared-nothing move carries the whole virtual disk, not just memory, so it saturates whatever link it's given. Hyper-V allows two simultaneous live migrations per host by default. ",[23,789,790],{},"Set-VMHost"," caps live and storage migrations separately (",[23,793,794],{},"MaximumVirtualMachineMigrations",", ",[23,797,798],{},"MaximumStorageMigrations","), and on a cluster node the cluster's ",[23,801,802],{},"MaximumParallelMigrations"," property takes precedence for live migrations. If you use the SMB performance option, the SMB bandwidth limit feature (",[23,805,806],{},"FS-SMBBW",", which defaults to 25% of a node's bandwidth once installed) keeps migrations from starving storage and cluster traffic on shared adapters.",[15,809,811],{"id":810},"the-migration-script","The Migration Script",[11,813,814,815,817,818,821,822,824],{},"This is the per-VM loop I run from a management machine. It reads the VMs in the order given, finds each one's owner node on the old cluster, checks the configuration version against the destination host and runs ",[23,816,71],{},". Without ",[23,819,820],{},"-Execute"," it stops there and prints the report, which is the pre-flight I run days ahead. With ",[23,823,820],{}," it removes the clustered role on the old cluster, live migrates the VM and its storage to the new CSV, and makes it highly available on the new cluster. If the move fails, it puts the role back on the old cluster.",[96,826,828],{"className":98,"code":827,"language":100,"meta":101,"style":101},"\u003C#\n.SYNOPSIS\n    Checks and, optionally, live migrates clustered VMs from an old Hyper-V cluster to a new one, one at a time.\n.DESCRIPTION\n    For each VM, in the order given: finds the owner node on the source cluster, checks that the destination\n    host supports the VM configuration version, and runs Compare-VM with storage. Without -Execute it only\n    reports. With -Execute it removes the VM's clustered role on the source cluster, runs Move-VM with\n    -IncludeStorage to a folder under the destination CSV, then runs Add-ClusterVirtualMachineRole on the\n    destination cluster. If Move-VM fails, the role is re-created on the source cluster.\n.PARAMETER VMName\n    VMs to migrate, lowest business risk first.\n.PARAMETER SourceCluster\n    The old cluster.\n.PARAMETER DestinationCluster\n    The new cluster.\n.PARAMETER DestinationHost\n    Node of the new cluster that receives the VMs.\n.PARAMETER DestinationCsvPath\n    CSV folder on the new cluster; each VM gets a subfolder named after it.\n.PARAMETER Execute\n    Perform the migration. Without it the script only reports.\n.EXAMPLE\n    .\\Move-VMToNewCluster.ps1 -VMName 'file01', 'print01' -SourceCluster 'old-clu' -DestinationCluster 'new-clu' -DestinationHost 'new-hv01' -DestinationCsvPath 'C:\\ClusterStorage\\Volume1'\n.NOTES\n    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n    Version : 1.0 (2026-06-10)\n    Requires: Hyper-V and FailoverClusters modules, Kerberos constrained delegation between the hosts\n#>\n\n[CmdletBinding()]\nparam (\n    [Parameter(Mandatory = $true)]\n    [string[]]$VMName,\n\n    [Parameter(Mandatory = $true)]\n    [string]$SourceCluster,\n\n    [Parameter(Mandatory = $true)]\n    [string]$DestinationCluster,\n\n    [Parameter(Mandatory = $true)]\n    [string]$DestinationHost,\n\n    [Parameter(Mandatory = $true)]\n    [string]$DestinationCsvPath,\n\n    [switch]$Execute\n)\n\n$ErrorActionPreference = 'Stop'\n$sourceNodes = (Get-ClusterNode -Cluster $SourceCluster).Name\n$supportedVersions = (Get-VMHostSupportedVersion -ComputerName $DestinationHost).Version | ForEach-Object { \"$_\" }\n\nforeach ($name in $VMName) {\n    $vm = Get-VM -ComputerName $sourceNodes -Name $name -ErrorAction SilentlyContinue | Select-Object -First 1\n\n    if (-not $vm) {\n        Write-Warning \"$name not found on $SourceCluster\"\n        continue\n    }\n\n    $storagePath = Join-Path -Path $DestinationCsvPath -ChildPath $vm.Name\n    $problems = @()\n\n    if ($supportedVersions -notcontains \"$($vm.Version)\") {\n        $problems += \"Configuration version $($vm.Version) is not supported on $DestinationHost (Update-VMVersion needs a shutdown)\"\n    }\n\n    $report = Compare-VM -ComputerName $vm.ComputerName -Name $vm.Name -DestinationHost $DestinationHost -IncludeStorage -DestinationStoragePath $storagePath\n    $problems += $report.Incompatibilities | ForEach-Object { \"$($_.MessageId): $($_.Message)\" }\n\n    [PSCustomObject]@{\n        VM       = $vm.Name\n        Owner    = $vm.ComputerName\n        Version  = \"$($vm.Version)\"\n        SizeGB   = [math]::Round(((Get-VHD -ComputerName $vm.ComputerName -VMId $vm.VMId).FileSize | Measure-Object -Sum).Sum \u002F 1GB, 1)\n        Problems = if ($problems) { $problems -join ' | ' } else { 'None' }\n    }\n\n    if (-not $Execute -or $problems) {\n        continue\n    }\n\n    # Take the VM out of the old cluster's control; the VM keeps running on its owner node.\n    Remove-ClusterGroup -Cluster $SourceCluster -VMId $vm.VMId -RemoveResources -Force\n\n    try {\n        $clock = [System.Diagnostics.Stopwatch]::StartNew()\n        Move-VM -ComputerName $vm.ComputerName -Name $vm.Name -DestinationHost $DestinationHost -IncludeStorage -DestinationStoragePath $storagePath\n        Write-Output \"$($vm.Name) moved to $DestinationHost in $([int]$clock.Elapsed.TotalMinutes) minutes\"\n    } catch {\n        Write-Warning \"Move of $($vm.Name) failed, restoring its clustered role on $SourceCluster : $($_.Exception.Message)\"\n        Add-ClusterVirtualMachineRole -Cluster $SourceCluster -VMId $vm.VMId | Out-Null\n        continue\n    }\n\n    Add-ClusterVirtualMachineRole -Cluster $DestinationCluster -VMName $vm.Name | Out-Null\n    Get-ClusterGroup -Cluster $DestinationCluster -Name $vm.Name | Format-Table -Property Name, OwnerNode, State -AutoSize\n}\n",[23,829,830,834,840,845,851,856,861,866,871,876,885,890,899,904,913,918,927,932,941,946,955,960,966,971,977,981,985,990,994,998,1006,1012,1028,1039,1043,1059,1070,1074,1090,1101,1105,1121,1132,1136,1152,1163,1167,1177,1181,1185,1195,1213,1247,1251,1263,1301,1305,1317,1336,1342,1347,1352,1373,1386,1391,1418,1447,1452,1457,1493,1540,1545,1559,1570,1581,1601,1652,1685,1690,1695,1713,1718,1723,1728,1734,1760,1765,1774,1790,1816,1858,1869,1906,1925,1930,1935,1940,1960,2000],{"__ignoreMap":101},[105,831,832],{"class":107,"line":108},[105,833,112],{"class":111},[105,835,836,838],{"class":107,"line":115},[105,837,119],{"class":118},[105,839,123],{"class":122},[105,841,842],{"class":107,"line":126},[105,843,844],{"class":111},"    Checks and, optionally, live migrates clustered VMs from an old Hyper-V cluster to a new one, one at a time.\n",[105,846,847,849],{"class":107,"line":132},[105,848,119],{"class":118},[105,850,137],{"class":122},[105,852,853],{"class":107,"line":140},[105,854,855],{"class":111},"    For each VM, in the order given: finds the owner node on the source cluster, checks that the destination\n",[105,857,858],{"class":107,"line":146},[105,859,860],{"class":111},"    host supports the VM configuration version, and runs Compare-VM with storage. Without -Execute it only\n",[105,862,863],{"class":107,"line":152},[105,864,865],{"class":111},"    reports. With -Execute it removes the VM's clustered role on the source cluster, runs Move-VM with\n",[105,867,868],{"class":107,"line":158},[105,869,870],{"class":111},"    -IncludeStorage to a folder under the destination CSV, then runs Add-ClusterVirtualMachineRole on the\n",[105,872,873],{"class":107,"line":164},[105,874,875],{"class":111},"    destination cluster. If Move-VM fails, the role is re-created on the source cluster.\n",[105,877,878,880,882],{"class":107,"line":175},[105,879,119],{"class":118},[105,881,169],{"class":122},[105,883,884],{"class":122}," VMName\n",[105,886,887],{"class":107,"line":181},[105,888,889],{"class":111},"    VMs to migrate, lowest business risk first.\n",[105,891,892,894,896],{"class":107,"line":191},[105,893,119],{"class":118},[105,895,169],{"class":122},[105,897,898],{"class":122}," SourceCluster\n",[105,900,901],{"class":107,"line":197},[105,902,903],{"class":111},"    The old cluster.\n",[105,905,906,908,910],{"class":107,"line":205},[105,907,119],{"class":118},[105,909,169],{"class":122},[105,911,912],{"class":122}," DestinationCluster\n",[105,914,915],{"class":107,"line":211},[105,916,917],{"class":111},"    The new cluster.\n",[105,919,920,922,924],{"class":107,"line":219},[105,921,119],{"class":118},[105,923,169],{"class":122},[105,925,926],{"class":122}," DestinationHost\n",[105,928,929],{"class":107,"line":225},[105,930,931],{"class":111},"    Node of the new cluster that receives the VMs.\n",[105,933,934,936,938],{"class":107,"line":231},[105,935,119],{"class":118},[105,937,169],{"class":122},[105,939,940],{"class":122}," DestinationCsvPath\n",[105,942,943],{"class":107,"line":237},[105,944,945],{"class":111},"    CSV folder on the new cluster; each VM gets a subfolder named after it.\n",[105,947,948,950,952],{"class":107,"line":243},[105,949,119],{"class":118},[105,951,169],{"class":122},[105,953,954],{"class":122}," Execute\n",[105,956,957],{"class":107,"line":250},[105,958,959],{"class":111},"    Perform the migration. Without it the script only reports.\n",[105,961,962,964],{"class":107,"line":263},[105,963,119],{"class":118},[105,965,202],{"class":122},[105,967,968],{"class":107,"line":272},[105,969,970],{"class":111},"    .\\Move-VMToNewCluster.ps1 -VMName 'file01', 'print01' -SourceCluster 'old-clu' -DestinationCluster 'new-clu' -DestinationHost 'new-hv01' -DestinationCsvPath 'C:\\ClusterStorage\\Volume1'\n",[105,972,973,975],{"class":107,"line":297},[105,974,119],{"class":118},[105,976,216],{"class":122},[105,978,979],{"class":107,"line":311},[105,980,222],{"class":111},[105,982,983],{"class":107,"line":316},[105,984,228],{"class":111},[105,986,987],{"class":107,"line":333},[105,988,989],{"class":111},"    Requires: Hyper-V and FailoverClusters modules, Kerberos constrained delegation between the hosts\n",[105,991,992],{"class":107,"line":343},[105,993,240],{"class":111},[105,995,996],{"class":107,"line":349},[105,997,247],{"emptyLinePlaceholder":246},[105,999,1000,1002,1004],{"class":107,"line":354},[105,1001,254],{"class":253},[105,1003,257],{"class":118},[105,1005,260],{"class":253},[105,1007,1008,1010],{"class":107,"line":366},[105,1009,266],{"class":122},[105,1011,269],{"class":253},[105,1013,1014,1016,1018,1020,1022,1024,1026],{"class":107,"line":371},[105,1015,275],{"class":253},[105,1017,278],{"class":118},[105,1019,281],{"class":253},[105,1021,285],{"class":284},[105,1023,288],{"class":122},[105,1025,291],{"class":118},[105,1027,294],{"class":253},[105,1029,1030,1032,1034,1037],{"class":107,"line":392},[105,1031,275],{"class":253},[105,1033,302],{"class":122},[105,1035,1036],{"class":253},"[]]$VMName",[105,1038,308],{"class":122},[105,1040,1041],{"class":107,"line":406},[105,1042,247],{"emptyLinePlaceholder":246},[105,1044,1045,1047,1049,1051,1053,1055,1057],{"class":107,"line":434},[105,1046,275],{"class":253},[105,1048,278],{"class":118},[105,1050,281],{"class":253},[105,1052,285],{"class":284},[105,1054,288],{"class":122},[105,1056,291],{"class":118},[105,1058,294],{"class":253},[105,1060,1061,1063,1065,1068],{"class":107,"line":457},[105,1062,275],{"class":253},[105,1064,302],{"class":122},[105,1066,1067],{"class":253},"]$SourceCluster",[105,1069,308],{"class":122},[105,1071,1072],{"class":107,"line":463},[105,1073,247],{"emptyLinePlaceholder":246},[105,1075,1076,1078,1080,1082,1084,1086,1088],{"class":107,"line":469},[105,1077,275],{"class":253},[105,1079,278],{"class":118},[105,1081,281],{"class":253},[105,1083,285],{"class":284},[105,1085,288],{"class":122},[105,1087,291],{"class":118},[105,1089,294],{"class":253},[105,1091,1092,1094,1096,1099],{"class":107,"line":474},[105,1093,275],{"class":253},[105,1095,302],{"class":122},[105,1097,1098],{"class":253},"]$DestinationCluster",[105,1100,308],{"class":122},[105,1102,1103],{"class":107,"line":488},[105,1104,247],{"emptyLinePlaceholder":246},[105,1106,1107,1109,1111,1113,1115,1117,1119],{"class":107,"line":504},[105,1108,275],{"class":253},[105,1110,278],{"class":118},[105,1112,281],{"class":253},[105,1114,285],{"class":284},[105,1116,288],{"class":122},[105,1118,291],{"class":118},[105,1120,294],{"class":253},[105,1122,1123,1125,1127,1130],{"class":107,"line":518},[105,1124,275],{"class":253},[105,1126,302],{"class":122},[105,1128,1129],{"class":253},"]$DestinationHost",[105,1131,308],{"class":122},[105,1133,1134],{"class":107,"line":541},[105,1135,247],{"emptyLinePlaceholder":246},[105,1137,1138,1140,1142,1144,1146,1148,1150],{"class":107,"line":559},[105,1139,275],{"class":253},[105,1141,278],{"class":118},[105,1143,281],{"class":253},[105,1145,285],{"class":284},[105,1147,288],{"class":122},[105,1149,291],{"class":118},[105,1151,294],{"class":253},[105,1153,1154,1156,1158,1161],{"class":107,"line":577},[105,1155,275],{"class":253},[105,1157,302],{"class":122},[105,1159,1160],{"class":253},"]$DestinationCsvPath",[105,1162,308],{"class":122},[105,1164,1165],{"class":107,"line":593},[105,1166,247],{"emptyLinePlaceholder":246},[105,1168,1169,1171,1174],{"class":107,"line":599},[105,1170,275],{"class":253},[105,1172,1173],{"class":122},"switch",[105,1175,1176],{"class":253},"]$Execute\n",[105,1178,1179],{"class":107,"line":604},[105,1180,346],{"class":253},[105,1182,1183],{"class":107,"line":628},[105,1184,247],{"emptyLinePlaceholder":246},[105,1186,1187,1190,1192],{"class":107,"line":660},[105,1188,1189],{"class":118},"$ErrorActionPreference",[105,1191,288],{"class":122},[105,1193,1194],{"class":521}," 'Stop'\n",[105,1196,1197,1200,1202,1205,1208,1210],{"class":107,"line":665},[105,1198,1199],{"class":253},"$sourceNodes ",[105,1201,377],{"class":122},[105,1203,1204],{"class":253}," (",[105,1206,1207],{"class":118},"Get-ClusterNode",[105,1209,360],{"class":122},[105,1211,1212],{"class":253},"Cluster $SourceCluster).Name\n",[105,1214,1215,1218,1220,1222,1225,1227,1230,1232,1235,1238,1240,1243,1245],{"class":107,"line":674},[105,1216,1217],{"class":253},"$supportedVersions ",[105,1219,377],{"class":122},[105,1221,1204],{"class":253},[105,1223,1224],{"class":118},"Get-VMHostSupportedVersion",[105,1226,360],{"class":122},[105,1228,1229],{"class":253},"ComputerName $DestinationHost).Version ",[105,1231,639],{"class":122},[105,1233,1234],{"class":118}," ForEach-Object",[105,1236,1237],{"class":253}," { ",[105,1239,536],{"class":521},[105,1241,1242],{"class":118},"$_",[105,1244,536],{"class":521},[105,1246,657],{"class":253},[105,1248,1249],{"class":107,"line":707},[105,1250,247],{"emptyLinePlaceholder":246},[105,1252,1253,1255,1258,1260],{"class":107,"line":739},[105,1254,477],{"class":122},[105,1256,1257],{"class":253}," ($name ",[105,1259,386],{"class":122},[105,1261,1262],{"class":253}," $VMName) {\n",[105,1264,1265,1268,1270,1273,1275,1278,1280,1283,1285,1288,1290,1293,1295,1298],{"class":107,"line":744},[105,1266,1267],{"class":253},"    $vm ",[105,1269,377],{"class":122},[105,1271,1272],{"class":118}," Get-VM",[105,1274,360],{"class":122},[105,1276,1277],{"class":253},"ComputerName $sourceNodes ",[105,1279,619],{"class":122},[105,1281,1282],{"class":253},"Name $name ",[105,1284,619],{"class":122},[105,1286,1287],{"class":253},"ErrorAction SilentlyContinue ",[105,1289,639],{"class":122},[105,1291,1292],{"class":118}," Select-Object",[105,1294,360],{"class":122},[105,1296,1297],{"class":253},"First ",[105,1299,1300],{"class":118},"1\n",[105,1302,1303],{"class":107,"line":749},[105,1304,247],{"emptyLinePlaceholder":246},[105,1306,1307,1309,1311,1314],{"class":107,"line":767},[105,1308,668],{"class":122},[105,1310,1204],{"class":253},[105,1312,1313],{"class":122},"-not",[105,1315,1316],{"class":253}," $vm) {\n",[105,1318,1320,1323,1325,1328,1331,1334],{"class":107,"line":1319},58,[105,1321,1322],{"class":118},"        Write-Warning",[105,1324,713],{"class":521},[105,1326,1327],{"class":253},"$name",[105,1329,1330],{"class":521}," not found on ",[105,1332,1333],{"class":253},"$SourceCluster",[105,1335,590],{"class":521},[105,1337,1339],{"class":107,"line":1338},59,[105,1340,1341],{"class":122},"        continue\n",[105,1343,1345],{"class":107,"line":1344},60,[105,1346,460],{"class":253},[105,1348,1350],{"class":107,"line":1349},61,[105,1351,247],{"emptyLinePlaceholder":246},[105,1353,1355,1358,1360,1363,1365,1368,1370],{"class":107,"line":1354},62,[105,1356,1357],{"class":253},"    $storagePath ",[105,1359,377],{"class":122},[105,1361,1362],{"class":118}," Join-Path",[105,1364,360],{"class":122},[105,1366,1367],{"class":253},"Path $DestinationCsvPath ",[105,1369,619],{"class":122},[105,1371,1372],{"class":253},"ChildPath $vm.Name\n",[105,1374,1376,1379,1381,1383],{"class":107,"line":1375},63,[105,1377,1378],{"class":253},"    $problems ",[105,1380,377],{"class":122},[105,1382,512],{"class":122},[105,1384,1385],{"class":253},"()\n",[105,1387,1389],{"class":107,"line":1388},64,[105,1390,247],{"emptyLinePlaceholder":246},[105,1392,1394,1396,1399,1402,1404,1406,1408,1411,1413,1415],{"class":107,"line":1393},65,[105,1395,668],{"class":122},[105,1397,1398],{"class":253}," ($supportedVersions ",[105,1400,1401],{"class":122},"-notcontains",[105,1403,713],{"class":521},[105,1405,525],{"class":122},[105,1407,281],{"class":521},[105,1409,1410],{"class":253},"$vm.Version",[105,1412,533],{"class":521},[105,1414,536],{"class":521},[105,1416,1417],{"class":253},") {\n",[105,1419,1421,1424,1427,1430,1432,1434,1436,1438,1441,1444],{"class":107,"line":1420},66,[105,1422,1423],{"class":253},"        $problems ",[105,1425,1426],{"class":122},"+=",[105,1428,1429],{"class":521}," \"Configuration version ",[105,1431,525],{"class":122},[105,1433,281],{"class":521},[105,1435,1410],{"class":253},[105,1437,533],{"class":521},[105,1439,1440],{"class":521}," is not supported on ",[105,1442,1443],{"class":253},"$DestinationHost",[105,1445,1446],{"class":521}," (Update-VMVersion needs a shutdown)\"\n",[105,1448,1450],{"class":107,"line":1449},67,[105,1451,460],{"class":253},[105,1453,1455],{"class":107,"line":1454},68,[105,1456,247],{"emptyLinePlaceholder":246},[105,1458,1460,1463,1465,1468,1470,1473,1475,1478,1480,1483,1485,1488,1490],{"class":107,"line":1459},69,[105,1461,1462],{"class":253},"    $report ",[105,1464,377],{"class":122},[105,1466,1467],{"class":118}," Compare-VM",[105,1469,360],{"class":122},[105,1471,1472],{"class":253},"ComputerName $vm.ComputerName ",[105,1474,619],{"class":122},[105,1476,1477],{"class":253},"Name $vm.Name ",[105,1479,619],{"class":122},[105,1481,1482],{"class":253},"DestinationHost $DestinationHost ",[105,1484,619],{"class":122},[105,1486,1487],{"class":253},"IncludeStorage ",[105,1489,619],{"class":122},[105,1491,1492],{"class":253},"DestinationStoragePath $storagePath\n",[105,1494,1496,1498,1500,1503,1505,1507,1509,1511,1513,1515,1517,1520,1522,1525,1527,1529,1531,1534,1536,1538],{"class":107,"line":1495},70,[105,1497,1378],{"class":253},[105,1499,1426],{"class":122},[105,1501,1502],{"class":253}," $report.Incompatibilities ",[105,1504,639],{"class":122},[105,1506,1234],{"class":118},[105,1508,1237],{"class":253},[105,1510,536],{"class":521},[105,1512,525],{"class":122},[105,1514,281],{"class":521},[105,1516,1242],{"class":118},[105,1518,1519],{"class":253},".MessageId",[105,1521,533],{"class":521},[105,1523,1524],{"class":521},": ",[105,1526,525],{"class":122},[105,1528,281],{"class":521},[105,1530,1242],{"class":118},[105,1532,1533],{"class":253},".Message",[105,1535,533],{"class":521},[105,1537,536],{"class":521},[105,1539,657],{"class":253},[105,1541,1543],{"class":107,"line":1542},71,[105,1544,247],{"emptyLinePlaceholder":246},[105,1546,1548,1550,1552,1554,1556],{"class":107,"line":1547},72,[105,1549,275],{"class":253},[105,1551,412],{"class":122},[105,1553,415],{"class":253},[105,1555,418],{"class":122},[105,1557,1558],{"class":253},"{\n",[105,1560,1562,1565,1567],{"class":107,"line":1561},73,[105,1563,1564],{"class":253},"        VM       ",[105,1566,377],{"class":122},[105,1568,1569],{"class":253}," $vm.Name\n",[105,1571,1573,1576,1578],{"class":107,"line":1572},74,[105,1574,1575],{"class":253},"        Owner    ",[105,1577,377],{"class":122},[105,1579,1580],{"class":253}," $vm.ComputerName\n",[105,1582,1584,1587,1589,1591,1593,1595,1597,1599],{"class":107,"line":1583},75,[105,1585,1586],{"class":253},"        Version  ",[105,1588,377],{"class":122},[105,1590,713],{"class":521},[105,1592,525],{"class":122},[105,1594,281],{"class":521},[105,1596,1410],{"class":253},[105,1598,533],{"class":521},[105,1600,590],{"class":521},[105,1602,1604,1607,1609,1611,1614,1617,1620,1622,1624,1626,1629,1631,1634,1636,1639,1642,1645,1648,1650],{"class":107,"line":1603},76,[105,1605,1606],{"class":253},"        SizeGB   ",[105,1608,377],{"class":122},[105,1610,699],{"class":253},[105,1612,1613],{"class":122},"math",[105,1615,1616],{"class":253},"]::Round(((",[105,1618,1619],{"class":118},"Get-VHD",[105,1621,360],{"class":122},[105,1623,1472],{"class":253},[105,1625,619],{"class":122},[105,1627,1628],{"class":253},"VMId $vm.VMId).FileSize ",[105,1630,639],{"class":122},[105,1632,1633],{"class":118}," Measure-Object",[105,1635,360],{"class":122},[105,1637,1638],{"class":253},"Sum).Sum ",[105,1640,1641],{"class":122},"\u002F",[105,1643,1644],{"class":118}," 1",[105,1646,1647],{"class":122},"GB,",[105,1649,1644],{"class":118},[105,1651,346],{"class":253},[105,1653,1655,1658,1660,1663,1666,1669,1672,1675,1678,1680,1683],{"class":107,"line":1654},77,[105,1656,1657],{"class":253},"        Problems ",[105,1659,377],{"class":122},[105,1661,1662],{"class":122}," if",[105,1664,1665],{"class":253}," ($problems) { $problems ",[105,1667,1668],{"class":122},"-join",[105,1670,1671],{"class":521}," ' | '",[105,1673,1674],{"class":253}," } ",[105,1676,1677],{"class":122},"else",[105,1679,1237],{"class":253},[105,1681,1682],{"class":521},"'None'",[105,1684,657],{"class":253},[105,1686,1688],{"class":107,"line":1687},78,[105,1689,460],{"class":253},[105,1691,1693],{"class":107,"line":1692},79,[105,1694,247],{"emptyLinePlaceholder":246},[105,1696,1698,1700,1702,1704,1707,1710],{"class":107,"line":1697},80,[105,1699,668],{"class":122},[105,1701,1204],{"class":253},[105,1703,1313],{"class":122},[105,1705,1706],{"class":253}," $Execute ",[105,1708,1709],{"class":122},"-or",[105,1711,1712],{"class":253}," $problems) {\n",[105,1714,1716],{"class":107,"line":1715},81,[105,1717,1341],{"class":122},[105,1719,1721],{"class":107,"line":1720},82,[105,1722,460],{"class":253},[105,1724,1726],{"class":107,"line":1725},83,[105,1727,247],{"emptyLinePlaceholder":246},[105,1729,1731],{"class":107,"line":1730},84,[105,1732,1733],{"class":111},"    # Take the VM out of the old cluster's control; the VM keeps running on its owner node.\n",[105,1735,1737,1740,1742,1745,1747,1750,1752,1755,1757],{"class":107,"line":1736},85,[105,1738,1739],{"class":118},"    Remove-ClusterGroup",[105,1741,360],{"class":122},[105,1743,1744],{"class":253},"Cluster $SourceCluster ",[105,1746,619],{"class":122},[105,1748,1749],{"class":253},"VMId $vm.VMId ",[105,1751,619],{"class":122},[105,1753,1754],{"class":253},"RemoveResources ",[105,1756,619],{"class":122},[105,1758,1759],{"class":253},"Force\n",[105,1761,1763],{"class":107,"line":1762},86,[105,1764,247],{"emptyLinePlaceholder":246},[105,1766,1768,1771],{"class":107,"line":1767},87,[105,1769,1770],{"class":122},"    try",[105,1772,1773],{"class":253}," {\n",[105,1775,1777,1780,1782,1784,1787],{"class":107,"line":1776},88,[105,1778,1779],{"class":253},"        $clock ",[105,1781,377],{"class":122},[105,1783,699],{"class":253},[105,1785,1786],{"class":122},"System.Diagnostics.Stopwatch",[105,1788,1789],{"class":253},"]::StartNew()\n",[105,1791,1793,1796,1798,1800,1802,1804,1806,1808,1810,1812,1814],{"class":107,"line":1792},89,[105,1794,1795],{"class":118},"        Move-VM",[105,1797,360],{"class":122},[105,1799,1472],{"class":253},[105,1801,619],{"class":122},[105,1803,1477],{"class":253},[105,1805,619],{"class":122},[105,1807,1482],{"class":253},[105,1809,619],{"class":122},[105,1811,1487],{"class":253},[105,1813,619],{"class":122},[105,1815,1492],{"class":253},[105,1817,1819,1821,1823,1825,1827,1830,1832,1835,1837,1840,1842,1845,1848,1850,1853,1855],{"class":107,"line":1818},90,[105,1820,710],{"class":118},[105,1822,713],{"class":521},[105,1824,525],{"class":122},[105,1826,281],{"class":521},[105,1828,1829],{"class":253},"$vm.Name",[105,1831,533],{"class":521},[105,1833,1834],{"class":521}," moved to ",[105,1836,1443],{"class":253},[105,1838,1839],{"class":521}," in ",[105,1841,525],{"class":122},[105,1843,1844],{"class":521},"([",[105,1846,1847],{"class":122},"int",[105,1849,415],{"class":521},[105,1851,1852],{"class":253},"$clock.Elapsed.TotalMinutes",[105,1854,533],{"class":521},[105,1856,1857],{"class":521}," minutes\"\n",[105,1859,1861,1864,1867],{"class":107,"line":1860},91,[105,1862,1863],{"class":253},"    } ",[105,1865,1866],{"class":122},"catch",[105,1868,1773],{"class":253},[105,1870,1872,1874,1877,1879,1881,1883,1885,1888,1890,1893,1895,1897,1899,1902,1904],{"class":107,"line":1871},92,[105,1873,1322],{"class":118},[105,1875,1876],{"class":521}," \"Move of ",[105,1878,525],{"class":122},[105,1880,281],{"class":521},[105,1882,1829],{"class":253},[105,1884,533],{"class":521},[105,1886,1887],{"class":521}," failed, restoring its clustered role on ",[105,1889,1333],{"class":253},[105,1891,1892],{"class":521}," : ",[105,1894,525],{"class":122},[105,1896,281],{"class":521},[105,1898,1242],{"class":118},[105,1900,1901],{"class":253},".Exception.Message",[105,1903,533],{"class":521},[105,1905,590],{"class":521},[105,1907,1909,1912,1914,1916,1918,1920,1922],{"class":107,"line":1908},93,[105,1910,1911],{"class":118},"        Add-ClusterVirtualMachineRole",[105,1913,360],{"class":122},[105,1915,1744],{"class":253},[105,1917,619],{"class":122},[105,1919,1749],{"class":253},[105,1921,639],{"class":122},[105,1923,1924],{"class":118}," Out-Null\n",[105,1926,1928],{"class":107,"line":1927},94,[105,1929,1341],{"class":122},[105,1931,1933],{"class":107,"line":1932},95,[105,1934,460],{"class":253},[105,1936,1938],{"class":107,"line":1937},96,[105,1939,247],{"emptyLinePlaceholder":246},[105,1941,1943,1946,1948,1951,1953,1956,1958],{"class":107,"line":1942},97,[105,1944,1945],{"class":118},"    Add-ClusterVirtualMachineRole",[105,1947,360],{"class":122},[105,1949,1950],{"class":253},"Cluster $DestinationCluster ",[105,1952,619],{"class":122},[105,1954,1955],{"class":253},"VMName $vm.Name ",[105,1957,639],{"class":122},[105,1959,1924],{"class":118},[105,1961,1963,1966,1968,1970,1972,1974,1976,1979,1981,1984,1987,1990,1992,1995,1997],{"class":107,"line":1962},98,[105,1964,1965],{"class":118},"    Get-ClusterGroup",[105,1967,360],{"class":122},[105,1969,1950],{"class":253},[105,1971,619],{"class":122},[105,1973,1477],{"class":253},[105,1975,639],{"class":122},[105,1977,1978],{"class":118}," Format-Table",[105,1980,360],{"class":122},[105,1982,1983],{"class":253},"Property Name",[105,1985,1986],{"class":122},",",[105,1988,1989],{"class":253}," OwnerNode",[105,1991,1986],{"class":122},[105,1993,1994],{"class":253}," State ",[105,1996,619],{"class":122},[105,1998,1999],{"class":253},"AutoSize\n",[105,2001,2003],{"class":107,"line":2002},99,[105,2004,466],{"class":253},[11,2006,2007],{},"A dry run produces a report like this, which is what we sequenced the schedule from:",[96,2009,2014],{"className":2010,"code":2012,"language":2013,"meta":101},[2011],"language-text","VM        Owner    Version SizeGB Problems\n--        -----    ------- ------ --------\nfile01    OLD-HV01 9.0      412.0 None\nprint01   OLD-HV02 9.0       60.0 None\nlegacy01  OLD-HV01 5.0       80.0 Configuration version 5.0 is not supported on new-hv01 (Update-VMVersion needs a shutdown)\n","text",[23,2015,2012],{"__ignoreMap":101},[11,2017,2018,2020,2021,119],{},[23,2019,40],{}," can't run inside a remote PowerShell session without CredSSP, so run the script in a local session on the management machine, not through ",[23,2022,2023],{},"Enter-PSSession",[15,2025,2027],{"id":2026},"sequencing-to-protect-the-business","Sequencing to Protect the Business",[11,2029,2030],{},"We didn't move everything at once, and not just because of bandwidth. Migrating VMs one at a time, starting with the lowest-risk, least-latency-sensitive workloads, gave us a chance to validate the new cluster's storage performance and network throughput under real migration load before committing anything that actually mattered to the timeline. It also meant that if a migration did have to be aborted partway through — which happened once, when a migration's network path saturated a link shared with a backup job we hadn't accounted for — the blast radius was one non-critical VM, not the whole schedule.",[15,2032,2034],{"id":2033},"what-wed-repeat","What We'd Repeat",[11,2036,2037,2038,2040],{},"Check configuration versions and run ",[23,2039,71],{}," for every VM before scheduling anything, and book the shutdowns that version upgrades and processor compatibility need. Set up constrained delegation early and test it with a throwaway VM. Move in ascending order of business criticality so early mistakes are cheap. And treat the network path for the migration traffic as a first-class resource to plan around, not spare capacity — the migrations that caused trouble were always the ones that collided with something else using the same link. None of the workloads went down. The migrations that felt uneventful were the ones where we'd already found the surprises on something smaller first.",[15,2042,2044],{"id":2043},"references","References",[2046,2047,2048,2058,2066,2073,2081,2088,2095,2110],"ul",{},[2049,2050,2051],"li",{},[2052,2053,2057],"a",{"href":2054,"rel":2055},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows-server\u002Fvirtualization\u002Fhyper-v\u002Fmanage\u002Fuse-live-migration-without-failover-clustering-to-move-a-virtual-machine",[2056],"nofollow","Use live migration without Failover Clustering to move a VM",[2049,2059,2060,2065],{},[2052,2061,2064],{"href":2062,"rel":2063},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows-server\u002Fvirtualization\u002Fhyper-v\u002Fdeploy\u002Fset-up-hosts-for-live-migration-without-failover-clustering",[2056],"Set up hosts for live migration without Failover Clustering"," (Kerberos, CredSSP and Windows Server 2025)",[2049,2067,2068],{},[2052,2069,2072],{"href":2070,"rel":2071},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows-server\u002Fvirtualization\u002Fhyper-v\u002Fprocessor-compatibility-mode",[2056],"Processor compatibility for Hyper-V virtual machines",[2049,2074,2075,2080],{},[2052,2076,2079],{"href":2077,"rel":2078},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows-server\u002Fvirtualization\u002Fhyper-v\u002Fdeploy\u002Fupgrade-virtual-machine-version-in-hyper-v-on-windows-or-windows-server",[2056],"Upgrade virtual machine version in Hyper-V"," (supported versions per host OS)",[2049,2082,2083],{},[2052,2084,2087],{"href":2085,"rel":2086},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows-server\u002Ffailover-clustering\u002Fcluster-operating-system-rolling-upgrade",[2056],"Cluster OS rolling upgrade",[2049,2089,2090],{},[2052,2091,2094],{"href":2092,"rel":2093},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fprevious-versions\u002Fwindows\u002Fit-pro\u002Fwindows-server-2012-r2-and-2012\u002Fdn486772(v=ws.11)",[2056],"Migration of highly available VMs using the Migrate a Cluster Wizard",[2049,2096,2097,795,2101,2105,2106],{},[2052,2098,71],{"href":2099,"rel":2100},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fpowershell\u002Fmodule\u002Fhyper-v\u002Fcompare-vm",[2056],[2052,2102,25],{"href":2103,"rel":2104},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fpowershell\u002Fmodule\u002Fhyper-v\u002Fmove-vm",[2056]," and ",[2052,2107,40],{"href":2108,"rel":2109},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fpowershell\u002Fmodule\u002Ffailoverclusters\u002Fadd-clustervirtualmachinerole",[2056],[2049,2111,2112],{},[2052,2113,2116],{"href":2114,"rel":2115},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows-server\u002Ffailover-clustering\u002Fconfigure-live-migration-smb-bandwidth",[2056],"Control Live Migration SMB bandwidth cluster-wide",[2118,2119,2120],"style",{},"html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":101,"searchDepth":115,"depth":115,"links":2122},[2123,2124,2125,2126,2127,2128,2129,2130],{"id":17,"depth":115,"text":18},{"id":47,"depth":115,"text":48},{"id":62,"depth":115,"text":63},{"id":78,"depth":115,"text":79},{"id":810,"depth":115,"text":811},{"id":2026,"depth":115,"text":2027},{"id":2033,"depth":115,"text":2034},{"id":2043,"depth":115,"text":2044},"techcolumnist",[2133],"engineering","2026-06-10T14:00:00Z","Moving VMs from an old Hyper-V cluster to a new one with shared-nothing live migration: configuration versions, CPU compatibility, delegation, bandwidth and a migration script.","md",false,null,{},"\u002Fblog\u002F2026\u002F06\u002F10\u002Fhyper-v-migrating-vms-off-an-aging-cluster-without-downtime",{"title":6,"description":2135},[2131],"blog\u002F2026\u002F06\u002F10\u002Fhyper-v-migrating-vms-off-an-aging-cluster-without-downtime",[2145,2146],"hyper-v","cluster","\u002F2026\u002F06\u002F10\u002Fhyper-v-migrating-vms-off-an-aging-cluster-without-downtime\u002F","eerxZm3HeLPp8Xz0nCPpsz29D-gv4rQv-TB9He-Ea1o",{"title":2150,"description":2151,"date":2152,"url":2153,"categories":2154,"tags":2155,"image":2138,"readingTime":158,"canonical":2131,"sites":2160,"series":2138,"seriesOrder":2138},"Windows 11: A Debloat and Hardening Baseline for New Deployments","A repeatable Windows 11 baseline: policy-based app removal, Microsoft security baselines, BitLocker, Defender and ASR settings, plus a fleet audit script.","2026-06-17T14:00:00Z","\u002F2026\u002F06\u002F17\u002Fwindows-11-a-debloat-and-hardening-baseline-for-new-deployments\u002F",[2133],[2156,2157,2158,2159],"windows-11","debloat","gpo","intune",[2131],{"title":2162,"description":2163,"date":2164,"url":2165,"categories":2166,"tags":2167,"image":2138,"readingTime":146,"canonical":2131,"sites":2168,"series":2138,"seriesOrder":2138},"Hyper-V: Deploying a Two-Node Failover Cluster on a Budget","Building a two-node Hyper-V cluster without a SAN: Storage Spaces Direct requirements, nested resiliency, witness options, hardware rules and scripts to build and test it.","2026-06-03T14:00:00Z","\u002F2026\u002F06\u002F03\u002Fhyper-v-deploying-a-two-node-failover-cluster-on-a-budget\u002F",[2133],[2145,2146],[2131],[2161,2170,2181],{"title":2171,"description":2172,"date":2173,"url":2174,"categories":2175,"tags":2177,"image":2138,"readingTime":140,"canonical":2131,"sites":2180,"series":2138,"seriesOrder":2138},"Hyper-V to Talos: Rethinking the Virtualization Stack","Why moving workloads off Hyper-V VMs onto a Talos Kubernetes cluster changed the whole stack, with an inventory script and a VM-to-manifest example.","2026-09-16T14:00:00Z","\u002F2026\u002F09\u002F16\u002Fhyper-v-to-talos-rethinking-the-virtualization-stack\u002F",[2133,2176],"strategy",[2145,2178,2179],"talos","kubernetes",[2131],{"title":2182,"description":2183,"date":2184,"url":2185,"categories":2186,"tags":2187,"image":2138,"readingTime":158,"canonical":2131,"sites":2189,"series":2138,"seriesOrder":2138},"Infrastructure: What a Real Disaster Recovery Test Actually Reveals","What a real DR failover exposes that a tabletop never catches, with a Hyper-V Replica test failover script that checks each recovered VM and a runbook checklist.","2026-07-22T14:00:00Z","\u002F2026\u002F07\u002F22\u002Finfrastructure-what-a-real-disaster-recovery-test-actually-reveals\u002F",[2133,2176],[2188,2145],"backup",[2131],{"doc":2138,"posts":2191},[],1790052514034]