[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,
|
relation_ids,
|
||||||
service_name,
|
service_name,
|
||||||
related_units,
|
related_units,
|
||||||
relation_get
|
relation_get,
|
||||||
|
log,
|
||||||
|
WARNING,
|
||||||
)
|
)
|
||||||
|
|
||||||
from charmhelpers.contrib.openstack.context import (
|
from charmhelpers.contrib.openstack.context import (
|
||||||
OSContextGenerator,
|
OSContextGenerator,
|
||||||
ApacheSSLContext as SSLContext,
|
ApacheSSLContext as SSLContext,
|
||||||
|
SubordinateConfigContext,
|
||||||
)
|
)
|
||||||
|
|
||||||
from charmhelpers.contrib.openstack.utils import (
|
from charmhelpers.contrib.openstack.utils import (
|
||||||
|
@ -110,3 +113,44 @@ class LoggingConfigContext(OSContextGenerator):
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
return {'debug': config('debug'), 'verbose': config('verbose')}
|
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.CephContext(),
|
||||||
cinder_contexts.HAProxyContext(),
|
cinder_contexts.HAProxyContext(),
|
||||||
cinder_contexts.ImageServiceContext(),
|
cinder_contexts.ImageServiceContext(),
|
||||||
context.SubordinateConfigContext(
|
cinder_contexts.CinderSubordinateConfigContext(
|
||||||
interface='storage-backend',
|
interface='storage-backend',
|
||||||
service='cinder',
|
service='cinder',
|
||||||
config_file=CINDER_CONF),
|
config_file=CINDER_CONF),
|
||||||
|
|
|
@ -135,3 +135,209 @@ class TestCinderContext(CharmTestCase):
|
||||||
'namespace': 'cinder'})
|
'namespace': 'cinder'})
|
||||||
self.assertTrue(mock_https.called)
|
self.assertTrue(mock_https.called)
|
||||||
mock_unit_get.assert_called_with('private-address')
|
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