Saturday, 2 December 2017

Mapping APIs to ClusterShell and PowerShell - UPDATE

An update to this April 2017 post! Not sure if it’s just me, or its ONTAP 9.3RC1 perhaps, but I couldn’t get Invoke-NcSsh to work with the PowerShell Toolkit 4.5 (Get-NaToolkitVersion 4.3). My work around requires you have plink.exe in your working folder. The pictured bit of code, creates a temporary password, creates a temporary user, runs plink with this user and password to get the show-ontapi output, then deletes the temporary user. I’ve never been a fan of Invoke-NcSsh or Invoke-NaSsh, this seems like a nice workaround and you’re only passing a temporary randomly generated plaintext password over the network.

Image: Using Plink instead of Invoke-NcSsh to get show-ontapi output

The Script

Copy into a text editor and save as say API-to-CS-PS.ps1
Then run the following in PowerShell::>


Import-Module DataONTAP
Connect-NcController {CLUSTER}
.\API-to-CS-PS.ps1



## API to CShell & PShell V3 ##
## ========================= ##

## PRE-REQ: A connection to a cluster:
## PS> Import-Module DataONTAP
## PS> Connect-NcController {CLUSTER}
## PS> .\API-to-CS-PS.ps1
## Also needs plink.exe in the working directory
## (used here as working alternative to Invoke-NcSsh)

[String]$CluName = (Get-NcCluster).ClusterName
[String]$CluIP   = (Get-NcCluster).NcController
If(!$CluName){EXIT}

## USING PLINK TO GET show-ontapi ##
## ============================== ##

[String]$alphabet =""
For($a=65;$a -le 90;$a++){$alphabet +=,[char][byte]$a}
[String]$tempPass = ""
For($loop=1;$loop -le 8;$loop++){$tempPass += ($alphabet|Get-RANDOM)}
$tempPass += [String](Get-Random -Maximum 10)
[Void](New-NcUser -UserName TempPlinkUser -Vserver $CluName -Application ssh -AuthMethod password -Role admin -Password $tempPass)
[System.Array]$Global:Lines = .\plink -ssh -x -a -l TempPlinkUser -pw $tempPass $CluIP "show-ontapi"
[Void](Remove-NcUser -UserName TempPlinkUser -Vserver $CluName -Application ssh -AuthMethod password -Confirm:$FALSE)

## MAP API TO CSHELL ##
## ================= ##

[System.Object]$Global:APItoCSHELL = @{}
[System.Array]$APIlist = @()
[Boolean]$Recording = $FALSE
[String]$ONTAPI     = ""
[String]$Command    = ""
$Global:Lines | Foreach{
  If($Recording){
    If($_.StartsWith(" ")){
      If($Command){$Command += " "}
      # += " " because command might carry onto next line #
      $Command += $_.Trim(" ")
    }else{
      If($ONTAPI -and $Command){
        $Global:APItoCSHELL.$ONTAPI = $Command
        $APIlist += $ONTAPI
        [String]$ONTAPI = ""
        [String]$Command = ""                         
      }
      If($_.Split(" ").Count -eq 1){ $ONTAPI = $_ }
      else{
        $ONTAPI = $_.Split(" ")[0]
        $Command = $_.SubString($ONTAPI.length,($_.length - $ONTAPI.length)).Trim(" ")
      }
    }
  }
  If($_.StartsWith("-")){$Recording = $TRUE}
  # The header finishes with a line of "-" #
  If($_ -like '[0-9]*'){$Recording = $FALSE}
  # The show-ontapi output ends with a count #
}

## MAP API TO PSHELL ##
## ================= ##

$GetNcHelp = Get-NcHelp
# A cmdlet might map to two or more APIs, we need unique APIs #
[System.Object]$Global:APItoPSHELL = @{}
$GetNcHelp | Foreach{
  If($_.API){
    Foreach($API in $_.API.Split(",")){
      If($Global:APItoPSHELL.$API){}
      else{
        [System.Object]$Global:APItoPSHELL.$API = @{}
        [String]$Global:APItoPSHELL.$API.Category   = ""
        [String]$Global:APItoPSHELL.$API.Family     = ""
        [String]$Global:APItoPSHELL.$API.PowerShell = ""
      }
      If($Global:APItoPSHELL.$API.PowerShell){$Global:APItoPSHELL.$API.PowerShell += " "}
      # Above adds " " if a cmdlet has already been logged for the API #
      If($_.Category){ $Global:APItoPSHELL.$API.Category    = $_.Category}
      If($_.Family){   $Global:APItoPSHELL.$API.Family      = [String]($_.Family)}
      If($_.Name){     $Global:APItoPSHELL.$API.PowerShell += $_.Name}
    }
  }
}

## GENERATE CSV AND EXPORT ##
## ======================= ##

[System.Array]$Global:CSV = @()

# TEXT OUT SECTION #
[System.Array]$TextOut = @()
$TK = Get-NaToolkitVersion
$TextOut += "API-to-CS-PS"
$TextOut += "============",""
$TextOut += "NaToolkitVersion = $($TK.major).$($TK.minor)"
$TextOut += "ONTAP Version    = $((Get-NcSystemVersionInfo).Version)",""

$APIlist | Foreach{
  $Category = $Family = $PSHELL = ""
  If($Global:APItoPSHELL.$_){
    $Category = $Global:APItoPSHELL.$_.Category
    $Family = $Global:APItoPSHELL.$_.Family
    $PSHELL = $Global:APItoPSHELL.$_.PowerShell
  }
  $Global:CSV += [PSCustomObject]@{
    "API"      = $_
    "Category" = $Category
    "Family"   = $Family
    "CSHELL"   = $Global:APItoCSHELL.$_
    "PSHELL"   = $PSHELL
  }
  # TEXT OUT SECTION (for PSHELL) #
  If($PSHELL){
       [String]$APIout = $_.Replace("`n","").Replace("`r","")
    [String]$CshOut = ($Global:APItoCSHELL.$_).Replace("`n","").Replace("`r","")
       $TextOut += ("API = $APIout")
       $TextOut += ("CS  = $CshOut")
       $PSHELL = $PSHELL.Trim(" ")
       [System.Array]$SplitPS = $PSHELL.Split(" ")
       Foreach($PS in $SplitPS){
              $TextOut += ("PS  = " + $PS)
       }
       $TextOut += ""
  }
}

$Global:CSV | Export-CSV "API-to-CS-PS.CSV" -NoTypeInformation
$TextOut | Set-Content "API-to-CS-PS.TXT"
Notepad "API-to-CS-PS.TXT"


No comments:

Post a Comment