Drum roll please…. Below is the first Operations Manager blog to be submitted to the Manageability Guys! Meaning we can now live up to our name as it isn’t just Configuration Manager articles.
My OpsMgr knowledge is limited at best but I do know how to be persistent; it’s taken a year of nagging and for the engineer in question to leave PFE for MCS but here it is!
On numerous occasions when putting together a service model for an OpsMgr management pack I have found that it would be worthwhile to model some application component, but that component doesn’t necessarily lend itself to being discovered in a traditional sense.
About a year ago I was involved in a management pack authoring project where there was a need to model functional stages of a business process. These processing stages were carried out by a group of dedicated servers, and any server could run any process at any point in time.
A pair of performance counters existed for each stage, across all servers, together they revealed how well a business stage was performing.
The circles in the above diagram represent the performance counter pair for each business stage. Please note that for three business stages there would be three unique performance counter pairs, actually found on each processing server.
In this case it is clear that every business stage exists on each of the processing servers. This means that once we have carried out an initial discovery to work out whether a given windows server computer is a “processing server” we don’t need to do any further deduction. There is no need to carry out any subsequent discovery workflow on the agent because we know that processing servers always host the same set of stages.
“Why not use a singleton class for each business stage?” I hear you ask. A singleton class is, by definition, a class which doesn’t need to be instantiated via any discovery mechanism – sounds perfect!
Unfortunately singleton classes cannot be hosted, since there is no discovery process, and no reference to any key properties required by a hosting relationship. This means that we cannot associate the singleton class “business unit 1” with a particular processing server. In turn this means that we cannot get at the performance counters on “processing server 1” by targeting “business unit 1” – there is no “business unit 1” instance associated with the windows computer identified as “processing server 1”.
In the screenshot above I attempted to mark a hosted class as singleton.
So what we want is to create hosted instances of a class, without carrying out a redundant workflow on an agent. It turns out the answer is very simple; make direct use of the ClassSnapShotDataMapper module which is used by many OpsMgr discovery types…
The System.Discovery.ClassSnapShotDataMapper module
When we carry out discovery of class x we’re essentially looping through each instance of the target class, checking whether certain criteria is met, and mapping the target instance to a new instance of class x.
The latter part of this process is often carried out by the System.Discovery.ClassSnapShotDataMapper module as part of a composite workflow, for example;
FilteredRegistryDiscoveryProvider - http://msdn.microsoft.com/en-us/library/ff400178.aspx
In we don’t need any further information to ascertain whether an instance of class x exists we can make use of the ClassSnapShotDataMapper directly, thereby avoiding the need for any agent workflow (awaiting confirmation that this workflow wouldn’t need to be executed on the agent).
This works in the same way as the other two, but comprises only a System.Discovery.Scheduler and a System.Discovery.ClassSnapShotDataMapper. N.B.Though the System.Discovery.Scheduler is now shown in the other two diagrams it is a composite module used in the Microsoft.Windows.Discovery.RegistryProvider and the Microsoft.Windows.WmiProvider.
ClassSnapShotDataMapper - http://msdn.microsoft.com/en-us/library/ee692953.aspx
Creating the ClassMapper Data Source
1) Create a new empty management pack in The Management Pack Authoring Console.
2) In “Type Library” > “Data sources” right click and choose “New” > “Composite Data Source”.
3) Give it an Id and Name.
4) In “Member Modules” add the “System.Discovery.Scheduler”.
5) In the module configuration promote “Interval” and “SyncTime” (do this by clicking the arrow that appears in the right hand corner of that parameters value cell).
6) Click “Apply”.
7) In “Member Modules” add the “System.Discovery.ClassSnapShotDataMapper”.
8) In the module configuration promote “ClassId”.
9) Click “Apply”.
10) In “Member Modules” set the NextModule for the scheduler to the mapper, and the mapper to module output.
11) In “Configuration Schema” > “Schema References” add the “System.Discovery.MapperSchema”.
12) In “Configuration Schema” > “Simple Configuration Schema”
- a. Set “Interval” to type “integer”.
- b. Set “SyncTime” to be non-required.
- c. Add a new element with the name “InstanceSettings”.
13) Click Apply.
14) Save the management pack.
15) Open the management pack in a text editor of your choice and change the following lines;
<xsd:element minOccurs="1" name="InstanceSettings" type="xsd:string" />
<xsd:element minOccurs="1" name="InstanceSettings" type="SettingsType" />
N.B. If you attempt to declare InstanceSettings as a SettingsType in The Management Pack Authoring Console it will produce an error.
Click here to view an example
Using the ClassMapper in a Discovery
Now that we have a data source that will allow us to simply map instances of one class to another we can use it in the following manor.
1) Back in The Management Pack Authoring Console go to “Health Model” > “Discoveries”.
2) Right click > “New” > “Custom Discovery”.
3) Give it an Id and Name.
4) Choose a target, all instances of which we wish to create instances of our new class.
5) In “Discovery Classes” add our new class.
6) In “Configuration” browse for the ClassMapper module and give it a friendly name.
7) In the module configuration provide “Interval” and “ClassId” parameter values. ClassId should take the form “$MPElement[Name=”YOUR CLASS ID HERE”]$”.
8) Next we need to provide instance settings. To do this click “Edit” and view the XML in a text editor of your choice. Instance settings take the following form;
We need to provide a name value pair for each key property of the class we wish to discover. Please note this includes all key properties from any inherited relationships (e.g. Microsoft.Windows.LocalApplication inherits the hosting relationship Microsoft.Windows.ComputerHostsLocalApplication and consequently the key property Microsoft.Windows.Computer/PrincipalName).
Taking Microsoft.Windows.LocalApplicatin as an example the instance settings would look as follows;
9) Save and close the editor.
10) The module configuration will appear updated to include your instance settings.
11) In the right hand corner of the value field for each instance setting you an arrow will appear (on clicking into the field). This can be used to browse for any required properties of the target class e.g. $Target/Property[Type=”Windows!Microsoft.Windows.Computer”]/PrincipalName$
12) Click “Apply”.
Click here to view an example.
This post was contributed by Gavin Ackroyd, a Developer Consultant with Microsoft Consulting Services, UK.