First steps with Python and Junos

27 04 2015

I’m just spending the day trying to get my head around some very basic automation, so I thought I would install Python 2.7 and work through some of the tutorials on the Techwiki to see how I get on.

The tutorial I’m following is called Python for Non-Programmers and offers an easy way in for people like me.  Of course as with a lot of open-source stuff, you don’t just download Python and get started – there are various dependencies, and dependencies with dependencies that you need to install first.  If at the end of all that you’ve not forgotten what your name is or why you were doing all this shenanigans in the first place you can count yourself as winning.

Installation on a Windows machine is documented nicely here, but there are a few things which are out of date.

One part where it tells you run an executable to install ‘lxml’ but there isn’t one when you click the link provided.  So instead you need to install it with a program called pip, which can be found in C:\Python27\scripts by default.  pip is not in the PATH envirronment variable by default either, so you need to use .\pip to invoke it at the powershell command line – see below:

PS C:\Python27\scripts> .\pip install lxml
Downloading/unpacking lxml
Installing collected packages: lxml
Successfully installed lxml
Cleaning up...
PS C:\Python27\scripts> .\pip install paramiko
Downloading/unpacking paramiko
Requirement already satisfied (use --upgrade to upgrade): pycrypto>=2.1,!=2.4 in c:\python27\lib\site-packages (from par
amiko)
Downloading/unpacking ecdsa>=0.11 (from paramiko)
Installing collected packages: paramiko, ecdsa
Successfully installed paramiko ecdsa
Cleaning up...
PS C:\Python27\scripts>

Then it tells you to go off and get ncclient from the Juniper Github repository. But that doesn’t exist any more. Instead it appears to get installed as part of the ‘junos-eznc’ installation. See below:

PS C:\Python27\scripts> .\pip install junos-eznc
Downloading/unpacking junos-eznc
Running setup.py (path:c:\users\andrew~1.mul\appdata\local\temp\pip_build_andrew.mulheirn\junos-eznc\setup.py) egg_info for package junos-eznc

Requirement already satisfied (use --upgrade to upgrade): lxml>=3.2.4 in c:\python27\lib\site-packages (from junos-eznc)

Downloading/unpacking ncclient>=0.4.3 (from junos-eznc)
Running setup.py (path:c:\users\andrew~1.mul\appdata\local\temp\pip_build_andrew.mulheirn\ncclient\setup.py) egg_info for package ncclient

Requirement already satisfied (use --upgrade to upgrade): paramiko in c:\python27\lib\site-packages (from junos-eznc)
Downloading/unpacking scp>=0.7.0 (from junos-eznc)
Downloading scp-0.9.0.tar.gz
Running setup.py (path:c:\users\andrew~1.mul\appdata\local\temp\pip_build_andrew.mulheirn\scp\setup.py) egg_info for package scp

Downloading/unpacking jinja2>=2.7.1 (from junos-eznc)
Running setup.py (path:c:\users\andrew~1.mul\appdata\local\temp\pip_build_andrew.mulheirn\jinja2\setup.py) egg_info for package jinja2

warning: no files found matching '*' under directory 'custom_fixers'
warning: no previously-included files matching '*' found under directory 'docs\_build'
warning: no previously-included files matching '*.pyc' found under directory 'jinja2'
warning: no previously-included files matching '*.pyc' found under directory 'docs'
warning: no previously-included files matching '*.pyo' found under directory 'jinja2'
warning: no previously-included files matching '*.pyo' found under directory 'docs'
Downloading/unpacking PyYAML>=3.10 (from junos-eznc)
Running setup.py (path:c:\users\andrew~1.mul\appdata\local\temp\pip_build_andrew.mulheirn\PyYAML\setup.py) egg_info for package PyYAML

Downloading/unpacking netaddr (from junos-eznc)
Requirement already satisfied (use --upgrade to upgrade): setuptools>0.6 in c:\python27\lib\site-packages (from ncclient>=0.4.3->junos-eznc)
Downloading/unpacking markupsafe (from jinja2>=2.7.1->junos-eznc)
Downloading MarkupSafe-0.23.tar.gz
Running setup.py (path:c:\users\andrew~1.mul\appdata\local\temp\pip_build_andrew.mulheirn\markupsafe\setup.py) egg_info for package markupsafe

Installing collected packages: junos-eznc, ncclient, scp, jinja2, PyYAML, netaddr, markupsafe
Running setup.py install for junos-eznc
Skipping installation of C:\Python27\Lib\site-packages\jnpr\__init__.py (namespace package)

Installing C:\Python27\Lib\site-packages\junos_eznc-1.1.2-py2.7-nspkg.pth
Running setup.py install for ncclient

Running setup.py install for scp

Running setup.py install for jinja2

warning: no files found matching '*' under directory 'custom_fixers'
warning: no previously-included files matching '*' found under directory 'docs\_build'
warning: no previously-included files matching '*.pyc' found under directory 'jinja2'
warning: no previously-included files matching '*.pyc' found under directory 'docs'
warning: no previously-included files matching '*.pyo' found under directory 'jinja2'
warning: no previously-included files matching '*.pyo' found under directory 'docs'
Running setup.py install for PyYAML
checking if libyaml is compilable
Microsoft Visual C++ 9.0 is required (Unable to find vcvarsall.bat). Get it from http://aka.ms/vcpython27
skipping build_ext

Running setup.py install for markupsafe

building 'markupsafe._speedups' extension
==========================================================================
WARNING: The C extension could not be compiled, speedups are not enabled.
Failure information, if any, is above.
Retrying the build without the C extension now.

==========================================================================
WARNING: The C extension could not be compiled, speedups are not enabled.
Plain-Python installation succeeded.
==========================================================================
Successfully installed junos-eznc ncclient scp jinja2 PyYAML netaddr markupsafe
Cleaning up...
PS C:\Python27\scripts>

So far so good!  Now it was time to test it.  I copied the sample script to do this and filled in the IP address, username and password to be used – I created this using the IDLE python development environment:

from pprint import pprint
from jnpr.junos import Device
dev = Device(host='192.168.3.99', user='andrew', password='Andrew')
dev.open()
pprint(dev.facts)
dev.close()

Then I ran the script from IDLE, but got this error back:

Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>>
Traceback (most recent call last):
File "C:\Python27\test.py", line 5, in <module>
dev.open()
File "C:\Python27\lib\site-packages\jnpr\junos\device.py", line 427, in open
raise EzErrors.ConnectRefusedError(self)
ConnectRefusedError: ConnectRefusedError(192.168.3.99)

 

This was a bit confusing.  I could SSH to the box just fine with those credentials, so it couldn’t be that surely?   I did a bit of googling and ended up looking at the code in device.py.  Fortunately it is well commented, and I found this:

except NcErrors.SSHError as err:
# this is a bit of a hack for now, since we want to
# know if the connection was refused or we simply could
# not open a connection due to reachability.  so using
# a timestamp to differentiate the two conditions for now
# if the diff is < 3 sec, then assume the host is
# reachable, but NETCONF connection is refushed.
ts_err = datetime.datetime.now()
diff_ts = ts_err - ts_start
if diff_ts.seconds < 3:
raise EzErrors.ConnectRefusedError(self)

 

So it looks like it tries to connect to the device, and if a connection fails within three seconds it is assumed the connection was refused.   Longer than three seconds and it is assumed there is an IP reachability problem and the connection is timing out.

This made it click for me.   Connections weren’t being refused for the user, but instead the netconf port was not open on the target device.   So SSH worked fine, but netconf connections were ‘refused’ at a TCP level,   A bit of a shame the error reporting wasn’t more precise, but we got there in the end.

Back to the router in question, and a “set system services netconf ssh” fixed it.

Now we get  the following in response to running the script:

>>>
{'2RE': True,
'HOME': '/var/home/andrew',
'RE0': {'last_reboot_reason': '0x1:power cycle/failure ',
'mastership_state': 'master',
'model': 'EX4500-40F',
'status': 'Absent',
'up_time': '221 days, 23 hours, 26 minutes, 6 seconds'},
'domain': None,
'fqdn': 'EX4500-1',
'hostname': 'EX4500-1',
'ifd_style': 'SWITCH',
'master': 'RE0',
'model': 'EX4500-40F',
'personality': 'SWITCH',
'serialnumber': 'GX0111297574',
'switch_style': 'VLAN',
'vc_capable': True,
'version': '12.3R5.7',
'version_RE0': '12.3R5.7',
'version_info': junos.version_info(major=(12, 3), type=R, minor=5, build=7)}

Bingo.

 

 

 

Advertisements

Actions

Information

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: