Important

   

Starting version 8.9.03, BMC Network Automation is renamed to TrueSight Network Automation. This space contains information about BMC Network Automation 8.9.02 and previous versions. For TrueSight Network Automation 8.9.03 and later releases, see the TrueSight Network Automation documentation.

Examples of custom action adapters

This topic presents examples and code snippets for custom action adapters.

Example: Capture device information using a Ping custom action, reporting results into job status

The Ping custom action is a basic example of how to request input from a user, with runtime parameters. The user’s input is plugged into the ping command executed at the device.

If the ping command fails, the completion status of the custom action (and the enclosing job) depends on the result of the ping (Success on complete success, Failed on a complete failure, or Succeeded with warning on a partial failure). 

This example is a simplified version of the standard Ping custom action, which is available on the Device Adapters page and is implemented for many device types.

1. <?xml version="1.0" encoding="UTF-8" ?>
2. <deviceTypeMap>
3.     <customDeviceCommandDeclaration>
4.         <name>Ping</name>
5.         <guid>F6D4804A-EF08-4D89-98CC-74E540492001</guid>
6.         <description>Pings from the device to the IP address entered at runtime.</description>
7.         <browserExecutable>true</browserExecutable>
8.         <inspectionOnly>true</inspectionOnly>
9.         <runtimeParameters>
10.            <runtimeParameter>
11.                <name>node</name>
12.                <prompt>IP address of node to ping</prompt>
13.                <type>text</type>
14.                <required>true</required>
15.                <mask>\d+\.\d+\.\d+.\d+</mask>
16.            </runtimeParameter>
17.        </runtimeParameters>
18.    </customDeviceCommandDeclaration>
19.    <deviceType>
20.        <guid>BE2B2D21-1CAA-53C3-05C3-CBB0A5D151B8</guid>
21.        <extension>true</extension>
22.        <deviceCommand>
23.            <guid>F6D4804A-EF08-4D89-98CC-74E540492001</guid>
24.             <interaction regex="true">
25.                <prompt>%prompt%</prompt>
26.                <command>ping %runtime.node%</command>
27.                <response property="cmd.pingSuccess">Success rate is 100 percent</response>
28.                <response property="cmd.pingWarning">Success rate is (20|40|60|80) percent</response>
29.                <response property="cmd.pingAbort">Success rate is 0 percent</response>
30.            </interaction>
31.            <assert condition="((-EXISTS- cmd.pingSuccess) -OR- (-EXISTS- cmd.pingWarning))" onFailure="abort">
32.                Ping returned success rate of 0 percent.
33.            </assert>
34.            <assert condition="(-EXISTS- cmd.pingSuccess)" onFailure="warning">
35.                Ping returned success rate of greater than 0 but less than 100 percent.
36.            </assert>
37.        </deviceCommand>
38.    </deviceType>
39.</deviceTypeMap>
LineExplanation
4Name of the action displayed to the user
5GUID identifying the custom action
8This action makes no changes to the device.
11This is the property name to be used in the XML code, prefixed with runtime.
12Tells the user what to enter into the text entry field, when the user adds this custom action to a job, predefined job, or policy.
15Validates the format of what the user enters; this checks a simple IPv4 address.
20The GUID of the Cisco IOS device type. This custom action is being implemented for Cisco IOS.
23The GUID of the custom action, from line 5. This <deviceCommand> is implementing the custom action for Cisco IOS.
26The command to be run on the device, with a keyword to plug in the IP address entered by the user.
27-29Interpretation of the ping results, setting properties to examine next. If the ping reports a success rate of 20, 40, 60, or 80 percent, then the cmd.pingWarning property is set. If it is 0 percent, then the cmd.pingAbort property is set. If it is 100 percent, then cmd.pingSuccess is set.
31Checks if properties, cmd.pingSuccess or cmd.pingWarning exist (from being set in the preceding lines); if not, causes this action to fail with an error.
35Checks if property cmd.pingSuccess exists; if not, causes this action to to fail with a warning. Else, processing continues on; since there is nothing else to do, the action completes successfully.

Back to top 

 Recommendations to direct the custom action results

The results of executing a custom action can be directed to the following locations:

  • The custom action's completion status (as shown in the preceding example)
  • The custom action's execution transcript
  • The Captured results column in the Job Details report
  • Device dynamic fields
  • Imported hardware inventory

 When determining which location to direct the custom action results, use the following recommendations:

  • Job status: Use alone for simple checks whose result can be evaluated to success or failure. Use with other techniques for more complicated actions. Always look for invalid or unsupported command syntax and match that to an <error> element, which results in a failure.
  • Transcripts: Use for long lists containing a lot of data that you want to review, or for transient reports gathering statistics or low-level operational states (for example, run a show ipc queue every 24 hours and report the results). Custom action transcripts can be attached to job email notifications and included in the Job Details exported and emailed versions, when you choose to include all details. The Print View version of the Job Details page also displays all the transcripts in the job.
  • Captured results: Use for small amounts of data that you want parsed out of longer show command results and presented in the Job Details page. Also, use captured results for custom actions that you use often (for example, show current vlans defined on all switches). A captured result is limited to 2000 characters.
  • Dynamic fields: Use for small bits of persistent information that do not change often (for example, serial numbers, uplink interfaces, and so on). Dynamic field values are limited in length, but a device can have many dynamic fields and a field can have either a single value or multiple values. Devices can be auto-grouped on the value, and the value can be referenced by templates, compliance rules, and other custom actions as a device substitution parameter. The value can be viewed and exported using the Device inventory report. A Text type of dynamic field limits the value to 2000 characters; other dynamic fields impose a limit to 255 characters. See Adding dynamic fields.
  • Imported inventory: Use for a single large blob of information related to the hardware installed on the device that does not change very often (for example, the output of the IOS show module command). A device has a single imported inventory that can be viewed when you view or edit a device, and viewed and exported from the Device Inventory report. The size of the imported inventory is unlimited.

Back to top 

Example: Menu-based runtime parameter: menu options supplied inline

This code snippet results in a custom action page displayed to the user containing a menu labeled What to Show, with menu options configuration and memory (in that order). Since the runtime parameter is defined as required, the user must choose one of the two menu options. If the runtime parameter is defined as optional, the menu includes a blank option to allow the user to make no selection.

This custom action runs a show command, whose output is captured in the transcript. The user can view the transcript to see the result of the job.

<?xml version="1.0" encoding="UTF-8" ?>
<deviceTypeMap>
    <customDeviceCommandDeclaration>
        <name>Show Using Inline Menu Values</name>
        <guid>590FBB15-FB00-48AB-803A-9F928A7BAEFE</guid>
        <browserExecutable>true</browserExecutable>
        <inspectionOnly>true</inspectionOnly>
        <runtimeParameters>
            <runtimeParameter>
                <name>show</name>
                <prompt>What to Show</prompt>
                <type>menu</type>
                <required>true</required>
                <menuValues>
                    <inline>
                        <menuValue>configuration</menuValue>
                        <menuValue>memory</menuValue>
                    </inline>
                </menuValues>
            </runtimeParameter>
        </runtimeParameters>
    </customDeviceCommandDeclaration>
    <deviceType>
        <guid>BE2B2D21-1CAA-53C3-05C3-CBB0A5D151B8</guid>
        <extension>true</extension>
        <deviceCommand>
            <guid>590FBB15-FB00-48AB-803A-9F928A7BAEFE</guid> <!-- show -->
            <interaction>
                <command>show %runtime.show%</command>
                <response>%prompt%</response>
                <error>Invalid input</error>
            <interaction>
        </deviceCommand>
    </deviceType>
</deviceTypeMap>

Back to top 

Example: Menu-based runtime parameter: menu options supplied in a file

In this example, the custom action page displayed to the user contains a menu labeled What to Show, with menu options that are specified in the ShowmenuOptions.txt file. The text file is located in the BCAN_DATA\endorsed directory. Since the runtime parameter is defined as required, the user must choose from the presented options. If the runtime parameter is defined as optional, the menu includes a blank option to allow the user to make no selection.

<?xml version="1.0" encoding="UTF-8" ?>
<deviceTypeMap>
    <customDeviceCommandDeclaration>
        <name>Show Using CSV Menu Values</name>
        <guid>590FBB15-FB00-48AB-803A-9F928A7BAEFE</guid>
        <browserExecutable>true</browserExecutable>
        <inspectionOnly>true</inspectionOnly>
        <runtimeParameters>
            <runtimeParameter>
                <name>show</name>
                <prompt>What to Show</prompt>
                <type>menu</type>
                <required>true</required>
                <menuValues>
                    <file>
                        <fileName>ShowMenuOptions.txt</fileName>
                    </file>
                </menuValues>
            </runtimeParameter>
        </runtimeParameters>
    </customDeviceCommandDeclaration>
    <deviceType>
        <guid>BE2B2D21-1CAA-53C3-05C3-CBB0A5D151B8</guid>
        <extension>true</extension>
        <deviceCommand>
            <guid>590FBB15-FB00-48AB-803A-9F928A7BAEFE</guid> <!-- show -->
            <interaction>
                <prompt>%prompt%</prompt>
                <command>show %runtime.show%</command>
                <response>%prompt%</response>
                <error>Invalid input</error>
            </interaction>
        </deviceCommand>
    </deviceType>
</deviceTypeMap>

Note

  • The file named ShowMenuOptions.txt must be placed in the BCAN_DATA\endorsed directory.
  • If the file is missing, empty, or not readable by the web server, the menu displays an empty list.
  • The file must contain one menu option per line, in the order you want them to appear in the menu. For example:
    • Menu Option 1
    • Menu Option 2
    • Menu Option 3

Back to top 

Example: Menu-based runtime parameter: menu options supplied in an SQL database

In this example, the custom action page displayed to the user includes a menu with options derived from querying a database table.

In this example, the database requires a user name and password embedded in the HTTP query. The user name and password are encoded in the following form:

user=bcan&amp;password=mypassword

bcan represents the database user name and mypassword represents the actual password. The &amp; entity encodes the ampersand (&).

<?xml version="1.0" encoding="UTF-8" ?>
<deviceTypeMap>
    <customDeviceCommandDeclaration>
        <name>Show Using JDBC Menu Values</name>
        <guid>C296EB5E-69C2-42A3-AE42-964DE35AAD27</guid>
        <browserExecutable>true</browserExecutable>
        <inspectionOnly>true</inspectionOnly>
        <runtimeParameters>
            <runtimeParameter>
                <name>show</name>
                <prompt>What to Show</prompt>
                <type>menu</type>
                <required>true</required>
                <menuValues>
                    <jdbc>
                        <dbUrl>jdbc:postgresql://localhost:5432/bcandb?user=myusername&amp;password=mypassword</dbUrl>
                        <dbQuery>SELECT name FROM menu_data WHERE location='ATL' ORDER BY name</dbQuery>
                    </jdbc>
                </menuValues>
            </runtimeParameter>
        </runtimeParameters>
    </customDeviceCommandDeclaration>
    <deviceType>
        <guid>BE2B2D21-1CAA-53C3-05C3-CBB0A5D151B8</guid>
        <extension>true</extension>
        <deviceCommand>
            <guid>590FBB15-FB00-48AB-803A-9F928A7BAEFE</guid> <!-- show -->
            <interaction>
                <prompt>%prompt%</prompt>
                <command>show %runtime.show%</command>
                <response>%prompt%</response>
                <error>Invalid input</error>
            </interaction>
        </deviceCommand>
    </deviceType>
</deviceTypeMap>

Notes

  • Only the first selected column is used for the menu value.
  • The options in the menu are displayed in the order the database server returns the rows. Include an ORDER BY clause in the SQL statement to ensure a readable ordering in a large menu.
  • If the query fails (for example, the database is unreachable, the query has a syntax error, or the query returns no rows), the menu displays an empty list.
  • Errors reaching the database, or in the query, are reported in detail in the web server's log file.

Back to top 

Example: Text-based runtime parameter: validating if a value exists for the parameter

If you do not specify a value for an optional runtime parameter in a custom action, the property does not exist for the XML logic to use. Therefore, to ensure that a runtime parameter actually has a value, check for -EXISTS- condition before you use the runtime parameter. Consider the following code snippet in which the optional runtime parameter node is defined in the custom action:

<runtimeParameters>
    <runtimeParameter>                       
        <name>node</name>                                                           
        <prompt>IP Address</prompt>
        <type>text</type>
        <required>false</required>
    </runtimeParameter>                             
</runtimeParameters>

<!-- code snippet uses -EXISTS- before using the runtime parameter -->
<condition test="-EXISTS- runtime.node">
    <interaction>
        <prompt>%prompt%</prompt>
        <command>ping %runtime.node%</command>
        <response>%prompt%</response>
    </interaction>                         
</condition>

Back to top 

Example: Password runtime parameter: Sorting parameters on the user interface

In this example, the custom action page displayed to the user includes three text entry fields. These fields appear in the order specified by the sortOrder tags. Since they are password type parameters, the typed-in values are masked from view.

Note that the new password is prompted for twice. To validate that the user typed the same password, you can write a conditional expression using the -EQ- operator. Or, you can let the device react to the invalid inputs.

<customDeviceCommandDeclaration>
    <name>Set Local Password</name>
    <guid>958DF9D3-DA5D-4791-958A-B92F91F7F787</guid>
    <browserExecutable>true</browserExecutable>
    <inspectionOnly>false</inspectionOnly>
    <runtimeParameters>
        <runtimeParameter>
            <name>oldPassword</name>
            <prompt>Old Password</prompt>
            <type>password</type>
            <required>true</required>
            <sortOrder>1</sortOrder>
        </runtimeParameter>
        <runtimeParameter>
            <name>newPassword</name>
            <prompt>New Password</prompt>
            <type>password</type>
            <required>true</required>
            <sortOrder>2</sortOrder>
        </runtimeParameter>
        <runtimeParameter>
            <name>confirmPassword</name>
            <prompt>Confirm New Password</prompt>
            <type>password</type>
            <required>true</required>
            <sortOrder>3</sortOrder>
        </runtimeParameter>
    </runtimeParameters>
</customDeviceCommandDeclaration>

<!-- test that the new passwords are the same -->
<assert condition="%runtime.newPassword% -EQ- %runtime.confirmPassword%" onFailure="abort">
    Confirmation password does not match the new password.
</assert>
<!-- safe to proceed to set the the password... -->

Back to top 

Example: Grouping custom actions into submenus

You can group custom actions into display submenus by using the optional <groupName> tag, which defines the menu option that is the custom action's parent menu option. Note that <groupName> affects only browser-executable actions, since it is related to the GUI.

Example:

  • Add Actions Menu:
    • Span Actions
    • Endpoint Actions
    • Notifications
    • Custom Actions
      • Action 1, is in Group A
      • Action 2, is in Group A
      • Action 3, in not in any group
      • Action 4, is in Group B
<?xml version="1.0" encoding="UTF-8" ?>
<deviceTypeMap>
    <customDeviceCommandDeclaration>
        <name>Action 1</name>
        <guid>C9FDC1C8-A2DF-4E18-AE2B-849CF66221AA</guid>
        <groupName>Group A</groupName>
        <browserExecutable>true</browserExecutable>
    </customDeviceCommandDeclaration>

    <customDeviceCommandDeclaration>
        <name>Action 2</name>
        <guid>171A3D80-9201-4BB7-AAD0-A4C744192671</guid>
        <groupName>Group A</groupName>
        <browserExecutable>true</browserExecutable>
    </customDeviceCommandDeclaration>

    <customDeviceCommandDeclaration>
        <name>Action 3</name>
        <guid>B95115A0-4ED0-4D97-A847-DB21862EF3D0</guid>
        <browserExecutable>true</browserExecutable>
    </customDeviceCommandDeclaration>

    <customDeviceCommandDeclaration>
        <name>Action 4</name>
        <guid>DD288EE4-7B97-4916-80EB-5E13BDAB9130</guid>
        <groupName>Group B</groupName>
        <browserExecutable>true</browserExecutable>
    </customDeviceCommandDeclaration>
</deviceTypeMap> 

Back to top 

Example: Populating dynamic fields from a custom action

This section describes best practices for defining dynamic fields and examples of populating simple and multi-select dynamic fields from custom actions.

Best practices for defining dynamic fields

When defining a dynamic field, you should consider the kind of data being captured from the device. Although any dynamic field is acceptable, the Value Type that you choose can affect the usability of the system. If the data is unique for each device, you should define the dynamic field as Text because there will be a large range of unpredictable values. If the data belongs to a small range of discrete values, such as domain names or netmasks, you should define the dynamic field as a Single-Select menu type. When creating new devices, the menu type provides users a limited selection by displaying a menu on the device edit page.

Carefully consider whether you want to enable auto-grouping. If the data is unique per device, do not enable auto-grouping. Enabling auto-grouping results in a single auto-group per device, making it difficult to use large group lists and imposing a performance impact on the system as values change.

Note

If you want to capture a long value through a dynamic field, for example, a long encryption key, set the maximum length of the dynamic field to 2000 characters. This limit is available only when you create a Text type dynamic field for a Device type component and if you do not select the Display in Lists and Auto-Group options. For all other component and value types, the maximum length allowed is 255 characters. The limit for the default value of new components is 255 characters.

Populating simple dynamic fields from a custom action

Get System Serial Number is a factory-installed custom action that shows how to populate a device record's dynamic field called Serial Number with the serial number captured by the custom action’s command output.

Before running the custom action, create a device dynamic field called Serial Number; specify it as a Text field with a maximum length of at least 50 characters.

You must also edit the custom action definition in the device adapter, which is available from Admin > Device Adapters. Export and edit the adapter. Uncomment the <dynamicFIeld> section that tells the system to populate this dynamic field from the result.pbid property, and then import the modified adapter. The following code segment is an excerpt from the factory-installed custom action for Cisco IOS:

<deviceTypeMap>
    <customDeviceCommandDeclaration>
        <name>Get System Serial Number</name>
        <guid>045D9DF3-AB31-4BB7-8A60-524F2219CE17</guid>
        <groupName>Hardware</groupName>
        <description>Gets the system serial number of the device.</description>
        <browserExecutable>true</browserExecutable>
        <inspectionOnly>true</inspectionOnly>
        <dynamicField>
            <name>Serial Number</name>
            <sourceResult>result.pbid</sourceResult>
        </dynamicField>
    </customDeviceCommandDeclaration>

    <deviceType>
        <guid>BE2B2D21-1CAA-53C3-05C3-CBB0A5D151B8</guid>  <!-- Cisco IOS -->
        <extension>true</extension>
        <deviceCommand>
            <guid>045D9DF3-AB31-4BB7-8A60-524F2219CE17</guid> <!-- Get System Serial Number -->
            <interaction>
                <prompt>%prompt%</prompt>
                <command>show ver</command>
                <response>%prompt%</response>
                <error>Invalid input</error>
                <capture buffer="Processor\s+board\s+ID\s*(\S+) "ignoreFailure="true">
                    <property name="result.pbid">{1}</property>
                </capture>
            </interaction>
        </deviceCommand>
    </deviceType>
</deviceTypeMap>

The captured property result.pbid is displayed in the Captured Results column of the Job Details report, as shown in the following figure:

Important

A captured value must conform to the data type allowed by that dynamic field.

Examples:

  • If you have a text type dynamic field, the captured value must not exceed the maximum character length specified by the dynamic field.
  • If the dynamic field is an integer type, the captured value must be numeric.
  • If the dynamic field is a date type, the captured value must be a date in the format, yy/mm/dd.

By default, invalid values are ignored and are not stored into the device. However, if you try to populate a field that drives auto-grouping, you might want to know about invalid values.

In the custom action declaration, you can specify what error handling should occur when an invalid dynamic field value is detected. Inside the <dynamicField> tag, you can include the <onBadValue> tag with one of the values listed in the following table:

ValueDescription
logEventLog a warning-level event to the event log; the action still succeeds.
failActionMinorFlag the action as succeeded with warning.
failActionMajorFlag the action as failed.

For example, if the Serial Number text-type dynamic field has a maximum field length of 20, upon executing the following XML snippet, the event log includes a warning event for each captured result.pbid that exceeds a length of 20 characters. The event specifies which device is being processed, which dynamic field is being populated, and the value that fails validation. The failActionMinor and failActionMajor settings specify the dynamic field and value in error.

<dynamicField>
    <name>Serial Number</name>
    <sourceResult>result.pbid</sourceResult>
    <onBadValue>logEvent</onBadValue>
</dynamicField>

Back to top 

Populating multi-select menu-based dynamic fields from a custom action

To populate multi-select menu dynamic fields, the declaration is the same as when populating a single value. The following script snippet is from the Get Trunk Interfaces factory-installed custom action:

<dynamicField>
    <name>Trunks</name>
    <sourceResult>result.Trunk</sourceResult>
    <rejectUnknownMenuOptions>false</rejectUnknownMenuOptions>
</dynamicField>
...
<interaction>
    <prompt>%prompt%</prompt>
    <command>show int desc | exclude Interface</command>
    <response>%prompt%</response>
    <error>Invalid input</error>
    <capture buffer="(\S+)\s+.*$" multipleValues="true" ignoreFailure="true" >
        <property name="cmd.allInterfaces">{1}</property>
    </capture>
</interaction>
<loop variable="Interface" input="cmd.allInterfaces">
    <interaction>
        <prompt>%prompt%</prompt>
        <command>show int %loop.Interface% switchport</command>
        <response>%prompt%</response>
        <capture buffer="^Operational Mode:\s*(\S+).*" ignoreFailure="true">
            <property name="cmd.operMode">{1}</property>
        </capture>
    </interaction>
    <condition test="(-EXISTS- cmd.operMode) -AND- (%cmd.operMode% -EQ- trunk)">
        <assign property="result.Trunk.%loop.Interface%" value="%loop.Interface%"/>
        <assign property="cmd.operMode" value=""/>
    </condition>
</loop>

The first interaction captures a set of interface names into properties called cmd.allInterfaces.<index>, where <index> is a number assigned by the system, starting at zero and ranging up to the number of results that match the pattern. Each value is the interface name taken from the output of the show int desc command.

Note

The <capture> tag includes the multipleValues attribute, which tells the system to loop over the command's output, looking for every match to the pattern.

The second interaction loops over the set of discovered cmd.allInterfaces properties, running a show int switchport command on each; when the output includes the operational mode of trunk, then a property called result.Trunk.<name> is set, where <name> is the name of the interface.

The system then finds if such a dynamic field exists because the results must populate Trunks, a dynamic field. You must have added it, and to support multiple values, it must be a multi-select menu.

When properties matching the value specified in <sourceResult> are captured, the system erases the device's current values for the specified dynamic field, then finds all the properties named starting with result.Trunk; each property's value is added to the device's setting for this dynamic field.

When no properties matching the value specified in <sourceResult> are captured, the current values are cleared for system-assigned dynamic fields. The values are unchanged for user-assigned dynamic fields to allow a user to assign values manually, should a device not support the commands run by the custom action.

The custom action declaration specifies that any values not already in the dynamic field's menu are not to be rejected, but are to be automatically added to the menu. If you instead specify that unknown options are to be rejected, you must predefine the legal range of values in the dynamic field's menu. Any value encountered in a property that is not already in the dynamic field's menu will be ignored.

You can reference the trunk interfaces in a Rule as shown in the following figure. The Rule Domain specification resolves to For each trunk interface.

Back to top 

Example: Populating the Imported Hardware field from a custom action

Each device has an attribute known as the imported inventory. The value stored in it is usually obtained from an external element manager such as CiscoWorks or HP OpenView Network Node Manager during the device import process. The inventory is shown when you view a device, and in the Device Inventory Report. Instead of importing the data from an element manager, you can fill it with relevant information directly from the device.

The following example shows how to populate the imported hardware field of a device from a custom action. This is very similar to storing results of custom actions into dynamic fields.

The differences are as follows:

  • The Imported Hardware field of a device is not limited in size and can capture large text values.
  • A device has only a single value for its current imported inventory.
  • The imported inventory is not available as a substitution parameter, and thus cannot be referenced in rules, templates, or other actions.
<customDeviceCommandDeclaration>
    <name>Show system information for switch</name>
    <guid>1676338B-BCE5-48D5-976F-28890E2965BC</guid>
    <browserExecutable>true</browserExecutable>
    <inspectionOnly>true</inspectionOnly>
    <importedHardware>
        <sourceResult>result.sys.info</sourceResult>
    </importedHardware>
</customDeviceCommandDeclaration>

Back to top 

Related topics

About network spans
Managing static groups
Adding dynamic fields

Was this page helpful? Yes No Submitting... Thank you

Comments