Merge "HPE 3par: Unable to create clone of replicated vol"

This commit is contained in:
Zuul 2024-03-22 10:09:46 +00:00 committed by Gerrit Code Review
commit 273175720f
4 changed files with 107 additions and 19 deletions

View File

@ -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 = {

View File

@ -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

View File

@ -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:

View File

@ -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