Merge ~chad.smith/cloud-init:feature/ec2-secondary-nics into cloud-init:master
- Git
- lp:~chad.smith/cloud-init
- feature/ec2-secondary-nics
- Merge into master
Status: | Work in progress | ||||
---|---|---|---|---|---|
Proposed branch: | ~chad.smith/cloud-init:feature/ec2-secondary-nics | ||||
Merge into: | cloud-init:master | ||||
Diff against target: |
463 lines (+210/-75) 3 files modified
cloudinit/sources/DataSourceEc2.py (+47/-15) doc/rtd/topics/datasources/ec2.rst (+3/-0) tests/unittests/test_datasource/test_ec2.py (+160/-60) |
||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Server Team CI bot | continuous-integration | Approve | |
cloud-init Commiters | Pending | ||
Review via email: mp+369792@code.launchpad.net |
Commit message
ec2: render secondary IPs on primary nic when present in metadata
Parse local-ipv4s and subnet-
2018-09-24 to obtain secondary nic private IPs and network mask for
the primary nic.
In adding this feature, convert DataSourceEc2.
emit network version 2 instead of version 1.
To allow for retaining original network config behavior on earlier
distribution series, surface a datasource config option
configure_
Older/stable distribution series will set configure_
default to False.
Description of the change
Server Team CI bot (server-team-bot) wrote : | # |
Dan Watkins (oddbloke) wrote : | # |
Overall, this looks good, thanks! I have a few inline comments/questions, but the overall structure/logic seems sound to me.
(Looks like the CI failures are due to linting.)
Chad Smith (chad.smith) : | # |
Dan Watkins (oddbloke) wrote : | # |
Thanks! A couple of follow-ups, and a couple of nits I missed first time around.
Ryan Harper (raharper) : | # |
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:f6b0d9eb283
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
SUCCESS: Ubuntu LTS: Integration
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:db953566a9e
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
SUCCESS: Ubuntu LTS: Integration
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:047a654e9b7
https:/
Executed test runs:
SUCCESS: Checkout
FAILED: Unit & Style Tests
Click here to trigger a rebuild:
https:/
Chad Smith (chad.smith) : | # |
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:2ae7c7c3b3e
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
SUCCESS: Ubuntu LTS: Integration
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
Chad Smith (chad.smith) wrote : | # |
Waiting on this change of behavior until after 19.2 upstream release
Leo Crawford (leo-leocrawford) wrote : | # |
> Waiting on this change of behavior until after 19.2 upstream release
cloud-init 19.2 was released 17 July. Does this unblock this change being applied?
Ryan Harper (raharper) wrote : | # |
I think Chad meant after our next SRU[1], which will begin shortly. I'd expect this come in the SRU after the current planned one.
Ryan Harper (raharper) wrote : | # |
Inline comment asking for clarification on AWS DHCP lease contents, requirements for routing traffic to IMDS, DNS, and off-box, as with Azure. Let's document what's needed; we may need to add secondary ips with a metric. See
https:/
For AmazonLinux net implementation; I do see some setting of source_ip and route table/metrics in use.
Andrea Scarpino (ilpianista) wrote : | # |
Up! Any news here? Which is the blocker here?
Dan Watkins (oddbloke) wrote : | # |
Hi Andrea, this branch was migrated over to GitHub (along with the rest of cloud-init's code hosting :) and was proposed here: https:/
It landed in March and was included in the 20.2 cloud-init release. It is available in Ubuntu 20.04 (Focal Fossa), and will be backported to all stable Ubuntu releases (i.e. 16.04 and later) in the next couple of weeks.
Thanks for your interest!
Unmerged commits
- 2ae7c7c... by Chad Smith
-
ec2: render secondary IPs on primary nic when present in metadata
Parse local-ipv4s and subnet-
ipv4-cidr- block on EC2 metadata version
2018-09-24 to obtain secondary nic private IPs and network mask for
the primary nic.
Preview Diff
1 | diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py |
2 | index 5c017bf..f39b73f 100644 |
3 | --- a/cloudinit/sources/DataSourceEc2.py |
4 | +++ b/cloudinit/sources/DataSourceEc2.py |
5 | @@ -54,7 +54,7 @@ class DataSourceEc2(sources.DataSource): |
6 | |
7 | # Priority ordered list of additional metadata versions which will be tried |
8 | # for extended metadata content. IPv6 support comes in 2016-09-02 |
9 | - extended_metadata_versions = ['2016-09-02'] |
10 | + extended_metadata_versions = ['2018-09-24', '2016-09-02'] |
11 | |
12 | # Setup read_url parameters per get_url_params. |
13 | url_max_wait = 120 |
14 | @@ -332,8 +332,13 @@ class DataSourceEc2(sources.DataSource): |
15 | macs_to_nics = {net.get_interface_mac(iface): iface} |
16 | net_md = self.metadata.get('network') |
17 | if isinstance(net_md, dict): |
18 | + # SRU_BLOCKER: xenial, bionic and disco should default |
19 | + # configure_secondary_ips to False to retain original behavior on |
20 | + # those releases. |
21 | result = convert_ec2_metadata_network_config( |
22 | - net_md, macs_to_nics=macs_to_nics, fallback_nic=iface) |
23 | + net_md, macs_to_nics=macs_to_nics, fallback_nic=iface, |
24 | + config_secondary_ips=util.is_true( |
25 | + self.ds_cfg.get('configure_secondary_ips', True))) |
26 | |
27 | # RELEASE_BLOCKER: xenial should drop the below if statement, |
28 | # because the issue being addressed doesn't exist pre-netplan. |
29 | @@ -373,7 +378,7 @@ class DataSourceEc2(sources.DataSource): |
30 | if not self.wait_for_metadata_service(): |
31 | return {} |
32 | api_version = self.get_metadata_api_version() |
33 | - crawled_metadata = {} |
34 | + crawled_metadata = {'_metadata_api_version': api_version} |
35 | try: |
36 | crawled_metadata['user-data'] = ec2.get_instance_userdata( |
37 | api_version, self.metadata_address) |
38 | @@ -388,7 +393,6 @@ class DataSourceEc2(sources.DataSource): |
39 | LOG, "Failed reading from metadata address %s", |
40 | self.metadata_address) |
41 | return {} |
42 | - crawled_metadata['_metadata_api_version'] = api_version |
43 | return crawled_metadata |
44 | |
45 | |
46 | @@ -523,8 +527,9 @@ def _collect_platform_data(): |
47 | return data |
48 | |
49 | |
50 | -def convert_ec2_metadata_network_config(network_md, macs_to_nics=None, |
51 | - fallback_nic=None): |
52 | +def convert_ec2_metadata_network_config( |
53 | + network_md, macs_to_nics=None, fallback_nic=None, |
54 | + config_secondary_ips=True): |
55 | """Convert ec2 metadata to network config version 1 data dict. |
56 | |
57 | @param: network_md: 'network' portion of EC2 metadata. |
58 | @@ -535,25 +540,52 @@ def convert_ec2_metadata_network_config(network_md, macs_to_nics=None, |
59 | not provided, get_interfaces_by_mac is called to get it from the OS. |
60 | @param: fallback_nic: Optionally provide the primary nic interface name. |
61 | This nic will be guaranteed to minimally have a dhcp4 configuration. |
62 | + @param: config_secondary_ips: Boolean set True to configure any |
63 | + secondary IPs described by the metadata service. |
64 | |
65 | - @return A dict of network config version 1 based on the metadata and macs. |
66 | + @return A dict of network config version 2 based on the metadata and macs. |
67 | """ |
68 | - netcfg = {'version': 1, 'config': []} |
69 | + netcfg = {'version': 2, 'ethernets': {}} |
70 | if not macs_to_nics: |
71 | macs_to_nics = net.get_interfaces_by_mac() |
72 | macs_metadata = network_md['interfaces']['macs'] |
73 | for mac, nic_name in macs_to_nics.items(): |
74 | + dev_config = {} |
75 | nic_metadata = macs_metadata.get(mac) |
76 | if not nic_metadata: |
77 | continue # Not a physical nic represented in metadata |
78 | - nic_cfg = {'type': 'physical', 'name': nic_name, 'subnets': []} |
79 | - nic_cfg['mac_address'] = mac |
80 | - if (nic_name == fallback_nic or nic_metadata.get('public-ipv4s') or |
81 | - nic_metadata.get('local-ipv4s')): |
82 | - nic_cfg['subnets'].append({'type': 'dhcp4'}) |
83 | + local_ipv4s = nic_metadata.get('local-ipv4s') |
84 | + if not config_secondary_ips: |
85 | + LOG.debug( |
86 | + 'Skipping secondary IP config because configure_secondary_ips' |
87 | + ' datasource config option is False') |
88 | + elif (nic_name == fallback_nic or |
89 | + nic_metadata.get('public-ipv4s') or |
90 | + local_ipv4s): |
91 | + dev_config['dhcp4'] = True |
92 | + # In version < 2018-09-24 local_ipvs is a str with a single IP |
93 | + if isinstance(local_ipv4s, list) and len(local_ipv4s) > 1: |
94 | + dev_config['addresses'] = [] |
95 | + subnet_cidr = nic_metadata.get('subnet-ipv4-cidr-block') |
96 | + if not subnet_cidr or len(subnet_cidr.split('/')) != 2: |
97 | + LOG.warning( |
98 | + 'Could not parse subnet-ipv4-cidr-block %s.' |
99 | + ' Network config for Secondary IPs default to /32', |
100 | + subnet_cidr) |
101 | + prefix = '32' |
102 | + else: |
103 | + _ip, prefix = subnet_cidr.split('/') |
104 | + # Primary nic IP is at index 0 and obtained via dhcp on Ec2 |
105 | + # Iterate over all secondary IPs in local_ipv4s at index >= 1 |
106 | + for secondary_ip in local_ipv4s[1:]: |
107 | + dev_config['addresses'].append( |
108 | + '{ip}/{prefix}'.format(ip=secondary_ip, prefix=prefix)) |
109 | if nic_metadata.get('ipv6s'): |
110 | - nic_cfg['subnets'].append({'type': 'dhcp6'}) |
111 | - netcfg['config'].append(nic_cfg) |
112 | + dev_config['dhcp6'] = True |
113 | + dev_config.update({ |
114 | + 'match': {'macaddress': mac.lower()}, |
115 | + 'set-name': nic_name}) |
116 | + netcfg['ethernets'][nic_name] = dev_config |
117 | return netcfg |
118 | |
119 | |
120 | diff --git a/doc/rtd/topics/datasources/ec2.rst b/doc/rtd/topics/datasources/ec2.rst |
121 | index 76beca9..5535edf 100644 |
122 | --- a/doc/rtd/topics/datasources/ec2.rst |
123 | +++ b/doc/rtd/topics/datasources/ec2.rst |
124 | @@ -79,6 +79,9 @@ The settings that may be configured are: |
125 | * **timeout**: the timeout value provided to urlopen for each individual http |
126 | request. This is used both when selecting a metadata_url and when crawling |
127 | the metadata service. (default: 50) |
128 | + * **configure_secondary_ips**: Boolean (default: True) to allow cloud-init |
129 | + to configure any secondary IPs described by the metadata service. |
130 | + On Ubuntu Xenial, Bionic and Disco, this defaults to False. |
131 | |
132 | An example configuration with the default values is provided below: |
133 | |
134 | diff --git a/tests/unittests/test_datasource/test_ec2.py b/tests/unittests/test_datasource/test_ec2.py |
135 | index 20d59bf..8ed4c18 100644 |
136 | --- a/tests/unittests/test_datasource/test_ec2.py |
137 | +++ b/tests/unittests/test_datasource/test_ec2.py |
138 | @@ -112,6 +112,96 @@ DEFAULT_METADATA = { |
139 | "services": {"domain": "amazonaws.com", "partition": "aws"}, |
140 | } |
141 | |
142 | +# collected from api version 2018-09-24/ with |
143 | +# python3 -c 'import json |
144 | +# from cloudinit.ec2_utils import get_instance_metadata as gm |
145 | +# print(json.dumps(gm("2018-09-24"), indent=1, sort_keys=True))' |
146 | +SECONDARY_IP_METADATA_2018_09_24 = { |
147 | + "ami-id": "ami-0986c2ac728528ac2", |
148 | + "ami-launch-index": "0", |
149 | + "ami-manifest-path": "(unknown)", |
150 | + "block-device-mapping": { |
151 | + "ami": "/dev/sda1", |
152 | + "root": "/dev/sda1" |
153 | + }, |
154 | + "events": { |
155 | + "maintenance": { |
156 | + "history": "[]", |
157 | + "scheduled": "[]" |
158 | + } |
159 | + }, |
160 | + "hostname": "ip-172-31-44-13.us-east-2.compute.internal", |
161 | + "identity-credentials": { |
162 | + "ec2": { |
163 | + "info": { |
164 | + "AccountId": "329910648901", |
165 | + "Code": "Success", |
166 | + "LastUpdated": "2019-07-06T14:22:56Z" |
167 | + } |
168 | + } |
169 | + }, |
170 | + "instance-action": "none", |
171 | + "instance-id": "i-069e01e8cc43732f8", |
172 | + "instance-type": "t2.micro", |
173 | + "local-hostname": "ip-172-31-44-13.us-east-2.compute.internal", |
174 | + "local-ipv4": "172.31.44.13", |
175 | + "mac": "0a:07:84:3d:6e:38", |
176 | + "metrics": { |
177 | + "vhostmd": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" |
178 | + }, |
179 | + "network": { |
180 | + "interfaces": { |
181 | + "macs": { |
182 | + "0a:07:84:3d:6e:38": { |
183 | + "device-number": "0", |
184 | + "interface-id": "eni-0d6335689899ce9cc", |
185 | + "ipv4-associations": { |
186 | + "18.218.219.181": "172.31.44.13" |
187 | + }, |
188 | + "local-hostname": ("ip-172-31-44-13.us-east-2." |
189 | + "compute.internal"), |
190 | + "local-ipv4s": [ |
191 | + "172.31.44.13", |
192 | + "172.31.45.70" |
193 | + ], |
194 | + "mac": "0a:07:84:3d:6e:38", |
195 | + "owner-id": "329910648901", |
196 | + "public-hostname": ("ec2-18-218-219-181.us-east-2." |
197 | + "compute.amazonaws.com"), |
198 | + "public-ipv4s": "18.218.219.181", |
199 | + "security-group-ids": "sg-0c387755222ba8d2e", |
200 | + "security-groups": "launch-wizard-4", |
201 | + "subnet-id": "subnet-9d7ba0d1", |
202 | + "subnet-ipv4-cidr-block": "172.31.32.0/20", |
203 | + "vpc-id": "vpc-a07f62c8", |
204 | + "vpc-ipv4-cidr-block": "172.31.0.0/16", |
205 | + "vpc-ipv4-cidr-blocks": "172.31.0.0/16" |
206 | + } |
207 | + } |
208 | + } |
209 | + }, |
210 | + "placement": { |
211 | + "availability-zone": "us-east-2c" |
212 | + }, |
213 | + "profile": "default-hvm", |
214 | + "public-hostname": ( |
215 | + "ec2-18-218-219-181.us-east-2.compute.amazonaws.com"), |
216 | + "public-ipv4": "18.218.219.181", |
217 | + "public-keys": { |
218 | + "yourkeyname,e": [ |
219 | + "ssh-rsa AAAAW...DZ yourkeyname" |
220 | + ] |
221 | + }, |
222 | + "reservation-id": "r-09b4917135cdd33be", |
223 | + "security-groups": "launch-wizard-4", |
224 | + "services": { |
225 | + "domain": "amazonaws.com", |
226 | + "partition": "aws" |
227 | + } |
228 | +} |
229 | + |
230 | +M_PATH_NET = 'cloudinit.sources.DataSourceEc2.net.' |
231 | + |
232 | |
233 | def _register_ssh_keys(rfunc, base_url, keys_data): |
234 | """handle ssh key inconsistencies. |
235 | @@ -261,30 +351,23 @@ class TestEc2(test_helpers.HttprettyTestCase): |
236 | register_mock_metaserver(instance_id_url, None) |
237 | return ds |
238 | |
239 | - def test_network_config_property_returns_version_1_network_data(self): |
240 | - """network_config property returns network version 1 for metadata. |
241 | - |
242 | - Only one device is configured even when multiple exist in metadata. |
243 | - """ |
244 | + def test_network_config_property_returns_version_2_network_data(self): |
245 | + """network_config property returns network version 2 for metadata""" |
246 | ds = self._setup_ds( |
247 | platform_data=self.valid_platform_data, |
248 | sys_cfg={'datasource': {'Ec2': {'strict_id': True}}}, |
249 | md={'md': DEFAULT_METADATA}) |
250 | - find_fallback_path = ( |
251 | - 'cloudinit.sources.DataSourceEc2.net.find_fallback_nic') |
252 | + find_fallback_path = M_PATH_NET + 'find_fallback_nic' |
253 | with mock.patch(find_fallback_path) as m_find_fallback: |
254 | m_find_fallback.return_value = 'eth9' |
255 | ds.get_data() |
256 | |
257 | mac1 = '06:17:04:d7:26:09' # Defined in DEFAULT_METADATA |
258 | - expected = {'version': 1, 'config': [ |
259 | - {'mac_address': '06:17:04:d7:26:09', 'name': 'eth9', |
260 | - 'subnets': [{'type': 'dhcp4'}, {'type': 'dhcp6'}], |
261 | - 'type': 'physical'}]} |
262 | - patch_path = ( |
263 | - 'cloudinit.sources.DataSourceEc2.net.get_interfaces_by_mac') |
264 | - get_interface_mac_path = ( |
265 | - 'cloudinit.sources.DataSourceEc2.net.get_interface_mac') |
266 | + expected = {'version': 2, 'ethernets': {'eth9': { |
267 | + 'match': {'macaddress': '06:17:04:d7:26:09'}, 'set-name': 'eth9', |
268 | + 'dhcp4': True, 'dhcp6': True}}} |
269 | + patch_path = M_PATH_NET + 'get_interfaces_by_mac' |
270 | + get_interface_mac_path = M_PATH_NET + 'get_interface_mac' |
271 | with mock.patch(patch_path) as m_get_interfaces_by_mac: |
272 | with mock.patch(find_fallback_path) as m_find_fallback: |
273 | with mock.patch(get_interface_mac_path) as m_get_mac: |
274 | @@ -302,21 +385,45 @@ class TestEc2(test_helpers.HttprettyTestCase): |
275 | platform_data=self.valid_platform_data, |
276 | sys_cfg={'datasource': {'Ec2': {'strict_id': True}}}, |
277 | md={'md': DEFAULT_METADATA}) |
278 | - find_fallback_path = ( |
279 | - 'cloudinit.sources.DataSourceEc2.net.find_fallback_nic') |
280 | + find_fallback_path = M_PATH_NET + 'find_fallback_nic' |
281 | with mock.patch(find_fallback_path) as m_find_fallback: |
282 | m_find_fallback.return_value = 'eth9' |
283 | ds.get_data() |
284 | |
285 | mac1 = '06:17:04:d7:26:0A' # IPv4 only in DEFAULT_METADATA |
286 | - expected = {'version': 1, 'config': [ |
287 | - {'mac_address': '06:17:04:d7:26:0A', 'name': 'eth9', |
288 | - 'subnets': [{'type': 'dhcp4'}], |
289 | - 'type': 'physical'}]} |
290 | - patch_path = ( |
291 | - 'cloudinit.sources.DataSourceEc2.net.get_interfaces_by_mac') |
292 | - get_interface_mac_path = ( |
293 | - 'cloudinit.sources.DataSourceEc2.net.get_interface_mac') |
294 | + expected = {'version': 2, 'ethernets': {'eth9': { |
295 | + 'match': {'macaddress': mac1.lower()}, 'set-name': 'eth9', |
296 | + 'dhcp4': True}}} |
297 | + patch_path = M_PATH_NET + 'get_interfaces_by_mac' |
298 | + get_interface_mac_path = M_PATH_NET + 'get_interface_mac' |
299 | + with mock.patch(patch_path) as m_get_interfaces_by_mac: |
300 | + with mock.patch(find_fallback_path) as m_find_fallback: |
301 | + with mock.patch(get_interface_mac_path) as m_get_mac: |
302 | + m_get_interfaces_by_mac.return_value = {mac1: 'eth9'} |
303 | + m_find_fallback.return_value = 'eth9' |
304 | + m_get_mac.return_value = mac1 |
305 | + self.assertEqual(expected, ds.network_config) |
306 | + |
307 | + def test_network_config_property_secondary_private_ips(self): |
308 | + """network_config property configures any secondary ipv4 addresses. |
309 | + |
310 | + Only one device is configured even when multiple exist in metadata. |
311 | + """ |
312 | + ds = self._setup_ds( |
313 | + platform_data=self.valid_platform_data, |
314 | + sys_cfg={'datasource': {'Ec2': {'strict_id': True}}}, |
315 | + md={'md': SECONDARY_IP_METADATA_2018_09_24}) |
316 | + find_fallback_path = M_PATH_NET + 'find_fallback_nic' |
317 | + with mock.patch(find_fallback_path) as m_find_fallback: |
318 | + m_find_fallback.return_value = 'eth9' |
319 | + ds.get_data() |
320 | + |
321 | + mac1 = '0a:07:84:3d:6e:38' # IPv4 with 1 secondary IP |
322 | + expected = {'version': 2, 'ethernets': {'eth9': { |
323 | + 'match': {'macaddress': mac1}, 'set-name': 'eth9', |
324 | + 'addresses': ['172.31.45.70/20'], 'dhcp4': True}}} |
325 | + patch_path = M_PATH_NET + 'get_interfaces_by_mac' |
326 | + get_interface_mac_path = M_PATH_NET + 'get_interface_mac' |
327 | with mock.patch(patch_path) as m_get_interfaces_by_mac: |
328 | with mock.patch(find_fallback_path) as m_find_fallback: |
329 | with mock.patch(get_interface_mac_path) as m_get_mac: |
330 | @@ -352,8 +459,7 @@ class TestEc2(test_helpers.HttprettyTestCase): |
331 | register_mock_metaserver( |
332 | 'http://169.254.169.254/2009-04-04/meta-data/', DEFAULT_METADATA) |
333 | mac1 = '06:17:04:d7:26:09' # Defined in DEFAULT_METADATA |
334 | - get_interface_mac_path = ( |
335 | - 'cloudinit.sources.DataSourceEc2.net.get_interface_mac') |
336 | + get_interface_mac_path = M_PATH_NET + 'get_interface_mac' |
337 | ds.fallback_nic = 'eth9' |
338 | with mock.patch(get_interface_mac_path) as m_get_interface_mac: |
339 | m_get_interface_mac.return_value = mac1 |
340 | @@ -362,11 +468,9 @@ class TestEc2(test_helpers.HttprettyTestCase): |
341 | self.assertIn( |
342 | 'Refreshing stale metadata from prior to upgrade', |
343 | self.logs.getvalue()) |
344 | - expected = {'version': 1, 'config': [ |
345 | - {'mac_address': '06:17:04:d7:26:09', |
346 | - 'name': 'eth9', |
347 | - 'subnets': [{'type': 'dhcp4'}, {'type': 'dhcp6'}], |
348 | - 'type': 'physical'}]} |
349 | + expected = {'version': 2, 'ethernets': {'eth9': { |
350 | + 'match': {'macaddress': mac1}, 'set-name': 'eth9', |
351 | + 'dhcp4': True, 'dhcp6': True}}} |
352 | self.assertEqual(expected, ds.network_config) |
353 | |
354 | def test_ec2_get_instance_id_refreshes_identity_on_upgrade(self): |
355 | @@ -546,19 +650,19 @@ class TestConvertEc2MetadataNetworkConfig(test_helpers.CiTestCase): |
356 | |
357 | def setUp(self): |
358 | super(TestConvertEc2MetadataNetworkConfig, self).setUp() |
359 | - self.mac1 = '06:17:04:d7:26:09' |
360 | + self.mac1 = '06:17:04:D7:26:09' |
361 | self.network_metadata = { |
362 | 'interfaces': {'macs': { |
363 | - self.mac1: {'public-ipv4s': '172.31.2.16'}}}} |
364 | + self.mac1: {'mac': self.mac1, 'public-ipv4s': '172.31.2.16'}}}} |
365 | |
366 | def test_convert_ec2_metadata_network_config_skips_absent_macs(self): |
367 | """Any mac absent from metadata is skipped by network config.""" |
368 | macs_to_nics = {self.mac1: 'eth9', 'DE:AD:BE:EF:FF:FF': 'vitualnic2'} |
369 | |
370 | # DE:AD:BE:EF:FF:FF represented by OS but not in metadata |
371 | - expected = {'version': 1, 'config': [ |
372 | - {'mac_address': self.mac1, 'type': 'physical', |
373 | - 'name': 'eth9', 'subnets': [{'type': 'dhcp4'}]}]} |
374 | + expected = {'version': 2, 'ethernets': {'eth9': { |
375 | + 'match': {'macaddress': self.mac1.lower()}, 'set-name': 'eth9', |
376 | + 'dhcp4': True}}} |
377 | self.assertEqual( |
378 | expected, |
379 | ec2.convert_ec2_metadata_network_config( |
380 | @@ -572,9 +676,9 @@ class TestConvertEc2MetadataNetworkConfig(test_helpers.CiTestCase): |
381 | network_metadata_ipv6['interfaces']['macs'][self.mac1]) |
382 | nic1_metadata['ipv6s'] = '2620:0:1009:fd00:e442:c88d:c04d:dc85/64' |
383 | nic1_metadata.pop('public-ipv4s') |
384 | - expected = {'version': 1, 'config': [ |
385 | - {'mac_address': self.mac1, 'type': 'physical', |
386 | - 'name': 'eth9', 'subnets': [{'type': 'dhcp6'}]}]} |
387 | + expected = {'version': 2, 'ethernets': {'eth9': { |
388 | + 'match': {'macaddress': self.mac1.lower()}, 'set-name': 'eth9', |
389 | + 'dhcp6': True}}} |
390 | self.assertEqual( |
391 | expected, |
392 | ec2.convert_ec2_metadata_network_config( |
393 | @@ -588,9 +692,9 @@ class TestConvertEc2MetadataNetworkConfig(test_helpers.CiTestCase): |
394 | network_metadata_ipv6['interfaces']['macs'][self.mac1]) |
395 | nic1_metadata['local-ipv4s'] = '172.3.3.15' |
396 | nic1_metadata.pop('public-ipv4s') |
397 | - expected = {'version': 1, 'config': [ |
398 | - {'mac_address': self.mac1, 'type': 'physical', |
399 | - 'name': 'eth9', 'subnets': [{'type': 'dhcp4'}]}]} |
400 | + expected = {'version': 2, 'ethernets': {'eth9': { |
401 | + 'match': {'macaddress': self.mac1.lower()}, 'set-name': 'eth9', |
402 | + 'dhcp4': True}}} |
403 | self.assertEqual( |
404 | expected, |
405 | ec2.convert_ec2_metadata_network_config( |
406 | @@ -605,9 +709,9 @@ class TestConvertEc2MetadataNetworkConfig(test_helpers.CiTestCase): |
407 | nic1_metadata['public-ipv4s'] = '' |
408 | |
409 | # When no ipv4 or ipv6 content but fallback_nic set, set dhcp4 config. |
410 | - expected = {'version': 1, 'config': [ |
411 | - {'mac_address': self.mac1, 'type': 'physical', |
412 | - 'name': 'eth9', 'subnets': [{'type': 'dhcp4'}]}]} |
413 | + expected = {'version': 2, 'ethernets': {'eth9': { |
414 | + 'match': {'macaddress': self.mac1.lower()}, 'set-name': 'eth9', |
415 | + 'dhcp4': True}}} |
416 | self.assertEqual( |
417 | expected, |
418 | ec2.convert_ec2_metadata_network_config( |
419 | @@ -622,10 +726,9 @@ class TestConvertEc2MetadataNetworkConfig(test_helpers.CiTestCase): |
420 | nic1_metadata['ipv6s'] = '2620:0:1009:fd00:e442:c88d:c04d:dc85/64' |
421 | nic1_metadata.pop('public-ipv4s') |
422 | nic1_metadata['local-ipv4s'] = '10.0.0.42' # Local ipv4 only on vpc |
423 | - expected = {'version': 1, 'config': [ |
424 | - {'mac_address': self.mac1, 'type': 'physical', |
425 | - 'name': 'eth9', |
426 | - 'subnets': [{'type': 'dhcp4'}, {'type': 'dhcp6'}]}]} |
427 | + expected = {'version': 2, 'ethernets': {'eth9': { |
428 | + 'match': {'macaddress': self.mac1.lower()}, 'set-name': 'eth9', |
429 | + 'dhcp4': True, 'dhcp6': True}}} |
430 | self.assertEqual( |
431 | expected, |
432 | ec2.convert_ec2_metadata_network_config( |
433 | @@ -638,10 +741,9 @@ class TestConvertEc2MetadataNetworkConfig(test_helpers.CiTestCase): |
434 | nic1_metadata = ( |
435 | network_metadata_both['interfaces']['macs'][self.mac1]) |
436 | nic1_metadata['ipv6s'] = '2620:0:1009:fd00:e442:c88d:c04d:dc85/64' |
437 | - expected = {'version': 1, 'config': [ |
438 | - {'mac_address': self.mac1, 'type': 'physical', |
439 | - 'name': 'eth9', |
440 | - 'subnets': [{'type': 'dhcp4'}, {'type': 'dhcp6'}]}]} |
441 | + expected = {'version': 2, 'ethernets': {'eth9': { |
442 | + 'match': {'macaddress': self.mac1.lower()}, 'set-name': 'eth9', |
443 | + 'dhcp4': True, 'dhcp6': True}}} |
444 | self.assertEqual( |
445 | expected, |
446 | ec2.convert_ec2_metadata_network_config( |
447 | @@ -649,12 +751,10 @@ class TestConvertEc2MetadataNetworkConfig(test_helpers.CiTestCase): |
448 | |
449 | def test_convert_ec2_metadata_gets_macs_from_get_interfaces_by_mac(self): |
450 | """Convert Ec2 Metadata calls get_interfaces_by_mac by default.""" |
451 | - expected = {'version': 1, 'config': [ |
452 | - {'mac_address': self.mac1, 'type': 'physical', |
453 | - 'name': 'eth9', |
454 | - 'subnets': [{'type': 'dhcp4'}]}]} |
455 | - patch_path = ( |
456 | - 'cloudinit.sources.DataSourceEc2.net.get_interfaces_by_mac') |
457 | + expected = {'version': 2, 'ethernets': {'eth9': { |
458 | + 'match': {'macaddress': self.mac1.lower()}, |
459 | + 'set-name': 'eth9', 'dhcp4': True}}} |
460 | + patch_path = M_PATH_NET + 'get_interfaces_by_mac' |
461 | with mock.patch(patch_path) as m_get_interfaces_by_mac: |
462 | m_get_interfaces_by_mac.return_value = {self.mac1: 'eth9'} |
463 | self.assertEqual( |
FAILED: Continuous integration, rev:a16796ed79f c4d58710fa01857 1011d1adefc032 /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 757/
https:/
Executed test runs:
SUCCESS: Checkout
FAILED: Unit & Style Tests
Click here to trigger a rebuild: /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 757/rebuild
https:/