美文网首页
Nornir文档翻译----第四节 失败的任务

Nornir文档翻译----第四节 失败的任务

作者: Bless_H | 来源:发表于2022-04-24 01:29 被阅读0次

    Failed Tasks

    有些时候一些任务会失败。让我们看下在nornir中如何处理这些失败的任务。
    让我们和之前一样从样本代码开始:

    import logging
    
    from nornir import InitNornir
    from nornir.core.task import Task, Result
    from nornir_utils.plugins.functions import print_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}"
        )
    
    

    现在用一个我们上节教程中用过的例子:

    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!",
        )
    

    大家记着我们在host2.cmh上设置了一个错误,现在我们执行这个任务看下将会发生什么:

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

    让我们看下这个result对象:

    print(result.faild)
    
    输出:
    True
    
    print(result.faild_hosts)
    
    输出:
    {'host2.cmh': MultiResult: [Result: "greet_and_count", Result: "Greeting is the polite thing to do"]}
    
    print(result['host2.cmh'].exception)
    
    输出:
    Subtask: Greeting is the polite thing to do (failed)
    
    print(result['host2.cmh'][1].exception)
    
    输出:
    I can't say anything right now
    
    

    如你所见,result对象是意识到了一些错误的,如果你想看的话也可以查看。
    你也可以用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/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_failed_tasks.py", line 20, in say
        raise Exception("I can't say anything right now")
    Exception: I can't say anything right now
    
    ^^^^ END greet_and_count ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    还有一个方法可以抛出异常如果task又错误的话(目前我还没看出来这个怎么应用):

    from nornir.core.exceptions import NornirExecutionError
    try:
        result.raise_on_error()
    except NornirExecutionError:
        print("ERROR!!!")
    
    输出:
    ERROR!!!
    

    Skipped hosts

    Norni会跟踪任务失败的hosts,并且不会在这些hosts中执行接下来的任务:

    #这段代码必须要加在前面的后面才可以感受到
    #host2.cmh这个host在前面的任务中失败,所以在执行这个hi时Nornir会直接跳过
    def hi(task: Task) -> Result:
        return Result(host=task.host, result=f"{task.host.name}: Hi, I am still here!")
    
    result = cmh.run(task=hi)
    print_result(result)
    
    输出:
    hi******************************************************************************
    * host1.cmh ** changed : False *************************************************
    vvvv hi ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
    host1.cmh: Hi, I am still here!
    ^^^^ END hi ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    你可以通过传递这个参数on_failed=True,来强制执行:

    result = cmh.run(task=hi, on_failed=True)
    
    print_result(result)
    
    输出:
    hi******************************************************************************
    * host1.cmh ** changed : False *************************************************
    vvvv hi ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
    host1.cmh: Hi, I am still here!
    ^^^^ END hi ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    * host2.cmh ** changed : False *************************************************
    vvvv hi ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
    host2.cmh: Hi, I am still here!
    

    你还可以排除一些执行成功的host,通过on_good这个参数:

    result = cmh.run(task=hi, on_failed=True, on_good=False)
    print_result(result)
    
    输出:
    
    hi******************************************************************************
    * host2.cmh ** changed : False *************************************************
    vvvv hi ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
    host2.cmh: Hi, I am still here!
    ^^^^ END hi ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    

    为了实现这个,Nornir保留了一个共享的data对象,存储一系列失败的hosts

    print(nr.data.failed_hosts)
    
    输出:
    {'host2.cmh'}
    

    如果你想把一些hosts变成成功的并且使他们执行后续的任务,可以同对单独的host执行recover_host函数或者通过reset_failed_hosts重置整个列表。

    nr.data.reset_failed_hosts()
    print(nr.data.failed_hosts)
    
    输出:
    set()
    
    

    Raise on error automatically

    另外,可以通过raise_on_error配置选项来实现错误发生时自动抛出异常:

    nr = InitNornir(config_file="config.yaml", core={"raise_on_error": True})
    cmh = nr.filter(site="cmh", type="host")
    try:
        result = cmh.run(
            task=greet_and_count,
            number=5,
        )
    except NornirExecutionError:
        print("ERROR!!!")
    
    输出:
    ERROR!!!
    

    Workflows

    默认的工作流适用于大多数的用例,当错误发生时跳过这些host,并且print_result会给出足够的信息去里理解发生了什么。对于更复杂的工作流,这个框架会提供足够的空间去轻松部署。

    相关文章

      网友评论

          本文标题:Nornir文档翻译----第四节 失败的任务

          本文链接:https://www.haomeiwen.com/subject/wywzertx.html