Merge ~larsks/cloud-init:lp/1665441 into cloud-init:master

Proposed by Lars Kellogg-Stedman
Status: Merged
Merged at revision: f81d6c7bde2af206d449de593b35773068270c84
Proposed branch: ~larsks/cloud-init:lp/1665441
Merge into: cloud-init:master
Diff against target: 123 lines (+88/-3)
2 files modified
cloudinit/net/sysconfig.py (+2/-2)
tests/unittests/test_net.py (+86/-1)
Reviewer Review Type Date Requested Status
cloud-init Commiters Pending
Review via email: mp+317553@code.launchpad.net

Description of the change

This corrects the problem reported in #1665441. The resulting files are incompatible with NetworkManager, but will work correctly in a legacy networking environment.

To post a comment you must log in.
Revision history for this message
Scott Moser (smoser) wrote :

Lars,
Thanks so much for investigating and finding a fix.

I hate it when I provide a fix for a bug in someone's code and they ask for a unit test.

That said...
A unit test here will avoid a regression in the future. Could you add one?

If you don't add one, then I'm going to, and it will just take me longer to pull it.

~larsks/cloud-init:lp/1665441 updated
5e8bd6b... by Lars Kellogg-Stedman

unit tests for #1665441

This adds inputs and outputs to OS_SAMPLES to test the code path for a
network configuration that provides multiple subnets on the same
interface. This test will fail until the fix for #1665441 is
committed.

LP: #1665441

Revision history for this message
Lars Kellogg-Stedman (larsks) wrote :

I've added a unit test.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index 9be7407..19e220a 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -283,10 +283,10 @@ class Renderer(renderer.Renderer):
283 cls._render_subnet(iface_cfg, route_cfg, iface_subnets[0])283 cls._render_subnet(iface_cfg, route_cfg, iface_subnets[0])
284 elif len(iface_subnets) > 1:284 elif len(iface_subnets) > 1:
285 for i, iface_subnet in enumerate(iface_subnets,285 for i, iface_subnet in enumerate(iface_subnets,
286 start=len(iface.children)):286 start=len(iface_cfg.children)):
287 iface_sub_cfg = iface_cfg.copy()287 iface_sub_cfg = iface_cfg.copy()
288 iface_sub_cfg.name = "%s:%s" % (iface_name, i)288 iface_sub_cfg.name = "%s:%s" % (iface_name, i)
289 iface.children.append(iface_sub_cfg)289 iface_cfg.children.append(iface_sub_cfg)
290 cls._render_subnet(iface_sub_cfg, route_cfg, iface_subnet)290 cls._render_subnet(iface_sub_cfg, route_cfg, iface_subnet)
291291
292 @classmethod292 @classmethod
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index b77d277..1b6288d 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -163,6 +163,91 @@ nameserver 172.19.0.12
163 ('etc/udev/rules.d/70-persistent-net.rules',163 ('etc/udev/rules.d/70-persistent-net.rules',
164 "".join(['SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ',164 "".join(['SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ',
165 'ATTR{address}=="fa:16:3e:ed:9a:59", NAME="eth0"\n']))]165 'ATTR{address}=="fa:16:3e:ed:9a:59", NAME="eth0"\n']))]
166 },
167 {
168 'in_data': {
169 "services": [{"type": "dns", "address": "172.19.0.12"}],
170 "networks": [{
171 "network_id": "public-ipv4",
172 "type": "ipv4", "netmask": "255.255.252.0",
173 "link": "tap1a81968a-79",
174 "routes": [{
175 "netmask": "0.0.0.0",
176 "network": "0.0.0.0",
177 "gateway": "172.19.3.254",
178 }],
179 "ip_address": "172.19.1.34", "id": "network0"
180 },{
181 "network_id": "private-ipv4",
182 "type": "ipv4", "netmask": "255.255.255.0",
183 "link": "tap1a81968a-79",
184 "routes": [],
185 "ip_address": "10.0.0.10", "id": "network1"
186 }],
187 "links": [
188 {
189 "ethernet_mac_address": "fa:16:3e:ed:9a:59",
190 "mtu": None, "type": "bridge", "id":
191 "tap1a81968a-79",
192 "vif_id": "1a81968a-797a-400f-8a80-567f997eb93f"
193 },
194 ],
195 },
196 'in_macs': {
197 'fa:16:3e:ed:9a:59': 'eth0',
198 },
199 'out_sysconfig': [
200 ('etc/sysconfig/network-scripts/ifcfg-eth0',
201 """
202# Created by cloud-init on instance boot automatically, do not edit.
203#
204BOOTPROTO=none
205DEVICE=eth0
206HWADDR=fa:16:3e:ed:9a:59
207NM_CONTROLLED=no
208ONBOOT=yes
209TYPE=Ethernet
210USERCTL=no
211""".lstrip()),
212 ('etc/sysconfig/network-scripts/ifcfg-eth0:0',
213 """
214# Created by cloud-init on instance boot automatically, do not edit.
215#
216BOOTPROTO=static
217DEFROUTE=yes
218DEVICE=eth0:0
219GATEWAY=172.19.3.254
220HWADDR=fa:16:3e:ed:9a:59
221IPADDR=172.19.1.34
222NETMASK=255.255.252.0
223NM_CONTROLLED=no
224ONBOOT=yes
225TYPE=Ethernet
226USERCTL=no
227""".lstrip()),
228 ('etc/sysconfig/network-scripts/ifcfg-eth0:1',
229 """
230# Created by cloud-init on instance boot automatically, do not edit.
231#
232BOOTPROTO=static
233DEVICE=eth0:1
234HWADDR=fa:16:3e:ed:9a:59
235IPADDR=10.0.0.10
236NETMASK=255.255.255.0
237NM_CONTROLLED=no
238ONBOOT=yes
239TYPE=Ethernet
240USERCTL=no
241""".lstrip()),
242 ('etc/resolv.conf',
243 """
244; Created by cloud-init on instance boot automatically, do not edit.
245;
246nameserver 172.19.0.12
247""".lstrip()),
248 ('etc/udev/rules.d/70-persistent-net.rules',
249 "".join(['SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ',
250 'ATTR{address}=="fa:16:3e:ed:9a:59", NAME="eth0"\n']))]
166 }251 }
167]252]
168253
@@ -529,8 +614,8 @@ USERCTL=no
529 self.assertEqual(expected_content, content)614 self.assertEqual(expected_content, content)
530615
531 def test_openstack_rendering_samples(self):616 def test_openstack_rendering_samples(self):
532 render_dir = self.tmp_dir()
533 for os_sample in OS_SAMPLES:617 for os_sample in OS_SAMPLES:
618 render_dir = self.tmp_dir()
534 ex_input = os_sample['in_data']619 ex_input = os_sample['in_data']
535 ex_mac_addrs = os_sample['in_macs']620 ex_mac_addrs = os_sample['in_macs']
536 network_cfg = openstack.convert_net_json(621 network_cfg = openstack.convert_net_json(

Subscribers

People subscribed via source and target branches