Help us improve your experience.

Let us know what you think.

Do you have time for a two-minute survey?

Announcement: Try the Ask AI chatbot for answers to your technical questions about Juniper products and solutions.

close
header-navigation
keyboard_arrow_up
close
keyboard_arrow_left
Automation Scripting User Guide
Table of Contents Expand all
list Table of Contents
file_download PDF
{ "lLangCode": "en", "lName": "English", "lCountryCode": "us", "transcode": "en_US" }
English
keyboard_arrow_right

Example: Specify the Session Protocol for a Connection within Scripts

date_range 08-Mar-22

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

The jcs:open() extension 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

content_copy zoom_out_map
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

content_copy zoom_out_map
<?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('&#10;Session protocol: ', $protocol, '&#10;')"/>
              </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/., 
                          '&#10;Configuration not committed.&#10;')"/>
                      </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

Procedure

Step-by-Step Procedure

To download, enable, and test the script:

  1. Copy the XSLT or SLAX script into a text file, name the file netconf-session.xsl or netconf-session.slax as appropriate, and copy it to the /var/db/scripts/op/ directory on the device.

  2. In configuration mode, include the file statement at the [edit system scripts op] hierarchy level and netconf-session.xsl or netconf-session.slax as appropriate.

    content_copy zoom_out_map
    [edit system scripts op]
    bsmith@local-host# set file netconf-session.(slax | xsl)
    
  3. Issue the commit and-quit command.

    content_copy zoom_out_map
    [edit]
    bsmith@local-host# commit and-quit
    
  4. 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.

    content_copy zoom_out_map
    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.

content_copy zoom_out_map
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" 
   xmlns: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.

content_copy zoom_out_map
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.

content_copy zoom_out_map
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.

content_copy zoom_out_map
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

Problem

The script generates the following error message:

content_copy zoom_out_map
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:

content_copy zoom_out_map
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:

content_copy zoom_out_map
[edit]
bsmith@fivestar# set system services netconf ssh
bsmith@fivestar# commit

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:

content_copy zoom_out_map
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.

content_copy zoom_out_map
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:

content_copy zoom_out_map
configuration database locked by:
  root terminal p0 (pid 24113) on since 2011-07-11 11:48:06 PDT, idle 00:07:59
content_copy zoom_out_map
Users currently editing the configuration:
  root terminal p1 (pid 24279) on since 2011-07-11 12:28:30 PDT
      {master}[edit]
content_copy zoom_out_map
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:

content_copy zoom_out_map
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:

content_copy zoom_out_map
  <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.

footer-navigation