The following is a fairly robust tool for syncing CIFS
shares on replicated volumes. SVM-DR is a cool feature of cDOT; the incarnation
in 8.3.1 may not fit every requirement though...
Briefly, what the tool does (note that exactly the same
code will work in WFA - it has added WFA detection):
Acquisition Stage
Connected to the Source Cluster:
- Checks connection to the cluster
- Checks the Source SVM exists
- Checks there’s a CIFS server on this SVM
- Acquires volume junction paths
- Acquires shares
- Acquires ACLs
Connected to the Remote Cluster (which can
be the same as the Source, but the Vservers must be different):
- Checks connection to the cluster
- Checks the Remote SVM exists
- Checks there’s a CIFS server on this SVM
- Acquires volume junction paths
- Acquires shares
- Acquires ACLs
- Acquires SnapMirrors (only those with the
specified Source Vserver, SnapMirrored, and not SVM-DR relations)
CIFS Share
Synchronization Stage
Still connected to the Remote Cluster:
- Cycles through the SnapMirrored volumes
- Checks the junction-path and fixes if required
- Checks the shares on the volume and adds/sets
them as required
- Checks the share’s ACLs and adds/sets them as
required
- Checks for additional ACLs on the Remote Share,
and removes
- Checks for additional shares on the Remote
Volume, and removes
The Script
Note: As always,
formatted for blogger by replacing tabs with two spaces.
#######################
## Sync-NcCifsShares ##
#######################
Param(
[parameter(Mandatory=$true)][String]$Source_Cluster,
[parameter(Mandatory=$true)][String]$Source_Vserver,
## Remote_Cluster CAN be
the same as Source_Cluster ##
## Remote_Vserver CANNOT
be the same as Source_Vserver ##
[parameter(Mandatory=$true)][String]$Remote_Cluster,
[parameter(Mandatory=$true)][String]$Remote_Vserver,
[String]$Title =
"Sync-NcCifsShares",
[Switch]$Log,
[String]$LogFile = ($Title + "_" +
$Source_Vserver + "_to_" + $Remote_Vserver + ".log")
)
###################
## GENERAL STUFF ##
###################
## ===== WFA ENVIRONMENT DETECTION ===== ##
[Boolean]$WFA
= $FALSE
If(Get-Command
Get-WFALogger -ErrorAction SilentlyContinue){ $WFA = $TRUE }
## ===== OUTPUT FUNCTION ===== ##
Function
Wr{
Param([String]$Echo =
"",[String]$Ink = "WHITE",[Switch]$EXIT)
If($Log){ $Echo >> $LogFile }
If($WFA -and $Echo){ Get-WFALogger -Info
-message $("$Echo") }
elseif($WFA){ Get-WFALogger -Info -message
$(" ") }
If($EXIT){ Write-Host $Echo -ForegroundColor
RED; Write-Host; EXIT }
Write-Host $Echo -ForegroundColor $Ink
};Wr
## ===== TITLE ===== ##
Wr
"+++++ $Title +++++" MAGENTA;Wr
## ===== TRAP DETECTION ===== ##
Trap{
Wr;Wr "TRAP DETECTED!" RED
Wr ("Time of Error : " +
(get-date).DateTime) RED
Wr ("Line Number : " +
$_.InvocationInfo.ScriptLineNumber) RED
Wr ("Offset in Line: " +
$_.InvocationInfo.OffsetInLine) RED
Wr ("Error Message : " +
$_.Exception.Message) RED;Wr
}
## ===== MAPPING VSERVER TO CLUSTER ===== ##
[System.Object]$VsToCl
= @{}
[String]$VsToCl.$Source_Vserver
= $Source_Cluster
[String]$VsToCl.$Remote_Vserver
= $Remote_Cluster
If($Source_Vserver
-eq $Remote_Vserver){ Wr "Cannot have Source and Remote Vserver with same
name!" -EXIT }
## ===== LOAD THE DATA ONTAP PSTK ===== ##
If(!(Get-Module
DataONTAP)){ [Void](Import-Module DataONTAP -ErrorAction SilentlyContinue) }
If(!(Get-Module
DataONTAP)){ Wr "Failed to load DataONTAP PSTK!" -EXIT }
else{
Wr "Loaded DataONTAP PSTK" GREEN;Wr }
#######################
## ACQUISITION STAGE ##
#######################
Wr
">>>>> Acquisition Stage <<<<<"
MAGENTA;Wr
## ===== DEFINING VARIABLES ===== ##
[System.Object]$Vols = @{}
[System.Object]$Shares = @{}
[System.Object]$ACLs = @{}
## ===== CYCLE THROUGH SOURCE & REMOTE VSERVER ===== ##
Foreach($Vserver
in ($Source_Vserver,$Remote_Vserver )){
[String]$Cluster = $VsToCl.$Vserver
## ===== WFA
RUNNING / OR NOT ===== ##
If($WFA){ Connect-WfaCluster $Cluster }
else{
## =====
CREDENTIALS & CONNECT TO CONTROLLER DETECTION ===== ##
If(!(Get-NcCredential $Cluster)){ Wr
"Failed to Get-NcCredential $Cluster!" -EXIT }
else{ Wr ("Using credential " +
((Get-NcCredential $Cluster).Credential.UserName) + " for $Cluster")
GREEN }
If(!(Connect-NcController $Cluster
-ErrorAction SilentlyContinue)){ Wr "Failed to connect to cluster
$Cluster!" -EXIT }
else{ Wr "Successfully tested
connection to $Cluster" GREEN }
}
## ===== RUNNING
DATA SVM & CIFS SERVER DETECTION ===== ##
If( !(Get-NcVserver | where { ($_.State -eq
"running") -and ($_.VserverType -eq "data") -and
($_.VserverName -eq $Vserver) }) ){ Wr "Cluster $Cluster has no running
data SVM called $Vserver!" -EXIT }
else{ Wr "Found running data SVM called
$Vserver" GREEN }
If( !(Get-NcCifsServer -VserverContext
$Vserver) ){ Wr "$Vserver has no CIFS server!" -EXIT }
else{ Wr "$Vserver has CIFS server"
GREEN }
## ===== ACQUIRE
VOLS, SHARES & SHARE ACLs ===== ##
$VolAttrs = Get-NcVol -Template
Initialize-NcObjectProperty -object $VolAttrs
-name VolumeIdAttributes
$VolAttrs.VolumeIdAttributes.JunctionPath =
""
$Vols.$Vserver = Get-NcVol -Attributes $VolAttrs
-VserverContext $Vserver
Wr "Acquired volume junction path info
from $Vserver" GREEN
$Shares.$Vserver = Get-NcCifsShare
-VserverContext $Vserver
Wr "Acquired CIFS share info from
$Vserver" GREEN
$ACLs.$Vserver = Get-NcCifsShareAcl -VserverContext
$Vserver
Wr "Acquired CIFS share ACL info from
$Vserver" GREEN;Wr
}
## ===== ACQUIRE SNAPMIRRORS ===== ##
$SMattrs
= Get-NcSnapMirror -Template
$SMattrs.MirrorState
= ""
[System.Object]$GetNcSnapMirror
= Get-NcSnapMirror -Attributes $SMattrs -VserverContext $Remote_Vserver | Where
{($_.SourceVserver -eq $Source_Vserver) -and ($_.MirrorState -eq
"snapmirrored") -and ($_.SourceVolume -ne "")}
Wr
"Acquired SnapMirrors from $Source_Vserver to $Remote_Vserver"
GREEN;Wr
######################################
## CIFS SHARE SYNCHRONIZATION STAGE ##
######################################
Wr
"<<<<< CIFS Share Synchronization Stage
>>>>>" MAGENTA;Wr
## ===== FUNCTION TO CHECK/CORRECT JUNCTION PATH ===== ##
Function
Sync-NcJunctionPathVolumeDpPair{
## NOTE! The following
variables exist outside this function: ##
## $Shares,$ACLs,$Source_Vserver,$Remote_Vserver,$SourceVol,$SrcVolName,$RemoteVol,$RemVolName
##
[String]$SrcJPath =
$SourceVol.VolumeIdAttributes.JunctionPath
[String]$RemJPath =
$RemoteVol.VolumeIdAttributes.JunctionPath
## ===== SYNC JUNCTION
PATHS ===== ##
If($SrcJPath -eq $RemJPath){
Wr "$SrcVolName has matching junction
path with $RemVolName" GREEN
RETURN $TRUE
}elseif($SrcJPath -eq $NULL){
Wr "$SrcVolName on $Source_Vserver has
no junction path. Dismounting volume $RemVolName on $Remote_Vserver!"
YELLOW
[Void](Dismount-NcVol -Name $RemVolName
-VserverContext $Remote_Vserver)
}elseif($RemJPath -eq $NULL){
Wr "$RemVolName on $Remote_Vserver has
no junction path - mounting volume!" YELLOW
[Void](Mount-NcVol -Name $RemVolName -JunctionPath
$SrcJPath -VserverContext $Remote_Vserver)
}else{
Wr "$RemVolName on $Remote_Vserver has
incorrect junction path - re-mounting volume!" YELLOW
[Void](Dismount-NcVol -Name $RemVolName
-VserverContext $Remote_Vserver)
[Void](Mount-NcVol -Name $RemVolName
-JunctionPath $SrcJPath -VserverContext $Remote_Vserver)
}
## ===== RE-VERIFY
JUNCTION PATH ===== ##
$RemJPath = (Get-NcVol -Name $RemVolName
-Attributes $VolAttrs -VserverContext $Remote_Vserver).VolumeIdAttributes.JunctionPath
If($SrcJPath -ne $RemJPath){
Wr "Failed to correct junction
path!" RED
RETURN $FALSE
}
Wr "Successfully updated junction
path!" GREEN
RETURN $TRUE
}
## ===== FUNCTION TO SYNC SHARES FOR A VOLUME DP PAIR ===== ##
Function
Sync-NcSharesOnVolumeDpPair{
## NOTE! The following
variables exist outside this function: ##
##
$Source_Vserver,$Remote_Vserver,$SourceVol,$SrcVolName,$RemoteVol,$RemVolName,$VolAttrs
##
If( !(Sync-NcJunctionPathVolumeDpPair) ){
RETURN }
## ===== GET SHARES ON
SOURCE AND REMOTE (DP) VOLUME ===== ##
$SrcSharesOnVol = $Shares.$Source_Vserver |
Where { $_.Volume -eq $SrcVolName }
$RemSharesOnVol = $Shares.$Remote_Vserver |
Where { $_.Volume -eq $RemVolName }
## ===== CYCLE THROUGH
SHARES ON THE SOURCE VOLUME ===== ##
Foreach($Share in $SrcSharesOnVol){
[String]$ShareName = $Share.ShareName
[String]$Comment = $Share.Comment
$Share.NcController = $NULL
$Share.Vserver = $NULL
$Share.Volume = $RemVolName
## ===== CHECK IF THE
SHARE EXISTS; IF NOT ADD, OTHERWISE SET ===== ##
[Boolean]$NewShareCreated = $FALSE
If( !($RemSharesOnVol | Where {
$_.ShareName -eq $ShareName }) ){
Wr "Share $ShareName does not exist
on $RemVolName - creating!" YELLOW
[Void]($Share | Add-NcCifsShare -Name
$ShareName -VserverContext $Remote_Vserver -Comment $Comment)
$NewShareCreated = $TRUE
}else{
Wr "Share $ShareName does exist on
$RemVolName - verifying settings ..." GREEN
[Void]($Share | Set-NcCifsShare
-VserverContext $Remote_Vserver -Comment $Comment)
}
## ===== CYCLE THROUGH
THE ACLs ON THE SHARE ===== ##
Foreach($ACL in ($ACLs.$Source_Vserver |
Where { $_.Share -eq $ShareName }) ){
[String]$UserOrGroup = $ACL.UserOrGroup
$ACL.NcController = $NULL
$ACL.Vserver = $NULL
## ===== CHECK IF
THE ACL EXISTS; IF NOT ADD (UNLESS NewShareCreated & Everyone), OTHERWISE
SET ===== ##
If($NewShareCreated -and ($UserOrGroup
-eq "Everyone")){
Wr "Setting ACL for $UserOrGroup
on share $ShareName ..." GREEN
[Void]($ACL | Set-NcCifsShareAcl
-VserverContext $Remote_Vserver)
}elseif( !($ACLs.$Remote_Vserver | Where
{ ($_.Share -eq $ShareName) -and ($_.UserOrGroup -eq $UserOrGroup) }) ){
Wr "Adding ACL for $UserOrGroup on
share $ShareName ..." YELLOW
[Void]($ACL | Add-NcCifsShareAcl
-VserverContext $Remote_Vserver)
}else{
Wr "Setting ACL for $UserOrGroup
on share $ShareName ..." GREEN
[Void]($ACL | Set-NcCifsShareAcl
-VserverContext $Remote_Vserver)
}
}
## ===== REMOVE
ADDITIONAL ACLs ON THE REMOTE SHARE ===== ##
Foreach($ACL in ($ACLs.$Remote_Vserver |
Where { $_.Share -eq $ShareName }) ){
[String]$UserOrGroup = $ACL.UserOrGroup
If( !($ACLs.$Source_Vserver | Where {
($_.Share -eq $ShareName) -and ($_.UserOrGroup -eq $UserOrGroup) } ) ){
Wr "ACL for $UserOrGroup on share
$ShareName does not exist on source - removing!" RED
[Void]($ACL | Remove-NcCifsShareAcl)
}
}
}
## ===== REMOVE
ADDITIONAL SHARES ON THE REMOTE VOLUME ===== ##
Foreach($Share in $RemSharesOnVol){
[String]$ShareName = $Share.ShareName
If( !($SrcSharesOnVol | Where { $_.ShareName
-eq $ShareName }) ){
Wr "Share $ShareName does not exist
on the $Source_Vserver - removing!" RED
[Void](Remove-NcCifsShare -Name
$ShareName -VserverContext $Remote_Vserver -Confirm:$FALSE)
}
}
}
## ===== MAIN PROGRAM: CYCLE THROUGH THE SNAPMIRRORED VOLUMES
===== ##
Foreach($SM
in $GetNcSnapMirror){
$SourceVol
= $Vols.$Source_Vserver | where { $_.Name -eq $SM.SourceVolume }
$RemoteVol
= $Vols.$Remote_Vserver | where { $_.Name -eq $SM.DestinationVolume }
[String]$SrcVolName = $SourceVol.Name
[String]$RemVolName = $RemoteVol.Name
[Void](Sync-NcSharesOnVolumeDpPair);Wr
}
Comments
Post a Comment