NetApp IMT FAS SAN Host Checking Tool (ImtChk.ps1)

I wrote this tool early last year (’16), and happened to have a need for it again recently and remembered I’d not blogged about it, so here it is...

Introduction

If you’ve got lots of FC SAN hosts to check for interoperability with ONTAP, it can be a bit clunky to have to click your way through the web interface (at https://mysupport.netapp.com/matrix/). So, having a need to check lots of FC SAN hosts myself for compatibility, I wrote this tool. It would be super great if the NetApp Interoperability Matrix had an API (if anyone knows, please let me know.)

Help

I did write a help output. If you run the tool as -

.\ImtChk.ps1

- you’ll get the help output which is below.

Image: ImtChk Help Output (Click on image to make bigger)

The Script

Copy and paste into a text editor and save as say ImtChk.ps1.


##################################################
## ImtChk.ps1: IMT SAN Host Check using PS CLI  ##
##################################################

Param( ## Note: ( or ) are not valid values here ##
  [Switch]$Export_Workbook_To_CSVs,
  [String]$Excel_Workbook,
  [Switch]$Get_IMT_Stuff,
  [String]$IMT_CSV_File,
  [String]$Supported, 
  [Switch]$Help,
  [String]$Host_OS,
  [String]$Host_OS2,
  [String]$Host_HBA,
  [String]$Host_Multipath,
  [String]$Host_Platform,
  [String]$Host_Feature,
  [String]$Protocol,
  [String]$Host_Utilities,
  [String]$ONTAP_OS,
  [String]$ONTAP_OS2,
  [Switch]$ShowCount
)
If(!$Host_OS -and !$Host_OS2 -and !$Host_HBA -and !$Host_Multipath -and !$Host_Platform -and !$Host_Feature -and !$Protocol -and !$Host_Utilities -and !$ONTAP_OS -and !$ONTAP_OS2 -and !$ShowCount){$Help = $TRUE}
FUNCTION Wr {Param([String]$Echo,[String]$Ink = "WHITE"); If($Echo){ Write-Host $Echo -ForegroundColor $Ink -NoNewLine } ELSE { Write-Host }}

#############################
## EXPORT WORKSHEET TO CSV ##
#############################

Function ExportWorksheetsToCSV {
  Param([String]$excelFile)
  $excelFile = Resolve-Path $excelFile
  $E = New-Object -ComObject Excel.Application
  $E.Visible = $false
  $E.DisplayAlerts = $false
  $wb = $E.Workbooks.Open($excelFile)
  foreach ($ws in $wb.Worksheets){
    $n = $excelFile + "_" + $ws.Name
    $ws.SaveAs($n + ".csv", 6)
  }
  $E.Quit()
}

If($Export_Workbook_To_CSVs){
  [Void](ExportWorksheetsToCSV $Excel_Workbook)
  EXIT
}

###################
## GET IMT STUFF ##
###################

FUNCTION Get-UniqueValues{
  Param([System.Array]$ArrayIn,[String]$NoteProperty)
  [System.Array]$ArrayOut = @()
  $NoteProperties = $ArrayIn.$NoteProperty
  [System.Array]$Properties = $NoteProperties.Split("`n")
  Foreach ($Property in $Properties){
    $Property = $Property.trim(";")
    If($ArrayOut -contains $Property){}
    elseif($Property -ne ""){ $ArrayOut += $Property }
  }
  , $ArrayOut
}

If($Get_IMT_Stuff){
  If(Test-Path $IMT_CSV_File){}
  else{ Wr "Unable to find $IMT_CSV_File!" Red; Wr; EXIT }
  $CSV = import-csv $IMT_CSV_File
  $Global:IMT = @{}
 
  ## The CSV has IMT Configs, some blank rows ...
  ## ... then goes onto an Alerts section and an Info section
 
  FUNCTION Get-EndOfList{
    Param([System.Array]$ArrIn)
    [Int]$Count = 0
    Foreach ($Member in $ArrIn){
      If($Member."Name" -eq ""){
        RETURN ($Count - 1)
      }
      $Count++
    }
  }
 
  [Int]$Pointer = Get-EndOfList $CSV
  [System.Array]$Global:IMT.Configurations = $CSV[0..$Pointer]
 
  $Pointer++
  while($CSV[$Pointer]."Name" -ne "Alerts"){ $Pointer++ }
  $CSV = $CSV[$Pointer..($CSV.count -1)]
  [Int]$Pointer = Get-EndOfList $CSV
  [System.Object]$Global:IMT.Alerts = @{}
  $CSV[0..$Pointer] | Foreach { $Global:IMT.Alerts.($_.Name) = $_ }
 
  $Pointer++
  while($CSV[$Pointer]."Name" -ne "Info"){ $Pointer++ }
  [System.Object]$Global:IMT.Info = @{}
  $CSV[$Pointer..($CSV.count -1)] | Foreach { $Global:IMT.Info.($_.Name) = $_ }
 
  ## FINDING VALID ITEMS ##
  ## =================== ##
 
  ## $Headings Excluded = "Foot notes","Name"
  [System.Array]$Headings = "Guest OS","Host Clustering","Host Feature","Host File System","Host HBA","Host Multipath","Host OS","Host Platform","Host Utilities","Host Volume Manager","ONTAP OS","Protocol","Software Initiator","Status"
  $Headings | Foreach {
    [String]$Header = $_.Replace(" ","_")
    [System.Array]$Global:IMT.$Header = Get-UniqueValues $Global:IMT.Configurations $_
  }
  ## $Global:IMT.Guest_OS | sort ... etcetera
  EXIT
}

###################
## GET SUPPORTED ##
###################

If ($Supported){      
  Get-UniqueValues $Global:IMTCheck $Supported.Replace("_"," ")
  EXIT
}

##########
## HELP ##
##########

If($Help){
  Wr; Wr "+++++ ImtChk.ps1: IMT SAN Host Check using PS CLI +++++" Magenta; Wr; Wr
  Wr "STEP 1: Download the IMT FAS_SAN_HOST xls from:" Green; Wr
  Wr "http://mysupport.netapp.com/matrix3/reports/FAS_SAN_Host.xls" Yellow; Wr; Wr
  Wr "STEP 2: Run the below to extract the FAS_SAN_Host workbook into CSVs PS>" Green; Wr
  Wr ".\ImtChk.ps1 -Export_Workbook_To_CSVs -Excel_Workbook {NAME-OF-EXCEL-WORKBOOK}" Cyan; Wr; Wr
  Wr "STEP 3: Run the below to generate the IMT Global Variables from the CSV of interest PS>" Green; Wr
  Wr ".\ImtChk.ps1 -Get_IMT_Stuff -IMT_CSV_File {NAME-OF-IMT-CSV}" Cyan; Wr; Wr
  FUNCTION Cln {Wr " : " Cyan}
  Wr "This makes the following variables available from the PowerShell CLI:" Green; Wr       
  Wr '$IMT' Yellow; Cln; Wr '$IMT.Configurations' Yellow; Cln; Wr '$IMT.Alerts' Yellow; Cln; Wr '$IMT.Info' Yellow; Wr; Wr
  Wr "Also, the following variables come available listing unique values:" Green; Wr
  Wr '$IMT.Guest_OS' Yellow; Cln; Wr '$IMT.Host_Clustering' Yellow; Cln; Wr '$IMT.Host_Feature' Yellow; Cln; Wr '$IMT.Host_File_System' Yellow; Wr
  Wr '$IMT.Host_HBA' Yellow; Cln; Wr '$IMT.Host_Multipath' Yellow; Cln; Wr '$IMT.Host_OS' Yellow; Cln; Wr '$IMT.Host_Platform' Yellow; Wr
  Wr '$IMT.Host Utilities' Yellow; Cln; Wr '$IMT.Host_Volume_Manager' Yellow; Wr
  Wr '$IMT.ONTAP_OS' Yellow; Cln; Wr '$IMT.Protocol' Yellow; Cln; Wr '$IMT.Software_Initiator' Yellow; Cln; Wr '$IMT.Status' Yellow; Wr; Wr
  Wr "STEP 4: Run queries from the PowerShell CLI using the syntax below (as many switches as you like) PS>" Green; Wr
  Wr ".\ImtChk.ps1" Cyan; Wr
  Wr " -Host_OS        {Host_OS}" Cyan; Wr
  Wr " -Host_OS2       {Host_OS2}" Cyan; Wr
  Wr " -Host_HBA       {Host_HBA}" Cyan; Wr
  Wr " -Host_Multipath {Host_Multipath}" Cyan; Wr
  Wr " -Host_Platform  {Host_Platform}" Cyan; Wr
  Wr " -Host_Feature   {Host_Feature}" Cyan; Wr
  Wr " -Protocol       {Protocol}" Cyan; Wr
  Wr " -Host_Utilities {Host_Utilities}" Cyan; Wr
  Wr " -ONTAP_OS       {ONTAP_OS}" Cyan; Wr
  Wr " -ONTAP_OS2      {ONTAP_OS2}" Cyan; Wr
  Wr " -ShowCount      {ShowCount}" Cyan; Wr; Wr
  Wr "This will also make available the variable " green; Wr '$IMTCheck' Yellow; Wr; Wr
  Wr "NOTE: To check the output of step 4 for supported values of a certain type, run PS>" Green; Wr
  FUNCTION FSl {Wr "/" Yellow}
  Wr ".\ImtChk.ps1 -Supported Host_OS" Cyan; FSl; Wr "Host_Multipath" Cyan; FSl; Wr "Host_Platform" Cyan; FSl
  Wr "Host_Feature" Cyan; FSl; Wr "Protocol" Cyan; FSl; Wr "Host_Utilities" Cyan; FSl; Wr "ONTAP_OS" Cyan; Wr; Wr
  Wr "EXAMPLE: PS> " Green; Wr
  Wr '.\ImtChk -help' Cyan; Wr
  Wr '.\ImtChk -Export_Workbook_To_CSVs -Excel_Workbook FAS_SAN_Host_20151206.xls' Cyan; Wr
  Wr '.\ImtChk -Get_IMT_Stuff -IMT_CSV_File "FAS_SAN_Host_20151206.xls_Windows Server 2008.csv"' Cyan; Wr
  Wr '.\ImtChk -ONTAP_OS "Data ONTAP 8.1.4 7-Mode" -ONTAP_OS2 "Clustered Data ONTAP 8.3.1" -Host_OS "Microsoft Windows Server 2008 R2 EE" -HOST_OS2 "SP1" -HOST_HBA "QLE2672"' Cyan; Wr
  Wr;   EXIT
}

##################
## MAIN PROGRAM ##
##################

FUNCTION Item-Check{
  Param([String]$Name,[String]$Check)
  [String]$Header = $Name.Replace("_"," ")
  Foreach($Item in $Global:IMT.$Name){
    If($Item -Match $Check){
      [System.Array]$TempArray = @()
      Foreach($Member in $Global:IMTCheck){                        
        If($Member.$Header -Match $Check){ $TempArray += $Member }                
      }
      $Global:IMTCheck = $TempArray
      If($ShowCount){ Wr ([String]($Global:IMTCheck.Count)) Green; Wr " @ $Name = $Check" Cyan; Wr }
      RETURN
    }  
  }    
  "NO MATCH: $Header is not listed!"; EXIT
}

[System.Array]$Global:IMTCheck = $Global:IMT.Configurations
If($ShowCount){ Wr ([String]($Global:IMTCheck.Count)) Green; Wr " @ start" Cyan; Wr }
If($Host_OS)       { Item-Check "Host_OS" $Host_OS }
If($Host_OS2)      { Item-Check "Host_OS" $Host_OS2 }
If($Host_HBA)      { Item-Check "Host_HBA" $Host_HBA }
If($Host_Multipath){ Item-Check "Host_Multipath" $Host_Multipath }
If($Host_Platform) { Item-Check "Host_Platform" $Host_Platform }
If($Host_Feature)  { Item-Check "Host_Feature" $Host_Feature }
If($Protocol)      { Item-Check "Protocol" $Protocol }
If($Host_Utilities){ Item-Check "Host_Utilities" $Host_Utilities }
If($ONTAP_OS)      { Item-Check "ONTAP_OS" $ONTAP_OS }
If($ONTAP_OS2)     { Item-Check "ONTAP_OS" $ONTAP_OS2 }

If(!$ShowCount){
  [System.Array]$ValidHostHBAs = $Global:IMTCheck."Host HBA"
  [System.Array]$UniqueHostHBAs = @()
  $ValidHostHBAs = $ValidHostHBAs.Split("`n")
  Foreach ($HBA in $ValidHostHBAs){
    $HBA = $HBA.trim(";")
    If($UniqueHostHBAs -contains $HBA){}
    elseif($HBA -ne ""){ $UniqueHostHBAs += $HBA }
  }
  If($Host_HBA){
    Foreach ($HBA in $UniqueHostHBAs){
      If ($HBA -match $Host_HBA){ $HBA }
    }
  } else { $UniqueHostHBAs }
}


Note: There is definitely room for improvement with this tool, and if you get a chance to make it better, please share the finished superior product, many thanks!

Comments