Getting and Setting Path Selection Policies with PowerCLI

A colleague I work with was looking for a script that would list all disk devices on ESXi hosts that were not set to Round Robin. After this, he wanted to be able to set all of these to the Round Robin Path Selection Policy (PSP). The two tasks can actually be achieved really easily with just a few lines of PowerCLI.

Getting disk devices on all ESX hosts that do not use the Round Robin PSP:

$AllESXHosts = Get-VMHost | Where { ($_.ConnectionState -eq "Connected") -or ($_.ConnectionState -eq "Maintenance")} | Sort Name
Foreach ($esxhost in $AllESXHosts) {
	Get-VMhost $esxhost | Get-ScsiLun -LunType disk | Where { $_.MultipathPolicy -notlike "RoundRobin" } | Select CanonicalName,MultipathPolicy
}

To set the path selection policy to something else, it is a simple modification of the above to add the Set-ScsiLun cmdlet:

 

$AllESXHosts = Get-VMHost | Where { ($_.ConnectionState -eq "Connected") -or ($_.ConnectionState -eq "Maintenance")} | Sort Name
Foreach ($esxhost in $AllESXHosts) {
	Get-VMhost $esxhost | Get-ScsiLun -LunType disk | Where { $_.MultipathPolicy -notlike "RoundRobin" } | Set-ScsiLun -MultipathPolicy "RoundRobin"
}

There are quite a few scripts floating around out there that achieve similiar results, but I thought I would do my own take on this task. Below is my full script that offers a simple menu system with two options, one to list/log all current path selection policies on hosts that are not round robin to a timestamped log file, and one to set all path selection policies not round robin, to round robin and log these.

 

# Description:  Offers to either check and log path selection policies not set to RoundRobin, OR, set and log these disk PSPs to RoundRobin
# Author: Sean Duffy
# Web/blog: http://www.shogan.co.uk
# Date: 25/05/2013
## IMPORTANT: Always test scripts in preproduction or your lab before using them live!!

#region UserDefined
# Setup the location of our log files...
# This should be the only custom bit you need to set (the location you want log files to be)
# This will only be used when changing path selection policies
$SetPSPlogfile = "C:\temp\SetPathSelectionPolicy_UpdateScript_Log.txt"
# This will only be used when seeing what path selection policies are in place that are not round robin
$GetPSPlogfile = "C:\temp\GetPathSelectionPolicy_UpdateScript_Log.txt"
#endregion

# Ask for connection details, then connect using these
$vcenter = Read-Host "Enter vCenter Name or IP"
$username = Read-Host "Enter your username"
$password = Read-Host "Enter your password"
$Connection = Connect-VIServer $vcenter -User $username -Password $password

# Grab all ESX hosts on the connection that are either connected, or connected and in maintenance mode
$AllESXHosts = Get-VMHost | Where { ($_.ConnectionState -eq "Connected") -or ($_.ConnectionState -eq "Maintenance")} | Sort Name

# Prompt user with two options - 1) List all disk devices where no roundrobin PSP is set, or 2) Change all disk devices to RoundRobin PSP
Clear
Write-Host "1) Log all disk devices on all hosts where RoundRobin not set." -ForegroundColor Yellow
Write-Host "2) Set and log all disk devices on all hosts where RoundRobin not set, to RoundRobin." -ForegroundColor Yellow
$MenuChoice = Read-Host "Enter your selection (1/2)"

# We could use a switch statement here too, but an if,elseif,else statement is fine in this case...
# Chose option 1
if ($MenuChoice -like "1") {
	# Log the username to our log file
	$User = $Connection.User
	Write "User logged in for reading of PSPs: $User" | Out-File $GetPSPlogfile -Append
	Write-Host "Paths not set to RoundRobin for each host will be logged to the $GetPSPlogfile"
	Foreach ($esxhost in $AllESXHosts) {
		# Write an entry into our log for the host we busy reading PSPs from
		$Now = Get-Date
		Write "$Now :: Getting paths on $esxhost where not set to RoundRobin" | Out-File $GetPSPlogfile -Append
		Write-Host "ESX Host: $esxhost :: Disk devices not set to RoundRobin" -ForegroundColor Cyan
		Get-VMhost $esxhost | Get-ScsiLun -LunType disk | Where { $_.MultipathPolicy -notlike "RoundRobin" } | Select CanonicalName,MultipathPolicy | Out-File $GetPSPlogfile -Append
	}
	Write "------------- End of this run -------------" | Out-File $GetPSPlogfile -Append
	Disconnect-VIServer * -Confirm:$false
}
# Chose option 2
elseif ($MenuChoice -like "2") {
	# Prompt user with a warning first and ask to confirm to continue as this is a change to policies...
	Write-Host "WARNING: You are about to loop through all ESX hosts found and change disks to a PSP of RoundRobin! 
	Are you sure you want to continue? (Y/N): " -ForegroundColor Yellow -NoNewline
	$Answer = Read-Host

	# If user answered y, or Y, then continue with the change...
	if ($Answer -like "y") {
		# Log the username to our log file
		$User = $Connection.User
		Write "User logged in for change: $User" | Out-File $SetPSPlogfile -Append
		# Loop through all ESX hosts
		Foreach ($esxhost in $AllESXHosts) {
			# Write an entry into our log for the host we are working on along with the current timestamp
			$Now = Get-Date
			Write "$Now :: Setting PSP for the following current devices on $esxhost to RoundRobin" | Out-File $SetPSPlogfile -Append
			Write-Host "ESX Host: $esxhost :: Now setting path selection policy for all disk devices that are not already set to RoundRobin, to RoundRobin" -ForegroundColor Cyan
			# Find all disk devices where they are not already set to Round Robin Path Selection Policy and log these to log file
			Get-VMHost $esxhost | Get-ScsiLun -LunType disk | Where { $_.MultipathPolicy -notlike "RoundRobin" } | Select CanonicalName,MultipathPolicy | Out-File $SetPSPlogfile -Append
			# Find all disk devices where they are not already set to Round Robin Path Selection Policy and set these to RoundRobin
			Get-VMhost $esxhost | Get-ScsiLun -LunType disk | Where { $_.MultipathPolicy -notlike "RoundRobin" } | Set-ScsiLun -MultipathPolicy "RoundRobin"
		}
		Write "------------- End of this run -------------" | Out-File $SetPSPlogfile -Append
		Disconnect-VIServer * -Confirm:$false
	}
	else {
		Disconnect-VIServer * -Confirm:$false
		Write-Host "Script aborted" -ForegroundColor White
	}
}
# Didn't enter a valid choice...
else {
	Disconnect-VIServer * -Confirm:$false
	Write-Host "Not a valid choice! Exiting script..."
}

The vExpert 2013 applications are now open – apply now

 

Applications are now open here: http://blogs.vmware.com/vmtn/2013/03/vexpert-2013-applications-are-now-open.html

 

The vExpert 2013 applications are now open. This is a great group to be a part of, so if you have been an active contributor to the VMware community, I highly recommend applying! There are three tracks you can follow though for application, so follow the link above for more information and guidance on applying. This last year I was lucky enough to be awarded the title, and I hope to be able to retain it this year – as such I have been blogging as regularly as possible and have also released some cool little utilities, scripts and other bits and pieces to the community. Hopefully this will all pay off and I will be able to retain vExpert status through 2013 🙂

Over the past year, John Troyer has done a sterling job keeping the group going and organising events and other collateral, so much thanks go to him and the other vExperts who have of course helped out where possible.

Good luck on the applications and don’t forget to keep contributing. This is what makes the community stronger!

Cloud Credibility challenges – blogging about my team members

So there is a fun website called “CloudCred” that allows individuals or teams to participate in various tasks and challenges –  everything from technical challenges to social and fun are covered and it is quite a good team building exercise, apart from the leaderboard challenge aspect!

One of the tasks is to blog about my team members and include links to their own blogs. We have quite a few team members so I can’t cover all of them, but here goes:

Of course this task is for our team – Xtravirt Limited, so we also have a company blog you can go and visit for some excellent content around the Cloud and Virtualisation industry.

Another update! ESXi Host Backup & Restore GUI Utility (PowerCLI based) updated to 1.3

The other weekend I managed to get some spare time to do another update to my ESXi 5.0 / 5.1 Host Backup & Restore GUI utility, this time it has been updated to version 1.3. I didn’t post up the changes as it was done by special request from one of my blog readers (thanks Flavio!) However, after receiving more comments with a few others having a similiar issue to what Flavio had, I thought I should definitely post the updated version here, which should hopefully solve the issues some people are seeing.

 

The changes are based on feedback received in the comments I have received about the utility relating to exceptions received when users in some circumstances try to backup their host configurations. Specifically the exception message “Exception caught: Get-VMHost VMHost with name ‘xxx’ was not found using the specified filter(s).

You can check the utility out over on it’s page here.

Updates (17-02-2013) – version 1.3:

  • Hosts are retrieved using a new method (for both backup and restore options)

 

A function to lookup Host System friendly name by MoRef using PowerCLI

In a recent blog post, I showed a simple method of outputting a list of hosts with their friendly names, as well as their MoRef (Managed Object Reference) names alongside eachother, enabling you to match up which host belongs to which MoRef. I wanted to take that a little further, with a function that is able to return the friendly name of a host’s MoRef that is input into the function. I have used this is a larger reporting script, where I can only get the MoRef of a host via it’s property within a cluster object. Basically, I look for any Failover hosts (admission control policy), which is an array, and the hosts are listed as indexed objects of this array. They are also only displayed as MoRef names, so at this point, instead of inserting the MoRef into my results, I insert the MoRef into this function, return the friendly name, and input this instead. Which allows the person reading the report to easily identify the host! $cluster.ExtensionData.Configuration.DasConfig.AdmissionControlPolicy.FailoverHosts <- In this example, $cluster is a particular cluster using the “specify a failover host” policy, and “FailoverHosts” is the array, with each object within containing a host MoRef. For example FailoverHosts[0].Value would be one instance, and may equate to “HostSystem-host-28” for example.   So here is the function. It takes two mandatory parameters: -MoRef (the MoRef of the host in question of course), and -Cluster (the name of the Cluster to do the lookup in) – the function loops through each host in this cluster to look for a host that matches the input MoRef.

Function Get-VMHostByMoRef() {

<#
.SYNOPSIS
Fetches host name by input MoRef and Cluster to look in

.DESCRIPTION
Fetches host name by input MoRef and Cluster to look in

.PARAMETER MoRef
The MoRef of the host system

.PARAMETER Cluster
The name of the cluster to do the lookup in

.EXAMPLE
PS F:\> Get-VMHostByMoRef -MoRef HostSystem-host-28 -Cluster MyCluster01

.LINK
http://www.shogan.co.uk

.NOTES
Created by: Sean Duffy
Date: 22/02/2013
#>

[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=$true,HelpMessage="Specify the Host MoRef name you would like to query for it's friendly name.",
ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)][String]$MoRef,[Parameter(Position=1,Mandatory=$true,HelpMessage="Specify the Cluster to search hosts in.",
ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)][String]$Cluster
)

process {

$AllHosts = Get-Cluster $Cluster | Get-VMHost
$thehost = $AllHosts | Where {$_.ExtensionData.MoRef -match $MoRef} | Select-Object -Property Name

return $thehost

}
}

Here is a quick sample of the output when called directly from the PowerCLI prompt (note the MoRef of “host-22” used to find the real host name of “esxi02.homelab.local”: Hopefully this may be of use to some – add it to your PowerCLI script/function toolkit or throw it into your PowerShell $profile for easy access in the future!