【Nornir系列】Nornir自动化的核心组件task
  vYgR16aEGw5K 2023年11月02日 83 0

【Nornir系列】Nornir自动化的核心组件task

前言

书接上文,我们和大家分享了Nornir的设备筛选相关的功能,可以帮我们灵活的筛选出制定的网络设备。

最后起了一个头,讲了讲task,在我们初始化nornir、筛选完设备之后,nornir是如何在一组设备上执行task的,咱们今天重新仔仔细细、认认真真的和大家聊聊task。

Task

何为task

task是一段可以被循环使用的用于执行一定逻辑的代码,类似ansible的module,它在筛选的设备上进行操作。,它可以简单理解成一个函数,它的第一个参数是task,这个task内含了一些任务的上下文,比如这次执行的是哪部分设备(零个或者多个,零是一种极端情况了,筛选出的设备为空),可以拿到设备的Host对象,进而拿到很多参数,以及一些长链接。

注意:这里有两个task,一个是task的函数,执行一个具体的操作;一个是task的上下文变量,缓存一些任务执行的情况,比如现在是哪台设备在执行,配置文件是哪些等等。大家千万不要混淆!

task示例,让每台设备和大家打个招呼

from nornir import InitNornir
from nornir.core.task import Result, Task
from nornir_utils.plugins.functions import print_result
import logging

nr = InitNornir(
    config_file="nornir.yaml"
)


# 创建一个nornir可以调用的task函数, 官方对于类型注解使用的比较多,比较严谨。
# task是一个Task的对象,返回的是一个Result的对象
def say_hello(task: Task) -> Result:
"""
    让每台设备来和大家打个招呼
    :param task: 必须有一个参数是task 且在第一个。
                 用于上下文相关信息的管理,比如设备信息,nornir的配置等等
    :return:返回打招呼的字符串
    """

    words = f"Hello!I'm a network device. My name is {task.host.name}"
return Result(
        host=task.host,  # 当前这个执行结果的设备信息
        result=words,  # 执行结果,可以是任意python对象。
# 最终都会以str的方式打印出来,但是不影响我们取出相关信息做一些判断之类的
# severity_level=logging.DEBUG, # log的level
    )

我们定义了一个say_hello的函数,第一个参数必须为task,nornir会把相关上下文赋值给此参数。

让我们执行这个自定义的task来看一下。

调用的方法如下

# 使用Nornir对象的实例nr调用run函数。
# 第一个参数task赋值成我们自己写的task函数say_hello。
# 第二个参数name是输出时比较易读准备的。
results = nr.run(task=say_hello, name='A task for saying hi!')

# 安装nornir_utils,调用它的打印函数,打印的效果和ansible很像。
# 但是注意,当你看到这个过程的时候,这段task实际上已经执行结束了
print_result(results)

执行结果如下:

【Nornir系列】Nornir自动化的核心组件task_赋值

image-20201220220336070

大家可以看到每台设备的具体执行情况,非常像ansible。其中有个字段changed,代表配置是否发生变化,默认是false,我们在写自己的task的时候按实际情况在result中赋值为True。

task函数添加任意自定义的参数

上面的say_hello这个task函数只有一个参数,默认的task,有时候我们的函数里希望传入一些额外的参数,我们可以扩展我们的task函数,添加任意个参数。

# 创建一个nornir可以调用的task函数, 官方对于类型注解使用的比较多,比较严谨。task是一个Task的对象,返回的是一个Result的对象
def say_hello(task: Task, dev_type: str = '', sth: str = '') -> Result:
"""
    让每台设备来和大家打个招呼
    :param sth: 添加的额外参数,额外要说的话
    :param dev_type: 添加的额外参数,设备种类
    :param task: 必须有一个参数是task 且在第一个,用于上下文相关信息的管理,比如设备信息,nornir的配置等等

    :return:返回打招呼的字符串
    """
# 添加一段额外的逻辑,纯粹为了演示,在task里,我们可以实现比较复杂的逻辑
if 'spine' in task.host.name:
        sth = f'{sth},and I\'m a spine'
    words = f"Hello!I'm a network dev of {dev_type}. My name is {task.host.name}.{sth}"

return Result(
        host=task.host,  # 当前这个执行结果的设备信息
        result=words,  # 执行结果,可以是任意python对象,最终都会以str的方式打印出来,但是不影响我们取出相关信息做一些判断之类的
# severity_level=logging.DEBUG, # log的level
    )

调用

# 使用Nornir对象的实例nr调用run函数。
# 第一个参数task赋值成我们自己写的task函数say_hello。
# 第二个参数name是输出时比较易读准备的。可有可无
# 第三个参数是我们自己定义的设备类型
# 第四个参数是我们定义的额外要说的话
results = nr.run(task=say_hello,
                 name='A task for saying hi with more args!',
                 dev_type='switch',
                 sth='let\'s learn nornir!')

# 安装nornir_utils,调用它的打印函数,打印的效果和ansible很像。
# 但是注意,当你看到这个过程的时候,这段task实际上已经执行结束了
print_result(results)

查看结果

【Nornir系列】Nornir自动化的核心组件task_设备信息_02

image-20201220222412124

开脑洞时间到,我们会发现task特别灵活,我们指定自己的逻辑,比如执行命令后备份配置,或者解析交换机信息作为巡检或者应急检查,可以刷入配置作为应急操作。

task的组合拳

同时task可以相互之间组合,在一个task中包含另外其他若干个task,来一套组合拳(官方称之为grouping task)以便实现一些复杂的功能,复用一些已有的task。

我们来一套组合拳,给大家演示一下。

我们让每台设备打个招呼,告诉大家自己的version,然后再说声再见。

那打招呼和再见,可以复用一个task,say_sth,传入我们想让它说的话。再写一个task,登录设备执行show version的命令。

我们这次修改一下hosts.yaml

【Nornir系列】Nornir自动化的核心组件task_设备信息_03

image-20201226223954221

由于我最近重装了系统,所以华为的模拟器没了,我们用一下思科的实验环境设备。

简单到不能再简单的一个hosts文件,我们再来写两个task函数。

首先是say_sth的task函数

【Nornir系列】Nornir自动化的核心组件task_赋值_04

image-20201226224315662

然后是一个show_version的task函数

【Nornir系列】Nornir自动化的核心组件task_复用_05

image-20201226224356207

二者进行组合,组合的方式也非常简单,依次调用,调用的方式是用到了task上下文这个变量。

【Nornir系列】Nornir自动化的核心组件task_设备信息_06

image-20201226224811302

我们只看第三台设备的相关信息,我们执行的时候只调用了一个组合task,但是实际执行的时候执行了三个task。

【Nornir系列】Nornir自动化的核心组件task_赋值_07

我们如果在组合task中返回值

【Nornir系列】Nornir自动化的核心组件task_设备信息_08

image-20201226225322331

执行结果,会优先调用最外层的task函数的结果,然后依次调用子task函数的结果,这个过程有点递归的意思。

【Nornir系列】Nornir自动化的核心组件task_设备信息_09

image-20201226225444550

延展

我们为了演示,用了一些简单的函数,在实际操作中,我们展开脑洞,比如say_sth可以是一个配置备份task函数,再写一个把文本输出到指定文件的task函数,或者二者再组合成一个grouping task,备份并保存配置,然后写一个下发配置的task函数,最后再调用刚才写的备份并保存配置的grouping task,这样嵌套着来,灵活复用。就是一个非常标准考虑比较周到的备份下发过程。

同时,我们也可以把一些ZTP写成一个grouping task,每个子task函数,是一个小的配置项,组合多个就是一个完整的ZTP。

小结

以上,我们演示了nornir的核心模块task,从最简单的task,到加参数的task,到组合拳task。其中比较难以理解的是task函数的task上下文参数,它主要用于维护上下文信息,何为上下文,从字面理解就是承上启下,你是谁即当前是哪个设备要做什么,你之前做了什么,有哪些信息要传递给下文。以下是一个debug的信息,我们看到组合拳在调用say_sth的时候,task上下文变量的相关参数。

【Nornir系列】Nornir自动化的核心组件task_设备信息_10

image-20201227084946097

Nornir如果是简单使用,其实非常简单,我们的例子里用了自己的netmiko去登录设备采集信息,实际上nornir封装了很多优秀的工具包,帮我们完成,比如nornir_netmiko,内置了一些netmiko的相关task,还有一些其他的nornir_X工具包,帮我们完成jinja2、netconf、保存文件等相关task,这种plugin的不仅局限在task函数,实际上plugin分为很多种,后续有机会我们慢慢讲讲。今天的分享就到这里了!

最后

同名知乎专栏和微信公众号:NetDevOps加油站,欢迎你的加入!

【Nornir系列】Nornir自动化的核心组件task_设备信息_11

image-20201219222006955

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

vYgR16aEGw5K