Subscribe
Accepted Solution

PowerShell commands for inodes

Are there commands to display and modify inodes?  Equivelents for df -i and maxfiles in the toolkit?

PowerShell commands for inodes

The information is available in the VolumeInfo object.

Here is a sample script to output the inode information.

$filer1 = Connect-NaController -Name "filer1" -Credential "root"

$vols = Get-NaVol

$vols | Format-Table -Property Name,FilesUsed,FilesTotal -AutoSize

If you also want the FilesAvailable, you can change the Format-Table line as follows:

$vols | Format-Table -Property Name,FilesUsed,@{Label = "FilesAvailable"; Expression = {$_.FilesTotal - $_.FilesUsed}; Align = "Right"},"FilesTotal" -AutoSize

To modify the maxfiles, use the Set-NaVolTotalFiles.  For example, to set the maxfiles to 2,000,000 on a volume named vol1, the command is:

Set-NaVolTotalFiles -Name "vol1" -TotalFiles 2000000

I hope this helps.

PowerShell commands for inodes

Thanks paleon, that was exactly what I was looking for.  I added % used as an additional column.

$filer1 = Connect-NaController -Name foo

$vols = Get-NaVol

$vols | Format-Table -Property Name, FilesUsed, @{Label = "FilesAvailable"; Expression = {$_.FilesTotal - $_.FilesUsed}; Align = "Right"},@{Label = "%Used"; Expression = {$_.FilesUsed / $_.FilesTotal};FormatString="N2"},"FilesTotal" -AutoSize

PowerShell commands for inodes

thepunisher,

I'm glad I could help.  If you will need the FilesAvailable and %Used values later in your script, you can add them as members of the objects.  If you would like to do that, here are some sample scripts.

foreach ($vol in $vols) {

    $vol | Add-Member -MemberType "ScriptProperty" -Name "FilesAvailable"      -Value {$this.FilesTotal - $this.FilesUsed}

    $vol | Add-Member -MemberType "ScriptProperty" -Name "FilesUsedPercentage" -Value {[Int]($this.FilesUsed / $this.FilesTotal * 100)}

}

The [Int] casts the value of ($this.FilesUsed / $this.FilesTotal * 100) as an integer.  This will match the format of the PercentageUsed property on the VolumeInfo object.  From your script it looks like you want two (2) decimal places of precision in the percent field.  If you want that, the code will look something like this...

foreach ($vol in $vols) {

    $vol | Add-Member -MemberType "ScriptProperty" -Name "FilesAvailable"      -Value {$this.FilesTotal - $this.FilesUsed}

    $vol | Add-Member -MemberType "ScriptProperty" -Name "FilesUsedPercentage" -Value {($this.FilesUsed / $this.FilesTotal * 100).ToString("N2")}

}


You may notice that the Format-Table cmdlet now aligns the FilesUsedPercentage to the left side of the column, but most of the other values are aligned to the right.  From what I can tell, this is because the value is now a String and not a number (Int, Float, etc.).  From my testing, when I cast the string as a Float -- which looked like this: -Value {[Float](($this.FilesUsed / $this.FilesTotal * 100).ToString("N2"))}, the value was aligned correctly, but it was displayed without any trailing zeros.  For example, 11.50 was displayed as 11.5.  I'll leave it to you to decide how you would like the data to be displayed.

As a final note, please be aware that PowerShell uses Bankers' Rounding.  Bankers' Rounding is slightly different than the traditional rounding taught in mathematics classes and is designed to help reduce inaccuracy when working with large amounts of rounded numbers.  If you're interested, here is a blog article explaining Bankers' Rounding in VBScript.  http://blogs.msdn.com/b/ericlippert/archive/2003/09/26/bankers-rounding.aspx.  From what I can tell, casting as an Int and using the .ToString() method both use Bankers' Rounding.

Good luck!

Bill

PowerShell commands for inodes

It looks like you've already got what you needed but in case it's useful I've been using the code below to run daily checks for volumes where maxfiles is becoming an issue. I include the function below in my Powershell profile then a single line of script can show me any volumes that need checking;

connect-NaController yourcontroller | get-NaMaxfiles -Percent 30

Hope it's helpful.

Ed.

function Get-NaMaxfiles {

    <#

.SYNOPSIS

    Find volumes where the maxfiles values is greater than a specified threshold (default 50%).

.DESCRIPTION

    Find volumes where the maxfiles values is greater than a specified threshold (default 50%).

.PARAMETER Controller

    NetApp Controller to query (defaults to current controller if not specified).

.PARAMETER Percent

    Filters the results to volumes when the %used files is greater than the number specified. Defaults to 50% if not specified.

.EXAMPLE

    connect-NaController zcgprsan1n1 | get-NaMaxfiles -Percent 30

    Get all volumes on filer zcgprsan1n1 where the number of files used is greater than 30% of the max available

#>

    [cmdletBinding()]

    Param(

        [Parameter(Mandatory=$false,

        ValueFromPipeLine=$true

        )]

        [NetApp.Ontapi.Filer.NaController]

        $Controller=($CurrentNaController)

    ,

        [Parameter(Mandatory=$false)]

        [int]

        $Percent=50

    )

    Begin {

        #check that a controller has been specified

    }

    Process {

        $vols = Get-NaVol -controller $Controller | where {$_.FilesTotal -gt 0 -and ($_.FilesUsed/$_.FilesTotal)*100 -gt $Percent}

        #check that at least one volume exists on this controller

        if ($vols.Count -gt 0) {

            foreach ($vol in $vols) {

                #calculate the percentage of files used and add a field to the Volume object with the value

                $filesPercent = [int]("{0:N2}" -f (($vol.FilesUsed/$vol.FilesTotal)*100))

                add-member -inputobject $vol -membertype noteproperty -name Controller -value $Controller.Name

                add-member -inputobject $vol -membertype noteproperty -name Used -value $filesPercent

            }

        }

        return $vols | sort Used -descending | select Controller,Name,FilesUsed,FilesTotal,Used

    }

}

Re: PowerShell commands for inodes

Ed,

That is a very nicely coded function.  Thank you for sharing it.  If I may, I would suggest two changes.

1.  If a variable named $vols already exists and "Get-NaVol -controller $Controller | where {$_.FilesTotal -gt 0 -and ($_.FilesUsed/$_.FilesTotal)*100 -gt $Percent}" returns no value (either because the connection to $Controller fails or there are no volumes that meet the criteria), the prior value of $vols will be used in the foreach command.  (I've been burned by this on one of my regular reporting scripts.)  To address the connection error, I suggets using try/catch blocks.  To ensure that a null result from the Where-Object filter does not cause the Foreach-Object cmdlet to process an existing value of $vols from a higher scope, I recommend creating a $null valued instance of the variable within the function scope.  As a result, the "if ($vols.Count -gt 0) {" line should change to "if ($vols -ne $null) {".  (Technically speaking if $vols is $null then $vols.Count will also be $null, and ($null -gt 0) evaluates as $false, so the prior if statement will function correctly.)

The new code would look like this:

     Process {

          $exception = $null

          try {

               # create a null valued instance of $vol within the local scope

               $vols = $null

               $vols = Get-NaVol -controller $Controller -ErrorAction "Stop" | where {$_.FilesTotal -gt 0 -and ($_.FilesUsed/$_.FilesTotal)*100 -gt $Percent}

               #check that at least one volume exists on this controller

               if ($vols -ne $null) {

                    foreach ($vol in $vols) {

                         #calculate the percentage of files used and add a field to the Volume object with the value

                         $filesPercent = [int]("{0:N2}" -f (($vol.FilesUsed/$vol.FilesTotal)*100))

                         add-member -inputobject $vol -membertype noteproperty -name Controller -value $Controller.Name

                         add-member -inputobject $vol -membertype noteproperty -name Used -value $filesPercent

                    }

               }

          }

     catch {

          $exception = $_

     }

     if ($exception -eq $null) {

          $returnValue = ($vols | Sort-Object -Property "Used" -Descending | Select-Object -Property "Controller","Name","FilesUsed","FilesTotal","Used"

     }

     else {

          $returnValue = $exception

     }

     return $returnValue

}

2.  The line "$filesPercent = [int]("{0:N2}" -f (($vol.FilesUsed/$vol.FilesTotal)*100))" introduces a possible precision error.  The result is rounded twice -- first to the nearest hudredth and then to the nearest integer.  For example, if the number 11.496 is rounded to the nearest hundredth and then rounded to the nearest integer, the result is 12.  However, if 11.496 is rounded to the nearest integer, the result is 11.  Therefore, I suggest the following code:

$filesPercent = [int](($vol.FilesUsed/$vol.FilesTotal)*100)

Bill

Re: PowerShell commands for inodes

Great suggestions, both added to my function. Thanks!

Note: I've changed the 'Used' value to '%FilesUsed' as there's now a Used attribute as standard on every volume (this function was written with Toolkit v1!).The final code is;

function Get-NaMaxfiles {

<#

.SYNOPSIS

    Find volumes where the maxfiles values is greater than a specified threshold (default 50%).

.DESCRIPTION

    Find volumes where the maxfiles values is greater than a specified threshold (default 50%).

.PARAMETER Controller

    NetApp Controller to query (defaults to current controller if not specified).

.PARAMETER Percent

    Filters the results to volumes when the %used files is greater than the number specified. Defaults to 50% if not specified.

.EXAMPLE

    connect-NaController zcgprsan1n1 | get-NaMaxfiles -Percent 30

    Get all volumes on filer zcgprsan1n1 where the number of files used is greater than 30% of the max available

#>

    [cmdletBinding()]

    Param(

        [Parameter(Mandatory=$false,

        ValueFromPipeLine=$true

        )]

        [NetApp.Ontapi.Filer.NaController]

        $Controller=($CurrentNaController)

    ,

        [Parameter(Mandatory=$false)]

        [int]

        $Percent=50

    )

    Begin {

        #check that a controller has been specified

    }

    Process {

        $exception = $null

        try {

            # create a null valued instance of $vol within the local scope

            $vols = $null

            $vols = Get-NaVol -controller $Controller -ErrorAction "Stop" | where {$_.FilesTotal -gt 0 -and ($_.FilesUsed/$_.FilesTotal)*100 -gt $Percent}

            #check that at least one volume exists on this controller

            if ($vols -ne $null) {

                foreach ($vol in $vols) {

                    #calculate the percentage of files used and add a field to the Volume object with the value

                    $filesPercent = [int](($vol.FilesUsed/$vol.FilesTotal)*100)

                    add-member -inputobject $vol -membertype noteproperty -name Controller -value $Controller.Name

                    add-member -inputobject $vol -membertype noteproperty -name %FilesUsed -value $filesPercent

                }

            }

        }

        catch {

            $exception = $_

        }

        if ($exception -eq $null) {

            $returnValue = ($vols | Sort-Object -Property "Used" -Descending | Select-Object -Property "Controller","Name","FilesUsed","FilesTotal","%FilesUsed")

        }

        else {

            $returnValue = $exception

        }

        return $returnValue

    }

}