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.
Launch the script with the host name appended.
Now we see the paths disabled for that port across all storage devices.
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
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!
Hi Matt,
I have been using your script for a long time. However we just got esxi 6 hosts and it stopped working. I have posted the details in the vmware community. Here:
https://communities.vmware.com/thread/543770
Please help me
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!
Hi
If I try to run your script I get the following message:
PowerCLI E:\Install Sources\VMware\Scripte\3_datastores> .\10__disable_fc_path.ps1
At E:\Install Sources\VMware\Scripte\3_datastores\10__disable_fc_path.ps1:17 char:1
+ [cmdletbinding()]
+ ~~~~~~~~~~~~~~~~~
Unexpected attribute ‘cmdletbinding’.
At E:\Install Sources\VMware\Scripte\3_datastores\10__disable_fc_path.ps1:18 char:1
+ Param([string]$VMhost)
+ ~~~~~
Unexpected token ‘Param’ in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : UnexpectedAttribute
Did you have any idee what happen?
I have to deactivate two path on a subset of hosts on a subset of LUNs and hope to get this with your fantastic script.