This section details the creation of a PowerShell Custom Activity using the shipped EV390_IST105I_Activity as an example. This activity will execute the Powershell command given to it.
Requirements
- Select Ironstream Mainframe Event Management as scoped application before launching the Workflow Editor
- Enter a PowerShell hostname as an input parameter
- Enter a PowerShell Command as an input parameter
- Place all results back onto the workflow data stream for handling
- Have both Success and Failure handling
Procedure
- In your instance go to Orchestration > Workflow Editor, and open the Workflow Editor
- In the Workflow Editor, go to the Custom tab and click the plus ("+") button to create a new Activity. This will display the context menu where you can choose a custom Activity Template.
- Choose the Powershell Template from the menu. This will display the Activity Designer with the template form.
- Fill out the form with this details:
Name: EV390_IST105I _Activity
Short Description: Execute VTAM display command
Accessible from: All application scopes Category: PowerShell
Description: Execute VTAM display command
- Click on the Continue button to display the Inputs form.
- Add three fields under Input{}:
Name: Node Type: String Name: Host Type: String Name: vtam_resource Type: String - Click on the Go to Pre-Processing button to display the Pre-Processing form.
- Fill in the Pre-Processing form with this logging for troubleshooting:Input process script:
var location = 'WFEV390_IST105I: Run PowerShell EV390_IST105I Inputs Activity'; if (activityInput.Node !== null) { gs.info('---> [{1}-{2}] activityInput.Node: {0}', [activityInput.Node, new GlideDateTime().getNumericValue(), location]); } else { gs.info('---> [{1}-{2}] bad Node: {0} does not exist.', [activityInput.Node, new GlideDateTime().getNumericValue(), location]); } if (activityInput.Host !== null) { gs.info('---> [{1}-{2}] activityInput.Host: {0}', [activityInput.Host, new GlideDateTime().getNumericValue(), location]); } else { gs.info('---> [{1}-{2}] bad Host: {0} does not exist.', [activityInput.Host, new GlideDateTime().getNumericValue(), location]); } if (activityInput.vtam_resource !== null) { gs.info('---> [{1}-{2}] activityInput.vtam_resource: {0}', [activityInput.vtam_resource, new GlideDateTime().getNumericValue(), location]); } else { gs.info('---> [{1}-{2}] bad vtam_resource: {0} does not exist.', [activityInput.vtam_resource, new GlideDateTime().getNumericValue(), location]); }
- Click the Continue button to display the Execution Command form.
In the Target host field, enter:
${activityInput.Host}
In the Script type field, select “Custom PowerShell command”.
In the Command field, enter:
ev390hostcmd 40 D net,id=$vtam_resource.$Node
In the Powershell variables fields, enter the following:Name Value Type Node
${activityInput.Node}
Plain
vtam_resource
${activityInput.vtam_resource}}
Plain
Select the box of “Use MID Service Account”.
- Click the Continue button to continue to the Outputs form.
- Add three fields under Output{}:
Name: result
Type: String Name: output
Type: String Name: errorMessage
Type: String - Click the Go to Post-Processing button to continue.
- Fill in the Post-Processing form with the following:Output process script:
var location = 'WFEV390_IST105I: Run PowerShell EV390_IST105I Outputs Activity'; if (gs.nil(executionResult.error)) { activityOutput.result = "success"; try { var output = executionResult.output; if (output != null) { activityOutput.output = output.substring(output.indexOf('<Objects>')); gs.info('---> [{1}:{2}] activityOutput.output: {0}', [activityOutput.output, new GlideDateTime().getNumericValue(), location]); //DEBUG } } catch(err) { gs.error('---> [{1}:{2}] {0}', [err, new GlideDateTime().getNumericValue(), location]); } } else { activityOutput.result = "failure"; activityOutput.errorMessage = executionResult.errorMessages; gs.info('---> [{1}:{2}] activityOutput.errorMessage: {0}', [activityOutput.errorMessage, new GlideDateTime().getNumericValue(), location]); // DEBUG }
- Click the Continue button to continue to the Conditions form.
- Add two condition fields:
Name Condition Order Success
activityOutput.result == 'success'
100
Failure
activityOutput.result != 'success'
200
- Click on the Save button to save the new Custom Activity.
- Click on the Publish button to make the new activity public.
- Verify the new custom EV390_IST105I_Activity.
- In the Workflow Editor navigate to Custom > Ironstream Mainframe Event Management >. You will now see the new EV390_IST105I_Activity present.
- Go to the Workflows tab and click the plus "+" button to create a new workflow.
- Fill in the New Workflow form with the following:
Name: EV390_IST105I workflow
Table: Remediation Task[em_remediation_task]
Description: Run the VTAM display on inactive resource
If condition matches: Run the workflow always - Click the Submit button to start building your workflow.
- Drag your custom EV390_IST105I_Activity onto the new workflow and fill in the properties form with the following:
Name: EV390_IST105I Activity Input
Node: ${workflow.scratchpad.node}
Host: ${workflow.scratchpad.host}
Vtam Resource: ${workflow.scratchpad.vtam_resource}
- Click the Submit button to save the activity to the workflow.
- To access the results for the Custom Activity, add a Run Script Activity after the EV390_IST105I Activity Input in the Success branch. The after-activity results from your Custom Activity are available for coding in the Data tab and might have a different data objects number than the data.get(4) used here. (See the two items marked in red.)Note: It is important to understand that workflow.scratchpad (and other workflow variables) are not available inside the Custom Activity.
- Go to Core tab > Utilities and drag out a Run Script activity onto the Success output line of your custom activity.
- Fill in the properties form with the following:
Name:
Handle Results
Script:var location = 'WFEV390_IST105I:' + context.name + '.' + activity.name; var psScriptTest = data.get(4); try { gs.info('---> [{1}:{2}] previous_activity.result: {0}', [psScriptTest.result, new GlideDateTime().getNumericValue(), location]); gs.info('---> [{1}:{2}] previous_activity.output: {0}', [psScriptTest.output, new GlideDateTime().getNumericValue(), location]); gs.info('---> [{1}:{2}] previous_activity.errorMessage: {0}', [psScriptTest.errorMessage, new GlideDateTime().getNumericValue(), location]); var results = {output : '', error : ''}; results.output = psScriptTest.output; results.error = psScriptTest.errorMessage; workflow.info('---> [{1}:{2}] {0}', [results.output, new GlideDateTime().getNumericValue(), location]); workflow.scratchpad.output = results; // pass the results out onto the data stream // Get current task record object var gr = new GlideRecord("em_remediation_task"); gr.addQuery( "number", current.number ); workflow.info("current.number:"+current.number); gr.query(); if ( gr.next() ) { // Add command output as attachment to this record var attachment = new GlideSysAttachment(); var attachment_sys_id = attachment.write( gr, "cmdoutput.txt", "txt", psScriptTest.output ); workflow.info("attachment_sys_id:"+attachment_sys_id); } // Put command output in description field up to limit of field current.description = psScriptTest.output; } catch(err) { gs.error('---> [{1}:{2}]\n{0}', [err, new GlideDateTime().getNumericValue(),location]); }
- Click the Submit button to save your Activity to the workflow.
- Add another Run Script Activity into the Failure output of the EV390_IST105I Activity Input. (Best Practice: You should always handle potential errors!)
- Fill out the form with the following:
Name:
Handle Failure
Script:var location = 'WFEV390_IST105I:' + context.name + '.' + activity.name; var psScriptTest = data.get(4); try { gs.info('---> [{1}:{2}] previous_activity.result: {0}', [psScriptTest.result, new GlideDateTime().getNumericValue(), location]); gs.info('---> [{1}:{2}] previous_activity.output: {0}', [psScriptTest.output, new GlideDateTime().getNumericValue(), location]); gs.error('---> [{1}:{2}] previous_activity.errorMessage: {0}', [psScriptTest.errorMessage, new GlideDateTime().getNumericValue(), location]); // package up the results for pushing onto the workflow (future use) var results = {output : '', error : ''}; results.output = psScriptTest.output; results.error = psScriptTest.errorMessage; workflow.info('---> [{1}:{2}] {0}', [results.output, new GlideDateTime().getNumericValue(),location]); workflow.scratchpad.output = results; // pass the results onto the data stream } catch(err) { gs.error('---> [{1}:{2}]\n{0}', [err, new GlideDateTime().getNumericValue(),location]); }
- Wire up the workflow to match this diagram: