Merge ~adam-collard/maas:relax-custom-image-validation into maas:master

Proposed by Adam Collard
Status: Merged
Approved by: Adam Collard
Approved revision: 41d9d89eaa0eab88f991f6706764d99973b91b98
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~adam-collard/maas:relax-custom-image-validation
Merge into: maas:master
Diff against target: 239 lines (+96/-57)
2 files modified
src/maasserver/preseed.py (+28/-27)
src/maasserver/tests/test_preseed.py (+68/-30)
Reviewer Review Type Date Requested Status
MAAS Lander Needs Fixing
Christian Grabowski Approve
Review via email: mp+424869@code.launchpad.net

Commit message

LP:1978154: Don't require netplan for custom CentOS images

We erroneously checked custom CentOS images for netplan, remove that.

Switch to using `rpm -q` for package installation (a more reaonable
translation of `dpkq-query -s`)

Validate RHEL based custom images too.

To post a comment you must log in.
Revision history for this message
Christian Grabowski (cgrabowski) wrote :

+1

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b relax-custom-image-validation lp:~adam-collard/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas/job/branch-tester/12969/console
COMMIT: c5eedd4ed827604b54da157a0dafc509a0561162

review: Needs Fixing
Revision history for this message
MAAS Lander (maas-lander) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/preseed.py b/src/maasserver/preseed.py
2index 994af4e..c692969 100644
3--- a/src/maasserver/preseed.py
4+++ b/src/maasserver/preseed.py
5@@ -7,8 +7,10 @@ from collections import namedtuple
6 import json
7 import os.path
8 from pipes import quote
9+import typing
10 from urllib.parse import urlencode, urlparse
11
12+import attr
13 from crochet import TimeoutError
14 from curtin.config import merge_config
15 from curtin.pack import pack_install
16@@ -603,6 +605,20 @@ def get_curtin_config(request, node, base_osystem=None, base_series=None):
17 return yaml.safe_dump(config)
18
19
20+@attr.s(auto_attribs=True)
21+class PackageManager:
22+
23+ package_tool: str
24+ deps: typing.List[str]
25+
26+
27+PACKAGE_MANAGER_PER_OS = {
28+ "ubuntu": PackageManager("dpkg-query -s", ["cloud-init", "netplan.io"]),
29+ "centos": PackageManager("rpm -q", ["cloud-init"]),
30+ "rhel": PackageManager("rpm -q", ["cloud-init"]),
31+}
32+
33+
34 def get_custom_image_dependency_validation(node, base_osystem):
35 if node.get_osystem() != "custom":
36 return None
37@@ -610,33 +626,18 @@ def get_custom_image_dependency_validation(node, base_osystem):
38 cmd = {}
39 err_msg = "not detected, MAAS will not be able to configure this machine properly"
40
41- deps = ["cloud-init", "netplan.io"]
42- for i, dep in enumerate(deps):
43- in_target = None
44- if base_osystem == "ubuntu":
45- in_target = 'dpkg-query -s {dep} || (echo "{dep} {err_msg}" && exit 1)'.format(
46- dep=dep, err_msg=err_msg
47- )
48- if base_osystem == "centos":
49- in_target = (
50- 'dnf list {dep} || (echo "{dep} {err_msg}" && exit 1)'.format(
51- dep=dep, err_msg=err_msg
52- )
53- )
54-
55- if in_target is not None:
56- cmd[
57- "{priority}-validate-custom-image-has-{dep}".format(
58- priority=98 + i, dep=dep
59- )
60- ] = [
61- "curtin",
62- "in-target",
63- "--",
64- "bash",
65- "-c",
66- in_target,
67- ]
68+ package_manager = PACKAGE_MANAGER_PER_OS[base_osystem]
69+
70+ for priority, dep in enumerate(package_manager.deps, start=98):
71+ in_target = f'{package_manager.package_tool} {dep} || (echo "{dep} {err_msg}" && exit 1)'
72+ cmd[f"{priority}-validate-custom-image-has-{dep}"] = [
73+ "curtin",
74+ "in-target",
75+ "--",
76+ "bash",
77+ "-c",
78+ in_target,
79+ ]
80 return cmd
81
82
83diff --git a/src/maasserver/tests/test_preseed.py b/src/maasserver/tests/test_preseed.py
84index c2572f8..95e7a91 100644
85--- a/src/maasserver/tests/test_preseed.py
86+++ b/src/maasserver/tests/test_preseed.py
87@@ -38,6 +38,7 @@ from maasserver.compose_preseed import get_archive_config, make_clean_repo_name
88 from maasserver.enum import FILESYSTEM_TYPE, NODE_STATUS, PRESEED_TYPE
89 from maasserver.exceptions import ClusterUnavailable, MissingBootImage
90 from maasserver.models import BootResource, Config, PackageRepository
91+from maasserver.models.bootresource import LINUX_OSYSTEMS
92 from maasserver.preseed import (
93 compose_curtin_archive_config,
94 compose_curtin_cloud_config,
95@@ -323,20 +324,20 @@ class TestGetPreseedTemplate(MAASServerTestCase):
96 class TestGetCustomImageDependencyValidation(MAASServerTestCase):
97 """Tests for 'get_custom_image_dependency_validation"""
98
99- def test_get_custom_image_dependency_validation_for_custom_ubuntu(self):
100+ def test_validation_for_custom_ubuntu(self):
101+ distro_series = factory.make_name("ubuntu")
102 boot_resource = factory.make_BootResource(
103- name="custom/%s" % factory.make_name("ubuntu"),
104+ name=f"custom/{distro_series}",
105 base_image="ubuntu/focal",
106 architecture="amd64/generic",
107 )
108- base_osystem, _ = boot_resource.split_base_image()
109- machine = factory.make_Machine(status=NODE_STATUS.DEPLOYED)
110- machine.osystem, machine.distro_series = boot_resource.name.split("/")
111- machine.architecture = boot_resource.architecture
112- machine.save()
113- validation = get_custom_image_dependency_validation(
114- machine, base_osystem
115+ machine = factory.make_Machine(
116+ status=NODE_STATUS.DEPLOYED,
117+ architecture=boot_resource.architecture,
118+ osystem="custom",
119+ distro_series=distro_series,
120 )
121+ validation = get_custom_image_dependency_validation(machine, "ubuntu")
122 expected = {
123 "98-validate-custom-image-has-cloud-init": [
124 "curtin",
125@@ -355,23 +356,22 @@ class TestGetCustomImageDependencyValidation(MAASServerTestCase):
126 'dpkg-query -s netplan.io || (echo "netplan.io not detected, MAAS will not be able to configure this machine properly" && exit 1)',
127 ],
128 }
129- for k in expected:
130- self.assertCountEqual(validation[k], expected[k])
131+ self.assertEqual(validation, expected)
132
133- def test_get_custom_image_dependency_validation_for_custom_centos(self):
134+ def test_validation_for_custom_centos(self):
135+ distro_series = factory.make_name("centos7")
136 boot_resource = factory.make_BootResource(
137- name="custom/%s" % factory.make_name("centos7"),
138+ name=f"custom/{distro_series}",
139 base_image="centos/centos7",
140 architecture="amd64/generic",
141 )
142- base_osystem, _ = boot_resource.split_base_image()
143- machine = factory.make_Machine(status=NODE_STATUS.DEPLOYED)
144- machine.osystem, machine.distro_series = boot_resource.name.split("/")
145- machine.architecture = boot_resource.architecture
146- machine.save()
147- validation = get_custom_image_dependency_validation(
148- machine, base_osystem
149+ machine = factory.make_Machine(
150+ status=NODE_STATUS.DEPLOYED,
151+ architecture=boot_resource.architecture,
152+ osystem="custom",
153+ distro_series=distro_series,
154 )
155+ validation = get_custom_image_dependency_validation(machine, "centos")
156 expected = {
157 "98-validate-custom-image-has-cloud-init": [
158 "curtin",
159@@ -379,32 +379,70 @@ class TestGetCustomImageDependencyValidation(MAASServerTestCase):
160 "--",
161 "bash",
162 "-c",
163- 'dnf list cloud-init || (echo "cloud-init not detected, MAAS will not be able to configure this machine properly" && exit 1)',
164+ 'rpm -q cloud-init || (echo "cloud-init not detected, MAAS will not be able to configure this machine properly" && exit 1)',
165 ],
166- "99-validate-custom-image-has-netplan.io": [
167+ }
168+ self.assertEqual(validation, expected)
169+
170+ def test_validation_for_custom_rhel(self):
171+ distro_series = factory.make_name("rhel8")
172+ boot_resource = factory.make_BootResource(
173+ name=f"custom/{distro_series}",
174+ base_image="rhel/rhel8",
175+ architecture="amd64/generic",
176+ )
177+ machine = factory.make_Machine(
178+ status=NODE_STATUS.DEPLOYED,
179+ architecture=boot_resource.architecture,
180+ osystem="custom",
181+ distro_series=distro_series,
182+ )
183+ validation = get_custom_image_dependency_validation(machine, "rhel")
184+ expected = {
185+ "98-validate-custom-image-has-cloud-init": [
186 "curtin",
187 "in-target",
188 "--",
189 "bash",
190 "-c",
191- 'dnf list netplan.io || (echo "netplan.io not detected, MAAS will not be able to configure this machine properly" && exit 1)',
192+ 'rpm -q cloud-init || (echo "cloud-init not detected, MAAS will not be able to configure this machine properly" && exit 1)',
193 ],
194 }
195- for k in expected:
196- self.assertCountEqual(validation[k], expected[k])
197+ self.assertEqual(validation, expected)
198
199- def test_get_custom_image_dependency_validation_for_non_custom(self):
200+ def test_validation_for_non_custom(self):
201 boot_resource = factory.make_BootResource(
202 name="ubuntu/focal", architecture="amd64/generic"
203 )
204- machine = factory.make_Machine(status=NODE_STATUS.DEPLOYED)
205- machine.osystem, machine.distro_series = boot_resource.name.split("/")
206- machine.architecture = boot_resource.architecture
207- machine.save()
208+ machine = factory.make_Machine(
209+ status=NODE_STATUS.DEPLOYED,
210+ architecture=boot_resource.architecture,
211+ osystem="ubuntu",
212+ distro_series="focal",
213+ )
214 self.assertIsNone(
215 get_custom_image_dependency_validation(machine, boot_resource.name)
216 )
217
218+ def test_validation_for_linuxes(self):
219+ machine = factory.make_Machine(
220+ status=NODE_STATUS.DEPLOYED,
221+ architecture="amd64/generic",
222+ osystem="custom",
223+ )
224+ for osystem in LINUX_OSYSTEMS:
225+ distro_series = factory.make_name(osystem)
226+ factory.make_BootResource(
227+ name=f"custom/{distro_series}",
228+ base_image=f"{osystem}/{osystem}",
229+ architecture="amd64/generic",
230+ )
231+ machine.distro_series = distro_series
232+ machine.save()
233+ self.assertIsNotNone(
234+ get_custom_image_dependency_validation(machine, osystem)
235+ )
236+
237
238 class TestLoadPreseedTemplate(MAASServerTestCase):
239 """Tests for `load_preseed_template`."""

Subscribers

People subscribed via source and target branches