Merge "Verify volume is replication capable"
This commit is contained in:
commit
4b0e06af7a
@ -6305,6 +6305,24 @@ class GenericVolumeDriverTestCase(DriverTestCase):
|
||||
volume_api.enable_replication,
|
||||
ctxt, volume)
|
||||
|
||||
def test_enable_replication_invalid_type(self):
|
||||
volume_api = cinder.volume.api.API()
|
||||
ctxt = context.get_admin_context()
|
||||
|
||||
volume = tests_utils.create_volume(self.context,
|
||||
size=1,
|
||||
host=CONF.host,
|
||||
replication_status='disabled')
|
||||
volume['volume_type_id'] = 'dab02f01-b50f-4ed6-8d42-2b5b9680996e'
|
||||
fake_specs = {}
|
||||
with mock.patch.object(volume_types,
|
||||
'get_volume_type_extra_specs',
|
||||
return_value = fake_specs):
|
||||
self.assertRaises(exception.InvalidVolume,
|
||||
volume_api.enable_replication,
|
||||
ctxt,
|
||||
volume)
|
||||
|
||||
def test_enable_replication(self):
|
||||
volume_api = cinder.volume.api.API()
|
||||
ctxt = context.get_admin_context()
|
||||
@ -6313,8 +6331,14 @@ class GenericVolumeDriverTestCase(DriverTestCase):
|
||||
size=1,
|
||||
host=CONF.host,
|
||||
replication_status='disabled')
|
||||
volume['volume_type_id'] = 'dab02f01-b50f-4ed6-8d42-2b5b9680996e'
|
||||
fake_specs = {'replication_enabled': '<is> True'}
|
||||
with mock.patch.object(volume_rpcapi.VolumeAPI,
|
||||
'enable_replication') as mock_enable_rep:
|
||||
'enable_replication') as mock_enable_rep,\
|
||||
mock.patch.object(volume_types,
|
||||
'get_volume_type_extra_specs',
|
||||
return_value = fake_specs):
|
||||
|
||||
volume_api.enable_replication(ctxt, volume)
|
||||
self.assertTrue(mock_enable_rep.called)
|
||||
|
||||
@ -6339,8 +6363,13 @@ class GenericVolumeDriverTestCase(DriverTestCase):
|
||||
host=CONF.host,
|
||||
replication_status='disabled')
|
||||
|
||||
volume['volume_type_id'] = 'dab02f01-b50f-4ed6-8d42-2b5b9680996e'
|
||||
fake_specs = {'replication_enabled': '<is> True'}
|
||||
with mock.patch.object(volume_rpcapi.VolumeAPI,
|
||||
'disable_replication') as mock_disable_rep:
|
||||
'disable_replication') as mock_disable_rep,\
|
||||
mock.patch.object(volume_types,
|
||||
'get_volume_type_extra_specs',
|
||||
return_value = fake_specs):
|
||||
volume_api.disable_replication(ctxt, volume)
|
||||
self.assertTrue(mock_disable_rep.called)
|
||||
|
||||
|
@ -115,6 +115,29 @@ def check_policy(context, action, target_obj=None):
|
||||
cinder.policy.enforce(context, _action, target)
|
||||
|
||||
|
||||
def valid_replication_volume(func):
|
||||
"""Check that the volume is capable of replication.
|
||||
|
||||
This decorator requires the first 3 args of the wrapped function
|
||||
to be (self, context, volume)
|
||||
"""
|
||||
@functools.wraps(func)
|
||||
def wrapped(self, context, volume, *args, **kwargs):
|
||||
rep_capable = False
|
||||
if volume.get('volume_type_id', None):
|
||||
extra_specs = volume_types.get_volume_type_extra_specs(
|
||||
volume.get('volume_type_id'))
|
||||
rep_capable = extra_specs.get('replication_enabled',
|
||||
False) == "<is> True"
|
||||
if not rep_capable:
|
||||
msg = _("Volume is not a replication enabled volume, "
|
||||
"replication operations can only be performed "
|
||||
"on volumes that are of type replication_enabled.")
|
||||
raise exception.InvalidVolume(reason=msg)
|
||||
return func(self, context, volume, *args, **kwargs)
|
||||
return wrapped
|
||||
|
||||
|
||||
class API(base.Base):
|
||||
"""API for interacting with the volume manager."""
|
||||
|
||||
@ -1594,8 +1617,8 @@ class API(base.Base):
|
||||
# now they're a special resource, so no.
|
||||
|
||||
@wrap_check_policy
|
||||
@valid_replication_volume
|
||||
def enable_replication(self, ctxt, volume):
|
||||
|
||||
# NOTE(jdg): details like sync vs async
|
||||
# and replica count are to be set via the
|
||||
# volume-type and config files.
|
||||
@ -1631,6 +1654,7 @@ class API(base.Base):
|
||||
self.volume_rpcapi.enable_replication(ctxt, vref)
|
||||
|
||||
@wrap_check_policy
|
||||
@valid_replication_volume
|
||||
def disable_replication(self, ctxt, volume):
|
||||
|
||||
valid_disable_status = ['disabled', 'enabled']
|
||||
@ -1656,6 +1680,7 @@ class API(base.Base):
|
||||
self.volume_rpcapi.disable_replication(ctxt, vref)
|
||||
|
||||
@wrap_check_policy
|
||||
@valid_replication_volume
|
||||
def failover_replication(self,
|
||||
ctxt,
|
||||
volume,
|
||||
@ -1688,6 +1713,7 @@ class API(base.Base):
|
||||
secondary)
|
||||
|
||||
@wrap_check_policy
|
||||
@valid_replication_volume
|
||||
def list_replication_targets(self, ctxt, volume):
|
||||
|
||||
# NOTE(jdg): This collects info for the specified volume
|
||||
|
Loading…
Reference in New Issue
Block a user