Nornir 处理结果

在本教程中,我们将看到如何处理正在运行的task的结果。

让我们从类似于我们已经看到的代码开始:

import logging

from nornir import InitNornir
from nornir.core.task import Task, Result

# instantiate the nr object
nr = InitNornir(config_file="config.yaml")
# let's filter it down to simplify the output
cmh = nr.filter(site="cmh", type="host")

def count(task: Task, number: int) -> Result:
    return Result(
        host=task.host,
        result=f"{[n for n in range(0, number)]}"
    )

def say(task: Task, text: str) -> Result:
    if task.host.name == "host2.cmh":
        raise Exception("I can't say anything right now")
    return Result(
        host=task.host,
        result=f"{task.host.name} says {text}"
    )

到目前为止,没有什么新鲜的东西,我们已经在saytask中对错误进行了硬编码,这将帮助我们说明一些概念。现在,让我们为在先前的教程中看到的分组task创建一个变体:

def greet_and_count(task: Task, number: int):
    task.run(
        name="Greeting is the polite thing to do",
        severity_level=logging.DEBUG,
        task=say,
        text="hi!",
    )

    task.run(
        name="Counting beans",
        task=count,
        number=number,
    )
    task.run(
        name="We should say bye too",
        severity_level=logging.DEBUG,
        task=say,
        text="bye!",
    )

    # let's inform if we counted even or odd times
    even_or_odds = "even" if number % 2 == 1 else "odd"
    return Result(
        host=task.host,
        result=f"{task.host} counted {even_or_odds} times!",
    )

与我们之前的分组task几乎相同,只是我们传递severity_level=logging.DEBUG给第一个和最后一个子task的区别。稍后我们将了解这意味着什么。

现在,让我们调用task组,以便我们可以开始检查结果对象:

result = cmh.run(
    task=greet_and_count,
    number=5,
)

简单的方法

在大多数情况下,您只想提供有关正在发生的事情的反馈。为此,您可以使用软件包随附的print_result函数nornir_utils

from nornir_utils.plugins.functions import print_result

print_result(result)
greet_and_count*****************************************************************
* host1.cmh ** changed : False *************************************************
vvvv greet_and_count ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
host1.cmh counted even times!
---- Counting beans ** changed : False ----------------------------------------- INFO
[0, 1, 2, 3, 4]
^^^^ END greet_and_count ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* host2.cmh ** changed : False *************************************************
vvvv greet_and_count ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv ERROR
Subtask: Greeting is the polite thing to do (failed)

---- Greeting is the polite thing to do ** changed : False --------------------- ERROR
Traceback (most recent call last):
  File "/home/dbarroso/workspace/dbarrosop/nornir/nornir/core/task.py", line 98, in start
    r = self.task(self, **self.params)
  File "<ipython-input-1-c084194db610>", line 19, in say
    raise Exception("I can't say anything right now")
Exception: I can't say anything right now

^^^^ END greet_and_count ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

您还应该能够打印一个host:

print_result(result["host1.cmh"])
vvvv greet_and_count ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
host1.cmh counted even times!
---- Counting beans ** changed : False ----------------------------------------- INFO
[0, 1, 2, 3, 4]
^^^^ END greet_and_count ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

甚至是一个task:

print_result(result["host1.cmh"][2])
---- Counting beans ** changed : False ----------------------------------------- INFO
[0, 1, 2, 3, 4]

可能已经注意到,并非所有task都已打印。这是由于severity_level我们通过了论证。这让我们用任何日志记录级别标记task。然后print_result可以遵循日志记录规则来打印结果。默认情况下,仅INFO打印标记为的task(如果未指定,这也是task的默认设置)。

失败的task将始终将其严重性级别更改为,ERROR而不管用户指定的级别如何。你可以看到,在task的。Greeting is the polite thing to dohost2.cmh

现在,让我们告诉print_result您打印标记为的taskDEBUG

print_result(result, severity_level=logging.DEBUG)
greet_and_count*****************************************************************
* host1.cmh ** changed : False *************************************************
vvvv greet_and_count ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
host1.cmh counted even times!
---- Greeting is the polite thing to do ** changed : False --------------------- DEBUG
host1.cmh says hi!
---- Counting beans ** changed : False ----------------------------------------- INFO
[0, 1, 2, 3, 4]
---- We should say bye too ** changed : False ---------------------------------- DEBUG
host1.cmh says bye!
^^^^ END greet_and_count ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* host2.cmh ** changed : False *************************************************
vvvv greet_and_count ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv ERROR
Subtask: Greeting is the polite thing to do (failed)

---- Greeting is the polite thing to do ** changed : False --------------------- ERROR
Traceback (most recent call last):
  File "/home/dbarroso/workspace/dbarrosop/nornir/nornir/core/task.py", line 98, in start
    r = self.task(self, **self.params)
  File "<ipython-input-1-c084194db610>", line 19, in say
    raise Exception("I can't say anything right now")
Exception: I can't say anything right now

^^^^ END greet_and_count ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

现在我们打印了所有task。您还可以在输出的最右列看到严重性级别。

编程方式

我们已经暗示了如何处理结果对象,但让我们对其进行详细说明。首先,task组将返回AggregatedResult。该对象是一个类似dict的对象,可用于遍历或直接访问host:

result
AggregatedResult (greet_and_count): {'host1.cmh': MultiResult: [Result: "greet_and_count", Result: "Greeting is the polite thing to do", Result: "Counting beans", Result: "We should say bye too"], 'host2.cmh': MultiResult: [Result: "greet_and_count", Result: "Greeting is the polite thing to do"]}
result.keys()
dict_keys(['host1.cmh','host2.cmh'])
result["host1.cmh"]
MultiResult: [Result: "greet_and_count", Result: "Greeting is the polite thing to do", Result: "Counting beans", Result: "We should say bye too"]

您可能已经注意到,在AggregatedResult的每个键中都有一个MultiResult对象。该对象是类似列表的对象,可用于迭代或访问所需的任何Result:

result["host1.cmh"][0]
结果:“ greet_and_count”

双方MultiResultResult应明确指出,如果有系统中的一些错误或更改:

print("changed: ", result["host1.cmh"].changed)
print("failed: ", result["host1.cmh"].failed)
changed:  False
failed:  False
print("changed: ", result["host2.cmh"][0].changed)
print("failed: ", result["host2.cmh"][0].failed)
changed:  False
failed:  True

觉得文章有用?

点个广告表达一下你的爱意吧 !😁