Handle RBD mirroring mode set in the relation
Change-Id: I423eb38f5197879c5f8f7999acb11ece3d26a6a4 Co-authored-by: Marius Oprin <morpin@cloudbasesolutions.com> Signed-off-by: Marius Oprin <moprin@cloudbasesolutions.com>
This commit is contained in:
parent
3b1527df25
commit
3562e11bda
|
@ -126,8 +126,8 @@ class CephRBDMirrorCharm(charms_openstack.plugins.CephCharm):
|
||||||
universal_newlines=True)
|
universal_newlines=True)
|
||||||
return json.loads(output)
|
return json.loads(output)
|
||||||
|
|
||||||
def mirror_pool_enabled(self, pool):
|
def mirror_pool_enabled(self, pool, mode='pool'):
|
||||||
return self._mirror_pool_info(pool).get('mode', None) == 'pool'
|
return self._mirror_pool_info(pool).get('mode', None) == mode
|
||||||
|
|
||||||
def mirror_pool_has_peers(self, pool):
|
def mirror_pool_has_peers(self, pool):
|
||||||
return len(self._mirror_pool_info(pool).get('peers', [])) > 0
|
return len(self._mirror_pool_info(pool).get('peers', [])) > 0
|
||||||
|
@ -151,9 +151,9 @@ class CephRBDMirrorCharm(charms_openstack.plugins.CephCharm):
|
||||||
stats['image_states'][state] += value
|
stats['image_states'][state] += value
|
||||||
return stats
|
return stats
|
||||||
|
|
||||||
def mirror_pool_enable(self, pool):
|
def mirror_pool_enable(self, pool, mode='pool'):
|
||||||
base_cmd = ['rbd', '--id', self.ceph_id, 'mirror', 'pool']
|
base_cmd = ['rbd', '--id', self.ceph_id, 'mirror', 'pool']
|
||||||
subprocess.check_call(base_cmd + ['enable', pool, 'pool'])
|
subprocess.check_call(base_cmd + ['enable', pool, mode])
|
||||||
subprocess.check_call(base_cmd + ['peer', 'add', pool,
|
subprocess.check_call(base_cmd + ['peer', 'add', pool,
|
||||||
'client.{}@remote'
|
'client.{}@remote'
|
||||||
.format(self.ceph_id)])
|
.format(self.ceph_id)])
|
||||||
|
@ -176,6 +176,32 @@ class CephRBDMirrorCharm(charms_openstack.plugins.CephCharm):
|
||||||
result_set.add(op['name'])
|
result_set.add(op['name'])
|
||||||
return result_set
|
return result_set
|
||||||
|
|
||||||
|
def pool_mirroring_mode(self, pool, broker_requests=[]):
|
||||||
|
"""Get the Ceph RBD mirroring mode for the pool.
|
||||||
|
|
||||||
|
Checks if the pool RBD mirroring mode was explicitly set as part of
|
||||||
|
the 'create-pool' operation into any of the given broker requests.
|
||||||
|
If this is true, its value is returned, otherwise the default 'pool'
|
||||||
|
mirroring mode is used.
|
||||||
|
|
||||||
|
:param pool: Pool name
|
||||||
|
:type pool: str
|
||||||
|
:param broker_requests: List of broker requests
|
||||||
|
:type broker_requests: List[ch_ceph.CephBrokerRq]
|
||||||
|
:returns: Ceph RBD mirroring mode
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
default_mirroring_mode = 'pool'
|
||||||
|
for rq in broker_requests:
|
||||||
|
if not rq:
|
||||||
|
continue
|
||||||
|
assert rq.api_version == 1
|
||||||
|
for op in rq.ops:
|
||||||
|
if op['op'] == 'create-pool' and op['name'] == pool:
|
||||||
|
return op.get(
|
||||||
|
'rbd-mirroring-mode', default_mirroring_mode)
|
||||||
|
return default_mirroring_mode
|
||||||
|
|
||||||
def collapse_and_filter_broker_requests(self, broker_requests,
|
def collapse_and_filter_broker_requests(self, broker_requests,
|
||||||
allowed_ops, require_vp=None):
|
allowed_ops, require_vp=None):
|
||||||
"""Extract allowed ops from broker requests into one collapsed request.
|
"""Extract allowed ops from broker requests into one collapsed request.
|
||||||
|
|
|
@ -117,12 +117,16 @@ def configure_pools():
|
||||||
pools_in_rq |= charm_instance.pools_in_broker_request(
|
pools_in_rq |= charm_instance.pools_in_broker_request(
|
||||||
remote_rq) if remote_rq else set()
|
remote_rq) if remote_rq else set()
|
||||||
for pool, attrs in charm_instance.eligible_pools(local.pools).items():
|
for pool, attrs in charm_instance.eligible_pools(local.pools).items():
|
||||||
if not (charm_instance.mirror_pool_enabled(pool) and
|
pool_mirroring_mode = charm_instance.pool_mirroring_mode(
|
||||||
charm_instance.mirror_pool_has_peers(pool)):
|
pool, [rq, remote_rq])
|
||||||
|
mirroring_enabled = charm_instance.mirror_pool_enabled(
|
||||||
|
pool, pool_mirroring_mode)
|
||||||
|
has_peers = charm_instance.mirror_pool_has_peers(pool)
|
||||||
|
if not (mirroring_enabled and has_peers):
|
||||||
ch_core.hookenv.log('Enabling mirroring for pool "{}"'
|
ch_core.hookenv.log('Enabling mirroring for pool "{}"'
|
||||||
.format(pool),
|
.format(pool),
|
||||||
level=ch_core.hookenv.INFO)
|
level=ch_core.hookenv.INFO)
|
||||||
charm_instance.mirror_pool_enable(pool)
|
charm_instance.mirror_pool_enable(pool, pool_mirroring_mode)
|
||||||
if (pool not in pools_in_rq and
|
if (pool not in pools_in_rq and
|
||||||
'erasure_code_profile' not in attrs['parameters']):
|
'erasure_code_profile' not in attrs['parameters']):
|
||||||
# A pool exists that there is no broker request for which means
|
# A pool exists that there is no broker request for which means
|
||||||
|
|
|
@ -157,11 +157,17 @@ class TestCephRBDMirrorHandlers(test_utils.PatchHelper):
|
||||||
self.patch_object(handlers.reactive, 'endpoint_from_flag')
|
self.patch_object(handlers.reactive, 'endpoint_from_flag')
|
||||||
endpoint_local = mock.MagicMock()
|
endpoint_local = mock.MagicMock()
|
||||||
endpoint_remote = mock.MagicMock()
|
endpoint_remote = mock.MagicMock()
|
||||||
|
self.crm_charm.collapse_and_filter_broker_requests.side_effect = [
|
||||||
|
endpoint_local, endpoint_remote]
|
||||||
endpoint_local.endpoint_name = 'ceph-local'
|
endpoint_local.endpoint_name = 'ceph-local'
|
||||||
endpoint_local.pools = {
|
endpoint_local.pools = {
|
||||||
'cinder-ceph': {
|
'cinder-ceph': {
|
||||||
'applications': {'rbd': {}},
|
'applications': {'rbd': {}},
|
||||||
'parameters': {'pg_num': 42, 'size': 3},
|
'parameters': {
|
||||||
|
'pg_num': 42,
|
||||||
|
'size': 3,
|
||||||
|
'rbd-mirroring-mode': 'pool'
|
||||||
|
},
|
||||||
'quota': {'max_bytes': 1024, 'max_objects': 51},
|
'quota': {'max_bytes': 1024, 'max_objects': 51},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -170,6 +176,8 @@ class TestCephRBDMirrorHandlers(test_utils.PatchHelper):
|
||||||
endpoint_remote]
|
endpoint_remote]
|
||||||
self.crm_charm.eligible_pools.return_value = endpoint_local.pools
|
self.crm_charm.eligible_pools.return_value = endpoint_local.pools
|
||||||
self.crm_charm.mirror_pool_enabled.return_value = False
|
self.crm_charm.mirror_pool_enabled.return_value = False
|
||||||
|
self.crm_charm.pool_mirroring_mode.return_value = 'pool'
|
||||||
|
|
||||||
handlers.configure_pools()
|
handlers.configure_pools()
|
||||||
self.endpoint_from_flag.assert_has_calls([
|
self.endpoint_from_flag.assert_has_calls([
|
||||||
mock.call('ceph-local.available'),
|
mock.call('ceph-local.available'),
|
||||||
|
@ -177,8 +185,10 @@ class TestCephRBDMirrorHandlers(test_utils.PatchHelper):
|
||||||
])
|
])
|
||||||
self.crm_charm.eligible_pools.assert_called_once_with(
|
self.crm_charm.eligible_pools.assert_called_once_with(
|
||||||
endpoint_local.pools)
|
endpoint_local.pools)
|
||||||
|
self.crm_charm.pool_mirroring_mode.assert_called_once_with(
|
||||||
|
'cinder-ceph', [endpoint_local, endpoint_remote])
|
||||||
self.crm_charm.mirror_pool_enabled.assert_called_once_with(
|
self.crm_charm.mirror_pool_enabled.assert_called_once_with(
|
||||||
'cinder-ceph')
|
'cinder-ceph', 'pool')
|
||||||
self.crm_charm.mirror_pool_enable.assert_called_once_with(
|
self.crm_charm.mirror_pool_enable.assert_called_once_with(
|
||||||
'cinder-ceph')
|
'cinder-ceph', 'pool')
|
||||||
endpoint_remote.maybe_send_rq.assert_called_once_with(mock.ANY)
|
endpoint_remote.maybe_send_rq.assert_called_once_with(endpoint_local)
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
import mock
|
import mock
|
||||||
|
import json
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
import charms_openstack.test_utils as test_utils
|
import charms_openstack.test_utils as test_utils
|
||||||
|
@ -92,10 +93,10 @@ class TestCephRBDMirrorCharm(Helper):
|
||||||
'client.rbd-mirror.juju-c50b1a-zaza-4ce96f1e7e43-12'}]
|
'client.rbd-mirror.juju-c50b1a-zaza-4ce96f1e7e43-12'}]
|
||||||
}
|
}
|
||||||
crmc._mirror_pool_info = _mirror_pool_info
|
crmc._mirror_pool_info = _mirror_pool_info
|
||||||
self.assertTrue(crmc.mirror_pool_enabled('apool'))
|
self.assertTrue(crmc.mirror_pool_enabled('apool', mode='pool'))
|
||||||
_mirror_pool_info.assert_called_once_with('apool')
|
_mirror_pool_info.assert_called_once_with('apool')
|
||||||
_mirror_pool_info.return_value = {'mode': 'disabled'}
|
_mirror_pool_info.return_value = {'mode': 'disabled'}
|
||||||
self.assertFalse(crmc.mirror_pool_enabled('apool'))
|
self.assertFalse(crmc.mirror_pool_enabled('apool', mode='pool'))
|
||||||
|
|
||||||
def test_mirror_pool_has_peers(self):
|
def test_mirror_pool_has_peers(self):
|
||||||
self.patch_object(ceph_rbd_mirror.socket, 'gethostname')
|
self.patch_object(ceph_rbd_mirror.socket, 'gethostname')
|
||||||
|
@ -192,3 +193,55 @@ class TestCephRBDMirrorCharm(Helper):
|
||||||
{'app-name': 'rbd', 'name': 'pool-rq2', 'op': 'create-pool',
|
{'app-name': 'rbd', 'name': 'pool-rq2', 'op': 'create-pool',
|
||||||
'someotherkey': 'value'})
|
'someotherkey': 'value'})
|
||||||
self.assertTrue(len(rq.ops) == 1)
|
self.assertTrue(len(rq.ops) == 1)
|
||||||
|
|
||||||
|
def test_pool_mirroring_mode(self):
|
||||||
|
self.patch_object(ceph_rbd_mirror.ch_ceph, 'CephBrokerRq')
|
||||||
|
|
||||||
|
class FakeCephBrokerRq(object):
|
||||||
|
def __init__(self, raw_request_data=None):
|
||||||
|
request_data = json.loads(raw_request_data)
|
||||||
|
self.api_version = request_data['api-version']
|
||||||
|
self.request_id = request_data['request-id']
|
||||||
|
self.set_ops(request_data['ops'])
|
||||||
|
|
||||||
|
def set_ops(self, ops):
|
||||||
|
self.ops = ops
|
||||||
|
|
||||||
|
def add_op(self, op):
|
||||||
|
self.ops.append(op)
|
||||||
|
|
||||||
|
self.CephBrokerRq.side_effect = FakeCephBrokerRq
|
||||||
|
|
||||||
|
brq1_data = json.dumps({
|
||||||
|
'api-version': 1,
|
||||||
|
'request-id': 'broker_rq1',
|
||||||
|
'ops': [
|
||||||
|
{
|
||||||
|
'op': 'create-pool',
|
||||||
|
'name': 'pool-rq0',
|
||||||
|
'app-name': 'rbd-pool',
|
||||||
|
'rbd-mirroring-mode': 'pool'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
})
|
||||||
|
brq2_data = json.dumps({
|
||||||
|
'api-version': 1,
|
||||||
|
'request-id': 'broker_rq2',
|
||||||
|
'ops': [
|
||||||
|
{
|
||||||
|
'op': 'create-pool',
|
||||||
|
'name': 'pool-rq1',
|
||||||
|
'app-name': 'rbd-image',
|
||||||
|
'rbd-mirroring-mode': 'image'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
brq1 = self.CephBrokerRq(raw_request_data=brq1_data)
|
||||||
|
brq2 = self.CephBrokerRq(raw_request_data=brq2_data)
|
||||||
|
broker_requests = [brq1, brq2, None]
|
||||||
|
crmc = ceph_rbd_mirror.CephRBDMirrorCharm()
|
||||||
|
rq0 = crmc.pool_mirroring_mode('pool-rq0', broker_requests)
|
||||||
|
self.assertEqual('pool', rq0)
|
||||||
|
rq1 = crmc.pool_mirroring_mode('pool-rq1', broker_requests)
|
||||||
|
self.assertEqual('image', rq1)
|
||||||
|
|
Loading…
Reference in New Issue