- play_arrow Overview
- play_arrow Junos Automation Scripts Overview
- play_arrow Junos XML Management Protocol and Junos XML API Overview
-
- play_arrow Automation Scripting Using XSLT
- play_arrow XSLT Overview
- play_arrow Standard XPath and XSLT Functions Used in Automation Scripts
- play_arrow Standard XSLT Elements and Attributes Used in Automation Scripts
-
- play_arrow Automation Scripting Using SLAX
- play_arrow SLAX Overview
- SLAX Overview
- SLAX Syntax Rules Overview
- SLAX Elements and Element Attributes Overview
- SLAX Elements as Function Arguments
- Understanding SLAX Default Namespaces
- XPath Expressions Overview for SLAX
- SLAX Templates Overview
- SLAX Functions Overview
- SLAX Parameters Overview
- SLAX Variables Overview
- SLAX Statements Overview
- XSLT Elements Without SLAX Equivalents
- SLAX Operators
- play_arrow SLAX Statements
- append
- apply-imports
- apply-templates
- attribute
- attribute-set
- call
- copy-node
- copy-of
- decimal-format
- element
- else
- else if
- expr
- fallback
- for
- for-each
- function
- if
- import
- key
- match
- message
- mode
- mvar
- number
- output-method
- param
- preserve-space
- priority
- processing-instruction
- result
- set
- sort
- strip-space
- template
- terminate
- trace
- uexpr
- use-attribute-sets
- var
- version
- while
- with
- play_arrow The libslax Distribution for Automation Scripting
- libslax Distribution Overview
- libslax Library and Extension Libraries Overview
- Download and Install the libslax Distribution
- libslax Default Extension Libraries: bit, curl, db, os, and xutil
- Understanding the SLAX Processor (slaxproc)
- How to Use the SLAX Processor (slaxproc)
- SLAX Debugger, Profiler, and callflow
-
- play_arrow Automation Script Input
- play_arrow Global Parameters in Automation Scripts
-
- play_arrow Extension Functions and Named Templates for Automation Scripts
- play_arrow Extension Functions for Automation Scripting
- play_arrow Extension Functions in the jcs and slax Namespaces
- base64-decode() Function (SLAX)
- base64-encode() Function (SLAX)
- break-lines() Function (SLAX and XSLT)
- close() Function (SLAX and XSLT)
- dampen() Function (Python, SLAX, and XSLT)
- document() Function (SLAX)
- emit_error() Function (Python)
- emit_snmp_attributes Function (Python)
- emit_warning() Function (Python)
- empty() Function (SLAX and XSLT)
- evaluate() Function (SLAX)
- execute() Function (SLAX and XSLT)
- first-of() Function (SLAX and XSLT)
- get-command() Function (SLAX)
- get-hello() Function (SLAX and XSLT)
- get-input() Function (SLAX and XSLT) and get_input() (Python)
- get-protocol() Function (SLAX and XSLT)
- get-secret() Function (SLAX and XSLT) and get_secret() (Python)
- get_snmp_action() Function (Python)
- get_snmp_oid() Function (Python)
- hostname() Function (Python, SLAX, and XSLT)
- invoke() Function (SLAX and XSLT)
- open() Function (SLAX and XSLT)
- output() Function (Python, SLAX, and XSLT)
- parse-ip() Function (SLAX and XSLT) and parse_ip() (Python)
- printf() Function (Python, SLAX, and XSLT)
- progress() Function (Python, SLAX, and XSLT)
- regex() Function (SLAX and XSLT)
- set_routing_instance() Function (Python)
- sleep() Function (SLAX and XSLT)
- split() Function (SLAX and XSLT)
- sysctl() Function (Python, SLAX, and XSLT)
- syslog() Function (Python, SLAX, and XSLT)
- trace() Function (Python, SLAX, and XSLT)
- play_arrow Named Templates for Automation Scripting
- play_arrow Named Templates in the jcs Namespace
-
- play_arrow Manage Automation Scripts
- play_arrow Store and Enable Scripts
- play_arrow Configure a Remote Source for Scripts
- play_arrow Configure the Session Protocol for Scripts
- play_arrow Control Execution of Scripts
- play_arrow Synchronize Scripts Between Routing Engines
- play_arrow Convert Scripts Between SLAX and XSLT
-
- play_arrow Commit Scripts
- play_arrow Commit Scripts Overview
- play_arrow Create and Execute Commit Scripts
- Required Boilerplate for Commit Scripts
- XML Syntax for Common Commit Script Tasks
- Design Considerations for Commit Scripts
- How to Avoid Potential Conflicts When Using Multiple Commit Scripts
- Line-by-Line Explanation of Sample Commit Scripts
- Control the Execution of Commit Scripts During Commit Operations
- Control the Execution of Commit Scripts in the QFabric System
- Configure Checksum Hashes for a Commit Script
- How to Process Large Configurations Against Commit Scripts
- Example: Retrieve the Pre-Inheritance Candidate Configuration in a Commit Script
- play_arrow Generate a Custom Warning, Error, or System Log Message Using Commit Scripts
- Overview of Generating Custom Warning, Error, and System Log Messages
- Generate a Custom Warning, Error, or System Log Message in Commit Scripts
- SLAX and XSLT Commit Script Tag Elements to Use When Generating Messages
- Example: Generate a Custom Warning Message
- Example: Generate a Custom Error Message
- Example: Generate a Custom System Log Message
- play_arrow Generate Persistent or Transient Configuration Changes Using Commit Scripts
- Overview of Generating Persistent or Transient Configuration Changes Using Commit Scripts
- Generate a Persistent or Transient Configuration Change in SLAX and XSLT Commit Scripts
- Generate a Persistent or Transient Configuration Change in Python Commit Scripts
- SLAX and XSLT Commit Script Tag Elements to Use When Generating Persistent and Transient Configuration Changes
- Remove a Persistent or Transient Configuration Change Using Commit Scripts
- Example: Generate Persistent and Transient Configuration Changes Using Commit Scripts
- play_arrow Create Custom Configuration Syntax with Commit Script Macros
- Overview of Creating Custom Configuration Syntax with Commit Script Macros
- Create Custom Configuration Syntax with Commit Script Macros
- Create a Commit Script Macro to Read the Custom Syntax and Generate Related Configuration Statements
- Example: Creating Custom Configuration Syntax with Commit Script Macros
- play_arrow Commit Script Examples
- Example: Adding a Final then accept Term to a Firewall
- Example: Adding T1 Interfaces to a RIP Group
- Example: Assign a Classifier Using a Commit Script
- Example: Automatically Configure Logical Interfaces and IP Addresses
- Example: Configure Administrative Groups for LSPs
- Example: Configure a Default Encapsulation Type
- Example: Configure Dual Routing Engines
- Example: Configure an Interior Gateway Protocol on an Interface
- Example: Control IS-IS and MPLS Interfaces
- Example: Control LDP Configuration
- Example: Create a Complex Configuration Based on a Simple Interface Configuration
- Example: Impose a Minimum MTU Setting
- Example: Limit the Number of ATM Virtual Circuits
- Example: Limit the Number of E1 Interfaces
- Example: Load a Base Configuration
- Example: Prepend a Global Policy
- Example: Prevent Import of the Full Routing Table
- Example: Require Internal Clocking on T1 Interfaces
- Example: Require and Restrict Configuration Statements
- play_arrow Junos XML and XSLT Tag Elements Used in Commit Scripts
- play_arrow Troubleshoot Commit Scripts
-
- play_arrow Op Scripts
- play_arrow Op Scripts Overview
- play_arrow Create and Execute Op Scripts
- Required Boilerplate for Op Scripts
- Map Operational Mode Commands and Output Fields to Junos XML Notation
- How to Use RPCs and Operational Mode Commands in Op Scripts
- Declare and Use Command-Line Arguments in Op Scripts
- Configure Help Text for Op Scripts
- Define Operational Mode Commands to Allow in an Op Script
- Enable an Op Script and Define a Script Alias
- Configure Checksum Hashes for an Op Script
- Execute an Op Script on the Local Device
- Execute an Op Script from a Remote Site
- Disable an Op Script
- play_arrow Op Script Examples
- Change the Configuration Using SLAX and XSLT Scripts
- Example: Change the Configuration Using SLAX and XSLT Op Scripts
- Example: Change the Configuration Using Python Op Scripts
- Example: Customize Output of the show interfaces terse Command Using an Op Script
- Example: Display DNS Hostname Information Using an Op Script
- Example: Find LSPs to Multiple Destinations Using an Op Script
- Example: Restart an FPC Using an Op Script
- Example: Export Files Using an Op Script
- Example: Import Files Using an Op Script
- Example: Search Files Using an Op Script
- play_arrow Provision Services Using Service Template Automation
- play_arrow Troubleshoot Op Scripts
-
- play_arrow Event Policies and Event Scripts
- play_arrow Event Policy Overview
- play_arrow Event Policy Triggers
- Use Correlated Events to Trigger an Event Policy
- Trigger an Event Policy Based on Event Count
- Example: Trigger an Event Policy Based on Event Count
- Use Regular Expressions to Refine the Set of Events That Trigger a Policy
- Example: Controlling Event Policy Using a Regular Expression
- Generate Internal Events to Trigger Event Policies
- Use Nonstandard System Log Messages to Trigger Event Policies
- Junos Logger Utility
- play_arrow Event Policy Actions
- Configure an Event Policy to Execute Operational Mode Commands
- Configure an Event Policy to Change the Configuration
- Example: Changing the Configuration Using an Event Policy
- Example: Changing the Interface Configuration in Response to an Event
- Execute Event Scripts in an Event Policy
- Change the Configuration Using an Event Script
- Configuring an Event Policy to Pass Arguments to an Event Script
- Configure Event Policies to Ignore an Event
- Example: Ignore Events Based on Receipt of Other Events
- Overview of Using Event Policies to Raise SNMP Traps
- Example: Raise an SNMP Trap in Response to an Event
- Understanding the Event System Log Priority in an Event Policy
- Example: Configuring the Event System Log Priority in an Event Policy
- Example: Limit Event Script Output Based on a Specific Event Type
- play_arrow Configure Event Policy File Archiving
- play_arrow Configure Event Policy Privileges
- play_arrow Event Scripts Overview
- play_arrow Create and Execute Event Scripts
- play_arrow Troubleshoot Event Policies and Event Scripts
-
- play_arrow SNMP Scripts
- play_arrow SNMP Scripts Overview
- play_arrow Create and Execute SNMP Scripts
- play_arrow SNMP Script Example
- play_arrow Troubleshoot SNMP Scripts
-
- play_arrow Configuration Statements and Operational Commands
How to Use the Requests Library for Python on Devices Running Junos OS
The Requests library for Python is available
on certain devices running Junos OS that support the Python extensions
package. You can use the requests
module
in Python scripts to send HTTP/1.1 requests. On devices running Junos
OS with Enhanced Automation, you can also use the requests
module in Python interactive mode. The Requests library provides
additional methods for supporting initial deployments as well as for
performing routine monitoring and configuration changes on devices
running Junos OS. For information about the requests
module and its functions, see the Requests documentation at http://docs.python-requests.org/.
Issuing Requests
You can use the requests
module in
onbox Python scripts to send HTTP/1.1 requests. To make a request,
import the module in your script, and call the function corresponding
to the desired request. The module supports HTTP GET
and POST
requests as well as HEAD
, DELETE
, and PUT
requests. The request returns a Response object containing the server’s response. By default, requests
are made using the default routing instance.
The Requests library can be used to execute RPCs on devices
running Junos OS that support the REST API service. The target device
must be configured with the appropriate statements at the [edit
system services rest]
hierarchy level to enable Junos OS commands
over HTTP or HTTPS using REST.
For example, the following op script performs a GET request
that executes the get-software-information
RPC on a remote device running Junos OS that has the REST API service
over HTTP configured on the default port (3000). The script prints
the response status code, and if the status code indicates success,
it prints the response content.
from junos import Junos_Context import jcs import requests user = Junos_Context['user-context']['user'] password = jcs.get_secret('Enter user password: ') r = requests.get('http://198.51.100.1:3000/rpc/get-software-information', auth=(user, password)) print (r.status_code) if (r.status_code == requests.codes.ok): print (r.text)
user@host> op show-version.py Enter user password: 200 <software-information> <host-name>router1</host-name> <product-model>mx240</product-model> <product-name>mx240</product-name> <junos-version>18.3R1.8</junos-version> <package-information> <name>os-kernel</name> ...
To retrieve just the headers, you can send a simple HEAD
request.
r = requests.head('http://198.51.100.1:3000/rpc/get-software-information', auth=(user, password)) print (r.headers) print (r.headers['content-type'])
user@host> op request-headers.py Enter user password: {'Date': 'Tue, 02 Apr 2019 18:30:58 GMT', 'Connection': 'close', 'Content-Type': 'application/xml; charset=utf-8', 'Server': 'lighttpd/1.4.48'} application/xml; charset=utf-8
If a GET request requires additional parameters, you can either
include the params
argument and supply
a dictionary or a list of tuples or bytes to send in the query string,
or you can pass in key/value pairs as part of the URL. Similarly,
you can supply custom headers by including the headers
argument and a dictionary of HTTP headers.
The following request executes the get-interface-information
RPC with the terse option for the given interface and returns the
response in text format:
headers={'content-type': 'application/xml', 'Accept': 'text/plain'} params={'interface-name':'ge-2/0/1', 'terse':''} r = requests.get('http://198.51.100.1:3000/rpc/get-interface-information', auth=(user, password), headers=headers, params=params)
The following example supplies the arguments as key/value pairs in the URL:
headers={'content-type': 'application/xml', 'Accept': 'text/plain'} rpc = 'get-interface-information?interface-name=ge-2/0/1&terse=' r = requests.get('http://198.51.100.1:3000/rpc/' + rpc, auth=(user, password), headers=headers)
To execute multiple RPCs in the same request, initiate an HTTP
POST request, and set the data
parameter
to reference the RPCs to execute. See sections Executing Operational RPCs and Managing the Configuration for examples that execute
multiple RPCs.
Executing Operational RPCs
You can use the requests
module to execute RPCs from the Junos
XML API on a remote device running Junos OS that has the REST API service
enabled.
The following op script uses the requests
module to execute the
RPC equivalent of the show interfaces ge-2/0/1 terse
operational mode command on the target device:
from junos import Junos_Context import jcs import requests user = Junos_Context['user-context']['user'] password = jcs.get_secret('Enter user password: ') r = requests.get('http://198.51.100.1:3000/rpc/get-interface-information', auth=(user, password), params={'interface-name':'ge-2/0/1','terse':''}) print(r.text)
The following op script sends a POST request that executes multiple RPCs on the
target device. The data
parameter references the RPCs to
execute, which are defined in a multiline string for readability.
from junos import Junos_Context import jcs import requests user = Junos_Context['user-context']['user'] password = jcs.get_secret('Enter user password: ') headers={'content-type': 'application/xml', 'Accept': 'text/plain'} payload=""" <get-software-information/> <get-interface-information> <interface-name>ge-2/0/1</interface-name> </get-interface-information>""" r = requests.post('http://198.51.100.1/rpc/', auth=(user, password), headers=headers, data=payload) if (r.status_code == requests.codes.ok): print (r.text)
You can also create a generic op script for which the user supplies the necessary
variables and the script constructs and executes the request. Consider the
following op script configuration, which configures the host
,
rpc
, and rpc_args
command line arguments
for the requests-rpc.py op script:
[edit system scripts] op { file requests-rpc.py { arguments { host { description "host:port to which to connect"; } rpc { description "base RPC to execute on target device"; } rpc_args { description "dictionary of RPC arguments to use"; } } } } language python;
The following sample op script connects to a remote device running Junos OS,
which has been configured with the appropriate statements at the [edit
system services rest]
hierarchy level to enable Junos OS commands
over HTTP using REST. The script prompts for the connection password and
connects to the host and port provided through the host
argument. The script then uses the requests
module to send a
GET request executing the RPC that was provided through the command-line
arguments.
Starting in Junos OS Release 21.2R1 and Junos OS Evolved Release 21.2R1, when the device passes command-line arguments to a Python op script, it prefixes a single hyphen (-) to single-character argument names and prefixes two hyphens (--) to multi-character argument names. In earlier releases, the devices prefixes a single hyphen (-) to all argument names.
# Junos OS Release 21.1 and earlier from junos import Junos_Context from ast import literal_eval import jcs import argparse import requests ## Argument list as configured in [edit system scripts op] arguments = { 'host': 'host:port to which to connect', 'rpc' : 'base RPC to execute on target device', 'rpc_args' : 'dictionary of RPC arguments to use' } ## Retrieve script arguments (Junos OS Release 21.1 and earlier) parser = argparse.ArgumentParser(description='This is a demo script.') for key in arguments: if key == 'rpc_args': parser.add_argument(('-' + key), help=arguments[key]) else: parser.add_argument(('-' + key), required=True, help=arguments[key]) args = parser.parse_args() ## Convert rpc_args to a dictionary if args.rpc_args is not None: args.rpc_args = literal_eval(args.rpc_args) ## Retrieve username and prompt for password for connecting to target device user = Junos_Context['user-context']['user'] password = jcs.get_secret('Enter user password: ') ## Execute RPC if args.rpc_args is None: r = requests.get('http://' + args.host + '/rpc/' + args.rpc, auth=(user, password)) else: r = requests.get('http://' + args.host + '/rpc/' + args.rpc, auth=(user, password), params=args.rpc_args) ## Print RPC contents if HTTP status code indicates success if (r.status_code == requests.codes.ok): print (r.text) else: print (r.status_code)
When you execute the script, it executes the RPC with the specified options on the remote device and prints the response to standard output.
user@host> op requests-rpc.py host 198.51.100.1:3000 rpc get-interface-information rpc_args {'interface-name':'ge-2/0/1','terse':''} Enter user password: <interface-information xmlns="http://xml.juniper.net/junos/18.3R1/junos-interface" xmlns:junos="http://xml.juniper.net/junos/*/junos" junos:style="terse"> <physical-interface> <name>ge-2/0/1</name> <admin-status>up</admin-status> <oper-status>up</oper-status> </physical-interface> </interface-information>
Managing the Configuration
You can use the requests
module to
retrieve or change the configuration on a device running Junos OS
that has the REST API service enabled.
The following op script retrieves the [edit system]
hierarchy from the candidate configuration using a POST request:
from junos import Junos_Context import jcs import requests user = Junos_Context['user-context']['user'] password = jcs.get_secret('Enter user password: ') headers = { 'content-type' : 'application/xml' } payload = '<get-configuration><configuration><system/></configuration></get-configuration>' r = requests.post('http://198.51.100.1:3000/rpc/', auth=(user, password), data=payload, headers=headers) print (r.content)
HTTP POST requests also enable you to execute multiple RPCs in a single request, for example, to lock, load, commit, and unlock a configuration.
The following sample op script connects to the remote device and configures an address on the given interface. The lock, load, commit, and unlock operations are defined separately for readability, but the RPCs are concatenated in the request.
from junos import Junos_Context import jcs import requests user = Junos_Context['user-context']['user'] password = jcs.get_secret('Enter user password: ') #### lock, load, commit, unlock configuration headers={'content-type': 'application/xml'} lock = '<lock><target><candidate/></target></lock>' load = """<edit-config> <target><candidate></candidate></target> <default-operation>merge</default-operation> <config> <configuration> <interfaces> <interface> <name>ge-2/0/1</name> <unit> <name>0</name> <family> <inet> <address> <name>192.0.2.1/24</name> </address> </inet> </family> </unit> </interface> </interfaces> </configuration> </config> <error-option>stop-on-error</error-option> </edit-config>""" commit = '<commit/>' unlock = '<unlock><target><candidate/></target></unlock>' payload = lock + load + commit + unlock r = requests.post('http://198.51.100.1:3000/rpc/', auth=(user, password), headers=headers, data=payload) print(r.content)
When you execute the op script, it returns the RPC results
for the lock, load, commit, and unlock operations. On some devices,
the response output separates the individual RPC replies with boundary
lines that include --
followed by a boundary
string and a Content-Type
header. Other
devices might include just the Content-Type
header.
user@host> op requests-set-interface.py Enter user password: --harqgehabymwiax Content-Type: application/xml; charset=utf-8 <ok/> --harqgehabymwiax Content-Type: application/xml; charset=utf-8 <load-success/> --harqgehabymwiax Content-Type: application/xml; charset=utf-8 <commit-results xmlns:junos="http://xml.juniper.net/junos/*/junos"> <routing-engine junos:style="normal"> <name>re0</name> <commit-success/> <commit-revision-information> <new-db-revision>re0-1555351754-53</new-db-revision> <old-db-revision>re0-1555033614-52</old-db-revision> </commit-revision-information> </routing-engine> </commit-results> --harqgehabymwiax Content-Type: application/xml; charset=utf-8 <ok/> --harqgehabymwiax--
Using Certificates in HTTPS Requests
The HTTP basic authentication mechanism sends user credentials as a Base64-encoded clear-text string. To protect the authentication credentials from eavesdropping, we recommend enabling the RESTful API service over HTTPS, which encrypts the communication using Transport Layer Security (TLS) or Secure Sockets Layer (SSL). For information about configuring this service, see the Junos OS REST API Guide.
By default, the Requests library verifies SSL certificates for
HTTPS requests. You can include the verify
and cert
arguments in the request to
control the SSL verification options. For detailed information about
these options, see the Requests documentation.
When you use Python 2.7 to execute a script that uses
the requests
module to execute HTTPS requests,
the script generates InsecurePlatformWarning
and SubjectAltNameWarning
warnings.
The following op script sends a GET request over HTTPS,
and sets the verify
argument to the file
path of a CA bundle or a directory containing trusted CA certificates.
The specified CA certificates are used to verify the server’s
certificate.
from junos import Junos_Context import jcs import requests user = Junos_Context['user-context']['user'] password = jcs.get_secret('Enter user password: ') r = requests.get('https://198.51.100.1:3443/rpc/get-software-information', auth=(user, password), verify='path-to-ca-bundle') print (r.status_code) if (r.status_code == requests.codes.ok): print (r.text)
To specify a local client-side certificate, set the cert
argument equal to the path of a single file containing
the client’s private key and certificate or to a tuple containing
the paths of the individual client certificate and private key files.
r = requests.get('https://198.51.100.1:3443/rpc/get-software-information', auth=(user, password), verify='path-to-ca-bundle', cert=('path-to-client-cert','path-to-client-key')
Specifying the Routing Instance
By default, requests are executed using the default routing
instance. You can also execute requests using the mgmt_junos
management instance or another non-default routing instance. When
you execute scripts through the Junos OS infrastructure, you can specify
the routing instance by calling the set_routing_instance()
function in the script. Certain devices also support specifying
the routing instance and executing a script in the Unix-level shell.
On devices running Junos OS Evolved, the set_routing_instance()
function only supports using
the management routing instance.
In a Python script, to execute a request using a non-default
routing instance, including the mgmt_junos
instance:
The following op script uses the mgmt_junos
management instance to connect to the target device and execute
requests.
from junos import Junos_Context import jcs import requests user = Junos_Context['user-context']['user'] password = jcs.get_secret('Enter user password: ') jcs.set_routing_instance('mgmt_junos') r = requests.get('http://198.51.100.1:3000/rpc/get-software-information', auth=(user, password)) print (r.text)
For information about using the set_routing_instance()
function in Python scripts, see set_routing_instance().
In addition to specifying the routing instance in the script,
certain devices support specifying the routing instance and executing
a script from the Unix-level shell. On devices running Junos OS with
Enhanced Automation (FreeBSD Release 7.1 or later), you can use the setfib
command to execute requests with the given routing instance,
including the management instance and other non-default routing instances.
The following Python script simply executes the get-software-information
RPC on a remote device and
prints the response:
#!/usr/bin/env python import requests from getpass import getpass user = raw_input ('Enter username: ') password = getpass('Enter password: ') r = requests.get('http://198.51.100.1:3000/rpc/get-software-information', auth=(user, password)) print (r.text)
To use setfib
to execute the script using
a non-default routing instance on a device running Junos OS with Enhanced
Automation:
Find the software index associated with the routing table for that instance.
In the following example, the device is configured to use the non-default dedicated management instance
mgmt_junos
. The routing table index is referenced in the command output.content_copy zoom_out_mapuser@host> show route forwarding-table extensive table mgmt_junos Routing table: mgmt_junos.inet [Index 36738] Internet: Enabled protocols: Bridging, Destination: default Route type: permanent Route reference: 0 Route interface-index: 0 Multicast RPF nh index: 0 P2mpidx: 0 Flags: none Next-hop type: reject Index: 340 Reference: 1
To execute the op script with the given routing instance, use the
setfib
command to execute the script and reference the index. For example:content_copy zoom_out_mapuser@host> start shell % setfib -F36738 python /var/db/scripts/op/request-software-info.py
In the following example, the device is configured with a non-default routing instance, vr1, and the vr1.inet routing table index is 8:
content_copy zoom_out_mapuser@host> show route forwarding-table extensive table vr1 Routing table: vr1.inet [Index 8] Internet: Enabled protocols: Bridging, All VLANs, Destination: default Route type: permanent Route reference: 0 Route interface-index: 0 Multicast RPF nh index: 0 P2mpidx: 0 Flags: sent to PFE Next-hop type: reject Index: 592 Reference: 1
The following command executes the op script using the vr1 routing instance:
content_copy zoom_out_map% setfib -F8 python /var/db/scripts/op/request-software-info.py
Performing ZTP Operations
Zero touch provisioning (ZTP) enables you to provision new Juniper Networks devices in your network automatically, with minimal manual intervention. To use ZTP, you configure a server to provide the required information, which can include a Junos OS image and a configuration file to load or a script to execute. When you physically connect a device to the network and boot it with a factory-default configuration, the device retrieves the information from the designated server, upgrades the Junos OS image as appropriate, and executes the script or loads the configuration file.
When you connect and boot a new networking device, if Junos OS detects a file on the server, the first line of the file is examined. If Junos OS finds the characters #! followed by an interpreter path, it treats the file as a script and executes it with the specified interpreter. You can use the Requests library in executed scripts to streamline the ZTP process.
For example, consider the following sample Python script,
which the new device downloads and executes during the ZTP process.
When the script executes, it first downloads the CA certificate from
the ca_cert_remote
location on the specified
server and stores it locally in the ca_cert_local
location. The script then connects to the configuration server on
port 8000 and issues a GET request to retrieve the new device configuration.
The request includes the path to the CA certificate, which is used
to verify the server’s certificate during the exchange. The
script then uses the Junos PyEZ library to load the configuration
on the device and commit it.
#!/usr/bin/python import os import paramiko import requests from jnpr.junos import Device from jnpr.junos.utils.config import Config # Define the servers storing the certificate and configuration host_cert = '198.51.100.1' host_config = '192.0.2.1' username = 'admin' password = 'secret123' # Define CA certificate file locations ca_cert_remote = '/u01/app/myCA/certs/rootCA.crt' ca_cert_local = '/var/tmp/rootCA.crt' # Retrieve the CA certificate from the server ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(hostname=host_cert, username=username, password=password) sftp = ssh.open_sftp() sftp.get(ca_cert_remote, ca_cert_local) sftp.close() ssh.close() # Retrieve the configuration from the server uri = 'https://' + host_config + ':8000/' config = requests.get(uri, auth=(username, password), verify=ca_cert_local) # Load and commit the configuration on the device with Device() as dev: cu = Config(dev) cu.load(config.text, format='text', overwrite=True) cu.commit()