Wednesday, July 11, 2012

Measuring VMWare Storage vMotion performance

Hello guys! A lot of Powershell these days as you can see from my previous blog posts. I have just been busy taking care of a Storage vMotion between a source ESX host, a buffer Openfiler-based NFS datastore, and a destination ESX host. As I was encountering pretty slow transfer rates between the ESX and the NFS datastore, I decided to improve the classic Powershell script used to relocate VMDKs (which is easily found on many blog posts). So, to make it better, I added the capability of executing a network performance measurement by taking advantage of the Measure-Command cmdlet.

In fact this cmdlet measure the time it takes to execute any kind of script/command/block. You just have to include the block of commands containing the "RelocateVM" method between "Measure-Command {" and "}" and just retrieve the "TotalSeconds" property to know how many seconds it took to make the transfer.

At this point round the returned value to the nearest whole number:
$duration1rounded = [math]::round($duration1)
Then make a quick calculation of the size of the disks for the VM you want to migrate:
$vmdksize =  [math]::round((Get-VM -Name $vm | Select-Object Name,UsedSpaceGB).usedspaceGB)
... and find the speed rate by dividing $vmdksize by $duration1rounded:
$speedrate = [math]::round(($vmdksize * 1024) / $duration1rounded)
Easy, right? Let's have a look at the whole script.
There are four parts.
  1. In the beginning we get the list of the VMs sitting on the source ESX and we drop from this list the VMs that we specify in the $exclude_targetVM variable.
  2. For each VM we move the VMDK from the local datastore to the NFS. The duration of this action is measured with Measure-Command and its value in seconds is stored in a variable called $duration1, which is then rounded using [math]:round
  3. In this part the VM is vMotioned to the destination ESX (which has access to the same NFS datastore). The duration of this action goes in $duration2
  4. The vmdks for this VM is relocated on the local datastore of the destination ESX. Measure-Command does the job of counting the seconds it takes.
Here's the full script:
$sourcehost = "host1"
$targethost = "host2"
Add-PSSnapIn VMware.VimAutomation.Core
# write here the VM you don't want to migrate:
$exclude_targetVM ="vm to exclude"
# change this to suit your needs:
Connect-VIServer VCservername
$src= (get-vmhost $sourcehost) 
#looks for a datastore named nfs (change this to suit your needs):
$ds1=($src |Get-Datastore "nfs*")
$dssrc=$ds1.Extensiondata.MoRef
# now it retrieves all the VMs: 
$vms = ($src | Get-VM )
$vmlist= $vms | where {!($_.name -match $exclude_targetVM)} 
$tgt= (get-vmhost $targethost) 
# looks for a datastore named local* (change this to suit your needs):
$ds2=($tgt | Get-Datastore "local*")
$dsdest=$ds2.Extensiondata.MoRef
$rp= ($tgt |Get-ResourcePool)|select -First 1 |get-view
$tgtv=$tgt|get-view
 
foreach ($vm in $vmlist){ # moves all the VMs one by one 
$vmdksize =  [math]::round((Get-VM -Name $vm | Select-Object Name,UsedSpaceGB).usedspaceGB) 
Write-Host "*** Started SVMotion Script for $vm *** to $($ds1.name)" -foregroundcolor blue 
$duration1 = ((measure-command {
$HardDisks = @(Get-HardDisk -VM $vm)
$spec = New-Object VMware.Vim.VirtualMachineRelocateSpec
$spec.Datastore = $dssrc
1..$HardDisks.Count | %{
$objDisk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$objDisk.DiskID = $HardDisks[$_ - 1].Id.Split('/')[1]
$objDisk.DataStore = $dssrc
$spec.Disk += $objDisk        }
$action1 = $vm.ExtensionData.RelocateVM($spec, "defaultPriority") 
}).totalseconds)    
write-host "Done SVMOTION to NFS" -ForegroundColor green
$duration1rounded = [math]::round($duration1)
$rate = [math]::round(($vmdksize * 1024) / $duration1rounded)
"Trasferred $vmdksize GB in $duration1rounded seconds. Rate: $rate MBps" 
Write-Host "*** VMotion Script for $vm *** to $($ds1.name)" -foregroundcolor blue
$duration2 = ((measure-command {
$action2=$vm.ExtensionData.migrateVM($rp.MoRef,$tgtv.moref,"defaultPriority",$null)
}).totalseconds)    
write-host "Done VMOTION in $duration2rounded seconds" -ForegroundColor green
$duration2rounded = [math]::round($duration2) 
Write-Host "*** Started SVMotion Script for $vm *** to $dsdest.name" -foregroundcolor blue 
$duration3 = ((measure-command {
$HardDisks = @(Get-HardDisk -VM $vm)
$spec = New-Object VMware.Vim.VirtualMachineRelocateSpec
$spec.Datastore = $dsdest
1..$HardDisks.Count | %{
$objDisk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$objDisk.DiskID = $HardDisks[$_ - 1].Id.Split('/')[1]
$objDisk.DataStore = $dsdest
$spec.Disk += $objDisk        }
$action3 = $vm.ExtensionData.RelocateVM($spec, "defaultPriority") 
}).totalseconds) 
write-host "Done SVMOTION to NFS" -ForegroundColor green 
$duration3rounded = [math]::round($duration3)
$rate = [math]::round(($vmdksize * 1024) / $duration3rounded)
"Trasferred $vmdksize GB in $duration3rounded seconds. Rate: $rate MBps"
} #end foreach
The output of this script should look like this:
*** Started SVMotion Script for vm1 *** to nfs
Done SVMOTION to NFS
Trasferred 26 GB in 1128 seconds. Rate: 24 MBps
*** VMotion Script for vm1 *** to nfs
done VMOTION in 37 seconds
*** Started SVMotion Script for vm1 *** to Datastore-datastore-99107
Done SVMOTION to NFS
Trasferred 26 GB in 799 seconds. Rate: 33 MBps
*** Started SVMotion Script for vm2 *** to nfs
Done SVMOTION to NFS
Trasferred 26 GB in 993 seconds. Rate: 27 MBps
*** VMotion Script for vm2 *** to nfs
done VMOTION in 30 seconds
*** Started SVMotion Script for vm2 *** to Datastore-datastore-99107
Done SVMOTION to NFS

If you have any question about this script feel free to comment and I'll try to help. Alos if you want to suggest any improvement I'll be glad to hear from you!

No comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...