python - Jinja2 网络自动化 - 增加一个变量(子网+1)

标签 python templates networking jinja2 cisco

首先,我是一名网络工程师,正在学习一些编码并尝试使用这种相对较新的技术进行发展。关于以下问题,我已经在互联网上搜索了很多小时,但大多数搜索结果都包含我不想要的 Ansible(目前)。

我正在使用 python/jinja2 脚本,该脚本基于 VAR 生成名为 confplate 的配置:请参阅 https://github.com/verbosemode/confplate - 我已经做了一些测试,效果很好。 super 简单快速。

但是,我尝试使用变量(网络地址)并在 Jinja2 模板中递增它来设置 IP 地址。

参见下面的 Jinja2 代码片段:

ip dhcp pool WLAN01
network {{ vlan400_network }} 255.255.255.0
domain-name abc.xyz
default-router {{ vlan400_network + 1 }}
lease 0 1

vlan400_network = 172.29.50.0

我希望默认路由器为172.29.50.1 - 当然我无法使用上面的代码片段来增加它。

我需要为此使用正则表达式吗?单独使用 Jinja2 似乎不太容易。 我的偏好是仅使用 Python/Jinja2 来完成此任务。这可能吗?提前致谢!

最佳答案

正如您所发现的,如果您仅依赖 Jinja2 的默认过滤器,您将无法在生成网络设备配置方面取得很大进展。

您必须编写自己的自定义过滤器(用 Python)并在模板文件中使用它们。

对于您的示例,请执行以下操作:

第 1 步:设计模板

我将提供 vlan 网络作为 CIDR 规范:

./confplate.py template.txt vlan400_network=21.22.23.0/24

如您所见,这是直观且灵活的:如果您愿意,您可以将网络更改为 21.22.23.192/26,一切都会继续正常工作,我们很快就会看到。

此模板如下所示:

ip dhcp pool WLAN01
 network {{ vlan400_network | network_from_cidr }}
 domain-name abc.xyz
 default-router {{ vlan400_network | gateway_from_cidr }}
 lease 0 1

其中 network_from_cidrgateway_from_cidr 是我们将很快创建的自定义 Jinja2 过滤器。

其想法是,network_from_cidr 过滤器将采用类似“21.22.23.0/24”的字符串并返回字符串“21.22.23.0 255.255.255.0”。同样,gateway_from_cidr 过滤器将采用字符串“21.22.23.0/24”并返回“21.22.23.1”(即子网中的第一个非零主机地址)。

第 2 步:为自定义过滤器编写 Python 代码

创建一个名为custom_filters.py的文件并放入以下代码:

import ipaddress

def network_from_cidr (cidr):
    ipn = ipaddress.ip_network(unicode(cidr), strict=True)
    return '{} {}'.format(ipn.network_address, ipn.netmask)

def gateway_from_cidr (cidr):
    ipn = ipaddress.ip_network(unicode(cidr), strict=True)
    # By convention, the gateway has the first non-zero address in the subnet
    first_address = list(ipn.hosts())[0]
    return first_address

代码使用 ipaddress module 。正如您所看到的,我们定义了两个函数,一个函数用于我们想要创建的每个自定义过滤器。这些函数采用一个参数,即模板中 | 之前的字符串。

第 3 步:告诉 confplate.py 您的自定义过滤器

confplate.py 开头的某个位置写入 import custom_filters

然后你必须说:

env = Environment(loader=FileSystemLoader(self.templatepath), undefined=StrictUndefined)

# Load our custom filters
env.filters['network_from_cidr'] = custom_filters.network_from_cidr
env.filters['gateway_from_cidr'] = custom_filters.gateway_from_cidr

在代码中的适当位置(在confplate.py中,您实际上必须执行两次,一次在get_template_vars函数中,一次在render_template中)

测试

./confplate.py template.txt vlan400_network=21.22.23.0/24
ip dhcp pool WLAN01
 network 21.22.23.0 255.255.255.0
 domain-name abc.xyz
 default-router 21.22.23.1
 lease 0 1

./confplate.py template.txt vlan400_network=21.22.23.192/26
ip dhcp pool WLAN01
 network 21.22.23.192 255.255.255.192
 domain-name abc.xyz
 default-router 21.22.23.193
 lease 0 1

关于python - Jinja2 网络自动化 - 增加一个变量(子网+1),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58714289/

相关文章:

c++ - 使用非类型模板参数而不是常规参数的原因?

android - 如何找到所有不在范围内的 WiFi 网络?

amazon-web-services - Horton Sandbox - AWS EC2 上的 Ambari 未加载(公共(public) IP)

python - Flask Jsonify mongoengine 查询

python - 构建 Django 多对多关系

perl - 如何覆盖 Template Toolkit 模板文件中的 WRAPPER?

模板类中的 C++ 非模板方法

php - 使用 PHP 的原始文本 SOAP 消息

python - 如何通过 Python 以编程方式使用 gcloud 命令

在 jobstore (apscheduler) 中找不到 Python 高级调度程序作业