Use Junos PyEZ to Retrieve a Configuration
SUMMARY You can create Junos PyEZ applications that retrieve configuration data from the specified configuration database on a Junos device.
Junos PyEZ applications can execute Remote Procedure Calls (RPCs) on demand on Junos devices.
After creating an instance of the Device
class, an application can
execute RPCs as a property of the Device
instance. Junos PyEZ
applications can use the get_config()
RPC to request the complete
configuration or selected portions of the configuration for both the native Junos OS
configuration as well as for configuration data corresponding to standard (IETF,
OpenConfig) or custom YANG data models that have been added to the device.
The Junos PyEZ get_config
RPC invokes the Junos XML protocol
<get-configuration>
operation. For more information about
the <get-configuration>
operation and its options, see <get-configuration>.
This topic discuss how to retrieve the configuration by using the Junos PyEZ
get_config()
RPC. For information about using Tables and Views to
retrieve configuration data, see Define Junos PyEZ Configuration Tables and Use Junos PyEZ Configuration Tables to Retrieve Configuration Data.
Retrieve the Complete Candidate Configuration
To retrieve the complete candidate configuration from a Junos device, execute the
get_config()
RPC. The default output format is XML. For
example:
from jnpr.junos import Device from lxml import etree with Device(host='router1.example.net') as dev: data = dev.rpc.get_config() print (etree.tostring(data, encoding='unicode', pretty_print=True))
Specify the Source Database for the Configuration Data
When a Junos PyEZ application uses the get_config()
RPC to retrieve
configuration information from a Junos device, by default, the server returns
data from the candidate configuration database. A Junos PyEZ application can
also retrieve configuration data from the committed configuration database or
the ephemeral configuration database.
Candidate Configuration Database
To retrieve data from the candidate configuration database,
execute the get_config()
RPC, and optionally
include any additional arguments.
from jnpr.junos import Device from lxml import etree with Device(host='router1.example.net') as dev: data = dev.rpc.get_config() print (etree.tostring(data, encoding='unicode', pretty_print=True))
Committed Configuration Database
To retrieve data from the committed configuration database,
include the options
argument with 'database':'committed'
in the get_config()
RPC call.
from jnpr.junos import Device from lxml import etree with Device(host='router1.example.net') as dev: data = dev.rpc.get_config(options={'database' : 'committed'}) print (etree.tostring(data, encoding='unicode', pretty_print=True))
Ephemeral Configuration Database
Junos PyEZ supports operations on the ephemeral configuration database on devices that support this database. When you retrieve configuration data from the shared configuration database, by default, the results do not include data from the ephemeral configuration database.
The ephemeral database is an alternate configuration database that provides a fast programmatic interface for performing configuration updates on Junos devices. The ephemeral configuration database 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.
To retrieve data from the default instance of the ephemeral
configuration database, first open the default ephemeral instance
and then request the data. To open the default instance, use a context
manager to create the Config
instance,
and include the mode='ephemeral'
argument.
For example:
from jnpr.junos import Device from jnpr.junos.utils.config import Config from jnpr.junos.exception import ConnectError from lxml import etree dev = Device(host='router1.example.net') try: dev.open() with Config(dev, mode='ephemeral') as cu: data = dev.rpc.get_config(options={'format':'text'}) print(etree.tostring(data, encoding='unicode')) dev.close() except ConnectError as err: print ("Cannot connect to device: {0}".format(err)) except Exception as err: print (err)
To retrieve data from a specific instance of the ephemeral
configuration database, first open the ephemeral instance and then
request the data. To open a user-defined instance of the ephemeral
configuration database, use a context manager to create the Config
instance, include the mode='ephemeral'
argument, and set the ephemeral_instance
argument to the name of the ephemeral instance.
from jnpr.junos import Device from jnpr.junos.utils.config import Config from jnpr.junos.exception import ConnectError from lxml import etree dev = Device(host='router1.example.net') try: dev.open() with Config(dev, mode='ephemeral', ephemeral_instance='eph1') as cu: data = dev.rpc.get_config(options={'format':'text'}) print(etree.tostring(data, encoding='unicode')) dev.close() except ConnectError as err: print ("Cannot connect to device: {0}".format(err)) except Exception as err: print (err)
Specify the Scope of Configuration Data to Return
In addition to retrieving the complete Junos OS configuration,
a Junos PyEZ application can retrieve specific portions of the configuration
by invoking the get_config()
RPC with the filter_xml
argument. The filter_xml
parameter takes a string containing the subtree filter that selects
the configuration statements to return. The subtree filter returns
the configuration data that matches the selection criteria.
To request multiple hierarchies, the filter_xml
string must include the <configuration>
root element. Otherwise, the value of filter_xml
must represent all levels of the configuration hierarchy starting
just under the root <configuration>
element
down to the hierarchy to display. To select a subtree, include the
empty tag for that hierarchy level. To return a specific object, include
a content match node that defines the element and value to match.
The following Junos PyEZ application retrieves and prints
the configuration at the [edit interfaces]
and [edit
protocols]
hierarchy levels in the candidate configuration:
from jnpr.junos import Device from lxml import etree with Device(host='router1.example.net') as dev: filter = '<configuration><interfaces/><protocols/></configuration>' data = dev.rpc.get_config(filter_xml=filter) print (etree.tostring(data, encoding='unicode', pretty_print=True))
The following example retrieves and prints the configuration
at the [edit system services]
hierarchy level using different
but equivalent values for the filter_xml
argument:
from jnpr.junos import Device from lxml import etree with Device(host='router1.example.net') as dev: data = dev.rpc.get_config(filter_xml='<system><services/></system>') print (etree.tostring(data, encoding='unicode', pretty_print=True)) data = dev.rpc.get_config(filter_xml='system/services') print (etree.tostring(data, encoding='unicode', pretty_print=True)) filter = etree.XML('<system><services/></system>') data = dev.rpc.get_config(filter_xml=filter) print (etree.tostring(data, encoding='unicode', pretty_print=True))
The following example retrieves the <name>
element for each <interface>
element
under the <interfaces>
hierarchy in
the post-inheritance candidate configuration:
from jnpr.junos import Device from lxml import etree with Device(host='router1.example.net') as dev: filter = '<interfaces><interface><name/></interface></interfaces>' data = dev.rpc.get_config(filter_xml=filter, options={'inherit':'inherit'}) print (etree.tostring(data, encoding='unicode', pretty_print=True))
user@server:~$ python3 junos-pyez-get-interface-names.py <configuration changed-seconds="1544032801" changed-localtime="2018-12-05 10:00:01 PST"> <interfaces> <interface> <name>ge-1/0/0</name> </interface> <interface> <name>ge-1/0/1</name> </interface> <interface> <name>lo0</name> </interface> <interface> <name>fxp0</name> </interface> </interfaces> </configuration>
The following example retrieves the subtree for the ge-1/0/1 interface:
from jnpr.junos import Device from lxml import etree with Device(host='router1.example.net') as dev: filter = '<interfaces><interface><name>ge-1/0/1</name></interface></interfaces>' data = dev.rpc.get_config(filter_xml=filter, options={'inherit':'inherit'}) print (etree.tostring(data, encoding='unicode', pretty_print=True))
user@server:~$ python3 junos-pyez-get-single-interface.py <configuration changed-seconds="1544032801" changed-localtime="2018-12-05 10:00:01 PST"> <interfaces> <interface> <name>ge-1/0/1</name> <description>customerA</description> <disable/> <unit> <name>0</name> <family> <inet> <address> <name>198.51.100.1/24</name> </address> </inet> </family> </unit> </interface> </interfaces> </configuration>
Specify the Format for Configuration Data to Return
The Junos PyEZ get_config()
RPC invokes
the Junos XML protocol <get-configuration>
operation, which can return Junos OS configuration data as Junos
XML elements, CLI configuration statements, Junos OS set
commands, or JavaScript Object Notation (JSON).
By default, the get_config()
RPC returns
configuration data as XML.
To specify the format in which to return the configuration data,
the Junos PyEZ application includes the options
dictionary with 'format':'format'
in the get_config()
argument
list. To request CLI configuration statements, Junos OS set
commands, or JSON format, set the format
value to text
, set
, or json
, respectively.
As in NETCONF and Junos XML protocol sessions, Junos PyEZ returns
the configuration data in the expected format enclosed within the
appropriate XML element for that format. The RPC reply encloses configuration
data in XML, text, or set
command formats
in <configuration>
, <configuration-text>
, and <configuration-set>
elements,
respectively.
from jnpr.junos import Device from lxml import etree from pprint import pprint with Device(host='router1.example.net') as dev: # XML format (default) data = dev.rpc.get_config() print (etree.tostring(data, encoding='unicode', pretty_print=True)) # Text format data = dev.rpc.get_config(options={'format':'text'}) print (etree.tostring(data, encoding='unicode', pretty_print=True)) # Junos OS set format data = dev.rpc.get_config(options={'format':'set'}) print (etree.tostring(data, encoding='unicode', pretty_print=True)) # JSON format data = dev.rpc.get_config(options={'format':'json'}) pprint (data)
Depending on the version of Python and the format of the output, you might need to modify the print statement to display more human-readable output.
Retrieve Configuration Data for Standard or Custom YANG Data Models
You can load standardized or custom YANG modules onto Junos devices to add data models that are not natively supported by Junos OS but can be supported by translation. You configure nonnative data models in the candidate configuration using the syntax defined for those models. When you commit the configuration, the data model’s translation scripts translate that data and commit the corresponding Junos OS configuration as a transient change in the checkout configuration.
The candidate and active configurations contain the configuration data for nonnative YANG data
models in the syntax defined by those models. Junos PyEZ applications can
retrieve configuration data for standard and custom YANG data models in addition
to retrieving the native Junos OS configuration by including the appropriate
arguments in the get_config()
RPC. By default, nonnative
configuration data is not included in the get_config()
RPC
reply.
To retrieve configuration data that is defined by a nonnative
YANG data model in addition to retrieving the Junos OS configuration,
execute the get_config()
RPC with the model
argument, and include the namespace
argument when appropriate. The model
argument
takes one of the following values:
custom
—Retrieve configuration data that is defined by custom YANG data models. You must include thenamespace
argument when retrieving data for custom YANG data models.ietf
—Retrieve configuration data that is defined by IETF YANG data models.openconfig
—Retrieve configuration data that is defined by OpenConfig YANG data models.True
—Retrieve all configuration data, including the complete Junos OS configuration and data from any YANG data models.
If you specify the ietf
or openconfig
value for the model
argument, Junos PyEZ automatically uses the appropriate namespace.
If you retrieve data for a custom YANG data model by using model='custom'
, you must also include the namespace
argument with the corresponding namespace.
If you include the model
argument
with the value custom
, ietf
, or openconfig
and also include the filter_xml
argument to return a specific XML subtree,
Junos OS only returns the matching hierarchy from the nonnative data
model. If the Junos OS configuration contains a hierarchy of the same
name, for example "interfaces", it is not included in the reply. The filter_xml
option is not supported when using model=True
.
In the following example, the get_config()
RPC retrieves the OpenConfig bgp
configuration hierarchy
from the candidate configuration on the device. If you omit the filter_xml
argument, the RPC returns the complete Junos
OS and OpenConfig candidate configurations.
from jnpr.junos import Device from lxml import etree with Device(host='router1.example.net') as dev: data = dev.rpc.get_config(filter_xml='bgp', model='openconfig') print (etree.tostring(data, encoding='unicode', pretty_print=True))
The following RPC retrieves the interfaces
configuration hierarchy from the candidate configuration for an
IETF YANG data model:
data = dev.rpc.get_config(filter_xml='interfaces', model='ietf') print (etree.tostring(data, encoding='unicode', pretty_print=True))
The following RPC retrieves the l2vpn
configuration
hierarchy from the candidate configuration for a custom YANG data
model with the given namespace:
data = dev.rpc.get_config(filter_xml='l2vpn', model='custom', namespace='http://yang.juniper.net/customyang/demo/l2vpn') print (etree.tostring(data, encoding='unicode', pretty_print=True))
The following RPC retrieves the complete Junos OS candidate configuration as well as the configuration data for other YANG data models that have been added to the device:
data = dev.rpc.get_config(model=True) print (etree.tostring(data, encoding='unicode', pretty_print=True))
Specify Additional RPC Options
When you use the Junos PyEZ get_config()
RPC to retrieve the configuration, it
invokes the Junos XML protocol <get-configuration>
operation. The RPC supports the options
argument, which enables
you to include a dictionary of key/value pairs of any attributes supported by
the <get-configuration>
operation. For the complete list
of attributes supported by the Junos XML protocol
<get-configuration>
operation, see <get-configuration>.
For example, the get_config()
RPC
retrieves data from the pre-inheritance configuration, in which the <groups>
, <apply-groups>
, <apply-groups-except>
, and <interface-range>
tags are separate elements in
the configuration output. To retrieve data from the post-inheritance
configuration, which displays statements that are inherited from user-defined
groups and ranges as children of the inheriting statements, you can
include the options
argument with 'inherit':'inherit'
.
For example, the following code retrieves the configuration
at the [edit system services]
hierarchy level from the
post-inheritance candidate configuration. In this case, if the configuration
also contains statements configured at the [edit groups global
system services]
hierarchy level, those statements would be
inherited under the [edit system services]
hierarchy in
the post-inheritance configuration and returned in the retrieved configuration
data.
from jnpr.junos import Device from lxml import etree with Device(host='router1.example.net') as dev: data = dev.rpc.get_config(filter_xml='system/services', options={'inherit':'inherit'}) print (etree.tostring(data, encoding='unicode', pretty_print=True))
How to Handle Namespaces in Configuration Data
The Junos PyEZ get_config()
RPC,
by default, strips out any namespaces in the returned configuration
data. Junos PyEZ applications can retain the namespace in the returned
configuration data, which enables you to load the data back onto a
device, such as when you want to quickly modify the existing configuration.
To retain namespaces in the configuration data, include
the remove_ns=False
argument in the get_config()
argument list. For example:
from jnpr.junos import Device from lxml import etree with Device(host='router1.example.net') as dev: data = dev.rpc.get_config(filter_xml='bgp', model='openconfig', remove_ns=False) print (etree.tostring(data, encoding='unicode', pretty_print=True))
In the following truncated output, the <bgp>
element retains the xmlns
attribute that defines the namespace:
<bgp xmlns="http://openconfig.net/yang/bgp"> <neighbors> <neighbor> <neighbor-address>198.51.100.1</neighbor-address> <config> <peer-group>OC</peer-group> <neighbor-address>198.51.100.1</neighbor-address> <enabled>true</enabled> <peer-as>64496</peer-as> </config> </neighbor> </neighbors> ...
If the get_config()
remove_ns=False
argument is omitted, the namespace
is not included in the output.
<bgp> <neighbors> <neighbor> <neighbor-address>198.51.100.1</neighbor-address> <config> <peer-group>OC</peer-group> <neighbor-address>198.51.100.1</neighbor-address> <enabled>true</enabled> <peer-as>64496</peer-as> </config> </neighbor> </neighbors> ...