Automation

Scripting How-To: Access RPC on demand

By Elevate posted 02-19-2014 04:30

  

Access RPC On Demand Directly

 

You should always have the ability to do anything that the Junos OS or XML API provide. Each Device variable has an rpc property to make accessing Junos OS at this low level easy. Junos PyEZ  has metaprogramming to do what you want only when you need it (on demand).
 
The term "metaprogramming" means that the rpc will dynamically create Junos OS XML Remote Procedure Calls (RPCs) as you invoke them, rather than pre-coding them as part of the Junos PyEZ library.
 
In other words, if a Junos OS device provides thousands of RPCs, Junos PyEZ does not contain thousands of RPC functions. It metaprograms only the RPCs that you use, keeping the size of this module small, and the portability flexible.
 

Usage Example

 
The following illustrates a basic example using the Device.rpc property to retrieve the inventory, and display the model and serial number information. 
 
1 from jnpr.junos import Device
2 jdev = Device(user='jeremy', host='vsrx_cyan', password='jeremy1')jdev.open()
3 # invoke the RPC equivalent to "show chassis hardware"
4 inv = jdev.rpc.get_chassis_inventory()
5 # use XPath expressions to extract the data from the Junos/XML response# the :inv: variable is an lxml Element object
6 print "model: %s" % inv.findtext('chassis/description')print "serial-number: %s" %inv.findtext('chassis/serial-number')
7 jdev.close()
 

RPC Command

It is very easy to determine a Junos OS XML API command. On a Junos CLI you use the | display xml rpc mechanism, as illustrated:
 
01 jeremy@junos> show chassis hardware | display xml rpc
02 <rpc-reply xmlns:junos="http://xml.juniper.net/junos/12.1X44/junos">
03     <rpc>
04         <get-chassis-inventory>
05         </get-chassis-inventory>
06     </rpc>
07     <cli>
08         <banner></banner>
09     </cli>
10 </rpc-reply>
 
The content between the rpc elements is the XML RPC command, in this case get-chassis-inventory. As you can see from the above code example, to invoke this API, use the NETCONF object rpc attribute and invoke a method name corresponding to the XML RPC command. If the command has dashes (-), swap them to underscores (_). 
 
1 inv = jdev.rpc.get_chassis_inventory()
 
If the command has parameters, do the same. Here is an example retrieving the status of a given interface: 

 

01 jeremy@junos> show interfaces ge-0/0/0 media | display xml rpc
02 <rpc-reply xmlns:junos="http://xml.juniper.net/junos/12.1X44/junos">
03     <rpc>
04         <get-interface-information>
05                 <media/>                <interface-name>ge-0/0/0</interface-name>        </get-interface-information>
06     </rpc>
07     <cli>
08         <banner></banner>
09     </cli>
10 </rpc-reply>
 

The equivalent Python would look like this: 

 
1 rsp = jdev.rpc.get_interface_information( media=True, interface_name='ge-0/0/0' )
 
Here the media parameter does not take a value, so you simply assign it to True. Again, for parameter names that contain dashes, you swap them for underscores; interface-name becomes interface_name

 

RPC Response

 

It is very easy to determine the response of a Junos OS XML API command. On a Junos OS CLI you use the | display xml mechanism: 

 

01 jeremy@junos> show chassis hardware | display xml
02 <rpc-reply xmlns:junos="http://xml.juniper.net/junos/12.1X44/junos">
03     <chassis-inventory xmlns="http://xml.juniper.net/junos/12.1X44/junos-chassis">
04         <chassis junos:style="inventory">
05             <name>Chassis</name>
06             <serial-number>AD2909AA0096</serial-number>
07             <description>SRX210H</description>
08             <chassis-module>
09                 <name>Routing Engine</name>
10                 <version>REV 28</version>
11                 <part-number>750-021779</part-number>
12                 <serial-number>AAAH4755</serial-number>
13                 <description>RE-SRX210H</description>
14             </chassis-module>
15             <chassis-module>
16                 <name>FPC 0</name>
17                 <description>FPC</description>
18                 <chassis-sub-module>
19                     <name>PIC 0</name>
20                     <description>2x GE, 6x FE, 1x 3G</description>
21                 </chassis-sub-module>
22             </chassis-module>
23             <chassis-module>
24                 <name>FPC 1</name>     
25                 <version>REV 04</version>
26                 <part-number>750-023367</part-number>
27                 <serial-number>AAAG7981</serial-number>
28                 <description>FPC</description>
29                 <chassis-sub-module>
30                     <name>PIC 0</name>
31                     <description>1x T1E1 mPIM</description>
32                 </chassis-sub-module>
33             </chassis-module>
34             <chassis-module>
35                 <name>Power Supply 0</name>
36             </chassis-module>
37         </chassis>
38     </chassis-inventory>
39     <cli>
40         <banner></banner>
41     </cli>
42 </rpc-reply>
 
 

The result of the RPC command is an lxml element, set at the first element after the <rpc-reply>. In the above example, that would be<chassis-inventory>. Given that, any XPath expression is relative. So to extract the chassis serial number, the XPath expression is simply chassis/serial-number.

 
1 inv = jdev.rpc.get_chassis_inventory()
2 print "model: %s" % inv.findtext('chassis/description')print "serial-number: %s" %inv.findtext('chassis/serial-number')
 
Since the response variable is an lxml element, you can use any routine available from that library.
 
For details, refer to the lxml documentation.

 


#overview
#rpc
#Python
#How-To
#junospyez
9 comments
0 views

Permalink

Comments

11-07-2014 04:44

zhoumi says:
 
hi,rsherman
Thanks for your help.I think this is a better way to get the serial number.
Actually,I want to get mac-address on the interface.I think maybe I can use the file arp.py to do this,just like you to use fpc.py.
Thanks again!
Posted 18:51, 7 Nov 2014

11-07-2014 04:43

rsherman says:
 
Hi Mi Zhou,

The easiest way to do this would actually be the FPC Table/View:

>>> from jnpr.junos.op.fpc import FpcHwTable
>>> fpc = FpcHwTable(dev)
>>> fpc.get()
FpcHwTable:device: 2 items
>>> fpc.keys()
['FPC 0', 'FPC 1']
>>> fpc.values()
[[('ver', 'REV 09'), ('model', 'QFX5100-48S-AFO'), ('pn', '650-049938'), ('sn', 'TA37XXXXXXXX'), ('desc', 'QFX5100-48S-6Q')], [('ver', 'REV 11'), ('model', 'EX4300-24P'), ('pn', '650-044935'), ('sn', 'PF37XXXXXXXX'), ('desc', 'EX4300-24P')]]

>>> fpc['FPC 1'].sn
'PF37XXXXXXXX'
Posted 15:13, 7 Nov 2014

11-06-2014 04:43

zhoumi says:
 
I have a question.
on port of "RPC Response",how can I got the fpc 1's serital number?
If I use:
inv = jdev.rpc.get_chassis_inventory()
print "model: %s" % inv.findtext('chassis/chassis-module/serial-number")
Because findtext always find the first match,so I can only get the serital number for Routing Engine,not the fpc 1.
Did any other way can do this?
Many thanks !
Posted 06:29, 6 Nov 2014

05-14-2014 04:41

joao.netto@actar.com.br says:
 
Hello Schulman, thanks a lot for your answer. i'll see about that pages what you talking about. Again, thanks.
Posted 08:13, 14 May 2014

04-29-2014 04:40

jschulman says:
 
@Joao - Alternatively you could use the Table/View mechanism, which I would recommend. Please take a look at those pages for "audit/reporting/troubleshooting" to get an idea of how these are used. The Table mechanism allows for more native Python iteration so you don't need to write code to process XML.

Hope this helps!
Posted 04:56, 29 Apr 2014

04-29-2014 04:40

jschulman says:
 
@Joao - apologies for the delay responding, been traveling. I believe you might want to try something like

inv = dev.rpc.get_interface_information(interface_name="ge*")

You will then need to write a short python loop/iterator to extract each interface/name and print.
Posted 04:33, 29 Apr 2014

04-23-2014 04:39

joao.netto@actar.com.br says:
 
Hello Schulman,

I'm try to get G* interfaces from physical-interface (show interface g* | display xml). To do this task i using findall method like you can see below.

inv = dev.rpc.get_interface_information()
print " Interface: %s" % inv.findall('[g]\w+', 'physical-interface/name')

When i run this commands i receive a lot of errors, but i using this kind of findall method without problems in other scripts, but not in junos, so, how can i pick up all or partial informations like the command above ?

Best Regards
Posted 20:24, 23 Apr 2014

02-20-2014 04:38

jschulman says:
 
@Lukas,

Thank you for your post and providing your working sample. I did check this code running on a FireFly (vSRX) and the original code does seem to work. I am curious what the entire XML for the "inv" looks like on your SRX. I am guessing that perhaps on your system there is more XML prior to the 'chassis' node-set. If you could dump the XML and email me a copy (jschulman@juniper.net) that would be helpful. You can dump the XML using the following:

>>> from lxml import etree
>>> etree.dump( inv )

Thank you!
Posted 05:44, 20 Feb 2014

02-19-2014 04:35

lukas.borkovec@asx.com.au says:
 
Hi,

Good page, but last two lines below did not work for me for some reason.

print "model: %s" % inv.findtext('chassis/description')
print "serial-number: %s" % inv.findtext('chassis/serial-number')

I have Python 2.7.6 and Junos SRX 11.4R6.5

Working syntax is:

print "model: %s" % inv.findtext('.//chassis/description')
print "serial-number: %s" % inv.findtext('.//chassis/serial-number')

Have a nice day

Lukas
Posted 16:12, 19 Feb 2014