python - 诺尼尔 : Passing Python Function to Jinja2 Template

标签 python jinja2

我正在使用 Nornir 来自动化网络设备的配置。在我的 Jinja2 模板中,我想调用一个 Python 函数来为我进行子网计算。我似乎不知道如何让 Jinja2 能够以 Nornir 作为驱动程序调用 Python 函数。

错误输出:

**** Nornir Playbook to generate site configurations ***************************
device_config*******************************************************************
* router01 ** changed : False **************************************************
vvvv device_config ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv ERROR
Subtask: <function template_file at 0x7f547c2418c8> (failed)

---- Device Configuration ** changed : False ----------------------------------- ERROR
Traceback (most recent call last):
  File "/home/user1234/venv/lib/python3.6/site-packages/nornir/core/task.py", line 85, in start
    r = self.task(self, **self.params)
  File "/home/user1234/venv/lib/python3.6/site-packages/nornir/plugins/tasks/text/template_file.py", 
  line 35, in template_file
    **kwargs
  File "/home/user1234/venv/lib/python3.6/site-packages/nornir/core/helpers/jinja_helper.py", line 
  18, in render_from_file
    return t.render(**kwargs)
  File "/home/user1234/venv/lib/python3.6/site-packages/jinja2/asyncsupport.py", line 76, in render
    return original_render(self, *args, **kwargs)
  File "/home/user1234/venv/lib/python3.6/site-packages/jinja2/environment.py", line 1008, in render
    return self.environment.handle_exception(exc_info, True)
  File "/home/user1234/venv/lib/python3.6/site-packages/jinja2/environment.py", line 780, in 
  handle_exception
    reraise(exc_type, exc_value, tb)
  File "/home/user1234/venv/lib/python3.6/site-packages/jinja2/_compat.py", line 37, in reraise
    raise value.with_traceback(tb)
  File "./templates/router_master_config.j2", line 52, in top-level template code
    {% include 'router01_interfaces.j2' %}
  File "./templates/router01_interfaces.j2", line 17, in top-level template code
    description VLAN 3000 - WAN Interlink {{ calculate_subnet() }}
jinja2.exceptions.UndefinedError: 'calculate_subnet' is undefined

^^^^ END device_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Process finished with exit code 0

Jinja2 模板部分:

interface Port-channel10.1000
 description VLAN 1000 - WAN {{ calculate_subnet(host.interfaces[2]['ipv4_addr'], host.interfaces[2]['ipv4_mask'] ) }}
 encapsulation dot1Q 1000
 ip address {{ host.interfaces[2]['ipv4_addr'] }} {{ host.interfaces[2]['ipv4_mask']}}
 ip nbar protocol-discovery
 bfd interval 750 min_rx 750 multiplier 4
 no shutdown

Python 脚本:

from nornir import InitNornir
from nornir.plugins.tasks import networking, text
from nornir.plugins.tasks.networking import napalm_configure
from nornir.plugins.functions.text import print_title, print_result


def device_config(task):
    # Transform inventory data to configuration via a template file
    var = task.run(task=text.template_file,
                   name="Device Configuration",
                   template="router_master_config.j2",
                   path=f"./templates/"
                   )

    # Save the compiled configuration into a host variable
    task.host["config"] = var.result


def calculate_subnet(ip,mask):
    # Hard coding subnet for testing
    subnet = "10.10.10.0/24"
    # Calculation will happen here
    return subnet


def main():
    nr = InitNornir(config_file="config.yaml", dry_run=False)
    print_title("Nornir Playbook to generate site configurations")
    routers = nr.filter(device_type="router")
    task = routers.run(task=device_config)
    print_result(task)


if __name__ == "__main__":
    main()

最佳答案

如果您跟踪 nornir.core.task.run 的代码,您会发现它只是将关键字参数传递给插件,最终传递给 t.rendernornir.core.helpers.jinja_helper.render_from_file 中。

因此,您只需将函数对象作为附加关键字参数传递给 task.run 即可使其在模板的命名空间中可用:

var = task.run(task=text.template_file,
               name="Device Configuration",
               template="router_master_config.j2",
               path=f"./templates/",
               calculate_subnet=calculate_subnet
               )

关于python - 诺尼尔 : Passing Python Function to Jinja2 Template,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58842376/

相关文章:

python - 如何绘制双色边缘?

Python 对字典中回调的引用

python - Numpy 切片结果与 for 循环不同

python - 在 jinja 中设置变量

python - 如何根据预定值字母为列表中的单词分配值(Python 3.9)

python - 在用户提交的内容中呈现换行符(Python 网络应用程序)

python - WTForms render_field() 方法引用 for 循环变量

python - 为什么在 jinja2 Python 中使用 "| safe"

javascript - 如何解码 Flask 模板中的 url 字符串

python - 在 Python 中打开远程文档