PowerCLI Script to set RDM LUNs to Perennially Reserved – Fixes Slow Boot of ESXi 5.1 with MSCS RDMs
I've previously posted around this topic as part of another problem but having had to figure out the process again I think it's worth re-posting a proper script for this. VMware KB 1016106 is snappily titled "ESXi/ESX hosts with visibility to RDM LUNs being used by MSCS nodes with RDMs may take a long time to boot or during LUN rescan" and describes the situation where booting ESXi (5.1 in my case) takes a huge amount of time to boot because it's attempting to gain a SCSI reservation on an RDM disk used by MS Clustering Services. It also details the fix.
The process is fairly simple, but a bit labour intensive if you're doing it manually on a large cluster.
- Retrieve the ScsiCanonicalName for each RDM
- Set the configuration for each RDM on each Host to "PerenniallyReserved"
Step 1 - Retrieve the ScsiCanonicalName for each RDM
This PowerCLI command lists the RDM disks attached to any VMs in a particular cluster. What we need here specifically is the SCSI canonical name (often known as the naa or eui identifier), but for the sake of sanity I suggest running it manually and examining the disks to ensure you're happy with the ones the script will set to PerenniallyReserved:
Get-VM -Location "DefinIT Lab Cluster" | Get-HardDisk -DiskType "RawPhysical","RawVirtual" | Select Parent,Name,DiskType,ScsiCanonicalName
Step 2 - Set the configuration for each RDM on each Host to "PerenniallyReserved"
Once we have the list of RDM disks, we can then set the reservation via Get-EsxCli
Connect-VIServer "host01.definit.local" -Credential (Get-Credential) $esxcli = Get-EsxCli $esxcli.storage.core.device.setconfig($false, "naa.6005076307ffc7930000000000000109", $true)
Building Steps 1 and 2 into a script
Now it's just a simple case of constructing a script to loop through the hosts in a cluster and the RDMs on each host:
param(
[string] $TargetCluster,
[PSCredential] $RootCredentials = (Get-Credential)
)
# Create a connection object to all hosts in the Target Cluster
Get-Cluster $TargetCluster | Get-VMHost | % { Connect-VIServer $_ -Credential $RootCredentials | Out-Null }
# Find the ScsiCanonicalName for all RDM Disks attached to VMs in the Target Cluster
$RDMDisks = Get-VM -Location $TargetCluster | Get-HardDisk -DiskType "RawPhysical","RawVirtual" | Select ScsiCanonicalName
# Retrieve and EsxCli instance for each connection
foreach($esxcli in Get-EsxCli) {
# And for each RDM Disk
foreach($RDMDisk in $RDMDisks) {
# Set the configuration to "PereniallyReserved".
# setconfig method: void setconfig(boolean detached, string device, boolean perenniallyreserved)
$esxcli.storage.core.device.setconfig($false, ($RDMDisk.ScsiCanonicalName), $true)
}
}
# Disconnect the connection objects created for the Target Cluster
Disconnect-VIServer * -Confirm:$false | Out-Null
The script connects to each ESXi instance in the target cluster, queries all VMs on the target cluster and returns the RDM disks and then sets the PerenniallyReserved flag for each of the cluster hosts and RDM disks.
As usual, post any comments or improvements!
Edit: After my conversations with Mike, I've modified the script a little and attached as a zip file to download here: Set-RDMReservations

The PowerCLI Script to set RDM LUNs to Perennially Reserved – Fixes Slow Boot of ESXi 5.1 with MSCS RDMs by DefinIT, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

May 8th, 2013 - 15:48
Hey Sam!
This is exactly what I was looking for. However if I use the script you created I get a error:
= : Missing expression after ‘=’.
+ CategoryInfo : ParserError: (=:String) [], ParseException
+ FullyQualifiedErrorId : MissingExpressionAfterToken
May 8th, 2013 - 16:01
Hi – is that the full error message? Does it prompt you for credentials or not get that far? Can you try putting brackets around Get-Credential at the beginning? Line 3
Sam
May 8th, 2013 - 16:14
Here is the full error – no prompt for creds.
At H:\VMware_Scripts\RDM_Perennially\RDM.ps1:3 char:35
+ [PSCredential] $RootCredentials = Get-Credential)
+ ~
Missing expression after ‘=’.
At H:\VMware_Scripts\RDM_Perennially\RDM.ps1:3 char:33
+ [PSCredential] $RootCredentials = Get-Credential)
+ ~
Missing ‘)’ in function parameter list.
At H:\VMware_Scripts\RDM_Perennially\RDM.ps1:3 char:50
+ [PSCredential] $RootCredentials = Get-Credential)
+ ~
Unexpected token ‘)’ in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : MissingExpressionAfterToken
May 8th, 2013 - 17:54
Ok, that’s definitely the brackets around the get-credential, I’ll update the script! Must have lost them in the paste as they’re in my original file! Let me know if that solves it for you?
May 8th, 2013 - 18:08
Yeah – when I originally copied the code the formatting didn’t come over clean and was pasted onto one line. I’ve tested the copy on Powershell ISE and PowerGUI with the same results. After updating the brackets I do get further however it gets stuck on the $TargetCluster in line 7. See error below:
Get-Cluster : Cannot validate argument on parameter ‘Name’. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.
At H:\VMware_Scripts\RDM_Perennially\RDM.ps1:7 char:13
+ Get-Cluster $TargetCluster | Get-VMHost | % { Connect-VIServer $_ -Credential $R …
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-Cluster], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetCluster
Get-VM : 5/8/2013 2:02:13 PM Get-VM VIContainer parameter: Could not find any of the objects specified by name.
At H:\VMware_Scripts\RDM_Perennially\RDM.ps1:10 char:13
+ $RDMDisks = Get-VM -Location $TargetCluster | Get-HardDisk -DiskType “RawPhysica …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (VMware.VimAutom…iner[] Location:RuntimePropertyInfo) [Get-VM], ObnRecordProcessingFailedException
+ FullyQualifiedErrorId : Core_ObnSelector_SetNewParameterValue_ObjectNotFoundCritical,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetVM
Get-EsxCli : 5/8/2013 2:02:13 PM Get-EsxCli Value cannot be found for the mandatory parameter VMHost
At H:\VMware_Scripts\RDM_Perennially\RDM.ps1:13 char:20
+ foreach($esxcli in Get-EsxCli) {
+ ~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-EsxCli], VimException
+ FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetEsxCli
Disconnect-VIServer : 5/8/2013 2:02:13 PM Disconnect-VIServer Could not find any of the servers specified by name.
At H:\VMware_Scripts\RDM_Perennially\RDM.ps1:23 char:2
+ Disconnect-VIServer * -Confirm:$false | Out-Null
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (VMware.VimAutom…Server[] Server:RuntimePropertyInfo) [Disconnect-VIServer], ServerObnFailureException
+ FullyQualifiedErrorId : Core_ObnSelector_SetNewParameterValue_ServerSpecifiedButNotFound,VMware.VimAutomation.ViCore.Cmdlets.Commands.DisconnectVIServer
May 9th, 2013 - 13:24
That seems to indicate that you’ve not put the $TargetCluster parameter into the script when you called it? I’ve not made it a mandatory parameter so perhaps it’s not too clear, call it using the name of the script, then the target cluster, e.g:
.\Set-RDMReservation.ps1 "Production Cluster 1"May 9th, 2013 - 13:50
Hey Sam – thanks for the help. I’ve tried that too however when I call out the cluster when running the script it errors out on Get-Cluster with “you are not currently connected to any servers” even though I’ve when opening PowerCLI and getting prompted from the execution of the script.
May 9th, 2013 - 13:54
Are you connected to a vCenter Server? Connect-VIServer “servername” first!
May 9th, 2013 - 13:55
Of course!
May 9th, 2013 - 14:10
Hmmm, not sure what to suggest here – I have just run the script without any issue:
Connect-VIserver "virtualcenter".\Set-RDMReservations.ps1 "Production Cluster 1"
It prompts me for credentials and then processes the RDMs:
May 9th, 2013 - 15:11
I noticed you were running Release 2 so I just upgraded my version. Got a slightly different error however its still credential related. Any way you can send me the original code so I can compare it to what im using?
Connect-VIServer : 5/9/2013 10:57:34 AM Connect-VIServer Cannot complete login due to an incorrect user name or
password.
At H:\vmware_scripts\RDM_Perennially\RDM.ps1:7 char:47
+ Get-Cluster $TargetCluster | Get-VMHost | % { Connect-VIServer $_ -Credential $R …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Connect-VIServer], InvalidLogin
+ FullyQualifiedErrorId : Client20_ConnectivityServiceImpl_Reconnect_Exception,VMware.VimAutomation.ViCore.Cmdlets.Comm
ands.ConnectVIServer
May 9th, 2013 - 15:32
The code is now linked above, that’s exactly the code I am using. The new error suggests that you aren’t supplying the root credential to log into the ESXi host? The credentials for vCenter won’t do here as it needs to get an ESXCLI instance.
May 9th, 2013 - 15:46
Seems to work now! The code from the link above worked and it appears to bit slightly different from what I originally copied. Thanks again for all the help! This is gonna save me tons of time on my 5.1 upgrades. My hosts are take 3+ hrs. to boot. I’ll report back on timings after I put these changes in.
May 9th, 2013 - 15:52
Great! I think a re-write of how to use the script might help a bit
May 9th, 2013 - 17:21
Seems like you have to reconnect to the VC before running this script regardless if you have done so when first launching PowerCLI. Ran this on my Cluster and my reboots are running about 7mins, down from 2.5-3hrs! Thanks again Sam!!
May 9th, 2013 - 22:23
That’s great news, glad to be of help! The script disconnects all the sessions at the end because it creates one for each host, so that probably explains the need to connect. I can probably sort that fairly easily, but it’s not the sort of script I envisage needing to run too often!
May 10th, 2013 - 19:06
Any suggestions on how to write a script that would display the “Perennially reserved =” status for each RDM visible to each host?
By the time you get an ESXi cluster of 9 hosts, with a dozen or so MSCS clusters, each with 3 or 4 RDMs each, it becomes cubersome to make sure you have created a reservation for each one. And if they don’t have reservations, then the maitre d’ can make you wait an hour for a table, and you end up waiting in the lounge drinking Manhattans on an empty stomach and getting into a debate about how long the Euro will last with a hapless bystander.
So you see why I need to have a script like that.
Thanks for any help you might be able to provide.
May 10th, 2013 - 20:49
Definitely, I manage several clusters of 32 hosts with dozens of MSCS clusters, so I feel that pain! I’ve written a script that will detect RDMs and set the Perennially reserved status here: http://www.definit.co.uk/2013/03/powercli-script-to-set-rdm-luns-to-perennially-reserved-fixes-slow-boot-of-esxi-5-1-with-mscs-rdms/
I’m sure it could easily be modified to display the status if you needed – but the end goal might be achieved as is!
May 10th, 2013 - 22:53
Thanks for quick response.