S2D: Origem de Dados de Métricas de Desempenho
Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.MetricsDataSource (DataSourceModuleType)
Origem de dados de métricas de desempenho.
Element properties: Member Modules:
Overrideable Parameters:
Source Code: <DataSourceModuleType ID="Microsoft.Windows.Server.10.0.Storage.StorageSpacesDirect.MetricsDataSource" Accessibility="Internal">
<Configuration>
<IncludeSchemaTypes>
<SchemaType>Windows!Microsoft.Windows.PowerShellSchema</SchemaType>
<SchemaType>System!System.ExpressionEvaluatorSchema</SchemaType>
</IncludeSchemaTypes>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="StorageClassName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" maxOccurs="1" name="TimeoutSeconds" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="IntervalSeconds" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SyncTime" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="0" name="DebugMode" type="xsd:boolean"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int"/>
<OverrideableParameter ID="SyncTime" Selector="$Config/SyncTime$" ParameterType="string"/>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
<OverrideableParameter ID="DebugMode" Selector="$Config/DebugMode$" ParameterType="bool"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<DataSource ID="Scheduler" TypeID="System!System.Scheduler">
<Scheduler>
<SimpleReccuringSchedule>
<Interval>$Config/IntervalSeconds$</Interval>
<SyncTime>$Config/SyncTime$</SyncTime>
</SimpleReccuringSchedule>
<ExcludeDates/>
</Scheduler>
</DataSource>
<ProbeAction ID="Script" TypeID="Windows!Microsoft.Windows.PowerShellPropertyBagProbe">
<ScriptName>GetPerformanceMetricsScript.ps1</ScriptName>
<ScriptBody><Script>
param([string] $storageClassName,$DebugMode)
#general variables
#-----------------
$errorActionPreference = 'Stop'
$errEvent = [System.Diagnostics.EventLogEntryType]::Error;
$infoEvent = [System.Diagnostics.EventLogEntryType]::Information;
$GenericInformationEvent = 8671;
$GenericFailureEvent = 8672;
$DiscoveryGenericInformationEvent = 8861;
$DiscoveryGenericFailureEvent = 8862;
$script:traceMsg = "";
$ObjectNotFoundCode = -2146233087
$msft_namespace = "root\microsoft\windows\storage"
$cluster_namespace = "root\mscluster"
# Guid length for Virtual Disk
$guidLength = 38
$PadLength = 1 #Object Id ended with double quote
if ($false -eq [string]::IsNullOrEmpty($DebugMode))
{
$DebugMode = [string]::Equals("true",$DebugMode,[System.StringComparison]::OrdinalIgnoreCase)
}
else
{
$DebugMode = $false
}
$momAPI = New-Object -comObject 'MOM.ScriptAPI'
#Common Functions
Function Get-Guid([string]$sguid)
{
if ([string]::IsNullOrEmpty($sguid))
{
return $null
}
$guid = [guid]::NewGuid()
if ($false -eq [guid]::TryParse($sguid,[ref] $guid))
{
return $null;
}
return $guid
}
Function GetDiskIdFilterFromVdObjectId([string]$ObjectId)
{
if ($true -eq [string]::IsNullOrEmpty($ObjectId))
{
return $null
}
$Length = $ObjectId.Length
#check guid length - 38 in {guid} format
$rGuidLength = $guidLength + $PadLength
if ($Length -lt $rGuidLength) {return $null;}
$sguid = $ObjectId.Substring($Length - $rGuidLength,$guidLength)
$guid = Get-Guid -sguid $sguid
if ($null -eq $guid) {return $null;}
return "DiskId='\\\\?\\Disk{$guid}'"
}
Function GetVolumesFromVd($vd)
{
$errorActionPreference = "Stop"
$Filter = GetDiskIdFilterFromVdObjectId -ObjectId $vd.ObjectId
if ($null -eq $Filter ) {return $null;}
$partitions = Get-CimInstance -ClassName "MSFT_Partition" -Namespace $msft_namespace -Filter $Filter | Where-Object {$_.AccessPaths -ne $null}
$volumes = @{}
foreach ($partition in $partitions)
{
$Volume = Get-CimAssociatedInstance -Association "MSFT_PartitionToVolume" -InputObject $partition -Namespace $msft_namespace
if ($null -ne $Volume -and "CSVFS" -eq $Volume.FileSystem )
{
$volumes[$Volume] = 1;
}
}
return $volumes
}
Function AddTraceMessage
{
param($message)
$errorActionPreference = 'SilentlyContinue'
$timeStamp = (get-date -format "HH:mm:ss:fff");
$script:traceMsg = $script:traceMsg + "`n[" + $timeStamp + "] " + $message;
}
Function Log-FinalDebugData([int]$FailureEvent,[int]$InformationEvent,$exception,[string]$SCRIPT_NAME,[string]$traceMsg,[bool]$DebugMode = $false,$message = [string]::Empty)
{
$ErrorActionPreference = "SilentlyContinue"
if ($null -ne $exception)
{
if ([string]::Empty -eq $message) {$message = "Error occured during script execution:"}
$momAPI.LogScriptEvent($SCRIPT_NAME, $FailureEvent, 1, "$message $($exception.Message)");
}
if ($script:traceMsg -ne $null -and $true -eq $DebugMode)
{
$momAPI.LogScriptEvent($SCRIPT_NAME,$InformationEvent, 0, $traceMsg);
}
}
Function Check-CimError($Exception)
{
$errorActionPreference = 'SilentlyContinue'
$result = $false
if ($null -eq $Exception)
{
return $result
}
$error.Clear()
$type = $Exception.GetType()
if (0 -ne $error.Count)
{
$error.Clear()
return $result
}
if ("Microsoft.PowerShell.Cmdletization.Cim.CimJobException" -eq $type.FullName -and $ObjectNotFoundCode -eq $Exception.HResult)
{
$result = $true
}
return $result
}
Function Get-FaultException($exception,$IsObjectExist)
{
if ($false -eq $IsObjectExist)
{
$IsError = Check-CimError -Exception $exception
if ($true -eq $IsError)
{
$exception = $null
}
}
return $exception
}
Function Load-Module ([string] $ModuleName)
{
if ([string]::IsNullOrEmpty($ModuleName) )
{
return $false
}
$ErrorActionPreference="SilentlyContinue"
$error.Clear()
$retval = $false
$Tmodule = Get-Module -Name $ModuleName
########Check for powershell 1.0
if ($error.Count -ne 0)
{
$Exception = $error[0].Exception
if ($null -ne $Exception)
{
$type = $Exception.GetType()
if ([System.Management.Automation.CommandNotFoundException] -eq $type)
{
$error.Clear()
return $retval
}
}
$error.Clear()
}
if ($null -eq $Tmodule)
{
$Tmodule = Get-Module -Name $ModuleName -ListAvailable
if ($error.Count -ne 0){ return $retval;}
if ($null -eq $Tmodule) {return $retval;}
Import-Module $ModuleName
if ($error.Count -eq 0){ $retval = $true;}
}
else
{
$retval = $true
}
return $retval
}
AddTraceMessage -message "Start on Node: $env:COMPUTERNAME"
$IsStorageModuleReady = Load-Module -ModuleName "Storage"
if ($false -eq $IsStorageModuleReady)
{
if ($error.Count -ne 0)
{
$message = "Cannot initializa Storage module. Error: " + $error[0].ToString()
}
else
{
$message = "Cannot load Storage module."
}
AddTraceMessage -message $message
}
#Load cimcmdlets
$IsCimReady = Load-Module -ModuleName "CimCmdLets"
#param([string] $storageClassName, [string] $targetInstanceUniqueID,$DebugMode)
$scriptName = "GetPerformanceMetricsScript.ps1"
$msft_namespace = "root\microsoft\windows\storage"
#-----------------
#Log Errors
function LogErrors($exception)
{
$messageToLog = ""
if ($null -ne $exception)
{
$messageToLog = "Error occured during script execution. Instance UniqueID: $targetInstanceUniqueID . `n "
}
Log-FinalDebugData -FailureEvent $GenericFailureEvent -InformationEvent $GenericInformationEvent -exception $exception -SCRIPT_NAME $scriptName -traceMsg $script:traceMsg -DebugMode $DebugMode -message $messageToLog
}
#function to get divider for the various metrics
function GetDivider
{
param([string] $metName)
switch ($metName)
{
MemoryAvailable {return "1GB"}
MemoryTotal {return "1GB"}
CapacityPhysicalUnpooled {return "1GB"}
CapacityPhysicalTotal {return "1GB"}
CapacityPhysicalPooledTotal {return "1GB"}
CapacityPhysicalPooledAvailable {return "1GB"}
CapacityTotal {return "1GB"}
CapacityAvailable {return "1GB"}
CapacityVolumesAvailable {return "1GB"}
CapacityVolumesTotal {return "1GB"}
IOThroughputRead {return "1MB"}
IOThroughputTotal {return "1MB"}
IOThroughputWrite {return "1MB"}
IOLatencyRead {return 0.001}
IOLatencyWrite {return 0.001}
IOLatencyAverage {return 0.001}
default {return 1}
}
return 1
}
function GetS2DStorageSubsystem($storageobject)
{
$ErrorActionPreference = "SilentlyContinue"
if ($null -eq $storageObject)
{
return $null
}
$error.Clear()
$storageSubSystem = ($storageObject |Get-StorageSubSystem)
if (0 -ne $error.Count)
{
AddTraceMessage -message "Cannot get storage subsystem for storage object."
$exception = $error[0].Exception
LogErrors -exception $exception
return $null
}
return $storageSubSystem
}
function GetHealthReport($storageSubSystem,$storageObject)
{
$ErrorActionPreference = "SilentlyContinue"
$cimReportMethod = "GetReport"
####################################
# Check Object Type and valid values
# Don't get data on null objects
###################################
if ($null -eq $storageObject)
{
return $null
}
if ($null -eq $storageSubSystem)
{
return $null
}
if ($null -eq $storageSubSystem.GetType)
{
AddTraceMessage -message "S2D capable storage subsystem is not found."
return $null
}
$StorageHealthObject = $null
$StorageHealthObjects = $null
$error.Clear()
##########################################
#Getting Object requireg for Health Report
# Don't get data on null objects
##########################################
#Trying to get Storage Health Object
AddTraceMessage -message "Trying to get storage health object."
$StorageHealthObjects = Get-CimAssociatedInstance -InputObject $storageSubSystem -Association "MSFT_STorageSubsystemToStorageHealth" -Namespace $msft_namespace
if ($error.Count -ne 0)
{
$message = $error[0].Exception.Message
AddTraceMessage -message "Cannot get S2D storage subsystem health object. `nError details:$message"
}
if($null -eq $StorageHealthObjects)
{
AddTraceMessage -message "S2D storage subsystem doesn't have any health data."
return $null
}
if ($StorageHealthObjects.Count -gt 0)
{
$StorageHealthObject = $StorageHealthObjects[0]
}
else
{
$StorageHealthObject = $StorageHealthObjects
}
$error.Clear()
#Trying to get Storage Health Report
AddTraceMessage -message "Trying to get storage health report."
$HealthReportObject = $null
$HealthReportObjects = $null
$HealthReportObjects = Invoke-CimMethod -InputObject $StorageHealthObject -MethodName $cimReportMethod -Arguments @{TargetObject=$storageObject;Count=1}
if ($error.Count -ne 0)
{
$exception = $error[0].Exception
$message = $exception.Message
AddTraceMessage -message "Cannot get S2D storage subsystem health report. `nError details:$message"
LogErrors -exception $exception
}
if ($null -eq $HealthReportObjects -or 0 -eq $HealthReportObjects.Count)
{
AddTraceMessage -message "S2D storage subsystem doesn't have any health reports available."
return $null
}
$error.Clear()
if ($null -eq $HealthReportObjects.Count)
{
$HealthReportObject = $HealthReportObjects
}
else
{
$HealthReportObject = $HealthReportObjects[0]
}
if ($error.Count -ne 0)
{
$exception = $error[0].Exception
$message = $exception.Message
AddTraceMessage -message "Cannot get S2D storage subsystem health report data. `nError details:$message"
}
if ($null -eq $HealthReportObject)
{
AddTraceMessage -message "S2D storage subsystem doesn't have any health report available. Exiting..."
return $null
}
return $HealthReportObject.ItemValue
}
function Get-StoragePoolPerfCollection {
[CmdletBinding()]
param
(
[Parameter(
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True,
HelpMessage='- FriendlyName ')]
[Alias('StoragePool')]
[string[]]$FriendlyName,
[string]$MediaType = 'all'
)
begin
{
$MediaType = $MediaType.ToUpper()
$ClusterNodes = Get-ClusterNode
if (! $ClusterNodes) {
Return
}
if (! $FriendlyName) {
# $SP = Get-StoragePool | ? IsPrimordial -eq $False
$SP = Get-StoragePool -UniqueId $targetInstanceUniqueID
if ($SP) {
$FriendlyName = $SP.FriendlyName
}
}
$Obj = @()
}
Process
{
foreach ($Pool in $FriendlyName)
{
$thisPool = Get-StoragePool -FriendlyName $Pool -ErrorAction Stop
if ( $MediaType -eq "all" )
{
$CapacityDisks = $thisPool | Get-PhysicalDisk | ? MediaType -ne "Journal"
} else {
$CapacityDisks = $thisPool | Get-PhysicalDisk | ? MediaType -eq $MediaType
}
if (! $CapacityDisks) {
Return
}
$PoolDiskCount = $CapacityDisks.Count
$TotalSize = 0
$TotalAlloc = 0
ForEach ($Disk in $CapacityDisks)
{
$DiskSize = $Disk.Size /1TB
$DiskAlloc = $Disk.AllocatedSize /1TB
$FreeSpace = $DiskSize - $DiskAlloc
$TotalSize += $DiskSize
$TotalAlloc += $DiskAlloc
}
$PoolFree = $TotalSize - $TotalAlloc
$PercentFull = $TotalAlloc / $TotalSize * 100
$ReserveRequired = $TotalSize / $PoolDiskCount
$Properties = [Ordered]@{
'Pool'=$thisPool.FriendlyName;
'TotalCapacity'=$TotalSize;
'TotalUsedSpace'=$TotalAlloc;
'TotalFreeSpace'=$PoolFree;
'PercentUsed'=$PercentFull
'UnitOfMeasure'="GB";
'DiskCount'=$PoolDiskCount;
'SelectedMediaType'=$MediaType;
'ReserveRequired'=$ReserveRequired;
}
$Obj += New-Object –Typename PSObject –Property $Properties
}
Write-Output $Obj
}
}
#add propertyBag
function AddBagStorageNode([HashTable]$valuenameDictionary,$UniqueID)
{
$ErrorActionPreference = "Stop"
if ($null -eq $valuenameDictionary -or 0 -eq $valuenameDictionary.Count)
{
return
}
$propertyBag = $momAPI.CreatePropertyBag()
$propertyBag.AddValue("SourceUniqueId", $UniqueID);
$propertyBag.AddValue("CPUUsage", $valuenameDictionary["CPUUsage"]);
$propertyBag.AddValue("IOLatencyAverage", $valuenameDictionary["IOLatencyAverage"]);
$propertyBag.AddValue("IOLatencyRead", $valuenameDictionary["IOLatencyRead"]);
$propertyBag.AddValue("IOLatencyWrite", $valuenameDictionary["IOLatencyWrite"]);
$propertyBag.AddValue("IOPSRead", $valuenameDictionary["IOPSRead"]);
$propertyBag.AddValue("IOPSTotal", $valuenameDictionary["IOPSTotal"]);
$propertyBag.AddValue("IOPSWrite", $valuenameDictionary["IOPSWrite"]);
$propertyBag.AddValue("IOThroughputRead", $valuenameDictionary["IOThroughputRead"]);
$propertyBag.AddValue("IOThroughputTotal", $valuenameDictionary["IOThroughputTotal"]);
$propertyBag.AddValue("IOThroughputWrite", $valuenameDictionary["IOThroughputWrite"]);
$propertyBag.AddValue("MemoryAvailable", $valuenameDictionary["MemoryAvailable"]);
$propertyBag.AddValue("MemoryTotal", $valuenameDictionary["MemoryTotal"]);
$propertyBag
}
function Get-S2DStorageHealthReport($s2dNodes)
{
if($s2dNodes)
{
$valuenameDictionary = @{}
$table = @()
$s2dreport = $s2dNodes | Get-StorageHealthReport -Count 1
If($s2dreport)
{
foreach ($s2drecord in $s2dreport.itemValue.records)
{
if ($s2drecord.Units -eq 0)
{
$UnitType = "Bytes"
$s2dValue= [math]::Round($s2drecord.Value / 1GB, 3)
}
ElseIf ($s2drecord.Units -eq 1)
{
$UnitType = "BytesPerSecond"
$s2dValue = $s2drecord.Value
}
ElseIf ($s2drecord.Units -eq 2)
{
$UnitType = "CountPerSecond"
$s2dValue = $s2drecord.Value
}
ElseIf ($s2drecord.Units -eq 3)
{
$UnitType = "Seconds"
$s2dValue = $s2drecord.Value
}
ElseIf ($s2drecord.Units -eq 4)
{
$UnitType = "Percentage"
$s2dValue = $s2drecord.Value
}
if ($valuenameDictionary.ContainsKey($s2drecord.Name)) {continue;}
$valuenameDictionary.Add($s2drecord.Name, $s2dValue);
}
}
AddBagStorageNode -valuenameDictionary $valuenameDictionary -UniqueID $s2dNodes.UniqueID
}
}
#add propertyBag
function AddBag([HashTable]$valuenameDictionary,$UniqueID)
{
$ErrorActionPreference = "Stop"
if ($null -eq $valuenameDictionary -or 0 -eq $valuenameDictionary.Count)
{
return
}
$propertyBag = $momAPI.CreatePropertyBag()
$propertyBag.AddValue("SourceUniqueId", $UniqueID);
$propertyBag.AddValue("AverageCPUUsage", $valuenameDictionary["CPUUsageAverage"]);
$propertyBag.AddValue("ReadIOPS", $valuenameDictionary["IOPSRead"]);
$propertyBag.AddValue("TotalIOPS", $valuenameDictionary["IOPSTotal"]);
$propertyBag.AddValue("WriteIOPS", $valuenameDictionary["IOPSWrite"]);
$propertyBag.AddValue("ReadLatency", $valuenameDictionary["IOLatencyRead"]);
$propertyBag.AddValue("AverageLatency", $valuenameDictionary["IOLatencyAverage"]);
$propertyBag.AddValue("WriteLatency", $valuenameDictionary["IOLatencyWrite"]);
$propertyBag.AddValue("MemoryAvailable", $valuenameDictionary["MemoryAvailable"]);
$propertyBag.AddValue("MemoryTotal", $valuenameDictionary["MemoryTotal"]);
$propertyBag.AddValue("PhysicalCapacityRemaining", $valuenameDictionary["CapacityPhysicalUnpooled"]);
$propertyBag.AddValue("PhysicalCapacityTotal", $valuenameDictionary["CapacityPhysicalTotal"]);
$propertyBag.AddValue("PoolCapacityRemaining", $valuenameDictionary["CapacityPhysicalPooledAvailable"]);
$propertyBag.AddValue("PoolCapacityTotal", $valuenameDictionary["CapacityPhysicalPooledTotal"]);
$propertyBag.AddValue("VolumeCapacityRemaining", $valuenameDictionary["CapacityVolumesAvailable"]);
$propertyBag.AddValue("VolumeCapacityTotal", $valuenameDictionary["CapacityVolumesTotal"]);
$propertyBag.AddValue("ReadThroughput", $valuenameDictionary["IOThroughputRead"]);
$propertyBag.AddValue("TotalThroughput", $valuenameDictionary["IOThroughputTotal"]);
$propertyBag.AddValue("WriteThroughput", $valuenameDictionary["IOThroughputWrite"]);
$propertyBag.AddValue("CapacityAvailable", $valuenameDictionary["CapacityAvailable"]);
$propertyBag.AddValue("CapacityTotal", $valuenameDictionary["CapacityTotal"]);
$propertyBag
}
#Create Storage Metrics property bag data
$healthreport = @()
$storageObject = $null
$IsStorageObjectExist = $false
$IsStorageSubSystem = $false
Try
{
$error.Clear();
AddTraceMessage -message "Metrics Script was run"
AddTraceMessage -message $storageClassName
if ($false -eq $IsStorageModuleReady)
{
$message = "Cannot initialize storage Powershell cmdlets. Exiting.."
AddTraceMessage -message $message
LogErrors -exception $null
exit
}
if ($storageClassName -eq "MSFT_StorageSubSystem")
{
$message = "Trying to get storage subsystems"
AddTraceMessage -message $message
$storageObjects = Get-StorageSubsystem -Model Cluster*
$IsStorageObjectExist = $true
$message = "Finish getting storage object data."
AddTraceMessage -message $message
$IsStorageSubSystem = $true
}
elseif($storageClassName -eq "MSFT_Volume")
{
$message = "Trying to get volumes"
AddTraceMessage -message $message
$storageObjects = Get-Volume -StorageSubSystem (Get-StorageSubSystem -Model Cluster*) | Where-Object {$_.FileSystemLabel -ne "ClusterPerformanceHistory"}
$IsStorageObjectExist = $true
$message = "Finish getting storage object data."
AddTraceMessage -message $message
}
elseif ($storageClassName -eq "MSFT_FileShare")
{
$message = "Trying to get file shares"
AddTraceMessage -message $message
$fileshares = Get-FileShare -Subsystem (Get-StorageSubSystem -Model Cluster*)
$IsStorageObjectExist = $true
$message = "Finish getting storage object data."
AddTraceMessage -message $message
if ([string]::IsNullOrEmpty($fileshares))
{
$message = "File Shares are not found. Exiting.."
AddTraceMessage -message $message
LogErrors -exception $null
exit
}
$storageObjects = @()
foreach($fileshare in $fileshares)
{
$message = "Trying to get storage volume from File Share with Id: $fileshare.UniqueID"
AddTraceMessage -message $message
$volume = Get-CimAssociatedInstance -InputObject $fileshare -Association MSFT_VolumeToFileShare -Namespace $msft_namespace
$message = "Finish getting volumes for File Share."
AddTraceMessage -message $message
if ($volume -eq $null -or $volume.OperationalStatus -ne "OK")
{
$message = "Volume for File Share with Id: $fileshare.UniqueID is not found or in offline state. Exiting.."
AddTraceMessage -message $message
LogErrors -exception $null
}
else
{
$storageObjects += ,$volume
}
}
}
elseif ($storageClassName -eq "MSFT_StorageNode")
{
$message = "Trying to get storage Nodes"
AddTraceMessage -message $message
$storageObjects = Get-StorageNode -StorageSubSystem (Get-StorageSubSystem -Model Cluster*)
$IsStorageObjectExist = $true
$message = "Finish getting storage object data."
AddTraceMessage -message $message
$IsStorageSubSystem = $true
if ($null -eq $storageObjects)
{
$message = "Storage Objects are empty. Exiting.."
AddTraceMessage -message $message
LogErrors -exception $null
exit
}
foreach($storageObject in $storageObjects)
{
if ($storageObject.OperationalStatus -ne "UP")
{
$message = "Storage Object with Id: $storageObject.UniqueID is in $($storageObject.OperationalStatus) state. Exiting.."
AddTraceMessage -message $message
LogErrors -exception $null
exit
}
Get-S2DStorageHealthReport $storageObject
}
exit
}
elseif ($storageClassName -eq "MSFT_StoragePool")
{
$storageObjects = Get-StoragePool | ? {$_.IsPrimordial -eq $false}
$IsStorageObjectExist = $true
if ($null -eq $storageObjects)
{
$message = "Storage Object are empty. Exiting.."
AddTraceMessage -message $message
LogErrors -exception $null
exit
}
foreach($storageObject in $storageObjects)
{
$ErrorActionPreference = "Stop"
$TotalCapacity = $storageObject.Size / 1TB
$TotalUsedSpace = $storageObject.AllocatedSize / 1TB
$TotalFreeSpace = $TotalCapacity - $TotalUsedSpace
$propertyBag = $momAPI.CreatePropertyBag()
$propertyBag.AddValue("SourceUniqueId", $storageObject.UniqueID);
$propertyBag.AddValue("TotalCapacity", $TotalCapacity);
$propertyBag.AddValue("TotalUsedSpace", $TotalUsedSpace);
$propertyBag.AddValue("TotalFreeSpace", $TotalFreeSpace);
$propertyBag
}
exit
}
if ($null -eq $storageObjects)
{
$message = "Storage Objects are empty. Exiting.."
AddTraceMessage -message $message
LogErrors -exception $null
exit
}
Foreach ($storageObject in $storageObjects)
{
if ($storageObject.OperationalStatus -ne "OK" -and $storageObject.OperationalStatus -ne "Online")
{
$message = "Storage Object with Id: $storageObject.UniqueID is in $($storageObject.OperationalStatus) state. Exiting.."
AddTraceMessage -message $message
LogErrors -exception $null
}
else
{
if ($true -eq $IsStorageSubSystem)
{
$message = "Trying to get Health Report for storage object with Id: $storageObject.UniqueID"
AddTraceMessage -message $message
$healthreport = GetHealthReport -storageSubSystem $storageObject -storageObject $storageObject
}
else
{
$message = "Trying to get S2D storage subsystem for storage object with Id: $storageObject.UniqueID"
AddTraceMessage -message $message
$storagesubsystem = GetS2DStorageSubsystem -storageobject $storageObject
$message = "Trying to get Health Report for storage object with Id: $storageObject.UniqueID"
AddTraceMessage -message $message
$healthreport = GetHealthReport -storageSubSystem $storagesubsystem -storageObject $storageObject
}
$message = "Finish processing Health Report for storage object with Id: $storageObject.UniqueID"
AddTraceMessage -message $message
if ($null -eq $healthreport -or $healthreport.Count -eq 0)
{
$message = "Metrics for Storage Object with UniqueID: $storageObject.UniqueID, were not found. Health report is empty."
AddTraceMessage -message $message
LogErrors -exception $null
exit
}
$valuenameDictionary = @{}
$recordsList = @()
$recordsList += $healthreport.Records | select
if($recordsList -eq $null -or $recordsList.Count -eq 0)
{
$message = "Metrics records for Storage Object with UniqueID: $storageObject.UniqueID, were not found in health report."
AddTraceMessage -message $message
LogErrors -exception $null
exit
}
foreach ($record in $recordsList)
{
if ($null -eq $record.Value -or [string]::IsNullOrEmpty($record.Name)) {continue;}
if ($valuenameDictionary.ContainsKey($record.Name)) {continue;}
$divider = GetDivider($record.Name)
$calculatedValue = [Math]::Round($record.Value/$divider,3);
$valuenameDictionary.Add($record.Name, $calculatedValue);
}
AddBag -valuenameDictionary $valuenameDictionary -UniqueID $storageObject.UniqueID
}
}
}
Catch
{
#If storage object doesn't exist SCOM may have lag in discovery so ignore this case
$exception = Get-FaultException -exception $_.Exception -IsObjectExist $IsStorageObjectExist
AddTraceMessage -message $exception.Message
}
Finally
{
LogErrors -exception $exception
}
</Script> </ScriptBody>
<Parameters>
<Parameter>
<Name>storageClassName</Name>
<Value>$Config/StorageClassName$</Value>
</Parameter>
<Parameter>
<Name>DebugMode</Name>
<Value>$Config/DebugMode$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
<StrictErrorHandling>true</StrictErrorHandling>
</ProbeAction>
</MemberModules>
<Composition>
<Node ID="Script">
<Node ID="Scheduler"/>
</Node>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.PropertyBagData</OutputType>
</DataSourceModuleType>