Merge "HPE 3par: Unable to create clone of replicated vol"
This commit is contained in:
commit
273175720f
@ -2992,6 +2992,69 @@ class TestHPE3PARDriverBase(HPE3PARBaseDriver):
|
||||
|
||||
mock_client.assert_has_calls(expected)
|
||||
|
||||
@mock.patch.object(volume_types, 'get_volume_type')
|
||||
def test_create_cloned_replicated_volume(self, _mock_volume_types):
|
||||
# setup_mock_client drive with default configuration
|
||||
# and return the mock HTTP 3PAR client
|
||||
conf = self.setup_configuration()
|
||||
self.replication_targets[0]['replication_mode'] = 'sync'
|
||||
conf.replication_device = self.replication_targets
|
||||
mock_client = self.setup_driver(config=conf)
|
||||
|
||||
mock_client.getStorageSystemInfo.return_value = (
|
||||
{'id': self.CLIENT_ID})
|
||||
mock_client.getRemoteCopyGroup.side_effect = (
|
||||
hpeexceptions.HTTPNotFound)
|
||||
mock_client.getCPG.return_value = {'domain': None}
|
||||
|
||||
_mock_volume_types.return_value = {
|
||||
'name': 'replicated',
|
||||
'extra_specs': {
|
||||
'replication_enabled': '<is> True',
|
||||
'replication:mode': 'sync',
|
||||
'volume_type': self.volume_type_replicated}}
|
||||
|
||||
mock_client = self.setup_driver()
|
||||
mock_client.getVolume.return_value = {'name': mock.ANY}
|
||||
task_id = 1
|
||||
mock_client.copyVolume.return_value = {'taskid': task_id}
|
||||
mock_client.getTask.return_value = {'status': 1}
|
||||
with mock.patch.object(hpecommon.HPE3PARCommon,
|
||||
'_create_client') as mock_create_client:
|
||||
mock_create_client.return_value = mock_client
|
||||
|
||||
type_id_replicated = HPE3PARBaseDriver.VOLUME_TYPE_ID_REPLICATED
|
||||
volume = copy.deepcopy(self.volume_replicated)
|
||||
src_vref = {'id': HPE3PARBaseDriver.VOLUME_ID,
|
||||
'name': HPE3PARBaseDriver.VOLUME_NAME,
|
||||
'size': 2, 'status': 'available',
|
||||
'volume_type': 'replicated',
|
||||
'volume_type_id': type_id_replicated}
|
||||
model_update = self.driver.create_cloned_volume(volume, src_vref)
|
||||
self.assertEqual(model_update['replication_status'],
|
||||
fields.ReplicationStatus.ENABLED)
|
||||
|
||||
common = hpecommon.HPE3PARCommon(None)
|
||||
vol_name = common._get_3par_vol_name(volume['id'])
|
||||
src_vol_name = common._get_3par_vol_name(src_vref['id'])
|
||||
optional = {'priority': 1}
|
||||
comment = mock.ANY
|
||||
|
||||
expected = [
|
||||
mock.call.createVolume(vol_name, 'OpenStackCPG',
|
||||
2048, comment),
|
||||
mock.call.copyVolume(
|
||||
src_vol_name,
|
||||
vol_name,
|
||||
None,
|
||||
optional=optional),
|
||||
mock.call.getTask(task_id),
|
||||
mock.call.getRemoteCopyGroup('rcg-0DM4qZEVSKON-DXN-N'),
|
||||
mock.call.startRemoteCopy('rcg-0DM4qZEVSKON-DXN-N')
|
||||
]
|
||||
|
||||
mock_client.assert_has_calls(expected)
|
||||
|
||||
def test_migrate_volume(self):
|
||||
|
||||
conf = {
|
||||
|
@ -147,7 +147,7 @@ class HPE3PARDriverBase(driver.ManageableVD,
|
||||
pass
|
||||
|
||||
@volume_utils.trace
|
||||
def create_volume(self, volume):
|
||||
def create_volume(self, volume, perform_replica=True):
|
||||
return self.common.create_volume(volume)
|
||||
|
||||
@volume_utils.trace
|
||||
|
@ -305,11 +305,12 @@ class HPE3PARCommon(object):
|
||||
4.0.19 - Update code to work with new WSAPI (of 2023). Bug #2015746
|
||||
4.0.20 - Use small QoS Latency value. Bug #2018994
|
||||
4.0.21 - Fix issue seen during retype/migrate. Bug #2026718
|
||||
4.0.22 - Fixed clone of replicated volume. Bug #2021941
|
||||
|
||||
|
||||
"""
|
||||
|
||||
VERSION = "4.0.21"
|
||||
VERSION = "4.0.22"
|
||||
|
||||
stats = {}
|
||||
|
||||
@ -2370,7 +2371,7 @@ class HPE3PARCommon(object):
|
||||
|
||||
return volume_settings
|
||||
|
||||
def create_volume(self, volume):
|
||||
def create_volume(self, volume, perform_replica=True):
|
||||
LOG.debug('CREATE VOLUME (%(disp_name)s: %(vol_name)s %(id)s on '
|
||||
'%(host)s)',
|
||||
{'disp_name': volume['display_name'],
|
||||
@ -2468,10 +2469,11 @@ class HPE3PARCommon(object):
|
||||
LOG.error("Exception: %s", ex)
|
||||
raise exception.CinderException(ex)
|
||||
|
||||
if (self._volume_of_replicated_type(volume,
|
||||
hpe_tiramisu_check=True)
|
||||
and self._do_volume_replication_setup(volume)):
|
||||
replication_flag = True
|
||||
if perform_replica:
|
||||
if (self._volume_of_replicated_type(volume,
|
||||
hpe_tiramisu_check=True)
|
||||
and self._do_volume_replication_setup(volume)):
|
||||
replication_flag = True
|
||||
|
||||
except hpeexceptions.HTTPConflict:
|
||||
msg = _("Volume (%s) already exists on array") % volume_name
|
||||
@ -2613,13 +2615,17 @@ class HPE3PARCommon(object):
|
||||
if str(src_vref['status']) == 'backing-up':
|
||||
back_up_process = True
|
||||
|
||||
# if the sizes of the 2 volumes are the same and except backup
|
||||
# process for ISCSI volume with chap enabled on it.
|
||||
# (i) if the sizes of the 2 volumes are the same and
|
||||
# (ii) this is not a backup process for ISCSI volume with chap
|
||||
# enabled on it and
|
||||
# (iii) volume is not replicated
|
||||
# we can do an online copy, which is a background process
|
||||
# on the 3PAR that makes the volume instantly available.
|
||||
# We can't resize a volume, while it's being copied.
|
||||
if volume['size'] == src_vref['size'] and not (
|
||||
back_up_process and vol_chap_enabled):
|
||||
back_up_process and vol_chap_enabled) and not (
|
||||
self._volume_of_replicated_type(volume,
|
||||
hpe_tiramisu_check=True)):
|
||||
LOG.debug("Creating a clone of volume, using online copy.")
|
||||
|
||||
type_info = self.get_volume_settings_from_type(volume)
|
||||
@ -2655,18 +2661,11 @@ class HPE3PARCommon(object):
|
||||
LOG.error(msg)
|
||||
raise exception.CinderException(msg)
|
||||
|
||||
# v2 replication check
|
||||
replication_flag = False
|
||||
if (self._volume_of_replicated_type(volume,
|
||||
hpe_tiramisu_check=True)
|
||||
and self._do_volume_replication_setup(volume)):
|
||||
replication_flag = True
|
||||
|
||||
if self._volume_of_hpe_tiramisu_type(volume):
|
||||
hpe_tiramisu = True
|
||||
|
||||
return self._get_model_update(volume['host'], cpg,
|
||||
replication=replication_flag,
|
||||
replication=False,
|
||||
provider_location=self.client.id,
|
||||
hpe_tiramisu=hpe_tiramisu)
|
||||
else:
|
||||
@ -2676,7 +2675,8 @@ class HPE3PARCommon(object):
|
||||
LOG.debug("Creating a clone of volume, using non-online copy.")
|
||||
|
||||
# we first have to create the destination volume
|
||||
model_update = self.create_volume(volume)
|
||||
model_update = self.create_volume(volume,
|
||||
perform_replica=False)
|
||||
|
||||
optional = {'priority': 1}
|
||||
body = self.client.copyVolume(src_vol_name, vol_name, None,
|
||||
@ -2693,6 +2693,24 @@ class HPE3PARCommon(object):
|
||||
LOG.debug('Copy volume completed: create_cloned_volume: '
|
||||
'id=%s.', volume['id'])
|
||||
|
||||
# v2 replication check
|
||||
LOG.debug("v2 replication check")
|
||||
replication_flag = False
|
||||
if (self._volume_of_replicated_type(volume,
|
||||
hpe_tiramisu_check=True)
|
||||
and self._do_volume_replication_setup(volume)):
|
||||
replication_flag = True
|
||||
type_info = self.get_volume_settings_from_type(volume)
|
||||
cpg = type_info['cpg']
|
||||
model_update = self._get_model_update(
|
||||
volume['host'], cpg,
|
||||
replication=True,
|
||||
provider_location=self.client.id,
|
||||
hpe_tiramisu=hpe_tiramisu)
|
||||
|
||||
LOG.debug("replication_flag: %(flag)s",
|
||||
{'flag': replication_flag})
|
||||
|
||||
return model_update
|
||||
|
||||
except hpeexceptions.HTTPForbidden:
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
HPE 3PAR driver `bug #2021941
|
||||
<https://bugs.launchpad.net/cinder/+bug/2021941>`_:
|
||||
Fixed: Now clone of replicated volume can be created
|
||||
|
Loading…
Reference in New Issue
Block a user