Synchronize-NFS.ps1

Continuing the X4 Series (not an X4 though since for NFS we’re only concerning ourselves with a traditional production and DR setup).
Note: I reckon this is the best Synchronize configuration script in the series so far - check it out!

Introduction

After synchronizing CIFS shares and volume junction paths (mounts) in the previous post, the next thing to do is synchronize the NFS configuration for export policies, export policy rules and NFS exports (export policy applied to a volume or qtree).

Image: SVM to SVM DR Relationship

Creating Export Policy and Rules from ClusterShell

In SVM-CreatorX4.ps1 I’d not created any export policies or rules, so using this KB to make sure I’m not creating rubbish, I’ve created an export policy and rules for VMware, suitable to allow for VAAI over NFS.

vserver export-policy
create -policyname VMWARE1 -vserver NCA1V1
rule create -policyname VMWARE1 -vserver NCA1V1 -ruleindex 1 -protocol nfs -clientmatch 10.10.10.51 -rorule sys -rwrule sys -allow-suid true -allow-dev true -anon 65534 -superuser sys
## Add more rules, e.g. for 10.10.10.52/53/54 ... ##
volume
modify -volume VOL1 -vserver NCA1V1 -policy VMWARE1

And repeat...

The Synchronization Steps

STEP 1: GET SOURCE EXPORT-POLICY INFORMATION
STEP 2: GET SOURCE EXPORT-POLICY RULE INFORMATION (PER POLICY)
STEP 3: GET APPLIED EXPORT POLICY TO SOURCE VOLUMES
STEP 4: GET APPLIED EXPORT POLICY TO SOURCE QTREES (PER VOLUME)
STEP 5: SYNCHRONIZE EXPORT-POLICY INFORMATION
STEP 6: SYNCHRONIZE EXPORT-POLICY RULE INFORMATION
STEP 7: SYNCHRONIZE NFS EXPORTS for VOLUMES
STEP 8: SYNCHRONIZE NFS EXPORTS for QTREES

The Synchronization Script

#########################
## Synchronize-NFS.ps1 ##
#########################

Param($User,$Pass)
Import-Module DataONTAP

"";"<<<<< Synchronize-NFS.ps1 >>>>>";""
"The script is designed to Synchronize the NFS Export Policies and Rules between an SVM and it's DR SVM, e.g:"
"SOURCE_SVM (SRC) --SM--> DESTINATION_SVM (DST)";""

If(!$User){$User = Read-Host ">>> Enter Admin User "}
If(!$Pass){$Pass = Read-Host ">>> Enter Password " -AsSecureString}
else {$Pass = $Pass | ConvertTo-SecureString  -AsPlainText -Force}
$Cred = New-Object System.Management.Automation.PsCredential($User,$Pass)

$SRC_Cluster = "NCA1"
$SRC_SVM     = "NCA1V1"
$DST_Cluster = "NCB1"
$DST_SVM     = "NCB1V1"

"";">>>> CONNECTING TO SOURCE CLUSTER: $SRC_CLUSTER <<<"
[Void](Connect-NcController -Name $SRC_Cluster -Credential $Cred)

"";"STEP 1: GET SOURCE EXPORT-POLICY INFORMATION"
$SRC_ExportPolicies = Get-NcExportPolicy -VserverContext $SRC_SVM

"";"STEP 2: GET SOURCE EXPORT-POLICY RULE INFORMATION (PER POLICY)"
$SRC_ExportRules = @{}
Foreach ($SRC_ExpPol in $SRC_ExportPolicies){
$PolicyName = $SRC_ExpPol.PolicyName
$SRC_ExportRules.$PolicyName = Get-NcExportRule -Policy $PolicyName -VserverContext $SRC_SVM | sort-object RuleIndex
}

"";"STEP 3: GET APPLIED EXPORT POLICY TO SOURCE VOLUMES"
$Vol_Attributes = Get-NcVol -Template
Initialize-NcObjectProperty -object $Vol_Attributes -name VolumeExportAttributes
$Vol_Attributes.VolumeExportAttributes.Policy = ""
$SRC_Volumes = Get-NcVol -Attributes $Vol_Attributes -VserverContext $SRC_SVM

"";"STEP 4: GET APPLIED EXPORT POLICY TO SOURCE QTREES (PER VOLUME)"
$SRC_Qtrees = @{}
Foreach ($SRC_Vol in $SRC_Volumes){
$SRC_VolName = $SRC_Vol.Name
$SRC_Qtrees.$SRC_VolName = Get-NcQtree -Volume $SRC_VolName -VserverContext $SRC_SVM
}

"";">>> CONNECTING TO DESTINATION CLUSTER: $DST_CLUSTER <<<"
[Void](Connect-NcController -Name $DST_Cluster -Credential $Cred)

"";"STEP 5: SYNCHRONIZE EXPORT-POLICY INFORMATION"
$DST_ExportPolicies = Get-NcExportPolicy -VserverContext $DST_SVM

Foreach ($SRC_ExpPol in $SRC_ExportPolicies){
$SRC_ExpPol_Name = $SRC_ExpPol.PolicyName
$MatchFound = $false

Foreach ($DST_ExpPol in $DST_ExportPolicies){
$DST_ExpPol_Name = $DST_ExpPol.PolicyName
If ($SRC_ExpPol_Name -eq $DST_ExpPol_Name){$MatchFound = $true}
}

If (!$MatchFound){
Write-Host "Not found the export policy $SRC_ExpPol_Name on $DST_SVM - creating it!!!" -ForegroundColor Red
New-NcExportPolicy -Name $SRC_ExpPol_Name -VserverContext $DST_SVM
}
}

"";"STEP 6: SYNCHRONIZE EXPORT-POLICY RULE INFORMATION"
$Global:CurrentNcController.Vserver = $DST_SVM

Foreach ($SRC_ExpPol in $SRC_ExportPolicies){
$PolicyName = $SRC_ExpPol.PolicyName
$AnIndexAt = @{}

Foreach ($SRC_Rule in $SRC_ExportRules.$PolicyName){
$SRC_Rule.NcController = $null
$SRC_Rule.VserverName = $null
$SRC_Index = $SRC_Rule.RuleIndex
$AnIndexAt.$SRC_Index = $true
$DST_ExportRule = Get-NcExportRule -Policy $PolicyName -Index $SRC_Index

If(!$DST_ExportRule){
Write-Host "$DST_SVM > Export Policy $PolicyName missing rule at index $SRC_Index - adding new rule!!!" -ForegroundColor Red
If ($SRC_Rule.IsAllowDevIsEnabled -eq "True"){$Dev = " -EnableDev"}else{$Dev = " -DisableDev"}
If ($SRC_Rule.IsAllowSetUidEnabled -eq "True"){$UID = " -EnableSetUid"}else{$UID = " -DisableSetUid"}
$NewRule  = "New-NcExportRule"
$NewRule += " -Policy "                  + $PolicyName
$NewRule += " -Index "                   + $SRC_Index
$NewRule += " -ClientMatch "             + $SRC_Rule.ClientMatch
$NewRule += " -ReadOnlySecurityFlavor "  + $SRC_Rule.RoRule
$NewRule += " -ReadWriteSecurityFlavor " + $SRC_Rule.RwRule
$NewRule += " -Protocol "                + $SRC_Rule.Protocol
$NewRule += " -Anon "                    + $SRC_Rule.AnonymousUserId
$NewRule += " -SuperUserSecurityFlavor " + $SRC_Rule.SuperUserSecurity
$NewRule +=    $DEV
$NewRule +=    $UID
$NewRule += " -NtfsUnixSecurityOps "     + $SRC_Rule.ExportNtfsUnixSecurityOps
$NewRule += " -ChownMode "               + $SRC_Rule.ExportChownMode
Invoke-Expression $NewRule
} else {
$SRC_Rule | Set-NcExportRule
}
}
$DST_ExportRules = Get-NcExportRule -Policy $PolicyName | sort-object RuleIndex

Foreach ($DST_Rule in $DST_ExportRules){
$DST_Index = $DST_Rule.RuleIndex

If (!($AnIndexAt.$DST_Index)){
Write-Host "$DST_SVM > Export Policy $PolicyName contains an rule at index $DST_Index which is not on the source - removing the rule!!!" -ForegroundColor Red
Remove-NcExportRule -Policy $PolicyName -Index $DST_Index -Confirm:$false
}
}
}
$Global:CurrentNcController.Vserver = $null

"";"STEP 7: SYNCHRONIZE NFS EXPORTS for VOLUMES on $DST_SVM"
$Vol_Query = Get-NcVol -Template
Foreach ($SRC_Vol in $SRC_Volumes){
$Vol_Attributes.VolumeExportAttributes.Policy = $SRC_Vol.VolumeExportAttributes.Policy
$Vol_Query.Name = $SRC_Vol.Name
$Vol_Query.Vserver = $DST_SVM
Update-NcVol -Attributes $Vol_Attributes -Query $Vol_Query
}

"";"STEP 8: SYNCHRONIZE NFS EXPORTS for QTREES on $DST_SVM"
Foreach ($SRC_Vol in $SRC_Volumes){
$SRC_VolName = $SRC_Vol.Name
$NeedMirrorBreak = $false

Foreach ($SRC_Qtree in $SRC_Qtrees.$SRC_VolName){

If ($SRC_Qtree.Qtree){
$DST_Qtree = Get-NcQtree -Volume $SRC_VolName -Qtree $SRC_Qtree.Qtree -VserverContext $DST_SVM

If ($DST_Qtree.ExportPolicy -ne $SRC_Qtree.ExportPolicy) {
$NeedMirrorBreak = $true
}
}
}

If($NeedMirrorBreak){
Write-Host "$DST_SVM > Detected qtree export mismatch for volume $SRC_VolName - need to break the snapmirror, set, and resync!!!" -ForegroundColor Red
Invoke-NcSnapMirrorBreak -DestinationVserver $DST_SVM -DestinationVolume $SRC_VolName -Confirm:$false

Foreach ($SRC_Qtree in $SRC_Qtrees.$SRC_VolName){

If ($SRC_Qtree.Qtree){
Set-NcQtree -Volume $SRC_Qtree.Volume -Qtree $SRC_Qtree.Qtree -ExportPolicy $SRC_Qtree.ExportPolicy -VserverContext $DST_SVM
}
}
Invoke-NcSnapMirrorResync -DestinationVserver $DST_SVM -DestinationVolume $SRC_VolName
}
}

## THE END ##

Comments