Merge ~akaris/cloud-init:bug1679817 into cloud-init:master
- Git
- lp:~akaris/cloud-init
- bug1679817
- Merge into master
Status: | Superseded |
---|---|
Proposed branch: | ~akaris/cloud-init:bug1679817 |
Merge into: | cloud-init:master |
Diff against target: |
452 lines (+193/-133) 3 files modified
cloudinit/net/sysconfig.py (+168/-71) tests/unittests/test_distros/test_netconfig.py (+3/-5) tests/unittests/test_net.py (+22/-57) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Server Team CI bot | continuous-integration | Approve | |
cloud-init Commiters | Pending | ||
Review via email: mp+323082@code.launchpad.net |
This proposal supersedes a proposal from 2017-04-24.
Commit message
Fix dual stack IPv4/IPv6 configuration for RHEL
Dual stack IPv4/IPv6 configuration via config drive is broken for RHEL7.
This patch fixes several scenarios for IPv4/IPv6/dual stack with multiple IP assignment
Removes unpopular IPv4 alias files and invalid IPv6 alias files
Also fixes associated unit tests
Description of the change
Fix dual stack IPv4/IPv6 configuration for RHEL
Dual stack IPv4/IPv6 configuration via config drive is broken for RHEL7.
This patch fixes several scenarios for IPv4/IPv6/dual stack with multiple IP assignment
Removes unpopular IPv4 alias files and invalid IPv6 alias files
Also fixes associated unit tests
Server Team CI bot (server-team-bot) wrote : Posted in a previous version of this proposal | # |
Server Team CI bot (server-team-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:9ad5280dcc5
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:a94ded7f67e
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:a94ded7f67e
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:46c35411fd7
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 5a0bc13... by Andreas Karis
-
fix for flake
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:5a0bc1350a8
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
- 025f52b... by Andreas Karis
-
consolidated to_string_ipv4 and to_string_ipv6
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:025f52bc8f3
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Unmerged commits
- 025f52b... by Andreas Karis
-
consolidated to_string_ipv4 and to_string_ipv6
- 5a0bc13... by Andreas Karis
-
fix for flake
- 46c3541... by Andreas Karis
-
cleanup for flake
- 23c7007... by Andreas Karis
-
cleanup for flake
- a94ded7... by Andreas Karis
-
Moved IPv6 routes to route6-
- 7569e43... by Andreas Karis
-
added route handling for ipv4 and ipv6 routes
- 2d818c2... by Andreas Karis
-
wrapped str around netmask in cases it is integer
- 9ad5280... by Andreas Karis
-
Remove BOOTPROTO=static and make it BOOTPROTO=none as it should be
- e43facb... by Andreas Karis
- ca539b9... by Andreas Karis
-
fix1
Preview Diff
1 | diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py |
2 | index 504e4d0..49da3a3 100644 |
3 | --- a/cloudinit/net/sysconfig.py |
4 | +++ b/cloudinit/net/sysconfig.py |
5 | @@ -59,6 +59,9 @@ class ConfigMap(object): |
6 | def __setitem__(self, key, value): |
7 | self._conf[key] = value |
8 | |
9 | + def __getitem__(self, key): |
10 | + return self._conf[key] |
11 | + |
12 | def drop(self, key): |
13 | self._conf.pop(key, None) |
14 | |
15 | @@ -83,7 +86,8 @@ class ConfigMap(object): |
16 | class Route(ConfigMap): |
17 | """Represents a route configuration.""" |
18 | |
19 | - route_fn_tpl = '%(base)s/network-scripts/route-%(name)s' |
20 | + route_fn_tpl_ipv4 = '%(base)s/network-scripts/route-%(name)s' |
21 | + route_fn_tpl_ipv6 = '%(base)s/network-scripts/route6-%(name)s' |
22 | |
23 | def __init__(self, route_name, base_sysconf_dir): |
24 | super(Route, self).__init__() |
25 | @@ -102,9 +106,53 @@ class Route(ConfigMap): |
26 | return r |
27 | |
28 | @property |
29 | - def path(self): |
30 | - return self.route_fn_tpl % ({'base': self._base_sysconf_dir, |
31 | - 'name': self._route_name}) |
32 | + def path_ipv4(self): |
33 | + return self.route_fn_tpl_ipv4 % ({'base': self._base_sysconf_dir, |
34 | + 'name': self._route_name}) |
35 | + |
36 | + @property |
37 | + def path_ipv6(self): |
38 | + return self.route_fn_tpl_ipv6 % ({'base': self._base_sysconf_dir, |
39 | + 'name': self._route_name}) |
40 | + |
41 | + def is_ipv6_route(self, address): |
42 | + return ':' in address |
43 | + |
44 | + def to_string(self, proto="ipv4"): |
45 | + buf = six.StringIO() |
46 | + buf.write(_make_header()) |
47 | + if self._conf: |
48 | + buf.write("\n") |
49 | + # need to reindex IPv4 addresses |
50 | + # (because Route can contain a mix of IPv4 and IPv6) |
51 | + reindex = -1 |
52 | + for key in sorted(self._conf.keys()): |
53 | + if 'ADDRESS' in key: |
54 | + index = key.replace('ADDRESS', '') |
55 | + address_value = str(self._conf[key]) |
56 | + # only accept combinations: |
57 | + # ipv6 route and proto ipv6 |
58 | + # ipv4 route and proto ipv4 |
59 | + # do not add any other routes |
60 | + if proto == "ipv4" and not self.is_ipv6_route(address_value): |
61 | + netmask_value = str(self._conf['NETMASK' + index]) |
62 | + gateway_value = str(self._conf['GATEWAY' + index]) |
63 | + # increase IPv4 index |
64 | + reindex = reindex + 1 |
65 | + buf.write("%s=%s\n" % ('ADDRESS' + str(reindex), |
66 | + _quote_value(address_value))) |
67 | + buf.write("%s=%s\n" % ('GATEWAY' + str(reindex), |
68 | + _quote_value(gateway_value))) |
69 | + buf.write("%s=%s\n" % ('NETMASK' + str(reindex), |
70 | + _quote_value(netmask_value))) |
71 | + elif proto == "ipv6" and self.is_ipv6_route(address_value): |
72 | + netmask_value = str(self._conf['NETMASK' + index]) |
73 | + gateway_value = str(self._conf['GATEWAY' + index]) |
74 | + buf.write("%s/%s via %s\n" % (address_value, |
75 | + netmask_value, |
76 | + gateway_value)) |
77 | + |
78 | + return buf.getvalue() |
79 | |
80 | |
81 | class NetInterface(ConfigMap): |
82 | @@ -211,65 +259,117 @@ class Renderer(renderer.Renderer): |
83 | iface_cfg[new_key] = old_value |
84 | |
85 | @classmethod |
86 | - def _render_subnet(cls, iface_cfg, route_cfg, subnet): |
87 | - subnet_type = subnet.get('type') |
88 | - if subnet_type == 'dhcp6': |
89 | - iface_cfg['DHCPV6C'] = True |
90 | - iface_cfg['IPV6INIT'] = True |
91 | - iface_cfg['BOOTPROTO'] = 'dhcp' |
92 | - elif subnet_type in ['dhcp4', 'dhcp']: |
93 | - iface_cfg['BOOTPROTO'] = 'dhcp' |
94 | - elif subnet_type == 'static': |
95 | - iface_cfg['BOOTPROTO'] = 'static' |
96 | - if subnet_is_ipv6(subnet): |
97 | - iface_cfg['IPV6ADDR'] = subnet['address'] |
98 | + def _render_subnets(cls, iface_cfg, subnets): |
99 | + # setting base values |
100 | + iface_cfg['BOOTPROTO'] = 'none' |
101 | + |
102 | + # modifying base values according to subnets |
103 | + for i, subnet in enumerate(subnets, start=len(iface_cfg.children)): |
104 | + subnet_type = subnet.get('type') |
105 | + if subnet_type == 'dhcp6': |
106 | iface_cfg['IPV6INIT'] = True |
107 | + iface_cfg['DHCPV6C'] = True |
108 | + iface_cfg['BOOTPROTO'] = 'dhcp' |
109 | + elif subnet_type in ['dhcp4', 'dhcp']: |
110 | + iface_cfg['BOOTPROTO'] = 'dhcp' |
111 | + elif subnet_type == 'static': |
112 | + # grep BOOTPROTO sysconfig.txt -A2 | head -3 |
113 | + # BOOTPROTO=none|bootp|dhcp |
114 | + # 'bootp' or 'dhcp' cause a DHCP client |
115 | + # to run on the device. Any other |
116 | + # value causes any static configuration |
117 | + # in the file to be applied. |
118 | + # ==> the following should not be set to 'static' |
119 | + # but should remain 'none' |
120 | + # if iface_cfg['BOOTPROTO'] == 'none': |
121 | + # iface_cfg['BOOTPROTO'] = 'static' |
122 | + if subnet_is_ipv6(subnet): |
123 | + iface_cfg['IPV6INIT'] = True |
124 | else: |
125 | - iface_cfg['IPADDR'] = subnet['address'] |
126 | - else: |
127 | - raise ValueError("Unknown subnet type '%s' found" |
128 | - " for interface '%s'" % (subnet_type, |
129 | - iface_cfg.name)) |
130 | - if 'netmask' in subnet: |
131 | - iface_cfg['NETMASK'] = subnet['netmask'] |
132 | - for route in subnet.get('routes', []): |
133 | - if subnet.get('ipv6'): |
134 | - gw_cfg = 'IPV6_DEFAULTGW' |
135 | - else: |
136 | - gw_cfg = 'GATEWAY' |
137 | - |
138 | - if _is_default_route(route): |
139 | - if ( |
140 | - (subnet.get('ipv4') and |
141 | - route_cfg.has_set_default_ipv4) or |
142 | - (subnet.get('ipv6') and |
143 | - route_cfg.has_set_default_ipv6) |
144 | - ): |
145 | - raise ValueError("Duplicate declaration of default " |
146 | - "route found for interface '%s'" |
147 | - % (iface_cfg.name)) |
148 | - # NOTE(harlowja): ipv6 and ipv4 default gateways |
149 | - gw_key = 'GATEWAY0' |
150 | - nm_key = 'NETMASK0' |
151 | - addr_key = 'ADDRESS0' |
152 | - # The owning interface provides the default route. |
153 | - # |
154 | - # TODO(harlowja): add validation that no other iface has |
155 | - # also provided the default route? |
156 | - iface_cfg['DEFROUTE'] = True |
157 | - if 'gateway' in route: |
158 | - iface_cfg[gw_cfg] = route['gateway'] |
159 | - route_cfg.has_set_default = True |
160 | - else: |
161 | - gw_key = 'GATEWAY%s' % route_cfg.last_idx |
162 | - nm_key = 'NETMASK%s' % route_cfg.last_idx |
163 | - addr_key = 'ADDRESS%s' % route_cfg.last_idx |
164 | - route_cfg.last_idx += 1 |
165 | - for (old_key, new_key) in [('gateway', gw_key), |
166 | - ('netmask', nm_key), |
167 | - ('network', addr_key)]: |
168 | - if old_key in route: |
169 | - route_cfg[new_key] = route[old_key] |
170 | + raise ValueError("Unknown subnet type '%s' found" |
171 | + " for interface '%s'" % (subnet_type, |
172 | + iface_cfg.name)) |
173 | + |
174 | + # set IPv4 and IPv6 static addresses |
175 | + ipv4_index = -1 |
176 | + ipv6_index = -1 |
177 | + for i, subnet in enumerate(subnets, start=len(iface_cfg.children)): |
178 | + subnet_type = subnet.get('type') |
179 | + if subnet_type == 'dhcp6': |
180 | + continue |
181 | + elif subnet_type in ['dhcp4', 'dhcp']: |
182 | + continue |
183 | + elif subnet_type == 'static': |
184 | + if subnet_is_ipv6(subnet): |
185 | + ipv6_index = ipv6_index + 1 |
186 | + if 'netmask' in subnet and str(subnet['netmask']) != "": |
187 | + ipv6_cidr = (subnet['address'] + |
188 | + '/' + |
189 | + str(subnet['netmask'])) |
190 | + else: |
191 | + ipv6_cidr = subnet['address'] |
192 | + if ipv6_index == 0: |
193 | + iface_cfg['IPV6ADDR'] = ipv6_cidr |
194 | + elif ipv6_index == 1: |
195 | + iface_cfg['IPV6ADDR_SECONDARIES'] = ipv6_cidr |
196 | + else: |
197 | + iface_cfg['IPV6ADDR_SECONDARIES'] = ( |
198 | + iface_cfg['IPV6ADDR_SECONDARIES'] + |
199 | + " " + ipv6_cidr) |
200 | + else: |
201 | + ipv4_index = ipv4_index + 1 |
202 | + if ipv4_index == 0: |
203 | + iface_cfg['IPADDR'] = subnet['address'] |
204 | + if 'netmask' in subnet: |
205 | + iface_cfg['NETMASK'] = subnet['netmask'] |
206 | + else: |
207 | + iface_cfg['IPADDR' + str(ipv4_index)] = \ |
208 | + subnet['address'] |
209 | + if 'netmask' in subnet: |
210 | + iface_cfg['NETMASK' + str(ipv4_index)] = \ |
211 | + subnet['netmask'] |
212 | + |
213 | + @classmethod |
214 | + def _render_subnet_routes(cls, iface_cfg, route_cfg, subnets): |
215 | + for i, subnet in enumerate(subnets, start=len(iface_cfg.children)): |
216 | + for route in subnet.get('routes', []): |
217 | + if subnet.get('ipv6'): |
218 | + gw_cfg = 'IPV6_DEFAULTGW' |
219 | + else: |
220 | + gw_cfg = 'GATEWAY' |
221 | + |
222 | + if _is_default_route(route): |
223 | + if ( |
224 | + (subnet.get('ipv4') and |
225 | + route_cfg.has_set_default_ipv4) or |
226 | + (subnet.get('ipv6') and |
227 | + route_cfg.has_set_default_ipv6) |
228 | + ): |
229 | + raise ValueError("Duplicate declaration of default " |
230 | + "route found for interface '%s'" |
231 | + % (iface_cfg.name)) |
232 | + # NOTE(harlowja): ipv6 and ipv4 default gateways |
233 | + gw_key = 'GATEWAY0' |
234 | + nm_key = 'NETMASK0' |
235 | + addr_key = 'ADDRESS0' |
236 | + # The owning interface provides the default route. |
237 | + # |
238 | + # TODO(harlowja): add validation that no other iface has |
239 | + # also provided the default route? |
240 | + iface_cfg['DEFROUTE'] = True |
241 | + if 'gateway' in route: |
242 | + iface_cfg[gw_cfg] = route['gateway'] |
243 | + route_cfg.has_set_default = True |
244 | + else: |
245 | + gw_key = 'GATEWAY%s' % route_cfg.last_idx |
246 | + nm_key = 'NETMASK%s' % route_cfg.last_idx |
247 | + addr_key = 'ADDRESS%s' % route_cfg.last_idx |
248 | + route_cfg.last_idx += 1 |
249 | + for (old_key, new_key) in [('gateway', gw_key), |
250 | + ('netmask', nm_key), |
251 | + ('network', addr_key)]: |
252 | + if old_key in route: |
253 | + route_cfg[new_key] = route[old_key] |
254 | |
255 | @classmethod |
256 | def _render_bonding_opts(cls, iface_cfg, iface): |
257 | @@ -295,15 +395,9 @@ class Renderer(renderer.Renderer): |
258 | iface_subnets = iface.get("subnets", []) |
259 | iface_cfg = iface_contents[iface_name] |
260 | route_cfg = iface_cfg.routes |
261 | - if len(iface_subnets) == 1: |
262 | - cls._render_subnet(iface_cfg, route_cfg, iface_subnets[0]) |
263 | - elif len(iface_subnets) > 1: |
264 | - for i, isubnet in enumerate(iface_subnets, |
265 | - start=len(iface_cfg.children)): |
266 | - iface_sub_cfg = iface_cfg.copy() |
267 | - iface_sub_cfg.name = "%s:%s" % (iface_name, i) |
268 | - iface_cfg.children.append(iface_sub_cfg) |
269 | - cls._render_subnet(iface_sub_cfg, route_cfg, isubnet) |
270 | + |
271 | + cls._render_subnets(iface_cfg, iface_subnets) |
272 | + cls._render_subnet_routes(iface_cfg, route_cfg, iface_subnets) |
273 | |
274 | @classmethod |
275 | def _render_bond_interfaces(cls, network_state, iface_contents): |
276 | @@ -387,7 +481,10 @@ class Renderer(renderer.Renderer): |
277 | if iface_cfg: |
278 | contents[iface_cfg.path] = iface_cfg.to_string() |
279 | if iface_cfg.routes: |
280 | - contents[iface_cfg.routes.path] = iface_cfg.routes.to_string() |
281 | + contents[iface_cfg.routes.path_ipv4] = \ |
282 | + iface_cfg.routes.to_string("ipv4") |
283 | + contents[iface_cfg.routes.path_ipv6] = \ |
284 | + iface_cfg.routes.to_string("ipv6") |
285 | return contents |
286 | |
287 | def render_network_state(self, network_state, target=None): |
288 | diff --git a/tests/unittests/test_distros/test_netconfig.py b/tests/unittests/test_distros/test_netconfig.py |
289 | index 8837066..6d6b985 100644 |
290 | --- a/tests/unittests/test_distros/test_netconfig.py |
291 | +++ b/tests/unittests/test_distros/test_netconfig.py |
292 | @@ -431,7 +431,7 @@ NETWORKING=yes |
293 | expected_buf = ''' |
294 | # Created by cloud-init on instance boot automatically, do not edit. |
295 | # |
296 | -BOOTPROTO=static |
297 | +BOOTPROTO=none |
298 | DEVICE=eth0 |
299 | IPADDR=192.168.1.5 |
300 | NETMASK=255.255.255.0 |
301 | @@ -488,7 +488,6 @@ NETWORKING=yes |
302 | mock.patch.object(util, 'load_file', return_value='')) |
303 | mocks.enter_context( |
304 | mock.patch.object(os.path, 'isfile', return_value=False)) |
305 | - |
306 | rh_distro.apply_network(BASE_NET_CFG_IPV6, False) |
307 | |
308 | self.assertEqual(len(write_bufs), 4) |
309 | @@ -581,11 +580,10 @@ IPV6_AUTOCONF=no |
310 | expected_buf = ''' |
311 | # Created by cloud-init on instance boot automatically, do not edit. |
312 | # |
313 | -BOOTPROTO=static |
314 | +BOOTPROTO=none |
315 | DEVICE=eth0 |
316 | -IPV6ADDR=2607:f0d0:1002:0011::2 |
317 | +IPV6ADDR=2607:f0d0:1002:0011::2/64 |
318 | IPV6INIT=yes |
319 | -NETMASK=64 |
320 | NM_CONTROLLED=no |
321 | ONBOOT=yes |
322 | TYPE=Ethernet |
323 | diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py |
324 | index 89e7536..1157c95 100644 |
325 | --- a/tests/unittests/test_net.py |
326 | +++ b/tests/unittests/test_net.py |
327 | @@ -136,7 +136,7 @@ OS_SAMPLES = [ |
328 | """ |
329 | # Created by cloud-init on instance boot automatically, do not edit. |
330 | # |
331 | -BOOTPROTO=static |
332 | +BOOTPROTO=none |
333 | DEFROUTE=yes |
334 | DEVICE=eth0 |
335 | GATEWAY=172.19.3.254 |
336 | @@ -204,38 +204,14 @@ nameserver 172.19.0.12 |
337 | # Created by cloud-init on instance boot automatically, do not edit. |
338 | # |
339 | BOOTPROTO=none |
340 | -DEVICE=eth0 |
341 | -HWADDR=fa:16:3e:ed:9a:59 |
342 | -NM_CONTROLLED=no |
343 | -ONBOOT=yes |
344 | -TYPE=Ethernet |
345 | -USERCTL=no |
346 | -""".lstrip()), |
347 | - ('etc/sysconfig/network-scripts/ifcfg-eth0:0', |
348 | - """ |
349 | -# Created by cloud-init on instance boot automatically, do not edit. |
350 | -# |
351 | -BOOTPROTO=static |
352 | DEFROUTE=yes |
353 | -DEVICE=eth0:0 |
354 | +DEVICE=eth0 |
355 | GATEWAY=172.19.3.254 |
356 | HWADDR=fa:16:3e:ed:9a:59 |
357 | IPADDR=172.19.1.34 |
358 | +IPADDR1=10.0.0.10 |
359 | NETMASK=255.255.252.0 |
360 | -NM_CONTROLLED=no |
361 | -ONBOOT=yes |
362 | -TYPE=Ethernet |
363 | -USERCTL=no |
364 | -""".lstrip()), |
365 | - ('etc/sysconfig/network-scripts/ifcfg-eth0:1', |
366 | - """ |
367 | -# Created by cloud-init on instance boot automatically, do not edit. |
368 | -# |
369 | -BOOTPROTO=static |
370 | -DEVICE=eth0:1 |
371 | -HWADDR=fa:16:3e:ed:9a:59 |
372 | -IPADDR=10.0.0.10 |
373 | -NETMASK=255.255.255.0 |
374 | +NETMASK1=255.255.255.0 |
375 | NM_CONTROLLED=no |
376 | ONBOOT=yes |
377 | TYPE=Ethernet |
378 | @@ -265,7 +241,7 @@ nameserver 172.19.0.12 |
379 | }], |
380 | "ip_address": "172.19.1.34", "id": "network0" |
381 | }, { |
382 | - "network_id": "public-ipv6", |
383 | + "network_id": "public-ipv6-a", |
384 | "type": "ipv6", "netmask": "", |
385 | "link": "tap1a81968a-79", |
386 | "routes": [ |
387 | @@ -276,6 +252,20 @@ nameserver 172.19.0.12 |
388 | } |
389 | ], |
390 | "ip_address": "2001:DB8::10", "id": "network1" |
391 | + }, { |
392 | + "network_id": "public-ipv6-b", |
393 | + "type": "ipv6", "netmask": "64", |
394 | + "link": "tap1a81968a-79", |
395 | + "routes": [ |
396 | + ], |
397 | + "ip_address": "2001:DB9::10", "id": "network2" |
398 | + }, { |
399 | + "network_id": "public-ipv6-c", |
400 | + "type": "ipv6", "netmask": "64", |
401 | + "link": "tap1a81968a-79", |
402 | + "routes": [ |
403 | + ], |
404 | + "ip_address": "2001:DB10::10", "id": "network3" |
405 | }], |
406 | "links": [ |
407 | { |
408 | @@ -295,41 +285,16 @@ nameserver 172.19.0.12 |
409 | # Created by cloud-init on instance boot automatically, do not edit. |
410 | # |
411 | BOOTPROTO=none |
412 | -DEVICE=eth0 |
413 | -HWADDR=fa:16:3e:ed:9a:59 |
414 | -NM_CONTROLLED=no |
415 | -ONBOOT=yes |
416 | -TYPE=Ethernet |
417 | -USERCTL=no |
418 | -""".lstrip()), |
419 | - ('etc/sysconfig/network-scripts/ifcfg-eth0:0', |
420 | - """ |
421 | -# Created by cloud-init on instance boot automatically, do not edit. |
422 | -# |
423 | -BOOTPROTO=static |
424 | DEFROUTE=yes |
425 | -DEVICE=eth0:0 |
426 | +DEVICE=eth0 |
427 | GATEWAY=172.19.3.254 |
428 | HWADDR=fa:16:3e:ed:9a:59 |
429 | IPADDR=172.19.1.34 |
430 | -NETMASK=255.255.252.0 |
431 | -NM_CONTROLLED=no |
432 | -ONBOOT=yes |
433 | -TYPE=Ethernet |
434 | -USERCTL=no |
435 | -""".lstrip()), |
436 | - ('etc/sysconfig/network-scripts/ifcfg-eth0:1', |
437 | - """ |
438 | -# Created by cloud-init on instance boot automatically, do not edit. |
439 | -# |
440 | -BOOTPROTO=static |
441 | -DEFROUTE=yes |
442 | -DEVICE=eth0:1 |
443 | -HWADDR=fa:16:3e:ed:9a:59 |
444 | IPV6ADDR=2001:DB8::10 |
445 | +IPV6ADDR_SECONDARIES="2001:DB9::10/64 2001:DB10::10/64" |
446 | IPV6INIT=yes |
447 | IPV6_DEFAULTGW=2001:DB8::1 |
448 | -NETMASK= |
449 | +NETMASK=255.255.252.0 |
450 | NM_CONTROLLED=no |
451 | ONBOOT=yes |
452 | TYPE=Ethernet |
FAILED: Continuous integration, rev:e43facbb2b0 b0e88e16c45c8b1 ed14c621bdf3ad /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 263/ /jenkins. ubuntu. com/server/ job/cloud- init-ci/ nodes=metal- amd64/263/ console /jenkins. ubuntu. com/server/ job/cloud- init-ci/ nodes=metal- arm64/263/ console /jenkins. ubuntu. com/server/ job/cloud- init-ci/ nodes=metal- ppc64el/ 263/console /jenkins. ubuntu. com/server/ job/cloud- init-ci/ nodes=metal- s390x/263/ console /jenkins. ubuntu. com/server/ job/cloud- init-ci/ nodes=vm- i386/263/ console
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 263/rebuild
https:/