您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Python

网络工程师的Python之路——Netmiko终极指南

时间:2022-07-24 12:44:26  来源:  作者:弈心

作为Paramiko最为成功的衍生模块.NETmiko成为了很多学习Python/ target=_blank class=infotextkey>Python网络运维自动化技术的网工日常工作中最常用的模块之一。相较于Paramiko,Netmiko将很多细节优化和简化,比如不需要导入time模块做休眠,输入每条命令不需要在后面加换行符n,不需要执行config term,exit,end等命令,提取、打印回显内容更方便,可以配合Jinja2模块调用配置模板,以及配合TextFSM、pyATS、Genie等模块将回显内容以有序的JSON格式输出,方便我们过滤和提取出所需的数据等等,并且在Netmiko的基础上也诞生出了napalm, pyntc,netdev等扩展模块甚至Nornir这样成功的网络运维自动化框架

在我的《网络工程师的Python之路》一书里,我刻意减少了Netmiko的相关内容,重点讲解了Paramiko,因为道理很简单:Netmiko将太多功能简化的做法其实并不利于初学者学习。Netmiko和Paramiko两者就像自动挡汽车和手动挡汽车的区别。会驾车的都知道,一开始就学手动挡车的人100%会开自动挡的车,而从一开始就学自动挡车的人,除非额外加课,否则是100%不会开手动挡的车的。Paramiko虽然复杂、繁琐一些,但是就像手动挡车一样,整体“操控感”更强,运维脚本中的所有细节和各种参数都在我们自己的掌控之中,更利于我们从整体来把握进而写出自己需要的脚本,并且无需像Netmiko那样担心对各种设备各种OS的支持的问题。

随着越来越多的网工读者们逐渐上手和适应Paramiko,为了弥补我书里“重Paramiko,轻Netmiko”的遗憾,特此补上一篇《Netmiko终极指南》,本文和之前我连载的Nornir3.0.0的教程类似,将Netmiko的各个知识点直接以实验形式演示、讲解,总计8个实验,由简到难涵盖Netmiko的各个知识点。


实验平台:

本文承接《网络工程师的Python之路》过往的拓扑,还是老规矩:一台centos 8主机(192.168.2.1)上跑Netmiko,下面连上5台试验用的虚拟三层思科交换机IP从192.168.2.11到192.168.2.15。

网络工程师的Python之路——Netmiko终极指南

 

实验准备:

通过pip安装netmiko后在Python解释器里用import验证,截至2021年4月27号,目前最新的Netmiko版本为3.4.0。

网络工程师的Python之路——Netmiko终极指南

 

实验1: 通过Netmiko登录一台交换机

要通过netmiko来登录一台设备需要用到它的核心对象ConnectHandler。ConnetHandler()包含几个必要的参数和可选参数,必要参数包括device_type,ip(也可以为host),username和password,可选参数包括port, secret,use_keys,key_file,conn_timeout等等,可选参数的作用和用法在后面的实验中会陆续讲到。

首先创建第一个脚本netmiko1.py,然后写入下面代码:

from netmiko import ConnectHandler
sw1 = {
	'device_type': 'cisco_IOS',
	'ip': '192.168.2.11',
	'username': 'python',
	'password': '123'
}

with ConnectHandler(**sw1) as connect:
	print ("已经成功登陆交换机" + sw1['ip'])
网络工程师的Python之路——Netmiko终极指南

 

代码分段讲解:

  • 首先通过 import 语句从Netmiko导入它的核心对象ConnectHandler()。
from netmiko import ConnectHandler
  • 创建一个名为SW1的字典,该字典包含'device_type'、'ip'、'username'和'password'4个必选的键。SW1字典里的四组键值对等会会以关键字参数的形式(**kwargs)在ConnectHandler()里打开,被用作前面讲到的ConnectHandler()的4个必选参数(device_type,ip,username和password)。其中ip,username,password3个键的意思很好理解(在实际工作中,username和password建议通过input()和getpass模块来输入,这里因为只是实验演示使用,我就偷懒直接把username和password明文写进脚本里了),这里主要说下'device_type'。截至2021年4月,Netmiko 支持 Arista、Cisco、HP、Juniper、Alcatel、Huawei、Extreme和Palo Alto等绝大多数主流厂商的设备。除此之外,Netmiko同样支持拥有多种不同 OS 类型的厂商的设备,比如针对思科的设备,Netmiko能同时支持 Cisco ASA、Cisco IOS、Cisco IOS-XE、Cisco IOS-XR、Cisco NX-OS 和 Cisco SG300共 6 种不同 OS 类型的设备。由于不同厂商的设备登录 SSH 后命令行界面和特性不尽相同,因此我们必须通过'device_type'来指定需要登录的设备的类型。因为实验里我们用到的是思科 IOS设备,因此'deivce_type'的键值为'cisco_ios'。
sw1 = {
	'device_type': 'cisco_ios',
	'ip': '192.168.2.11',
	'username': 'python',
	'password': '123'
}
  • 最后调用ConnetHandler(),以关键字参数的形式将sw1这个字典里的键值对提取出来,作为自己的ConnetHandler()本身的参数使用,最后打印出“已经成功登录交换机xx.xx.xx.xx"来提示我们SSH登录成功,这里注意我用了context manager(上下文管理器,也就是with语句)来调用ConnetHandler,它的好处是可以在脚本运行完毕后自动帮助我们关闭SSH会话(如果你不想使用context manager,而是写成connect = ConnectHandler(**sw1)当然也是可以的,不影响Netmiko登录设备):
with ConnectHandler(**sw1) as connect:
	print ("已经成功登陆交换机" + sw1['ip'])
  • 这里额外提一点:如果脚本只需要单独登录一台设备的话,这里也可以不创建sw1这个字典,而是直接在ConnetHandler()里面放入'device_type'、'ip'、'username'和'password'四个参数,如下:
from netmiko import ConnectHandler
with ConnectHandler(device_type='cisco_ios', ip='192.168.2.11', username='python', password='123') as connect:
        print ("已经成功登陆交换机192.168.2.11")

运行脚本看效果:

运行脚本前先在S1上开启debug ip ssh,以便我们验证脚本是否真正SSH登录了交换机。

网络工程师的Python之路——Netmiko终极指南

 

运行脚本:

网络工程师的Python之路——Netmiko终极指南

 

然后回到S1上,如果看到如下debug日志,则说明netmiko登录交换机成功:

网络工程师的Python之路——Netmiko终极指南

 


实验2:通过Netmiko向设备做配置

Netmiko主要有四种函数向设备做配置:send_command(),send_config_set()以及send_config_from_file(),除此之外还有一个不太常用的send_command_timing(),它们的用法和区别如下:

send_command():只支持向设备发送一条命令,通常是show/display之类的查询、排错命令或者wr mem这样保存配置的命令。发出命令后,默认情况下这个函数会一直等待,直到接收到设备的完整回显内容为止(以收到设备提示符为准,比如说要一直等到读取到“S1#"为止),如果想要指定netmiko从回显内容中读到我们需要的内容,则需要用到expect_string参数(expect_string默认值为None),如果send_command()从回显内容中读到了expect_string参数指定的内容,则send_command()依然返回完整的回显内容,如果没读到expect_string参数指定的内容,则netmiko会返回一个OSError: Search pattern never detected in send_command: xxxxx的异常,关于expect_string参数的用法会在稍后的实验里演示。

send_config_set(): 向设备发送一条或多条配置命令,注意是配置命令,不是show/display之类的查询命令,因为send_config_set()本身会自动替我们加上一个config terminal命令进入配置模式(以及在命令末尾自动替我们加上一个end命令),在config terminal下除非在show命令前面加上一个do,比如do show ip int brief,否则show命令无效(以上以思科IOS设备为例)。send_config_set()一般配合列表使用。

send_config_from_file(): 在配置命令数量较多的时候,将所有配置命令写入列表显然是比较笨拙的,因为会造成代码过长,不方便阅读,并且在部分厂商的设备上(比如华为)还会出现超时报错的情况。我们可以先将所有的配置命令写入一个配置文件中,然后使用send_config_from_file()去读取该文件的内容帮助我们完成配置。和send_config_set()一样,send_config_from_file()也会自动帮我们添加config terminal和end两个命令,所以在我们的配置文件里无需加入这两个命令。

send_command_timing(): 和send_command()一样,只支持向设备发送一条show/display命令。区别是在用send_command()输入一条show命令后,send_command()会一直等待,直到接收到设备的完整回显内容为止(以收到设备提示符为准)。send_command_timing()则会自己去“猜”什么时候停止运行,它的原理是如果没有从设备收到更多新的回显内容后,它会继续等待2秒钟,然后才停止运行,send_command_timing()里有一个叫做delay_factor的参数,默认为1,如果将它修改为2,则send_command_timing()会等待4秒钟,修改为3,则等待6秒,修改为4,等待8秒。。以此类推。有时候在输入show tech-support或者show log(logging buffer特别大,日志特别长的那种)这种回显内容巨多的命令时,即使输入了term len 0来取消分屏显示,设备在返回回显内容时依然会有停顿,有时停顿时间会大于2秒钟,这样就会导致截屏不完整,必须手动去调整delay_factor这个参数。

接下来做实验,首先创建一个config.txt文件,然后写入下列配置命令,这里我们将gi0/0端口的description改为Netmiko2.py

int gi0/0
description Netmiko2.py
网络工程师的Python之路——Netmiko终极指南

 

然后创建第二个实验脚本netmiko.py2(确保实验脚本和config.txt配置命令位于同一个文件夹下),在脚本中放入下列代码:

from netmiko import ConnectHandler
sw1 = {
        'device_type': 'cisco_ios',
        'ip': '192.168.2.11',
        'username': 'python',
        'password': '123'
}

commands = ['interface gi0/1', 'description Nornir2.py']
with ConnectHandler(**sw1) as connect:
        print ("已经成功登陆交换机" + sw1['ip'])
        output = connect.send_command('show interface description')
        print(output)
        output = connect.send_config_set(commands)
        print(output)
        output = connect.send_config_from_file('config.txt')
        print(output)
        output = connect.send_command('show interface description')
        print(output)
        output = connect.send_command('wr mem')
        print(output)
网络工程师的Python之路——Netmiko终极指南

 

代码分段讲解:

  • 首先通过 import 语句从Netmiko导入它的核心对象ConnectHandler(),创建字典sw1用作ConnectHandler()登陆交换机的参数:
from netmiko import ConnectHandler
sw1 = {
        'device_type': 'cisco_ios',
        'ip': '192.168.2.11',
        'username': 'python',
        'password': '123'
}
  • 然后创建一个列表commands,放入要对gi0/1端口修改description的配置,该commands列表等会儿会被send_config_set()函数调用:
commands = ['interface gi0/1', 'description Nornir2.py']
  • 通过ConnectHandler()连入交换机S1后,首先使用send_command('show interface description')查询配置前Gi0/0和Gi0/1两个端口当前的description,然后通过send_config_set(commands)调用commands这个列表对gi0/1做配置,然后再使用send_config_from_file('config.txt')读取之前我们创建的配置文件里的命令对gi0/0做配置,最后再用send_command('show interface description')查询配置完毕后两个端口的description,并send_command('wr mem')保存配置:
with ConnectHandler(**sw1) as connect:
        print ("已经成功登陆交换机" + sw1['ip'])
        output = connect.send_command('show interface description')
        print(output)
        output = connect.send_config_set(commands)
        print(output)
        output = connect.send_config_from_file('config.txt')
        print(output)
        output = connect.send_command('show interface description')
        print(output)
        output = connect.send_command('wr mem')
        print(output)

运行脚本看效果:

网络工程师的Python之路——Netmiko终极指南

 


实验3:用Netmiko配合Textfsm或者Genie将回显内容以JSON格式输出,以pprint模块打印出来

在我的书中曾重点介绍过什么是Textfsm以及它的用法。除了Textfsm之外,思科也出过类似的工具pyATS和Genie来帮助我们将网络设备无序的回显内容以有序的JSON格式输出(不过只限于思科设备)。在Netmiko的send_command()和send_command_timing()中已经内置了可以直接调用Textfsm和Genie的参数,非常方便。实验3就来分别介绍一下它们的用法:

首先通过pip install来下载TextFSM,pyATS和Genie,这里要注意的是pyATS和Genie只支持linux不支持windows(Windows下运行pip install pyats genie会报错),如果你是Windows用户的话需要使用WLS2或者通过虚拟机运行Linux再来安装pyATS和Genie。另外并且强烈建议先通过pip install --upgrade pip将pip升级到最新版本,否则下载的pyATS和Genie会碰到各种奇怪的问题。

pip install --upgrade pip
pip install textfsm
pip install pyats
pip install genie

我们以show interfaces命令为例,首先创建一个test.py来看下不使用textfsm或genie,输入该命令后的回显内容:

test.py代码如下:

from netmiko import ConnectHandler
import pprint

connection_info = {
        'device_type': 'cisco_ios',
        'host': '192.168.2.11',
        'username': 'python',
        'password': '123'
}

with ConnectHandler(**connection_info) as conn:
    out = conn.send_command("show interfaces")
    print(out)

运行脚本后的效果:

网络工程师的Python之路——Netmiko终极指南

 

接下来创建脚本netmiko3_1.py,写入下面代码:

from netmiko import ConnectHandler

connection_info = {
        'device_type': 'cisco_ios',
        'host': '192.168.2.11',
        'username': 'python',
        'password': '123'
}

with ConnectHandler(**connection_info) as conn:
    out = conn.send_command("show interfaces", use_textfsm=True)
    print(out)

可以看到和Nornir一样,要在Netmiko里调用textfsm很简单,只需要在send_command()或者send_command_timing()里直接添加一个参数use_textfsm=True即可(默认为False)。接下来运行脚本看效果:

网络工程师的Python之路——Netmiko终极指南

 

这里可以看到虽然textfsm输出的内容为JSON格式,但是依然不具备可读性。为了将内容更美观地打印出来,这里我们可以用到Python另外一个很强大的内置库:pprint,pprint全称是pretty printer,它的功能是将各种数据结构更美观地输出。这里我们将netmiko3_1.py的代码稍作修改,在第二行加上from pprint import pprint,在最后一行将print(out)改为pprint(out)即可,如下:

from netmiko import ConnectHandler
from pprint import pprint

connection_info = {
        'device_type': 'cisco_ios',
        'host': '192.168.2.11',
        'username': 'python',
        'password': '123'
}

with ConnectHandler(**connection_info) as conn:
    out = conn.send_command("show interfaces", use_textfsm=True)
    pprint(out)

运行代码看效果,输出内容是不是更美观,可读性更强了?

网络工程师的Python之路——Netmiko终极指南

 

和textfsm一样,在Netmiko中使用genie也很简单,只需要在send_command()或者send_command_timing()里直接添加一个参数use_genie=True即可(默认为False),当然前提是你之前有通过pip安装了pyATS和Genie(虽然参数只是use_genie,但是pyATS也必须下载安装,缺一不可),接下来我们再创建netmiko3_2.py,看下用genie配合pprint将数据内容输出后是什么效果,代码如下:

from netmiko import ConnectHandler
from pprint import pprint

connection_info = {
        'device_type': 'cisco_ios',
        'host': '192.168.2.11',
        'username': 'python',
        'password': '123'
}

with ConnectHandler(**connection_info) as conn:
    out = conn.send_command("show interfaces", use_genie=True)
    pprint(out)

运行代码看效果,可以看到Netmiko使用genie配合pprint后输出的内容比Textfsm+pprint更美观,层次更分明:

网络工程师的Python之路——Netmiko终极指南

 

那么我们可以参照paramiko的方法,创建一个ip_list.txt文件,将所有设备的管理IP地址都写进去,如下,这里我将SW1-SW5总共5个交换机的IP地址都写入了ip_list.txt文件里:

from netmiko import ConnectHandler
import pprint

connection_info = {
        'device_type': 'cisco_ios',
        'host': '192.168.2.11',
        'username': 'python',
        'password': '123'
}

with ConnectHandler(**connection_info) as conn:
    out = conn.send_command("show interfaces", use_genie=True)
    for name, detAIls in out.items():
        print(f"{name}")
        print(f"- Status: {details.get('enabled', None)}")
        print(f"- Physical address: {details.get('phys_address', None)}")
        print(f"- Duplex mode: {details.get('duplex_mode', None)}")
    for counter, count in details.get('counters', {}).items():
            if isinstance(count, int):
                if count > 0:
                    print(f"- {counter}: {count}")
            elif isinstance(count, dict):
                for sub_counter, sub_count in count.items():
                    if sub_count > 0:
                        print(f"- {counter}::{sub_counter}: {sub_count}")

脚本运行后的效果如下:

网络工程师的Python之路——Netmiko终极指南

 


实验4:通过Netmiko连接多台交换机

前面三个实验我们都是通过Netmiko登录一台设备,实验4里我们来看下怎么通过Netmiko登录多台设备,根据情况不同主要有两种方法,分两个脚本讲解。

第一种情况:生产网络里所有设备的username, password, port这些参数都一样

那么我们可以参照paramiko的方法,创建一个ip_list.txt文件,将所有设备的管理IP地址都写进去,如下,这里我将SW1-SW5总共5个交换机的IP地址都写入了ip_list.txt文件里:

网络工程师的Python之路——Netmiko终极指南

 

然后创建脚本netmiko4_1.py,写入下列代码:

from netmiko import ConnectHandler

with open('ip_list.txt') as f:
    for ips in f.readlines():
        ip = ips.strip()
        connection_info = {
                'device_type': 'cisco_ios',
                'ip': ip,
                'username': 'python',
                'password': '123',
        }
        with ConnectHandler(**connection_info) as conn:
            print (f'已经成功登陆交换机{ip}')
            output = conn.send_command('show run | i hostname')
            print(output)
网络工程师的Python之路——Netmiko终极指南

 

代码分段讲解:

  • 这里我们用context manager (with语句)打开保存5台交换机管理IP的ip_list.txt文件,然后用for循环配合readlines()遍历里面的每一个ip,因为readlines()返回的列表里的每个元素后面都会接一个换行符n,所以我们用strip()函数将其拿掉然后赋值给变量ip,这个变量ip则作为字典connection_info里'ip'这个键的值放入字典,这里因为我所有的交换机用的SSH端口号都为默认的22,所以没有必要在字典里明文给出来。
from netmiko import ConnectHandler

with open('ip_list.txt') as f:
    for ips in f.readlines():
        ip = ips.strip()
        connection_info = {
                'device_type': 'cisco_ios',
                'ip': ip,
                'username': 'python',
                'password': '123',
        }
  • 然后通过ConnetHandler(**connection_info)依次登陆每台交换机,这里除了打印“已经成功登陆交换机xxx.xxx.xxx.xxx“之外我还额外向每台交换机发送了一个show run |ihostname并将回显内容(即交换机各自的hostname)打印出来,目的是验证我们确实通过Netmiko登录了每台交换机。
        with ConnectHandler(**connection_info) as conn:
            print (f'已经成功登陆交换机{ip}')
            output = conn.send_command('show run | i hostname')
            print(output)

运行脚本看效果:

网络工程师的Python之路——Netmiko终极指南

 

第二种情况:生产网络里设备的username, password, port这些参数不尽相同

这种情况下就不能再用ip_list.txt的方法来做了,必须给每一个参数不同的交换机创建一个字典,因为每个字典一般都要占据5,6排代码的空间,设备一多的时候脚本代码量会非常恐怖。我们可以将这些字典写入一个额外的文件类型为json的文件,将其取名为switches.json,在Python脚本里可以导入Python内置的json模块,利用json.load()这个函数来加载switches.json文件里的内容,因为json.load()会返回一个列表类型的JSON数据,我们可以使用for循环来遍历该列表里的JSON数据来达到依次登录多台设备的目的。具体方法如下:

首先创建switches.json文件,将包含交换机S1和S2的数据以字典形式写入:

[
  {
    "name": "SW1",
    "connection": {
       "device_type": "cisco_ios",
          "host": "192.168.2.11",
          "username": "python",
          "password": "123"
    }
  },
  {
    "name": "SW2",
    "connection": {
       "device_type": "cisco_ios",
          "host": "192.168.2.12",
          "username": "python",
          "password": "123"
    }
  }
]
网络工程师的Python之路——Netmiko终极指南

 

然后创建实验4的第二个脚本netmiko4_2.py

import json
from netmiko import ConnectHandler

with open("switches.json") as f:
    devices = json.load(f)
for device in devices:
    with ConnectHandler(**device['connection']) as conn:
        hostname = device['name']
        print (f'已经成功登陆交换机{hostname}')
        output = conn.send_command('show run | i hostname')
        print(output)
网络工程师的Python之路——Netmiko终极指南

 

代码分段讲解:

  • 导入Python内置的json模块,然后调用它的load()函数将我们之前创建的switches.json里面的SW1和SW2的登录信息导出并赋值给变量devices,注意json.load()返回值的数据类型为为列表。
import json
from netmiko import ConnectHandler

with open("switches.json") as f:
    devices = json.load(f)
  • 随后用for循环遍历devices,并对每台交换机执行命令show run | i hostname打印出它们的hostname:
for device in devices:
    with ConnectHandler(**device['connection']) as conn:
        hostname = device['name']
        print (f'已经成功登陆交换机{hostname}')
        output = conn.send_command('show run | i hostname')
        print(output)

运行脚本看效果:

网络工程师的Python之路——Netmiko终极指南

 



实验5:Netmiko配合Jinja2配置模板给设备做配置

Jinja2是Python的内置模块,无需通过pip下载安装。Jinja2在我的专栏里已经多次提到过,这里就不介绍它的基本语法和用法了,这里直接给出它在Netmiko中的用法。

这里我们将使用netmiko配合jinja2给SW1的loopback 1端口配置一个inbound方向的ACL 1,该ACL 1会分别允许和拒绝一些IP地址。首先创建一个文件夹,取名templates,进入该文件夹后创建我们的jinja2模板文件,将其取名为acl.conf.tpl,然后放入下面的jinja2语句:

interface {{ interface }}
ip access-group 1 in
{% for host in disallow_ip %}
access-list 1 deny host {{ host }}
{% endfor %}
{% for host in allow_ip %}
access-list 1 permit host {{ host }}
{% endfor %}
网络工程师的Python之路——Netmiko终极指南

 


网络工程师的Python之路——Netmiko终极指南

 

from netmiko import ConnectHandler
from jinja2 import Environment, FileSystemLoader

sw1 = {
        'device_type': 'cisco_ios',
        'ip': '192.168.2.11',
        'username': 'python',
        'password': '123'
}

loader = FileSystemLoader('templates')
environment = Environment(loader=loader)
tpl = environment.get_template('acl.conf.tpl')

allow_ip = ['10.1.1.1', '10.1.1.2']
disallow_ip = ['10.1.1.3', '10.1.1.4']
out = tpl.render(allow_ip=allow_ip, disallow_ip=disallow_ip, interface='loopback 1')

with open("configuration.conf", "w") as f:
       f.write(out)

with ConnectHandler(**sw1) as conn:
        print ("已经成功登陆交换机" + sw1['ip'])
        output = conn.send_config_from_file("configuration.conf")
        print (output)
网络工程师的Python之路——Netmiko终极指南

 


  • 这里我们导入Jinja2的Enviroment和FileSystemLoader两个子类,用来读取templates文件夹下的Jinja2模板文件acl.conf.tpl,然后赋值给tpl这个函数:
from netmiko import ConnectHandler
from jinja2 import Environment, FileSystemLoader

sw1 = {
        'device_type': 'cisco_ios',
        'ip': '192.168.2.11',
        'username': 'python',
        'password': '123'
}

loader = FileSystemLoader('templates')
environment = Environment(loader=loader)
tpl = environment.get_template('acl.conf.tpl')
  • 然后我们将允许和拒绝的IP写入两个列表,分别取名allow_ip和disallow_ip,然后通过render()这个函数对模板文件做渲染(注意这里render()里的三个参数allow_ip,disallow_ip和interface就是模板文件里的变量)将渲染后的模板文件赋值给变量out:
allow_ip = ['10.1.1.1', '10.1.1.2']
disallow_ip = ['10.1.1.3', '10.1.1.4']
out = tpl.render(allow_ip=allow_ip, disallow_ip=disallow_ip, interface='loopback 1')
  • 有了渲染后的模板文件后,我们需要将它写入一个扩展名为conf的文件,这里我们创建一个configuration.conf文件,将模板文件内容全部写入进去:
with open("configuration.conf", "w") as f:
       f.write(out)
  • 最后通过ConnectHandler()登录SW1,然后使用send_config_from_file()读取configuration.conf文件里的内容对SW1做配置:
with ConnectHandler(**sw1) as conn:
        out = conn.send_config_from_file("configuration.conf")

运行脚本看效果:

运行脚本前首先确认SW1里没有ACL 1,并且loopback 1下也没有放入任何ACL:

网络工程师的Python之路——Netmiko终极指南

 


网络工程师的Python之路——Netmiko终极指南

 

脚本运行完毕后再次返回SW1验证:

网络工程师的Python之路——Netmiko终极指南

 


实验6:在Netmiko中使用enable密码进入设备特权模式

在我之前的所有专栏文章以及书里我都是将SSH用户名的特权级别设为15,跳过了输入enable密码这一步。鉴于部分读者的生产网络中仍然要求使用enable密码来进入设备的特权模式,这里就来看下如何在Netmiko中使用enable密码。

开始实验之前,首先将SW1上的用户python的特权级别从之前的15改为1:

网络工程师的Python之路——Netmiko终极指南

 

然后使用用户名python手动SSH登录SW1,可以发现输入SSH密码后,来到了用户模式(>提示符),必须再次输入enable密码才能进入特权模式:

网络工程师的Python之路——Netmiko终极指南

 

验证完毕后,开始创建实验6的脚本netmiko6.py,写入下列代码:

from netmiko import ConnectHandler
sw1 = {
        'device_type': 'cisco_ios',
        'ip': '192.168.2.11',
        'username': 'python',
        'password': '123',
        'secret': '123'
}

with ConnectHandler(**sw1) as connect:
    connect.enable()
    print ("已经成功登陆交换机" + sw1['ip'])
    output = connect.send_command('show run')
    print (output)
网络工程师的Python之路——Netmiko终极指南

 

代码分段讲解:

  • 要在Netmiko中使用enable密码,需要在设备登录信息的字典里加入secret这个键,该键对应的值就是设备的enable密码,这里我用的enable密码是123:
from netmiko import ConnectHandler
sw1 = {
        'device_type': 'cisco_ios',
        'ip': '192.168.2.11',
        'username': 'python',
        'password': '123',
        'secret': '123'
}
  • 之后在使用ConnectHandler()登录交换机时这里要多一个步骤:调用enable()这个方法,这样Netmiko才能配合之前的secret键,将它的值作为enable密码输入后登陆设备的特权模式。注意这里我特意用send_command()输入了show run这个只能在特权模式下使用,用户模式下不支持的命来验证Netmiko确实帮我们输入了enable密码,进入了特权模式:
with ConnectHandler(**sw1) as connect:
    connect.enable()
    print ("已经成功登陆交换机" + sw1['ip'])
    output = connect.send_command('show run')
    print (output)

运行脚本看效果:

网络工程师的Python之路——Netmiko终极指南

 


实验7: 使用Netmiko向设备传送文件。

开始实验7之前不要忘记先把用户python的特权级别从1改回15。

平常的网络运维工作中少不了要向设备传送文件,比如新的OS的镜像文件。实验7将演示如何使用Netmiko配合scp协议来向设备(SW1)传送文件。

首先在SW1上开启scp:

网络工程师的Python之路——Netmiko终极指南

 

然后创建一个名为test.txt的文本文件,在其中写入test这个单词。

网络工程师的Python之路——Netmiko终极指南

 

然后创建脚本netmiko7.py,写入下列代码:

from netmiko import ConnectHandler, file_transfer

sw1 = {
        'device_type': 'cisco_ios',
        'ip': '192.168.2.11',
        'username': 'python',
        'password': '123'
}

with ConnectHandler(**sw1) as connect:
     print ("已经成功登陆交换机" + sw1['ip'])
     output = file_transfer(connect,
                source_file="test.txt",
                dest_file="test.txt",
                file_system="flash:",
                direction="put")
     print (output)
网络工程师的Python之路——Netmiko终极指南

 

代码分段讲解:

  • 这里我们除ConnectHandler之外,额外从netmiko引入了file_transfer这个子类用来向设备传送文件:
from netmiko import ConnectHandler, file_transfer

sw1 = {
        'device_type': 'cisco_ios',
        'ip': '192.168.2.11',
        'username': 'python',
        'password': '123'
}
  • 通过ConnectHandler()登录SW1后, 调用file_transfer(),里面的各个参数应该不难理解,这里提一下因为我用的SW1是思科的IOS设备,所以file_system参数后面放的是flash:,如果是思科NX-OS的话,需要放bootflash:,如果是Arista设备的话,需要放/mnt/flash,如果是Junos设备的话,则要放/var/tmp。大家可以根据自己的情况来做改变。最后的direction这个参数,根据Netmiko官网API资料只能放“put”这一个值:
with ConnectHandler(**sw1) as connect:
     print ("已经成功登陆交换机" + sw1['ip'])
     output = file_transfer(connect,
                source_file="test.txt",
                dest_file="test.txt",
                file_system="flash:",
                direction="put")
     print (output)

运行脚本看效果:

首先查看SW1的文件系统flash0,确认里面没有test.txt文件

网络工程师的Python之路——Netmiko终极指南

 

运行脚本:

网络工程师的Python之路——Netmiko终极指南

 

注意这里print(output)返回的内容为一个字典,如果文件传输失败的话,该字典的file_transferred这个键的值将为False。

最后回到SW1上验证,可以看到test.txt文件已经成功上传到SW1的flash0::

网络工程师的Python之路——Netmiko终极指南

 


实验8:用Netmiko处理设备提示命令。

在网络设备中输入某些命令后系统会返回一个提示命令,询问你是继续执行命令还是撤销命令,比如我们在实验7中向SW1传入了test.txt这个文件,如果这时我们想将它删除,则需要输入命令del flash0:/test.txt,输入该命令后,系统会询问你是否confirm,如下:

这时如果你输入字母y或者敲下回车键则系统会执行del命令将该文件删除,如果你输入字母n,则系统会中断该命令,该文件不会被删除。

在Netmiko中我们可以调用send_command()函数中的command_stringexpect_string,strip_prompt,strip_command四个参数来应对这种情况。

首先创建实验8的脚本netmiko8.py,写入下列代码:

from netmiko import ConnectHandler
sw1 = {
        'device_type': 'cisco_ios',
        'ip': '192.168.2.11',
        'username': 'python',
        'password': '123'
}

with ConnectHandler(**sw1) as connect:
    print ("已经成功登陆交换机" + sw1['ip'])
    output = connect.send_command(command_string="del flash0:/test.txt",
                  expect_string=r"Delete flash0:/test.txt?",
                  strip_prompt=False,
                  strip_command=False)
    output += connect.send_command(command_string="y",
                  expect_string=r"#",
                  strip_prompt=False,
                  strip_command=False)

print(output)
    output = connect.send_command(command_string="del flash0:/test.txt",

代码分段讲解:

  • 前面这段代码没什么可讲的,正常创建字典用以登录交换机SW1
from netmiko import ConnectHandler 
sw1 ={
      'device_type':'cisco_ios',
      'ip':'192.168.2.11',
      'username':'python',
      'password':'123'
      }
from netmiko import ConnectHandler 
  • 通过ConnectHandler()登录SW1后,我们前后两次调用send_command()函数,我们在第一个send_command()函数中通过command_string这个参数向SW1输入命令del flash0:/test.txt,然后在expect_string这个参数里告知Netmiko去SW1的回显内容里查找“Delete flash0:/test.txt?”这段系统返回的提示命令,如果查到了的话,则继续输入命令y(第二个send_command())让脚本删除test.txt这个文件,之后如果接收到命令提示符"#",则继续执行脚本后面的代码。strip_prompt和strip_command两个参数这里放Fasle就行,目的是让代码最后的print(output)输出的内容的格式更好看一点:
with ConnectHandler(**sw1) as connect:
    print ("已经成功登陆交换机" + sw1['ip'])
    output = connect.send_command(command_string="del flash0:/test.txt",
                  expect_string=r"Delete flash0:/test.txt?",
                  strip_prompt=False,
                  strip_command=False)
    output += connect.send_command(command_string="y",
                  expect_string=r"#",
                  strip_prompt=False,
                  strip_command=False)

print(output)
    output = connect.send_command(command_string="del flash0:/test.txt",

运行脚本看效果:

首先确认目前 SW1的flash0下还有test.txt文件:

运行脚本netmiko8.py:

可以看到Netmiko在遇到提示命令“Delete flash0:/test.txt?”帮我们自动输入了命令y,删除了test.txt文件。

回到SW1上验证,test.txt已被删除:

前面说了,“strip_prompt和strip_command两个参数这里放Fasle就行,目的是让代码最后的print(output)输出的内容的格式更好看一点”, 如果把它们改成True会怎么样呢?来看效果:

显然不如放False的时候美观,并且看不到Netmiko帮我们输入的y这个命令。

 

个命令。

 

代码最后的print(output)输出的内容的格式更好看一点”, 如果把它们改成True会怎么样呢?来看效果:

显然不如放False的时候美观,并且看不到Netmiko帮我们输入的y这个命令。

 

个命令。

 

果:

显然不如放False的时候美观,并且看不到Netmiko帮我们输入的y这个命令。

 

个命令。



Tags:Netmiko   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
网络工程师的Python之路——Netmiko终极指南
作为Paramiko最为成功的衍生模块,Netmiko成为了很多学习Python网络运维自动化技术的网工日常工作中最常用的模块之一。相较于Paramiko,Netmiko将很多细节优化和简化,比如不需要...【详细内容】
2022-07-24  Search: Netmiko  点击:(905)  评论:(0)  加入收藏
玩转网络自动化之Netmiko模块
众所周知网络设备的配置在不同厂商之间、相同厂商的不同型号之间及相同型号不同版本之间都有着巨大的差异,同时随着数据中心网络设备的爆发式增长,通过人工来配置管理这些设备...【详细内容】
2020-09-09  Search: Netmiko  点击:(4725)  评论:(0)  加入收藏
▌简易百科推荐
一篇文章教会你使用Python中三种简单的函数
所谓函数,就是指:把某些特定功能的代码组成为一个整体,这个整体就叫做函数。一、函数简介所谓函数,就是指:把某些特定功能的代码组成为一个整体,这个整体就叫做函数。二、函数定义...【详细内容】
2024-04-11  Go语言进阶学习  微信公众号  Tags:Python   点击:(12)  评论:(0)  加入收藏
一篇文章带你了解Python的分布式进程接口
在Thread和Process中,应当优选Process,因为Process更稳定,而且,Process可以分布到多台机器上,而Thread最多只能分布到同一台机器的多个CPU上。一、前言在Thread和Process中,应当优...【详细内容】
2024-04-11  Go语言进阶学习    Tags:Python   点击:(10)  评论:(0)  加入收藏
Python 可视化:Plotly 库使用基础
当使用 Plotly 进行数据可视化时,我们可以通过以下示例展示多种绘图方法,每个示例都会有详细的注释和说明。1.创建折线图import plotly.graph_objects as go# 示例1: 创建简单...【详细内容】
2024-04-01  Python技术    Tags:Python   点击:(15)  评论:(0)  加入收藏
Python 办公神器:教你使用 Python 批量制作 PPT
介绍本文将介绍如何使用openpyxl和pptx库来批量制作PPT奖状。本文假设你已经安装了python和这两个库。本文的场景是:一名基层人员,要给一次比赛活动获奖的500名选手制作奖状,并...【详细内容】
2024-03-26  Python技术  微信公众号  Tags:Python   点击:(21)  评论:(0)  加入收藏
Python实现工厂模式、抽象工厂,单例模式
工厂模式是一种常见的设计模式,它可以帮助我们创建对象的过程更加灵活和可扩展。在Python中,我们可以使用函数和类来实现工厂模式。一、Python中实现工厂模式工厂模式是一种常...【详细内容】
2024-03-07  Python都知道  微信公众号  Tags:Python   点击:(38)  评论:(0)  加入收藏
不可不学的Python技巧:字典推导式使用全攻略
Python的字典推导式是一种优雅而强大的工具,用于创建字典(dict)。这种方法不仅代码更加简洁,而且执行效率高。无论你是Python新手还是有经验的开发者,掌握字典推导式都将是你技能...【详细内容】
2024-02-22  子午Python  微信公众号  Tags:Python技巧   点击:(43)  评论:(0)  加入收藏
如何进行Python代码的代码重构和优化?
Python是一种高级编程语言,它具有简洁、易于理解和易于维护的特点。然而,代码重构和优化对于保持代码质量和性能至关重要。什么是代码重构?代码重构是指在不改变代码外部行为的...【详细内容】
2024-02-22  编程技术汇    Tags:Python代码   点击:(44)  评论:(0)  加入收藏
Python开发者必备的八个PyCharm插件
在编写代码的过程中,括号几乎无处不在,以至于有时我们会拼命辨别哪个闭合括号与哪个开头的括号相匹配。这款插件能帮助解决这个众所周知的问题。前言在PyCharm中浏览插件列表...【详细内容】
2024-01-26  Python学研大本营  微信公众号  Tags:PyCharm插件   点击:(92)  评论:(0)  加入收藏
Python的Graphlib库,再也不用手敲图结构了
Python中的graphlib库是一个功能强大且易于使用的工具。graphlib提供了许多功能,可以帮助您创建、操作和分析图形对象。本文将介绍graphlib库的主要用法,并提供一些示例代码和...【详细内容】
2024-01-26  科学随想录  微信公众号  Tags:Graphlib库   点击:(95)  评论:(0)  加入收藏
Python分布式爬虫打造搜索引擎
简单分布式爬虫结构主从模式是指由一台主机作为控制节点负责所有运行网络爬虫的主机进行管理,爬虫只需要从控制节点那里接收任务,并把新生成任务提交给控制节点就可以了,在这个...【详细内容】
2024-01-25  大雷家吃饭    Tags:Python   点击:(63)  评论:(0)  加入收藏
站内最新
站内热门
站内头条