PowerCLI

  • 1.  Script for Compute + Storage vMotion

    Posted May 08, 2024 10:18 AM

    @LucD it's been a while but looking for some help.  Worked with you in the past.  

    Looking for a good PS script I can manipulate for the following task:

    1. Compute and Storage vMotion a VM to a new ESXi host
    2. Run it using a list of VMs
    3. Run only 2 concurrent tasks at a time to avoid saturation

    Basically looking to kick off a long duration job that can be checked every few hours.  

    Thank you so much!  



  • 2.  RE: Script for Compute + Storage vMotion

    Posted May 08, 2024 12:06 PM

    1. What exactly do you mean by "compute"?
    3. I assume you mean background jobs (-RunAsync)?



    ------------------------------


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


    ------------------------------



  • 3.  RE: Script for Compute + Storage vMotion

    Posted May 08, 2024 02:10 PM

    Ah yes sorry we are looking to vMotion a VM to another ESXi host, + storage vMotion its LUN location as well in the same task.  

    Run 2 x tasks in parallel.  

    1 x task a time works too if it keeps pulling the next one in a list sequentially 




  • 4.  RE: Script for Compute + Storage vMotion

    Posted May 08, 2024 03:07 PM

    Not sure I understand what you mean by "storage vMotion its LUN location"
    Is that LUN used for an RDM disk on the VM?



    ------------------------------


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


    ------------------------------



  • 5.  RE: Script for Compute + Storage vMotion

    Posted Jun 05, 2024 09:26 AM
    Edited by E splat Jun 05, 2024 09:28 AM

    Hi @LucD sorry for the late response.  Looking to run the following task automatically from a VM list.  Screenshot below.  

    When 1 x VM completes, kick off the next VM same task without interaction.  

    No RDMs are used in our environment.  Regular VMFS LUNs in a datastore cluster.  




  • 6.  RE: Script for Compute + Storage vMotion

    Posted Jun 05, 2024 09:34 AM

    That is basically using the Move-VM cmdlet with the VMHost and Datastore parameters.
    When you don't use the RunAsync switch the cmdlet will wait till the move is complete.

    You can read the names of the VMs, and then in a foreach loop execute the Move-VM cmdlet.



    ------------------------------


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


    ------------------------------



  • 7.  RE: Script for Compute + Storage vMotion

    Posted Feb 04, 2025 02:28 PM
    Edited by E splat Feb 04, 2025 02:28 PM

    Thanks again!  This worked great for me as I only needed to do storage moves for this round...  

    $VMs = get-vm (Get-Content d:\temp\VmList.txt)

    foreach ($v in $VMs) {

        $new_san_cluster = Get-DatastoreCluster -Name DatastoreClusterName-iSCSI

        Write-Host "Storage vMotion of $v to $random_new_san_lun is beginning"

        Move-VM -VM $v -Datastore $new_san_cluster -Confirm:$false

    }




  • 8.  RE: Script for Compute + Storage vMotion

    Posted Jun 10, 2024 12:54 AM

    I wrote a script a few years back to move VMs to new hosts and datastores. 

    I am sharing that script with you but please modify as per your environment/need before executing it.

    <#
    VMs bigger than 500GB will move between 7 and 12
    VMs smaller than 500GB will move between 12 and 5
    VM which should not be in the same datastore must be separated manually
    Script will confirm that destination datastore has enough free space to fit the vm
    Script will skip following
    •	VMs with "F5" in their name
    •	VMs with "MSX" in their name (Exchange)
    •	VMs with "Was" in their name (Websphere)
    •	VMs which have snapshot
    •	VMs with RDM
    #>
    
    $vms =  @"
    APPD01WASPOC
    APPD09WAS
    APPD11WAS
    APPS66WAS
    APPT04WAS
    "@ -split "`r`n"  -replace '(^\s+|\s+$)','' -replace '\s+',' ' 
    
    
    $Cluster = "DevCluster" # exact cluster name
    $TargetDS = Get-Datastore internal* | sort name | select -First 10
    
    
    $AllVMs = Get-Cluster | Get-VM
    # Minus VMs which have already moved
    $VMstoMove = $AllVMs | ? {($_ | Get-Datastore).name -notin  $TargetDS.name}
    
    # Minus VMs with Snapshot
    $VMstoMove = $VMstoMove | ? { (!($_ | get-snapshot))}  | select -Property VM -Unique
    
    
    
    $vms = Get-cluster DevCluster | get-vm | where { ($_.Name -notmatch "f5") -and ($_.Name -notmatch "msx") -and ($_.Name -notmatch "was") } | sort -Property ProvisionedSpaceGB -Descending
    $vmswithRDM = $vms | Get-HardDisk -DiskType "RawPhysical", "RawVirtual" | Select -Unique -property Parent | select Parent
    #$vmswithsnapshot = $vms | get-snapshot | select -Property VM -Unique
    foreach ($r in $vmswithRDM)
    {
    	$vms = $vms | ? { $_.name -ne $r.parent }
    }
    foreach ($s in $vmswithsnapshot)
    {
    	$vms = $vms | ? { $_.name -ne $s.VM }
    }
    
    $big = $vms | ? { [int]$_.ProvisionedSpaceGB -gt 500 -and (!($_ | Get-Datastore |sort Name | select -First 19)) } 
    
    
    $small = $vms | ? { [int]$_.ProvisionedSpaceGB -lt 500 -and (!($_ | Get-Datastore |sort Name | select -First 19)) } 
    $dir = split-path -parent $MyInvocation.MyCommand.Definition
    cd $dir
    
    
    
    Function Get-FreeDatastore
    {
    	$BusyVMs = (get-task | ? { ($_.state -EQ "Running") -and ($_.Name -eq "RelocateVM_Task") }) | select ObjectId
    	$BusyDatastore = (get-vm -id $BusyVMs.ObjectId | Get-VIEvent -Start (get-date).AddDays(-1) | ? { $_.fullformattedmessage -like "migrating*" -or $_.fullformattedmessage -like "Relocating*" -and $_.fullformattedmessage -like "*from*" -and $_.fullformattedmessage -like "*to*" } | Select @{ N = "Datastore"; E = { $_.destdatastore.name } }).Datastore
    	Get-Datastore internal* | sort name | select -First 19 | Select Name, @{ N = "FreeSpace"; E = { [math]::round($_.ExtensionData.Summary.freespace/1GB) } }, @{ N = "Provisioned"; E = { [math]::round(($_.ExtensionData.Summary.Capacity - $_.ExtensionData.Summary.FreeSpace + $_.ExtensionData.Summary.Uncommitted)/1GB) } } | Sort-Object -Property Provisioned | ? { $_.name -notin $BusyDatastore } | select -First 1
    }
    
    Function Get-Freehosts
    {
    	$BusyVMs = (get-task | ? { ($_.state -EQ "Running") -and ($_.Name -eq "RelocateVM_Task") }) | select ObjectId
        $Busyhosts = ((get-vm -id $BusyVMs.ObjectId | get-vmhost).name)
    	(Get-cluster DevC* | get-vmhost).name | ? {$_ -notin $Busyhosts}
    	#(get-vmhost $Busyhosts | get-cluster | get-vmhost | sort name | ? { $_.name -notin $Busyhosts }).name
    }
    
    
    
    While ($True)
    {
    	[int]$hour = get-date -format HH
    	If ($hour -gt 7 -and $hour -lt 17)
    	{
    		[int]$Currentjobs = (get-task | ? { ($_.state -EQ "Running") -and ($_.Name -eq "RelocateVM_Task") }).count
    		If ($Currentjobs -lt 3)
    		{
    			If ($hour -le 8)
    			{
    				"$($big.count) big vms left"
    				try
    				{
    					$bigvm = Get-VM $($big.name | select -First 1) -ErrorAction SilentlyContinue
                        $big = $big | ? { $_.name -ne $bigvm.name }
    				}
    				catch { }
    				If ($bigvm -ne $null)
    				{
    					$datastore = Get-FreeDatastore
    					If ($bigvm.ProvisionedSpaceGB -lt $datastore.FreeSpace)
    					{
    						"Moving big vm"
    						$CurrentHost = $bigvm | Get-VMHost
    						$freeHosts = Get-Freehosts
    						If ($CurrentHost -iin $freeHosts) { }
    						else { Move-VM $bigvm -Destination $(((get-vmhost $freeHosts) | Select Name, @{ N = "Provisioned"; E = { (($_ | get-vm).MemoryGB | Measure-Object -sum).Sum } } | Sort-Object -Property Provisioned -Descending | select -Last 1).name) }
    						Move-VM -VM $bigvm -datastore $datastore.Name -DiskStorageFormat Thin -RunAsync -Confirm:$false -Verbose
    						
    					}
    					else
    					{
    						Write-Host "$bigvm is too big for $datastore.name" | Tee-Object .\SVMotion.log -Append | write-host -ForegroundColor Red
    					}
    				}
    				else
    				{
    					Write-Host "All big vms have been moved" -ForegroundColor green
    				}
    				Clear-Variable bigvm
    			}
    			Else
    			{
    				"$($small.count) small vms left"
    				try
    				{
    					$smallvm = Get-VM $($small.name | select -First 1) -ErrorAction SilentlyContinue
                        $small = $small | ? { $_.name -ne $smallvm.name }
    				}
    				catch { }
    				If ($smallvm -ne $null)
    				{
    					$datastore = Get-FreeDatastore
    					If ($smallvm.ProvisionedSpaceGB -lt $datastore.FreeSpace)
    					{
    						"Moving small vm"
    						$freeHosts = Get-Freehosts
    						If ($CurrentHost -iin $freeHosts) { }
    						else { Move-VM $smallvm -Destination $(((get-vmhost $freeHosts) | Select Name, @{ N = "Provisioned"; E = { (($_ | get-vm).MemoryGB | Measure-Object -sum).Sum } } | Sort-Object -Property Provisioned -Descending | select -Last 1).name) }
    						Move-VM -VM $smallvm -datastore $datastore.Name -DiskStorageFormat Thin -RunAsync -Confirm:$false -Verbose
    					}
    					else
    					{
    						Write-Host "$smallvm is too big for $datastore.name" | Tee-Object .\SVMotion.log -Append | write-host -ForegroundColor Red
    					}
    				}
    				else
    				{
    					Write-Host "All small vms have been moved" -ForegroundColor green
    				}
    				Clear-Variable smallvm
    			}
    		}
    	}
    	
    	if (!($hour -gt 7 -or $hour -lt 17))
    	{
    		Write-Host "SVMotion has been paused till 7am"
    		Start-Sleep -Seconds 300
    	}
    	Start-Sleep -Seconds 5
    }