Skip to content

Commit 4b67697

Browse files
authored
Add proper multi-bond support to debianish distros (#83)
We've long supported configuring multiple bonds for RedHat based distros, this is the same but for Debians. Still left is Alpine.
2 parents 56edf3e + 0507c3a commit 4b67697

File tree

5 files changed

+97
-12
lines changed

5 files changed

+97
-12
lines changed

packetnetworking/builder.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ def build_bonding(self):
9696
)
9797

9898
def build_interfaces(self):
99-
self.interfaces = utils.WhereList()
10099
physical_ifaces = utils.get_interfaces()
101100
matched_ifaces = utils.get_matched_interfaces(
102101
self.nw_metadata.interfaces, physical_ifaces
@@ -110,7 +109,7 @@ def build_interfaces(self):
110109

111110
def build_bonds(self):
112111
self.bonds = utils.RecursiveDictAttributes({})
113-
for iface in self.nw_metadata.interfaces:
112+
for iface in self.interfaces:
114113
if "bond" in iface and iface.bond:
115114
if iface.bond not in self.bonds:
116115
self.bonds[iface.bond] = [iface]

packetnetworking/distros/debian/templates/bonded/etc_network_interfaces.j2

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@ iface lo inet loopback
33

44
{% if osinfo.distro == 'ubuntu' %}
55
{% for iface in interfaces %}
6+
67
auto {{ iface.name }}
78
iface {{ iface.name }} inet manual
89
{% if iface.name != interfaces[0].name %}
910
pre-up sleep 4
1011
{% endif %}
1112
bond-master bond0
12-
1313
{% endfor %}
1414
{% endif %}
15-
auto bond0
16-
iface bond0 inet static
15+
16+
{% for bond in bonds %}
17+
18+
auto {{ bond }}
19+
iface {{ bond }} inet static
20+
{% if bond == "bond0" %}
1721
{% if ip4pub %}
1822
address {{ ip4pub.address }}
1923
netmask {{ ip4pub.netmask }}
@@ -25,6 +29,7 @@ iface bond0 inet static
2529
{% endif %}
2630
dns-nameservers {{ resolvers | join(" ") }}
2731

32+
{% endif %}
2833
bond-downdelay 200
2934
bond-miimon 100
3035
bond-mode {{ net.bonding.mode }}
@@ -33,7 +38,8 @@ iface bond0 inet static
3338
{% if osinfo.distro == 'ubuntu' and net.bonding.mode == 4 %}
3439
bond-lacp-rate 1
3540
{% endif %}
36-
bond-slaves {{ interfaces | selectattr('bond', 'in', '["bond0"]') | map(attribute='name') | join(' ')}}
41+
bond-slaves {{ bonds[bond] | map(attribute='name') | sort | join(' ') }}
42+
{% if bond == "bond0" %}
3743
{% if ip6pub %}
3844

3945
iface bond0 inet6 static
@@ -52,3 +58,5 @@ iface bond0:0 inet static
5258
post-down route del -net {{ subnet }} gw {{ ip4priv.gateway }}
5359
{% endfor %}
5460
{% endif %}
61+
{% endif %}
62+
{% endfor %}

packetnetworking/distros/debian/test_bonded.py

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ def test_public_bonded_task_etc_network_interfaces(
6464
result += dedent(partial)
6565
if distro == "ubuntu":
6666
result += " bond-lacp-rate 1\n"
67-
result += f""" bond-slaves {' '.join([iface.name for iface in builder.network.interfaces if iface.bond == "bond0"])}\n"""
67+
result += f""" bond-slaves {' '.join(sorted(nic.name for nic in builder.network.bonds["bond0"]))}\n"""
68+
6869
partial = f"""
6970
iface bond0 inet6 static
7071
address {ipv6pub.address}
@@ -79,6 +80,24 @@ def test_public_bonded_task_etc_network_interfaces(
7980
post-down route del -net 10.0.0.0/8 gw {ipv4priv.gateway}
8081
"""
8182
result += dedent(partial)
83+
84+
for bond, members in builder.network.bonds.items():
85+
if bond == "bond0":
86+
continue
87+
88+
partial = f"""
89+
auto {bond}
90+
iface {bond} inet static
91+
bond-downdelay 200
92+
bond-miimon 100
93+
bond-mode {bonding_mode}
94+
bond-updelay 200
95+
bond-xmit_hash_policy layer3+4
96+
"""
97+
result += dedent(partial)
98+
if distro == "ubuntu":
99+
result += " bond-lacp-rate 1\n"
100+
result += f" bond-slaves {' '.join(sorted(nic.name for nic in members))}\n"
82101
assert tasks["etc/network/interfaces"] == result
83102

84103

@@ -135,8 +154,25 @@ def test_private_bonded_task_etc_network_interfaces(
135154
result += dedent(partial)
136155
if distro == "ubuntu":
137156
result += " bond-lacp-rate 1\n"
138-
result += f""" bond-slaves {' '.join([iface.name for iface in builder.network.interfaces if iface.bond == "bond0"])}\n"""
157+
result += f" bond-slaves {' '.join(sorted(nic.name for nic in builder.network.bonds['bond0']))}\n"
158+
159+
for bond, members in builder.network.bonds.items():
160+
if bond == "bond0":
161+
continue
139162

163+
partial = f"""
164+
auto {bond}
165+
iface {bond} inet static
166+
bond-downdelay 200
167+
bond-miimon 100
168+
bond-mode {bonding_mode}
169+
bond-updelay 200
170+
bond-xmit_hash_policy layer3+4
171+
"""
172+
result += dedent(partial)
173+
if distro == "ubuntu":
174+
result += " bond-lacp-rate 1\n"
175+
result += f" bond-slaves {' '.join(sorted(nic.name for nic in members))}\n"
140176
assert tasks["etc/network/interfaces"] == result
141177

142178

@@ -194,7 +230,7 @@ def test_public_bonded_task_etc_network_interfaces_with_custom_private_ip_space(
194230
if distro == "ubuntu":
195231
result += " bond-lacp-rate 1\n"
196232

197-
result += f""" bond-slaves {' '.join([iface.name for iface in builder.network.interfaces if iface.bond == "bond0"])}\n"""
233+
result += f""" bond-slaves {' '.join(sorted(nic.name for nic in builder.network.bonds["bond0"]))}\n"""
198234
partial = f"""
199235
iface bond0 inet6 static
200236
address {ipv6pub.address}
@@ -211,6 +247,24 @@ def test_public_bonded_task_etc_network_interfaces_with_custom_private_ip_space(
211247
post-down route del -net 172.16.0.0/12 gw {ipv4priv.gateway}
212248
"""
213249
result += dedent(partial)
250+
251+
for bond, members in builder.network.bonds.items():
252+
if bond == "bond0":
253+
continue
254+
255+
partial = f"""
256+
auto {bond}
257+
iface {bond} inet static
258+
bond-downdelay 200
259+
bond-miimon 100
260+
bond-mode {bonding_mode}
261+
bond-updelay 200
262+
bond-xmit_hash_policy layer3+4
263+
"""
264+
result += dedent(partial)
265+
if distro == "ubuntu":
266+
result += " bond-lacp-rate 1\n"
267+
result += f" bond-slaves {' '.join(sorted(nic.name for nic in members))}\n"
214268
assert tasks["etc/network/interfaces"] == result
215269

216270

@@ -269,7 +323,25 @@ def test_private_bonded_task_etc_network_interfaces_with_custom_private_ip_space
269323
if distro == "ubuntu":
270324
result += " bond-lacp-rate 1\n"
271325

272-
result += f""" bond-slaves {' '.join([iface.name for iface in builder.network.interfaces if iface.bond == "bond0"])}\n"""
326+
result += f""" bond-slaves {' '.join(sorted(nic.name for nic in builder.network.bonds["bond0"]))}\n"""
327+
328+
for bond, members in builder.network.bonds.items():
329+
if bond == "bond0":
330+
continue
331+
332+
partial = f"""
333+
auto {bond}
334+
iface {bond} inet static
335+
bond-downdelay 200
336+
bond-miimon 100
337+
bond-mode {bonding_mode}
338+
bond-updelay 200
339+
bond-xmit_hash_policy layer3+4
340+
"""
341+
result += dedent(partial)
342+
if distro == "ubuntu":
343+
result += " bond-lacp-rate 1\n"
344+
result += f" bond-slaves {' '.join(sorted(nic.name for nic in members))}\n"
273345
assert tasks["etc/network/interfaces"] == result
274346

275347

packetnetworking/distros/distro_builder.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
import re
23
import sys
34
import logging
45
import json
@@ -73,6 +74,7 @@ def build_tasks(self):
7374

7475
def context(self):
7576
return {
77+
"bonds": self.network.bonds,
7678
"hostname": self.metadata.hostname,
7779
"iface0": self.network.interfaces[0],
7880
"interfaces": self.network.interfaces,
@@ -153,14 +155,17 @@ def render(self):
153155
tmpl.environment.globals.update(generated_header=utils.generated_header)
154156

155157
try:
158+
content = tmpl.render(context)
159+
# replace multiple empty lines with just one
160+
content = re.sub(r"\n+(?=\n)", "\n", content)
156161
if file_mode or mode:
157162
rendered_tasks[path] = {
158163
"file_mode": file_mode,
159164
"mode": mode,
160-
"content": tmpl.render(context),
165+
"content": content,
161166
}
162167
else:
163-
rendered_tasks[path] = tmpl.render(context)
168+
rendered_tasks[path] = content
164169
except UndefinedError:
165170
# having to use print as log.* isn't printing out the json
166171
print(

packetnetworking/distros/test_distro_builder.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ def test_distro_builder_context_as_expected(fake_distro_builder_with_metadata):
175175
fake_distro = fake_distro_builder_with_metadata()
176176
context = fake_distro.context()
177177
wanted_context = {
178+
"bonds": fake_distro.network.bonds,
178179
"hostname": fake_distro.metadata.hostname,
179180
"iface0": fake_distro.network.interfaces[0],
180181
"interfaces": fake_distro.network.interfaces,

0 commit comments

Comments
 (0)