VMware Cloud Community
BenLiebowitz
Expert
Expert

Script to migrate VMs from one cluster to another



I need help with this script as it's not working properly for me...  


My environment is currently running 4.1 and I have a need to migrate VMs from Cluster 1 running the Nexus 1000v to Cluster 2 running a normal vDS switch.  When i attempt to do this via the VI client, I'm forced to remove the network adapter, migrate the VM and then re-add the network adapter back...  This makes me lose my network config in windows.  I came up with this script that will shutdown the VMs in a specific folder, remove them from inventory, re-add them to inventory in on a host in the 2nd cluster, change the VM Portgroup and then power the VM back on.  However, I'm running into a problem with the 2nd half of the script, it's not able to locate the VMX file.  


Any help would be greatly appreciated!  


Thanks!


Ben 

-


  1. *** Part 1 ***</div>

  1. export list of VMs to Migrate to CSV</div>


Get-Folder -Name "Migrate" | get-vm | Select Name, @{N="Datastore";E={get-datastore -VM $_}},@{N="Network";E={get-virtualportgroup -VM $_}}| export-csv "c:\migrate.csv" -NoTypeinformation


  1. Get VMs to Migrate</div>


$migrate = Get-Folder -Name "Migrate"


  1. Shutdown VMs (cleanly)</div>


$migrate | Get-VM | Shutdown-VMGuest -Confirm:$false


  1. Wait for VMs to shutdown</div>


start-sleep -s 60


  1. Remove VMs from Inventory</div>


Get-Folder -Name "Migrate" | Get-Inventory | Remove-Inventory -Confirm:$false


  1. *** Part 2 ***</div>

  1. Set a host in Cluster2 to add them to.</div>


$esxhost = "VMHost10.domain.com"


    1. Add backto inventory &amp; Change network for VMs</div>


foreach ($row in (Import-Csv c:\Migrate.csv)) {



    $vmName = $row.Name



    $vmxfile = '[$row.Datastore] $vmName/$vmName.vmx'



    $vmNewVM = New-VM -VMFilePath $vmxfile -VMhost $esxhost


   

  1. Change Network Portgroup</div>


    get-vm -VM $row.Name | Get-NetworkAdapter | Set-NetworkAdapter -NetworkName $row.Network


   

  1. Poweron VMs</div>


    Start-VM -VM $row.Name -Confirm:$false | wait-tools  



} ## end foreach

Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
44 Replies
LucD
Leadership
Leadership

Try changing this line

$vmxfile = '[$row.Datastore] $vmName/$vmName.vmx'

into

$vmxfile = '[$($row.Datastore)] $($vmName)/$($vmName).vmx'

Does that change anything ?

If not, are you getting any error messages ?


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

Reply
0 Kudos
BenLiebowitz
Expert
Expert



That didn't change anything... here's the error I'm getting... 


New-VM : 2/25/2014 1:31:45 PM    New-VM        The operation for the entity "vm



" failed with the following message: "Invalid datastore path '[$($row.Datastore



)] $($vmName)/$($vmName).vmx'."



At C:\ps1\vmware\migrate_to_clust2.ps1:27 char:22



+     $vmNewVM = New-VM <<<<  -VMFilePath $vmxfile -VMhost $esxhost


    + CategoryInfo          : NotSpecified: (Smiley Happy , InvalidDatastorePath


    + FullyQualifiedErrorId : Client20_TaskServiceImpl_CheckServerSideTaskUpda



   tes_OperationFailed,VMware.VimAutomation.ViCore.Cmdlets.Commands.NewVM



New-VM : 2/25/2014 1:31:46 PM    New-VM        2/25/2014 1:31:45 PM    New-VM



      The operation for the entity "vm" failed with the following message: "Inv



alid datastore path '[$($row.Datastore)] $($vmName)/$($vmName).vmx'."



At C:\ps1\vmware\migrate_to_clust2.ps1:27 char:22



+     $vmNewVM = New-VM <<<<  -VMFilePath $vmxfile -VMhost $esxhost


    + CategoryInfo          : NotSpecified: (Smiley Happy , InvalidDatastorePath


    + FullyQualifiedErrorId : Client20_TaskServiceImpl_CheckServerSideTaskUpda



   tes_OperationFailed,VMware.VimAutomation.ViCore.Cmdlets.Commands.NewVM



Get-VM : A parameter cannot be found that matches parameter name 'VM'.



At C:\ps1\vmware\migrate_to_clust2.ps1:30 char:15



+     get-vm -VM <<<<  $row.Name | Get-NetworkAdapter | Set-NetworkAdapter -Net



workName $row.Network


    + CategoryInfo          : InvalidArgument: (Smiley Happy , ParameterBindingE


   xception



    + FullyQualifiedErrorId : NamedParameterNotFound,VMware.VimAutomation.ViCo



   re.Cmdlets.Commands.GetVM



Start-VM : 2/25/2014 1:31:48 PM    Start-VM        Could not find VirtualMachin



e with name 'VM03'.



At C:\ps1\vmware\migrate_to_clust2.ps1:33 char:13



+     Start-VM <<<<  -VM $row.Name -Confirm:$false | wait-tools


    + CategoryInfo          : ObjectNotFound: (VM03:String)


   , VimException



    + FullyQualifiedErrorId : Core_ObnSelector_SelectObjectByNameCore_ObjectNo



   tFound,VMware.VimAutomation.ViCore.Cmdlets.Commands.StartVM

Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
Reply
0 Kudos
LucD
Leadership
Leadership

I just noticed, you have single quotes around that string with the variables.

Replace them by double quotes, otherwise the variables will not be resolved


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

Reply
0 Kudos
BenLiebowitz
Expert
Expert

I just copied/pasted what you put above.  Smiley Wink 

Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
Reply
0 Kudos
LucD
Leadership
Leadership

So did I :smileygrin:

But does that change anything ?


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

Reply
0 Kudos
BenLiebowitz
Expert
Expert

Smiley Happy  It got me further... 

It's now able to add the VMs back to inventory but the section to change the portgroup isn't working.  Smiley Sad

Error: 

Get-VM : A parameter cannot be found that matches parameter name 'VM'.

At C:\ps1\vmware\migrate_to_clust2.ps1:31 char:15

+     get-vm -VM <<<<  $row.Name | Get-NetworkAdapter | Set-NetworkAdapter -Net

workName $row.Network

    + CategoryInfo          : InvalidArgument: (:) [Get-VM], ParameterBindingE

   xception

    + FullyQualifiedErrorId : NamedParameterNotFound,VMware.VimAutomation.ViCo

   re.Cmdlets.Commands.GetVM

I pasted my migrate.csv below...  The portgroup names are exactly the same on both the 1000v and the VDS.

NameDatastoreNetwork
VM01LUN01VLAN-126
VM02LUN01LAN-VLAN-40
VM03LUN02DMZ-VLAN-52
VM04LUN02DMZ-VLAN-52
Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
Reply
0 Kudos
LucD
Leadership
Leadership

That should be

get-vm -Name $row.Name


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

BenLiebowitz
Expert
Expert

Mr. Dekens, you sir are my hero.  Smiley Happy 

Can I add -Confirm:$false to the end of that get-vm line? 

Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
Reply
0 Kudos
BenLiebowitz
Expert
Expert

Also, is there a way to script the answer to the virtual machine question asking if I moved or copied the VM?  Smiley Happy 

Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
Reply
0 Kudos
BenLiebowitz
Expert
Expert

Just looked that up and it looks like I can do this... 

get-vm -Name $row.Name | Get-NetworkAdapter | Set-NetworkAdapter -NetworkName $row.Network -Confirm:$false | Get-VMQuestion | Set-VMQuestion –Option "I moved it"

Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
Reply
0 Kudos
LucD
Leadership
Leadership

No need to have the network adapter in the question line.

Just do

$vm = get-vm -Name $row.Name

Get-VMQuestion -VM $vm | Set-VMQuestion –Option "I moved it"

Get-NetworkAdapter -VM $vm | Set-NetworkAdapter -NetworkName $row.Network -Confirm:$false


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

Reply
0 Kudos
LucD
Leadership
Leadership

The Get-VM cmdlet doesn't have a Confirm switch, in fact there is no point in having a Confirm switch on any of the Get- cmdlets.


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

Reply
0 Kudos
BenLiebowitz
Expert
Expert

Okay, my next question falls in the "would be nice" category... 

How can I add the VM's folder location to my migrate.csv so I can set the location and put the VM back in the same folder after migration...  We have multiple folders with the same name, one in the DMZ parent folder and one in the Internal parent folder... Some VMs are in a folder, within a folder, within a folder, etc... 

Thanks for all your help!

Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
Reply
0 Kudos
LucD
Leadership
Leadership

With the BlueFolderPath New-VIProperty from my Folder by Path post, you can add the folder location of the VM to the export info.

On the import side, you will have to take that path info and located the correct folder, before importing the VM.

Let me know if you need some further info on that ?


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

Reply
0 Kudos
BenLiebowitz
Expert
Expert

So you're saying on the import side, I'd need to do something like...

Get-Folder -Name "Parent" | Get-Folder -Name "Level 2" | Get-Folder -Name "Level 3" | new-vm ....

?  That might be rough to script out of the bluefolderpath export...  Might not be worth my time... May just export the path info so I can move them manually later. 

Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
Reply
0 Kudos
LucD
Leadership
Leadership

No, no.

If you include the New-VIProperty from that post in your script, you can use the new property BlueFolderPath which will be added to each VirtualMachine object (which are returned by Get-VM).

See the last example in the post, you could do

Get-VM | Select Name,BlueFolderPath

See my VIProperties page for some more info on the New-VIProperty cmdlet


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

Reply
0 Kudos
BenLiebowitz
Expert
Expert

Yeah I saw that on how to extract the blue folder path and thats great...  I'll use that to build a list of what's in what folder... however, how can I use that in conjunction with the New-VM line in my script with the -Location switch? 

Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
Reply
0 Kudos
LucD
Leadership
Leadership

When you have the blue folder path, you can split the string, and then check if each of the intermediate folders exist.

Similar to the import part I did in Re: Export and Import of Resource Pools using PowerCLI


Are all the folders created in advance (before you start importing VMs), or do you need to create the folders on the fly ?


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

Reply
0 Kudos
BenLiebowitz
Expert
Expert

The folders are already created...  When I add the VMs back to inventory, I'd like to be able to put them VMs back into the folder(s) they came from...  so, I'd like to put the folder path into the migrate.csv and then read that from the CSV to place the VM back into the same folder it came from. 

Ben Liebowitz, VCP vExpert 2015, 2016, & 2017 If you found my post helpful, please mark it as helpful or answered to award points.
Reply
0 Kudos