PoshCode Logo PowerShell Code Repository

Netapp SDK by Jason Ochoa 29 months ago
View followups from Jason Ochoa | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/1323"></script>download | new post

Here is a handful of functions that I use to manage netapp appliances. The code could be improved in several ways, but I think it is a good starting point and functions as a good set of examples for those interested in using the ontap SDK in powershell.

  1. #Jason Ochoa 9/16/09
  2. #Set up NaServerObject
  3. $null = [reflection.assembly]::loadfile('C:\DotNet\ManageOntap.dll')
  4. $Toaster1 = new-Object netapp.manage.naserver('Toaster1',1,0)
  5. $Toaster1.setadminuser("admin",'password')
  6.  
  7.  
  8. #-------------------functions to be remade
  9. function global:Get-DF-s ($NaServer){#this data can be gathered directly from the volume-info package
  10.         $NaElement = New-Object NetApp.Manage.NaElement(”system-cli)
  11.         $arg = New-Object NetApp.Manage.NaElement(”args”)
  12.         $arg.AddNewChild(’arg’,'df’)
  13.         $arg.AddNewChild(’arg’,'-s)
  14.         $NaElement.AddChildElement($arg)
  15.         $results= $NaServer.InvokeElem($naelement).GetChildContent(”cli-output”)
  16.         $results = $results.Split("`n")
  17.        
  18.         $ResultsObj = $results| ?{$_ -match "vol"}| %{$null = $_ -match "(?<FileSystem>(\S+))\s+(?<used>(\d+))\s+(?<saved>(\d+))\s+(?<PercentSave>(\d+))";
  19.                                                 $myobj = "" | Select-Object filesystem, usedGB, savedGB, percentsave;
  20.                                                 $myobj.filesystem = $matches.Filesystem;
  21.                                                 $myobj.usedGB = [Math]::Round([double]$matches.used /1mb, 2);
  22.                                                 $myobj.savedGB = [Math]::Round([double]$matches.saved /1mb, 2);
  23.                                                 $myobj.percentsave = [int]$matches.percentsave;
  24.                                                 ,$myobj}
  25.         ,($ResultsObj| Sort-Object filesystem)
  26. }
  27. #------------------------------sis functions
  28. function global:Get-SIS-Status ($NaServer){
  29. $naelement = New-Object netapp.manage.naelement("sis-status")
  30. $NaElement.AddNewChild('verbose','true')
  31. $Output = ([xml]($NaServer.invokeelem($naelement)).tostring()).results.'sis-object'.'dense-status'
  32. $Output =  $output | Add-Member -MemberType NoteProperty -Name "StartTime" -Value $null -PassThru |
  33.                                          Add-Member -MemberType NoteProperty -Name "Duration" -Value $null -PassThru
  34. $Output|  %{$_.Duration =(((get-date -date 1/1/1970).addhours(-7)).addseconds($_.'last-operation-end-timestamp') - ((get-date -date 1/1/1970).addhours(-7)).addseconds($_.'last-operation-begin-timestamp') )}
  35. $Output|  %{$_.StartTime = (((get-date -date 1/1/1970).addhours(-7)).addseconds($_.'last-operation-begin-timestamp'))}
  36. $Output
  37. }
  38. function global:Get-SIS-LongJobs ($NaServer){
  39. $output = Get-SIS-Status ($NaServer)
  40. $output |Sort-Object State, duration -descending| Select-Object path, duration, schedule, 'last-operation-size', State| ft -AutoSize
  41. }
  42. function global:Set-SIS-config ($NaServer, $volume, $schedule){
  43. $naelement = New-Object netapp.manage.naelement("sis-set-config")
  44. $NaElement.AddNewChild('path',$volume)
  45. $NaElement.AddNewChild('schedule',$schedule)
  46. ([xml]($NaServer.invokeelem($naelement)).tostring()).results.'sis-object'
  47. }
  48. function global:start-SIS ($NaServer, $volume){
  49. $naelement = New-Object netapp.manage.naelement("sis-start")
  50. $NaElement.AddNewChild('path',$volume)
  51. $null = ([xml]($NaServer.invokeelem($naelement)).tostring()).results.'sis-object'
  52. }
  53. function global:stop-SIS ($NaServer, $volume){
  54. $naelement = New-Object netapp.manage.naelement("sis-stop")
  55. $NaElement.AddNewChild('path',$volume)
  56. $null = ([xml]($NaServer.invokeelem($naelement)).tostring()).results.'sis-object'
  57. }
  58. function  global:Set-SIS-ON($NaServer, $volume, [switch]$SISOFF )
  59. {
  60. if (-not $SISOFF){
  61.         $naelement = New-Object netapp.manage.naelement("sis-enable")
  62.         $NaElement.AddNewChild('path',$volume)
  63.         $null = ([xml]($NaServer.invokeelem($naelement)).tostring()).results.'sis-object'
  64.         }
  65. else{
  66.         $naelement = New-Object netapp.manage.naelement("sis-disable")
  67.         $NaElement.AddNewChild('path',$volume)
  68.         $null = ([xml]($NaServer.invokeelem($naelement)).tostring()).results.'sis-object'
  69.         }
  70. }
  71. function global:Start-SIS-All ($NaServer, $MaxJobs = 4){
  72. $StartTime = get-date
  73. foreach ($path in (Get-SIS-status $NaServer|%{$_.path})){
  74.         while (@(Get-SIS-status $NaServer|?{$_.status -eq "Active"}).count -ge $MaxJobs){start-sleep 15; write-host "." -nonewline}
  75.         write-host "Starting $Path"
  76.         start-sis $NaServer $Path
  77.         Start-Sleep 5}
  78. Write-Host "This task took: $((get-date) - $StartTime)"
  79. }
  80.  
  81. #-----------------------Snapshot functions
  82. function global:get-Snap-AutoDeleteInfo ($NaServer)
  83. {
  84.         $naelement = New-Object netapp.manage.naelement("volume-list-info")
  85.         $volumes = ([xml]($NaServer.invokeelem($naelement)).tostring()).results.volumes.'volume-info'
  86.         foreach ($vol in $volumes){
  87.                 $naelement = New-Object netapp.manage.naelement("snapshot-autodelete-list-info")
  88.                 $NaElement.AddNewChild('volume',$Vol.name)
  89.                 $snapInfo = ([xml]($NaServer.invokeelem($naelement)).tostring()).results.options.'snapshot-autodelete-info'
  90.                 $myobj = "" | Select-Object Volume, state, commitment, trigger, target_free_space, delete_order, defer_delete, destroy_list
  91.                 $myobj.Volume = $vol.name
  92.                 foreach ($option in $snapInfo){$myobj.($option.'option-name') = $option.'option-value'}
  93.                 $myobj
  94.         }
  95. }
  96. function global:set-Snap-AutoDeleteInfo ($NaServer, $volume, $state="on", $commitment="try", $trigger="volume", $targer_free_space="15", $delete_order="oldest_first", $defer_delete="user_created"){
  97.         $Options = @($state, $commitment, $trigger, $targer_free_space, $delete_order, $defer_delete)
  98.         $OptionNames = @("state", "commitment", "trigger", "target_free_space", "delete_order", "defer_delete")
  99.         foreach ($Counter in (0..5)){
  100.                 $naelement = New-Object netapp.manage.naelement("snapshot-autodelete-set-option")
  101.                 $NaElement.AddNewChild('volume',$volume)
  102.                 $NaElement.AddNewChild('option-name', $OptionNames[$counter])
  103.                 $NaElement.AddNewChild('option-value',$Options[$counter])
  104.                 $null = $NaServer.invokeelem($naelement)
  105.                 }      
  106. }
  107. function global:get-Snap-List ($NaServer)
  108. {
  109.         $naelement = New-Object netapp.manage.naelement("volume-list-info")
  110.         $volumes = ([xml]($NaServer.invokeelem($naelement)).tostring()).results.volumes.'volume-info'
  111.         foreach ($vol in $volumes){
  112.                 $naelement = New-Object netapp.manage.naelement("snapshot-list-info")
  113.                 $NaElement.AddNewChild('target-type','volume’)
  114.                 $NaElement.AddNewChild('target-name',$Vol.name)
  115.                 $snapshots = ([xml]($NaServer.invokeelem($naelement)).tostring()).results.snapshots.'snapshot-info'
  116.                 foreach ($Snap in $snapshots){
  117.                         $myobj = "" | Select-Object Volume, Name, accesstime, totalMB, CTotalMB, POfUsedB, CPOfUsedB
  118.                         $myobj.Volume = $vol.name
  119.                         $myobj.name = $Snap.name
  120.                         $myobj.accesstime = ((get-date -date 1/1/1970).addhours(-7)).addseconds($Snap.'access-time')
  121.                         $myobj.totalMB = [Math]::round($Snap.total / 1kb, 2)
  122.                         $myobj.CTotalMB = [Math]::round($Snap.'cumulative-total' /1kb, 2)
  123.                         $myobj.POfUsedB = $Snap.'percentage-of-used-blocks'
  124.                         $myobj.CPOfUsedB = $Snap.'cumulative-percentage-of-used-blocks'
  125.                         $myobj
  126.                 }
  127.         }
  128. }
  129. function global:get-SnapList-Top-Total(){
  130.         $Snaps = (get-Snap-List $1504) + (get-Snap-List $1505)
  131.         "Top 20 Large Snapshots"
  132.         $Snaps|sort-object -prop totalMB -desc| select-object -first 20 | ft -AutoSize
  133.         "Top 20 Snapshot footprint"
  134.         $Snaps| Group-Object -Property volume|%{$_.group|sort-object -prop accesstime|select-object -First 1 }| sort-object -prop CtotalMB -desc| select-object -first 20|ft -AutoSize
  135.         "Top 5 Oldest Snapshots"
  136.         $Snaps| Group-Object -Property volume|%{$_.group|sort-object -prop accesstime|select-object -First 1 }| ?{$_.name -ne $null}|sort-object -prop accesstime| select-object -first 5 | ft -AutoSize
  137. }
  138. function global:rename-Snap($NaServer, $CurrentName, $newName, $volume){
  139.         $naelement = New-Object netapp.manage.naelement("snapshot-rename")
  140.         $NaElement.AddNewChild('current-name',$CurrentName)
  141.         $NaElement.AddNewChild('new-name',$newName)
  142.         $NaElement.AddNewChild('volume',$volume)
  143.         $null = $NaServer.invokeelem($naelement)
  144. }
  145. function global:remove-Snap($NaServer, $Snapshot, $volume){
  146.         $naelement = New-Object netapp.manage.naelement("snapshot-delete")
  147.         $NaElement.AddNewChild('snapshot',$Snapshot)
  148.         $NaElement.AddNewChild('volume',$volume)
  149.         $null = $NaServer.invokeelem($naelement)
  150. }
  151. function global:get-snap ($NaServer, $volume){
  152.         $naelement = New-Object netapp.manage.naelement("snapshot-list-info")
  153.         $NaElement.AddNewChild('target-type','volume’)
  154.         $NaElement.AddNewChild('target-name',$volume)
  155.         $snapshots = ([xml]($NaServer.invokeelem($naelement)).tostring()).results.snapshots.'snapshot-info'
  156.         foreach ($Snap in $snapshots){
  157.                         $myobj = "" | Select-Object Volume, Name, accesstime, totalMB, CTotalMB, POfUsedB, CPOfUsedB
  158.                         $myobj.Volume = $volume
  159.                         $myobj.name = $Snap.name
  160.                         $myobj.accesstime = ((get-date -date 1/1/1970).addhours(-7)).addseconds($Snap.'access-time')
  161.                         $myobj.totalMB = [Math]::round($Snap.total / 1kb, 2)
  162.                         $myobj.CTotalMB = [Math]::round($Snap.'cumulative-total' /1kb, 2)
  163.                         $myobj.POfUsedB = $Snap.'percentage-of-used-blocks'
  164.                         $myobj.CPOfUsedB = $Snap.'cumulative-percentage-of-used-blocks'
  165.                         $myobj
  166.                 }
  167. }
  168. function global:New-Snap ($NaServer, $SnapPrefix, $volume, $MaxSave = 5){
  169.         if ([int]$MaxSave -lt 1) {return -1}
  170.         $CurrentSnaps = get-snap $NaServer $volume
  171.         $CurrentSnaps = @($CurrentSnaps| ?{$_.name -match "^$SnapPrefix\.\d+$"}| Sort-Object -Property accesstime )
  172.         #"count: $($CurrentSnaps.count) - $MaxSave = $($CurrentSnaps.count  - $MaxSave)"
  173.         if ($CurrentSnaps.count -gt $MaxSave-1 -and $CurrentSnaps.count -gt 0) {#remove Oldest Snap
  174.                 #"hit cleanup process"
  175.                 foreach ($i in 0..($CurrentSnaps.count  - $MaxSave )){
  176.                         #"Removing: $($CurrentSnaps[0].Name)"
  177.                         remove-snap $NaServer $CurrentSnaps[0].Name $volume
  178.                         $CurrentSnaps = @($CurrentSnaps| ?{$_.name -ne $CurrentSnaps[0].Name})
  179.                         }      
  180.         }
  181.         #"current snaps after removals"
  182.         #$CurrentSnaps|%{$_.name}
  183.         if ($CurrentSnaps -ne $null){
  184.                 foreach ($Snap in $CurrentSnaps){
  185.                                 $null = $Snap.name -match "^$SnapPrefix\.(?<digit>\d+)$"
  186.                                 rename-snap $NaServer $Snap.name "$SnapPrefix.$([int]$matches.digit+1)" $volume
  187.                                 #"Renaming: $($Snap.name) -> $SnapPrefix.$([int]$matches.digit+1)"
  188.                         }
  189.                 }
  190.         $naelement = New-Object netapp.manage.naelement("snapshot-create")
  191.         $NaElement.AddNewChild('snapshot',"$SnapPrefix.0")
  192.         $NaElement.AddNewChild('volume',$volume)
  193.         $null = $NaServer.invokeelem($naelement)
  194. }
  195. # --------------- Lun functions
  196. function Set-LUN-Caption ($NaServer, $LUNpath, $Comment){
  197.         $naelement = New-Object netapp.manage.naelement("lun-set-comment")
  198.         $NaElement.AddNewChild('comment',$comment)
  199.         $NaElement.AddNewChild('path',$LUNpath)
  200.         $null = ($NaServer.invokeelem($naelement)).tostring()
  201. }
  202. function global:get-Lun-Info ($NaServer, $LUNpattern='.*'){
  203.         $naelement = New-Object netapp.manage.naelement("lun-list-info")
  204.         $LUNs = ([xml]($NaServer.invokeelem($naelement)).tostring()).results.luns.'lun-info'
  205.         $LUNs| ?{$_.path -match $LUNpattern}| Sort-Object path
  206. }
  207. function global:Map-Lun ($NaServer, $LUNpath, $iGroup, $LUNid){
  208.         $naelement = New-Object netapp.manage.naelement("lun-map")
  209.         $NaElement.AddNewChild('path',$LUNpath)
  210.         $NaElement.AddNewChild('initiator-group',$iGroup)
  211.         $NaElement.AddNewChild('lun-id',$LUNid)
  212.         $null = ($NaServer.invokeelem($naelement)).tostring()
  213. }
  214. function global:Get-LUN-Map ($NaServer, $filter ='.*'){
  215.         $LUNs = get-Lun-Info $NaServer
  216.         $Maps = foreach ($LUN in $LUNs){
  217.                 $naelement = New-Object netapp.manage.naelement("lun-map-list-info")
  218.                 $NaElement.AddNewChild('path',$LUN.path)
  219.                 $Groups = ([xml]($NaServer.invokeelem($naelement)).tostring()).results.'initiator-groups'.'initiator-group-info'
  220.                 $groups | Add-Member -MemberType noteproperty -Name path -Value $LUN.path -Force -PassThru
  221.         }
  222.         $Maps| ?{$_.'initiator-group-name' -match $filter -or $_.path -match $filter}|Sort-Object path, 'lun-id'
  223. }
  224. function global:copy-LUN-Map ($NaServer, $SourceiGroup, $DestinationiGroup, $filter = '.*'){
  225.         $LUNmaps = Get-LUN-Map $NaServer $SourceiGroup $filter
  226.         foreach ($LUNmap in $LUNmaps){
  227.                 Map-Lun $NaServer $LUNmap.path $DestinationiGroup $LUNmap.'lun-id'
  228.         }
  229. }
  230. #------------- Performance functions
  231. function list {$args}
  232. function global:Print-NaMatrix($values){
  233.         $c =list b c c c c d d d g g c d d d d g g g y y c d d d d g g g y y c d d d d g g g y y c d d d d g g g y y d g g g g y y y m m d g g g g y y y m m d g g g g y y y m m g y y y y m m m r r g y y y y m m m r r
  234.         $d = $c|%{ switch ($_) { "b" {"cyan"}; "c" {"cyan"}; "d" {"darkgreen"}; "g" {"Green"}; "y" {"Yellow"}; "m" {"magenta"}; "r" {"Red"}}}
  235.         $x=0;$values|%{$x=$x+$_}
  236.         1..100|%{if ($_ % 10 -eq 0){write-host ("{0:P2}" -f (($values[$_-1])/$x)) -for $d[$_-1]} else {write-host ("{0:P2}" -f (($values[$_-1])/$x)) -for $d[$_-1] -no}}
  237. }
  238. function global:Get-NaCounter($Filer, $counter){
  239.         $naelement = New-Object netapp.manage.naelement("perf-object-get-instances")
  240.         $NaElement.AddNewChild(’objectname’,'perf’)
  241.         $results = [xml]($Filer.invokeelem($naelement)).tostring()
  242.         $myobj = "" | Select-Object Value, Timestamp
  243.         $myobj.TimeStamp = ((get-date -date 1/1/1970).addhours(-7)).addseconds($results.results.timestamp)
  244.         $value = ($results.results.instances.'instance-data'.counters.'counter-data'|?{$_.name -eq $counter}).value
  245.         $myobj.Value = if ($value){$value} else{"Missing Counter"}
  246.         $myObj
  247. }
  248. function global:Get-NaCounter-TimeSlice($NaServer, $counter = 'disk_user_reads_latency_histogram', $timeSample = 10){
  249.         $values1 = (Get-NaCounter $NaServer $counter).Value
  250.         $values1= [regex]::split($values1,",")
  251.         Start-Sleep $timeSample
  252.         $values2 = (Get-NaCounter $NaServer $counter).Value
  253.         $values2= [regex]::split($values2,",")
  254.         $values =(0..($values1.count))|%{($values2[$_] - $values1[$_])}
  255.         $values
  256. }
  257. function global:Get-NaMatrix-Full($NaServer){
  258.         $values = (Get-NaCounter $NaServer 'cpu_disk_util_matrix').Value
  259.         $values= [regex]::split($values,",")
  260.         Print-NaMatrix $values
  261. }
  262. function global:Get-NaMatrix-TimeSlice($NaServer,$timeSample = 10){    
  263.         Print-NaMatrix (Get-NaCounter-TimeSlice $NaServer 'cpu_disk_util_matrix' $timeSample)
  264. }
  265.  
  266. #------------- Get and Set netapp options functions
  267.  
  268. function global:Set-NaOption ($NaServer, $OptionName, $OptionValue){
  269.         $naelement = New-Object netapp.manage.naelement("options-set")
  270.         $NaElement.AddNewChild('name',$OptionName)
  271.         $NaElement.AddNewChild('value',$OptionValue)
  272.         $null = [xml]($NaServer.invokeelem($naelement)).tostring()
  273.         Get-NaOption $NaServer "^$OptionName"
  274. }
  275. function global:Get-NaOption ($NaServer, $Search = '.*'){
  276.         $naelement = New-Object netapp.manage.naelement("options-list-info")
  277.         $Options = ([xml]($NaServer.invokeelem($naelement)).tostring()).results.options.'option-info'
  278.         $Options|?{$_.name -match $Search}
  279. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me