Re: Working with Juniper

76 views
Skip to first unread message

Jathan McCollum

unread,
Jul 1, 2014, 7:00:26 PM7/1/14
to trigge...@googlegroups.com
Hey there Dermot and welcome to the Trigger community!

The default for Juniper devices is to use Junoscript.This was the original way that this was implemented in Trigger, so that's why it's not the default and in order to get CLI output you need to pass force_cli=True. 

The Element object you see there is from the xml.etree.ElementTree library that comes with Python. This makes it very easy to iterate through results using XSLT. But if you want to get at the raw XML it's not terribly hard.

The quickest and easiest way is this (ran against an SRX 210 I have on my home network):

In [1]: from trigger.cmds import Commando

In [2]: c = Commando(devices=['192.168.0.202'], commands=['show version'])

In [3]: c.run()

In [4]: c.results
Out[4]: {'192.168.0.202': {'show version': <Element '{http://xml.juniper.net/xnm/1.1/xnm}roc-reply' at 0x10b1bd190>}}

Now here is where you use ElementTree.tostring() method to dump the raw XML:

In [5]: import xml.etree.ElementTree as ET

In [6]: ET.tostring(c.results['192.168.0.202']['show version'])
Out[6]: '<ns0:roc-reply xmlns:ns0="http://xml.juniper.net/xnm/1.1/xnm">\n<ns0:software-information>\n<ns0:host-name>srx</ns0:host-name>\n<ns0:product-model>srx210h</ns0:product-model>\n<ns0:product-name>srx210h</ns0:product-name>\n<ns0:jsr />\n<ns0:package-information>\n<ns0:name>junos</ns0:name>\n<ns0:comment>JUNOS Software Release [12.1X44-D15.5]</ns0:comment>\n</ns0:package-information>\n</ns0:software-information>\n</ns0:rpc-reply>'

Or you can use .dump() to just print it to stdout:

In [12]: data = c.results['192.168.0.202']['show version']

In [13]: ET.dump(data)
<ns0:rpc-reply xmlns:ns0="http://xml.juniper.net/xnm/1.1/xnm">
<ns0:software-information>
<ns0:host-name>srx</ns0:host-name>
<ns0:product-model>srx210h</ns0:product-model>
<ns0:product-name>srx210h</ns0:product-name>
<ns0:jsr />
<ns0:package-information>
<ns0:name>junos</ns0:name>
<ns0:comment>JUNOS Software Release [12.1X44-D15.5]</ns0:comment>
</ns0:package-information>
</ns0:software-information>
</ns0:rpc-reply>

Of course working with XML with namespaces immediately becomes obviously horrible and ugly. There are some utilities within the Trigger libs that make this a little easier but it's not quite user-friendly just yet, but here they are. We're working on simplifying a lot of this end-user experience as we approach Trigger 2.0, so please keep this in mind. We're aware of the pain, too!

So here goes... First you want to import trigger.utils.xmltodict, and then you also want trigger.utils.strip_juniper_namespace. Then you can use these together to convert the XML to a Python dictionary and walk through the Juniper configuration logically and naturally. So we'll use the data variable we defined above that references the XML ElementTree object:

In [30]: data
Out[30]: <Element '{http://xml.juniper.net/xnm/1.1/xnm}rpc-reply' at 0x10b1bd190>

And then import those 2 functions I referenced above (trigger.utils.xmltodict and trigger.utils.strip_juniper_namespace):

In [31]: from trigger.utils import xmltodict

In [32]: from trigger.utils import strip_juniper_namespace

And then use xmltodict.parse with strip_juniper_namespace as a post-processor (This isn't really well documented right now so you'll have to trust me):

In [33]: xmltodict.parse(ET.tostring(data), postprocessor=strip_juniper_namespace)
Out[33]: OrderedDict([(u'rpc-reply', OrderedDict([(u'@xmlns:ns0', u'http://xml.juniper.net/xnm/1.1/xnm'), (u'software-information', OrderedDict([(u'host-name', u'srx'), (u'product-model', u'srx210h'), (u'product-name', u'srx210h'), (u'jsr', None), (u'package-information', OrderedDict([(u'name', u'junos'), (u'comment', u'JUNOS Software Release [12.1X44-D15.5]')]))]))]))])

You see it returns an OrderedDict, so let's capture that in a variable and then reference the "software-information/package-information/comment" key that includes the software version (it took me a few tries to remember the nested elements including "roc-reply"):

In [37]: xml_dict['rpc-reply']['software-information']['package-information']['comment']
Out[37]: u'JUNOS Software Release [12.1X44-D15.5]'

That's all for now. I hope this helps you! Please consider joining us on IRC if you can at  #trigger on  irc.freenode.net!

Cheers!

jathan.


On Fri, Jun 27, 2014 at 8:03 AM, Dermot Williams <der...@deadlocked.org> wrote:
Hi Jathan,

Having tried several times to make some headway with Junosscript, I was intrigued by Trigger, which looks like it should make automated interactions with routers so much easier. True to form though, I've hit a brick wall :-(

Starting with the basics, I do the following:

In [1]: from trigger.cmds import Commando

In [2]: c = Commando(devices=['10.7.9.1'], commands=['show version'])

In [3]: c.run()

In [4]: c.results
Out[4]: {'10.7.9.1': {'show version': <Element '{http://xml.juniper.net/xnm/1.1/xnm}rpc-reply' at 0x25bc890>}}

Erk! How do I get at the XML that was returned? Passing force_cli=True to Commando is a little more useful but it feels like I shouldn't have to do that!

In [4]: c.results
Out[4]: {'10.7.9.1': {'show version': 'Hostname: lab\r\nModel: j4300\r\nJUNOS Software Release [8.2R4.5]\r\nJUNOS Web Management [8.2R4.5]\r\n\r\n'}}

Any pointers on what I'm missing?

Thanks,

Dermot

--
You received this message because you are subscribed to the Google Groups "Trigger" group.
To unsubscribe from this group and stop receiving emails from it, send an email to trigger-user...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Jathan.
--

Dermot Williams

unread,
Jul 4, 2014, 8:56:50 AM7/4/14
to trigge...@googlegroups.com
Hi Jathan,

Thanks, that was *very* helpful and much more than I expected! 

I was idling in IRC for a while but didn't want to come across as pushy, having just asked my question here! If I've any more questions I'll be sure to ask them in the channel though.

Regards,

Dermot

Jathan McCollum

unread,
Jul 10, 2014, 12:34:29 PM7/10/14
to trigge...@googlegroups.com
Awesome. I'm glad it was helpful. Someday we'll turn these into user docs. For now I just archive them away!

BTW, we just hang out in IRC all the time but aren't always necessarily present. If you pop in and pop out we might not have a chance to engage. But, that's why mailing list exists. Whatever works! :)

j.
Reply all
Reply to author
Forward
0 new messages