Merge ~raharper/cloud-init:curtin-centos into cloud-init:master

Proposed by Ryan Harper
Status: Merged
Merged at revision: 7e41b2a773b81452f14a18ec8c4f3316a66d3f5e
Proposed branch: ~raharper/cloud-init:curtin-centos
Merge into: cloud-init:master
Diff against target: 357 lines (+232/-3)
4 files modified
cloudinit/net/eni.py (+1/-1)
cloudinit/net/sysconfig.py (+18/-0)
cloudinit/sources/DataSourceAzure.py (+1/-1)
tests/unittests/test_net.py (+212/-1)
Reviewer Review Type Date Requested Status
cloud-init Commiters Pending
Review via email: mp+327648@code.launchpad.net

Description of the change

WIP branch with changes for el6/el7 networking rendering

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

I pulled:

Your-commit trunk-comt summary
8da074f831c d1e8eb73ac sysconfig: include GATEWAY value if set in subnet

changes:
i shorted lines in commit messages and made tox tests pass (had to add the newly rendered GATEWAY values) to more than the one test you did it to.

$ git diff 8da074f831c..d1e8eb73ac | pastebinit -f diff
http://paste.ubuntu.com/25121124/

Revision history for this message
Ryan Harper (raharper) wrote :

Not sure that's right (I Think it should be IPV6_GATEWAY0)

On Tue, Jul 18, 2017 at 4:09 PM, Scott Moser <email address hidden> wrote:

> I pulled:
>
> Your-commit trunk-comt summary
> 8da074f831c d1e8eb73ac sysconfig: include GATEWAY value if set in subnet
>
> changes:
> i shorted lines in commit messages and made tox tests pass (had to add the
> newly rendered GATEWAY values) to more than the one test you did it to.
>
> $ git diff 8da074f831c..d1e8eb73ac | pastebinit -f diff
> http://paste.ubuntu.com/25121124/
>
> --
> https://code.launchpad.net/~raharper/cloud-init/+git/
> cloud-init/+merge/327648
> You are the owner of ~raharper/cloud-init:curtin-centos.
>

Revision history for this message
Scott Moser (smoser) wrote :

i took your commit
  Use prefix for ipv6 and set v4 and v6 gateway keys, use DEFROUTE

and put up
 https://code.launchpad.net/~smoser/cloud-init/+git/cloud-init/+merge/327739

Revision history for this message
Scott Moser (smoser) wrote :

your commit
 Templatize systemd service files
is modified and up at
 https://code.launchpad.net/~smoser/cloud-init/+git/cloud-init/+merge/327743

Revision history for this message
Scott Moser (smoser) wrote :

merge for your
 Fix sysconfig rendering of virtual interfaces with network configurations
is up at
 https://code.launchpad.net/~smoser/cloud-init/+git/cloud-init/+merge/327821

i plan on adding a vlan and a simple bridge test.

Revision history for this message
Scott Moser (smoser) wrote :

merge for
   sysconfig: fix ipv6 gateway routes
at
  https://code.launchpad.net/~smoser/cloud-init/+git/cloud-init/+merge/327828

Revision history for this message
Scott Moser (smoser) wrote :
~raharper/cloud-init:curtin-centos updated
14f552e... by Ryan Harper

sysconfig: use MACADDR on bonds/bridges to configure mac_address

Previously, sysconfig rendered HWADDR for all interface types, but
that value is only used to identify physical devices. Instead use
MACADDR to configure the MAC on virtual devices, like bonds and
bridges.

- Sort bond slave list to ensure consistent ordering in sysconfig
  rendered files.
- Add unittests for sysconfig rendering of bonds/bridges with
  mac_address

LP: #1701417

Revision history for this message
Scott Moser (smoser) wrote :

https://code.launchpad.net/~smoser/cloud-init/+git/cloud-init/+merge/327836
has
 sysconfig: enable mtu set per subnet, including ipv6 mtu
and then
 net: eni route rendering missed ipv6 default route config

~raharper/cloud-init:curtin-centos updated
8bf9253... by Ryan Harper

sysconfig: enable mtu set per subnet, including ipv6 mtu

Render MTU values if present in subnet and route configurations
for v4 and v6.

LP: #1702513

Revision history for this message
Scott Moser (smoser) wrote :

marked as merged as we have these all now in trunk.
thanks Ryan

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/net/eni.py b/cloudinit/net/eni.py
2index b707146..bb80ec0 100644
3--- a/cloudinit/net/eni.py
4+++ b/cloudinit/net/eni.py
5@@ -355,7 +355,7 @@ class Renderer(renderer.Renderer):
6 default_gw = " default gw %s" % route['gateway']
7 content.append(up + default_gw + or_true)
8 content.append(down + default_gw + or_true)
9- elif route['network'] == '::' and route['netmask'] == 0:
10+ elif route['network'] == '::' and route['prefix'] == 0:
11 # ipv6!
12 default_gw = " -A inet6 default gw %s" % route['gateway']
13 content.append(up + default_gw + or_true)
14diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
15index b0f2ccf..e4490c4 100644
16--- a/cloudinit/net/sysconfig.py
17+++ b/cloudinit/net/sysconfig.py
18@@ -264,6 +264,9 @@ class Renderer(renderer.Renderer):
19 for (old_key, new_key) in [('mac_address', 'HWADDR'), ('mtu', 'MTU')]:
20 old_value = iface.get(old_key)
21 if old_value is not None:
22+ # only set HWADDR on physical interfaces
23+ if old_key == 'mac_address' and iface['type'] != 'physical':
24+ continue
25 iface_cfg[new_key] = old_value
26
27 @classmethod
28@@ -273,6 +276,7 @@ class Renderer(renderer.Renderer):
29
30 # modifying base values according to subnets
31 for i, subnet in enumerate(subnets, start=len(iface_cfg.children)):
32+ mtu_key = 'MTU'
33 subnet_type = subnet.get('type')
34 if subnet_type == 'dhcp6':
35 iface_cfg['IPV6INIT'] = True
36@@ -292,7 +296,13 @@ class Renderer(renderer.Renderer):
37 # if iface_cfg['BOOTPROTO'] == 'none':
38 # iface_cfg['BOOTPROTO'] = 'static'
39 if subnet_is_ipv6(subnet):
40+ mtu_key = 'IPV6_MTU'
41 iface_cfg['IPV6INIT'] = True
42+ if 'mtu' in subnet:
43+ iface_cfg[mtu_key] = subnet['mtu']
44+
45+ elif subnet_type == 'manual':
46+ iface_cfg['ONBOOT'] = False
47 else:
48 raise ValueError("Unknown subnet type '%s' found"
49 " for interface '%s'" % (subnet_type,
50@@ -425,6 +435,9 @@ class Renderer(renderer.Renderer):
51 master_cfg['BONDING_MASTER'] = True
52 master_cfg.kind = 'bond'
53
54+ if 'mac_address' in iface and iface.get('mac_address'):
55+ iface_cfg['MACADDR'] = iface.get('mac_address')
56+
57 iface_subnets = iface.get("subnets", [])
58 route_cfg = iface_cfg.routes
59 cls._render_subnets(iface_cfg, iface_subnets)
60@@ -436,6 +449,7 @@ class Renderer(renderer.Renderer):
61 [slave_iface['name'] for slave_iface in
62 network_state.iter_interfaces(slave_filter)
63 if slave_iface['bond-master'] == iface_name])
64+
65 for index, bond_slave in enumerate(bond_slaves):
66 slavestr = 'BONDING_SLAVE%s' % index
67 iface_cfg[slavestr] = bond_slave
68@@ -494,6 +508,10 @@ class Renderer(renderer.Renderer):
69 for old_key, new_key in cls.bridge_opts_keys:
70 if old_key in iface:
71 iface_cfg[new_key] = iface[old_key]
72+
73+ if 'mac_address' in iface and iface.get('mac_address'):
74+ iface_cfg['MACADDR'] = iface.get('mac_address')
75+
76 # Is this the right key to get all the connected interfaces?
77 for bridged_iface_name in iface.get('bridge_ports', []):
78 # Ensure all bridged interfaces are correctly tagged
79diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
80index b5a95a1..e02d7a7 100644
81--- a/cloudinit/sources/DataSourceAzure.py
82+++ b/cloudinit/sources/DataSourceAzure.py
83@@ -442,7 +442,7 @@ class DataSourceAzure(sources.DataSource):
84 self.ds_cfg['agent_command'])
85 try:
86 fabric_data = metadata_func()
87- except Exception as exc:
88+ except Exception:
89 LOG.warning(
90 "Error communicating with Azure fabric; You may experience."
91 "connectivity issues.", exc_info=True)
92diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
93index e625934..4e05a82 100644
94--- a/tests/unittests/test_net.py
95+++ b/tests/unittests/test_net.py
96@@ -422,6 +422,31 @@ NETWORK_CONFIGS = {
97 via: 65.61.151.37
98 set-name: eth99
99 """).rstrip(' '),
100+ 'expected_sysconfig': {
101+ 'ifcfg-eth1': textwrap.dedent("""\
102+ # Created by cloud-init on instance boot automatically, do not edit.
103+ #
104+ BOOTPROTO=none
105+ DEVICE=eth1
106+ HWADDR=cf:d6:af:48:e8:80
107+ NM_CONTROLLED=no
108+ ONBOOT=yes
109+ TYPE=Ethernet
110+ USERCTL=no""").rstrip(' '),
111+ 'ifcfg-eth99': textwrap.dedent("""\
112+ # Created by cloud-init on instance boot automatically, do not edit.
113+ #
114+ BOOTPROTO=dhcp
115+ DEFROUTE=yes
116+ DEVICE=eth99
117+ GATEWAY=65.61.151.37
118+ HWADDR=c0:d6:9f:2c:e8:80
119+ IPADDR=192.168.21.3
120+ NETMASK=255.255.255.0
121+ NM_CONTROLLED=no
122+ ONBOOT=yes
123+ TYPE=Ethernet
124+ USERCTL=no """).rstrip(' ')},
125 'yaml': textwrap.dedent("""
126 version: 1
127 config:
128@@ -541,6 +566,8 @@ iface br0 inet static
129 # control-alias br0
130 iface br0 inet6 static
131 address 2001:1::1/64
132+ post-up route add -A inet6 default gw 2001:4800:78ff:1b::1 || true
133+ pre-down route del -A inet6 default gw 2001:4800:78ff:1b::1 || true
134
135 auto bond0.200
136 iface bond0.200 inet dhcp
137@@ -675,6 +702,9 @@ pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true
138 eth3: 50
139 eth4: 75
140 priority: 22
141+ routes:
142+ - to: ::/0
143+ via: 2001:4800:78ff:1b::1
144 vlans:
145 bond0.200:
146 dhcp4: true
147@@ -697,6 +727,146 @@ pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true
148 - sacchromyces.maas
149 - brettanomyces.maas
150 """).rstrip(' '),
151+ 'expected_sysconfig': {
152+ 'ifcfg-bond0': textwrap.dedent("""\
153+ # Created by cloud-init on instance boot automatically, do not edit.
154+ #
155+ BONDING_MASTER=yes
156+ BONDING_OPTS="mode=active-backup xmit_hash_policy=layer3+4 miimon=100"
157+ BONDING_SLAVE0=eth1
158+ BONDING_SLAVE1=eth2
159+ BOOTPROTO=dhcp
160+ DEVICE=bond0
161+ DHCPV6C=yes
162+ IPV6INIT=yes
163+ MACADDR=aa:bb:cc:dd:ee:ff
164+ NM_CONTROLLED=no
165+ ONBOOT=yes
166+ TYPE=Bond
167+ USERCTL=no
168+ """).rstrip(' '),
169+ 'ifcfg-bond0.200': textwrap.dedent("""\
170+ # Created by cloud-init on instance boot automatically, do not edit.
171+ #
172+ BOOTPROTO=dhcp
173+ DEVICE=bond0.200
174+ NM_CONTROLLED=no
175+ ONBOOT=yes
176+ PHYSDEV=bond0
177+ TYPE=Ethernet
178+ USERCTL=no
179+ VLAN=yes
180+ """).rstrip(' '),
181+ 'ifcfg-br0': textwrap.dedent("""\
182+ # Created by cloud-init on instance boot automatically, do not edit.
183+ #
184+ AGEING=250
185+ BOOTPROTO=none
186+ DEFROUTE=yes
187+ DEVICE=br0
188+ IPADDR=192.168.14.2
189+ IPV6ADDR=2001:1::1/64
190+ IPV6INIT=yes
191+ IPV6_DEFAULTGW=2001:4800:78ff:1b::1
192+ NETMASK=255.255.255.0
193+ NM_CONTROLLED=no
194+ ONBOOT=yes
195+ PRIO=22
196+ STP=off
197+ TYPE=Bridge
198+ USERCTL=no
199+ """).rstrip(' '),
200+ 'ifcfg-eth0': textwrap.dedent("""\
201+ # Created by cloud-init on instance boot automatically, do not edit.
202+ #
203+ BOOTPROTO=none
204+ DEVICE=eth0
205+ HWADDR=c0:d6:9f:2c:e8:80
206+ NM_CONTROLLED=no
207+ ONBOOT=yes
208+ TYPE=Ethernet
209+ USERCTL=no
210+ """).rstrip(' '),
211+ 'ifcfg-eth0.101': textwrap.dedent("""\
212+ # Created by cloud-init on instance boot automatically, do not edit.
213+ #
214+ BOOTPROTO=none
215+ DEFROUTE=yes
216+ DEVICE=eth0.101
217+ GATEWAY=192.168.0.1
218+ IPADDR=192.168.0.2
219+ IPADDR1=192.168.2.10
220+ MTU=1500
221+ NETMASK=255.255.255.0
222+ NETMASK1=255.255.255.0
223+ NM_CONTROLLED=no
224+ ONBOOT=yes
225+ PHYSDEV=eth0
226+ TYPE=Ethernet
227+ USERCTL=no
228+ VLAN=yes
229+ """).rstrip(' '),
230+ 'ifcfg-eth1': textwrap.dedent("""\
231+ # Created by cloud-init on instance boot automatically, do not edit.
232+ #
233+ BOOTPROTO=none
234+ DEVICE=eth1
235+ HWADDR=aa:d6:9f:2c:e8:80
236+ MASTER=bond0
237+ NM_CONTROLLED=no
238+ ONBOOT=yes
239+ SLAVE=yes
240+ TYPE=Ethernet
241+ USERCTL=no
242+ """).rstrip(' '),
243+ 'ifcfg-eth2': textwrap.dedent("""\
244+ # Created by cloud-init on instance boot automatically, do not edit.
245+ #
246+ BOOTPROTO=none
247+ DEVICE=eth2
248+ HWADDR=c0:bb:9f:2c:e8:80
249+ MASTER=bond0
250+ NM_CONTROLLED=no
251+ ONBOOT=yes
252+ SLAVE=yes
253+ TYPE=Ethernet
254+ USERCTL=no
255+ """).rstrip(' '),
256+ 'ifcfg-eth3': textwrap.dedent("""\
257+ # Created by cloud-init on instance boot automatically, do not edit.
258+ #
259+ BOOTPROTO=none
260+ BRIDGE=br0
261+ DEVICE=eth3
262+ HWADDR=66:bb:9f:2c:e8:80
263+ NM_CONTROLLED=no
264+ ONBOOT=yes
265+ TYPE=Ethernet
266+ USERCTL=no
267+ """).rstrip(' '),
268+ 'ifcfg-eth4': textwrap.dedent("""\
269+ # Created by cloud-init on instance boot automatically, do not edit.
270+ #
271+ BOOTPROTO=none
272+ BRIDGE=br0
273+ DEVICE=eth4
274+ HWADDR=98:bb:9f:2c:e8:80
275+ NM_CONTROLLED=no
276+ ONBOOT=yes
277+ TYPE=Ethernet
278+ USERCTL=no
279+ """).rstrip(' '),
280+ 'ifcfg-eth5': textwrap.dedent("""\
281+ # Created by cloud-init on instance boot automatically, do not edit.
282+ #
283+ BOOTPROTO=dhcp
284+ DEVICE=eth5
285+ HWADDR=98:bb:9f:2c:e8:8a
286+ NM_CONTROLLED=no
287+ ONBOOT=no
288+ TYPE=Ethernet
289+ USERCTL=no
290+ """).rstrip(' ')},
291 'yaml': textwrap.dedent("""
292 version: 1
293 config:
294@@ -807,6 +977,10 @@ pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true
295 address: 192.168.14.2/24
296 - type: static
297 address: 2001:1::1/64 # default to /64
298+ routes:
299+ - gateway: 2001:4800:78ff:1b::1
300+ netmask: '::'
301+ network: '::'
302 # A global nameserver.
303 - type: nameserver
304 address: 8.8.8.8
305@@ -869,7 +1043,7 @@ pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true
306 DEFROUTE=yes
307 DEVICE=bond0
308 GATEWAY=192.168.0.1
309- HWADDR=aa:bb:cc:dd:e8:ff
310+ MACADDR=aa:bb:cc:dd:e8:ff
311 IPADDR=192.168.0.2
312 IPADDR1=192.168.1.2
313 IPV6ADDR=2001:1::1/92
314@@ -2004,6 +2178,43 @@ class TestEniRoundTrip(CiTestCase):
315 expected, [line for line in found if line])
316
317
318+class TestSysconfigRoundTrip(CiTestCase):
319+ def _render_and_read(self, network_config=None, state=None, dir=None):
320+ if dir is None:
321+ dir = self.tmp_dir()
322+
323+ if network_config:
324+ ns = network_state.parse_net_config_data(network_config)
325+ elif state:
326+ ns = state
327+ else:
328+ raise ValueError("Expected data or state, got neither")
329+
330+ renderer = sysconfig.Renderer()
331+ renderer.render_network_state(ns, dir)
332+ return dir2dict(dir)
333+
334+ def testsimple_render_small(self):
335+ entry = NETWORK_CONFIGS['small']
336+ files = self._render_and_read(network_config=yaml.load(entry['yaml']))
337+ expected_sysconfig = entry.get('expected_sysconfig')
338+ for ifcfg_name in expected_sysconfig:
339+ expected_ifcfg = expected_sysconfig.get(ifcfg_name)
340+ ifcfg_path = '/etc/sysconfig/network-scripts/' + ifcfg_name
341+ self.assertEqual(expected_ifcfg.splitlines(),
342+ files[ifcfg_path].splitlines())
343+
344+ def testsimple_render_all(self):
345+ entry = NETWORK_CONFIGS['all']
346+ files = self._render_and_read(network_config=yaml.load(entry['yaml']))
347+ expected_sysconfig = entry.get('expected_sysconfig')
348+ for ifcfg_name in expected_sysconfig:
349+ expected_ifcfg = expected_sysconfig.get(ifcfg_name)
350+ ifcfg_path = '/etc/sysconfig/network-scripts/' + ifcfg_name
351+ self.assertEqual(expected_ifcfg.splitlines(),
352+ files[ifcfg_path].splitlines())
353+
354+
355 class TestNetRenderers(CiTestCase):
356 @mock.patch("cloudinit.net.renderers.sysconfig.available")
357 @mock.patch("cloudinit.net.renderers.eni.available")

Subscribers

People subscribed via source and target branches