Configure the interfaces File with Mako

Issue

The /etc/network/interfaces file gets very long and cumbersome. What if multiple ports have similar configurations? Is there a way automate this without having to use something like Ansible or Puppet, or without making a custom Python/bash script?

Solution

ifupdown2 supports Mako templates on Cumulus Linux. Template engines are usually used for generating HTML content, but they work great for large network configurations. Read the Mako documentation for more information.

Examples

Mako Output
## Note that the "range" ends with '4'
## But will iterate only from 1 to 3
## See Python range() for more details
% for i in range(1, 4):
auto swp${i}
iface swp${i}
% endfor
auto swp1
iface swp1

auto swp2
iface swp2

auto swp3
iface swp3
## Mako code when commented out, should be
## done using two comments, not one.
## Otherwise incorrect processing may occur
## <%def name="other_defaults()">
## mtu 3000
## </%def>
###
<%def name="interface_defaults()">
mtu 9000
link-speed 10000
link-duplex full
link-autoneg off
</%def>

% for i in range(3,7):
auto swp${i}
iface swp${i}
${interface_defaults()}
% endfor

auto default_bridge
iface default_bridge
bridge_ports glob swp3-6
bridge-stp on
auto swp3
iface swp3

mtu 9000
link-speed 10000
link-duplex full
link-autoneg off

auto swp4
iface swp4
mtu 9000
link-speed 10000
link-duplex full
link-autoneg off

auto swp5
iface swp5

mtu 9000
link-speed 10000
link-duplex full
link-autoneg off

auto swp6
iface swp6

mtu 9000
link-speed 10000
link-duplex full
link-autoneg off

auto default_bridge
iface default_bridge
bridge_ports glob swp3-6
bridge-stp on
<%
vlan_range_1 = [200,220,260]
vlan_range_2 = range(300,305)
full_vlan_list = vlan_range_1 + vlan_range_2
%>

% for v in full_vlan_list:
auto vlan${v}
iface vlan${v}
bridge-ports glob swp1-6.${v}
bridge-stp on
% endfor
auto vlan200
iface vlan200
bridge-ports glob swp1-6.200
bridge-stp on
auto vlan220
iface vlan220
bridge-ports glob swp1-6.220
bridge-stp on
auto vlan260
iface vlan260
bridge-ports glob swp1-6.260
bridge-stp on
auto vlan300
iface vlan300
bridge-ports glob swp1-6.300
bridge-stp on
auto vlan301
iface vlan301
bridge-ports glob swp1-6.301
bridge-stp on
auto vlan302
iface vlan302
bridge-ports glob swp1-6.302
bridge-stp on
auto vlan303
iface vlan303
bridge-ports glob swp1-6.303
bridge-stp on
auto vlan304
iface vlan304
bridge-ports glob swp1-6.304
bridge-stp on

Layer 3 Configuration Using Mako

The following is a layer 3 configuration created with Mako for ifupdown2:

This requires apt-get install python-ipaddr if not already installed.

Mako Output
iface lo inet loopback
auto eth0
iface eth0 inet dhcp

<%!
from ipaddr import IPAddress
ip = IPAddress('10.1.1.0')
%>

<%def name="incr_ip(ip, count, incr)">
<% newip = ip + (count * incr) %>
address ${newip}/31
</%def>

% for i in range(1,10):
auto swp${i}
iface swp${i}
${incr_ip(ip, i, 2)}
% endfor
iface lo inet loopback
auto eth0
iface eth0 inet dhcp

auto swp1
iface swp1
address 10.1.1.2/31

auto swp2
iface swp2
address 10.1.1.4/31

auto swp3
iface swp3
address 10.1.1.6/31

auto swp4
iface swp4
address 10.1.1.8/31

auto swp5
iface swp5
address 10.1.1.10/31

auto swp6
iface swp6
address 10.1.1.12/31

auto swp7
iface swp7
address 10.1.1.14/31

auto swp8
iface swp8
address 10.1.1.16/31

auto swp9
iface swp9
address 10.1.1.18/31
<%!
from ipaddr import IPAddress
ip = IPAddress('12.12.12.12')
%>

<%def name="incr_ip(ip, count, incr)">
<% newip = ip + (count * incr) %>
address ${newip}/31
</%def>

% for i in range(1,4):
auto swp${i}
iface swp${i}
% endfor

% for i in range(5,8):
auto vlan${i}
iface vlan${i}
bridge-ports swp1.${i}
swp2.${i} swp3.${i}
${incr_ip(ip, i, 2)}
% endfor
auto swp1
iface swp1

auto swp2
iface swp2

auto swp3
iface swp3

auto vlan5
iface vlan5
bridge-ports swp1.5 swp2.5 swp3.5
address 12.12.12.22/31

auto vlan6
iface vlan6
bridge-ports swp1.6 swp2.6 swp3.6
address 12.12.12.24/31

auto vlan7
iface vlan7
bridge-ports swp1.7 swp2.7 swp3.7
address 12.12.12.26/31

Notes

To correctly comment Mako code, make sure to comment out the code twice (using two hash marks — ##). Otherwise, you might see the following error when running ifquery on an interface:

cumulus@switch:~$ ifquery swp1
error: /etc/network/interfaces: failed to render template (Undefined). Continue without template rendering ...
auto swp1
iface swp1 inet static
address 10.1.2.2
netmask 255.255.255.252
down ip addr flush dev swp1

See Also

Compare ifupdown2 Commands with ifupdown Commands