Merge ~chad.smith/cloud-init:feature/azure-to-network-v2 into cloud-init:master
- Git
- lp:~chad.smith/cloud-init
- feature/azure-to-network-v2
- Merge into master
Status: | Merged |
---|---|
Approved by: | Chad Smith |
Approved revision: | 5106244d7e7105079ec689ca34d93a61b3c8e045 |
Merge reported by: | Server Team CI bot |
Merged at revision: | not available |
Proposed branch: | ~chad.smith/cloud-init:feature/azure-to-network-v2 |
Merge into: | cloud-init:master |
Diff against target: |
330 lines (+130/-39) 6 files modified
cloudinit/net/__init__.py (+11/-20) cloudinit/net/network_state.py (+8/-4) cloudinit/net/tests/test_init.py (+10/-9) cloudinit/sources/DataSourceAzure.py (+6/-1) tests/unittests/test_datasource/test_azure.py (+58/-1) tests/unittests/test_net.py (+37/-4) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Server Team CI bot | continuous-integration | Approve | |
Ryan Harper | Approve | ||
Review via email: mp+370970@code.launchpad.net |
Commit message
azure/net: generate_
The function generate_
not consuming IMDS configuration data. This function is also used by any
datasource which does not implement it's own network config. This simple
fallback configuration sets up dhcp on the most likely NIC. It will now
emit network v2 instead of network v1.
This is a step toward moving all components talking in v2 and allows us
to avoid costly conversions between v1 and v2 for newer distributions
which rely on netplan.
Description of the change
Server Team CI bot (server-team-bot) wrote : | # |
Ryan Harper (raharper) wrote : | # |
One inline question.
- 2c1cc00... by Chad Smith
-
azure/net: generate_
fallback_ nic emits network v2 config instead of v1 The function generate_
fallback_ config is used by Azure by default when
not consuming IMDS configuration data. This function is also used by any
datasource which does not implement it's own network config. This simple
fallback configuration sets up dhcp on the most likely NIC. It will now
emit network v2 instead of network v1.This is a step toward moving all components talking in v2 and allows us
to avoid costly conversions between v1 and v2 for newer distributions
which rely on netplan.
Ryan Harper (raharper) wrote : | # |
One debugging line needs removing and some questions inline.
Chad Smith (chad.smith) : | # |
Chad Smith (chad.smith) : | # |
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:9af66a67ecc
https:/
Executed test runs:
SUCCESS: Checkout
FAILED: Unit & Style Tests
Click here to trigger a rebuild:
https:/
- 5106244... by Chad Smith
-
azure: add route-metric to net config on non-primary dhcp interfaces
To retain default network routes on primary dhcp interface, set the
route-metric to 100 for primary interface and 200+ for any secondary
interfaces. This ensures that any dhcp routes provided by the secondary
nics will not be used as a default route for external bound traffic.
Ryan Harper (raharper) wrote : | # |
That looks nice! One comment on where to set maxDiff, but we can do that separately
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:805f4718126
https:/
Executed test runs:
SUCCESS: Checkout
FAILED: Unit & Style Tests
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:5106244d7e7
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 : | # |
Validated on disco given eth0 (with addtional secondary IP) and eth1 (dhcp secondary NIC)
# QUESTION: am I missing a metric 200 on 10.0.0.8?
ubuntu@
{'compute': {'location': 'eastus2', 'name': 'test-sru-disco', 'offer': 'UbuntuServer', 'osType': 'Linux', 'placementGroupId': '', 'platformFaultD
ubuntu@
# This file is generated from information provided by
# the datasource. Changes to it will not persist across an instance.
# To disable cloud-init's network configuration capabilities, write a file
# /etc/cloud/
# network: {config: disabled}
network:
ethernets:
eth0:
- 10.0.0.23/24
dhcp4: true
match:
eth1:
dhcp4: true
match:
version: 2
2: eth0: <BROADCAST,
link/ether 00:0d:3a:7b:7c:34 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.23/24 brd 10.0.0.255 scope global eth0
valid_lft forever preferred_lft forever
inet 10.0.0.5/24 brd 10.0.0.255 scope global secondary eth0
valid_lft forever preferred_lft forever
inet6 fe80::20d:
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,
link/ether 00:0d:3a:7b:9e:10 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.8/24 brd 10.0.0.255 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::20d:
valid_lft forever preferred_lft forever
ubuntu@
default via 10.0.0.1 dev eth0 proto dhcp src 10.0.0.5 metric 100
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.23
10.0.0.0/24 dev eth1 proto kernel scope link src 10.0.0.8
168.63.129.16 via 10.0.0.1 dev eth0 proto dhcp src 10.0.0.5 m...
Chad Smith (chad.smith) wrote : | # |
Landing as secondary NICs with unique gateways is not a primary network use-case in Azure. Netplan additional route-metric overrides on secondary NICs has been validated on OpenStack vms where unique gateways per-nic are simpler to setup.
Preview Diff
1 | diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py | |||
2 | index f3cec79..ea707c0 100644 | |||
3 | --- a/cloudinit/net/__init__.py | |||
4 | +++ b/cloudinit/net/__init__.py | |||
5 | @@ -265,32 +265,23 @@ def find_fallback_nic(blacklist_drivers=None): | |||
6 | 265 | 265 | ||
7 | 266 | 266 | ||
8 | 267 | def generate_fallback_config(blacklist_drivers=None, config_driver=None): | 267 | def generate_fallback_config(blacklist_drivers=None, config_driver=None): |
12 | 268 | """Determine which attached net dev is most likely to have a connection and | 268 | """Generate network cfg v2 for dhcp on the NIC most likely connected.""" |
10 | 269 | generate network state to run dhcp on that interface""" | ||
11 | 270 | |||
13 | 271 | if not config_driver: | 269 | if not config_driver: |
14 | 272 | config_driver = False | 270 | config_driver = False |
15 | 273 | 271 | ||
16 | 274 | target_name = find_fallback_nic(blacklist_drivers=blacklist_drivers) | 272 | target_name = find_fallback_nic(blacklist_drivers=blacklist_drivers) |
34 | 275 | if target_name: | 273 | if not target_name: |
18 | 276 | target_mac = read_sys_net_safe(target_name, 'address') | ||
19 | 277 | nconf = {'config': [], 'version': 1} | ||
20 | 278 | cfg = {'type': 'physical', 'name': target_name, | ||
21 | 279 | 'mac_address': target_mac, 'subnets': [{'type': 'dhcp'}]} | ||
22 | 280 | # inject the device driver name, dev_id into config if enabled and | ||
23 | 281 | # device has a valid device driver value | ||
24 | 282 | if config_driver: | ||
25 | 283 | driver = device_driver(target_name) | ||
26 | 284 | if driver: | ||
27 | 285 | cfg['params'] = { | ||
28 | 286 | 'driver': driver, | ||
29 | 287 | 'device_id': device_devid(target_name), | ||
30 | 288 | } | ||
31 | 289 | nconf['config'].append(cfg) | ||
32 | 290 | return nconf | ||
33 | 291 | else: | ||
35 | 292 | # can't read any interfaces addresses (or there are none); give up | 274 | # can't read any interfaces addresses (or there are none); give up |
36 | 293 | return None | 275 | return None |
37 | 276 | target_mac = read_sys_net_safe(target_name, 'address') | ||
38 | 277 | cfg = {'dhcp4': True, 'set-name': target_name, | ||
39 | 278 | 'match': {'macaddress': target_mac.lower()}} | ||
40 | 279 | if config_driver: | ||
41 | 280 | driver = device_driver(target_name) | ||
42 | 281 | if driver: | ||
43 | 282 | cfg['match']['driver'] = driver | ||
44 | 283 | nconf = {'ethernets': {target_name: cfg}, 'version': 2} | ||
45 | 284 | return nconf | ||
46 | 294 | 285 | ||
47 | 295 | 286 | ||
48 | 296 | def extract_physdevs(netcfg): | 287 | def extract_physdevs(netcfg): |
49 | diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py | |||
50 | index 0ca576b..c0c415d 100644 | |||
51 | --- a/cloudinit/net/network_state.py | |||
52 | +++ b/cloudinit/net/network_state.py | |||
53 | @@ -596,6 +596,7 @@ class NetworkStateInterpreter(object): | |||
54 | 596 | eno1: | 596 | eno1: |
55 | 597 | match: | 597 | match: |
56 | 598 | macaddress: 00:11:22:33:44:55 | 598 | macaddress: 00:11:22:33:44:55 |
57 | 599 | driver: hv_netsvc | ||
58 | 599 | wakeonlan: true | 600 | wakeonlan: true |
59 | 600 | dhcp4: true | 601 | dhcp4: true |
60 | 601 | dhcp6: false | 602 | dhcp6: false |
61 | @@ -631,15 +632,18 @@ class NetworkStateInterpreter(object): | |||
62 | 631 | 'type': 'physical', | 632 | 'type': 'physical', |
63 | 632 | 'name': cfg.get('set-name', eth), | 633 | 'name': cfg.get('set-name', eth), |
64 | 633 | } | 634 | } |
66 | 634 | mac_address = cfg.get('match', {}).get('macaddress', None) | 635 | match = cfg.get('match', {}) |
67 | 636 | mac_address = match.get('macaddress', None) | ||
68 | 635 | if not mac_address: | 637 | if not mac_address: |
69 | 636 | LOG.debug('NetworkState Version2: missing "macaddress" info ' | 638 | LOG.debug('NetworkState Version2: missing "macaddress" info ' |
70 | 637 | 'in config entry: %s: %s', eth, str(cfg)) | 639 | 'in config entry: %s: %s', eth, str(cfg)) |
73 | 638 | phy_cmd.update({'mac_address': mac_address}) | 640 | phy_cmd['mac_address'] = mac_address |
74 | 639 | 641 | driver = match.get('driver', None) | |
75 | 642 | if driver: | ||
76 | 643 | phy_cmd['params'] = {'driver': driver} | ||
77 | 640 | for key in ['mtu', 'match', 'wakeonlan']: | 644 | for key in ['mtu', 'match', 'wakeonlan']: |
78 | 641 | if key in cfg: | 645 | if key in cfg: |
80 | 642 | phy_cmd.update({key: cfg.get(key)}) | 646 | phy_cmd[key] = cfg[key] |
81 | 643 | 647 | ||
82 | 644 | subnets = self._v2_to_v1_ipcfg(cfg) | 648 | subnets = self._v2_to_v1_ipcfg(cfg) |
83 | 645 | if len(subnets) > 0: | 649 | if len(subnets) > 0: |
84 | diff --git a/cloudinit/net/tests/test_init.py b/cloudinit/net/tests/test_init.py | |||
85 | index e6e77d7..d2e38f0 100644 | |||
86 | --- a/cloudinit/net/tests/test_init.py | |||
87 | +++ b/cloudinit/net/tests/test_init.py | |||
88 | @@ -212,9 +212,9 @@ class TestGenerateFallbackConfig(CiTestCase): | |||
89 | 212 | mac = 'aa:bb:cc:aa:bb:cc' | 212 | mac = 'aa:bb:cc:aa:bb:cc' |
90 | 213 | write_file(os.path.join(self.sysdir, 'eth1', 'address'), mac) | 213 | write_file(os.path.join(self.sysdir, 'eth1', 'address'), mac) |
91 | 214 | expected = { | 214 | expected = { |
95 | 215 | 'config': [{'type': 'physical', 'mac_address': mac, | 215 | 'ethernets': {'eth1': {'match': {'macaddress': mac}, |
96 | 216 | 'name': 'eth1', 'subnets': [{'type': 'dhcp'}]}], | 216 | 'dhcp4': True, 'set-name': 'eth1'}}, |
97 | 217 | 'version': 1} | 217 | 'version': 2} |
98 | 218 | self.assertEqual(expected, net.generate_fallback_config()) | 218 | self.assertEqual(expected, net.generate_fallback_config()) |
99 | 219 | 219 | ||
100 | 220 | def test_generate_fallback_finds_dormant_eth_with_mac(self): | 220 | def test_generate_fallback_finds_dormant_eth_with_mac(self): |
101 | @@ -223,9 +223,9 @@ class TestGenerateFallbackConfig(CiTestCase): | |||
102 | 223 | mac = 'aa:bb:cc:aa:bb:cc' | 223 | mac = 'aa:bb:cc:aa:bb:cc' |
103 | 224 | write_file(os.path.join(self.sysdir, 'eth0', 'address'), mac) | 224 | write_file(os.path.join(self.sysdir, 'eth0', 'address'), mac) |
104 | 225 | expected = { | 225 | expected = { |
108 | 226 | 'config': [{'type': 'physical', 'mac_address': mac, | 226 | 'ethernets': {'eth0': {'match': {'macaddress': mac}, 'dhcp4': True, |
109 | 227 | 'name': 'eth0', 'subnets': [{'type': 'dhcp'}]}], | 227 | 'set-name': 'eth0'}}, |
110 | 228 | 'version': 1} | 228 | 'version': 2} |
111 | 229 | self.assertEqual(expected, net.generate_fallback_config()) | 229 | self.assertEqual(expected, net.generate_fallback_config()) |
112 | 230 | 230 | ||
113 | 231 | def test_generate_fallback_finds_eth_by_operstate(self): | 231 | def test_generate_fallback_finds_eth_by_operstate(self): |
114 | @@ -233,9 +233,10 @@ class TestGenerateFallbackConfig(CiTestCase): | |||
115 | 233 | mac = 'aa:bb:cc:aa:bb:cc' | 233 | mac = 'aa:bb:cc:aa:bb:cc' |
116 | 234 | write_file(os.path.join(self.sysdir, 'eth0', 'address'), mac) | 234 | write_file(os.path.join(self.sysdir, 'eth0', 'address'), mac) |
117 | 235 | expected = { | 235 | expected = { |
121 | 236 | 'config': [{'type': 'physical', 'mac_address': mac, | 236 | 'ethernets': { |
122 | 237 | 'name': 'eth0', 'subnets': [{'type': 'dhcp'}]}], | 237 | 'eth0': {'dhcp4': True, 'match': {'macaddress': mac}, |
123 | 238 | 'version': 1} | 238 | 'set-name': 'eth0'}}, |
124 | 239 | 'version': 2} | ||
125 | 239 | valid_operstates = ['dormant', 'down', 'lowerlayerdown', 'unknown'] | 240 | valid_operstates = ['dormant', 'down', 'lowerlayerdown', 'unknown'] |
126 | 240 | for state in valid_operstates: | 241 | for state in valid_operstates: |
127 | 241 | write_file(os.path.join(self.sysdir, 'eth0', 'operstate'), state) | 242 | write_file(os.path.join(self.sysdir, 'eth0', 'operstate'), state) |
128 | diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py | |||
129 | index d2fad9b..e6ed2f3 100755 | |||
130 | --- a/cloudinit/sources/DataSourceAzure.py | |||
131 | +++ b/cloudinit/sources/DataSourceAzure.py | |||
132 | @@ -1241,7 +1241,7 @@ def parse_network_config(imds_metadata): | |||
133 | 1241 | privateIpv4 = addr4['privateIpAddress'] | 1241 | privateIpv4 = addr4['privateIpAddress'] |
134 | 1242 | if privateIpv4: | 1242 | if privateIpv4: |
135 | 1243 | if dev_config.get('dhcp4', False): | 1243 | if dev_config.get('dhcp4', False): |
137 | 1244 | # Append static address config for nic > 1 | 1244 | # Append static address config for ip > 1 |
138 | 1245 | netPrefix = intf['ipv4']['subnet'][0].get( | 1245 | netPrefix = intf['ipv4']['subnet'][0].get( |
139 | 1246 | 'prefix', '24') | 1246 | 'prefix', '24') |
140 | 1247 | if not dev_config.get('addresses'): | 1247 | if not dev_config.get('addresses'): |
141 | @@ -1251,6 +1251,11 @@ def parse_network_config(imds_metadata): | |||
142 | 1251 | ip=privateIpv4, prefix=netPrefix)) | 1251 | ip=privateIpv4, prefix=netPrefix)) |
143 | 1252 | else: | 1252 | else: |
144 | 1253 | dev_config['dhcp4'] = True | 1253 | dev_config['dhcp4'] = True |
145 | 1254 | # non-primary interfaces should have a higher | ||
146 | 1255 | # route-metric (cost) so default routes prefer | ||
147 | 1256 | # primary nic due to lower route-metric value | ||
148 | 1257 | dev_config['dhcp4-overrides'] = { | ||
149 | 1258 | 'route-metric': (idx + 1) * 100} | ||
150 | 1254 | for addr6 in intf['ipv6']['ipAddress']: | 1259 | for addr6 in intf['ipv6']['ipAddress']: |
151 | 1255 | privateIpv6 = addr6['privateIpAddress'] | 1260 | privateIpv6 = addr6['privateIpAddress'] |
152 | 1256 | if privateIpv6: | 1261 | if privateIpv6: |
153 | diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py | |||
154 | index 2de2aea..4d57ceb 100644 | |||
155 | --- a/tests/unittests/test_datasource/test_azure.py | |||
156 | +++ b/tests/unittests/test_datasource/test_azure.py | |||
157 | @@ -12,6 +12,7 @@ from cloudinit.tests.helpers import ( | |||
158 | 12 | HttprettyTestCase, CiTestCase, populate_dir, mock, wrap_and_call, | 12 | HttprettyTestCase, CiTestCase, populate_dir, mock, wrap_and_call, |
159 | 13 | ExitStack, resourceLocation) | 13 | ExitStack, resourceLocation) |
160 | 14 | 14 | ||
161 | 15 | import copy | ||
162 | 15 | import crypt | 16 | import crypt |
163 | 16 | import httpretty | 17 | import httpretty |
164 | 17 | import json | 18 | import json |
165 | @@ -129,6 +130,26 @@ NETWORK_METADATA = { | |||
166 | 129 | } | 130 | } |
167 | 130 | } | 131 | } |
168 | 131 | 132 | ||
169 | 133 | SECONDARY_INTERFACE = { | ||
170 | 134 | "macAddress": "220D3A047598", | ||
171 | 135 | "ipv6": { | ||
172 | 136 | "ipAddress": [] | ||
173 | 137 | }, | ||
174 | 138 | "ipv4": { | ||
175 | 139 | "subnet": [ | ||
176 | 140 | { | ||
177 | 141 | "prefix": "24", | ||
178 | 142 | "address": "10.0.1.0" | ||
179 | 143 | } | ||
180 | 144 | ], | ||
181 | 145 | "ipAddress": [ | ||
182 | 146 | { | ||
183 | 147 | "privateIpAddress": "10.0.1.5", | ||
184 | 148 | } | ||
185 | 149 | ] | ||
186 | 150 | } | ||
187 | 151 | } | ||
188 | 152 | |||
189 | 132 | MOCKPATH = 'cloudinit.sources.DataSourceAzure.' | 153 | MOCKPATH = 'cloudinit.sources.DataSourceAzure.' |
190 | 133 | 154 | ||
191 | 134 | 155 | ||
192 | @@ -619,8 +640,43 @@ scbus-1 on xpt0 bus 0 | |||
193 | 619 | 'ethernets': { | 640 | 'ethernets': { |
194 | 620 | 'eth0': {'set-name': 'eth0', | 641 | 'eth0': {'set-name': 'eth0', |
195 | 621 | 'match': {'macaddress': '00:0d:3a:04:75:98'}, | 642 | 'match': {'macaddress': '00:0d:3a:04:75:98'}, |
197 | 622 | 'dhcp4': True}}, | 643 | 'dhcp4': True, |
198 | 644 | 'dhcp4-overrides': {'route-metric': 100}}}, | ||
199 | 645 | 'version': 2} | ||
200 | 646 | dsrc = self._get_ds(data) | ||
201 | 647 | dsrc.get_data() | ||
202 | 648 | self.assertEqual(expected_network_config, dsrc.network_config) | ||
203 | 649 | |||
204 | 650 | def test_network_config_set_from_imds_route_metric_for_secondary_nic(self): | ||
205 | 651 | """Datasource.network_config adds route-metric to secondary nics.""" | ||
206 | 652 | sys_cfg = {'datasource': {'Azure': {'apply_network_config': True}}} | ||
207 | 653 | odata = {} | ||
208 | 654 | data = {'ovfcontent': construct_valid_ovf_env(data=odata), | ||
209 | 655 | 'sys_cfg': sys_cfg} | ||
210 | 656 | expected_network_config = { | ||
211 | 657 | 'ethernets': { | ||
212 | 658 | 'eth0': {'set-name': 'eth0', | ||
213 | 659 | 'match': {'macaddress': '00:0d:3a:04:75:98'}, | ||
214 | 660 | 'dhcp4': True, | ||
215 | 661 | 'dhcp4-overrides': {'route-metric': 100}}, | ||
216 | 662 | 'eth1': {'set-name': 'eth1', | ||
217 | 663 | 'match': {'macaddress': '22:0d:3a:04:75:98'}, | ||
218 | 664 | 'dhcp4': True, | ||
219 | 665 | 'dhcp4-overrides': {'route-metric': 200}}, | ||
220 | 666 | 'eth2': {'set-name': 'eth2', | ||
221 | 667 | 'match': {'macaddress': '33:0d:3a:04:75:98'}, | ||
222 | 668 | 'dhcp4': True, | ||
223 | 669 | 'dhcp4-overrides': {'route-metric': 300}}}, | ||
224 | 623 | 'version': 2} | 670 | 'version': 2} |
225 | 671 | imds_data = copy.deepcopy(NETWORK_METADATA) | ||
226 | 672 | imds_data['network']['interface'].append(SECONDARY_INTERFACE) | ||
227 | 673 | third_intf = copy.deepcopy(SECONDARY_INTERFACE) | ||
228 | 674 | third_intf['macAddress'] = third_intf['macAddress'].replace('22', '33') | ||
229 | 675 | third_intf['ipv4']['subnet'][0]['address'] = '10.0.2.0' | ||
230 | 676 | third_intf['ipv4']['ipAddress'][0]['privateIpAddress'] = '10.0.2.6' | ||
231 | 677 | imds_data['network']['interface'].append(third_intf) | ||
232 | 678 | |||
233 | 679 | self.m_get_metadata_from_imds.return_value = imds_data | ||
234 | 624 | dsrc = self._get_ds(data) | 680 | dsrc = self._get_ds(data) |
235 | 625 | dsrc.get_data() | 681 | dsrc.get_data() |
236 | 626 | self.assertEqual(expected_network_config, dsrc.network_config) | 682 | self.assertEqual(expected_network_config, dsrc.network_config) |
237 | @@ -925,6 +981,7 @@ scbus-1 on xpt0 bus 0 | |||
238 | 925 | expected_cfg = { | 981 | expected_cfg = { |
239 | 926 | 'ethernets': { | 982 | 'ethernets': { |
240 | 927 | 'eth0': {'dhcp4': True, | 983 | 'eth0': {'dhcp4': True, |
241 | 984 | 'dhcp4-overrides': {'route-metric': 100}, | ||
242 | 928 | 'match': {'macaddress': '00:0d:3a:04:75:98'}, | 985 | 'match': {'macaddress': '00:0d:3a:04:75:98'}, |
243 | 929 | 'set-name': 'eth0'}}, | 986 | 'set-name': 'eth0'}}, |
244 | 930 | 'version': 2} | 987 | 'version': 2} |
245 | diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py | |||
246 | index 1840ade..4f7e420 100644 | |||
247 | --- a/tests/unittests/test_net.py | |||
248 | +++ b/tests/unittests/test_net.py | |||
249 | @@ -2156,7 +2156,7 @@ DEFAULT_DEV_ATTRS = { | |||
250 | 2156 | "carrier": False, | 2156 | "carrier": False, |
251 | 2157 | "dormant": False, | 2157 | "dormant": False, |
252 | 2158 | "operstate": "down", | 2158 | "operstate": "down", |
254 | 2159 | "address": "07-1C-C6-75-A4-BE", | 2159 | "address": "07-1c-c6-75-a4-be", |
255 | 2160 | "device/driver": None, | 2160 | "device/driver": None, |
256 | 2161 | "device/device": None, | 2161 | "device/device": None, |
257 | 2162 | "name_assign_type": "4", | 2162 | "name_assign_type": "4", |
258 | @@ -2207,6 +2207,39 @@ class TestGenerateFallbackConfig(CiTestCase): | |||
259 | 2207 | @mock.patch("cloudinit.net.sys_dev_path") | 2207 | @mock.patch("cloudinit.net.sys_dev_path") |
260 | 2208 | @mock.patch("cloudinit.net.read_sys_net") | 2208 | @mock.patch("cloudinit.net.read_sys_net") |
261 | 2209 | @mock.patch("cloudinit.net.get_devicelist") | 2209 | @mock.patch("cloudinit.net.get_devicelist") |
262 | 2210 | def test_device_driver_v2(self, mock_get_devicelist, mock_read_sys_net, | ||
263 | 2211 | mock_sys_dev_path): | ||
264 | 2212 | """Network configuration for generate_fallback_config is version 2.""" | ||
265 | 2213 | devices = { | ||
266 | 2214 | 'eth0': { | ||
267 | 2215 | 'bridge': False, 'carrier': False, 'dormant': False, | ||
268 | 2216 | 'operstate': 'down', 'address': '00:11:22:33:44:55', | ||
269 | 2217 | 'device/driver': 'hv_netsvc', 'device/device': '0x3', | ||
270 | 2218 | 'name_assign_type': '4'}, | ||
271 | 2219 | 'eth1': { | ||
272 | 2220 | 'bridge': False, 'carrier': False, 'dormant': False, | ||
273 | 2221 | 'operstate': 'down', 'address': '00:11:22:33:44:55', | ||
274 | 2222 | 'device/driver': 'mlx4_core', 'device/device': '0x7', | ||
275 | 2223 | 'name_assign_type': '4'}, | ||
276 | 2224 | |||
277 | 2225 | } | ||
278 | 2226 | |||
279 | 2227 | tmp_dir = self.tmp_dir() | ||
280 | 2228 | _setup_test(tmp_dir, mock_get_devicelist, | ||
281 | 2229 | mock_read_sys_net, mock_sys_dev_path, | ||
282 | 2230 | dev_attrs=devices) | ||
283 | 2231 | |||
284 | 2232 | network_cfg = net.generate_fallback_config(config_driver=True) | ||
285 | 2233 | expected = { | ||
286 | 2234 | 'ethernets': {'eth0': {'dhcp4': True, 'set-name': 'eth0', | ||
287 | 2235 | 'match': {'macaddress': '00:11:22:33:44:55', | ||
288 | 2236 | 'driver': 'hv_netsvc'}}}, | ||
289 | 2237 | 'version': 2} | ||
290 | 2238 | self.assertEqual(expected, network_cfg) | ||
291 | 2239 | |||
292 | 2240 | @mock.patch("cloudinit.net.sys_dev_path") | ||
293 | 2241 | @mock.patch("cloudinit.net.read_sys_net") | ||
294 | 2242 | @mock.patch("cloudinit.net.get_devicelist") | ||
295 | 2210 | def test_device_driver(self, mock_get_devicelist, mock_read_sys_net, | 2243 | def test_device_driver(self, mock_get_devicelist, mock_read_sys_net, |
296 | 2211 | mock_sys_dev_path): | 2244 | mock_sys_dev_path): |
297 | 2212 | devices = { | 2245 | devices = { |
298 | @@ -2486,7 +2519,7 @@ class TestRhelSysConfigRendering(CiTestCase): | |||
299 | 2486 | # | 2519 | # |
300 | 2487 | BOOTPROTO=dhcp | 2520 | BOOTPROTO=dhcp |
301 | 2488 | DEVICE=eth1000 | 2521 | DEVICE=eth1000 |
303 | 2489 | HWADDR=07-1C-C6-75-A4-BE | 2522 | HWADDR=07-1c-c6-75-a4-be |
304 | 2490 | NM_CONTROLLED=no | 2523 | NM_CONTROLLED=no |
305 | 2491 | ONBOOT=yes | 2524 | ONBOOT=yes |
306 | 2492 | STARTMODE=auto | 2525 | STARTMODE=auto |
307 | @@ -3030,7 +3063,7 @@ class TestOpenSuseSysConfigRendering(CiTestCase): | |||
308 | 3030 | # | 3063 | # |
309 | 3031 | BOOTPROTO=dhcp | 3064 | BOOTPROTO=dhcp |
310 | 3032 | DEVICE=eth1000 | 3065 | DEVICE=eth1000 |
312 | 3033 | HWADDR=07-1C-C6-75-A4-BE | 3066 | HWADDR=07-1c-c6-75-a4-be |
313 | 3034 | NM_CONTROLLED=no | 3067 | NM_CONTROLLED=no |
314 | 3035 | ONBOOT=yes | 3068 | ONBOOT=yes |
315 | 3036 | STARTMODE=auto | 3069 | STARTMODE=auto |
316 | @@ -3342,13 +3375,13 @@ class TestNetplanNetRendering(CiTestCase): | |||
317 | 3342 | 3375 | ||
318 | 3343 | expected = """ | 3376 | expected = """ |
319 | 3344 | network: | 3377 | network: |
320 | 3345 | version: 2 | ||
321 | 3346 | ethernets: | 3378 | ethernets: |
322 | 3347 | eth1000: | 3379 | eth1000: |
323 | 3348 | dhcp4: true | 3380 | dhcp4: true |
324 | 3349 | match: | 3381 | match: |
325 | 3350 | macaddress: 07-1c-c6-75-a4-be | 3382 | macaddress: 07-1c-c6-75-a4-be |
326 | 3351 | set-name: eth1000 | 3383 | set-name: eth1000 |
327 | 3384 | version: 2 | ||
328 | 3352 | """ | 3385 | """ |
329 | 3353 | self.assertEqual(expected.lstrip(), contents.lstrip()) | 3386 | self.assertEqual(expected.lstrip(), contents.lstrip()) |
330 | 3354 | self.assertEqual(1, mock_clean_default.call_count) | 3387 | self.assertEqual(1, mock_clean_default.call_count) |
PASSED: Continuous integration, rev:850c0d90bdf 26f45b5d771e77c aee3d32d73ba74 /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 1026/
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: /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 1026//rebuild
https:/