VMware Cloud Community
Abacus99
Contributor
Contributor
Jump to solution

PowerCLI script to migrate VMs to new vCenter environment

Hi everybody,

in the next few weeks we need to migrate about 700 server VMs (Windows/Linux) to a new environment (new vCenter, new hosts, but VMs will remain on the same datastores). VMs will be migrated not in a single batch, but rather time by time (which, on the other hand, can include the need to migrate some 10s of VMs at the same time).

Cluster names and the folder structure will be identical in the old and new vCenters. As the host names in the new vCenter differ from the ones in the old vCenter, I thought about providing a "translation table" which tells the script to register a given VM at host B (new vCenter) when having been registered to host A (old vCenter) and so on.

I thought about writing a PowerCLI script which, more or less, can accomplish the following steps:

  • Connect to vCenterOld and vCenterNew
  • Read host correlation table from a file (see step "register VM to vCenterNew below)

Then, in a loop:

  • Ask for VM name
  • Get VM paramaters: Datastore/Path, Network/Portgroup, HA Restart Priority, Host, Folder, Notes
  • Show VM name and parameters and ask for confirmation to migrate the VM
  • Power down VM (Shut down OS gracefully, but force power off if power state is still not equal "off" after a given time)
  • Unregister VM from vCenterOld (revmove from inventory)
  • Register VM to vCenterNew from datastore (assumptions: same folder as in vCenterOld, host names differ, but for each source host in vCenterOld a destination host in vCenterNew to register the VM to can be provided, i.e. as CSV)
  • Set VM portgroup (same name as in vCenterOld)
  • Set VM HA restart priority
  • PowerON VM
  • Wait for/Check VM connectivity (e.g. ping) / Continue immediately if VM is reachable or after a given time if VM is still unreachable
  • Confirm that the VM has been migrated successfully OR ask user to check the VM connectivity

Now to my questios:

  • Does somebody know about an existing script which does something similar or contains parts that may be useful to compile a script like that?
  • How can two vCenter connections at the same time been managed within a PowerCLI script - or doesn't this work at all and a connect/disconnect to/from both vCenters needs to be done for each VM?

Thanks a lot for any help.

0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

The following seems to work for me

$vm = Get-VM -Name MyVM
$nic = Get-NetworkAdapter -VM $vm
$vdPG = $nic | select -ExpandProperty NetworkName

Get-VDPortgroup -Name $vdPG


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

0 Kudos
7 Replies
LucD
Leadership
Leadership
Jump to solution

There is such a script described in Maish's vCenter PowerCLI Migration Script  post.

You can connect to multiple vCenters by configuring PowerCLI in multiple mode.

See the Set-PowerCLIConfiguration cmdlet and the DefaultVIServerMode parameter.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Abacus99
Contributor
Contributor
Jump to solution

Thanks a lot for the link. The script you mentioned is very interesting, but I decided to put a new one together. By the way: no multiple mode - I decided to connect first to the source vCenter, read all needed attributes and power down and unregister the VM. After connecting to the new (destination) vCenter, the script does the rest - this works. So no loop - but the script takes all required arguments and has a quiet mode, so it can be scripted itself.

Right now, I'm nearly done - but I'm a bit stuck witch handling the dvPortgroups. I need to read the name of the dvPortgroup which the adapter of the VM is attached to in the old (source) vCenter. I don't want to get the portgroup object (which would be invalid after being disconnectet from the source vCenter), but just the (string) name of the dvPortgroup.

$vmportgroup = $vm.NetworkAdapters.NetworkName does the trick, but tells me to be deprecated and to use "Get-NetworkAdapter" instead. What I couldn't figure out so far is how to get this simple string safely extracted with this new commandlet.

On the other hand, when the script is connected to the new vCenter and has sucessfully registered the VM, attaching the (identically named) dvPortgroup of the new dvSwitch to the network adapter seems to be tricky too. I tried this:

[$vmportgroup is the (string) name of the dvPortgroup (same name in botch vCenters)]

$vm = Get-Vm -Name $migvm -ErrorAction Stop

$mig_portgroup = Get-VDPortgroup -Name $vmportgroup -ErrorAction Stop > $null

$vm | Get-NetworkAdapter | Set-NetworkAdapter -PortGroup $mig_portgroup -ErrorAction Stop -Confirm:$False > $null

This doesn't work, and the debugger tells me that $mig_portgroup is empty after the second line (while it throws no error and a portgroup corresponding to $vmportgroup is definitely there)!

This one works, but seems to be unreliable (works only sometimes - don't really get when it works and when not):

$vm = Get-Vm -Name $migvm -ErrorAction Stop

$vm | Get-NetworkAdapter | Set-NetworkAdapter -NetworkName $vmportgroup -ErrorAction Stop -Confirm:$False > $null

So - what would be the correct and safe way to handle this?

Very confused - thanks for any support.

Nachricht geändert durch Abacus99 May I add another question: all VMs that are registerd by the script get, after being powerd on, a "vSphere HA Protection error" which basically says that the VM is unprotected. Disabling and re-enabling HA on the cluster fixes the error. This behaviour is described in a KB article - with no current resolution: http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=202008... Is there something I can do about this in the script? VMs are registered with this command: $newvm = New-VM -VMFilePath $vmpath -VMHost $targethost -Location $dest_folder -HARestartPriority $vmrestart -ErrorAction Stop -Confirm:$false > $null Removing the -HARestartPriority argument (which means: use cluster settings) doesn't fix the problem. Thanks again - thought it to be an easy task, but it turns out to be rather tricky...

0 Kudos
LucD
Leadership
Leadership
Jump to solution

The following seems to work for me

$vm = Get-VM -Name MyVM
$nic = Get-NetworkAdapter -VM $vm
$vdPG = $nic | select -ExpandProperty NetworkName

Get-VDPortgroup -Name $vdPG


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
Abacus99
Contributor
Contributor
Jump to solution

Thank you so much! The cause for my issue was the "> $null" redirection which I had used in the Get-VDPortgroup statement. Thanks again.

Do you have any idea concerning the HA issue?

And. by the way: is there any way to get rid of the "popup" messages with the progress bar which apper at certain operations (for example, register VM)? I think, using the -RunAsync parameter would accomplish it - but brings new issues (like the need to wait for myself for the operation to complete).

Thanks again for any hint.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

You can disable the progress bar by adding

$ProgressPreference = "SilentlyContinue"

I'm afraid I have no other solution for the HA problem, besides the one mentioned in the KB.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
Abacus99
Contributor
Contributor
Jump to solution



Right now, I'm nearly done. Nevertheless, I found some strange behaviour: Since we use the same folder names in different datacenters, I needed some way to register a VM with a full folder path. You functions Get-FolderPath and Get-FolderByPath came in here very handy - thank you so much. What I found is that one of our two vCenters (the old one, 5.0U1) gives a root folder named "Datacenters" (as your functions assume), while the new one (5.5B) returns "Datencenter" instead. This is of course very annoying, because it means that your functions will work only when migration in one direction.

Of course the script can handle this (manually), but nevertheless I'd very much like to keep it generic and know where the German string "Datencenter" comes from. Server OS is English, but local settings (keyboard, date&time format etc.) are German. Is there anything that can be done to get the same result out of both vCenter servers?

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Yes, I could check the ESXi version in the function and act accordingly.

I'll see if I can update my functions this evening.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos