Use Junos PyEZ to Manage the Rescue Configuration on Junos Devices
The Junos PyEZ
jnpr.junos.utils.config.Config
utility enables you to manage the rescue configuration on Junos devices. 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.
How to Manage the Rescue Configuration
The
jnpr.junos.utils.config.Config
utility enables you to save, retrieve, load, and delete the rescue
configuration on a Junos device. 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.
- Save a Rescue Configuration
- Retrieve the Rescue Configuration
- Load and Commit the Rescue Configuration
- Delete the Rescue Configuration
Save 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')
Retrieve 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'))
Load and Commit 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()
Delete 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: Use Junos PyEZ to Save a Rescue Configuration
This example uses the Junos PyEZ
jnpr.junos.utils.config.Config
utility to save a rescue configuration on a Junos device, if one does not
already exist.
Requirements
This example uses the following hardware and software components:
Configuration management server running Python 3.5 or later and Junos PyEZ Release 2.0 or later
Junos device 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 Junos device
Overview
This example presents a Python application 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 application imports the Device
class, which handles the connection
with the Junos device; 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 Junos devices. After creating the
Device
instance for the target device, the
open()
method establishes a connection and NETCONF session with the device.
The application 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 application 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 application calls the
close()
method to terminate the NETCONF session and connection. The
application includes code for handling exceptions such as
ConnectError
for errors that occur when connecting to the
device. The application also includes code to handle any additional exceptions
that might occur.
Configuration
Create the Junos PyEZ Application
Step-by-Step Procedure
To create a Python application that uses Junos PyEZ to save a rescue configuration, if one does not already exist on the Junos device:
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 application. If the application does not display the intended code, repeat the instructions in this example to correct the application.
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()
Execute the Junos PyEZ Code
Execute the Application
To execute the Junos PyEZ code:
-
On the configuration management server, execute the application.
user@server:~$ python3 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 application a second time, it outputs the rescue configuration that was saved during the initial execution.
Verification
Verify the Configuration
Purpose
Verify that the rescue configuration exists on the Junos device.
Action
Log in to the Junos device 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
Troubleshoot 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"
.