Example: Change the Configuration Using Junos XML Protocol Perl Client Applications
The Junos XML protocol Perl distribution includes
several sample Perl scripts that perform various functions on devices
running Junos OS. The load_configuration.pl script locks, modifies, uploads, and commits the configuration on
a device. It uses the basic structure for sending requests described
in Submitting a Request to the Junos XML
Protocol Server in Perl Client Applications but also defines
a graceful_shutdown
subroutine that handles
errors. The following sections describe the different functions that
the script performs:
Handling Error Conditions
The graceful_shutdown
subroutine
in the load_configuration.pl script
handles errors encountered in the Junos XML protocol session. It employs
the following additional constants:
use constant REPORT_SUCCESS => 1; use constant REPORT_FAILURE => 0; use constant STATE_CONNECTED => 1; use constant STATE_LOCKED => 2; use constant STATE_CONFIG_LOADED => 3;
The first two if
statements in the subroutine refer
to the STATE_CONFIG_LOADED
and STATE_LOCKED
conditions, which apply specifically to
loading a configuration in the load_configuration.pl script. The eval
statement ensures that any errors that
occur during execution of the enclosed function call are trapped so
that failure of the function call does not cause the script to exit.
sub graceful_shutdown { my ($jnx, $req, $state, $success) = @_; if ($state >= STATE_CONFIG_LOADED) { print "Rolling back configuration ...\n"; eval { $jnx->load_configuration(rollback => 0); }; } if ($state >= STATE_LOCKED) { print "Unlocking configuration database ...\n"; eval { $jnx->unlock_configuration(); }; } if ($state >= STATE_CONNECTED) { print "Disconnecting from the device ...\n"; eval { $jnx->request_end_session() $jnx->disconnect(); }; } if ($success) { die "REQUEST $req SUCCEEDED\n"; } else { die "REQUEST $req FAILED\n"; }; }
Locking the Configuration
The main section of the load_configuration.pl script begins by establishing a connection to a Junos XML protocol
server. It then invokes the lock_configuration
method to lock the configuration database. If an error occurs, the
script invokes the graceful_shutdown
subroutine
described in Handling Error Conditions.
print "Locking configuration database ...\n"; my $res = $jnx->lock_configuration(); my $err = $res->getFirstError(); if ($err) { print "ERROR: $deviceinfo{hostname}: failed to lock configuration. Reason: $err->{message}.\n"; graceful_shutdown($jnx, $xmlfile, STATE_CONNECTED, REPORT_FAILURE); }
Reading In and Parsing the Configuration Data
In the following code sample, the load_configuration.pl script reads in and parses a file that contains Junos XML configuration tag elements or ASCII-formatted statements. A detailed discussion of the functional subsections follows the complete code sample.
# Load the configuration from the given XML file print "Loading configuration from $xmlfile ...\n"; if (! -f $xmlfile) { print "ERROR: Cannot load configuration in $xmlfile\n"; graceful_shutdown($jnx, $xmlfile, STATE_LOCKED, REPORT_FAILURE); } my $parser = new XML::DOM::Parser; ... my $doc; if ($opt{t}) { my $xmlstring = get_escaped_text($xmlfile); $doc = $parser->parsestring($xmlstring) if $xmlstring; } else { $doc = $parser->parsefile($xmlfile); } unless ( ref $doc ) { print "ERROR: Cannot parse $xmlfile, check to make sure the XML data is well-formed\n"; graceful_shutdown($jnx, $xmlfile, STATE_LOCKED, REPORT_FAILURE); }
The first subsection of the preceding code sample verifies the
existence of the file containing configuration data. The name of the
file was previously obtained from the command line and assigned to
the $xmlfile
variable. If the file does
not exist, the script invokes the graceful_shutdown
subroutine:
print "Loading configuration from $xmlfile ...\n"; if (! -f $xmlfile) { print "ERROR: Cannot load configuration in $xmlfile\n"; graceful_shutdown($jnx, $xmlfile, STATE_LOCKED, REPORT_FAILURE); }
If the -t
command-line option was included when the load_configuration.pl script was invoked, the file
referenced by the $xmlfile
variable should
contain formatted ASCII configuration statements like those returned
by the CLI configuration-mode show
command. The script
invokes the get_escaped_text
subroutine
described in Converting Disallowed Characters
in Junos XML Protocol Perl Client Applications, assigning
the result to the $xmlstring
variable.
The script invokes the parsestring
function
to transform the data in the file into the proper format for loading
into the configuration hierarchy, and assigns the result to the $doc
variable. The parsestring
function is defined in the XML::DOM::Parser
module, and the first line in the following sample code instantiates
the module as an object, setting the $parser
variable to refer to it:
my $parser = new XML::DOM::Parser; ... my $doc; if ($opt{t}) { my $xmlstring = get_escaped_text($xmlfile); $doc = $parser->parsestring($xmlstring) if $xmlstring;
If the -t
command-line option was included when the load_configuration.pl script was invoked, the file
referenced by the $xmlfile
variable contains
Junos XML configuration tag elements instead. In this case, the script
invokes the parsefile
function (also defined
in the XML::DOM::Parser
module) on the
file.
} else { $doc = $parser->parsefile($xmlfile); }
If the parser cannot transform the file, the script invokes
the graceful_shutdown
subroutine described
in Handling Error Conditions.
unless ( ref $doc ) { print "ERROR: Cannot parse $xmlfile, check to make sure the XML data is well-formed\n"; graceful_shutdown($jnx, $xmlfile, STATE_LOCKED, REPORT_FAILURE); }
Loading the Configuration Data
The script now invokes the load_configuration
method to load the configuration changes onto the device. It places
the statement inside an eval
block to ensure
that the graceful_shutdown
subroutine is
invoked if the response from the Junos XML protocol server has errors.
eval { $res = $jnx->load_configuration( format => $config_format, action => $load_action, configuration => $doc); }; if ($@) { print "ERROR: Failed to load the configuration from $xmlfile. Reason: $@\n"; graceful_shutdown($jnx, $xmlfile, STATE_CONFIG_LOADED, REPORT_FAILURE); exit(1); }
The variables used to define the method’s three arguments were set at previous points in the application file:
The
$config_format
variable is set to "xml" unless the-t
command-line option was included when invoking the script.my $config_format = "xml"; $config_format = "text" if $opt{t};
The
$load_action
variable is set to "merge" unless the-a
command-line option was included when invoking the script. The final two lines verify that the specified value is valid.my $load_action = "merge"; $load_action = $opt{a} if $opt{a}; use constant VALID_ACTIONS => "merge|replace|override"; output_usage() unless ( $load_action =~ /VALID_ACTIONS/);
The
$doc
variable contains the output from theparsestring
orparsefile
function (defined in theXML::DOM::Parser
module).
The script performs two additional checks for errors
and invokes the graceful_shutdown
subroutine
in either case.
unless ( ref $res ) { print "ERROR: Failed to load the configuration from $xmlfile\n"; graceful_shutdown($jnx, $xmlfile, STATE_LOCKED, REPORT_FAILURE); } $err = $res->getFirstError(); if ($err) { print "ERROR: Failed to load the configuration. Reason: $err->{message}\n"; graceful_shutdown($jnx, $xmlfile, STATE_CONFIG_LOADED, REPORT_FAILURE); }
Committing the Configuration
If there are no errors up to this point, the script invokes
the commit_configuration
method (defined
in the file lib/JUNOS/Methods.pm in
the Junos XML protocol Perl distribution) to commit the configuration
on the device and make it the active configuration.
print "Committing configuration from $xmlfile ...\n"; $res = $jnx->commit_configuration(); $err = $res->getFirstError(); if ($err) { print "ERROR: Failed to commit configuration. Reason: $err->{message}.\n"; graceful_shutdown($jnx, $xmlfile, STATE_CONFIG_LOADED, REPORT_FAILURE); }