Example: Creating Custom Configuration Syntax with Commit Script Macros
A Junos OS configuration can contain apply-macro
statements with custom configuration syntax. By itself, the apply-macro
statement has no operational impact on the device.
Commit script macros process the custom configuration syntax and expand
it into standard Junos OS configuration statements, which are then
added as a persistent or transient change. This example demonstrates
how to use commit script macros to inspect apply-macro
statements
and generate Junos OS configuration statements.
Requirements
This example uses the following hardware and software components:
Device running Junos OS.
Junos OS Release 16.1R3 or later release when using a Python script.
Overview and Commit Script
Table 1 shows a macro containing custom syntax and the corresponding expansion to standard Junos OS command-line interface (CLI) syntax.
Custom Macro Syntax |
Expanded Junos OS CLI Syntax |
---|---|
protocols { mpls { apply-macro blue-type-lsp { 10.1.1.1; 10.2.2.2; 10.3.3.3; 10.4.4.4; color blue; group-value 0; } } } |
protocols { mpls { admin-groups { blue 0; } label-switched-path blue-lsp-10.1.1.1 { to 10.1.1.1; admin-group include-any blue; } label-switched-path blue-lsp-10.2.2.2 { to 10.2.2.2; admin-group include-any blue; } label-switched-path blue-lsp-10.3.3.3 { to 10.3.3.3; admin-group include-any blue; } label-switched-path blue-lsp-10.4.4.4 { to 10.4.4.4; admin-group include-any blue; } } } |
In this example, the Junos OS management (mgd) process inspects
the configuration, looking for apply-macro
statements.
For each apply-macro
statement with the color
parameter included at the [edit protocols mpls]
hierarchy
level, the script generates a transient change, using the data provided within the apply-macro
statement
to expand the macro into a standard Junos OS administrative group
for LSPs.
For this example to work, an apply-macro
statement
must be included at the [edit protocols mpls]
hierarchy
level with a set of addresses, a color
,
and a group-value
parameter. The commit
script converts each address to an LSP configuration, and the script
converts the color
parameter into an administrative
group.
Following are the commit script instructions that expand the macro in Table 1 and a line-by-line explanation of the script:
XSLT Syntax
1 <?xml version="1.0" standalone="yes"?> 2 <xsl:stylesheet version="1.0" 3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 4 xmlns:junos="http://xml.juniper.net/junos/*/junos" 5 xmlns:xnm="http://xml.juniper.net/xnm/1.1/xnm" 6 xmlns:jcs="http://xml.juniper.net/junos/commit-scripts/1.0"> 7 <xsl:import href="../import/junos.xsl"/> 8 <xsl:template match="configuration"> 9 <xsl:variable name="mpls" select="protocols/mpls"/> 10 <xsl:for-each select="$mpls/apply-macro[data/name = 'color']"> 11 <xsl:variable name="color" select="data[name = 'color']/value"/> 12 <xsl:variable name="group-value" select="data[name = \ 'group-value']/value"/> 13 <transient-change> 14 <protocols> 15 <mpls> 16 <admin-groups> 17 <name> 18 <xsl:value-of select="$color"/> 19 </name> 20 <group-value> 21 <xsl:value-of select="$group-value"/> 22 </group-value> 23 </admin-groups> 24 <xsl:for-each select="data[not(value)]/name"> 25 <label-switched-path> 26 <name> 27 <xsl:value-of select="concat($color, '-lsp-', .)"/> 28 </name> 29 <to><xsl:value-of select="."/></to> 30 <admin-group> 31 <include-any> 32 <xsl:value-of select="$color"/> 33 </include-any> 34 </admin-group> 35 </label-switched-path> 36 </xsl:for-each> 37 </mpls> 38 </protocols> 39 </transient-change> 40 </xsl:for-each> 41 </xsl:template> 42 </xsl:stylesheet>
Lines 1 through 8 (and Lines 43 and 44) are the boilerplate that you include in every XSLT commit script. For brevity, Lines 1 through 8 are omitted here.
Line 9 assigns the [edit protocols mpls]
hierarchy
level to a variable called mpls
.
9 <xsl:variable name="mpls" select="protocols/mpls"/>
Line 10 selects every apply-macro
statement
at the [edit protocols mpls]
hierarchy level that contains
the color
parameter. The sample configuration
in Table 1 contains
only one apply-macro
statement. Therefore, this <xsl:for-each>
programming instruction takes effect
only once.
10 <xsl:for-each select="$mpls/apply-macro[data/name = 'color']">
Line 11 assigns the value of the color
parameter, in this case blue
, to a variable
called color
.
11 <xsl:variable name="color" select="data[name = 'color']/value"/>
Line 12 assigns the value of the group-value
parameter, in this case 0
, to a variable
called group-value
.
12 <xsl:variable name="group-value" select="data[name = \ 'group-value']/value"/>
Lines 13 through 15 generate a transient change at the [edit protocols mpls]
hierarchy level.
13 <transient-change> 14 <protocols> 15 <mpls>
Lines 16 through 23 add the admin-groups
statement
to the configuration and assign the value of the color
variable to the group name and the value of the group-value
variable to the group value.
16 <admin-groups> 17 <name> 18 <xsl:value-of select="$color"/> 19 </name> 20 <group-value> 21 <xsl:value-of select="$group-value"/> 22 </group-value> 23 </admin-groups>
The resulting configuration statements are as follows:
admin-groups { blue 0; }
Line 24 selects the name of every parameter that does
not have a value assigned to it, which in this case are the four IP
addresses. This <xsl:for-each>
programming
instruction uses recursion through the macro and selects each IP address
in turn. The color
and group-value
parameters each have a value assigned (blue
and 0
, respectively), so this line does
not apply to them.
24 <xsl:for-each select="data[not(value)]/name">
Line 25 adds the label-switched-path
statement
in the configuration.
25 <label-switched-path>
Lines 26 through 28 assign the label-switched-path
a name that concatenates the value of the color
variable, the text -lsp
-, and the current
IP address currently selected by Line 24 (represented by the “ .
” ).
26 <name> 27 <xsl:value-of select="concat($color, '-lsp-', .)"/> 28 </name>
Line 29 adds the to
statement
to the configuration and sets its value to the IP address currently
selected by Line 24.
29 <to><xsl:value-of select="."/></to>
Lines 30 through 34 add the admin-group include-any
statement to the configuration and set its value to the value of
the color
variable.
30 <admin-group> 31 <include-any> 32 <xsl:value-of select="$color"/> 33 </include-any> 34 </admin-group>
The resulting configuration statements (for one pass) are as follows:
label-switched-path blue-lsp-10.1.1.1 { to 10.1.1.1; admin-group include-any blue; }
Lines 35 through 42 are closing tags.
35 </label-switched-path> 36 </xsl:for-each> 37 </mpls> 38 </protocols> 39 </transient-change> 40 </xsl:for-each> 41 </xsl:template> 42 </xsl:stylesheet>
SLAX Syntax
The equivalent SLAX script is:
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 { var $mpls = protocols/mpls; for-each ($mpls/apply-macro[data/name = 'color']) { var $color = data[name = 'color']/value; var $group-value = data[name='group-value']/value; <transient-change> { <protocols> { <mpls> { <admin-groups> { <name> $color; <group-value> $group-value; } for-each (data[not(value)]/name) { <label-switched-path> { <name> $color _ '-lsp-' _ .; <to> .; <admin-group> { <include-any> $color; } } } } } } } }
Python Syntax
The following Python syntax produces the identical configuration changes:
from junos import Junos_Configuration import jcs def main(): # Get configuration root object root = Junos_Configuration for element in root.xpath("./protocols/mpls/ \ apply-macro[data/name='color']"): color = element.find("data[name='color']/value").text group_value = element.find("data[name='group-value']/value").text lsp_config ="" for element2 in element.xpath("data[not(value)]/name"): lsp_config = lsp_config + """ <label-switched-path> <name>{0}-lsp-{1}</name> <to>{1}</to> <admin-group> <include-any>{0}</include-any> </admin-group> </label-switched-path> """.format(color, element2.text) change_xml = """ <protocols> <mpls> <admin-groups> <name>{0}</name> <group-value>{1}</group-value> </admin-groups> {2} </mpls> </protocols> """.format(color, group_value, lsp_config).strip() jcs.emit_change(change_xml, "transient-change", "xml") if __name__ == '__main__': main()
For more information about this example, see Example: Configure Administrative Groups for LSPs.
Configuration
Procedure
Step-by-Step Procedure
To download, enable, and test the script:
Copy the script into a text file, name the file lsp-admin.xsl, lsp-admin.slax, or lsp-admin.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.If the script is written in Python, enable the execution of unsigned Python scripts.
[edit] user@host# set system scripts language python
Note:Configure the
language python3
statement to use Python 3 to execute Python scripts, or configure thelanguage python
statement to use Python 2.7 to execute Python scripts. For more information, see language.Select the following test configuration stanzas, and press Ctrl+c to copy them to the clipboard. If you are using the SLAX or Python version of the script, update the filename at the
[edit system scripts commit file]
hierarchy level.system { scripts { commit { allow-transients; file lsp-admin.xsl; } } } protocols { mpls { apply-macro blue-type-lsp { 10.1.1.1; 10.2.2.2; 10.3.3.3; 10.4.4.4; color blue; group-value 0; } } }
In configuration mode, issue the
load merge terminal
command to merge the stanzas into your device configuration.[edit] user@host# load merge terminal [Type ^D at a new line to end input] ... Paste the contents of the clipboard here ...
At the prompt, paste the contents of the clipboard by using the mouse and the paste icon.
Press Enter.
Press Ctrl+d.
Commit the configuration.
user@host# commit
Verification
Verifying Script Execution
Purpose
Verify that the script behaves as expected.
Action
To display the configuration statements created by the
script, issue the show protocols mpls | display commit-scripts
command.
[edit] user@host# show protocols mpls | display commit-scripts apply-macro blue-type-lsp { 10.1.1.1; 10.2.2.2; 10.3.3.3; 10.4.4.4; color blue; group-value 0; } admin-groups { blue 0; } label-switched-path blue-lsp-10.1.1.1 { to 10.1.1.1; admin-group include-any blue; } label-switched-path blue-lsp-10.2.2.2 { to 10.2.2.2; admin-group include-any blue; } label-switched-path blue-lsp-10.3.3.3 { to 10.3.3.3; admin-group include-any blue; } label-switched-path blue-lsp-10.4.4.4 { to 10.4.4.4; admin-group include-any blue; }