Merge ~alexsander-souza/maas:lp1966474_ignore_unused_creds into maas:master

Proposed by Alexsander de Souza
Status: Merged
Approved by: Alexsander de Souza
Approved revision: e804ab39588d1c1a76477ab2c6747cb7ade62e0f
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~alexsander-souza/maas:lp1966474_ignore_unused_creds
Merge into: maas:master
Diff against target: 289 lines (+149/-8)
7 files modified
src/maasserver/models/node.py (+5/-0)
src/maasserver/models/nodemetadata.py (+18/-0)
src/maasserver/models/tests/test_nodemetadata.py (+21/-0)
src/metadataserver/api_twisted.py (+7/-4)
src/metadataserver/tests/test_api_twisted.py (+66/-0)
src/metadataserver/tests/test_vendor_data.py (+26/-0)
src/metadataserver/vendor_data.py (+6/-4)
Reviewer Review Type Date Requested Status
Alberto Donato (community) Approve
MAAS Lander Approve
Review via email: mp+418116@code.launchpad.net

Commit message

Ignore unused creds when deploying a KVM host

fixes LP#1966474

To post a comment you must log in.
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b lp1966474_ignore_unused_creds lp:~alexsander-souza/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 72818047ae4f821cadd7588af6c07b02e74b7290

review: Approve
Revision history for this message
Alberto Donato (ack) wrote :

The change itself looks good as a fallback, but _create_vmhost_for_deployment() (from metadataserver.api_twisted) is supposed to delete credentials when registering the VM hosts.

It'd be good to understand why this is not happening, which is the real cause of the bug.

review: Needs Information
Revision history for this message
Alberto Donato (ack) wrote :

Actually, I guess the reason is that if the deployment doesn't complete, the secrets are leftover.

I think the right fix would be to
 - delete all secrets when a machine is released
 - delete all secrets (before creating new ones) when the machine is deployed

7b95791... by Alexsander de Souza

delete credentials on node release

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

UNIT TESTS
-b lp1966474_ignore_unused_creds lp:~alexsander-souza/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 65d4d4cb9799d200e12ddc0aa74169582242d781

review: Approve
467fb58... by Alexsander de Souza

remove leftover credentials

Revision history for this message
Alexsander de Souza (alexsander-souza) wrote :

Updated with the suggested fixes

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

UNIT TESTS
-b lp1966474_ignore_unused_creds lp:~alexsander-souza/maas/+git/maas into -b master lp:~maas-committers/maas

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

review: Needs Fixing
3ece4a7... by Alexsander de Souza

lint

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

UNIT TESTS
-b lp1966474_ignore_unused_creds lp:~alexsander-souza/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: fead4ad066dddfe92944c1a3c5e8364b47d67fe4

review: Approve
Revision history for this message
Alberto Donato (ack) wrote :

A few additional comments

54b55de... by Alexsander de Souza

fixes

93037f9... by Alexsander de Souza

revert unrequired change

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

UNIT TESTS
-b lp1966474_ignore_unused_creds lp:~alexsander-souza/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas/job/branch-tester/12322/console
COMMIT: 04f963359a11170841d3d97f05e625ec936ab3c8

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

UNIT TESTS
-b lp1966474_ignore_unused_creds lp:~alexsander-souza/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas/job/branch-tester/12323/console
COMMIT: 93037f922ef22e2745a372ba48a611db3a4defad

review: Needs Fixing
e804ab3... by Alexsander de Souza

fix test

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

UNIT TESTS
-b lp1966474_ignore_unused_creds lp:~alexsander-souza/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: e804ab39588d1c1a76477ab2c6747cb7ade62e0f

review: Approve
Revision history for this message
Alberto Donato (ack) wrote :

Thanks for the changes, looks good! +1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/models/node.py b/src/maasserver/models/node.py
2index 5740b70..cdcedfa 100644
3--- a/src/maasserver/models/node.py
4+++ b/src/maasserver/models/node.py
5@@ -3718,6 +3718,11 @@ class Node(CleanSave, TimestampedModel):
6 # If this node has non-installable children, remove them.
7 self.children.all().delete()
8
9+ # Release volatile metadata
10+ from maasserver.models import NodeMetadata
11+
12+ NodeMetadata.objects.release_volatile(self)
13+
14 # Power was off or cannot be powered off so release to ready now.
15 if finalize_release:
16 self._finalize_release()
17diff --git a/src/maasserver/models/nodemetadata.py b/src/maasserver/models/nodemetadata.py
18index 0daa3d0..8ad361b 100644
19--- a/src/maasserver/models/nodemetadata.py
20+++ b/src/maasserver/models/nodemetadata.py
21@@ -22,6 +22,24 @@ class NodeMetadataManager(Manager):
22 except NodeMetadata.DoesNotExist:
23 return default
24
25+ def release_volatile(cls, node):
26+ """Remove volatile information.
27+
28+ Should be called when releasing the node to remove all data that
29+ is related to this deployment.
30+ """
31+ from metadataserver import vendor_data
32+
33+ volatile_meta = (
34+ vendor_data.LXD_CERTIFICATE_METADATA_KEY,
35+ vendor_data.VIRSH_PASSWORD_METADATA_KEY,
36+ )
37+
38+ NodeMetadata.objects.filter(
39+ node=node,
40+ key__in=volatile_meta,
41+ ).delete()
42+
43
44 class NodeMetadata(CleanSave, TimestampedModel):
45 """A `NodeMetadata` represents a key/value storage for Node metadata.
46diff --git a/src/maasserver/models/tests/test_nodemetadata.py b/src/maasserver/models/tests/test_nodemetadata.py
47index 9a19956..6e979d9 100644
48--- a/src/maasserver/models/tests/test_nodemetadata.py
49+++ b/src/maasserver/models/tests/test_nodemetadata.py
50@@ -9,6 +9,7 @@ from django.core.exceptions import ValidationError
51 from maasserver.models import NodeMetadata
52 from maasserver.testing.factory import factory
53 from maasserver.testing.testcase import MAASServerTestCase
54+from maasserver.utils.orm import reload_object
55 from maastesting.crochet import wait_for
56
57 wait_for_reactor = wait_for()
58@@ -50,3 +51,23 @@ class TestNodeMetadata(MAASServerTestCase):
59 default,
60 NodeMetadata.objects.get(node=node, key=key, default=default),
61 )
62+
63+ def test_release_volatile(self):
64+ from metadataserver.vendor_data import (
65+ LXD_CERTIFICATE_METADATA_KEY,
66+ VIRSH_PASSWORD_METADATA_KEY,
67+ )
68+
69+ node = factory.make_Node()
70+ dummy = factory.make_NodeMetadata(node=node)
71+ cred_virsh = factory.make_NodeMetadata(
72+ key=VIRSH_PASSWORD_METADATA_KEY, node=node
73+ )
74+ cred_lxd = factory.make_NodeMetadata(
75+ key=LXD_CERTIFICATE_METADATA_KEY, node=node
76+ )
77+
78+ NodeMetadata.objects.release_volatile(node)
79+ self.assertIsNotNone(reload_object(dummy))
80+ self.assertIsNone(reload_object(cred_virsh))
81+ self.assertIsNone(reload_object(cred_lxd))
82diff --git a/src/metadataserver/api_twisted.py b/src/metadataserver/api_twisted.py
83index 6460184..77cac8c 100644
84--- a/src/metadataserver/api_twisted.py
85+++ b/src/metadataserver/api_twisted.py
86@@ -184,13 +184,16 @@ POD_CREATION_ERROR = (
87
88
89 def _create_vmhost_for_deployment(node):
90+ cred_types = set()
91+ if node.register_vmhost:
92+ cred_types.add(LXD_CERTIFICATE_METADATA_KEY)
93+ if node.install_kvm:
94+ cred_types.add(VIRSH_PASSWORD_METADATA_KEY)
95+
96 creds_meta = list(
97 NodeMetadata.objects.filter(
98 node=node,
99- key__in=(
100- LXD_CERTIFICATE_METADATA_KEY,
101- VIRSH_PASSWORD_METADATA_KEY,
102- ),
103+ key__in=cred_types,
104 )
105 )
106 if not creds_meta:
107diff --git a/src/metadataserver/tests/test_api_twisted.py b/src/metadataserver/tests/test_api_twisted.py
108index a58e200..20332fd 100644
109--- a/src/metadataserver/tests/test_api_twisted.py
110+++ b/src/metadataserver/tests/test_api_twisted.py
111@@ -1263,3 +1263,69 @@ class TestCreateVMHostForDeployment(MAASServerTestCase):
112 node=node, key="virsh_password", value="xyz123"
113 )
114 self.assertRaises(DatabaseError, _create_vmhost_for_deployment, node)
115+
116+ def test_ignore_unused_lxd_creds(self):
117+ user = factory.make_User()
118+ node = factory.make_Node_with_Interface_on_Subnet(
119+ owner=user,
120+ status=NODE_STATUS.DEPLOYING,
121+ agent_name="maas-kvm-pod",
122+ install_kvm=True,
123+ )
124+ ip = factory.make_StaticIPAddress(interface=node.boot_interface)
125+ virsh_password_meta = NodeMetadata.objects.create(
126+ node=node, key="virsh_password", value="xyz123"
127+ )
128+ cert = generate_certificate("maas")
129+ lxd_cert_meta = NodeMetadata.objects.create(
130+ node=node,
131+ key="lxd_certificate",
132+ value=cert.certificate_pem() + cert.private_key_pem(),
133+ )
134+ addr = ip.ip
135+ if IPAddress(addr).version == 6:
136+ addr = f"[{addr}]"
137+ _create_vmhost_for_deployment(node)
138+ virsh_vmhost = Pod.objects.get(power_type="virsh")
139+ self.assertEqual(node.status, NODE_STATUS.DEPLOYED)
140+ self.mock_discover_and_sync.assert_has_calls(
141+ [
142+ call(virsh_vmhost, user),
143+ ],
144+ any_order=True,
145+ )
146+ self.assertIsNone(reload_object(virsh_password_meta))
147+ self.assertIsNotNone(reload_object(lxd_cert_meta))
148+
149+ def test_ignore_unused_virsh_creds(self):
150+ user = factory.make_User()
151+ node = factory.make_Node_with_Interface_on_Subnet(
152+ owner=user,
153+ status=NODE_STATUS.DEPLOYING,
154+ agent_name="maas-kvm-pod",
155+ register_vmhost=True,
156+ )
157+ ip = factory.make_StaticIPAddress(interface=node.boot_interface)
158+ virsh_password_meta = NodeMetadata.objects.create(
159+ node=node, key="virsh_password", value="xyz123"
160+ )
161+ cert = generate_certificate("maas")
162+ lxd_cert_meta = NodeMetadata.objects.create(
163+ node=node,
164+ key="lxd_certificate",
165+ value=cert.certificate_pem() + cert.private_key_pem(),
166+ )
167+ addr = ip.ip
168+ if IPAddress(addr).version == 6:
169+ addr = f"[{addr}]"
170+ _create_vmhost_for_deployment(node)
171+ lxd_vmhost = Pod.objects.get(power_type="lxd")
172+ self.assertEqual(node.status, NODE_STATUS.DEPLOYED)
173+ self.mock_discover_and_sync.assert_has_calls(
174+ [
175+ call(lxd_vmhost, user),
176+ ],
177+ any_order=True,
178+ )
179+ self.assertIsNotNone(reload_object(virsh_password_meta))
180+ self.assertIsNone(reload_object(lxd_cert_meta))
181diff --git a/src/metadataserver/tests/test_vendor_data.py b/src/metadataserver/tests/test_vendor_data.py
182index 6f625a2..a2044a7 100644
183--- a/src/metadataserver/tests/test_vendor_data.py
184+++ b/src/metadataserver/tests/test_vendor_data.py
185@@ -26,6 +26,7 @@ from maasserver.testing.factory import factory
186 from maasserver.testing.fixtures import RBACEnabled
187 from maasserver.testing.testcase import MAASServerTestCase
188 from maasserver.utils.converters import systemd_interval_to_calendar
189+from maasserver.utils.orm import reload_object
190 from maastesting.matchers import MockNotCalled
191 from metadataserver import vendor_data
192 from metadataserver.vendor_data import (
193@@ -45,6 +46,8 @@ from metadataserver.vendor_data import (
194 HARDWARE_SYNC_MACHINE_TOKEN_PATH,
195 HARDWARE_SYNC_SERVICE_TEMPLATE,
196 HARDWARE_SYNC_TIMER_TEMPLATE,
197+ LXD_CERTIFICATE_METADATA_KEY,
198+ VIRSH_PASSWORD_METADATA_KEY,
199 )
200 from provisioningserver.drivers.pod.lxd import LXD_MAAS_PROJECT_CONFIG
201
202@@ -335,6 +338,17 @@ class TestGenerateKVMPodConfiguration(MAASServerTestCase):
203 netboot=False,
204 install_kvm=True,
205 )
206+ factory.make_NodeMetadata(
207+ key=VIRSH_PASSWORD_METADATA_KEY,
208+ node=node,
209+ value="old value",
210+ )
211+ cred_lxd = factory.make_NodeMetadata(
212+ key=LXD_CERTIFICATE_METADATA_KEY,
213+ node=node,
214+ value="old value",
215+ )
216+
217 config = list(generate_kvm_pod_configuration(node))
218 self.assertEqual(
219 config,
220@@ -389,6 +403,7 @@ class TestGenerateKVMPodConfiguration(MAASServerTestCase):
221 password_meta = NodeMetadata.objects.first()
222 self.assertEqual(password_meta.key, "virsh_password")
223 self.assertEqual(password_meta.value, password)
224+ self.assertIsNone(reload_object(cred_lxd))
225
226 def test_yields_configuration_when_machine_register_vmhost_true(self):
227 cert = vendor_data.generate_certificate("maas")
228@@ -399,6 +414,16 @@ class TestGenerateKVMPodConfiguration(MAASServerTestCase):
229 netboot=False,
230 register_vmhost=True,
231 )
232+ cred_virsh = factory.make_NodeMetadata(
233+ key=VIRSH_PASSWORD_METADATA_KEY,
234+ node=node,
235+ value="old value",
236+ )
237+ factory.make_NodeMetadata(
238+ key=LXD_CERTIFICATE_METADATA_KEY,
239+ node=node,
240+ value="old value",
241+ )
242 config = list(generate_kvm_pod_configuration(node))
243 self.assertEqual(
244 config,
245@@ -436,6 +461,7 @@ class TestGenerateKVMPodConfiguration(MAASServerTestCase):
246 self.assertEqual(
247 creds_meta.value, cert.certificate_pem() + cert.private_key_pem()
248 )
249+ self.assertIsNone(reload_object(cred_virsh))
250
251 def test_includes_smt_off_for_install_kvm_on_ppc64(self):
252 password = "123secure"
253diff --git a/src/metadataserver/vendor_data.py b/src/metadataserver/vendor_data.py
254index b82fd80..7ccfcb5 100644
255--- a/src/metadataserver/vendor_data.py
256+++ b/src/metadataserver/vendor_data.py
257@@ -189,15 +189,17 @@ def generate_kvm_pod_configuration(node):
258 if node.netboot or not (node.install_kvm or node.register_vmhost):
259 return
260
261+ NodeMetadata.objects.release_volatile(node)
262+
263 arch, _ = node.split_arch()
264
265 if node.register_vmhost:
266 cert = generate_certificate(Config.objects.get_config("maas_name"))
267 cert_pem = cert.certificate_pem() + cert.private_key_pem()
268- NodeMetadata.objects.update_or_create(
269+ NodeMetadata.objects.create(
270 node=node,
271 key=LXD_CERTIFICATE_METADATA_KEY,
272- defaults={"value": cert_pem},
273+ value=cert_pem,
274 )
275 # write out the LXD cert on node to add it to the trust after setup
276 maas_project = "maas"
277@@ -230,10 +232,10 @@ def generate_kvm_pod_configuration(node):
278
279 if node.install_kvm:
280 password = _generate_password()
281- NodeMetadata.objects.update_or_create(
282+ NodeMetadata.objects.create(
283 node=node,
284 key=VIRSH_PASSWORD_METADATA_KEY,
285- defaults={"value": password},
286+ value=password,
287 )
288 # Make sure SSH password authentication is enabled.
289 yield "ssh_pwauth", True

Subscribers

People subscribed via source and target branches