Merge ~chad.smith/cloud-init:bug/17746666-netplan-mtu-on-bonds into cloud-init:master
- Git
- lp:~chad.smith/cloud-init
- bug/17746666-netplan-mtu-on-bonds
- Merge into master
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Chad Smith | ||||
Approved revision: | 51388607f3dd3e4b3ce9c8a50c804f01c0eabbed | ||||
Merge reported by: | Chad Smith | ||||
Merged at revision: | c3f1ad9abd4a28c1b4c1f34db28ac72a646cdca6 | ||||
Proposed branch: | ~chad.smith/cloud-init:bug/17746666-netplan-mtu-on-bonds | ||||
Merge into: | cloud-init:master | ||||
Diff against target: |
340 lines (+91/-12) 6 files modified
cloudinit/net/eni.py (+17/-3) cloudinit/net/netplan.py (+14/-8) cloudinit/net/sysconfig.py (+7/-0) doc/rtd/topics/network-config-format-v1.rst (+27/-0) doc/rtd/topics/network-config-format-v2.rst (+6/-0) tests/unittests/test_net.py (+20/-1) |
||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Server Team CI bot | continuous-integration | Approve | |
Ryan Harper | Needs Fixing | ||
Review via email: mp+347559@code.launchpad.net |
Commit message
netplan: fix mtu if provided by network config for all rendered types
When network configuration for any interface defines maximum transmission
values (MTU) the netplan, eni and sysconfig renders will take into account
any device-level, or subnet-level mtu values.
When network configuration has conflicting device-level and ipv4 subnet
mtu values, the subnet-specific value is honored and a warning will be
logged about any ignored device-level setting.
LP: #1774666
Description of the change
Server Team CI bot (server-team-bot) wrote : | # |
- 6956c65... by Chad Smith
-
netplan: render bond and vlan mtu if provided by network config
When network configuration for vlan and bond interfaces declare
mtu values, the netplan renderer will pass those config values
into netplan.LP: #1774666
- 4eb1912... by Chad Smith
-
rtd docs adding mtu to bond and vlan
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:885901fd730
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
FAILED: Ubuntu LTS: Integration
Click here to trigger a rebuild:
https:/
Ryan Harper (raharper) wrote : | # |
Let's doing this generically in the _extract_addresses method; that gets called on all types.
diff --git a/cloudinit/
index 6344348..817f415 100644
--- a/cloudinit/
+++ b/cloudinit/
@@ -124,6 +124,9 @@ def _extract_
+ if 'mtu' in config:
+ entry.update(
+
if len(addresses) > 0:
if len(routes) > 0:
- 51004fc... by Chad Smith
-
address review commment handle mtu config settings in comment _extract_addresses function
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:f9fa0a562ed
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
FAILED: Ubuntu LTS: Integration
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:bf2c1d564f8
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
SUCCESS: Ubuntu LTS: Integration
SUCCESS: MAAS Compatability Testing
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
- 8470eef... by Chad Smith
-
use subnet's ipv4 mtu over device-level mtu config
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:8c6c6fbe3bd
https:/
Executed test runs:
SUCCESS: Checkout
FAILED: Unit & Style Tests
Click here to trigger a rebuild:
https:/
Ryan Harper (raharper) wrote : | # |
This looks good, likely needs a sysconfig update for this path as well.
- 12c7a50... by Chad Smith
-
pycodestyle fix
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:12c7a50095c
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
SUCCESS: Ubuntu LTS: Integration
SUCCESS: MAAS Compatability Testing
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
- 10a79a4... by Chad Smith
-
sysconfig should also emit a warning if device-level mtu is provided and ipv4-subnet also provided
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:10a79a40dae
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
SUCCESS: Ubuntu LTS: Integration
SUCCESS: MAAS Compatability Testing
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
Ryan Harper (raharper) wrote : | # |
Let's only warn if the mtu values differ between device/subnet values.
- 9b946e1... by Chad Smith
-
net render: only warn if device-level mtu != subnet-level mtu
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:9b946e16376
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
SUCCESS: Ubuntu LTS: Integration
SUCCESS: MAAS Compatability Testing
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
- e4486d4... by Chad Smith
-
Add an assert that we only emit warnings when device-level mtu does not match subnet-level mtu if both are present.
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:e4486d4a33a
https:/
Executed test runs:
SUCCESS: Checkout
FAILED: Unit & Style Tests
Click here to trigger a rebuild:
https:/
Ryan Harper (raharper) wrote : | # |
Let's update the commit message to indicate that generally we're fixing mtu value rendering in netplan (that covers all types), For the docs, move the MTU value under the Common settings; since it is indeed common in netplan (and now in how we apply config).
Lastly mention that we now detect and log a warning if a per-subnet mtu value differs from an mtu setting on the device.
- 0cef9d1... by Chad Smith
-
drop debug maxDiff
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:0cef9d16945
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
SUCCESS: Ubuntu LTS: Integration
SUCCESS: MAAS Compatability Testing
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
- 5138860... by Chad Smith
-
add mtu config docs to common netplan rtd
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:51388607f3d
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
SUCCESS: Ubuntu LTS: Integration
SUCCESS: MAAS Compatability Testing
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
Chad Smith (chad.smith) wrote : | # |
An upstream commit landed for this bug.
To view that commit see the following URL:
https:/
Preview Diff
1 | diff --git a/cloudinit/net/eni.py b/cloudinit/net/eni.py |
2 | index c6a71d1..bd20a36 100644 |
3 | --- a/cloudinit/net/eni.py |
4 | +++ b/cloudinit/net/eni.py |
5 | @@ -10,9 +10,12 @@ from . import ParserError |
6 | from . import renderer |
7 | from .network_state import subnet_is_ipv6 |
8 | |
9 | +from cloudinit import log as logging |
10 | from cloudinit import util |
11 | |
12 | |
13 | +LOG = logging.getLogger(__name__) |
14 | + |
15 | NET_CONFIG_COMMANDS = [ |
16 | "pre-up", "up", "post-up", "down", "pre-down", "post-down", |
17 | ] |
18 | @@ -61,7 +64,7 @@ def _iface_add_subnet(iface, subnet): |
19 | |
20 | |
21 | # TODO: switch to valid_map for attrs |
22 | -def _iface_add_attrs(iface, index): |
23 | +def _iface_add_attrs(iface, index, ipv4_subnet_mtu): |
24 | # If the index is non-zero, this is an alias interface. Alias interfaces |
25 | # represent additional interface addresses, and should not have additional |
26 | # attributes. (extra attributes here are almost always either incorrect, |
27 | @@ -100,6 +103,13 @@ def _iface_add_attrs(iface, index): |
28 | value = 'on' if iface[key] else 'off' |
29 | if not value or key in ignore_map: |
30 | continue |
31 | + if key == 'mtu' and ipv4_subnet_mtu: |
32 | + if value != ipv4_subnet_mtu: |
33 | + LOG.warning( |
34 | + "Network config: ignoring %s device-level mtu:%s because" |
35 | + " ipv4 subnet-level mtu:%s provided.", |
36 | + iface['name'], value, ipv4_subnet_mtu) |
37 | + continue |
38 | if key in multiline_keys: |
39 | for v in value: |
40 | content.append(" {0} {1}".format(renames.get(key, key), v)) |
41 | @@ -377,12 +387,15 @@ class Renderer(renderer.Renderer): |
42 | subnets = iface.get('subnets', {}) |
43 | if subnets: |
44 | for index, subnet in enumerate(subnets): |
45 | + ipv4_subnet_mtu = None |
46 | iface['index'] = index |
47 | iface['mode'] = subnet['type'] |
48 | iface['control'] = subnet.get('control', 'auto') |
49 | subnet_inet = 'inet' |
50 | if subnet_is_ipv6(subnet): |
51 | subnet_inet += '6' |
52 | + else: |
53 | + ipv4_subnet_mtu = subnet.get('mtu') |
54 | iface['inet'] = subnet_inet |
55 | if subnet['type'].startswith('dhcp'): |
56 | iface['mode'] = 'dhcp' |
57 | @@ -397,7 +410,7 @@ class Renderer(renderer.Renderer): |
58 | _iface_start_entry( |
59 | iface, index, render_hwaddress=render_hwaddress) + |
60 | _iface_add_subnet(iface, subnet) + |
61 | - _iface_add_attrs(iface, index) |
62 | + _iface_add_attrs(iface, index, ipv4_subnet_mtu) |
63 | ) |
64 | for route in subnet.get('routes', []): |
65 | lines.extend(self._render_route(route, indent=" ")) |
66 | @@ -409,7 +422,8 @@ class Renderer(renderer.Renderer): |
67 | if 'bond-master' in iface or 'bond-slaves' in iface: |
68 | lines.append("auto {name}".format(**iface)) |
69 | lines.append("iface {name} {inet} {mode}".format(**iface)) |
70 | - lines.extend(_iface_add_attrs(iface, index=0)) |
71 | + lines.extend( |
72 | + _iface_add_attrs(iface, index=0, ipv4_subnet_mtu=None)) |
73 | sections.append(lines) |
74 | return sections |
75 | |
76 | diff --git a/cloudinit/net/netplan.py b/cloudinit/net/netplan.py |
77 | index 6344348..4014363 100644 |
78 | --- a/cloudinit/net/netplan.py |
79 | +++ b/cloudinit/net/netplan.py |
80 | @@ -34,7 +34,7 @@ def _get_params_dict_by_match(config, match): |
81 | if key.startswith(match)) |
82 | |
83 | |
84 | -def _extract_addresses(config, entry): |
85 | +def _extract_addresses(config, entry, ifname): |
86 | """This method parse a cloudinit.net.network_state dictionary (config) and |
87 | maps netstate keys/values into a dictionary (entry) to represent |
88 | netplan yaml. |
89 | @@ -124,6 +124,15 @@ def _extract_addresses(config, entry): |
90 | |
91 | addresses.append(addr) |
92 | |
93 | + if 'mtu' in config: |
94 | + entry_mtu = entry.get('mtu') |
95 | + if entry_mtu and config['mtu'] != entry_mtu: |
96 | + LOG.warning( |
97 | + "Network config: ignoring %s device-level mtu:%s because" |
98 | + " ipv4 subnet-level mtu:%s provided.", |
99 | + ifname, config['mtu'], entry_mtu) |
100 | + else: |
101 | + entry['mtu'] = config['mtu'] |
102 | if len(addresses) > 0: |
103 | entry.update({'addresses': addresses}) |
104 | if len(routes) > 0: |
105 | @@ -262,10 +271,7 @@ class Renderer(renderer.Renderer): |
106 | else: |
107 | del eth['match'] |
108 | del eth['set-name'] |
109 | - if 'mtu' in ifcfg: |
110 | - eth['mtu'] = ifcfg.get('mtu') |
111 | - |
112 | - _extract_addresses(ifcfg, eth) |
113 | + _extract_addresses(ifcfg, eth, ifname) |
114 | ethernets.update({ifname: eth}) |
115 | |
116 | elif if_type == 'bond': |
117 | @@ -288,7 +294,7 @@ class Renderer(renderer.Renderer): |
118 | slave_interfaces = ifcfg.get('bond-slaves') |
119 | if slave_interfaces == 'none': |
120 | _extract_bond_slaves_by_name(interfaces, bond, ifname) |
121 | - _extract_addresses(ifcfg, bond) |
122 | + _extract_addresses(ifcfg, bond, ifname) |
123 | bonds.update({ifname: bond}) |
124 | |
125 | elif if_type == 'bridge': |
126 | @@ -321,7 +327,7 @@ class Renderer(renderer.Renderer): |
127 | |
128 | if len(br_config) > 0: |
129 | bridge.update({'parameters': br_config}) |
130 | - _extract_addresses(ifcfg, bridge) |
131 | + _extract_addresses(ifcfg, bridge, ifname) |
132 | bridges.update({ifname: bridge}) |
133 | |
134 | elif if_type == 'vlan': |
135 | @@ -333,7 +339,7 @@ class Renderer(renderer.Renderer): |
136 | macaddr = ifcfg.get('mac_address', None) |
137 | if macaddr is not None: |
138 | vlan['macaddress'] = macaddr.lower() |
139 | - _extract_addresses(ifcfg, vlan) |
140 | + _extract_addresses(ifcfg, vlan, ifname) |
141 | vlans.update({ifname: vlan}) |
142 | |
143 | # inject global nameserver values under each all interface which |
144 | diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py |
145 | index e53b9f1..3d71923 100644 |
146 | --- a/cloudinit/net/sysconfig.py |
147 | +++ b/cloudinit/net/sysconfig.py |
148 | @@ -304,6 +304,13 @@ class Renderer(renderer.Renderer): |
149 | mtu_key = 'IPV6_MTU' |
150 | iface_cfg['IPV6INIT'] = True |
151 | if 'mtu' in subnet: |
152 | + mtu_mismatch = bool(mtu_key in iface_cfg and |
153 | + subnet['mtu'] != iface_cfg[mtu_key]) |
154 | + if mtu_mismatch: |
155 | + LOG.warning( |
156 | + 'Network config: ignoring %s device-level mtu:%s' |
157 | + ' because ipv4 subnet-level mtu:%s provided.', |
158 | + iface_cfg.name, iface_cfg[mtu_key], subnet['mtu']) |
159 | iface_cfg[mtu_key] = subnet['mtu'] |
160 | elif subnet_type == 'manual': |
161 | # If the subnet has an MTU setting, then ONBOOT=True |
162 | diff --git a/doc/rtd/topics/network-config-format-v1.rst b/doc/rtd/topics/network-config-format-v1.rst |
163 | index 2f8ab54..3b0148c 100644 |
164 | --- a/doc/rtd/topics/network-config-format-v1.rst |
165 | +++ b/doc/rtd/topics/network-config-format-v1.rst |
166 | @@ -130,6 +130,18 @@ the bond interfaces. |
167 | The ``bond_interfaces`` key accepts a list of network device ``name`` values |
168 | from the configuration. This list may be empty. |
169 | |
170 | +**mtu**: *<MTU SizeBytes>* |
171 | + |
172 | +The MTU key represents a device's Maximum Transmission Unit, the largest size |
173 | +packet or frame, specified in octets (eight-bit bytes), that can be sent in a |
174 | +packet- or frame-based network. Specifying ``mtu`` is optional. |
175 | + |
176 | +.. note:: |
177 | + |
178 | + The possible supported values of a device's MTU is not available at |
179 | + configuration time. It's possible to specify a value too large or to |
180 | + small for a device and may be ignored by the device. |
181 | + |
182 | **params**: *<Dictionary of key: value bonding parameter pairs>* |
183 | |
184 | The ``params`` key in a bond holds a dictionary of bonding parameters. |
185 | @@ -268,6 +280,21 @@ Type ``vlan`` requires the following keys: |
186 | - ``vlan_link``: Specify the underlying link via its ``name``. |
187 | - ``vlan_id``: Specify the VLAN numeric id. |
188 | |
189 | +The following optional keys are supported: |
190 | + |
191 | +**mtu**: *<MTU SizeBytes>* |
192 | + |
193 | +The MTU key represents a device's Maximum Transmission Unit, the largest size |
194 | +packet or frame, specified in octets (eight-bit bytes), that can be sent in a |
195 | +packet- or frame-based network. Specifying ``mtu`` is optional. |
196 | + |
197 | +.. note:: |
198 | + |
199 | + The possible supported values of a device's MTU is not available at |
200 | + configuration time. It's possible to specify a value too large or to |
201 | + small for a device and may be ignored by the device. |
202 | + |
203 | + |
204 | **VLAN Example**:: |
205 | |
206 | network: |
207 | diff --git a/doc/rtd/topics/network-config-format-v2.rst b/doc/rtd/topics/network-config-format-v2.rst |
208 | index 335d236..ea370ef 100644 |
209 | --- a/doc/rtd/topics/network-config-format-v2.rst |
210 | +++ b/doc/rtd/topics/network-config-format-v2.rst |
211 | @@ -174,6 +174,12 @@ recognized by ``inet_pton(3)`` |
212 | Example for IPv4: ``gateway4: 172.16.0.1`` |
213 | Example for IPv6: ``gateway6: 2001:4::1`` |
214 | |
215 | +**mtu**: *<MTU SizeBytes>* |
216 | + |
217 | +The MTU key represents a device's Maximum Transmission Unit, the largest size |
218 | +packet or frame, specified in octets (eight-bit bytes), that can be sent in a |
219 | +packet- or frame-based network. Specifying ``mtu`` is optional. |
220 | + |
221 | **nameservers**: *<(mapping)>* |
222 | |
223 | Set DNS servers and search domains, for manual address configuration. There |
224 | diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py |
225 | index e13ca3c..5ab61cf 100644 |
226 | --- a/tests/unittests/test_net.py |
227 | +++ b/tests/unittests/test_net.py |
228 | @@ -525,6 +525,7 @@ NETWORK_CONFIGS = { |
229 | config: |
230 | - type: 'physical' |
231 | name: 'iface0' |
232 | + mtu: 8999 |
233 | subnets: |
234 | - type: static |
235 | address: 192.168.14.2/24 |
236 | @@ -660,8 +661,8 @@ iface eth0.101 inet static |
237 | dns-nameservers 192.168.0.10 10.23.23.134 |
238 | dns-search barley.maas sacchromyces.maas brettanomyces.maas |
239 | gateway 192.168.0.1 |
240 | - hwaddress aa:bb:cc:dd:ee:11 |
241 | mtu 1500 |
242 | + hwaddress aa:bb:cc:dd:ee:11 |
243 | vlan-raw-device eth0 |
244 | vlan_id 101 |
245 | |
246 | @@ -757,6 +758,7 @@ pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true |
247 | id: 101 |
248 | link: eth0 |
249 | macaddress: aa:bb:cc:dd:ee:11 |
250 | + mtu: 1500 |
251 | nameservers: |
252 | addresses: |
253 | - 192.168.0.10 |
254 | @@ -920,6 +922,8 @@ pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true |
255 | mtu: 1500 |
256 | subnets: |
257 | - type: static |
258 | + # When 'mtu' matches device-level mtu, no warnings |
259 | + mtu: 1500 |
260 | address: 192.168.0.2/24 |
261 | gateway: 192.168.0.1 |
262 | dns_nameservers: |
263 | @@ -1028,6 +1032,7 @@ pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true |
264 | - type: bond |
265 | name: bond0 |
266 | mac_address: "aa:bb:cc:dd:e8:ff" |
267 | + mtu: 9000 |
268 | bond_interfaces: |
269 | - bond0s0 |
270 | - bond0s1 |
271 | @@ -1070,6 +1075,7 @@ pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true |
272 | interfaces: |
273 | - bond0s0 |
274 | - bond0s1 |
275 | + mtu: 9000 |
276 | parameters: |
277 | mii-monitor-interval: 100 |
278 | mode: active-backup |
279 | @@ -1157,6 +1163,7 @@ pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true |
280 | IPADDR1=192.168.1.2 |
281 | IPV6ADDR=2001:1::1/92 |
282 | IPV6INIT=yes |
283 | + MTU=9000 |
284 | NETMASK=255.255.255.0 |
285 | NETMASK1=255.255.255.0 |
286 | NM_CONTROLLED=no |
287 | @@ -1203,6 +1210,7 @@ pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true |
288 | name: en0 |
289 | mac_address: "aa:bb:cc:dd:e8:00" |
290 | - type: vlan |
291 | + mtu: 2222 |
292 | name: en0.99 |
293 | vlan_link: en0 |
294 | vlan_id: 99 |
295 | @@ -1238,6 +1246,7 @@ pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true |
296 | IPV6ADDR=2001:1::bbbb/96 |
297 | IPV6INIT=yes |
298 | IPV6_DEFAULTGW=2001:1::1 |
299 | + MTU=2222 |
300 | NETMASK=255.255.255.0 |
301 | NETMASK1=255.255.255.0 |
302 | NM_CONTROLLED=no |
303 | @@ -1669,6 +1678,8 @@ iface eth1 inet dhcp |
304 | |
305 | class TestSysConfigRendering(CiTestCase): |
306 | |
307 | + with_logs = True |
308 | + |
309 | scripts_dir = '/etc/sysconfig/network-scripts' |
310 | header = ('# Created by cloud-init on instance boot automatically, ' |
311 | 'do not edit.\n#\n') |
312 | @@ -1917,6 +1928,9 @@ USERCTL=no |
313 | found = self._render_and_read(network_config=yaml.load(entry['yaml'])) |
314 | self._compare_files_to_expected(entry['expected_sysconfig'], found) |
315 | self._assert_headers(found) |
316 | + self.assertNotIn( |
317 | + 'WARNING: Network config: ignoring eth0.101 device-level mtu', |
318 | + self.logs.getvalue()) |
319 | |
320 | def test_small_config(self): |
321 | entry = NETWORK_CONFIGS['small'] |
322 | @@ -1929,6 +1943,10 @@ USERCTL=no |
323 | found = self._render_and_read(network_config=yaml.load(entry['yaml'])) |
324 | self._compare_files_to_expected(entry['expected_sysconfig'], found) |
325 | self._assert_headers(found) |
326 | + expected_msg = ( |
327 | + 'WARNING: Network config: ignoring iface0 device-level mtu:8999' |
328 | + ' because ipv4 subnet-level mtu:9000 provided.') |
329 | + self.assertIn(expected_msg, self.logs.getvalue()) |
330 | |
331 | def test_dhcpv6_only_config(self): |
332 | entry = NETWORK_CONFIGS['dhcpv6_only'] |
333 | @@ -2410,6 +2428,7 @@ class TestNetplanRoundTrip(CiTestCase): |
334 | |
335 | |
336 | class TestEniRoundTrip(CiTestCase): |
337 | + |
338 | def _render_and_read(self, network_config=None, state=None, eni_path=None, |
339 | netrules_path=None, dir=None): |
340 | if dir is None: |
FAILED: Continuous integration, rev:2240d209653 6d914ebaed472d1 c19ea98eda19ab /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 51/
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
FAILED: Ubuntu LTS: Integration
Click here to trigger a rebuild: /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 51/rebuild
https:/