前言
祝大家有美好的一天!
我是一家大型电信运营商的网络工程师,在我的控制下,整个动物园遍布各种网络设备,但我们将讨论接入交换机。
本文不是行动指南,也不是唯一的解决方案,并且显然也不假装是年度提名的剧本,但我想分享这个创意,也许对某人有用。
本文将在扰流板下提供一个代码块,并在下面进行剪辑和说明,并说明其原因和用途。
挑战赛
专门使用python3。 该脚本应该能够从列表中转到交换机,确定哪种供应商,给出所需的命令,进行日志。
其实我怎么来的
面对在大量交换机上更改配置的小问题,我将立即对我们拥有的网络设备的集中管理系统保留一下,我的同事也有许多以脚本形式进行开发以方便手动工作的工具,主要是bash,perl。
但是对我来说,做点不同的事情很重要,因为 我最近开始学习python,我需要提高编程技能,并且我的工具应该看起来像锤子(易于使用且易于维护)。 如果仍然有兴趣,那么我要猫。
谷歌搜索并没有找到合适的解决方案(好像在论坛上提出了这个问题,但那里一切都错了),我决定开始编写自己的脚本。
我们有以下开关:
- Raisecom
- Qtech版本 1.0
- Qtech版本 2.0(语法差异)
- Eltex
- D链接
- 用Qtech版本1.0的枪口产生弗兰肯斯坦开关,而Raisecom的铁杆我们称之为ROS
首先,导入所需的库:
import telnetlib import time import os import sys import getpass import pexpect from telnetlib import Telnet import datetime import subprocess
最初,我们描述供应商定义功能,因为 决定使用两种方法:
1)假设它是哪种类型的供应商(应邀输入登录名),因为我注意到每个人都不同:Qtech(登录:),Raisecom和ROS(登录:),Eltex(用户名:),D-link(用户名)。
2)登录后-确保第一项均已正确完成,并能更好地识别我们所处的开关。
整个功能在扰流板之下。 我们声明对整个脚本可见的全局变量:
global ver_status global sab_versus global versus
变量a,d,f,h,j,k,n存储关键字,通过这些关键字我们随后将确定开关的模型。
a = 'Serial No.:1405'
打开ver.txt文件后,我们逐行读取并检查关键字输入,因为 如果此结果为负,则find()函数返回-1,我们将建立分支。
parser=open('servers_&_log/ver.txt', 'r')
...
我给出了代码的示例部分,其余部分在上面的扰流器下。
该文件的内容将在下面描述。 在完成所有操作并定义了供应商之后,删除ver.txt文件。
主变量声明,主循环主体 user='user' password='password' komm=open('servers_&_log/komm.txt') log=open('servers_&_log/log.txt','a')
我决定不打扰,并在正文中使用用户名和密码设置变量,我知道这不是安全的,我正在努力。
打开日志文件和开关列表
komm=open('servers_&_log/komm.txt') log=open('servers_&_log/log.txt','a')
在使用for循环之后,读取带有交换机ip地址的行
for host in komm.readlines(): print('connect....',host) vend = ''
我们检查它的可用性
response = os.system('ping -c 1 ' + host)
如果可以使用pexpect库访问它,我们将在此迭代中尝试通过telnet进行连接,并在邀请时进行第一次检查,这是我在开始时写到的。
if response == 0: telnet = pexpect.spawn('telnet ' + host,timeout=40) vend = telnet.expect(['login:', 'Login:', 'User Name:', 'Username']) telnet.close() tn = Telnet(host.replace('\n', ''), 23,30)
vend变量的值将介于0到3之间(含0和3),并且根据看到的登录提示,将形成另一个分支。
从这段代码中,细心的读者可能会注意到我正在与交换机建立连接并立即关闭连接,这并非没有道理。 我尝试仅使用telnetlib库,但是在第一次测试中,该脚本会定期卡住,并因超时而掉落,这对我们很有帮助。
关闭连接后,我们仅使用telnetlib库进行重新连接。
为了避免出错,我们已经在上面检查了该开关是否可访问,并排除了由于一个空闲开关而在操作期间导致脚本中断的问题,请尝试将所有内容包装在try除块之外。
反复出现的情况是,在100台交换机中,有1台不让自己进入。
try: print('Ok'+'\n') tn.read_until(b':') tn.write((user +'\n').encode('ascii')) tn.read_until(b':') tn.write((password + '\n').encode('ascii')) time.sleep(3) tn.read_until(b'#',timeout=20) except: print('connection refused' + '\n') f = open('servers_&_log/log.txt', 'a') print(host, 'connection refused', file=log) print('#' * 100, host, file=log)
...
如果一切正常,并且我们已建立连接,那么我们需要输入用户名和密码,
我们肯定知道任何冒号提示都使用冒号。
所以我们在等他
tn.read_until(b':')
输入登录名后
tn.write((user +'\n').encode('ascii'))
等待密码冒号
tn.read_until(b':')
输入密码
tn.write((password + '\n').encode('ascii'))
然后我们等待3秒(尽管如此,否则我们做了很多工作)
time.sleep(3)
等待邀请后
tn.read_until(b'#',timeout=20)
在此阶段,我们进入第二级以检查供应商。
if vend == 0:
因为 我们以为我们到达了Qtech,如果您仔细阅读,则在我们的动物园中有两种版本的qtech语法不同,我们仍然需要调和。
因此,我们给出show ver命令,将所有输出放入ver.txt文件
并调用如上所述的who_is()过程。 表演团队对所有Qtech,Raisecom,Eltex,
不幸的是,D-link并不理解,他需要说点swich,但是我们很聪明,并没有白费力气地使用假定的供应商定义进行迭代。
if vend == 3:
因此,立即在输入show swich后打了一个小字,该开关显示不完整的信息,并等待用户按任意键以进一步输出,因此,我们然后发送“ a”字符以显示完整的信息。
tn.write(('a' + '\n').encode('ascii'))
为避免这种情况,您可以关闭clipadding
这是供应商验证结束的地方,我们可以以99%的概率假定我们已经正确识别了交换机的型号,然后可以继续进行配置。
对于每个开关,我们都有一个单独的文件,其中包含一组命令。
配置块 ... elif ver_status == 'qtech_rev_1.0': tn.write(('show ver' + '\n').encode('ascii')) print((tn.read_until(b'#').decode('ascii')), file=log) counter_qtech1_0+=1 komand_qtech1_0=open('servers_&_log/komand_qtech_ver1.0.txt') for kommand in komand_qtech1_0.readlines(): tn.write((kommand.replace('\n', '') + '\n').encode('ascii')) tn.write(('exit' + '\n').encode('ascii')) print(tn.read_all().decode('ascii'), file=log) print(' qtech1.0') print('Qtech rev1.0 ' + host, file=log) print('#' * 100, file=log)
函数计算完并返回ver_status变量后,我们可以继续进行分支工作,因为 我们确切知道当前正在使用哪个开关。
首先,我们给switch命令show ver,并将输出写入日志(关于d-link,记住我们给它命令sh sw)
tn.write(('show ver' + '\n').encode('ascii')) print((tn.read_until(b'#').decode('ascii')), file=log)
确保保留计数器以识别不符合项。
counter_qtech1_0+=1
我们用命令打开一个文件
komand_qtech1_0=open('servers_&_log/komand_qtech_ver1.0.txt')
文件中命令的顺序必须与管理员手动输入的顺序相同
一个例子:
conf
vlan 2525
name SPD
int ethe 1/1
sw mode access
sw acc vl 2525
exit
exit
save
y
然后一切都取决于场景-我们读取文件直到行结束并执行它们
for kommand in komand_qtech1_0.readlines(): tn.write((kommand.replace('\n', '') + '\n').encode('ascii'))
退出循环后,我们告诉交换机退出并将所有输出读取到文件中,因此我们仅使用qtech1.0,因为 有时,脚本会预料到某些事情,并且这种切换就是这样,以免大惊小怪,这种解决方案在我看来似乎更优雅。
配置完交换机后,我们将总计数器增加一。
counter_komm+=1
然后,我们重新开始,使用开关从文件中读取下一行,确定模型并进行配置。
退出主要周期后,您需要总结已完成的工作,
在日志末尾,我们输入所有处理过的模型,并且日期是必填项,那么,如果没有日期,该怎么办。
print('\n\n\n : ', counter_komm,file=log) print('\n\nD-link:', counter_dlink,'\nQtech ver1.0:', counter_qtech1_0,'\nROS:', counter_ROS,'\nRaisecom:',counter_raisecom,'\nEltex:', counter_eltex,'\nQtech ver2.0 :', counter_qtech2_0,file=log) print('\n: ', datetime.datetime.now().isoformat(),'\n', '#'*100,'\n\n\n\n\n',file=log) verinfo.close() log.close()
该脚本已被重复处理,并且该过程不会在那里停止。
谢谢大家的关注。 欢迎进行建设性的批评。
所有代码都在扰流器下。