Jinja2网络自动化——增加一个变量(子网+1)
Jinja2 Network Automation - increasing a variable (subnet +1)
首先,我是一名网络工程师,正在学习一些编码并尝试使用这种相对较新的技术进行改进。关于以下问题,我已经在互联网上搜索了很多小时,但大多数搜索结果都包含我不想要的 Ansible(目前)。
我正在使用 python/jinja2 脚本生成一个基于 VAR 的配置,称为 confplate:请参阅 https://github.com/verbosemode/confplate - 我已经进行了一些测试并且效果很好。超级简单快捷。
但是,我正在尝试使用变量(网络地址)并在 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_cidr
和 gateway_from_cidr
是我们将很快创建的自定义 Jinja2 过滤器。
想法是,network_from_cidr
过滤器将采用类似“21.22.23.0/24”的字符串,return 将采用字符串“21.22.23.0 255.255.255.0”。同样,gateway_from_cidr
过滤器将采用字符串“21.22.23.0/24”和 return“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
首先,我是一名网络工程师,正在学习一些编码并尝试使用这种相对较新的技术进行改进。关于以下问题,我已经在互联网上搜索了很多小时,但大多数搜索结果都包含我不想要的 Ansible(目前)。
我正在使用 python/jinja2 脚本生成一个基于 VAR 的配置,称为 confplate:请参阅 https://github.com/verbosemode/confplate - 我已经进行了一些测试并且效果很好。超级简单快捷。
但是,我正在尝试使用变量(网络地址)并在 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_cidr
和 gateway_from_cidr
是我们将很快创建的自定义 Jinja2 过滤器。
想法是,network_from_cidr
过滤器将采用类似“21.22.23.0/24”的字符串,return 将采用字符串“21.22.23.0 255.255.255.0”。同样,gateway_from_cidr
过滤器将采用字符串“21.22.23.0/24”和 return“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