Merge ~ltrager/maas:lp1835275_2.6 into maas:2.6
- Git
- lp:~ltrager/maas
- lp1835275_2.6
- Merge into 2.6
Proposed by
Lee Trager
Status: | Merged |
---|---|
Approved by: | Lee Trager |
Approved revision: | 3e60de3e98265c202e9835b8174fed0d03c20693 |
Merge reported by: | MAAS Lander |
Merged at revision: | not available |
Proposed branch: | ~ltrager/maas:lp1835275_2.6 |
Merge into: | maas:2.6 |
Diff against target: |
256 lines (+77/-18) 3 files modified
src/metadataserver/tests/test_api.py (+3/-4) src/metadataserver/tests/test_vendor_data.py (+53/-12) src/metadataserver/vendor_data.py (+21/-2) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Lee Trager (community) | Approve | ||
Review via email:
|
Commit message
Backport of 302d171 LP: #1835275 - Remove netplan interface lock.
Netplan creates a configuration file which locks the interface used to boot.
This ensures netbooted environments don't get disconnected. MAAS may send
a netplan configuration file which will reconfigure the boot interface. The
script runner will ensure the machine reconnects.
Description of the change
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
MAAS Lander (maas-lander) wrote : | # |
LANDING
-b lp1835275_2.6 lp:~ltrager/maas/+git/maas into -b 2.6 lp:~maas-committers/maas
STATUS: FAILED BUILD
LOG: http://
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/src/metadataserver/tests/test_api.py b/src/metadataserver/tests/test_api.py | |||
2 | index 45a8361..e9f4b25 100644 | |||
3 | --- a/src/metadataserver/tests/test_api.py | |||
4 | +++ b/src/metadataserver/tests/test_api.py | |||
5 | @@ -114,7 +114,6 @@ from testtools.matchers import ( | |||
6 | 114 | ContainsAll, | 114 | ContainsAll, |
7 | 115 | ContainsDict, | 115 | ContainsDict, |
8 | 116 | Equals, | 116 | Equals, |
9 | 117 | HasLength, | ||
10 | 118 | KeysEqual, | 117 | KeysEqual, |
11 | 119 | StartsWith, | 118 | StartsWith, |
12 | 120 | ) | 119 | ) |
13 | @@ -855,7 +854,7 @@ class TestMetadataCommon(MAASServerTestCase): | |||
14 | 855 | self.assertThat(content, LooksLikeCloudInit) | 854 | self.assertThat(content, LooksLikeCloudInit) |
15 | 856 | self.assertThat( | 855 | self.assertThat( |
16 | 857 | yaml.safe_load(content['cloud-init']), | 856 | yaml.safe_load(content['cloud-init']), |
18 | 858 | KeysEqual("system_info")) | 857 | KeysEqual("system_info", "runcmd")) |
19 | 859 | 858 | ||
20 | 860 | def test_vendor_data_node_without_def_user_includes_no_system_info(self): | 859 | def test_vendor_data_node_without_def_user_includes_no_system_info(self): |
21 | 861 | # Test vendor_data includes no system_info when the node has an owner | 860 | # Test vendor_data includes no system_info when the node has an owner |
22 | @@ -871,7 +870,7 @@ class TestMetadataCommon(MAASServerTestCase): | |||
23 | 871 | self.assertThat(content, LooksLikeCloudInit) | 870 | self.assertThat(content, LooksLikeCloudInit) |
24 | 872 | self.assertThat( | 871 | self.assertThat( |
25 | 873 | yaml.safe_load(content['cloud-init']), | 872 | yaml.safe_load(content['cloud-init']), |
27 | 874 | HasLength(0)) | 873 | KeysEqual('runcmd')) |
28 | 875 | 874 | ||
29 | 876 | def test_vendor_data_for_node_without_owner_includes_no_system_info(self): | 875 | def test_vendor_data_for_node_without_owner_includes_no_system_info(self): |
30 | 877 | view_name = self.get_metadata_name('-meta-data') | 876 | view_name = self.get_metadata_name('-meta-data') |
31 | @@ -883,7 +882,7 @@ class TestMetadataCommon(MAASServerTestCase): | |||
32 | 883 | self.assertThat(content, LooksLikeCloudInit) | 882 | self.assertThat(content, LooksLikeCloudInit) |
33 | 884 | self.assertThat( | 883 | self.assertThat( |
34 | 885 | yaml.safe_load(content['cloud-init']), | 884 | yaml.safe_load(content['cloud-init']), |
36 | 886 | HasLength(0)) | 885 | KeysEqual('runcmd')) |
37 | 887 | 886 | ||
38 | 888 | def test_vendor_data_calls_through_to_get_vendor_data(self): | 887 | def test_vendor_data_calls_through_to_get_vendor_data(self): |
39 | 889 | # i.e. for further information, see `get_vendor_data`. | 888 | # i.e. for further information, see `get_vendor_data`. |
40 | diff --git a/src/metadataserver/tests/test_vendor_data.py b/src/metadataserver/tests/test_vendor_data.py | |||
41 | index a5db4fc..ad770d2 100644 | |||
42 | --- a/src/metadataserver/tests/test_vendor_data.py | |||
43 | +++ b/src/metadataserver/tests/test_vendor_data.py | |||
44 | @@ -5,10 +5,14 @@ | |||
45 | 5 | 5 | ||
46 | 6 | __all__ = [] | 6 | __all__ = [] |
47 | 7 | 7 | ||
48 | 8 | import random | ||
49 | 9 | |||
50 | 10 | from maasserver.enum import NODE_STATUS | ||
51 | 8 | from maasserver.models import ( | 11 | from maasserver.models import ( |
52 | 9 | Config, | 12 | Config, |
53 | 10 | NodeMetadata, | 13 | NodeMetadata, |
54 | 11 | ) | 14 | ) |
55 | 15 | from maasserver.node_status import COMMISSIONING_LIKE_STATUSES | ||
56 | 12 | from maasserver.server_address import get_maas_facing_server_host | 16 | from maasserver.server_address import get_maas_facing_server_host |
57 | 13 | from maasserver.testing.factory import factory | 17 | from maasserver.testing.factory import factory |
58 | 14 | from maasserver.testing.fixtures import RBACEnabled | 18 | from maasserver.testing.fixtures import RBACEnabled |
59 | @@ -237,7 +241,8 @@ class TestGenerateRackControllerConfiguration(MAASServerTestCase): | |||
60 | 237 | })) | 241 | })) |
61 | 238 | 242 | ||
62 | 239 | def test_yields_configuration_when_machine_install_kvm_true(self): | 243 | def test_yields_configuration_when_machine_install_kvm_true(self): |
64 | 240 | node = factory.make_Node(osystem='ubuntu', netboot=False) | 244 | node = factory.make_Node( |
65 | 245 | status=NODE_STATUS.DEPLOYING, osystem='ubuntu', netboot=False) | ||
66 | 241 | node.install_kvm = True | 246 | node.install_kvm = True |
67 | 242 | configuration = get_vendor_data(node, None) | 247 | configuration = get_vendor_data(node, None) |
68 | 243 | config = str(dict(configuration)) | 248 | config = str(dict(configuration)) |
69 | @@ -271,7 +276,8 @@ class TestGenerateRackControllerConfiguration(MAASServerTestCase): | |||
70 | 271 | 276 | ||
71 | 272 | def test_includes_smt_off_for_install_kvm_on_ppc64(self): | 277 | def test_includes_smt_off_for_install_kvm_on_ppc64(self): |
72 | 273 | node = factory.make_Node( | 278 | node = factory.make_Node( |
74 | 274 | osystem='ubuntu', netboot=False, architecture='ppc64el/generic') | 279 | status=NODE_STATUS.DEPLOYING, osystem='ubuntu', netboot=False, |
75 | 280 | architecture='ppc64el/generic') | ||
76 | 275 | node.install_kvm = True | 281 | node.install_kvm = True |
77 | 276 | configuration = get_vendor_data(node, None) | 282 | configuration = get_vendor_data(node, None) |
78 | 277 | config = dict(configuration) | 283 | config = dict(configuration) |
79 | @@ -288,6 +294,26 @@ class TestGenerateRackControllerConfiguration(MAASServerTestCase): | |||
80 | 288 | self.assertThat(config['runcmd'], Contains(['/etc/rc.local'])) | 294 | self.assertThat(config['runcmd'], Contains(['/etc/rc.local'])) |
81 | 289 | 295 | ||
82 | 290 | 296 | ||
83 | 297 | class TestGenerateEphemeralNetplanLockRemoval(MAASServerTestCase): | ||
84 | 298 | """Tests for `generate_ephemeral_netplan_lock_removal`.""" | ||
85 | 299 | |||
86 | 300 | def test__does_nothing_if_deploying(self): | ||
87 | 301 | # MAAS transitions a machine from DEPLOYING to DEPLOYED after | ||
88 | 302 | # user_data has been requested. Make sure deploying nodes don't | ||
89 | 303 | # get this config. | ||
90 | 304 | node = factory.make_Node(status=NODE_STATUS.DEPLOYING) | ||
91 | 305 | configuration = get_vendor_data(node, None) | ||
92 | 306 | config = dict(configuration) | ||
93 | 307 | self.assertNotIn('runcmd', config) | ||
94 | 308 | |||
95 | 309 | def test__removes_lock_when_ephemeral(self): | ||
96 | 310 | node = factory.make_Node( | ||
97 | 311 | status=random.choice(COMMISSIONING_LIKE_STATUSES)) | ||
98 | 312 | configuration = get_vendor_data(node, None) | ||
99 | 313 | config = dict(configuration) | ||
100 | 314 | self.assertThat(config['runcmd'], Contains('rm -rf /run/netplan')) | ||
101 | 315 | |||
102 | 316 | |||
103 | 291 | class TestGenerateEphemeralDeploymentNetworkConfiguration(MAASServerTestCase): | 317 | class TestGenerateEphemeralDeploymentNetworkConfiguration(MAASServerTestCase): |
104 | 292 | """Tests for `generate_ephemeral_deployment_network_configuration`.""" | 318 | """Tests for `generate_ephemeral_deployment_network_configuration`.""" |
105 | 293 | 319 | ||
106 | @@ -303,8 +329,10 @@ class TestGenerateEphemeralDeploymentNetworkConfiguration(MAASServerTestCase): | |||
107 | 303 | config = dict(configuration) | 329 | config = dict(configuration) |
108 | 304 | self.assertThat( | 330 | self.assertThat( |
109 | 305 | config['write_files'][0]['path'], | 331 | config['write_files'][0]['path'], |
112 | 306 | Contains("/etc/netplan/config.yaml")) | 332 | Contains("/etc/netplan/50-maas.yaml")) |
113 | 307 | self.assertThat(config['runcmd'], Contains("netplan apply")) | 333 | # Make sure netplan's lock is removed before applying the config |
114 | 334 | self.assertEquals(config['runcmd'][0], 'rm -rf /run/netplan') | ||
115 | 335 | self.assertEquals(config['runcmd'][1], 'netplan apply --debug') | ||
116 | 308 | 336 | ||
117 | 309 | 337 | ||
118 | 310 | class TestGenerateVcenterConfiguration(MAASServerTestCase): | 338 | class TestGenerateVcenterConfiguration(MAASServerTestCase): |
119 | @@ -312,19 +340,24 @@ class TestGenerateVcenterConfiguration(MAASServerTestCase): | |||
120 | 312 | 340 | ||
121 | 313 | def test_does_nothing_if_not_vmware(self): | 341 | def test_does_nothing_if_not_vmware(self): |
122 | 314 | mock_get_configs = self.patch(Config.objects, 'get_configs') | 342 | mock_get_configs = self.patch(Config.objects, 'get_configs') |
124 | 315 | node = factory.make_Node(owner=factory.make_admin()) | 343 | node = factory.make_Node( |
125 | 344 | status=NODE_STATUS.DEPLOYING, owner=factory.make_admin()) | ||
126 | 316 | config = get_vendor_data(node, None) | 345 | config = get_vendor_data(node, None) |
127 | 317 | self.assertThat(mock_get_configs, MockNotCalled()) | 346 | self.assertThat(mock_get_configs, MockNotCalled()) |
128 | 318 | self.assertDictEqual({}, config) | 347 | self.assertDictEqual({}, config) |
129 | 319 | 348 | ||
130 | 320 | def test_returns_nothing_if_no_values_set(self): | 349 | def test_returns_nothing_if_no_values_set(self): |
132 | 321 | node = factory.make_Node(osystem='esxi', owner=factory.make_admin()) | 350 | node = factory.make_Node( |
133 | 351 | status=NODE_STATUS.DEPLOYING, osystem='esxi', | ||
134 | 352 | owner=factory.make_admin()) | ||
135 | 322 | node.nodemetadata_set.create(key='vcenter_registration', value='True') | 353 | node.nodemetadata_set.create(key='vcenter_registration', value='True') |
136 | 323 | config = get_vendor_data(node, None) | 354 | config = get_vendor_data(node, None) |
137 | 324 | self.assertDictEqual({}, config) | 355 | self.assertDictEqual({}, config) |
138 | 325 | 356 | ||
139 | 326 | def test_returns_vcenter_yaml(self): | 357 | def test_returns_vcenter_yaml(self): |
141 | 327 | node = factory.make_Node(osystem='esxi', owner=factory.make_admin()) | 358 | node = factory.make_Node( |
142 | 359 | status=NODE_STATUS.DEPLOYING, osystem='esxi', | ||
143 | 360 | owner=factory.make_admin()) | ||
144 | 328 | node.nodemetadata_set.create(key='vcenter_registration', value='True') | 361 | node.nodemetadata_set.create(key='vcenter_registration', value='True') |
145 | 329 | vcenter = { | 362 | vcenter = { |
146 | 330 | 'vcenter_server': factory.make_name('vcenter_server'), | 363 | 'vcenter_server': factory.make_name('vcenter_server'), |
147 | @@ -343,7 +376,9 @@ class TestGenerateVcenterConfiguration(MAASServerTestCase): | |||
148 | 343 | 376 | ||
149 | 344 | def test_returns_vcenter_yaml_if_rbac_admin(self): | 377 | def test_returns_vcenter_yaml_if_rbac_admin(self): |
150 | 345 | rbac = self.useFixture(RBACEnabled()) | 378 | rbac = self.useFixture(RBACEnabled()) |
152 | 346 | node = factory.make_Node(osystem='esxi', owner=factory.make_User()) | 379 | node = factory.make_Node( |
153 | 380 | status=NODE_STATUS.DEPLOYING, osystem='esxi', | ||
154 | 381 | owner=factory.make_User()) | ||
155 | 347 | node.nodemetadata_set.create(key='vcenter_registration', value='True') | 382 | node.nodemetadata_set.create(key='vcenter_registration', value='True') |
156 | 348 | rbac.store.add_pool(node.pool) | 383 | rbac.store.add_pool(node.pool) |
157 | 349 | rbac.store.allow(node.owner.username, node.pool, 'admin-machines') | 384 | rbac.store.allow(node.owner.username, node.pool, 'admin-machines') |
158 | @@ -364,7 +399,9 @@ class TestGenerateVcenterConfiguration(MAASServerTestCase): | |||
159 | 364 | 399 | ||
160 | 365 | def test_returns_nothing_if_rbac_user(self): | 400 | def test_returns_nothing_if_rbac_user(self): |
161 | 366 | rbac = self.useFixture(RBACEnabled()) | 401 | rbac = self.useFixture(RBACEnabled()) |
163 | 367 | node = factory.make_Node(osystem='esxi', owner=factory.make_User()) | 402 | node = factory.make_Node( |
164 | 403 | status=NODE_STATUS.DEPLOYING, osystem='esxi', | ||
165 | 404 | owner=factory.make_User()) | ||
166 | 368 | node.nodemetadata_set.create(key='vcenter_registration', value='True') | 405 | node.nodemetadata_set.create(key='vcenter_registration', value='True') |
167 | 369 | rbac.store.add_pool(node.pool) | 406 | rbac.store.add_pool(node.pool) |
168 | 370 | rbac.store.allow(node.owner.username, node.pool, 'deploy-machines') | 407 | rbac.store.allow(node.owner.username, node.pool, 'deploy-machines') |
169 | @@ -380,7 +417,7 @@ class TestGenerateVcenterConfiguration(MAASServerTestCase): | |||
170 | 380 | self.assertDictEqual({}, config) | 417 | self.assertDictEqual({}, config) |
171 | 381 | 418 | ||
172 | 382 | def test_returns_nothing_if_no_user(self): | 419 | def test_returns_nothing_if_no_user(self): |
174 | 383 | node = factory.make_Node(osystem='esxi') | 420 | node = factory.make_Node(status=NODE_STATUS.DEPLOYING, osystem='esxi') |
175 | 384 | for i in ['server', 'username', 'password', 'datacenter']: | 421 | for i in ['server', 'username', 'password', 'datacenter']: |
176 | 385 | key = 'vcenter_%s' % i | 422 | key = 'vcenter_%s' % i |
177 | 386 | Config.objects.set_config(key, factory.make_name(key)) | 423 | Config.objects.set_config(key, factory.make_name(key)) |
178 | @@ -388,7 +425,9 @@ class TestGenerateVcenterConfiguration(MAASServerTestCase): | |||
179 | 388 | self.assertDictEqual({}, config) | 425 | self.assertDictEqual({}, config) |
180 | 389 | 426 | ||
181 | 390 | def test_returns_nothing_if_user(self): | 427 | def test_returns_nothing_if_user(self): |
183 | 391 | node = factory.make_Node(osystem='esxi', owner=factory.make_User()) | 428 | node = factory.make_Node( |
184 | 429 | status=NODE_STATUS.DEPLOYING, osystem='esxi', | ||
185 | 430 | owner=factory.make_User()) | ||
186 | 392 | for i in ['server', 'username', 'password', 'datacenter']: | 431 | for i in ['server', 'username', 'password', 'datacenter']: |
187 | 393 | key = 'vcenter_%s' % i | 432 | key = 'vcenter_%s' % i |
188 | 394 | Config.objects.set_config(key, factory.make_name(key)) | 433 | Config.objects.set_config(key, factory.make_name(key)) |
189 | @@ -396,7 +435,9 @@ class TestGenerateVcenterConfiguration(MAASServerTestCase): | |||
190 | 396 | self.assertDictEqual({}, config) | 435 | self.assertDictEqual({}, config) |
191 | 397 | 436 | ||
192 | 398 | def test_returns_nothing_if_vcenter_registration_not_set(self): | 437 | def test_returns_nothing_if_vcenter_registration_not_set(self): |
194 | 399 | node = factory.make_Node(osystem='esxi', owner=factory.make_admin()) | 438 | node = factory.make_Node( |
195 | 439 | status=NODE_STATUS.DEPLOYING, osystem='esxi', | ||
196 | 440 | owner=factory.make_admin()) | ||
197 | 400 | for i in ['server', 'username', 'password', 'datacenter']: | 441 | for i in ['server', 'username', 'password', 'datacenter']: |
198 | 401 | key = 'vcenter_%s' % i | 442 | key = 'vcenter_%s' % i |
199 | 402 | Config.objects.set_config(key, factory.make_name(key)) | 443 | Config.objects.set_config(key, factory.make_name(key)) |
200 | diff --git a/src/metadataserver/vendor_data.py b/src/metadataserver/vendor_data.py | |||
201 | index b4c7adf..1e992d9 100644 | |||
202 | --- a/src/metadataserver/vendor_data.py | |||
203 | +++ b/src/metadataserver/vendor_data.py | |||
204 | @@ -17,6 +17,7 @@ from maasserver.models import ( | |||
205 | 17 | Config, | 17 | Config, |
206 | 18 | NodeMetadata, | 18 | NodeMetadata, |
207 | 19 | ) | 19 | ) |
208 | 20 | from maasserver.node_status import COMMISSIONING_LIKE_STATUSES | ||
209 | 20 | from maasserver.permissions import NodePermission | 21 | from maasserver.permissions import NodePermission |
210 | 21 | from maasserver.preseed import get_network_yaml_settings | 22 | from maasserver.preseed import get_network_yaml_settings |
211 | 22 | from maasserver.preseed_network import NodeNetworkConfiguration | 23 | from maasserver.preseed_network import NodeNetworkConfiguration |
212 | @@ -34,6 +35,7 @@ def get_vendor_data(node, proxy): | |||
213 | 34 | generate_ntp_configuration(node), | 35 | generate_ntp_configuration(node), |
214 | 35 | generate_rack_controller_configuration(node, proxy), | 36 | generate_rack_controller_configuration(node, proxy), |
215 | 36 | generate_kvm_pod_configuration(node), | 37 | generate_kvm_pod_configuration(node), |
216 | 38 | generate_ephemeral_netplan_lock_removal(node), | ||
217 | 37 | generate_ephemeral_deployment_network_configuration(node), | 39 | generate_ephemeral_deployment_network_configuration(node), |
218 | 38 | generate_vcenter_configuration(node), | 40 | generate_vcenter_configuration(node), |
219 | 39 | )) | 41 | )) |
220 | @@ -110,6 +112,20 @@ def generate_rack_controller_configuration(node, proxy): | |||
221 | 110 | ] | 112 | ] |
222 | 111 | 113 | ||
223 | 112 | 114 | ||
224 | 115 | def generate_ephemeral_netplan_lock_removal(node): | ||
225 | 116 | """Remove netplan's interface lock. | ||
226 | 117 | |||
227 | 118 | When booting a machine over the network netplan creates a configuration | ||
228 | 119 | file in /run/netplan for the interface used to boot. This contains the | ||
229 | 120 | settings used on boot(DHCP), what renderer was used(networkd), and marks | ||
230 | 121 | the interface as critical. Netplan will ensure interfaces marked critical | ||
231 | 122 | will always have the specified configuration applied. This overrides | ||
232 | 123 | anything put in /etc/netplan breaking custom network configuration.""" | ||
233 | 124 | |||
234 | 125 | if node.status in COMMISSIONING_LIKE_STATUSES: | ||
235 | 126 | yield 'runcmd', ['rm -rf /run/netplan'] | ||
236 | 127 | |||
237 | 128 | |||
238 | 113 | def generate_ephemeral_deployment_network_configuration(node): | 129 | def generate_ephemeral_deployment_network_configuration(node): |
239 | 114 | """Generate cloud-init network configuration for ephemeral deployment.""" | 130 | """Generate cloud-init network configuration for ephemeral deployment.""" |
240 | 115 | if node.ephemeral_deployment: | 131 | if node.ephemeral_deployment: |
241 | @@ -125,10 +141,13 @@ def generate_ephemeral_deployment_network_configuration(node): | |||
242 | 125 | yield "write_files", [ | 141 | yield "write_files", [ |
243 | 126 | { | 142 | { |
244 | 127 | 'content': network_config_yaml, | 143 | 'content': network_config_yaml, |
246 | 128 | 'path': "/etc/netplan/config.yaml", | 144 | 'path': "/etc/netplan/50-maas.yaml", |
247 | 129 | } | 145 | } |
248 | 130 | ] | 146 | ] |
250 | 131 | yield "runcmd", ["netplan apply"] | 147 | yield "runcmd", [ |
251 | 148 | "rm -rf /run/netplan", | ||
252 | 149 | "netplan apply --debug", | ||
253 | 150 | ] | ||
254 | 132 | 151 | ||
255 | 133 | 152 | ||
256 | 134 | def generate_kvm_pod_configuration(node): | 153 | def generate_kvm_pod_configuration(node): |
Reviewed in - https:/ /code.launchpad .net/~ltrager/ maas/+git/ maas/+merge/ 370289