Passing Data in Composite Workflow

I thought a quick and fun blog subject would be to build a composite workflow, passing data between each module, and writing output to the event log.

Workflow sequence:

  • Module1 outputs a ServiceName property bag data item – in this case “dhcp”.
  • Module2 accepts that ServiceName input, queries the service, and outputs Status property bag data item.
  • Module3 accepts that Status input, and simply writes it to the event log.
  • Composite module ties them together and executes in sequence.
  • Rule1 starts with a scheduler and ends with a write action, to execute the composite workflow.

Anyway – this is strictly a learning tool, but I thought it might be helpful to anyone interested in practicing composite workflows.

Here’s the full code:

<?xml version="1.0" encoding="utf-8"?> 
<ManagementPack SchemaVersion="2.0" ContentReadable="true" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Manifest>
<Identity>
<ID>CompositeModuleTest</ID>
<Version>1.0.0.3</Version>
</Identity>
<Name>CompositeModuleTest</Name>
<References>
<Reference Alias="Windows">
<ID>Microsoft.Windows.Library</ID>
<Version>7.5.8501.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>
<ModuleTypes>
<WriteActionModuleType ID="composite" Accessibility="Internal">
<Configuration></Configuration>
<ModuleImplementation>
<Composite>
<MemberModules>
<WriteAction ID="com1" TypeID="module1" />
<WriteAction ID="com2" TypeID="module2" />
<WriteAction ID="com3" TypeID="module3" />
</MemberModules>
<Composition>
<Node ID="com3">
<Node ID="com2">
<Node ID="com1" />
</Node>
</Node>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.PropertyBagData</OutputType>
<InputType>System!System.BaseData</InputType>
</WriteActionModuleType>
<WriteActionModuleType ID="module1" Accessibility="Internal">
<Configuration></Configuration>
<ModuleImplementation>
<Composite>
<MemberModules>
<WriteAction ID="script1" TypeID="Windows!Microsoft.Windows.PowerShellPropertyBagWriteAction">
<ScriptName>script1.ps1</ScriptName>
<ScriptBody>

$api= new-object -comObject "MOM.ScriptAPI"
$api.LogScriptEvent('script1.ps1',100,4,"start")
$bag = $api.CreatePropertyBag()
$bag.AddValue("ServiceName","dhcp")
$bag

</ScriptBody>
<Parameters></Parameters>
<TimeoutSeconds>300</TimeoutSeconds>
</WriteAction>
</MemberModules>
<Composition>
<Node ID="script1" />
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.PropertyBagData</OutputType>
<InputType>System!System.BaseData</InputType>
</WriteActionModuleType>
<WriteActionModuleType ID="module2" Accessibility="Internal">
<Configuration></Configuration>
<ModuleImplementation>
<Composite>
<MemberModules>
<WriteAction ID="script2" TypeID="Windows!Microsoft.Windows.PowerShellPropertyBagWriteAction">
<ScriptName>script2.ps1</ScriptName>
<ScriptBody>

param($ServiceName)
$api= new-object -comObject "MOM.ScriptAPI"
$api.LogScriptEvent('Script2.ps1',100,4,$ServiceName)
$service = get-service $ServiceName
$bag = $api.CreatePropertyBag()
$bag.AddValue("ServiceName",$serviceName)
$bag.AddValue("Status",$service.status.ToString())
$bag

</ScriptBody>
<Parameters>
<Parameter>
<Name>ServiceName</Name>
<Value>$Data/Property[@Name="ServiceName"]$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>300</TimeoutSeconds>
</WriteAction>
</MemberModules>
<Composition>
<Node ID="script2" />
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.PropertyBagData</OutputType>
<InputType>System!System.BaseData</InputType>
</WriteActionModuleType>
<WriteActionModuleType ID="module3" Accessibility="Internal">
<Configuration></Configuration>
<ModuleImplementation>
<Composite>
<MemberModules>
<WriteAction ID="script3" TypeID="Windows!Microsoft.Windows.PowerShellPropertyBagWriteAction">
<ScriptName>script3.ps1</ScriptName>
<ScriptBody>

param($Status)
$api= new-object -comObject "MOM.ScriptAPI"
$api.LogScriptEvent('Script3.ps1',100,4,$Status)

</ScriptBody>
<Parameters>
<Parameter>
<Name>Status</Name>
<Value>$Data/Property[@Name="Status"]$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>300</TimeoutSeconds>
</WriteAction>
</MemberModules>
<Composition>
<Node ID="script3" />
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.PropertyBagData</OutputType>
<InputType>System!System.BaseData</InputType>
</WriteActionModuleType>
</ModuleTypes>
</TypeDefinitions>
<Monitoring>
<Rules>
<Rule ID="rule1" Enabled="true" Target="Windows!Microsoft.Windows.Computer">
<Category>Operations</Category>
<DataSources>
<DataSource ID="schedule" TypeID="System!System.SimpleScheduler">
<IntervalSeconds>10</IntervalSeconds>
<SyncTime />
</DataSource>
</DataSources>
<WriteActions>
<WriteAction ID="WA1" TypeID="composite" />
</WriteActions>
</Rule>
</Rules>
</Monitoring>
</ManagementPack>

Logical Disk Free Space Monitor (extended)

The question of how to manage the logical disk free space monitor comes up time and time again. Just about every customer I’ve worked with, and all over the forums, people express their disdain for and frustration of managing overrides related to this monitor – and for good reason. It’s one of those monitors that touch every type of logical disk on every computer in the environment, and of course there are going to be different threshold requirements that require overrides – even the out-of-box flexibility of using both types of thresholds (mb and %) usually isn’t enough for us to “set it and forget it”.

This a great opportunity to reduce administrative overhead by enabling local administrators to change monitoring thresholds directly on the local machine, without having to login to the console and create overrides.

Because this is such a popular request, I’ve extended the Logical Disk Free Space monitor and added it to the Windows Monitoring (Extended) community pack.

Download the community pack from GitHub.

 

NOTE 1 – There are overrides defined in the pack that disable the vendor Logical Disk Free Space unit monitor. Once this pack is installed, that monitor will be replaced by this monitor. If you have overrides applied to the vendor monitors that you want to keep, those will need to be applied to this new unit monitor.

NOTE 2 – The unit monitor works out of the box exactly the same say as the original Logical Disk Free Space unit monitor. It will only behave differently if you implement the extended features of the unit monitor.

NOTE 3 – I chose to target Microsoft.Windows.LogicalDisk because the script data source, according to library documentation, should run fine against all versions of Windows. This reduces it from three monitors to just one.

 

Product knowledge has also been extended to include usage instructions:

image

 

An alert generated by this monitor will look like this:

image

 

A state change event (health explorer) for this monitor will look like this:

image

 

 

Smile