One module to rule them all – a custom #scom managed module
During many years of MP development I faced cases where I would have loved the chance to pass a complete DataItem to a powershell module. There are many real world cases when you’d want to do that:
– You want to leverage the native OLEDB provider and you want to correlate multiple returned rows
– You need to use internal data sources that do not return property bags, but rather custom DataItems (for example the Microsoft.SystemCenter.GetWorkflowsReportProbe that can be used to query the agent for running and failed workflows)
– you need to take care of an entire walk from the standard SNMP modules and add logic to create your own data
– You don’t know how many properties the DataItem has in its payload and you want dynamically process them all
Today this is not possible for a couple of reasons:
1) You cannot reference the whole DataItem from the previous module, for example writing $Data$
2) The POSH module strips away any XML tag, so even if you find a way to pass an XML fragment to a POSH module all the XML tags are stripped away and you end up with a useless sequence of values.
For those who are not MP developers (yet) and are interested a DataItem is the way OpsMgr modules can pass data one to each other. It’s an XML document with DataItem as the root element:
A more complex one from the Microsoft.SystemCenter.GetWorkflowsReportProbe module is
And this is an example of a property bag DataItem
The goal is to pass the entire DataItem as-is to a powershell module to be able to use all the POSH power to manipulate the data.
I’m proud to announce that now we can achieve this goal, I just released a custom managed module that make it possible. The current version is a working version, but still not finished. I need to add tracing (hoping some help from the team since it’s not documented how to integrate in standard tracing) and add some polishing. But if you need and dare you can use it today.
The module is a custom ConditionDetection batching enabled (more on this later) that takes any DataItem in input and outputs the encoded DataItem embedded in a parent DataItem. Returning to the previous sample DataItem:
Basically the new dataItem has a single tag <EncodedItem> that contains the encoded and XML friendly version of the original dataItem. The encoding is achieved using the standard System.Xml.XmlWriter .NET class.
The receiving POSH module just needs to use System.Xml.XmlReader to un-ecode the payload and get the original XML document.
The condition detection module accept one parameter: ReturnMultipleItems of type Boolean. This is allow to manage batching. When a module is batch enabled it takes all the dataItem on its input ports before writing anything in output.
Example. You have a datasource who returns multiple objects you want to filter and then discover. Pretty common scenario many native e modules implements. The workflow is composed like this: datasource->filter->discovery mapper. This composition can work only if the filter module implements batching. It takes all the DataItem, discards the ones that do not match the filter and post all the remaining ones in a single batch. If the filter module were not batch enabled then you would have just the first object discovered.
The encoder condition detection implements batching and more. If the ReturnMultipleItems is true it will output (in batch) all the input dataItem as it received them. So if it gets 10 dataItem it will return a batch of 10 encoded DataItem. If ReturnMultipleItems is false it will always return a single DataItem where the encoded payload is the sum of all the input DataItem.
Why? you would ask. A couple of reasons:
1) POSH modules are not batch enabled so to make everything work batching must be implemented
2) Its way more efficient to call a single POSH module for all dataItems instead of calling a POSH module for each returned DataItem
In the end this parameter put control in your hands.
How to use it
The first step is to import QND.DataItemEncoder.Library.mpb, once imported you have access to the following condition detection:
Then yyou just add the ConditionDetection module between the datasource and the POSH module where you want to process the DataItem:
Note the $Data/EncodedItem$ substitution to access the encoded body.
The get back the original DataItem you jut need to add the following lines of POSH to your module:
In $unencoded you add the orginal DataItem XML document.
The sample Management Pack
To make it easier to ujnderstand and use the module you can find a companion helper management pack QND.EncodedDataItem.Tester.xml on CodePlex.
The Management Pack implements 3 Tasks targeted at the HealthService class:
– QND DIE Test 1 in 1 out – this task task takes a single DataItem in input from Microsoft.SystemCenter.GetWorkflowsReportProbe and outputs a single DataItem showing the endoded and decoded item.
– QND DIE Test N in N out – this task takes a collection of 10 property bags and returns a collections of 10 encoded dataItems. The task will show just the first DataItem since POSH doesn’t support batching.
– QND DIE Test N in 1 out – this task takes a collection of 10 property bags and returns a single DataItem composed by all 10 DataItems. The task will show the endoded and decodeded composed DataItem
Implementing Managed Modules – MSDN (http://msdn.microsoft.com/en-us/library/hh769912.aspx)
System Center 2012 – Operations Manager Managed Module Samples – CodePlex (https://opsmgr2012sdk.codeplex.com/)
This posting is provided “AS IS” with no warranties, and confers no rights.