Introducing the “Super
Rootvol LS Mirrors Creator” or SRLMC for short!
Creating load-sharing mirrors of the Data SVM’s rootvol -
where the Data SVM serves NAS protocols - has been a NetApp best practice from
pretty much year dot of Clustered DataONTAP (or ONTAP). It’s often arguable
whether they’re really needed, and they can be a bit of a pain, but this blog
post isn’t the place to go into the debate.
To make them less of a pain, here’s the “Super Rootvol LS
Mirrors Creator”, and this is how it works:
- Run it (either from PowerShell, or you could
create a BAT file to run the PowerShell - double-click and you’re off)
- It will prompt for cluster, username, and
password.
- It does the usual, load DataONTAP PowerShell
Toolkit, and connects to the cluster.
- It acquires the nodes in the cluster.
- It acquires the data aggregates in the cluster.
- If any node does not have a data aggregate, it
exits!
- It automatically selects the first acquired
data aggregate per node to be used for the LS Mirror volumes.
- It acquires all the running NAS data SVMs, and their
root volume information.
- Then it goes ahead and creates LS Mirrors for
the rootvol, for all the NAS data SVMs.
- If a data
SVM already has LS Mirrors, it does nothing for that data SVM.
- If a data
SVM had say only 2 nodes out of 4 with LS Mirrors, it creates LS Mirrors on the
other 2 nodes (the tool might prove useful if you’re expanding your cluster.)
The Script
Copy and paste into a text editor and save as say SRLMC.ps1
######################################
##
Super Rootvol LS Mirrors Creator ##
######################################
Param(
[Parameter(Mandatory=$True)][String]$Cluster,
[Parameter(Mandatory=$True)][String]$UserName,
[Parameter(Mandatory=$True)][Security.SecureString]$Password
# TIP: PS> $P = Read-Host -AsSecureString
# ... you can use $P after -Password
)
##
TITLE ##
"`nSuper
Rootvol LS Mirrors Creator"
"================================`n"
##
GENERIC: Loading PSTK ##
"INFO:
DataONTAP PSTK loading ..."
[Void](Import-Module
DataONTAP)
If(!(Get-Module
DataONTAP)){"ERROR: No DataONTAP PSTK!";EXIT;PAUSE}
"INFO:
DataONTAP PSTK loaded.`n"
##
GENERIC: Connecting to $Cluster ##
"INFO:
$Cluster connecting ..."
$Global:CurrentNcController
= $NULL
$Cred
= New-Object System.Management.Automation.PsCredential($UserName,$Password)
[Void](Connect-NcController
-Name $Cluster -Credential $Cred)
If(!$Global:CurrentNcController){"ERROR:
Cannot connect to $Cluster!";EXIT;PAUSE}
"INFO:
$Cluster connected.`n"
##
COLLECTING DATA - NODES ##
$Attrs_Node
= Get-NcNode -Template
[System.Array]$Nodes
= (Get-NcNode -Attributes $Attrs_Node).Node
##
COLLECTING DATA - AGGRs ##
$Attrs_Aggr
= Get-NcAggr -Template
Initialize-NcObjectProperty
-Object $Attrs_Aggr -Name AggrOwnershipAttributes
$Query_Aggr
= Get-NcAggr -Template
Initialize-NcObjectProperty
-Object $Query_Aggr -Name AggrRaidAttributes
$Query_Aggr.AggrRaidAttributes.IsRootAggregate
= $FALSE
$Aggrs
= Get-NcAggr -Attributes $Attrs_Aggr -Query $Query_Aggr
If(!$Aggrs){"ERROR:
No Data Aggregates!";EXIT;PAUSE}
##
CHECKING ALL NODES HAVE (ATLEAST) ONE DATA AGGR ##
[System.Object]$AggrForLSM
= @{}
[Boolean]$AllNodesHaveDataAggr
= $TRUE
Foreach($Node
in $Nodes){
[System.Object]$DataAggrsOnNode = $Aggrs |
Where{$_.AggrOwnershipAttributes.OwnerName -eq $Node}
If($DataAggrsOnNode){
[System.Array]$AggrsArray =
$DataAggrsOnNode.Name
$Aggregate = $AggrsArray[0]
[String]$AggrForLSM.$Node = $Aggregate
"INFO: Data aggr for LSM for node
$Node = $Aggregate"
} else {
"ERROR: Node $Node has no data
aggrs!";EXIT;PAUSE
}
};""
##
GET RUNNING NAS DATA SVMs with ROOTVOL INFO ##
$Attrs_DSVM
= Get-NcVserver -Template
$Attrs_DSVM.RootVolume
= ""
$Attrs_DSVM.AllowedProtocols
= ""
$Query_DSVM
= Get-NcVserver -Template
$Query_DSVM.State
= "running"
$Query_DSVM.VserverType
= "data"
$GetDataSVMs
= Get-NcVserver -Attributes $Attrs_DSVM -Query $Query_DSVM
[System.Array]$DataSVMs
= @()
$GetDataSVMs
| Foreach{
If(($_.AllowedProtocols -contains
"cifs") -or ($_.AllowedProtocols -contains "nfs")){
$DataSVMs += $_
}
}
If(!$DataSVMs){"ERROR:
No running NAS data SVMs!";EXIT;PAUSE}
else{
$DataSVMs | Foreach{
"INFO: Data SVM " +
$_.VserverName + " has rootvol name = " + $_.RootVolume
}
};""
##
GET DATA FOR ROOTVOLs (need size and languge) ##
$Attrs_Vol
= Get-NcVol -Template
Initialize-NcObjectProperty
-Object $Attrs_Vol -Name VolumeLanguageAttributes
Initialize-NcObjectProperty
-Object $Attrs_Vol -Name VolumeSpaceAttributes
[System.Object]$RootvolInfo
= @{}
$DataSVMs
| Foreach{
[String]$SVM = $_.VserverName
$RootvolInfo.$SVM = Get-NcVol -Attributes
$Attrs_Vol -Name $_.RootVolume -VserverContext $SVM
"INFO: Data SVM " + $SVM +,
" has language " +
$RootvolInfo.$SVM.VolumeLanguageAttributes.LanguageCode +,
" and size " +
$RootvolInfo.$SVM.VolumeSpaceAttributes.Size
};""
##
CREATE OBJECT FOR SVM.NODE and if it has an LSM or not ##
$Attrs_SMRR
= Get-NcSnapMirror -Template
$Query_SMRR
= Get-NcSnapMirror -Template
$Query_SMRR.RelationshipType
= "load_sharing"
Initialize-NcObjectProperty
-Object $Attrs_Vol -Name VolumeIdAttributes
[System.Object]$CurrLSMs
= @{}
$DataSVMs
| Foreach{
## Setup some variables ##
[String]$SVM = $_.VserverName
[System.Object]$CurrLSMs.$SVM = @{}
[Boolean]$CurrLSMs.$SVM.HasRootVolLSMs =
$FALSE
Foreach($Node in $Nodes){
[Boolean]$CurrLSMs.$SVM.$Node = $FALSE }
## Query for LS SnapMirrors of the RootVolume
##
$Query_SMRR.SourceVserver = $SVM
$Query_SMRR.SourceVolume = $_.RootVolume
$LSMs = Get-NcSnapMirror -Attributes
$Attrs_SMRR -Query $Query_SMRR
## Gather LSM info (if any) ##
If($LSMs){
"INFO: $SVM has LS mirrors of the
rootvol."
$CurrLSMs.$SVM.HasRootVolLSMs = $TRUE
## Cycle through LSMs ##
Foreach($LSM in $LSMs){
$DestLSMvol = $LSM.DestinationVolume
$DestLSMnode = (Get-NcVol -Attributes
$Attrs_Vol -Name $DestLSMvol -VserverContext $SVM).VolumeIdAttributes.Node
"INFO: $SVM has an LSM volume on
$DestLSMnode"
$CurrLSMs.$SVM.$DestLSMnode = $TRUE
}
}else{
"INFO: $SVM does NOT have LS mirrors
of the rootvol."
}
};""
##
CREATE LSMs on NODES THAT DON'T HAVE THEM ##
$DataSVMs
| Foreach{
[String]$SVM = $_.VserverName
[String]$RootVol = $_.RootVolume
Foreach($Node in $Nodes){
If($CurrLSMs.$SVM.$Node){}
else{
## Volume Create ##
[String]$Vol = ("$RootVol" +
"_LSM_" + $Node.replace("-","_"))
[String]$Agg = $AggrForLSM.$Node
[Int32]$Size =
$RootvolInfo.$SVM.VolumeSpaceAttributes.Size
[String]$Lang =
$RootvolInfo.$SVM.VolumeLanguageAttributes.LanguageCode
[Void](New-NcVol -Name $Vol
-VserverContext $SVM -Aggregate $Agg -Type dp -Size $Size -Language $Lang
-JunctionPath $null)
"INFO: Created LSM volume for $SVM on $Node called $Vol"
## LS SnapMirror Create ##
[Void](New-NcSnapMirror -Source
"//$SVM/$RootVol" -Destination "//$SVM/$Vol" -Type ls
-Schedule hourly)
"INFO: Created LSM mirror for $SVM
and $RootVol to $Vol"
## LS SnapMirror Initialize (if didn't
already have an LS mirror) ##
If($CurrLSMs.$SVM.HasRootVolLSMs){
[Void](Invoke-NcSnapMirrorInitialize
-Destination "//$SVM/$Vol")
"INFO: Initialized snapmirror to
$Vol"
}
}
}
## Initialize LS Set (if SVM had NO LSMs
before) ##
If($CurrLSMs.$SVM.HasRootVolLSMs){}
Else{
[Void](Invoke-NcSnapMirrorLsInitialize
-Source "//$SVM/$RootVol")
"INFO: //$SVM/$RootVol
initialize-ls-set"
}
};"";PAUSE
BONUS: Running
with a Batch File
It’s nice to be able to double-click and run, and this is
very easy to do. Copy paste the below into a text editor and save as say SRLMC.bat.
PowerShell.exe
.\SRLMC.ps1
And below is an example of running this by
double-clicking the SRLMC.bat file.
In this example we have 3 NAS SVMs. 1 already has LSMs on
both nodes, so SRLMC has nothing to do for that SVM. The other 2 need LSMs
created on both nodes.
Image: Super
Rootvol LS Mirrors Creator in action!
Note: This was
tested with ONTAP 9.1.
Comments
Post a Comment