Automation & Programmability
Showing results for 
Search instead for 
Do you mean 

Python for Non-Programmers (Part 5)

by ‎12-03-2013 11:42 AM - edited ‎03-27-2014 04:41 AM

WHAT IS OPERATIONAL STATE?

 

Operational state is the result of the network configuration and system behavior.  To the network engineer, this information is generally provided by the Junos CLI "show" commands.  We can, for eample, configure interfaces to participate in OSPF.  We can then obtain the operational state of their neighbor relationship with the "show ospf neighbor" command. 

 

These "show" command make up the backbone of troubleshooting, reporting, and auditing tasks.  Performing these tasks manually is often painfully complex and often requires coordinating various pieces of data from different show commands.  Sometimes you need to login to multiple devices to perform network-wide troubleshooting.

 

There is a better way.

 

A DIFFERENT POINT OF VIEW

 

Imagine that all Junos operational data is stored in a "database".  A database is a collection of "tables".  The Junos CLI command "show ospf neighbor" command, for example, provides the a table of ospf-neighbor information from the operational-state database.  Viewed from the CLI that information is rendered into human readable text, but we know that everything inside Junos is constructed as XML.  The Junos CLI provides us with a "view" of the data, and in some cases we can control if we want that view to be "brief", "detailed" or "extensive".

 

The Junos EZ library uses the same idea and concepts and applies them into the Python shell environment.  In this way, you can retrieve table information and extract the fields from the associated view.  The novel aspect of Junos EZ is you get to decide the content of the view - you can decide the name of the fields, and how the information is presented.  Best of all, you don't need to write any Python code do setup Tables and Views - but we'll get to that in a bit.

 

A QUICK TOUR

 

Let's take a quick tour of the "Ethernet Port Table".  First we need to import the Table we want:

 

>>> from jnpr.junos.op.ethport import *

# display the existing items, we see 'EthPortTable'

>>> dir()
['EthPortTable', 'EthPortView', '__builtins__', '__doc__', '__name__', '__package__', 'connect', 'dev', 'dirname', 'join', 'junos', 'loadyaml', 'pp', 'sshconf_find', 'sys']

 

Next we make an association with a Device variable and that Table definition.  This action does not retrieve any data, just creates the association:

 

>>> eths = EthPortTable(dev)

# examining the table, we can see the name of the Device
# bound, and that the table has 0 items, since we haven't
# retrieved anything yet
 
>>> eths
EthPortTable:jnpr-dc-fw: 0 items

 

Next we retrieve the table records.  We have a few options here.  We could retrieve all of the records or we can limit the scope.  This would be the same as either doing "show interfaces" (all) or "show interfaces ge-0/0/0" (scoped).  There is more to say on the scoping capabilities, and you can find more at the online docs, here.

 

For now, just get all of the table data:

 

>>> eths.get()
EthPortTable:jnpr-dc-fw: 3 items

 

We can examine the keys (record names):

 

>>> eths.keys()
['ge-0/0/0', 'ge-0/0/1', 'ge-0/0/2']

 

And even dump all of the items.  You can do this by pretty printing the eths.items(), but I'll leave that as an excercise for the reader.

 

To select a specific record, you can index the selection by either an index number (starting wtih 0 = first record) or by key-name.

 

>>> e0 = eths['ge-0/0/0']

# if we examine the variable, we see that it is a "View"

>>> e0
EthPortView:ge-0/0/0

 

A "View" allows you to access the fields of the record.  To see a list of field-names, you could do:

 

>>> pprint( e0.keys() )
['oper',
 'rx_packets',
 'macaddr',
 'rx_bytes',
 'admin',
 'mtu',
 'running',
 'link_mode',
 'tx_bytes',
 'tx_packets',
 'present']

 

And you can access the field values by name like so:

 

# what is the MAC address?

>>> e0.macaddr
'00:0c:29:eb:a2:b7'

 

 

EXAMPLE TROUBLESHOOTING

 

Let's say that you want to find any interface that is administratively configured to be "up", but happens to be operational "down".  What might that look like, assuming we've got our eths table loaded.  We could do something like this.  Assuming "ge-0/0/1" was in this condition:

 

>>> for port in eths:
...    if port.admin == 'up' and port.oper == 'down':
...       print "port %s is messed up" % port.name
... 
port ge-0/0/1 is messed up

 

 

Once you get into using Python "idioms", you could simply into something that looks like this:

 

>>> [ port.name for port in eths if port.oper == 'down' and port.admin == 'up']
['ge-0/0/1']

 

 

DEFINING YOUR POINT OF VIEW

 

The "power" of any framework is defined by how open and easy it is for someone other than the developer to extend the functionality.  To this end, I've tried to make the process of defining Tables and Views very easy - no programming is actually required.  You simply define your Tables and Views in a YAML (structured text) file and then import the definitions at runime.  You can see examples of these YAML files in the Junos EZ "op" directory, here.

 

Let's see how these files are imported by doing one manually.  I'll load the "EthPortTable" definition explicitly (this is done automatically by the ethport.py file).  Assuming that the file was local to the directory I started in, this would be:

 

>>> from jnpr.junos.factory import loadyaml

# load the definitions into a Python dictionary >>> mydefs = loadyaml('ethport.yml') # inspect mydefs, this is a dictionary of item name to class. >>> mydefs {'EthPortTable': <class 'jnpr.junos.op.rsmaker.EthPortTable'>, 'EthPortView': <class 'jnpr.junos.op.rsmaker.EthPortView'>} # you can then use the EthPortTable like so: >>> EthPortTable = mydefs['EthPortTable'] >>> eths = EthPortTable(dev) >>> eths EthPortTable:jnpr-dc-fw: 0 items >>> eths.get() EthPortTable:jnpr-dc-fw: 3 items

 

 

WHAT'S NEXT?

 

I'll be writing more documentation on the step-by-step guide to writing Table/View YAML files.  Keep an eye on the github repo docs directory.

 

I'll also start working on short "cookbook" articles and post them on the Juniper "TechWiki".  Stay tuned!

 

I hope this series has helped you get started with Junos automation using Python.  Any questions, please reach out to me, or open requests/issues directly on the Junos EZ github repo, here.

 

Happy not-coding!

 

 

 

 


 

 

 

Comments
by Nitin Kumar
on ‎03-21-2014 02:39 AM

Need to update the page. 

below import command wont work now.

from jnpr.junos.op.yaml import loadyaml

 

Now it will be:

from jnpr.junos.factory import loadyaml

by
on ‎03-27-2014 04:42 AM

@Nitin,

 

Thank you, I just fixed the blog. 

by Juniper Employee
on ‎10-08-2015 07:17 AM

The eths.get() is not working.  I tried with both an MX router and EX4500 switch.  Can someone tell me how to get this to work?

Thanks.

 

--------------------------------------------------------------------------------------------------------------------------------------

 

>>> eths = EthPortTable(dev)

 

>>> eths
EthPortTable:10.8.2.152 - Table empty

>>> eths.get()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\site-packages\jnpr\junos\factory\optable.py", line 63, in get
    self.xml = getattr(self.RPC, self.GET_RPC)(**rpc_args)
  File "C:\Python27\lib\site-packages\jnpr\junos\rpcmeta.py", line 143, in _exec_rpc
    return self._junos.execute(rpc, **dec_args)
  File "C:\Python27\lib\site-packages\jnpr\junos\decorators.py", line 44, in wrapper
    restore_transform = dev.transform
  File "C:\Python27\lib\site-packages\jnpr\junos\device.py", line 230, in transform
    return self._conn._device_handler.transform_reply
AttributeError: 'NoneType' object has no attribute '_device_handler'

 

by Distinguished Expert
on ‎10-08-2015 08:22 AM

Hi V

 

I think you forgot to do dev.open(). I see the same error if I don't do it:

 

>>> from jnpr.junos import Device
>>> from jnpr.junos.op.ethport import EthPortTable
>>> dev = Device(host="10.254.0.34", user="****", passwd="*****")
>>> eths = EthPortTable(dev)
>>> eths
EthPortTable:10.254.0.34 - Table empty
>>> eths.get()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/factory/optable.py", line 63, in get
    self.xml = getattr(self.RPC, self.GET_RPC)(**rpc_args)
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/rpcmeta.py", line 143, in _exec_rpc
    return self._junos.execute(rpc, **dec_args)
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/decorators.py", line 44, in wrapper
    restore_transform = dev.transform
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/device.py", line 230, in transform
    return self._conn._device_handler.transform_reply
AttributeError: 'NoneType' object has no attribute '_device_handler'
>>> dev.open()
Device(10.254.0.34)
>>> eths.get()
EthPortTable:10.254.0.34: 4 items
>>> 
by Juniper Employee
on ‎10-08-2015 08:35 AM

That resolved the issue, thank you PK !

Announcements

Juniper Design & Architecture Center - Mobile Cloud
About the Author
  • Ben has been working with service providers around the world for the last 15 years developing business cases for a variety of product concepts and new ventures. Ben holds an MBA from MIT and a BS & MS in Mechanical Engineering from Johns Hopkins University.
  • Part of Juniper PS EMEA since 2005 Primarily interested in making technology do the boring repetitive work so I can do fun new work.
  • Donyel Jones-Williams is the Director of Service Provider Product Marketing Management overseeing all of Juniper's Service Provider Products for Juniper Networks. In this role, he leads all of the internal and external marketing activities for Juniper with respect to routing, automation, SDN and NFV. Prior to joining Juniper Networks in January 2014, Donyel was a Senior Product Line Manager for Cisco Systems with in the High End Optical Routing Group managing product lifecycle for multiple products lines helping telecom providers operate efficiently and effectively including; ONS 155xx Product Family, ONS 15216, ONS 15454 MSTP, Carrier Packet Transport Product Family, ME 2600x, & ASR 9000v. He also negotiated favorable agreements with 3rd-party vendors furnishing components and parts and conducted both outbound and inbound marketing (webinars, case study-development, developed and delivered both business & technical at Cisco Live 2005-2012). Donyel graduated from California Polytechnic State University-San Luis Obispo with a Bachelor of Science in Computer Science. While attending Cal Poly SLO he was a collegiate student athlete playing football as a wide receiver and a key member of the National Society of Black Engineers. Donyel is now an active volunteer for V Foundation.
  • Ebben Aries is a Principal Engineer for Junos Manageability in the Juniper Development and Innovation Division.
  • Marcel Wiget is a member of the Routing TME team. His career within Juniper started back in 2009 as a Senior Systems Engineer driving one of the first MX based Broadband Edge deployment to success. Prior to Juniper, Marcel held various positions in pre-sales, professional services and development at Chantry Networks, Spring Tide, Nortel Networks and Wellfleet.
  • Michael Pergament, JNCIE-SP #510, JNCIE-ENT #23, JNCIP-SEC
  • Pallavi Mahajan is Vice President Engineering, Junos Engineering, and leads the Junos Programmability & Automation teams
  • Product Manager, JUNOS Automation