I was tasked the other day with creating a recovery action on a monitor, which in itself is not complicated, however I needed to use a data item from the monitor workflow in the recovery.  On searching, I found very little documentation about how to achieve this, but I did find a helpful example Diagnostic and Recovery MP from Brian Wren (as usual) here, http://www.opsmanjam.com/default.aspx?RootFolder=%2fOpsManJam%20Library%2fManagement%20Packs&FolderCTID=&View=%7bB441DC0E%2d3F55%2d42C6%2d8C9E%2d0FA229F8DBDD%7d.  This example MP is great for showing how to run a diagnostic and then use the output of the diagnostic in the recovery action.  However, the requirement I had was run a recovery action directly, without a diagnostic, based on a data item returned from the workflow.

After some investigation, I cracked it, and these are a couple of examples of the context parameters that can be used.

1.  If the monitor returns a property bag, data from the property bag can be resolved using “$Data/StateChange/DataItem/Context/DataItem/Property[@Name='ITEM']$”.  (Replace ITEM with the name of the property bag value)

2.  If the monitor using a module where the data items are already mapped, the data can be resolved using something like this “$Data/StateChange/DataItem/Context/DataItem/EventDescription$”.  In this example, the monitor is using the EventProvider module to monitor to an event log, and the description of the event is being passed.

So, now we have the correct context parameters, we can resolve the data items we need in a recovery action.  Here’s an example where I have a script monitor that it monitoring for an existence of a file, if the file doesn’t exist this will trigger an unhealthy state and the recovery action, which will output the file name, from the monitor, to the event log.

<UnitMonitor ID="Recovery.Example.Monitor.ScriptTwoState" Accessibility="Public" Enabled="false" Target="Windows!Microsoft.Windows.Computer" ParentMonitorID="Health!System.Health.AvailabilityState" Remotable="true" Priority="Normal" TypeID="Windows!Microsoft.Windows.TimedScript.TwoStateMonitorType" ConfirmDelivery="false">
        <Category>AvailabilityHealth</Category>
        <AlertSettings AlertMessage="Recovery.Example.Monitor.ScriptTwoState_AlertMessageResourceID">
          <AlertOnState>Error</AlertOnState>
          <AutoResolve>true</AutoResolve>
          <AlertPriority>Normal</AlertPriority>
          <AlertSeverity>Error</AlertSeverity>
        </AlertSettings>
        <OperationalStates>
          <OperationalState ID="Success" MonitorTypeStateID="Success" HealthState="Success" />
          <OperationalState ID="Error" MonitorTypeStateID="Error" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <IntervalSeconds>301</IntervalSeconds>
          <SyncTime />
          <ScriptName>Example.vbs</ScriptName>
          <Arguments />
          <ScriptBody><![CDATA[Option Explicit

SetLocale("en-us")

Dim oAPI, oBag
Set oAPI = CreateObject("MOM.ScriptAPI")
Set oBag = oAPI.CreatePropertyBag()

Call oAPI.LogScriptEvent("Example.vbs",5555,4,"Script Started")

DIM oFso, strFile
Set oFso = CreateObject("Scripting.FileSystemObject")
strFile = "C:\Temp\test.txt"

If (oFso.FileExists(strFile)) Then

Call oBag.AddValue("Status","OK")
Else
Call oBag.AddValue("Status","BAD")
Call oBag.AddValue("File",strFile)
End If

Call oAPI.LogScriptEvent("Example.vbs",5555,4,"Script Finished")

Call oAPI.Return(oBag)
              ]]></ScriptBody>
          <SecureInput />
          <TimeoutSeconds>60</TimeoutSeconds>
          <ErrorExpression>
            <SimpleExpression>
              <ValueExpression>
                <XPathQuery Type="String">Property[@Name='Status']</XPathQuery>
              </ValueExpression>
              <Operator>Equal</Operator>
              <ValueExpression>
                <Value Type="String">BAD</Value>
              </ValueExpression>
            </SimpleExpression>
          </ErrorExpression>
          <SuccessExpression>
            <SimpleExpression>
              <ValueExpression>
                <XPathQuery Type="String">Property[@Name='Status']</XPathQuery>
              </ValueExpression>
              <Operator>Equal</Operator>
              <ValueExpression>
                <Value Type="String">OK</Value>
              </ValueExpression>
            </SimpleExpression>
          </SuccessExpression>
        </Configuration>
      </UnitMonitor>
    </Monitors>
    <Recoveries>
      <Recovery ID="Recovery.Example.Recovery" Accessibility="Public" Enabled="true" Target="Windows!Microsoft.Windows.Computer" Monitor="Recovery.Example.Monitor.ScriptTwoState" ResetMonitor="false" ExecuteOnState="Error" Remotable="true" Timeout="300">
        <Category>Operations</Category>
        <WriteAction ID="Script" TypeID="Windows!Microsoft.Windows.ScriptWriteAction">
          <ScriptName>Recovery.vbs</ScriptName>
          <Arguments>$Data/StateChange/DataItem/Context/DataItem/Property[@Name='File']$</Arguments>
          <ScriptBody><![CDATA[
Option Explicit

SetLocale("en-us")

Dim oArgs, strFile
Set oArgs = Wscript.Arguments
strFile = oArgs(0)

Dim oAPI
Set oAPI = CreateObject("MOM.ScriptAPI")

Call oAPI.LogScriptEvent("Recovery.vbs",5556,4,"File: " & strFile)

]]></ScriptBody>
          <TimeoutSeconds>300</TimeoutSeconds>
        </WriteAction>
      </Recovery>
    </Recoveries>

Note:  This is just an example for demonstration purposes, it is not a real production monitor.

The full example MP is downloadable here.

Hope that’s helpful and makes the use of recovery actions more appealing Smile

 

David

Anonymous