Tuesday, 18 September 2018

XDP SnapMirror 9.4 to 9.2 and 9.2 to 9.4 Does Work Just Not Supported

I took exception to something in Justin Parisi’s blog post:

In it he wrote -
“...If you are running ONTAP 9.4, XDP SnapMirror will work across all prior ONTAP 9.x releases except for ONTAP 9.2...”
That tripped my fake news detector. If you think about it, it makes zero sense that 9.4 to 9.1 works, but 9.4 to 9.2 doesn’t, and then 9.4 to 9.3 does - XDP SnapMirror is such an awesome and powerful technology, why would it just decide to stop working for 9.2!?

Image: The exception I took exception to

This is what he should have written:
“...If you are running ONTAP 9.4, XDP SnapMirror will be supported across all prior ONTAP 9.x releases except for ONTAP 9.2...”

In the screenshots below is proof of sorts to show it does indeed work for 9.2 to 9.4 and vice versa.

Image: XDP SnapMirror from 9.2 to 9.4 works (just not supported)

Image: XDP SnapMirror from 9.4 to 9.2 works (just not supported)

In the official table below, I think the language is wrong; instead of “Will work with these previous releases” it should be “is guaranteed to work and supported with these previous releases”. Pernickety me?

Image: SnapMirror XDP Release Interoperability

APPENDIX: CLI

In case my proof images go missing, I have put the CLI output below:


clu1::> version
NetApp Release 9.2P4: Tue May 01 19:23:51 UTC 2018

clu1::> snapmirror show
                                                                       Progress
Source            Destination Mirror  Relationship   Total             Last
Path        Type  Path        State   Status         Progress  Healthy Updated
----------- ---- ------------ ------- -------------- --------- ------- --------
clu2v1:vol2 XDP  clu1v1:vol2_DR Snapmirrored Idle    -         true    -

clu1::> snapmirror list-destinations
                                                  Progress
Source             Destination         Transfer   Last         Relationship
Path         Type  Path         Status Progress   Updated      Id
----------- ----- ------------ ------- --------- ------------ ---------------
clu1v1:vol1 XDP   clu2v1:vol1_DR Idle  -         -            678c478c-b9f2-11e8-ba81-000c299131c0

clu1::> qtree show -qtree !""
Vserver    Volume        Qtree        Style        Oplocks   Status
---------- ------------- ------------ ------------ --------- --------
clu1v1     vol1          qtree1       unix         enable    normal
clu1v1     vol2_DR       qtree2       unix         enable    readonly
2 entries were displayed.



clu2::> version
NetApp Release 9.4: Fri Jun 08 22:50:12 UTC 2018

clu2::> snapmirror show
                                                                       Progress
Source            Destination Mirror  Relationship   Total             Last
Path        Type  Path        State   Status         Progress  Healthy Updated
----------- ---- ------------ ------- -------------- --------- ------- --------
clu1v1:vol1 XDP  clu2v1:vol1_DR Snapmirrored Idle    -         true    -

clu2::> snapmirror list-destinations
                                                  Progress
Source             Destination         Transfer   Last         Relationship
Path         Type  Path         Status Progress   Updated      Id
----------- ----- ------------ ------- --------- ------------ ---------------
clu2v1:vol2 XDP   clu1v1:vol2_DR Idle  -         -            3ea380b6-b9f3-11e8-b19e-000c293eecae

clu2::> qtree show -qtree !""
Vserver    Volume        Qtree        Style        Oplocks   Status
---------- ------------- ------------ ------------ --------- --------
clu2v1     vol1_DR       qtree1       unix         enable    readonly
clu2v1     vol2          qtree2       unix         enable    normal
2 entries were displayed.


Friday, 14 September 2018

PowerShell to Update Clusters with Multiple Cluster Peers in Multiple IPSpaces

Not something I’m likely to use where I am at-the-moment seeing as there are certain restrictions. Still, I thought I’d show how easy it would be to use the DataONTAP PowerShell Toolkit to connect to a cluster, find all the cluster peers, peer IPSpaces, and intercluster LIFs in each of those IPSpaces, and then connect to all the peer clusters and update the cluster peer's peer addresses. This is something you’d only really be interested in doing if expanding/contracting a cluster/clusters, or checking that existing clusters have their ‘Remote Intercluster Addresses’ configured correctly (‘Active IP Addresses’ manage themselves to a degree.)

Image: Update Cluster Peers in action

Note i: The script was tested with ONTAP 9.0RC1 and the DataONTAP PowerShell ToolKit 4.0.0.231 (I’m not sure why I had to put a dummy passphrase in the script, perhaps this “bug” is fixed in later versions.)
Note ii: Assumptions are that the same credentials can login to all the involved clusters, IPSpace names are consistent...

The Script


## SOURCE CLUSTER ##

Import-Module DataONTAP
$cluster  = Read-Host "Enter Cluster Name"
$username = Read-Host "Enter Admin User  "
$password = Read-Host "Enter Password    " -AsSecureString
$credential = New-Object System.Management.Automation.PsCredential($username,$password)
Connect-NcController $cluster -Credential $credential

$Peers = Get-NcClusterPeer
$Query = Get-NcNetInterface -Template
$Query.role = "intercluster"
$IcInts = Get-NcNetInterface -Query $Query

## INTERCLUSTER LIFS to IPSPACES (I2I) ##

[System.Object]$I2I = @{}
[System.Array]$I2I.IPSs = @()

$IcInts | Foreach{
  [Int]$Unique = ($I2I.IPSs).count
  [System.Array]$I2I.IPSs = ($I2I.IPSs += $_.ipspace) | Select-Object -Unique
  If($Unique -ne ($I2I.IPSs).count){[System.Array]$I2I.($_.Ipspace) = @()}
  $I2I.($_.Ipspace) += ($_.Address)
}

## PEER CLUSTERS ##

$Peers | Foreach{
  Connect-NcController $_.ClusterName -Credential $credential
  [String]$IPspace = (Get-NcClusterPeer -ClusterName $cluster).IpspaceName
  [Void](Get-NcClusterPeer -ClusterName $cluster | Set-NcClusterPeer -Address ($I2I.$IPspace) -Passphrase "anything")
}


Sunday, 9 September 2018

Brocade 6510: snmp.64mibCap.FCMGMT-MIB:0x7b Value Out of Range

I was attempting to install the Brocade_6510_7500N_v9.1 RCF files on Brocade 6510 Fabric Switches for NetApp MetroCluster, following the official procedure -
- and got this error:


Warning: a config file without enabling VF feature is used.
configdownload will be done on the default switch and chassis.
** snmp.64mibCap.FCMGMT-MIB:0x7b Value Out of Range
Process function of configdownload failed for filter "snmp"
2018/08/24-16:11:02, [CONF-1023], 145, FID 128, INFO, ... , configDownload failed for chassis.


The solution (thanks JS) was to:

1) Disable VF

fosconfig --disable vf

2) Reboot

3) For ConfigDownload use section switch (not all):

Section (all|chassis|switch [all]): switch

Image: Brocade 6510

NaPTaC Tool: Nslookup and Ping-Test a Cluster(s) (and Report)

Another PowerShell tool I’ve been playing around with. This one does a few things:

1) Performs NSLookup on your cluster logical interface names as they should be in DNS, and records the IP (DNR = Did Not Resolve)
2) Ping tests the IP Addresses and records whether they are up or down
3) Outputs the data to the command prompt in a DOS table
4) Outputs the data to a CSV (you can apply conditional formatting in Excel to have UP as green and DOWN as red)
5) And will repeat as many times as you like (so you can easily build a spreadsheet with all the clusters you’re interested in)

Note: This doesn’t use the NetApp DataONTAP PowerShell Toolkit. On whatever desktop you can run powershell, you’ll be able to run this!
Note: Of course this was written with NetApp ONTAP clusters in mind, but it could be applied to pretty much any cluster that has nodes and interfaces.
Note: If - like in most places - you need network assignments first before kit goes in, reporting the nslookups of nodes that haven’t yet been physically installed is very useful!

A few notes which might help if you’re thinking of customizing it for your environment:

i: I’ve made it more generic that the one I was using (for obvious reasons), and I’ve not tested it in this form
ii: $LUps is the hashtable for LookUps, and we get the CLUSTER-mgmt IP first, then all the other LIFs
iii: Here we have LIFs: "-n$DD-sp","-n$DD-mgmt","-n$DD-ic","-svm1-$i","-svm2-$i" where $i is the node number, and $DD is the node number in 2 digits (i.e. node 5 is 05)
iv: The Vserver lookups are in case the SVM LIFs are in a DNS load-balancer and not explicit in DNS, so we get all the IPs in the DNS load-balancer
v: The $Output has to be sorted to get the columns in the correct order
vi: Output is to a file called Output.CSV

Image: naptac.ps1 user input (can paste in a list if you want)

The Script


######################################
## NSLOOKUP AND PING TEST A CLUSTER ##
######################################

Function Wr{ ## Write function ...
  Param([String]$Text,[String]$FColor,[String]$BColor,[Int]$Pad)
  If(!$Text){Write-Host;RETURN}
  If(!$FColor){Write-Host $Text -NoNewLine -ForegroundColor White;RETURN}
  If(!$BColor){Write-Host $Text -NoNewLine -ForegroundColor $FColor;RETURN}
  If(!$Pad){Write-Host $Text -NoNewLine -ForegroundColor $FColor -BackgroundColor $BColor;RETURN}
  Write-Host ($Text.PadRight($Pad," ")) -NoNewLine -ForegroundColor $FColor -BackgroundColor $BColor
}

Function WP{ ## Pad Function ...
  Param([String]$BColor = "Black",[Int]$Pad = 1)
  Write-Host " ".PadRight($Pad," ") -NoNewLine -BackgroundColor $BColor
}

Function VC-Nslookup{
  Param([String]$lookThisUp)
  [System.Array]$nslookup = (nslookup $LookThisUp)
  [Boolean]$Record = $False
  [String]$Result = ""
  Foreach($line in $nslookup){
    If($Record -and ($line.trim() -ne "")){
      If(!$Result){ $Result = $line.Split(" ")[2]}
      else{ $Result += ("," + $line.trim()) }
    }
  If($line.StartsWith("Name")){$Record = $TRUE}
  }
  Return $Result
}

Function TC{Test-Connection -ComputerName $Args[0] -Count 1 -Quiet}

################################
## RESIZE THE WINDOW'S BUFFER ##
################################

$Window = (Get-Host).UI.RawUI
$resize = $Window.BufferSize
$resize.Height = 9999
$resize.Width = 999
$Window.BufferSize = $resize

###########
## START ##
###########

[Boolean]$Do = $TRUE
[System.Array]$ClustersAndNodes = @()
Wr "Enter lines of - " CYAN; Wr "cluster,number-of-nodes" YELLOW; Wr " - then press ENTER on empty line to end list:" CYAN; Wr
While($do){
  $ReadIn = Read-Host
  If(!$ReadIn){$do = $FALSE}else{$ClustersAndNodes += $ReadIn}
}

[System.Array]$Output = @()
Foreach($CandN in $ClustersAndNodes){
 
  [String]$C = $CandN.Split(",")[0]
  [Int16]$Nodes = $CandN.Split(",")[1]
 
  ###########################
  ## GETTING LIF NSLOOKUPS ##
  ###########################
 
  Wr "Starting nslookup:" CYAN;Wr
  [System.Object]$LUps = @{}
  $LUps.($C + "-mgmt") = VC-Nslookup ($C + "-mgmt")
  For($i=1; $i -le $Nodes; $i++){
    $DD = "$i".PadLeft(2,"0")
    [System.Array]$LIFs = "-n$DD-sp","-n$DD-mgmt","-n$DD-ic","-svm1-$i","-svm2-$i"
    $LIFs | Foreach{ $LUps.($C + $_) = VC-Nslookup ($C + $_) }
  }
 
  Wr "Vserver nslokups:" CYAN;Wr ## SVM NSlookups ...
  "-svm1","-svm2" | Foreach{$LUps.($C + $_) = VC-Nslookup ($C + $_)};Wr
 
  ############
  ## OUTPUT ##
  ############
 
  ## COMMAND PROMPT: Heading ...
  Wr "Cluster" BLACK GRAY 20; WP
  Wr "Node ({cluster}-nX/n0X)" BLACK GRAY 30; WP
  "{cluster}-mgmt","{node}-sp","{node}-mgmt","{node}-ic","SVM1-lif-X","SVM2-lif-X" | Foreach{Wr $_ BLACK GRAY 20;WP};Wr      
 
  ## Data output ...
  For($i=1; $i -le $Nodes; $i++){
   
    $DD = "$i".PadLeft(2,"0")
    Wr $C BLACK CYAN 20; WP
    Wr "$C-n$DD" BLACK CYAN 30; WP
   
    [System.Array]$LIFs = "-mgmt","-n$DD-sp","-n$DD-mgmt","-n$DD-ic","-svm1-lif-$i","-svm2-lif-$i"
    [System.Object]$NsLRec = @{}
    [System.Object]$PngRec = @{}
    [Int]$x = 1
   
    Foreach($LIF in $LIFs){

      [String]$TempTC  = ($C + $LIF)
      [String]$TempNSL = $LUps.($C + $LIF)
     
      ## START: Handling SVM LIFs ...
      "-svm1","-svm2" | Foreach{
        If($LIF.Startswith($_+"-lif")){
          [System.Array]$SVM_LIFs = ($LUps.($C + $_)).Split(",")
          If($i -le $SVM_LIFs.count){$TempTC = $TempNSL = $SVM_LIFs[$i-1]}                          
        }
      } ## END: ... handled SVM LIFs
     
      If($TempNSL -eq ""){$TempNSL = "DNR"}
      If(TC $TempTC){Wr $TempNSL BLACK GREEN 20; WP; [String]$IsUp = "YES"}
      else{Wr $TempNSL WHITE RED 20; WP; [String]$IsUp = "NO"}
     
      ## Recording for CSV output ...
      [String]$NsLRec."$x" = $TempNSL
      [String]$PngRec."$x" = $IsUp
      $x++
    }

    ## Filling the CSV columns ...   
    $Output += New-Object PSObject -Property @{
      "CLUSTER"               = "$C"
      "NODE (CLUSTER-n0X/nX)" = "$C-n$DD"
      "1:CLUSTER-mgmt"        = $NsLRec."1"
      "1:Ping?"               = $PngRec."1"
      "2:NODE-sp"             = $NsLRec."2"
      "2:Ping?"               = $PngRec."2"
      "3:NODE-mgmt"           = $NsLRec."3"
      "3:Ping?"               = $PngRec."3"
      "4:NODE-ic"             = $NsLRec."4"
      "4:Ping?"               = $PngRec."4"
      "5:SVM1-lif-X"          = $NsLRec."5"
      "5:Ping?"               = $PngRec."5"
      "6:SVM2-lif-X"          = $NsLRec."6"
      "6:Ping?"               = $PngRec."6"
    }        
    Wr
  }
  $Output | Select-Object "CLUSTER","NODE (CLUSTER-n0X/nX)","1:CLUSTER-mgmt","1:Ping?","2:NODE-sp","2:Ping?","3:NODE-mgmt","3:Ping?","4:NODE-ic","4:Ping?","5:SVM1-lif-X","5:Ping?","6:SVM2-lif-X","6:Ping?" | Export-CSV "Output.CSV" -NoTypeInformation
}


Saturday, 8 September 2018

PingTester++ - Ping Testing Multiple Lists of DNS Names/IP Addresses with PowerShell

A slight modification of a tool I published back in April 2015 - Multiple Pings Testing Tool. The main change is that it autosizes the output Windows, and opens a new PowerShell window running PingTester++ for you to supply another list of DNS Names / IP Addresses to ping test. The screenshot below gives an example.

Image: PingTester++

The variable $ToolPath will need to be set correctly for your environment.

The Script

Copy and paste into a text editor and save as say pingTester++.ps1 then run in PowerShell from the save directory as .\pingTester++.ps1


####################
# PingTester++.ps1 #
####################

[String]$ToolPath = "H:\MY TOOLS"
[String]$ToolName = "pingTester++.ps1"

[Int16]$i = 1
[Int16]$MaxWidth = 0
[System.Array]$targets = @()

"Enter IP Addresses/Hostnames of Targets (press enter to terminate entry)"    
[String]$answer = $TRUE
While($answer){
  $answer = Read-Host "$i"
  If($answer){
    $targets += $answer
    If($answer.length -gt $MaxWidth){
      $MaxWidth = $answer.length
    }
  }
  If(($answer -eq "") -and ($i -eq 1)){
    "No input - exiting!"; Sleep 5; EXIT
  }
  $i++
}

$MaxWidth += 6
$Window = (Get-Host).UI.RawUI

$resize = $Window.WindowSize
$resize.Height = $targets.count + 2
$resize.Width = $MaxWidth + 2
$Window.WindowSize = $resize

$resize = $Window.BufferSize
$resize.Height = 9999
$resize.Width = $MaxWidth + 2
$Window.BufferSize = $resize

[System.Array]$status = @()
$targets | Foreach{$status += "Unitialized"}

Function Wr{Write-Host $Args[0] -BackgroundColor $Args[1] -ForegroundColor $Args[2]}

Function PrintStatus{
  Param([Int16]$pointer)
  If($pointer -eq ($targets.Count - 1)){$pointer = 0}
  else{$pointer ++}     
  cls
  $i = 0
  $targets | Foreach{
    If($pointer -eq $i){
      $Display = " * $_ "
    }else{
      $Display = "   $_ "
    }
    If($status[$i] -eq "UP"){
      Wr ($Display.PadRight($MaxWidth)) GREEN BLACK
    }elseif($status[$i] -eq "DOWN"){
      Wr ($Display.PadRight($MaxWidth)) RED WHITE
    }else{
      Wr ($Display.PadRight($MaxWidth)) GRAY BLACK
    }
    $i++
  }
}

Function GetResult{
  [Int16]$j = 0
  $targets | Foreach{
    [Boolean]$Result = Test-Connection -ComputerName $_ -Count 1 -Quiet
    If ($Result){$status[$j] = "UP"}
    If(!$Result){$status[$j] = "DOWN"}
    PrintStatus $j
    $j++
  }
}

Start PowerShell.EXE ".\$ToolName" -WorkingDirectory $ToolPath
While ($true){GetResult}