Documentation forNetwork Configuration Manager

Commands for NCM config change templates

There are two commands in a config change template:

  • script:  Defines the input type for each variable defined by the template parameters.

  • CLI: Includes the arguments and logical operations needed to produce a set of CLI commands and execute those commands against each NCM node targeted for a specific config change.

Script Command

The script{} command declares the input type for every variable defined by the template parameters. The form of the script command is:

script script_name (
	data_type @variable
       data_type @variable
       data_type @variable	)

The data_type can be int (integer), string, or swis.entity where swis.entity is a SolarWinds Information Service (SWIS) entity (for example, NCM.Nodes). For descriptions of available entities, see SWIS entities used in config change templates.

Cisco Example

script ConfigureVLANmembershipCiscoIOS (
	NCM.Nodes @ContextNode,
	NCM.Interfaces[] @TargetPorts,
	NCM.VLANs[] @VlansToRemove,
	NCM.VLANs[] @VlanToAssign	)

In this example, the four variables that were introduced in the parameter section of the template with an instance of PARAMETER_LABEL are each given a specific SolarWinds Information Service entity data type:

  • @ContextNode is determined with data from the NCM.Nodes entity in the database.
  • @TargetPorts is determined with data from the NCM.Interfaces entity.
  • @VlansToRemove and @VlansToAssign are determined with data from the NCM.VLANs entity.

Any variable that references an NCM object that NCM knows through device inventory must take a SolarWinds Information Service entity as its data type. In this case, the four variables work with data that NCM captured and stored in the database through the device inventory process. If you attempt to assign a string instead of a SWIS entity in such cases, NCM fails to correctly parse your script.

CLI command

CLI{} defines a specific CLI command that NCM issues on a target device when the config change template is executed. Its purpose is to create a command line statement that NCM can execute directly on the command line of NCM nodes targeted for the template's config changes.

The config change template creator creates a CLI command by including its arguments wrapped by curly brackets { }. At run time, NCM parses any variables contained within CLI{}. Often a CLI command is as simple as the command you would type directly on the command line of an NCM device.

Cisco Example

To enter config mode on Cisco IOS devices, type configure terminal. In your config change template script, add the command as follows:

CLI
{
 configure terminal
}

NCM parses the argument of the CLI{} command by passing through the string itself (configure terminal) as a command to execute against each targeted NCM node at template run time:

Cisco Example with Variables

script ConfigureVLANmembershipCiscoIOS (
	NCM.Nodes @ContextNode,
	NCM.Interfaces[] @TargetPorts,
	NCM.VLANs[] @VlansToRemove,
	NCM.VLANs[] @VlanToAssign	)
{
	CLI
	{
	 vlan database vlan @vlaniddescription @vlandesc exit
	}
}

This example shows a CLI statement with variables to specify VLAN properties while using the vlan database command line editor. For purposes of demonstration, we assume that:

  • @vlanid = 1
  • @vlandesc = Local-Office

At run time, NCM parses the CLI{ } command as:

vlan database vlan 1 description Local-Office exit

If this were all that is included in the Change VLAN Membership on Ports Cisco IOS template, then the config change result would be to set the description of vlan 1 to Local-Office on all NCM nodes selected as targets.

This config change template, however, actually changes the VLANs associated with targeted NCM node ports. For that we need to introduce advanced CLI{} command logic.

Advanced CLI command logic

The scripting framework for change config templates allows you to create CLI{} command arguments that include foreach loops, if/else conditional operations, and functions for manipulating string patterns.

Foreach Loops

A foreach statement iterates through an array of items based on a SWIS entity data type. Foreach statements use the following pattern:

foreach (@ItemVaraible in @EntityArrayVariable)

A primary purpose of a foreach loop is to allow the template user to select multiple NCM objects for config change. The loop instructs NCM to perform the same config change on all items in scope as determined by the SWIS entity in the database and delimited at run time by the template user's selections in the template wizard.

Cisco Example

foreach (@portItem in @TargetPorts)
{
	CLI
	{
	  interface @portItem.InterfaceDescription
	}

The foreach statement creates a set that contains two related variables: @portItem and @TargetPorts.

The @TargetPorts variable holds an array of objects with the data type of an SWIS entity called NCM.Interfaces[ ]. The array will be a set of interfaces on NCM nodes.

The @TargetPorts variable is associated with the PARAMETER_LABELSelect port(s) and the template user selects one or more ports at run time. The template user determines the set of interfaces to fill the array NCM.Interfaces[ ], and the template will perform VLAN membership config changes on each interface in that array.

@portItem is a dynamic variable that the loop uses during its iterating to hold the value of the current interface from the array represented by @TargetPorts.

The foreach loop format is fixed and NCM expects it to include the dynamic variable.

The user interacts with this template wizard screen:

Click Select Interfaces List to load a tree that displays available interfaces and NCM nodes previously selected in the wizard.

Conditional Statements

Conditional logic in a config change template script uses an if/else pattern to define two branches of possible action, enclosing specific conditions within parentheses. Within each branch of the conditional pattern are CLI{} commands to execute if that branch meets the specific conditions.

Here is the basic structure:

if (condition is true)
CLI
{
 execute commands
}
else
CLI
{
 Execute other commands
}

The else section is optional. If you omit it, and the if condition is false, NCM excludes the relevant CLI{} commands from the template output.

Operators

Use any of the following operators to specify a parenthetical condition. Use single quotes around string values.

Operator Condition
== Is Equal To
> Is Greater Than
>= Is Greater Than or Equal To
< Is Less Than
<= Is Less Than or Equal To
!= Is Not Equal To
Contains 'string'
containsExact 'case sensitive string'
startsWith 'string'
startsWithExact 'case sensitive string'
endsWith 'string'
endsWithExact 'case sensitive string'

Cisco Example

Add conditional logic in the foreach loop to prevent errors that may occur if the user accidentally selects an incorrect interface (for example, the loopback address).

foreach @portItem in @TargetPorts)
{
	if (@PortItem.InterfaceDescription != 'Loop0')
	{
  	 CLI
  	 {
  	  interface @portItem.InterfaceDescription
  	 }

If the template encounters the loopback interface, it does nothing and passes on to the next interface. This code prevents damage from template user error.

Manipulating Strings

Five functions for manipulating strings are a scripting resource that you can use (for example) to manage ACL config changes for network firewalls, in which a config change template needs to iterate through a predictably variable set of IP addresses.

Function Description Declaration Variable Definitions
Substring Specify a starting point within a string and the length from the starting point that you want to capture for manipulation. string Substring(string str, int startIndex, int length)
  • str is the full string from which the substring comes
  • startIndex marks the position where the substring begins
  • length is the number of characters that the substring includes
StrLength Return the length of a string. In StrLength(string str)
  • str is the user-input string whose length is used as the integer value
IndexOf Find the number of characters in a string. int IndexOf(string str, string search)
  • str is a string to search on
  • search is a user-input string NCM uses to find the numerical value of the string being searched
SetOctet Replace an octet within an IP address. string SetOctet(string ipAddr, int octetPosition, string octet)
  • ipAddr is the IP address
  • octetPostion marks the position where the target octet begins
  • octet is the new value of the target octet
GetOctet Retrieve an octet from a user-specified IP address and octet position. string GetOctet(string ipAddress, int octetPosition)
  • ipAddress is a user-input IP address
  • octetPosition is the user-input value for the place where the function finds the beginning of the octet to get

Example 1: Manipulating a String

script IPshuffle(string @str, string @search )
{
	int @length = strlength(@str)
	int @startIndex = indexof(@str,@search)
	int @substringLength = @length - @startIndexstring
	@res = substring(@strA, @startIndex, @substringLength)

	CLI
	{
	 @res
	}
}		

The user enters ABCDEF for the @str variable and CD for the @search variable in the template's wizard. Based on those values, the script does the following:

  1. Uses ABCDEF in the strlength function to give a value of 6 to a variable called @length.
  2. Uses CD as the substring of ABCDEF to set a value 2 for the variable called @startIndex.
  3. Subtracts 2 (@startIndex) from 6 (@length) to determine the value of @substringLength as 4.
  4. Takes the original string ABCDEF and calculates a result (@res) using @startIndex to count in two positions and @substringlength to count four positions from the start index.
  5. Outputs CDEF as the result.

Example 2: Changing an Access Control List

This example creates a block of Access Control List (ACL) instructions that predictably vary the value of a specific octet within an IP address. The instructions conform to the pattern 10.10.@id.10, where the value of @id is determined by user input.

The user enters 10.10.10.10 as the value of @ipaddress in the config change template's run-time wizard. The user enters 1, 22, and 222 for the @indexes variable declared in the script command.

.PARAMETER_LABEL @ipaddress
	IP address     
.PARAMETER_DESCRIPTION @ipaddress
	Enter an IP address

.PARAMETER_LABEL @indexes
	Octets
.PARAMETER_DESCRIPTION @Indexes
	Enter a pattern of octet replacements.
	Separate numbers with a comma.
*/

script ACLChanges(string @ipaddress, int[] @indexes)
{
	string @ipnew

	foreach(@id in @indexes)
	{
		@ipnew = setoctet(@ipaddress,3,@id)
		CLI
		{
     		Allow @ipnew out
		Allow @ipnew UDP 2055 OUT
		}
	}
}		

The script uses the SetOctet function to determine the value of an @ipnew variable. SetOctet is defined to take the user-input IP address and create a new IP address by iteratively replacing the third octet with user-input values. For each new IP address, the script produces a command to create outgoing UDP transmission access through port 2055:

  • Allow 10.10.1.10 outAllow 10.10.1.10 UDP 2055 OUT
  • Allow 10.10.22.10 outAllow 10.10.22.10 UDP 2055 OUT
  • Allow 10.10.222.10 outAllow 10.10.222.10 UDP 2055 OUT

Example 3: Managing an Access Control List for Multiple Routers

In this example, a config change template generates a block of ACL instructions for a router in a store. We create an ACL block of instructions for this device that varies based on a portion of the device's IP address.

If the store has four routers, 10.1.1.1, 10.1.4.1, 10.1.6.1, and 10.1.10.1, the template script generates an ACL block that appears this way on the selected router (10.1.1.1):

Allow 10.1.2.0/24 out

Allow 10.1.2.4 UDP 2055 OUT

Allow 10.1.4.0/24 out

Allow 10.1.4.4 UDP 2055 OUT

Allow 10.1.6.0/24 out

Allow 10.1.6.4 UDP 2055 OUT

Allow 10.1.10.0/24 out

Allow 10.1.10.4 UDP 2055 OUT

Here is the script that produces the output:

script OpenACLs(NCM.Nodes @ContextNode, string[] @IpRouters)
{
	foreach(@ipRouter in @ipRouters)    
	{ 
		string @octet = getoctet(@IpRouter,3)
		string @ipnew = setoctet(@ContextNode, 3,@octet)
		CLI
		{
		  Allow @ipnew out
		  Allow @ipnew UDP 2055 OUT
		}
	}	

This script does the following:

  • Uses a foreach loop to go through a user-input series of router IP addresses.
  • Uses the GetOctet function to focus the third octet of the current router IP address.
  • Uses the SetOctet function to create a new IP address as a value for @ipnew.
  • Creates a CLI { } command that will execute Allow operations for each of the selected routers.

The result is a set of Allow commands that open access in the ACL so that the router 10.1.1.1 can send OUT traffic via UDP on port 2055 to 10.1.4.1, 10.1.6.1, and 10.1.10.1.

Here are the parameters for this config change template. The template user selects the router on which to make ACL changes and inputs the target router IP address through this template:

.PARAMETER_LABEL @ACLRouter
	Router for ACL Change     
.PARAMETER_DESCRIPTION @ACLRouters
	Select a Router
.PARAMETER_LABEL @ipRouters
	Target Routers     
.PARAMETER_DESCRIPTION @ipRouters
	Add Routers to Target with ACL Allowances	

Tips

Including special symbols in CLI commands

If you need to include a special symbol, such as a pipe, in a CLI command, you cannot do it directly. For example, the following would break the script:

show clock | append disk0:show_tech

Instead, define a string variable with the symbol as its value, and then place the variable in the command:

script BaseChangeTemplate(NCM.Nodes @ContextNode)
{ 
  string @PipeSymbol='|'
  CLI
  {	
    show clock @PipeSymbol append disk0:show_tech
  }  
}

Including variables in CLI commands

To keep config change templates as device-independent as possible, you can include command variables defined in device templates. You can also include node variables (also called macros) to reference attributes of each node. To include these, define a string variable in the CLI command with the command or node variable as its value.

The following example uses the node variable ${StorageAddress} to reference the IP address of the TFTP server. Because the IP address is not hard-coded in the script, the script does not break if the IP address changes.

script BaseChangeTemplate(NCM.Nodes @ContextNode)
{ 
  string @myTFTPImage='${StorageAddress}' + '/image.bin'
  CLI
  {
    copy tftp://@myTFTPImage flash
    ...
  }
}

The resulting script is:

copy tftp://${StorageAddress}/image.bin flash