|
大家好!我又来了!我自己只是一名普通网工,做的事情其实也谈不上“开发”。但,我很乐意把我践行Python网络运维自动化的点滴分享出来,并努力营造一个正向氛围,同时非常鼓励有开发志向的读者们尝试造轮子等开发行动。最近与我讨论框架或者工具开发的,有 @Elin @风之魔影 @JimWorks 等。他们或直接把代码开源发布,或直接提供工具支持。这些行动都在为NetDevOps领域做正向努力。本文我先与大家分享一个 net_inspect 模块,由@Elin 开发并维护。大体上,Net_inspect是一个跨厂商的设备信息解析工具,支持TextFSM模板,支持模块化插件(即“耦合”或“解耦”)。@Elin 还做了一个ntc-template的分仓ntc_templates_elinpf,旨在更好支持国内设备。
〇、参考资料
本专栏简介及目录入口,如果你不知道从何读起,建议从这篇《目录》开始,链接如下:
@弈心 大神教学文章、视频汇总,链接如下:
Net_inspect 模块代码已在github仓库发布,提供了正式的交流渠道,如提Issues等。
Net_inspect 模块作者 @Elin 自己也在知乎上撰写了该模块使用教程,链接如下:
一、模块安装
常规操作,我们直接在系统上安装net_inspect模块。这是我目前体验到的为数不多的“国产”Python模块安装,还是挺兴奋的。
pip install net_inspect接着,我们show一下这个模块。这是我第一次看到Summary位置是用中文显示的。这里提供了
C:\WINDOWS\system32>pip3 show net_inspect
WARNING: Ignoring invalid distribution -yang (c:\users\zhuji\appdata\roaming\python\python310\site-packages)
Name: net-inspect
Version: 1.3.4
Summary: 基于已收集的网络设备信息进行的结构化数据分析框架
Home-page: https://github.com/Elinpf/net_inspect
Author: Elin
Author-email: 365433079@qq.com
License: Apache-2.0
Location: c:\program files\python310\lib\site-packages
Requires: ntc_templates_elinpf, openpyxl, rich, rich_typer, textfsm
Required-by:
C:\WINDOWS\system32>模块安装后,按照其官网提示,可以直接在CMD上执行net_inspect命令,我们试试看。

这里会有一些命令提示,net_inspect命令携带不同的参数可以做一些设置或者查询。

为什么我们在CMD窗口任意路径下可执行net_inspect命令呢?因为在Python安装目录中的Scripts文件夹中会生成一个net_inspect.exe,而这个Scripts路径已经在安装Python的时候已经添加入系统环境变量,所以我们在CMD即可直接使用。

这里我们先大体了解下这个模块还可供了这个命令,可作为此模块日常维护和查询的接口。作为初探,我们就不要挖太深了。
二、实验拓扑
依然是我们熟悉的那个拓扑,这是模拟器的。

三、示例复现
3.1 官方示例复现
参照官网教程的简单例子,我们准备一个实验文件夹,存放3台交换机的指令回显信息。3台SW的display version内容是类似的, 这里我们以SW1为示例。
<SW1>display version
Huawei Versatile Routing Platform Software
VRP (R) software, Version 5.110 (S5700 V200R001C00)
Copyright (c) 2000-2011 HUAWEI TECH CO., LTD
Quidway S5700-28C-HI Routing Switch uptime is 0 week, 0 day, 0 hour, 2 minutes
<SW1>没错,这些信息可以用paramiko、netmiko之类的模块收集,这里我们简单手工处理一下。

我们把示例代码拷贝过来,保存成net_inspect1.py文件。
from net_inspect import NetInspect
net = NetInspect()
net.set_plugins(input_plugin=&#39;console&#39;)
net.run(path=&#39;log&#39;)
print(&#39;total devices:&#39;, len(net.cluster.devices))
for device in net.cluster.devices:
info = device.info
print(&#39; | &#39;.join([info.hostname, info.ip, info.vendor,
info.version, info.model, info.cpu_usage]))运行脚本,轻松复现其示例结果,3台设备的型号都相同,因此,脚本执行结果截图如下。

3.2 示例代码讲解
官网信息对示例代码没有做解释,这边我们来逐行探究一下。
from net_inspect import NetInspect从net_inspect模块中引入NetInspect类,这种是常规操作,很多Python模块都是这么操作的。我们去探一探源代码。

NetInspect 还是定义了不少东西,简单说,有它可以创建一个信息解析对象。
net = NetInspect()创建一个NetInspect对象,赋值给变量net。我们在CMD上调测一下,依然是最最基础的print、type、help、dir等
E:\sync\点读系列\网络工程师的Python之路\net_inspect\lab1>python
Python 3.10.6 (tags/v3.10.6:9c7b4bd, Aug 1 2022, 21:53:49) [MSC v.1932 64 bit (AMD64)] on win32
Type &#34;help&#34;, &#34;copyright&#34;, &#34;credits&#34; or &#34;license&#34; for more information.
>>> from net_inspect import NetInspect
>>> net = NetInspect()
>>>
>>> net
<net_inspect.api.NetInspect object at 0x0000014AF95A7C40>
>>>
>>> type(net)
<class &#39;net_inspect.api.NetInspect&#39;>
>>>
>>> dir(net)
[&#39;__class__&#39;, &#39;__delattr__&#39;, &#39;__dict__&#39;, &#39;__dir__&#39;, &#39;__doc__&#39;, &#39;__eq__&#39;, &#39;__format__&#39;, &#39;__ge__&#39;, &#39;__getattribute__&#39;, &#39;__gt__&#39;, &#39;__hash__&#39;, &#39;__init__&#39;, &#39;__init_subclass__&#39;, &#39;__le__&#39;, &#39;__lt__&#39;, &#39;__module__&#39;, &#39;__ne__&#39;, &#39;__new__&#39;, &#39;__reduce__&#39;, &#39;__reduce_ex__&#39;, &#39;__repr__&#39;, &#39;__setattr__&#39;, &#39;__sizeof__&#39;, &#39;__str__&#39;, &#39;__subclasshook__&#39;, &#39;__weakref__&#39;, &#39;_plugin_manager&#39;, &#39;_plugins&#39;, &#39;cluster&#39;, &#39;get_all_plugins&#39;, &#39;get_analysis_plugins&#39;, &#39;get_base_info&#39;, &#39;get_input_plugins&#39;, &#39;get_output_plugins&#39;, &#39;get_parse_plugins&#39;, &#39;run&#39;, &#39;run_analysis&#39;, &#39;run_input&#39;, &#39;run_output&#39;, &#39;run_parse&#39;, &#39;search&#39;, &#39;set_base_info_handler&#39;, &#39;set_external_templates&#39;, &#39;set_input_plugin&#39;, &#39;set_log_level&#39;, &#39;set_output_plugin&#39;, &#39;set_parse_plugin&#39;, &#39;set_plugins&#39;, &#39;verbose&#39;]
>>>
>>> help(net)
Help on NetInspect in module net_inspect.api object:
...略...显然,net_inspect.api.NetInspect与上面截图的“路径”是一致的。
我们过掉掉一些看起来好像比较“高深”的魔法方法,只保留普通方法。
>>> [method for method in dir(net) if not method.startswith(&#39;_&#39;)]
[&#39;cluster&#39;, &#39;get_all_plugins&#39;, &#39;get_analysis_plugins&#39;, &#39;get_base_info&#39;, &#39;get_input_plugins&#39;, &#39;get_output_plugins&#39;, &#39;get_parse_plugins&#39;, &#39;run&#39;, &#39;run_analysis&#39;, &#39;run_input&#39;, &#39;run_output&#39;, &#39;run_parse&#39;, &#39;search&#39;, &#39;set_base_info_handler&#39;, &#39;set_external_templates&#39;, &#39;set_input_plugin&#39;, &#39;set_log_level&#39;, &#39;set_output_plugin&#39;, &#39;set_parse_plugin&#39;, &#39;set_plugins&#39;, &#39;verbose&#39;]
>>>这是net对象的各种方法,后续可以配合着调用起来。目前只生成了这个对象,还灌入“网络设备信息”,所以会比较空。我们先大致浏览下即可。
变量net对象的每个方法,其实本身也是一个对象,又可以用dir或者help进行查询。这与剥洋葱是很相似的,一层一层又一层,还是那句话,Python无处不类和对象!

net.set_plugins(input_plugin=&#39;console&#39;)示例代码用到了set_plugins方法,传输了参数input_plugin=&#39;console&#39;,指定net对象的输入插件是console。
>>> help(net.set_plugins)
Help on method set_plugins in module net_inspect.api:
set_plugins(input_plugin: &#39;Optional[Type[InputPluginAbstract] | str]&#39; = None, output_plugin: &#39;Optional[Type[OutputPluginAbstract] | str]&#39; = None, parse_plugin: &#39;Optional[Type[ParsePluginAbstract] | str]&#39; = None) method of net_inspect.api.NetInspect instance
设置插件
:param input_plugin: 输入插件
:param output_plugin: 输出插件
:param parse_plugin: 解析插件
>>>回到源代码文件路径,逻辑稍微有点点复杂,不过没关系,我们知道大概就好!

有兴趣可以打开源码文件看看,这边我们就打住了,继续往下走!
>>> net.run(path=&#39;log&#39;)继续help一下,此时调用了一个参数是path,用于指定路径。
>>> help(net.run)
Help on method run in module net_inspect.api:
run(path: &#39;str&#39;, output_file_path: &#39;str&#39; = &#39;&#39;, output_plugin_params: &#39;Dict[str, str]&#39; = {}) -> &#39;Cluster&#39; method of net_inspect.api.NetInspect instance
运行输入解析输出插件
:param path: 文件或者目录路径
:param output_file_path: 输出文件路径
:param output_plugin_params: 输出插件参数
:return Cluster: 设备列表
>>>好了,示例内容走到这里实际已经把信息“灌入”了net这个net_inspect对象中了,实际上它已经把信息都处理好了,于是,后面的内容基本上以print为主进行铺排。
print(&#39;total devices:&#39;, len(net.cluster.devices))这个好理解,计算多少台设备,log文件夹中有三个设备回显文件,因此结果得到3。
>>> len(net.cluster.devices)
3
>>> type(net.cluster.devices)
<class &#39;net_inspect.domain.DeviceList&#39;>
>>>此时你如果有兴趣的话,就可以去探索一下源码。

示例使用了DeviceList类方法获知一共有3台设备,随后用了另一个Device类方法查到每台设备的具体信息。
for device in net.cluster.devices:
info = device.info
print(&#39; | &#39;.join([info.hostname, info.ip, info.vendor,
info.version, info.model, info.cpu_usage]))DeviceList类中重写了__iter__方法,因此其用for循环可以自动变成一个迭代器,从而进行设备遍历。
我们重新调整一下。
>>> for device in net.cluster.devices:
... type(device)
...
<class &#39;net_inspect.domain.Device&#39;>
<class &#39;net_inspect.domain.Device&#39;>
<class &#39;net_inspect.domain.Device&#39;>于是我们可以知道源代码domain.py中有个Device类。我们继续用老方法,层层剖析!
>>> [method for method in dir(device) if not method.startswith(&#39;_&#39;)]
[&#39;analysis&#39;, &#39;analysis_result&#39;, &#39;check_vendor&#39;, &#39;cmds&#39;, &#39;info&#39;, &#39;parse&#39;, &#39;parse_result&#39;, &#39;save_to_cmds&#39;, &#39;search_cmd&#39;, &#39;vendor&#39;]
>>> [method for method in dir(device.info) if not method.startswith(&#39;_&#39;)]
[&#39;analysis&#39;, &#39;cpu_usage&#39;, &#39;hostname&#39;, &#39;ip&#39;, &#39;memory_usage&#39;, &#39;model&#39;, &#39;sn&#39;, &#39;uptime&#39;, &#39;vendor&#39;, &#39;vendor_platform&#39;, &#39;version&#39;]
>>>回到示例,其中设备的信息呈现,就是从这里取的信息。
示例代码中用到了字符串方法join,可能有点点复杂,我们再重新调整个更简单的,并且打印出示例代码没有的信息。
from net_inspect import NetInspect
net = NetInspect()
net.set_plugins(input_plugin=&#39;console&#39;)
net.run(path=&#39;log&#39;)
for device in net.cluster.devices:
info = device.info
if info.hostname == &#39;SW1&#39;: # 这里做个过滤,只拿SW1的信息。
print(info.uptime) # SW1的启动时长。其运行结果如下。

四、互动交流
使用ENSP模拟器的网元测试示例代码成功后,我便测试了一下手头的一台真机设备。
[SW-wgsy]DISP VER
Huawei Versatile Routing Platform Software
VRP (R) software, Version 5.150 (S5300 V200R005C00SPC500)
Copyright (C) 2000-2015 HUAWEI TECH CO., LTD
Quidway S5328C-EI Routing Switch uptime is 0 week, 6 days, 16 hours, 13 minutes
CX22EFGE 0(Master) : uptime is 0 week, 6 days, 16 hours, 12 minutes
256M bytes DDR Memory
32M bytes FLASH
Pcb Version : VER.B
Basic BOOTROM Version : 206 Compiled at Jul 1 2015, 14:25:55
CPLD Version : 80
Software Version : VRP (R) Software, Version 5.150 (V200R005C00SPC500)
FORECARD information
Pcb Version : CX22E4GF VER.A
FPGA Version : 0
HINDCARD information
Pcb Version : CX22ETPB VER.C
FANCARD I information
Pcb Version : FAN VER.B
PWRCARD I information
Pcb Version : PWR VER.A
[SW-wgsy]还是官方的示例代码,脚本跑出来的脚本截图如下。

这个结果并不是我们要的。这个时候其实也可以再去挖一下源代码看看的。但这里我偷“懒”了,把回显内容发个了模块作者。

很快他发现问题,input组件有个分割命令小BUG,修复一下就即可。随后,连同其它内容,他更新了一个版本。
pip install net_inspect -U于是我将版本更新一下。
E:>pip show net_inspect
WARNING: Ignoring invalid distribution -yang (c:\users\zhuji\appdata\roaming\python\python310\site-packages)
Name: net-inspect
Version: 1.3.5
Summary: 基于已收集的网络设备信息进行的结构化数据分析框架
Home-page: https://github.com/Elinpf/net_inspect
Author: Elin
Author-email: 365433079@qq.com
License: Apache-2.0
Location: c:\users\zhuji\appdata\roaming\python\python310\site-packages
Requires: ntc_templates_elinpf, openpyxl, rich, rich_typer, textfsm
Required-by:
E:>重新测试就正常了。

五、本文总结
本文只是net_inspect模块的基础应用,其还可以配合TextFSM模板进行,更过大家可以参考官网进阶内容尝试起来,并把实际应用再梳理分享出来。期间,我们可以通过知乎、微信或者更“正规”的issues与模块作者@Elin 形成良性互动,让这个轮子得以发展!另外,@Elin 也为ntc-template开发了一个分仓ntc_templates_elinpf旨在更好支持国内设备。我虽然还没怎么使用,但非常开心能看到这些,希望对此有兴趣的读者们一起来研究使用。同时,我也期待更多的国产轮子出现。
我读过的书、用过的物(持续更新)
感谢阅读,欢迎关注点赞收藏评论交流。
发布2022年09月于广东汕头
更新2022年09月于广东汕头 |
|