Skip to content

Network Automation

My journey with Network & Cloud Automation

Menu
  • Beginner
  • DevOps-NetDevOps
  • Network Automation
    • Docker
    • Python Libraries
      • NAPALM
      • Netmiko
      • Jinja2
      • Scrapli
      • Yang
  • Cloud Automation
    • Terraform
  • Python 🐍 Tips and Tricks
Menu
Netmiko TEXTFSM

How to Automate Network Devices using Python Netmiko Part I

Posted on August 3, 2021October 1, 2024 by Gurpreet Kochar

In this post, we are going to cover the very basics of Netmiko. This is a beginner-level introduction on how to automate networking devices using python netmiko in which we will talk about how to install and set up SSH to network devices using python. Also how to write a basic script for interacting with devices programmatically.

Installation

pip install netmiko / pip3 install netmiko
Depending upon if you are using pip or pip3

Interact (SSH / Telnet ) with a network device using Netmiko

CISCO ALWAYS ON DEVNET SANDBOX LAB

Create a dictionary of all devices that we want to interact with. For this post, we will create the dictionary statically but we can also generate the dictionary dynamically from any network inventory source as well like excel sheets.

csr1000v1 = {
    'device_type': 'cisco_xe',
    'host':   'sandbox-iosxe-latest-1.cisco.com',
    'username': 'developer',
    'password': 'C1sco12345',
    'port' : 22,                # optional, defaults to 22
    'secret': 'C1sco12345',     # optional, defaults to ''
}
csr1000v2 = {
    'device_type': 'cisco_xe',
    'host':   'sandbox-iosxe-recomm-1.cisco.com',
    'username': 'developer',
    'password': 'C1sco12345',
    'port' : 22,
    'secret': 'C1sco12345',
}
iosxrv9000 = {
    'device_type': 'cisco_xr',
    'host':   'sandbox-iosxr-1.cisco.com',
    'username': 'admin',
    'password': 'C1sco12345',
    'port' : 22,
    'secret': 'C1sco12345',
}
nxosv9000 = {
    'device_type': 'cisco_nxos',
    'host':   'sandbox-nxos-1.cisco.com',
    'username': 'admin',
    'password': 'Admin_1234!',
    'port' : 22,
    'secret': 'Admin_1234!',
}

Let’s connect to csr1000v1 device and extract the output of show ip int br from that device using python

from netmiko import ConnectHandler
net_connect = ConnectHandler(**csr1000v1)
output = net_connect.send_command('show ip int brief')
print(output)
╰─ python3 script.py                                                                                                                                                                       ─╯
Interface              IP-Address      OK? Method Status                Protocol
GigabitEthernet1       10.10.20.48     YES NVRAM  up                    up      
GigabitEthernet2       unassigned      YES NVRAM  administratively down down    
GigabitEthernet3       unassigned      YES NVRAM  administratively down down    
Loopback100            111.111.111.111 YES manual up                    up      

Explanation:-

  1. Import ConnectHandler from netmiko module. ConnectHandler is responsible for establishing the SSH read write connection with the device in the background.
  2. net_connect = ConnectHandler(**csr1000v1)
    • Pass the dictionary of device details that we want to connect to and assign that connection to a variable called net_connect. You could call it anything you want to.
    • To see available methods for net_connect, type print(dir(net_connect)) and this will show you all the methods that you can call against that connection. You can read more about all these methods in the github API documentation of Netmiko. The intention here is to cover the absolute basics to get the ball rolling.
  3. output = net_connect.send_command(‘show ip int brief’)
    • Call send_command method on net_connect connection handler and pass in the command you want to execute on the device. The result of the command execution will be saved to a variable called output.

If we want to extract outputs from all devices, we can put all the dictionary of devices into a list like below

For each device in the all_devices list

all_devices = [csr1000v1, csr1000v2, iosxrv9000, nxosv9000]
for device in all_devices:
    net_connect = ConnectHandler(**device)
    output = net_connect.send_command('show ip int brief | ex unass')
    print(device['host'])
    print("=" * len(device['host']))
    print(output)
╰─ python3 script.py                                                                                                                                                                       ─╯
sandbox-iosxe-latest-1.cisco.com
================================
Interface              IP-Address      OK? Method Status                Protocol
GigabitEthernet1       10.10.20.48     YES NVRAM  up                    up      
GigabitEthernet2       10.255.255.2    YES other  up                    up      
Loopback100            111.111.111.111 YES manual up                    up      
sandbox-iosxe-recomm-1.cisco.com
================================
Interface              IP-Address      OK? Method Status                Protocol
GigabitEthernet1       10.10.20.48     YES NVRAM  up                    up      
GigabitEthernet3       172.31.1.1      YES manual down                  down    
Loopback2              2.2.2.2         YES manual up                    up      
Loopback10             10.111.10.1     YES manual up                    up      
Loopback100            10.3.3.3        YES other  up                    up      
VirtualPortGroup0      192.168.0.254   YES manual up                    up      
sandbox-iosxr-1.cisco.com
=========================
Fri Jul 30 14:21:41.134 UTC
Interface                      IP-Address      Status          Protocol Vrf-Name
Loopback100                    1.1.1.100       Up              Up       default 
Loopback200                    1.1.1.200       Up              Up       default 
MgmtEth0/RP0/CPU0/0            10.10.20.175    Up              Up       default 
sandbox-nxos-1.cisco.com
========================
IP Interface Status for VRF "default"(1)
Interface            IP Address      Interface Status
Vlan3                33.33.33.33     protocol-down/link-down/admin-up   
Vlan100              172.16.100.1    protocol-up/link-up/admin-up       
Vlan101              172.16.101.1    protocol-down/link-down/admin-down 
Vlan102              172.16.102.1    protocol-down/link-down/admin-down 
Vlan103              172.16.103.1    protocol-down/link-down/admin-down 
Vlan104              172.16.104.1    protocol-down/link-down/admin-down 
Vlan105              172.16.105.1    protocol-down/link-down/admin-down 
Lo1                  172.16.0.1      protocol-up/link-up/admin-up       
Lo21                 3.3.3.3         protocol-up/link-up/admin-up       
Lo23                 27.27.27.27     protocol-up/link-up/admin-up       
Lo25                 8.8.8.8         protocol-up/link-up/admin-up       
Lo31                 2.2.2.2         protocol-up/link-up/admin-up       
Lo101                192.168.232.0   protocol-up/link-up/admin-up       
Lo102                192.168.2.1     protocol-up/link-up/admin-up       
Lo127                192.168.127.1   protocol-up/link-up/admin-up       
Lo128                192.168.128.1   protocol-up/link-up/admin-up       
Lo200                5.5.5.5         protocol-up/link-up/admin-up       
Lo201                201.201.201.201 protocol-up/link-up/admin-up       
Lo500                9.9.9.9         protocol-up/link-up/admin-up       
Lo998                7.7.7.7         protocol-up/link-up/admin-up       
Lo999                4.4.4.4         protocol-up/link-up/admin-up       
Eth1/5               172.16.1.1      protocol-up/link-up/admin-up       

If we want to extract multiple commands and multiple devices, we can modify the script a little bit to do so.

For each device in the all_devices list, we will execute each command in the commands list. We are using nested for loops here to achieve the task.

all_devices = [csr1000v1, csr1000v2, iosxrv9000, nxosv9000]
commands = ['show version', 'show ip int br | ex unass', 'show cdp nei']
for device in all_devices:
    net_connect = ConnectHandler(**device)
    print(device['host'])
    print("=" * len(device['host']))
    for command in commands:
        output = net_connect.send_command(command)
        print(output)

send_command as the name suggests sends the command to the device and outputs the response to a variable. send_command method is looking for the device prompt, it keeps on reading the output until the device prompt is found again which is usually when the command execution is completed. Instead of using send_command, there may be scenarios where you need to execute

  • send_command_timing
    • You can control the delay in this command in scenarios where you want to copy paste files to and from bootflash and the default wait interval of netmiko is too less specially when you want to work over WAN. So instead of stopping the execution after finding the device prompt, the script works on predefined delay intervals.
  • send_command_expect
    • Interactive CLI commands where you need to hit return / enter. So instead of stopping the command execution after default device prompt is seen or a specific time. The command execution is controlled by the pattern you specify and expect to see the entire order of operations.
# cisco1#delete flash:/testb.txt
# Delete filename [testb.txt]? 
# Delete flash:/testb.txt? [confirm]y

# Use 'send_command' and the 'expect_string' argument (note, expect_string uses RegEx patterns).
# Netmiko will move-on to the next command when the 'expect_string' is detected.

Here is a showcase of all arguments that you can pass to the netmiko send_command( ) method

def send_command(
    self,
    command_string: str,
    expect_string: Optional[str] = None,
    delay_factor: float = 1.0,
    max_loops: int = 500,
    auto_find_prompt: bool = True,
    strip_prompt: bool = True,
    strip_command: bool = True,
    normalize: bool = True,
    use_textfsm: bool = False,
    textfsm_template: Optional[str] = None,
    use_ttp: bool = False,
    ttp_template: Optional[str] = None,
    use_genie: bool = False,
    cmd_verify: bool = True,
) -> str:
    """Execute command_string on the SSH channel using a pattern-based mechanism. Generally
    used for show commands. By default this method will keep waiting to receive data until the
    network device prompt is detected. The current network device prompt will be determined
    automatically.

    :param command_string: The command to be executed on the remote device.
    :type command_string: str

    :param expect_string: Regular expression pattern to use for determining end of output.
        If left blank will default to being based on router prompt.
    :type expect_string: str

    :param delay_factor: Multiplying factor used to adjust delays (default: 1).
    :type delay_factor: int

    :param max_loops: Controls wait time in conjunction with delay_factor. Will default to be
        based upon self.timeout.
    :type max_loops: int

    :param strip_prompt: Remove the trailing router prompt from the output (default: True).
    :type strip_prompt: bool

    :param strip_command: Remove the echo of the command from the output (default: True).
    :type strip_command: bool

    :param normalize: Ensure the proper enter is sent at end of command (default: True).
    :type normalize: bool

    :param use_textfsm: Process command output through TextFSM template (default: False).
    :type normalize: bool

    :param textfsm_template: Name of template to parse output with; can be fully qualified
        path, relative path, or name of file in current directory. (default: None).

    :param use_ttp: Process command output through TTP template (default: False).
    :type use_ttp: bool

    :param ttp_template: Name of template to parse output with; can be fully qualified
        path, relative path, or name of file in current directory. (default: None).
    :type ttp_template: str

    :param use_genie: Process command output through PyATS/Genie parser (default: False).
    :type normalize: bool

    :param cmd_verify: Verify command echo before proceeding (default: True).
    :type cmd_verify: bool
    """

In the next post on how to automate networking devices using python netmiko series, we see how to enter into enable mode and configure mode to push configuration changes to devices.

How to Automate Network Devices using Python Netmiko Part 2

Know someone who may benefit? Share this:

  • Tweet
  • Click to share on Telegram (Opens in new window) Telegram
  • Click to share on WhatsApp (Opens in new window) WhatsApp
  • Click to email a link to a friend (Opens in new window) Email
  • More
  • Click to print (Opens in new window) Print
  • Click to share on Reddit (Opens in new window) Reddit
  • Share on Tumblr
  • Pocket

Like this:

Like Loading...

Related

3 thoughts on “How to Automate Network Devices using Python Netmiko Part I”

  1. Pingback: How to read write csv with python for Network Automation Part 2
  2. Pingback: How to Automate Network Devices using Python Netmiko Part 2
  3. Pingback: How to read write csv with python for Network Automation Part 1

Leave a ReplyCancel reply

All Blog Posts
My Resume

Upcoming Posts

Sorry - nothing planned yet!

Recent Posts

  • How to backup configuration to TFTP Server using Ansible – Part II
  • How to backup network devices using Ansible – Part I
  • Netmiko SSH Proxy/JumpServer
  • A short note on SASE
  • Understanding Ansible

Recent Comments

  1. Jack on Multithreading with Python for Network Engineers
  2. LifeCanvas on [Theory] Multithreading vs Multiprocessing vs AsyncIO
  3. Jasper Horng on Netmiko SSH Proxy/JumpServer
  4. asdfasdf on Python API Using FASTAPI – UPDATE – PUT – PATCH – Part V
  5. Gurpreet Kochar on Python Scrapli AsyncIO Usage

Archives

  • September 2022
  • February 2022
  • January 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • August 2021
  • July 2021
Topic Request / Suggestion
Loading
© 2025 Network Automation | Powered by Minimalist Blog WordPress Theme
%d