Combining PowerCLI & ESXCLI to change PSP on a Large Scale

Using PowerCLI you can use Set-ScsiLun -MultipathPolicy “RoundRobin” to set the PSP, but I found it quite slow using it on a large scale. It would update one datastore on one host every 5 seconds. If there were 10 ESXi hosts with 200 Datastores, that’s 2000 operations, at 5 seconds each, it adds up to 3 hours. The same can be done using ESXCLI extremely quickly, but it’s run on each host. If only there was a way to combine PowerCLI and ESXCLI.

There is… Get-EsxCli

A quick and dirty script that combines PowerCLI & ESXCLI to change the PSP on multiple hosts & datastores.

Use at your own risk. This will change the PSP to RoundRobin for any non local device.

Get existing PSP to see how many you need to change:

1:  $AllESXHosts = Get-Cluster CLUSTERNAME | Get-VMHost | Where { ($_.ConnectionState -eq "Connected") -or ($_.ConnectionState -eq "Maintenance")} | Sort Name   <br />2:  ForEach ($esxhost in $AllESXHosts) {  <br />3:    Get-VMhost $esxhost | Get-ScsiLun -LunType disk | Where { $_.MultipathPolicy -notlike "RoundRobin" } |Where {$_.IsLocal -notlike "True"} | Select CanonicalName,MultipathPolicy,IsLocal |ft -autosize  <br />4:  }  <br />

Set PSP:

1:  $AllESXHosts = Get-Cluster CLUSTERNAME |Get-VMHost | Where { ($_.ConnectionState -eq "Connected") -or ($_.ConnectionState -eq "Maintenance")} | Sort Name   <br />2:  ForEach ($esxhost in $AllESXHosts) {  <br />3:    $esxcli = Get-EsxCli -VMHost $esxhost  <br />4:    $targetdevice = Get-VMhost $esxhost | Get-ScsiLun -LunType disk | Where { $_.MultipathPolicy -notlike "RoundRobin" } |Where {$_.IsLocal -notlike "True"}   <br />5:    ForEach ($device in $targetdevice) {  <br />6:      Write-Host "Updating $ $device.CanonicalName"  <br />7:      $$null,$device,"VMW_PSP_RR")  <br />8:    }  <br />9:   }  <br />

 For a more cautious approach, try one host at a time:

1: $esxcli = Get-EsxCli -VMHost $esxhost
2: Get-VMhost $esxhost | Get-ScsiLun -LunType disk | Where { $_.MultipathPolicy -notlike "RoundRobin" } |Where {$_.IsLocal -notlike "True"} | $$null,$device,"VMW_PSP_RR")  <br />

Run the script to get PSP again to confirm it worked.

The interesting thing is there’s no logs of the changes happening in vCenter when using esxcli as opposed to Set-ScsiLun,and ssh is NOT enabled, so it’s still using your vCenter credentials.

So you don’t have to go through this process again, remember to set the default PSP on each host, or use Host Profiles!!

esxcli storage nmp satp set --default-psp=policy --satp=your_SATP_name


Disclaimer: I’m pretty terrible with PowerCLI, so this must look pretty ugly. I’m sure there’s better ways to do it, but it gets the job done.


Comment by Anonymous on 2017-06-19 20:06:19 +0000

for “$”, why do you use $null? i’ve seen several sources that use differing parameters: $null, $true, $false. Is there still a bug where param #1 is not used correctly?

Andrew Dauncey
Andrew Dauncey
Senior Consultant at VMware PSO

Every day I’m shuffling