Using Junos PyEZ to Manage the Rescue Configuration on Devices Running Junos OS
The Junos PyEZ jnpr.junos.utils.config.Config
utility enables
you to manage the rescue configuration on devices running Junos OS.
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.
Managing the Rescue Configuration
The jnpr.junos.utils.config.Config
utility enables
you to save, retrieve, load, and delete the rescue configuration on
a device running Junos OS. After creating an instance of the Config
class, you use the rescue()
method to mange the rescue configuration.
Specify the action to perform on the rescue configuration by setting
the rescue()
method action
parameter to the desired operation. Valid action values include "save"
, "get"
, "reload"
, and "delete"
.
The following examples illustrate the method call for each rescue()
method action.
Saving a Rescue Configuration
When you create a rescue configuration, the device saves
the most recently committed configuration as the rescue configuration.
To save the active configuration as the rescue configuration, specify action="save"
in the rescue()
method argument list. This operation overwrites any existing rescue
configuration. For example:
from jnpr.junos import Device
from jnpr.junos.utils.config import Config
with Device(host='dc1a.example.com') as dev:
cu = Config(dev)
cu.rescue(action="save")
Retrieving the Rescue Configuration
To retrieve an existing rescue configuration, specify action="get"
, and optionally specify the format as "json"
, "text"
or "xml"
. If you do not specify a format, the default
format is text. If the device does not have an existing rescue configuration,
the rescue()
method returns None
.
The following example retrieves and prints the rescue configuration, if one exists.
from jnpr.junos import Device
from jnpr.junos.utils.config import Config
from lxml import etree
with Device(host='dc1a.example.com') as dev:
cu = Config(dev)
rescue = cu.rescue(action="get", format="xml")
if rescue is None:
print ("No existing rescue configuration.")
else:
print (etree.tostring(rescue, encoding='unicode'))
Loading and Committing the Rescue Configuration
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 attempts to load the rescue configuration, and if one exists, commits it to make it the active configuration.
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()
Deleting the Rescue Configuration
To delete the existing rescue configuration, specify action="delete"
.
from jnpr.junos import Device
from jnpr.junos.utils.config import Config
with Device(host='dc1a.example.com') as dev:
cu = Config(dev)
cu.rescue(action="delete")
Example: Using Junos PyEZ to Save a Rescue Configuration
Juniper Networks provides support for using
Python to manage devices running Junos OS. This example outlines
how to use the Junos PyEZ jnpr.junos.utils.config.Config
utility to save
a rescue configuration on a device running Junos OS, if one does not
already exist.
Requirements
This example uses the following hardware and software components:
Configuration management server running Python 2.7 or 3.4 and Junos PyEZ Release 2.0 or later
Device running Junos OS with NETCONF enabled and a user account configured with appropriate permissions
SSH public/private key pair configured for the appropriate user on the server and device running Junos OS
Overview
This example presents a Python program that uses the Junos PyEZ Config
utility to save a rescue configuration on the
specified device. 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. When you create a rescue configuration, the
device saves the most recently committed configuration as the rescue
configuration.
The Python program imports the Device
class, which handles the connection with the device running Junos
OS; the Config
class, which is used to
perform the rescue configuration operations on the target device;
and required exceptions from the jnpr.junos.exception
module, which contains exceptions encountered when managing devices
running Junos OS. After creating the Device
instance for the target device, the open()
method establishes a connection and NETCONF
session with the device.
The program first determines if there is an existing rescue
configuration on the target device. If a rescue configuration exists,
it is printed to standard output. If there is no existing rescue configuration,
the program instructs the device to create one. The rescue()
method action
parameter is set to "get"
to retrieve
the existing rescue configuration and to "save"
to create a rescue configuration if one does not exist.
After performing the rescue configuration operations, the NETCONF
session and connection are terminated using the close()
method. The Python program includes code
for handling exceptions such as ConnectError
for errors that occur when connecting to the device. The program
also includes code to handle any additional exceptions that might
occur.
Configuration
Creating the Junos PyEZ Program
Step-by-Step Procedure
To create a Python program that uses Junos PyEZ to save a rescue configuration if one does not already exist on the device running Junos OS:
- Import any required modules, classes, and objects.
from jnpr.junos import Device from jnpr.junos.utils.config import Config from jnpr.junos.exception import ConnectError
- Include any required variables, which for this example
includes the hostname of the managed device.
host = 'dc1a.example.com'
- Create a
main()
function definition and function call, and place the remaining statements within the definition.def main(): if __name__ == "__main__": main()
- Create an instance of the
Device
class, and supply the hostname and any parameters required for that specific connection.dev = Device(host=host)
- Open a connection and establish a NETCONF session with
the device.
# open a connection with the device and start a NETCONF session try: dev.open() except ConnectError as err: print ("Cannot connect to device: {0}".format(err)) return
- Create an instance of the
Config
utility.# Create an instance of Config cu = Config(dev)
- Print the existing rescue configuration or save one if
none exists.
# Print existing rescue configuration or save one if none exists try: rescue = cu.rescue(action="get", format="text") if rescue is None: print ("No existing rescue configuration.") print ("Saving rescue configuration.") cu.rescue(action="save") else: print ("Rescue configuration found:") print (rescue) except Exception as err: print (err)
- End the NETCONF session and close the connection with
the device.
# End the NETCONF session and close the connection dev.close()
Results
On the configuration management server, review the completed program. If the program does not display the intended code, repeat the instructions in this example to correct the program.
from jnpr.junos import Device
from jnpr.junos.utils.config import Config
from jnpr.junos.exception import ConnectError
host = 'dc1a.example.com'
def main():
dev = Device(host=host)
# open a connection with the device and start a NETCONF session
try:
dev.open()
except ConnectError as err:
print ("Cannot connect to device: {0}".format(err))
return
# Create an instance of Config
cu = Config(dev)
# Print existing rescue configuration or save one if none exists
try:
rescue = cu.rescue(action="get", format="text")
if rescue is None:
print ("No existing rescue configuration.")
print ("Saving rescue configuration.")
cu.rescue(action="save")
else:
print ("Rescue configuration found:")
print (rescue)
except Exception as err:
print (err)
# End the NETCONF session and close the connection
dev.close()
if __name__ == "__main__":
main()
Executing the Junos PyEZ Code
Step-by-Step Procedure
To execute the Junos PyEZ code:
On the configuration management server, execute the program.
user@server:~$ python junos-pyez-config-rescue-create.py
No existing rescue configuration. Saving rescue configuration.
In this example, the target device does not have an existing rescue configuration, so the device saves one. If you execute the program a second time, it outputs the rescue configuration that was saved during the initial execution.
Verification
Verifying the Configuration
Purpose
Verify that the rescue configuration exists on the device running Junos OS.
Action
Log in to the device running Junos OS and view the rescue configuration. For example:
user@dc1a> show system configuration rescue
## Last changed: 2014-07-31 17:59:04 PDT version 13.3R1.8; groups { re0 { system { host-name dc1a; ... [output truncated]
Troubleshooting
Troubleshooting Unsupported Action Errors
Problem
The Junos PyEZ code generates an error message indicating an unsupported action.
unsupported action:
This error message is generated when the rescue()
method action
argument contains an invalid
value.
Solution
Set the rescue()
method action
argument to a valid action, which includes "save"
, "get"
, "reload"
, and "delete"
.