Thanks for the heads up on the API documentation. I'll save that for future reference.
I just completed the script and after using measure-command to check some execution times, it turns out that it wasn't the esxcli commands that were causing the excessive run times. By converting everything else over to get-view commands, the script is now very quick to execute.
I'll post the script here in case anyone can see any easy ways to improve it. I definitely cobbled it together pulling ideas from a few sources. Most notably it was adapted from this script by Arnim van Lieshout: Match VM and Windows harddisks using PowerShell | Arnim van Lieshout
PS this is my first time posting code, is there no way to do syntax highlighting for PowerShell??
#Load PowerCLI modues
if ( !(Get-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) ) {
. “C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1"}
#Prompt for vCenter Server if no connection exists
if(!$global:DefaultVIServers){$vCenterServer = Read-Host -Prompt "Enter the vCenter server you would like to connect to"
Connect-VIServer $vCenterServer}
else{Write-Host "You are connected to $Global:DefaultVIServers, continuing with connected server"}
#Prompt for datacenter
$Datacenter = Read-Host -Prompt "Enter the datacenter you would like to check for perennial reservations"
#Get VMs from the specified datacenter that have a SCSI adapter set in physical sharing mode
$DatacenterFilter = Get-View -ViewType Datacenter -Property Name -Filter @{"Name"="^$Datacenter$"} | select -ExpandProperty MoRef
$MSCSVMsView = Get-View -ViewType VirtualMachine -SearchRoot $DatacenterFilter |
Where-Object {$_.Config.Hardware.Device.SharedBus -eq "physicalSharing" -and $_.Config.Hardware.Device.DeviceInfo.Label -match "SCSI Controller"}
#Get LUN ID of each RDM attached to the physically shared SCSI adapter on each VM
foreach($MSCSVMView in $MSCSVMsView){
$VirtualSCSIControllers = $MSCSVMView.Config.Hardware.Device | Where-Object{$_.SharedBus -eq "physicalSharing" -and $_.DeviceInfo.Label -match "SCSI Controller"}
foreach($VirtualSCSIController in $VirtualSCSIControllers){
$MSCSVirtualDiskDevices = $MSCSVMView.Config.Hardware.Device | Where-Object {$_.ControllerKey -eq $VirtualSCSIController.Key}
$MSCSLUNIds += $MSCSVirtualDiskDevices.Backing.LunUuid}}
#Filter for duplicate LUN IDs (due to multiple VMs in a cluster having the same LUNs presented)
$MSCSLunIds = $MSCSLunIds | Sort -Unique
#Check each host for the LUN. If the LUN exists, check for perennial reservation. If no reservation exists, set reservation.
Foreach($VMHost in ($VMHosts = Get-View -ViewType HostSystem -SearchRoot $DatacenterFilter)){
$myesxcli = Get-EsxCli -VMhost $VMHost.Name
Foreach($MSCSLUNId in $MSCSLUNIds){
if(!($MSCSCanonicalName = $VMHost.Config.StorageDevice.ScsiLun | Where-Object{$_.Uuid -eq $MSCSLUNId} | Select -ExpandProperty CanonicalName)){
Write-Host $MSCSLUNId "does not exist on " $VMHost.Name ". Skipping"}
else{
if($myesxcli.storage.core.device.list($MSCSCanonicalName).IsPerenniallyReserved -eq "true"){
Write-Host "$MSCSCanonicalName is already perennially reserved on" $VMHost.Name ". Skipping"}
else{
$myesxcli.storage.core.device.setconfig($false, $MSCSCanonicalName, $true)
Write-Host "Added perennial reservation for $MSCSCanonicalName on " $VMHost.Name}
}}}