Subscribe
Accepted Solution

Hopefully simple PowerShell question

Hi PowerShell Power Users,

I'm working on a new Resize Volume command which will act on all the SnapVault destinations of a volume, as well as the source volume itself. I'm new to PowerShell and am having some problems properly munging my output into a form that can be used by other commands. To wit:

PS C:\DataONTAP PowerShell Toolkit 2.0> $VolumeName = "ngs01_nfs"


This command returns all the destinations I'm interested in resizing:

PS C:\DataONTAP PowerShell Toolkit 2.0> $svDestinations = Get-NaSnapvaultPriDestinations | Where-Object{$_.SourcePath -match "/vol/$VolumeName/"} | Select-Object -Property ChainedDestinations

PS C:\DataONTAP PowerShell Toolkit 2.0> $svDestinations

ChainedDestinations

-------------------

{dedusngs02:/vol/ngs01_nfs_sv/qt1}

The variable returned looks like a string, but it's an object

PS C:\DataONTAP PowerShell Toolkit 2.0> $svDestinations.ChainedDestinations

DestinationPath                                             DestinationSystem

---------------                                             -----------------

/vol/ngs01_nfs_sv/qt1                                       dedusngs02

A Miracle Happens Here (this is where I could use the help!) that extracts the following two variables

$DestSystem = dedusngs02

$DestVolumeName = ngs01_nfs_sv

This is simple in Perl, so since PowerShell is awesome, this must be easy...

and then I can solve my problem and run:

Connect-WFAController -Array $DestSystem

Set-NaVolSize -Name $DestVolumeName -NewSize ($TargetSize + "m") -Controller $DestSystem

Thanks for any tips!


Re: Hopefully simple PowerShell question

Hi,

$svDestinations.ChainedDestinations[0].DestinationPath should give you the path (and similar for the system). If you have more than one destination that is returned (e.g. multiple qtrees in the same volume that are snapvaulted), you can access the first destination path at $svDestinations[0].ChainedDestinations[0]DestinationPath and so on.

Hope that helps

Hendrik

Re: Hopefully simple PowerShell question

Hi Hendrik and The Community,

that helps me get to the object I need to address, which was half the battle. The other half is acting on the object in a useful manner. I've poked around at the PowerShell blogs for an equivalent to a perl command such as:

$svDestinations[0].ChainedDestinations[0]DestinationPath =~ /\/vol\/([a-z0-9_]+)\//;

$DestVolumeName = $1;

to extract the volume name string out of the path name (since I need to hand the resize cmdlet a volume name, not a path name), but I haven't found any equivalent functions. Any ideas as to how to produce similar results in PowerShell?

Cheers!

Re: Hopefully simple PowerShell question

There is a built in function called splitByDelimeter which can be used for this action.  Provide the string to split, the delimeter and then the index.  In this case the index would be 2. splitByDelimiter("/vol/test/me", "/", 2) = "test".  Just pass in your Destination Path.

Re: Hopefully simple PowerShell question

This may be a silly question, but it seems like you're much more familiar with Perl, so why not create your commands in Perl instead of PowerShell?  Wouldn't that be easier for you?

Re: Hopefully simple PowerShell question

I don't think that will work for him, Jeremy, since he's looking to do this within the Command, not within the WFA framework itself.  It needs to be a PowerShell thing, not MVEL Java.

Re: Hopefully simple PowerShell question

Here's the easy way (in PowerShell):

$DestVolumeName = $svDestinations[0].ChainedDestinations[0].DestinationPath

$DestVolumeName = $DestVolumeName.Split("/")[2]

Cheers,

Dave

Re: Hopefully simple PowerShell question

Hi,

the thought of doing it in Perl crossed my mind as well, but as there are no examples of Perl commands, I'd have a lot more trial-and-error work in figuring out how variables are passed in and how to interface with WFA itself without the WFA PowerShell module (e.g. how to call the WFA logger, etc.). The second reason was that there's an existing Powershell command that does a lot of what I want to do, so I'd prefer to modify it rather than start from scratch.

The working version looks like this:

Get-NaSnapvaultPriDestinations | Where-Object{$_.SourcePath -match "/vol/$VolumeName/"} | ForEach-Object {

    $SecondaryVolume=$_.ChainedDestinations[0].DestinationPath.split("/")[2]

    $SecondaryArray=$_.ChainedDestinations[0].DestinationSystem

...

    }

Thanks for the help!

Re: Hopefully simple PowerShell question

Just FYI, jont, I posted several Perl example commands and an example workflow that uses them to the WFA community site recently.  I used Perl to talk to DFM using just ZAPI calls.  No SSH required.   

Shortcut: https://communities.netapp.com/docs/DOC-17802

Cheers,

Dave

Re: Hopefully simple PowerShell question

Hi bdave,

Thanks for the pointer to your Perl example, I'll take a look! The Powershell command I was building (resizing a primary and all secondary destinations) is now in production testing. I'm appending the code if you're interested.

# ResizeSourceAndDestVolume Command Version 3.3

param (

  [parameter(Mandatory=$true, HelpMessage="Array name or IP address")]

  [string] $Array,

  [parameter(Mandatory=$true, HelpMessage="Name of primary volume to be modified")]

  [string]$VolumeName,

 

  [parameter(Mandatory=$true, HelpMessage="The max size of the volume while autosizing in MBytes")]

  [int]$TargetSize,

  [parameter(Mandatory=$true, HelpMessage="Maximum % full level of a volume after resize")]

  [int]$MaxFillPercentage

)

# connect to controller

Connect-WFAController -Array $Array

# Check if volume exists

$volume = Get-NaVol -Names $VolumeName -ErrorAction Stop

if($volume.State -eq "restricted")

{

    throw "Volume " + $VolumeName + " is in restricted state"

}

elseif($volume.State -eq "offline")

{

    throw "Volume " + $VolumeName + " is in offline state"

}

# If the size is 0GB and we've gotten this far, remap it to 20mb (minimum size for a volume).

# Someone apparently wants a minimally sized volume.

if($TargetSize -eq 0)

{

$TargetSize = 20

}

# Enforce the policy that a volume may not be resized to be more than (usable space) MaxFillPercentage full.

$SnapReserve = Get-NaSnapshotReserve -Name $VolumeName

$FuturePercentFull=($volume.Used) * $TargetSize / (($volume.TotalSize + $SnapReserve.Size)/1024/1024)

   

if($FuturePercentFull -gt $MaxFillPercentage)

{

    throw "Volume " + $VolumeName + " would be " + [string]$FuturePercentFull + "% full after resizing. Maximum permitted is " + [string]$MaxFillPercentage + "%"

}

Get-WFALogger -Info -message $("Resizing volume " + $VolumeName + " with value: "+ ([string]$TargetSize + "m"))

Set-NaVolSize -Name $VolumeName -NewSize ([string]$TargetSize + "m")

# Find out if the volume being changed is a source volume for a replication relationship.

# If it is, try to resize the destination volume(s) as well. The destination will be

# resized to be MaxFillPercentage full after resizing (e.g if MaxFillPercentage is 85, the volume

# will be set to be whatever size would result in an 85% full level). If this is too small, the

# autogrow policies on the nearstores will extend the volume dynamically.

Get-NaSnapvaultPriDestinations | Where-Object{$_.SourcePath -match "/vol/$VolumeName/"} | ForEach-Object {

    $SecondaryVolume=$_.ChainedDestinations[0].DestinationPath.split("/")[2]

    $SecondaryArray=$_.ChainedDestinations[0].DestinationSystem

    Connect-WFAController -Array $SecondaryArray

    $destVolume=Get-NaVol -Names $SecondaryVolume -ErrorAction Stop

    # The minimum size for a destinatino volume is 10 GB per policy.

    $NewSize=$destVolume.SizeUsed/($MaxFillPercentage/100)/1024/1024

    if($NewSize -lt 10*1024*1024*1024)

    {

        $NewSize=10*1024*1024*1024

    }

    $StringNewSize=[string]$NewSize + "m"

    $message="Resizing SnapVault destination volume " + $SecondaryVolume + " with value: " + $StringNewSize

    Get-WFALogger -Info -message $($message)

    Set-NaVolSize -Name $SecondaryVolume -NewSize $StringNewSize

}

Connect-WFAController -Array $Array

# Valid for QSM only (need to separate QSM and VSM to avoid searching for "vol1" and resizing destinations of "vol1a"

Get-NaSnapmirrorDestination | Where-Object{$_.SourceLocation -match "/vol/$VolumeName/"} | ForEach-Object {

    $SecondaryVolume=$_.DestinationLocation.split("/")[2]

    $SecondaryArray=$_.DestinationLocation.split(":")[0]

    Connect-WFAController -Array $SecondaryArray

    $destVolume=Get-NaVol -Names $SecondaryVolume -ErrorAction Stop

    $NewSize=$destVolume.SizeUsed/($MaxFillPercentage/100)

    # The minimum size for a destinatino volume is 10 GB per policy.

    if($NewSize -lt 10*1024*1024*1024)

    {

        $NewSize=10*1024*1024*1024

    }

    $StringNewSize=[string]$NewSize + "m"

    $message="Resizing Qtree SnapMirror destination volume " + $SecondaryVolume + " with value: " + $StringNewSize

    Get-WFALogger -Info -message $($message)

    Set-NaVolSize -Name $SecondaryVolume -NewSize $StringNewSize

}

Connect-WFAController -Array $Array

# Valid for VSM only

# Note: shrinking a destination will fail, as the file system in the destination will be resized only

# after a VSM update is completed.

# ***This resize is expected to fail in the unlikely event that a VSM destination is shrunk!***

Get-NaSnapmirrorDestination | Where-Object{$_.SourceLocation.split(":")[1] -eq $VolumeName} | ForEach-Object {

    $SecondaryVolume=$_.DestinationLocation.split(":")[1]

    $SecondaryArray=$_.DestinationLocation.split(":")[0]

    Connect-WFAController -Array $SecondaryArray

    $destVolume=Get-NaVol -Names $SecondaryVolume -ErrorAction Stop

    $NewSize=$destVolume.SizeUsed/($MaxFillPercentage/100)

    # The minimum size for a destinatino volume is 10 GB per policy.

    if($NewSize -lt 10*1024*1024*1024)

    {

        $NewSize=10*1024*1024*1024

    }

    $StringNewSize=[string]$NewSize + "m"

    $message="Resizing Volume SnapMirror destination volume " + $SecondaryVolume + " with value: " + $StringNewSize

    Get-WFALogger -Info -message $($message)

    Set-NaVolSize -Name $SecondaryVolume -NewSize $StringNewSize

}