VM Junkie

January 29, 2009

Balancing LUN Paths on your ESX Hosts with PowerShell

Filed under: esx, powershell, vmware — ermac318 @ 4:28 pm

After watching this video that was posted by the VI Toolkit team, I immediately thought of this script that was posted quite a while back on Yellow Bricks. I decided to try to recreate this script in PowerShell, and while I was at it expand it so it would modify all nodes in a cluster at once. As such I wrote the following script. Please feel free to give feedback or make modifications! You can download it from my Sky Drive or check it out below:

# Cluster-wide LUN Path Load Balancing Script
# Written by Justin Emerson, http://vmjunkie.wordpress.com
# Idea originally from a PERL script I saw here:
#    http://www.yellow-bricks.com/2008/04/01/load-balancing-activeactive-sans/
# This script requires the VI Toolkit version 1.5
# NOTE: This script assumes that every LUN has the same number of paths.
#       If you have multiple storage arrays, and they have different numbers of paths,
#		I make no guarentees that this will work!
# If you have an improvement to this script, please feel free to leave a comment on my blog!
Write-Host "This script will modify the policy of all your shared LUNs on all ESX Servers" -ForegroundColor Cyan
Write-Host "in a Cluster to Fixed and select a preferred path in a round-robin fashion." -ForegroundColor Cyan
if ($args.Length -eq 0) {$clusterName = Read-Host "Please enter the Cluster name"} else {$clusterName = $args[0]}
$VMHosts = Get-Cluster $clusterName | Get-VMHost
# Run through this loop for each host in the cluster
foreach ($VMHost in $VMHosts)
{
	# Keep only disks of luntype "disk" to avoid any storageArrayController devices.
	# Filter to only objects where the ConsoleDeviceName starts with vml to avoid any DAS disks.
	# Note: I have tested both HP EVA and Xiotech storage and SAN LUNs always appear this way.
	# Please check if this is the same on your storage before running.
	$luns = $VMHost|get-scsilun -luntype disk|
	where-object {$_.ConsoleDeviceName -like "/vmfs/devices/disks/vml*"}|Sort-Object CanonicalName
	$firstLUNPaths = Get-ScsiLunPath $luns[0]
	$numPaths = $firstLUNPaths.Length
	$count = 0
	foreach ($lun in $luns)
	{
		if ($count -ge $numPaths) { $count = 0 }
		$paths = Get-ScsiLunPath -ScsiLun $lun
		$lun|Set-ScsiLun -MultipathPolicy Fixed -PreferredPath $paths[$count]
		$count += 1
		# Sleep for 30 seconds as I've heard some arrays dont like doing this too fast.
		Start-Sleep -Seconds 30
	}
}

Note that after running the script, my ESX servers had esxcfg-mpath -l an output of:

[root@tb20 root]# esxcfg-mpath -l
Disk vmhba1:0:3 /dev/sdc (307200MB) has 4 paths and policy of Fixed
 FC 14:0.0 500110a00016013e<->50001fe1500ef599 vmhba1:0:3 On
 FC 14:0.0 500110a00016013e<->50001fe1500ef59d vmhba1:1:3 On
 FC 23:0.0 500110a000160152<->50001fe1500ef598 vmhba2:0:3 On active preferred
 FC 23:0.0 500110a000160152<->50001fe1500ef59c vmhba2:1:3 On

Disk vmhba1:0:4 /dev/sdd (1048576MB) has 4 paths and policy of Fixed
 FC 14:0.0 500110a00016013e<->50001fe1500ef599 vmhba1:0:4 On
 FC 14:0.0 500110a00016013e<->50001fe1500ef59d vmhba1:1:4 On
 FC 23:0.0 500110a000160152<->50001fe1500ef598 vmhba2:0:4 On
 FC 23:0.0 500110a000160152<->50001fe1500ef59c vmhba2:1:4 On active preferred

Disk vmhba1:0:6 /dev/sdf (358400MB) has 4 paths and policy of Fixed
 FC 14:0.0 500110a00016013e<->50001fe1500ef599 vmhba1:0:6 On
 FC 14:0.0 500110a00016013e<->50001fe1500ef59d vmhba1:1:6 On active preferred
 FC 23:0.0 500110a000160152<->50001fe1500ef598 vmhba2:0:6 On
 FC 23:0.0 500110a000160152<->50001fe1500ef59c vmhba2:1:6 On

Disk vmhba1:0:1 /dev/sda (204800MB) has 4 paths and policy of Fixed
 FC 14:0.0 500110a00016013e<->50001fe1500ef599 vmhba1:0:1 On active preferred
 FC 14:0.0 500110a00016013e<->50001fe1500ef59d vmhba1:1:1 On
 FC 23:0.0 500110a000160152<->50001fe1500ef598 vmhba2:0:1 On
 FC 23:0.0 500110a000160152<->50001fe1500ef59c vmhba2:1:1 On

Disk vmhba0:0:0 /dev/cciss/c0d0 (139979MB) has 1 paths and policy of Fixed
 Local 6:0.0 vmhba0:0:0 On active preferred

Disk vmhba1:0:2 /dev/sdb (153600MB) has 4 paths and policy of Fixed
 FC 14:0.0 500110a00016013e<->50001fe1500ef599 vmhba1:0:2 On
 FC 14:0.0 500110a00016013e<->50001fe1500ef59d vmhba1:1:2 On active preferred
 FC 23:0.0 500110a000160152<->50001fe1500ef598 vmhba2:0:2 On
 FC 23:0.0 500110a000160152<->50001fe1500ef59c vmhba2:1:2 On

Disk vmhba1:0:5 /dev/sde (307200MB) has 4 paths and policy of Fixed
 FC 14:0.0 500110a00016013e<->50001fe1500ef599 vmhba1:0:5 On active preferred
 FC 14:0.0 500110a00016013e<->50001fe1500ef59d vmhba1:1:5 On
 FC 23:0.0 500110a000160152<->50001fe1500ef598 vmhba2:0:5 On
 FC 23:0.0 500110a000160152<->50001fe1500ef59c vmhba2:1:5 On

Disk vmhba1:0:7 /dev/sdg (102400MB) has 4 paths and policy of Fixed
 FC 14:0.0 500110a00016013e<->50001fe1500ef599 vmhba1:0:7 On
 FC 14:0.0 500110a00016013e<->50001fe1500ef59d vmhba1:1:7 On
 FC 23:0.0 500110a000160152<->50001fe1500ef598 vmhba2:0:7 On active preferred
 FC 23:0.0 500110a000160152<->50001fe1500ef59c vmhba2:1:7 On

Disk vmhba1:0:8 /dev/sdh (102400MB) has 4 paths and policy of Fixed
 FC 14:0.0 500110a00016013e<->50001fe1500ef599 vmhba1:0:8 On
 FC 14:0.0 500110a00016013e<->50001fe1500ef59d vmhba1:1:8 On
 FC 23:0.0 500110a000160152<->50001fe1500ef598 vmhba2:0:8 On
 FC 23:0.0 500110a000160152<->50001fe1500ef59c vmhba2:1:8 On active preferred

RAID Controller (SCSI-3) vmhba1:1:0  (0MB) has 4 paths and policy of Fixed
 FC 14:0.0 500110a00016013e<->50001fe1500ef59d vmhba1:1:0 On active preferred
 FC 14:0.0 500110a00016013e<->50001fe1500ef599 vmhba1:0:0 On
 FC 23:0.0 500110a000160152<->50001fe1500ef598 vmhba2:0:0 On
 FC 23:0.0 500110a000160152<->50001fe1500ef59c vmhba2:1:0 On

Yay, it worked!

7 Comments »

  1. [...] in Management & Automation, Server Just noticed this pingback. The topic title “Balancing LUN paths on your ESX hosts with powershell” sounded promising so I headed over. Justin Emerson is the owner of the blog and he wrote a [...]

    Pingback by Balancing LUN paths with powershell ยป Yellow Bricks — January 29, 2009 @ 9:34 pm

  2. Great script.
    Why bother to enter the cluster name?
    Why not just retrieve all clusters from vCenter and loadbalace all cluster?

    Nice to run this at a regular interval.

    Comment by Arnim van Lieshout — February 5, 2009 @ 8:46 am

  3. I chose to only do it to a single cluster at a time because some customers may have some clusters running iSCSI and others running Fiberchannel, and I was unable to test it against any iSCSI LUNs at the time. Plus, someone may want to run it just against their development or VDI cluster or something first. And I figure it’s trivial to adapt my script to do every cluster for someone so inclined.
    Thanks for the feedback!

    Comment by ermac318 — February 5, 2009 @ 8:49 am

  4. [...] in the VMware community. First of all, there is nothing wrong with those scripts. For example, Justin Emerson wrote an excellent script that changes the active paths on an active/active SAN. But running an [...]

    Pingback by HP CA and the use of LUN balancing scripts « Frank Denneman — February 9, 2009 @ 11:28 pm

  5. Thanks for the script.

    I tweaked it a bit and posted a question in the forums.

    Id like to see it work on systems connected to different array models.

    Maybe an If statement if this array run it this way if this array run it that way.

    Thanks again

    http://communities.vmware.com/message/1169352

    Comment by cititechs — February 11, 2009 @ 2:23 pm

  6. [...] in the VMware community. First of all, there is nothing wrong with those scripts. For example, Justin Emerson wrote an excellent script that changes the active paths on an active/active SAN. But running an [...]

    Pingback by Frank Denneman » Blog Archive » HP CA and the use of LUN balancing scripts — May 1, 2009 @ 8:09 am

  7. To use the script with non cluster server, you may change the script a little bit.
    Remove the following two lines and add my code.
    if ($args.Length -eq 0) {$clusterName = Read-Host “Please enter the Cluster name”} else {$clusterName = $args[0]}
    $VMHosts = Get-Cluster $clusterName | Get-VMHost

    if ($args.Length -lt 2) {
    Write-Host “usage: -c or -s ”
    exit 1
    } else {
    if ($args[0] -eq “-c”) { $VMHosts = Get-Cluster $args[1] | Get-VMHost }
    if ($args[0] -eq “-s”) { $VMHosts = Get-VMHost $args[1] }
    }
    Write-Host “Modifiying ESX hosts:” $VMHosts

    Comment by Ulf — June 3, 2009 @ 1:10 am


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.