[Nano Server] Cluster Shared Volume Monitoring Script Data Source

Microsoft.Windows.Server.ClusterSharedVolumeMonitoring.ClusterSharedVolume.Monitoring.ScriptDataSource (DataSourceModuleType)

Element properties:

TypeDataSourceModuleType
IsolationAny
AccessibilityInternal
RunAsDefault
OutputTypeSystem.PropertyBagData

Member Modules:

ID Module Type TypeId RunAs 
Scheduler DataSource System.Scheduler Default
DS ProbeAction Microsoft.Windows.PowerShellPropertyBagProbe Default
Filter ConditionDetection System.ExpressionFilter Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
IntervalSecondsint$Config/IntervalSeconds$Interval
LogSuccessEventbool$Config/LogSuccessEvent$Log Successful Event
ScriptGroupIdstring$Config/ScriptGroupId$Event Log Source
TimeoutSecondsint$Config/TimeoutSeconds$Timeout

Source Code:

<DataSourceModuleType ID="Microsoft.Windows.Server.ClusterSharedVolumeMonitoring.ClusterSharedVolume.Monitoring.ScriptDataSource" Accessibility="Internal" Batching="false">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="IntervalSeconds" type="xsd:integer" minOccurs="1"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SyncTime" type="xsd:string" minOccurs="1"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="LogSuccessEvent" type="xsd:boolean"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ScriptGroupId" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="TargetComputer" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ClusterName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="TimeoutSeconds" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ClusterSharedVolumeName" type="xsd:string"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int"/>
<OverrideableParameter ID="LogSuccessEvent" Selector="$Config/LogSuccessEvent$" ParameterType="bool"/>
<OverrideableParameter ID="ScriptGroupId" Selector="$Config/ScriptGroupId$" ParameterType="string"/>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
</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="DS" TypeID="Windows!Microsoft.Windows.PowerShellPropertyBagProbe">
<ScriptName>Microsoft.Windows.Server.CSV.MonitorClusterSharedVolume.ps1</ScriptName>
<ScriptBody><Script>

param ($mblnLogSuccessEvent, $mstrIdentifier, $strTargetComputer, $strClusterName)

$SCRIPT_VERSION = "1.05"
$LOG_SUCCESS_EVENT_PARAMETER_NAME = "LogSuccessEvent"
$MP_ELEMENT_PARAMETER_NAME = "MP Element"
$MANAGED_ENTITY_ID_PARAMETER_NAME = "Managed Entity"
$TARGET_COMPUTER_PARAMETER_NAME = "Target Computer"
$CLUSTER_NAME_PARAMETER_NAME = "Cluster Name"

#WMI constants
$WMI_MSCLUSTER_NAMESPACE = "root\MSCluster"
$WMI_CIMV2_NAMESPACE = "root\cimv2"
$WMI_MSCLUSTER_CLUSTER_SHARED_VOLUME = "MSCluster_ClusterSharedVolume"
$WMI_CLUSTER_SHARED_VOLUME_TO_PARTITION_ASSOCIATOR_CLASS = "MSCluster_ClusterSharedVolumeToPartition"
$WMI_CLUSTER_SHARED_VOLUME_TO_RESOURCE_ASSOCIATOR_CLASS = "MSCluster_ClusterSharedVolumeToResource"

$WMI_MSCLUSTER_CLUSTER_CLASS = "MSCluster_Cluster"
$WMI_NAME_PROPERTY_NAME = "Name"
$WMI_PATH_PROPERTY_NAME = "Path"
$WMI_FILESYSTEM_PROPERTY_NAME = "FileSystem"
$WMI_TOTALSIZE_PROPERTY_NAME = "TotalSize"
$WMI_FREESPACE_PROPERTY_NAME = "FreeSpace"
$WMI_FAULTSTATE_PROPERTY_NAME = "FaultState"
$WMI_VOLUMELABEL_PROPERTY_NAME = "VolumeLabel"
$MAX_FIELD_LENGTH = 256

#State property bag constants
$STATE_DATA_TYPE = 3
$STATE_PROPERTY_NAME = "State"
$STATE_NTFS_NAME = "NTFSIsDirty"
$STATE_GOOD = "GOOD"
$STATE_BAD = "BAD"

#Performance property bag constants
$INSTANCE_NAME = "ClusterSharedVolumeName"
$PERFORMANCE_DATA_TYPE = 2
$PERFORMANCE_OBJECT_NAME = "PerfObject"
$PERFORMANCE_COUNTER_NAME = "PerfCounter"
$PERFORMANCE_INSTANCE_NAME = "PerfInstance"
$PERFORMANCE_VALUE_NAME = "PerfValue"
$PERF_OBJECT_CSV = "Cluster Shared Volume"
$PERF_COUNTER_TOTAL_SIZE_MB = "Total size / MB"
$PERF_COUNTER_FREE_SPACE_MB = "Free space / MB"
$PERF_COUNTER_FREE_SPACE_PERCENT = "Free space / Percent"
$PERF_COUNTER_STATE_PROPERTY_NAME = "State"
$PERF_COUNTER_STATE_NTFS_NAME = "NTFSIsDirty"

#Event constants
$EVENT_TYPE_SUCCESS = 0
$EVENT_TYPE_ERROR = 1
$EVENT_TYPE_WARNING = 2
$EVENT_TYPE_INFORMATION = 4

$EVENT_ID_SUCCESS = 1000 #Use IDs in the range 1 - 1000
$EVENT_ID_SCRIPTERROR = 999 #Then you can use eventcreate.exe to test the MP

#Scripting.FileSystemObject constants
$FOR_READING = 1 #Open a file for reading only. You can#t write to this file.
$FOR_WRITING = 2 #Open a file for writing.
$FOR_APPENDING = 8 #Open a file and write to the end of the file.

#Global vars
#$mblnLogSuccessEvent #As String(ToBoolean) (passed in as parameter of script)
#$mstrIdentifier #As String (passed in as parameter of script)


#*********************************************************************************************
# PROCEDURE: Main
# DESCRIPTION: Reads the script parameters and creates the cluster shared volume discovery data.
# PARAMETERS: void
#*********************************************************************************************
Function Main()
{

$useCIM = CheckCmdLets
$mblnLogSuccessEvent = Convert-ToBoolean -sBool $mblnLogSuccessEvent
$objMomScriptAPI = New-Object -ComObject Mom.ScriptAPI -ErrorAction SilentlyContinue
if($null -eq $objMomScriptAPI)
{
return
}

$blnSuccess = $false

if($useCIM)
{
Get-PerfDataCim -objMomScriptAPI $objMomScriptAPI -blnSuccess ([ref]$blnSuccess)
}
else
{
Get-PerfDataNonCim -objMomScriptAPI $objMomScriptAPI -blnSuccess ([ref]$blnSuccess)
}

$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

if ($blnSuccess)
{
if ($mblnLogSuccessEvent -eq $true)
{
$objMomScriptAPI.LogScriptEvent(("Cluster Shared Volumes Monitoring Script -- `n`nScript name: " + (Split-Path $MyInvocation.ScriptName -Leaf) + "`nVersion: " + $SCRIPT_VERSION + "`n"),
$EVENT_ID_SUCCESS, $EVENT_TYPE_INFORMATION, "`nScript executed successfully.")
}
}
else
{
$objMomScriptAPI.LogScriptEvent(("Cluster Shared Volumes Monitoring Script -- `n`nScript name: " + (Split-Path $MyInvocation.ScriptName -Leaf) + "`nVersion: " + $SCRIPT_VERSION + "`n"),
$EVENT_ID_SCRIPTERROR, $EVENT_TYPE_WARNING, "`nAn error occurred while running script")
}
}






Function Set-PerfDataFromList($list, $objMomScriptAPI)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

if ($null -eq $objMomScriptAPI)
{
return
}

foreach($data in $list)
{
#Add the values for the perf counter#s object name, counter name, instance name and the value)
if(($data.$PERFORMANCE_OBJECT_NAME -eq $null) -or ($data.$PERFORMANCE_OBJECT_NAME -eq "")){
continue
}
$objTypedPropertyBag = $objMomScriptAPI.CreateTypedPropertyBag($PERFORMANCE_DATA_TYPE)
$objTypedPropertyBag.AddValue($PERFORMANCE_OBJECT_NAME, $data.$PERFORMANCE_OBJECT_NAME)
$objTypedPropertyBag.AddValue($PERFORMANCE_COUNTER_NAME, $data.$PERFORMANCE_COUNTER_NAME)
$objTypedPropertyBag.AddValue($PERFORMANCE_INSTANCE_NAME, $data.$PERFORMANCE_INSTANCE_NAME)
if($data.$PERFORMANCE_VALUE_NAME -eq $null)
{
$objTypedPropertyBag.AddValue($PERFORMANCE_VALUE_NAME, 0)
}else{
$objTypedPropertyBag.AddValue($PERFORMANCE_VALUE_NAME, $data.$PERFORMANCE_VALUE_NAME)
}

#Necessary information for the property bag data source filter condition
#to enable Agent cook down
$objTypedPropertyBag.AddValue($INSTANCE_NAME, $data.$INSTANCE_NAME)
$objTypedPropertyBag
#$objMomScriptAPI.Return($objTypedPropertyBag)
}

$error.Clear()
}

Function Get-PerfDataNonCim($objMomScriptAPI,[ref]$blnSuccess)
{
$blnSuccess.Value = $false
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$list = New-Object System.Collections.ArrayList($null)

if ($error.Count -ne 0)
{
$error.Clear()
return
}

$objClusterSharedVolumes = Get-WMIObject -Namespace $WMI_MSCLUSTER_NAMESPACE -Class $WMI_MSCLUSTER_CLUSTER_SHARED_VOLUME
if ($error.Count -ne 0)
{
$error.Clear()
return
}
#Loop through all returned cluster shared volumes
foreach ($objClusterSharedVolume in $objClusterSharedVolumes)
{
$objClusterDiskPartitions = $objClusterSharedVolume.GetRelated("MSCluster_DiskPartition")
$objClusterResources = $objClusterSharedVolume.GetRelated("MSCluster_Resource")
if ($error.Count -ne 0)
{
$error.Clear()
return
}

foreach ($objClusterDiskPartition in $objClusterDiskPartitions)
{
if ($error.Count -ne 0)
{
$error.Clear()
return
}

#Get the associated resource

foreach ($objClusterResource in $objClusterResources)
{
if ($error.Count -ne 0)
{
$error.Clear()
return
}

CreateMonitoringData -objClusterSharedVolume $objClusterSharedVolume -objClusterDiskPartition $objClusterDiskPartition -objClusterResource $objClusterResource -list $list
}
}
}

$blnSuccess.Value = $true
Set-PerfDataFromList -list $list -objMomScriptAPI $objMomScriptAPI
$error.Clear()

}

Function Get-PerfDataCim($objMomScriptAPI,[ref]$blnSuccess)
{
$blnSuccess.Value = $false
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$list = New-Object System.Collections.ArrayList($null)

if ($error.Count -ne 0)
{
$error.Clear()
return
}

$objClusterSharedVolumes = Get-CimInstance -Namespace $WMI_MSCLUSTER_NAMESPACE -ClassName $WMI_MSCLUSTER_CLUSTER_SHARED_VOLUME
if ($error.Count -ne 0)
{
$error.Clear()
return
}

#Loop through all returned cluster shared volumes
foreach ($objClusterSharedVolume in $objClusterSharedVolumes)
{
$objClusterDiskPartitions = (Get-CimAssociatedInstance -InputObject $objClusterSharedVolume -Association $WMI_CLUSTER_SHARED_VOLUME_TO_PARTITION_ASSOCIATOR_CLASS)
$objClusterResources = (Get-CimAssociatedInstance -InputObject $objClusterSharedVolume -Association $WMI_CLUSTER_SHARED_VOLUME_TO_RESOURCE_ASSOCIATOR_CLASS)
if ($error.Count -ne 0)
{
$error.Clear()
return
}

foreach ($objClusterDiskPartition in $objClusterDiskPartitions)
{
if ($error.Count -ne 0)
{
$error.Clear()
return
}

#Get the associated resource
foreach ($objClusterResource in $objClusterResources)
{
if ($error.Count -ne 0)
{
$error.Clear()
return
}

CreateMonitoringData -objClusterSharedVolume $objClusterSharedVolume -objClusterDiskPartition $objClusterDiskPartition -objClusterResource $objClusterResource -list $list

}
}
}

$blnSuccess.Value = $true
Set-PerfDataFromList -list $list -objMomScriptAPI $objMomScriptAPI
$error.Clear()

}


#****************************************************************************************************************
# FUNCTION: CreateMonitoringData
# DESCRIPTION: Create monitoring data for a cluster shared volume.
#
# PARAMETERS: IN Object objClusterSharedVolume: the cluster shared volume as SWbemObject of type MSCluster_ClusterSharedVolume.
# IN Object objClusterDiskPartition: the associated disk partition as SWbemObject of type MSCluster_DiskPartition.
# IN Object objClusterResource: the associated cluster resource as SWbemObject of type MSCluster_Resource.
# IN String strTargetComputer: the principal name of the targeted cluster virtual server hosting the cluster shared volume,
# i.e. the cluster name and not the current owner!
# IN String strClusterName: the cluster containing the cluster shared volume
# RETURNS: Boolean: True if successful
#****************************************************************************************************************
Function CreateMonitoringData($objClusterSharedVolume, $objClusterDiskPartition, $objClusterResource,$list) #As Boolean
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
#Create performance data
if ($null -eq $list)
{
$error.Clear()
return
}

$strCSVName = $objClusterResource.$WMI_NAME_PROPERTY_NAME + "_" + $objClusterSharedVolume.$WMI_NAME_PROPERTY_NAME

if ($strCSVName.Length -gt $MAX_FIELD_LENGTH)
{
$strCSVName = $strCSVName.Substring(0,$MAX_FIELD_LENGTH)
}

if ($true -eq [string]::IsNullOrEmpty($objClusterResource.$WMI_NAME_PROPERTY_NAME) -or $true -eq [string]::IsNullOrEmpty($objClusterSharedVolume.$WMI_NAME_PROPERTY_NAME) )
{
return
}

#CSV State
[void]$list.Add( (CreatePerformanceTypedPropertyBag $PERF_OBJECT_CSV $PERF_COUNTER_STATE_PROPERTY_NAME $strCSVName `
$objClusterSharedVolume.$WMI_FAULTSTATE_PROPERTY_NAME $strCSVName))

#NTFSDirty (for future use)
[void]$list.Add( (CreatePerformanceTypedPropertyBag $PERF_OBJECT_CSV $PERF_COUNTER_STATE_NTFS_NAME $strCSVName `
0 $strCSVName ))
#Total Size /MB
[void]$list.Add( (CreatePerformanceTypedPropertyBag $PERF_OBJECT_CSV $PERF_COUNTER_TOTAL_SIZE_MB $strCSVName `
$objClusterDiskPartition.$WMI_TOTALSIZE_PROPERTY_NAME $strCSVName))
#Free Space /MB
[void]$list.Add( (CreatePerformanceTypedPropertyBag $PERF_OBJECT_CSV $PERF_COUNTER_FREE_SPACE_MB $strCSVName `
$objClusterDiskPartition.$WMI_FREESPACE_PROPERTY_NAME $strCSVName))
#Free Space /%
[void]$list.Add( (CreatePerformanceTypedPropertyBag $PERF_OBJECT_CSV $PERF_COUNTER_FREE_SPACE_PERCENT $strCSVName `
([math]::round(($objClusterDiskPartition.$WMI_FREESPACE_PROPERTY_NAME)/($objClusterDiskPartition.$WMI_TOTALSIZE_PROPERTY_NAME), 2) * 100) `
$strCSVName))

$error.Clear()

}

#***************************************************************************************
# PROCEDURE: CreatePerformanceTypedPropertyBag
# DESCRIPTION: Generates a performance typed property bag and adds it to the script#s XML output.
# PARAMETERS: IN String strObjectName: name of the performance object
# IN String strCounterName: name of the performance counter
# IN String strInstanceName: name of the performance counter in instance
# IN Variant varValue: value of the performance counter
# IN String strCSVInstanceName: Friendly volume name of the cluster shared volume
# IN Object objMomScriptAPI: initialised MOM.ScriptAPI object
#***************************************************************************************
Function CreatePerformanceTypedPropertyBag($strObjectName, $strCounterName, $strInstanceName,$varValue, $strCSVInstanceName)
{
return @{ $PERFORMANCE_OBJECT_NAME = $strObjectName;
$PERFORMANCE_COUNTER_NAME = $strCounterName;
$PERFORMANCE_INSTANCE_NAME = $strInstanceName;
$PERFORMANCE_VALUE_NAME = $varValue;
$INSTANCE_NAME = $strCSVInstanceName}
}
################################################################
##Common Functions
################################################################
$CIM_ERROR_INVALIDCLASS = 2147749902
$CIM_ERROR_INVALIDNAMESPACE = 2147749904
$WMI_ERROR_INVALIDCLASS = -2147217392
$WMI_ERROR_INVALIDNAMESPACE = -2147217394


Function Check-WmiException ($Exception)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$bresult = $false

if ($null -eq $Exception)
{
return $bresult
}

$type = $Exception.GetType()

#Invalid ClassName or NameSpace
if([System.Management.ManagementException] -eq $type)
{
$ErrorCode = $Exception.ErrorCode.value__
if ($WMI_ERROR_INVALIDCLASS -eq $ErrorCode -or $WMI_ERROR_INVALIDNAMESPACE -eq $ErrorCode)
{
$bresult = $true
}
}

return $bresult

}

Function Check-CimException ($Exception)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$bresult = $false

if ($null -eq $Exception)
{
return $bresult
}

$type = $Exception.GetType()
$error.Clear()
$WmiExcept = [Microsoft.Management.Infrastructure.CimException] -eq $type
if ($error.Count -ne 0)
{
$error.Clear()
return $bresult
}
#Invalid ClassName or NameSpace
if($WmiExcept)
{
$ErrorCode = $Exception.ErrorData.Error_code
if ($CIM_ERROR_INVALIDCLASS -eq $ErrorCode -or $CIM_ERROR_INVALIDNAMESPACE -eq $ErrorCode)
{
$bresult = $true
}
}

return $bresult

}

Function Convert-ToBoolean([string] $sBool)
{
[bool] $result = $false
[bool] $iresult = $false

if ($false -eq [string]::IsNullOrEmpty($sBool) )
{
$result = $sBool.Equals("true",[System.StringComparison]::InvariantCultureIgnoreCase)
$iresult = $sBool.Equals("1",[System.StringComparison]::InvariantCultureIgnoreCase)
$result = $result -or $iresult
}

return $result
}


Function CheckCimModule()
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$retval = $false
$cim = Get-Module -Name CimCmdlets

########Check for powershell 1.0
if ($error.Count -ne 0)
{
$type = $error[0].Exception.GetType()
if ([System.Management.Automation.CommandNotFoundException] -eq $type)
{
return $retval
}

$error.Clear()
}

if ($null -eq $cim)
{
Import-Module CimCmdLets
if ($error.Count -eq 0)
{
$retval = $true
}

$error.Clear()
}
else
{
$retval = $true
}

return $retval
}

function CheckCmdLets()
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()

$retval = $false
$objSWbemObjectSet =$null

if (CheckCimModule)
{
$objSWbemObjectSet = Get-CimInstance -Class Win32_OperatingSystem -ErrorAction Stop
if ($error.Count -eq 0)
{
$retval = $true
}
}

$error.Clear()
return $retval;
}

Function Get-ClusterNameFromRegistry
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$ClusterPath = "HKLM:\Cluster"
$key = Get-ItemProperty -Path $ClusterPath -Name "ClusterName"
$result = [string]::Empty

if ($key -ne $null)
{
$result = $key.ClusterName
}

$error.Clear()
return $result

}

Function Get-ClusterName ($useCim)
{
$ClusterName = Get-ClusterNameFromRegistry

If (-Not [string]::IsNullOrEmpty($ClusterName) )
{
return $ClusterName
}

$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$WMI_MSCLUSTER_NAMESPACE_Local = "root\MSCluster"

if($useCIM)
{
$Clusters = Get-CimInstance -ClassName MSCluster_Cluster -NameSpace $WMI_MSCLUSTER_NAMESPACE_Local
if ($error.Count -ne 0)
{
return $ClusterName
}

foreach ($Cluster in $Clusters)
{
$ClusterName = $Cluster.Name
break
}
}else
{
$Clusters = Get-WmiObject -Class MSCluster_Cluster -NameSpace $WMI_MSCLUSTER_NAMESPACE_Local
if ($error.Count -ne 0)
{
return $ClusterName
}

foreach ($Cluster in $Clusters)
{
$ClusterName = $Cluster.Name
break
}
}

$error.Clear()

return $ClusterName

}


Function Get-ComputerName([string]$strTargetComputer)
{
$ErrorActionPreference = 'SilentlyContinue' # Scoped only to function
$error.Clear()
$strTargetComputerShortName = $strTargetComputer

if([string]::IsNullOrEmpty($strTargetComputerShortName))
{
return [string]::Empty
}

$index = $strTargetComputer.IndexOf(".")

if ( $index -gt 0)
{
$strTargetComputerShortName = $strTargetComputer.Substring(0, $index)
}

return $strTargetComputerShortName
}



Main


</Script></ScriptBody>
<Parameters>
<Parameter>
<Name>mblnLogSuccessEvent</Name>
<Value>$Config/LogSuccessEvent$</Value>
</Parameter>
<Parameter>
<Name>mstrIdentifier</Name>
<Value>$Config/ScriptGroupId$</Value>
</Parameter>
<Parameter>
<Name>strTargetComputer</Name>
<Value>$Config/TargetComputer$</Value>
</Parameter>
<Parameter>
<Name>strClusterName</Name>
<Value>$Config/ClusterName$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</ProbeAction>
<ConditionDetection ID="Filter" TypeID="System!System.ExpressionFilter">
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="String">Property[@Name='ClusterSharedVolumeName']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="String">$Config/ClusterSharedVolumeName$</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</ConditionDetection>
</MemberModules>
<Composition>
<Node ID="Filter">
<Node ID="DS">
<Node ID="Scheduler"/>
</Node>
</Node>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.PropertyBagData</OutputType>
</DataSourceModuleType>