The other day I had a need to collect HBA (Host Base Fiber Adapters) from all my Servers. So the first place I looked was at WMI, but unfortunately… no dice. It didnt have the information I needed. The only way I knew to get the info I needed was to use was HBACmd.exe (utility to collect HBA information remotely.) So I went to writing a wrapper script in powershell to call the exe and then grep the text for what I was looking for, but I thought… HEY! Thats not the powershell thing to do! We do objects not text. So I went to parsing the text and making an object out of it. The script below is the result and while I dont believe many of you will find it particularly useful as it has a VERY specific use, I wanted to share with you how I went about objectizing the output.
Here is a littel Q and A on the script
Q: Purpose?
A: To get all the HBA information include Type, Firmware, Bios, Target Lun, WWN and a slew of other stuff.
Q: Why Did I objectize my text?
A: Because I know can simply use properties to filter and output data. Like what Machines have what Bios and what type of HBAs they have. Before I would have the parse the text for every different senario… now I just use where-object and filter away.
I few things that I wanted to point out here are the use of Switch to create the Custom Objects. IMO, Switch is one of the most powerful commands in the Powershell Language. It is INSANELY Powerfull. To be honest, It is pretty much the only one you need.
To compare it “Select Case” in vbscript would be insulting, but it can peform a similar function Like
-
switch ($a){
-
Value1 {"It was Value 1"}
-
Value2 {"It was Value 2"}
-
Value3 {"It was Value 3"}
-
Value4 {"It was Value 4"}
-
}
It would take a whole series of post to completely cover switch, but for this one I only want to go over -regex use. For complete use read the help located:
PS> Get-help About_Switch # Read it, Learn it, Love it
Some Quick Notes about Switch
- Can use RegEx, WildCard, Exact, CaseSensitive, or File options.
- It takes input via Pipeline {expression} or File. The cool thing is the pipeline can be any expression that results in piped output.
- For each match it can perform any ScritpBlock use $_ as the current Item
- It performs EVERY match on each element unless you use Continue after a match to stop processing that record
Like I said, Switch is insanely powerful. Just one of those powers is using RegEx for comparison.
Here is an example of using the -RegEx option
-
switch -RegEx (Get-ChildItem C:\test)
-
{
-
"^\d" {"Starts with number: " + $_.FullName}
-
"\d" {"Has a number in it: " + $_.FullName}
-
"[^A-Za-z]" {"Does NOT start with Number: " + $_.FullName}
-
"tmp" {"Has ‘tmp’ in it: " + $_.FullName}
-
# Notice that you can even use and expression to match
-
{$_.Mode -match "-a"} {"Has Archive Bit Set: " + $_.FullName}
-
}
Now.. lets look at the script below. You will noticed I used RegEx to decide what value gets put in to what property of the object.
The script converts the output of three commands into two different objects. Lets look at one of them
It takes text like This
-
Manageable HBA List
-
-
Port WWN : 10:00:00:00:11:11:11:11
-
Node WWN : 20:00:00:00:11:11:11:11
-
Fabric Name: 00:00:00:00:00:00:00:00
-
Flags : 0000f0a5
-
Host Name : Server1
-
Mfg : Emulex Corporation
-
-
Port WWN : 10:00:00:00:22:22:22:22
-
Node WWN : 20:00:00:00:22:22:22:22
-
Fabric Name: 00:00:00:00:00:00:00:00
-
Flags : 0000f0a5
-
Host Name : Server1
-
Mfg : Emulex Corporation
And converts Into an object like This
-
TypeName:
System.
Management.
Automation.
PSCustomObject
-
-
Name MemberType Definition
-
—- ———- ———-
-
Equals Method
System.
Boolean Equals
(Object obj
)
-
GetHashCode Method
System.
Int32 GetHashCode
()
-
-
-
Fabric NoteProperty
System.
String Fabric=
00:
00:
00:
00:
00:
00:
00:
00
-
-
HBADetail NoteProperty
System.
Object[] HBADetail=
System.
Object[]
-
-
-
-
NodeWWN NoteProperty
System.
String NodeWWN=
20:
00:
00:
00:
11:
11:
11:
11
-
PortWWN NoteProperty
System.
String PortWWN=
10:
00:
00:
00:
11:
11:
11:
11
Here is the Script
-
Param($List,$HostName,[switch]$FullDetail,[switch]$Verbose)
-
Begin{
-
$erroractionpreference = "SilentlyContinue"
-
$HBACMDPath = "<path To HbaCmd.exe>"
-
function CreateHBAListObj{
-
Param($srv)
-
$objCol = @()
-
$result = &"$HBACMDPath" "h=$srv" ListHBAs
-
foreach($item in $result)
-
{
-
$parsd =
$item.
split([string[]](": "),
[system.
StringSplitOptions]::
RemoveEmptyEntries)
-
switch -regex ($parsd[0])
-
{
-
"^Port" {
-
$myobj = "" | Select-Object Host,PortWWN,NodeWWN,Fabric,Flags,LUN,MFG
-
$myobj.PortWWN = $parsd[1]
-
$myobj.Lun = GetTargetLun $srv $myobj.PortWWN
-
}
-
"^Node" {$myobj.NodeWWN = $parsd[1]}
-
"^Fabr" {$myobj.Fabric = $parsd[1]}
-
"^Flag" {$myobj.Flags = $parsd[1]}
-
"^Host" {$myobj.Host = $parsd[1]}
-
"^MFG " {
-
$myobj.MFG = $parsd[1]
-
$objCol += $myObj
-
}
-
}
-
}
-
$objCol
-
}
-
function CreateHBAInfoObj{
-
Param($srv,$wwn)
-
$objCol = @()
-
$result = &"$HBACMDPath" "h=$srv" HBAAttrib $wwn
-
-
$myobj = "" |Select-Object Host,MFG,SN,Model,ModelDesc,NodeWWN,NodeSymname,
-
HWVersion,ROM,FW,VenderID,Ports,DriverName,DeviceID,HBAType,
-
OpFW,SLT1FW,SLT2FW,IEEEAddress,BootBios,DriverVer,KernelVer
-
foreach($item in $result)
-
{
-
$parsd =
$item.
split([string[]](": "),
[system.
StringSplitOptions]::
RemoveEmptyEntries)
-
switch -regex ($parsd[0])
-
{
-
"^Host" {$myobj.Host = $parsd[1]}
-
"^Manufacturer" {$myobj.MFG = $parsd[1]}
-
"^Serial" {$myobj.Sn = $parsd[1]}
-
"^Model " {$myobj.Model = $parsd[1]}
-
"^Model Desc" {$myobj.ModelDesc = $parsd[1]}
-
"^Node WWN " {$myobj.NodeWWN = $parsd[1]}
-
"^Node Symname" {$myobj.NodeSymname = $parsd[1]}
-
"^HW" {$myobj.HWVersion = $parsd[1]}
-
"^Opt" {$myobj.ROM = $parsd[1]}
-
"^FW" {$myobj.FW = $parsd[1]}
-
"^Vender" {$myobj.VenderID = $parsd[1]}
-
"^Number" {$myobj.Ports = $parsd[1]}
-
"^Driver Name" {$myobj.DriverName = $parsd[1]}
-
"^Device" {$myobj.DeviceID = $parsd[1]}
-
"^HBA Type" {$myobj.HBAType = $parsd[1]}
-
"^Operational" {$myobj.OpFW = $parsd[1]}
-
"^SLI1 FW" {$myobj.SLT1FW = $parsd[1]}
-
"^SLI2 FW" {$myobj.SLT2FW = $parsd[1]}
-
"^IEEE" {$myobj.IEEEAddress = $parsd[1]}
-
"^Boot " {$myobj.BootBios = $parsd[1]}
-
"^Driver Ver" {$myobj.DriverVer = $parsd[1]}
-
"^Kernel " {$myobj.KernelVer = $parsd[1]
-
$objCol += $myObj}
-
}
-
}
-
$objCol
-
}
-
function GetTargetLun{
-
Param($srv,$wwn)
-
$objCol = @()
-
$result = &"$HBACMDPath" "h=$srv" TargetMapping $wwn
-
-
switch -regex ($result)
-
{
-
"^SCSI OS Lun" {$lun =
$_.
split([string[]](": "),
[system.
StringSplitOptions]::
RemoveEmptyEntries)[1].
trim()}
-
}
-
"{0:x}" -f $lun
-
}
-
function Ping-Server {
-
-
if($srv -eq ""){return $false}
-
$pingresult = Get-WmiObject win32_pingstatus -f "address=’$srv’"
-
if($pingresult.statuscode -eq 0) {$true} else {$false}
-
}
-
Write-Host
-
if($verbose){$VerbosePreference = "Continue"}
-
}
-
Process{
-
if($_)
-
{
-
Write-Host "Getting HBA Info from $_"
-
if($FullDetail)
-
{
-
$MyObject = CreateHBAListObj $_
-
$HBADetail = $MyObject | %{CreateHBAInfoObj $_.Host $_.PortWWN}
-
$MyObject | add-Member -Name HBADetail -type NoteProperty -Value $HBADetail -force
-
$MyObject
-
}
-
else
-
{
-
$MyObject = CreateHBAListObj $_
-
$MyObject
-
}
-
}
-
}
-
End{
-
if($list)
-
{
-
$servers = Get-Content $list
-
Write-Host "Running HBA Check against Servers in $list"
-
foreach($server in $servers)
-
{
-
if($server -ne "")
-
{
-
if(ping-server $server)
-
{
-
Write-Host "Getting HBA Info from $server"
-
if($FullDetail)
-
{
-
$MyObject = CreateHBAListObj $server
-
$HBADetail = $MyObject | %{CreateHBAInfoObj $_.Host $_.PortWWN}
-
$MyObject | add-Member -Name HBADetail -type NoteProperty -Value $HBADetail -force
-
$MyObject
-
}
-
else
-
{
-
$MyObject = CreateHBAListObj $server
-
$MyObject
-
}
-
}
-
else
-
{
-
Write-Host "$Server not Pingable `n" -foregroundcolor RED
-
}
-
}
-
}
-
}
-
if($HostName)
-
{
-
Write-Host "Running HBA Check against Servers in $HostName"
-
if(ping-server $HostName)
-
{
-
Write-Host "Getting HBA Info from $HostName"
-
if($FullDetail)
-
{
-
$MyObject = CreateHBAListObj $HostName
-
$HBADetail = $MyObject | %{CreateHBAInfoObj $_.Host $_.PortWWN}
-
$MyObject | add-Member -Name HBADetail -type NoteProperty -Value $HBADetail -force
-
$MyObject
-
}
-
else
-
{
-
$MyObject = CreateHBAListObj $HostName
-
$MyObject
-
}
-
}
-
else
-
{
-
Write-Host "$HostName not Pingable `n" -foregroundcolor RED
-
}
-
}
-
Write-Host
-
}
tshell :: Nov.08.2007 ::
Custom Objects, HowTo, Powershell, Scripting, functions ::
No Comments »