PowerCLI Scripting to set Queue Full Threshold and Queue Full Sample Size
If you've ever dug into the guts of an ESXi host configuration, you've probably found that there are some settings that you just can't configure without the command line. An example that I came across recently was for a customer with 3Par storage. As per the VMware and 3Par Best Practices Guide, you should configure 3 settings on a per LUN basis: the Multipathing Policy, the Queue Full Threshold and the Queue Full Sample Size.
The Multipathing Policy is easy to set through the GUI, at least if you really like clicking your mouse. The Queue Full settings don't exist in the GUI though; to get at them, you must use the command line. The 3Par guide helpfully provides the ESXCLI command that you need in order to configure those LUNs:
So, just run that command on every LUN, from the command line on every Host in your environment. Yeah, right. Instead, we can script that through PowerCLI, although it's not as elegant as it would be if we had cmdlets (and it requires a connect-viserver connection directly to the ESXi host).
Before we get to that script, let's have a brief aside about ESXCLI command syntax. It's not very elegant, for its arguments are positional. If you look at that set command, you'll see that we're passing it a bunch of nulls. Those are placeholders, so that we can space it out to get to the 4th and 5th parameters, which correspond with the Queue Full Sample Size and Queue Full Threshold. So, how do you know this? Trial and error... pipe to Get-Member... or you can just check the list of all ESXCLI PowerCLI functions and their syntax.
I've taken that PowerCLI knowledge and, with some help from my coworker Dennis Bray, put together a script that will easily configure an ESXi host (or a whole set of them) to use vendor specific settings for Path Selection Policy, Queue Full Threshold and Queue Full Sample Size. As always, this script is posted for educational purposes and is "use at your own risk". While it worked for me in this particular environment, that is no guarantee that it will work for you in yours.
#Sets all LUNs from a given vendor to use a given path selection policy on a given host(s). Defaults to setting all 3PAR storage to use RoundRobin. Passing the "-r" option sets it to Report Only mode where it reports all LUNs from the vendor, highlighting those that do not conform to the selected policy
#Author: Jason Coleman and Dennis Bray
#Usage: .\configure-storage.ps1 [-h <Hostname, wildcards accepted>] [-v <storage vendor string>] [-p <Path Selection Policy>] [-r]
param(
[alias("h")]
[string]$hostIn = $(read-host -Prompt "Enter the target Host"),
[alias("v")]
[string]$thisVendor = "3PARData",
[alias("p")]
[string]$thisPolicy,
[int]$queueFullSample,
[int]$queueFullThreshold,
[alias("r")]
[switch]$justReport
)
if (($thisPolicy -eq $null) -or ($queueFullSample -eq $null) -or ($queueFullThreshold -eq $null) -or ($thisVendor -eq $null))
{
switch ($thisVendor)
{
"3PARData"
{
$thisPolicy = "RoundRobin"
$queueFullSample = 32
$queueFullThreshold = 4
}
Default
{
Echo "Warning: No preconfigured values defined for storage vendor '$thisVendor', please supply required information."
if ($thisVendor -eq $null)
{
$thisVendor = $(read-host -Prompt "Enter the desired storage vendor")
}
if ($thisPolicy -eq $null)
{
$thisPolicy = $(read-host -Prompt "Enter the desired path selection policy")
}
if ($queueFullSample -eq $null)
{
$queueFullSample = $(read-host -Prompt "Enter the desired Queue Full Sample size")
}
if ($queueFullThreshold -eq $null)
{
$queueFullThreshold = $(read-host -Prompt "Enter the desired Queue Full Threshold size")
}
}
}
}
$allHosts = get-vmhost $hostIn
foreach ($thisHost in $allHosts)
{
Connect-VIServer $thisHost.name | out-null
$esxcli = Get-EsxCli -VMHost $thisHost
$allLUNs = get-vmhost -name $thisHost.name | Get-ScsiLun -LunType disk
foreach ($thisLUN in $allLUNs | where {$_.Vendor -eq $thisVendor})
{
echo "Host: $($thisLUN.VMHost) LUN: $($thisLun.CanonicalName)"
If ($thisLUN.MultipathPolicy -ne $thisPolicy)
{
echo ""
if (!($justReport))
{
echo "Original PSP: $($thisLUN.MultipathPolicy), Attempting to set as: $thisPolicy"
$thisLUN | set-scsilun -MultipathPolicy $thisPolicy | out-null
}
$thisLunPolicy = (get-vmhost -name $thisHost.name | get-ScsiLun -LunType disk -CanonicalName $thisLun.CanonicalName).MultipathPolicy
echo "Policy currently set as: $thisLunPolicy"
}
if (!($justReport))
{
echo ""
echo "Setting Queue Full Sample Size and Threshold..."
$esxcli.storage.core.device.set($thisLUN.CanonicalName,$null,$null,$queueFullSample,$queueFullThreshold,$null)
}
echo "Queue Full Sample Size: $(($esxcli.storage.core.device.list($thisLUN.CanonicalName)).QueueFullSampleSize)"
echo "Queue Full Threshold: $(($esxcli.storage.core.device.list($thisLUN.CanonicalName)).QueueFullThreshold)"
}
disconnect-VIServer $thisHost.name -Confirm:$false
}
The Multipathing Policy is easy to set through the GUI, at least if you really like clicking your mouse. The Queue Full settings don't exist in the GUI though; to get at them, you must use the command line. The 3Par guide helpfully provides the ESXCLI command that you need in order to configure those LUNs:
esxcli storage core device set --device <canonical name> --queue-full-sample-size 32
--queue-full-threshold 4
So, just run that command on every LUN, from the command line on every Host in your environment. Yeah, right. Instead, we can script that through PowerCLI, although it's not as elegant as it would be if we had cmdlets (and it requires a connect-viserver connection directly to the ESXi host).
$esxcli = Get-EsxCli -VMHost <ESX Server FQDN>
$esxcli.storage.core.device.set(<LUN Canonical Name>,$null,$null,32,4,$null)
That doesn't look any better than just using ESXCLI straight... in fact, now we have 2 commands instead of 1! True, but these are two PowerCLI commands, which lend themselves very well to scripting for mass application. With those commands available to us, it's fairly trivial to write a script that will iterate through every LUN on every Host and make the required configurations.Before we get to that script, let's have a brief aside about ESXCLI command syntax. It's not very elegant, for its arguments are positional. If you look at that set command, you'll see that we're passing it a bunch of nulls. Those are placeholders, so that we can space it out to get to the 4th and 5th parameters, which correspond with the Queue Full Sample Size and Queue Full Threshold. So, how do you know this? Trial and error... pipe to Get-Member... or you can just check the list of all ESXCLI PowerCLI functions and their syntax.
I've taken that PowerCLI knowledge and, with some help from my coworker Dennis Bray, put together a script that will easily configure an ESXi host (or a whole set of them) to use vendor specific settings for Path Selection Policy, Queue Full Threshold and Queue Full Sample Size. As always, this script is posted for educational purposes and is "use at your own risk". While it worked for me in this particular environment, that is no guarantee that it will work for you in yours.
#Sets all LUNs from a given vendor to use a given path selection policy on a given host(s). Defaults to setting all 3PAR storage to use RoundRobin. Passing the "-r" option sets it to Report Only mode where it reports all LUNs from the vendor, highlighting those that do not conform to the selected policy
#Author: Jason Coleman and Dennis Bray
#Usage: .\configure-storage.ps1 [-h <Hostname, wildcards accepted>] [-v <storage vendor string>] [-p <Path Selection Policy>] [-r]
param(
[alias("h")]
[string]$hostIn = $(read-host -Prompt "Enter the target Host"),
[alias("v")]
[string]$thisVendor = "3PARData",
[alias("p")]
[string]$thisPolicy,
[int]$queueFullSample,
[int]$queueFullThreshold,
[alias("r")]
[switch]$justReport
)
if (($thisPolicy -eq $null) -or ($queueFullSample -eq $null) -or ($queueFullThreshold -eq $null) -or ($thisVendor -eq $null))
{
switch ($thisVendor)
{
"3PARData"
{
$thisPolicy = "RoundRobin"
$queueFullSample = 32
$queueFullThreshold = 4
}
Default
{
Echo "Warning: No preconfigured values defined for storage vendor '$thisVendor', please supply required information."
if ($thisVendor -eq $null)
{
$thisVendor = $(read-host -Prompt "Enter the desired storage vendor")
}
if ($thisPolicy -eq $null)
{
$thisPolicy = $(read-host -Prompt "Enter the desired path selection policy")
}
if ($queueFullSample -eq $null)
{
$queueFullSample = $(read-host -Prompt "Enter the desired Queue Full Sample size")
}
if ($queueFullThreshold -eq $null)
{
$queueFullThreshold = $(read-host -Prompt "Enter the desired Queue Full Threshold size")
}
}
}
}
$allHosts = get-vmhost $hostIn
foreach ($thisHost in $allHosts)
{
Connect-VIServer $thisHost.name | out-null
$esxcli = Get-EsxCli -VMHost $thisHost
$allLUNs = get-vmhost -name $thisHost.name | Get-ScsiLun -LunType disk
foreach ($thisLUN in $allLUNs | where {$_.Vendor -eq $thisVendor})
{
echo "Host: $($thisLUN.VMHost) LUN: $($thisLun.CanonicalName)"
If ($thisLUN.MultipathPolicy -ne $thisPolicy)
{
echo ""
if (!($justReport))
{
echo "Original PSP: $($thisLUN.MultipathPolicy), Attempting to set as: $thisPolicy"
$thisLUN | set-scsilun -MultipathPolicy $thisPolicy | out-null
}
$thisLunPolicy = (get-vmhost -name $thisHost.name | get-ScsiLun -LunType disk -CanonicalName $thisLun.CanonicalName).MultipathPolicy
echo "Policy currently set as: $thisLunPolicy"
}
if (!($justReport))
{
echo ""
echo "Setting Queue Full Sample Size and Threshold..."
$esxcli.storage.core.device.set($thisLUN.CanonicalName,$null,$null,$queueFullSample,$queueFullThreshold,$null)
}
echo "Queue Full Sample Size: $(($esxcli.storage.core.device.list($thisLUN.CanonicalName)).QueueFullSampleSize)"
echo "Queue Full Threshold: $(($esxcli.storage.core.device.list($thisLUN.CanonicalName)).QueueFullThreshold)"
}
disconnect-VIServer $thisHost.name -Confirm:$false
}
Hey! Great, exactly what I was looking for! Thx
ReplyDelete