4

Disable ESXi fibre ports using PowerCLI

I have to start this post with a warning to run this script at your own risk. If you’re careful and know exactly what you’re doing, this can be very useful. Misuse of this script can cause data corruption and unnecessary outages. So why would I write such a script?

Like most data centers, we use multiple independent fibre SANs. This is supposed to allow us to do maintenance and sustain the loss of a network. Unfortunately, we got burned when things didn’t work as they should.

We were doing a routine firmware upgrade on one of the SAN switches. This is a smooth process which should have no impact to traffic. Unless the switch suffers a kernel panic like ours did. In a multi-path enabled host, the fibre card is responsible for identifying a path being down and reporting back to the VMkernel with a “No_Connect” message. The kernel should then re-route traffic to the remaining active paths. For reasons unknown, a number of our hosts never got the message and ultimately HA had to migrate a bunch of production VM’s.

We’ve since made changes to our PSP’s, ALUA’s, and LPFC drivers. Now it’s time to upgrade another SAN switch. Even after hours of testing, we’re still a bit nervous about the upgrade. For piece of mind I wanted some sort of port maintenance mode, and this is what I came up with.

Usage:

  • Change vcenter.fqdn to the name of your vCenter server
  • Place your host in maintenance mode (to be safe)
  • Execute the script and append the hostname to the command line entry (see example below)
  • Select the WWPN you would like to disable
  • Verify whether you want to go through with this

To begin, we see all four paths are active.

 

Paths-Before

Launch the script with the host name appended.

Script

 

Now we see the paths disabled for that port across all storage devices.

Paths-After

 

I’d highly recommend running this in your sandbox environment for the first time.

 

#=========================
# Disable Fibre Paths
# Matt Bradford 
# 1/24/2015
#=========================
$vcenter = "vcenter.fqdn"

#Collect ESXi host name from command line
[cmdletbinding()]
Param([string]$VMhost)
#Load the Vmware Powershell Snapin (For users executing script from powershell)
Add-PSSnapin VMware.VimAutomation.Core -ErrorAction 'SilentlyContinue'
#Connect to vCenter
Write-Host ""
Write-Host "Connecting to vCenter..." -NoNewline
Connect-VIServer $vcenter | Out-Null
Write-Host " Connected"
Write-Host ""

#Get WWPN's from host
$WWNs = Get-VMHost $VMhost | Get-VMHostHba -Type FibreChannel | Select @{N="WWN";E={"{0:X}"-f$_.PortWorldWideName}}
#Create a selection menu from WWPN's
Write-Host "WWPN's Available:"
$i = 0
foreach ($WWN in $WWNs)
{
 $WWN = $WWNS[$i].WWN
 Write-Host "$i $WWN" -ForegroundColor 'Green'
 $i ++
}
Write-Host ""
$Selection = Read-Host "Select a path to disable"
$WWN = $WWNs[$Selection].WWN
#Validate that the user wants to disable ports
Write-Host ""
Write-Host "DISABLE $WWN " -ForegroundColor 'Red' -NoNewline
$validate = Read-Host "ARE YOU SURE? Y/N"
if ($validate -eq "Y")
{
#Get each disk device 
$Scsilun = Get-ScsiLun -VMHost $VMhost -LunType disk
#Get paths that use the selected WWPN
$Scsipaths = $scsilun | Get-ScsiLunPath | Where-Object {$_.LunPath -Like "*$WWN*"}
#Disable each path using the selected WWPN
foreach ($scsipath in $scsipaths)
{
 Set-ScsiLunPath -ScsiLunPath $Scsipath -Active $false
 }
}
elseif ($validate -eq "N")
{
 Write-Host ""
 Write-Host "User Abort Process. Exiting" -ForegroundColor 'Red'
 Write-Host ""
 Exit
}
else
{
 Write-Host ""
 Write-Host "Invalid Entry. Exiting" -ForegroundColor 'Red'
 Write-Host ""
 Exit
}

To re-enable the ports just copy the above to a new script and change

 Set-ScsiLunPath -ScsiLunPath $Scsipath -Active $false

To

 Set-ScsiLunPath -ScsiLunPath $Scsipath -Active $true

 

Matt Bradford

4 Comments

  1. This saved me a ton of time — thank you.
    Migrating from Brocade to MDS switches and needed to disable the ports ahead of time – Migration was backed out but this part worked beautifully!

  2. Hi Matt,

    brilliant script.
    Was it possible to target this script to a particular cluster and have the script disable paths for say HBA0 of ALL the hosts in the cluster?

    Thanks!

Leave a Reply