Saturday, 25 October 2014

List 0/10 of Out-of-the-Box Entities in WFA 2.2 focusing on Clustered ONTAP

The following 10 posts list Out-of-the-Box Entities in OnCommand Workflow Automation 2.2. This is focused on Clustered ONTAP.

47 items

18 items

85 items

93 items

37 items

39 items

4 items

10 items

4 items

33 items

List 1/10 of Out-of-the-Box Workflows in WFA 2.2 for Clustered ONTAP

Below is a list of Out-of-the-Box Workflows from -
WFA > Designer > Workflows
- filtered under the CDOT Scheme (cm_storage)

“A scheme is a collection of dictionary entries”

Image: WFA > Designer > Workflows (Filtered by ‘cm_storage’)

The List of 47 Items

Abort SnapMirror
Add or expand capacity storage class to Infinite Volume
Add or expand performance storage class to Infinite Volume
Break SnapMirror
CIFS/SMB Server Configuration
Controller and shelf upgrade of a HA pair
Create a basic Clustered Data ONTAP Volume
Create a Clustered Data ONTAP NFS Volume
Create a Clustered Data ONTAP Qtree CIFS Share
Create a Clustered Data ONTAP Volume
Create a Clustered Data ONTAP Volume CIFS Share
Create a Clustered Data ONTAP Volume with QoS Policy Group
Create a Cron Schedule
Create and configure a Storage Virtual Machine with Infinite Volume
Create and configure a SAN Storage Virtual Machine
Create Clustered Data ONTAP SnapMirror Relationship on 8.1.x
Create Schedules and Policies
Create SnapMirror
Create SnapMirror policy and rules
Create SnapMirror then SnapMirror cascade
Create SnapMirror then SnapVault cascade
Create SnapVault
Create SnapVault then SnapMirror cascade
Create VMware NFS Datastore on Clustered Data ONTAP Storage
Create, map and protect Clustered Data ONTAP LUNs with SnapMirror
Establish Cluster Peering
Expand and Infinite Volume without storage classes
Modify SnapMirror
Move a Clustered Data ONTAP Volume
Multiprotocol File Access
Multiprotocol Server Configuration
NFSv3 Server Configuration
Protect volume with SnapMirror
Protect volume with SnapVault
Quiesce SnapMirror
Remove a Clustered Data ONTAP Volume
Remove SnapMirror
Resume SnapMirror
Resync SnapMirror
Reverse Resync SnapMirror
Sample workflow with find charts
Setup data protection for an Infinite Volume
SMB File Access
Storage Virtual Machine Peering
Storage Virtual Machine Root Volume Promotion
Storage Virtual Machine Root Volume Protection
Transfer SnapMirror

List 2/10 of Out-of-the-Box Finders in WFA 2.2 for Clustered ONTAP

Below is a list of Out-of-the-Box Finders from -
WFA > Designer > Finders
- filtered under the CDOT Scheme (cm_storage)

“A finder is a combination of one or more filters that are used together to identify common results.”

Image: WFA > Designer > Finders (Filtered by ‘cm_storage’)

The List of 18 Items

Find aggregate by available capacity
Find aggregate by space, thresholds and RAID type
Find aggregate for SnapMirror destination volume
Find aggregate for SnapVault destination volume
Find aggregates by class of storage
Find clone volumes by parent volume
Find infinite volume constituents by role
Find infinite volume data constituents with no SnapMirror relationship
Find logical interfaces by current node and role
Find logical interfaces by home node and role
Find NAS logical interfaces by current node
Find NAS logical interfaces by home node
Find nodes of a cluster
Find SAN logical interfaces by home node
Find Storage Virtual Machine by key, type, protocol, service and state
Find Storage Virtual Machine in a given cluster
Find volume by name in a given Storage Virtual Machine
Find volumes by node excluding node root volumes

List 3/10 of Out-of-the-Box Filters in WFA 2.2 for Clustered ONTAP

Below is a list of Out-of-the-Box Filters from -
WFA > Designer > Filters
- filtered under the CDOT Scheme (cm_storage)

“A WFA filter is an SQL-based query that works on the WFA database.”

Image: WFA > Designer > Filters (Filtered by ‘cm_storage’)

The List of 85 Items

Filter aggregates based on effective Clustered Data ONTAP version
Filter aggregates based on ONTAP version
Filter aggregates by a given overcommitment threshold
Filter aggregates by available capacity
Filter aggregates by available capacity in all clusters
Filter aggregates by block type
Filter aggregates by cluster and name
Filter aggregates by delegation to Storage Virtual Machine
Filter aggregates by disk type
Filter aggregates by FlashPool attribute
Filter aggregates by key
Filter aggregates by license in cluster
Filter aggregates by node
Filter aggregates by RAID type
Filter aggregates by state as online
Filter aggregates by supported models for infinite volume constituents
Filter aggregates by used space %
Filter aggregates excluding root aggregates
Filter aggregates excluding the specified aggregate
Filter aggregates excluding the specified cluster
Filter aggregates excluding the specified node
Filter aggregates in a resource group in a specified OCUM excluding aggr0
Filter aggregates in a resource pool
Filter aggregates not aggr0
Filter clone volumes by parent volume
Filter clusters by key
Filter clusters by license
Filter clusters by node count
Filter cron schedules by attributes
Filter efficiency policies by attributes
Filter export policies by key
Filter export policies by Storage Virtual Machine
Filter export policies by volume
Filter export policies that have a default CIFS rule
Filter export rules by export policy
Filter export rules that are default CIFS rules
Filter FCP adapters by online status
Filter igroups by name
Filter infinite volumes by Storage Virtual Machine
Filter infinite volumes by Storage Virtual Machine with class details
Filter infinite volume constituents by constituents role
Filter infinite volume data constituents by no SnapMirror relationship
Filter logical interfaces by current node
Filter logical interfaces by home node
Filter logical interfaces by protocol
Filter logical interfaces by role
Filter logical interfaces by Storage Virtual Machine
Filter LUNs by key
Filter NAS logical interfaces by current node
Filter NAS logical interfaces by home node
Filter nodes by cluster
Filter nodes by name
Filter nodes by no constituents of infinite volumes
Filter ports by cluster, node and name
Filter ports by role
Filter portsets by name
Filter portsets by protocol
Filter QoS policy group by key
Filter SAN logical interfaces by home node
Filter schedules by key
Filter schedules by type
Filter secondary infinite volumes by primary volume
Filter SnapMirror policies by name
Filter SnapMirror policies by relationship type
Filter SnapMirror policy rule by key
Filter SnapMirror policy rules by policy name
Filter SnapMirror policy rules by Storage Virtual Machine
Filter SnapMirror relationship by destination volume
Filter SnapMirror relationships by relationship state
Filter snapshot policies by name
Filter snapshot policy schedule by key
Filter Storage Virtual Machines by key
Filter Storage Virtual Machines by protocol
Filter Storage Virtual Machines by state
Filter Storage Virtual Machines by Storage Virtual Machine type
Filter volumes by key
Filter volumes by name and numeric suffix in a specified Storage Virtual Machine
Filter volumes by node excluding node root volumes
Filter volumes by state
Filter volumes not root volume of Storage Virtual Machine
Filter volumes not SnapMirror destination
Get all aggregates with node details and disk type
Get all aggregates with node priority and volume count
Get all clusters
Get all the nodes

List 4/10 of Out-of-the-Box Commands in WFA 2.2 for Clustered ONTAP

Below is a list of Out-of-the-Box Commands from -
WFA > Designer > Commands
- filtered under the CDOT Scheme (cm_storage)

“A WFA command is initiated by WFA while the workflow is in its execution phase.”

Image: WFA > Designer > Commands (Filtered by ‘cm_storage’)
The List of 93 Items

Abort SnapMirror
Add CIFS share ACL
Add logical interface to portset
Add route to logical interface
Add rule to SnapMirror policy
Add rule to SnapMirror policy - Perl
Add schedule to snapshot policy
Bind igroup to portset
Break SnapMirror
Clone volume
Create aggregate
Create and configure Storage Virtual Machine
Create CIFS share
Create cluster peer
Create efficiency policy
Create export policy
Create export rule
Create FCP logical interface
Create igroup
Create infinite volume
Create infinite volume constituents
Create logical interface
Create LUN
Create portset
Create QoS policy group
Create qtree
Create schedule
Create schedule - Perl
Create SnapMirror
Create SnapMirror policy
Create SnapMirror policy - Perl
Create snapshot policy
Create snapshot policy - legacy
Create Storage Virtual Machine peer
Create volume
Delegate Storage Virtual Machine administration
Delete Active Directory account
Invoke AutoSupport
Log EMS entry
Map LUN
Map unix and windows user names
Migrate logical interface
Modify High-Availability configuration
Modify infinite volume
Modify logical interface
Modify LUN
Modify QoS policy group
Modify schedule
Modify SnapMirror
Modify storage failover
Modify Storage Virtual Machine
Modify volume
Mount volume
Move volume
No-Op Cluster-Mode
Quiesce SnapMirror
Release SnapMirror
Relocate aggregate
Remove CIFS share ACL
Remove igroup
Remove logical interface
Remove logical interface from portset
Remove LUN
Remove node from cluster
Remove QoS policy group
Remove qtree
Remove SnapMirror
Remove SnapMirror - Perl
Remove volume
Rename volume
Resize volume
Resume SnapMirror
Resync SnapMirror
Setup Active Directory account
Setup deduplication and compression
Setup FCP service
Setup iSCSI service
Setup LDAP service
Setup NFS service
Setup NIS service
SnapMirror initialize or update set
SnapMirror promote
Split volume clone
Transfer cluster epsilon
Transfer SnapMirror
Unmap LUN
Wait for aggregate online
Wait for aggregate relocation
Wait for multiple volume moves
Wait for SnapMirror initialization
Wait for SnapMirror initialize load sharing set
Wait for volume clone split
Wait for volume move

List 5/10 of Out-of-the-Box Dictionary Entries in WFA 2.2 for Clustered ONTAP

Below is a list of Out-of-the-Box Dictionary Entries from -
WFA > Designer > Dictionary
- filtered under the CDOT Scheme (cm_storage)

“Dictionary entries are one of the OnCommand Workflow Automation (WFA) building blocks. You can use dictionary entries to represent object types and their relationships in your storage and storage-related environments.”

Image: WFA > Designer > Dictionary (Filtered by ‘cm_storage’)

The List of 37 Items

Aggregate
CIFS_Share
CIFS_Share_ACL
Cluster
Cluster_License
Disk
Disk_Aggregate
Efficiency_Policy
Export_Policy
Export_Rule
FCP_Adapter
Igroup
Logical_Interface
LUN
LUNMap
Node
Port
Portset
Portset_Member
QoS_Policy_Group
Qtree
Quota_Policy
Quota_Rule
Resource_Group
Resource_Group_Member
Resource_Pool
Resource_Pool_Member
Schedule
SnapMirror
Snapmirror_Policy
Snapmirror_Policy_Rule
Snapshot_Policy
Snapshot_Policy_Schedule
Volume
Vserver
Vserver_Allowed_Aggregate
Vserver_Association

List 6/10 of Out-of-the-Box Functions in WFA 2.2

Below is a list of Out-of-the-Box Functions from -
WFA > Designer > Functions
Note: This cannot be filtered under the CDOT Scheme (cm_storage)

“You can use a function in your workflows for a complex task that has to be completed during the planning phase of the workflow.”

Image: WFA > Designer > Functions

The List of 39 Items

actualVolumeSize
calculateSnapReserveSize
calculateVolumeSizeFromDataSize
calculateVolumeTargetFreeSpace
compareOntapVersion
convertNullToValue
convertNullToZero
extractConstituentNameSuffix
fullQtreePathName
getColumnValues
getDataConstituentSizeIncrement
getIgroupOSTTypeFromLunOSType
getMaximumVolumeSize
getNameSpaceConstituentTargetSize
getNumberOfDataConstituents
getQtreeFromPath
getSize
getTotalDataConstituentsSizeFromAggregate
getValueAt
getValueAt2D
getValueAt2DWithDefault
getValueFrom2DByRowKey
getValueIfEnabled
isElementPresent
listSize
minimumSize
nextIP
nextIPByIncrement
nextName
nextNamePadded
nextNamePaddedBy
NextObjectNameWithSuffix
padNumber
replaceFirst
returnNullOnEmpty
roundRobinNextIP
splitByDelimiter
toLower
toUpper

List 7/10 of Out-of-the-Box Templates in WFA 2.2 for Clustered ONTAP

Below is a list of Out-of-the-Box Templates from -
WFA > Designer > Templates
- filtered under the CDOT Scheme (cm_storage)

“A WFA template acts as a blueprint of an object definition.”

Image: WFA > Designer > Templates (Filtered by ‘cm_storage’)

The List of 4 Items

Space Efficient NAS Settings
Space Efficient Settings for NFS DataStores
Space Guaranteed Settings
Space Settings for SAN

List 8/10 of Out-of-the-Box Categories in WFA 2.2

Below is a list of Out-of-the-Box Categories from -
WFA > Designer > Categories
Note: This cannot be filtered under the CDOT Scheme (cm_storage)

“You can categorize your workflows to better organize the workflows and to apply access control capability on the workflows.”

Image: WFA > Designer > Categories
The List of 10 Items (with Clustered Data ONTAP workflows in the brackets)

Application Provisioning (0)
Content Repository (5)
Data Protection (20)
Decommissioning (1)
Getting Started (1)
Migration (2)
Miscellaneous (0)
Setup (7)
Storage Provisioning (9)
Virtualization (1)

List 9/10 of Out-of-the-Box Data Source Types in WFA 2.2 for Clustered ONTAP

Below is a list of Out-of-the-Box Data Source Types from -
WFA > Designer > Data Source Types
- filtered under the CDOT Scheme (cm_storage)

“A data source is a read-only data structure that serves as a connection to the data source object of specific data source type.”

Image: WFA > Designer > Data Source Types
The List of 4 Items

OnCommand Unified Manager 5.1.X for Clustered Data ONTAP
OnCommand Unified Manager 5.2.X for Clustered Data ONTAP
OnCommand Unified Manager 6.0
OnCommand Unified Manager 6.1

List 10/10 of Out-of-the-Box Cache Queries in WFA 2.2 for Clustered ONTAP and OnCommand Unified Manager 6.1

Below is a list of Out-of-the-Box Cache Queries from -
WFA > Designer > Cache Queries
- filtered under the CDOT Scheme (cm_storage)
- and filtered by Data Provider Types OnCommand Unified Manager_6.1

“WFA caches information through various data sources.”

Image: WFA > Designer > Cache Queries (Filtered by ‘OnCommand Unified Manager_6.1’ and also by ‘cm_storage’)

The List of 33 Items

Aggregate
CIFS_Share
CIFS_Share_ACL
Cluster
Cluster_License
Disk
Disk_Aggregate
Efficiency_Policy
Export_Policy
Export_Rule
FCP_Adapter
Igroup
LUN
LUNMap
Logical_Interface
Node
Port
Portset
Portset_Member
QoS_Policy_Group
Qtree
Resource_Pool
Resource_Pool_Member
Schedule
SnapMirror
SnapMirror_Policy
SnapMirror_Policy_Rule
Snapshot_Policy
Snapshot_Policy_Schedule
Volume
Vserver
Vserver_Allowed_Aggregate
Vserver_Associate

WFA: Backup.ps1 “Invalid Credentials Specified, Cannot take a Backup”

On a newly installed OnCommand Workflow Automation 2.2 box, I was setting up scheduled backups of the database using the provided Backup.ps1, but was encountering difficulties:

PS D:\Program Files\NetApp\WFA\bin>
.\Backup.ps1 -User backup -Password backup

Invalid credentials specified, cannot take a backup!

Note: By default WFA takes daily backup at 2 am, and retains the latest 2 in the {INSTALL_DRIVE}:\Program Files\NetApp\WFA-Backups.

I knew the credentials were definitely correct as could log into - http://localhost/rest/backups - with the same credentials and download the backup file with no issue. Also, I’d used this process before when upgrading from WFA 2.2RC1 to WFA 2.2 GA and it had worked fine, so maybe something changed in the WFA 2.2 GA release!?

After a while scratching my head ... I was looking at the Backup.ps1 script, and it occurred to me that we can do this in another way with PowerShell 3’s Invoke-WebRequest (Windows 2012+ come with PowerShell 3 pre-installed.)

Backup-WFA.ps1

We’re going to supply the username, password, and backup location in the script, for ease of getting the script setup on an Enterprise Scheduled Task Management system (backup can only do backup anyway!) Also, we know we’re using the default port 80 for HTTP and the backup folder already exists - which makes our script super simple! Copy the content below into a text editor and save as say Backup-WFA.ps1 in the WFA\bin folder.

## START COPYING HERE ##

# Handle credentials
$User = "backup"
$Pass = "backup"
$SecP = $Pass | ConvertTo-SecureString  -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PsCredential($User,$SecP)

# Handle Backup Folder, File and Path
$Folder   = "D:\Backups\"
$File     = "wfa_backup." + (Get-Date -Format "yyyyMMddHHmmss") + ".sql.gz"
$FilePath = $Folder + $File

# Invoke-WebRequest
[Void](Invoke-WebRequest -Uri http://localhost/rest/backups -OutFile $FilePath -Credential $Cred)

## STOP COPYING HERE ##

Note: Backup.ps1 also uses System.Management.Automation.PsCredential

The Proof that the Backups Work!

After running a backup using Backup-WFA.ps1:

PS D:\Program Files\NetApp\WFA\bin>
.\Backup-WFA.ps1

We login to http://localhost/wfa/ > Administration > Backup & Restore

Image: WFA > Backup & Restore

Browse to our newly backed up WFA database file, and hit the Restore button. If all is good we are greeted with “Successfully restored WFA’s database”!

Image: Successfully restoring the WFA database
Running Backup-WFA.ps1 from the Command Prompt

Before getting this to run as a scheduled task, we first check this will run via the DOS Command Prompt:

C:\Users\Administrator>
powershell.exe -File "D:\Program Files\NetApp\WFA\bin\Backup-WFA.ps1" -ExecutionPolicy Bypass

Running Backup-WFA.ps1 from Task Scheduler

Pretty much as above, with:

Program/script =
powershell.exe

Arguments =
-File "D:\Program Files\NetApp\WFA\bin\Backup-WFA.ps1" -ExecutionPolicy Bypass

Image: Task Scheduler Action to run Backup-WFA.ps1
And test it runs!

THE END

Sunday, 19 October 2014

Why Workflow Automation is Essential!

The final post in the X4 Series! In this series we’ve developed PowerShell scripts to do all the below:

To complete the package we’d need a set of scripts to automate DR Testing (failover/failback), and invoke/recover from actual DR. When you start to plan the DR scripts by stringing elements together, you start to realise that - no matter how much fun PowerShell is ... - being able to pick from a catalogue of commands and smaller workflows will help massively, and any custom functionality we want that’s not available out the box, we can use our PowerShell skills (or Perl, or ...) to add it to the command set.

And this brings us to why NetApp OnCommand Workflow Automation is an Essential Tool for being able to efficiently manage your environment. As an example DR workflow, I’ve quickly strung together the following flow charts for a DR Test Failover/Failback. Achieving this in PowerShell would be no mean feat - WFA is there is make life easier, so let’s use it!

Example DR Test Failover/Failback Flow Charts

Flow Chart: Stage 1 - Prepare for DR Test

Flow Chart: Stage 2 - DR Test Failover
Flow Chart: Stage 3 - Prepare for DR Test Failback
Flow Chart: Stage 4 - DR Test Failback

Synchronizing Quotas - Part 3/3: Quotas-Recover.ps1

Note: Did this in a bit of a rush...

########################
## Quotas-Recover.ps1 ##
########################

Param($User,$Pass,$Cluster,$SVM,[Switch]$Demo)
Import-Module DataONTAP

"";"<<<<< Quotas-Recover.ps1 >>>>>";""
"The script is designed to restore Quota Policy Rule information from special hidden CIFS shares and their comments field, in a DR situation. For simplification, it is assumed that the VOLUMES and CIFS shares are synched perfectly (i.e. no additional QUOTA.RULE.* shares on DR that should have been deleted!)";""

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)
If(!$Cluster){$Cluster = Read-Host ">>> Enter DR Cluster "}
If(!$SVM){$SVM = Read-Host ">>> Enter DR SVM "}

"";"STEP 1: CONNECTING TO DR CLUSTER $Cluster AND FOCUSING ON THE DR SVM $SVM <<<"
[Void](Connect-NcController -Name $Cluster -Credential $Cred)
$Global:CurrentNcController.Vserver = $SVM

"";"STEP 2: GET THE QUOTA.RULE.* SHARES"
$Shares = Get-NcCifsShare -ShareName "QUOTA.RULE.*"

"";"STEP 3: EXTRACT VOLUMES FOR QUOTA ON"
$QRules_V = @{}
$QRules_V_Q = @{}
Foreach ($Share in $Shares){
$ShareName = $Share.ShareName
$ShareNameSplit = $ShareName.Split(".")
$VolName = $ShareNameSplit[2]
$QRules_V.$VolName = "on"
$QRules_V_Q.$VolName = @{}
}

"";"STEP 4: EXTRACT QTREES WITH DISK LIMITS"
Foreach ($Share in $Shares){
$ShareComment = $Share.Comment
$ShareName = $Share.ShareName
$ShareNameSplit = $ShareName.Split(".")
$SplitCount = $ShareNameSplit.Count
$VolName = $ShareNameSplit[2]
$QtreeName = $ShareNameSplit[3]
If ($SplitCount -eq 5){
$QRules_V_Q.$VolName.$QtreeName = $ShareComment
}     
}

"";"STEP 5: GET THE APPLIED QUOTA POLICY"
$SVM_Attrs = Get-NcVserver -Template
$SVM_Attrs.QuotaPolicy = ""
$Quota_Pol = (Get-NcVserver -Attributes $SVM_Attrs).QuotaPolicy

"";"STEP 6: CYCLE THROUGH VOLUMES, SETTING DISK-LIMITS ON QTREES, THEN TURNING QUOTA ON"
$DiskLimitRules = @{}

Foreach ($VolName in $QRules_V.Keys){
$DiskLimitRules.$VolName = 0

Foreach ($QtreeName in $QRules_V_Q.$VolName.Keys){
$DiskLimit = $QRules_V_Q.$VolName.$QtreeName
Write-Host "Adding Quota Rule to /vol/$VolName/$QtreeName with Disk Limit of $DiskLimit" -ForegroundColor Red
If(!$DEMO){Add-NcQuota -Path "/vol/$VolName/$QtreeName" -DiskLimit $DiskLimit -Policy $Quota_Pol}
$DiskLimitRules.$VolName ++
}

If($DiskLimitRules.$VolName -ne 0){
Write-Host "Enabling Quota on $VolName" -ForegroundColor Red
If(!$DEMO){Enable-NcQuota -Volume $VolName}

} else {
Write-Host "Volume $VolName has only tracking rules, we'll turn the quota on in STEP 6!" -ForegroundColor Red
}
}

"";"STEP 7: CYCLE THROUGH VOLUMES, SETTING SOFT-DISK LIMITS ON QTREES (without DISK-LIMITS), THEN RUNNING QUOTA RESIZE"
$VOL_Attrs = Get-NcVol -Template
Initialize-NcObjectProperty -object $VOL_Attrs -name VolumeSpaceAttributes
$VOL_Attrs.VolumeSpaceAttributes.Size = ""
$QTREE_Attrs = Get-NcQtree -Template
$QTREE_Attrs.Qtree = ""

Foreach ($VolName in $QRules_V.Keys){
$VOL_Size = (Get-NcVol -Volume $VolName -Attributes $VOL_Attrs -Vserver $SVM).TotalSize
$SoftDiskLimitSetting = $VOL_Size*4
$QTREE_List = (Get-NcQtree -Attributes $QTREE_Attrs -Volume $VolName -Vserver $SVM).Qtree

Foreach ($QtreeName in $QTREE_List){

If($QtreeName){

If(!$QRules_V_Q.$VolName.$QtreeName){
Write-Host "Enabling tracking quota on /vol/$VolName/$QtreeName" -ForegroundColor Red
If(!$DEMO){Add-NcQuota -Path "/vol/$VolName/$QtreeName" -SoftDiskLimit $SoftDiskLimitSetting -Policy $Quota_Pol}         
}
}
}            

If($DiskLimitRules.$VolName -ne 0){ Write-Host "Resizing Quota on $VolName" -ForegroundColor Red }
else { Write-Host "Enabling Quota on $VolName" -ForegroundColor Red }

If(!$DEMO -and ($DiskLimitRules.$VolName -ne 0)){
$JobStarted = $False

While(!$JobStarted){
$JobStarted = Start-NcQuotaResize -Volume $VolName -ErrorAction SilentlyContinue

If(!$JobStarted){
Write-Host "Resizing Quota Job Failed to Start - waiting 10 seconds!" -ForegroundColor Red
Sleep 10
}
}
}

If(!$DEMO -and ($DiskLimitRules.$VolName -eq 0)){
Enable-NcQuota -Volume $VolName
}
}

## THE END ##

Synchronizing Quotas - Part 2/3: Quotas-Acquire.ps1

Note: Did this in a bit of a rush...

########################
## Quotas-Acquire.ps1 ##
########################

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

"";"<<<<< Quotas-Acquire.ps1 >>>>>";""
"The script is designed to store Quota Policy Rule information in special hidden CIFS shares and their comments field.";""

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)
If(!$Cluster){$Cluster = Read-Host ">>> Enter Source Cluster "}
If(!$SVM)    {$SVM     = Read-Host ">>> Enter Source SVM "}

"";"STEP 1: CONNECTING TO SOURCE CLUSTER $Cluster AND FOCUSING ON SVM $SVM <<<"
[Void](Connect-NcController -Name $Cluster -Credential $Cred)
$Global:CurrentNcController.Vserver = $SVM

"";"STEP 2: GET THE APPLIED QUOTA POLICY"
$SVM_Attrs = Get-NcVserver -Template
$SVM_Attrs.QuotaPolicy = ""
$Quota_Pol = (Get-NcVserver -Attributes $SVM_Attrs).QuotaPolicy

"";"STEP 3: GET THE LIST OF VOLUMES WITH QUOTA ENABLED (ON)"
$QUOTA_Status_Attrs = Get-NcQuotaStatus -Template
$QUOTA_Status_Attrs.Volume = ""
$QUOTA_Status_Query = Get-NcQuotaStatus -Template
$QUOTA_Status_Query.Status = "on"
$QUOTA_On_Vols = (Get-NcQuotaStatus -Attributes $QUOTA_Status_Attrs -Query $QUOTA_Status_Query).Volume
$QUOTA_Vols = @{}
$QUOTA_On_Vols | foreach { $QUOTA_Vols.$_ = $true }

"";"STEP 4: GET THE VOLUME SIZES (for Tracking Quotas)"
$VOL_Attrs = Get-NcVol -Template
Initialize-NcObjectProperty -object $VOL_Attrs -name VolumeSpaceAttributes
$VOL_Attrs.VolumeSpaceAttributes.Size = ""
$VOL_Sizes = Get-NcVol -Attributes $VOL_Attrs -Vserver $SVM
$VOL_Size = @{}
$VOL_Sizes | foreach { $VOL_Size.($_.Name) = $_.TotalSize }

"";"STEP 5: GET THE QUOTA POLICY RULES PER VOLUME PER QTREE (Belonging to the Active Policy)"
$QUOTA_Query = Get-NcQuota -Template
$QUOTA_Query.Policy = $Quota_Pol
$QUOTA_Query.Vserver = $SVM
$QUOTA_Rules = Get-NcQuota -Query $Quota_Query
$VOL_Attrs = Get-NcVol -Template
$VOL_List = (Get-NcVol -Attributes $VOL_Attrs -Vserver $SVM).Name
$VOL_Hash = @{} # HASH gives true for .VolName is VolName exists!
$QTREE_Attrs = Get-NcQtree -Template
$QTREE_Attrs.Qtree = ""
$QTREE_V_Q = @{} # HASH gives true for .VolName.Qtree if Qtree exists!
$QUOTA_V_Q = @{} # HASH gives Disk Limit for .VolName.Qtree if it exists or null!

Foreach ($VolName in $VOL_List) {
$VOL_Hash.$VolName = $true
$QTREE_V_Q.$VolName = @{}
$QUOTA_V_Q.$VolName = @{}
$QTREE_List = (Get-NcQtree -Attributes $QTREE_Attrs -Volume $VolName -Vserver $SVM).Qtree

Foreach ($QtreeName in $QTREE_List){

If ($QtreeName){
$QTREE_V_Q.$VolName.$QtreeName = $true
$QUOTA_V_Q.$VolName.$QtreeName = $null
}
}
}

Foreach ($QUOTA_Rule in $QUOTA_Rules){
$VolName = $QUOTA_Rule.Volume
$QtreeName = (($QUOTA_Rule.QuotaTarget).Split("/"))[3]
# Get-NcQuota returns the Qtree in the QuotaTarget fields as /vol/VOLNAME/QTREENAME, even if the volume is mounted to /. So the split is always on 3 as in 0/1/2/3. It does not return the Qtree in .Qtree! #
$DiskLimit = $QUOTA_Rule.DiskLimit
If ($QtreeName){ $QUOTA_V_Q.$VolName.$QtreeName = $DiskLimit }
# A tracking quota with no defined DiskLimit gives $DiskLimit -eq "-" #
}

"";"STEP 6: CHECK EXISTING QUOTA.RULE.* SHARES"
$Shares = Get-NcCifsShare -ShareName "QUOTA.RULE.*"
$QR_Shares_V = @{} # HASH records if volumes already have a share
$QR_Shares_V_Q = @{} # HASH records if qtrees already have a share
$VOL_List | foreach { $QR_Shares_V_Q.$_ = @{} }

Foreach ($Share in $Shares){
$ShareName = $Share.ShareName
$ShareNameSplit = $ShareName.Split(".")
$SplitCount = $ShareNameSplit.Count
$VolName = $ShareNameSplit[2]
$QtreeName = $ShareNameSplit[3]

If (!$ShareName.EndsWith(".$")){
Write-Host "Invalid Quota Rule share - $ShareName (does not end with .$) - removing!" -ForegroundColor Red
Remove-NcCifsShare $ShareName -Confirm:$false  

} elseif(!$VolName){
Write-Host "Invalid Quota Rule share - $ShareName - removing!" -ForegroundColor Red
Remove-NcCifsShare $ShareName -Confirm:$false

} elseif (!$VOL_Hash.$VolName){
Write-Host "Invalid Quota Rule share - $ShareName ($VolName does not exist) - removing!" -ForegroundColor Red
Remove-NcCifsShare $ShareName -Confirm:$false

} elseif (!$QUOTA_Vols.$VolName){
Write-Host "Invalid Quota Rule share - $ShareName ($VolName Quota off) - removing!" -ForegroundColor Red
Remove-NcCifsShare $ShareName -Confirm:$false         

} elseif ($SplitCount -eq 5){

If (!$QTREE_V_Q.$VolName.$QtreeName){
Write-Host "Invalid Quota Rule share - $ShareName ($QtreeName does exist) - removing!" -ForegroundColor Red
Remove-NcCifsShare $ShareName -Confirm:$false

} elseif (!$QUOTA_V_Q.$VolName.$QtreeName -or ($QUOTA_V_Q.$VolName.$QtreeName -eq "-")) {
Write-Host "Invalid Quota Rule share - $ShareName ($QtreeName has a tracking quota) - removing!" -ForegroundColor Red
Remove-NcCifsShare $ShareName -Confirm:$false                

} else {
$QR_Shares_V_Q.$VolName.$QtreeName = $true
}

} else {
$QR_Shares_V.$VolName = $true
}
}

"";"STEP 7: CREATE/SET QUOTA.RULE.* SHARES"
$VOL_Attrs = Get-NcVol -Template
Initialize-NcObjectProperty -object $VOL_Attrs -name VolumeIdAttributes
$VOL_Attrs.VolumeIdAttributes.JunctionPath = ""
$SHARE_Prefix = "QUOTA.RULE."
$Resize_Required = @{}

Foreach ($VolName in $QUOTA_On_Vols){
$SHARE = $SHARE_Prefix + $VolName + ".$"
$JunctionPath = (Get-NcVol -Volume $VolName -Attributes $VOL_Attrs -Vserver $SVM).JunctionPath

If ($QR_Shares_V.$VolName){
[Void](Set-NcCifsShare -Name $SHARE -Path $JunctionPath)

} else {
Write-Host "Creating the new CIFS Share $SHARE!" -ForegroundColor Red
Add-NcCifsShare -Name $SHARE -Path $JunctionPath
}

$QTREE_List = (Get-NcQtree -Attributes $QTREE_Attrs -Volume $VolName -Vserver $SVM).Qtree

Foreach ($QtreeName in $QTREE_List){
$SHARE = $SHARE_Prefix + $VolName + "." + $QtreeName + ".$"
$Path = $JunctionPath + "/" + $QtreeName

If ($QtreeName){

If($QR_Shares_V_Q.$VolName.$QtreeName){
[Void](Set-NcCifsShare -Name $SHARE -Path $Path -Comment $QUOTA_V_Q.$VolName.$QtreeName)

} elseif ($QUOTA_V_Q.$VolName.$QtreeName -and ($QUOTA_V_Q.$VolName.$QtreeName -ne "-")) {
Write-Host "Creating the new CIFS Share $SHARE!" -ForegroundColor Red
Add-NcCifsShare -Name $SHARE -Path $Path -Comment $QUOTA_V_Q.$VolName.$QtreeName

} elseif ($QUOTA_V_Q.$VolName.$QtreeName -eq "-") {
$QUOTA_Query.QuotaTarget = "/vol/$VolName/$QtreeName"
$CurrentSoftDiskLimit = (Get-NcQuota -Query $QUOTA_Query).SoftDiskLimit
$SoftDiskLimitSetting = $VOL_Size.$VolName*4

If (([Int64]$CurrentSoftDiskLimit)*1024 -ne $SoftDiskLimitSetting){
[Void](Set-NcQuota -Path "/vol/$VolName/$QtreeName" -SoftDiskLimit $SoftDiskLimitSetting -Policy $Quota_Pol)
$Resize_Required.$VolName = $true
}

} else {
Write-Host "No tracking quota defined, setting on /vol/$VolName/$QtreeName!" -ForegroundColor Red
Add-NcQuota -Path "/vol/$VolName/$QtreeName" -SoftDiskLimit $SoftDiskLimitSetting -Policy $Quota_Pol
$Resize_Required.$VolName = $true
}
}
}
}

"";"STEP 8: RUN QUOTA RESIZE TO APPLY SET/ADD-ed QUOTA RULES APPLIED IN 7"
Foreach ($VolName in $QUOTA_On_Vols){
If ($Resize_Required.$VolName){
Start-NcQuotaResize -Volume $VolName
}
}

## THE END ##