Microsoft.SystemCenter.OperationsManager.Storage.RefreshCache.DSType (DataSourceModuleType)

Element properties:

TypeDataSourceModuleType
IsolationAny
AccessibilityInternal
RunAsSystem.PrivilegedMonitoringAccount
OutputTypeSystem.PropertyBagData

Member Modules:

ID Module Type TypeId RunAs 
WmiEventProviderDS DataSource Microsoft.Windows.WmiEventProvider Default
PA ProbeAction Microsoft.Windows.PowerShellPropertyBagProbe Default

Overrideable Parameters:

IDParameterTypeSelector
PollIntervalint$Config/PollInterval$

Source Code:

<DataSourceModuleType ID="Microsoft.SystemCenter.OperationsManager.Storage.RefreshCache.DSType" Accessibility="Internal" Batching="false" RunAs="System!System.PrivilegedMonitoringAccount">
<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="VMMServerName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="StorageObjectUniqueId" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="StorageObjectOMClassInstanceId" type="xsd:string"/>
<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" name="PollInterval" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" maxOccurs="1" name="TimeoutSeconds" type="xsd:integer"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="PollInterval" Selector="$Config/PollInterval$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<DataSource ID="WmiEventProviderDS" TypeID="Windows!Microsoft.Windows.WmiEventProvider">
<NameSpace>\\$Config/VMMServerName$\root\Microsoft\Windows\Storage</NameSpace>
<Query>Select * from MSFT_StorageAlertEvent Where AlertType=2</Query>
<!--2 stands for "One or more indications may have been dropped". This is our cue to refresh by calling Diagnose script-->
<PollInterval>$Config/PollInterval$</PollInterval>
</DataSource>
<ProbeAction ID="PA" TypeID="Windows!Microsoft.Windows.PowerShellPropertyBagProbe">
<ScriptName>DiagnoseFileShareVolume.ps1</ScriptName>
<ScriptBody><Script># Creates sets of property bag data with File share to it's VHD subscription percentage
# Script parameters
# - $vmmServerName - VMM server name
# - $domain,$username,$pass - VMM Server Connection Account
# - $storageObjectUniqueId - UniqueId property of a given storage object
# - $storageObjectOMClassInstanceId - target storage object's class instance Id (OM)
# - Sample usage - .\DiagnoseFileShareVolume.ps1 -vmmServerName vmvmmServerName -domain redmond -username asttest -pass &lt;asttest_password&gt; -storageObjectUniqueId "{30fe9473-f681-482e-9373-44a46871219a}:SS" -storageObjectOMClassInstanceId "{B5DCAC09-20E9-B9C6-1FBF-B7841F629F06}"

param( [string] $vmmServerName, [string] $domain, [string] $username, [string] $pass, [string] $storageObjectUniqueId, [string] $storageObjectOMClassInstanceId, $storageClassName)

#Storage Monitoring Event Ids
$GenericInformationEvent = 8800;
$GenericWarningEvent = 8801;
$GenericFailureEvent = 8802;
$CredentialNullCode = 8803;

$errorActionPreference = 'Stop'

$momAPI = New-Object -comObject 'MOM.ScriptAPI'

$errEvent = [System.Diagnostics.EventLogEntryType]::Error;
$infoEvent = [System.Diagnostics.EventLogEntryType]::Information;
$warningEvent = [System.Diagnostics.EventLogEntryType]::Warning;

#Alert Resolution States
$ResolutionStateClose = 255;
$ResolutionStateActive = 0;

$script:traceMsg = "";

#Adds tracemessage to $Script
Function AddTraceMessage
{
param($message)
$timeStamp = (get-date -format "HH:mm:ss:fff");
$script:traceMsg = $script:traceMsg + "`n[" + $timeStamp + "] " + $message;
}

Function CloseAlert
{
param($faultId)

Try
{
$FaultIdpatternToLookForInAlertContext = ("*" + $faultId +":" + $storageObjectUniqueId + "*");

AddTraceMessage -message "Searching OM Alert with this pattern: `n $FaultIdpatternToLookForInAlertContext"

$alert = (Get-SCOMAlert) | Where-Object {($_.Context -like $FaultIdpatternToLookForInAlertContext)}

if($alert -ne $null)
{
$alertName = $alert[0].Name;
AddTraceMessage -message ("Alert found. Name = " + $alertName)
Set-SCOMAlert -Alert $alert -ResolutionState $ResolutionStateClose
AddTraceMessage -message "Alert is closed."
}
else
{
AddTraceMessage -message "Could not find OM Alert with CompositeId = $faultId +":" + $storageObjectUniqueId"
}
}
Catch
{
$momAPI.LogScriptEvent("DiagnoseFileShareVolume.ps1", $GenericWarningEvent, 0, "Failed to close alert, please close the alert manually once the recommended action for the alert is taken. Exception message: " + $_.Exception.Message);
}
}

Try
{
$error.Clear();

AddTraceMessage -message "Storage monitoring script DiagnoseFileShareVolume.ps1 started."

AddTraceMessage -message "vmmServerName = $vmmServerName `ndomain = $domain`nusername = $username`nstorageObjectUniqueId=$storageObjectUniqueId`nstorageObjectOMClassInstanceId=$storageObjectOMClassInstanceId`storageClassName=$storageClassName"

#Import OperationsManager commands
$omModule = get-module -name "OperationsManager"
if ($omModule -eq $null)
{
$SCOMPowerShellKey = "HKLM:\SOFTWARE\Microsoft\System Center Operations Manager\12\Setup\Powershell\V2"
$SCOMModulePath = Join-Path (Get-ItemProperty $SCOMPowerShellKey).InstallDirectory "OperationsManager"
Import-module $SCOMModulePath | Out-Null
}

#Connect to OM server
AddTraceMessage -message "Getting OM management server to connect to."

$managementServerName = 'localhost'

'if($mg -ne $null)
{
$managementServerName = $mg.OpsMgrServerName;
}
else
{
Throw [System.NullReferenceException] "Failed to connect get OM MG connection. This is fatal error, script will fail.";
}
'

AddTraceMessage -message "Connecting to $managementServerName OM management server."

New-SCManagementGroupConnection -ComputerName $managementServerName

AddTraceMessage -message "Connected to $managementServerName SDK. Now getting target class Instance"

# Get MonitoringObjectId in Guid format
$storageObjectId = New-Object -TypeName System.Guid -ArgumentList $storageObjectOMClassInstanceId

if($storageObjectId -eq $null)
{
AddTraceMessage -message "Failed to get storageObjectId."
return;
}

# Get OM MonitoringObject
$scomMonitoringObject = Get-SCOMMonitoringObject -Id $storageObjectId
if($scomMonitoringObject -eq $null)
{
AddTraceMessage -message "Failed to get scomMonitoringObject."
return;
}

$newAlertsNeeded = @{}

$cred = $null;

if($domain -AND $username -AND $pass)
{
#Append domain to get domain\username
$domainUser = $domain + "\" + $username;

#Create Cred object
$securePass = ConvertTo-SecureString -AsPlainText $pass -force
$cred = New-Object System.Management.Automation.PSCredential $domainUser, $securePass;
}

if ($cred -eq $null)
{
$momAPI.LogScriptEvent(("Credentials are null for user: " + $domainUser), $CredentialNullCode, 1, $error);
return;
}

$error.Clear();

$session = New-PSSession -ComputerName $vmmServerName -Authentication Credssp -Credential $cred;
if ( ($error -ne $null) -and ($error.Count -ne 0) )
{
if ($session -ne $null)
{
Remove-PSSession $session;
$session = $null;
}
return;
}

AddTraceMessage -message ("Creating new PS session with VMM server: " + $vmmServerName)

$scVMMServer = Invoke-Command -Session $session -ArgumentList $vmmServerName -ScriptBlock {$module = get-module -name "virtualmachinemanager"; if ($module -eq $null) {Import-Module "virtualmachinemanager"; } $vmm = Get-SCVMMServer -ComputerName $args[0]; $vmm};
if ($scVMMServer -eq $null)
{
AddTraceMessage -message ("VMM Server was null" + $error)
Remove-PSSession $session;
$session = $null;
return;
}

AddTraceMessage -message ("Created new PS session with VMM server: " + $vmmServerName)

# storage block that is invoked on remote PS session to VMM server
$sb = {
Function AddTraceMessage
{
param($message)
$timeStamp = (get-date -format "HH:mm:ss:fff");
$global:blockTraceMsg = $global:blockTraceMsg + "`n[RemoteSession]: " + "[" + $timeStamp + "]" + $message;
}

Try
{
$evt = New-Object System.Diagnostics.Eventlog("Application");
$evt.Source = "System Center Operations Manager Storage Monitoring";
$errorevent = [System.Diagnostics.EventLogEntryType]::Error;
$infoevent = [System.Diagnostics.EventLogEntryType]::Information;

$error.Clear()

$global:blockTraceMsg = "";
$storageclassName = $args[1]
AddTraceMessage -message "getting storage object of class $storageClassName"

if($storageclassName -eq "MSFT_FileShare")
{
$storageObject = Get-FileShare -UniqueId $args[0]
}
elseif($storageclassName -eq "MSFT_Volume")
{
$storageObject = Get-Volume -UniqueId $args[0]
}

if($storageObject -eq $null)
{
AddTraceMessage -message "Can not call Diagnose(), storage object is null."
}

$results = Invoke-CimMethod -InputObject $storageObject -Method Diagnose

AddTraceMessage -message "Diagnose succeeded."

$results
}
Finally #disconnect VMM in remote session before exiting
{
if ($vmm -ne $null)
{
$vmm.Disconnect();
$vmm = $null;
}

if ($error -ne $null -and $error.Count -gt 0)
{
if ($error[0].Exception -ne $null)
{
$evt.WriteEntry($error[0].Exception.ToString(), $errorevent, 8508);
}
}
if ($global:blockTraceMsg -ne $null -and $global:blockTraceMsg.Length -lt 31839)
{
$evt.WriteEntry($global:blockTraceMsg, $infoevent, 8508);
}
}};

AddTraceMessage -message ("Invoking command to get storage object Diagsnotics result using Diagnose() method on vmm server: " + $vmmServerName)

$results = Invoke-Command -Session $session -ScriptBlock $sb -ArgumentList @($storageObjectUniqueId, $storageClassName)

if($results -ne $null)
{
$diagnoseResultsCount = $results.DiagnoseResults.Count
AddTraceMessage -message "Number of storage Diagnostics results found = $diagnoseResultsCount";
}

foreach($diagnosticsResult in $results.DiagnoseResults)
{
$storageFaultId = $diagnosticsResult.FaultId

# it is very unlikely that we will have result with a null or empty fault id string,
# but a safe check because this script closes all alerts based on fault id pattern, and in case of empty faultid string it may end up closing all active OM alerts for this object
if([string]::IsNullOrEmpty($storageFaultId))
{
AddTraceMessage -message "Null or empty storageFaultId in the Diagnostics Result. Skipping this fault";
continue
}

AddTraceMessage -message "An existing fault found on storage object $storageObjectUniqueId : $storageFaultId";

# Check if there are SCOM alerts for this fault Id
$FaultIdpatternToLookForInAlertContext = ("*" + $diagnosticsResult.FaultId +":" + $storageObjectUniqueId + "*");

AddTraceMessage -message "Searching OM Alert with this pattern: `n $FaultIdpatternToLookForInAlertContext"

$omAlertsForStorageFault = (Get-SCOMAlert -Instance $scomMonitoringObject) | Where-Object {$_.Context -like $FaultIdpatternToLookForInAlertContext}
if($omAlertsForStorageFault.Count -ne 0) #Alert already present
{
AddTraceMessage -message "No need to generate an alert for fault id $storageFaultId as there is already an alert generated for this fault Id."
}
else
{
# Delta between faults in Diagnose() results that are not in OMAlerts
AddTraceMessage -message "No alert found for fault id storageFaultId. Adding this fault Id to the list of new alerts to be generated."
$newAlertsNeeded.Add($diagnosticsResult.FaultId, $diagnosticsResult);
}
}

if($newAlertsNeeded -ne $null)
{
$numberOfNewAlerts = $newAlertsNeeded.Count;
AddTraceMessage -message "Number of alerts to be generated = $numberOfNewAlerts"
}

#Generate new alerts for new faults
foreach($newAlertsNeededItem in $newAlertsNeeded.GetEnumerator())
{
$faultIdForNewAlert = $newAlertsNeededItem.Key;
$diagnosticsResultForNewAlert = $newAlertsNeededItem.Value;

#Create new alert property bag data
$propertyBag = $momAPI.CreatePropertyBag()
$propertyBag.AddValue("FaultId", $diagnosticsResultForNewAlert.FaultId);
$propertyBag.AddValue("FaultingObjectDescription", $diagnosticsResultForNewAlert.FaultingObjectDescription);
$propertyBag.AddValue("Reason", $diagnosticsResultForNewAlert.Reason);
$propertyBag.AddValue("RecommendedActions", $diagnosticsResultForNewAlert.RecommendedActions -join "`n");
$propertyBag.AddValue("SourceUniqueId", $storageObjectUniqueId);

$perceivedSeverity = $diagnosticsResultForNewAlert.PerceivedSeverity;
$propertyBag.AddValue("PerceivedSeverity", $perceivedSeverity);

#OM Alert severity
$alertSeverity = 1; # Default for OM would be warning
if($perceivedSeverity -eq 2)
{
$alertSeverity = 0 #Information
}
elseif(($perceivedSeverity -eq 3) -or ($perceivedSeverity -eq 4))
{
$alertSeverity = 1 #Warning
}
elseif(($perceivedSeverity -ge 5))
{
$alertSeverity = 2 #Warning
}

$propertyBag.AddValue("OM Alert Severity", $alertSeverity);

$propertyBag.AddValue("CompositeAlertId", $diagnosticsResultForNewAlert.FaultId + ":" + $storageObjectUniqueId);

$propertyBag
}

Try
{
# Get All active storage alerts
$allOMAlerts = Get-SCOMAlert -Instance $scomMonitoringObject | where-object {($_.Context -like '*FaultId*') -and ($_.ResolutionState -eq $ResolutionStateActive)}

# Get list of all FaultIds from all active storage alerts
$allOMAlertsFaultIds = ($allOMAlerts | ForEach-Object { $context = [xml]$_.Context; ($context.DataItem.Property | where {$_.Name -eq "FaultId"}).InnerText})

AddTraceMessage -message "Found alerts with storage faults on this object.`nAlert exist for these FaultIds = $allOMAlertsFaultIds"

$allDiagnosticcsResultsFaults = $results.DiagnoseResults.FaultId
AddTraceMessage -message "Diagnose() found these faults are still present = $allDiagnosticcsResultsFaults"

# Delta between OMAlerts that are not in the Diagnose() results anymore
$closeAlertsForTheseFaults = $allOMAlertsFaultIds | ?{$results.DiagnoseResults.FaultId -notcontains $_}

$numberOfStaleAlerts = $closeAlertsForTheseFaults.Count
AddTraceMessage -message "Number of alerts to be closed = $numberOfStaleAlerts"

# Close Alerts
foreach($faultIdToBeClosed in $closeAlertsForTheseFaults)
{
CloseAlert -faultId $faultIdToBeClosed
}
}
Catch
{
$momAPI.LogScriptEvent("DiagnoseFileShareVolume.ps1", $GenericWarningEvent, 0, "Failed to close active storage alerts for closed storage faults, please close the alert manually once the recommended actions for any such alerts are taken. Exception message: " + $_.Exception.Message);
}

AddTraceMessage -message "Storage monitoring script DiagnoseFileShareVolume.ps1 completed."
}
Catch
{
AddTraceMessage -message $_.Exception.Message
}
Finally
{
if ($session -ne $null)
{
Remove-PSSession $session;
}

if ($error -ne $null -and $error.Count -gt 0 -and $error[0] -ne $null)
{
$momAPI.LogScriptEvent("DiagnoseFileShareVolume.ps1", $GenericFailureEvent, 1, [string]$error);
}

if ($script:traceMsg -ne $null)
{
$momAPI.LogScriptEvent("DiagnoseFileShareVolume.ps1", $GenericInformationEvent, 0, $script:traceMsg);
}
}</Script></ScriptBody>
<Parameters>
<Parameter>
<Name>vmmServerName</Name>
<Value>$Config/VMMServerName$</Value>
</Parameter>
<Parameter>
<Name>domain</Name>
<Value>$RunAs[Name="PROV2Library!Microsoft.SystemCenter.VirtualMachineManager.2012.VMMServerConnectionRunAsProfile"]/Domain$</Value>
</Parameter>
<Parameter>
<Name>username</Name>
<Value>$RunAs[Name="PROV2Library!Microsoft.SystemCenter.VirtualMachineManager.2012.VMMServerConnectionRunAsProfile"]/UserName$</Value>
</Parameter>
<Parameter>
<Name>pass</Name>
<Value>$RunAs[Name="PROV2Library!Microsoft.SystemCenter.VirtualMachineManager.2012.VMMServerConnectionRunAsProfile"]/Password$</Value>
</Parameter>
<Parameter>
<Name>storageObjectUniqueId</Name>
<Value>$Config/StorageObjectUniqueId$</Value>
</Parameter>
<Parameter>
<Name>storageObjectOMClassInstanceId</Name>
<Value>$Config/StorageObjectOMClassInstanceId$</Value>
</Parameter>
<Parameter>
<Name>storageClassName</Name>
<Value>$Config/StorageClassName$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
<StrictErrorHandling>true</StrictErrorHandling>
</ProbeAction>
<!--<ConditionDetection ID="CD" TypeID="System!System.ExpressionFilter">
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="String">Property[@Name='AlertType']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value>2</Value>
-->
<!--2 stands for "One or more indications may have been dropped". This is our cue to refresh by calling Diagnose script-->
<!--
</ValueExpression>
</SimpleExpression>
</Expression>
</ConditionDetection>-->
</MemberModules>
<Composition>
<!--<Node ID="CD">-->
<Node ID="PA">
<Node ID="WmiEventProviderDS"/>
</Node>
<!--</Node>-->
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.PropertyBagData</OutputType>
</DataSourceModuleType>