Viewing entries tagged
netapp

PowerShell: NetApp LUN monitoring with a PRTG custom sensor

PowerShell: NetApp LUN monitoring with a PRTG custom sensor

When a LUN goes offline, bad things tend to happen on the host using it. It is good to know sooner rather than later if that happens. I was looking for a way to do this and what made the most sense was using PowerShell and PRTG.

Requirements

  • PRTG installation (you can get it free for up to 100 sensors!)
    • While you don't NEED PRTG that is how this script reports back. You'll need to change what the actions are for offline LUNs if you want to do other things.
  • ONTap PowerShell toolkit
    • This will need to be installed where you are using the script.
  • A user account on the NetApp(s) that the script can leverage.

Setup

You'll need to setup:

  • The module full path for the ONTap toolkit (if different).
  • The password setup section that is commented out.
  • The username ($user) you are going to use to connect to the NetApp(s).
  • The array ($netAppControllers) of your controllers. For 7-mode simply include the controller name, for CDOT add -c after the name so the script knows which is which.
  • The $exclude variable file path. (It is best to set this up even if it is a blank text file).
[cmdletbinding()]
param(
    [string]
    $Controller,
    [string]
    $action
)
#Import the OnTap module manually using the following path.
Import-Module 'C:\Program Files (x86)\NetApp\NetApp PowerShell Toolkit\Modules\DataONTAP\dataontap.psd1'

#Encrypted password hash used to get the password securely.
$File = "D:\PRTG Network Monitor\Custom Sensors\EXEXML\lunpass.txt"

#Setup password (Do this one time or whenever you change the password!:
#[Byte[]] $key = (1..16)
#$Password = "P@ssword1" | ConvertTo-SecureString -AsPlainText -Force
#$Password | ConvertFrom-SecureString -key $key | Out-File $File

#User account used to get NetApp information.
$user                     = 'your NetApp PowerShell user account'

#Key used to decrypt password
[Byte[]] $key = (1..16)

#Import the password from the file using the key.
$pass = Get-Content $File | ConvertTo-SecureString -Key $key

#Create the credential used to connect to each NetApp controller
$netAppCredential         = New-Object System.Management.Automation.PSCredential($user,$Pass)

#Set the variable which contains all of your controllers (add -c for CDOT)
$global:NetAppControllers = @('netapp1','netapp2','netapp3-c')

#LUNs to exclude
$exclude = Get-Content 'D:\PRTG Network Monitor\Custom Sensors\EXEXML\exclude.txt'

#This sets the variable of $stopTxt to null (which is set later if there is a failed LUN)
$stopTxt = $null

The functions and switch

#This function connects to the 7-Mode controllers the way they need to be connected to, as well as C-DOT.
function Connect-NetAppController {

    
    if (($foundController).Split("-")[1] -like "*c*") { 

        $nController = $foundController.Split("-")[0]
        

        
        if (Test-Connection $nController -Count 1 -Quiet) {

       
        Connect-NcController $nController -Credential $netAppCredential | Out-Null

    
        } Else {
            
           #Write-Host `n"Unable to ping: " $nController
            
        }

    } else {

        $7Controller = $foundController

        if (Test-Connection $foundController -Count 1 -Quiet) {
        
        $7Controller = $foundController

        Connect-NaController $foundController -Credential $netAppCredential | Out-Null

       
         } Else {
            
            #Write-Host `n"Unable to ping: " $7Controller
            
        }
    } 
}

#This functions takes the object created in the switch and output the information properly for PRTG to interpret
Function Display-PRTGText {
[cmdletbinding()]
param([array]
      $PRTGObject
)   
    
    $header = '<prtg>'
    $footer = '</prtg>'

    Write-Output $header
    
    foreach ($lun in $PRTGObject) {

    if ($lun.NameOff) {
        
        $stopTxt    = $true
        $offlineLun += $lun.NameOff 
        
    }    

    if ($lun.Exclusions) {
        
        $exclude    = $true
        $excludeTxt = $lun.Exclusions
        
    }
    
    Write-Output "
    
    <result>
    <channel>Total LUNs ($($lun.Name))</channel>
    <value>$($lun.TotalLuns)</value>
    </result>
    
    <result>
    <channel>Offline LUNs ($($lun.Name))</channel>
    <value>$($lun.OfflineLuns)</value>
    </result>
    
    "   
    }

    if ($stopTxt) {
        
        Write-Output "
        
        <text>Offline LUNs: $offlineLun</text>
        
        "
    } elseif (!$stopTxt -and $exclude) {
        
        Write-Output "
        
        <text>Exclusions: $excludeTxt</text>
        
        "
    }

    Write-Output $footer    
    
}


#This switch takes action based on what you specify in the parameter. Right now there is only one: luncheck
Switch ($action) {
    
    'luncheck' {
          
        if ($controller -eq 'all') { 
    
            [array]$cModeControllers = $NetAppControllers
     
        } else {
            
            [array]$cmodecontrollers = $controller

        }
        
        #Set/Clear this array to be used at the NetApp Object
        [array]$netAppObject = $null
        
        foreach ($array in $cModeControllers) {
            $foundcontroller = $array
            $controller      = $array   
            $numLuns         = 0
            $numOn           = 0
            $numOff          = 0
            $offline         = $null
            $online          = $null
            $luns            = $null
            $omit            = $null
            $newLuns         = $null
            $text            = $null
            
            #if it is a CDOT controllers (I add -c in the name to segement them out)
            if (($foundController).Split("-")[1] -like "*c*") {

                Connect-NetAppController 
                
                $luns    = Get-NCLun | Where-Object{$_.Path -notlike "*test*"}

                if ($exclude.count -gt 0) {

                    $omit = $exclude | ForEach-Object{$no = $_;$luns | Where-Object{$_.path -like $no}}
                    $luns = $luns | Where-Object{$_.Path -notin $omit.Path}
                
                }
                
                $numLuns = $luns.count
                $offline = $luns | Where-Object{$_.Online -ne $true}
                $online  = $luns | Where-Object{$_.Online -eq $true}
                $numOff  = $offline.count
                $numOn   = $online.count       
                
                $netAppProp     = @{Name=$controller}
                $netAppProp     += @{TotalLuns=$numLuns}
                $netAppProp     += @{OfflineLuns=$numOff}
                $netAppProp     += @{OnlineLuns=$numOn}
                $netAppProp     += @{Exclusions=$exclude}
                
                if ($numOff -gt 0) {
                    
                    foreach ($off in $offline) {[array]$text += 'Lun: ' + $off.path + ' VServer: ' + $off.vserver}                
                    $netAppProp += @{NameOff=$text}
                    
                }

                $naO             = New-Object PSObject -Property $netAppProp
                $netAppObject   += $naO       
                                      
            #Else they are 7-mode so use 7-mode commands            
            } else {

                Connect-NetAppController 
                
                $luns    = Get-NALun | Where-Object{$_.Path -notlike "*test*"}  
                
                if ($exclude.count -gt 0) {
                    
                    $omit = $exclude | ForEach-Object{$no = $_;$luns | Where-Object{$_.path -like $no}}
                    $luns = $luns | Where-Object{$_.Path -notin $omit.Path}
                
                }
                
                $numLuns = $luns.count
                $offline = $luns | Where-Object{$_.Online -ne $true}
                $online  = $luns | Where-Object{$_.Online -eq $true}
                $numOff  = $offline.count
                $numOn   = $online.count
                
                $netAppProp     = @{Name=$controller}
                $netAppProp     += @{TotalLuns=$numLuns}
                $netAppProp     += @{OfflineLuns=$numOff}
                $netAppProp     += @{OnlineLuns=$numOn} 
                $netAppProp     += @{Exclusions=$exclude}
                              
                if ($numOff -gt 0) {
                    
                    foreach ($off in $offline) {[array]$text += 'Lun: ' + $off.path}           
                    $netAppProp += @{NameOff=$text}
                    
                }
                
                $naO             = New-Object PSObject -Property $netAppProp
                $netAppObject   += $naO    

            }      
        
        }
   
        Display-PRTGText $netAppObject
    
    }
}

The code lets you run the script specifying "all" controllers (which will use the array defined at the beginning of the script), or a controller of your choice.

The function Display-PRTGText takes the $netAppObject object that is built below in the switch option luncheck. It first displays the PRTG header, the LUN information, and finally the PRTG footer. 

The switch looks for the action you'd like to take. Right now there is only one, "luncheck". You can add more for different sensor types to check different things based on what you pass to -action.

Examples

To test the script, run it as follows:

.\Lun-Check.ps1 -Controller yourcontroller-c -action luncheck

The above code will execute and if all goes well it will return results with opening and closing <prtg> tags.

If there are any offline, they will be returned into the PRTG sensor via the <text> tag. 

Exclusions

You can exclude certain LUNs from being checked. If you have decommissioned a server or are testing anything that involves setting a LUN's state to be offline this can be handy. Add entries to exclude.txt line by line. You can include either the full LUN path, or anything in the path name with wildcards around it.  Please note that there is also a line that omits any LUN with "test" in the name. To change this, remove that if line.

Examples:

  • /vol/finance1/lun1
  • *finance*

The first example will omit just that one LUN, whereas the second example will omit any LUN with finance in the path. Any exclusions you do add will be noted in the sensor's message as text if no LUNs are currently offline.

Once you have verified you received the results from the script as needed, we can now perform the sensor setup in PRTG.

PRTG Setup

You'll want to perform the following steps in PRTG:

  1. Ensure you have the script in your EXEXML custom sensor folder. Example: "D:\PRTG Network Monitor\Custom Sensors\EXEXML\lun-check.ps1"
  2. Create an "EXE/Script Advanced" sensor on a device of your choice.
  3. Select the lun-check.ps1 script in the drop down.
  4. Set the following parameters: -controller all -action luncheck
  5. Modify the timeout of the script to 180 seconds.

If you do not want to use the array with all the NetApp(s) change 'all' to the name of a controller. If it is a CDOT controller, be sure to add -c to the name.

You should now see channels for total and offline LUNs.

I have it setup to show the sensor as down if there are any LUNs offline. To do this, be sure to change the channel limits accordingly. It will return the path of the LUN and the VServer it is on (CDOT) or just the path for 7-Mode. This is displayed in the sensor's message as text.

 

And finally, you'll want to tweak the notification settings of the sensor if for some reason you want it different than the parent's settings.

Full Code

[cmdletbinding()]
param(
    [string]
    $Controller,
    [string]
    $action
)
#Import the OnTap module manually using the following path.
Import-Module 'C:\Program Files (x86)\NetApp\NetApp PowerShell Toolkit\Modules\DataONTAP\dataontap.psd1'

#Encrypted password hash used to get the password securely.
$File = "D:\PRTG Network Monitor\Custom Sensors\EXEXML\lunpass.txt"

#Setup password (Do this one time or whenever you change the password!:
#[Byte[]] $key = (1..16)
#$Password = "P@ssword1" | ConvertTo-SecureString -AsPlainText -Force
#$Password | ConvertFrom-SecureString -key $key | Out-File $File

#User account used to get NetApp information.
$user                     = 'your NetApp PowerShell user account'

#Key used to decrypt password
[Byte[]] $key = (1..16)

#Import the password from the file using the key.
$pass = Get-Content $File | ConvertTo-SecureString -Key $key

#Create the credential used to connect to each NetApp controller
$netAppCredential         = New-Object System.Management.Automation.PSCredential($user,$Pass)

#Set the variable which contains all of your controllers (add -c for CDOT)
$global:NetAppControllers = @('netapp1','netapp2','netapp3-c')

#LUNs to exclude
$exclude = Get-Content 'D:\PRTG Network Monitor\Custom Sensors\EXEXML\exclude.txt'

#This sets the variable of $stopTxt to null (which is set later if there is a failed LUN)
$stopTxt = $null

#This function connects to the 7-Mode controllers the way they need to be connected to, as well as C-DOT.
function Connect-NetAppController {

    
    if (($foundController).Split("-")[1] -like "*c*") { 

        $nController = $foundController.Split("-")[0]
        

        
        if (Test-Connection $nController -Count 1 -Quiet) {

       
        Connect-NcController $nController -Credential $netAppCredential | Out-Null

    
        } Else {
            
           #Write-Host `n"Unable to ping: " $nController
            
        }

    } else {

        $7Controller = $foundController

        if (Test-Connection $foundController -Count 1 -Quiet) {
        
        $7Controller = $foundController

        Connect-NaController $foundController -Credential $netAppCredential | Out-Null

       
         } Else {
            
            #Write-Host `n"Unable to ping: " $7Controller
            
        }
    } 
}

#This functions takes the object created in the switch and output the information properly for PRTG to interpret
Function Display-PRTGText {
[cmdletbinding()]
param([array]
      $PRTGObject
)   
    
    $header = '<prtg>'
    $footer = '</prtg>'

    Write-Output $header
    
    foreach ($lun in $PRTGObject) {

    if ($lun.NameOff) {
        
        $stopTxt    = $true
        $offlineLun += $lun.NameOff 
        
    }    

    if ($lun.Exclusions) {
        
        $exclude    = $true
        $excludeTxt = $lun.Exclusions
        
    }
    
    Write-Output "
    
    <result>
    <channel>Total LUNs ($($lun.Name))</channel>
    <value>$($lun.TotalLuns)</value>
    </result>
    
    <result>
    <channel>Offline LUNs ($($lun.Name))</channel>
    <value>$($lun.OfflineLuns)</value>
    </result>
    
    "   
    }

    if ($stopTxt) {
        
        Write-Output "
        
        <text>Offline LUNs: $offlineLun</text>
        
        "
    } elseif (!$stopTxt -and $exclude) {
        
        Write-Output "
        
        <text>Exclusions: $excludeTxt</text>
        
        "
    }

    Write-Output $footer    
    
}


#This switch takes action based on what you specify in the parameter. Right now there is only one: luncheck
Switch ($action) {
    
    'luncheck' {
          
        if ($controller -eq 'all') { 
    
            [array]$cModeControllers = $NetAppControllers
     
        } else {
            
            [array]$cmodecontrollers = $controller

        }
        
        #Set/Clear this array to be used at the NetApp Object
        [array]$netAppObject = $null
        
        foreach ($array in $cModeControllers) {
            $foundcontroller = $array
            $controller      = $array   
            $numLuns         = 0
            $numOn           = 0
            $numOff          = 0
            $offline         = $null
            $online          = $null
            $luns            = $null
            $omit            = $null
            $newLuns         = $null
            $text            = $null
            
            #if it is a CDOT controllers (I add -c in the name to segement them out)
            if (($foundController).Split("-")[1] -like "*c*") {

                Connect-NetAppController 
                
                $luns    = Get-NCLun | Where-Object{$_.Path -notlike "*test*"}

                if ($exclude.count -gt 0) {

                    $omit = $exclude | ForEach-Object{$no = $_;$luns | Where-Object{$_.path -like $no}}
                    $luns = $luns | Where-Object{$_.Path -notin $omit.Path}
                
                }
                
                $numLuns = $luns.count
                $offline = $luns | Where-Object{$_.Online -ne $true}
                $online  = $luns | Where-Object{$_.Online -eq $true}
                $numOff  = $offline.count
                $numOn   = $online.count       
                
                $netAppProp     = @{Name=$controller}
                $netAppProp     += @{TotalLuns=$numLuns}
                $netAppProp     += @{OfflineLuns=$numOff}
                $netAppProp     += @{OnlineLuns=$numOn}
                $netAppProp     += @{Exclusions=$exclude}
                
                if ($numOff -gt 0) {
                    
                    foreach ($off in $offline) {[array]$text += 'Lun: ' + $off.path + ' VServer: ' + $off.vserver}                
                    $netAppProp += @{NameOff=$text}
                    
                }

                $naO             = New-Object PSObject -Property $netAppProp
                $netAppObject   += $naO       
                                      
            #Else they are 7-mode so use 7-mode commands            
            } else {

                Connect-NetAppController 
                
                $luns    = Get-NALun | Where-Object{$_.Path -notlike "*test*"}  
                
                if ($exclude.count -gt 0) {
                    
                    $omit = $exclude | ForEach-Object{$no = $_;$luns | Where-Object{$_.path -like $no}}
                    $luns = $luns | Where-Object{$_.Path -notin $omit.Path}
                
                }
                
                $numLuns = $luns.count
                $offline = $luns | Where-Object{$_.Online -ne $true}
                $online  = $luns | Where-Object{$_.Online -eq $true}
                $numOff  = $offline.count
                $numOn   = $online.count
                
                $netAppProp     = @{Name=$controller}
                $netAppProp     += @{TotalLuns=$numLuns}
                $netAppProp     += @{OfflineLuns=$numOff}
                $netAppProp     += @{OnlineLuns=$numOn} 
                $netAppProp     += @{Exclusions=$exclude}
                              
                if ($numOff -gt 0) {
                    
                    foreach ($off in $offline) {[array]$text += 'Lun: ' + $off.path}           
                    $netAppProp += @{NameOff=$text}
                    
                }
                
                $naO             = New-Object PSObject -Property $netAppProp
                $netAppObject   += $naO    

            }      
        
        }
   
        Display-PRTGText $netAppObject
    
    }
}

I wrote this to fill a need rather quickly. For error handling, the PRTG sensor itself does a good job at telling you why and where the script broke. As for variable renaming and cleanup, that is something I am always striving to do.

I hope you found this helpful, and as always feedback is appreciated!

-Ginger Ninja

     

PowerShell: Check for NetApp failed and unowned disks (CDOT)

PowerShell: Check for NetApp failed and unowned disks (CDOT)

Why I needed this

I received a call from a technician in another site one day to let me know that we had 3 amber lights in our NetApp cluster. While autosupport should have caught this, it didn't (one controller showed them pre-failed, and the other showed them as failed disks).

So I turned to my love of PowerShell and added to the NetApp functions I wrote that perform actions when connected to NetApp controllers. If you haven't seen those posts, check them out!

How to use this

You'll need to first be connected to a NetApp controller and have the NetApp PowerShell module installed. Once that part is completed, you can use the code below. I also like to set a global variable for $foregroundColor, and this script utilizes that.

The Code

$netAppSystemInfo = Get-NCNode

        Write-Host `n"Controller information (CDOT)"`n -ForegroundColor $foregroundColor

        foreach ($node in $netappSystemInfo) {
            
            Write-Host "Node" $node.Node ` -foregroundcolor $foregroundcolor
            Write-Host "Model   :" $node.NodeModel
            Write-Host "Serial #:" $node.NodeSerialNumber
            Write-Host "Location:" $node.NodeLocation
            Write-Host "Healthy?:" $node.IsNodeHealthy
            Write-Host "Uptime  :" $node.NodeUptime
            Write-Host "ONTAPver:" $node.ProductVersion `n
            
        }
$failedDisks = Get-NcDisk | ?{ $_.DiskRaidInfo.ContainerType -eq "broken" }
        
        if ($failedDisks) {
        
            Write-Host `n"There are failed disks on this NetApp cluster!" -foregroundColor Red
            Write-Host "Failed Disks:"`n -foregroundColor $foregroundcolor
            
            foreach ($disk in $failedDisks){
                
                Write-Host "Disk Name      :" $disk.DiskName
                Write-Host "Disk UID       :" $disk.DiskUID
                Write-Host "Disk Controller:" $disk.NcController
                Write-Host "Disk Bay       :" $disk.Bay
                Write-Host "Disk Shelf     :" $disk.Shelf
                Write-Host "Disk model/FW  :" $disk.Model "/" $disk.FW `n
                
                
            }
            
            $openCase = Read-Host "Would you like to open a support case?"
            if ($openCase -like "*y*") {
                
                Start-Process "http://mysupport.netapp.com/cssportal/faces/oracle/webcenter/portalapp/pages/css/casesparts/CreateCaseLanding.jspx?_adf.no-new-window-redirect=true"
                
            }
            
        }
        
        
        $unOwnedDisks =  get-NCDisk
        
        foreach ($d in $unOwnedDisks) { 

            if ($d.diskownershipinfo.OwnerNodeName -eq $null) {
                
                Write-Host `n"Unowned disks found!" -foregroundColor Red
                Write-Host "Unowned Disks:"`n -foregroundcolor $foregroundColor
                Write-Host "Disk Name:" $d.DiskName
                
                $setOwner = Read-Host "Set owner to one of the nodes in the cluster?"
                
                if ($setOwner -like "*y*") {
                    
                    $i = 0 
                    foreach ($node in $netAppSystemInfo) {
                        
                        Write-Host $i -> "Node:" $node.Node
                        $i++
                    
                }
                
                $node = Read-Host "Which node #?"
                $nodeSystemID = $netAppSystemInfo[$node].NodeSystemID
                $nodeName = $netAppSystemInfo[$node].node
                $diskname = $d.DiskName
                $confirm = Read-Host "Set disk owner for disk $diskName to:" $nodeName "with systemID" $nodeSystemID"?"
                
                if ($confirm -like "*y*") {
                    
                    Set-NCDiskOwner -DiskName $diskName -NodeId $nodeSystemID
                    
                }
                    
                    
                    
                }

            } 
        
    
        }

What it will do

It will hunt down any failed or unowned disks. It will then prompt you to open the support page to open a new case. If it finds any unowned disks, it will give you the option to assign them to the controller of your choice.

As always, let me know if you have any feedback!

-Ginger Ninja

 

PowerShell: Working with the NetApp module (part 2) 7-Mode

PowerShell: Working with the NetApp module (part 2) 7-Mode

A couple weeks ago I shared part of a script that enables you to separate out the connection to 7-Mode and CDOT controllers.

If you missed that, check it out!

Today I will share the part that expands upon what you can do with the 7-Mode information.

The Code:

Function Get-7ModeInfo {


param ($naCredentials,
       $naController)
    
    if (Get-NASystemVersion) {
        $netAppSystemInfo = Get-NASystemInfo

        Write-Host `n"Controller information (7 Mode)" -ForegroundColor $foregroundColor

        Write-Host   "System Name      : " $netAppSystemInfo.SystemName 
        Write-Host   "System ID        : " $netAppSystemInfo.SystemId
        Write-Host   "System Revision  : " $netAppSystemInfo.SystemRevision 
        Write-Host   "System Serial    : " $NetAppSystemInfo.SystemSerialNumber
    
        Write-Host `n"Partner Information" -ForegroundColor $foregroundColor

        Write-Host   "Partner          : " $netAppSystemInfo.PartnerSystemName 
        Write-Host   "Partner System ID: " $netAppSystemInfo.PartnerSystemId

        Write-Host `n"Options..." -ForegroundColor $foregroundColor
        Write-Host "1. Reset your password"
        Write-Host "2. Search through volumes"
        Write-Host "3. Volume Space Report"
        Write-Host "4. Lun Report"`n
        Write-Host "'q' drops to shell"`n

        $selection = Read-Host "Which #?"
        
        Switch ($selection) {

            1 {
    
                $userName     = $NetAppCredential.UserName 
                $oldPass      = $netAppCredential.Password | ConvertFrom-SecureString        
                $newPassword  = Get-Credential -Message "Enter new password below" -UserName "Doesn't Matter"
                $newdPassword = $newPassword.GetNetworkCredential().Password

                Set-NaUserPassword -User $userName -OldPassword $oldPass -NewPassword $newdPassword
                
                Get-7ModeInfo

            }

            2 {

            }

            3{ 

            Get-NaVol | Select @{Name="VolumeName";Expression={$_.name}},@{Name="TotalSize(GB)";Expression={[math]::Round([decimal]$_.SizeTotal/1gb,2)}},@{Name="AvailableSize(GB)";Expression={[math]::Round([decimal]$_.SizeAvailable/1gb,2)}},@{Name="UsedSize(GB)";Expression={[math]::Round([decimal]$_.SizeUsed/1gb,2)}},@{Name="SnapshotBlocksReserved(GB)";Expression={[math]::Round([decimal]$_.SnapshotBlocksReserved/1gb,2)}},SnapshotPercentReserved,Aggregate,IsDedupeEnabled,type,DiskCount,RaidStatus,Autosize,ChecksumStyle,state | Export-Csv -LiteralPath $Location\$nacontroller.csv -Force -NoTypeInformation -Verbose
            Start-Process .\$nacontroller.csv
            
            Get-7ModeInfo
            
            }

            4{

            Get-NaLun | Select Path,@{Name="TotalSize(GB)";Expression={[math]::Round([decimal]$_.TotalSize/1gb,2)}},@{Name="UsedSize(GB)";Expression={[math]::Round([decimal]$_.SizeUsed/1gb,2)}},Protocol,Online,Thin,Comment | Export-Csv -LiteralPath $Location\$nacontroller"luns".csv -Force -NoTypeInformation -Verbose
            Start-Process .\$nacontroller"luns".csv
            
            Get-7ModeInfo

            }
             
            q {Write-Host "I see 'q', dropping to shell..." -foregroundcolor $foregroundcolor;break}

            }
        }
}

This is very basic and some of the switch options are not even set up yet. I used it as a shell to get some ideas for further administration. Coming up next will will be the same thing but with CDOT commands!

As always, let me know if you have any ideas or comments.

PowerShell: Working with the NetApp module (part 1)

PowerShell: Working with the NetApp module (part 1)

I've been tasked with heading up a storage migration where I am currently employed.

We have both 7-Mode and CDOT systems here (NetApp), and I wanted a way to run different functions with varying options based on each OS. 

To do this I created a couple variables up front:

$accountRun and $NetAppControllers.

$accountRun simply gets the account name you're running PowerShell as.

$accountRun               = (Get-ChildItem ENV:username).Value

$netAppControllers is an array of your controllers.

$global:NetAppControllers = @("controller1","controller2-c")

Notice how controller2 has -c after it. This is used in the below code to delineate between 7-Mode and CDOT controllers.

function Connect-NetAppController {

    $i = 0
    Write-Host `n"NetApp Controllers"`n -ForegroundColor $foregroundColor

    foreach ($n in $NetAppControllers) { 
    
        if ($n.Split("-")[1] -like "*c*"){

            Write-Host $i -NoNewline
            Write-Host -> -NoNewLine -ForegroundColor $foregroundcolor 
            Write-Host $n.Split("-")[0]  -NoNewline
            Write-Host "(CDOT)" -ForegroundColor $foregroundColor

        } else {

            Write-Host $i -NoNewline
            Write-Host -> -NoNewLine -ForegroundColor $foregroundcolor 
            Write-Host $n 

        }

        $i++

}
    Write-Host `n

    $selection = Read-Host "Which #?"
    
    if (($netAppControllers[$selection]).Split("-")[1] -like "*c*") { 
    Write-Host ($netAppControllers[$selection]).Split("-")[0]
        $nController = $netAppControllers[$selection].Split("-")[0]
        
        Write-Host `n"Attempting to connect to: " $nController "(CDOT)"`n -ForegroundColor $foregroundColor
        
        if (Test-Connection $nController -Count 1 -Quiet) {
            
        Write-Host `n"We are able to connect to:" $nController "... gathering credentials."`n -foregroundcolor $foregroundColor
        
        $netAppCredential = Get-Credential -UserName $accountRun.ToLower() -Message "Enter NetApp Credentials for $nController"
       
        Connect-NcController $nController -Credential $netAppCredential | Out-Null

        Get-CDOTInfo $netAppCredential $nController
    
        } Else {
            
            Write-Host `n"Unable to ping: " $nController`n -foregroundcolor Red
            
        }

    } else {

        $7Controller = $NetAppControllers[$selection]
        
        Write-Host `n"Attempting to connect to: " $7Controller`n -ForegroundColor $foregroundColor

        if (Test-Connection $NetAppControllers[$selection] -Count 1 -Quiet) {
        
        $7Controller = $NetAppControllers[$selection]
            
        Write-Host `n"We are able to connect to:" $7Controller "... gathering credentials."`n -foregroundcolor $foregroundColor 
            
        $netAppCredential = Get-Credential -UserName $accountRun.ToLower() -Message "Enter NetApp Credentials for $nController"

        Connect-NaController $NetAppControllers[$selection] -Credential $netAppCredential | Out-Null

        Get-7ModeInfo $netAppCredential $NetAppControllers[$selection]
       
         } Else {
            
            Write-Host `n"Unable to ping: " $7Controller`n -foregroundcolor Red
            
        }
         
     }
  }

Let me know what you think, xor you have any ideas!