SymmMetrics.psm1
# Using using module .\Progress.psm1 # # Module Declarations # Global/Private constants are available to all nested modules # These constants will be required by other nested modules & the Symm module Set-Variable -Name SGDir -Value "SGInfo" -Option Constant -Scope Global -Visibility Private -Description "SG folder"; Set-Variable -Name FADir -Value "FAInfo" -Option Constant -Scope Global -Visibility Private -Description "FA folder"; Set-Variable -Name MEDir -Value "MetInfo" -Option Constant -Scope Global -Visibility Private -Description "Symm Metrics folder"; Set-Variable -Name SGPath -Value "$PWD\$Global:SGDir" -Option Constant -Scope Global -Visibility Private -Description "SG path"; Set-Variable -Name FAPath -Value "$PWD\$Global:FADir" -Option Constant -Scope Global -Visibility Private -Description "FA path"; Set-Variable -Name MEPath -Value "$PWD\$Global:MEDir" -Option Constant -Scope Global -Visibility Private -Description "Symm Metrics path"; $Script:PureMetricsCSV = "PureMetrics.csv"; $Script:SymmMetricsCSV = "SymmMetrics.csv"; $Script:usr = $null; $Script:pw = $null; $Script:org = $null; $Script:DomainName = $null; Set-Variable -Name credExt -Value ".enc.xml" -Option Constant -Scope Script; # # Non-Exported Functions . $PSScriptRoot\Local\Set-Ignore-SelfSignedCerts.ps1 . $PSScriptRoot\Local\Get-JSON-RequestBody.ps1 . $PSScriptRoot\Local\ConvertSize.ps1 . $PSScriptRoot\Local\Convert-UTC.ps1 . $PSScriptRoot\Local\Export-PSCredentials.ps1 . $PSScriptRoot\Local\Import-PSCredentials.ps1 . $PSScriptRoot\Local\Get-ArrayInfoXML.ps1 # XML Get Functions function Get-FA-SGPorts { # Get a list of port groups masked to a specific FA param ([string]$dirport) $URI = "https://$userver/univmax/restapi/$Script:prv/symmetrix/" + "$Script:sidsn/portgroup?dir_port=" + $dirport; try { $resp = Invoke-RestMethod -Method Get -Uri $URI -Headers $Headers2; return $resp } catch { Write-Host $_ -ForegroundColor Magenta Write-Host "URI: $URI" -ForegroundColor Yellow return $null } } function Get-MaskingView { param([string]$mv) try { $URI = "https://$userver/univmax/restapi/$Script:prv/symmetrix/" + "$Script:sidsn/maskingview/" + $mv; $resp = Invoke-RestMethod -Method Get -Uri $URI -Headers $Headers2; # return Masking view details. return $resp } catch { #Write-Host $_ -ForegroundColor Magenta #Write-Host "URI: $URI" -ForegroundColor Yellow #exit } } function Get-PGViews { param ([ProgressManager]$pm) begin { }; process { $pg = $_ $URI = "https://$userver/univmax/restapi/$Script:prv/symmetrix/" + "$Script:sidsn/maskingview?port_group_name=" + $pg; $PSCmdlet.WriteProgress( $pm.GetCurrentProgressRecord(3, "Getting view info for $pg")) try { $resp = Invoke-RestMethod -Method Get -Uri $URI -Headers $Headers2; } catch { Write-Host $_ -ForegroundColor Magenta Write-Host "URI: $URI" -ForegroundColor Yellow return $null } $mviews = $resp.listMaskingViewResult.maskingViewId if ($mviews -ne $null) { $childv, $parentv = $mviews.Split(" "); if ($parentv -ne $null) { $childv = $parentv } # ignore parent view & replace with child $vresp = Get-MaskingView $childv # Create a PSObject containing View info of port groups masked to a director port. $PGview = New-Object -typename PSObject $val = $vresp.getMaskingViewResult.maskingview.maskingViewId if ($val -ne $null) { $PGview | Add-Member -MemberType NoteProperty -Name "View" -Value $val $PGview | Add-Member -MemberType NoteProperty -Name "Initiator_ig" -Value $vresp.getMaskingViewResult.maskingview.hostId $PGview | Add-Member -MemberType NoteProperty -Name "Storage_sg" -Value $vresp.getMaskingViewResult.maskingview.storageGroupId $PGview | Add-Member -MemberType NoteProperty -Name "Port_pg" -Value $vresp.getMaskingViewResult.maskingview.portGroupID $Script:PGViews += $PGview; } } else { Write-Host "$pg is not in a masking view" } } end { }; } function Get-ArrayKeyInfo { param ([string]$userver) begin {$Script:ArrayKeys = @();} process { $Keys = New-Object -typename PSObject # $_ is System.Xml.XmlElement $Keys | Add-Member -MemberType NoteProperty -Name "sid" -Value $_.symmetrixId $sid = $_.symmetrixId if ($sid -ne $null) { # filter out null responses typically for newly added arrays. $sutc = $_.firstAvailableDate # Convert to local time $sutc10 = $sutc.Substring(0,10); $Keys | Add-Member -MemberType NoteProperty -Name "start" -Value $sutc10 $start = Convert-UTC $sutc10 $Keys | Add-Member -MemberType NoteProperty -Name "localstart" -Value $start # Convert to local time $eutc = $_.lastAvailableDate $eutc10 = $eutc.Substring(0,10) $Keys | Add-Member -MemberType NoteProperty -Name "end" -Value $eutc10 $end = Convert-UTC $eutc10 $Keys | Add-Member -MemberType NoteProperty -Name "localend" -Value $end $Keys | Add-Member -MemberType NoteProperty -Name "uniserver" -Value $userver $Script:ArrayKeys += $Keys; } } end {} } function Get-FEKeyInfo { param ([string]$userver, [string]$sidsn) begin {$Script:FEKeys = @();} process { $Keys = New-Object -typename PSObject # $_ is System.Xml.XmlElement $Keys | Add-Member -MemberType NoteProperty -Name "sid" -Value $sidsn $Keys | Add-Member -MemberType NoteProperty -Name "fedir" -Value $_.directorID $sutc = $_.firstAvailableDate # Convert to local time $sutc10 = $sutc.Substring(0,10); $Keys | Add-Member -MemberType NoteProperty -Name "start" -Value $sutc10 $start = Convert-UTC $sutc10 $Keys | Add-Member -MemberType NoteProperty -Name "localstart" -Value $start # Convert to local time $eutc = $_.lastAvailableDate $eutc10 = $eutc.Substring(0,10) $Keys | Add-Member -MemberType NoteProperty -Name "end" -Value $eutc10 $end = Convert-UTC $eutc10 $Keys | Add-Member -MemberType NoteProperty -Name "localend" -Value $end $Keys | Add-Member -MemberType NoteProperty -Name "uniserver" -Value $userver $Script:FEKeys += $Keys; } end {} } function Get-SGKeyInfo { param ([string]$userver, [string]$sidsn) begin {$Script:SGKeys = @();} process { $Keys = New-Object -typename PSObject # $_ is System.Xml.XmlElement $Keys | Add-Member -MemberType NoteProperty -Name "sid" -Value $sidsn $Keys | Add-Member -MemberType NoteProperty -Name "StorageGroup" -Value $_.storageGroupID $sutc = $_.firstAvailableDate # Convert to local time $sutc10 = $sutc.Substring(0,10); $Keys | Add-Member -MemberType NoteProperty -Name "start" -Value $sutc10 $start = Convert-UTC $sutc10 $Keys | Add-Member -MemberType NoteProperty -Name "localstart" -Value $start # Convert to local time $eutc = $_.lastAvailableDate $eutc10 = $eutc.Substring(0,10) $Keys | Add-Member -MemberType NoteProperty -Name "end" -Value $eutc10 $end = Convert-UTC $eutc10 $Keys | Add-Member -MemberType NoteProperty -Name "localend" -Value $end $Keys | Add-Member -MemberType NoteProperty -Name "uniserver" -Value $userver $Script:SGKeys += $Keys; } end {} } function Get-Array-SN { param([string]$sid1) $URI = "https://$userver/univmax/restapi/performance/Array/keys" Try { $resp = Invoke-RestMethod -Method Get -Uri $URI -Headers $Headers } catch { Write-Host $_ -ForegroundColor Red Write-Host $URI -ForegroundColor Red return $null } if ($resp.gettype().name -eq "XmlDocument") { $resp.arrayKeyResult.arrayInfo | Get-ArrayKeyInfo $URIserver foreach ($vmax in $Script:ArrayKeys) { $sid = $vmax.sid $sid4 = $sid.Substring(8,4); if ($sid1 -eq $sid4) { return $sid } } Write-Host "Array $sid1 was not found" -ForegroundColor Red return $null } else { Write-Host "XML data not returned from: Get-Array-SN" -ForegroundColor Red Write-Host $URI -ForegroundColor Yellow return $null } } function Get-SG-CapInfo { param([string]$storageGroup) $URI = "https://$userver/univmax/restapi/$Script:prv/symmetrix/$Script:sidsn/storagegroup/$storageGroup" try { $resp = Invoke-RestMethod -Method Get -Uri $URI -Headers $Headers2 } Catch { Write-Host $_ -ForegroundColor Magenta Write-Host "URI: $URI" -ForegroundColor Yellow return $null } $CapGB = $resp.getstorageGroupResult.storagegroup.cap_gb $Vols = $resp.getstorageGroupResult.storagegroup.num_of_vols $capmet = $CapGB + "_" + $Vols; return $capmet; } function Get-SGInfo { param([string]$sid4) begin { }; process { # $_ is System.Xml.XmlElement $storageGroupID = $_.StorageGroupID ForEach ($storageGroup in $_.StorageGroupID) { $SGInfo = New-Object -typename PSObject $SGInfo | Add-Member -MemberType NoteProperty -Name "StorageGroup" -Value $storageGroup $SGInfo | Add-Member -MemberType NoteProperty -Name "Sid" -Value $sid4 $URI = "https://$userver/univmax/restapi/$Script:prv/symmetrix/$Script:sidsn/storagegroup/$storageGroup" $PSCmdlet.WriteProgress( $pm.GetCurrentProgressRecord(1, "Getting $storageGroup Metrics on $sid4")) try { $resp = Invoke-RestMethod -Method Get -Uri $URI -Headers $Headers2 } Catch { Write-Host $_ -ForegroundColor Magenta Write-Host "URI: $URI" -ForegroundColor Yellow return $null } $val = [Math]::Round($resp.getStorageGroupResult.storageGroup.cap_gb) $va6 = $val.ToString().PadLeft(6,'0'); $SGInfo | Add-Member -MemberType NoteProperty -Name "Size (GB)" -Value $va6; $val = $resp.getStorageGroupResult.storageGroup.num_of_vols $va4 = $val.ToString().PadLeft(4,'0'); $SGInfo | Add-Member -MemberType NoteProperty -Name "Vols" -Value $va4 $SGInfo | Add-Member -MemberType NoteProperty -Name "View" -Value $resp.getStorageGroupResult.storageGroup.maskingview $SGInfo | Add-Member -MemberType NoteProperty -Name "Views" -Value $resp.getStorageGroupResult.storageGroup.num_of_masking_views $SGInfo | Add-Member -MemberType NoteProperty -Name "Type" -Value $resp.getStorageGroupResult.storageGroup.type $SGInfo | Add-Member -MemberType NoteProperty -Name "Policy" -Value $resp.getStorageGroupResult.storageGroup.fast_policy_name $SGInfo | Add-Member -MemberType NoteProperty -Name "Priority" -Value $resp.getStorageGroupResult.storageGroup.fast_policy_priority $SGInfo | Add-Member -MemberType NoteProperty -Name "Parent" -Value $resp.getStorageGroupResult.storageGroup.num_of_parent_sgs $SGInfo | Add-Member -MemberType NoteProperty -Name "Child" -Value $resp.getStorageGroupResult.storageGroup.num_of_child_sgs $SGInfo | Add-Member -MemberType NoteProperty -Name "QoS-IOps" -Value $resp.getStorageGroupResult.storageGroup.hostIOLimit.host_io_limit_io_sec $SGInfo | Add-Member -MemberType NoteProperty -Name "QoS-MBps" -Value $resp.getStorageGroupResult.storageGroup.hostIOLimit.host_io_limit_mb_sec $Script:SGInfo += $SGInfo; } } end { }; } # # Other XML Functions function Add-MetInfoPath { New-Item -Path $PWD\$Global:MEDir -ItemType Directory | Out-Null; $amXML = $Global:MEPath + "\" + "ArrayMetrics.xml" $feXML = $Global:MEPath + "\" + "FrontEnd.xml" $qdXML = $Global:MEPath + "\" + "QDC-FrontEnd.xml" $sgXML = $Global:MEPath + "\" + "SGPerformance.xml" Copy-Item -Path $PSScriptRoot\Data\ArrayMetrics.xml -Destination $amXML; Copy-Item -Path $PSScriptRoot\Data\FrontEnd.xml -Destination $feXML; Copy-Item -Path $PSScriptRoot\Data\QDC-FrontEnd.xml -Destination $qdXML; Copy-Item -Path $PSScriptRoot\Data\SGPerformance.xml -Destination $sgXML; } function Get-Keys-JSON { param ([string]$keytype) if ($sidr -eq "0000") { Write-Host "Must specify a SID value for $report report" -ForegroundColor Red; return $null } else { # Get the full symmetrix SN $Script:sidsn = Get-Array-SN $sidr $jsonBody = Get-JSON-RequestBody $Script:sidsn } $URI = "https://$userver/univmax/restapi/performance/" + "$keytype/keys" try { $resp = Invoke-RestMethod -Method Post -Uri $URI -Headers $Headers1 -Body $jsonBody; return $resp } catch { Write-Host $_ -ForegroundColor Magenta Write-Host "URI: $URI" -ForegroundColor Yellow return $null } } function Show-Metrics { begin { $ArrayMetrics = @(); } process { $Met = New-Object -typename PSObject # $_ is System.Xml.XmlElement $ts = $_.timestamp $utc = $ts.Substring(0,10); $ts = Convert-UTC $utc; if ($report -match "Summary") { $Met | Add-Member -MemberType NoteProperty -Name "Array" -Value $Script:ArrayNam; $Met | Add-Member -MemberType NoteProperty -Name "Model" -Value $Script:ArrayMod; } $Met | Add-Member -MemberType NoteProperty -Name "Time Stamp" -Value $ts $iorate = [Math]::Round($_.HostIOs) $Met | Add-Member -MemberType NoteProperty -Name "IO (ps)" -Value $iorate $readrt = [Math]::Round($_.ReadResponseTime,1); $Met | Add-Member -MemberType NoteProperty -Name "Read RT (ms)" -Value $readrt $writert = [Math]::Round($_.WriteResponseTime,1); $Met | Add-Member -MemberType NoteProperty -Name "Write RT (ms)" -Value $writert $readps = [Math]::Round($_.HostMBReads) $Met | Add-Member -MemberType NoteProperty -Name "Reads (MB)" -Value $readps $writeps = [Math]::Round($_.HostMBWritten) $Met | Add-Member -MemberType NoteProperty -Name "Writes (MB)" -Value $writeps $readpct = [Math]::Round($_.PercentReads) $Met | Add-Member -MemberType NoteProperty -Name "READ %" -Value $readpct $hitpct = [Math]::Round($_.PercentHit) $Met | Add-Member -MemberType NoteProperty -Name "HIT %" -Value $hitpct $ArrayMetrics += $Met } end { if ($report -match "Summary") { $Script:SumMetrics += $ArrayMetrics[$ArrayMetrics.Length - 1]; } else { return $ArrayMetrics } } } function Get-SGMetrics-Summary { param ([string]$sgID, [int]$count, [string]$sid4) begin { $tsmax = "0"; $IOmax = "0"; $IOsum = 0; $RIOmax = "0"; $RIOsum = 0; $WIOmax = "0"; $MBmax = "0"; $MBsum = 0; $RMBmax = "0"; $RMBsum = 0; $WMBmax = "0"; $WMBsum = 0; $RTmax = "0"; $RTsum = 0; $RRTmax = "0"; $RRTsum = 0; $WRTmax = "0"; $WRTsum = 0; $RPmax = "0"; $RPsum = 0; $WPmax = "0"; $WPsum = 0; $IOSmax = "0"; $IOSsum = 0; $RSmax = "0"; $RSsum = 0; $WSmax = "0"; $WSsum = 0; $BSmax = "0"; $BSsum = 0; $XSTmax = "0"; $XSTsum = 0; $mSTmax = "0"; $MSTsum = 0; } process { if ($_."IO (ps)" -gt $IOmax) { $IOmax = $_."IO (ps)"; } $IOsum += $_."IO (ps)"; if ($_."Read IO (ps)" -gt $RIOmax) { $RIOmax = $_."Read IO (ps)"; } $RIOsum += $_."Read IO (ps)"; if ($_."Write IO (ps)" -gt $WIOmax) { $WIOmax = $_."Write IO (ps)"; } $WIOsum += $_."Write IO (ps)"; if ($_."MB (ps)" -gt $MBmax) { $MBmax = $_."MB (ps)"; } $MBsum += $_."MB (ps)"; if ($_."Read MB (ps)" -gt $RMBmax) { $RMBmax = $_."Read MB (ps)"; } $RMBsum += $_."Read MB (ps)"; if ($_."Write MB (ps)" -gt $WMBmax) { $WMBmax = $_."Write MB (ps)"; } $WMBsum += $_."Write MB (ps)"; if ($_."Response Time (ms)" -gt $RTmax) { $RTmax = $_."Response Time (ms)"; } $RTsum += $_."Response Time (ms)"; if ($_."ReadRT(ms)" -gt $RRTmax) { $RRTmax = $_."ReadRT(ms)"; } $RRTsum += $_."ReadRT(ms)"; if ($_."WriteRT(ms)" -gt $WRTmax) { $WRTmax = $_."WriteRT(ms)"; } $WRTsum += $_."WriteRT(ms)"; if ($_."Read %" -gt $RPmax) { $RPmax = $_."Read %"; } $RPsum += $_."Read %"; if ($_."Write %" -gt $WPmax) { $WPmax = $_."Write %"; } $WPsum += $_."Write %"; if ($_."AvgIOSize" -gt $IOSmax) { $IOSmax = $_."AvgIOSize"; } $IOSsum += $_."AvgIOSize"; if ($_."AvgReadSize" -gt $RSmax) { $RSmax = $_."AvgReadSize"; } $RSsum += $_."AvgReadSize"; if ($_."AvgWriteSize" -gt $WSmax) { $WSmax = $_."AvgWriteSize"; } $WSsum += $_."AvgWriteSize"; <# if ($_."BlockSize" -gt $BSmax) { $BSmax = $_."BlockSize"; } $BSsum += $_."BlockSize"; if ($_."MaxIOServiceTime" -gt $XSTmax) { $XSTmax = $_."MaxIOServiceTime"; } $XSTsum += $_."MaxIOServiceTime"; if ($_."MinIOServiceTime" -gt $mSTmax) { $mSTmax = $_."MinIOServiceTime"; } $mSTsum += $_."MinIOServiceTime"; #> } end { $Sum = New-Object -typename PSObject; $Sum | Add-Member -MemberType NoteProperty -Name "TimeStamp" -Value $_.timestamp $Sum | Add-Member -MemberType NoteProperty -Name "VMAX" -Value $sid4 $Sum | Add-Member -MemberType NoteProperty -Name "SG" -Value $sgID #$va6 = $val.ToString().PadLeft(6,'0'); $IOavg = [Math]::Round(($IOsum / $count),1); $Sum | Add-Member -MemberType NoteProperty -Name "IO Max (ps)" -Value $IOmax $Sum | Add-Member -MemberType NoteProperty -Name "IO Avg (ps)" -Value $IOavg $RIOavg = [Math]::Round(($RIOsum / $count),1); $Sum | Add-Member -MemberType NoteProperty -Name "Read IO Max(ps)" -Value $RIOmax $Sum | Add-Member -MemberType NoteProperty -Name "Read IO Avg(ps)" -Value $RIOavg $WIOavg = [Math]::Round(($WIOsum / $count),1); $Sum | Add-Member -MemberType NoteProperty -Name "Write IO Max(ps)" -Value $WIOmax $Sum | Add-Member -MemberType NoteProperty -Name "Write IO Avg(ps)" -Value $WIOavg $MBavg = [Math]::Round(($MBsum / $count),1); $Sum | Add-Member -MemberType NoteProperty -Name "MB Max(ps)" -Value $MBmax $Sum | Add-Member -MemberType NoteProperty -Name "MB Avg(ps)" -Value $MBavg $RMBavg = [Math]::Round(($RMBsum / $count),1); $Sum | Add-Member -MemberType NoteProperty -Name "Read MB Max(ps)" -Value $RMBmax $Sum | Add-Member -MemberType NoteProperty -Name "Read MB Avg(ps)" -Value $RMBavg $WMBavg = [Math]::Round(($WMBsum / $count),1); $Sum | Add-Member -MemberType NoteProperty -Name "Write MB Max(ps)" -Value $WMBmax $Sum | Add-Member -MemberType NoteProperty -Name "Write MB Min(ps)" -Value $WMBavg $RTavg = [Math]::Round(($RTsum / $count),1); $Sum | Add-Member -MemberType NoteProperty -Name "Response Time Max(ms)" -Value $RTmax $Sum | Add-Member -MemberType NoteProperty -Name "Response Time Avg(ms)" -Value $RTavg $RRTavg = [Math]::Round(($RTsum / $count),1); $Sum | Add-Member -MemberType NoteProperty -Name "Read RT Max(ms)" -Value $RRTmax $Sum | Add-Member -MemberType NoteProperty -Name "Read RT Avg(ms)" -Value $RRTavg $WRTavg = [Math]::Round(($WRTsum / $count),1); $Sum | Add-Member -MemberType NoteProperty -Name "Write RT Max(ms)" -Value $WRTmax $Sum | Add-Member -MemberType NoteProperty -Name "Write RT Avg(ms)" -Value $WRTavg $RPavg = [Math]::Round(($RPsum / $count),1); $Sum | Add-Member -MemberType NoteProperty -Name "Read Max%" -Value $RPmax $Sum | Add-Member -MemberType NoteProperty -Name "Read Avg%" -Value $RPavg $WPavg = [Math]::Round(($WPsum / $count),1); $va8 = "$WPmax / $WPAvg" $Sum | Add-Member -MemberType NoteProperty -Name "Write Max%" -Value $WPmax $Sum | Add-Member -MemberType NoteProperty -Name "Write Avg%" -Value $WPavg $IOSavg = [Math]::Round(($IOSsum / $count),1); $Sum | Add-Member -MemberType NoteProperty -Name "AvgIOSize Max" -Value $IOSmax $Sum | Add-Member -MemberType NoteProperty -Name "AvgIOSize Avg" -Value $IOSavg $RSavg = [Math]::Round(($RSsum / $count),1); $Sum | Add-Member -MemberType NoteProperty -Name "AvgReadSize Max" -Value $RSmax $Sum | Add-Member -MemberType NoteProperty -Name "AvgReadSize Avg" -Value $RSavg $WSavg = [Math]::Round(($WSsum / $count),1); $Sum | Add-Member -MemberType NoteProperty -Name "AvgWriteSize Max" -Value $WSmax $Sum | Add-Member -MemberType NoteProperty -Name "AvgWriteSize Avg" -Value $WSavg <# $BSavg = [Math]::Round(($BSsum / $count),1); $va8 = "$BSmax / $BSAvg" $Sum | Add-Member -MemberType NoteProperty -Name "BlockSize" -Value $va8 $XSTavg = [Math]::Round(($XSTsum / $count),1); $va8 = "$XSTmax / $XSTAvg" $Sum | Add-Member -MemberType NoteProperty -Name "MaxIOServiceTime" -Value $va8 $mSTavg = [Math]::Round(($mSTsum / $count),1); $va8 = "$mSTmax / $mSTAvg" $Sum | Add-Member -MemberType NoteProperty -Name "MinIOServiceTime" -Value $va8 #> if ($csv) { $capmet = Get-SG-CapInfo $sgID $CapGB, $Vols = $capmet.Split("_"); $va6 = [Math]::Round($CapGB,1) $Sum | Add-Member -MemberType NoteProperty -Name "Capacity (gb)" -Value $va6 $va6 = [Math]::Round($Vols,1) $Sum | Add-Member -MemberType NoteProperty -Name "Volumes" -Value $va6 } if ($csv) { $Script:SGMetSum += $Sum } if ($con) { return $Sum }; } } function Submit-StorageGroupsFA { param ([Object]$resp, [string]$sidsn, [string]$dirport, [ProgressManager]$pm) $resp.storageGroupKeyResult.storageGroupInfo[0] | Get-SGKeyInfo $URIserver $sidsn foreach ($sg in $Script:SGKeys) { # only one entry in array $sid = $sg.sid $sid4 = $sidsn.Substring(8,4); $localstart = $sg.localstart; $start = $sg.start $localend = $sg.localend; $end = $sg.end $uniserver = $sg.uniserver; if ($Script:noluv) { $Script:noluv = $false; if ($con) { Write-Host "VMAX: $sid4 on Unisphere Server $uniserver" -ForegroundColor Blue Write-Host " Performance Data Range" -ForegroundColor Yellow Write-Host " Start: $localstart (UTC:$start)" -ForegroundColor Yellow Write-Host " End: $localend (UTC:$end)" -ForegroundColor Yellow } else { $title = "$report for $sid4 on $UNIserver_NODOM" } } #Load Metrics XML file for request content if (!(Test-Path $Global:MEPath)) { Add-MetInfoPath } $xmlFile = $Global:MEPath + "\" + "SGPerformance.xml" #$metFile = Get-ChildItem -Path $Global:MEPath | Where-Object {$_.PSChildName -eq $xmlFile} if (Test-Path $xmlFile) { $metXML = new-object "System.Xml.XmlDocument" $metXML.Load($xmlFile); } else { Write-Host "Metrics file not found, $xmlFile - Submit-StorageGroupsFA" -ForegroundColor Red break } # [int]$iend = $end; $iend -= $secs; # Getting past time of performance [string]$start = $iend; $start += "000"; $end += "000"; # Update Metrics XML with current parameter values for this Storage Group. $metXML.storageGroupParam.startdate = $start; $metXML.storageGroupParam.enddate = $end; $metXML.storageGroupParam.symmetrixId = $sid; ForEach ($mv in $Script:PGViews) { $sgId = $mv.Storage_sg $metXML.storageGroupParam.storageGroupId = $sgId; #$metXML.Save($metFile); $userver = $uniserver + $URIport; $URI = "https://$userver/univmax/restapi/performance/StorageGroup/metrics" $PSCmdlet.WriteProgress( $pm.GetCurrentProgressRecord(4, "Getting Storage Group Metrics for $sgId")) try { $metResp = Invoke-RestMethod -Method Post -Uri $URI -Headers $Headers -Body $metXML; } catch { Write-Host $_ -ForegroundColor Red Write-Host $URI "@ At line 614" -ForegroundColor Red return $null } $count = $metResp.iterator.count $metResp.iterator.resultList.result | Get-SGMetricsObj $sgId $count $dirport } } } function Get-FAPortsObj { begin {} process { $Met = New-Object -typename PSObject # $_ is System.Xml.XmlElement $Met | Add-Member -MemberType NoteProperty -Name "FADir" -Value $_.directorId $Met | Add-Member -MemberType NoteProperty -Name "FAPort" -Value $_.portID $Script:FAPorts += $Met } end {} } function Get-FAMetricsObj { param ([string]$fedir, [int]$count) begin {[int]$idx = 0;} process { $idx += 1; if ($count -eq 0 -or $idx -eq $count) { $Met = New-Object -typename PSObject # $_ is System.Xml.XmlElement #$_ | Get-Member | Out-Host #Read-Host "waiting" $ts = $_.timestamp $utc = $ts.Substring(0,10); $ts = Convert-UTC $utc; $Met | Add-Member -MemberType NoteProperty -Name "TimeStamp" -Value $ts $Met | Add-Member -MemberType NoteProperty -Name "FADir" -Value $fedir $percentbusy = [Math]::Round($_.PercentBusy) $Met | Add-Member -MemberType NoteProperty -Name "Busy %" -Value $percentbusy $iorate = [Math]::Round($_.HostIOs) $Met | Add-Member -MemberType NoteProperty -Name "IO (ps)" -Value $iorate $readrt = [Math]::Round($_.ReadResponseTime,1); $Met | Add-Member -MemberType NoteProperty -Name "Read (ms)" -Value $readrt $writert = [Math]::Round($_.WriteResponseTime,1); $Met | Add-Member -MemberType NoteProperty -Name "Write (ms)" -Value $readrt $mbps = [Math]::Round($_.HostMBs) $Met | Add-Member -MemberType NoteProperty -Name "MB (ps)" -Value $mbps $qdu = [Math]::Round($_.QueueDepthUtilization) $Met | Add-Member -MemberType NoteProperty -Name "QDU" -Value $qdu $Script:FAMetrics += $Met } } end {} } function Get-QDCMetricsObj { param ([string]$sid4, [string]$fedir, [int]$count) begin {[int]$idx = 0;} process { $idx += 1; #if ($count -eq 0 -or $idx -eq $count) { $Met = New-Object -typename PSObject # $_ is System.Xml.XmlElement $ts = $_.timestamp $utc = $ts.Substring(0,10); $ts = Convert-UTC $utc; $Met | Add-Member -MemberType NoteProperty -Name "Array" -Value $sid4 $Met | Add-Member -MemberType NoteProperty -Name "TimeStamp" -Value $ts $Met | Add-Member -MemberType NoteProperty -Name "FADir" -Value $fedir $val = [Math]::Round($_.QueueDepthUtilization,1); $Met | Add-Member -MemberType NoteProperty -Name "QDU%" -Value $val $val = [Math]::Round($_.QUEUE_DEPTH_COUNT_RANGE_9,1); $Met | Add-Member -MemberType NoteProperty -Name "QDC-9" -Value $val $val = [Math]::Round($_.QUEUE_DEPTH_COUNT_RANGE_8,1) $Met | Add-Member -MemberType NoteProperty -Name "QDC-8" -Value $val $val = [Math]::Round($_.QUEUE_DEPTH_COUNT_RANGE_7,1) $Met | Add-Member -MemberType NoteProperty -Name "QDC-7" -Value $val $val = [Math]::Round($_.QUEUE_DEPTH_COUNT_RANGE_6,1) $Met | Add-Member -MemberType NoteProperty -Name "QDC-6" -Value $val $val = [Math]::Round($_.QUEUE_DEPTH_COUNT_RANGE_5,1) $Met | Add-Member -MemberType NoteProperty -Name "QDC-5" -Value $val $val = [Math]::Round($_.QUEUE_DEPTH_COUNT_RANGE_4,1) $Met | Add-Member -MemberType NoteProperty -Name "QDC-4" -Value $val $val = [Math]::Round($_.QUEUE_DEPTH_COUNT_RANGE_3,1) $Met | Add-Member -MemberType NoteProperty -Name "QDC-3" -Value $val $val = [Math]::Round($_.QUEUE_DEPTH_COUNT_RANGE_2,1) $Met | Add-Member -MemberType NoteProperty -Name "QDC-2" -Value $val $val = [Math]::Round($_.QUEUE_DEPTH_COUNT_RANGE_1,1) $Met | Add-Member -MemberType NoteProperty -Name "QDC-1" -Value $val $val = [Math]::Round($_.QUEUE_DEPTH_COUNT_RANGE_0,1) $Met | Add-Member -MemberType NoteProperty -Name "QDC-0" -Value $val $Script:QDCMetrics += $Met #} } end {} } function Get-SysCallMetricsObj { param ([string]$fedir, [int]$count) begin {[int]$idx = 0;} process { $idx += 1; if ($count -eq 0 -or $idx -eq $count) { $Met = New-Object -typename PSObject # $_ is System.Xml.XmlElement $ts = $_.timestamp $utc = $ts.Substring(0,10); $ts = Convert-UTC $utc; $Met | Add-Member -MemberType NoteProperty -Name "Time Stamp" -Value $ts $Met | Add-Member -MemberType NoteProperty -Name "FA Dir" -Value $fedir $syscallcnt = [Math]::Round($_.SyscallCount) $Met | Add-Member -MemberType NoteProperty -Name "SysCalls" -Value $syscallcnt $syscallavg = [Math]::Round($_.AvgTimePerSyscall,2) $Met | Add-Member -MemberType NoteProperty -Name "Avg Time (ms)" -Value $syscallavg $syscallps = [Math]::Round($_.SYSCALL_COUNT_PER_SEC,1) $Met | Add-Member -MemberType NoteProperty -Name "SysCalls (ps)" -Value $syscallps $rdircnt = [Math]::Round($_.SyscallRemoteDirCounts,2); $Met | Add-Member -MemberType NoteProperty -Name "RDir Calls" -Value $rdircnt $rdirps = [Math]::Round($_.SYSCALL_REMOTE_DIR_COUNT_PER_SEC,2) $Met | Add-Member -MemberType NoteProperty -Name "RDir (ps)" -Value $rdirps $rdfcnt = [Math]::Round($_.Syscall_RDF_DirCounts,2); $Met | Add-Member -MemberType NoteProperty -Name "RDF Calls" -Value $rdfcnt $rdfps = [Math]::Round($_.SYSCALL_RDF_DIR_COUNT_PER_SEC,2) $Met | Add-Member -MemberType NoteProperty -Name "RDF (ps)" -Value $rdfps $Script:SysCallMetrics += $Met } } end {} } function Get-SGMetricsObj { param ([string]$sgID, [int]$count) begin {[int]$idx = 0;} process { $idx += 1; #if ($count -eq 0 -or $idx -eq $count) { # to limit to specific interval $Met = New-Object -typename PSObject # $_ is System.Xml.XmlElement $ts = $_.timestamp $utc = $ts.Substring(0,10); $ts = Convert-UTC $utc; $Met | Add-Member -MemberType NoteProperty -Name "TimeStamp" -Value $ts $Met | Add-Member -MemberType NoteProperty -Name "SG" -Value $sgID if ($dirport -ne $null) { $Met | Add-Member -MemberType NoteProperty -Name "DirPort" -Value $dirport } #$va6 = $val.ToString().PadLeft(6,'0'); $va6 = $_.HostIOs; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "IO (ps)" -Value $va6 $va6 = $_.HostReads; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "Read IO (ps)" -Value $va6 $va6 = $_.HostWrites; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "Write IO (ps)" -Value $va6 $va6 = $_.HostMBs; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "MB (ps)" -Value $va6; $va6 = $_.HostMBReads; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "Read MB (ps)" -Value $va6 $va6 = $_.HostMBWritten; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "Write MB (ps)" -Value $va6 $va6 = $_.ResponseTime; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "Response Time (ms)" -Value $va6 $va6 = $_.ReadResponseTime; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "ReadRT(ms)" -Value $va6 $va6 = $_.WriteResponseTime; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "WriteRT(ms)" -Value $va6 $va6 = $_.PercentRead; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "Read %" -Value $va6 $va6 = $_.PercentWrite; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "Write %" -Value $va6 $va6 = $_.AvgIOSize; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "AvgIOSize" -Value $va6 $va6 = $_.AvgReadSize; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "AvgReadSize" -Value $va6 $va6 = $_.AvgWriteSize; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "AvgWriteSize" -Value $va6 <# $va6 = $_.BlockSize; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "BlockSize" -Value $va6 $va6 = $_.MaxIOServiceTime; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "MaxIOServiceTime" -Value $va6 $va6 = $_.MinIOServiceTime; $va6 = [Math]::Round($va6,1) $Met | Add-Member -MemberType NoteProperty -Name "MinIOServiceTime" -Value $va6 #> if ($csv) { $capmet = Get-SG-CapInfo $sgID $CapGB, $Vols = $capmet.Split("_"); $va6 = [Math]::Round($CapGB,1) $Met | Add-Member -MemberType NoteProperty -Name "CapGB" -Value $va6 $va6 = [Math]::Round($Vols,1) $Met | Add-Member -MemberType NoteProperty -Name "Volumes" -Value $va6 } $Script:SGMetrics += $Met #} } end {} } function Show-ArrayMetrics { param ([Object]$resp) $resp.arrayKeyResult.arrayInfo | Get-ArrayKeyInfo $URIserver foreach ($vmax in $Script:ArrayKeys) { $sid = $vmax.sid $sid4 = $sid.Substring(8,4); if ($sidr -eq "0000" -or $sidr -eq $sid4) { $Script:noluv = $false; $localstart = $vmax.localstart; $start = $vmax.start; $localend = $vmax.localend; $end = $vmax.end; $uniserver = $vmax.uniserver; if ($con -and $report -ne "Summary") { Write-Host "VMAX: $sid on Unisphere Server $uniserver" -ForegroundColor Blue Write-Host " Performance Data Range" -ForegroundColor Yellow Write-Host " Start: $localstart (UTC:$start)" -ForegroundColor Yellow Write-Host " End: $localend (UTC:$end)" -ForegroundColor Yellow } elseif ($report -eq "Summary") { #Write-Host " Summary $sid" -ForegroundColor Blue } else { $title = "$report for $sid4 on $UNIserver_NODOM" } #Load Metrics XML file for request content if (!(Test-Path $Global:MEPath)) { Add-MetInfoPath } if ($report -match "Summary") { $xmlFile = $Global:MEPath + "\" + "ArrayMetrics.xml" } else { $xmlFile = $Global:MEPath + "\" + $report + ".xml";} # $metFile = Get-ChildItem | Where-Object {$_.PSChildName -eq $xmlFile} # if (Test-Path $xmlFile) { $metXML = new-object "System.Xml.XmlDocument" $metXML.Load($xmlFile); } else { Write-Host "Metrics file not found, $xmlFile" -ForegroundColor Red break } [int]$iend = $end; $iend -= $secs; # Getting past hour of performance [string]$newstart = $iend; $newstart += "000"; $end += "000"; # Update Metrics XML with current parameter values. $metXML.arrayParam.startdate = $newstart; $metXML.arrayParam.enddate = $end; $metXML.arrayParam.symmetrixId = $sid; #$metXML.Save($metFile); # $userver = $uniserver + $URIport; $URI = "https://$userver/univmax/restapi/performance/Array/metrics" $PSCmdlet.WriteProgress( $pm.GetCurrentProgressRecord(5, "Getting metrics for $sid")) $metResp = Invoke-RestMethod -Method Post -Uri $URI -Headers $Headers -Body $metXML; if ($metResp.gettype().name -eq "XmlDocument") { if ($con -and $report -ne "Summary") { $metResp.iterator.resultList.result | show-metrics | Format-Table -AutoSize } elseif ($report -eq "Summary") { $metResp.iterator.resultList.result | show-metrics } else { $metResp.iterator.resultList.result | show-metrics | Out-GridView -Title $title } } else { Write-Host "Metrics data not returned"; } } } } function Show-FAPerformance { param ([string]$director) $sid4 = $Script:sidsn.Substring(8,4); if (!($con)) { Write-Host "Generating SG Performance Report VMAX $sid4 on $director ..." -ForegroundColor Green } $Script:PGViews = @(); $Script:FAPorts = @(); $Script:SGMetrics = @(); # Get a list of portIDs for the director. $URI = "https://$userver/univmax/restapi/$Script:prv/symmetrix/$Script:sidsn/director/$director/port?aclx=true&port_status=ON" [long]$totalTasks = 64; $pm = [ProgressManager]::new("Getting list of portIDs for the director, $director", "$URI ", $totalTasks) try { $resp = Invoke-RestMethod -Method Get -Uri $URI -Headers $Headers2 } Catch { Write-Host $_ -ForegroundColor Magenta Write-Host "URI: $URI" -ForegroundColor Yellow return $null } $success = $resp.listPortResult.success $message = $resp.listPortResult.message if (($success -match "true") -and ($message -ne "No Ports Found")) { $resp.listPortResult.symmetrixPortKey | Get-FAPortsObj; ForEach ($fap in $Script:FAPorts) { $dirport = $director + ":" + $fap.FAPort; # Get a list of port groups masked to a specific FA $PSCmdlet.WriteProgress( $pm.GetCurrentProgressRecord(2, "Getting Port Groups masked to $dirport")) $pgresp = Get-FA-SGPorts $dirport; $success = $pgresp.listPortGroupResult.success $message = $pgresp.listPortGroupResult.message if (($success -match "true") -and ($message -ne "No Port Groups Found")) { #$prresp | Format-Table -AutoSize # Get provisioning groups for each port group $pgresp.listPortGroupResult.portGroupId | Get-PGViews $pm; # Get Storage Group performance keys. $response = Get-Keys-JSON "StorageGroup"; # Build $Script:SGMetrics PSObject Submit-StorageGroupsFA $response $Script:sidsn $dirport $pm; } } } else { Write-Host "Unable to obtain a list of portID(s) for $director $message" -ForegroundColor Red return $null } $PSCmdlet.WriteProgress($pm.GetCompletedRecord()); if ($con) { $Script:SGMetrics | Format-Table -AutoSize } else { $grpcount = $Script:PGviews.length $title = "Total of ($grpcount) Storage Groups Performance for $sid4 on $URIserver"; $Script:SGMetrics | Sort-Object TimeStamp | Out-GridView -Title $title } } function Get-FEDirector { param ([Object]$resp, [string]$sidsn) $Script:FAMetrics = @(); $Script:QDCMetrics = @(); $Script:SysCallMetrics = @(); $FAid = $dir; if ($dir -ne "000") { $FAid = "FA-" + $dir.ToUpper() } [long]$totalTasks = 64; $pm = [ProgressManager]::new("Getting $report Metrics", " ", $totalTasks) $PSCmdlet.WriteProgress( $pm.GetCurrentProgressRecord(1, "Processing Metric Key info")) $resp.feDirectorKeyResult.feDirectorInfo | Get-FEKeyInfo $URIserver $sidsn $fekeycnt = $Script:FEKeys.Length; foreach ($fe in $Script:FEKeys) { $sid = $fe.sid $sid4 = $sid.Substring(8,4); if ($FAid -eq "000" -or $FAid -eq $fe.fedir) { $localstart = $fe.localstart; $start = $fe.start $localend = $fe.localend; $end = $fe.end $uniserver = $fe.uniserver; $fedir = $fe.fedir if ($Script:noluv) { $Script:noluv = $false; if ($con) { Write-Host "VMAX: $sid4 on Unisphere Server $uniserver" -ForegroundColor Blue Write-Host " Performance Data Range" -ForegroundColor Yellow Write-Host " Start: $localstart (UTC:$start)" -ForegroundColor Yellow Write-Host " End: $localend (UTC:$end)" -ForegroundColor Yellow } else { $title = "$report for $sid4 on $UNIserver_NODOM" } } #Load Metrics XML file for request content if (!(Test-Path $Global:MEPath)) { Add-MetInfoPath } $xmlFile = $Global:MEPath + "\" + $report + ".xml" #$metFile = Get-ChildItem -Path $Global:MEPath | Where-Object {$_.PSChildName -eq $xmlFile} if (Test-Path $xmlFile) { $metXML = new-object "System.Xml.XmlDocument" $metXML.Load($xmlFile); } else { Write-Host "Metrics file not found, $xmlFile - Get-FEDirector" -ForegroundColor Red break } # #if ($FAid -eq "000") { $secs = 600 }; [int]$iend = $end; $iend -= $secs; # Getting past time of performance [string]$newstart = $iend; $newstart += "000"; $end += "000"; # Update Metrics XML with current parameter values for this FA Director. $metXML.feDirectorParam.startdate = $newstart; $metXML.feDirectorParam.enddate = $end; $metXML.feDirectorParam.symmetrixId = $sid; $metXML.feDirectorParam.directorId = $fedir #$metXML.Save($metFile); $userver = $uniserver + $URIport; $URI = "https://$userver/univmax/restapi/performance/FEDirector/metrics" $PSCmdlet.WriteProgress( $pm.GetCurrentProgressRecord($totalTasks, "Getting $report Director $fedir Metrics on $sid")); try { $metResp = Invoke-RestMethod -Method Post -Uri $URI -Headers $Headers -Body $metXML; } catch { Write-Host $_ -ForegroundColor Red Write-Host $URI -ForegroundColor Red return $null } # if $FAid -eq "000" then report on last metric data point returned for each FA # else report on all metric instances for a specific FA request. [int]$count = 0; if ($FAid -eq "000") { $count = $metResp.iterator.count }; switch ($report) { "FrontEnd" { $metResp.iterator.resultList.result | Get-FAMetricsObj $fedir $count } "QDC-FrontEnd" { $metResp.iterator.resultList.result | Get-QDCMetricsObj $sid4 $fedir $count } "SysCall" { $metResp.iterator.resultList.result | Get-SysCallMetricsObj $fedir $count } } } } $PSCmdlet.WriteProgress($pm.GetCompletedRecord()); switch ($report) { "FrontEnd" { if ($con) { $Script:FAMetrics | Format-Table -AutoSize } else { # Write-Host "Generating Front End report for $sid4 on $URIserver ..." -ForegroundColor Green; $title = "Front End Report for $sid4 on $URIserver"; $selected_fa = $Script:FAMetrics | Out-GridView -OutputMode Single -Title $title if ($selected_fa -ne $null) { $FAid = $selected_fa.FADir Show-FAPerformance $FAid } } } "QDC-FrontEnd" { if (($con) -and (!($csv))) { $Script:QDCMetrics | Format-Table -AutoSize } elseif ($csv) { if (!(Test-Path $Global:FAPath)) { New-Item -Path $PWD\$Global:FADir -ItemType Directory | Out-Null; } $csvPath = $Global:FAPath + "\" + "QDC-Report.csv" $Script:QDCMetrics | Export-Csv -Path $csvPath -NoTypeInformation -Append Write-Host "QDC-Report for $sid4 appended to $csvPath" -ForegroundColor Green; } else { if (!(Test-Path $Global:FAPath)) { New-Item -Path $PWD\$Global:FADir -ItemType Directory | Out-Null; } # Write-Host "Generating Queue Depth Count report for $sid4 on $URIserver ..." -ForegroundColor Green; $title = "Queue Depth Count Report for $sid4 on $URIserver"; $Script:QDCMetrics | Out-GridView -Title $title Write-Host "Create a QDC Report CSV file for $sid4 (Y or N)?:" -NoNewline -ForegroundColor Yellow [string]$createCSV = Read-Host; if ($createCSV -match "Y") { $csvPath = $Global:FAPath + "\" + "$sid4" + "-" + "QDC-Report" + ".csv" $Script:QDCMetrics | Export-Csv -Path $csvPath -NoTypeInformation Write-Host "$csvPath created" -ForegroundColor Green } } } "SysCall" { if ($con) { $Script:SysCallMetrics | Format-Table -AutoSize } else { $Script:SysCallMetrics | Out-GridView -Title $title } } } } function Get-StorageGroups { param ([Object]$resp, [string]$sidsn) $Script:SGMetrics = @(); $sgId = $Script:sg; if ($sgId -eq "000") { $resp.storageGroupKeyResult.storageGroupInfo | Get-SGKeyInfo $URIserver $sidsn } else { $resp.storageGroupKeyResult.storageGroupInfo[0] | Get-SGKeyInfo $URIserver $sidsn } [int]$ctr = 0 foreach ($sg in $Script:SGKeys) { $sid = $sg.sid $sid4 = $sidsn.Substring(8,4); $sgroup = $sg.StorageGroup if ($sgId -eq "000" -or $sgId -ne $null) { $localstart = $sg.localstart; $start = $sg.start $localend = $sg.localend; $end = $sg.end $uniserver = $sg.uniserver; if ($sgId -eq "000") { $psgId = $sgroup $Script:SGMetrics = @(); $Script:SGMetSum = @(); } else { $psgId = $sgId } if ($Script:noluv) { $Script:noluv = $false; if ($con) { Write-Host "VMAX: $sid4 on Unisphere Server $uniserver" -ForegroundColor Blue Write-Host " Performance Data Range" -ForegroundColor Yellow Write-Host " Start: $localstart (UTC:$start)" -ForegroundColor Yellow Write-Host " End: $localend (UTC:$end)" -ForegroundColor Yellow } else { $title = "$report for $sid4 on $UNIserver_NODOM" } } #Load Metrics XML file for request content if (!(Test-Path $Global:MEPath)) { Add-MetInfoPath } $xmlFile = $Global:MEPath + "\" + $report + ".xml" #$metFile = Get-ChildItem -Path $Global:MEPath | Where-Object {$_.PSChildName -eq $xmlFile} if (Test-Path $xmlFile) { $metXML = new-object "System.Xml.XmlDocument" $metXML.Load($xmlFile); } else { Write-Host "Metrics file not found, $xmlFile Get-StorageGroups" -ForegroundColor Red break } # #if ($sgId -eq "000") { $secs = 600 }; [int]$iend = $end; $iend -= $secs; # Getting past time of performance [string]$start = $iend; $start += "000"; $end += "000"; # Update Metrics XML with current parameter values for this Storage Group. $metXML.storageGroupParam.startdate = $start; $metXML.storageGroupParam.enddate = $end; $metXML.storageGroupParam.symmetrixId = $sid $metXML.storageGroupParam.storageGroupId = $psgId #$metXML.Save($metFile); # $URI = "https://$userver/univmax/restapi/performance/StorageGroup/metrics" try { $metResp = Invoke-RestMethod -Method Post -Uri $URI -Headers $Headers -Body $metXML; } catch { Write-Host $_ -ForegroundColor Red Write-Host $URI "@ At Line 1147" -ForegroundColor Red return $null } $count = $metResp.iterator.count $metResp.iterator.resultList.result | Get-SGMetricsObj $psgId $count if (($con) -and (!($csv))) { $Script:SGMetrics | Format-Table -AutoSize } elseif ($csv) { if ($ctr -eq 0) { $csvPath = $Global:SGPath + "\" + "SG-Performance-Summary.csv" Write-Host "Generating $csvPath Report ..." -ForegroundColor Green } $Script:SGMetSum = @(); $Script:SGMetrics | Get-SGMetrics-Summary $psgId $count $sid4 $Script:SGMetSum | Export-Csv -Path $csvPath -NoTypeInformation -Append } else { $title = "Storage Group Performance for $sid4 on $URIserver"; $Script:SGMetrics | Out-GridView -Title $title } } $ctr++ } } function Select-StorageGroup { param ([Object]$resp) $Script:SGInfo = @(); $sid4 = $Script:sidsn.Substring(8,4); $resp.listStorageGroupResult | Get-SGInfo $sid4 } function Convert-ArraysXml { begin {$Script:PSArrays = @();} process { $PSArray = New-Object -typename PSObject $PSArray | Add-Member -MemberType NoteProperty -Name "Data Center" -Value $_.DataCenter $PSArray | Add-Member -MemberType NoteProperty -Name "ORG" -Value $_.Org $PSArray | Add-Member -MemberType NoteProperty -Name "RestAPI" -Value $_.restapi $PSArray | Add-Member -MemberType NoteProperty -Name "Array" -Value $_.Name $PSArray | Add-Member -MemberType NoteProperty -Name "Sid" -Value $_.sid $PSArray | Add-Member -MemberType NoteProperty -Name "Model" -Value $_.Model $PSArray | Add-Member -MemberType NoteProperty -Name "Usage" -Value $_.usage $PSArray | Add-Member -MemberType NoteProperty -Name "SN" -Value $_.sn $Script:PSArrays += $PSArray } # return an array of storage arrays end { $Script:PSArrays } } function Get-Array-MD { param([string]$sid1) $AIFile = Get-ChildItem -Path $Global:AIPath | Where-Object {$_.PSChildName -like "ArrayInfo*.xml"} | Sort-object -property @{Expression={$_.LastWriteTime}; Ascending=$false}; $FileIn = $Global:AIPath + "\" + $AIFile.PSChildName[0]; $doc = new-object "System.Xml.XmlDocument" $doc.Load($FileIn) [int]$objcnt = 0; $URIserver, $sid = $null; $doc.SelectNodes("//Array") | Where-Object {$_.Sid -match $sid1 -and $_.Org -eq $org} | Convert-ArraysXml; } function Get-Arrays { begin { } process { $ary = $_; $Model = $ary.Model; switch -Wildcard ($Model) { "VMAX*" { # Symmetrix arrays $Script:ArrayNam = $ary.Name; $Script:ArrayMod = $ary.Model; $URIserver = $ary.restapi; $UNIserver_NODOM = $ary.restapi; $sid = $ary.Sid; $sidr = $ary.Sid; $Script:sidsn = $ary.sn; $Script:sidmd = $ary.Model; $URIserver += ".$Script:DomainName"; $userver = $URIserver + $URIport; if ($Script:sidmd -match "VMAX3") { $Script:prv = "sloprovisioning" } else { $Script:prv = "provisioning" } $URI = "https://$userver/univmax/restapi/performance/Array/keys" #Write-Host "Get-Arrays $Script:ArrayNam" -ForegroundColor white [bool]$noError = $true; [long]$totalTasks = 7; $pm = [ProgressManager]::new("Processing response from $URI", "Getting Array Metrics", $totalTasks) $PSCmdlet.WriteProgress( $pm.GetCurrentProgressRecord(1, "Executing Web Request")) try { $response = Invoke-RestMethod -Method Get -Uri $URI -Headers $Headers } Catch { Write-Host $_ -ForegroundColor Magenta Write-Host "URI: $URI" -ForegroundColor Yellow $noError = $false; #exit } if ($noError) { Show-ArrayMetrics $response }; } "FA-m70*" { # Pure arrays $pureCSVFile = "$PWD" + "\" + $Script:org + "-" + $Script:PureMetricsCSV; if (Test-Path $pureCSVFile) { $PSCmdlet.WriteProgress( $pm.GetCurrentProgressRecord(1, "Processing Pure Storage metrics")) $PureRec = Import-CSV -Path $pureCSVFile | Where-Object { $_.Array -eq $ary.Name}; $Script:SumMetrics += $PureRec; } } Default { } } $PSCmdlet.WriteProgress($pm.GetCompletedRecord()); } end { } } function Get-Summary { $xmlDB = Get-ArrayInfoXML; #Write-Progress -Activity "Retrieving array metric data..." -Status "Please wait." $pm = [ProgressManager]::new("Processing response from $URI1", "Getting Game Results", $totalTasks) $PSCmdlet.WriteProgress( $pm.GetCurrentProgressRecord(1, "Executing Web Request")) if ($dc -ne $null) { $xmlDB.SelectNodes("//Array") | Where-Object {$_.DataCenter -match $dc -and $_.org -match $Script:org} | Get-Arrays } else { # this is the default $xmlDB.SelectNodes("//Array") | Where-Object { $_.org -match $Script:org } | Get-Arrays; } $Script:SumMetrics | Format-Table -AutoSize $metCSVfile = "$PWD" + "\" + $Script:org + "-" + $Script:SymmMetricsCSV; if (Test-Path $metCSVfile) { Remove-Item -Path $metCSVfile } $Script:SumMetrics | Export-CSV -Path $metCSVfile -Delimiter "," -Append -NoTypeInformation [int]$totalIOPS = 0; [int]$totalRead = 0; [int]$totalWritten = 0; [int]$sz = $Script:SumMetrics.Length - 1; for ($i=0; $i -le $sz; $i++) { $totalIOPS += $Script:SumMetrics[$i]."IO (ps)" $totalRead += $Script:SumMetrics[$i]."Reads (MB)" $totalWritten += $Script:SumMetrics[$i]."Writes (MB)" } if ($totalIOPS -gt $Script:highIOPS) { $Script:highIOPS = $totalIOPS}; if ($totalIOPS -lt $Script:lowIOPS -or $Script:lowIOPS -eq 0) { $Script:lowIOPS = $totalIOPS}; if ($totalRead -gt $Script:highRead) { $Script:highRead = $totalRead}; if ($totalRead -lt $Script:lowRead -or $Script:lowRead -eq 0) { $Script:lowRead = $totalRead}; if ($totalWritten -gt $Script:highWritten) { $Script:highWritten = $totalWritten}; if ($totalWritten -lt $Script:lowWritten -or $Script:lowWritten -eq 0) { $Script:lowWritten = $totalWritten}; Write-Host " Total IOPS: $totalIOPS Reads (MB): $totalRead Writes (MB): $totalWritten" -ForegroundColor Green #Write-Progress -Activity "Completed" -Completed; if ($repeat) { $hiLowIOPS = "$Script:highIOPS" + "/" + "$Script:lowIOPS"; $hiLowRead = "$Script:highRead" + "/" + "$Script:lowRead"; $hiLowWrit = "$Script:highWritten" + "/" + "$Script:lowWritten"; Write-Host " High/Low: $hiLowIOPS $hiLowRead $hiLowWrit" -ForegroundColor Yellow } } function Select-Unisphere { $AIFile = Get-ChildItem -Path $Global:AIPath | Where-Object {$_.PSChildName -like "ArrayInfo*.xml"} | Sort-object -property @{Expression={$_.LastWriteTime}; Ascending=$false}; $FileIn = $Global:AIPath + "\" + $AIFile.PSChildName[0]; $doc = new-object "System.Xml.XmlDocument" $doc.Load($FileIn) $title = "Select a RestAPI/Unisphere server & the desired storage arrays for the report"; [int]$objcnt = 0; $URIserver, $sid = $null; $doc.SelectNodes("//Array") | Where-Object {$_.Model -match "VMAX"} | Convert-ArraysXml | Sort-Object "Data Center", Org, RestAPI, Sid | Out-GridView -Title $title -OutputMode Multiple | ForEach-Object { if ($objcnt -eq 0) { $URIserver = $_.restapi $sid = $_.Sid $sn = $_.sn $mod = $_.Model } $objcnt++; } if ($URIserver -eq $null) { Write-Host " selection cancelled" -ForegroundColor Red Write-Host "Thanks for trying! Bye" -ForegroundColor Blue return $null } if ($objcnt -gt 1) { # process all arrays on Unisphere server $sid = "0000" } $selection = $URIserver + "_" + $sid + "_" + $sn + "_" + $mod; return $selection } function Select-Report { $reports = @(); $reports += [pscustomobject]@{Report="ArrayMetrics"; Description = " Performance metrics for all or a specific Symmetrix on the Unisphere server"} $reports += [pscustomobject]@{Report="FrontEnd"; Description = " Front End director performance metrics for a specific array and all or a specific director port"}; $reports += [pscustomobject]@{Report="QDC-FrontEnd"; Description = " Queue Depth Count for Front End director(s) for a specific array and all or a specific director port"}; $reports += [pscustomobject]@{Report="SysCall"; Description = " Array SysCall metrics"}; $reports += [pscustomobject]@{Report="StorageGroup"; Description = " Table of the Storage Groups and meta data for a symmetrix array"}; $reports += [pscustomobject]@{Report="Summary"; Description = "Symmetrix IO Performance Summary"}; $reports += [pscustomobject]@{Report="SGPerformance"; Description = " CLI ONLY: Storage Group Performance for named SG or All SGs on FA port"}; $title = "Select a Symmetrix Performance Report" $selectA_report = $reports | Out-GridView -Title $title -OutputMode Single; if ($selectA_report -eq $null) { Write-Host " Selection Cancelled" -ForegroundColor Red Write-Host "Thanks for trying! Bye" -ForegroundColor Blue return "done" } else { return $selectA_report.report } } function Get-OrgCredentials { Param ([string]$borg) $xmlDB = Get-ArrayInfoXML; if ([string]::IsNullOrEmpty($borg)) { # org value from first record since none specified $unique = $xmlDB.SelectNodes("//Array") | Where-Object { $_.Model -match "VMAX"} | Select-Object -Property Org, username, domainname -Unique; $borg = $unique[0].Org } else { $unique = $xmlDB.SelectNodes("//Array") | Where-Object { $_.Model -match "VMAX" -and $_.Org -match $borg} | Select-Object -Property Org, username, domainname -Unique; } $Script:DomainName = $unique[0].domainname; $credBase = "-" + $borg + "-" + $env:COMPUTERNAME + $credExt; $Script:credfilename = $Global:CRPath + "\" + $unique[0].username + $credBase; if (!(Test-Path $Script:credfilename)) { # create cache credential Write-Host "Unisphere Credentials require for $borg Storage" -ForegroundColor Green Export-PSCredential $unique[0].username $credBase Start-Sleep 3; } $cred = Import-PSCredential $Script:credfilename $Script:usr = $cred.UserName; $Script:pw = $cred.GetNetworkCredential().Password; $Script:org = $borg; $rslt = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $Script:usr,$Script:pw))) return $rslt; } # # # Exported Functions <# .SYNOPSIS Reports on Symmetrix array performance data by executing RESTAPI calls to a specific Unisphere server. .DESCRIPTION Reports symmetrix array metrics. A table of existing arrays is presented for selection of the desired array for reporting. .PARAMETER URIserver Unisphere server name. The <domainname> tag in the XMLDB will be appended. Default "select" - A table of arrays will be presented for selection. .PARAMETER sidr Symmetrix 4-digit serial number. If not specified will report on all local arrays seen by the Unisphere server. .PARAMETER secs Default display last hour (3600 secs) of metric data points. Number of seconds specified limited to 5 digits. .PARAMETER report Default 'select' to present a table of reports for selection. ArrayMetrics Displays performance metrics for all or a specific Symmetrix array. FrontEnd Displays front end director performance metrics for a specific array and all or specific director. QDC-FrontEnd Displays Front End Queue Depth Count metrics for a specific array and all or specific director. SysCall Displays front end syscall metrics. StorageGroup Displays a list of storage groups on the selected array along with storage group meta data. SGPerformance Display Performance metrics for a specified storage group. If the '-csv' option is used, then the metrics will be summarized for the specified time period and output to a CSV file. Summary Display a summary of the ArrayMetrics report for all arrays or all arrays in a specific data center. .PARAMETER dir For FrontEnd, SysCall, and SGPerformance reports only. Specify a specific director value for the report. .PARAMETER sg Name of the Storage Group for Performance report. .PARAMETER con Output to the console rather than Out-Gridview. .PARAMETER csv For SGPerformance report. Output to summary csv file in the 'SGInfo' folder. .PARAMETER dc Specifics a data center name filter to be used with the Summary Report. .PARAMETER repeat Repeats the Summary report every 6 minutes. .INPUTS Each report requires a specific xml file to be present in the execution directory. The XMLDB file is named after the report name with an extension of .xml. .INPUTS ArrayInfo\ArrayInfo.xml Reads the file to present a table for selecting the desired symmetrix array. .INPUTS SGInfo\<sid>-StorageGroups.xml If the file's last write time is less that 8 hours old, it is imported to display the storage group information. .OUTPUTS Output defaults to Out-GridView unless the -con option is specified. .OUTPUTS SGInfo\<sid>.StorageGroups.xml Export of the Storage Group object in xml format. .OUTPUTS SGInfo\SG-Performance-Summary.csv When the csv option is used with the SGPerformance report. .EXAMPLE Get-VeArrayMetrics sanmgmt01 Displays metrics for all arrays configured on Unisphere server admassan45. .EXAMPLE Get-VeArrayMetrics sanmgmt01 0700 7200 Displays 2 hours metrics for VMAX 0700. .EXAMPLE Get-VeArrayMetrics sanmgmt01 0700 -report FrontEnd Displays the latest metrics for all FE directors. .EXAMPLE Get-VeArrayMetrics sanmgmt01 0700 -report FrontEnd -dir 1e Displays one hour of metrics for FE director 1E. .EXAMPLE Get-VeArrayMetrics sanmgmt01 0700 -report SysCall Displays the latest syscall metrics for all FE directors. .EXAMPLE Get-VeArrayMetrics sanmgmt01 0700 -sg hayesx401-408_sg -csv -secs 86400 Output the a summary of a SG performance metrics for a specified period of time to a csv file. .EXAMPLE Get-VeArrayMetrics sanmgmt01 0700 -report QDC-FrontEnd Displays the last hour of Queue Depth Count metrics for all directors on 1296 in the Out-Gridview format. A prompt is presented to save the report to a CSV file, if desired. .EXAMPLE Get-VeArrayMetrics sanmgmt01 0700 -report QDC-FrontEnd -dir 15e -secs 7200 Same as prior example but limit output to director 15e and extents the reporting window to 2 hours. .EXAMPLE Get-VeArrayMetrics sanmgmt01 0700 -report QDC-FrontEnd -csv -secs 43200 Output is appended to the CSV file, QDC-Report.csv with QDC metrics for the last 12 hours. Use the following comand to reopen the CSV in the Out-Gridview. Import-CSV QDC-Report.csv | Out-GridView Or use Excel to open the csv file. All csv files are in the FAInfo folder. .EXAMPLE Get-VeArrayMetrics -report Summary Display the last available ArrayMetrics data points for all storage arrays in the environment. Get-VeArrayMetrics -report Summary -dc Polaris Same as the prior example but only for arrays in the Polaris data center. Get-VeArrayMetrics -report Summary -dc Polaris -repeat Same as prior examples, but Summary report is repeated every 6 minutes. .NOTES Author: Craig Dayton 0.0.2.0 07/05/2017 cadayton: converted to Get-VeSymmMetrics cmdlet in the module, Venom 0.0.1.5: 11/07/2016 cadayton: Fixed logic to support VMAX3 FrontEnd report. 0.0.1.4: 11/02/2016 cadayton: Added Queue Depth Count Report with optional csv option 0.0.1.3: 10/21/2016 cadayton: Added SGPerformance with optional csv option. 0.0.1.2: 10/16/2016 cadayton: Added StorageGroup report 0.0.1.1: 09/27/2016 cadayton: Added SysCall report 0.0.1.0: 09/26/2016 cadayton: Added FrontEnd report .LINK https://github.com/cadayton/Venom .LINK http://venom.readthedocs.io #> function Get-VeSymmMetrics { # Get-VeArrayMetrics Params [cmdletbinding()] Param ( [Parameter(Position=0, Mandatory=$False, ValueFromPipeline=$True)] [ValidatePattern("^[a-zA-Z0-9]{3,30}")] [string]$URIserver = "select", [Parameter(Position=1, Mandatory=$False, ValueFromPipeline=$True)] [ValidatePattern("^[0-9]{4}$")] [string]$sidr = "0000", [Parameter(Position=2, Mandatory=$False, ValueFromPipeline=$True)] [ValidatePattern("^[0-9]{4,5}$")] [int]$secs = 3600, [Parameter(Position=3, Mandatory=$False, ValueFromPipeline=$True)] [ValidatePattern("^[a-zA-Z0-9]{3,30}")] [string]$report = "select", [Parameter(Position=4, Mandatory=$False, ValueFromPipeline=$True)] [ValidatePattern("^[d-hD-H0-9]{2,3}")] [string]$dir = "000", [Parameter(Position=5, Mandatory=$False, ValueFromPipeline=$True)] [string]$sg, [Parameter(Position=6, Mandatory=$False, ValueFromPipeline=$True)] [switch]$con, [Parameter(Position=7, Mandatory=$False, ValueFromPipeline=$True)] [switch]$csv, [Parameter(Position=8, Mandatory=$False, ValueFromPipeline=$True)] [string]$dc = $null, [Parameter(Position=9, Mandatory=$false, ValueFromPipeline=$true)] [string]$org = $null, [Parameter(Position=10, Mandatory=$False, ValueFromPipeline=$True)] [bool]$repeat = $true ) # Write-Host "Get-VeSymmMetrics version 0.0.2.0" -ForegroundColor Green $EUP = Get-OrgCredentials $org; $Headers = @{'Authorization'="Basic $($EUP)";'Content-type'='application/xml';'Accept'='application/xml'} $Headers1 = @{'Authorization'="Basic $($EUP)";'Content-type'='application/json';'Accept'='application/xml'} $Headers2 = @{'Authorization'="Basic $($EUP)";'Accept'='application/xml'} # set requests, to use TLSv1.2 protocol [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; # tell Windows to ignore self-signed certs Set-Ignore-SelfSignedCerts; $UNIserver_NODOM = $URIserver; $URIport = ":8443"; $userver = $URIserver + $URIport; [bool]$Script:noluv = $true; $Script:sg = $sg; $Script:SumMetrics = @(); if ($report -ne "Summary") { if ($URIserver -match "select") { $selection = Select-Unisphere if ([string]::IsNullOrEmpty($selection)) { return } $URIserver, $sidr, $Script:sidsn, $Script:sidmd = $selection.Split("_") $UNIserver_NODOM = $URIserver; $URIserver += ".$Script:DomainName"; $userver = $URIserver + $URIport; } else { $Script:sidsn = Get-Array-SN $sidr; Get-Array-MD $sidr | Out-Null $Script:sidmd = $Script:PSArrays[0].Model; } if ($Script:sidmd -match "VMAX3") { $Script:prv = "sloprovisioning" } else { $Script:prv = "provisioning" } if ($report -match "select") { $report = Select-Report if ($report -eq "done") { return } } } switch ($report) { "ArrayMetrics" { $URI = "https://$userver/univmax/restapi/performance/Array/keys" [long]$totalTasks = 2; $pm = [ProgressManager]::new("Processing response from $URI", "Getting Array Metrics", $totalTasks) $PSCmdlet.WriteProgress( $pm.GetCurrentProgressRecord(1, "Executing Web Request")) $response = Invoke-RestMethod -Method Get -Uri $URI -Headers $Headers } "FrontEnd" { $response = Get-Keys-JSON "FEDirector"; } "QDC-FrontEnd" { $response = Get-Keys-JSON "FEDirector"; } "SysCall" { $response = Get-Keys-JSON "FEDirector"; } "StorageGroup" { $sid4 = $Script:sidsn.Substring(8,4); [string]$xmlSGFile = $Global:SGPath + "\" + $sid4 + "-StorageGroups.xml" [int]$mts = 0; if (Test-Path $xmlSGFile) { $csvFile = Get-ChildItem $xmlSGFile; $cts = $csvFile.LastWriteTime $nts = New-TimeSpan -Start (Get-Date) -End $cts # Number of minutes since LastWriteTime [int]$mts = (($nts.Days * 1440) + ($nts.Hours * 60) + ($nts.Minutes)) * -1; } if (($mts -gt 480) -or ($mts -eq 0)) { # older than 8 hours or doesn't exist $URI = "https://$userver/univmax/restapi/$Script:prv/symmetrix/$Script:sidsn/storagegroup" [long]$totalTasks = 2; $pm = [ProgressManager]::new("Getting Storage Groups on $Script:sidsn", " From $URI", $totalTasks) $PSCmdlet.WriteProgress( $pm.GetCurrentProgressRecord(1, "Getting Storage Groups on $Script:sidsn")) try { $response = Invoke-RestMethod -Method Get -Uri $URI -Headers $Headers2 } Catch { Write-Host $_ -ForegroundColor Magenta Write-Host "URI: $URI" -ForegroundColor Yellow return $null } } else { $Script:SGinfo = Import-Clixml -Path $xmlSGFile $title = "VMAX $sid4 Storage Groups $cts"; $selected_sg = $Script:SGinfo | Out-GridView -OutputMode Single -Title $title if ($selected_sg -ne $null) { $response = Get-Keys-JSON "StorageGroup"; $Script:noluv = $false $Script:sg = $selected_sg.StorageGroup; $report = "SGPerformance"; Get-StorageGroups $response $Script:sidsn } return $null } } "SGPerformance" { if ($Script:sg -ne "") { $response = Get-Keys-JSON "StorageGroup"; } elseif ($dir -ne "000") { $FAid = $dir; $FAid = "FA-" + $dir.ToUpper(); Show-FAPerformance $FAid return $null } else { Write-Host "SGPerformance report is only available from the CLI" -ForegroundColor Green Write-Host "Get-VeSymmMetrics $UNIserver_NODOM $sidr -report SGPerformance -sg <Storage group name>" -ForegroundColor Yellow Write-Host "Get-VeSymmMetrics $UNIserver_NODOM $sidr -report SGPerformance -dir <Director ID>" -ForegroundColor Yellow Write-Host "Output Options:" Write-Host " -con output to console" Write-Host " -csv output to CSV " Write-Host " default output is Out-Gridview" return $null } } "Summary" { [int]$Script:highIOPS = 0; [int]$Script:lowIOPS = 0; [int]$Script:highRead = 0; [int]$Script:lowRead = 0; [int]$Script:highWritten = 0; [int]$Script:lowWritten = 0; Get-Summary; if ($repeat) { $StopWatch = New-Object -TypeName System.Diagnostics.Stopwatch $StopWatch.Start() $ticker = $null; try { While ($repeat) { if ($ticker -eq $null) { Write-Host " "; Write-Host "Refresh in 6 minutes " -NoNewLine -ForegroundColor Yellow Write-Host " Ctrl-C to exit" } $ticker = $StopWatch.Elapsed.ToString(); <# $curPos = $host.UI.RawUI.CursorPosition $y = $curPos.Y - 1; #$curPos.X = 2; $curPos.Y = $y; $host.UI.RawUI.CursorPosition = $curPos #> Start-Sleep -Seconds 10; if ($StopWatch.Elapsed.minutes -ge 6) { Clear-Host; $Script:SumMetrics = @(); Get-Summary; $StopWatch.ReStart(); $ticker = $null; } } } catch { } finally { #Write-Host "Performing clean up work" $StopWatch.Stop(); } } return $null } Default { Write-Host "Report logic not defined for $report" -ForegroundColor Red } } if ($response.gettype().name -eq "XmlDocument") { # System.Object being piped to a function for processing switch ($report) { "ArrayMetrics" { Show-ArrayMetrics $response $PSCmdlet.WriteProgress($pm.GetCompletedRecord()); } "FrontEnd" { Get-FEDirector $response $Script:sidsn } "QDC-FrontEnd" { if ($secs -gt "3600") { Write-Host "Generating Queue Depth Count report greater than 3600 secs" -ForegroundColor Green Write-Host "can take some time to process, so be patience." -ForegroundColor Green } Get-FEDirector $response $Script:sidsn } "SysCall" { Get-FEDirector $response $Script:sidsn } "StorageGroup" { $Script:noluv = $false Select-StorageGroup $response $sid4 = $Script:sidsn.Substring(8,4) if (!(Test-Path $Global:SGPath)) { New-Item -Path $PWD\$Global:SGDir -ItemType Directory | Out-Null; } $xmlSGInfo = $Global:SGPath + "\" + $sid4 + "-StorageGroups.xml" $Script:SGInfo | Export-Clixml -Path $xmlSGInfo $PSCmdlet.WriteProgress($pm.GetCompletedRecord()); $td = Get-Date; $title = "VMAX $sid4 Storage Groups $td" $selected_sg = $Script:SGInfo | Out-GridView -OutputMode Single -Title $title if ($selected_sg -ne $null) { $response = Get-Keys-JSON "StorageGroup"; $Script:noluv = $false $Script:sg = $selected_sg.StorageGroup; $report = "SGPerformance"; Get-StorageGroups $response $Script:sidsn } } "SGPerformance" { #$Script:noluv = $false Get-StorageGroups $response $Script:sidsn } Default { $Script:noluv = $false Write-Host "Report logic not defined for $report" -ForegroundColor Red } } if ($Script:noluv) { Write-Host "VMAX $sidr not found on $URIserver" -ForegroundColor Red } } else { Write-Host "XML data not returned from:" -ForegroundColor Red Write-Host $URI -ForegroundColor Yellow } } # |