<# .SYNOPSIS Used to get information about the disks in a filer .DESCRIPTION Get disk status information from RAID. Only disks owned by the filer or its partner are eligible for inclusion in the returned list.. .PARAMETER Disk Name of the disk example 'v0.20' .PARAMETER Server NaServer to query .EXAMPLE #Get all spares in a filer. PS > Get-NaDisk -spares .EXAMPLE #Get the status of disk "v2.22" from filer "toaster". PS > $NaServer = New-NaServer -server "Toaster" PS > Get-NaDisk -disk "v2.22" -Server $NaServer .OUTPUTS NetApp.SDK.NaDisk[] .Link Set-NaDisk #> function Get-NaDisk { [CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the disk example 'v0.20'")] [Alias("Disk")] [string] $Name, [Parameter()] [switch] $spares, [Parameter(Position=1,HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) Begin { $out = @() } Process { $request = New-Object Netapp.Manage.NaElement -ArgumentList @("disk-list-info") if ($Name){ $request.AddNewChild("disk",$Name) } try { $result = ([xml]$server.InvokeElem($request)).results } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message $result = $null continue; } if ($?){ $result."disk-details"."disk-detail-info" |% { $out += New-Object NetApp.SDK.NaDisk -ArgumentList @( $_."aggregate", $_."bay", $_."blocks-Read", $_."blocks-Written", $_."broken-details", $_."bytes-Per-Sector", $_."checksum-Compatibility", $_."copy-Destination", $_."copy-Percent", $_."disk-Model", $_."disk-Type", $_."disk-Uid", $_."effective-Disk-Type", $_."firmware-Revision", $_."grown-Defect-List-Count", $_."host-Adapter", $_."id", (ConvertFrom-NaBool $_."is-dynamically-Qualified"), (ConvertFrom-NaBool $_."is-offline"), (ConvertFrom-NaBool $_."is-prefailed"), (ConvertFrom-NaBool $_."is-replacing"), (ConvertFrom-NaBool $_."is-zeroed"), $_."name", $_."physical-Blocks", $_."physical-Space", $_."pool", $_."plex", $_."port", $_."port-Name", $_."power-On-Hours", $_."raid-group", $_."raid-State", $_."raid-Type", $_."raw-Disk-Sectors", $_."reconstruction-Percent", $_."rpm", $_."scrubCount", $_."scrubLast-Done", $_."secondary-Name", $_."secondary-Port", $_."serial-Number", $_."shelf", $_."shm-Time-Interval", $_."used-Blocks", $_."used-Space", ($_."v-series-detail-info"."v-series-detail-info" | % { New-Object NetApp.SDK.NaVSeries -ArgumentList @( $_."product-id", $_."primary-array-port-wwn", $_."primary-array-switch-port-wwn", $_."primary-controller-port-wwn", $_."primary-lun-number", $_."primary-switch-name", $_."primary-switch-port", $_."alternate-array-port-wwn", $_."alternate-array-switch-port-wwn", $_."alternate-controller-port-wwn", $_."alternate-lun-number", $_."alternate-switch-name", $_."alternate-switch-port" )} ), $_."vendor-Id", $_."volume", $_."zeroing-Percent" ) } } } end { if ($spares) { return $out | ? {$_.raidstate -eq "spare"} } else { return $out } } } Function Set-NaDisk { <# .Synopsis Used to Set the physical state of a disk .Description Used to Set the physical state of a disk .Parameter Disk Name of the disk example 'v0.20' .Parameter Fail Fail a file system disk. Removes the specified file system disk from the RAID configuration, spinning the disk down when removal is complete. .Parameter FailNow Fail the specified disk immediately, the disk will not be spun down .Parameter Remove Remove a spare disk. Removes the specified spare disk from the RAID configuration, spinning the disk down when removal is complete. .Parameter Replace Initiate replacing a file system disk with an appropriate spare disk. .Parameter ReplacementDisk Name of the spare disk to use as a replacement. .Parameter Force Allow replacement-disk to come from the opposite spare pool. Also allow replacement disk not matching rotational speed of majority of disks in the aggregate .Parameter CancelReplace Abort disk replace operation. .Parameter UnFail Unfail a disk in the broken pool, by clearing its FDR (Failed Disk Registry) entry and unfailing it at the Storage Layer. .Parameter MakeSpare Force the disk to become a spare upon unfail .Parameter Server NaServer to query .Example # Fail a disk by default fail will safley remove a drive. PS > Get-NaDisk -Disk v0.20 | Set-NaDisk -Fail .Example # if more imediate action is required -FailNow will force an instantantious result! PS > Set-NaDisk -disk (Get-NaDisk -disk v0.20) -Fail -FailNOW .Example # Unfail will mark a failed disk as good and return it to the pool PS > Set-NaDisk -disk (Get-NaDisk -disk v0.20) -UnFail .Example # Unfail will mark a failed disk as good and return it to the pool. The -MakeSpare # switch will also mark that drive as a non-zeroed spare. PS > Set-NaDisk -disk "v0.20" -UnFail -MakeSpare .Example # Prepair a drive for removal from the system. PS > Get-NaDisk -Disk v0.20 | Set-NaDisk -remove .Example # Live migrate from one drive to another. -replace requires two disks # be specified. # -replace Target disk -> the one being replaced. # -ReplacementDisk The spare that will replace your target. PS > $Spare = Get-nadisk -spare |?{$_.RPM -eq 15000}|select -First 1 PS > Get-NaDisk -disk v0.20 | Set-NaDisk -ReplacementDisk $Spare.disk .Outputs NetApp.SDK.NaDisk[] .Link Get-NaDisk #> [CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] param( [Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="ReplaceDisk",HelpMessage="Name of the disk example 'v0.20'")] [Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="AbortReplaceDisk",HelpMessage="Name of the disk example 'v0.20'")] [Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="Faildisk",HelpMessage="Name of the disk example 'v0.20'")] [Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="unFaildisk",HelpMessage="Name of the disk example 'v0.20'")] [Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,ParameterSetName="RemoveDisk",HelpMessage="Name of the disk example 'v0.20'")] [Alias("Disk")] [string] $Name, [Parameter(ParameterSetName="Faildisk")] [switch] $Fail, [Parameter(ParameterSetName="Faildisk")] [switch] $FailNow, [Parameter(ParameterSetName="RemoveDisk")] [switch] $Remove, [Parameter(ParameterSetName="ReplaceDisk")] [switch] $Replace, [Parameter(Mandatory=$TRUE,Position=1,ParameterSetName="ReplaceDisk")] [string] $ReplacementDisk, [Parameter(ParameterSetName="ReplaceDisk")] [switch] $Force, [Parameter(ParameterSetName="AbortReplaceDisk")] [switch] $CancelReplace, [Parameter(ParameterSetName="unFaildisk")] [switch] $UnFail, [Parameter(ParameterSetName="unFaildisk")] [switch] $MakeSpare, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) Process { switch ($pscmdlet.ParametersetName) { "Faildisk" { $request = New-Object Netapp.Manage.NaElement -ArgumentList @("disk-fail") $request.AddNewChild("disk",$name) $msg = "Fail Disk $Name" if ($FailNow){ $request.AddNewChild("is-immediate",$TRUE) $msg += " Immediaty" } } "unFaildisk" { $request = New-Object Netapp.Manage.NaElement -ArgumentList @("disk-unfail") $request.AddNewChild("disk",$Name) $msg = "Unfail Disk $Name" if ($MakeSpare){ $request.AddNewChild("make-spare",$TRUE) $msg += " and make spare" } } "RemoveDisk" { $request = New-Object Netapp.Manage.NaElement -ArgumentList @("disk-remove") $request.AddNewChild("disk",$Name) $msg = "Remove Disk $Name" } "ReplaceDisk" { $request = New-Object Netapp.Manage.NaElement -ArgumentList @("disk-replace-start") $request.AddNewChild("disk",$Name) if ($ReplacementDisk){ $request.AddNewChild("replacement-disk",$ReplacementDisk) $msg = "Replace $Name with $ReplacementDisk " } else{ Throw " If -replace is specified, then -ReplacementDisk <[string]> must also be supplied. " } if ($Force){ $request.AddNewChild("force",$TRUE) } } "AbortReplaceDisk" { $request = New-Object Netapp.Manage.NaElement -ArgumentList @("disk-replace-stop") $request.AddNewChild("disk",$Name) $msg = "Cancel Disk Replace $Name" } } if ($pscmdlet.ShouldProcess($Server.Server, $Msg)){ try { $server.InvokeElem($request)|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } if ($?){ return Get-NaDisk -disk $Name -Server $server } } } } Function Add-NaDisk { <# .Synopsis Add disks to the specified aggregate. .Description Add disks to the specified aggregate, whether it is free-standing or embedded in a traditional volume. The disks to add are specified in the same way as for Add-NaAggr. Disks cannot be added to a mirrored aggregate if one or more of the plexes is offline. By the time the API returns, the disk(s) may not yet be completely added. Use Get-NaAggr to query the aggregate status to determine when it has finished growing due to the added disk(s). .Parameter Name Name of the aggregate to which the disks will be added. .Parameter DiskCount Number of disks to add, including the parity disks. The disks will come from the pool of spare disks. The smallest disks in this pool join the aggregate first, unless the -DiskSize argument is specified. Either the -DiskSize or -Disk argument must be specified. .Parameter DiskSize The disk size in GB. Disks that are within approximately 20% 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 Disk Specific list of disks to add to the 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 RaidGroup Specifies the RAID group (for example rg0) to which the indicated disks are to be added. When a RAID group other than the last RAID group is specified, the aggregate can no longer be reverted to a version of ONTAP prior to 6.2. in such a case, the -ForceSparePool switch must be specified as well. By default, the filer fills up one RAID group with disks before starting another RAID group. Suppose an aggregate currently has one RAID group of 12 disks and its RAID group size is 14. if you add 5 disks to this aggregate, it will have one RAID group with 14 disks and another RAID group with 3 disks. The filer does not evenly distribute disks among RAID groups. .Parameter Force Disks in a plex are not normally permitted to span spare pools. This behavior is overridden when this option is specified. .Parameter GroupSelectionMode Specifies how DATA ONTAP adds the specified disks to raidgroups. Legitimate values are "last", "one", "new" or "all". -GroupSelectionMode is an optional argument, and the behavior when it is not used is selected by value of -RaidGroup. if -raidgroup is used, the behavior is the same as for -GroupSelectionMode "one". if -RaidGroup is not used, the behavior is the same as for -GroupSelectionMode "last". The -RaidGroup option must be used with -GroupSelectionMode value "one", and it cannnot be used with others. if the string value is "last", Data ONTAP adds the specified disks to the existing last RAID group first. After the last RAID group is full, it creates one or more new RAID groups and adds the remaining disks to the new groups. if the string value is "one", Data ONTAP adds the specified disks to the existing RAID group specified by raid-group option until this specified RAID group is full. if the string value is "new", Data ONTAP creates one or more new RAID groups and adds the specified disks to the new groups, even if they would fit into an existing RAID group. The name of new RAID groups are selected automatically. It is not possible to specify the name for the new RAID groups. if the string value is "all", Data ONTAP adds the specified disks to existing RAID groups first. Only after all existing RAID groups are full, it creates one or more new RAID groups and adds the remaining disks to the new groups. .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. .Parameter Server NaServer to query .Example # Add four disks to aggr1 PS > Get-NaAggr aggr1 | Add-NaAggr -DiskCount 4 .Example # Add 8 disks to Aggr1 RG0 PS > Get-NaAggr aggr1 | Add-NaAggr -DiskCount 8 -RaidGroup RG0 .Example Add disks from shelf 4 to the mirrored Aggregate Aggr3, and add the disks from shelf 5 to aggr3 mirror. Create a new rg with the specified disks PS > $disks = Get-NaDisk -spare | ? {$_.shelf -eq 4}| Select -ExpandProperty Disk PS > $Mirrordisk = Get-NaDisk -spare | ? {$_.shelf -eq 5}| Select -ExpandProperty Disk PS > Add-NaDisk -Name Aggr3 -Disk $disks -MirrorDisks $Mirrordisk -GroupSelectionMode "new" .Outputs NetApp.SDK.NaAggr[] .Link Get-NaAggr New-NaAggr #> [CmdletBinding(SupportsShouldProcess=$true,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="Diskcount")] param( [Parameter(Position=0,Mandatory=$TRUE,ParameterSetName="Diskcount",ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the aggregate to which the disks will be added.")] [Parameter(Position=0,Mandatory=$TRUE,ParameterSetName="Disklist",ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the aggregate to which the disks will be added.")] [Parameter(Position=0,Mandatory=$TRUE,ParameterSetName="MirrorDisklist",ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the aggregate to which the disks will be added.")] [Alias("Aggregate")] [STRING] $Name, [Parameter(Position=1,Mandatory=$TRUE,ParameterSetName="Diskcount",HelpMessage="Number of disks to add, including the parity disks.")] [INT] $DiskCount, [Parameter(ParameterSetName="Diskcount",HelpMessage="The disk size in GB.")] [INT] $DiskSize, [Parameter(Mandatory=$TRUE,ParameterSetName="Disklist",HelpMessage="Specific list of disks to use for the new aggregate.")] [Parameter(Mandatory=$TRUE,ParameterSetName="MirrorDisklist",HelpMessage="Specific list of disks to use for the new aggregate.")] [string[]] $Disk, [Parameter(Mandatory=$TRUE,ParameterSetName="MirrorDisklist",HelpMessage="List of mirror disks to use. It must contain the same number of disks specified in -disks")] [string[]] $MirrorDisks, [Parameter(HelpMessage="Specifies how DATA ONTAP adds the specified disks to raidgroups. Legitimate values are last, one, new or all.")] [ValidateSet("last", "one", "new","all")] [STRING] $GroupSelectionMode, [Parameter(HelpMessage="Specifies the RAID group (for example rg0) to which the indicated disks are to be added.")] [STRING] $RaidGroup, [Parameter()] [switch] $Force, [Parameter(HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) Process{ $request = New-Object Netapp.Manage.NaElement -ArgumentList @("aggr-add") $request.AddNewChild("aggregate",$name) switch ($PSCmdlet.ParametersetName) { "Diskcount" { $request.AddNewChild("disk-count",$DiskCount) $msg = "Adding $diskCount disks to $Name" if ($DiskSize){ $request.AddNewChild("disk-size",$DiskSize) } } "Disklist" { $d = New-Object Netapp.Manage.NaElement("disks") foreach ($_d in $Disk){ $di = New-Object Netapp.Manage.NaElement("disk-info") $di.AddNewChild("name",$_d.disk) $d.AddChildElement($di) } $request.AddChildElement($d) } "MirrorDisklist" { $d = New-Object Netapp.Manage.NaElement("disks") foreach ($_d in $Disk){ $di = New-Object Netapp.Manage.NaElement("disk-info") $di.AddNewChild("name",$_d) $d.AddChildElement($di) } $request.AddChildElement($d) $m = New-Object Netapp.Manage.NaElement("mirror-disks") foreach ($_d in $MirrorDisks){ $mi = New-Object Netapp.Manage.NaElement("disk-info") $mi.AddNewChild("name",$_d) $m.AddChildElement($mi) } $request.AddChildElement($m) } } if ($Force){ $request.AddNewChild("force-spare-pool",$TRUE) } if ($GroupSelectionMode){ $request.AddNewChild("group-selection-mode",$GroupSelectionMode) } if ($RaidGroup){ $request.AddNewChild("raid-group",$RaidGroup) } if ($pscmdlet.ShouldProcess($Server.Server,$msg)){ try { $server.InvokeElem($request)|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } if ($?){ $pscmdlet.WriteVerbose("Disks added!") return Get-NaAggr -name $name -Server $Server } } } } Function Start-NaDiskSwap { <# .Synopsis Prepare (quiet) bus for swap. Applies to SCSI disks only. .Description Prepare (quiet) bus for swap. Applies to SCSI disks only. It stalls all I/O on the filer to allow a disk to be physically added or removed from a disk shelf. Typically, this command would be used to allow removal of a failed disk, or of a file system or spare disk that was prepared for removal using the disk fail or disk remove command. Once a disk is physically added or removed from a disk shelf, system I/O will automatically continue. NOTE: It is important to issue the disk swap command only when you have a disk that you want to physically remove or add to a disk shelf, because all I/O will stall until a disk is added or removed from the shelf. .Parameter Server NaServer to query .Example # Prepair a scsi bus for disk swap PS > Start-NADiskSwap .Link Stop-NaDiskSwap #> [CmdletBinding(SupportsShouldProcess=$TRUE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")] param( [Parameter(Position=0,HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) Process { if ($pscmdlet.ShouldProcess($Server.Server,"Stoping ALL I/O")){ try { $server.Invoke("disk-swap")|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } } } } function Stop-NaDiskSwap { <# .Synopsis Undo disk swap and resume service. .Description Undo disk swap and resume service. .Parameter Server NaServer to query .Example # Stops a Disk swap and resumes all I/O on SCSI bus. PS > Stop-NADiskSwap .Link Start-NaDiskSwap #> [CmdletBinding(SupportsShouldProcess=$TRUE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")] param( [Parameter(Position=0,HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) Process{ if ($pscmdlet.ShouldProcess($Server.Server, "Resuming service")){ try { $server.Invoke("disk-unswap") | out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } } } } function Start-NaZeroSpares { <# .Synopsis Set up all non-zeroed spares owned by the filer to start zeroing. .Description Set up all non-zeroed spares owned by the filer to start zeroing. This operation is asynchronous, and therefore returns no errors that might occur when the zeroing operation actually starts, which could be several seconds after this API operation completes. Zeroing progress can be monitored via the Get-NaDisk Cmdlet. The ZeroingPercent Property is returned if disk zeroing has started, and the Zeroed returns TRUE once the zeroing has completed (or, if zeroing wasn't necessary in the first place). .Parameter Server NaServer to query .Example # Zero All spares Start-NaZeroSpares #> [CmdletBinding(SupportsShouldProcess=$TRUE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")] param( [Parameter(Position=0,HelpMessage="NaServer to query")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) Process { if ($pscmdlet.ShouldProcess($Server.Server, "Zero All Spares")){ $server.Invoke("disk-zero-spares") | out-null } } } function Update-NaDiskFirmware { <# .Synopsis Start disk firmware download process to update firmware on disks. .Description Start disk firmware download process to update firmware on disks. This operation is asynchronous, and therefore returns no errors that might occur during the download process. This operation will only update firmware on disks that do not have the latest firmware revision. The firmware revision on the disk can be monitored via the Get-NaDisk Cmdlet. .Parameter Disk Name of the disk example 'v0.20' .Parameter Server NaServer to query .Example # Update the firmware on all disks PS > Start-NaZeroSpares .Example # Update the firmware on a disk. PS > Update-NaDiskFirmware -name 'v1.20' .Example # update any disks model VD-100MB where the firmware isnot 0042 PS > Get-NaDisk | ?{$_.Model -eq 'VD-100MB' -and $_.Firmware -ne '0042'} | Update-NaDiskFirmware #> [CmdletBinding(SupportsShouldProcess=$TRUE,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")] param( [Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the disk example 'v0.20'")] [Alias("Disk")] [string[]] $Name, [Parameter(Position=1,HelpMessage="[NAServer]NAserver (New-NAServer)")] [NetApp.SDK.NaServer] $server = (Get-NaServer) ) Process { $target = 'All Spares' $request = New-Object Netapp.Manage.NaElement -ArgumentList @("disk-update-disk-fw") if ($Name){ $d = New-Object Netapp.Manage.NaElement("disk-list") foreach ($n in $name){ $d.AddNewChild("disk-name", $n) } $request.AddChildElement($d) } if ($pscmdlet.ShouldProcess($Server.Server,"Starting firmware download")) { try { $server.InvokeElem($request)|out-null } catch [NetApp.Manage.NaApiFailedException]{ Write-Warning $_.Exception.GetBaseException().message continue; } } } }