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
(cherry picked from commit 1467cbb1b3)
This commit is contained in:
James Page 2017-03-09 12:51:25 +00:00
parent b89c86d088
commit e0c187cb7a
5 changed files with 73 additions and 0 deletions

View File

@ -0,0 +1 @@
nova_compute_hooks.py

View File

@ -18,6 +18,7 @@ import platform
import sys import sys
import uuid import uuid
import yaml import yaml
import os
import charmhelpers.core.unitdata as unitdata import charmhelpers.core.unitdata as unitdata
@ -29,6 +30,7 @@ from charmhelpers.core.hookenv import (
log, log,
ERROR, ERROR,
relation_ids, relation_ids,
remote_service_name,
related_units, related_units,
relation_get, relation_get,
relation_set, relation_set,
@ -37,6 +39,9 @@ from charmhelpers.core.hookenv import (
UnregisteredHookError, UnregisteredHookError,
status_set, status_set,
) )
from charmhelpers.core.templating import (
render
)
from charmhelpers.core.host import ( from charmhelpers.core.host import (
service_restart, service_restart,
) )
@ -80,6 +85,7 @@ from nova_compute_utils import (
register_configs, register_configs,
NOVA_CONF, NOVA_CONF,
ceph_config_file, CEPH_SECRET, ceph_config_file, CEPH_SECRET,
CEPH_BACKEND_SECRET,
enable_shell, disable_shell, enable_shell, disable_shell,
configure_lxd, configure_lxd,
fix_path_ownership, fix_path_ownership,
@ -527,6 +533,23 @@ def designate_changed():
CONFIGS.write(NOVA_CONF) 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') @hooks.hook('update-status')
@harden() @harden()
def update_status(): def update_status():

View File

@ -272,6 +272,7 @@ LIBVIRT_RESOURCE_MAP = {
LIBVIRT_RESOURCE_MAP.update(BASE_RESOURCE_MAP) LIBVIRT_RESOURCE_MAP.update(BASE_RESOURCE_MAP)
CEPH_SECRET = '/etc/ceph/secret.xml' CEPH_SECRET = '/etc/ceph/secret.xml'
CEPH_BACKEND_SECRET = '/etc/ceph/secret-{}.xml'
CEPH_RESOURCES = { CEPH_RESOURCES = {
CEPH_SECRET: { CEPH_SECRET: {

View File

@ -50,6 +50,8 @@ requires:
ephemeral-backend: ephemeral-backend:
interface: ephemeral-backend interface: ephemeral-backend
scope: container scope: container
ceph-access:
interface: cinder-ceph-key
peers: peers:
compute-peer: compute-peer:
interface: nova interface: nova

View File

@ -51,6 +51,7 @@ TO_PATCH = [
'service_name', 'service_name',
'related_units', 'related_units',
'unit_get', 'unit_get',
'remote_service_name',
# charmhelpers.core.host # charmhelpers.core.host
'apt_install', 'apt_install',
'apt_purge', 'apt_purge',
@ -96,6 +97,8 @@ TO_PATCH = [
'uuid', 'uuid',
# unitdata # unitdata
'unitdata', 'unitdata',
# templating
'render',
] ]
@ -734,3 +737,46 @@ class NovaComputeRelationsTests(CharmTestCase):
mock_kv.set.assert_called_with('restart-nonce', mock_kv.set.assert_called_with('restart-nonce',
'nonce') 'nonce')
self.assertTrue(mock_kv.flush.called) 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',
)