Dynamically creating groups

At my current client, server codes are used to identify a set of servers serving a single purpose. For example: XMS20 is the servercode for all SCOM management servers belonging to a certain management group. This code is inserted into the registry of each server under a specific key.

The goal was to have one group for each code, which would contain all servers having the code.

As there are lots of servercodes (hundreds!), creating a group for each single one would be time-consuming. Also, the servercode-system is volatile in nature: some disappear and some new ones are added from time to time. What we needed was something that could dynamically create the groups for us and maintain them automatically.

As it appears, this is perfectly possible in SCOM, with one drawback (more on that later).

So what is the trick?

Each group that you create manually in SCOM is a derivative class from Microsoft.SystemCenter.InstanceGroup. Because you create this group yourself, it isn’t created by a discovery, it just “starts to exist” after you click finish. The term that is used to mark such an object is a ‘singleton’. A singleton is a class which also is an object at the same time. Singletons in SCOM are not hosted, they are maintained by the management servers.

The thing that we have to do is define a derivative class for Microsoft.SystemCenter.InstanceGroup, but without making it a singleton. This can be done by making sure the box that controls this property isn’t checked. This way our group class can be created on the fly, by using a discovery (targeted to windows computer) to create one instead of having a singleton property set.

What is important is that we create a key attribute on the class. Why? A key attribute is used to mark an instance of a class as unique. This means that should a discovery define 2 instances of a class which have an identical value as key attribute, they will be merged in a single object. Translating to our scenario, we want to prevent that for each servercode being collected from a server’s registry, a new group is created. Therefore, we define a key-attribute ‘ServerCode’ on our new group-class. This will merge subsequent discoveries of the same servercode into one group-object.

Ok, now we have unique groups, we must populate them. This can be easily done from within the same discovery. First I want to talk about SCOM-relationships: relationships define how objects are positioned in a hierarchy. Specifically to our scenario: the base-class of our class is still ‘Microsoft.SystemCenter.InstanceGroup’. This base-class has a relationship called “InstanceGroupContainsEntities”, which specifies that the class may contain any item. Because we derivate from this class, we automatically inherit this relationship as well. So the only thing we have to do is create an instance of this relationship in our discovery, put the instance of the servercode-group as parent and put the Windows-Computer object as a child. Where will we get this Windows Computer object? We will create it! A Windows Computer object can be created by a custom discovery, without worrying about breaking the built-in discoveries (unless you really try to). By defining an instance using only PrincipalName (it is the key attribute and must always be defined), we can have a representation of the very Windows computer object we are targeting with our discovery and use it to complete the relationship instance.

I know this is a lot of heavy stuff, therefore I will provide a break down on what kind of discovery we will be doing. A vb script will be ran on each server and do the following:

  • Retrieve the servercode from registry
  • Create a new instance of our class with the servercode from registry set as key attribute
  • Create an instance of Windows.Computer (using only the principalname as attribute)
  • Create an instance of the “InstanceGroupContainsEntities”-relationship, and add the 2 previous instance as respective parent and child
  • Return the discovery data to SCOM

This will create a populated group, which is usable for overrides and subscription management!

But there is one more thing! Because there will be multiple servers submitting discovery data for a single group-object, we will have to enable proxying on each server. This might be a high price to pay, but you do get a fully dynamic group management system in return. This might be a showstopper, but this is your decision to make.

I provide the VBScript used to perform the discovery (for this one a derivative class is used for the Windows Computer object as well, but this isn’t mandatory):


Dim oAPI

Set oAPI = CreateObject(“MOM.ScriptAPI”)


Dim oArgs

Set oArgs = WScript.Arguments

‘ Check for the required script arguments.

if oArgs.Count < 3 Then

‘ If the script is called without the required arguments,

‘ create an information event and then quit.

Call oAPI.LogScriptEvent(“CustomBaseDiscovery.vbs”,101,1, _

“Script was called with fewer than three arguments and was not executed.”)

Wscript.Quit -1

End If


Dim SourceID, ManagedEntityId, TargetComputer


SourceId = oArgs(0) ‘ The GUID of the discovery object that launched the script.

ManagedEntityId = oArgs(1) ‘ The GUID of the computer class targeted by the script.

TargetComputer = oArgs(2) ‘ The hostname of the computer targeted by the script.


Dim oDiscoveryData, oInstManagedServer,oInstServerGroup,ServerCode,arrSubKeys

Const HKEY_LOCAL_MACHINE = &H80000002

Set oReg=GetObject(“winmgmts:{impersonationLevel=impersonate}!rootdefault:StdRegProv”)

oReg.GetStringValue HKEY_LOCAL_MACHINE,”SOFTWAREXXXParameters”,”ServerCode”,ServerCode

oReg.EnumKey HKEY_LOCAL_MACHINE,”SOFTWAREWow6432Node”,arrSubKeys


If IsNull (ServerCode) Then ServerCode = “NA”



‘Add Computer instance

Set oDiscoveryData = oAPI.CreateDiscoveryData(0, SourceID, ManagedEntityID)

set oInstManagedServer = oDiscoveryData.CreateClassInstance(“$MPElement[Name=’JVM-NET.Computer’]$”)

call oInstManagedServer.AddProperty(“$MPElement[Name=’WindowsLibrary!Microsoft.Windows.Computer’]/PrincipalName$”, TargetComputer)

call oInstManagedServer.AddProperty(“$MPElement[Name=’Computer’]/ServerCode$”, ServerCode)

call oDiscoveryData.AddInstance(oInstManagedServer)


‘Add ServerGroup instance

set oInstServerGroup = oDiscoveryData.CreateClassInstance(“$MPElement[Name=’JVM-NET.ServerCodeGroup’]$”)

call oInstServerGroup.AddProperty(“$MPElement[Name=’MP.ServerCodeGroup’]/ServerCode$”, ServerCode)

call oInstServerGroup.AddProperty(“$MPElement[Name=’System!System.Entity’]/DisplayName$”, ServerCode)


if Err.Number <> 0 Then

Call oAPI.LogScriptEvent(“CustomBaseDiscovery.vbs”,104,1, “Script Error : Can’t create ServerGroup (” & Err.Number & “) ” & Err.Description)

WScript.Quit -1

End If


call oDiscoveryData.AddInstance(oInstServerGroup)


‘Create a relationship between ServerGroup and Windows Computer

Dim oInstWindowsComputer

set oInstWindowsComputer = oDiscoveryData.CreateClassInstance(“$MPElement[Name=’WindowsLibrary!Microsoft.Windows.Computer’]$”)

call oInstWindowsComputer.AddProperty(“$MPElement[Name=’WindowsLibrary!Microsoft.Windows.Computer’]/PrincipalName$”, TargetComputer)

call oDiscoveryData.AddInstance(oInstWindowsComputer)


Set oRelationship = oDiscoveryData.CreateRelationshipInstance(“$MPElement[Name=’SystemCenterInstanceGroupLibrary!Microsoft.SystemCenter.InstanceGroupContainsEntities’]$”)

oRelationship.Source = oInstServerGroup

oRelationship.Target = oInstWindowsComputer


Call oDiscoveryData.AddInstance(oRelationship)


if Err.Number <> 0 Then

Call oAPI.LogScriptEvent(“CustomBaseDiscovery.vbs”,104,1, “Script Error : Can’t create ServerGroup to Computer relationship (” & Err.Number & “) ” & Err.Description)

WScript.Quit -1

End If


call oAPI.Return(oDiscoveryData)



This entry was posted in Uncategorized. Bookmark the permalink.

2 Responses to Dynamically creating groups

  1. Sam T says:

    Good post there! Just technical enough. 😀

  2. Steve says:

    Hi! The images in your post appear to be broken. The page behind them (jvm-net.com) seems to be timing out.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s