ON THIS PAGE
Use the Junos PyEZ Config Utility to Configure Junos Devices
Junos PyEZ enables you to make structured and unstructured configuration changes on Junos
devices. This topic discuss how to use the
jnpr.junos.utils.config.Config
utility to make unstructured configuration changes, which consist of static or
templatized configuration data that is formatted as ASCII text, Junos XML elements,
Junos OS set
commands, or JavaScript Object Notation (JSON). The
Config
utility also enables you to roll back to a previously
committed configuration or revert to a rescue configuration.
Configuration Process Overview
After successfully connecting to a Junos device, to configure the device using the
Config
utility, first create a Config
object and associate it with the Device
instance. For
example:
from jnpr.junos import Device from jnpr.junos.utils.config import Config dev = Device(host='dc1a.example.com').open() cu = Config(dev)
By default, Junos PyEZ updates the candidate global configuration
(also known as the shared configuration database). The basic process for making configuration changes is to lock
the configuration database, load the configuration changes, commit
the configuration to make it active, and then unlock the configuration
database. When you use the Junos PyEZ Config
utility to make unstructured configuration changes in the shared
configuration database, you can perform these actions by calling the
appropriate instance methods outlined here:
-
Lock the configuration using
lock()
-
Modify the configuration by performing one of the following actions:
-
Call
load()
when loading a new complete configuration or modifying specific portions of the configuration -
Call
rollback()
to revert to a previously committed configuration, as described in Roll Back the Configuration -
Call
rescue()
to load the rescue configuration, as described in Load the Rescue Configuration
-
-
Commit the configuration using
commit()
, as described in Commit the Configuration and Use Junos PyEZ to Commit the Configuration -
Unlock the configuration using
unlock()
You can also use a context manager (with
... as
syntax) to create a Config
object instance, and certain configuration modes
require that you use one. For these modes, Junos PyEZ automatically
locks and unlocks the configuration. For more information, see Specify the Configuration Mode.
When you use the load()
method to modify the configuration, in addition to
specifying the configuration mode, you can also specify the type of load
operation, the format of the configuration changes, and the source of the
configuration data. The Config
utility supports many of the
same load operations and formats that are available in the Junos CLI. For more
information, see:
You can specify the source of the configuration data as a file on the local server, a file on the target device, or a file at a URL that is reachable from the target device, or as a string, an XML object, or a Jinja2 template. For information about specifying the configuration data source, see the following sections:
Specify the Configuration Mode
By default, when you create a Config
object and do not explicitly specify a
configuration mode, Junos PyEZ updates the candidate global configuration. You
can also specify a different configuration mode to use when modifying the
configuration database. To specify a mode other than the default, you must
create the Config
object using a context manager and set the
mode
argument to the desired mode. Supported modes include
private
, exclusive
,
dynamic
, batch
, and
ephemeral
.
You can use Junos PyEZ to update the ephemeral configuration database on devices that support this database. The ephemeral database is an alternate configuration database that provides a fast programmatic interface for performing configuration updates on Junos devices. It is an advanced feature which if used incorrectly can have a serious negative impact on the operation of the device. For more information, see Understanding the Ephemeral Configuration Database.
When you specify a mode other than the default, the context
manager handles opening and locking and closing and unlocking the
database. This ensures that you do not unintentionally leave the database
in a locked state. In these cases, you only need to call the load()
and commit()
methods
to configure the device.
For example, the following code makes configuration changes
using the configure private
mode, which opens a private
copy of the candidate configuration:
from jnpr.junos import Device from jnpr.junos.utils.config import Config dev = Device(host='dc1a.example.com').open() with Config(dev, mode='private') as cu: cu.load('set system services netconf traceoptions file test.log', format='set') cu.pdiff() cu.commit() dev.close()
For more information about the different configuration modes, see the CLI User Guide and Use Junos PyEZ to Configure Junos Devices.
Specify the Load Operation
Junos PyEZ supports loading configuration changes using using many of the same load operations
that are supported in the Junos CLI. You specify the desired load operation by
including or omitting the appropriate parameters in the Config
load()
method.
Table 1
outlines the supported load operations and the corresponding
load()
method argument. By default, Junos PyEZ performs a
load replace
operation. To use a different load operation,
set the corresponding parameter to True
in the
load()
method.
Load Operation |
Argument |
Description |
First Supported Junos PyEZ Release |
---|---|---|---|
|
|
Merge the loaded configuration with the existing configuration. |
1.0 |
|
|
Replace the entire configuration with the loaded configuration. |
1.0 |
|
|
Load configuration data from a patch file. |
2.4.0 |
|
– |
Merge the loaded configuration with the existing configuration,
but replace statements in the existing configuration with those that
specify the |
1.0 |
|
|
Load a complete configuration and compare it against the existing configuration. Each configuration element that is different in the loaded configuration replaces its corresponding element in the existing configuration. During the commit operation, only system processes that are affected by changed configuration elements parse the new configuration. |
2.1.0 |
The following example performs a load override
operation,
which replaces the entire candidate configuration with the loaded
configuration, and then commits the candidate configuration to make
it active.
from jnpr.junos import Device from jnpr.junos.utils.config import Config config_mx = 'configs/junos-config-mx.conf' dev = Device(host='router1.example.com').open() with Config(dev, mode='exclusive') as cu: cu.load(path=config_mx, overwrite=True) cu.commit() dev.close()
Specify the Format of the Configuration Data to Load
The Junos PyEZ
Config
utility enables you to configure Junos devices using one of the
standard, supported formats. You can provide configuration data as strings,
files, XML objects, or Jinja2 Template objects. Files can contain either
configuration data snippets or Jinja2 templates. When providing configuration
data within a string, file, or Jinja2 template, supported formats for the data
include ASCII text, Junos XML elements, Junos OS set
commands,
and JSON. You can specify the format of the configuration data either by
explicitly including the format
parameter in the
Config
utility
load()
method or by adding the appropriate extension to the configuration
data file. If you do not specify a format, the default is XML.
Starting in Junos PyEZ Release 1.2, Junos PyEZ automatically detects the format when you supply the configuration data as a string.
Table 2 summarizes
the supported formats for the configuration data and the corresponding
value for the file extension and format
parameter. When using Junos XML formatting for the configuration
data, you must enclose the data in the top-level <configuration>
tag.
You do not need to enclose configuration data that is
formatted as ASCII text, Junos OS set
commands, or
JSON in <configuration-text>
, <configuration-set>
, or <configuration-json>
tags as required when configuring the device directly within a NETCONF
session.
Configuration Data Format |
File Extension |
format Parameter |
---|---|---|
ASCII text |
.conf, .text, .txt |
text |
JavaScript Object Notation (JSON) |
.json |
json |
Junos OS |
.set |
set |
Junos XML elements |
.xml |
xml |
When the overwrite
or update
parameter is set to True
, you cannot use the Junos OS set
command format.
Devices running Junos OS Release 16.1R1 or later support loading configuration data in JSON format.
Specify the Location of the Configuration Data
Junos PyEZ enables you to load configuration data as strings, files, XML objects, or Jinja2 Template objects. Files can contain either configuration data snippets or Jinja2 templates.
Table 3 summarizes
the
load()
method parameters that you use to pass in the configuration data or
reference its location. You must always specify the format of the data by
including the format
parameter in the method call except when
using strings, XML objects, or files that have the format indicated by the file
extension. When using Jinja2 templates, include the
template_vars
parameter to pass in the dictionary of
required template variables.
Parameter |
Configuration Data Source |
Description |
|
---|---|---|---|
|
Local file |
Path to a file on the local configuration management
server containing configuration data formatted as ASCII text, Junos
XML elements, Junos OS |
You must include the |
|
Jinja2 Template object |
Pre-loaded Jinja2 Template object. Include the |
You must include the |
|
Local Jinja2 template file |
Path to a file on the local configuration management server
containing a Jinja2 template formatted as ASCII text, Junos XML elements,
Junos OS Include the |
You must include the |
|
Remote file |
Path to a file located on the Junos device or at a remote URL that is reachable from the Junos device using an FTP or Hypertext Transfer Protocol (HTTP) URL. |
You must include the |
|
XML object String |
XML object or a string that contains configuration data formatted
as ASCII text, Junos XML elements, Junos OS |
Junos PyEZ automatically detects the format of the configuration
data in this case, and the |
Load Configuration Data from a Local or Remote File
Junos PyEZ enables you to load configuration data formatted as ASCII text, Junos XML
elements, Junos OS set
commands, or JSON from a local or remote
file.
To load configuration data from a local file on the configuration
management server, set the
load()
method’s path
parameter to the absolute or relative
path of the file. For
example:
from jnpr.junos import Device from jnpr.junos.utils.config import Config dev = Device(host='dc1a.example.com').open() conf_file = 'configs/junos-config-interfaces.conf' with Config(dev, mode='exclusive') as cu: cu.load(path=conf_file, merge=True) cu.commit() dev.close()
You
can also load configuration data from a file located on the Junos device or at a
URL that is reachable from the Junos device. To load configuration data from a
file on the Junos device, set the url
parameter to the absolute
or relative path of the file on the target device, and include any other
parameters required for the load operation. For
example:
cu.load(url='/var/home/user/golden.conf')
url
parameter to the FTP location or Hypertext Transfer Protocol (HTTP) URL of a remote
file, and include any other parameters required for the load operation. For
example:cu.load(url='ftp://username@ftp.hostname.net/path/filename')
cu.load(url='http://username:password@example.com/path/filename')
For
detailed information about specifying the URL, see the url
attribute for the Junos XML protocol <load-configuration>
operation.
If the file does not indicate the format of the configuration
data by using one of the accepted file extensions as listed in Specify the Format of the Configuration Data to Load, then you must specify the
format by including the format
parameter in the
load()
method parameter list. For
example:
conf_file = 'configs/junos-config-interfaces' cu.load(path=conf_file, format='text', merge=True)
For information about loading configuration data from Jinja2 templates or template files, see Load Configuration Data Using Jinja2 Templates.
Load Configuration Data from a String
To load configuration data that is formatted as ASCII text, Junos XML elements, Junos OS
set
commands, or JSON from a string, include the string as
the first argument in the
load()
method argument list. Junos PyEZ automatically detects the format of
the configuration data in strings, so the format
parameter is
optional in this case.
The following code snippets present sample multiline strings containing configuration data in the
different formats and the corresponding calls to the load()
method. The optional format
parameter is explicitly included in
each example for clarity. In the examples, cu
is an instance of
the Config
utility, which operates on the target Junos
device.
from jnpr.junos import Device from jnpr.junos.utils.config import Config dev = Device(host='dc1a.example.com').open() cu = Config(dev)
For configuration data formatted as ASCII text:
config_text = """ system { scripts { op { file test.slax; } } } """
Load the configuration data by supplying the string as the first argument in the list, and optionally specify
format="text"
.cu.load(config_text, format='text', merge=True)
For configuration data formatted as Junos XML:
config_xml = """ <configuration> <system> <scripts> <op> <file> <name>test.slax</name> </file> </op> </scripts> </system> </configuration> """
Load the configuration data by supplying the string as the first argument in the list, and optionally specify
format="xml"
.cu.load(config_xml, format='xml', merge=True)
For configuration data formatted as Junos OS
set
commands:config_set = """ set system scripts op file test.slax """
Load the configuration data by supplying the string as the first argument in the list, and optionally specify
format="set"
.cu.load(config_set, format='set', merge=True)
For configuration data formatted using JSON:
config_json = """{ "configuration" : { "system" : { "scripts" : { "op" : { "file" : [ { "name" : "test.slax" } ] } } } } }"""
Load the configuration data by supplying the string as the first argument in the list, and optionally specify
format="json"
.cu.load(config_json, format='json', merge=True)
Load Configuration Data Formatted as an XML Object
To load configuration data formatted as an XML object, include
the object as the first argument in the load()
method argument list, and supply any other
required parameters. Because the default format for configuration
data is XML, you do not need to explicitly include the format
parameter in the method call.
The following code presents an XML object and the corresponding
call to the load()
method:
from jnpr.junos import Device from jnpr.junos.utils.config import Config from lxml.builder import E config_xml_obj = ( E.configuration( # create an Element called "configuration" E.system( E.scripts( E.op ( E.file ( E.name("test.slax"), ) ) ) ) ) ) with Device(host='dc1a.example.com') as dev: with Config(dev, mode='exclusive') as cu: cu.load(config_xml_obj, merge=True) cu.commit()
Load Configuration Data Using Jinja2 Templates
Junos PyEZ supports using Jinja2 templates to render Junos configuration data. Jinja is
a template engine for Python that enables you to generate documents from
predefined templates. The templates, which are text files in the desired
language, provide flexibility through the use of expressions and variables. You
can create Junos configuration data using Jinja2 templates in one of the
supported configuration formats, which includes ASCII text, Junos XML elements,
Junos OS set
commands, and JSON. Junos PyEZ uses the Jinja2
template and a supplied dictionary of variables to render the configuration
data.
Jinja2 templates provide a powerful method to generate configuration
data, particularly for similar configuration stanzas. For example, rather than
manually adding the same configuration statements for each interface on a
device, you can create a template that iterates over a list of interfaces and
creates the required configuration statements for each one. In Jinja, blocks are
delimited by '{%
' and '%}
' and variables are
enclosed within '{{
' and '}}
'.
The following sample Jinja2 template generates configuration data that enables MPLS on logical unit 0 for each interface in a given list and also configures the interface under the MPLS and RSVP protocols.
interfaces { {% for item in interfaces %} {{ item }} { description "{{ description }}"; unit 0 { family {{ family }}; } } {% endfor %} } protocols { mpls { {% for item in interfaces %} interface {{ item }}; {% endfor %} } rsvp { {% for item in interfaces %} interface {{ item }}; {% endfor %} } }
In the Junos PyEZ code, the corresponding dictionary of Jinja2 template variables is:
config_vars = { 'interfaces': ['ge-1/0/1', 'ge-1/0/2', 'ge-1/0/3'], 'description': 'MPLS interface', 'family': 'mpls' }
To
load the Jinja2 template in the Junos PyEZ code, set the
template_path
parameter to the path of the template file,
and set the template_vars
parameter to the dictionary of
template variables. If you do not use one of the accepted file extensions to
indicate the format of the configuration data, then you must include the
format
parameter in the load()
method
parameter list.
from jnpr.junos import Device from jnpr.junos.utils.config import Config conf_file = 'configs/junos-config-interfaces-mpls.conf' config_vars = { 'interfaces': ['ge-1/0/1', 'ge-1/0/2', 'ge-1/0/3'], 'description': 'MPLS interface', 'family': 'mpls' } with Device(host='router1.example.com') as dev: with Config(dev, mode='exclusive') as cu: cu.load(template_path=conf_file, template_vars=config_vars, merge=True) cu.commit()
If you are supplying a pre-loaded Jinja2 Template object, you must use the
template
parameter instead of the
template_path
parameter in the load()
method argument list.
Junos PyEZ uses the Jinja2 template and dictionary of variables to render the following configuration data, which is then loaded into the candidate configuration and committed on the device:
interfaces { ge-1/0/1 { description "MPLS interface"; unit 0 { family mpls; } } ge-1/0/2 { description "MPLS interface"; unit 0 { family mpls; } } ge-1/0/3 { description "MPLS interface"; unit 0 { family mpls; } } } protocols { mpls { interface ge-1/0/1; interface ge-1/0/2; interface ge-1/0/3; } rsvp { interface ge-1/0/1; interface ge-1/0/2; interface ge-1/0/3; } }
The following video presents a short Python session that demonstrates how to use a Jinja2 template to configure a Junos device.
For additional information about Jinja2, see the Jinja2 documentation at https://jinja.pocoo.org/docs/.
Roll Back the Configuration
Junos devices store a copy of the most recently committed configuration and up to 49 previous configurations, depending on the platform. You can roll back to any of the stored configurations. This is useful when configuration changes cause undesirable results, and you want to revert back to a known working configuration. Rolling back the configuration is similar to the process for making configuration changes on the device, but instead of loading configuration data, you perform a rollback, which replaces the entire candidate configuration with a previously committed configuration.
The Junos PyEZ
jnpr.junos.utils.config.Config
class
rollback()
method enables you to roll back the configuration on a Junos device.
To roll back the configuration, call the rollback()
method and
and set the rb_id
argument to the ID of the rollback
configuration. Valid ID values are 0 (zero, for the most recently committed
configuration) through one less than the number of stored previous
configurations (maximum is 49). If you omit this parameter in the method call,
it defaults to 0.
The following example prompts for the rollback ID of the configuration to restore, rolls back the configuration, prints the configuration differences, and then commits the configuration to make it the active configuration on the device.
from jnpr.junos import Device from jnpr.junos.utils.config import Config rollback_id = int(input('Rollback ID of the configuration to restore: ')) with Device(host='dc1a.example.com') as dev: with Config(dev, mode='exclusive') as cu: cu.rollback(rb_id=rollback_id) cu.pdiff() cu.commit()
user@server:~$ python3 junos-pyez-rollback.py Rollback ID of the configuration to restore: 1 [edit interfaces] - ge-0/0/1 { - unit 0 { - family inet { - address 198.51.100.1/24; - } - } - }
For a more extensive example that includes error handling, see Example: Use Junos PyEZ to Roll Back the Configuration.
Load the Rescue Configuration
A rescue configuration allows you to define a known working configuration or a configuration with a known state that you can restore at any time. You use the rescue configuration when you need to revert to a known configuration or as a last resort if your router or switch configuration and the backup configuration files become damaged beyond repair. When you create a rescue configuration, the device saves the most recently committed configuration as the rescue configuration.
The Junos PyEZ
jnpr.junos.utils.config.Config
utility enables you to manage the rescue configuration on Junos
devices. After creating an instance of the Config
class, you
use the
rescue()
method to mange the rescue configuration. You specify the action to
perform on the rescue configuration by setting the rescue()
method action
parameter to the desired operation.
To load the existing rescue configuration into the candidate
configuration, specify action="reload"
.
If no rescue configuration exists, the load operation returns False
. After loading the rescue configuration, you
must commit the configuration to make it the active configuration
on the device.
The following example loads and commits the rescue configuration, if one exists:
from jnpr.junos import Device from jnpr.junos.utils.config import Config with Device(host='dc1a.example.com') as dev: with Config(dev, mode='exclusive') as cu: rescue = cu.rescue(action='reload') if rescue is False: print ('No existing rescue configuration.') else: cu.pdiff() cu.commit()
For information about creating, retrieving, or deleting the rescue configuration and for additional examples, see Use Junos PyEZ to Manage the Rescue Configuration on Junos Devices.
Commit the Configuration
After modifying the configuration, you must commit the configuration
to make it the active configuration on the device. When you use the Config
utility to make unstructured configuration changes
on a device, you commit the candidate configuration by calling the commit()
method.
from jnpr.junos import Device from jnpr.junos.utils.config import Config conf_file = 'configs/junos-config-interfaces.conf' with Device(host='dc1a.example.com') as dev: with Config(dev, mode='exclusive') as cu: cu.load(path=conf_file, merge=True) cu.commit()
For more information about the commit operation and supported commit options in Junos PyEZ scripts, see Use Junos PyEZ to Commit the Configuration.
Change History Table
Feature support is determined by the platform and release you are using. Use Feature Explorer to determine if a feature is supported on your platform.