Example: Generating Persistent and Transient Configuration Changes Using Commit Scripts
Example: Generating a Persistent Change
Junos OS commit scripts enable users to customize the validation process of their configurations in accordance with their own practices and policies and enforce custom configuration rules during the commit process. This example demonstrates a commit script that generates a persistent change that adds the family mpls statement in the configuration of SONET/SDH interfaces when the statement is not already included in the configuration. If you do not explicitly configure the MPLS protocol family on an interface, the interface is not enabled for MPLS applications.
Requirements
This example uses the following hardware and software components:
Device running Junos OS with one or more SONET/SDH interfaces.
Junos OS Release 16.1R3 or later release when using a Python script.
Overview and Commit Script
The commit script in this example finds all SONET/SDH interfaces that have a logical interface configured but that do not have the family mpls statement configured. For these interfaces, the script adds the family mpls statement to the interface configuration as a persistent change at the [edit interfaces interface-name unit logical-unit-number] hierarchy level. The script is shown in SLAX, XSLT, and Python.
The SLAX and XSLT versions of the commit script generate the
persistent change by using the jcs:emit-change
template, which is a helper template contained in the junos.xsl
import file. The tag
parameter of the jcs:emit-change
template
is omitted, which directs the script to emit the change as a persistent
change. The content
parameter of the jcs:emit-change
template includes the configuration
statements to add as a persistent change. The message
parameter of the jcs:emit-change
template
includes the warning message to be displayed in the CLI, notifying
you that the configuration has been changed.
The Python version of the commit script generates the persistent
change by using the jcs.emit_change()
function,
which is imported from the jcs
module.
The Python script indicates that this is a persistent change by passing
in the positional argument 'change'.
XSLT Syntax
<?xml version="1.0" standalone="yes"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:junos="http://xml.juniper.net/junos/*/junos"
xmlns:xnm="http://xml.juniper.net/xnm/1.1/xnm"
xmlns:jcs="http://xml.juniper.net/junos/commit-scripts/1.0">
<xsl:import href="../import/junos.xsl"/>
<xsl:template match="configuration">
<xsl:for-each select="interfaces/interface[starts-with(name, 'so-')]/unit">
<xsl:if test="not(family/mpls)">
<xsl:call-template name="jcs:emit-change">
<xsl:with-param name="message">
<xsl:text>Adding 'family mpls' to SONET/SDH interface.</xsl:text>
</xsl:with-param>
<xsl:with-param name="content">
<family>
<mpls/>
</family>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
SLAX Syntax
version 1.0;
ns junos = "http://xml.juniper.net/junos/*/junos";
ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
import "../import/junos.xsl";
match configuration {
for-each (interfaces/interface[starts-with(name, 'so-')]/unit) {
if (not(family/mpls)) {
call jcs:emit-change() {
with $message = {
expr "Adding 'family mpls' to SONET/SDH interface.";
}
with $content = {
<family> {
<mpls>;
}
}
}
}
}
}
Python Syntax
from junos import Junos_Configuration import jcs def main(): # Get configuration root object root = Junos_Configuration for element in root.xpath("./interfaces/ \ interface[starts-with(name,'so-')]/unit"): if element.find('family/mpls') is None: if_name = element.find('../name').text unit_name = element.find('name').text change_xml = """ <interfaces> <interface> <name>{0}</name> <unit> <name>{1}</name> <family> <mpls> </mpls> </family> </unit> </interface> </interfaces> """.format(if_name, unit_name).strip() jcs.emit_change(change_xml, "change", "xml") jcs.emit_warning("Adding 'family mpls' to SONET/SDH interface: " + if_name) if __name__ == '__main__': main()
Configuration
Step-by-Step Procedure
To download, enable, and test the script.
- Copy the script into a text file, name the file
mpls.xsl
,mpls.slax
, ormpls.py
as appropriate, and copy it to the/var/db/scripts/commit/
directory on the device.Note Unsigned Python scripts must be owned by either root or a user in the Junos OS super-user login class, and only the file owner can have write permission for the file.
- In configuration mode, configure the file statement
and the script filename at the [edit system scripts commit] hierarchy level.[edit]user@host# set system scripts commit file mpls.xsl
- If the script is written in Python, enable the execution
of unsigned Python scripts.[edit]user@host# set system scripts language python
Note The language python statement executes scripts using Python 2.7. To use Python 3 to execute Python scripts on devices running Junos OS Release 19.4R1 or later, configure the language python3 statement instead.
- To test that the commit script generates the persistent change correctly, make sure that the configuration contains the condition that elicits the change. To test this script, ensure that the family mpls statement is not included at the [edit interfaces so-fpc/pic/port unit logical-unit-number] hierarchy level for at least one SONET/SDH interface.
- Issue the commit check command to preview a
trace of commit script processing to verify that the script will add
the persistent change to the candidate configuration. The commit
check command verifies the syntax of the configuration prior
to a commit, but it does not commit the changes.
The commit script in this example produces a message for each change it makes. Use the commit check command to preview these messages to determine whether the script will update the configuration with the family mpls statement for the appropriate interfaces.
Issue the commit check | display xml command to display the XML-formatted version of the message. The sample output indicates that the script will add the family mpls statement to the so-2/3/4.0 interface configuration during the commit operation.
[edit]
user@host# commit check | display xml
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/11.2R1/junos">
<commit-results>
<routing-engine junos:style="normal">
<name>re0</name>
<xnm:warning xmlns:xnm="http://xml.juniper.net/xnm/1.1/xnm">
<edit-path>
[edit interfaces interface so-2/3/4 unit 0]
</edit-path>
<message>
Adding 'family mpls' to SONET/SDH interface.
</message>
</xnm:warning>
<commit-check-success/>
</routing-engine>
</commit-results>
</rpc-reply> - To display a detailed trace of commit script processing,
issue the commit check | display detail command. In the
sample output, there is one persistent change that will be loaded
into the configuration during the commit operation.
[edit]
user@host# commit check | display detail
2011-06-17 14:17:35 PDT: reading commit script configuration
2011-06-17 14:17:35 PDT: testing commit script configuration
2011-06-17 14:17:35 PDT: opening commit script '/var/db/scripts/commit/mpls.xsl'
2011-06-17 14:17:35 PDT: reading commit script 'mpls.xsl'
2011-06-17 14:17:35 PDT: running commit script 'mpls.xsl'
2011-06-17 14:17:35 PDT: processing commit script 'mpls.xsl'
2011-06-17 14:17:35 PDT: no errors from mpls.xsl
2011-06-17 14:17:35 PDT: saving commit script changes for script mpls.xsl
2011-06-17 14:17:35 PDT: summary of script mpls.xsl: changes 1, transients 0, syslog 0
2011-06-17 14:17:35 PDT: start loading commit script changes
2011-06-17 14:17:35 PDT: loading commit script changes into real db
2011-06-17 14:17:35 PDT: finished commit script changes into real db
2011-06-17 14:17:35 PDT: no transient commit script changes
2011-06-17 14:17:35 PDT: finished loading commit script changes
2011-06-17 14:17:35 PDT: copying juniper.db to juniper.data+
2011-06-17 14:17:35 PDT: finished copying juniper.db to juniper.data+
... configuration check succeeds - After verifying that the script produces the correct changes,
issue the commit command to start the commit operation
and execute the script.user@host# commit
Verification
Verifying the Configuration
Purpose
Verify that the correct changes are integrated into the configuration.
Action
After executing the commit operation, view the configuration by issuing the show interfaces configuration mode command. If the MPLS protocol family is not enabled on one or more SONET/SDH interfaces before the script runs, the output is similar to the following:
[edit]
user@host# show interfaces
... other configured interface types ...
so-2/3/4 {
unit 0 {
family mpls; # Added by persistent change
}
}
... other configured interface types ...
See also
Generating a Persistent or Transient Configuration Change in SLAX and XSLT Commit Scripts
Overview of Generating Persistent or Transient Configuration Changes Using Commit Scripts
Removing a Persistent or Transient Configuration Change Using Commit Scripts
emit-change Template (SLAX and XSLT) and emit_change (Python)
Example: Generating a Transient Change
This example uses a commit script to set PPP encapsulation on all SONET/SDH interfaces with the IPv4 protocol family enabled. The changes are added as transient changes.
Requirements
This example uses the following hardware and software components:
Device running Junos OS with one or more SONET/SDH interfaces.
Junos OS Release 16.1R3 or later release when using a Python script.
Overview and Commit Script
The commit script in this example finds all SONET/SDH interfaces with the IPv4 protocol family enabled in the configuration and adds the encapsulation ppp statement to the interface configuration. The commit script generates a transient change, which adds the change to the checkout configuration but not the candidate configuration. The script is shown in SLAX, XSLT, and Python.
The SLAX and XSLT versions of the commit script generate the
transient change by using the jcs:emit-change
template, which is a helper template contained in the junos.xsl
import file. The tag
parameter of the jcs:emit-change
template
has the value transient-change
, which directs
the script to emit the change as a transient change rather than a persistent change.
The content
parameter of the jcs:emit-change
template includes the configuration
statements to be added as a transient change.
The Python version of the commit script generates the transient
change by using the jcs.emit_change()
function,
which is imported from the jcs
module.
The Python script indicates that this is a transient change by passing
in the positional argument 'transient-change'.
XSLT Syntax
<?xml version="1.0" standalone="yes"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:junos="http://xml.juniper.net/junos/*/junos"
xmlns:xnm="http://xml.juniper.net/xnm/1.1/xnm"
xmlns:jcs="http://xml.juniper.net/junos/commit-scripts/1.0">
<xsl:import href="../import/junos.xsl"/>
<xsl:template match="configuration">
<xsl:for-each select="interfaces/interface[starts-with(name, 'so-')
and unit/family/inet]">
<xsl:call-template name="jcs:emit-change">
<xsl:with-param name="tag" select="'transient-change'"/>
<xsl:with-param name="content">
<encapsulation>ppp</encapsulation>
</xsl:with-param>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
SLAX Syntax
version 1.0;
ns junos = "http://xml.juniper.net/junos/*/junos";
ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
import "../import/junos.xsl";
match configuration {
for-each (interfaces/interface[starts-with(name, 'so-') and unit/family/inet]) {
call jcs:emit-change($tag = 'transient-change') {
with $content = {
<encapsulation> "ppp";
}
}
}
}
Python Syntax
from junos import Junos_Configuration import jcs def main(): # Get configuration root object root = Junos_Configuration for element in root.xpath("./interfaces/ \ interface[starts-with(name,'so-') and unit/family/inet]"): if_name = element.find('name').text change_xml = """ <interfaces> <interface> <name>{0}</name> <encapsulation>ppp</encapsulation> </interface> </interfaces> """.format(if_name).strip() jcs.emit_change(change_xml, "transient-change", "xml") jcs.emit_warning("Adding 'ppp' encapsulation to SONET interface: " + if_name) jcs.emit_warning(change_xml) if __name__ == '__main__': main()
Configuration
Step-by-Step Procedure
To download, enable, and test the script.
- Copy the script into a text file, name the file
encap-ppp.xsl
,encap-ppp.slax
, orencap-ppp.py
as appropriate, and copy it to the/var/db/scripts/commit/
directory on the device.Note Unsigned Python scripts must be owned by either root or a user in the Junos OS super-user login class, and only the file owner can have write permission for the file.
- In configuration mode, configure the file statement
and the script filename at the [edit system scripts commit] hierarchy level.[edit]user@host# set system scripts commit file encap-ppp.xsl
- Configure the allow-transients statement to
enable commit scripts to load transient changes into the checkout
configuration.[edit]user@host# set system scripts commit allow-transients
- If the script is written in Python, enable the execution
of unsigned Python scripts.[edit]user@host# set system scripts language python
Note The language python statement executes scripts using Python 2.7. To use Python 3 to execute Python scripts on devices running Junos OS Release 19.4R1 or later, configure the language python3 statement instead.
- To test that the commit script generates the transient change correctly, make sure that the configuration contains the condition that elicits the change. Ensure that the encapsulation ppp statement is not included at the [edit interfaces so-fpc/pic/port] hierarchy level for at least one SONET/SDH interface.
- Issue the commit check command to preview a
trace of commit script processing to verify that the script will add
the transient change to the checkout configuration. The commit
check command verifies the syntax of the configuration prior
to a commit, but it does not commit the changes.
Issue the commit check | display detail command to display a detailed trace of commit script processing. In the sample output, there are two transient changes that are loaded into the checkout configuration.
[edit]
user@host# commit check | display detail
2011-06-15 12:07:30 PDT: reading commit script configuration
2011-06-15 12:07:30 PDT: testing commit script configuration
2011-06-15 12:07:30 PDT: opening commit script '/var/db/scripts/commit/encap-ppp.xsl'
2011-06-15 12:07:30 PDT: reading commit script 'encap-ppp.xsl'
2011-06-15 12:07:30 PDT: running commit script 'encap-ppp.xsl'
2011-06-15 12:07:30 PDT: processing commit script 'encap-ppp.xsl'
2011-06-15 12:07:30 PDT: no errors from encap-ppp.xsl
2011-06-15 12:07:30 PDT: saving commit script changes for script encap-ppp.xsl
2011-06-15 12:07:30 PDT: summary of script encap-ppp.xsl: changes 0, transients 2 (allowed), syslog 0
2011-06-15 12:07:30 PDT: start loading commit script changes
2011-06-15 12:07:30 PDT: no commit script changes
2011-06-15 12:07:30 PDT: updating transient changes into transient tree
2011-06-15 12:07:30 PDT: finished loading commit script changes
2011-06-15 12:07:30 PDT: copying juniper.db to juniper.data+
2011-06-15 12:07:30 PDT: finished copying juniper.db to juniper.data+
2011-06-15 12:07:30 PDT: exporting juniper.conf
2011-06-15 12:07:30 PDT: merging transient changes
... configuration check succeeds - After verifying that the script produces the correct changes,
issue the commit command to start the commit operation
and execute the script.user@host# commit
Verification
Verifying the Configuration
Purpose
Verify that the correct changes are integrated into the checkout configuration. If there are one or more SONET/SDH interfaces with the IPv4 protocol family enabled, you should see the encapsulation ppp statement added as a transient change to the interface hierarchy.
Action
To view the configuration with transient changes, issue the show interfaces | display commit-scripts configuration mode command. The show interfaces | display commit-scripts command displays all the statements that are in the configuration, including statements that are generated by transient changes. If there are one or more SONET/SDH interfaces with the IPv4 protocol family enabled, the output is similar to the following:
[edit]
user@host# show interfaces | display commit-scripts
... so-1/2/3 { mtu 576; encapsulation ppp; /* Added by transient change. */ unit 0 { family inet { address 10.0.0.3/32; } } } so-1/2/4 { encapsulation ppp; /* Added by transient change. */ unit 0 { family inet { address 10.0.0.4/32; } } } so-2/3/4 { encapsulation cisco-hdlc; # Not affected by the script, because IPv4 protocol # family is not configured on this interface. unit 0 { family mpls; } }
Troubleshooting
Troubleshooting Commit Errors
Problem
The CLI generates an invalid transient change error, and the commit fails.
user@host# commit check
error: invalid transient change generated by commit script: encap-ppp.xsl warning: 1 transient change was generated without [system scripts commit allow-transients] error: 1 error reported by commit scripts error: commit script failure
Solution
You must configure the allow-transients statement at the [edit system scripts commit] hierarchy level to enable commit scripts to load transient changes into the checkout configuration.
Configure the following statement to allow transient changes:
See also
Generating a Persistent or Transient Configuration Change in SLAX and XSLT Commit Scripts
Overview of Generating Persistent or Transient Configuration Changes Using Commit Scripts
Removing a Persistent or Transient Configuration Change Using Commit Scripts
emit-change Template (SLAX and XSLT) and emit_change (Python)
Related Documentation
Generating a Persistent or Transient Configuration Change in SLAX and XSLT Commit Scripts
Overview of Generating Persistent or Transient Configuration Changes Using Commit Scripts
Removing a Persistent or Transient Configuration Change Using Commit Scripts
emit-change Template (SLAX and XSLT) and emit_change (Python)