Tutorial: Writing Perl Client Applications
This tutorial explains how to write a Perl client application that requests operational or configuration information from the NETCONF server or loads configuration information onto a device. The following sections use the sample scripts included in the NETCONF XML Protocol Perl distribution as examples:
- Import Perl Modules and Declare Constants
- Connect to the NETCONF Server
- Submitting a Request to the NETCONF Server
- Parsing and Formatting the Response from the NETCONF Server
- Closing the Connection to the NETCONF Server
Import Perl Modules and Declare Constants
Include the following statement at the start of the application. This statement imports the functions provided by the Net::Netconf::Manager object, which the application uses to connect to the NETCONF server on a device.
use Net::Netconf::Manager;
Include statements to import other Perl modules as appropriate for your application. For example, several of the sample scripts import the following standard Perl modules, which include functions that handle input from the command line:
- Carp—Includes functions for user error warnings.
- Getopt::Std—Includes functions for reading in keyed options from the command line.
- Term::ReadKey—Includes functions for controlling terminal modes, for example suppressing onscreen echo of a typed string such as a password.
If the application uses constants, declare their values at this
point. For example, the sample diagnose_bgp.pl script includes the following statement to declare a constant for
the access method:
use constant VALID_ACCESS_METHOD => 'ssh';
The edit_configuration.pl script
includes the following statements to declare constants for reporting
return codes and the status of the configuration database:
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;
Connect to the NETCONF Server
The following sections explain how to use the NET::Netconf::Manager object to connect to the NETCONF server on a device:
- Satisfy Protocol Prerequisites
- Group Requests
- Obtain and Record Parameters Required by the NET::Netconf::Manager Object
- Obtain Application-Specific Parameters
- Establishing the Connection
Satisfy Protocol Prerequisites
The NETCONF server supports several access protocols. For each connection to the NETCONF server on a device, the application must specify the protocol it is using. Client Perl applications can communicate with the NETCONF server via SSH only.
Before your application can run, you must satisfy the prerequisites for SSH. This involves enabling NETCONF on the device (set system services netconf ssh).
Group Requests
Establishing a connection to the NETCONF server on a device is one of the more time-intensive and resource-intensive functions performed by an application. If the application sends multiple requests to a device, it makes sense to send all of them within the context of one connection. If your application sends the same requests to multiple devices, you can structure the script to iterate through either the set of devices or the set of requests. Keep in mind, however, that your application can effectively send only one request to one NETCONF server at a time. This is because the NET::Netconf::Manager object does not return control to the application until it receives the closing </rpc-reply> tag that represents the end of the NETCONF server's response to the current request.
Obtain and Record Parameters Required by the NET::Netconf::Manager Object
The NET::Netconf::Manager object takes the following required parameters, specified as keys in a Perl hash:
- The access protocol to use when communicating with the NETCONF server (key name: access). Before the application runs, satisfy the SSH prerequisites.
- The name of the device to which to connect (key name: hostname). For best results, specify either a fully-qualified hostname or an IP address.
- The username under which to establish the connection to the NETCONF server and issue requests (key name: login). The username must already exist on the specified device and have the permission bits necessary for making the requests invoked by the application.
- The password for the username (key name: password).
The sample scripts record the parameters in a Perl hash called %deviceinfo, declared as follows:
my %deviceinfo = (
'access' => $access,
'login' => $login,
'password' => $password,
'hostname' => $hostname,
);The sample scripts obtain the parameters from options entered on the command line by a user. Your application can also obtain values for the parameters from a file or database, or you can hardcode one or more of the parameters into the application code if they are constant.
Example: Collect Parameters Interactively
Each sample script obtains the parameters required by the NET::Netconf::Manager object from command-line options provided by the user who invokes the script. The script records the options in a Perl hash called %opt, using the getopts function defined in the Getopt::Std Perl module to read the options from the command line. (Scripts used in production environments probably do not obtain parameters interactively, so this section is important mostly for understanding the sample scripts.)
In the following example from the get_chassis_inventory.pl script, the first parameter to the getopts function defines
the acceptable options, which vary depending on the application. A
colon after the option letter indicates that it takes an argument.
The second parameter, \%opt, specifies that the values are recorded in the %opt hash. If the user does not provide at least one option, provides an invalid option, or provides the -h option, the script invokes the output_usage subroutine, which prints a usage message to the screen:
my %opt;
getopts('l:p:d:x:f:m:o:h', \%opt) || output_usage();
output_usage() if $opt{'h'};The following code defines the output_usage subroutine
for the get_chassis_inventory.pl script.
The contents of the my $usage definition and the Where and Options sections are specific to the script,
and differ for each application.
sub output_usage
{
my $usage = "Usage: $0 [options] <target>
Where:
<target> The hostname of the target device.
Options:
-l <login> A login name accepted by the target device.
-p <password> The password for the login name.
-m <access> Access method. The only supported method is 'ssh'.
-x <format> The name of the XSL file to display the response.
Default: xsl/chassis_inventory.xsl
-f <xmlfile> The name of the XML file to print server response to.
Default: xsl/chassis_inventory.xml
-o <filename> output is written to this file instead of standard output.
-d <level> Debug level [1-6]\n\n";
croak $usage;
}The get_chassis_inventory.pl script includes the following code to obtain values from the command
line for the parameters required by the NET::Netconf::Manager object. A detailed discussion of the various functional units follows
the complete code sample.
# Get the hostname
my $hostname = shift || output_usage();
# Get the access method, can be ssh only
my $access = $opt{'m'} || 'ssh';
use constant VALID_ACCESS_METHOD => 'ssh';
output_usage() unless (VALID_ACCESS_METHOD =~ /$access/);
# Check for login name. If not provided, prompt for it
my $login = "";
if ($opt{'l'}) {
$login = $opt{'l'};
} else {
print STDERR "login: ";
$login = ReadLine 0;
chomp $login;
}
# Check for password. If not provided, prompt for it
my $password = "";
if ($opt{'p'}) {
$password = $opt{'p'};
} else {
print STDERR "password: ";
ReadMode 'noecho';
$password = ReadLine 0;
chomp $password;
ReadMode 'normal';
print STDERR "\n";
}In the first line of the preceding code sample, the script uses the Perl shift function to read the hostname from the end of the command line. If the hostname is missing, the script invokes the output_usage subroutine to print the usage message, which specifies that a hostname is required:
my $hostname = shift || output_usage();
The script next determines which access protocol to use, setting the $access variable to the value of the -m command-line option. If the specified value does not match the only valid value defined by the VALID_ACCESSES constant, the script invokes the output_usage subroutine to print the usage message.
my $access = $opt{'m'} || 'ssh';
use constant VALID_ACCESS_METHOD => 'ssh';
output_usage() unless (VALID_ACCESS_METHOD =~ /$access/);The script then determines the username, setting the $login variable to the value of the -l command-line option. If the option is not provided, the script prompts for it and uses the ReadLine function (defined in the standard Perl Term::ReadKey module) to read it from the command line:
my $login = "";
if ($opt{'l'}) {
$login = $opt{'l'};
} else {
print STDERR "login: ";
$login = ReadLine 0;
chomp $login;
}The script finally determines the password for the username, setting the $password variable to the value of the -p command-line option. If the option is not provided, the script prompts for it. It uses the ReadMode function (defined in the standard Perl Term::ReadKey module) twice: first to prevent the password from echoing visibly on the screen and then to return the shell to normal (echo) mode after it reads the password:
my $password = "";
if ($opt{'p'}) {
$password = $opt{'p'};
} else {
print STDERR "password: ";
ReadMode 'noecho';
$password = ReadLine 0;
chomp $password;
ReadMode 'normal';
print STDERR "\n";
}Obtain Application-Specific Parameters
In addition to the parameters required by the NET::Netconf::Manager object, applications might need to define other parameters, such as the name of the file to which to write the data returned by the NETCONF server in response to a request, or the name of the Extensible Stylesheet Transformation Language (XSLT) file to use for transforming the data.
As with the parameters required by the NET::Netconf::Manager object, your application can hardcode the values in the application code, obtain them from a file, or obtain them interactively. The sample scripts obtain values for these parameters from command-line options in the same manner as they obtain the parameters required by the NET::Netconf::Manager object. Several examples follow.
The following line enables a debugging trace if the user includes the -d command-line option.
my $debug_level = $opt{'d'};The following line sets the $outputfile variable to the value specified by the -o command-line option. It names the local file to which the NETCONF server's response is written. If the -o option is not provided, the variable is set to the empty string.
my $outputfile = $opt{'o'} || "";The following code from the diagnose_bgp.pl script defines which XSLT file to use to transform the NETCONF server's
response. The first line sets the $xslfile variable to the
value specified by the -x command-line option. If the option
is not provided, the script uses the text.xsl file supplied with the script, which transforms the data to ASCII
text. The if statement verifies that the specified XSLT file
exists; the script terminates if it does not.
# Get the xsl file
my $xslfile = $opt{'x'} || "xsl/bgp.xsl";
# Check for the existence of the given file
if (! -f $xslfile) {
croak "XSL file $xslfile does not exist.";
}Establishing the Connection
After obtaining values for the parameters required for the NET::Netconf::Manager object, each sample script records them in the %deviceinfo hash:
my %deviceinfo = (
'access' => $access,
'login' => $login,
'password' => $password,
'hostname' => $hostname,
);The script then invokes the NETCONF-specific new subroutine to create a NET::Netconf::Manager object and establish a connection to the specified routing, switching, or security platform. If the connection attempt fails (as tested by the ref operator), the script exits.
my $jnx = new Net::Netconf::Manager(%deviceinfo);
unless (ref $jnx) {
croak "ERROR: $deviceinfo{hostname}: failed to connect.\n";
}Submitting a Request to the NETCONF Server
After establishing a connection to a NETCONF server (see Submitting a Request to the NETCONF Server), your application can submit one or more requests by invoking the Perl methods that are supported in the version of the NETCONF XML protocol and Junos XML API used by the application:
- Each version of software supports a set of methods that correspond to CLI operational mode commands (later releases generally support more methods). For a list of the operational methods supported in the current version, see the files stored in the lib\Net\Netconf\Plugins\Plugin\release directory of the NETCONF Perl distribution (release is the Junos OS version code, such as 6.1R1 for the initial version of Junos OS Release 6.1). The files have names in the format package_methods.pl, where package is a software package.
- The set of methods that correspond to operations on configuration
objects is defined in the
lib/Net/Netconf/Plugins.pmfile in the NETCONF distribution.
See the following sections for more information:
- Providing Method Options or Attributes
- Submitting a Request
- Example: Get an Inventory of Hardware Components
- Example: Edit Configuration Statements
Providing Method Options or Attributes
Many Perl methods have one or more options or attributes. The
following list describes the notation used to define a method's options
in the lib/Net/Netconf/Plugins.pm and lib/Net/Netconf/release/package_methods.pl files, and the notation that an application
uses when invoking the method:
- A method without options is defined as $NO_ARGS, as in the following entry for the get_autoinstallation_status_information method:
## Method : get-autoinstallation-status-information ## Returns: autoinstallation-status-information ## Command: "show system autoinstallation status" get_autoinstallation_status_information => $NO_ARGS,
To invoke a method without options, follow the method name with an empty set of parentheses as in the following example:
$jnx->get_autoinstallation_status_information( );
- A fixed-form option is defined as type $TOGGLE. In the following example, the get_software_information method takes two fixed-form options, brief and detail:
## Method : <get-ancp-neighbor-information> ## Returns: <ancp-neighbor-information> ## Command: "show ancp neighbor" get_ancp_neighbor_information => { brief => $TOGGLE, detail => $TOGGLE, }To include a fixed-form option when invoking a method, set it to the value 1 (one) as in the following example:
$jnx->get-ancp-neighbor-information(brief => 1);
- An option with a variable value is defined as type $STRING. In the following example, the get_cos_drop_profile_information method takes the profile_name argument:
## Method : <get-passive-monitoring-usage-information> ## Returns: <passive-monitoring-usage-information> ## Command: "show passive-monitoring usage" get_passive_monitoring_usage_information => { interface_name => $STRING, }To include a variable value when invoking a method, enclose the value in single quotes as in the following example:
$jnx->get_cos_drop_profile_information(profile_name => 'user-drop-profile');
- A set of configuration statements or corresponding tag
elements is defined as type $DOM. In the following example,
the get_config method takes a set of configuration statements
(along with two attributes):
'get_config' => { 'source' => $DOM_STRING, 'source_url' => $URL_STRING, 'filter' => $DOM },A DOM object is XML code:
my $xml_string = " <filter type=\"subtree\"> <configuration> <protocols> <bgp></bgp> </protocols> </configuration> </filter> "; my %queryargs = ( 'source' => "running", 'filter' => $xml_string, );This generates an RPC request:
<rpc message-id='1'> <get-config> <source> <running/> </source> <filter type="subtree"> <configuration> <protocols> <bgp></bgp> </protocols> </configuration> </filter> </get-config></rpc>
A method can have a combination of fixed-form options, options with variable values, attributes, and a set of configuration statements. For example, the get_forwarding_table_information method has four fixed-form options and five options with variable values:
Submitting a Request
The following code is the recommended way to send a request to the NETCONF server and shows how to handle error conditions. The $jnx variable is defined to be a NET::Netconf::Manager object.
my $res; # Netconf server response
# connect to the Netconf server
my $jnx = new Net::Netconf::Manager(%deviceinfo);
unless (ref $jnx) {
croak "ERROR: $deviceinfo{hostname}: failed to connect.\n";
}
# Lock the configuration database before making any changes
print "Locking configuration database ...\n";
my %queryargs = ( 'target' => 'candidate' );
$res = $jnx->lock_config(%queryargs);
# See if you got an error
if ($jnx->has_error) {
print "ERROR: in processing request \n $jnx->{'request'} \n";
graceful_shutdown($jnx, STATE_CONNECTED, REPORT_FAILURE);
}
# 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, STATE_LOCKED, REPORT_FAILURE);
}
# Read in the XML file
my $config = read_xml_file($xmlfile);
print "\n\n$config \n\n";
%queryargs = (
'target' => 'candidate',
'config' => $config
);
$res = $jnx->edit_config(%queryargs);
# See if you got an error
if ($jnx->has_error) {
print "ERROR: in processing request \n $jnx->{'request'} \n";
# Get the error
my $error = $jnx->get_first_error();
get_error_info(%$error);
# Disconnect
graceful_shutdown($jnx, STATE_LOCKED, REPORT_FAILURE);
}
# Commit the changes
print "Committing the edit-config changes ...\n";
$jnx->commit();
if ($jnx->has_error) {
print "ERROR: Failed to commit the configuration.\n";
graceful_shutdown($jnx, STATE_CONFIG_LOADED, REPORT_FAILURE);
}
# Unlock the configuration database and
# disconnect from the Netconf server
print "Disconnecting from the Netconf server ...\n";
graceful_shutdown($jnx, STATE_LOCKED, REPORT_SUCCESS);Example: Get an Inventory of Hardware Components
The get_chassis_inventory.pl script retrieves and displays a detailed inventory of the hardware
components installed in a routing, swtiching, or security platform.
It is equivalent to issuing the show chassis hardware detail command.
After establishing a connection to the NETCONF server, the script defines get_chassis_inventory as the request to send and includes the detail argument:
my $query = "get_chassis_inventory"; my %queryargs = ( 'detail' => 1 );
The script sends the query and assigns the results to the $res variable. It performs two tests on the results, and prints an error message if it cannot send the request or if errors occurred when executing it. If no errors occurred, the script uses XSLT to transform the results.
# send the command and get the server response
my $res = $jnx->$query(%queryargs);
print "Server request: \n $jnx->{'request'}\n Server response: \n $jnx->{'server_response'} \n";
# print the server response into xmlfile
print_response($xmlfile, $jnx->{'server_response'});
# See if you got an error
if ($jnx->has_error) {
croak "ERROR: in processing request \n $jnx->{'request'} \n";
} else {
# Transform the server response using XSL file
my $res = new Net::Netconf::Transform();
print "Transforming ...\n";
my $nm = $res->translateXSLtoRelease('xmlns:lc', $xslfile,
"$xslfile.tmp",
$xmlfile);
if ($nm) {
format_by_xslt($nm, $xmlfile, );
} else {
print STDERR "ERROR: Invalid XSL File $xslfile\n";
}
}
# Disconnect from the Netconf server
$jnx->disconnect();Example: Edit Configuration Statements
The edit_configuration.pl script
edits configuration statements and loads the configuration onto a
device. It uses the basic structure for sending requests but also
defines a graceful_shutdown subroutine that handles errors.
The following sections describe the different functions that the script
performs:
- Handling Error Conditions
- Locking the Configuration
- Reading In the Configuration Data
- Editing the Configuration Data
- Committing the Configuration
Handling Error Conditions
The graceful_shutdown subroutine in the edit_configuration.pl script handles errors in a
slightly more elaborate manner than the generic structure described
in Handling Error Conditions . It employs
the following additional constants:
# query execution status 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 edit_configuration.pl script.
sub graceful_shutdown
{
my ($jnx, $state, $success) = @_;
if ($state >= STATE_CONFIG_LOADED) {
# We have already done an <edit-config> operation
# - Discard the changes
print "Discarding the changes made ...\n";
$jnx->discard_changes();
if ($jnx->has_error) {
print "Unable to discard <edit-config> changes\n";
}
}
if ($state >= STATE_LOCKED) {
# Unlock the configuration database
$jnx->unlock_config();
if ($jnx->has_error) {
print "Unable to unlock the candidate configuration\n";
}
}
if ($state >= STATE_CONNECTED) {
# Disconnect from the Netconf server
$jnx->disconnect();
}
if ($success) {
print "REQUEST succeeded !!\n";
} else {
print "REQUEST failed !!\n";
}
exit;
}Locking the Configuration
The main section of the edit_configuration.pl script begins by establishing a connection to a NETCONF server.
It then invokes the lock_configuration method to lock the
configuration database. In case of error, the script invokes the graceful_shutdown subroutine described in Handling Error Conditions .
print "Locking configuration database ...\n";
my %queryargs = ( 'target' => 'candidate' );
$res = $jnx->lock_config(%queryargs);
# See if you got an error
if ($jnx->has_error) {
print "ERROR: in processing request \n $jnx->{'request'} \n";
graceful_shutdown($jnx, STATE_CONNECTED, REPORT_FAILURE);
}Reading In the Configuration Data
In the following code sample, the edit_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, STATE_LOCKED, REPORT_FAILURE);
}
# Read in the XML file
my $config = read_xml_file($xmlfile);
print "\n\n$config \n\n";
%queryargs = (
'target' => 'candidate'
);
# If we are in text mode, use config-text arg with wrapped
# configuration-text, otherwise use config arg with raw XML
if ($opt{t}) {
$queryargs{'config-text'} = '<configuration text> . $config . </configuration-text>';
} else {
$queryargs{'config'} = $config;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, STATE_LOCKED, REPORT_FAILURE);
}The script then invokes the read_xml_file subroutine, which opens the file for reading and return its contents in the $config variable. The queryargs key target is set to the value candidate. When the script calls the edit_configuration method, the candidate configuration is edited.
# Read in the XML file
my $config = read_xml_file($xmlfile);
print "\n\n$config \n\n";
%queryargs = (
'target' => 'candidate'
);
If the -t command-line option was included when the edit_configuration.pl script was invoked, the file
referenced by the $xmlfile variable should contain ASCII-formatted
configuration statements like those returned by the CLI configuration-mode show command. If the configuration statements are in ASCII-formatted
text, the script encloses the configuration stored in the $config variable within the <configuration-text> tag
element and stores the result in the value associated with the queryargs hash key config-text.
If the -t command-line option was not included when
the edit_configuration.pl script
was invoked, the file referenced by the $xmlfile variable
contains Junos XML configuration tag elements. In this case, the script
stores just the $config variable as the value associated
with the queryargs hash key config.
if ($opt{t}) {
$queryargs{'config-text'} = '<configuration text> . $config . </configuration-text>';
} else {
$queryargs{'config'} = $config;Editing the Configuration Data
The script now invokes the edit_config method to edit the candidate configuration on the device. It invokes the graceful_shutdown subroutine if the response from the NETCONF server has errors.
$res = $jnx->edit_config(%queryargs);
# See if you got an error
if ($jnx->has_error) {
print "ERROR: in processing request \n $jnx->{'request'} \n";
# Get the error
my $error = $jnx->get_first_error();
get_error_info(%$error);
# Disconnect
graceful_shutdown($jnx, STATE_LOCKED, REPORT_FAILURE);Committing the Configuration
If there are no errors, the script invokes the commit method:
# Commit the changes
print "Committing the <edit-config> changes ...\n";
$jnx->commit();
if ($jnx->has_error) {
print "ERROR: Failed to commit the configuration.\n";
graceful_shutdown($jnx, STATE_CONFIG_LOADED, REPORT_FAILURE);
}Parsing and Formatting the Response from the NETCONF Server
As the last step in sending a request, the application verifies that there are no errors with the response from the NETCONF server. It can then write the response to a file, to the screen, or both. If the response is for an operational query, the application usually uses XSLT to transform the output into a more readable format, such as HTML or formatted ASCII. If the response consists of configuration data, the application can store it as XML (the Junos XML tag elements generated by default from the NETCONF server) or transform it into formatted ASCII text.
The following sections discuss parsing and formatting options:
Parsing and Formatting an Operational Response
The following code sample from the diagnose_bgp.pl script uses XSLT to transform an operational response from the NETCONF
server into a more readable format. A detailed discussion of the functional
subsections follows the complete code sample.
# Get the output file
my $outputfile = $opt{'o'} || "";
# Get the xsl file
my $xslfile = $opt{'x'} || "xsl/bgp.xsl";
# Check for the existence of the given file
if (! -f $xslfile) {
croak "XSL file $xslfile does not exist.";
}
# Get the xmlfile
my $xmlfile = $opt{'f'} || "xsl/bgp.xml";
# send the command and get the server response
my $res = $jnx->$query();
# print the server response into xmlfile
print_response($xmlfile, $jnx->{'server_response'});
# See if you got an error
if ($jnx->has_error) {
croak "ERROR: in processing request \n $jnx->{'request'} \n";
} else {
# Transform the server response using XSL file
my $res = new Net::Netconf::Transform();
print "Transforming ...\n";
my $nm = $res->translateXSLtoRelease('xmlns:lc', $xslfile,
"$xslfile.tmp",
$xmlfile);
if ($nm) {
format_by_xslt($nm, $xmlfile, );
} else {
print STDERR "ERROR: Invalid XSL File $xslfile\n";
}
}The first line of the preceding code sample illustrates how the scripts read the -o option from the command line to obtain the name of the file into which to write the results of the XSLT transformation:
my $outputfile = $opt{'o'} || "";From the -x command-line option, the scripts obtain
the name of the XSLT file to use, setting a default value if the option
is not provided. The scripts exit if the specified file does not exist.
The following example is from the diagnose_bgp.pl script:
my $xslfile = $opt{'x'} || "xsl/bgp.xsl";
if (! -f $xslfile) {
croak "XSL file $xslfile does not exist.";
}For examples of XSLT files, see the following directories in the NETCONF Perl distribution:
- The
examples/diagnose_bpg/xsldirectory contains an XSLT file for thediagnose_bpg.plscript. - The
examples/get_chassis_inventory/xsldirectory contains XSLT files for theget_chassis_inventory.plscript.
The actual parsing operation invokes the translateXSLtoRelease function (defined in the Net::Netconf::Transform module) to alter one of the namespace definitions in the XSLT file.
my $res = new Net::Netconf::Transform();
print "Transforming ...\n";
my $nm = $res->translateXSLtoRelease('xmlns:lc', $xslfile,
"$xslfile.tmp",
$xmlfile);
if ($nm) {
format_by_xslt($nm, $xmlfile, );
} else {
print STDERR "ERROR: Invalid XSL File $xslfile\n";
}This is necessary because the XSLT 1.0 specification requires that every XSLT file define a specific value for each default namespace used in the data being transformed. The xmlns attribute in a NETCONF operational response tag element includes a code representing the Junos OS version, such as10.3R1 for the initial version of Junos OS Release 10.3. Because the same XSLT file can be applied to operational response tag elements from devices running different versions of the Junos OS, the XSLT file cannot predefine an xmlns namespace value that matches all versions. The translateXSLtoRelease function alters the namespace definition in the XSLT file identified by the $xslfile variable to match the value in the NETCONF server's response. It assigns the resulting XSLT file to the $nm variable.
After verifying that the translateXSLtoRelease function succeeded, the script invokes the format_by_xslt function, which builds a command string and assigns it to the $command variable. The first part of the command string invokes the xsltproc command and specifies the names of the XSLT and configuration data files ($xslfile and $xmlfile)::
sub format_by_xslt
{
my ($xslfile, $xmlfile, $outfile) = @_;
print "Transforming $xmlfile with $xslfile...\n" if $outfile;
my $command = "xsltproc $xslfile $xmlfile";
$command .= "> $outfile" if $outfile;
system($command);
print "Done\n" if $outfile;
print "See $outfile\n" if $outfile;
}If the $outfile variable is defined (the file for storing the result of the XSLT transformation exists), the script appends a string to the $command variable to write the results of the xsltproc command to the file. (If the file does not exist, the script writes the results to standard out [stdout].) The script then invokes the system function to execute the command string and prints status messages to stdout.
If the translateXSLtoRelease function fails (the if ($nm) expression evaluates to “false”), the script prints an error:
if ($nm) {
format_by_xslt($nm, $xmlfile, );
} else {
print STDERR "ERROR: Invalid XSL File $xslfile\n";
}Closing the Connection to the NETCONF Server
To end the NETCONF session and close the connection to the device, each sample script invokes the disconnect method. Several of the scripts do this in standalone statements:
$jnx->disconnect();
The edit_configuration.pl script
invokes the graceful_shutdown method instead.
graceful_shutdown($jnx, $xmlfile, STATE_LOCKED, REPORT_SUCCESS);
The graceful_shutdown method takes the appropriate actions with regard to the configuration database and then invokes the disconnect method.
Hide Navigation Pane
Show Navigation Pane
Download
SHA1