Supported Platforms
Related Documentation
- ACX, EX, M, MX, SRX, T Series
- get-hello() Function (jcs Namespace)
- get-protocol() Function (jcs Namespace)
- ACX, EX, M, MX, PTX, SRX, T Series
- open() Function (jcs Namespace)
Specifying the Session Protocol for Connections Using Junos Automation Scripts
Session Protocol in Junos Automation Scripts Overview
The Junos XML management protocol is a Juniper Networks proprietary protocol used to request information from and configure devices running Junos OS. The NETCONF XML management protocol is a standard used to request and change configuration information on a routing, switching, or security device. The NETCONF protocol is defined in RFC 4741, NETCONF Configuration Protocol, which is available at http://www.ietf.org/rfc/rfc4741.txt .
Starting with Junos OS Release 11.4, the jcs:open() function includes the option to create a session either with the Junos XML protocol server on devices running Junos OS or with the NETCONF server on devices where NETCONF service over SSH is enabled. Previously, the function supported only sessions with the Junos XML protocol server on devices running Junos OS. The additional support for NETCONF sessions permits automation scripts to configure and manage devices in a multi-vendor environment.
The jcs:open() function supports the following session protocol types:
- junoscript—Session with the Junos XML protocol server on a routing, switching, or security device running Junos OS. This session type supports the operations defined in the Junos XML protocol and the Junos XML API, which are used to configure devices running Junos OS or to request information about the device configuration or operation. This is the default session type.
- netconf—Session with the NETCONF XML protocol server on a routing, switching, or security device over an SSHv2 connection. The device to which the connection is made must be enabled for NETCONF service over SSH. NETCONF over SSH is described in RFC 4742, Using the NETCONF Configuration Protocol over Secure SHell (SSH), which is available at http://www.ietf.org/rfc/rfc4742.txt .
- junos-netconf—Proprietary session with the NETCONF XML protocol server over an SSHv2 connection on a routing, switching, or security device running Junos OS.
The NETCONF server on a device running Junos OS has the additional capabilities defined in http://xml.juniper.net/netconf/junos/1.0 . The NETCONF server on these devices supports NETCONF XML protocol operations, most Junos XML protocol operations, and the tag elements defined in the Junos XML API. For netconf and junos-netconf sessions with devices running Junos OS, you should use only native NETCONF XML protocol operations and the extensions available in the Junos XML protocol for configuration functions as documented in the NETCONF XML Management Protocol Guide.
The syntax for the jcs:open() function when specifying a session protocol is:
SLAX Syntax
var $connection = jcs:open(remote-hostname, session-options);
XSLT Syntax
<xsl:variable name="connection" select="jcs:open(remote-hostname, session-options)"/>
The session-options parameter is an XML node-set that specifies the session type and connection parameters. The session type is one of three values: junoscript, netconf, or junos-netconf. If you do not specify a session type, the default is junoscript, which opens a session with the Junos XML protocol server only on devices running Junos OS. The format of the node-set is:
var $session-options := { <method> ("junoscript" | "netconf" | "junos-netconf"); <username> "username"; <passphrase> "passphrase"; <password> "password"; <port> "port-number"; <instance> "routing-instance-name"; <routing-instance> "routing-instance-name"; }
If you do not specify a username and it is required for the connection, the script uses the local name of the user executing the script. The <passphrase> and <password> elements serve the same purpose. If you do not specify a passphrase or password element and it is required for authentication, you should be prompted for one during script execution by the device to which you are connecting.
Optionally, you can specify the server port number for netconf and junos-netconf sessions. The default NETCONF server port number is 830. If you do not specify a port number for a netconf or junos-netconf session, jcs:open() connects to the NETCONF server using port 830. However, if you specify a port number, jcs:open() connects to the given port instead. Specifying a port number has no impact on junoscript sessions, which are always established over SSH port 22.
To redirect the SSH connection to originate from within a specific routing instance, include the instance or routing-instance element and the routing instance name. The routing instance must be configured at the [edit routing-instances] hierarchy level. The remote device must be reachable either using the routing table for that routing instance or from one of the interfaces configured under that routing instance. The instance and routing-instance elements serve the same purpose.
To verify the protocol for a specific connection, call the jcs:get-protocol(connection) extension function and pass the connection handle as the argument. The function returns “junoscript”, “netconf”, or “junos-netconf”, depending on the session type.
During session establishment with a NETCONF server, the client application and NETCONF server each emit a <hello> tag element to specify which operations, or capabilities, they support from among those defined in the NETCONF specification or published as proprietary extensions. In netconf and junos-netconf sessions, you can retrieve the session capabilities of the NETCONF server by calling the jcs:get-hello(connection) extension function.
For example, the NETCONF server on a typical device running Junos OS might return the following capabilities:
<hello> <capabilities> <capability>urn:ietf:params:xml:ns:netconf:base:1.0</capability> <capability> urn:ietf:params:xml:ns:netconf:capability:candidate:1.0 </capability> <capability> urn:ietf:params:xml:ns:netconf:capability:confirmed-commit:1.0 </capability> <capability> urn:ietf:params:xml:ns:netconf:capability:validate:1.0 </capability> <capability> urn:ietf:params:xml:ns:netconf:capability:url:1.0?protocol=http,ftp,file </capability> <capability>http://xml.juniper.net/netconf/junos/1.0</capability> <capability>http://xml.juniper.net/dmi/system/1.0</capability> </capabilities> <session-id>20826</session-id> </hello>
Example: Specifying the Session Protocol for a Connection Using an Automation Script
The following example demonstrates how to specify the session protocol within a Junos automation script when creating a connection with a remote device. Specifically, the example op script establishes a NETCONF session with a remote device running Junos OS, retrieves and prints the NETCONF server capabilities, and then updates and commits the configuration on that device.
Requirements
- Routing, switching, or security device running Junos OS Release 11.4 or later.
- Client application can log in to the device where the NETCONF server resides.
- NETCONF service over SSH is enabled on the device where the NETCONF server resides.
Overview and Script
Starting with Junos OS Release 11.4, the jcs:open() function includes the option to create a session either with the Junos XML protocol server on devices running Junos OS or with the NETCONF server on devices where NETCONF service over SSH is enabled. In the following example, the script creates a connection and establishes a NETCONF session with a remote device running Junos OS. If the connection and session are successfully established, the script updates the configuration on the remote device to add the ftp statement to the [edit system services] hierarchy level. The script also retrieves and prints the session protocol and the capabilities of the NETCONF server.
The script takes one argument, remote-host, which is the IP address or hostname of the remote device. The arguments variable is declared at the global level of the script so that the argument name and description are visible in the command-line interface (CLI) when a user requires context-sensitive help.
The variable netconf is a node-set that specifies the session protocol and the connection parameters for the remote device. The value of the <method> element is set to “netconf” to establish a session with the NETCONF server over an SSHv2 connection. The <username> element specifies the username for the connection. If you do not specify a username and it is required for the connection, the script uses the local name of the user executing the script. In this example, the passphrase and port are not specified. If a passphrase is required for authentication, the remote device should prompt for one during script execution. The script establishes the session using the default NETCONF port 830.
If the connection and establishment of the NETCONF session are successful, the script executes remote procedure calls (RPCs). The RPCs contain the tag elements <lock>, <edit-config>, <commit>, and <unlock>, which are NETCONF operations to lock, edit, commit, and unlock the candidate configuration. The script stores the RPC for each task in a separate variable. The results for each RPC are also stored separately and parsed for errors. The script only executes each subsequent step if the previous step is successful. For example, if the script cannot lock the configuration, it does not execute the RPCs to edit, commit, or unlock the configuration.
The variable rpc-edit-config contains the tag element <edit-config>, which is a NETCONF operation to modify a configuration. The child element, <config>, includes the modified portion of the configuration that is merged with the candidate configuration on the device. If errors are encountered, the script calls the copy-of statement to copy the result tree fragment variable to the results tree so that the error message prints to the CLI during script execution.
SLAX Syntax
version 1.0; ns junos = "http://xml.juniper.net/junos/*/junos"; ns xnm = "http://xml.juniper.net/xnm/1.1/xnm"; ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0"; ns ext = "http://xmlsoft.org/XSLT/namespace"; var $arguments = { <argument> { <name> "remote-host"; <description> "device hostname or IP address to which to connect"; } } param $remote-host; match / { <op-script-results> { var $netconf := { <method> "netconf"; <username> "bsmith"; } var $rpc-lock-config = { <lock> { <target> { <candidate>; } } } var $rpc-unlock-config = { <unlock> { <target> { <candidate>; } } } var $rpc-commit = { <commit>; } var $rpc-edit-config = { <edit-config> { <target> { <candidate>; } <default-operation> "merge"; <config> { <configuration> { <system> { <services> { <ftp>; } } } } } } if ($remote-host = '') { <xnm:error> { <message> "missing mandatory argument 'remote-host'"; } } else { var $connection = jcs:open($remote-host, $netconf); if ($connection) { /* request protocol and capabilities */ var $protocol = jcs:get-protocol($connection); var $capabilities = jcs:get-hello($connection); <output> "\nSession protocol: " _ $protocol _ "\n"; copy-of $capabilities; /* execute rpcs to lock, edit, commit, and unlock config */ var $lock-reply = jcs:execute($connection, $rpc-lock-config); if ($lock-reply/..//rpc-error) { copy-of $lock-reply; } else { var $edit-config-reply = jcs:execute($connection, $rpc-edit-config); if ($edit-config-reply/..//rpc-error) { <output>"Configuration error: "_ $edit-config-reply/..//error-message/. _ "\nConfiguration not committed.\n" ; copy-of $edit-config-reply; } else { var $commit-reply = jcs:execute($connection, $rpc-commit); if ($commit-reply/..//rpc-error) { <output>"Commit error or warning: " _ $commit-reply/..//error-message/.; copy-of $commit-reply; } } var $unlock-reply = jcs:execute($connection, $rpc-unlock-config); } expr jcs:close($connection); } else { <output>"\nNo connection - exiting script"; } } } }
XSLT Syntax
<?xml version="1.0" standalone="yes"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:junos="http://xml.juniper.net/junos/*/junos" xmlns:xnm="http://xml.juniper.net/xnm/1.1/xnm" xmlns:jcs="http://xml.juniper.net/junos/commit-scripts/1.0" xmlns:ext="http://xmlsoft.org/XSLT/namespace" version="1.0"> <xsl:variable name="arguments"> <argument> <name>remote-host</name> <description>device hostname or IP address to which to connect</description> </argument> </xsl:variable> <xsl:param name="remote-host"/> <xsl:template match="/"> <op-script-results> <xsl:variable name="netconf-temp-1"> <method>netconf</method> <username>bsmith</username> </xsl:variable> <xsl:variable xmlns:ext="http://xmlsoft.org/XSLT/namespace" name="netconf" select="ext:node-set($netconf-temp-1)"/> <xsl:variable name="rpc-lock-config"> <lock> <target> <candidate/> </target> </lock> </xsl:variable> <xsl:variable name="rpc-unlock-config"> <unlock> <target> <candidate/> </target> </unlock> </xsl:variable> <xsl:variable name="rpc-commit"> <commit/> </xsl:variable> <xsl:variable name="rpc-edit-config"> <edit-config> <target> <candidate/> </target> <default-operation>merge</default-operation> <config> <configuration> <system> <services> <ftp/> </services> </system> </configuration> </config> </edit-config> </xsl:variable> <xsl:choose> <xsl:when test="$remote-host = ''"> <xnm:error> <message>missing mandatory argument 'remote-host'</message> </xnm:error> </xsl:when> <xsl:otherwise> <xsl:variable name="connection" select="jcs:open($remote-host, $netconf)"/> <xsl:choose> <xsl:when test="$connection"> <!-- request protocol and capabilities --> <xsl:variable name="protocol" select="jcs:get-protocol($connection)"/> <xsl:variable name="capabilities" select="jcs:get-hello($connection)"/> <output> <xsl:value-of select="concat(' Session protocol: ', $protocol, ' ')"/> </output> <xsl:copy-of select="$capabilities"/> <!-- execute rpcs --> <xsl:variable name="lock-reply" select="jcs:execute($connection, $rpc-lock-config)"/> <xsl:choose> <xsl:when test="$lock-reply/..//rpc-error"> <xsl:copy-of select="$lock-reply"/> </xsl:when> <xsl:otherwise> <xsl:variable name="edit-config-reply" select="jcs:execute($connection, $rpc-edit-config)"/> <xsl:choose> <xsl:when test="$edit-config-reply/..//rpc-error"> <output> <xsl:value-of select="concat('Configuration error: ', $edit-config-reply/..//error-message/., ' Configuration not committed. ')"/> </output> <xsl:copy-of select="$edit-config-reply"/> </xsl:when> <xsl:otherwise> <xsl:variable name="commit-reply" select="jcs:execute($connection, $rpc-commit)"/> <xsl:if test="$commit-reply/..//rpc-error"> <output> <xsl:value-of select="concat('Commit error or warning: ', $commit-reply/..//error-message/.)"/> </output> <xsl:copy-of select="$commit-reply"/> </xsl:if> </xsl:otherwise> </xsl:choose> <xsl:variable name="unlock-reply" select="jcs:execute($connection, $rpc-unlock-config)"/> </xsl:otherwise> </xsl:choose> <xsl:value-of select="jcs:close($connection)"/> </xsl:when> <xsl:otherwise> <output>No connection - exiting script</output> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </op-script-results> </xsl:template> </xsl:stylesheet>
Configuration
Step-by-Step Procedure
To download, enable, and test the script:
- Copy the XSLT or SLAX script into a text file, name the
file
netconf-session.xsl
ornetconf-session.slax
as appropriate, and copy it to the/var/db/scripts/op/
directory on the device. In configuration mode, include the file statement at the [edit system scripts op] hierarchy level and
netconf-session.xsl
ornetconf-session.slax
as appropriate.[edit system scripts op]bsmith@local-host# set file netconf-session.(slax | xsl)Issue the commit and-quit command.
[edit]bsmith@local-host# commit and-quit- Execute the op script on the local device by issuing the op netconf-session operational mode command and include any
necessary arguments.
In this example, the user, bsmith, is connecting to the remote device, fivestar. The remote device has dual routing engines, so the commit operation returns a warning that the commit synchronize command should be used to commit the new candidate configuration to both routing engines.
bsmith@local-host> op netconf-session remote-host fivestar
bsmith@fivestar's password: Session protocol: netconf Commit error or warning: graceful-switchover is enabled, commit synchronize should be used
Verification
Confirm that the device is working properly.
Verifying Op Script Execution
Purpose
Verify that the script behaves as expected.
Action
Review the script output in the CLI and in the op script
log file. Take particular note of any errors that occurred during
execution. The default op script log file is /var/log/op-script.log
. If the log file is significantly lengthy, limit the display by
appending the | last number-of-lines option to the show log command and specify the number
of lines to print to the CLI. The output within the <op-script-results> element is relevant to the script execution.
bsmith@local-host> show log op-script.log |
last 100
...output omitted for brevity... <op-script-results xmlns:junos="http://xml.juniper.net/junos/*/junos" xmlns:xnm="http://xml.juniper.net/xnm/1.1/xnm" xml ns:jcs="http://xml.juniper.net/junos/commit-scripts/1.0" xmlns:ext="http://xmlsoft.org/XSLT/namespace"> <output> Session protocol: netconf </output> <hello> <capabilities> <capability>urn:ietf:params:xml:ns:netconf:base:1.0</capability> <capability>urn:ietf:params:xml:ns:netconf:capability:candidate:1.0 </capability> <capability>urn:ietf:params:xml:ns:netconf:capability:confirmed-commit:1.0 </capability> <capability>urn:ietf:params:xml:ns:netconf:capability:validate:1.0</capability> <capability> urn:ietf:params:xml:ns:netconf:capability:url:1.0?protocol=http,ftp,file </capability> <capability>http://xml.juniper.net/netconf/junos/1.0</capability> <capability>http://xml.juniper.net/dmi/system/1.0</capability> </capabilities> <session-id>29087</session-id> </hello> <output>Commit error or warning: graceful-switchover is enabled, commit synchronize should be used </output> <rpc-error> <error-severity>warning</error-severity> <error-message> graceful-switchover is enabled, commit synchronize should be used </error-message> </rpc-error> <ok/> </op-script-results>
You can also obtain more descriptive script output on a device running Junos OS by including the | display xml option when you execute an op script.
bsmith@local-host> op netconf-session remote-host
fivestar | display xml
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/11.4D0/junos"> <output> Session protocol: netconf </output> <hello> <capabilities> <capability> urn:ietf:params:xml:ns:netconf:base:1.0 </capability> <capability> urn:ietf:params:xml:ns:netconf:capability:candidate:1.0 </capability> <capability> urn:ietf:params:xml:ns:netconf:capability:confirmed-commit:1.0 </capability> <capability> urn:ietf:params:xml:ns:netconf:capability:validate:1.0 </capability> <capability> urn:ietf:params:xml:ns:netconf:capability:url:1.0?protocol=http,ftp,file </capability> <capability> http://xml.juniper.net/netconf/junos/1.0 </capability> <capability> http://xml.juniper.net/dmi/system/1.0 </capability> </capabilities> <session-id> 29087 </session-id> </hello> <output> Commit error or warning: graceful-switchover is enabled, commit synchronize should be used </output> <rpc-error> <error-severity> warning </error-severity> <error-message> graceful-switchover is enabled, commit synchronize should be used </error-message> </rpc-error> <ok/> </op-script-results> <cli> <banner></banner> </cli> </rpc-reply>
Meaning
This example creates a NETCONF session on a remote device running Junos OS. The capabilities of the NETCONF server include both standard NETCONF operations and Juniper Networks proprietary extensions, which are defined in http://xml.juniper.net/netconf/junos/1.0 and http://xml.juniper.net/dmi/system/1.0 . The RPC results for the commit operation include one warning, but the commit operation is still successful.
Verifying the Configuration Changes
Purpose
Verify that the commit was successful by viewing the configuration change and the commit log on the remote device.
Action
On the remote device, execute the show configuration system services operational mode command to view the [edit system services] hierarchy level of the configuration. If the script is successful, the configuration includes the ftp statement.
bsmith@fivestar> show configuration system services
ftp; netconf { ssh; }
Additionally, you can review the commit log. On the remote device, execute the show system commit operational mode command to view the commit log. In this example, the log confirms that bsmith committed the candidate configuration in a NETCONF session at the given date and time.
bsmith@fivestar> show system commit
0 2011-07-11 12:04:01 PDT by bsmith via netconf 1 2011-07-08 15:16:33 PDT by root via cli
Troubleshooting
- Troubleshooting Connection Errors
- Troubleshooting Configuration Lock Errors
- Troubleshooting Configuration Syntax Errors
Troubleshooting Connection Errors
Problem
The script generates the following error message:
hello packet:1:(0) Document is empty hello packet:1:(0) Start tag expected, '<' not found error: netconf: could not read hello error: did not receive hello packet from server error: Error in creating the session with "fivestar" server No connection - exiting script
Potential causes for the connection error include:
- The device or interface to which you are connecting is down or unavailable.
- The script argument for the IP address or DNS name of the remote device is incorrect.
- The connection timeout value was exceeded before establishing the connection.
- The user authentication for the remote device is not valid or is entered incorrectly.
- You are trying to establish a NETCONF session, and NETCONF over SSH is not enabled on the device where the NETCONF server resides, or it is enabled on a different port.
Solution
Ensure that the remote device is up and running and that the user has access to the device. Also verify that you supplied the correct argument for the IP address or DNS name of the remote device when executing the script.
For NETCONF sessions, ensure that you have enabled NETCONF over SSH on the device where the NETCONF server resides. Since the example program does not specify a specific port number for the NETCONF session, the session is established on the default NETCONF-over-SSH port, 830. To verify whether NETCONF over SSH is enabled on the default port for a device running Junos OS, enter the following operational mode command on the remote device:
bsmith@fivestar> show configuration system services
netconf { ssh; }
If the netconf configuration hierarchy is absent on the remote device, issue the following statements in configuration mode to enable NETCONF over SSH on the default port:
If the netconf configuration hierarchy specifies a port other than the default port, include the port number in the XML node-set that you pass to the jcs:open() function. For example, the following device is configured for NETCONF over SSH on port 12345:
bsmith@fivestar> show configuration system services
netconf { ssh { port 12345; } }
To create a NETCONF session on the alternate port, include the new port number in the XML node-set.
var $netconf := { <method> "netconf"; <username> "bsmith"; <port> "12345"; } var $connection = jcs:open($remote-host, $netconf); ...
Troubleshooting Configuration Lock Errors
Problem
The script generates one of the following error messages:
configuration database locked by: root terminal p0 (pid 24113) on since 2011-07-11 11:48:06 PDT, idle 00:07:59
Users currently editing the configuration: root terminal p1 (pid 24279) on since 2011-07-11 12:28:30 PDT {master}[edit]
configuration database modified
Solution
Another user currently has a lock on the candidate configuration or has modified the candidate configuration but has not yet committed the configuration. Wait until the lock is released, and then execute the program.
Troubleshooting Configuration Syntax Errors
Problem
The following error message prints to the CLI:
Configuration error: syntax error Configuration not committed.
Examine the result tree for additional information. In this case, the result tree shows the following error message:
<rpc-error> <error-severity> error </error-severity> <error-info> <bad-element> ftp2 </bad-element> </error-info> <error-message> syntax error </error-message> </rpc-error>
Solution
The <bad-element> tag element indicates that the configuration statement is not valid. Correct the configuration hierarchy and run the script. In this example error, the user entered the tag <ftp2> instead of <ftp>. Since that is not an acceptable element in the configuration, the NETCONF server returns an error.
Related Documentation
- ACX, EX, M, MX, SRX, T Series
- get-hello() Function (jcs Namespace)
- get-protocol() Function (jcs Namespace)
- ACX, EX, M, MX, PTX, SRX, T Series
- open() Function (jcs Namespace)
Published: 2013-03-05
Supported Platforms
Related Documentation
- ACX, EX, M, MX, SRX, T Series
- get-hello() Function (jcs Namespace)
- get-protocol() Function (jcs Namespace)
- ACX, EX, M, MX, PTX, SRX, T Series
- open() Function (jcs Namespace)