Processing results
在这个教程中我们将看下我们是如何处理tasks处理的结果的。
我们从这个我们已经见过的代码中去看下:
import logging
from nornir import InitNornir
from nornir.core.task import Task, Result
nr = InitNornir(config_file="config.yaml")
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}"
)
目前为止没有新代码出现,我们在say任务中写了一个错误提醒,来帮我们说明一些概念。
下面我们写一个我们上节见过的比较复杂的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对象:
result = cmh.run(
task=greet_and_count,
number=5,
)
简单方式
大多时候你只是想通过回显看到发生了什么。对于这个你只需要用nornir_utils中的print_result函数就行。
from nornir_utils.plugins.functions import print_result
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!
---- 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/bless/.local/lib/python3.8/site-packages/nornir/core/task.py", line 99, in start
r = self.task(self, **self.params)
File "/mnt/d/Project/nornir_learn2/learn_result.py", line 18, 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 host1.cmh: greet_and_count ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvv 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])
应该你已经注意到了,不是所有的任务都被打印了。这是由于我们传递了severity_level这个参数。这个参数可以让
我们标识任务的日志级别。然后print_result可以根据日志规则来打印结果。默认情况下任务会被标识未INFO级别的
才会被打印(如果一个任务没有被特殊指定,默认值就是INFO)。
一个失败任务的严重级别会被改成未ERROR即使用户指定了特定值。你可以先看下host2.cmh在Greeting is the polite thing to do
任务中看到这个。
现在我们可以告诉print_result来打印DEBUG级别的任务。
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/bless/.local/lib/python3.8/site-packages/nornir/core/task.py", line 99, in start
r = self.task(self, **self.params)
File "/mnt/d/Project/nornir_learn2/learn_result.py", line 18, in say
raise Exception("I can't say anything right now")
Exception: I can't say anything right now
^^^^ END greet_and_count ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
现在我们得到了所有任务的输出。你可以看到严重级别基本都在输出的最右侧。
编程方式
前面我们已经暗示了如何处理result对象,现在让我们详细的说明下。我们从任务组返回的一个AggregatedResult开始。
这个对象是一个类似字典的对象,你可以迭代出所有结果或直接访问某个host。
print(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"
]
}
print(result.keys())
输出:
dict_keys(['host1.cmh', 'host2.cmh'])
print(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对象。这个对象是一个类似列表的对象,
你可以完成堆叠或者访问你想要的任何结果:
print(result["host1.cmh"][0])
输出:
host1.cmh counted even times!
MultiResult和Result都可以清晰的表明是否有change或者error在系统中:
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
网友评论