From 1467cbb1b3883cfe7c47ac484b2da96d13fa9e13 Mon Sep 17 00:00:00 2001 From: James Page Date: Thu, 9 Mar 2017 12:51:25 +0000 Subject: [PATCH] Fix support for cinder ceph rbd in Ocata As of Ocata, the ceph key used to access a specific Cinder Ceph backend must match the name of the key used by cinder, with an appropriate secret configured for libvirt use with the cephx key used by the cinder-ceph charm. Add support for the new ceph-access relation to allow nova-compute units to communicate with multiple ceph backends using different cephx keys and user names. The side effect of this change is that nova-compute will have a key for use with its own ephemeral backend ceph access, and a key for each cinder ceph backend configured in the deployment. Change-Id: I638473fc46c99a8bfe301f9a0c844de9efd47a2a Closes-Bug: 1671422 --- hooks/ceph-access-relation-changed | 1 + hooks/nova_compute_hooks.py | 23 ++++++++++++++ hooks/nova_compute_utils.py | 1 + metadata.yaml | 2 ++ unit_tests/test_nova_compute_hooks.py | 46 +++++++++++++++++++++++++++ 5 files changed, 73 insertions(+) create mode 120000 hooks/ceph-access-relation-changed diff --git a/hooks/ceph-access-relation-changed b/hooks/ceph-access-relation-changed new file mode 120000 index 00000000..3ba0bdea --- /dev/null +++ b/hooks/ceph-access-relation-changed @@ -0,0 +1 @@ +nova_compute_hooks.py \ No newline at end of file diff --git a/hooks/nova_compute_hooks.py b/hooks/nova_compute_hooks.py index a27a568e..82530104 100755 --- a/hooks/nova_compute_hooks.py +++ b/hooks/nova_compute_hooks.py @@ -18,6 +18,7 @@ import platform import sys import uuid import yaml +import os import charmhelpers.core.unitdata as unitdata @@ -29,6 +30,7 @@ from charmhelpers.core.hookenv import ( log, ERROR, relation_ids, + remote_service_name, related_units, relation_get, relation_set, @@ -36,6 +38,9 @@ from charmhelpers.core.hookenv import ( UnregisteredHookError, status_set, ) +from charmhelpers.core.templating import ( + render +) from charmhelpers.core.host import ( service_restart, ) @@ -79,6 +84,7 @@ from nova_compute_utils import ( register_configs, NOVA_CONF, ceph_config_file, CEPH_SECRET, + CEPH_BACKEND_SECRET, enable_shell, disable_shell, configure_lxd, fix_path_ownership, @@ -527,6 +533,23 @@ def designate_changed(): CONFIGS.write(NOVA_CONF) +@hooks.hook('ceph-access-relation-changed') +def ceph_access(rid=None, unit=None): + '''Setup libvirt secret for specific ceph backend access''' + key = relation_get('key', unit, rid) + uuid = relation_get('secret-uuid', unit, rid) + if config('virt-type') in ['kvm', 'qemu', 'lxc'] and key and uuid: + secrets_filename = CEPH_BACKEND_SECRET.format( + remote_service_name(rid) + ) + render(os.path.basename(CEPH_SECRET), secrets_filename, + context={'ceph_secret_uuid': uuid, + 'service_name': remote_service_name(rid)}) + create_libvirt_secret(secret_file=secrets_filename, + secret_uuid=uuid, + key=key) + + @hooks.hook('update-status') @harden() def update_status(): diff --git a/hooks/nova_compute_utils.py b/hooks/nova_compute_utils.py index 7319b7da..fbdc334e 100644 --- a/hooks/nova_compute_utils.py +++ b/hooks/nova_compute_utils.py @@ -272,6 +272,7 @@ LIBVIRT_RESOURCE_MAP = { LIBVIRT_RESOURCE_MAP.update(BASE_RESOURCE_MAP) CEPH_SECRET = '/etc/ceph/secret.xml' +CEPH_BACKEND_SECRET = '/etc/ceph/secret-{}.xml' CEPH_RESOURCES = { CEPH_SECRET: { diff --git a/metadata.yaml b/metadata.yaml index f01232fb..b165e318 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -50,6 +50,8 @@ requires: ephemeral-backend: interface: ephemeral-backend scope: container + ceph-access: + interface: cinder-ceph-key peers: compute-peer: interface: nova diff --git a/unit_tests/test_nova_compute_hooks.py b/unit_tests/test_nova_compute_hooks.py index 3a67ffeb..8ca0a3e2 100644 --- a/unit_tests/test_nova_compute_hooks.py +++ b/unit_tests/test_nova_compute_hooks.py @@ -50,6 +50,7 @@ TO_PATCH = [ 'relation_set', 'service_name', 'related_units', + 'remote_service_name', # charmhelpers.core.host 'apt_install', 'apt_purge', @@ -97,6 +98,8 @@ TO_PATCH = [ 'uuid', # unitdata 'unitdata', + # templating + 'render', ] @@ -739,3 +742,46 @@ class NovaComputeRelationsTests(CharmTestCase): mock_kv.set.assert_called_with('restart-nonce', 'nonce') self.assertTrue(mock_kv.flush.called) + + def test_ceph_access_incomplete(self): + self.relation_get.return_value = None + self.test_config.set('virt-type', 'kvm') + hooks.ceph_access() + self.relation_get.assert_has_calls([ + call('key', None, None), + call('secret-uuid', None, None), + ]) + self.render.assert_not_called() + self.create_libvirt_secret.assert_not_called() + + def test_ceph_access_lxd(self): + self.relation_get.side_effect = ['mykey', 'uuid2'] + self.test_config.set('virt-type', 'lxd') + hooks.ceph_access() + self.relation_get.assert_has_calls([ + call('key', None, None), + call('secret-uuid', None, None), + ]) + self.render.assert_not_called() + self.create_libvirt_secret.assert_not_called() + + def test_ceph_access_complete(self): + self.relation_get.side_effect = ['mykey', 'uuid2'] + self.remote_service_name.return_value = 'cinder-ceph' + self.test_config.set('virt-type', 'kvm') + hooks.ceph_access() + self.relation_get.assert_has_calls([ + call('key', None, None), + call('secret-uuid', None, None), + ]) + self.render.assert_called_with( + 'secret.xml', + '/etc/ceph/secret-cinder-ceph.xml', + context={'ceph_secret_uuid': 'uuid2', + 'service_name': 'cinder-ceph'} + ) + self.create_libvirt_secret.assert_called_with( + secret_file='/etc/ceph/secret-cinder-ceph.xml', + secret_uuid='uuid2', + key='mykey', + )