题图由 angel1238812 在 Pixabay 上发布
-------------------------
我硬盘里的 Ansible 资料也不少了,也看过一些,但是作为一个售前,其实没啥机会去实际使用它。结果就是这些资料在我脑袋里吃灰——忘光了。
现在发现一个可以替代Ansible的工具,Nornir,似乎有机会去使用它,不至于学了就忘。
Nornir 和 Ansible 的关键区别是:前者是一个纯粹的 Python 工具,仅需要用 Python 语言去使用它;而后者的 Playbook 显然是有别于 Python 的另外一种语言,对于愚笨的我来说,学习成本太高了。
Nornir 的项目地址是 https://pypi.org/project/nornir/
文档中心在 https://readthedocs.org/projects/nornir/
下面是 Nornir 2.X 支持的几种连接插件,函数,Inventory 插件,Task 插件等。可以说,除了 core 组件之外,其他的组件都是以插件的形式存在的。

说到插件,有个问题需要注意。Nornir 从 3.0 版本开始,在安装 package 的时候不会自动帮助用户安装插件了,需要用户在安装 Nornir 之后手工安装插件。下图左侧是 Nornir 3.1.0 的虚拟环境,右侧是 Nornir 2.4.0 的虚拟环境。可以看到 3.1.0 版本基本上啥都没装,而 2.4.0 已经自动安装了很多依赖包。而且 Nornir 3.X 和 2.X 的代码差异比较大,比如 2.X 版本就没有 runner ,只有 task。网上 2.X 的作业会更多一些,抄起来比较方便。像我这种笨人,当然要选择 2.X 了。

另外,Nornir 需要 Python 3.6 或以上版本。
用 pip 安装 Nornir 并指定版本:
pip install nornir==2.5.0
安装之后要做的第一件事,就是初始化 Nornir。方法有 2 种。
方法 1:创建一个 YAML 格式的配置文件,然后在 Python 脚本里面用 InitNornir 函数创建 Nornir 项目。下面是官网提供的 config file example:

从这份配置文件我们发现,Nornir 内置的 Simple Inventory 的几个组成部分:
host_file:用来存储主机/设备信息,还可以定义主机/设备所属的 group
group_file:可选,创建 group 并存储 group 的通用信息
defaults_file:可选,用于存储一些更通用更广泛的信息,例如 domain name 之类的
其实这和 Ansible 区别不大。实际上,Nornir 还可以使用 Ansible 的 inventory。我们就按照上面 config file 的内容,新建 inventory 文件夹,以及 hosts.yaml 文件和 groups.yaml 文件。我给 IP 和密码打了马赛克。


在这里咱先使用 napalm 插件管理到设备的连接。它的作用是用来对 stdout 做抽象化。前几天不是写了一些 TTP 的介绍么,napalm 干的事情其实和 ttp 一样,parse 半结构化数据。它最大的用武之地其实是用于 netconf。
从设备取出原始配置数据/状态数据之后,可以使用 NAPALM 将其翻译成标准格式的 NAPALM 数据。反之,也可以将标准格式的 NAPALM 数据翻译成设备原始配置数据,并 Push 到网络设备里面,以修改设备的配置文件。
非资深老网工,公众号:非资深老网工应该选用哪种 API 来实现网络自动化?
写好 inventory 文件之后,就要 import Nornir 并初始化项目:

方法 2:可以不使用 inventory 文件,直接在 Python 脚本里面使用为变量赋值的方式来初始化 Nornir 项目。
方法 3:可以同时使用上述 2 种方法,先创建 inventory 文件,然后在 Python 脚本里面补充或者修改若干参数。
然后就可以执行任务了。我们 import networking 插件,用 run() 函数调用 napalm_get 方法采集设备的基本信息:

这里面要注意的是,result 是一个 Nornir 对象,无法直接打印,所以还需要 import print_result 然后用 print_result() 函数来打印它。
NAPALM 似乎有些小众,下面把连接插件换成 Netmiko 试一下。改写一下 groups.yaml,把 connection_options 改成 netmiko

run() 函数可以用 task 参数调用另外一个函数,来实现同时执行多个 task 的目的。我们这次写个函数,在 2 台设备上 show lldp neighbors。

注意哦,因为 connection 插件变成了 netmiko,所以 task 也要跟着变。然后打印 show 结果(IP地址被我打码了):

看到最关键的区别了嘛?如果用 Netmiko 插件,输出的是 string,而不是 dict。因为 Nornir 的 Netmiko 插件依赖于 TextFSM。有的时候 TextFSM 能直接输出 dict,但更多的时候它只能输出 string,还得再写模版 parse。
所以看上去还是 napalm_get() 更好用 :-)




