Blogs

Scripting How-To: Identify configuration identifiers

By Erdem posted 08-10-2015 01:23

  

Identify Configuration Identifiers

 

Identifiers are used as unique keys to differentiate between two otherwise identical configuration stanzas. For example, consider the <interfaces> hierarchy, which can, and almost always does, contain multiple instances of <interface> child elements, with each of these elements being distinguished by an identifier element named <name>.

 

01	<interfaces>
02	    <interface>
03	        <name>ge-0/0/0</name>
04	    </interface>
05	    <interface>
06	        <name>ge-0/0/1</name>
07	    </interface>
08	    <interface>
09	        <name>lo0</name>
10	    </interface>
11	</interfaces>

Most identifiers are conveniently named <name>, making it easy to identify the majority of identifiers by simply scanning for elements with a name of "name". This is how the jcs:emit-change template builds its change configuration hierarchies. It is provided a chunk of configuration XML along with a reference point, and it then adds the ancestors of that structure backwards, pulling out and including <name> identifiers as it goes.

 

Using Non-Name Identifier Elements

 

Now, if all identifiers were named "name", then there would be no need for this article, but they are not. Other identifier elements include: <from-zone-name>, <to-zone-name>,<neighbor-id>, <transit-area>, and so on, and any configuration change made within one of these hierarchies, which have non-"name" identifiers, must include the identifiers in order to be valid. However, the problem is that there is no indication given within the configuration XML itself whether a particular element is an identifier or not.

 

Why is this a problem? Well, return to the jcs:emit-change example and assume that you want to make a change within a security policy. You would provide the code chunk to jcs:emit-change, which would happily generate a <change> element for you, and Junos OS would just as happily fail your commit with an error message.

 

Why? Because the generated <change> element would be invalid because that jcs:emit-change had no idea that <from-zone-name> and <to-zone-name> were identifiers and needed to be included. Now, it might be possible to go through and manually identify every single non-name identifier possible in the configuration and hard-code that into your script, but what happens if the next Junos OS version adds a new one? Is that a commitment you really want to make?

 

Ultimately, we need a mechanism that informs scripts whether an element is an identifier or not. This would ideally be included as an attribute of <get-configuration>, allowing you to specify whether you want identifiers identified or not. This is being requested by PR 492912, which has yet to see a fix.

 

In the meantime, here is a workaround that could be useful in some scenarios, but not all. The "| display xml" CLI pipe has an undocument option that can be appended, "junos-key", and if you include that option then you will get output like this:

 

01	jnpr@srx210> show configuration interfaces ge-0/0/0 | display xml junos-key
02	<rpc-reply xmlns:junos="http://xml.juniper.net/junos/12.1D0/junos">
03	    <configuration junos:commit-seconds="1327137218" junos:commit-localtime="2012-01-21 09:13:38 UTC" junos:commit-user="jnpr">
04	            <interfaces>
05	                <interface>
06	                    <name junos:key="key">ge-0/0/0</name>
07	                    <unit>
08	                        <name junos:key="key">0</name>
09	                        <family>
10	                            <inet>
11	                                <address>
12	                                    <name junos:key="key">10.0.0.10/24</name>
13	                                </address>
14	                            </inet>
15	                        </family>
16	                    </unit>
17	                </interface>
18	            </interfaces>
19	    </configuration>
20	    <cli>
21	        <banner></banner>
22	    </cli>
23	</rpc-reply>

This can be leveraged within a script as well, using code such as below:

 

1	var $rpc = <command> "show configuration security policies | display xml junos-key";
2	var $results = jcs:invoke( $rpc );

Here is the returned XML content:

 

01	<pipe>
02	    <display-xml>
03	        <junos-key/>
04	    </display-xml>
05	</pipe>
06	<configuration xmlns:junos="http://xml.juniper.net/junos/*/junos" junos:commit-seconds="1327137218" junos:commit-localtime="2012-01-21 09:13:38 UTC" junos:commit-user="jnpr">
07	    <security>
08	        <policies>
09	            <policy>
10	                <from-zone-name junos:key="key">trust</from-zone-name>
11	                <to-zone-name junos:key="key">trust</to-zone-name>
12	                <policy>
13	                    <name junos:key="key">example</name>
14	                    <match>
15	                        <source-address junos:key="key">any</source-address>
16	                        <destination-address junos:key="key">any</destination-address>
17	                        <application junos:key="key">any</application>
18	                    </match>
19	                    <then>
20	                        <permit>
21	                        </permit>
22	                        <count>
23	                        </count>
24	                    </then>
25	                </policy>
26	            </policy>
27	        </policies>
28	    </security>
29	</configuration>

As you can see, all of the identifiers are now tagged with the junos:key attribute, making it possible to identify them through an attribute check (@junos:key).

 

Limitations

 

  • Pipes are not actually supported in Junos OS scripts. On the other hand, there is no supported way to do this today, and it works
  • Only the committed configuration database can be returned in this fashion
  • So it is not useful in commit scripts

#xml
#JUNOS
#Slax
#Scripting
#How-To
#ScriptingHow-To