Merge ~cgrabowski/maas:fix_lp1982866_3.1_backport into maas:3.1
- Git
- lp:~cgrabowski/maas
- fix_lp1982866_3.1_backport
- Merge into 3.1
Proposed by
Christian Grabowski
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Christian Grabowski | ||||
Approved revision: | cd09b8b718cbbd68b07c4c9df9b3d7091e57c867 | ||||
Merge reported by: | MAAS Lander | ||||
Merged at revision: | not available | ||||
Proposed branch: | ~cgrabowski/maas:fix_lp1982866_3.1_backport | ||||
Merge into: | maas:3.1 | ||||
Diff against target: |
316 lines (+187/-14) 6 files modified
src/maasserver/forms/__init__.py (+17/-4) src/maasserver/forms/tests/test_bootresource.py (+40/-5) src/maasserver/models/bootresource.py (+11/-0) src/maasserver/models/tests/test_bootresource.py (+12/-0) src/maasserver/rpc/boot.py (+1/-4) src/maasserver/rpc/tests/test_boot.py (+106/-1) |
||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
MAAS Lander | Approve | ||
MAAS Maintainers | Pending | ||
Review via email: mp+430384@code.launchpad.net |
Commit message
use BootResource's method for splitting base image to get a default value in get_boot_
(cherry picked from commit d58366ec06df69f
Description of the change
To post a comment you must log in.
Revision history for this message
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b fix_lp1982866_
STATUS: FAILED
LOG: http://
COMMIT: cd09b8b718cbbd6
review:
Needs Fixing
Revision history for this message
Christian Grabowski (cgrabowski) wrote : | # |
jenkins: !test
Revision history for this message
MAAS Lander (maas-lander) wrote : | # |
UNIT TESTS
-b fix_lp1982866_
STATUS: SUCCESS
COMMIT: cd09b8b718cbbd6
review:
Approve
Revision history for this message
Christian Grabowski (cgrabowski) wrote : | # |
self-approving backport
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/src/maasserver/forms/__init__.py b/src/maasserver/forms/__init__.py | |||
2 | index d88c443..2c0cf46 100644 | |||
3 | --- a/src/maasserver/forms/__init__.py | |||
4 | +++ b/src/maasserver/forms/__init__.py | |||
5 | @@ -2493,7 +2493,7 @@ class BootResourceForm(MAASModelForm): | |||
6 | 2493 | return name | 2493 | return name |
7 | 2494 | 2494 | ||
8 | 2495 | def _get_base_image_info(self): | 2495 | def _get_base_image_info(self): |
10 | 2496 | base_image = self.cleaned_data["base_image"] | 2496 | base_image = self.cleaned_data.get("base_image") |
11 | 2497 | if not base_image: | 2497 | if not base_image: |
12 | 2498 | existing_resource = super().save(commit=False) | 2498 | existing_resource = super().save(commit=False) |
13 | 2499 | existing_resource.name = self.cleaned_data["name"] | 2499 | existing_resource.name = self.cleaned_data["name"] |
14 | @@ -2522,9 +2522,22 @@ class BootResourceForm(MAASModelForm): | |||
15 | 2522 | try: | 2522 | try: |
16 | 2523 | base_osystem, base_version = self._get_base_image_info() | 2523 | base_osystem, base_version = self._get_base_image_info() |
17 | 2524 | except ValueError: | 2524 | except ValueError: |
21 | 2525 | raise ValidationError( | 2525 | if not self.data.get("base_image"): |
22 | 2526 | "custom images require a valid base image name" | 2526 | return "/".join( |
23 | 2527 | ) | 2527 | [ |
24 | 2528 | val | ||
25 | 2529 | for val in Config.objects.get_configs( | ||
26 | 2530 | [ | ||
27 | 2531 | "commissioning_osystem", | ||
28 | 2532 | "commissioning_distro_series", | ||
29 | 2533 | ] | ||
30 | 2534 | ).values() | ||
31 | 2535 | ] | ||
32 | 2536 | ) | ||
33 | 2537 | else: | ||
34 | 2538 | raise ValidationError( | ||
35 | 2539 | "a base image must follow the format: <osystem>/<series>" | ||
36 | 2540 | ) | ||
37 | 2528 | else: | 2541 | else: |
38 | 2529 | if base_osystem not in ("ubuntu", "centos", "rhel"): | 2542 | if base_osystem not in ("ubuntu", "centos", "rhel"): |
39 | 2530 | raise ValidationError( | 2543 | raise ValidationError( |
40 | diff --git a/src/maasserver/forms/tests/test_bootresource.py b/src/maasserver/forms/tests/test_bootresource.py | |||
41 | index e8aaeec..4544a1d 100644 | |||
42 | --- a/src/maasserver/forms/tests/test_bootresource.py | |||
43 | +++ b/src/maasserver/forms/tests/test_bootresource.py | |||
44 | @@ -10,7 +10,7 @@ from django.core.files.uploadedfile import SimpleUploadedFile | |||
45 | 10 | 10 | ||
46 | 11 | from maasserver.enum import BOOT_RESOURCE_FILE_TYPE, BOOT_RESOURCE_TYPE | 11 | from maasserver.enum import BOOT_RESOURCE_FILE_TYPE, BOOT_RESOURCE_TYPE |
47 | 12 | from maasserver.forms import BootResourceForm | 12 | from maasserver.forms import BootResourceForm |
49 | 13 | from maasserver.models import BootResource, BootResourceFile | 13 | from maasserver.models import BootResource, BootResourceFile, Config |
50 | 14 | from maasserver.models.signals import bootresourcefiles, bootsources | 14 | from maasserver.models.signals import bootresourcefiles, bootsources |
51 | 15 | from maasserver.testing.architecture import make_usable_architecture | 15 | from maasserver.testing.architecture import make_usable_architecture |
52 | 16 | from maasserver.testing.factory import factory | 16 | from maasserver.testing.factory import factory |
53 | @@ -303,7 +303,7 @@ class TestBootResourceForm(MAASServerTestCase): | |||
54 | 303 | image = form.save() | 303 | image = form.save() |
55 | 304 | self.assertEqual(image.base_image, data["base_image"]) | 304 | self.assertEqual(image.base_image, data["base_image"]) |
56 | 305 | 305 | ||
58 | 306 | def test_invalidates_nonexistent_custom_image_base_os(self): | 306 | def test_uses_commissioning_os_for_nonexistent_custom_image_base_os(self): |
59 | 307 | name = "custom/%s" % factory.make_name("name") | 307 | name = "custom/%s" % factory.make_name("name") |
60 | 308 | upload_type, filetype = self.pick_filetype() | 308 | upload_type, filetype = self.pick_filetype() |
61 | 309 | size = random.randint(1024, 2048) | 309 | size = random.randint(1024, 2048) |
62 | @@ -315,10 +315,17 @@ class TestBootResourceForm(MAASServerTestCase): | |||
63 | 315 | "title": factory.make_name("title"), | 315 | "title": factory.make_name("title"), |
64 | 316 | "architecture": make_usable_architecture(self), | 316 | "architecture": make_usable_architecture(self), |
65 | 317 | "filetype": upload_type, | 317 | "filetype": upload_type, |
67 | 318 | "base_image": factory.make_name("invalid"), | 318 | "base_image": "", |
68 | 319 | } | 319 | } |
69 | 320 | form = BootResourceForm(data=data, files={"content": uploaded_file}) | 320 | form = BootResourceForm(data=data, files={"content": uploaded_file}) |
71 | 321 | self.assertFalse(form.is_valid()) | 321 | form.save() |
72 | 322 | cfg = Config.objects.get_configs( | ||
73 | 323 | ["commissioning_osystem", "commissioning_distro_series"] | ||
74 | 324 | ) | ||
75 | 325 | self.assertEqual( | ||
76 | 326 | f"{cfg['commissioning_osystem']}/{cfg['commissioning_distro_series']}", | ||
77 | 327 | form.instance.base_image, | ||
78 | 328 | ) | ||
79 | 322 | 329 | ||
80 | 323 | def test_invalidates_nonexistent_custom_image_base_os_no_prefix(self): | 330 | def test_invalidates_nonexistent_custom_image_base_os_no_prefix(self): |
81 | 324 | name = factory.make_name("name") | 331 | name = factory.make_name("name") |
82 | @@ -485,7 +492,7 @@ class TestBootResourceForm(MAASServerTestCase): | |||
83 | 485 | form = BootResourceForm(data={}) | 492 | form = BootResourceForm(data={}) |
84 | 486 | self.assertFalse(form.is_valid(), form.errors) | 493 | self.assertFalse(form.is_valid(), form.errors) |
85 | 487 | self.assertEqual( | 494 | self.assertEqual( |
87 | 488 | {"name", "architecture", "filetype", "content", "base_image"}, | 495 | {"name", "architecture", "filetype", "content"}, |
88 | 489 | form.errors.keys(), | 496 | form.errors.keys(), |
89 | 490 | ) | 497 | ) |
90 | 491 | 498 | ||
91 | @@ -522,3 +529,31 @@ class TestBootResourceForm(MAASServerTestCase): | |||
92 | 522 | resource_set__resource=resource | 529 | resource_set__resource=resource |
93 | 523 | ).count(), | 530 | ).count(), |
94 | 524 | ) | 531 | ) |
95 | 532 | |||
96 | 533 | def test_clean_base_image_sets_commissioning_osystem_and_distro_series_where_none_is_given( | ||
97 | 534 | self, | ||
98 | 535 | ): | ||
99 | 536 | architecture = make_usable_architecture(self) | ||
100 | 537 | upload_type, filetype = self.pick_filetype() | ||
101 | 538 | content = factory.make_string(1024).encode("utf-8") | ||
102 | 539 | upload_name = factory.make_name("filename") | ||
103 | 540 | uploaded_file = SimpleUploadedFile(content=content, name=upload_name) | ||
104 | 541 | data = { | ||
105 | 542 | "name": f"custom/{factory.make_name()}", | ||
106 | 543 | "architecture": architecture, | ||
107 | 544 | "filetype": upload_type, | ||
108 | 545 | } | ||
109 | 546 | form = BootResourceForm(data=data, files={"content": uploaded_file}) | ||
110 | 547 | form.save() | ||
111 | 548 | cfg = Config.objects.get_configs( | ||
112 | 549 | ["commissioning_osystem", "commissioning_distro_series"] | ||
113 | 550 | ) | ||
114 | 551 | self.assertEqual( | ||
115 | 552 | "/".join( | ||
116 | 553 | [ | ||
117 | 554 | cfg["commissioning_osystem"], | ||
118 | 555 | cfg["commissioning_distro_series"], | ||
119 | 556 | ] | ||
120 | 557 | ), | ||
121 | 558 | form.instance.base_image, | ||
122 | 559 | ) | ||
123 | diff --git a/src/maasserver/models/bootresource.py b/src/maasserver/models/bootresource.py | |||
124 | index 0c16c67..39b6a66 100644 | |||
125 | --- a/src/maasserver/models/bootresource.py | |||
126 | +++ b/src/maasserver/models/bootresource.py | |||
127 | @@ -28,6 +28,7 @@ from maasserver.fields import JSONObjectField | |||
128 | 28 | from maasserver.models.bootresourceset import BootResourceSet | 28 | from maasserver.models.bootresourceset import BootResourceSet |
129 | 29 | from maasserver.models.bootsourcecache import BootSourceCache | 29 | from maasserver.models.bootsourcecache import BootSourceCache |
130 | 30 | from maasserver.models.cleansave import CleanSave | 30 | from maasserver.models.cleansave import CleanSave |
131 | 31 | from maasserver.models.config import Config | ||
132 | 31 | from maasserver.models.timestampedmodel import now, TimestampedModel | 32 | from maasserver.models.timestampedmodel import now, TimestampedModel |
133 | 32 | from maasserver.utils.orm import get_first, get_one | 33 | from maasserver.utils.orm import get_first, get_one |
134 | 33 | from provisioningserver.drivers.osystem import OperatingSystemRegistry | 34 | from provisioningserver.drivers.osystem import OperatingSystemRegistry |
135 | @@ -582,6 +583,16 @@ class BootResource(CleanSave, TimestampedModel): | |||
136 | 582 | return self.architecture.split("/") | 583 | return self.architecture.split("/") |
137 | 583 | 584 | ||
138 | 584 | def split_base_image(self): | 585 | def split_base_image(self): |
139 | 586 | # handle older custom images that may not have a base image | ||
140 | 587 | if not self.base_image: | ||
141 | 588 | cfg = Config.objects.get_configs( | ||
142 | 589 | ["commissioning_osystem", "commissioning_distro_series"] | ||
143 | 590 | ) | ||
144 | 591 | return ( | ||
145 | 592 | cfg["commissioning_osystem"], | ||
146 | 593 | cfg["commissioning_distro_series"], | ||
147 | 594 | ) | ||
148 | 595 | |||
149 | 585 | return self.base_image.split("/") | 596 | return self.base_image.split("/") |
150 | 586 | 597 | ||
151 | 587 | def get_next_version_name(self): | 598 | def get_next_version_name(self): |
152 | diff --git a/src/maasserver/models/tests/test_bootresource.py b/src/maasserver/models/tests/test_bootresource.py | |||
153 | index e4280b0..ba3dc71 100644 | |||
154 | --- a/src/maasserver/models/tests/test_bootresource.py | |||
155 | +++ b/src/maasserver/models/tests/test_bootresource.py | |||
156 | @@ -21,6 +21,7 @@ from maasserver.models.bootresource import ( | |||
157 | 21 | BootResource, | 21 | BootResource, |
158 | 22 | RTYPE_REQUIRING_OS_SERIES_NAME, | 22 | RTYPE_REQUIRING_OS_SERIES_NAME, |
159 | 23 | ) | 23 | ) |
160 | 24 | from maasserver.models.config import Config | ||
161 | 24 | from maasserver.models.signals import bootsources | 25 | from maasserver.models.signals import bootsources |
162 | 25 | from maasserver.testing.factory import factory | 26 | from maasserver.testing.factory import factory |
163 | 26 | from maasserver.testing.testcase import MAASServerTestCase | 27 | from maasserver.testing.testcase import MAASServerTestCase |
164 | @@ -1155,3 +1156,14 @@ class TestBootResource(MAASServerTestCase): | |||
165 | 1155 | self.assertFalse( | 1156 | self.assertFalse( |
166 | 1156 | resource.supports_subarch(factory.make_name("subarch")) | 1157 | resource.supports_subarch(factory.make_name("subarch")) |
167 | 1157 | ) | 1158 | ) |
168 | 1159 | |||
169 | 1160 | def test_split_base_image_handles_no_base_image(self): | ||
170 | 1161 | resource = factory.make_BootResource() | ||
171 | 1162 | resource.base_image = None | ||
172 | 1163 | cfg = Config.objects.get_configs( | ||
173 | 1164 | ["commissioning_osystem", "commissioning_distro_series"] | ||
174 | 1165 | ) | ||
175 | 1166 | self.assertCountEqual( | ||
176 | 1167 | (cfg["commissioning_osystem"], cfg["commissioning_distro_series"]), | ||
177 | 1168 | resource.split_base_image(), | ||
178 | 1169 | ) | ||
179 | diff --git a/src/maasserver/rpc/boot.py b/src/maasserver/rpc/boot.py | |||
180 | index 12f14b4..22f4102 100644 | |||
181 | --- a/src/maasserver/rpc/boot.py | |||
182 | +++ b/src/maasserver/rpc/boot.py | |||
183 | @@ -231,10 +231,7 @@ def get_boot_config_for_machine(machine, configs, purpose): | |||
184 | 231 | install_image = None | 231 | install_image = None |
185 | 232 | if osystem == "custom": | 232 | if osystem == "custom": |
186 | 233 | install_image = BootResource.objects.get(name=series) | 233 | install_image = BootResource.objects.get(name=series) |
191 | 234 | if install_image.base_image is not None: | 234 | osystem, series = install_image.split_base_image() |
188 | 235 | # if the operating system is a custom ubuntu image, | ||
189 | 236 | # use the base image to install | ||
190 | 237 | osystem, series = install_image.base_image.split("/") | ||
192 | 238 | 235 | ||
193 | 239 | if install_image is None or osystem != "ubuntu": | 236 | if install_image is None or osystem != "ubuntu": |
194 | 240 | # Use only the commissioning osystem and series, for operating | 237 | # Use only the commissioning osystem and series, for operating |
195 | diff --git a/src/maasserver/rpc/tests/test_boot.py b/src/maasserver/rpc/tests/test_boot.py | |||
196 | index 517dc8e..a0cae0d 100644 | |||
197 | --- a/src/maasserver/rpc/tests/test_boot.py | |||
198 | +++ b/src/maasserver/rpc/tests/test_boot.py | |||
199 | @@ -24,7 +24,11 @@ from maasserver.models.timestampedmodel import now | |||
200 | 24 | from maasserver.node_status import get_node_timeout, MONITORED_STATUSES | 24 | from maasserver.node_status import get_node_timeout, MONITORED_STATUSES |
201 | 25 | from maasserver.preseed import compose_enlistment_preseed_url | 25 | from maasserver.preseed import compose_enlistment_preseed_url |
202 | 26 | from maasserver.rpc import boot as boot_module | 26 | from maasserver.rpc import boot as boot_module |
204 | 27 | from maasserver.rpc.boot import event_log_pxe_request, get_boot_filenames | 27 | from maasserver.rpc.boot import ( |
205 | 28 | event_log_pxe_request, | ||
206 | 29 | get_boot_config_for_machine, | ||
207 | 30 | get_boot_filenames, | ||
208 | 31 | ) | ||
209 | 28 | from maasserver.rpc.boot import get_config as orig_get_config | 32 | from maasserver.rpc.boot import get_config as orig_get_config |
210 | 29 | from maasserver.rpc.boot import merge_kparams_with_extra | 33 | from maasserver.rpc.boot import merge_kparams_with_extra |
211 | 30 | from maasserver.testing.architecture import make_usable_architecture | 34 | from maasserver.testing.architecture import make_usable_architecture |
212 | @@ -1520,3 +1524,104 @@ class TestGetBootFilenames(MAASServerTestCase): | |||
213 | 1520 | initrd, | 1524 | initrd, |
214 | 1521 | ) | 1525 | ) |
215 | 1522 | self.assertIsNone(boot_dbt) | 1526 | self.assertIsNone(boot_dbt) |
216 | 1527 | |||
217 | 1528 | |||
218 | 1529 | class TestGetBootConfigForMachine(MAASServerTestCase): | ||
219 | 1530 | def test_get_boot_config_for_machine_builtin_image(self): | ||
220 | 1531 | machine = factory.make_Machine( | ||
221 | 1532 | status=NODE_STATUS.DEPLOYING, | ||
222 | 1533 | osystem="ubuntu", | ||
223 | 1534 | distro_series="focal", | ||
224 | 1535 | ) | ||
225 | 1536 | configs = Config.objects.get_configs( | ||
226 | 1537 | [ | ||
227 | 1538 | "commissioning_osystem", | ||
228 | 1539 | "commissioning_distro_series", | ||
229 | 1540 | "enable_third_party_drivers", | ||
230 | 1541 | "default_min_hwe_kernel", | ||
231 | 1542 | "default_osystem", | ||
232 | 1543 | "default_distro_series", | ||
233 | 1544 | "kernel_opts", | ||
234 | 1545 | "use_rack_proxy", | ||
235 | 1546 | "maas_internal_domain", | ||
236 | 1547 | "remote_syslog", | ||
237 | 1548 | "maas_syslog_port", | ||
238 | 1549 | ] | ||
239 | 1550 | ) | ||
240 | 1551 | |||
241 | 1552 | osystem, series, config_arch = get_boot_config_for_machine( | ||
242 | 1553 | machine, configs, "xinstall" | ||
243 | 1554 | ) | ||
244 | 1555 | |||
245 | 1556 | self.assertEqual(osystem, "ubuntu") | ||
246 | 1557 | self.assertEqual(series, "focal") | ||
247 | 1558 | self.assertEqual(config_arch, "generic") | ||
248 | 1559 | |||
249 | 1560 | def test_get_boot_config_for_machine_new_custom_image(self): | ||
250 | 1561 | arch = make_usable_architecture(self) | ||
251 | 1562 | boot_resource = factory.make_BootResource( | ||
252 | 1563 | base_image="ubuntu/jammy", architecture=arch | ||
253 | 1564 | ) | ||
254 | 1565 | machine = factory.make_Machine( | ||
255 | 1566 | status=NODE_STATUS.DEPLOYING, | ||
256 | 1567 | osystem="custom", | ||
257 | 1568 | distro_series=boot_resource.name, | ||
258 | 1569 | ) | ||
259 | 1570 | configs = Config.objects.get_configs( | ||
260 | 1571 | [ | ||
261 | 1572 | "commissioning_osystem", | ||
262 | 1573 | "commissioning_distro_series", | ||
263 | 1574 | "enable_third_party_drivers", | ||
264 | 1575 | "default_min_hwe_kernel", | ||
265 | 1576 | "default_osystem", | ||
266 | 1577 | "default_distro_series", | ||
267 | 1578 | "kernel_opts", | ||
268 | 1579 | "use_rack_proxy", | ||
269 | 1580 | "maas_internal_domain", | ||
270 | 1581 | "remote_syslog", | ||
271 | 1582 | "maas_syslog_port", | ||
272 | 1583 | ] | ||
273 | 1584 | ) | ||
274 | 1585 | |||
275 | 1586 | osystem, series, config_arch = get_boot_config_for_machine( | ||
276 | 1587 | machine, configs, "xinstall" | ||
277 | 1588 | ) | ||
278 | 1589 | |||
279 | 1590 | self.assertEqual(osystem, "ubuntu") | ||
280 | 1591 | self.assertEqual(series, "jammy") | ||
281 | 1592 | self.assertEqual(config_arch, "generic") | ||
282 | 1593 | |||
283 | 1594 | def test_get_boot_config_for_machine_legacy_custom_image(self): | ||
284 | 1595 | arch = make_usable_architecture(self) | ||
285 | 1596 | boot_resource = factory.make_BootResource( | ||
286 | 1597 | base_image="", architecture=arch | ||
287 | 1598 | ) | ||
288 | 1599 | machine = factory.make_Machine( | ||
289 | 1600 | status=NODE_STATUS.DEPLOYING, | ||
290 | 1601 | osystem="custom", | ||
291 | 1602 | distro_series=boot_resource.name, | ||
292 | 1603 | ) | ||
293 | 1604 | configs = Config.objects.get_configs( | ||
294 | 1605 | [ | ||
295 | 1606 | "commissioning_osystem", | ||
296 | 1607 | "commissioning_distro_series", | ||
297 | 1608 | "enable_third_party_drivers", | ||
298 | 1609 | "default_min_hwe_kernel", | ||
299 | 1610 | "default_osystem", | ||
300 | 1611 | "default_distro_series", | ||
301 | 1612 | "kernel_opts", | ||
302 | 1613 | "use_rack_proxy", | ||
303 | 1614 | "maas_internal_domain", | ||
304 | 1615 | "remote_syslog", | ||
305 | 1616 | "maas_syslog_port", | ||
306 | 1617 | ] | ||
307 | 1618 | ) | ||
308 | 1619 | |||
309 | 1620 | osystem, series, config_arch = get_boot_config_for_machine( | ||
310 | 1621 | machine, configs, "xinstall" | ||
311 | 1622 | ) | ||
312 | 1623 | |||
313 | 1624 | # legacy custom images should use the default commissioning image as a base image | ||
314 | 1625 | self.assertEqual(osystem, configs["commissioning_osystem"]) | ||
315 | 1626 | self.assertEqual(series, configs["commissioning_distro_series"]) | ||
316 | 1627 | self.assertEqual(config_arch, "generic") |
UNIT TESTS 3.1_backport lp:~cgrabowski/maas/+git/maas into -b 3.1 lp:~maas-committers/maas
-b fix_lp1982866_
STATUS: FAILED maas-ci. internal: 8080/job/ maas-tester/ 753/consoleText 854ba22bca64e59 c2739031f6
LOG: http://
COMMIT: 446f3819632f3ea