Sunday, July 11, 2010

Diagram Your NetApp Volumes and LUNs in Visio With PowerShell

For starters I just want to thank Alan Renouf for his vDiagram PowerShell script which I borrowed heavily from.   There isn't much more in the code listed here than changing some naming, and swapping the NetApp OnTap module for the VMware PowerCLI stuff.  All of this was tested only in Visio 2010 so your mileage may vary.

Basically this is a very simple script that will connect to a NetApp array, find all aggregates, volumes, and LUNs on that system, and then draw their relationships in Visio.  There are a few pre-requisites to have this script work in your environment.

  1. Download the NetApp Visio stencils and extract them all into your "My Documents\My Shapes" directory.
  2. Install the NetApp Data OnTap Powershell ToolKit.
  3. Run the script and enter the FQDN of your NetApp array when prompted.
The output will draw something like the diagram listed below:




By choosing some of the other layout options in Visio, and adjusting the spacing you can easily create some pretty dynamic looking diagrams for your environment.






Pick up the script over at the NetApp forums here:  http://communities.netapp.com/docs/DOC-6411 or simply grab it from below.

$shpFile1 = "\NetApp-Logic-Icons.vss"
$shpFile2 = "\NetApp-Equipment-Icons.vss"

$FASName = read-host "Enter the FQDN of your NetApp array" 
If ($FASName -eq "") { Write-Host "No selection made, script now exiting." ; exit }

function connect-visioobject ($firstObj, $secondObj)
{
 $shpConn = $pagObj.Drop($pagObj.Application.ConnectorToolDataObject, 0, 0)

 #// Connect its Begin to the 'From' shape:
 $connectBegin = $shpConn.CellsU("BeginX").GlueTo($firstObj.CellsU("PinX"))
 
 #// Connect its End to the 'To' shape:
 $connectEnd = $shpConn.CellsU("EndX").GlueTo($secondObj.CellsU("PinX"))
}

function add-visioobject ($mastObj, $item)
{
   Write-Host "Adding $item"
  # Drop the selected stencil on the active page, with the coordinates x, y
    $shpObj = $pagObj.Drop($mastObj, $x, $y)
  # Enter text for the object
    $shpObj.Text = $item
  #Return the visioobject to be used
  return $shpObj
 }

# Create an instance of Visio and create a document based on the Basic Diagram template.
$AppVisio = New-Object -ComObject Visio.Application
$docsObj = $AppVisio.Documents
$DocObj = $docsObj.Add("Basic Network Diagram.vst")

# Set the active page of the document to page 1
$pagsObj = $AppVisio.ActiveDocument.Pages
$pagObj = $pagsObj.Item(1)

# Load a set of stencils and select one to drop
$stnPath = [system.Environment]::GetFolderPath('MyDocuments') + "\My Shapes"
$stnObj1 = $AppVisio.Documents.Add($stnPath + $shpFile1)
$FlexVOLObj = $stnObj1.Masters.Item("FlexVol")
$AggrObj = $stnObj1.Masters.Item("Raid Grp Aggregate Storage")
$LUNObj = $stnObj1.Masters.Item("Cylinder")

$stnObj2 = $AppVisio.Documents.Add($stnPath + $shpFile2)
$FASObj = $stnObj2.Masters.Item("FAS3000 Double controllers")

Connect-NaController $FASName -Credential (Get-Credential)

$allAGGR = Get-NaAggr
$allVols = Get-NaVol
$allLUNs = Get-NaLun

$y = $allAGGR.Count * 1.50 / 2
$x = 1.50

$FASObj = add-visioobject $FASObj $FASName

$x = 3.50
$y += 2

Foreach ($aggr in $allAGGR) {

 $aggrObj = add-visioobject $AggrObj $aggr.Name
 connect-visioobject $FASObj $aggrObj
 
 $y += 1.5
 
  Foreach ($volume in $allVols) {

  If ($volume.ContainingAggregate -eq $aggr.Name) {
   
   $x += 2.50  
   
   $volInfo = "Volume Name: " + $volume.Name + "`r`n" + "Total Size (GB): " + "{0:n2}" -f ($volume.SizeTotal / 1gb) + "`r`n" + "Size Used: " + "{0:n2}" -f ($volume.SizeUsed / 1gb)
   $FlexVOLObj = add-visioobject $FlexVOLObj $volInfo
   
   
    connect-visioobject $aggrObj $FlexVOLObj
   
    Foreach ($lun in $allLUNs) {
  
    $lunVol = $lun.path.split("/")
   
     If ($lunVol[2] -eq $volume.name) { 
   
     $x += 1
     $y += .50
     
     $lunInfo = "LUN Name: " + $lun.path + "`r`n" + "Total Size (GB): " + "{0:n2}" -f ($lun.Size / 1gb)
     $LUNObj = add-visioobject $LUNObj $lunInfo
     connect-visioobject $FlexVOLObj $LUNObj
     
     $x -= 1
     $y -= .50
        
     }
      
    }
  
   }

  }
  
 $x = 3.50
 $y += 2.50
 
}

# Resize to fit page
$pagObj.ResizeToFitContents()

6 comments:

Anonymous said...

Thanks for posting this. Can't wait to check it out!

Adrian Buchmann said...

Thank you for this useful script.
I had a problem using it with a german WinXP, but changing the following
$stnPath = [system.Environment]::GetFolderPath('MyDocuments') + "\My Shapes"
to
$stnPath = [system.Environment]::GetFolderPath('MyDocuments') + "\Meine Shapes"
helped.

Rajesh said...

Thanks a lot mate its really very useful stuff.

Anonymous said...

works very good with visio 2007 in my case. you do not get size of the aggregate, and the icon for aggregate is still the same (8 disks) which is a tad misleading though.

Sven Böhler said...

Hallo
Habe da ein kleines Problem. kann mir da jemand helfen?


PS C:\> .\set-NTAPdiagram.ps1
Enter the FQDN of your NetApp array: NetApp.Domain.ch
Exception calling "Add" with "1" argument(s): "
File not found."
At C:\set-NTAPdiagram.ps1:40 char:35
+ $stnObj1 = $AppVisio.Documents.Add <<<< ($stnPath + $shpFile1)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException

You cannot call a method on a null-valued expression.
At C:\set-NTAPdiagram.ps1:41 char:36
+ $FlexVOLObj = $stnObj1.Masters.Item <<<< ("FlexVol")
+ CategoryInfo : InvalidOperation: (Item:String) [], RuntimeExcep
tion
+ FullyQualifiedErrorId : InvokeMethodOnNull

You cannot call a method on a null-valued expression.
At C:\set-NTAPdiagram.ps1:42 char:33
+ $AggrObj = $stnObj1.Masters.Item <<<< ("Raid Grp Aggregate Storage")
+ CategoryInfo : InvalidOperation: (Item:String) [], RuntimeExcep
tion
+ FullyQualifiedErrorId : InvokeMethodOnNull

You cannot call a method on a null-valued expression.
At C:\set-NTAPdiagram.ps1:43 char:32
+ $LUNObj = $stnObj1.Masters.Item <<<< ("Cylinder")
+ CategoryInfo : InvalidOperation: (Item:String) [], RuntimeExcep
tion
+ FullyQualifiedErrorId : InvokeMethodOnNull

Exception calling "Add" with "1" argument(s): "
File not found."
At C:\set-NTAPdiagram.ps1:45 char:35
+ $stnObj2 = $AppVisio.Documents.Add <<<< ($stnPath + $shpFile2)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException

You cannot call a method on a null-valued expression.
At C:\set-NTAPdiagram.ps1:46 char:32
+ $FASObj = $stnObj2.Masters.Item <<<< ("FAS3000 Double controllers")
+ CategoryInfo : InvalidOperation: (Item:String) [], RuntimeExcep
tion
+ FullyQualifiedErrorId : InvokeMethodOnNull

The term 'Connect-NaController' is not recognized as the name of a cmdlet, func
tion, script file, or operable program. Check the spelling of the name, or if a
path was included, verify that the path is correct and try again.
At C:\set-NTAPdiagram.ps1:48 char:21
+ Connect-NaController <<<< $FASName
+ CategoryInfo : ObjectNotFound: (Connect-NaController:String) []
, CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

The term 'Get-NaAggr' is not recognized as the name of a cmdlet, function, scri
pt file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again.
At C:\set-NTAPdiagram.ps1:49 char:22
+ $allAGGR = Get-NaAggr <<<<
+ CategoryInfo : ObjectNotFound: (Get-NaAggr:String) [], CommandN
otFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

Aricade said...

Great Script. Works like a charm.

Did have some issues Installing the DataOntap Powershell Module. Ended up righ clicking zip file and clicking (UnBlock) button on windows 7 host.

Continued to unzipped to $env:psmodulepath. Then I was cooking!

TY