Add identity-credentials relation support
Implement support for the identity-credentials relation as an alternative way to get keystone credentials when we are not registering a service endpoint via the identity-service relation. This solves an issue where the image volume cache does not work when the cinder volume service is deployed as a second cinder application ('cinder-volume') having enabled-services=volume set. Previously the following items were missing from cinder.conf: cinder_internal_tenant_project_id cinder_internal_tenant_user_id Resulting in the image cache not functioning with the following warnings: Unable to get internal tenant context: Missing required config parameters. Unable to get Cinder internal context, will not use image-volume cache. As there are now two possible interfaces to keystone ('identity-service' and 'identity-credentials') any existing bundles that don't specify the interface 'identity-service' when relating to keystone will fail to deploy and will need to be updated. Closes-Bug: #1978452 Change-Id: Ieef500c9c55eb3968b3e2e231a8ff6e2a5ec148d
This commit is contained in:
parent
dd8a9aae8a
commit
ba8d8fc3e1
26
README.md
26
README.md
@ -66,6 +66,32 @@ Cinder can be backed by a Pure Storage appliance reachable by its API endpoint.
|
||||
This functionality is provided by the
|
||||
[cinder-purestorage][cinder-purestorage-charm] subordinate charm.
|
||||
|
||||
## Separate Volume Service
|
||||
|
||||
For certain operations when an instance is not involved, the cinder application
|
||||
will connect directly to the storage for operations such as cloning a volume
|
||||
from a glance image. You can deploy a second cinder application for the volume
|
||||
service only where the primary cinder application cannot connect to this
|
||||
storage. This may be required for iSCSI connections because LXD containers
|
||||
cannot create iSCSI connections or where you need a physical Fibre Channel
|
||||
connection. This is not required for Ceph deployments which use userspace RBD
|
||||
tools.
|
||||
|
||||
1. Deploy cinder with enabled-services=api,scheduler
|
||||
2. Deploy a second application of cinder named 'cinder-volume' with
|
||||
enabled-services=volume
|
||||
3. Relate the storage subordinate (e.g. cinder-purestorage) to the
|
||||
cinder-volume application only (not to the 'cinder' application)
|
||||
4. Keystone should be related to cinder:identity-__service__ but
|
||||
cinder-volume:identity-__credentials__
|
||||
|
||||
The primary cinder application gets keystone credentials when registering a
|
||||
service endpoint via the identity-service relation. The cinder-volume
|
||||
application does not register a service, so we need to relate
|
||||
identity-credentials instead. The image volume cache will not work without
|
||||
this relation.
|
||||
5. Both cinder and cinder-volume should otherwise have the same relations
|
||||
|
||||
## High availability
|
||||
|
||||
This charm supports high availability via HAcluster.
|
||||
|
@ -469,6 +469,21 @@ def identity_changed():
|
||||
configure_https()
|
||||
|
||||
|
||||
@hooks.hook('identity-credentials-relation-joined')
|
||||
def identity_credentials_joined(rid=None):
|
||||
if service_enabled('volume') and not service_enabled('api'):
|
||||
settings = {'username': 'cinder', 'requested_roles': 'Admin'}
|
||||
relation_set(relation_id=rid, **settings)
|
||||
|
||||
|
||||
@hooks.hook('identity-credentials-relation-changed')
|
||||
@restart_on_change(restart_map())
|
||||
def identity_credentials_changed():
|
||||
if service_enabled('volume') and not service_enabled('api'):
|
||||
if 'identity-credentials' in CONFIGS.complete_contexts():
|
||||
CONFIGS.write(CINDER_CONF)
|
||||
|
||||
|
||||
@hooks.hook('ceph-relation-joined')
|
||||
def ceph_joined():
|
||||
if not os.path.isdir('/etc/ceph'):
|
||||
@ -586,6 +601,7 @@ def image_service_changed():
|
||||
|
||||
@hooks.hook('amqp-relation-broken',
|
||||
'identity-service-relation-broken',
|
||||
'identity-credentials-relation-broken',
|
||||
'image-service-relation-broken',
|
||||
'shared-db-relation-broken')
|
||||
@restart_on_change(restart_map(), stopstart=True)
|
||||
|
@ -224,6 +224,9 @@ BASE_RESOURCE_MAP = OrderedDict([
|
||||
config_file=CINDER_CONF),
|
||||
cinder_contexts.StorageBackendContext(),
|
||||
cinder_contexts.LoggingConfigContext(),
|
||||
context.IdentityCredentialsContext(
|
||||
service='cinder',
|
||||
service_user='cinder'),
|
||||
context.IdentityServiceContext(
|
||||
service='cinder',
|
||||
service_user='cinder'),
|
||||
@ -931,6 +934,9 @@ def get_optional_interfaces():
|
||||
if relation_ids('image-service'):
|
||||
optional_interfaces['image'] = ['image-service']
|
||||
|
||||
if service_enabled('volume') and not service_enabled('api'):
|
||||
optional_interfaces['identity-credentials'] = ['identity-credentials']
|
||||
|
||||
return optional_interfaces
|
||||
|
||||
|
||||
|
1
hooks/identity-credentials-relation-broken
Symbolic link
1
hooks/identity-credentials-relation-broken
Symbolic link
@ -0,0 +1 @@
|
||||
cinder_hooks.py
|
1
hooks/identity-credentials-relation-changed
Symbolic link
1
hooks/identity-credentials-relation-changed
Symbolic link
@ -0,0 +1 @@
|
||||
cinder_hooks.py
|
1
hooks/identity-credentials-relation-joined
Symbolic link
1
hooks/identity-credentials-relation-joined
Symbolic link
@ -0,0 +1 @@
|
||||
cinder_hooks.py
|
@ -27,6 +27,9 @@ requires:
|
||||
interface: rabbitmq
|
||||
identity-service:
|
||||
interface: keystone
|
||||
optional: true
|
||||
identity-credentials:
|
||||
interface: keystone-credentials
|
||||
ceph:
|
||||
interface: ceph-client
|
||||
image-service:
|
||||
|
@ -127,6 +127,14 @@ class TestChangedHooks(CharmTestCase):
|
||||
'identity-service': ['identity-service:1'],
|
||||
}
|
||||
|
||||
def svc_enabled(self, svc):
|
||||
enabled = self.test_config.get('enabled-services')
|
||||
|
||||
if enabled == 'all':
|
||||
return True
|
||||
|
||||
return svc in enabled
|
||||
|
||||
def setUp(self):
|
||||
super(TestChangedHooks, self).setUp(hooks, TO_PATCH)
|
||||
self.config.side_effect = self.test_config.get
|
||||
@ -329,6 +337,42 @@ class TestChangedHooks(CharmTestCase):
|
||||
hooks.hooks.execute(['hooks/identity-service-relation-changed'])
|
||||
self.assertFalse(self.CONFIGS.write.called)
|
||||
|
||||
@patch.object(hooks, 'service_enabled')
|
||||
def test_identity_credentials_joined_without_api(self, service_enabled):
|
||||
'It requests keystone credentials without API service'
|
||||
self.test_config.set('enabled-services', 'volume')
|
||||
service_enabled.side_effect = self.svc_enabled
|
||||
hooks.hooks.execute(['hooks/identity-credentials-relation-joined'])
|
||||
expected = {'relation_id': None,
|
||||
'username': 'cinder',
|
||||
'requested_roles': 'Admin'}
|
||||
self.relation_set.assert_called_with(**expected)
|
||||
|
||||
@patch.object(hooks, 'service_enabled')
|
||||
def test_identity_credentials_joined_with_api(self, service_enabled):
|
||||
'It requests keystone credentials with API service'
|
||||
self.test_config.set('enabled-services', 'all')
|
||||
service_enabled.side_effect = self.svc_enabled
|
||||
hooks.hooks.execute(['hooks/identity-credentials-relation-joined'])
|
||||
self.relation_set.assert_not_called()
|
||||
|
||||
@patch.object(hooks, 'service_enabled')
|
||||
def test_identity_credentials_changed(self, service_enabled):
|
||||
'It writes out cinder.conf on identity-credentials changed'
|
||||
self.CONFIGS.complete_contexts.return_value = ['identity-credentials']
|
||||
self.test_config.set('enabled-services', 'volume')
|
||||
service_enabled.side_effect = self.svc_enabled
|
||||
hooks.hooks.execute(['hooks/identity-credentials-relation-changed'])
|
||||
self.CONFIGS.write.assert_called_with('/etc/cinder/cinder.conf')
|
||||
|
||||
@patch.object(hooks, 'service_enabled')
|
||||
def test_identity_credentials_changed_incomplete(self, service_enabled):
|
||||
'It does not write cinder.conf with incomplete identity-service'
|
||||
self.test_config.set('enabled-services', 'volume')
|
||||
service_enabled.side_effect = self.svc_enabled
|
||||
hooks.hooks.execute(['hooks/identity-credentials-relation-changed'])
|
||||
self.assertFalse(self.CONFIGS.write.called)
|
||||
|
||||
@patch.object(hooks, 'identity_joined')
|
||||
def test_configure_https_enable(self, identity_joined):
|
||||
'It enables https from hooks when we have https data'
|
||||
|
Loading…
Reference in New Issue
Block a user