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
diff --git a/src/maasserver/models/node.py b/src/maasserver/models/node.py
index 5740b70..cdcedfa 100644
--- a/src/maasserver/models/node.py
+++ b/src/maasserver/models/node.py
@@ -3718,6 +3718,11 @@ class Node(CleanSave, TimestampedModel):
3718 # If this node has non-installable children, remove them.3718 # If this node has non-installable children, remove them.
3719 self.children.all().delete()3719 self.children.all().delete()
37203720
3721 # Release volatile metadata
3722 from maasserver.models import NodeMetadata
3723
3724 NodeMetadata.objects.release_volatile(self)
3725
3721 # Power was off or cannot be powered off so release to ready now.3726 # Power was off or cannot be powered off so release to ready now.
3722 if finalize_release:3727 if finalize_release:
3723 self._finalize_release()3728 self._finalize_release()
diff --git a/src/maasserver/models/nodemetadata.py b/src/maasserver/models/nodemetadata.py
index 0daa3d0..8ad361b 100644
--- a/src/maasserver/models/nodemetadata.py
+++ b/src/maasserver/models/nodemetadata.py
@@ -22,6 +22,24 @@ class NodeMetadataManager(Manager):
22 except NodeMetadata.DoesNotExist:22 except NodeMetadata.DoesNotExist:
23 return default23 return default
2424
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
2543
26class NodeMetadata(CleanSave, TimestampedModel):44class NodeMetadata(CleanSave, TimestampedModel):
27 """A `NodeMetadata` represents a key/value storage for Node metadata.45 """A `NodeMetadata` represents a key/value storage for Node metadata.
diff --git a/src/maasserver/models/tests/test_nodemetadata.py b/src/maasserver/models/tests/test_nodemetadata.py
index 9a19956..6e979d9 100644
--- a/src/maasserver/models/tests/test_nodemetadata.py
+++ b/src/maasserver/models/tests/test_nodemetadata.py
@@ -9,6 +9,7 @@ from django.core.exceptions import ValidationError
9from maasserver.models import NodeMetadata9from maasserver.models import NodeMetadata
10from maasserver.testing.factory import factory10from maasserver.testing.factory import factory
11from maasserver.testing.testcase import MAASServerTestCase11from maasserver.testing.testcase import MAASServerTestCase
12from maasserver.utils.orm import reload_object
12from maastesting.crochet import wait_for13from maastesting.crochet import wait_for
1314
14wait_for_reactor = wait_for()15wait_for_reactor = wait_for()
@@ -50,3 +51,23 @@ class TestNodeMetadata(MAASServerTestCase):
50 default,51 default,
51 NodeMetadata.objects.get(node=node, key=key, default=default),52 NodeMetadata.objects.get(node=node, key=key, default=default),
52 )53 )
54
55 def test_release_volatile(self):
56 from metadataserver.vendor_data import (
57 LXD_CERTIFICATE_METADATA_KEY,
58 VIRSH_PASSWORD_METADATA_KEY,
59 )
60
61 node = factory.make_Node()
62 dummy = factory.make_NodeMetadata(node=node)
63 cred_virsh = factory.make_NodeMetadata(
64 key=VIRSH_PASSWORD_METADATA_KEY, node=node
65 )
66 cred_lxd = factory.make_NodeMetadata(
67 key=LXD_CERTIFICATE_METADATA_KEY, node=node
68 )
69
70 NodeMetadata.objects.release_volatile(node)
71 self.assertIsNotNone(reload_object(dummy))
72 self.assertIsNone(reload_object(cred_virsh))
73 self.assertIsNone(reload_object(cred_lxd))
diff --git a/src/metadataserver/api_twisted.py b/src/metadataserver/api_twisted.py
index 6460184..77cac8c 100644
--- a/src/metadataserver/api_twisted.py
+++ b/src/metadataserver/api_twisted.py
@@ -184,13 +184,16 @@ POD_CREATION_ERROR = (
184184
185185
186def _create_vmhost_for_deployment(node):186def _create_vmhost_for_deployment(node):
187 cred_types = set()
188 if node.register_vmhost:
189 cred_types.add(LXD_CERTIFICATE_METADATA_KEY)
190 if node.install_kvm:
191 cred_types.add(VIRSH_PASSWORD_METADATA_KEY)
192
187 creds_meta = list(193 creds_meta = list(
188 NodeMetadata.objects.filter(194 NodeMetadata.objects.filter(
189 node=node,195 node=node,
190 key__in=(196 key__in=cred_types,
191 LXD_CERTIFICATE_METADATA_KEY,
192 VIRSH_PASSWORD_METADATA_KEY,
193 ),
194 )197 )
195 )198 )
196 if not creds_meta:199 if not creds_meta:
diff --git a/src/metadataserver/tests/test_api_twisted.py b/src/metadataserver/tests/test_api_twisted.py
index a58e200..20332fd 100644
--- a/src/metadataserver/tests/test_api_twisted.py
+++ b/src/metadataserver/tests/test_api_twisted.py
@@ -1263,3 +1263,69 @@ class TestCreateVMHostForDeployment(MAASServerTestCase):
1263 node=node, key="virsh_password", value="xyz123"1263 node=node, key="virsh_password", value="xyz123"
1264 )1264 )
1265 self.assertRaises(DatabaseError, _create_vmhost_for_deployment, node)1265 self.assertRaises(DatabaseError, _create_vmhost_for_deployment, node)
1266
1267 def test_ignore_unused_lxd_creds(self):
1268 user = factory.make_User()
1269 node = factory.make_Node_with_Interface_on_Subnet(
1270 owner=user,
1271 status=NODE_STATUS.DEPLOYING,
1272 agent_name="maas-kvm-pod",
1273 install_kvm=True,
1274 )
1275 ip = factory.make_StaticIPAddress(interface=node.boot_interface)
1276 virsh_password_meta = NodeMetadata.objects.create(
1277 node=node, key="virsh_password", value="xyz123"
1278 )
1279 cert = generate_certificate("maas")
1280 lxd_cert_meta = NodeMetadata.objects.create(
1281 node=node,
1282 key="lxd_certificate",
1283 value=cert.certificate_pem() + cert.private_key_pem(),
1284 )
1285 addr = ip.ip
1286 if IPAddress(addr).version == 6:
1287 addr = f"[{addr}]"
1288 _create_vmhost_for_deployment(node)
1289 virsh_vmhost = Pod.objects.get(power_type="virsh")
1290 self.assertEqual(node.status, NODE_STATUS.DEPLOYED)
1291 self.mock_discover_and_sync.assert_has_calls(
1292 [
1293 call(virsh_vmhost, user),
1294 ],
1295 any_order=True,
1296 )
1297 self.assertIsNone(reload_object(virsh_password_meta))
1298 self.assertIsNotNone(reload_object(lxd_cert_meta))
1299
1300 def test_ignore_unused_virsh_creds(self):
1301 user = factory.make_User()
1302 node = factory.make_Node_with_Interface_on_Subnet(
1303 owner=user,
1304 status=NODE_STATUS.DEPLOYING,
1305 agent_name="maas-kvm-pod",
1306 register_vmhost=True,
1307 )
1308 ip = factory.make_StaticIPAddress(interface=node.boot_interface)
1309 virsh_password_meta = NodeMetadata.objects.create(
1310 node=node, key="virsh_password", value="xyz123"
1311 )
1312 cert = generate_certificate("maas")
1313 lxd_cert_meta = NodeMetadata.objects.create(
1314 node=node,
1315 key="lxd_certificate",
1316 value=cert.certificate_pem() + cert.private_key_pem(),
1317 )
1318 addr = ip.ip
1319 if IPAddress(addr).version == 6:
1320 addr = f"[{addr}]"
1321 _create_vmhost_for_deployment(node)
1322 lxd_vmhost = Pod.objects.get(power_type="lxd")
1323 self.assertEqual(node.status, NODE_STATUS.DEPLOYED)
1324 self.mock_discover_and_sync.assert_has_calls(
1325 [
1326 call(lxd_vmhost, user),
1327 ],
1328 any_order=True,
1329 )
1330 self.assertIsNotNone(reload_object(virsh_password_meta))
1331 self.assertIsNone(reload_object(lxd_cert_meta))
diff --git a/src/metadataserver/tests/test_vendor_data.py b/src/metadataserver/tests/test_vendor_data.py
index 6f625a2..a2044a7 100644
--- a/src/metadataserver/tests/test_vendor_data.py
+++ b/src/metadataserver/tests/test_vendor_data.py
@@ -26,6 +26,7 @@ from maasserver.testing.factory import factory
26from maasserver.testing.fixtures import RBACEnabled26from maasserver.testing.fixtures import RBACEnabled
27from maasserver.testing.testcase import MAASServerTestCase27from maasserver.testing.testcase import MAASServerTestCase
28from maasserver.utils.converters import systemd_interval_to_calendar28from maasserver.utils.converters import systemd_interval_to_calendar
29from maasserver.utils.orm import reload_object
29from maastesting.matchers import MockNotCalled30from maastesting.matchers import MockNotCalled
30from metadataserver import vendor_data31from metadataserver import vendor_data
31from metadataserver.vendor_data import (32from metadataserver.vendor_data import (
@@ -45,6 +46,8 @@ from metadataserver.vendor_data import (
45 HARDWARE_SYNC_MACHINE_TOKEN_PATH,46 HARDWARE_SYNC_MACHINE_TOKEN_PATH,
46 HARDWARE_SYNC_SERVICE_TEMPLATE,47 HARDWARE_SYNC_SERVICE_TEMPLATE,
47 HARDWARE_SYNC_TIMER_TEMPLATE,48 HARDWARE_SYNC_TIMER_TEMPLATE,
49 LXD_CERTIFICATE_METADATA_KEY,
50 VIRSH_PASSWORD_METADATA_KEY,
48)51)
49from provisioningserver.drivers.pod.lxd import LXD_MAAS_PROJECT_CONFIG52from provisioningserver.drivers.pod.lxd import LXD_MAAS_PROJECT_CONFIG
5053
@@ -335,6 +338,17 @@ class TestGenerateKVMPodConfiguration(MAASServerTestCase):
335 netboot=False,338 netboot=False,
336 install_kvm=True,339 install_kvm=True,
337 )340 )
341 factory.make_NodeMetadata(
342 key=VIRSH_PASSWORD_METADATA_KEY,
343 node=node,
344 value="old value",
345 )
346 cred_lxd = factory.make_NodeMetadata(
347 key=LXD_CERTIFICATE_METADATA_KEY,
348 node=node,
349 value="old value",
350 )
351
338 config = list(generate_kvm_pod_configuration(node))352 config = list(generate_kvm_pod_configuration(node))
339 self.assertEqual(353 self.assertEqual(
340 config,354 config,
@@ -389,6 +403,7 @@ class TestGenerateKVMPodConfiguration(MAASServerTestCase):
389 password_meta = NodeMetadata.objects.first()403 password_meta = NodeMetadata.objects.first()
390 self.assertEqual(password_meta.key, "virsh_password")404 self.assertEqual(password_meta.key, "virsh_password")
391 self.assertEqual(password_meta.value, password)405 self.assertEqual(password_meta.value, password)
406 self.assertIsNone(reload_object(cred_lxd))
392407
393 def test_yields_configuration_when_machine_register_vmhost_true(self):408 def test_yields_configuration_when_machine_register_vmhost_true(self):
394 cert = vendor_data.generate_certificate("maas")409 cert = vendor_data.generate_certificate("maas")
@@ -399,6 +414,16 @@ class TestGenerateKVMPodConfiguration(MAASServerTestCase):
399 netboot=False,414 netboot=False,
400 register_vmhost=True,415 register_vmhost=True,
401 )416 )
417 cred_virsh = factory.make_NodeMetadata(
418 key=VIRSH_PASSWORD_METADATA_KEY,
419 node=node,
420 value="old value",
421 )
422 factory.make_NodeMetadata(
423 key=LXD_CERTIFICATE_METADATA_KEY,
424 node=node,
425 value="old value",
426 )
402 config = list(generate_kvm_pod_configuration(node))427 config = list(generate_kvm_pod_configuration(node))
403 self.assertEqual(428 self.assertEqual(
404 config,429 config,
@@ -436,6 +461,7 @@ class TestGenerateKVMPodConfiguration(MAASServerTestCase):
436 self.assertEqual(461 self.assertEqual(
437 creds_meta.value, cert.certificate_pem() + cert.private_key_pem()462 creds_meta.value, cert.certificate_pem() + cert.private_key_pem()
438 )463 )
464 self.assertIsNone(reload_object(cred_virsh))
439465
440 def test_includes_smt_off_for_install_kvm_on_ppc64(self):466 def test_includes_smt_off_for_install_kvm_on_ppc64(self):
441 password = "123secure"467 password = "123secure"
diff --git a/src/metadataserver/vendor_data.py b/src/metadataserver/vendor_data.py
index b82fd80..7ccfcb5 100644
--- a/src/metadataserver/vendor_data.py
+++ b/src/metadataserver/vendor_data.py
@@ -189,15 +189,17 @@ def generate_kvm_pod_configuration(node):
189 if node.netboot or not (node.install_kvm or node.register_vmhost):189 if node.netboot or not (node.install_kvm or node.register_vmhost):
190 return190 return
191191
192 NodeMetadata.objects.release_volatile(node)
193
192 arch, _ = node.split_arch()194 arch, _ = node.split_arch()
193195
194 if node.register_vmhost:196 if node.register_vmhost:
195 cert = generate_certificate(Config.objects.get_config("maas_name"))197 cert = generate_certificate(Config.objects.get_config("maas_name"))
196 cert_pem = cert.certificate_pem() + cert.private_key_pem()198 cert_pem = cert.certificate_pem() + cert.private_key_pem()
197 NodeMetadata.objects.update_or_create(199 NodeMetadata.objects.create(
198 node=node,200 node=node,
199 key=LXD_CERTIFICATE_METADATA_KEY,201 key=LXD_CERTIFICATE_METADATA_KEY,
200 defaults={"value": cert_pem},202 value=cert_pem,
201 )203 )
202 # write out the LXD cert on node to add it to the trust after setup204 # write out the LXD cert on node to add it to the trust after setup
203 maas_project = "maas"205 maas_project = "maas"
@@ -230,10 +232,10 @@ def generate_kvm_pod_configuration(node):
230232
231 if node.install_kvm:233 if node.install_kvm:
232 password = _generate_password()234 password = _generate_password()
233 NodeMetadata.objects.update_or_create(235 NodeMetadata.objects.create(
234 node=node,236 node=node,
235 key=VIRSH_PASSWORD_METADATA_KEY,237 key=VIRSH_PASSWORD_METADATA_KEY,
236 defaults={"value": password},238 value=password,
237 )239 )
238 # Make sure SSH password authentication is enabled.240 # Make sure SSH password authentication is enabled.
239 yield "ssh_pwauth", True241 yield "ssh_pwauth", True

Subscribers

People subscribed via source and target branches