Menu Close

How to create a SCOM Group of Disks that are related to an Application using CONTAINED and CONTAINS

This is a very common request.  Perhaps you have an application that you discover and monitor, and the application owner wants specific overrides for the disks related to that application.  Initially, this seems really hard, because there is no direct relationship between an application on a server, and disks on a server.  However – there actually is.  The application is “hosted” (and therefore contained) by the Windows Computer object.  Disks are also hosted (and therefore contained) by the Windows Computer.  So we can use these two relationships in a group expression to get specific disks related to an application.

For instance:  You need a Group of (Logical Disk objects where the Drive Letter = C: ) but ONLY on Computers that contain an instance of your custom application?

 

Unfortunately, while this is such a simple thing to do – this cannot be done using the SCOM Console group authoring.  You need to drop down into XML and edit the group expression.  Here is an example.

In this example, I am discovering my custom application class:  (Demo.App.ServerRole.Class)

The XML is actually pretty simple.  The key here is using CONTAINS and CONTAINED.

My membership rule for the group says:

I want a group, of Logical Disks, where the Drive Letter = C: AND I only want disks that are CONTAINED by a Windows Computer object, where that Windows Computer object also CONTAINS an instance of my custom application class.

<MembershipRule> <MonitoringClass>$MPElement[Name="MWSL!Microsoft.Windows.Server.LogicalDisk"]$</MonitoringClass> <RelationshipClass>$MPElement[Name="MSIL!Microsoft.SystemCenter.InstanceGroupContainsEntities"]$</RelationshipClass> <Expression> <And> <Expression> <SimpleExpression> <ValueExpression> <Property>$MPElement[Name="Windows!Microsoft.Windows.LogicalDevice"]/DeviceID$</Property> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value>C:</Value> </ValueExpression> </SimpleExpression> </Expression> <Expression> <Contained> <MonitoringClass>$MPElement[Name="Windows!Microsoft.Windows.Computer"]$</MonitoringClass> <Expression> <Contains> <MonitoringClass>$MPElement[Name="Demo.App.ServerRole.Class"]$</MonitoringClass> </Contains> </Expression> </Contained> </Expression> </And> </Expression> </MembershipRule>

 

Now, what if we want a group of disks, related to an application, but ONLY if it matches a specific property of the application, like a “Version”?  That’s easy too… you just add an expression to filter on the CONTAINED application class.  Here is an example of that

My membership rule for the group says:

I want a group, of Logical Disks, where the Drive Letter = C: AND I only want disks that are CONTAINED by a Windows Computer object, that also CONTAINS an instance of my custom application class, where that application class has a VERSION property = 4.0

<MembershipRule> <MonitoringClass>$MPElement[Name="MWSL!Microsoft.Windows.Server.LogicalDisk"]$</MonitoringClass> <RelationshipClass>$MPElement[Name="MSIL!Microsoft.SystemCenter.InstanceGroupContainsEntities"]$</RelationshipClass> <Expression> <And> <Expression> <SimpleExpression> <ValueExpression> <Property>$MPElement[Name="Windows!Microsoft.Windows.LogicalDevice"]/DeviceID$</Property> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value>C:</Value> </ValueExpression> </SimpleExpression> </Expression> <Expression> <Contained> <MonitoringClass>$MPElement[Name="Windows!Microsoft.Windows.Computer"]$</MonitoringClass> <Expression> <Contains> <MonitoringClass>$MPElement[Name="Demo.App.ServerRole.Class"]$</MonitoringClass> <Expression> <SimpleExpression> <ValueExpression> <Property>$MPElement[Name="Demo.App.ServerRole.Class"]/Version$</Property> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value>4.0</Value> </ValueExpression> </SimpleExpression> </Expression> </Contains> </Expression> </Contained> </Expression> </And> </Expression> </MembershipRule>

 

 

The full XML of the MP is below:

<?xml version="1.0" encoding="utf-8"?><ManagementPack ContentReadable="true" SchemaVersion="2.0" OriginalSchemaVersion="1.1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <Manifest> <Identity> <ID>Demo.App</ID> <Version>1.0.0.3</Version> </Identity> <Name>Demo.App</Name> <References> <Reference Alias="SC"> <ID>Microsoft.SystemCenter.Library</ID> <Version>7.0.8437.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> <Reference Alias="Windows"> <ID>Microsoft.Windows.Library</ID> <Version>7.5.8501.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> <Reference Alias="MSIL"> <ID>Microsoft.SystemCenter.InstanceGroup.Library</ID> <Version>7.5.8501.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> <Reference Alias="MWSL"> <ID>Microsoft.Windows.Server.Library</ID> <Version>10.0.0.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> <Reference Alias="System"> <ID>System.Library</ID> <Version>7.5.8501.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> </References> </Manifest> <TypeDefinitions> <EntityTypes> <ClassTypes> <ClassType ID="Demo.App.ServerRole.Class" Accessibility="Public" Abstract="false" Base="Windows!Microsoft.Windows.LocalApplication" Hosted="true" Singleton="false" Extension="false"> <Property ID="Version" Type="string" Key="false" CaseSensitive="false" MaxLength="256" MinLength="0" /> </ClassType> <ClassType ID="Demo.App.Disks.Group" Accessibility="Public" Abstract="false" Base="MSIL!Microsoft.SystemCenter.InstanceGroup" Hosted="false" Singleton="true" Extension="false" /> <ClassType ID="Demo.App.Version4.Disks.Group" Accessibility="Public" Abstract="false" Base="MSIL!Microsoft.SystemCenter.InstanceGroup" Hosted="false" Singleton="true" Extension="false" /> </ClassTypes> </EntityTypes> </TypeDefinitions> <Monitoring> <Discoveries> <Discovery ID="Demo.App.Disks.Group.Discovery" Enabled="true" Target="Demo.App.Disks.Group" ConfirmDelivery="false" Remotable="true" Priority="Normal"> <Category>Discovery</Category> <DiscoveryTypes> <DiscoveryRelationship TypeID="MSIL!Microsoft.SystemCenter.InstanceGroupContainsEntities" /> </DiscoveryTypes> <DataSource ID="GroupPopulationDataSource" TypeID="SC!Microsoft.SystemCenter.GroupPopulator"> <RuleId>$MPElement$</RuleId> <GroupInstanceId>$MPElement[Name="Demo.App.Disks.Group"]$</GroupInstanceId> <MembershipRules> <MembershipRule> <MonitoringClass>$MPElement[Name="MWSL!Microsoft.Windows.Server.LogicalDisk"]$</MonitoringClass> <RelationshipClass>$MPElement[Name="MSIL!Microsoft.SystemCenter.InstanceGroupContainsEntities"]$</RelationshipClass> <Expression> <And> <Expression> <SimpleExpression> <ValueExpression> <Property>$MPElement[Name="Windows!Microsoft.Windows.LogicalDevice"]/DeviceID$</Property> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value>C:</Value> </ValueExpression> </SimpleExpression> </Expression> <Expression> <Contained> <MonitoringClass>$MPElement[Name="Windows!Microsoft.Windows.Computer"]$</MonitoringClass> <Expression> <Contains> <MonitoringClass>$MPElement[Name="Demo.App.ServerRole.Class"]$</MonitoringClass> </Contains> </Expression> </Contained> </Expression> </And> </Expression> </MembershipRule> </MembershipRules> </DataSource> </Discovery> <Discovery ID="Demo.App.Version4.Disks.Group.Discovery" Enabled="true" Target="Demo.App.Version4.Disks.Group" ConfirmDelivery="false" Remotable="true" Priority="Normal"> <Category>Discovery</Category> <DiscoveryTypes> <DiscoveryRelationship TypeID="MSIL!Microsoft.SystemCenter.InstanceGroupContainsEntities" /> </DiscoveryTypes> <DataSource ID="GroupPopulationDataSource" TypeID="SC!Microsoft.SystemCenter.GroupPopulator"> <RuleId>$MPElement$</RuleId> <GroupInstanceId>$MPElement[Name="Demo.App.Version4.Disks.Group"]$</GroupInstanceId> <MembershipRules> <MembershipRule> <MonitoringClass>$MPElement[Name="MWSL!Microsoft.Windows.Server.LogicalDisk"]$</MonitoringClass> <RelationshipClass>$MPElement[Name="MSIL!Microsoft.SystemCenter.InstanceGroupContainsEntities"]$</RelationshipClass> <Expression> <And> <Expression> <SimpleExpression> <ValueExpression> <Property>$MPElement[Name="Windows!Microsoft.Windows.LogicalDevice"]/DeviceID$</Property> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value>C:</Value> </ValueExpression> </SimpleExpression> </Expression> <Expression> <Contained> <MonitoringClass>$MPElement[Name="Windows!Microsoft.Windows.Computer"]$</MonitoringClass> <Expression> <Contains> <MonitoringClass>$MPElement[Name="Demo.App.ServerRole.Class"]$</MonitoringClass> <Expression> <SimpleExpression> <ValueExpression> <Property>$MPElement[Name="Demo.App.ServerRole.Class"]/Version$</Property> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value>4.0</Value> </ValueExpression> </SimpleExpression> </Expression> </Contains> </Expression> </Contained> </Expression> </And> </Expression> </MembershipRule> </MembershipRules> </DataSource> </Discovery> <Discovery ID="Demo.App.ServerRole.Class.Discovery" Enabled="true" Target="Windows!Microsoft.Windows.Server.OperatingSystem" ConfirmDelivery="false" Remotable="true" Priority="Normal"> <Category>Discovery</Category> <DiscoveryTypes> <DiscoveryClass TypeID="Demo.App.ServerRole.Class" /> </DiscoveryTypes> <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.FilteredRegistryDiscoveryProvider"> <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</ComputerName> <RegistryAttributeDefinitions> <RegistryAttributeDefinition> <AttributeName>ServerRoleRegKeyExists</AttributeName> <Path>SOFTWARE\foo</Path> <PathType>0</PathType> <!-- 0=regKey 1=regValue --> <AttributeType>0</AttributeType> <!-- 0=CheckIfExists (Boolean) 1=treat data as (String) 2=treat data as (Integer) --> </RegistryAttributeDefinition> <RegistryAttributeDefinition> <AttributeName>ServerRoleRegKeyVersion</AttributeName> <Path>SOFTWARE\Foo\Version</Path> <PathType>1</PathType> <!-- 0=regKey 1=regValue --> <AttributeType>1</AttributeType> <!-- 0=CheckIfExists (Boolean) 1=treat data as (String) 2=treat data as (Integer) --> </RegistryAttributeDefinition> </RegistryAttributeDefinitions> <Frequency>86400</Frequency> <ClassId>$MPElement[Name="Demo.App.ServerRole.Class"]$</ClassId> <InstanceSettings> <Settings> <Setting> <Name>$MPElement[Name="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Name> <Value>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value> </Setting> <Setting> <Name>$MPElement[Name="System!System.Entity"]/DisplayName$</Name> <Value>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value> </Setting> <Setting> <Name>$MPElement[Name="Demo.App.ServerRole.Class"]/Version$</Name> <Value>$Data/Values/ServerRoleRegKeyVersion$</Value> </Setting> </Settings> </InstanceSettings> <Expression> <SimpleExpression> <ValueExpression> <XPathQuery Type="Boolean">Values/ServerRoleRegKeyExists</XPathQuery> <!-- Common options for XPathQuery Type are "Boolean" "String" "Integer" "Double" --> </ValueExpression> <Operator>Equal</Operator> <!-- Common options for SimpleExpression Operator are "Equal" "NotEqual" "Greater" "Less" "GreaterEqual" "LessEqual" "Like" "NotLike" --> <ValueExpression> <Value Type="Boolean">true</Value> <!-- Common options for XPathQuery Type are "Boolean" "String" "Integer" "Double" --> </ValueExpression> </SimpleExpression> </Expression> </DataSource> </Discovery> </Discoveries> </Monitoring> <LanguagePacks> <LanguagePack ID="ENU" IsDefault="true"> <DisplayStrings> <DisplayString ElementID="Demo.App"> <Name>Demo App </Name> </DisplayString> <DisplayString ElementID="Demo.App.Disks.Group"> <Name>Demo App Disks Group</Name> </DisplayString> <DisplayString ElementID="Demo.App.Disks.Group.Discovery"> <Name>Demo App Disks Group Discovery</Name> <Description /> </DisplayString> <DisplayString ElementID="Demo.App.Version4.Disks.Group"> <Name>Demo App Version 4 Disks Group</Name> </DisplayString> <DisplayString ElementID="Demo.App.Version4.Disks.Group.Discovery"> <Name>Demo App Version 4 Disks Group Discovery</Name> <Description /> </DisplayString> <DisplayString ElementID="Demo.App.ServerRole.Class"> <Name>Demo App ServerRole Class</Name> </DisplayString> <DisplayString ElementID="Demo.App.ServerRole.Class" SubElementID="Version"> <Name>Version</Name> </DisplayString> <DisplayString ElementID="Demo.App.ServerRole.Class.Discovery"> <Name>Demo App ServerRole Class Discovery</Name> </DisplayString> </DisplayStrings> </LanguagePack> </LanguagePacks> </ManagementPack>

 

 

Other examples:

 

A Group of Logical Disks (that do NOT have drive letter C: ) but are CONTAINED by Computers in some OTHER GROUP:

<MembershipRule> <MonitoringClass>$MPElement[Name="MWSL!Microsoft.Windows.Server.LogicalDisk"]$</MonitoringClass> <RelationshipClass>$MPElement[Name="MSIL!Microsoft.SystemCenter.InstanceGroupContainsEntities"]$</RelationshipClass> <Expression> <And> <Expression> <SimpleExpression> <ValueExpression> <Property>$MPElement[Name="Windows!Microsoft.Windows.LogicalDevice"]/Name$</Property> </ValueExpression> <Operator>NotEqual</Operator> <ValueExpression> <Value>C:</Value> </ValueExpression> </SimpleExpression> </Expression> <Expression> <Contained> <MonitoringClass>$MPElement[Name="Windows!Microsoft.Windows.Computer"]$</MonitoringClass> <Expression> <Contained> <MonitoringClass>$MPElement[Name="MicrosoftSQLServerLibrary!Microsoft.SQLServer.ComputerGroup"]$</MonitoringClass> </Contained> </Expression> </Contained> </Expression> </And> </Expression> </MembershipRule>

 

We add Health Service Watchers to Computer Groups using the same method of Contains/Contained.  The HealthServiceWatcher CONTAINS a HealthService, that is CONTAINED by a Windows Computer.  In this case, the $Target/Id$ is simply the group itself.  One membership rule populates the group with Windows Computers, the other membership rule populates the Watchers that are related to the Computers contained in the group.

<MembershipRules> <MembershipRule> <MonitoringClass>$MPElement[Name="Windows!Microsoft.Windows.Computer"]$</MonitoringClass> <RelationshipClass>$MPElement[Name="MSIL!Microsoft.SystemCenter.InstanceGroupContainsEntities"]$</RelationshipClass> <Expression> <Contains> <MonitoringClass>$MPElement[Name="##ClassID##"]$</MonitoringClass> </Contains> </Expression> </MembershipRule> <MembershipRule> <MonitoringClass>$MPElement[Name="SC!Microsoft.SystemCenter.HealthServiceWatcher"]$</MonitoringClass> <RelationshipClass>$MPElement[Name="MSIL!Microsoft.SystemCenter.InstanceGroupContainsEntities"]$</RelationshipClass> <Expression> <Contains> <MonitoringClass>$MPElement[Name="SC!Microsoft.SystemCenter.HealthService"]$</MonitoringClass> <Expression> <Contained> <MonitoringClass>$MPElement[Name="Windows!Microsoft.Windows.Computer"]$</MonitoringClass> <Expression> <Contained> <MonitoringClass>$Target/Id$</MonitoringClass> </Contained> </Expression> </Contained> </Expression> </Contains> </Expression> </MembershipRule> </MembershipRules>

 

You can use this same relationship if you just wanted groups of Watcher objects, related to an application:

<MembershipRule> <MonitoringClass>$MPElement[Name="SC!Microsoft.SystemCenter.HealthServiceWatcher"]$</MonitoringClass> <RelationshipClass>$MPElement[Name="MSIL!Microsoft.SystemCenter.InstanceGroupContainsEntities"]$</RelationshipClass> <Expression> <Contains> <MonitoringClass>$MPElement[Name="SC!Microsoft.SystemCenter.HealthService"]$</MonitoringClass> <Expression> <Contained> <MonitoringClass>$MPElement[Name="Windows!Microsoft.Windows.Computer"]$</MonitoringClass> <Expression> <Contains> <MonitoringClass>$MPElement[Name="##ClassID##"]$</MonitoringClass> </Contains> </Expression> </Contained> </Expression> </Contains> </Expression> </MembershipRule>

5 Comments

  1. ENDRE N

    Hi Kevin! Thank you this great solution. BUT I have a special scenario. Can I filter the class in the CONTAINS section?
    Based on your example:
    I want a group, of Logical Disks, where the Drive Letter = C: AND I only want disks that are CONTAINED by a Windows Computer object, that also CONTAIN an instance of my custom application class WITH SPECIFIED VERSION. VERSOIN is an attribute of the custom application class.

    Thanks in advance!

Leave a Reply

Your email address will not be published. Required fields are marked *