#requires -version 2.0 function Get-NaAggr { <# .Synopsis Get aggregate status. .Description List of aggregates and their status. .Parameter Aggregate The aggregate to get status for. If not supplied, get status of all aggregates. .Parameter Server NaServer to query .Example Get the status of all aggregates. PS > Get-NaAggr .Example Get the status of aggregate aggr0. PS > Get-NaAggr -name aggr0 .Outputs NetApp.SDK.NaAggr[] .Link Set-NaAggr Remove-NaAggr Rename-NaAggr #> [CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The aggregate to get status for.")] [Alias("Aggregate")] [STRING] $Name, [Parameter(Position=1,HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process{ $request = New-Object Netapp.Manage.NaElement -ArgumentList @("aggr-list-info") $request.AddNewChild("verbose",$TRUE) if ($Name){ $request.AddNewChild("aggregate",$Name) } try { $result = ([xml]$server.InvokeElem($request)).results } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message $result = $null continue; } if ($?){ $result.aggregates."aggr-info" | % { $p = new-object Collections.Hashtable if (!($_.state -eq "creating")){ $_.plexes."plex-Info" | % { $rg = new-object Collections.Hashtable $_."raid-groups"."raid-group-info" |% { $rg.add(($_.Name.split('/')[3]), (New-Object NetApp.SDK.NaRaidGroup -ArgumentList @( "/vol$($_.Name)", (ConvertFrom-NaBool $_.Reconstructing), [array]($_.disks."disk-info"|%{$_.name}), $(if ($_."reconstruction-percentage" -eq $null){0}else{$_."reconstruction-percentage"})) )) } $p.add(($_.name.split('/')[2]), (New-Object NetApp.SDK.NaPlex -ArgumentList @( "/vol$($_.name)", (ConvertFrom-NaBool $_."is-online"), (ConvertFrom-NaBool $_."is-resyncing"), $RG, $(if ($_."resyncing-percentage" -eq $null){0}else{$_."resyncing-percentage"})) )) } } return New-Object NetApp.SDK.NaAggr -ArgumentList @( $_."checksum-status", $_."checksum-style", $_."disk-count", $_."files-total", $_."files-used", (ConvertFrom-NaBool $_."has-local-root"), (ConvertFrom-NaBool $_."has-partner-root"), (ConvertFrom-NaBool $_."is-checksum-enabled"), (ConvertFrom-NaBool $_."is-inconsistent"), (ConvertFrom-NaBool $_."is-snaplock"), $_."mirror-status", $_."name", "/vol/$($_.name)", $_."plex-count", $p, $_."raid-size", $_."raid-status", [int64]$_."size-available", [int64]$_."size-total", [int64]$_."size-used", $_."state", $_."type", $_."uuid", $_."volume-count", [array]($_.volumes."contained-volume-info" | % { $_.name }), $_."size-percentage-used", $_."snaplock-type", $_."volume-count-striped-dv", $_."volume-count-striped-mdv" ) } } } } Function Rename-NaAggr { <# .Synopsis Rename the specified aggregate. .Description Rename the specified aggregate. .Parameter Name Name of the aggregate to rename. .Parameter NewName The new name desired for the aggregate. .Parameter Server NaServer to query .Example # rename aggr0 to aggr1 PS > Rename-NaAggr -Name aggr0 -NewName aggr1 .Example # rename aggr1 to aggr2 PS > Get-NaAggr aggr1 | Rename-NaAggr -NewName aggr2 .Outputs NetApp.SDK.NaAggr[] .Link Get-NaAggr Set-NaAggr Remove-NaAggr #> [CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] param( [Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the aggregate to rename.")] [Alias("Aggregate")] [STRING] $Name, [Parameter(Position=1,Mandatory=$TRUE,HelpMessage="The new name desired for the aggregate.")] [string] $NewName, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) Process{ $request = New-Object Netapp.Manage.NaElement -ArgumentList @("aggr-rename") $request.AddNewChild("aggregate",$name) $request.AddNewChild("new-aggregate-name",$newName) if ($pscmdlet.ShouldProcess($Server.Server,"rename $name to $NewName")){ try { $server.InvokeElem($request)|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } if ($?){ return Get-NaAggr -Name $NewName -Server $server } } } } Function Set-NaAggr { <# .Synopsis Used to Set the State of an aggregate/traditional volume. .Description Used to Set the State of an aggregate/traditional volume. .Parameter Name Name of the aggregate. .Parameter Offline Take the specified aggregate or plex offline. The operation takes effect before the API returns. Except in maintenance mode, the current root aggregate may not be taken offline. An aggregate marked to become the root aggregate cannot be taken offline. An aggregate containing one or more flexible volumes cannot be taken offline; its contained volumes must first be destroyed. A number of operations being performed on the given aggregate can prevent this operation from succeeding, either at all or for various lengths of time. if such operations are found, the system waits up to one second for them to finish. if they don't, the command is aborted. A check is also made for files in the aggregate opened by internal ONTAP processes. The command is aborted if any are found. .Parameter Online Bring the specified aggregate or plex online. This command takes effect immediately. All volumes on the aggregate are brought to whatever state they were in before the aggregate was restricted or taken offline. if there are CIFS shares associated with the any of the aggregate's volumes that were also onlined, they are enabled. .Parameter KeepUUID Keep existing foreign raidtree id (aggregate uuid). Normally when a foreign raidtree is onlined, the raidtree rtid (aggregate uuid) is changed to guarantee uniqueness. The behavior is overridden when this option is specified. .Parameter Restrict Restrict the specified aggregate. If the aggregate is embedded in a traditional volume, the entire traditional volume will be restricted. An aggregate with one or more flexible volumes cannot be restricted; all of its contained volumes must first be destroyed. .Parameter CifsDelay The number of seconds to wait before offlining/restricting any volumes that are hosted in the given aggregate that have active CIFS shares (if any). A value of 0 means that all such volumes are to be offlined/restricted immediately with no warning. CIFS users can lose data if they are not given a chance to terminate applications gracefully. By default, CifsDelay is 0. NOTE: This argument may ONLY appear if the -UnmountVolumes argument is also specified. .Parameter UnmountVolumes This option specifies that all of the volumes hosted by the given aggregate are to be unmounted before the offline/restrict operation is executed. By default, the system will reject any attempt to offline/restrict an aggregate that hosts one or more online volumes. .Parameter Server NaServer to query .Example # Offline aggr1 PS > Set-NaAggr -Name aggr1 -offline .Example # restrict aggr1 forcefully unmounting any existing volumes PS > Set-NaAggr -Name aggr1 -Restrict -UnmountVolumes .Example # Online any restricted/offlined aggregates Get-NaAggr | ? {$_.State -ne "online"} | Set-NaAggr -Online .Outputs NetApp.SDK.NaAggr[] .Link Get-NaAggr Rename-NaAggr Remove-NaAggr #> [CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="online")] param( [Parameter(ParameterSetName="online",Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the Aggregate ")] [Parameter(ParameterSetName="offline",Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the Aggregate ")] [Parameter(ParameterSetName="restrict",Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the Aggregate ")] [Alias("Aggregate")] [string] $name, [Parameter(ParameterSetName="offline")] [switch] $offline, [Parameter(ParameterSetName="online")] [switch] $online, [Parameter(ParameterSetName="online")] [switch] $KeepUUID, [Parameter(ParameterSetName="restrict")] [switch] $Restrict, [Parameter(ParameterSetName="offline",HelpMessage="The number of seconds to wait before offlining/restricting any volumes that are hosted in the given aggregate")] [Parameter(ParameterSetName="restrict",HelpMessage="The number of seconds to wait before offlining/restricting any volumes that are hosted in the given aggregate")] [int] $CifsDelay, [Parameter()] [switch] $unmountVolumes, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) Process{ switch ($PSCmdlet.ParameterSetName){ "online" { $request = New-Object Netapp.Manage.NaElement -ArgumentList @("aggr-online") if ($KeepUUID){ $request.AddNewChild("keep-same-uuid",$TRUE) } $msg = "Online aggregate" } "offline" { $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-offline") if ($unmountVolumes){ $request.AddNewChild("unmount-volumes",$TRUE) if ($CifsDelay){ $request.AddNewChild("cifs-delay-seconds",$CifsDelay) } } $msg = "Offline aggregate" } "Restrict" { $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-restrict") if ($unmountVolumes){ $request.AddNewChild("unmount-volumes",$TRUE) if ($CifsDelay){ $request.AddNewChild("cifs-delay-seconds",$CifsDelay) } } $msg = "Restrict aggregate" } } $request.AddNewChild("aggregate",$Name) if ($pscmdlet.ShouldProcess($Name,$msg)){ try { $server.InvokeElem($request)|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message $result = $null continue; } if ($?){ return Get-NaAggr -Name $Name -server $server } } } } Function Remove-NaAggr { <# .Synopsis Destroys the specified aggregate or plex. .Description Destroys the specified aggregate or plex. If an aggregate is specified, all plexes in the aggregate are destroyed. if the aggregate is embedded in a traditional volume, then the entire traditional volume is destroyed. Otherwise, the operation will be rejected if there are one or more flexible volumes in the aggregate - they must be destroyed beforehand. if a plex is specified, only that plex is destroyed, leaving an unmirrored aggregate containing the remaining plex. The disks in the destroyed object become spare disks. Only offline aggregates and plexes can be destroyed. .Parameter Name Name of the Aggregate to be destroyed. .Parameter Path Name of the existing aggregate or plex to be destroyed, using the following format: [/vol/][] .Parameter Force When using Remove-NaAggr on a traditional volume, force the destruction of the volume even if a non-default vfiler has storage on it. Normally, the system will not destroy such a volume and will instead return EVOLUME_HAS_VFILER_STORAGE. .Parameter Server NaServer to query .Example # Destroy aggr1 PS > Get-NaAggr aggr1 | Remove-NaAggr .Example # destroy plex1 from aggr3 PS > $Aggr = Get-NaAggr aggr3 PS > $Aggr.Plexes.Plex1 | Remove-NaAggr .Example # You can also just type in the path if you know it. PS > Remove-NaAggr -Path "/vol/vol1" -force -whatif .Link Get-NaAggr Set-NaAggr Rename-NaAggr #> [CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="high",DefaultParameterSetName="byname")] param( [Parameter(Position=0,Mandatory=$TRUE,ParameterSetName='byname',HelpMessage="Name of the Aggregate to be destroyed.")] [Alias("Aggragate")] [string] $Name, [Parameter(Mandatory=$TRUE,ParameterSetName='byPath',ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Path of the existing aggregate or plex to be destroyed, use Get-NaAggr to retrieve the path of a known aggr.")] [string] $Path, [Parameter()] [switch] $force, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process{ if ($Name){ $Path = Get-NaAggr -Name $Name -Server $Server | Select-Object -ExpandProperty Path } $request = New-Object Netapp.Manage.NaElement -ArgumentList @("aggr-destroy") $request.AddNewChild("aggregate",$Path) if ($force){ $request.AddNewChild("force",$TRUE) } if ($pscmdlet.ShouldProcess($Server.Server,"Destroying $path")){ try { $server.InvokeElem($request)|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } } } } Function New-NaAggr { <# .Synopsis Add disks to the specified aggregate. .Description Create a new aggregate with the given name. Up to 200 aggregates can be created on each filer (including the aggregates that are "embedded" in traditional volumes, which must be created as a side effect of a traditional volume creation). The aggregate may not yet be operational immediately after the API returns. Use Get-NaAggr to query the status of the newly-created aggregate to determine when it is fully operational. NOTE: if ECANT_USE_ALL_DISKS is returned, then the requested aggregate was indeed created, just not with all the disks that were specified. .Parameter Name Name of the aggregate to create. The aggregate name can contain letters, numbers, and the underscore character(_), but the first character must be a letter or underscore. .Parameter Disk Specific list of disks to use for the new aggregate. If the aggregate is mirrored and a specific list of disks is supplied, another list -MirrorDisks must also be supplied with the same number of disks. .Parameter DiskCount Number of disks to place into the aggregate, including parity disks. The disks in this newly created aggregate come from the spare disk pool. The smallest disks in this pool join the aggregate first, unless the -DiskSize argument is provided. .Parameter DiskSize Disk size in GB. Disks that are within 10% of the specified size will be selected for use in the aggregate. if not specified, existing groups are appended with disks that are the best match for the largest disk in the group. When starting new groups, the smallest disks are selected first. .Parameter DiskType Type of disks to use: ATA, EATA, FCAL, LUN, SAS, SATA, SCSI, XATA, or XSAS. This option is needed only when disks of different types are connected to the filer. An aggregate can never be created using a mix of disks of different types. .Parameter RPM Rotational speed of disks in revolutions per minute. Possible values are: 5400, 7200, 10000, and 15000. This option is needed only when disks with different rotational speeds are connected to the filer. .Parameter LanguageCode Specifies the language to use for the new traditional volume via a language code. The default language is the one used by the filer's root volume. This option may be used only when creating a traditional volume, i.e. when -Traditional Available language codes are: C (POSIX) da (Danish) de (German) en (English) en_US (English (US)) es (Spanish) fi (Finnish) fr (French) he (Hebrew) it (Italian) ja (Japanese euc-j) ja_JP.PCK (Japanese PCK (sjis)) ko (Korean) no (Norwegian) nl (Dutch) pt (Portuguese) sv (Swedish) zh (Simplified Chinese) zh.GBK (Simplified Chinese (GBK)) zh_TW (Traditional Chinese euc-tw) zh_TW.BIG5 (Traditional Chinese Big 5) NOTE: To use UTF-8 as the NFS character set, append '.UTF-8'. .Parameter RaidSize Specifies the maximum number of disks in each RAID group in the aggregate. The maximum value for this parameter is 28. The default value is platform-dependent. The valid range of values is also platform-dependent, but never wider than [2..28]. .Parameter RaidType Specifies the type of RAID groups to use in the new aggregate. Possible values: raid4, raid_dp. The default value is raid4 on most platforms. .Parameter Force Disks in a plex are not normally permitted to span spare pools. This behavior is overridden with this option. .Parameter Mirrored Specifies that the new aggregate be mirrored (have two plexes). If -Mirrored is specified, then the indicated disks will be split across the two plexes. By default, the new aggregate will not be mirrored. .Parameter MirrorDisks Specific list of mirror disks needed to accompany the list in the -Disk parameter. This list must contain the same number of disks as specified in -Disk. To create a list of disk use Get-NaDisk. The following example will select 5 disks from shelf 2 PS > $disks = Get-NaDisk | ? {$_.shelf -eq 2 -and $_.RaidState -eq "spare"} | select -first 5 .Parameter SnapLock Specifies the creation of a SnapLock aggregate. By default, is-snaplock is not specified. When -Snaplock is specified the type of snaplock aggregate is determined in the following way: 1> if -SnapLockType is set, create the type specified in -SnapLockType (see -SnapLockType for more details) 2> Otherwise, create a Snaplock enterprise aggregate if a Snaplock enterprise license has been installed. 3> Otherwise, create a Snaplock compliance aggregate. NOTE: ESERVICENOTLICENSED is returned if the required Snaplock Compliance or Enterprise license is not installed. EONTAPI_EWORMNOCLOCK is returned if SnapLock Compliance Clock is not running. if you need to create a snaplock aggregate, the suggested method is to specify -SnapLockType as "compliance" or "enterprise" and not specify -Snaplock at all. .Parameter SnapLockType Specifies the type of the SnapLock aggregate to be created. Possible values - "compliance" or "enterprise" NOTE: ESERVICENOTLICENSED is returned if the necessary Snaplock compliance or enterprise license has not been installed. EINVALIDINPUT is returned if -SnapLockType has an illegal value. EONTAPI_EWORMNOCLOCK is returned if SnapLock Compliance Clock is not running. .Parameter Server NaServer to query .Example # Create a New Aggregate named aggr1 using four 146GB 15K FCAL disks. PS > New-NaAggr -Name aggr1 -DiskCount 4 -DiskSize 146 -DiskType FCAL -RPM 15000 .Example # Create a New Traditional Volume named Vol0 with a Raid group size of 8, and a raid type of RaidDP. PS > New-NaAggr -Name Vol0 -DiskCount 4 -RaidSize 8 -RaidType raid_dp -Traditional .Example # Create a New aggregate named aggr5 mirrored(two plexes 4disk per plex), and a raid type of RaidDP. PS > New-NaAggr -Name aggr5 -DiskCount 8 -RaidType raid_dp -Mirrored .Example Create a mirrored aggregate named aggr3 using all the disks in shelf 4 for plex0, and plex1 with all the disks from shelf 5. PS > $disks = Get-NaDisk | ? {$_.shelf -eq 4} PS > $Mirrordisk = Get-NaDisk | ? {$_.shelf -eq 5} PS > New-NaAggr -Name aggr3 -Disk $disks -MirrorDisks $Mirrordisk .Outputs NetApp.SDK.NaAggr[] .Link Get-NaAggr Set-NaAggr Rename-NaAggr Remove-NaAggr #> [CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="Diskcount")] param( [Parameter(ParameterSetName="DiskList",Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$true,HelpMessage="Name of the aggregate to create.")] [Parameter(ParameterSetName="Diskcount",Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$true,HelpMessage="Name of the aggregate to create.")] [Alias("Aggregate")] [STRING] $Name, [Parameter(ParameterSetName="DiskList",Mandatory=$TRUE,HelpMessage="Specific list of disks to use for the new aggregate.")] [string[]] $Disk, [Parameter(ParameterSetName="Diskcount",Mandatory=$TRUE,HelpMessage="Number of disks to add, including the parity disks.")] [INT] $DiskCount, [Parameter(ParameterSetName="Diskcount",HelpMessage="The disk size in GB.")] [INT] $DiskSize, [Parameter(ParameterSetName="Diskcount",HelpMessage="Type of disks to use: ATA, EATA, FCAL, LUN, SAS, SATA, SCSI, XATA, or XSAS")] [ValidateSet("ATA", "EATA", "FCAL", "LUN", "SAS", "SATA", "SCSI", "XATA", "XSAS")] [STRING] $DiskType, [Parameter(ParameterSetName="Diskcount",HelpMessage="Rotational speed of disks in revolutions per minute.")] [ValidateSet(5400,7200,10000,15000)] [INT] $Rpm, [Parameter(HelpMessage="Specifies the maximum number of disks in each RAID group in the aggregate.")] [ValidateRange(2, 28)] [INT] $RaidSize, [Parameter(HelpMessage="specifies the type of RAID groups to use in the new aggregate.")] [ValidateSet("raid4","raid_dp")] [STRING] $RaidType, [Parameter(ParameterSetName="DiskList",HelpMessage="Disks in a plex are not normally permitted to span spare pools. This behavior is overridden with this option")] [switch] $Force, [Parameter(HelpMessage="Specifies that the new aggregate be mirrored (have two plexes).")] [switch] $Mirrored, [Parameter(ParameterSetName="DiskList",HelpMessage="List of mirror disks to use.")] [string[]] $MirrorDisks, [Parameter(HelpMessage="Specifies the creation of a SnapLock aggregate.")] [switch] $Snaplock, [Parameter(HelpMessage="Specifies the type of Snaplock aggregate to be created.")] [ValidateSet("compliance","enterprise")] [STRING] $SnaplockType, [Parameter(HelpMessage="Create a traditional volume (aggregate contains exactly one traditional volume)")] [switch] $Traditional, [Parameter(HelpMessage="Specifies the language to use for the new traditional volume via a language code.")] [ValidateSet("C","da","de","en","en_US","es","fi","fr","he","it","ja","ja_JP.PCK","ko","no","nl","pt","sv","zh","zh.GBK","zh_TW","zh_TW.BIG5")] [STRING] $LanguageCode, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) Process{ $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-create") switch ($PSCmdlet.ParameterSetName){ "DiskCount" { $request.AddNewChild("disk-count",$DiskCount) if ($DiskSize){ $request.AddNewChild("disk-size",(($DiskSize * 1gb)/4kb)) } if ($DiskType){ $request.AddNewChild("disk-type",$DiskType) } if ($Rpm) { $request.AddNewChild("rpm",$Rpm) } if ($Mirrored){ $request.AddNewChild("is-mirrored",$TRUE) if ($Force){ $request.AddNewChild("force-spare-pool",$TRUE) } } } "DiskList" { $d = New-Object Netapp.Manage.NaElement("disks") $Disk|%{ $di = New-Object Netapp.Manage.NaElement("disk-info") $di.AddNewChild("name",$_) $d.AddChildElement($di) } $request.AddChildElement($d) if ($MirrorDisks){ $m = New-Object Netapp.Manage.NaElement("mirror-disks") $Disk|%{ $mi = New-Object Netapp.Manage.NaElement("disk-info") $mi.AddNewChild("name",$_) $m.AddChildElement($mi) } $request.AddChildElement($m) $request.AddNewChild("is-mirrored",$TRUE) } } } if ($RaidSize){ $request.AddNewChild("raid-size",$RaidSize) } if ($RaidType){ $request.AddNewChild("raid-type",$RaidType) } if ($SnaplockType){ $request.AddNewChild("snaplock-type",$SnaplockType) } elseif ($Snaplock){ $request.AddNewChild("is-snaplock",$TRUE) } if ($Traditional){ $request.AddNewChild("type","trad") if ($LanguageCode){ $request.AddNewChild("language-code",$LanguageCode) } } else{ $request.AddNewChild("type","aggr") } $request.AddNewChild("aggregate",$name) if ($pscmdlet.ShouldProcess($Server.Server,"Creating new aggregate: $name")){ try { $server.InvokeElem($request)|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } if ($?){ write-output (Get-NaAggr -Name $name -server $server) } } } } function Test-NaSparesLow { <# .Synopsis Return true if there is no suitable spare disk available for any filesystem (parity or data) disk. .Description Return true if there is no suitable spare disk available for any filesystem (parity or data) disk. .Parameter Server NaServer to query .Example PS > Test-NaSparesLow false .Outputs System.Bool .Link Get-NaAggr Set-NaAggr Remove-NaAggr Add-NaDisk #> [CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipeline=$True,HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process { Write-Output (ConvertFrom-NaBool $server.Invoke("aggr-check-spare-low").getchildcontent("is-spare-low")) } } function Get-NaRootVol { <# .Synopsis Return the name of the "root" volume on the filer. .Description Return the name of the "root" volume on the filer. .Parameter Server NaServer to query .Example PS > Get-NaRootVol vol0 .Outputs System.String .Link Get-NaAggr Set-NaAggr Remove-NaAggr .Notes NAME: Get-NaRootVol AUTHOR: Glenn Sizemore #Requires -Version 2.0 #> [CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipeline=$True,HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) Process{ Write-Output $server.Invoke("aggr-get-root-name").getchildcontent("root-volume") } } Function New-NaMirror { <# .Synopsis Mirror the specified aggregate/traditional volume. .Description Turns an unmirrored aggregate/traditional volume into a mirrored aggregate/traditional volume by adding a plex to it. The plex is either newly formed from disks chosen from a spare pool or, if the -VictimAggr|-VictimVol option is specified, taken from another existing unmirrored aggregate/volume. The named aggregate/volume must currently be unmirrored. Disks may be specified explicitly using the -Disk option. The number of disks indicated must match the number present in the existing aggregate/traditional volume. if disks are not specified explicitly, then disks are automatically selected to match those in the aggregate's/traditional volumes existing plex. .Parameter Aggregate Name of the existing aggregate to be mirrored. .Parameter Volume Name of the existing volume to be mirrored. .Parameter VictimAggr The "victim" aggregate/volume to cannibalize in order to mirror the named aggregate. The "victim-aggregate" must have been previously joined with the aggregate to be mirrored and then split from it. The resulting mirrored aggregate is otherwise identical to the original aggregate before the operation. The "victim-aggregate" (and all its volumes) is effectively destroyed. Note: the victim aggregate (and all its volumes) must be offline. .Parameter Disk Specific list of mirror disks to add. This list must match the number of disks present on the existing aggregate. The specified disks are not permitted to span disk pools unless overridden with the "force-spare-pool" option. To create a list of disk use Get-NaDisk. The following example will select 5 disks from shelf 2 PS > $disks = Get-NaDisk -spares | where-object {$_.shelf -eq 2} | select -first 5 .Parameter ForceSparePool Disks in a plex are not normally permitted to span spare pools. This behavior is overridden with this option. .Parameter Server NaServer to query .Example # Create a new plex, mirroring aggr1. PS > $disks = Get-NaDisk -spares | select -First 5 PS > New-NaMirror -Name aggr1 -Disk $disks .Example # Rejoin aggr2 backinto the aggr1 mirror after a split operation has been performed. PS > Get-NaAggr aggr1 | New-NaMirror -victimaggr aggr2 .Outputs NetApp.SDK.NaAggr .Link Get-NaAggr Split-NaMirror #> [CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="Disklist")] param( [Parameter(ParameterSetName="Disklist",Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the existing aggregate to be mirrored.")] [Parameter(ParameterSetName="victim",Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the existing aggregate to be mirrored.")] [Alias("Aggregate","Volume")] [STRING] $Name, [Parameter(ParameterSetName="victim",Mandatory=$TRUE,HelpMessage="The victim aggregate/traditional volume to cannibalize in order to mirror the named aggregate.")] [string] $VictimAggr, [Parameter(ParameterSetName="Disklist",Mandatory=$TRUE,HelpMessage="Specific list of mirror disks to add. This list must match the number of disks present on the existing aggregate.")] [string[]] $Disk, [Parameter(ParameterSetName="Disklist", HelpMessage="Force the mirroring operation through, past the normal roadblocks that would otherwise cause it to be aborted.")] [switch] $force, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process { $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-mirror") $request.AddNewChild("aggregate",$Name) switch ($PSCmdlet.ParameterSetName){ "victim" { $request.AddNewChild("victim-aggregate",$VictimAggr) } "DiskList" { $d = New-Object Netapp.Manage.NaElement("mirror-disks") $Disk|%{ $di = New-Object Netapp.Manage.NaElement("disk-info") $di.AddNewChild("name",$_) $d.AddChildElement($di) } $request.AddChildElement($d) if ($force){ $request.AddNewChild("force",$TRUE) } } } if ($pscmdlet.ShouldProcess($server.Server,"Mirroring aggregate $Name")){ try { $server.InvokeElem($request)|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } if ($?){ return Get-NaAggr $name -Server $Server } } } } Function Split-NaMirror { <# .Synopsis Remove the specified plex from a mirrored aggregate and create a new unmirrored aggregate. .Description Remove the specified plex from a mirrored aggregate and create a new unmirrored aggregate with the specified name that contains the plex. The original mirrored aggregate thus becomes unmirrored. The plex to be split from the original aggregate must be functional (not partial), but it can otherwise be inactive, resyncing, or out-of-date. "Aggr split" can therefore be used to gain access to a plex that isn't up to date with respect to its partner plex if its partner plex is currently failed. If the plex is offline at the time of the split, the resulting aggregate will be offline. Otherwise, the resulting aggregate will be in the same online/offline/restricted state as the original aggregate. A split mirror can be joined back together via the -VictimAggr option to New-Mirror cmdlet. .Parameter Path Path of the plex to split out of its aggregate, using the following format: [/vol/][][] .Parameter Name Name of the new aggregate to create from the split plex. .Parameter Server NaServer to query .Example # Split the mirrored aggregate Aggr1. Split plex1 off, creating a new aggr named aggr2. PS > $aggr = Get-NaAggr aggr1 PS > $aggr.Plexes.plex2 | Split-NaMirror -name aggr2 .Example # Split the mirrored aggregate Aggr1. Split plex1 off, creating a new aggr named aggr2. PS > $aggr = Get-NaAggr aggr1 PS > $aggr.Plexes.Plex1.Path /vol/aggr1/plex1 PS > Split-NaMirror -Path "/vol/aggr1/plex1" -name aggr2 .Outputs NetApp.SDK.NaAggr[] .Link Get-NaAggr Mirror-NaMirror #> [CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")] param( [Parameter(Position=0,Mandatory=$TRUE,HelpMessage="Name of the new aggregate to create from the split plex.")] [STRING] $Name, [Parameter(Position=1,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Path of the plex to split out of its aggregate, using the following format: [/vol/][][] ")] [STRING] $Path, [Parameter(Position=2,HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process { $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-split") $request.AddNewChild("aggregate",$path) $request.AddNewChild("new-aggr-name",$Name) $source = $Path.split("/")[2] if ($pscmdlet.ShouldProcess($source,"Splitting $($Name) off")) { try { $server.InvokeElem($request)|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } if ($?){ $source,$Name | select @{n='Name';e={$_}}| Get-NaAggr -Server $Server } } } } function Get-NaAggrFilerInfo { <# .Synopsis Get information on what possibilities and parameters exist for aggregates on a given filer. .Description Get information on what possibilities and parameters exist for aggregates on a given filer. .Parameter Server NaServer to query .Example Get-NaAggrFilerInfo .Outputs NetApp.SDK.NaAggrFilerInfo .Link Get-NaAggr #> [CmdletBinding(SupportsShouldProcess=$False,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipeline=$True,HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process{ try { $results = ([xml]$server.Invoke("aggr-get-filer-info")).results } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } if ($?){ $RG = New-Object HashTable $results."raidgroup-size"."raidgroup-size-info" | % { $RT = New-Object NetApp.SDK.NaRaidGroupInfo -ArgumentList @( $_."raidtype", $_."default-size", $_."maximum-size", $_."minimum-size" ) $RG.Add($_."raidtype",$RT) } return New-Object NetApp.SDK.NaAggrFilerInfo -ArgumentList @( [array]($results."allowed-raidtypes"."raidtype-info".raidtype), $results."checksum-types", $results."default-raidtype", $results."disk-types", $results."max-named-disks-per-request", $RG, $results."root-volume", $results."snapshots-max" ) } } } Function Get-NaAggrOptions { <# .Synopsis Get the options that have been set for the specified aggregate. .Description Get the options that have been set for the specified aggregate. .Parameter Name Name of the aggregate whose options we want. .Parameter Server NaServer to query .Example # Get the options for aggr1 on the target filer. PS > Get-NaAggrFilerInfo aggr1 .Outputs PSObject[] .Link Get-NaAggr Set-NaAggrOptions #> [CmdletBinding(SupportsShouldProcess=$False,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")] param( [Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the aggregate whose options we want.")] [Alias("Aggregate")] [STRING] $Name, [Parameter(Position=1,HelpMessage="Name of the option we want.")] [STRING] $OptionName, [Parameter(Position=2,HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process { try { $request = New-Object NetApp.Manage.NaElement("aggr-options-list-info") $request.AddNewChild("aggregate",$Name) $results = ([xml]$server.InvokeElem($request)).results } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message $result = $null continue; } if ($?){ $results.options."aggr-option-info" | Select-Object @{ Expression={$Name} Name='Aggregate' }, @{ Expression={$_.name} Name='OptionName' }, @{ Expression={$_.value} Name='Optionvalue' } | Where-Object {$_.OptionName -match $OptionName} } } } Function Set-NaAggrOptions { <# .Synopsis Set the specified option for the given aggregate. .Description Set the specified option for the given aggregate. The change remains effective even if the filer is rebooted. Some options have values that are numbers, and some have values that are "on" (also expressible as "yes", "true", or "1" ) or "off" (also expressible as "no", "false", or "0"). A mixture of uppercase and lowercase characters may be used when typing an option's value. Note that the "root" option is special in that it doesn't have a corresponding value. .Parameter Name "fs_size_fixed" (value: "on" | "off") Setting this option to "on" causes the file system to remain the same size (and not grow) when the mirror is broken on a SnapMirrored aggregate (which MUST be embedded in a traditional volume), or when an "aggr add" is performed on it(see add-NaDisk). This option is automatically set to be "on" when an aggregate becomes SnapMirrored. It remains "on" after the "snapmirror break" command (see Split-NaMirror) is issued for an aggregate embedded in a traditional volume. This option allows an embedded aggregate to be SnapMirrored back to the source without needing to add disks to the source aggregate. If the aggregate size is larger than the file system size, turning off this option forces the file system to grow to the size of the aggregate. "ignore_inconsistent" (value: "on" | "off") This command can only be used in maintenance mode. If this option is set to "on", then the root aggregate may be brought online when booting even if it is marked as inconsistent. The user is cautioned that bringing it online prior to running WAFL_check or wafliron may result in further file system inconsistency. "nosnap" (value: "on" | "off") Setting this option to "on" disables automatic snapshots on the aggregate. "raid_cv" (value: "on" | "off") Setting the option to "off" disables block checksum protection on the aggregate. The default is "on". The user is cautioned that turning off the option exposes the filesystems contained in the aggregate to inconsistency that could be caused by a misbehaving hardware component in the system. "raid_zoned" (value: "on" | "off") Setting the option to "off" disables zoned checksum protection on the aggregate. The default is "on". The user is cautioned that turning off the option exposes the filesystems contained in the aggregate to inconsistency that could be caused by a misbehaving hardware component in the system. "raidsize" (value: < int >>) The maximum size of a RAID group within the aggregate. Changing this option doesn't cause existing RAID groups to grow or shrink. Rather, it only affects whether more disks will be added to the last existing RAID group in the future, and how large new RAID groups will be. "raidtype" (value: "raid4" | "raid_dp" | "raid0") The type of RAID group used for this aggregate. The "raid4" setting provides one parity disk per RAID group, while "raid_dp" provides two. Changing this option immediately changes the RAID group type for all RAID groups in the aggregate. When upgrading RAID groups from "raid4" to "raid_dp", each RAID group begins a reconstruction onto a spare disk allocated for the second "dparity" parity disk. "resyncsnaptime" (value: < int >) Sets the mirror resynchronization snapshot frequency to be the given number of minutes. The default value is 60 (minutes). "root" (value: < none >) The specified aggregate is to become the root aggregate for the filer on the next reboot. This option can be used on only one aggregate at any given time. The existing root aggregate will become a non-root aggregate after the reboot. Until the system is rebooted, the original aggregate will continue to show root as an option, and the new root aggregate will show diskroot as an option. In general, the aggregate that has the diskroot option is the one that becomes the root aggregate following the next reboot. The only way to remove the root status of an aggregate is to set it on another aggregate. "snapmirrored" (value : "off") If SnapMirror is enabled, the filer auto- matically sets this option to "on". Set this option to "off" with the "snapmirror" (see New-NaMirror)command if SnapMirror should no longer be used to update the mirror. After setting this option to "off", the mirror becomes a regular writable aggregate, and all its volumes are restored to whatever state they were last in. Note that it is not possible to set this option directly through this interface. Rather, it is automatically changed as a side effect of running the appropriate "snapmirror" commands. "snapshot_autodelete" (value: "on" | "off") Setting this option to "off" disables automatic snapshot deletion on the aggregate. "thorough_scrub" (value: "on" | "off") Setting the option to "on" enables thorough scrub on a block checksum aggregate. That means that a scrub will initialize any zeroed checksum entries that it finds. If there are any checksum entries to be initialized, scrub will run slower than normal. .Parameter Value The value to set the named option. It may be the NULL/empty value only in the case of the "root" option. .Parameter Aggregate Name of the aggregate for which we want to set an option. .Parameter Server NaServer to query .Example # Get the NoSnap option for aggr1 on the target filer. PS > Set-NaAggrOptions -Name "nosnap" -value "on" -Aggregate aggr1 .Outputs PSObject .Link Get-NaAggr Get-NaAggrOptions #> [CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] param( [Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the option to set.")] [STRING] $OptionName, [Parameter(Position=1,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The value to set the named option.")] [STRING] $OptionValue, [Parameter(Position=2,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the aggregate for which we want to set an option. ")] [STRING] $Aggregate, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process{ $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-set-option") $request.AddNewChild("aggregate",$Aggregate) $request.AddNewChild("option-name",$OptionName) $request.AddNewChild("option-value",$OptionValue) if ($pscmdlet.ShouldProcess($Aggregate, "Setting $OptionName to $OptionValue")){ try { $server.InvokeElem($request)|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } if ($?){ return Get-NaAggrOptions -Name $Aggregate -OptionName $OptionName -server $Server } } } } function Get-NaScrub { <# .Synopsis Get the status of parity scrubbing on the named aggregate, plex, or RAID group. .Description Get the status of parity scrubbing on the named aggregate, plex, or RAID group. Status includes percentage complete and the scrub's suspended status (if appropriate). .Parameter Path Path of an existing aggregate, plex, or RAID group using the following format: [/vol/][][] If no name is given, then status is generated for all RAID groups currently being scrubbed. .Parameter Server NaServer to query .Example # Get the status of plex1 on aggr2 PS > Get-NaScrub -aggregate '/vol/aggr2/plex1' # or use the pipeline PS > (Get-NaAggr aggr2).plexes.plex1 | Get-NaScrub .Outputs NetApp.SDK.NaScrubInfo[] .Link Get-NaAggr Start-NaScrub #> [CmdletBinding(SupportsShouldProcess=$False,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The aggregate/volume to get status for. If not supplied, get status of all aggregates.")] [STRING] $Path, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process { $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-scrub-list-info") $request.AddNewChild("verbose",$TRUE) if ($Path){ $request.AddNewChild("aggregate",$Path) } try { $result = ([xml]$server.InvokeElem($request)).results } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } if ($?){ $result."scrub-details"."scrub-detail-info" | % { return New-Object NetApp.SDK.NaScrubInfo -ArgumentList @( (ConvertFrom-NaBool $_."is-suspended"), $(if ($_."percentage-complete") { $_."percentage-complete"}else{[int]0}), $_."raid-group", (ConvertFrom-NaTime $_."last-scrub-timestamp") ) } } } } function Start-NaScrub { <# .Synopsis Start parity scrubbing on the named aggregate, plex, or RAID group. .Description Start parity scrubbing on the named aggregate, plex, or RAID group. Parity scrubbing compares the data disks to the parity disk in a RAID group, correcting the parity disk's contents as necessary. If no name is given, then parity scrubbing is started on all online aggregates. if an aggregate name is given, scrubbing is started on all RAID groups in the aggregate. if a plex name is given, scrubbing is started on all RAID groups contained in the plex. if a RAID group name is given, scrubbing is started only on that group. Use Get-NaScrub to check scrubbing status. .Parameter Path Path of the aggregate, plex, or RAID group to scrub, using the following format: [/vol/][][] .Parameter Server NaServer to query .Example # Get the status of plex1 on aggr2 PS > Start-NaScrub -path '/vol/aggr1' .Outputs NetApp.SDK.NaScrubInfo[] .Link Get-NaAggr Get-NaScrub Stop-NaScrub Suspend-NaScrub Resume-NaScrub #> [CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Path of the aggregate, plex, or RAID group for which we are to start parity scrubbing")] [string] $Path, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process{ $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-scrub-start") if ($Path){ $request.AddNewChild("aggregate",$Path) } if ($pscmdlet.ShouldProcess($path,"Starting parity scrub")){ try { $server.InvokeElem($request)|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } return Get-NaScrub $Path -server $Server } } } function Stop-NaScrub { <# .Synopsis Stop parity scrubbing on the named aggregate, plex, or RAID group. .Description Stop parity scrubbing on the named aggregate, plex, or RAID group. If no name is given, stop scrubbing on all RAID groups currently being scrubbed. .Parameter Path Path of the aggregate, plex, or RAID group for which we are to stop parity scrubbing, using the following format: [/vol/][][] .Parameter Server NaServer to query .Example # Stop parity scrubbing on aggr1 PS > Stop-NaAggrScrub -path '/vol/aggr1' .Outputs NetApp.SDK.NaScrubInfo[] .Link Get-NaAggr Get-NaScrub Start-NaScrub Suspend-NaScrub Resume-NaScrub #> [CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Path of the aggregate, plex, or RAID group for which we are to stop parity scrubbing")] [string] $path, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process{ $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-scrub-stop") if ($Path){ $request.AddNewChild("aggregate",$path) } if ($pscmdlet.ShouldProcess($path,"Stopping parity scrub")){ try { $server.InvokeElem($request)|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } if ($?){ return Get-NaScrub $Path -server $Server } } } } Function Suspend-NaScrub { <# .Synopsis Suspend parity scrubbing on the named aggregate, plex, or RAID group. .Description Suspend parity scrubbing on the named aggregate, plex, or RAID group. If no name is given, suspend scrubbing on all RAID groups currently being scrubbed. .Parameter Path Path of the aggregate, plex, or RAID group to suspend scrub, using the following format: [/vol/][][] .Parameter Server NaServer to query .Example # Suspend parity scrub for aggr1 PS > Suspend-NaScrub -path '/vol/aggr1' .Outputs NetApp.SDK.NaScrubInfo[] .Link Get-NaAggr Get-NaScrub Start-NaScrub Stop-NaScrub Resume-NaScrub #> [CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Path of the aggregate, plex, or RAID group for which we are to suspend parity scrubbing")] [string] $path, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process { $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-scrub-suspend") if ($Path){ $request.AddNewChild("aggregate",$Path) } if ($pscmdlet.ShouldProcess($path,"Suspending parity scrub")){ try { $server.InvokeElem($request)|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } if ($?) { return Get-NaScrub $Path -server $Server } } } } function Resume-NaScrub { <# .Synopsis Resume parity scrubbing on the named aggregate, plex, or RAID group. .Description Resume parity scrubbing on the named aggregate, plex, or RAID group. If no name is given, Resume scrubbing on all RAID groups currently being scrubbed. .Parameter Path Path of the aggregate, plex, or RAID group to resume scrub, using the following format: [/vol/][][] .Parameter Server NaServer to query .Example # resume parity scrub for aggr1 PS > Resume-NaScrub -aggregate '/vol/aggr1' .Outputs NetApp.SDK.NaScrubInfo[] .Link Get-NaAggr Get-NaScrub Start-NaScrub Stop-NaScrub Suspend-NaScrub #> [CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Path of the aggregate, plex, or RAID group for which we are to resume parity scrubbing")] [string] $path, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process{ $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-scrub-resume") if ($path){ $request.AddNewChild("aggregate",$path) } if ($pscmdlet.ShouldProcess($path,"Resuming parity scrub")){ try { $server.InvokeElem($request)|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } if ($?) { return Get-NaScrub $Path -server $Server } } } } Function Get-NaVerify { <# .Synopsis Get the status of RAID mirror verification on the named aggregate/volume. .Description Get the status of RAID mirror verification on the named aggregate/volume. Status includes percentage complete and whether it's currently suspended. .Parameter Name Name of an existing aggregate / volume. If no name is given, then mirror verification status is generated for all aggregates currently being verified. .Parameter Server NaServer to query .Example # Get the status of RAID mirror verification on aggr1 PS > Get-NaVerify -Aggregate aggr1 .Outputs NetApp.SDK.NaVerifyInfo[] .Link Get-NaAggr Start-NaVerify Resume-NaVerify Suspend-NaVerify Stop-NaVerify #> [CmdletBinding(SupportsShouldProcess=$False,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The aggregate/volume to get status for.")] [Alias("Aggregate")] [string] $name, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process{ $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-verify-list-info") if ($name){ $request.AddNewChild("aggregate",$name) } trap{ write-warning "no verifications are running at this time" continue; } $result = ([xml]$server.InvokeElem($request)).results $result."verify-details"."verify-detail-info" | % { if ($_.name -ne $null) { return New-Object NetApp.SDK.NaVerifyInfo -ArgumentList @( (ConvertFrom-NaBool $_."is-suspended"), $_.name, $_."percentage-complete" ) } } } } Function Start-NaVerify { <# .Synopsis Start RAID mirror verification on the named aggregate/volume. .Description Start RAID mirror verification on the named aggregate/volume. Verification compares the data in both plexes of a mirrored aggregate. in the default case, any blocks that differ are logged and no changes are made. The -FixPlex option is used to fix any mismatches. It specifies which plex to fix. if no name is given, then mirror verification is started on all online aggregates. Use the Get-NaVerify cmdlet to check mirror verification status. if the -FixPlex option is used, then a name must be specified. .Parameter Name Name of the mirrored aggregate to verify. .Parameter FixPlex If provided, this specifies the plex to fix in case the two plexes do not match. The default is to log any discrepancies instead of fixing them. .Parameter ASync If provided, then execute the cmd in the background return control to the console. This option only applies if -Name is provided. .Parameter Server NaServer to query .Example # start RAID mirror verification on aggr1 log only PS > Start-NaVerify -Name aggr1 .Example # start RAID mirror verification on aggr1 syncing plex1 PS > Start-NaVerify -Name aggr1 -fixplex 1 .Outputs NetApp.SDK.NaVerifyInfo[] .Link Get-NaAggr Get-NaVerify Resume-NaVerify Suspend-NaVerify Stop-NaVerify #> [CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the mirrored traditional volume to verify.")] [Alias("Volume","Aggregate")] [STRING] $Name, [Parameter(Position=1,HelpMessage="If provided, this specifies the plex to fix.")] [INT] $FixPlex, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process{ $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-verify-start") if ($name){ $request.AddNewChild("aggregate",$name) $target = $name } else{ $target = 'ALL mirrored aggregates' } if ($FixPlex){ $request.AddNewChild("fix-plex",$FixPlex) } if ($pscmdlet.ShouldProcess($target,"Verify RAID Mirror")){ trap{continue} $server.InvokeElem($request)|out-null return Get-NaVerify $name -server $Server } } } Function Resume-NaVerify { <# .Synopsis Resume RAID mirror verification on the named aggregate/volume. .Description Resume RAID mirror verification on the named aggregate. If no name is given, then resume mirror verification on all aggregates that have been suspended. .Parameter Name Name of the mirrored aggregate/volume to resume verification. .Parameter Server NaServer to query .Example # resume verification on aggr1 PS >Resume-NaVerify -Aggregate aggr1 .Outputs NetApp.SDK.NaVerifyInfo[] .Link Get-NaAggr Get-NaVerify Set-NaVerify Suspend-NaVerify Stop-NaVerify #> [CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the mirrored aggregate/traditional volume to resume verification.")] [Alias("Volume","Aggregate")] [STRING] $name, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process{ $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-verify-resume") if ($Name){ $request.AddNewChild("aggregate",$name) } else{ $name = "All Mirrored Aggregates" } if ($pscmdlet.ShouldProcess($name,"Resume RAID mirror verification")){ trap{continue} $server.InvokeElem($request)|out-null Get-NaVerify -Name $name -server $Server } } } function Suspend-NaVerify { <# .Synopsis Suspend RAID mirror verification on the named aggregate/volume. .Description Suspend RAID mirror verification on the named aggregate. If no name is given, suspend mirror verification on all aggregates currently being verified. .Parameter Name Name of the mirrored aggregate to suspend verification. .Parameter Server NaServer to query .Example # suspend verification on aggr1 PS > Suspend-NaVerify -Aggregate aggr1 .Outputs NetApp.SDK.NaVerifyInfo[] .Link Get-NaAggr Get-NaVerify Set-NaVerify Resume-NaVerify Stop-NaVerify #> [CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the mirrored traditional volume to suspend verification.")] [Alias("Volume","Aggregate")] [STRING] $name, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process{ $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-verify-suspend") if ($Name){ $request.AddNewChild("aggregate",$name) } else{ $name = "All Mirrored Aggregates" } if ($pscmdlet.ShouldProcess($name,"Suspend RAID mirror verification")){ trap{ write-warning "no verifications are running at this time" continue; } $server.InvokeElem($request)|out-null Get-NaVerify -Name $name -server $Server } } } function Stop-NaVerify { <# .Synopsis Stop RAID mirror verification on the named aggregate/volume. .Description Stop RAID mirror verification on the named aggregate. If no name is given, suspend mirror verification on all aggregates currently being verified. .Parameter Name Name of the mirrored aggregate to Stop verification. .Parameter Server NaServer to query .Example # Stop verification on aggr1 PS > Stop-NaVerify -Aggregate aggr1 .Outputs NetApp.SDK.NaVerifyInfo[] .Link Get-NaAggr Get-NaVerify Set-NaVerify Suspend-NaVerify Resume-NaVerify #> [CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the mirrored traditional volume to stop verification.")] [Alias("Volume","Aggregate")] [STRING] $name, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) process{ $request = New-Object NetApp.Manage.NaElement -ArgumentList @("aggr-verify-stop") if ($Name){ $request.AddNewChild("aggregate",$name) } else{ $name = "All Mirrored Aggregates" } if ($pscmdlet.ShouldProcess($name,"Stopping RAID mirror verification")){ trap{continue} $server.InvokeElem($request)|out-null Get-NaVerify -Name $name -server $Server } } }