公司要IT转型,我该怎么办?Python让我看见网络自动运维的曙光

 

 Python自动运维,释放自我。

 

01 面临问题

 

网络运维苦,电信级网络运维更苦。

账号密码是否过期?

设备能否正常登陆?

设备是否正常?
给定某设备IP地址,用户名和密码,完成以下任务:

  • 模拟telnet/ssh设备,可以测试账号可用性,设备连通性

  • 执行指令,返回结果,如查询配置文件

  • 分析配置文件,比如关注拓扑信息,学习Python正则表达式的基本知识;

 

02 怎么办

 

模拟telnet/ssh

Python有很多第三方库,实现ssh、ftp、telnet等命令交互。

如pexpect、paramiko等,都没时间涉及。

先用Python自带的telnetlib实现最简单的telnet功能,

后续如果有需求再进一步学习。

模拟telnet的代码如下:

import telnetlibhost = "x.x.x.x"    #设备IP,将来可以从一个地址池中读取user =b 'x'     #用户名密码password =b 'x'finsh = b"#"     #结束符号tn = telnetlib.Telnet(host) #创建telnet连接tn.read_until(b"login: ") #读取到给定字符串tn.write(user + b"\n")  #输入用户名tn.read_until(b"Password: ")tn.write(password + b"\n")tn.read_until(finsh)

确保网络是通的。

python正在模拟人工登陆。

telnetlib.Telnet(host) 没有报错,说明设备网络通的,也开放了telnet端口;

tn.read_until(finsh) 执行完毕,说明账号密码正常,可以正常登陆

 

执行指令并返回结果

正常telnet设备后,通过指令查询爱立信MME attach相关指标。

指令如下:

attach | tail -10

Python代码如下:

command =b "attach | tail -10" #待执行指令tn.write(command + b"\n") #Python执行指令,模拟人工输入、回车res = tn.read_until(finsh)  #python读取指令结果

tn.read_until(finsh) 可以理解为从执行上条指令开始,一直读取到finsh结束。

这里是#,不同平台可能不一样,如~等。

查看res结果如下,说明已经正确完成指令结果读取。

 

分析本地配置文件

由于安全原因路由器无法直接telnet,

暂时通过分析本地配置文件。

其实对于上述MME的指令结果也可以继续分析。

 

分析指令结果

配置文件可以分析很多东西,

今天只分析路由器的接口数据,配置了哪些接口?对端分别是哪些网元?接口IP是多少?

接口配置样例如下:

interface GigabitEthernet2/0/8.1055 vlan-type dot1q 1055 description To-[HZMxx]-[MHRD|2|4|11|B|1]-1G ip binding vpn-instance xx_xx_Media ip address x.x.x.149 255.255.255.252 statistic enable

通过正则表达式匹配这段内容,并提取相应信息。

Python正则表达式re

关于Python正则表达式的知识非常多,可以写一本书,暂时写不出来。

所谓正则表达式,就是给定一个模式字符串表达式patten,然后逐一匹配字符串,正如我们熟悉的*表示任何东西一样。

 

比如要在一句英文中匹配是否存在hello?

import re# 将正则表达式编译成Pattern对象pattern = re.compile(r'hello')s = pattern.search('hello world!') #调用search函数,查找if s: #匹配成功为真    print(s.group())#以上是输出hello

Pattern对象是一个编译好的正则表达式,提供了很多方法使用,如match()、search()、findall()。

用findall()匹配设备接口信息,会以列表形式返回全部匹配的字串代码如下:

In[227]: import pandas as pdf = open(u'XXXCE06-HWNE40E_配置备份文件保存.txt','r')conf = f.read() p_int= re.compile(r"interface GigabitEthernet(.*?)\n.*?description (.*?)\n")ints = p_int.findall(conf)#转换为DataFrame,以便后续输出报错ints = pd.DataFrame(ints,columns = ['interface','description'])ints['interface'] = ['GigabitEthernet'+i for i in list(ints['interface'])]In[228]: ints.head()Out[228]:                interface                             description0  GigabitEthernet1/0/10          TO-[xxx]-[LSW01-GE0/0/13]_1G1  GigabitEthernet1/0/23                     TO-xxx-1G-WANGGUAN2   GigabitEthernet2/0/1  TO-[GDHIZ-xxx-HWNE40E]-GE2/0/1-1G3   GigabitEthernet2/0/2  TO-[GDHIZ-xxx-HWNE40E]-GE2/0/2-1G4   GigabitEthernet2/0/3         To-[HZMxx]-[MHRD|1|2|11|B|1]-1G

其中正则表达式

"interface GigabitEthernet(.?)\n.?description (.*?)\n"

以下划重点

表示以interface GigabitEthernet开头,先匹配任意字符,直到换行\n;

第一个括号匹配接口号interface;

然后再忽略一些字符. *?,

找到description ,匹配对端网元,

以换行符\n结束匹配。

 

这个写法直接返回()中匹配上的内容,如端口号、desc等,

但是对于没有desc的端口则无法匹配命中

整个配置文件findall()后可以全部匹配想要的接口号及对端信息。

 

更多接口信息

上面只匹配了有对端的GigabitEthernet接口信息,其实路由有很多接口类型,如vlan,还有子接口等。

下面尝试写一个更全面的功能,能够分析所有接口信息。

#给定配置文件conf,返回全部接口信息def get_intferaces(conf):    p_int = re.compile(r'#\n(interface .*?)\n#',re.S)    ints = p_int.findall(conf)    cols = ['interface','is_shutdown','description','ipaddress','vpn-instance','vlan']    rows = []    for i in ints:        name = i.split('interface ')[1].split('\n')[0]        if ('NULL' not in name) & ('Virtual' not in name):            if 'description ' in i:                desc = i.split('description ')[1].split('\n')[0]            else:                desc = ''            if 'ip address ' in i:                ipaddress = i.split('ip address ')[1].split('\n')[0]            else:                ipaddress = ''                 if 'ip binding vpn-instance ' in i:                vpn = i.split('ip binding vpn-instance ')[1].split('\n')[0]            else:                vpn = ''              if 'port default vlan ' in i:                vlan = i.split('port default vlan ')[1].split('\n')[0]            else:                vlan = ''            if 'undo shutdown' in i:                is_shutdow = 'undo shutdown'            elif 'shutdown' in i:                is_shutdow = 'shutdown'            else:                is_shutdow = '' #为空表示没有这个字段            row = [name,is_shutdow,desc,ipaddress,vpn,vlan]            rows.append(row)    interfaces = pd.DataFrame(rows,columns = cols)    return interfaces

由于接口类型很多,不好用统一的正则表达式匹配。

其实是我不会,没研究它。

大家有兴趣可以用一句话正则实现下。

 

通过get_intferaces(conf)可以获取到全部接口信息。

然后可以对这些接口信息进行处理,

比如只保留在用端口,IP地址用子网表示等。

# 保留在用端口interfaces = interfaces[~interfaces['is_shutdown'].isin(['shutdown'])]

由于对端描述不是特别规范,

提取真实网元名称需要一些判断逻辑,不麻烦,

同时如果知道全部IP地址信息,可以用子网进行匹配,更准确。

 

最终代码

整理上面代码,汇总如下。

大家可以新建automain_demo.py,

复制以下代码,测试是否正常。

import telnetlibimport reimport pandas as pd
#在指定网元上执行指令,并返回指令结果def doComd(host,user,password,finsh,commands):    tn = telnetlib.Telnet(host)    tn.read_until(b"login: ")    tn.write(user +b "\n")    tn.read_until(b"Password: ")    tn.write(password + b"\n")        tn.read_until(finsh)       print(host+"登陆成功!")    res = []    #可以执行多条指令    for command in commands:        tn.write(command +b "\n")            res.append(tn.read_until(finsh))    tn.close()    return res#给定配置文件conf,返回全部接口信息def get_intferaces(conf):    p_int = re.compile(r'#\n(interface .*?)\n#',re.S)    ints = p_int.findall(conf)    cols = ['interface','is_shutdown','description','ipaddress','vpn-instance','vlan']    rows = []    for i in ints:        name = i.split('interface ')[1].split('\n')[0]        if ('NULL' not in name) & ('Virtual' not in name):            if 'description ' in i:                desc = i.split('description ')[1].split('\n')[0]            else:                desc = ''            if 'ip address ' in i:                ipaddress = i.split('ip address ')[1].split('\n')[0]            else:                ipaddress = ''                 if 'ip binding vpn-instance ' in i:                vpn = i.split('ip binding vpn-instance ')[1].split('\n')[0]            else:                vpn = ''              if 'port default vlan ' in i:                vlan = i.split('port default vlan ')[1].split('\n')[0]            else:                vlan = ''            if 'undo shutdown' in i:                is_shutdow = 'undo shutdown'            elif 'shutdown' in i:                is_shutdow = 'shutdown'            else:                is_shutdow = '' #为空表示没有这个字段                row = [name,is_shutdow,desc,ipaddress,vpn,vlan]            rows.append(row)    interfaces = pd.DataFrame(rows,columns = cols)    interfaces = interfaces[~interfaces['is_shutdown'].isin(['shutdown'])]    return interfacesif __name__ == "__main__":      host = "x.x.x.x"    #设备IP,将来可以从一个地址池中读取    user = b'x'     #用户名密码    password =b 'x'    finsh = b"#"     #结束符号    command = ["hostname","dispaly current-config"]    #result = doComd(host,user,password,finsh,command)    f = open(u'GDHIZ-NGN-CE06-HWNE40E_配置备份文件保存.txt','r')    result = f.read()    #hostname = result[0]    hostname = "test"    conf = result[1]    interface = get_intferaces(conf)    interface.to_csv(hostname+'.csv',encoding = 'utf8',index = False)

注意换成真实的IP、用户名和密码既可,然后在命令行中运行测试。

运行脚本后,新增test.csv文件:

以上脚本只是基础,还可以扩展出很多功能。

 

至此,在公司IT转型过程中,我用Python完成了第3个小项目,看到自动运维的曙光。

 

03 为什么

为什么要这么做?

通信运维IT化、自动化、智能化是趋势,不可逆。

CT设备IT化,网络云化,传统通信网络在近几年会快速转型升级。

运维再也不能只靠人力,得依赖算力。

从小事做起,从小功能做起,用自动化释放人力,用智能化提升效率。

Python在自动运维领域应用大有可为。

值得深入学习。

 

04 其他选择

有没有更好的选择?

自动运维互联网大厂肯定有更好的平台和经验,

但是作为通信人,只能借鉴,更多还是要找适合自己的。

 

欢迎大家留言讨论,也可以通过公众号求道轩“约我”私信交流。

下篇我会继续分享第4个小项目实践,欢迎关注。

期待更多道友分享。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值