I subscribe to this guy's mailing list for his free python for network engineers email course, and he's just released an interesting little module.
Hope other python users find it interesting and/or useful!
It basically makes it much easier to manipulate devices in SSH than manually using existing tools like paramiko or pexpect which you have to manually 'screen scrape' the syntax in telnet/ssh (e.g. confirmation prompts, formatting issues, enable mode, etc.)
Highly recommend signing up for his course BTW
Kirk Byers
Twitter: @kirkbyers
https://pynet.twb-tech.com (https://pynet.twb-tech.com)
-----------------------------------------------------------------------
I have recently been working on an open-source Python library that simplifies SSH management to network devices. The library is based on the Paramiko SSH library.
The library is located here:
https://github.com/ktbyers/netmiko (https://github.com/ktbyers/netmiko)
and the latest release/download can be found at:
https://github.com/ktbyers/netmiko/releases (https://github.com/ktbyers/netmiko/releases)
The purposes of the library are the following:
1. Successfully establish an SSH connection to a device
2. Make it easy to execute show commands and to retrieve the output data
3. Make it easy to execute configuration commands
4. Do the above across a broad set of networking vendors and platforms
I have observed across time that you can encounter quite a few problems in managing Python SSH sessions. As an example, an HP ProCurve switch presents a "Press any key to continue" message after login. The ProCurve also has ANSI escape codes in the output. Note, this is not to pick on HP, you will run into issues with other vendors as well.
These type of issues can easily add hours of development time to your script and what is worse we have no way of leveraging the learning from other people (i.e. each person goes and reinvents the wheel).
So netmiko intends to simplify this lower-level SSH management across a wide set of networking vendors and platforms.
As of January 2015, Netmiko has been tested on the following (see the Netmiko README.md for more details):
Cisco IOS
Cisco IOS XE
Cisco IOS XR
Cisco ASA
Cisco NX-OS
Arista vEOS
HP ProCurve
Juniper Junos
Let me show you a couple of examples.
Example 1, a simple SSH session to a Cisco router that executes the 'show ip int brief' command.
First, I import the netmiko library and then define the network device as a dictionary:
>>> import netmiko
>>> cisco_881 = {
... 'device_type': 'cisco_ios',
... 'ip': '10.10.10.10', # real IP address hidden as it was a public IP
... 'username': 'test1',
... 'password': 'password',
... 'secret': 'secret',
... }
I then call a dispatcher using the device_type. The dispatcher just makes sure the right class is used.
>>> SSHClass = netmiko.ssh_dispatcher(cisco_881['device_type'])
I then connect to the device using the dictionary I created earlier:
>>> net_connect = SSHClass(**cisco_881)
SSH connection established to 10.10.10.10:22
Interactive SSH session established
At this point I have an SSH connection to the device and can execute commands on the channel. I use the send_command() method for this.
>>> output = net_connect.send_command("show ip int brief")
>>> print output
Interface IP-Address OK? Method Status Protocol
FastEthernet0 unassigned YES unset down down
FastEthernet1 unassigned YES unset down down
FastEthernet2 unassigned YES unset down down
FastEthernet3 unassigned YES unset down down
FastEthernet4 10.220.88.20 YES NVRAM up up
Vlan1 unassigned YES unset down down
Let's also try to make a configuration change to this router. First, I go into enable mode (which may or may not be necessary depending on your AAA setup):
>>> net_connect.enable()
>>> output = net_connect.send_command("show run | inc logging")
>>> print output
logging buffered 20010
no logging console
Now in order to make configuration changes, I specify a list of config commands that I want to execute. This could be a single command or multiple commands.
>>> config_commands = ['logging buffered 19999']
I then execute the send_config_set() method. This method takes care of entering configuration mode, enters the command(s), and then exits configuration mode.
>>> output = net_connect.send_config_set(config_commands)
>>> print output
pynet-rtr1#config term
Enter configuration commands, one per line. End with CNTL/Z.
pynet-rtr1(config)#logging buffered 19999
pynet-rtr1(config)#end
pynet-rtr1#
I can then verify my change:
>>> output = net_connect.send_command("show run | inc logging")
>>> print output
logging buffered 19999
no logging console
Example 2, executing 'show arp' on a set of networking devices consisting of different vendors and platforms.
First, I define the networking devices:
>>> import netmiko
>>>
>>> cisco_881 = {
... 'device_type': 'cisco_ios',
... 'ip': '10.10.10.10',
... 'username': 'admin',
... 'password': 'password',
... 'secret': 'secret',
... }
>>>
>>> cisco_asa = {
... 'device_type': 'cisco_asa',
... 'ip': '10.10.10.11',
... 'username': 'admin',
... 'password': 'password',
... 'secret': 'secret',
... }
>>>
>>> arista_veos_sw = {
... 'device_type': 'arista_eos',
... 'ip': '10.10.10.12',
... 'username': 'admin',
... 'password': 'password',
... 'port': 8522, # Firewall in front of this device, PAT from 8522 to 22
... }
>>>
>>> hp_procurve = {
... 'device_type': 'hp_procurve',
... 'ip': '10.10.10.12',
... 'username': 'admin',
... 'password': 'password',
... 'port': 9922, # Firewall in front of this device, PAT from 9922 to 22
... }
>>>
>>> juniper_srx = {
... 'device_type': 'juniper',
... 'ip': '10.10.10.12',
... 'username': 'root',
... 'password': 'password',
... 'port': 9822, # Firewall in front of this device, PAT from 9822 to 22
... }
Then create a list that includes all of these devices:
>>> all_devices = [cisco_881, cisco_asa, arista_veos_sw, hp_procurve, juniper_srx]
Finally, iterate over each of these devices and execute the 'show arp' command:
>>> for a_device in all_devices:
... SSHClass = netmiko.ssh_dispatcher(a_device['device_type'])
... net_connect = SSHClass(**a_device)
... output = net_connect.send_command("show arp")
... print "\n\n>>>>>>>>> Device {0} <<<<<<<<<".format(a_device['device_type'])
... print output
... print ">>>>>>>>> End <<<<<<<<<"
...
>>>>>>>>> Device cisco_ios <<<<<<<<<
Protocol Address Age (min) Hardware Addr Type Interface
Internet 10.220.88.1 42 001f.9e92.16fb ARPA FastEthernet4
Internet 10.220.88.20 - c89c.1dea.0eb6 ARPA FastEthernet4
Internet 10.220.88.100 207 f0ad.4e01.d933 ARPA FastEthernet4
>>>>>>>>> End <<<<<<<<<
>>>>>>>>> Device cisco_asa <<<<<<<<<
inside 10.220.88.10 0018.fe1e.b020 179
inside 10.220.88.39 6464.9be8.08c8 316
inside 10.220.88.31 5254.0001.3737 1068
inside 10.220.88.100 f0ad.4e01.d933 2568
inside 10.220.88.30 5254.0092.13bb 4049
inside 10.220.88.29 5254.0098.69b6 5408
inside 10.220.88.21 1c6a.7aaf.576c 6318
inside 10.220.88.28 5254.00ee.446c 6796
inside 10.220.88.40 001c.c4bf.826a 8358
inside 10.220.88.20 c89c.1dea.0eb6 11838
>>>>>>>>> End <<<<<<<<<
>>>>>>>>> Device arista_eos <<<<<<<<<
Address Age (min) Hardware Addr Interface
10.220.88.1 0 001f.9e92.16fb Vlan1, Ethernet1
10.220.88.28 0 5254.00ee.446c Vlan1, not learned
10.220.88.29 0 5254.0098.69b6 Vlan1, not learned
10.220.88.30 0 5254.0092.13bb Vlan1, not learned
>>>>>>>>> End <<<<<<<<<
>>>>>>>>> Device hp_procurve <<<<<<<<<
IP ARP table
IP Address MAC Address Type Port
--------------- ----------------- ------- ----
10.220.88.1 001f9e-9216fb dynamic 19
>>>>>>>>> End <<<<<<<<<
>>>>>>>>> Device juniper <<<<<<<<<
MAC Address Address Name Interface Flags
00:1f:9e:92:16:fb 10.220.88.1 10.220.88.1 vlan.0 none
f0:ad:4e:01:d9:33 10.220.88.100 10.220.88.100 vlan.0 none
Total entries: 2
>>>>>>>>> End <<<<<<<<<
Note, it took 51 seconds for the above for-loop code to execute. This could be improved by executing the SSH sessions in parallel, for an example of this see:
https://github.com/ktbyers/netmiko/blob/master/examples/multiprocess_example.py (https://github.com/ktbyers/netmiko/blob/master/examples/multiprocess_example.py)
For a list of supported device_types see:
https://github.com/ktbyers/netmiko/blob/master/netmiko/ssh_dispatcher.py (https://github.com/ktbyers/netmiko/blob/master/netmiko/ssh_dispatcher.py)
If you have additional vendors or platforms that you want supported, email me (or even better send me a pull-request). I would like to add additional vendor support, but in order to do this, I need a reasonable way to test the code against said vendor.
Special thanks to Pablo Lucena, Ron Nilekani, and Will Dennis for the assistance they have provided in writing and/or testing some of the code.
Kirk Byers
Twitter: @kirkbyers
https://pynet.twb-tech.com (https://pynet.twb-tech.com)
I think this type of modules had existed for years; I used something similar for Perl many years ago.
That's interesting. I've tried to avoid using modules like this recently. I had a few scripts that heavily relied on Exscript and they would always break when some lower-level module updated. It ended up being more work than just using Paramiko by itself.
Been using perl for stuff like this but with the huge momentum python has going maybe its time to pick it up..
Sent from my iPhone using Tapatalk