[hopem,r=jamespage]
Ensure 'host' is set in cinder.conf if rbd storage backend is related AND all backends are stateless e.g. rbd. Closes-Bug: 1493931
This commit is contained in:
commit
db7f68241b
|
@ -3,12 +3,15 @@ from charmhelpers.core.hookenv import (
|
|||
relation_ids,
|
||||
service_name,
|
||||
related_units,
|
||||
relation_get
|
||||
relation_get,
|
||||
log,
|
||||
WARNING,
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.openstack.context import (
|
||||
OSContextGenerator,
|
||||
ApacheSSLContext as SSLContext,
|
||||
SubordinateConfigContext,
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.openstack.utils import (
|
||||
|
@ -110,3 +113,44 @@ class LoggingConfigContext(OSContextGenerator):
|
|||
|
||||
def __call__(self):
|
||||
return {'debug': config('debug'), 'verbose': config('verbose')}
|
||||
|
||||
|
||||
class CinderSubordinateConfigContext(SubordinateConfigContext):
|
||||
|
||||
def __call__(self):
|
||||
ctxt = super(CinderSubordinateConfigContext, self).__call__()
|
||||
|
||||
# If all backends are stateless we can allow host setting to be set
|
||||
# across hosts/units to allow for HA volume failover but otherwise we
|
||||
# have to leave it as unique (LP: #1493931).
|
||||
rids = []
|
||||
for interface in self.interfaces:
|
||||
rids.extend(relation_ids(interface))
|
||||
|
||||
stateless = None
|
||||
any_stateless = False
|
||||
for rid in rids:
|
||||
for unit in related_units(rid):
|
||||
val = relation_get('stateless', rid=rid, unit=unit) or ""
|
||||
if val.lower() == 'true':
|
||||
if stateless is None:
|
||||
stateless = True
|
||||
else:
|
||||
stateless = stateless and True
|
||||
else:
|
||||
stateless = False
|
||||
|
||||
any_stateless = any_stateless or stateless
|
||||
|
||||
if stateless:
|
||||
if 'DEFAULT' in ctxt['sections']:
|
||||
ctxt['sections']['DEFAULT'].append(('host', service_name()))
|
||||
else:
|
||||
ctxt['sections']['DEFAULT'] = [('host', service_name())]
|
||||
|
||||
elif any_stateless:
|
||||
log("One or more stateless backends configured but unable to "
|
||||
"set host param since there appear to also be stateful "
|
||||
"backends configured.", level=WARNING)
|
||||
|
||||
return ctxt
|
||||
|
|
|
@ -172,7 +172,7 @@ CONFIG_FILES = OrderedDict([
|
|||
cinder_contexts.CephContext(),
|
||||
cinder_contexts.HAProxyContext(),
|
||||
cinder_contexts.ImageServiceContext(),
|
||||
context.SubordinateConfigContext(
|
||||
cinder_contexts.CinderSubordinateConfigContext(
|
||||
interface='storage-backend',
|
||||
service='cinder',
|
||||
config_file=CINDER_CONF),
|
||||
|
|
|
@ -135,3 +135,209 @@ class TestCinderContext(CharmTestCase):
|
|||
'namespace': 'cinder'})
|
||||
self.assertTrue(mock_https.called)
|
||||
mock_unit_get.assert_called_with('private-address')
|
||||
|
||||
@patch('%s.relation_get' % (mod_ch_context))
|
||||
@patch('%s.related_units' % (mod_ch_context))
|
||||
@patch('%s.relation_ids' % (mod_ch_context))
|
||||
@patch('%s.log' % (mod_ch_context), lambda *args, **kwargs: None)
|
||||
def test_subordinate_config_context_stateless(self, mock_rel_ids,
|
||||
mock_rel_units,
|
||||
mock_rel_get):
|
||||
mock_rel_ids.return_value = ['storage-backend:0']
|
||||
self.relation_ids.return_value = ['storage-backend:0']
|
||||
|
||||
mock_rel_units.return_value = ['cinder-ceph/0']
|
||||
self.related_units.return_value = ['cinder-ceph/0']
|
||||
|
||||
self.service_name.return_value = 'cinder'
|
||||
|
||||
settings = \
|
||||
{'backend_name': 'cinder-ceph',
|
||||
'private-address': '10.5.8.191',
|
||||
'stateless': 'True',
|
||||
'subordinate_configuration':
|
||||
'{"cinder": '
|
||||
'{"/etc/cinder/cinder.conf": '
|
||||
'{"sections": '
|
||||
'{"cinder-ceph": '
|
||||
'[["volume_backend_name", '
|
||||
'"cinder-ceph"], '
|
||||
'["volume_driver", '
|
||||
'"cinder.volume.drivers.rbd.RBDDriver"], '
|
||||
'["rbd_pool", '
|
||||
'"cinder-ceph"], '
|
||||
'["rbd_user", '
|
||||
'"cinder-ceph"]]}}}}'}
|
||||
|
||||
def fake_rel_get(attribute=None, unit=None, rid=None):
|
||||
return settings.get(attribute)
|
||||
|
||||
mock_rel_get.side_effect = fake_rel_get
|
||||
self.relation_get.side_effect = fake_rel_get
|
||||
|
||||
ctxt = contexts.CinderSubordinateConfigContext(
|
||||
interface='storage-backend',
|
||||
service='cinder',
|
||||
config_file='/etc/cinder/cinder.conf')()
|
||||
|
||||
exp = {'sections': {'DEFAULT': [('host', 'cinder')],
|
||||
u'cinder-ceph': [[u'volume_backend_name', u'cinder-ceph'],
|
||||
[u'volume_driver',
|
||||
u'cinder.volume.drivers.rbd.RBDDriver'],
|
||||
[u'rbd_pool', u'cinder-ceph'],
|
||||
[u'rbd_user', u'cinder-ceph']]}}
|
||||
|
||||
self.assertEquals(ctxt, exp)
|
||||
|
||||
@patch('%s.relation_get' % (mod_ch_context))
|
||||
@patch('%s.related_units' % (mod_ch_context))
|
||||
@patch('%s.relation_ids' % (mod_ch_context))
|
||||
@patch('%s.log' % (mod_ch_context), lambda *args, **kwargs: None)
|
||||
def test_subordinate_config_context_statefull(self, mock_rel_ids,
|
||||
mock_rel_units,
|
||||
mock_rel_get):
|
||||
mock_rel_ids.return_value = ['storage-backend:0']
|
||||
self.relation_ids.return_value = ['storage-backend:0']
|
||||
|
||||
mock_rel_units.return_value = ['cinder-ceph/0']
|
||||
self.related_units.return_value = ['cinder-ceph/0']
|
||||
|
||||
self.service_name.return_value = 'cinder'
|
||||
|
||||
settings = \
|
||||
{'backend_name': 'cinder-ceph',
|
||||
'private-address': '10.5.8.191',
|
||||
'stateless': 'False',
|
||||
'subordinate_configuration':
|
||||
'{"cinder": '
|
||||
'{"/etc/cinder/cinder.conf": '
|
||||
'{"sections": '
|
||||
'{"cinder-ceph": '
|
||||
'[["volume_backend_name", '
|
||||
'"cinder-ceph"], '
|
||||
'["volume_driver", '
|
||||
'"cinder.volume.drivers.rbd.RBDDriver"], '
|
||||
'["rbd_pool", '
|
||||
'"cinder-ceph"], '
|
||||
'["rbd_user", '
|
||||
'"cinder-ceph"]]}}}}'}
|
||||
|
||||
def fake_rel_get(attribute=None, unit=None, rid=None):
|
||||
return settings.get(attribute)
|
||||
|
||||
mock_rel_get.side_effect = fake_rel_get
|
||||
self.relation_get.side_effect = fake_rel_get
|
||||
|
||||
ctxt = contexts.CinderSubordinateConfigContext(
|
||||
interface='storage-backend',
|
||||
service='cinder',
|
||||
config_file='/etc/cinder/cinder.conf')()
|
||||
|
||||
exp = {'sections':
|
||||
{u'cinder-ceph': [[u'volume_backend_name',
|
||||
u'cinder-ceph'],
|
||||
[u'volume_driver',
|
||||
u'cinder.volume.drivers.rbd.RBDDriver'],
|
||||
[u'rbd_pool', u'cinder-ceph'],
|
||||
[u'rbd_user', u'cinder-ceph']]}}
|
||||
|
||||
self.assertEquals(ctxt, exp)
|
||||
|
||||
del settings['stateless']
|
||||
|
||||
ctxt = contexts.CinderSubordinateConfigContext(
|
||||
interface='storage-backend',
|
||||
service='cinder',
|
||||
config_file='/etc/cinder/cinder.conf')()
|
||||
|
||||
exp = {'sections':
|
||||
{u'cinder-ceph': [[u'volume_backend_name',
|
||||
u'cinder-ceph'],
|
||||
[u'volume_driver',
|
||||
u'cinder.volume.drivers.rbd.RBDDriver'],
|
||||
[u'rbd_pool', u'cinder-ceph'],
|
||||
[u'rbd_user', u'cinder-ceph']]}}
|
||||
|
||||
self.assertEquals(ctxt, exp)
|
||||
|
||||
@patch('%s.relation_get' % (mod_ch_context))
|
||||
@patch('%s.related_units' % (mod_ch_context))
|
||||
@patch('%s.relation_ids' % (mod_ch_context))
|
||||
@patch.object(contexts, 'log', lambda *args, **kwargs: None)
|
||||
@patch('%s.log' % (mod_ch_context), lambda *args, **kwargs: None)
|
||||
def test_subordinate_config_context_mixed(self, mock_rel_ids,
|
||||
mock_rel_units,
|
||||
mock_rel_get):
|
||||
mock_rel_ids.return_value = ['storage-backend:0', 'storage-backend:1']
|
||||
self.relation_ids.return_value = ['storage-backend:0',
|
||||
'storage-backend:1']
|
||||
|
||||
def fake_rel_units(rid):
|
||||
if rid == 'storage-backend:0':
|
||||
return ['cinder-ceph/0']
|
||||
else:
|
||||
return ['cinder-other/0']
|
||||
|
||||
mock_rel_units.side_effect = fake_rel_units
|
||||
self.related_units.side_effect = fake_rel_units
|
||||
|
||||
self.service_name.return_value = 'cinder'
|
||||
|
||||
cinder_ceph_settings = \
|
||||
{'backend_name': 'cinder-ceph',
|
||||
'private-address': '10.5.8.191',
|
||||
'stateless': 'True',
|
||||
'subordinate_configuration':
|
||||
'{"cinder": '
|
||||
'{"/etc/cinder/cinder.conf": '
|
||||
'{"sections": '
|
||||
'{"cinder-ceph": '
|
||||
'[["volume_backend_name", '
|
||||
'"cinder-ceph"], '
|
||||
'["volume_driver", '
|
||||
'"cinder.volume.drivers.rbd.RBDDriver"], '
|
||||
'["rbd_pool", '
|
||||
'"cinder-ceph"], '
|
||||
'["rbd_user", '
|
||||
'"cinder-ceph"]]}}}}'}
|
||||
|
||||
cinder_other_settings = \
|
||||
{'backend_name': 'cinder-other',
|
||||
'private-address': '10.5.8.192',
|
||||
'subordinate_configuration':
|
||||
'{"cinder": '
|
||||
'{"/etc/cinder/cinder.conf": '
|
||||
'{"sections": '
|
||||
'{"cinder-other": '
|
||||
'[["volume_backend_name", '
|
||||
'"cinder-other"], '
|
||||
'["volume_driver", '
|
||||
'"cinder.volume.drivers.OtherDriver"]]}}}}'}
|
||||
|
||||
def fake_rel_get(attribute=None, unit=None, rid=None):
|
||||
if unit == 'cinder-ceph/0':
|
||||
return cinder_ceph_settings.get(attribute)
|
||||
elif unit == 'cinder-other/0':
|
||||
return cinder_other_settings.get(attribute)
|
||||
|
||||
mock_rel_get.side_effect = fake_rel_get
|
||||
self.relation_get.side_effect = fake_rel_get
|
||||
|
||||
ctxt = contexts.CinderSubordinateConfigContext(
|
||||
interface='storage-backend',
|
||||
service='cinder',
|
||||
config_file='/etc/cinder/cinder.conf')()
|
||||
|
||||
exp = {'sections':
|
||||
{u'cinder-ceph': [[u'volume_backend_name',
|
||||
u'cinder-ceph'],
|
||||
[u'volume_driver',
|
||||
u'cinder.volume.drivers.rbd.RBDDriver'],
|
||||
[u'rbd_pool', u'cinder-ceph'],
|
||||
[u'rbd_user', u'cinder-ceph']],
|
||||
u'cinder-other': [[u'volume_backend_name',
|
||||
u'cinder-other'],
|
||||
[u'volume_driver',
|
||||
u'cinder.volume.drivers.OtherDriver']]}}
|
||||
|
||||
self.assertEquals(ctxt, exp)
|
||||
|
|
Loading…
Reference in New Issue