Device type command content
The following sections describe the various child tags allowed within the <deviceCommand> tag, within a given <deviceType> tag:
- interaction
- httpInteraction
- Bounded
- Unbounded
- Optional attribute
- Property substitution
- Property capture—simple
- Property capture—complex
- Property capture—multiple values
- Property capture—multiple passes
- Property capture—discovery
- Property assignment
- Conditions
- Response properties
- Error properties
- Retry
- Disconnect
- Loops
- Assertions
- Regular expression support
- Jitter time
- Sensitive commands
- Finally Block
- Sleep
interaction
An interaction is a block that defines the terminal commands to be executed on a target device. An Interaction element can include the following sub-elements:
- prompt: Checks the defined pattern as prompt in a device, and after getting the required prompt, a defined command in the command tag is executed.
- command: Defines the commands to be executed.
- response: Defines the response that device is going to exhibit after the command execution.
- error: Defines the pattern which if shown by the device after the command execution, BMC Network Automation treats the command execution as failure.
- capture: Enables you to capture the defined pattern as property from the device output.
- pauseSeconds: Defines the time in seconds for which you want to explicitly wait between sending the command and receiving the response.
httpInteraction
An httpInteraction is a block that defines HTTP-based commands such as get, post, put, and delete to be executed on a target device. This element can include the following sub-elements:
- requestHeader: Defines the header of the request.
- requestBody: Defines the body of the request.
- response: Defines the response that device is going to exhibit after the command execution.
- error: Defines the pattern which if shown by the device after the command execution, BMC Network Automation treats the command execution as failure.
- capture: Enables you to capture the defined pattern as property from the device output.
Bounded
Interactions which have both, prompt and response elements are called bounded.
The following example shows a device command with bounded interaction:
<interaction>
<prompt>text_A</prompt>
<command>text_B</command>
<response>text_C</response>
<error>text_D</error>
</interaction>
<interaction>
<prompt>text_C</prompt>
<command>text_E</command>
<response>text_F</response>
<error>text_G</error>
<error>text_H</error>
</interaction>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<prompt> | receive until text_A found in buffer |
<command> | clear buffer, send text_B |
<response> | receive until text_C or text_D found in buffer if buffer contains text_D then throw exception |
<prompt> | receive until text_C found in buffer |
<command> | clear buffer, send text_D |
<response> | receive until text_F or text_G or text_H found in buffer if buffer contains text_G then throw exception else if buffer contains text_H then throw exception |
<error> tags are generally just a convenience used to allow immediate failure detection in the communication process. A given interaction always generates a timeout exception if its timeout limit is reached. The default timeout limit for interactions is controlled via the deviceDefaultResponseTimeoutSeconds global property, but can also be specified on a per interaction basis by using an XMLattribute.
Unbounded
Interactions that are missing a prompt and/or response tags are called unbounded.
The following example shows a device command with unbounded interaction:
<interaction>
<command>text_A</command>
</interaction>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<command> | clear buffer, send text_A |
When the <response> specification is omitted, any <error> tags present might be effectively executed. This is because the receive action performed after such a command is a single non-blocking read, as opposed to a blocking read, which is performed when a <response> has been specified. If the device responds slowly, no text is present in the read buffer yet, so you would not detect the error. Likewise, if the device responds with a lot of jitter (more than 10 milliseconds in between characters sent), you would also miss the error.
You can specify a <pauseSeconds> tag for interactions when you want to explicitly wait one or more seconds between sending the command and receiving the response. This can be helpful for unbounded cases. For this reason, it is generally advisable to specify adequate <prompt> and <response> tag boundaries for your interactions.
Optional attribute
An <interaction> tag can include an optional attribute if necessary to reflect unpredictable device behavior.
The following example shows a device command containing an interaction with the optional attribute:
<interaction optional="true">
<prompt>text_A</prompt>
<command>text_B</command>
<response>text_C</response>
</interaction>
<interaction>
<prompt>text_C</prompt>
<command>text_D</command>
<response>text_E</response>
</interaction>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<prompt> | receive until text_A found in buffer or text_C found in buffer |
<command> | clear buffer, send text_B |
<response> | receive until text_C or text_D found in buffer if buffer contains text_D then throw exception |
<prompt> | receive until text_C found in buffer |
<command> | clear buffer, send text_D |
<response> | receive until text_E found in buffer else clear buffer, send text_D receive until text_E found in buffer |
Be careful when using optional interactions because they are not permitted in all circumstances. You cannot use an optional interaction as the last interaction prior to or within a complex block of interactions being evaluated. This means the last interaction in the <deviceCommand> tag cannot be optional. It also means that the last interaction prior to or within a loop cannot be optional either. In case of a condition, if it is not a simple block (for example, it contains nested conditions or loops), then the last interaction prior to or within such a condition cannot be optional either. Loopsand conditions are described in succeeding sections.
If you violate these rules, you are blocked until you receive the optional <prompt> within the receive buffer. If the device does not send the optional <prompt>, the command times out and fails erroneously.
Property substitution
Any of <interaction> child tags can contain property substitution strings. These strings follow the pattern %.*%, for instance %property_1%. When such a device interaction is executed, if a property named property_1 exists within the context of the current connection, its value is substituted. Otherwise, an empty string is substituted.
The following example shows a device command containing an interaction with a property substitution string:
<interaction>
<command>%property_1%</command>
</interaction>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<command> | clear buffer, send property_1 value |
The property_1 property must already have been added to the current connection's list of properties, generally by an argument passed to the current or an earlier connection action method. For instance, the snapshot method passes the username attribute as an argument to the login method. If the value is not empty, it is used to set a username property in that connection, and made available to all subsequent device commands it executes.
The following table lists all of the available connection properties, and describes when they get populated (for example, when the connection is first constructed, or when particular device commands are about to be executed):
Property | Description |
---|---|
accessMode | set by constructor |
accessPort | set by constructor |
address | set by N2R, N2S, R2N, S2N methods |
CR | set by constructor |
defaultResponseTimeoutSeconds | set by constructor |
deviceAddress | set by constructor |
deviceCategory | set by constructor |
deviceName | set by constructor |
disconnectTimeoutSeconds | set by constructor |
discoverTransferMode | set by login method |
doCommitAllContexts | set by commit method Note: Set to true or false depending on the user's selection of the Commit All Security Contexts When Applicable option on the commit action page. |
empty | set by constructor |
endpointAddress | set by getNextSwitch command |
endpointMacAddress | set by getNextSwitch command |
eraseFilesystem | set by the IOSImageLoader class (only for IOS) |
escape | set by constructor |
fileContents.* | set by N2R method |
fileDigestValue | set by prior to image verification |
ftpPassword | set by N2R, N2S, R2N, S2N, N2I, I2N methods |
ftpRestrictedPathAccess | set by constructor |
ftpUsername | set by N2R, N2S, R2N, S2N, N2I, I2N methods |
isWindowsOS | set by constructor |
LF | set by constructor |
maxBinaryTransferDurationSeconds | set by I2N, N2I methods |
maxTextTransferDurationSeconds | set by R2N, S2N, N2R, N2S methods |
password | set by login method (unencrypted) |
privPassword | set by login method (unencrypted) |
privUsername | set by login method |
rebootTimeoutSeconds | set by N2I method |
reconnectTimeoutSeconds | set by relogin method |
saveChoice | set by reboot method |
scpPassword | set by N2R, N2S, R2N, S2N, N2I, I2N methods |
scpUsername | set by N2R, N2S, R2N, S2N, N2I, I2N methods |
securityContextNameFromUser | set by login method |
securityContextTypeFromUser | set by login method |
space | set by constructor |
squeezeTimeoutSeconds | set by discoverImageDetails |
tab | set by constructor |
targetImageFilesystem | set by the image loader class |
targetSecurityContextName | set by createConfigureActions and createUnconfigureActions in ContainerFaultHostPair |
terminalLogin | set by login method |
terminalPrivLogin | set by login method |
terminalServerPassphrase | set by login method (unencrypted) |
terminalServerPassword | set by login method (unencrypted) |
terminalServerUsername | set by login method |
transferActivation | set by N2I method |
transferAlias | set by N2I method |
transferFilename | set by R2N, S2N, N2R, N2S, I2N, N2I methods |
transferMode | set by constructor |
username | set by login method |
The following table lists the values that are used to populate the properties listed in the preceding table, but does not include properties that emerge from the device as captured property values:
Property | Description |
---|---|
accessMode | from primary or auxiliary interface mode (depending on which interface is used to make the connection) |
accessPort | from primary or auxiliary interface port (depending on which interface is used to make the connection) |
address | from InetAddress.getLocalHost().getHostAddress() or Device.natAddress |
CR | from literal “\r” (a carriage return character) |
defaultResponseTimeoutSeconds | from Globals.DEVICE_DEFAULT_RESPONSE_ TIMEOUT_SECONDS |
deviceAddress | from primary or auxiliary interface address (depending on which interface is used to make the connection) |
deviceCategory | from Device.category |
deviceName | from Device.name |
disconnectTimeoutSeconds | from Globals.DEVICE_DISCONNECT_TIMEOUT _SECONDS |
discoverTransferMode | based on Device.transferMode being set to auto (true/false) |
doCommitAllContext | from user Note: Set to true or false depending on the user's selection of the Commit All Security Contexts When Applicable option on the commit action page. |
empty | from literal “” or the empty string %empty% is useful in conditions for checking whether another property has a non-zero-length value |
endpointAddress | from user |
endpointMacAddress | from getNextSwitch command |
eraseFilesystem | based on user choice to delete old image prior to load, on IOS systems that don’t support a delete command (“true”/”false”) |
escape | from unicode literal “\u001B” |
fileContents.* | from TextTransferFile.contents (successive lines assigned to fileContents.0, fileContents.1, fileContents.2, …, for tunneled merges) |
fileDigestValue | our calculation of the MD5 digest value of the image file you are sending |
ftpPassword | ftp password specified in the device agent configuration |
ftpRestrictedPathAccess | from the FTP User Restricted to Home Directory setting (On the Admin > Device Agent page) When this flag is checked, the property value is set to true to allow for conditional FTP command syntax |
imageArchive | set to true when an image filename matches the <imageArchiveFilename> regular expression. During a snapshot, the current image filename is evaluated; during an Deploy to Active operation, the new image filename is evaluated. |
isWindowsOS | set to true if the underlying operating system is Windows; else, false |
LF | from literal “\n” (a line feed character) |
maxBinaryTransferDurationSeconds | from SystemParameters.maxImageTransferDurationSeconds |
maxTextTransferDurationSeconds | from SystemParameters.maxScriptTransferDurationSeconds |
password | from device security profile, or from job if the system parameter is set to enter credentials at job creation time (unencrypted) |
privPassword | from device security profile, or from job if the system parameter is set to enter credentials at job creation time (unencrypted) |
privUsername | from device security profile, or from job if the system parameter is set to enter credentials at job creation time |
rebootTimeoutSeconds | from SystemParameters.rebootTimeoutSeconds |
reconnectTimeoutSeconds | from Globals.RECONNECT_TIMEOUT_SECONDS |
saveChoice | from user reboot mode choice (“y”/”n”/null) |
scpPassword | scp password specified in the device agent configuration |
scpUsername | scp user name specified in the device agent configuration |
securityContextNameFromUser | from Device.securityContextName Note: The name the user assigned to the security context on the device edit page. |
securityContextTypeFromUser | from Device.securityContextType Note: The type of security context defined by the user on the device edit page. Values are admin, system, userDefined, and none. |
space | from literal ““ |
squeezeTimeoutSeconds | from Globals.SQUEEZE_TIMEOUT_SECONDS |
tab | from literal “\t” |
targetImageFilesystem | from the users choice of where to load image file |
targetSecurityContextName | from DeviceType.creatorSecurityContextName Note: Name of the security context which that is automatically used to create (or destroy) a new guest context on a load balancer or firewall host during container configuration. This value is "system" for the FWSM device type. It can be null. |
terminalLogin | set to true when user is connecting to the device via the Terminal SSH proxy. (Note that only the login deviceCommand is executed when initiating a connection via the Terminal SSH Proxy.) |
terminalPrivLogin | set to true when user is connecting to the device via the Terminal SSH Proxy and has not used the -non-priv argument. |
terminalServerPassphrase | from device security profile (unencrypted) |
terminalServerPassword | from device security profile (unencrypted) |
terminalServerUsername | from device security profile |
transferAlias | from TransferFile.alias (name of transfer file within device’s filesystem, from device’s perspective, used during some image loads) |
transferFilename | from TransferFile.file.getName() (name of transfer file within ena filesystem, from ena’s perspective) |
transferMode | from primary or auxiliary interface mode (depending on which interface is used to make the connection) |
username | from device security profile, or from job if the system parameter is set to enter credentials at job creation time |
Property capture—simple
In addition to properties which are set via values passed by the code at runtime, you can set properties via text captured from a device response. This type of property capture is used for instance, to capture a device's dynamic <prompt> in a property, or to capture the entire contents of its configuration file dumped over the terminal session.
The following example shows a device command containing an interaction with a simple property capture:
<interaction>
<prompt>text_A</prompt>
<command>text_B</command>
<response>text_D</response>
<capture prefix=text_C suffix=text_D>
<property name="property_1"/>
</capture>
</interaction>
<interaction>
<prompt>%property_1%</prompt>
<command>text_E</command>
<response>text_F</response>
</interaction>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<prompt> | receive until text_A found in buffer |
<command> | clear buffer, send text_B |
<response> | receive until text_D found in buffer |
<capture> | if buffer contains text_C.*text_D then copy buffer between text_C and text_D to property_1 property else throw exception |
<prompt> | receive until property_1 value found in buffer |
<command> | clear buffer, send text_E |
<response> | receive until text_F found in buffer |
The prefix and suffix attributes in the preceding example are optional. If you omit <prefix>, text_B (the echoed command) is used as the prefix. If you omit <suffix>, text_D (the response) is used as the suffix.
You can also specify an optional includePrefix and/or includeSuffix attributes (they default to false). If both were true, for example, the value of property_1 would include the surrounding text_C and text_D strings instead of excluding them.
The optionalPrefix and optionalSuffix attributes are also available if you want to indicate that the prefix/suffix might not always be present. The normal behavior is for the absence of the indicated prefix/suffix to generate a chat error otherwise.
The eagerPrefix and eagerSuffix attributes are available to help you control which match of the prefix and suffix to use to bound your capture. This can be useful if they can be matched multiple times.
A value of true for eagerPrefix results in using the last match of the prefix, while a value of false results in using the first match of the prefix. Likewise, a value of true for eagerSuffix results in using the last match of the suffix, while a value of false results in using the first match of the suffix.
If you do not specify the <response> tag and specify the <capture> tag, an unbounded capture is performed. For unbounded captures, the underlying interpreter is slowed down so that it waits up to 1 second in between reads on an empty buffer before assuming that no more data is incoming. This is opposed to 10 milliseconds, which is the normal jitter time allowed for non-blocking read attempts. You can also specify a pauseSeconds tag if desired to help on unbounded captures.
A captured property setting remains in effect until its connection closes. Properties named cmd.* (used in the following Response and Error Properties sections) are an exception and are cleared after the current device command execution is completed. Likewise, any property named by using the namespace prefix of a <loop> tag is cleared after that loop terminates. Properties named disc.* are also a special case; such properties are cleared prior to each execution of the discover command (so that they can be rediscovered correctly). These properties are also displayed in the transcript.
Another exception is the fileContents property. The fileContents property gets special handling in the connection R2N and S2N methods. If it is detected in these methods after the device command has been executed, it is interpreted as a terminal capture of the configuration contents rather than a file transfer. The fileContents property is subsequently cleared before these connection methods return.
An append attribute is available on the <capture> tag if you want the captured string to be appended to a potentially existing property. The default behavior otherwise is to replace the value of any existing property of the same name. When appending, you can use an omitEOL attribute to control whether a trailing EOL is added to the captured value when it does not already have one. Making sure the capture always ends in an EOL is necessary for certain prompt capture logic. This check is always made when append is false. When append is true, the check is made by default, unless omitEOL is true.
Capturing in append mode can be used, for instance to construct a configuration file by using the output upon execution of multiple commands within the device. Another way to do this is to use the <deviceCommand> tag to capture the attribute. This attribute allows you to capture the output from the entire sequence of interactions within a device command and store it to a property, (presumably named fileContents).
If you capture a device's prompt during the login sequence, you might need to recapture it at the end of the Deploy to Active command in case the prompt dynamically changed during the Deploy to Active operation.
A failsafe attribute is available for use when there are multiple <capture> tags within a given interaction. When failsafe is true, the <capture> tag is only used if the preceding <capture> tag failed. Otherwise, it defaults to false.
Property capture—complex
More complex forms of property capture allow you to perform regular expression based matching within the normal capture boundaries to copy various substring snippets into regular expression buffers, which can then be assigned to one or more named properties.
The following example shows a device command containing an interaction with a complex property capture:
<interaction>
<prompt>text_A</prompt>
<command>text_B</command>
<response>text_D</response>
<capture prefix=text_C suffix=text_D buffer="X(.*)Y" ignoreFailure="true" defValue="unknown">
<property name="property_0">{0}</property>
<property name="property_1">{1}</property>
</capture>
</interaction>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<prompt> | receive until text_A found in buffer |
<command> | clear buffer, send text_B |
<response> | receive until text_D found in buffer |
<capture> | if buffer contains text_C.*text_D then if buffer between text_C and text_D contains X.*Y snippet then copy all bytes in snippet to property_0 property copy first grouped bytes in snippet to property_1 property else set property_0 to unknown set property_1 to unknown else throw exception |
The ignoreFailure and defValue attributes are optional. If ignoreFailure is used but defValue is not, the properties are left unset in the preceding example. If defValue is used, ignoreFailure must also be used.
Property capture—multiple values
If the multipleValues capture attribute is set to true, a special “multiple values” style of capture is performed.
The following example shows a multiple-value property capture:
<property name="arrayA">{1}</property>
</capture>
If the receive buffer contained the text “XAAAY XBBBY”, the capture would populate the properties { "arrayA.0"="AAA", "arrayA.1"="BBB" }. The regex pattern “X(.*)Y” is applied as many times as possible to the receive buffer when multipleValues is true, causing a sequence of “arrayA.#” properties to be populated. If it had not been matched successfully at least once, an exception would have been thrown.
Property capture—multiple passes
If the iterVariables and iterArrays capture attributes are set, a special “multiple passes” style of capture is performed.
The following example shows a multiple passes property capture:
iterVariables="varA,varB", iterArrays="arrayA,arrayB">
<property name="property_1">{1}</property>
</capture>
If the connection properties contains the entries { "arrayA.0”=”A0”, “arrayA.1=”A1”, “arrayA.2”=”A2”, “arrayB.0”=”B0”, “arrayB.1”=”B1”, “arrayB.2”=”B2” }, and the receive buffer contains the text “XXX A1 YYY B1 ZZZ”, this capture results in “YYY” being assigned to the “property_1” property.
The capture logic in this example makes two passes over the receive buffer. In the first pass, the values from the “%arrayA.0%” and “%arrayB.0%” properties (“A0” and “B0” respectively) are substituted into the “%capture.varA%” and “%capture.varB%” keywords, causing the capture pattern to be “XXX A0 (.*) B0ZZZ” during the first pass.
Because that pattern does not match the receive buffer, you make a second pass. This time the values from the “%arrayA.1%” and “%arrayB.1%” properties (“A1”and “B0” respectively) are substituted into the “%capture.varA%” and “%capture.varB%” keywords, causing the capture pattern to be “XXX A1 (.*) B1ZZZ” during the second pass.
Because that pattern does match the receive buffer, the capture succeeds (capturing the value “YYY”) and you do not attempt any more passes. If the capture does not succeed and you have exhausted the arrays of property values to try, an exception is generated.
The number of comma delimited labels in the iterVariables and iterArrays attributes must be the same in order for this logic to work. The first variable in iterVariables is populated by using values from the first array in iterArrays, while the second variable is populated by using values from the second array, and so on. Also, the length of each property array specified in the iterArrays attribute must be the same.
Property capture—discovery
When you execute the discover command after logging on, you attempt to capture an entire set of values within the device that are dependent on its internal state. By convention, you name these as “disc.*” properties.
Discovery properties
Property | Description |
---|---|
disc.imageName | name for OsImage object created for device |
disc.imageFilename | name of image file within device |
disc.imageFilesystem | filesystem holding image file within device |
disc.imageFileSize | size of the current running image on the device |
disc.imageFilesystemFreeSize | size of free image filesystem within dev |
disc.imageFilesystemFreeSizeUnits | units of image free filesystem size value |
disc.imageFilesystemTotalSize | size of total image filesystem within dev |
disc.imageFilesystemTotalSizeUnits | units of image total filesystem size value |
disc.imageFilesystemUsedSize | size of free image filesystem within dev |
disc.imageFilesystemUsedSizeUnits | units of image free filesystem size value |
disc.memoryTotalSize | size of total RAM memory within device |
disc.memoryTotalSizeUnits | units of size of total RAM memory in device |
disc.model | hardware model of device |
disc.securityContextName | for a multi-context device, the name of the security context you have logged in to |
disc.securityContextType | for a multi-context device, what type of security context you have logged in to (will be one of admin, system, or userDefined) |
disc.supportsFtp | flags if the device supports ftp |
disc.supportsScp | flags if the device supports scp |
disc.startupFilename | name of startup configuration file within device |
disc.startupFilesystem | filesystem holding startup configuration in device |
disc.startupMode | startup mode in device (CatOS: text/binary) |
disc.startupTextMode | startup text mode (CatOS: flash/nvram) |
disc.targetImageFileSize | target image file size |
disc.targetImageFilesystemFreeSize | target image filesystem free size |
disc.targetImageFilesystemTotalSize | target image filesystem total size |
disc.targetImageFilesystemUsedSize | target image filesystem used size |
disc.version | major.minor[.build] os version in device |
disc.versionBuild | os version build nr within device |
disc.versionShort | os version major.minor string within device |
disc.versionMajor | os version major nr within device |
disc.versionMinor | os version minor nr within device |
If any of the preceding quantities are unknown for a given device type, those properties are left unassigned. The exception is disc.startupMode, which defaults to “binary” for CatOS devices for which it could not be determined.
The preceding image filename/filesystem and memory related properties are captured only for device types that support OS image save/load operations.
Property assignment
<assign> tags are used to set a connection property value directly rather than via capturing text in the device response stream. The value assigned is either specified explicitly, or specified as a BeanShell script (see www.beanshell.org) which are evaluated at runtime.
The following example of an explicit assignment assigns the string “value_1” to the connection property “property_1.” You can embed a reference to another property in the value attribute if desired (for example, value=”%property_2%”):
The following example shows a script-based assignment:
import foo.Bar;
String string_1 = Bar.transmogrify("%property_2%");
String value = string_1 + "%property_3%";
</assign>
This script concatenates a transmogrified property_2 value with property_3 and stores the result in a special local variable named value, which is used to assign property_1. You must set a String variable called value to hold the result of your assignment calculations. The contents of value finally becomes the property value.
The code within the assign container in this example is a Java snippet. Any datatype supported by Java is supported in the snippet. These datatypes include the Java primitive datatypes (such as int and float), arrays, and classes defined in the Java JDK (such as String.) Because it is a Java snippet, you can define or import any data type that you need in the snippet.
The <assign> tag supports two optional Boolean attributes, append and omitEOL. When append is set true (defaults to false), the string value assigned to the property in question is appended to any existing string value. By default, a newline character is added before appending to the existing value, unless omitEOL is true (defaults to false).
Conditions
Device commands can contain not only simple sequences of interactions, but also conditions and loops.
A condition can be used to specify a block of interactions that should only be executed if the condition's test expression evaluates to true. It can also contain other nested device conditions or loops.
The following example shows a device command containing a condition:
<condition test = "-EXISTS- property_1">
<interaction>
<prompt>text_A</prompt>
<command>text_B</command>
<response>text_C</response>
</interaction>
</condition>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<condition> | if property property_1 is set then prompt: receive until text_A found in buffer |
<command> | clear buffer, send text_B |
<response> | receive until text_C found in buffer |
The test expression is parsed and evaluated against the current set of connection properties in effect. Boolean and string comparison operators and arithmetic functions are supported.
The following table lists the operators that BMC Network Automation recognizes in conditional expressions. The expression is true if the condition is met, false otherwise.
Condition expression operator
Operator | Description |
---|---|
-CONTAINS- | Tests whether the string before the operator is contained within the string following the operator. |
-EXISTS- | The object following the operator exists |
-EQ- | The objects have equal values. |
-GT- | Greater than |
-GE- | Greater than or equal to |
-LT- | Less than |
-LE- | Less than or equal to |
-NOT- | The logical condition following the operator is false. |
-AND- | Logical AND of the two boolean conditions |
-OR- | Logical OR (either or both conditions are true) |
-XOR- | Logical exclusive OR (one condition is true, but not both) |
The order of precedence must be determined by using parentheses, as shown in the following example:
"-NOT- (-EXISTS- property_1)""(%property_1% -EQ- value_1) -OR- (%property_1% -GT- value_1)"
When string inequality comparisons are evaluated, if both values involved start with numeric digits, the algorithm attempts to perform a numeric rather than a string-based comparison. Numeric comparisons can have embedded decimals, so, for example, “1.1.10 -GT- 1.1.9" evaluates to true.
Typing is implicit. It cannot be declared explicitly.
Any grammar violations present in your condition tests cause loading of the DeviceTypeMap XML file to fail when the system first starts up.
Response properties
The <response> elements can include a property attribute. When multiple <response> elements are present, the property of the response that is matched is set to true. This allows you to handle devices, which can respond in multiple ways via logical branching in XML.
The following example shows a device command containing an interaction with response properties:
<interaction>
<prompt>text_A</prompt>
<command>text_B</command>
<response property=cmd.property_1>text_C</response>
<response property=cmd.property_2>text_D</response>
</interaction>
<condition test="-EXISTS- cmd.property_1">
<interaction>
<prompt>text_C</prompt>
<command>text_E</command>
<response>text_F</response>
</interaction>
</condition>
<condition test="-EXISTS- cmd.property_2">
<interaction>
<prompt>text_D</prompt>
<command>text_G</command>
<response>text_H</response>
</interaction>
</condition>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<prompt> | receive until text_A found in buffer |
<command> | clear buffer, send text_B |
<response> | receive until text_C or text_D found in buffer if buffer contains text_C then set cmd.property_1 to true else set cmd.property_2 to true |
<condition> | if cmd.property_1 property set then |
<prompt> | receive until text_C found in buffer |
<command> | clear buffer, send text_E |
<response> | receive until text_F found in buffer |
<condition> | if cmd.property_2 property set then |
<prompt> | receive until text_D found in buffer |
<command> | clear buffer, send text_G |
<response> | receive until text_H found in buffer |
Error properties
The <error> elements can also include a property attribute. This element is used as a mechanism to allow handling for errors which are logically recoverable. If the error element is matched, instead of aborting execution via an exception, a property is set, which can be handled in the subsequent device interactions.
The following example shows a device command containing an interaction with error properties:
<interaction>
<prompt>text_A</prompt>
<command>text_B</command>
<response property=cmd.property_1>text_C</response>
<error property=cmd.property_2>text_D</error>
<capture>fileContents</capture>
</interaction>
<condition test="-EXISTS- cmd.property_1">
<interaction>
<prompt>text_B</prompt>
<command>text_E</command>
<response>text_F</response>
</interaction>
</condition>
<condition test="-EXISTS- cmd.property_2">
<interaction>
<prompt>text_C</prompt>
<command>text_G</command>
<response>text_H</response>
</interaction>
</condition>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<prompt> | receive until text_A found in buffer |
<command> | clear buffer, send text_B |
<response> | receive until text_C or text_D found in buffer if buffer contains text_C then set cmd.property_1 to true else set cmd.property_2 to true |
<condition> | if cmd.property_1 property set then |
<prompt> | receive until text_C found in buffer |
<command> | clear buffer, send text_E |
<response> | receive until text_F found in buffer |
<condition> | if cmd.property_2 property set then |
<prompt> | receive until text_D found in buffer |
<command> | clear buffer, send text_G |
<response> | receive until text_H found in buffer |
When such a recoverable error occurs, any <capture> tag that is specified is skipped. This capture skipping is the only justification for supporting error properties separately from response properties.
Retry
The <error> elements can also include a retry flag (defaults to false). This flag is used as a mechanism to allow retrying (once) the execution of the enclosing device command if a trivial and potentially recoverable error has occurred (concurrency collision with a 3rd party user of the device for instance). A retry attribute causes the command to be retried once again if it initially times out.
The following example shows a device command containing an interaction with the retry attribute:
<interaction>
<prompt>text_A</prompt>
<command>text_B</command>
<response>text_C</response>
<error retry=true>text_D</error>
</interaction>
<interaction>
<prompt>text_C</prompt>
<command>text_D</command>
<response>text_E</response>
</interaction>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<prompt> | receive until text_A found in buffer |
<command> | clear buffer, send text_B |
<response> | receive until text_C or text_D found in buffer if buffer contains text_D then if first execution attempt then relog in and reexecute command else throw exception |
<prompt> | receive until text_C found in buffer |
<command> | clear buffer, send text_D |
<response> | receive until text_E found in buffer |
Disconnect
An interaction can include a disconnect attribute. The attribute can have a value of always, sometimes, or never (default). If there is a chance of the device disconnecting after the command is sent, such an interaction sets this attribute. For the logout and reboot commands, this is always the case. For some devices, merging or restoring a configuration causes the device to reboot as a side effect as well.
The following example shows a device command containing an interaction with the disconnect attribute:
<interaction disconnect=always>
<prompt>text_A</prompt>
<command>text_B</command>
<error>text_C</error>
</interaction>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<prompt> | receive until text_A found in buffer |
<command> | clear buffer, send text_B |
<response> | receive until text_C found in buffer if buffer contains text_C then throw exception close connection if still open log in again if needed |
Explicitly declaring when a disconnection is expected is only necessary because some devices do not close their sockets when they logically disconnect. When the disconnect value is always or sometimes, the connection always times out waiting for the response of the interaction within 15 seconds if necessary, to avoid a potentially hung socket read.
If the disconnect value is sometimes, enforcement of this timeout is taken as an indication that a logical disconnect occurred; otherwise, you assume that the connection is active.
If a disconnection has occurred, you close the socket and relog into the device if the relogin flag has been specified. The relogin flag is specified as true in the context of the N2R, N2S, R2S, and reboot connection methods; otherwise, it is false.
Loops
A <loop> contains other device interactions, and other nested loops or conditions. These loops can be either in the style of a for loop, a while loop, a do loop, or a foreach loop.
The following example shows a device command with 'for' loop:
<loop counter="i" start="1" stop="2">
<interaction>
<prompt>text_A</prompt>
<command>%loop.i%</command>
<response>text_B</response>
</interaction>
</loop>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<loop> | for (loop.i = 1, loop.i <= 2, loop.i++) do |
<prompt> | receive until text_A found in buffer |
<command> | clear buffer, send loop.i |
<response> | receive until text_B found in buffer |
The iteration counter property “i” is automatically prefixed as “loop.i” when it is used. This is the default prefix. You can specify a non-default prefix via the namespace attribute. Properties of the form namespace.* are automatically removed after the loop terminates.
The following example shows a device command with 'while' loop:
<loop condition="-NOT- (-EXISTS- loop.property_1)">
<interaction>
<prompt>text_A</prompt>
<command>text_B</command>
<response>text_C</response>
<response property=loop.property_1>text_D</response>
</interaction>
</loop>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<loop> | while loop.property_1 not set do |
<prompt> | receive until text_A found in buffer |
<command> | clear buffer, send text_B |
<response> | receive until text_C or text_D found in buffer if buffer contains text_D then set loop.property_1 to true |
The following example shows a device command with 'do' loop:
<loop condition="-NOT- (-EXISTS- loop.property_1)">
<interaction>
<prompt>text_A</prompt>
<command>text_B</command>
<response>text_C</response>
<response property=loop.property_1>text_D</response>
</interaction>
<break condition="-EXISTS- loop.property_1"/>
</loop>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<loop> | do |
<prompt> | receive until text_A found in buffer |
<command> | clear buffer, send text_B |
<response> | receive until text_C or text_D found in buffer if buffer contains text_D then set loop.property_1 to true |
<break> | if loop.property_1 property set then terminate loop |
You use a <break> tag to allow the loop to terminate after the text_D response is found.
The following example shows a device command with 'foreach' loop:
<loop variable="entry" input="list">
<interaction>
<prompt>text_A</prompt>
<command>%loop.entry%</command>
<response>text_B</response>
</interaction>
</loop>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<loop> | foreach loop.entry in list.0 list.1 list.2 … |
<prompt> | receive until text_A found in buffer |
<command> | clear buffer, send %loop.entry% |
<response> | receive until text_B |
It is assumed that the properties list.0, list.1, list.2, and so on are already populated. On each iteration, the loop.entry property is assigned the value of the list.n property, where n is the loop iteration number starting from 0.
This 'foreach' style of loop is used during tunneled file transfers, to transfer a configuration file by sending it line by line to the device.
Assertions
An <assert> tag can be inserted anywhere in an interaction. If the conditional expression of the assertion evaluates to false, an exception is generated out of the device's command execution.
An onFailure attribute can be used to specify skip, warning, or abort, to control the type of exception thrown, and the type of handling performed.
A skip causes the device action to be marked as skipped in the results. A warning causes the action to be marked as succeeded with warning. An abort causes the action to be marked as failed. The onFailure condition shows in the job status as well.
The following example shows a device command with the assert condition:
<assert condition="%property_1% -EQ- value_1" onFailure="skip">
message
</assert>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<assert> | if property_1 property equals value_1 then throw skip exception containing message |
The minVersion attribute available in the <deviceCommand> tag functions the same way as an assertion, which tests the discovered version against the specified minimum version and throws a skip exception on failures. It is simply a convenient shorthand for a common type of assertion logic.
Regular expression support
Device interactions can also include regular expressions in the <prompt>, <response> and <error> elements. These regular expressions are useful when you are not sure of the exact response from the device. In the <interaction> tag, you must set regex to true to use this feature.
The following example shows a device command containing an interaction with a regular expression:
<interaction regex="true">
<prompt>A.*B</prompt>
<command>text_X</command>
<response>C.*D</response>
<error>E.*F</error>
</interaction>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<prompt> | receive until regex A.*B is matched in the buffer |
<command> | clear buffer, send text_X |
<response> | receive until regex C.*D or E.*F matched in the buffer if regex E.*F is matched then throw exception |
Jitter time
Jitter time controls how long the interpreter lingers while gathering bytes from the device before it checks whether what it has received so far matches the prompt or response string it is currently expecting. In some scenarios, the default jitter time of 10 milliseconds might be unsatisfactory. When the expected string is loosely specified (for example, a “.+” regular expression pattern), it might be problematic if the interpreter tries to match the expected string before the device has completely finished sending all the bytes involved. Specifying the expected string loosely is generally not advisable for this reason, but sometimes due to the complexities of the device, it might be unavoidable.
To work around this problem, you can temporarily establish a non-default jitter time. The <prompt> tag supports a jitterMilliSeconds attribute, which sets the interpreter jitter time to the specified value while it is matching that particular prompt, after which it is reset to the default value. The <interaction> tag also supports a responseJitterMilliSeconds attribute, which sets the interpreter jitter time to the specified value while it is matching that interaction’s responses/errors, after which it is reset to the default value.
Sensitive commands
The <command> tag supports a sensitive flag. If set to true, any error, exception, or debug trace generated while executing the interaction replaces the command text with “{HIDDEN}”. This is typically used on interactions that send passwords to the device. This flag is available with the <get> and <post> tags for HTTP interactions.
The following example shows an interaction with the sensitive flag:
<prompt>%prompt%</prompt>
<command sensitive="true">%privPassword%</command>
<response>#</response>
</interaction>
You can hide part of a line by using the sensitive attribute in conjunction with the sensitivePhrase attribute. In the following example, only the %ftpPassword% part of the command is replaced with {HIDDEN} in the transcript output, the rest of the command is displayed as clear text.
<prompt>%prompt%</prompt>
<command sensitive="true" sensitivePhrase="%ftpPassword%"
copy running-config ftp://%ftpUsername%:%ftpPassword%@%address%
</command>
<response>>%prompt%</response>
</interaction>
Finally Block
You can add an optional <finallyBlock> tag at the bottom of the <deviceCommand> tag to encapsulate the logic that you want to be executed after all the normal logic within the device command is executed. The <finallyBlock> logic is executed regardless of whether the normal logic executed successfully or unsuccessfully.
The following example shows a device command containing the <finallyBlock> tag:
<interaction>
<prompt>text_A</prompt>
<command>text_B</command>
<response>text_C</response>
</interaction>
<finallyBlock>
<interaction>
<command>text_D</command>
</interaction>
<finallyBlock>
</deviceCommand>
The preceding example causes BMC Network Automation to execute the following logic:
Tag | Execution order |
---|---|
<prompt> | receive until text_A found in buffer or interaction times out if interaction timed out then throw exception. |
<command> | clear buffer, send text_B |
<response> | receive until text_C found in buffer or interaction times out if interaction timed out then throw exception. |
<finally> | catch any exception that was thrown |
<command> | clear buffer, send text_D if exception was caught, rethrow it. |
In this sequence, the final interaction to send text_D is guaranteed to execute last, regardless of whether the preceding interaction succeeded or timed out.
Sleep
You can insert a <sleep> tag anywhere within an interaction. The timeSeconds attribute specifies the duration of the sleep period, in seconds. This mechanism is helpful within a loop where polling the device for the transition to some expected state.
The following example inserts a sleep period of five seconds:
<sleep timeSeconds="5">
</deviceCommand>