And here I thought this was an easy one.
Objective:
Prerequisites:
Since vMotion is not an option, a shutdown and startup is required. I put together the following simple script to shutdown guest; wait until machine is not running and do a Move-VM and Start-VM.
Script:
$vms = Import-CSVC:\Scripts\PowerCLI\CSmoveInput.csv
foreach ($vm in $vms){
$VMdestination = Get-VMHost $vm.tVMhost
$Network = $vm.tVLAN
Get-VM -Name $vm.name | Get-NetworkAdapter | Set-NetworkAdapter -StartConnected:$true -Confirm:$false -NetworkName $Network
Shutdown-VMGuest -VM $vm.name -Confirm:$false
while (Get-VMGuest $vm.name | where{$_.State -eq "Running"})
{
echo "Machine is Still Running"
Sleep -Seconds 3
}
Write-Host $vm.name is off
Move-VM -vm $vm.name -Destination$VMdestination
Start-VM -vm $vm.name
}
Most of the time it works fine but too often I get "The operation is not allowed in the current state."
Is there a better way to ensure the VM is OFF?
Any help is greatly appreciated!
Robert
Can you try the While-loop like this
$vms = Import-CSVC:\Scripts\PowerCLI\CSmoveInput.csv foreach ($vm in $vms){ $VMdestination = Get-VMHost $vm.tVMhost $Network = $vm.tVLAN Get-VM -Name $vm.name | Get-NetworkAdapter | Set-NetworkAdapter -StartConnected:$true -Confirm:$false -NetworkName $Network Shutdown-VMGuest -VM $vm.name -Confirm:$false while ((Get-VM $vm.name).PowerState -ne "PoweredOff") { echo "Machine is Still Running" Sleep -Seconds 3 } Write-Host $vm.name is off Move-VM -vm $vm.name -Destination$VMdestination Start-VM -vm $vm.name }
The State property returned by the Get-VMGuest cmdlet, returns the state of the VMware Tools on the guest.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Can you try the While-loop like this
$vms = Import-CSVC:\Scripts\PowerCLI\CSmoveInput.csv foreach ($vm in $vms){ $VMdestination = Get-VMHost $vm.tVMhost $Network = $vm.tVLAN Get-VM -Name $vm.name | Get-NetworkAdapter | Set-NetworkAdapter -StartConnected:$true -Confirm:$false -NetworkName $Network Shutdown-VMGuest -VM $vm.name -Confirm:$false while ((Get-VM $vm.name).PowerState -ne "PoweredOff") { echo "Machine is Still Running" Sleep -Seconds 3 } Write-Host $vm.name is off Move-VM -vm $vm.name -Destination$VMdestination Start-VM -vm $vm.name }
The State property returned by the Get-VMGuest cmdlet, returns the state of the VMware Tools on the guest.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Luc, thank you again for your help. It works perfect!
Robert
LucD -
I know that this is an old discussion, but I have a question regarding this script. (And forgive me because I'm a PowerCLI noob). Where do you specify the hostname and portgroup/dvportgroup name in the script? Is it after the "$vm." in $vm.tVMhost and $vm.tVLAN? If you want to move the 100+ VMs to several different hosts in a cluster, do you have to run this script several times, each time using a .csv with a different list of VM names?
Thanks!
The script uses a CSV file as input.
The Import-Csv cmdlet reads the file into variable $vms, then we loop through all the rows in $vms.
The $vm variable represents 1 row from the CSV file in the script.
And you address the different columns by using the columnname (tVMHost, tVLAN...) as the propertyname on the $vm variable.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Ahhh, I see. The second half of your response cleared it up for me. Thanks for the clarification LucD!
Going to start testing this script this week. I noticed that the script changes the network for the VM before shutting it down? In my scenario, the source cluster and destination cluster will have different network configs (different dvswitches, different dvportgroups). Not sure that changing the network for the VMs at that point would work since they can't see the new network until they're moved to the new cluster.
That is true, but it depends on what you want to do.
When you change the network, the OS running inside the VM will not be reachable anymore.
On the other hand, the cmdlets that work on the VM virtual HW itself, or through the VMware Tools interface will still work since they don't rely on the VM OS network connectivity.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I don't mind if the VMs lose network connectivity shortly before shutting down. Just was not sure if the network/dvportgroup change for the VMs would be successful on the VMware side since the old hosts are not part of that dvswitch and can't see the dvportgroups.
To be honest I'm not sure if the Set-NetworkAdapter will take a non-existing portgroup. I'll have to try that out.
But you can always create these portgroups temporary on the source cluster if needed, and remove them after the migration.
You don't need to connect any vNICs to these temporary portgroups.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
For my scenario, I modified the script to do the following for each VM:
Removed the shutting down VMs portion of the script, since in my case the VMs will already be down. Was thinking I would have to modify the script if any VMs had more than one network adapter, but it looks like I got lucky because all have just one adapter. Tested modified script and it's working. Would be nice if I could figure out how to modify the loop so that multiple VMs migrate at the same time (or perhaps I just use mulitple command windows, multiple spreadsheets). -Stacy
$vms = Import-CSV c:\csmoveinput
foreach ($vm in $vms){
$VMdestination = Get-VMHost $vm.VMhost
$Network = $vm.VLAN
Get-VM -Name $vm.name | Get-NetworkAdapter | Set-NetworkAdapter -StartConnected:$true -Confirm:$false -NetworkName dvTransfer
Move-VM -vm $vm.name -Destination $VMdestination
Get-VM -Name $vm.name | Get-NetworkAdapter | Set-NetworkAdapter -StartConnected:$true -Confirm:$false -NetworkName $Network
Start-VM -vm $vm.name
}
Your best bet to multi-thread the script woud be, imho, to use the Start-Job cmdlet and launch a job for each VM.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference