router image

Netmiko Library

By Kirk Byers
Updated 2019-01-02

Since late 2014, I have been working on an open-source Python library that simplifies SSH management to network devices. The library is based on the Paramiko SSH library and is named Netmiko.

You can find the library at https://github.com/ktbyers/netmiko and the latest released version of the software can be downloaded here.


The purposes of this library are the following:

  • Successfully establish an SSH connection to the device
  • Simplify the execution of show commands and the retrieval of output data
  • Simplify execution of configuration commands including possibly commit actions
  • Do the above across a broad set of networking vendors and platforms


Some additional articles and documentation on Netmiko can be found at:


Various example code can be found here:

Note, the ConnectHandler class is identical to the Netmiko class. You might see ConnectHandler referenced in other Netmiko examples.



Why was Netmiko created?

At the time, I had observed that many individuals encountered similar issues with Python-SSH and network devices. For example, HP ProCurve switches have ANSI escape codes in the output or the Cisco WLC has an extra 'login as:' message. These types of issues can soak up a lot of development and troubleshooting time and, what is worse, people keep solving the same issues over and over again (including sometimes not solving them and giving up).

So Netmiko was created to simplify this lower-level SSH management across a wide set of networking vendors and platforms.



Platform Support:

As of January 2019, Netmiko supports the following platforms with the indicated level of testing.

Regularly tested:

  • Arista EOS
  • Cisco ASA
  • Cisco IOS/IOS-XE
  • Cisco IOS-XR
  • Cisco NX-OS
  • Cisco SG300
  • HP Comware7
  • HP ProCurve
  • Juniper Junos
  • Linux

Limited testing:

  • Alcatel AOS6/AOS8
  • Apresia Systems AEOS
  • Calix B6
  • Cisco AireOS (Wireless LAN Controllers)
  • Dell OS9 (Force10)
  • Dell OS10
  • Dell PowerConnect
  • Extreme ERS (Avaya)
  • Extreme VSP (Avaya)
  • Extreme VDX (Brocade)
  • Extreme MLX/NetIron (Brocade/Foundry)
  • Huawei
  • IP Infusion OcNOS
  • Mellanox
  • NetApp cDOT
  • OneAccess
  • Palo Alto PAN-OS
  • Pluribus
  • Ruckus ICX/FastIron
  • Ubiquiti EdgeSwitch
  • Vyatta VyOS

Experimental:

  • A10
  • Accedian
  • Aruba
  • Ciena SAOS
  • Citrix Netscaler
  • Cisco Telepresence
  • Check Point GAiA
  • Coriant
  • Dell OS6
  • Dell EMC Isilon
  • Eltex
  • Enterasys
  • Extreme EXOS
  • Extreme Wing
  • Extreme SLX (Brocade)
  • F5 TMSH
  • F5 Linux
  • Fortinet
  • MRV Communications OptiSwitch
  • Nokia/Alcatel SR-OS
  • QuantaMesh
  • Rad ETX


Example 1: Simple SSH session to a Cisco router; execute and return the 'show ip int brief' command.

First, I must import the ConnectHandler factory function from Netmiko. This factory function selects the correct Netmiko class based upon the device_type. I then define a network device dictionary consisting of a device_type, ip, username, and password.

In [1]: from netmiko import ConnectHandler                                                                                                         

In [2]: cisco = { 
   ...:   'device_type': 'cisco_ios', 
   ...:   'host': 'cisco.domain.com', 
   ...:   'username': 'admin', 
   ...:   'password': 'cisco123', 
   ...:   }  

At this point, I should be able to connect to the device.

Notice above that I have specified the device_type as 'cisco_ios'. The supported device_types can generally be found here.


Now in order to connect all I need to do is call ConnectHandler and pass in my earlier defined device dictionary:

In [3]: net_connect = ConnectHandler(**cisco) 

Alternatively, I could just call the ConnectHandler function directly and not use a dictionary (as follows):

net_connect2 = ConnectHandler(device_type='cisco_ios', host='cisco.domain.com', username='admin', password='cisco123') 

Now at this point we should have an established SSH connection. I can verify this by executing the find_prompt() method

In [5]: net_connect.find_prompt()
Out[5]: 'cisco3#' 

I can also send commands down the SSH channel and receive the output back. Here, I use the .send_command() method to send the 'show ip int brief' command:

In [6]: output = net_connect.send_command("show ip int brief")

In [7]: print(output)
Interface              IP-Address      OK? Method Status                Protocol
GigabitEthernet0/0/0   10.10.10.22    YES manual up                    up      
GigabitEthernet0/0/1   unassigned      YES NVRAM  administratively down down    
GigabitEthernet0/1/0   unassigned      YES unset  down                  down    
GigabitEthernet0/1/1   unassigned      YES unset  down                  down    
GigabitEthernet0/1/2   unassigned      YES unset  down                  down    
GigabitEthernet0/1/3   unassigned      YES unset  down                  down    
Vlan1                  unassigned      YES unset  up                    down    

Let's also try to make a configuration change to this router. First, let's look at the current logging configuration:

In [8]: output = net_connect.send_command("show run | inc logging")

In [9]: print(output)
 logging synchronous 

Now in order to make configuration changes, I create a list of configuration commands that I want to execute. This could be a single command or multiple commands.

In [10]: config_commands = ['logging buffered 19999']  

I then execute the send_config_set() method. This method will enter configuration mode, execute the commands, and then exit configuration mode (note, there will be some exceptions to this behavior depending on the platform--for example, IOS-XR will not exit configuration mode due to pending changes).

In [11]: output = net_connect.send_config_set(config_commands)

In [12]: print(output)
config term
Enter configuration commands, one per line.  End with CNTL/Z.
cisco3(config)#logging buffered 19999
cisco3(config)#end
cisco3#

I can then verify my change:

In [13]: output = net_connect.send_command("show run | inc logging")

In [14]: print(output)
logging buffered 19999
 logging synchronous 


Example 2: Executing 'show arp' on a set of networking devices consisting of different vendors and platforms.

netmiko show arp image netmiko show arp image

First, I need to define the networking devices (real IP addresses and passwords have been hidden):

In [1]: from netmiko import ConnectHandler 

In [2]: from datetime import datetime

In [3]: cisco3 = {
   ...:     'device_type': 'cisco_ios',
   ...:     'host':   'cisco3.domain.com',
   ...:     'username': 'admin',
   ...:     'password': 'cisco123',
   ...: }
   ...:

In [4]: cisco_asa = {
   ...:     'device_type': 'cisco_asa',
   ...:     'host': '10.10.10.88',
   ...:     'username': 'admin',
   ...:     'password': 'cisco123',
   ...:     'secret': 'cisco123',
   ...: }
   ...:

In [5]: cisco_xrv = {
   ...:     'device_type': 'cisco_xr', 
   ...:     'host': '10.10.10.77', 
   ...:     'username': 'admin', 
   ...:     'password': 'cisco123', 
   ...: }

In [6]: arista8 = { 
   ...:     'device_type': 'arista_eos', 
   ...:     'host':   'arista8.domain.com', 
   ...:     'username': 'admin', 
   ...:     'password': '!cisco123', 
   ...: } 
   ...:

In [7]: hp_procurve = { 
   ...:     'device_type': 'hp_procurve', 
   ...:     'host': '10.10.10.68', 
   ...:     'username': 'admin', 
   ...:     'password': '!cisco123', 
   ...: } 
   ...:

In [8]: juniper_srx = { 
   ...:     'device_type': 'juniper', 
   ...:     'host':   'srx1.domain.com', 
   ...:     'username': 'admin', 
   ...:     'password': '!cisco123', 
   ...: } 
   ...:   

Next, I need to create a Python list that includes all of these devices:

all_devices = [cisco3, cisco_asa, cisco_xrv, arista8, hp_procurve, juniper_srx] 

Now, I will create a for loop that iterates over all of these devices. Each time through the loop: the code will connect to the device, execute 'show arp', and then display the output. I will also keep track of the time that it takes for the code execute.

Note, I have changed the output slightly (so that you can more clearly see what I pasted in versus the output back from the devices).

In [12]: start_time = datetime.now() 
    ...: for a_device in all_devices: 
    ...:     net_connect = ConnectHandler(**a_device) 
    ...:     output = net_connect.send_command("show arp") 
    ...:     print(f"\n\n--------- Device {a_device['device_type']} ---------") 
    ...:     print(output) 
    ...:     print("--------- End ---------") 
    ...:  
    ...: end_time = datetime.now() 
    ...: total_time = end_time - start_time  

Here is the output from the for loop (i.e. all of the "show arp" output):


--------- Device cisco_ios ---------
Protocol  Address          Age (min)  Hardware Addr   Type   Interface
Internet  10.10.10.1            32   0062.ec29.70fe  ARPA   GigabitEthernet0/0/0
Internet  10.10.10.20          156   c89c.1dea.0eb6  ARPA   GigabitEthernet0/0/0
Internet  10.10.10.22            -   a093.5141.b780  ARPA   GigabitEthernet0/0/0
Internet  10.10.10.37          178   0001.00ff.0001  ARPA   GigabitEthernet0/0/0
Internet  10.10.10.38           15   0002.00ff.0001  ARPA   GigabitEthernet0/0/0
--------- End ---------


--------- Device cisco_asa ---------
	outside 10.10.10.1 0062.ec29.70fe 1949
	outside 10.10.10.20 c89c.1dea.0eb6 10226
	outside 10.10.10.37 0001.00ff.0001 11606
	outside 10.10.10.38 0002.00ff.0001 11636

--------- End ---------


--------- Device cisco_xr ---------

Thu Jan  3 00:45:44.240 UTC

-------------------------------------------------------------------------------
0/0/CPU0
-------------------------------------------------------------------------------
Address         Age        Hardware Addr   State      Type  Interface
10.10.10.1     00:32:36   0062.ec29.70fe  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.19    02:50:35   0024.c4e9.48ae  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.20    00:30:26   c89c.1dea.0eb6  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.21    03:09:20   1c6a.7aaf.576c  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.22    02:58:54   a093.5141.b780  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.23    01:37:37   502f.a8b1.6900  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.32    02:56:30   5254.abc7.26aa  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.37    -          0001.00ff.0001  Interface  ARPA  GigabitEthernet0/0/0/0
10.10.10.38    01:55:33   0002.00ff.0001  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.39    00:11:32   6464.9be8.08c8  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.42    00:00:46   ec38.739e.2f08  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.43    00:22:35   5254.abda.5495  Dynamic    ARPA  GigabitEthernet0/0/0/0
--------- End ---------


--------- Device arista_eos ---------
Address         Age (min)  Hardware Addr   Interface
10.10.10.1             0  0062.ec29.70fe  Vlan1, Ethernet1
10.10.10.20            0  c89c.1dea.0eb6  Vlan1, not learned
10.10.10.43            0  5254.abda.5495  Vlan1, not learned
--------- End ---------


--------- Device hp_procurve ---------

 IP ARP table

  IP Address      MAC Address       Type    Port
  --------------- ----------------- ------- ----
  10.10.19.1     0062ec-2970fd     dynamic 26  
  10.10.19.20    c07bbc-65272e     dynamic 26  
 

--------- End ---------


--------- Device juniper ---------

MAC Address       Address         Name                      Interface           Flags
00:62:ec:29:70:fe 10.10.10.1     10.10.10.1               vlan.0              none
c8:9c:1d:ea:0e:b6 10.10.10.20    10.10.10.20              vlan.0              none
Total entries: 2

--------- End ---------

In [13]: print(total_time) 
0:00:42.062773 

As you can see the code took slightly longer than 42 seconds to execute. This could be significantly improved by creating the SSH sessions concurrently see the code here for some examples using concurrency.



Netmiko commonly-used methods:

  • net_connect.send_command() - Send command down the channel, return output back (pattern based)
  • net_connect.send_command_timing() - Send command down the channel, return output back (timing based)
  • net_connect.send_config_set() - Send configuration commands to remote device
  • net_connect.send_config_from_file() - Send configuration commands loaded from a file
  • net_connect.save_config() - Save the running-config to the startup-config
  • net_connect.enable() - Enter enable mode
  • net_connect.find_prompt() - Return the current router prompt
  • net_connect.commit() - Execute a commit action on Juniper and IOS-XR
  • net_connect.disconnect() - Close the connection
  • net_connect.write_channel() - Low-level write of the channel
  • net_connect.read_channel() - Low-level write of the channel


If you want to learn more about network automation, Python, and Ansible—then join my email-list. I also periodically run a free Python for Network Engineers email course which you can sign-up for here.

router image

Kirk Byers

router image

Netmiko Library

By Kirk Byers
Updated 2019-01-02

Since late 2014, I have been working on an open-source Python library that simplifies SSH management to network devices. The library is based on the Paramiko SSH library and is named Netmiko.

You can find the library at https://github.com/ktbyers/netmiko and the latest released version of the software can be downloaded here.


The purposes of this library are the following:

  • Successfully establish an SSH connection to the device
  • Simplify the execution of show commands and the retrieval of output data
  • Simplify execution of configuration commands including possibly commit actions
  • Do the above across a broad set of networking vendors and platforms


Some additional articles and documentation on Netmiko can be found at:


Various example code can be found here:

Note, the ConnectHandler class is identical to the Netmiko class. You might see ConnectHandler referenced in other Netmiko examples.



Why was Netmiko created?

At the time, I had observed that many individuals encountered similar issues with Python-SSH and network devices. For example, HP ProCurve switches have ANSI escape codes in the output or the Cisco WLC has an extra 'login as:' message. These types of issues can soak up a lot of development and troubleshooting time and, what is worse, people keep solving the same issues over and over again (including sometimes not solving them and giving up).

So Netmiko was created to simplify this lower-level SSH management across a wide set of networking vendors and platforms.



Platform Support:

As of January 2019, Netmiko supports the following platforms with the indicated level of testing.

Regularly tested:

  • Arista EOS
  • Cisco ASA
  • Cisco IOS/IOS-XE
  • Cisco IOS-XR
  • Cisco NX-OS
  • Cisco SG300
  • HP Comware7
  • HP ProCurve
  • Juniper Junos
  • Linux

Limited testing:

  • Alcatel AOS6/AOS8
  • Apresia Systems AEOS
  • Calix B6
  • Cisco AireOS (Wireless LAN Controllers)
  • Dell OS9 (Force10)
  • Dell OS10
  • Dell PowerConnect
  • Extreme ERS (Avaya)
  • Extreme VSP (Avaya)
  • Extreme VDX (Brocade)
  • Extreme MLX/NetIron (Brocade/Foundry)
  • Huawei
  • IP Infusion OcNOS
  • Mellanox
  • NetApp cDOT
  • OneAccess
  • Palo Alto PAN-OS
  • Pluribus
  • Ruckus ICX/FastIron
  • Ubiquiti EdgeSwitch
  • Vyatta VyOS

Experimental:

  • A10
  • Accedian
  • Aruba
  • Ciena SAOS
  • Citrix Netscaler
  • Cisco Telepresence
  • Check Point GAiA
  • Coriant
  • Dell OS6
  • Dell EMC Isilon
  • Eltex
  • Enterasys
  • Extreme EXOS
  • Extreme Wing
  • Extreme SLX (Brocade)
  • F5 TMSH
  • F5 Linux
  • Fortinet
  • MRV Communications OptiSwitch
  • Nokia/Alcatel SR-OS
  • QuantaMesh
  • Rad ETX


Example 1: Simple SSH session to a Cisco router; execute and return the 'show ip int brief' command.

First, I must import the ConnectHandler factory function from Netmiko. This factory function selects the correct Netmiko class based upon the device_type. I then define a network device dictionary consisting of a device_type, ip, username, and password.

In [1]: from netmiko import ConnectHandler                                                                                                         

In [2]: cisco = { 
   ...:   'device_type': 'cisco_ios', 
   ...:   'host': 'cisco.domain.com', 
   ...:   'username': 'admin', 
   ...:   'password': 'cisco123', 
   ...:   }  

At this point, I should be able to connect to the device.

Notice above that I have specified the device_type as 'cisco_ios'. The supported device_types can generally be found here.


Now in order to connect all I need to do is call ConnectHandler and pass in my earlier defined device dictionary:

In [3]: net_connect = ConnectHandler(**cisco) 

Alternatively, I could just call the ConnectHandler function directly and not use a dictionary (as follows):

net_connect2 = ConnectHandler(device_type='cisco_ios', host='cisco.domain.com', username='admin', password='cisco123') 

Now at this point we should have an established SSH connection. I can verify this by executing the find_prompt() method

In [5]: net_connect.find_prompt()
Out[5]: 'cisco3#' 

I can also send commands down the SSH channel and receive the output back. Here, I use the .send_command() method to send the 'show ip int brief' command:

In [6]: output = net_connect.send_command("show ip int brief")

In [7]: print(output)
Interface              IP-Address      OK? Method Status                Protocol
GigabitEthernet0/0/0   10.10.10.22    YES manual up                    up      
GigabitEthernet0/0/1   unassigned      YES NVRAM  administratively down down    
GigabitEthernet0/1/0   unassigned      YES unset  down                  down    
GigabitEthernet0/1/1   unassigned      YES unset  down                  down    
GigabitEthernet0/1/2   unassigned      YES unset  down                  down    
GigabitEthernet0/1/3   unassigned      YES unset  down                  down    
Vlan1                  unassigned      YES unset  up                    down    

Let's also try to make a configuration change to this router. First, let's look at the current logging configuration:

In [8]: output = net_connect.send_command("show run | inc logging")

In [9]: print(output)
 logging synchronous 

Now in order to make configuration changes, I create a list of configuration commands that I want to execute. This could be a single command or multiple commands.

In [10]: config_commands = ['logging buffered 19999']  

I then execute the send_config_set() method. This method will enter configuration mode, execute the commands, and then exit configuration mode (note, there will be some exceptions to this behavior depending on the platform--for example, IOS-XR will not exit configuration mode due to pending changes).

In [11]: output = net_connect.send_config_set(config_commands)

In [12]: print(output)
config term
Enter configuration commands, one per line.  End with CNTL/Z.
cisco3(config)#logging buffered 19999
cisco3(config)#end
cisco3#

I can then verify my change:

In [13]: output = net_connect.send_command("show run | inc logging")

In [14]: print(output)
logging buffered 19999
 logging synchronous 


Example 2: Executing 'show arp' on a set of networking devices consisting of different vendors and platforms.

netmiko show arp image netmiko show arp image

First, I need to define the networking devices (real IP addresses and passwords have been hidden):

In [1]: from netmiko import ConnectHandler 

In [2]: from datetime import datetime

In [3]: cisco3 = {
   ...:     'device_type': 'cisco_ios',
   ...:     'host':   'cisco3.domain.com',
   ...:     'username': 'admin',
   ...:     'password': 'cisco123',
   ...: }
   ...:

In [4]: cisco_asa = {
   ...:     'device_type': 'cisco_asa',
   ...:     'host': '10.10.10.88',
   ...:     'username': 'admin',
   ...:     'password': 'cisco123',
   ...:     'secret': 'cisco123',
   ...: }
   ...:

In [5]: cisco_xrv = {
   ...:     'device_type': 'cisco_xr', 
   ...:     'host': '10.10.10.77', 
   ...:     'username': 'admin', 
   ...:     'password': 'cisco123', 
   ...: }

In [6]: arista8 = { 
   ...:     'device_type': 'arista_eos', 
   ...:     'host':   'arista8.domain.com', 
   ...:     'username': 'admin', 
   ...:     'password': '!cisco123', 
   ...: } 
   ...:

In [7]: hp_procurve = { 
   ...:     'device_type': 'hp_procurve', 
   ...:     'host': '10.10.10.68', 
   ...:     'username': 'admin', 
   ...:     'password': '!cisco123', 
   ...: } 
   ...:

In [8]: juniper_srx = { 
   ...:     'device_type': 'juniper', 
   ...:     'host':   'srx1.domain.com', 
   ...:     'username': 'admin', 
   ...:     'password': '!cisco123', 
   ...: } 
   ...:   

Next, I need to create a Python list that includes all of these devices:

all_devices = [cisco3, cisco_asa, cisco_xrv, arista8, hp_procurve, juniper_srx] 

Now, I will create a for loop that iterates over all of these devices. Each time through the loop: the code will connect to the device, execute 'show arp', and then display the output. I will also keep track of the time that it takes for the code execute.

Note, I have changed the output slightly (so that you can more clearly see what I pasted in versus the output back from the devices).

In [12]: start_time = datetime.now() 
    ...: for a_device in all_devices: 
    ...:     net_connect = ConnectHandler(**a_device) 
    ...:     output = net_connect.send_command("show arp") 
    ...:     print(f"\n\n--------- Device {a_device['device_type']} ---------") 
    ...:     print(output) 
    ...:     print("--------- End ---------") 
    ...:  
    ...: end_time = datetime.now() 
    ...: total_time = end_time - start_time  

Here is the output from the for loop (i.e. all of the "show arp" output):


--------- Device cisco_ios ---------
Protocol  Address          Age (min)  Hardware Addr   Type   Interface
Internet  10.10.10.1            32   0062.ec29.70fe  ARPA   GigabitEthernet0/0/0
Internet  10.10.10.20          156   c89c.1dea.0eb6  ARPA   GigabitEthernet0/0/0
Internet  10.10.10.22            -   a093.5141.b780  ARPA   GigabitEthernet0/0/0
Internet  10.10.10.37          178   0001.00ff.0001  ARPA   GigabitEthernet0/0/0
Internet  10.10.10.38           15   0002.00ff.0001  ARPA   GigabitEthernet0/0/0
--------- End ---------


--------- Device cisco_asa ---------
	outside 10.10.10.1 0062.ec29.70fe 1949
	outside 10.10.10.20 c89c.1dea.0eb6 10226
	outside 10.10.10.37 0001.00ff.0001 11606
	outside 10.10.10.38 0002.00ff.0001 11636

--------- End ---------


--------- Device cisco_xr ---------

Thu Jan  3 00:45:44.240 UTC

-------------------------------------------------------------------------------
0/0/CPU0
-------------------------------------------------------------------------------
Address         Age        Hardware Addr   State      Type  Interface
10.10.10.1     00:32:36   0062.ec29.70fe  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.19    02:50:35   0024.c4e9.48ae  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.20    00:30:26   c89c.1dea.0eb6  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.21    03:09:20   1c6a.7aaf.576c  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.22    02:58:54   a093.5141.b780  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.23    01:37:37   502f.a8b1.6900  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.32    02:56:30   5254.abc7.26aa  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.37    -          0001.00ff.0001  Interface  ARPA  GigabitEthernet0/0/0/0
10.10.10.38    01:55:33   0002.00ff.0001  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.39    00:11:32   6464.9be8.08c8  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.42    00:00:46   ec38.739e.2f08  Dynamic    ARPA  GigabitEthernet0/0/0/0
10.10.10.43    00:22:35   5254.abda.5495  Dynamic    ARPA  GigabitEthernet0/0/0/0
--------- End ---------


--------- Device arista_eos ---------
Address         Age (min)  Hardware Addr   Interface
10.10.10.1             0  0062.ec29.70fe  Vlan1, Ethernet1
10.10.10.20            0  c89c.1dea.0eb6  Vlan1, not learned
10.10.10.43            0  5254.abda.5495  Vlan1, not learned
--------- End ---------


--------- Device hp_procurve ---------

 IP ARP table

  IP Address      MAC Address       Type    Port
  --------------- ----------------- ------- ----
  10.10.19.1     0062ec-2970fd     dynamic 26  
  10.10.19.20    c07bbc-65272e     dynamic 26  
 

--------- End ---------


--------- Device juniper ---------

MAC Address       Address         Name                      Interface           Flags
00:62:ec:29:70:fe 10.10.10.1     10.10.10.1               vlan.0              none
c8:9c:1d:ea:0e:b6 10.10.10.20    10.10.10.20              vlan.0              none
Total entries: 2

--------- End ---------

In [13]: print(total_time) 
0:00:42.062773 

As you can see the code took slightly longer than 42 seconds to execute. This could be significantly improved by creating the SSH sessions concurrently see the code here for some examples using concurrency.



Netmiko commonly-used methods:

  • net_connect.send_command() - Send command down the channel, return output back (pattern based)
  • net_connect.send_command_timing() - Send command down the channel, return output back (timing based)
  • net_connect.send_config_set() - Send configuration commands to remote device
  • net_connect.send_config_from_file() - Send configuration commands loaded from a file
  • net_connect.save_config() - Save the running-config to the startup-config
  • net_connect.enable() - Enter enable mode
  • net_connect.find_prompt() - Return the current router prompt
  • net_connect.commit() - Execute a commit action on Juniper and IOS-XR
  • net_connect.disconnect() - Close the connection
  • net_connect.write_channel() - Low-level write of the channel
  • net_connect.read_channel() - Low-level write of the channel


If you want to learn more about network automation, Python, and Ansible—then join my email-list. I also periodically run a free Python for Network Engineers email course which you can sign-up for here.

router image

Kirk Byers