The greatest challenge to any thinker is stating the problem in a way that will allow a solution

Bertrand Russell

By

On 3 Apr 2012

VMware

Tags: , , , , ,


With SSH access to your ESX servers, it is relatively easy to get the driver and firmware software revision versions that are running (see further reading section at bottom of post).  Which is fine for a one-off inspection, but if you want review your entire ESX estate, this can be quite tedious.

With the wonder of PowerCLI, it is possible to gain most of this information from your vCentre, which will have sourced the information from your ESX through its hardware CIM provider.  But the quality of data returned in this manner varies, you can get…

  • No data (if you server vendor hasn’t fully implemented CIM to cover the server and peripheral devices, or you haven’t installed the CIM provider software, even if you can get data for X and Y, Z may be missing, for example HBA firmware on all HP servers I’ve had the pleasure of looking after)
  • Duplicate data (if you’ve upgraded software you can sometimes get both old and new versions reported)
  • Inconsistent data (representations vary between manufacturers/vendors, so dealing with different makes or even models from the same manufacturer is problematic)

I do all reporting through PowerShell and PowerCLI scripts, and had got fed up with having to tinker with my scripts to try and never fully trusting the data I was seeing.  But more recently I’ve been using PowerShell to act as an SSH client, so decided to take a different approach…

Before we go any further, you need to have the SSH.NET library available, otherwise PowerShell will be incapable of accessing your ESX’s via SSH – see my SSH Clientr using PowerShell post.

Note that it will also make life easier if all your ESX’s have the same root password (the script below assumes you do).  I know this isn’t always the case, and if you’re in this situation you’ll have to think of secure way around it.  There are ways, but to do it in a way that doesn’t compromise security can be a challenge.  As it stands the script below is only suitable for one off/manual use, you should not be leaving your ESX root password in plain view in the script.

The script also assumes that it’s being run from a PowerCLI session that’s connected to your vCentre, so that it can get a list of ESX servers to probe – you could create this list manually in $ESXs and drop the $ESXs = Get-VMHost line.

$pass = "GenericESXPassword"                                # Root password for ESX SSH access
$SshNetLib = "..\lib\RenciSSH\Renci.SshNet3.5.dll"          # Path to SSH.Net DLL file
 
# SSH library prep and functions ====================================================
 
try {
    $RenciAss = [reflection.assembly]::LoadFrom( (Resolve-Path ($MyInvocation.MyCommand.Path.Replace($MyInvocation.MyCommand.Name, "") + $SshNetLib)) )
} catch {
    Write-Error $_
    throw "Unable to find/load the SshNet DLL"
}
 
function New-SshSession ([string]$server, [string]$user, [string]$pass, [int]$port = 22) {
    # Create a SSH client object, and connect to SSH server (on your ESX)
    $Client = New-Object Renci.SshNet.SshClient($server, $port, $user, $pass)
 
    try {
        $Client.Connect()
    } catch {
        throw $_
    }
 
    if ($Client.IsConnected) {
        Return $Client
    } else {
        throw "SSH client connect failed..!"
        Return 0
    }
}
 
function Get-SshCmdResult {
    param ([string]$command)
 
    # Run a command on SSH server and get results
 
    if ($SshClient.IsConnected) {
        $CmdRun = $SshClient.RunCommand($command)
    } else {
        throw "SshClient is not connected!"
    }
 
    if ($CmdRun.ExitStatus) {
        throw ("SSH cmd failed: $command > " + $CmdRun.Error)
        Return 0
    }
 
    Return $CmdRun.Result.Split("`n")
}
 
# Business part of script =======================================================
 
# Get list of ESX's
$ESXs = Get-VMHost
if (!$ESXs) {
    Write-Host "No ESX's found to examine - connected to a vCentre???"
    Exit
}
 
foreach ($esx in $ESXs) {
 
    Write-Host ("Connecting to " + $esx.Name + " SSH server...")
    try {
        $SshClient = New-SshSession -Server $esx.Name -User "root" -Pass $pass
    } catch {
        $_.Exception
        Exit
    }
 
    # HBA ---------------------------------------------------------------------------
 
    # Get list of directories under /proc/scsi (HBA types aka driver)
    $HBAtypes = Get-SshCmdResult "ls /proc/scsi/"
 
    foreach ($driver in $HBAtypes) {
        if ( !($driver -match "lpfc820" -or $driver -match "qla2xxx") ) {
            Continue
        }
 
        # Get list of directories for each adapter
        $HBAnos = Get-SshCmdResult "ls /proc/scsi/$driver/"
 
        foreach ($HBAno in $HBAnos) {
            if (!$HBAno) {
                Continue
            }
            $device = ""
            $firmware = ""
            $drv_ver = ""
 
            # Get detail for specific adapter
            $res = Get-SshCmdResult "more /proc/scsi/$driver/$HBAno"
 
            Switch ($driver) {
                "lpfc820" {
                    $drv_ver = ([regex]::Matches($res[0], "(\b\d)(.*?)(?=$)"))[0].Value
                    foreach ($line in $res) {
                        if ($line -match "ESX Adapter:") {
                            $device = $line.Replace("ESX Adapter: ", "")
                        } elseif ($line -match "Firmware Version:") {
                            $firmware = $line.Replace("Firmware Version: ", "")
                        }
                    }
 
                }
                "qla2xxx" {
                    foreach ($line in $res) {
                        if ($line -match "Firmware version") {
                            $matches = [regex]::Matches($line, "(?<=\s)(\b\d)(.*?)(?=$|\s)")
                            $firmware = $matches[0].Value
                            $drv_ver = $matches[1].Value
                        } elseif ($line -match "Host Device Name") {
                            $device = $line.Replace("Host Device Name ", "")
                        }
                    }
                }
                default {
                    # Catch unexpected error
                    Write-Host ("Error: Unknown HBA driver - " + $HBAtype)
                }   
            }
            Write-Host "$device`t$driver`t$firmware`t$drv_ver"
        }
 
    }
 
    # NIC ---------------------------------------------------------------------------
 
    $vmnics = Get-SshCmdResult ("vsish -e ls net/pNics") | Sort
 
    foreach ($vmnic in $vmnics) {
        if (!$vmnic) {
            Continue
        }
 
        $NICinfo = Get-SshCmdResult ("vsish -e get net/pNics/" + $vmnic + "properties")
 
        $driver = ""
        $drv_ver = ""
        $fware = ""
 
        foreach ($line in $NICinfo) {
            if ($line -match "Driver Name:") {
                $driver = $line.Replace("   Driver Name:", "")
            } elseif ($line -match "Driver Version:") {
                $drv_ver = $line.Replace("   Driver Version:", "")
            } elseif ($line -match "Driver Firmware Version:") {
                $fware = $line.Replace("   Driver Firmware Version:", "")
            }
        }
 
        $device = $vmnic.replace("/", "")
        Write-Host "$device`t$driver`t$fware`t$drv_ver"
 
    }
 
    $SshClient.Dispose()
 
}

 

Further reading

Getting HBA and NIC driver/firmware versions via SSH

Getting HBA and NIC driver/firmware versions via PowerCLI/CIM


5 Comments to “ESX HBA and NIC driver/firmware versions”

  1. Ron says:

    Looks like the end of the script is missing.

  2. Ron says:

    I’m getting the following now, I’m sure it’s a simple issue of the version powercli i’m using or something else. What if your config that your running this script successfully with?

    Exception calling “Matches” with “2” argument(s): “parsing “(?<=\s)(\b\d)(.*
    ?)(?=$|\s)” – Unrecognized grouping construct.”
    At C:\scripts\powercli\HBA versions.ps1:108 char:56
    + $matches = [regex]::Matches <<<< ($line, "(?<=
    \s)(\b\d)(.*?)(?=$|\s)")
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    • Simon Strutt says:

      I’m running PowerCLI v5 on PowerShell v2….


      PowerCLI C:\> (Get-Host).Version

      Major Minor Build Revision
      ----- ----- ----- --------
      2 0 -1 -1

      PowerCLI C:\> Get-PowerCLIversion

      PowerCLI Version
      ----------------
      VMware vSphere PowerCLI 5.0 build 435427
      ---------------
      Snapin Versions
      ---------------
      VMWare AutoDeploy PowerCLI 5.0 build 575
      VMWare ImageBuilder PowerCLI 5.0 build 575
      VMware License PowerCLI 5.0 build 395016
      VMWare vSphere PowerCLI 5.0 build 435427

      I did notice that I’d ended up with some HTML syntax in the middle of the regex which I’ve corrected. Your error doesn’t seem to show that, but its worth double checking the line that’s triggering the exception, with what is in the post.

  3. James says:

    I get this error when it calls $Client.connect()

    Exception calling “Connect” with “0” argument(s): “No suitable authentication method found to complete authentication.”

    Reading at the Renci site I found reference to it and tried to set PasswordConnectionInfo but I got the same error.

Leave a Reply

XHTML: You can use these tags if you know what they are: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

ERROR: si-captcha.php plugin says GD image support not detected in PHP!

Contact your web host and ask them why GD image support is not enabled for PHP.

ERROR: si-captcha.php plugin says imagepng function not detected in PHP!

Contact your web host and ask them why imagepng function is not enabled for PHP.