Powershell – Queue VMware Virtual Machine vMotion using powercli

powerclipowershellscriptingvmotionvmware-vsphere

I wrote this quick Powershell script where it queues vMotion of VMs and runs only 4 vMotion tasks at a time. I thought this might help someone, so you are free to modify the code as per your like.

We were moving VMs to 2 different datastore for a DR exercise overnight.

I have placed comments in the script, but if you have any questions, please comment below. I am sure this can be done in a much better way, but this was a quick thing as I had to leave it running, so the VMs are migrated overnight.

The main command that helped me was get-task.

I am not sure why I didn't have to specify Host for vMotion but VMs were migrated to correct hosts, Maybe DRS took care of that

Best Answer

Start-Transcript

#import the servernames from csv file
Import-Csv 'C:\Users\Administrator\Desktop\RestoreDetails Queue.csv' | foreach {

    #check if vm already on required datastore, change the datastore name as per your environment
    if ((get-vm $_.host |Get-Datastore).name -ne "DataStore1" -or (get-vm $_.host |Get-Datastore).name -ne "DataStore2") {

        Write-Host "`nStaring vMotion session for "$_.host

        #Get current running tasks for Relocatin VM and check if the count is lower than 4
        #I am checking for currently running tasks and with Perecentage over 0%, sometimes there are tasks that are just waiting
        if ((Get-Task | ?{$_.name -eq "RelocateVM_Task" -and $_.state -eq "Running" -and $_.PercentComplete -ne "0"}).count -lt "4") {


            Write-Host "`nLess than 4 vMotions Migrations are going"         

            #if the count is lower than 4 then check which datastore has more freespace available
            if ((Get-Datastore -Name "DataStore1").freespacegb -ge (Get-Datastore -Name "DataStore2").freespacegb) {

                Write-Host ("`nStarting " + $_.host + " to Datastore DataStore1")
                #send an email
                Send-MailMessage -to "username@domain.com" -from from@domain.com -Subject ("Starting " + $_.host + " to Datastore DataStore1") -SmtpServer smtp.domain.com -DeliveryNotificationOption OnFailure, delay

                #start vMotion to DataStore1
                get-vm -Name $_.HOST | Move-VM -Datastore DataStore1 -RunAsync

            }
            else {


                Write-Host ("`nStarting " + $_.host + " to DataStore2")
                Send-MailMessage -to "username@domain.com" -from from@domain.com -Subject ("Starting " + $_.host + " to Datastore DataStore1") -SmtpServer smtp.domain.com -DeliveryNotificationOption OnFailure, delay

                #Start vMotion to Storage DataStore2
                get-vm -Name $_.HOST | Move-VM -Datastore DataStore2 -RunAsync

            }
        }
        else {

            #if more that 4 relocation tasks are running then wait for them to finish
            sleep 5
            Write-Host "`nWaiting for current vMotions to finish..."
            Write-Host "`nCurrent number of vMotions:"(Get-Task | ?{$_.name -eq "RelocateVM_Task" -and $_.state -eq "Running" -and $_.PercentComplete -ne "0"}).count
            do {
                #wait 60 seconds and recheck again                    
                sleep 60
            } while ((Get-Task | ?{$_.name -eq "RelocateVM_Task" -and $_.state -eq "Running"-and $_.PercentComplete -ne "0"}).count -ge "4")

                #Repeate the above process when vMotion tasks go lower than 4
                if ((Get-Task | ?{$_.name -eq "RelocateVM_Task" -and $_.state -eq "Running" -and $_.PercentComplete -ne "0"}).count -lt "4") {

                Write-Host "`nLess than 4 vMotions Migrations are going"         

                if ((Get-Datastore -Name "DataStore1").freespacegb -ge (Get-Datastore -Name "DataStore2").freespacegb) {

                    Write-Host ("`nStarting " + $_.host + " to Datastore1")
                    Send-MailMessage -to "username@domain.com" -from from@domain.com -Subject ("Starting " + $_.host + " to Datastore DataStore1") -SmtpServer smtp.domain.com -DeliveryNotificationOption OnFailure, delay

                    get-vm -Name $_.HOST | Move-VM -Datastore DataStore1 -RunAsync

                }
                else {
                    Write-Host ("`nStarting " + $_.host + " to Datastore2")
                    Send-MailMessage -to "username@domain.com" -from from@domain.com -Subject ("Starting " + $_.host + " to Datastore DataStore1") -SmtpServer smtp.domain.com -DeliveryNotificationOption OnFailure, delay

                    get-vm -Name $_.HOST | Move-VM -Datastore DataStore2 -RunAsync

                }
            }

        }

    }
}

#Check which VM's are on DR DataStore storage already
Import-Csv 'C:\Users\Administrator\Desktop\RestoreDetails Queue.csv' | foreach {

    if ((get-vm $_.host |Get-Datastore).name -ne "DataStore2" -or (get-vm $_.host |Get-Datastore).name -ne "DataStore1") {
        [array]$DRStorage =+ $_.host
    }
    else {
        [array]$NoDRStorage =+ $_.host
      }
}


Stop-Transcript