Archive
, Super Contributor
Archive
Python for Non-Programmers (Part 3)
Nov 15, 2013

MANAGING RISK IN CHANGE

 

One of the consistent comments I get from soon-to-be-not-programmers is they are afraid  they will accidentally made changes to the configuration and hurt the network.  I think that is a very fair and valid concern.  Therefore to mitigate that fear and risk it is incumbent upon the Python library "Junos EZ" to provide the necessary "guard-rails". 

 

If you take a look at both the Puppet and Chef automation frameworks, they both are built around the concept that models changes in terms of "Resources" and "Properties".  They call these things by different names, but here is my simple interpretation and gist of it: 

 

  • A Resource is a thing that you want to config-manage
  • Every Resource has a Name that uniquely identifies it
  • Resources have a set of Properties that you can change
  • A Resources is selected by Name from a Manager
  • A Manager will provide you a List of Resource Names
  • A Manager will provide you a Catalog of the Resources 

 

MANAGING BY ABSTRACTION

 

What also makes IT frameworks like Puppet and Chef attractive is that they provide a layer of abstraction between "What" you want to manage and "How" the Resource is actually implemented. 

 

For example, when an admin wants to manage a user resource on a server with Puppet, it would look something like this:

 

 user { 'dave':
      ensure     => present,
      uid        => '507',
      gid        => 'admin',
      shell      => '/bin/zsh',
      home       => '/home/dave',
password => '"$1$JJsvHslV$szsCjVEroftprNn4JHtDi.", }

 

The above snippet is used to ensure that user named "dave" is on the server with the associated properties ("uid","gid","shell","home") set accordingly.   

 

The same user resource pattern is implemented with Chef like this:

 

user "dave" do
  supports :manage_home => true
  comment "Dave Bubbha Hotep"
  uid 507
  gid "admin"
  home "/home/dave"
  shell "/bin/zsh"
  password "$1$JJsvHslV$szsCjVEroftprNn4JHtDi."
end

 

RESOURCE MANAGEMENT - NOW FOR JUNOS

 

The jnpr.eznc library follows a similar design pattern.  Lets take a look at what this would look like from the Python shell.  For the sake of example brevity, assume that we've got an open Netconf connection variable called dev - if you want to see how these are created, refer back to the previous blog.

 

>>> from jnpr.junos.cfg.user import User
>>> users = User(dev)
>>> users
Resource Manager: User

 

If we want to see a list of users configured on this device, we can access the resource manager list attribute:

 

>>> users.list
['jeremy', 'kim']

 

If we wanted a catalog of the users, we can access the resource manager catalog attribute.  The catalog is a hash table (Python dictionary) of resource names and their current property values.   I'll leave that as an exercise for the reader, since the output is a bit lengthy. 

 

We can select a user resource by name from the resource manager.  Here I am selected user 'jeremy'.

 

>>> me = users['jeremy']

 

I can take a look at the contents of my existing properties, i.e. the current configuration, by inspecting the me variable:

 

>>> me
NAME: User: jeremy
HAS: {'$password': '$1$n/RPB3fZ$RGPy8hymoTa8G5oGiJMdr.',
 '$sshkeys': [('ssh-rsa',
               'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAm2JAE<SNIPPED>== jeremy@laptop.juniper.net')],
 '_active': True,
 '_exists': True,
 'fullname': 'Jeremy Schulman',
 'uid': 2001,
 'userclass': 'super-user'}
SHOULD:{}

 

There are a number of details here that I'm going to skip for now, but what's important is that you now have the ability to read and write specific property values using this resource and accessing it by the property name.  For example, if I want to access the current fullname property I can do this:

 

>>> print "My name is %s" % me['fullname']
My name is Jeremy Schulman

 

And if I want to update the name I can write the value into the resource write-back cache

 

>>> me['fullname'] = "Jeremy L. Schulman"

 

And now I can see what is in the write-back cache - look at the "SHOULD":

 

>>> me
NAME: User: jeremy
HAS: {'$password': '$1$n/RPB3fZ$RGPy8hymoTa8G5oGiJMdr.',
 '$sshkeys': [('ssh-rsa',
               'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA== jeremy@laptop.juniper.net')],
 '_active': True,
 '_exists': True,
 'fullname': 'Jeremy Schulman',
 'uid': 2001,
 'userclass': 'super-user'}
SHOULD:{'fullname': 'Jeremy L. Schulman'}

 

You can make many property changes before writing them back to the device.  When you are ready push your changes to the device, you invoke the write() on the resource.  It will only write the changes in the write-back cache.

 

>>> me.write()
True

 

There are alternative ways of changing the properties, and one includes the combination of setting multiple values and writing back to the Junos device. 

 

At this point the Junos candidate configuration has been changed, but not committed.  You can see the change and commit it using the Config utility we talked about in the prior blog:

 

>>> from jnpr.junos.utils.config import Config
>>> cu = Config(dev)
>>> print cu.diff()

[edit system login user jeremy]
-    full-name "Jeremy Schulman";
+    full-name "Jeremy L. Schulman";

 

Then we could commit-check and commit the changes:

 

>>> cu.commit_check()
True
>>> cu.commit()
True

 

 

WHAT ABOUT HELP?

 

If you want to see what properties a resource has, you can examine the properties attribute:

 

>>> me.properties
['_exists', '_active', 'uid', 'fullname', 'userclass', 'password', '$password', '$sshkeys']

 

And of course, you can get resource help by invoking the Python help() on the me resource, but I'll leave that as an exercise for the reader.

 

You're probably wondering what the dollar-sign ($) means on some of the property names.  Those properties are READ-ONLY.  So in the case of the User resource, the $password property is the read-only encrypted password value, and the password property can be used to change the value as plain-text.  For example, the current encrypted password is:

 

>>> me['$password']
'$1$n/RPB3fZ$RGPy8hymoTa8G5oGiJMdr.'

 

And I can change it to something else:

 

>>> me(password="this is so freaking cool")
True
>>> me.write()
True
>>> me['$password']
'$1$n/RPB3fZ$RGPy8hymoTa8G5oGiJMdr.'
###
### OOPS, we need to re-read the values from the device
###
>>> me.read()
True
>>> me['$password']
'J4XQN8E7qVtkE'

 

But I don't really want to make this change, so I'll rollback the config:

 

>>> cu.rollback()
True
>>> me.read()
True
>>> me['$password']
'$1$n/RPB3fZ$RGPy8hymoTa8G5oGiJMdr.'

 

BUT WAIT, THERE'S SO MUCH MORE!

 

If you'd like to see everything you can do with Resources, take a look at the on-line Junos EZ documentation, here.  The net-net, however, is you can basically do everything that you can do from the command line, including activate, deactivate, delete, rename, and re-order.

 

SO WHAT CAN I MANAGE AS A RESOURCE?

 

The catalog of jnpr.eznc Resources will expand over time.  At the time of this writing there is a large collection of resources to manage the SRX firewall.  Take a look at the jnpr.eznc documentation for use the help() command at the Python shell for more details.

 

BUILT FOR THE COMMUNITY, ... AND BY THE COMMUNITY?

 

The goal of the jnpr.eznc library is to enable the rapid development of new Resources and Utilities.  Some of these Juniper will build.  Other resources might be built by Juniper Partners or Customers.  It's an Open Source project that was designed for extensibility at high velocity.  We'll that's my bold aspiration at least.  Time will tell.

 

FURTHER READING

 

 

 

Jan 14, 2014
Juniper Employee

I recently wrote my first successful SLAX script and found your blogs about Python during my research..

 

I'm trying to pursuade my customer on the merits of Junos automation and am wondering how to position SLAX scripts vs Python?

 

What are the advanatages and disadvanatages of one and the other?

Jan 14, 2014

@challinger,

 

This is a good question, and one that has been asked by a number of folks.  Rather than answer it here, I will start a separate blog posting on this topic.  I hope to have that written within a week or so.

 

If you need some guidance urgently, please contact me directly and we can disucss 1x1: jschulman@juniper.net