fny5jt9 发表于 2024-8-18 06:02:30

Python自动化运维实战:运用Python管理网络设备


    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">此刻</span>,<span style="color: black;">咱们</span><span style="color: black;">已然</span><span style="color: black;">晓得</span><span style="color: black;">怎样</span>在<span style="color: black;">区别</span>的操作系统中<span style="color: black;">运用</span>和安装Python以及<span style="color: black;">怎样</span><span style="color: black;">运用</span>EVE-NG搭建网络拓扑。在本章中,<span style="color: black;">咱们</span>将学习<span style="color: black;">怎样</span><span style="color: black;">运用</span><span style="color: black;">日前</span>常用的网络自动化库自动完成<span style="color: black;">各样</span>网络任务。Python<span style="color: black;">能够</span>在<span style="color: black;">区别</span>的网络层上与网络设备进行交互。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">首要</span>,Python<span style="color: black;">能够</span><span style="color: black;">经过</span>套接字编程和socket模块<span style="color: black;">操作</span>底层网络,从而为Python所在的操作系统和网络设备之间搭建一个低层次的网络接口。<span style="color: black;">另外</span>,Python模块还<span style="color: black;">能够</span><span style="color: black;">经过</span>Telnet、SSH和API与网络设备进行更高级别的交互。本章将深入探讨<span style="color: black;">怎样</span>在Python中<span style="color: black;">运用</span>Telnet与SSH模块在远程设备上<span style="color: black;">创立</span>连接和执行命令。</p>
    <h2 style="color: black; text-align: left; margin-bottom: 10px;">1 技术<span style="color: black;">需求</span></h2>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">应<span style="color: black;">检测</span><span style="color: black;">是不是</span>正确安装了下列工具并<span style="color: black;">保准</span>它们能够正常<span style="color: black;">运用</span>:</p>Python 2.7.1x;PyCharm社区版或专业版;EVE-NG,网络仿真器的安装和配置请参阅第3章。<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">本章中<span style="color: black;">显现</span>的所有脚本请参见GitHub网站。</p>
    <h3 style="color: black; text-align: left; margin-bottom: 10px;">1.1 Python和SSH</h3>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">SSH和Telnet的<span style="color: black;">区别</span>之处在于客户端与服务器之间交换数据的通道不<span style="color: black;">同样</span>。SSH<span style="color: black;">运用</span>的是安全链路,在客户端和设备之间创建了一个<span style="color: black;">运用</span><span style="color: black;">区别</span>的安全机制进行加密的隧道,通信内容很难被解密。<span style="color: black;">因此呢</span>在<span style="color: black;">必须</span><span style="color: black;">保准</span>网络安全的时候,网络工程师会<span style="color: black;">首要</span><span style="color: black;">选取</span><span style="color: black;">运用</span>SSH协议。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">Paramiko</strong>库遵循SSH2协议,支持身份验证,密钥处理(DSA、RSA、ECDSA和ED25519),以及其他SSH功能(如proxy命令和SFTP)。在Python中当<span style="color: black;">必须</span><span style="color: black;">运用</span>SSH连接到网络设备时<span style="color: black;">一般</span><span style="color: black;">运用</span>这个库。</p>
    <h3 style="color: black; text-align: left; margin-bottom: 10px;">1.2 Paramiko模块</h3>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Paramiko是Python中应用最广的SSH模块。模块本身<span style="color: black;">运用</span>Python语言编写和<span style="color: black;">研发</span>,<span style="color: black;">仅有</span>像crypto<span style="color: black;">这般</span>的核心函数才会用到C语言。从其GitHub官方链接上能够看到代码的贡献者和模块历史等<span style="color: black;">许多</span>信息。</p>1.安装模块<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">打开Windows cmd或Linux shell,运行下面的命令,从PyPI下载最新的Paramiko模块。如下图所示,<span style="color: black;">同期</span>,该命令会自动下载其他依赖包(如cyrptography、ipaddress和six),并将它们安装到计算机上。</p><span style="color: black;">pip</span> install paramiko<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/fa1def259a574b5c93318b9c9361c57b~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=PbFCFSxNRMerzz6fDCviIIfC7Yg%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在命令行中输入Python,<span style="color: black;">而后</span>导入Paramiko模块,验证<span style="color: black;">是不是</span>安装成功。如下图所示,正确安装之后,能够成功导入模块。<span style="color: black;">亦</span><span style="color: black;">便是</span>说,命令行上不会<span style="color: black;">显现</span>任何错误提示。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/5fdc74f4e74f4cf19297c9985a8a7bf9~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=%2B2JtbLNBYuzH3SBIpeIkRhKjAd8%3D" style="width: 50%; margin-bottom: 20px;"></div>2.用SSH连接网络设备<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">如前所述,要<span style="color: black;">运用</span>Paramiko模块,<span style="color: black;">首要</span><span style="color: black;">必须</span>在Python脚本中导入它,<span style="color: black;">而后</span><span style="color: black;">经过</span>继承SSHClient()来创建SSH客户端。<span style="color: black;">而后</span>,设置Paramiko的参数,使其能够自动添加任意未知的主机密钥并信任与服务器之间的连接。接下来,将远程主机的信息(IP<span style="color: black;">位置</span>、用户名和<span style="color: black;">秘码</span>等)传递给connect函数。</p><span style="color: black;">#!/usr/bin/python</span>
    __author__ = <span style="color: black;">"Bassim Aly"</span>
    __EMAIL__ = <span style="color: black;">"basim.alyy@gmail.com"</span>

    <span style="color: black;">import</span> paramiko
    <span style="color: black;">import</span>time
    Channel = paramiko.SSHClient()
    Channel.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    Channel.connect(hostname=<span style="color: black;">"10.10.88.112"</span>, username=<span style="color: black;">admin</span>,
    password=<span style="color: black;">access123</span>, look_for_keys=<span style="color: black;">False</span>,allow_agent=<span style="color: black;">False</span>)

    shell = Channel.invoke_shell()<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">AutoAddPolicy()是一种策略,<span style="color: black;">能够</span><span style="color: black;">做为</span>函数</p>set_missing_host_key_policy()的输入参数。在虚拟实验室环境中<span style="color: black;">举荐</span><span style="color: black;">运用</span>这种策略,但在生产环境中应当<span style="color: black;">运用</span>更加严格的策略,如WarningPolicy()或RejectPolicy()。

    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">最后,invoke_shell()将<span style="color: black;">起步</span>一个连接到SSH服务器的交互式shell会话。在调用该函数时<span style="color: black;">能够</span>传入<span style="color: black;">有些</span>其他参数(如终端类型、宽度、高度等)。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Paramiko的连接参数如下。</p>Look_For_Keys:默认为True,强制Paramiko<span style="color: black;">运用</span>密钥进行身份验证。<span style="color: black;">亦</span><span style="color: black;">便是</span>说,用户<span style="color: black;">必须</span><span style="color: black;">运用</span>私钥和公钥对网络设备进行身份验证。在<span style="color: black;">这儿</span><span style="color: black;">运用</span><span style="color: black;">秘码</span>验证,<span style="color: black;">因此呢</span>将该参数设置为False。allow_agent:<span style="color: black;">暗示</span><span style="color: black;">是不是</span><span style="color: black;">准许</span>连接到SSH代理,默认为True。在用密钥验证时可能<span style="color: black;">必须</span><span style="color: black;">运用</span>这个选项。<span style="color: black;">因为</span><span style="color: black;">这儿</span><span style="color: black;">运用</span>的是用户名/<span style="color: black;">秘码</span>,<span style="color: black;">因此呢</span>禁用它。<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">最后一步,把<span style="color: black;">各样</span>命令(如show ip int b和show arp)发送到设备终端,并将返回结果输出到Python窗口中。</p><span style="color: black;">shell</span><span style="color: black;">.send</span>(<span style="color: black;">"enable\n"</span>)
    <span style="color: black;">shell</span><span style="color: black;">.send</span>(<span style="color: black;">"access123\n"</span>)
    <span style="color: black;">shell</span><span style="color: black;">.send</span>(<span style="color: black;">"terminal length 0\n"</span>)
    <span style="color: black;">shell</span><span style="color: black;">.send</span>(<span style="color: black;">"show ip int b\n"</span>)
    <span style="color: black;">shell</span><span style="color: black;">.send</span>(<span style="color: black;">"show arp \n"</span>)
    <span style="color: black;">time</span><span style="color: black;">.sleep</span>(<span style="color: black;">2</span>)
    <span style="color: black;">print</span> <span style="color: black;">shell</span><span style="color: black;">.recv</span>(<span style="color: black;">5000</span>)
    <span style="color: black;">Channel</span><span style="color: black;">.close</span>()<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">脚本运行结果如下图所示。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/4643bb4675da4c0a9ef2c8f55780bac4~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=3D1JEa8JzvfKDoss7dBpEoEitMI%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">倘若</span><span style="color: black;">必须</span>在远程设备上执行耗时很长的命令,就要强制Python等待一段时间,直到设备生成输出并将结果返回给Python,<span style="color: black;">因此呢</span>最好<span style="color: black;">运用</span>time.sleep()。否则,Python可能得不到正确的输出结果。</p>
    <h3 style="color: black; text-align: left; margin-bottom: 10px;">1.3 netmiko模块</h3>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">netmiko是Paramiko的<span style="color: black;">加强</span>版本,专门面向网络设备。虽然Paramiko能够处理与设备的SSH连接并判断设备类型是服务器、打印机还是网络设备,但netmiko在设计时针对网络设备做了优化,能够更有效地处理SSH连接。netmiko还支持<span style="color: black;">各样</span><span style="color: black;">区别</span>的设备厂商和平台。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">netmiko<span style="color: black;">亦</span>是对Paramiko的封装,它<span style="color: black;">运用</span>许多其他<span style="color: black;">加强</span>功能扩展了Paramiko,<span style="color: black;">例如</span><span style="color: black;">运用</span>启用的<span style="color: black;">秘码</span>直接<span style="color: black;">拜访</span>所支持的设备,从文件读取配置并将推送到设备,在登录<span style="color: black;">时期</span>禁用分页<span style="color: black;">表示</span>,以及默认在每条命令后面加上回车符“\n”。</p>1.支持的设备商<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">netmiko支持许多供应商的设备,并<span style="color: black;">定时</span>在支持列表中添加新的供应商。netmiko支持的供应商列表分为<span style="color: black;">定时</span>测试类、有限测试类和实验类。在该模块的GitHub页面上<span style="color: black;">能够</span>找到这个列表。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">定时</span>测试</strong>类中支持的供应商如下图所示。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/ef5aed493dc44f57a705a00642e43bb4~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=BJ0lNrH6XuxMhG%2BhAKijAydsa5Q%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">有限测试</strong>类中支持的供应商如下图所示。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/22baab6dd1854173a113fa8d25fe4343~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=E7dMh1%2BJc4owjewKsbWukXq%2F%2Bnc%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">实验</strong>类中支持的供应商如下图所示。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/859f33a3879e41d9a159831397674bc7~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=0bkHTuJiAnNihbF0nshdbGPh2wI%3D" style="width: 50%; margin-bottom: 20px;"></div>2.安装和验证<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">安装netmiko非常简单。打开Windows命令行窗口或Linux shell,执行下面的命令就<span style="color: black;">能够</span>从PyPI获取最新版本的netmiko包(见下图)。</p><span style="color: black;">pip</span> install netmiko<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/2ec60aee49d44c77834306f47dfb165e~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=%2BtX4KzGoGaobjoLWOmcfcW1vy0U%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">而后</span>,在Python shell中导入netmiko,验证模块<span style="color: black;">是不是</span>正确地安装到Python site-packages中。</p><span style="color: black;">$</span><span style="color: black;">python</span>
    <span style="color: black;"> &gt;</span><span style="color: black;">&gt;&gt;import netmiko</span>3.<span style="color: black;">运用</span>netmiko<span style="color: black;">创立</span>SSH连接<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">此刻</span>该<span style="color: black;">起始</span><span style="color: black;">运用</span>netmiko了,让<span style="color: black;">咱们</span>来<span style="color: black;">瞧瞧</span>它强大的SSH功能。<span style="color: black;">首要</span>连接到网络设备并在上面执行命令。默认<span style="color: black;">状况</span>下,netmiko在<span style="color: black;">创立</span>会话(session)的过程中会在后台处理许多操作(如添加未知的SSH密钥主机,设置终端类型、宽度和高度),在<span style="color: black;">必须</span>的时候还<span style="color: black;">能够</span>进入特权(enable)模式,<span style="color: black;">而后</span><span style="color: black;">经过</span>运行供应商<span style="color: black;">供给</span>的命令来禁用分页。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">首要</span>,以字典格式定义设备并<span style="color: black;">供给</span>下列5个必需的关键信息。</p><span style="color: black;">R1</span> = (
    <span style="color: black;">device type </span>: <span style="color: black;">cisco ios</span>,
    <span style="color: black;">ip</span>: <span style="color: black;">10.10.88.110</span>,
    <span style="color: black;">username</span>: <span style="color: black;">admin</span>,
    <span style="color: black;">password</span>: <span style="color: black;">access123</span>,
    <span style="color: black;">secret</span>: <span style="color: black;">access123</span>,
    }<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">第1</span>个参数是device_type,为了执行正确的命令,<span style="color: black;">必须</span><span style="color: black;">运用</span>这个参数来定义平台供应商。<span style="color: black;">而后</span>,<span style="color: black;">必须</span>SSH的IP<span style="color: black;">位置</span>。<span style="color: black;">倘若</span><span style="color: black;">已然</span><span style="color: black;">运用</span>DNS解析了IP<span style="color: black;">位置</span>,该参数可能是主机名;否则,该参数是IP<span style="color: black;">位置</span>。接下来,<span style="color: black;">供给</span>username、password以及以secret参数传递的特权模式的<span style="color: black;">秘码</span>。<span style="color: black;">重视</span>,<span style="color: black;">能够</span>使用getpass()模块<span style="color: black;">隐匿</span><span style="color: black;">秘码</span>,并且<span style="color: black;">仅在</span>脚本执行<span style="color: black;">时期</span>提示它们。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">虽然变量中的密钥序列不重要,<span style="color: black;">然则</span>为了使netmiko能够正确解析字典并<span style="color: black;">起始</span>和设备<span style="color: black;">创立</span>连接,密钥的名<span style="color: black;">叫作</span>应该和之前示例中<span style="color: black;">供给</span>的密钥完全<span style="color: black;">同样</span>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">接下来,从netmiko模块导入ConnectHandler函数,并<span style="color: black;">供给</span>定义的字典来<span style="color: black;">起始</span><span style="color: black;">创立</span>连接。因为所有的设备是<span style="color: black;">经过</span>特权模式的<span style="color: black;">秘码</span>配置的,<span style="color: black;">因此</span><span style="color: black;">必须</span>为创建的连接<span style="color: black;">供给</span>.enable(),以在特权模式下<span style="color: black;">拜访</span>。<span style="color: black;">运用</span>.send_command()在路由器终端上执行命令,.send_command()将会执行命令并<span style="color: black;">经过</span>变量的值<span style="color: black;">表示</span>设备的输出。</p><span style="color: black;">from</span> netmiko <span style="color: black;">import</span>ConnectHandler
    connection = ConnectHandler(**R1)
    connection.enable()
    output = connection.send_command(<span style="color: black;">"show ip int b"</span>)
    <span style="color: black;">print</span> output<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">脚本输出结果如下。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/21d01f9585d44b5abff84eab845cc074~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=AlMbCO%2BEevBhsDGJVMqnAq%2BJoFU%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">重视</span>,<span style="color: black;">这儿</span>看到的输出结果去掉了命令行中的命令回显和设备提示符。默认<span style="color: black;">状况</span>下,netmiko会替换设备的返回结果,使输出更加整洁,替换过程<span style="color: black;">经过</span>正则表达式完成,这部分会在下一章<span style="color: black;">中间商</span>绍。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">倘若</span>不想<span style="color: black;">运用</span>这种方式,而是<span style="color: black;">期盼</span>看到命令提示符,并在返回结果的后面执行命令,<span style="color: black;">能够</span>在.send_command()函数中加上以下参数。</p><span style="color: black;">output</span>= connection.send_command(<span style="color: black;">"show ip int
      b"</span>,strip_command=<span style="color: black;">False</span>,strip_prompt=<span style="color: black;">False</span>)<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">strip_command=False和strip_prompt=False告诉netmiko<span style="color: black;">保存</span>而不是替换命令行回显和提示符。默认情况下它为True,<span style="color: black;">能够</span><span style="color: black;">按照</span><span style="color: black;">必须</span>进行设置。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/31ef7700067a48eab04c476f0c5242be~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=LIVY7r3i%2Fc0k2GHF%2FSEBNWaRomc%3D" style="width: 50%; margin-bottom: 20px;"></div>4.<span style="color: black;">运用</span>netmiko配置设备<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">netmiko<span style="color: black;">能够</span><span style="color: black;">经过</span>SSH配置远程设备,<span style="color: black;">经过</span>.config<span style="color: black;">办法</span>进入设备的配置模式,<span style="color: black;">而后</span><span style="color: black;">根据</span>list格式中的信息(配置列表)配置设备。配置列表<span style="color: black;">能够</span>直接写在Python脚本中,<span style="color: black;">亦</span><span style="color: black;">能够</span>从文件中读取,<span style="color: black;">而后</span>用readlines()<span style="color: black;">办法</span>转换为列表。</p><span style="color: black;">from</span> netmiko <span style="color: black;">import</span> ConnectHandler

    SW2 = {
    <span style="color: black;">device_type</span>: <span style="color: black;">cisco_ios</span>,
    <span style="color: black;">ip</span>: <span style="color: black;">10.10.88.112</span>,
    <span style="color: black;">username</span>: <span style="color: black;">admin</span>,
    <span style="color: black;">password</span>: <span style="color: black;">access123</span>,
    <span style="color: black;">secret</span>: <span style="color: black;">access123</span>,
    }

    core_sw_config = [<span style="color: black;">"int range gig0/1 - 2"</span>,<span style="color: black;">"switchport trunk encapsulation
      dot1q"</span>,
    <span style="color: black;">"switchport mode trunk"</span>,<span style="color: black;">"switchport trunk allowed vlan
      1,2"</span>]

    <span style="color: black;">print</span> <span style="color: black;">"########## Connecting to Device {0} ############"</span>.format(SW2[<span style="color: black;">ip</span>])
    net_connect = ConnectHandler(**SW2)
    net_connect.enable()
    <span style="color: black;">print</span> <span style="color: black;">"***** Sending Configuration to Device *****"</span>
    net_connect.send_config_set(core_sw_config)<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">上面的脚本以<span style="color: black;">另一</span>一种形式连接到SW2并进入特权模式。但这次<span style="color: black;">运用</span>的是另一个netmiko<span style="color: black;">办法</span>——send_config_set(),该<span style="color: black;">办法</span><span style="color: black;">必须</span><span style="color: black;">运用</span>列表形式的配置文件,<span style="color: black;">同期</span>进入设备的配置模式并<span style="color: black;">按照</span>列表对设备进行配置。<span style="color: black;">这儿</span>测试了一个简单的配置,即修改gig0/1和gig0/2,并将这两个端口配成trunk模式。在设备上执行show run命令时,<span style="color: black;">倘若</span>命令执行成功,会<span style="color: black;">显现</span>类似下面的输出。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/533824d5e37f429abf4f082868ff88a8~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=NPYxFMrar%2BMqgmhqZTVdqbfsjB4%3D" style="width: 50%; margin-bottom: 20px;"></div>5.netmiko中的<span style="color: black;">反常</span>处理<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在设计Python脚本时,<span style="color: black;">咱们</span>可能会假设设备已<span style="color: black;">起步</span>并运行,并且用户已<span style="color: black;">供给</span>了正确的登录信息,但<span style="color: black;">实质</span><span style="color: black;">状况</span>并非总是如此。有时Python和远程设备之间的网络连接可能存在问题,<span style="color: black;">或</span>用户输入了错误的登录信息。<span style="color: black;">倘若</span><span style="color: black;">出现</span>这种<span style="color: black;">状况</span>,Python<span style="color: black;">一般</span>会抛出<span style="color: black;">反常</span>并退出,但这种<span style="color: black;">处理</span><span style="color: black;">方法</span>显然<span style="color: black;">不足</span>完美。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">netmiko中的<span style="color: black;">反常</span>处理模块netmiko.ssh_exception<span style="color: black;">供给</span>的<span style="color: black;">有些</span><span style="color: black;">反常</span>处理类<span style="color: black;">能够</span>处理上面所说的<span style="color: black;">哪些</span><span style="color: black;">状况</span>。<span style="color: black;">第1</span>个类AuthenticationException能够<span style="color: black;">捕捉</span>远程设备中的身份验证错误。第二个类NetMikoTimeoutException能够<span style="color: black;">捕捉</span>netmiko和设备之间的超时或任何连接问题。下面的例子中<span style="color: black;">运用</span>try-except子句<span style="color: black;">包括</span>了ConnectHandler()<span style="color: black;">办法</span>,用来<span style="color: black;">捕捉</span>超时和身份验证<span style="color: black;">反常</span>。</p><span style="color: black;">from</span> netmiko <span style="color: black;">import</span> ConnectHandler
    <span style="color: black;">from</span> netmiko.ssh_exception <span style="color: black;">import</span>AuthenticationException,
    NetMikoTimeoutException
    device = {<span style="color: black;">device_type</span>: <span style="color: black;">cisco_ios</span>,
    <span style="color: black;">ip</span>: <span style="color: black;">10.10.88.112</span>,
    <span style="color: black;">username</span>: <span style="color: black;">admin</span>,
    <span style="color: black;">password</span>: <span style="color: black;">access123</span>,
    <span style="color: black;">secret</span>: <span style="color: black;">access123</span>,
    }

    <span style="color: black;">print</span> <span style="color: black;">"########## Connecting to Device {0}
      ############"</span>.format(device[<span style="color: black;">ip</span>])
    try:
    net_connect = ConnectHandler(**device)
    net_connect.enable()

    <span style="color: black;">print</span> <span style="color: black;">"***** show ip configuration of Device *****"</span>
    output = net_connect.send_command(<span style="color: black;">"show ip int b"</span>)
    <span style="color: black;">print</span>output

    net_connect.disconnect()

    except NetMikoTimeoutException:<span style="color: black;">print</span> <span style="color: black;">"=========== SOMETHING WRONG HAPPEN WITH {0}
      ============"</span>.format(device[<span style="color: black;">ip</span>])

    except AuthenticationException:
    <span style="color: black;">print</span> <span style="color: black;">"========= Authentication Failed with {0}
      ============"</span>.format(device[<span style="color: black;">ip</span>])

    except Exception <span style="color: black;">as</span> unknown_error:
    <span style="color: black;">print</span> <span style="color: black;">"============ SOMETHING UNKNOWN HAPPEN WITH {0} ============"</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">6.设备自动<span style="color: black;">发掘</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">netmiko<span style="color: black;">供给</span>了一种<span style="color: black;">能够</span>“猜测”设备类型和<span style="color: black;">发掘</span>设备的机制。<span style="color: black;">经过</span>组合<span style="color: black;">运用</span>SNMP<span style="color: black;">发掘</span>OIDS和在远程<span style="color: black;">掌控</span>台上执行多个show命令这两种方式,<span style="color: black;">按照</span>输出字符串检测路由器的操作系统和类型。<span style="color: black;">而后</span>,netmiko将相应的驱动程序加载到ConnectHandler()类中。</p><span style="color: black;">#!/usr/local/bin/python</span>
    __author__ = <span style="color: black;">"Bassim Aly"</span>
    __EMAIL__ = <span style="color: black;">"basim.alyy@gmail.com"</span>

    <span style="color: black;">from</span> netmiko <span style="color: black;">import</span> SSHDetect, Netmiko
    device = {
    <span style="color: black;">device_type</span>: <span style="color: black;">autodetect</span>,
    <span style="color: black;">host</span>: <span style="color: black;">10.10.88.110</span>,
    <span style="color: black;">username</span>: <span style="color: black;">admin</span>,
    <span style="color: black;">password</span>: <span style="color: black;">"access123"</span>,
    }

    detect_device = SSHDetect(**device)
    device_type = detect_device.autodetect()<span style="color: black;">print</span>(device_type)
    <span style="color: black;">print</span>(detect_device.potential_matches)

    device[<span style="color: black;">device_type</span>] = device_type
    connection = Netmiko(**device)<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在上面的脚本中,应<span style="color: black;">重视</span>以下几点。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">首要</span>,设备字典中的device_type等于autodetect,<span style="color: black;">亦</span><span style="color: black;">便是</span>告诉netmiko在检测到设备类型之前不要加载驱动程序。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">而后</span>,<span style="color: black;">运用</span>netmiko的SSHDetect()类<span style="color: black;">发掘</span>设备。它<span style="color: black;">运用</span>SSH连接到设备,并执行<span style="color: black;">有些</span>命令以找出操作系统的类型,结果以字典形式返回。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">接着,<span style="color: black;">运用</span>autodetect()函数将匹配度最高的结果赋给device_type变量。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">接下来,输出potential_matches,查看字典内的<span style="color: black;">所有</span>返回结果。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">最后,<span style="color: black;">能够</span>更新设备字典并为其分配新的device_type。</p>
    <h2 style="color: black; text-align: left; margin-bottom: 10px;">2 在Python中<span style="color: black;">运用</span>Telnet协议</h2>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Telnet是TCP/IP协议栈中最早可用的协议之一,主要用来在服务器和客户端之间<span style="color: black;">创立</span>连接、交换数据。服务器端监听TCP端口23,等待客户端的连接请求。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在下面的例子中,<span style="color: black;">咱们</span>将创建一个Python脚本<span style="color: black;">做为</span>Telnet客户端,拓扑中的其他路由器和交换机则<span style="color: black;">做为</span>Telnet服务器。Python原生的telnetlib库<span style="color: black;">已然</span>支持Telnet,<span style="color: black;">因此</span>不<span style="color: black;">必须</span><span style="color: black;">另一</span>安装。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">客户端对象<span style="color: black;">能够</span><span style="color: black;">经过</span>telnetlib模块中的Telnet()类实例化创建。<span style="color: black;">经过</span>这个对象,<span style="color: black;">咱们</span>能够<span style="color: black;">运用</span>telnetlib中的两个重要函数——read_until()(用于读取输出结果)和write()(用于向远程设备写入内容)。这两个函数用来和Telnet连接交互,从Telnet连接读取或向Telnet连接写入数据。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">还有一点非常关键,<span style="color: black;">运用</span>read_until()读取Telnet连接的内容之后缓冲区会被清空,<span style="color: black;">没法</span>再次读取。<span style="color: black;">因此呢</span>,<span style="color: black;">倘若</span>在后面的处理中还会用到之前读取的重要数据,<span style="color: black;">必须</span>在脚本里将其另存为变量。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Telnet数据以明文形式发送,<span style="color: black;">因此呢</span><span style="color: black;">经过</span>“中间人攻击”<span style="color: black;">能够</span><span style="color: black;">捕捉</span>并查看到Telnet数据,如用户信息和<span style="color: black;">秘码</span>。即便如此,<span style="color: black;">有些</span>服务<span style="color: black;">供给</span>商和企业仍然在<span style="color: black;">运用</span>它,只是<span style="color: black;">她们</span>会集成VPN和radius/tacacs协议,以<span style="color: black;">供给</span>轻量级和安全的<span style="color: black;">拜访</span>方式。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">让<span style="color: black;">咱们</span>一步步分析这个脚本。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">(1)在Python脚本中导入telnetlib模块,在变量中定义用户名和<span style="color: black;">秘码</span>。代码如下。</p>import telnetlib
    username =<span style="color: black;">"admin"</span>
    password = <span style="color: black;">"access123"</span>
    enable_password = <span style="color: black;">"access123"</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">(2)定义一个变量,用来和远程主机<span style="color: black;">创立</span>连接。<span style="color: black;">重视</span>,只<span style="color: black;">必须</span><span style="color: black;">供给</span>远程主机的IP<span style="color: black;">位置</span>,<span style="color: black;">不消</span>在连接<span style="color: black;">创立</span>过程中<span style="color: black;">供给</span>用户名或<span style="color: black;">秘码</span>。</p>cnx = telnetlib.Telnet(host=<span style="color: black;">"10.10.88.110"</span>) <span style="color: black;">#here were telnet to</span>
    Gateway<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">(3)<span style="color: black;">经过</span>读取Telnet连接返回的输出并搜索“Username:”关键字来<span style="color: black;">供给</span>Telnet连接的用户名。<span style="color: black;">而后</span>写入管理员用户名。<span style="color: black;">倘若</span><span style="color: black;">必须</span>,用<span style="color: black;">一样</span>的<span style="color: black;">办法</span>输入Telnet<span style="color: black;">秘码</span>。</p><span style="color: black;">cnx</span><span style="color: black;">.read_until</span>(<span style="color: black;">"Username:"</span>)
    <span style="color: black;">cnx</span><span style="color: black;">.write</span>(username + <span style="color: black;">"\n"</span>)
    <span style="color: black;">cnx</span><span style="color: black;">.read_until</span>(<span style="color: black;">"Password:"</span>)
    <span style="color: black;">cnx</span><span style="color: black;">.write</span>(password + <span style="color: black;">"\n"</span>)
    <span style="color: black;">cnx</span><span style="color: black;">.read_until</span>(<span style="color: black;">"&gt;"</span>)
    <span style="color: black;">cnx</span><span style="color: black;">.write</span>(<span style="color: black;">"en"</span> + <span style="color: black;">"\n"</span>)
    <span style="color: black;">cnx</span><span style="color: black;">.read_until</span>(<span style="color: black;">"Password:"</span>)
    <span style="color: black;">cnx</span><span style="color: black;">.write</span>(enable_password + <span style="color: black;">"\n"</span>)<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Telnet连接建好之后,在脚本中加上<span style="color: black;">掌控</span>台提示符非常重要;否则,连接将陷入死循环。接着Python脚本就会超时并<span style="color: black;">显现</span>错误。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">(4)向Telnet连接写入show ip interface brief命令并<span style="color: black;">起始</span>读取返回内容,直到<span style="color: black;">显现</span>路由器提示符(#)为止。<span style="color: black;">经过</span>以下命令<span style="color: black;">能够</span>得到路由器的接口配置。</p>cnx.read_until(<span style="color: black;">"#"</span>)
    cnx.<span style="color: black;">write</span>(<span style="color: black;">"show ip int b"</span> + <span style="color: black;">"\n"</span>)
    <span style="color: black;">output</span> = cnx.read_until(<span style="color: black;">"#"</span>)
    <span style="color: black;">print</span> <span style="color: black;">output</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">完整的脚本如下所示。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p6-sign.toutiaoimg.com/pgc-image/2e46ddb2c2d6413cb5ef5fb6f77acf61~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=lFOstjlZmNuznKFNycfSaEK5SXE%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">脚本运行结果如下所示。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/08ff8848d3204c3d907e9e697e9f6cd0~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=RjZt9VGML9JUTlUpgIP%2F3ypRCbg%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">重视</span>,在输出中<span style="color: black;">包括</span>了执行的命令show ip int b,并且在stdout中输出和返回了路由器提示符”R1#”。<span style="color: black;">能够</span><span style="color: black;">运用</span>内置的字符串函数(如replace())从输出中清除它们。</p>cleaned_output = <span style="color: black;">output</span>.replace(<span style="color: black;">"show ip int b"</span>,<span style="color: black;">""</span>).replace(<span style="color: black;">"R1#"</span>,<span style="color: black;">""</span>)
    <span style="color: black;">print</span> cleaned_output<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/b93a2ea7c9e84ea9ad0332e572f6c92e~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=YA%2FQtn%2BRrHvPfzjnQoSSXRzY%2Fao%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">你可能<span style="color: black;">已然</span><span style="color: black;">重视</span>到脚本中<span style="color: black;">运用</span>了<span style="color: black;">秘码</span>并将<span style="color: black;">秘码</span>以明文形式写下来,<span style="color: black;">这般</span>做显然是不安全的。<span style="color: black;">同期</span>,在Python脚本中<span style="color: black;">运用</span>硬编码<span style="color: black;">亦</span>不是好习惯。在下一节中,<span style="color: black;">咱们</span>将学习<span style="color: black;">怎样</span><span style="color: black;">隐匿</span><span style="color: black;">秘码</span>并设计一种机制,从而在脚本运行时<span style="color: black;">需求</span>用户输入<span style="color: black;">秘码</span>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">另外</span>,<span style="color: black;">倘若</span>要执行<span style="color: black;">哪些</span>输出结果可能跨越多个页面的命令(如show running config),则<span style="color: black;">必须</span>在连接到设备之后和发送命令之前,先<span style="color: black;">经过</span>发送termindl length 0来禁用分页。</p>
    <h3 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">运用</span>telnetlib推送配置</h3>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在上一节中,<span style="color: black;">咱们</span><span style="color: black;">经过</span>执行show ip int brief简单介绍了telnetlib的操作过程。<span style="color: black;">此刻</span><span style="color: black;">咱们</span>要用telnetlib将VLAN配置推送到实验室网络拓扑中的4台交换机。<span style="color: black;">运用</span>Python的range()函数创建一个VLAN列表,遍历列表将VLAN ID推送到当前交换机。<span style="color: black;">重视</span>,<span style="color: black;">咱们</span>将交换机的IP<span style="color: black;">位置</span>放到了另一个列表中,<span style="color: black;">运用</span><span style="color: black;">外边</span>for循环来遍历这个列表。<span style="color: black;">同期</span><span style="color: black;">运用</span>内置模块getpass<span style="color: black;">隐匿</span><span style="color: black;">掌控</span>台中的<span style="color: black;">秘码</span>,在脚本运行时提示用户输入<span style="color: black;">秘码</span>。</p><span style="color: black;">#!/usr/bin/python</span>
    import telnetlib
    import getpass
    import time

    switch_ips = [<span style="color: black;">"10.10.88.111"</span>, <span style="color: black;">"10.10.88.112"</span>, <span style="color: black;">"10.10.88.113"</span>,
    <span style="color: black;">"10.10.88.114"</span>]
    username = raw_input(<span style="color: black;">"Please Enter your username:"</span>)
    password = getpass.getpass(<span style="color: black;">"Please Enter your Password:"</span>)
    enable_password = getpass.getpass(<span style="color: black;">"Please Enter your Enable Password:"</span>)

    for sw_ip in switch_ips:
    print <span style="color: black;">"\n#################### Working on Device "</span> + sw_ip + <span style="color: black;">"
      ####################"</span>
    connection = telnetlib.Telnet(host=sw_ip.strip())
    <span style="color: black;">connection.read_until("Username:")</span>
    connection.write(username + <span style="color: black;">"\n"</span>)
    <span style="color: black;">connection.read_until("Password:")</span>
    connection.write(password + <span style="color: black;">"\n"</span>)
    connection.read_until(<span style="color: black;">"&gt;"</span>)
    connection.write(<span style="color: black;">"enable"</span> + <span style="color: black;">"\n"</span>)
    <span style="color: black;">connection.read_until("Password:")</span>
    connection.write(enable_password + <span style="color: black;">"\n"</span>)
    connection.read_until(<span style="color: black;">"#"</span>)
    connection.write(<span style="color: black;">"config terminal"</span> + <span style="color: black;">"\n"</span>) <span style="color: black;"># now im in config mode</span>vlans = range(300,400)
    for vlan_id in vlans:
    print<span style="color: black;">"\n********* Adding VLAN "</span> + str(vlan_id) + <span style="color: black;">"**********"</span>
    connection.read_until(<span style="color: black;">"#"</span>)
    connection.write(<span style="color: black;">"vlan "</span> + str(vlan_id) + <span style="color: black;">"\n"</span>)
    time.sleep(1)
    connection.write(<span style="color: black;">"exit"</span> + <span style="color: black;">"\n"</span>)
    connection.read_until(<span style="color: black;">"#"</span>)
    connection.close()<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">最外层的for循环用来遍历设备列表,<span style="color: black;">而后</span>在每次循环(<span style="color: black;">每一个</span>设备)中生成范围为300~400的VLAN ID并将它们推送到当前设备。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">脚本运行结果如下。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/ade75f5bdef24991a6005ae246d3b46a~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=QSxl5fStxzBmechoz3Ya9MNIFDQ%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">当然,<span style="color: black;">亦</span><span style="color: black;">能够</span><span style="color: black;">经过</span>交换机<span style="color: black;">掌控</span>台<span style="color: black;">检测</span>运行结果(仅<span style="color: black;">表示</span>部分结果)。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/b1df721007164938b480bd82288d09ab~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=uVkdbqRj0LE7%2FLuerP12vT84zYs%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <h2 style="color: black; text-align: left; margin-bottom: 10px;">3 <span style="color: black;">运用</span>netaddr处理IP<span style="color: black;">位置</span>和网络</h2>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">管理和操作IP<span style="color: black;">位置</span>是网络工程师最重要的任务之一。Python<span style="color: black;">研发</span>人员<span style="color: black;">供给</span>了一个令人惊叹的库—— netaddr,它<span style="color: black;">能够</span>识别IP<span style="color: black;">位置</span>并对其进行处理。假设你<span style="color: black;">研发</span>了一个应用程序,其中<span style="color: black;">必须</span>获取129.183.1.55/21的网络<span style="color: black;">位置</span>和广播<span style="color: black;">位置</span>,<span style="color: black;">经过</span>模块内的内置<span style="color: black;">办法</span>network和broadcast<span style="color: black;">能够</span><span style="color: black;">容易</span>地获取到相应的<span style="color: black;">位置</span>。</p><span style="color: black;">net</span><span style="color: black;">.network</span>
    129<span style="color: black;">.183</span><span style="color: black;">.0</span>.
    <span style="color: black;">net</span><span style="color: black;">.broadcast</span>129<span style="color: black;">.183</span><span style="color: black;">.0</span><span style="color: black;">.0</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">netaddr支持<span style="color: black;">非常多</span>功能。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在第3层的<span style="color: black;">位置</span>中,netaddr支持下列功能。</p>识别IPv4和IPv6<span style="color: black;">位置</span>、子网、掩码和前缀。对IP网络进行迭代、切片、排序、汇总和<span style="color: black;">归类</span>。处理<span style="color: black;">各样</span>格式(CIDR、任意子网长度、nmap)。对IP<span style="color: black;">位置</span>和子网进行集合操作(联合、交叉等)。解析<span style="color: black;">各样</span><span style="color: black;">区别</span>的格式和符号。<span style="color: black;">查询</span>IANA IP块信息。生成DNS反向<span style="color: black;">查询</span>结果。检索超网和生成子网。<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在第2层的<span style="color: black;">位置</span>中,netaddr支持下列功能。</p>展示和操作Mac<span style="color: black;">位置</span>与EUI-64标识符。<span style="color: black;">查询</span>IEEE组织信息(OUI、IAB)。生成链路本地的IPv6<span style="color: black;">位置</span>。<h3 style="color: black; text-align: left; margin-bottom: 10px;">3.1 安装netaddr</h3>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">运用</span>pip安装netaddr模块,命令如下。</p><span style="color: black;">pip</span> install netaddr<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">安装完成之后打开PyCharm或Python<span style="color: black;">掌控</span>台并导入模块,验证模块<span style="color: black;">是不是</span>安装成功。<span style="color: black;">倘若</span><span style="color: black;">无</span><span style="color: black;">显现</span>错误信息,说明模块安装成功。</p>python
    &gt;&gt;&gt;<span style="color: black;">import</span> netaddr<h3 style="color: black; text-align: left; margin-bottom: 10px;">3.2 <span style="color: black;">运用</span>netaddr的<span style="color: black;">办法</span></h3>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">netaddr模块<span style="color: black;">供给</span>了两种重要的<span style="color: black;">办法</span>来定义IP<span style="color: black;">位置</span>并对其进行处理。<span style="color: black;">第1</span>种<span style="color: black;">办法</span>是IPAddress(),它用来定义<span style="color: black;">拥有</span>默认子网掩码的单个有类IP<span style="color: black;">位置</span>。第二种<span style="color: black;">办法</span>是IPNetwork(),它<span style="color: black;">运用</span>CIDR定义无类IP<span style="color: black;">位置</span>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">两种<span style="color: black;">办法</span>都将IP<span style="color: black;">位置</span><span style="color: black;">做为</span>字符串来处理,<span style="color: black;">按照</span>字符串返回IP<span style="color: black;">位置</span>或IP网络对象。返回的对象还<span style="color: black;">能够</span>继续执行许多<span style="color: black;">办法</span>,<span style="color: black;">例如</span>判断IP<span style="color: black;">位置</span>是单播<span style="color: black;">位置</span>、多播<span style="color: black;">位置</span>、环回<span style="color: black;">位置</span>、私有<span style="color: black;">位置</span>还是公有<span style="color: black;">位置</span>,以及<span style="color: black;">位置</span>有效还是无效<span style="color: black;">位置</span>。这些操作的结果是True或False。在Python的if<span style="color: black;">要求</span>中<span style="color: black;">能够</span>直接<span style="color: black;">运用</span>这些<span style="color: black;">办法</span>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">另一</span>,该模块支持<span style="color: black;">运用</span>==、<和>等比较运算符比较两个 IP <span style="color: black;">位置</span>,从而生成子网。它还<span style="color: black;">能够</span>检索一个给定IP<span style="color: black;">位置</span><span style="color: black;">或</span>子网术语的超网列表。<span style="color: black;">最后</span>,netaddr模块<span style="color: black;">能够</span>生成有效主机的一个完整列表(不<span style="color: black;">包含</span>网络IP<span style="color: black;">位置</span>和网络广播<span style="color: black;">位置</span>)。</p>#!/usr/bin/python
    __author__ = <span style="color: black;">"Bassim Aly"</span>
    __EMAIL__ = <span style="color: black;">"basim.alyy@gmail.com"</span>from netaddr import IPNetwork,IPAddress
    def check_ip_address(ipaddr):
    ip_attributes = []
    ipaddress = IPAddress(ipaddr)<span style="color: black;">if</span>ipaddress.is_private():
    ip_attributes.append(<span style="color: black;">"IP Address is Private"</span>)
    <span style="color: black;">else</span>:
    ip_attributes.append(<span style="color: black;">"IP Address is public"</span>)
    <span style="color: black;">if</span> ipaddress.is_unicast():
    ip_attributes.append(<span style="color: black;">"IP Address is unicast"</span>)
    elif ipaddress.is_multicast():
    ip_attributes.append(<span style="color: black;">"IP Address is multicast"</span>)
    <span style="color: black;">if</span> ipaddress.is_loopback():
    ip_attributes.append(<span style="color: black;">"IP Address is loopback"</span>)

    <span style="color: black;">return</span> <span style="color: black;">"\n"</span>.join(ip_attributes)

    def operate_on_ip_network(ipnet):

    net_attributes = []
    net = IPNetwork(ipnet)
    net_attributes.append(<span style="color: black;">"Network IP Address is "</span> + <span style="color: black;">str</span>(net.network) + <span style="color: black;">"
      and Netowrk Mask is "</span> + <span style="color: black;">str</span>(net.netmask))

    net_attributes.append(<span style="color: black;">"The Broadcast is "</span> + <span style="color: black;">str</span>(net.broadcast) )
    net_attributes.append(<span style="color: black;">"IP Version is "</span> + <span style="color: black;">str</span>(net.version) )
    net_attributes.append(<span style="color: black;">"Information known about this network is "</span> +
    <span style="color: black;">str</span>(net.info) )
    net_attributes.append(<span style="color: black;">"The IPv6 representation is "</span> + <span style="color: black;">str</span>(net.ipv6()))
    net_attributes.append(<span style="color: black;">"The Network size is "</span> + <span style="color: black;">str</span>(net.size))
    net_attributes.append(<span style="color: black;">"Generating a list of ip addresses inside the
      subnet"</span>)

    <span style="color: black;">for</span> ip <span style="color: black;">in</span> net:
    net_attributes.append(<span style="color: black;">"\t"</span> + <span style="color: black;">str</span>(ip))
    <span style="color: black;">return</span> <span style="color: black;">"\n"</span>.join(net_attributes)

    ipaddr = raw_input(<span style="color: black;">"Please Enter the IP Address: "</span>)
    print check_ip_address(ipaddr)

    ipnet = raw_input(<span style="color: black;">"Please Enter the IP Network: "</span>)
    print operate_on_ip_network(ipnet)<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在上面的脚本中,<span style="color: black;">首要</span><span style="color: black;">运用</span>raw_input()函数请求用户输入IP<span style="color: black;">位置</span>和IP网络,<span style="color: black;">而后</span>将输入的值<span style="color: black;">做为</span>参数传递给两个用户<span style="color: black;">办法</span>check_ip_address()和operate_on_ip_network()并调用它们。<span style="color: black;">第1</span>个函数check_ip_address()会<span style="color: black;">检测</span>输入的IP<span style="color: black;">位置</span>,<span style="color: black;">同期</span>尝试生成<span style="color: black;">相关</span>IP<span style="color: black;">位置</span>属性的报告(例如,IP<span style="color: black;">位置</span>是单播、多播、私有还是环回<span style="color: black;">位置</span>),并将输出返回给用户。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">第二个函数operate_on_ip_network()用来完成和网络<span style="color: black;">关联</span>的操作,即生成网络ID、掩码、广播、版本、网络上的已知信息、IPv6<span style="color: black;">位置</span>的<span style="color: black;">表示</span>方式,最后生成该子网内的所有IP<span style="color: black;">位置</span>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">重视</span>,net.info只能对公共IP<span style="color: black;">位置</span>生成可用信息,对私有IP<span style="color: black;">位置</span>不起<span style="color: black;">功效</span>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">一样</span>,在<span style="color: black;">运用</span>之前<span style="color: black;">必须</span>先从netaddr模块导入IP Network和IP Address。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">脚本运行结果如下所示。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/cb0f10ae5a25451d81710cbedc24d9c8~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=YvkF%2Fq8KRp91lkw7n0bLEccvd9U%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <h2 style="color: black; text-align: left; margin-bottom: 10px;">4 简单的用例</h2>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">随着网络变得越来越大,其中<span style="color: black;">包括</span><span style="color: black;">更加多</span>来自<span style="color: black;">各样</span><span style="color: black;">区别</span>供应商的设备,这就<span style="color: black;">必须</span>创建模块化的Python脚本来自动执行<span style="color: black;">各样</span>任务。接下来的几节将分析3个用例,这些用例<span style="color: black;">能够</span>从网络中收集<span style="color: black;">区别</span>信息,缩短<span style="color: black;">处理</span>问题所需的时间,<span style="color: black;">或</span><span style="color: black;">最少</span>将网络配置恢复到其上次已知的良好状态。<span style="color: black;">运用</span>自动化工作流来处理网络故障、修复网络环境,网络工程师能够更关心工作完成<span style="color: black;">状况</span>,<span style="color: black;">加强</span>业务水平。</p>
    <h3 style="color: black; text-align: left; margin-bottom: 10px;">4.1 备份设备配置</h3>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">备份设备配置<span style="color: black;">针对</span>任何一名网络工程师<span style="color: black;">来讲</span>都是最重要的任务之一。在这个用例中,<span style="color: black;">咱们</span>将<span style="color: black;">运用</span>netmiko库设计一个示例Python脚本。该脚本用来备份设备配置,它适用于<span style="color: black;">区别</span>的供应商和平台。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">为方便日后<span style="color: black;">拜访</span>或引用,<span style="color: black;">咱们</span>将<span style="color: black;">按照</span>设备IP<span style="color: black;">位置</span>格式化输出文件名,例如,SW1备份操作的输出文件<span style="color: black;">保留</span>在dev_10.10.88.111_.cfg中。</p>创建Python脚本<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">从定义交换机<span style="color: black;">起始</span>,<span style="color: black;">咱们</span><span style="color: black;">期盼</span>将其配置备份为文本文件(设备文件),用逗号分隔<span style="color: black;">拜访</span>设备的用户名、<span style="color: black;">秘码</span>等<span style="color: black;">仔细</span>信息。<span style="color: black;">这般</span>就<span style="color: black;">能够</span>在Python脚本中<span style="color: black;">运用</span>split()函数来获取这些数据,方便在ConnectHandler函数中<span style="color: black;">运用</span>这些数据。<span style="color: black;">另外</span>,还<span style="color: black;">能够</span>从Microsoft Excel工作表或任何数据库中<span style="color: black;">容易</span>导出该文件以及把该文件导入其中。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">文件结构如下。</p><span style="color: black;">&lt;<span style="color: black;">device_ipaddress</span>&gt;</span>,<span style="color: black;">&lt;<span style="color: black;">username</span>&gt;</span>,<span style="color: black;">&lt;<span style="color: black;">password</span>&gt;</span>,<span style="color: black;">&lt;<span style="color: black;">enable_password</span>&gt;</span>,<span style="color: black;">&lt;<span style="color: black;">vendor</span>&gt;</span>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/f8867f7a32d34bc8b9c22e26621508cc~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=lr4BQx68RflO%2BKBtIq9E7zkZYxw%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">创建Python脚本,<span style="color: black;">运用</span>with open子句在脚本中导入该文件。在导入的文件对象上<span style="color: black;">运用</span>readlines()<span style="color: black;">办法</span>将文件中的每一行<span style="color: black;">构成</span>列表,<span style="color: black;">而后</span>用for循环逐行遍历文件,用split()函数获取每一行中用逗号隔开的设备信息,并将它们赋予相应的变量。</p>from netmiko import ConnectHandler
    from datetime import datetime

    with
    open(<span style="color: black;">"/media/bassim/DATA/GoogleDrive/Packt/EnterpriseAutomationProject/Chap
      ter5_Using_Python_to_manage_network_devices/UC1_devices.txt"</span>) as
    <span style="color: black;">devices_file:</span>devices = devices_file.readlines()
    for line in devices:
    line = line.strip(<span style="color: black;">"\n"</span>)
    ipaddr = line.split(<span style="color: black;">","</span>)
    username = line.split(<span style="color: black;">","</span>)
    password = line.split(<span style="color: black;">","</span>)
    enable_password = line.split(<span style="color: black;">","</span>)

    vendor = line.split(<span style="color: black;">","</span>)

    if vendor.lower() == <span style="color: black;">"cisco"</span>:
    device_type = <span style="color: black;">"cisco_ios"</span>
    backup_command = <span style="color: black;">"show running-config"</span>elif vendor.lower() ==<span style="color: black;">"juniper"</span>:
    device_type = <span style="color: black;">"juniper"</span>
    backup_command = <span style="color: black;">"show configuration | display set"</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">因为</span><span style="color: black;">咱们</span>的<span style="color: black;">目的</span>是创建模块化的、支持多种设备供应商的脚本,<span style="color: black;">因此呢</span>在if子句中<span style="color: black;">必须</span><span style="color: black;">检测</span>设备供应商,并为该设备分配正确的device_type和backup_command。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">接下来,<span style="color: black;">创立</span>与设备的SSH连接,<span style="color: black;">运用</span>netmiko模块中的.send_command()<span style="color: black;">办法</span>执行备份命令。</p><span style="color: black;">print</span> str(datetime.now()) + <span style="color: black;">" Connecting to device {}"</span> .<span style="color: black;">format</span>(ipaddr)

    net_connect = ConnectHandler(device_type=device_type,
    ip=ipaddr,
    username=username,
    password=password,
    secret=enable_password)
    net_connect.enable()
    running_config = net_connect.send_command(backup_command)<span style="color: black;">print</span> str(datetime.now()) + <span style="color: black;">" Saving config from device {}"</span> .<span style="color: black;">format</span>(ipaddr)

    f =<span style="color: black;">open</span>( <span style="color: black;">"dev_"</span> + ipaddr + <span style="color: black;">"_.cfg"</span>, <span style="color: black;">"w"</span>)
    f.<span style="color: black;">write</span>(running_config)
    f.<span style="color: black;">close</span>()
    <span style="color: black;">print</span> <span style="color: black;">"=============================================="</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在最后的几行中,以写入方式打开一个文件(文件不存在时将自动创建),文件名中<span style="color: black;">包括</span>了前面从设备文件中读取的ipaddr变量。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">脚本运行结果如下。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/97d1e73659a542c5957af0a9ee8ef076~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=86A6L26qVYQbtUNY1nsppX3O%2BX0%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">必须</span><span style="color: black;">重视</span>的是,备份的配置文件存储在项目的主目录中,文件名<span style="color: black;">叫作</span><span style="color: black;">包括</span><span style="color: black;">每一个</span>设备的IP<span style="color: black;">位置</span>(见下图)。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p9-sign.toutiaoimg.com/pgc-image/2f1c993646124d3c9526accbff8ea61d~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=jtXbs9u5iZSCXNCo0GAI8t0iD%2F8%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">运用</span>Linux服务器上的cron任务,或Windows服务器上的计划任务,可让服务器在指<span style="color: black;">按时</span>间运行上面的Python脚本。例如,<span style="color: black;">每日</span>凌晨运行一次,将配置信息存储在latest目录中,以方便运维团队<span style="color: black;">运用</span>。</p>
    <h3 style="color: black; text-align: left; margin-bottom: 10px;">4.2 创建<span style="color: black;">拜访</span>终端</h3>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在Python或其他编程活动中,你<span style="color: black;">便是</span>自己的设备供应商。为了满足自己的需求,你<span style="color: black;">能够</span>创建任何<span style="color: black;">爱好</span>的代码组合和程序。在第二个例子中<span style="color: black;">咱们</span>创建自己的终端(terminal),<span style="color: black;">经过</span>telnetlib<span style="color: black;">拜访</span>路由器。只<span style="color: black;">必须</span>在终端写几个单词,就会在网络设备中执行<span style="color: black;">非常多</span>命令并返回输出结果。输出结果将会<span style="color: black;">表示</span>在标准输出或<span style="color: black;">保留</span>在文件中。</p>#!/usr/bin/python
    __author__ = <span style="color: black;">"Bassim Aly"</span>
    __EMAIL__ = <span style="color: black;">"basim.alyy@gmail.com"</span>import telnetlib

    connection = telnetlib.Telnet(host=<span style="color: black;">"10.10.88.110"</span>)
    connection.read_until(<span style="color: black;">"Username:"</span>)
    connection.<span style="color: black;">write</span>(<span style="color: black;">"admin"</span> + <span style="color: black;">"\n"</span>)
    connection.read_until(<span style="color: black;">"Password:"</span>)
    connection.<span style="color: black;">write</span>(<span style="color: black;">"access123"</span> + <span style="color: black;">"\n"</span>)
    connection.read_until(<span style="color: black;">"&gt;"</span>)
    connection.<span style="color: black;">write</span>(<span style="color: black;">"en"</span> + <span style="color: black;">"\n"</span>)
    connection.read_until(<span style="color: black;">"Password:"</span>)
    connection.<span style="color: black;">write</span>(<span style="color: black;">"access123"</span> + <span style="color: black;">"\n"</span>)
    connection.read_until(<span style="color: black;">"#"</span>)
    connection.<span style="color: black;">write</span>(<span style="color: black;">"terminal length 0"</span> + <span style="color: black;">"\n"</span>)
    connection.read_until(<span style="color: black;">"#"</span>)
    <span style="color: black;">while</span> True:
    command = raw_input(<span style="color: black;">"#:"</span>)
    <span style="color: black;">if</span> <span style="color: black;">"health"</span> <span style="color: black;">in</span> command.<span style="color: black;">lower</span>():
    commands = [<span style="color: black;">"show ip int b"</span>,
    <span style="color: black;">"show ip route"</span>,
    <span style="color: black;">"show clock"</span>,
    <span style="color: black;">"show banner motd"</span>
    ]

    elif <span style="color: black;">"discover"</span> <span style="color: black;">in</span> command.<span style="color: black;">lower</span>():
    commands = [<span style="color: black;">"show arp"</span>,
    <span style="color: black;">"show version | i uptime"</span>,
    <span style="color: black;">"show inventory"</span>,
    ]
    <span style="color: black;">else</span>:
    commands = <span style="color: black;">for</span> cmd <span style="color: black;">in</span> commands:
    connection.<span style="color: black;">write</span>(cmd + <span style="color: black;">"\n"</span>)
    <span style="color: black;">output</span> = connection.read_until(<span style="color: black;">"#"</span>)
    <span style="color: black;">print</span> <span style="color: black;">output</span>
    <span style="color: black;">print</span> <span style="color: black;">"==================="</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">首要</span>,<span style="color: black;">创立</span>到路由器的Telnet连接并输入相应的用户信息,<span style="color: black;">始终</span>到打开特权(enable)模式。<span style="color: black;">而后</span>,创建一个始终为true的无限while循环,<span style="color: black;">运用</span>内置的raw_input()函数<span style="color: black;">捉捕</span>用户输入的命令。脚本<span style="color: black;">捕捉</span>到用户输入之后,在网络设备上执行这些命令。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">倘若</span>用户输入关键字health或discover,终端将自动执行一系列命令以反映期望的操作。这些关键字在排除网络故障时非常有用,<span style="color: black;">能够</span><span style="color: black;">按照</span>常用的操作自由扩展它们。想象一下,在<span style="color: black;">必须</span><span style="color: black;">处理</span>两个路由器之间的开放式最短路径优先(Open Shortest Path First,OSPF)邻居问题时,只要打开自己的Python终端脚本(这个脚本中<span style="color: black;">已然</span>写好了几个排除故障常用的命令),并将这些命令打包到诸如tshoot_ospf之类的if<span style="color: black;">要求</span>之后。一旦脚本看到这个关键字,它就会执行这些命令,输出OSPF邻居状态、MTU的接口、OSPF的广播网络等,简化定位问题的过程。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">经过</span>在提示符中输入health尝试脚本中的<span style="color: black;">第1</span>条命令。脚本输出结果如下。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/a528acda8bd64d14ae99198629d3034e~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=zCuuEhywM%2BVCUSKCRmiTv2x0O8s%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">能够</span>看到,脚本将返回在设备上执行多条命令后的结果。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">接着试一下第二个命令discover。脚本输出结果如下。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/ad792cce9caa45dc9f47d36a1f9cea4f~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=MIJxvsJUiimaIvrJ9rhfZ2FeEQA%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">这次脚本返回discover命令的输出。在后面的章节中,<span style="color: black;">咱们</span>将会解析返回的输出结果并从中提取有用的信息。</p>
    <h3 style="color: black; text-align: left; margin-bottom: 10px;">4.3 从Excel工作表中读取数据</h3>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">网络和IT工程师始终<span style="color: black;">运用</span>Excel工作表来存储<span style="color: black;">基本</span><span style="color: black;">设备</span>的<span style="color: black;">关联</span>信息,如IP<span style="color: black;">位置</span>、设备供应商和登录凭证。Python支持从Excel工作表中读取数据并对其进行处理,以便<span style="color: black;">咱们</span>在脚本中<span style="color: black;">运用</span>数据。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在这个用例中,<span style="color: black;">咱们</span>将<span style="color: black;">运用</span><strong style="color: blue;">Excel Read(xlrd)</strong>模块读取UC3_devices.xlsx文件。该文件<span style="color: black;">保留</span>了<span style="color: black;">基本</span><span style="color: black;">设备</span>的主机名、IP<span style="color: black;">位置</span>、用户名、普通<span style="color: black;">秘码</span>、特权模式下的<span style="color: black;">秘码</span>和供应商名<span style="color: black;">叫作</span>。<span style="color: black;">而后</span>将读到的数据用作netmiko模块的输入。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Excel工作表中的内容如下图所示。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/278f548a4b3e44cfa8263049bc11f59f~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=b8Ky1VR%2Bs%2Boi2Pox2Uq5Dr33hHY%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">首要</span>,用pip安装xlrd模块,<span style="color: black;">由于</span><span style="color: black;">必须</span>用它来读取Microsoft Excel工作表。</p><span style="color: black;">pip</span> install xlrd<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">xlrd模块能够读取Excel工作表并将行和列转换为矩阵。<span style="color: black;">例如</span>,row<span style="color: black;">表率</span><span style="color: black;">第1</span>行<span style="color: black;">第1</span>列的单元格,右边紧接着它的单元格是row(见下图),以此类推。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/de5ea723568148ce9cc2c83c6bb99e5d~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=XWN%2BboN6YRWygRFRvyBbWk15pGk%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">xlrd在读取工作表时,每次读取一行,<span style="color: black;">同期</span>特殊计数器nrows(行数)自动加1。<span style="color: black;">一样</span>,每次读取一列,ncols(列数)自动加1,<span style="color: black;">这般</span><span style="color: black;">咱们</span>就能够<span style="color: black;">经过</span>这两个参数<span style="color: black;">晓得</span>矩阵的<span style="color: black;">体积</span>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">而后</span>,在xlrd的open_workbook()函数中输入文件路径,并用sheet_by_index()或sheet_by_name()函数<span style="color: black;">拜访</span>工作表。在本例中,数据存储在<span style="color: black;">第1</span>个工作表(index = 0)中,工作表文件存储在以章为名的文件夹下。接着,遍历工作表的每一行,<span style="color: black;">或</span><span style="color: black;">运用</span>row()函数来<span style="color: black;">拜访</span>指定行。返回的输出结果是一个列表,<span style="color: black;">运用</span>索引<span style="color: black;">能够</span><span style="color: black;">拜访</span>列表中的元素。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Python脚本如下。</p>__author__ =<span style="color: black;">"Bassim Aly"</span>
    __EMAIL__ = <span style="color: black;">"basim.alyy@gmail.com"</span>

    <span style="color: black;">from</span> netmiko <span style="color: black;">import</span> ConnectHandler
    <span style="color: black;">from</span> netmiko.ssh_exception <span style="color: black;">import</span>AuthenticationException,
    NetMikoTimeoutException<span style="color: black;">import</span> xlrd
    <span style="color: black;">from</span> pprint <span style="color: black;">import</span> pprint

    workbook =
    xlrd.open_workbook(r<span style="color: black;">"/media/bassim/DATA/GoogleDrive/Packt/EnterpriseAutomat
      ionProject/Chapter4_Using_Python_to_manage_network_devices/UC3_devices.xlsx
      "</span>)

    sheet = workbook.sheet_by_index(<span style="color: black;">0</span>)

    <span style="color: black;">for</span> index <span style="color: black;">in</span> range(<span style="color: black;">1</span>, sheet.nrows):
    hostname = sheet.row(index)[<span style="color: black;">0</span>].value
    ipaddr = sheet.row(index)[<span style="color: black;">1</span>].value
    username = sheet.row(index)[<span style="color: black;">2</span>].value
    password = sheet.row(index)[<span style="color: black;">3</span>].value
    enable_password = sheet.row(index)[<span style="color: black;">4</span>].value
    vendor = sheet.row(index)[<span style="color: black;">5</span>].value

    device = {
    <span style="color: black;">device_type</span>: vendor,<span style="color: black;">ip</span>: ipaddr,
    <span style="color: black;">username</span>: username,
    <span style="color: black;">password</span>: password,
    <span style="color: black;">secret</span>: enable_password,

    }
    <span style="color: black;"># pprint(device)</span>

    <span style="color: black;">print</span> <span style="color: black;">"########## Connecting to Device {0}
      ############"</span>.format(device[<span style="color: black;">ip</span>])
    try:
    net_connect = ConnectHandler(**device)
    net_connect.enable()

    <span style="color: black;">print</span> <span style="color: black;">"***** show ip configuration of Device *****"</span>
    output = net_connect.send_command(<span style="color: black;">"show ip int b"</span>)
    <span style="color: black;">print</span> output

    net_connect.disconnect()

    except NetMikoTimeoutException:
    <span style="color: black;">print</span> <span style="color: black;">"=======SOMETHING WRONG HAPPEN WITH
      {0}======="</span>.format(device[<span style="color: black;">ip</span>])

    except AuthenticationException:
    <span style="color: black;">print</span> <span style="color: black;">"=======Authentication Failed with
      {0}======="</span>.format(device[<span style="color: black;">ip</span>])
    except Exception <span style="color: black;">as</span> unknown_error:
    <span style="color: black;">print</span> <span style="color: black;">"=======SOMETHING UNKNOWN HAPPEN WITH {0}======="</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">4.4 其他用例</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">运用</span>netmiko<span style="color: black;">能够</span>实现<span style="color: black;">非常多</span>网络自动化用例。例如,在升级<span style="color: black;">时期</span>从远程设备上传/下载文件,利用Jinja2模板加载配置,<span style="color: black;">拜访</span>终端服务器,<span style="color: black;">拜访</span>终端设备等。要<span style="color: black;">认识</span><span style="color: black;">更加多</span>用例,请参见GitHub官网(见下图)。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p26-sign.toutiaoimg.com/pgc-image/743cc578276c4a41ade47aaf26b3794e~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=TBbjaqMW%2BAqnXeSC0NIOI4%2Fb5UU%3D" style="width: 50%; margin-bottom: 20px;"></div>
    <h2 style="color: black; text-align: left; margin-bottom: 10px;">5 小结</h2>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在本章中,<span style="color: black;">咱们</span><span style="color: black;">起始</span><span style="color: black;">运用</span>Python进入网络自动化世界。本章讨论了Python中的<span style="color: black;">有些</span>工具,<span style="color: black;">经过</span>Telnet和SSH<span style="color: black;">创立</span>到远程节点的连接,并在远程设备上执行命令。<span style="color: black;">另外</span>,本章还讲述了<span style="color: black;">怎样</span>在netaddr模块的<span style="color: black;">帮忙</span>下处理IP<span style="color: black;">位置</span>和网络子网。最后<span style="color: black;">经过</span>两个<span style="color: black;">实质</span>用例巩固了这些知识。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">下一章将介绍<span style="color: black;">怎样</span>处理返回的输出结果,从中提取有用的信息。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">本文摘自:<strong style="color: blue;">《Python自动化运维实战》</strong></p>
    <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/e54b8ed9faf54ac18b0e0ac3a2a12c14~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1723900449&amp;x-signature=doQ%2F4%2FfmU6ADR8lvJwj5FQ5pWRk%3D" style="width: 50%; margin-bottom: 20px;"></div>Python自动化运维实战:<span style="color: black;">运用</span>Python管理网络设备运维工程师教程书籍,自动化运维实践<span style="color: black;">经过</span>Python模块、库与工具自动配置和管理<span style="color: black;">海量</span>服务器的讲解,<span style="color: black;">加强</span>运维的效率<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">《Python自动化运维实战》介绍了<span style="color: black;">怎样</span><span style="color: black;">经过</span>Python来自动完成服务器的配置与管理,自动完成系统的管理任务(如用户管理、数据库管理和进程管理),以及完成这些工作所需的模块、库和工具。<span style="color: black;">另外</span>,本书还讲述了<span style="color: black;">怎样</span>使用Python脚本自动执行测试,<span style="color: black;">怎样</span><span style="color: black;">经过</span>Python在云<span style="color: black;">基本</span><span style="color: black;">设备</span>和虚拟机上自动执行任务,<span style="color: black;">怎样</span><span style="color: black;">运用</span>基于Python的安全工具自动完成与安全<span style="color: black;">关联</span>的任务。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">本书适合运维人员和<span style="color: black;">研发</span>人员阅读,<span style="color: black;">亦</span>可<span style="color: black;">做为</span><span style="color: black;">关联</span>专业人士的参考书。</p>
    <div style="color: black; text-align: left; margin-bottom: 10px;">
      <div style="color: black; text-align: left; margin-bottom: 10px;">
            <div style="color: black; text-align: left; margin-bottom: 10px;">
                <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="http://p1.toutiaoimg.com/large/pgc-image/15554965135136878c100cb" style="width: 50%; margin-bottom: 20px;">
                  <div style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">专栏</span></div>
                </div>
                <div style="color: black; text-align: left; margin-bottom: 10px;">
                  <div style="color: black; text-align: left; margin-bottom: 10px;">零<span style="color: black;">基本</span>学编程Python 3</div>
                  <div style="color: black; text-align: left; margin-bottom: 10px;">作者:异步社区</div>
                  <div style="color: black; text-align: left; margin-bottom: 10px;">
                        <div style="color: black; text-align: left; margin-bottom: 10px;">29币</div>
                        <div style="color: black; text-align: left; margin-bottom: 10px;">62人已购</div>
                  </div>
                  <div style="color: black; text-align: left; margin-bottom: 10px;">查看</div>
                </div>
            </div>
      </div>
    </div>




流星的美 发表于 2024-8-22 04:02:03

感谢你的精彩评论,为我的思绪打开了新的窗口。

4lqedz 发表于 2024-9-27 11:11:22

i免费外链发布平台 http://www.fok120.com/

4lqedz 发表于 2024-10-25 18:45:05

网站建设seio论坛http://www.fok120.com/

b1gc8v 发表于 2024-10-29 06:41:05

你的话语如春风拂面,温暖了我的心房,真的很感谢。
页: [1]
查看完整版本: Python自动化运维实战:运用Python管理网络设备