此刻,咱们已然晓得怎样在区别的操作系统中运用和安装Python以及怎样运用EVE-NG搭建网络拓扑。在本章中,咱们将学习怎样运用日前常用的网络自动化库自动完成各样网络任务。Python能够在区别的网络层上与网络设备进行交互。
首要,Python能够经过套接字编程和socket模块操作底层网络,从而为Python所在的操作系统和网络设备之间搭建一个低层次的网络接口。另外,Python模块还能够经过Telnet、SSH和API与网络设备进行更高级别的交互。本章将深入探讨怎样在Python中运用Telnet与SSH模块在远程设备上创立连接和执行命令。
1 技术需求
应检测是不是正确安装了下列工具并保准它们能够正常运用: Python 2.7.1x;PyCharm社区版或专业版;EVE-NG,网络仿真器的安装和配置请参阅第3章。本章中显现的所有脚本请参见GitHub网站。
1.1 Python和SSH
SSH和Telnet的区别之处在于客户端与服务器之间交换数据的通道不同样。SSH运用的是安全链路,在客户端和设备之间创建了一个运用区别的安全机制进行加密的隧道,通信内容很难被解密。因此呢在必须保准网络安全的时候,网络工程师会首要选取运用SSH协议。
Paramiko库遵循SSH2协议,支持身份验证,密钥处理(DSA、RSA、ECDSA和ED25519),以及其他SSH功能(如proxy命令和SFTP)。在Python中当必须运用SSH连接到网络设备时一般运用这个库。
1.2 Paramiko模块
Paramiko是Python中应用最广的SSH模块。模块本身运用Python语言编写和研发,仅有像crypto这般的核心函数才会用到C语言。从其GitHub官方链接上能够看到代码的贡献者和模块历史等许多信息。 1.安装模块打开Windows cmd或Linux shell,运行下面的命令,从PyPI下载最新的Paramiko模块。如下图所示,同期,该命令会自动下载其他依赖包(如cyrptography、ipaddress和six),并将它们安装到计算机上。 pip install paramiko
在命令行中输入Python,而后导入Paramiko模块,验证是不是安装成功。如下图所示,正确安装之后,能够成功导入模块。亦便是说,命令行上不会显现任何错误提示。
2.用SSH连接网络设备如前所述,要运用Paramiko模块,首要必须在Python脚本中导入它,而后经过继承SSHClient()来创建SSH客户端。而后,设置Paramiko的参数,使其能够自动添加任意未知的主机密钥并信任与服务器之间的连接。接下来,将远程主机的信息(IP位置、用户名和秘码等)传递给connect函数。 #!/usr/bin/python
__author__ = "Bassim Aly"
__EMAIL__ = "basim.alyy@gmail.com"
import paramiko
importtime
Channel = paramiko.SSHClient()
Channel.set_missing_host_key_policy(paramiko.AutoAddPolicy())
Channel.connect(hostname="10.10.88.112", username=admin,
password=access123, look_for_keys=False,allow_agent=False)
shell = Channel.invoke_shell()AutoAddPolicy()是一种策略,能够做为函数 set_missing_host_key_policy()的输入参数。在虚拟实验室环境中举荐运用这种策略,但在生产环境中应当运用更加严格的策略,如WarningPolicy()或RejectPolicy()。
最后,invoke_shell()将起步一个连接到SSH服务器的交互式shell会话。在调用该函数时能够传入有些其他参数(如终端类型、宽度、高度等)。
Paramiko的连接参数如下。 Look_For_Keys:默认为True,强制Paramiko运用密钥进行身份验证。亦便是说,用户必须运用私钥和公钥对网络设备进行身份验证。在这儿运用秘码验证,因此呢将该参数设置为False。allow_agent:暗示是不是准许连接到SSH代理,默认为True。在用密钥验证时可能必须运用这个选项。因为这儿运用的是用户名/秘码,因此呢禁用它。最后一步,把各样命令(如show ip int b和show arp)发送到设备终端,并将返回结果输出到Python窗口中。 shell.send("enable\n")
shell.send("access123\n")
shell.send("terminal length 0\n")
shell.send("show ip int b\n")
shell.send("show arp \n")
time.sleep(2)
print shell.recv(5000)
Channel.close()脚本运行结果如下图所示。
倘若必须在远程设备上执行耗时很长的命令,就要强制Python等待一段时间,直到设备生成输出并将结果返回给Python,因此呢最好运用time.sleep()。否则,Python可能得不到正确的输出结果。
1.3 netmiko模块
netmiko是Paramiko的加强版本,专门面向网络设备。虽然Paramiko能够处理与设备的SSH连接并判断设备类型是服务器、打印机还是网络设备,但netmiko在设计时针对网络设备做了优化,能够更有效地处理SSH连接。netmiko还支持各样区别的设备厂商和平台。
netmiko亦是对Paramiko的封装,它运用许多其他加强功能扩展了Paramiko,例如运用启用的秘码直接拜访所支持的设备,从文件读取配置并将推送到设备,在登录时期禁用分页表示,以及默认在每条命令后面加上回车符“\n”。 1.支持的设备商netmiko支持许多供应商的设备,并定时在支持列表中添加新的供应商。netmiko支持的供应商列表分为定时测试类、有限测试类和实验类。在该模块的GitHub页面上能够找到这个列表。
定时测试类中支持的供应商如下图所示。
有限测试类中支持的供应商如下图所示。
实验类中支持的供应商如下图所示。
2.安装和验证安装netmiko非常简单。打开Windows命令行窗口或Linux shell,执行下面的命令就能够从PyPI获取最新版本的netmiko包(见下图)。 pip install netmiko
而后,在Python shell中导入netmiko,验证模块是不是正确地安装到Python site-packages中。 $python
>>>import netmiko3.运用netmiko创立SSH连接此刻该起始运用netmiko了,让咱们来瞧瞧它强大的SSH功能。首要连接到网络设备并在上面执行命令。默认状况下,netmiko在创立会话(session)的过程中会在后台处理许多操作(如添加未知的SSH密钥主机,设置终端类型、宽度和高度),在必须的时候还能够进入特权(enable)模式,而后经过运行供应商供给的命令来禁用分页。
首要,以字典格式定义设备并供给下列5个必需的关键信息。 R1 = (
device type : cisco ios,
ip: 10.10.88.110,
username: admin,
password: access123,
secret: access123,
}第1个参数是device_type,为了执行正确的命令,必须运用这个参数来定义平台供应商。而后,必须SSH的IP位置。倘若已然运用DNS解析了IP位置,该参数可能是主机名;否则,该参数是IP位置。接下来,供给username、password以及以secret参数传递的特权模式的秘码。重视,能够使用getpass()模块隐匿秘码,并且仅在脚本执行时期提示它们。
虽然变量中的密钥序列不重要,然则为了使netmiko能够正确解析字典并起始和设备创立连接,密钥的名叫作应该和之前示例中供给的密钥完全同样。
接下来,从netmiko模块导入ConnectHandler函数,并供给定义的字典来起始创立连接。因为所有的设备是经过特权模式的秘码配置的,因此必须为创建的连接供给.enable(),以在特权模式下拜访。运用.send_command()在路由器终端上执行命令,.send_command()将会执行命令并经过变量的值表示设备的输出。 from netmiko importConnectHandler
connection = ConnectHandler(**R1)
connection.enable()
output = connection.send_command("show ip int b")
print output脚本输出结果如下。
重视,这儿看到的输出结果去掉了命令行中的命令回显和设备提示符。默认状况下,netmiko会替换设备的返回结果,使输出更加整洁,替换过程经过正则表达式完成,这部分会在下一章中间商绍。
倘若不想运用这种方式,而是期盼看到命令提示符,并在返回结果的后面执行命令,能够在.send_command()函数中加上以下参数。 output= connection.send_command("show ip int
b",strip_command=False,strip_prompt=False)strip_command=False和strip_prompt=False告诉netmiko保存而不是替换命令行回显和提示符。默认情况下它为True,能够按照必须进行设置。
4.运用netmiko配置设备netmiko能够经过SSH配置远程设备,经过.config办法进入设备的配置模式,而后根据list格式中的信息(配置列表)配置设备。配置列表能够直接写在Python脚本中,亦能够从文件中读取,而后用readlines()办法转换为列表。 from netmiko import ConnectHandler
SW2 = {
device_type: cisco_ios,
ip: 10.10.88.112,
username: admin,
password: access123,
secret: access123,
}
core_sw_config = ["int range gig0/1 - 2","switchport trunk encapsulation
dot1q",
"switchport mode trunk","switchport trunk allowed vlan
1,2"]
print "########## Connecting to Device {0} ############".format(SW2[ip])
net_connect = ConnectHandler(**SW2)
net_connect.enable()
print "***** Sending Configuration to Device *****"
net_connect.send_config_set(core_sw_config)上面的脚本以另一一种形式连接到SW2并进入特权模式。但这次运用的是另一个netmiko办法——send_config_set(),该办法必须运用列表形式的配置文件,同期进入设备的配置模式并按照列表对设备进行配置。这儿测试了一个简单的配置,即修改gig0/1和gig0/2,并将这两个端口配成trunk模式。在设备上执行show run命令时,倘若命令执行成功,会显现类似下面的输出。
5.netmiko中的反常处理在设计Python脚本时,咱们可能会假设设备已起步并运行,并且用户已供给了正确的登录信息,但实质状况并非总是如此。有时Python和远程设备之间的网络连接可能存在问题,或用户输入了错误的登录信息。倘若出现这种状况,Python一般会抛出反常并退出,但这种处理方法显然不足完美。
netmiko中的反常处理模块netmiko.ssh_exception供给的有些反常处理类能够处理上面所说的哪些状况。第1个类AuthenticationException能够捕捉远程设备中的身份验证错误。第二个类NetMikoTimeoutException能够捕捉netmiko和设备之间的超时或任何连接问题。下面的例子中运用try-except子句包括了ConnectHandler()办法,用来捕捉超时和身份验证反常。 from netmiko import ConnectHandler
from netmiko.ssh_exception importAuthenticationException,
NetMikoTimeoutException
device = {device_type: cisco_ios,
ip: 10.10.88.112,
username: admin,
password: access123,
secret: access123,
}
print "########## Connecting to Device {0}
############".format(device[ip])
try:
net_connect = ConnectHandler(**device)
net_connect.enable()
print "***** show ip configuration of Device *****"
output = net_connect.send_command("show ip int b")
printoutput
net_connect.disconnect()
except NetMikoTimeoutException:print "=========== SOMETHING WRONG HAPPEN WITH {0}
============".format(device[ip])
except AuthenticationException:
print "========= Authentication Failed with {0}
============".format(device[ip])
except Exception as unknown_error:
print "============ SOMETHING UNKNOWN HAPPEN WITH {0} ============"
6.设备自动发掘
netmiko供给了一种能够“猜测”设备类型和发掘设备的机制。经过组合运用SNMP发掘OIDS和在远程掌控台上执行多个show命令这两种方式,按照输出字符串检测路由器的操作系统和类型。而后,netmiko将相应的驱动程序加载到ConnectHandler()类中。 #!/usr/local/bin/python
__author__ = "Bassim Aly"
__EMAIL__ = "basim.alyy@gmail.com"
from netmiko import SSHDetect, Netmiko
device = {
device_type: autodetect,
host: 10.10.88.110,
username: admin,
password: "access123",
}
detect_device = SSHDetect(**device)
device_type = detect_device.autodetect()print(device_type)
print(detect_device.potential_matches)
device[device_type] = device_type
connection = Netmiko(**device)在上面的脚本中,应重视以下几点。
首要,设备字典中的device_type等于autodetect,亦便是告诉netmiko在检测到设备类型之前不要加载驱动程序。
而后,运用netmiko的SSHDetect()类发掘设备。它运用SSH连接到设备,并执行有些命令以找出操作系统的类型,结果以字典形式返回。
接着,运用autodetect()函数将匹配度最高的结果赋给device_type变量。
接下来,输出potential_matches,查看字典内的所有返回结果。
最后,能够更新设备字典并为其分配新的device_type。
2 在Python中运用Telnet协议
Telnet是TCP/IP协议栈中最早可用的协议之一,主要用来在服务器和客户端之间创立连接、交换数据。服务器端监听TCP端口23,等待客户端的连接请求。
在下面的例子中,咱们将创建一个Python脚本做为Telnet客户端,拓扑中的其他路由器和交换机则做为Telnet服务器。Python原生的telnetlib库已然支持Telnet,因此不必须另一安装。
客户端对象能够经过telnetlib模块中的Telnet()类实例化创建。经过这个对象,咱们能够运用telnetlib中的两个重要函数——read_until()(用于读取输出结果)和write()(用于向远程设备写入内容)。这两个函数用来和Telnet连接交互,从Telnet连接读取或向Telnet连接写入数据。
还有一点非常关键,运用read_until()读取Telnet连接的内容之后缓冲区会被清空,没法再次读取。因此呢,倘若在后面的处理中还会用到之前读取的重要数据,必须在脚本里将其另存为变量。
Telnet数据以明文形式发送,因此呢经过“中间人攻击”能够捕捉并查看到Telnet数据,如用户信息和秘码。即便如此,有些服务供给商和企业仍然在运用它,只是她们会集成VPN和radius/tacacs协议,以供给轻量级和安全的拜访方式。
让咱们一步步分析这个脚本。
(1)在Python脚本中导入telnetlib模块,在变量中定义用户名和秘码。代码如下。 import telnetlib
username ="admin"
password = "access123"
enable_password = "access123"
(2)定义一个变量,用来和远程主机创立连接。重视,只必须供给远程主机的IP位置,不消在连接创立过程中供给用户名或秘码。 cnx = telnetlib.Telnet(host="10.10.88.110") #here were telnet to
Gateway(3)经过读取Telnet连接返回的输出并搜索“Username:”关键字来供给Telnet连接的用户名。而后写入管理员用户名。倘若必须,用一样的办法输入Telnet秘码。 cnx.read_until("Username:")
cnx.write(username + "\n")
cnx.read_until("Password:")
cnx.write(password + "\n")
cnx.read_until(">")
cnx.write("en" + "\n")
cnx.read_until("Password:")
cnx.write(enable_password + "\n")Telnet连接建好之后,在脚本中加上掌控台提示符非常重要;否则,连接将陷入死循环。接着Python脚本就会超时并显现错误。
(4)向Telnet连接写入show ip interface brief命令并起始读取返回内容,直到显现路由器提示符(#)为止。经过以下命令能够得到路由器的接口配置。 cnx.read_until("#")
cnx.write("show ip int b" + "\n")
output = cnx.read_until("#")
print output
完整的脚本如下所示。
脚本运行结果如下所示。
重视,在输出中包括了执行的命令show ip int b,并且在stdout中输出和返回了路由器提示符”R1#”。能够运用内置的字符串函数(如replace())从输出中清除它们。 cleaned_output = output.replace("show ip int b","").replace("R1#","")
print cleaned_output
你可能已然重视到脚本中运用了秘码并将秘码以明文形式写下来,这般做显然是不安全的。同期,在Python脚本中运用硬编码亦不是好习惯。在下一节中,咱们将学习怎样隐匿秘码并设计一种机制,从而在脚本运行时需求用户输入秘码。
另外,倘若要执行哪些输出结果可能跨越多个页面的命令(如show running config),则必须在连接到设备之后和发送命令之前,先经过发送termindl length 0来禁用分页。
运用telnetlib推送配置
在上一节中,咱们经过执行show ip int brief简单介绍了telnetlib的操作过程。此刻咱们要用telnetlib将VLAN配置推送到实验室网络拓扑中的4台交换机。运用Python的range()函数创建一个VLAN列表,遍历列表将VLAN ID推送到当前交换机。重视,咱们将交换机的IP位置放到了另一个列表中,运用外边for循环来遍历这个列表。同期运用内置模块getpass隐匿掌控台中的秘码,在脚本运行时提示用户输入秘码。 #!/usr/bin/python
import telnetlib
import getpass
import time
switch_ips = ["10.10.88.111", "10.10.88.112", "10.10.88.113",
"10.10.88.114"]
username = raw_input("Please Enter your username:")
password = getpass.getpass("Please Enter your Password:")
enable_password = getpass.getpass("Please Enter your Enable Password:")
for sw_ip in switch_ips:
print "\n#################### Working on Device " + sw_ip + "
####################"
connection = telnetlib.Telnet(host=sw_ip.strip())
connection.read_until("Username:")
connection.write(username + "\n")
connection.read_until("Password:")
connection.write(password + "\n")
connection.read_until(">")
connection.write("enable" + "\n")
connection.read_until("Password:")
connection.write(enable_password + "\n")
connection.read_until("#")
connection.write("config terminal" + "\n") # now im in config modevlans = range(300,400)
for vlan_id in vlans:
print"\n********* Adding VLAN " + str(vlan_id) + "**********"
connection.read_until("#")
connection.write("vlan " + str(vlan_id) + "\n")
time.sleep(1)
connection.write("exit" + "\n")
connection.read_until("#")
connection.close()最外层的for循环用来遍历设备列表,而后在每次循环(每一个设备)中生成范围为300~400的VLAN ID并将它们推送到当前设备。
脚本运行结果如下。
当然,亦能够经过交换机掌控台检测运行结果(仅表示部分结果)。
3 运用netaddr处理IP位置和网络
管理和操作IP位置是网络工程师最重要的任务之一。Python研发人员供给了一个令人惊叹的库—— netaddr,它能够识别IP位置并对其进行处理。假设你研发了一个应用程序,其中必须获取129.183.1.55/21的网络位置和广播位置,经过模块内的内置办法network和broadcast能够容易地获取到相应的位置。 net.network
129.183.0.
net.broadcast129.183.0.0
netaddr支持非常多功能。
在第3层的位置中,netaddr支持下列功能。 识别IPv4和IPv6位置、子网、掩码和前缀。对IP网络进行迭代、切片、排序、汇总和归类。处理各样格式(CIDR、任意子网长度、nmap)。对IP位置和子网进行集合操作(联合、交叉等)。解析各样区别的格式和符号。查询IANA IP块信息。生成DNS反向查询结果。检索超网和生成子网。在第2层的位置中,netaddr支持下列功能。 展示和操作Mac位置与EUI-64标识符。查询IEEE组织信息(OUI、IAB)。生成链路本地的IPv6位置。3.1 安装netaddr
运用pip安装netaddr模块,命令如下。 pip install netaddr安装完成之后打开PyCharm或Python掌控台并导入模块,验证模块是不是安装成功。倘若无显现错误信息,说明模块安装成功。 python
>>>import netaddr3.2 运用netaddr的办法
netaddr模块供给了两种重要的办法来定义IP位置并对其进行处理。第1种办法是IPAddress(),它用来定义拥有默认子网掩码的单个有类IP位置。第二种办法是IPNetwork(),它运用CIDR定义无类IP位置。
两种办法都将IP位置做为字符串来处理,按照字符串返回IP位置或IP网络对象。返回的对象还能够继续执行许多办法,例如判断IP位置是单播位置、多播位置、环回位置、私有位置还是公有位置,以及位置有效还是无效位置。这些操作的结果是True或False。在Python的if要求中能够直接运用这些办法。
另一,该模块支持运用==、<和>等比较运算符比较两个 IP 位置,从而生成子网。它还能够检索一个给定IP位置或子网术语的超网列表。最后,netaddr模块能够生成有效主机的一个完整列表(不包含网络IP位置和网络广播位置)。 #!/usr/bin/python
__author__ = "Bassim Aly"
__EMAIL__ = "basim.alyy@gmail.com"from netaddr import IPNetwork,IPAddress
def check_ip_address(ipaddr):
ip_attributes = []
ipaddress = IPAddress(ipaddr)ifipaddress.is_private():
ip_attributes.append("IP Address is Private")
else:
ip_attributes.append("IP Address is public")
if ipaddress.is_unicast():
ip_attributes.append("IP Address is unicast")
elif ipaddress.is_multicast():
ip_attributes.append("IP Address is multicast")
if ipaddress.is_loopback():
ip_attributes.append("IP Address is loopback")
return "\n".join(ip_attributes)
def operate_on_ip_network(ipnet):
net_attributes = []
net = IPNetwork(ipnet)
net_attributes.append("Network IP Address is " + str(net.network) + "
and Netowrk Mask is " + str(net.netmask))
net_attributes.append("The Broadcast is " + str(net.broadcast) )
net_attributes.append("IP Version is " + str(net.version) )
net_attributes.append("Information known about this network is " +
str(net.info) )
net_attributes.append("The IPv6 representation is " + str(net.ipv6()))
net_attributes.append("The Network size is " + str(net.size))
net_attributes.append("Generating a list of ip addresses inside the
subnet")
for ip in net:
net_attributes.append("\t" + str(ip))
return "\n".join(net_attributes)
ipaddr = raw_input("Please Enter the IP Address: ")
print check_ip_address(ipaddr)
ipnet = raw_input("Please Enter the IP Network: ")
print operate_on_ip_network(ipnet)在上面的脚本中,首要运用raw_input()函数请求用户输入IP位置和IP网络,而后将输入的值做为参数传递给两个用户办法check_ip_address()和operate_on_ip_network()并调用它们。第1个函数check_ip_address()会检测输入的IP位置,同期尝试生成相关IP位置属性的报告(例如,IP位置是单播、多播、私有还是环回位置),并将输出返回给用户。
第二个函数operate_on_ip_network()用来完成和网络关联的操作,即生成网络ID、掩码、广播、版本、网络上的已知信息、IPv6位置的表示方式,最后生成该子网内的所有IP位置。
重视,net.info只能对公共IP位置生成可用信息,对私有IP位置不起功效。
一样,在运用之前必须先从netaddr模块导入IP Network和IP Address。
脚本运行结果如下所示。
4 简单的用例
随着网络变得越来越大,其中包括更加多来自各样区别供应商的设备,这就必须创建模块化的Python脚本来自动执行各样任务。接下来的几节将分析3个用例,这些用例能够从网络中收集区别信息,缩短处理问题所需的时间,或最少将网络配置恢复到其上次已知的良好状态。运用自动化工作流来处理网络故障、修复网络环境,网络工程师能够更关心工作完成状况,加强业务水平。
4.1 备份设备配置
备份设备配置针对任何一名网络工程师来讲都是最重要的任务之一。在这个用例中,咱们将运用netmiko库设计一个示例Python脚本。该脚本用来备份设备配置,它适用于区别的供应商和平台。
为方便日后拜访或引用,咱们将按照设备IP位置格式化输出文件名,例如,SW1备份操作的输出文件保留在dev_10.10.88.111_.cfg中。 创建Python脚本从定义交换机起始,咱们期盼将其配置备份为文本文件(设备文件),用逗号分隔拜访设备的用户名、秘码等仔细信息。这般就能够在Python脚本中运用split()函数来获取这些数据,方便在ConnectHandler函数中运用这些数据。另外,还能够从Microsoft Excel工作表或任何数据库中容易导出该文件以及把该文件导入其中。
文件结构如下。 <device_ipaddress>,<username>,<password>,<enable_password>,<vendor>
创建Python脚本,运用with open子句在脚本中导入该文件。在导入的文件对象上运用readlines()办法将文件中的每一行构成列表,而后用for循环逐行遍历文件,用split()函数获取每一行中用逗号隔开的设备信息,并将它们赋予相应的变量。 from netmiko import ConnectHandler
from datetime import datetime
with
open("/media/bassim/DATA/GoogleDrive/Packt/EnterpriseAutomationProject/Chap
ter5_Using_Python_to_manage_network_devices/UC1_devices.txt") as
devices_file:devices = devices_file.readlines()
for line in devices:
line = line.strip("\n")
ipaddr = line.split(",")[0]
username = line.split(",")[1]
password = line.split(",")[2]
enable_password = line.split(",")[3]
vendor = line.split(",")[4]
if vendor.lower() == "cisco":
device_type = "cisco_ios"
backup_command = "show running-config"elif vendor.lower() =="juniper":
device_type = "juniper"
backup_command = "show configuration | display set"
因为咱们的目的是创建模块化的、支持多种设备供应商的脚本,因此呢在if子句中必须检测设备供应商,并为该设备分配正确的device_type和backup_command。
接下来,创立与设备的SSH连接,运用netmiko模块中的.send_command()办法执行备份命令。 print str(datetime.now()) + " Connecting to device {}" .format(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)print str(datetime.now()) + " Saving config from device {}" .format(ipaddr)
f =open( "dev_" + ipaddr + "_.cfg", "w")
f.write(running_config)
f.close()
print "=============================================="
在最后的几行中,以写入方式打开一个文件(文件不存在时将自动创建),文件名中包括了前面从设备文件中读取的ipaddr变量。
脚本运行结果如下。
必须重视的是,备份的配置文件存储在项目的主目录中,文件名叫作包括每一个设备的IP位置(见下图)。
运用Linux服务器上的cron任务,或Windows服务器上的计划任务,可让服务器在指按时间运行上面的Python脚本。例如,每日凌晨运行一次,将配置信息存储在latest目录中,以方便运维团队运用。
4.2 创建拜访终端
在Python或其他编程活动中,你便是自己的设备供应商。为了满足自己的需求,你能够创建任何爱好的代码组合和程序。在第二个例子中咱们创建自己的终端(terminal),经过telnetlib拜访路由器。只必须在终端写几个单词,就会在网络设备中执行非常多命令并返回输出结果。输出结果将会表示在标准输出或保留在文件中。 #!/usr/bin/python
__author__ = "Bassim Aly"
__EMAIL__ = "basim.alyy@gmail.com"import telnetlib
connection = telnetlib.Telnet(host="10.10.88.110")
connection.read_until("Username:")
connection.write("admin" + "\n")
connection.read_until("Password:")
connection.write("access123" + "\n")
connection.read_until(">")
connection.write("en" + "\n")
connection.read_until("Password:")
connection.write("access123" + "\n")
connection.read_until("#")
connection.write("terminal length 0" + "\n")
connection.read_until("#")
while True:
command = raw_input("#:")
if "health" in command.lower():
commands = ["show ip int b",
"show ip route",
"show clock",
"show banner motd"
]
elif "discover" in command.lower():
commands = ["show arp",
"show version | i uptime",
"show inventory",
]
else:
commands = [command]for cmd in commands:
connection.write(cmd + "\n")
output = connection.read_until("#")
print output
print "==================="
首要,创立到路由器的Telnet连接并输入相应的用户信息,始终到打开特权(enable)模式。而后,创建一个始终为true的无限while循环,运用内置的raw_input()函数捉捕用户输入的命令。脚本捕捉到用户输入之后,在网络设备上执行这些命令。
倘若用户输入关键字health或discover,终端将自动执行一系列命令以反映期望的操作。这些关键字在排除网络故障时非常有用,能够按照常用的操作自由扩展它们。想象一下,在必须处理两个路由器之间的开放式最短路径优先(Open Shortest Path First,OSPF)邻居问题时,只要打开自己的Python终端脚本(这个脚本中已然写好了几个排除故障常用的命令),并将这些命令打包到诸如tshoot_ospf之类的if要求之后。一旦脚本看到这个关键字,它就会执行这些命令,输出OSPF邻居状态、MTU的接口、OSPF的广播网络等,简化定位问题的过程。
经过在提示符中输入health尝试脚本中的第1条命令。脚本输出结果如下。
能够看到,脚本将返回在设备上执行多条命令后的结果。
接着试一下第二个命令discover。脚本输出结果如下。
这次脚本返回discover命令的输出。在后面的章节中,咱们将会解析返回的输出结果并从中提取有用的信息。
4.3 从Excel工作表中读取数据
网络和IT工程师始终运用Excel工作表来存储基本设备的关联信息,如IP位置、设备供应商和登录凭证。Python支持从Excel工作表中读取数据并对其进行处理,以便咱们在脚本中运用数据。
在这个用例中,咱们将运用Excel Read(xlrd)模块读取UC3_devices.xlsx文件。该文件保留了基本设备的主机名、IP位置、用户名、普通秘码、特权模式下的秘码和供应商名叫作。而后将读到的数据用作netmiko模块的输入。
Excel工作表中的内容如下图所示。
首要,用pip安装xlrd模块,由于必须用它来读取Microsoft Excel工作表。 pip install xlrdxlrd模块能够读取Excel工作表并将行和列转换为矩阵。例如,row[0][0]表率第1行第1列的单元格,右边紧接着它的单元格是row[0][1](见下图),以此类推。
xlrd在读取工作表时,每次读取一行,同期特殊计数器nrows(行数)自动加1。一样,每次读取一列,ncols(列数)自动加1,这般咱们就能够经过这两个参数晓得矩阵的体积。
而后,在xlrd的open_workbook()函数中输入文件路径,并用sheet_by_index()或sheet_by_name()函数拜访工作表。在本例中,数据存储在第1个工作表(index = 0)中,工作表文件存储在以章为名的文件夹下。接着,遍历工作表的每一行,或运用row()函数来拜访指定行。返回的输出结果是一个列表,运用索引能够拜访列表中的元素。
Python脚本如下。 __author__ ="Bassim Aly"
__EMAIL__ = "basim.alyy@gmail.com"
from netmiko import ConnectHandler
from netmiko.ssh_exception importAuthenticationException,
NetMikoTimeoutExceptionimport xlrd
from pprint import pprint
workbook =
xlrd.open_workbook(r"/media/bassim/DATA/GoogleDrive/Packt/EnterpriseAutomat
ionProject/Chapter4_Using_Python_to_manage_network_devices/UC3_devices.xlsx
")
sheet = workbook.sheet_by_index(0)
for index in range(1, sheet.nrows):
hostname = sheet.row(index)[0].value
ipaddr = sheet.row(index)[1].value
username = sheet.row(index)[2].value
password = sheet.row(index)[3].value
enable_password = sheet.row(index)[4].value
vendor = sheet.row(index)[5].value
device = {
device_type: vendor,ip: ipaddr,
username: username,
password: password,
secret: enable_password,
}
# pprint(device)
print "########## Connecting to Device {0}
############".format(device[ip])
try:
net_connect = ConnectHandler(**device)
net_connect.enable()
print "***** show ip configuration of Device *****"
output = net_connect.send_command("show ip int b")
print output
net_connect.disconnect()
except NetMikoTimeoutException:
print "=======SOMETHING WRONG HAPPEN WITH
{0}=======".format(device[ip])
except AuthenticationException:
print "=======Authentication Failed with
{0}=======".format(device[ip])
except Exception as unknown_error:
print "=======SOMETHING UNKNOWN HAPPEN WITH {0}======="
4.4 其他用例
运用netmiko能够实现非常多网络自动化用例。例如,在升级时期从远程设备上传/下载文件,利用Jinja2模板加载配置,拜访终端服务器,拜访终端设备等。要认识更加多用例,请参见GitHub官网(见下图)。
5 小结
在本章中,咱们起始运用Python进入网络自动化世界。本章讨论了Python中的有些工具,经过Telnet和SSH创立到远程节点的连接,并在远程设备上执行命令。另外,本章还讲述了怎样在netaddr模块的帮忙下处理IP位置和网络子网。最后经过两个实质用例巩固了这些知识。
下一章将介绍怎样处理返回的输出结果,从中提取有用的信息。
本文摘自:《Python自动化运维实战》
Python自动化运维实战:运用Python管理网络设备运维工程师教程书籍,自动化运维实践经过Python模块、库与工具自动配置和管理海量服务器的讲解,加强运维的效率《Python自动化运维实战》介绍了怎样经过Python来自动完成服务器的配置与管理,自动完成系统的管理任务(如用户管理、数据库管理和进程管理),以及完成这些工作所需的模块、库和工具。另外,本书还讲述了怎样使用Python脚本自动执行测试,怎样经过Python在云基本设备和虚拟机上自动执行任务,怎样运用基于Python的安全工具自动完成与安全关联的任务。
本书适合运维人员和研发人员阅读,亦可做为关联专业人士的参考书。
专栏
零基本学编程Python 3
作者:异步社区
查看
|