Merge "3PAR: Fixed image cache enabled capability."
This commit is contained in:
@@ -1458,6 +1458,7 @@ class HPE3PARBaseDriver(object):
|
|||||||
def test_retype_not_3par(self, _mock_volume_types):
|
def test_retype_not_3par(self, _mock_volume_types):
|
||||||
_mock_volume_types.return_value = self.RETYPE_VOLUME_TYPE_1
|
_mock_volume_types.return_value = self.RETYPE_VOLUME_TYPE_1
|
||||||
mock_client = self.setup_driver(mock_conf=self.RETYPE_CONF)
|
mock_client = self.setup_driver(mock_conf=self.RETYPE_CONF)
|
||||||
|
mock_client.getVolumeSnapshots.return_value = []
|
||||||
|
|
||||||
with mock.patch.object(hpecommon.HPE3PARCommon,
|
with mock.patch.object(hpecommon.HPE3PARCommon,
|
||||||
'_create_client') as mock_create_client:
|
'_create_client') as mock_create_client:
|
||||||
@@ -1470,7 +1471,8 @@ class HPE3PARBaseDriver(object):
|
|||||||
self.RETYPE_DIFF,
|
self.RETYPE_DIFF,
|
||||||
self.RETYPE_HOST_NOT3PAR)
|
self.RETYPE_HOST_NOT3PAR)
|
||||||
|
|
||||||
expected = [mock.call.getVolume(self.VOLUME_3PAR_NAME)]
|
expected = [mock.call.getVolumeSnapshots(self.VOLUME_3PAR_NAME),
|
||||||
|
mock.call.getVolume(self.VOLUME_3PAR_NAME)]
|
||||||
mock_client.assert_has_calls(
|
mock_client.assert_has_calls(
|
||||||
self.standard_login +
|
self.standard_login +
|
||||||
expected +
|
expected +
|
||||||
@@ -1480,6 +1482,7 @@ class HPE3PARBaseDriver(object):
|
|||||||
def test_retype_volume_not_found(self, _mock_volume_types):
|
def test_retype_volume_not_found(self, _mock_volume_types):
|
||||||
_mock_volume_types.return_value = self.RETYPE_VOLUME_TYPE_1
|
_mock_volume_types.return_value = self.RETYPE_VOLUME_TYPE_1
|
||||||
mock_client = self.setup_driver(mock_conf=self.RETYPE_CONF)
|
mock_client = self.setup_driver(mock_conf=self.RETYPE_CONF)
|
||||||
|
mock_client.getVolumeSnapshots.return_value = []
|
||||||
mock_client.getVolume.side_effect = hpeexceptions.HTTPNotFound
|
mock_client.getVolume.side_effect = hpeexceptions.HTTPNotFound
|
||||||
|
|
||||||
with mock.patch.object(hpecommon.HPE3PARCommon,
|
with mock.patch.object(hpecommon.HPE3PARCommon,
|
||||||
@@ -1493,7 +1496,8 @@ class HPE3PARBaseDriver(object):
|
|||||||
self.RETYPE_DIFF,
|
self.RETYPE_DIFF,
|
||||||
self.RETYPE_HOST)
|
self.RETYPE_HOST)
|
||||||
|
|
||||||
expected = [mock.call.getVolume(self.VOLUME_3PAR_NAME)]
|
expected = [mock.call.getVolumeSnapshots(self.VOLUME_3PAR_NAME),
|
||||||
|
mock.call.getVolume(self.VOLUME_3PAR_NAME)]
|
||||||
mock_client.assert_has_calls(
|
mock_client.assert_has_calls(
|
||||||
self.standard_login +
|
self.standard_login +
|
||||||
expected +
|
expected +
|
||||||
@@ -1571,6 +1575,7 @@ class HPE3PARBaseDriver(object):
|
|||||||
def test_retype_different_array(self, _mock_volume_types):
|
def test_retype_different_array(self, _mock_volume_types):
|
||||||
_mock_volume_types.return_value = self.RETYPE_VOLUME_TYPE_1
|
_mock_volume_types.return_value = self.RETYPE_VOLUME_TYPE_1
|
||||||
mock_client = self.setup_driver(mock_conf=self.RETYPE_CONF)
|
mock_client = self.setup_driver(mock_conf=self.RETYPE_CONF)
|
||||||
|
mock_client.getVolumeSnapshots.return_value = []
|
||||||
|
|
||||||
mock_client.getStorageSystemInfo.return_value = {
|
mock_client.getStorageSystemInfo.return_value = {
|
||||||
'id': self.CLIENT_ID,
|
'id': self.CLIENT_ID,
|
||||||
@@ -1588,6 +1593,7 @@ class HPE3PARBaseDriver(object):
|
|||||||
self.RETYPE_HOST)
|
self.RETYPE_HOST)
|
||||||
|
|
||||||
expected = [
|
expected = [
|
||||||
|
mock.call.getVolumeSnapshots(self.VOLUME_3PAR_NAME),
|
||||||
mock.call.getVolume(self.VOLUME_3PAR_NAME),
|
mock.call.getVolume(self.VOLUME_3PAR_NAME),
|
||||||
mock.call.getStorageSystemInfo()]
|
mock.call.getStorageSystemInfo()]
|
||||||
|
|
||||||
@@ -1600,6 +1606,7 @@ class HPE3PARBaseDriver(object):
|
|||||||
def test_retype_across_cpg_domains(self, _mock_volume_types):
|
def test_retype_across_cpg_domains(self, _mock_volume_types):
|
||||||
_mock_volume_types.return_value = self.RETYPE_VOLUME_TYPE_1
|
_mock_volume_types.return_value = self.RETYPE_VOLUME_TYPE_1
|
||||||
mock_client = self.setup_driver(mock_conf=self.RETYPE_CONF)
|
mock_client = self.setup_driver(mock_conf=self.RETYPE_CONF)
|
||||||
|
mock_client.getVolumeSnapshots.return_value = []
|
||||||
|
|
||||||
mock_client.getCPG.side_effect = [
|
mock_client.getCPG.side_effect = [
|
||||||
{'domain': 'domain1'},
|
{'domain': 'domain1'},
|
||||||
@@ -1618,6 +1625,7 @@ class HPE3PARBaseDriver(object):
|
|||||||
self.RETYPE_HOST)
|
self.RETYPE_HOST)
|
||||||
|
|
||||||
expected = [
|
expected = [
|
||||||
|
mock.call.getVolumeSnapshots(self.VOLUME_3PAR_NAME),
|
||||||
mock.call.getVolume(self.VOLUME_3PAR_NAME),
|
mock.call.getVolume(self.VOLUME_3PAR_NAME),
|
||||||
mock.call.getStorageSystemInfo(),
|
mock.call.getStorageSystemInfo(),
|
||||||
mock.call.getCPG(self.RETYPE_VOLUME_INFO_0['userCPG']),
|
mock.call.getCPG(self.RETYPE_VOLUME_INFO_0['userCPG']),
|
||||||
@@ -1633,6 +1641,7 @@ class HPE3PARBaseDriver(object):
|
|||||||
def test_retype_across_snap_cpg_domains(self, _mock_volume_types):
|
def test_retype_across_snap_cpg_domains(self, _mock_volume_types):
|
||||||
_mock_volume_types.return_value = self.RETYPE_VOLUME_TYPE_1
|
_mock_volume_types.return_value = self.RETYPE_VOLUME_TYPE_1
|
||||||
mock_client = self.setup_driver(mock_conf=self.RETYPE_CONF)
|
mock_client = self.setup_driver(mock_conf=self.RETYPE_CONF)
|
||||||
|
mock_client.getVolumeSnapshots.return_value = []
|
||||||
|
|
||||||
mock_client.getCPG.side_effect = [
|
mock_client.getCPG.side_effect = [
|
||||||
{'domain': 'cpg_domain'},
|
{'domain': 'cpg_domain'},
|
||||||
@@ -1652,6 +1661,7 @@ class HPE3PARBaseDriver(object):
|
|||||||
self.RETYPE_HOST)
|
self.RETYPE_HOST)
|
||||||
|
|
||||||
expected = [
|
expected = [
|
||||||
|
mock.call.getVolumeSnapshots(self.VOLUME_3PAR_NAME),
|
||||||
mock.call.getVolume(self.VOLUME_3PAR_NAME),
|
mock.call.getVolume(self.VOLUME_3PAR_NAME),
|
||||||
mock.call.getStorageSystemInfo(),
|
mock.call.getStorageSystemInfo(),
|
||||||
mock.call.getCPG(self.RETYPE_VOLUME_INFO_0['userCPG']),
|
mock.call.getCPG(self.RETYPE_VOLUME_INFO_0['userCPG']),
|
||||||
@@ -1669,6 +1679,7 @@ class HPE3PARBaseDriver(object):
|
|||||||
def test_retype_to_bad_persona(self, _mock_volume_types):
|
def test_retype_to_bad_persona(self, _mock_volume_types):
|
||||||
_mock_volume_types.return_value = self.RETYPE_VOLUME_TYPE_BAD_PERSONA
|
_mock_volume_types.return_value = self.RETYPE_VOLUME_TYPE_BAD_PERSONA
|
||||||
mock_client = self.setup_driver(mock_conf=self.RETYPE_CONF)
|
mock_client = self.setup_driver(mock_conf=self.RETYPE_CONF)
|
||||||
|
mock_client.getVolumeSnapshots.return_value = []
|
||||||
|
|
||||||
with mock.patch.object(hpecommon.HPE3PARCommon,
|
with mock.patch.object(hpecommon.HPE3PARCommon,
|
||||||
'_create_client') as mock_create_client:
|
'_create_client') as mock_create_client:
|
||||||
@@ -1681,7 +1692,8 @@ class HPE3PARBaseDriver(object):
|
|||||||
self.RETYPE_DIFF,
|
self.RETYPE_DIFF,
|
||||||
self.RETYPE_HOST)
|
self.RETYPE_HOST)
|
||||||
|
|
||||||
expected = [mock.call.getVolume(self.VOLUME_3PAR_NAME)]
|
expected = [mock.call.getVolumeSnapshots(self.VOLUME_3PAR_NAME),
|
||||||
|
mock.call.getVolume(self.VOLUME_3PAR_NAME)]
|
||||||
mock_client.assert_has_calls(
|
mock_client.assert_has_calls(
|
||||||
self.standard_login +
|
self.standard_login +
|
||||||
expected +
|
expected +
|
||||||
@@ -2270,12 +2282,19 @@ class HPE3PARBaseDriver(object):
|
|||||||
'size': 2, 'status': 'available'}
|
'size': 2, 'status': 'available'}
|
||||||
model_update = self.driver.create_cloned_volume(volume, src_vref)
|
model_update = self.driver.create_cloned_volume(volume, src_vref)
|
||||||
self.assertIsNone(model_update)
|
self.assertIsNone(model_update)
|
||||||
|
common = hpecommon.HPE3PARCommon(None)
|
||||||
|
vol_name = common._get_3par_vol_name(src_vref['id'])
|
||||||
|
# snapshot name is random
|
||||||
|
snap_name = mock.ANY
|
||||||
|
optional = mock.ANY
|
||||||
expectedcall = [
|
expectedcall = [
|
||||||
mock.call.getStorageSystemInfo()]
|
mock.call.getStorageSystemInfo()]
|
||||||
|
|
||||||
expected = [
|
expected = [
|
||||||
|
mock.call.createSnapshot(snap_name, vol_name, optional),
|
||||||
|
mock.call.getVolume(snap_name),
|
||||||
mock.call.copyVolume(
|
mock.call.copyVolume(
|
||||||
self.VOLUME_NAME_3PAR,
|
snap_name,
|
||||||
'osv-0DM4qZEVSKON-AAAAAAAAA',
|
'osv-0DM4qZEVSKON-AAAAAAAAA',
|
||||||
HPE3PAR_CPG2,
|
HPE3PAR_CPG2,
|
||||||
{'snapCPG': 'OpenStackCPGSnap', 'tpvv': True,
|
{'snapCPG': 'OpenStackCPGSnap', 'tpvv': True,
|
||||||
@@ -2293,14 +2312,14 @@ class HPE3PARBaseDriver(object):
|
|||||||
def test_clone_volume_with_vvs(self, _mock_volume_types):
|
def test_clone_volume_with_vvs(self, _mock_volume_types):
|
||||||
# Setup_mock_client drive with default configuration
|
# Setup_mock_client drive with default configuration
|
||||||
# and return the mock HTTP 3PAR client
|
# and return the mock HTTP 3PAR client
|
||||||
mock_client = self.setup_driver()
|
conf = self.setup_configuration()
|
||||||
|
mock_client = self.setup_driver(config=conf)
|
||||||
|
|
||||||
_mock_volume_types.return_value = {
|
_mock_volume_types.return_value = {
|
||||||
'name': 'gold',
|
'name': 'gold',
|
||||||
'id': 'gold-id',
|
'id': 'gold-id',
|
||||||
'extra_specs': {'vvs': self.VVS_NAME}}
|
'extra_specs': {'vvs': self.VVS_NAME}}
|
||||||
|
|
||||||
mock_client = self.setup_driver()
|
|
||||||
mock_client.getVolume.return_value = {'name': mock.ANY}
|
mock_client.getVolume.return_value = {'name': mock.ANY}
|
||||||
mock_client.copyVolume.return_value = {'taskid': 1}
|
mock_client.copyVolume.return_value = {'taskid': 1}
|
||||||
|
|
||||||
@@ -2323,6 +2342,11 @@ class HPE3PARBaseDriver(object):
|
|||||||
'volume_type': 'gold',
|
'volume_type': 'gold',
|
||||||
'host': self.FAKE_CINDER_HOST,
|
'host': self.FAKE_CINDER_HOST,
|
||||||
'volume_type_id': 'gold-id'}
|
'volume_type_id': 'gold-id'}
|
||||||
|
# creation of the temp snapshot
|
||||||
|
common = hpecommon.HPE3PARCommon(conf)
|
||||||
|
snap_name = mock.ANY
|
||||||
|
vol_name = common._get_3par_vol_name(src_vref['id'])
|
||||||
|
optional = mock.ANY
|
||||||
|
|
||||||
model_update = self.driver.create_cloned_volume(volume_vvs,
|
model_update = self.driver.create_cloned_volume(volume_vvs,
|
||||||
src_vref)
|
src_vref)
|
||||||
@@ -2334,8 +2358,10 @@ class HPE3PARBaseDriver(object):
|
|||||||
self.assertEqual(clone_vol_vvs, source_vol_vvs)
|
self.assertEqual(clone_vol_vvs, source_vol_vvs)
|
||||||
|
|
||||||
expected = [
|
expected = [
|
||||||
|
mock.call.createSnapshot(snap_name, vol_name, optional),
|
||||||
|
mock.call.getVolume(snap_name),
|
||||||
mock.call.copyVolume(
|
mock.call.copyVolume(
|
||||||
self.VOLUME_NAME_3PAR,
|
snap_name,
|
||||||
'osv-0DM4qZEVSKON-AAAAAAAAA',
|
'osv-0DM4qZEVSKON-AAAAAAAAA',
|
||||||
'OpenStackCPG',
|
'OpenStackCPG',
|
||||||
{'snapCPG': 'OpenStackCPGSnap', 'tpvv': True,
|
{'snapCPG': 'OpenStackCPGSnap', 'tpvv': True,
|
||||||
@@ -2372,10 +2398,17 @@ class HPE3PARBaseDriver(object):
|
|||||||
'size': 2, 'status': 'backing-up'}
|
'size': 2, 'status': 'backing-up'}
|
||||||
model_update = self.driver.create_cloned_volume(volume, src_vref)
|
model_update = self.driver.create_cloned_volume(volume, src_vref)
|
||||||
self.assertIsNone(model_update)
|
self.assertIsNone(model_update)
|
||||||
|
# creation of the temp snapshot
|
||||||
|
common = hpecommon.HPE3PARCommon(None)
|
||||||
|
snap_name = mock.ANY
|
||||||
|
vol_name = common._get_3par_vol_name(src_vref['id'])
|
||||||
|
optional = mock.ANY
|
||||||
|
|
||||||
expected = [
|
expected = [
|
||||||
|
mock.call.createSnapshot(snap_name, vol_name, optional),
|
||||||
|
mock.call.getVolume(snap_name),
|
||||||
mock.call.copyVolume(
|
mock.call.copyVolume(
|
||||||
self.VOLUME_NAME_3PAR,
|
snap_name,
|
||||||
'osv-0DM4qZEVSKON-AAAAAAAAA',
|
'osv-0DM4qZEVSKON-AAAAAAAAA',
|
||||||
HPE3PAR_CPG2,
|
HPE3PAR_CPG2,
|
||||||
{'snapCPG': 'OpenStackCPGSnap', 'tpvv': True,
|
{'snapCPG': 'OpenStackCPGSnap', 'tpvv': True,
|
||||||
@@ -2413,13 +2446,17 @@ class HPE3PARBaseDriver(object):
|
|||||||
self.assertIsNone(model_update)
|
self.assertIsNone(model_update)
|
||||||
|
|
||||||
common = hpecommon.HPE3PARCommon(None)
|
common = hpecommon.HPE3PARCommon(None)
|
||||||
|
snap_name = mock.ANY
|
||||||
vol_name = common._get_3par_vol_name(src_vref['id'])
|
vol_name = common._get_3par_vol_name(src_vref['id'])
|
||||||
|
optional = mock.ANY
|
||||||
|
|
||||||
expected = [
|
expected = [
|
||||||
mock.call.getVolumeMetaData(vol_name,
|
mock.call.getVolumeMetaData(vol_name,
|
||||||
'HPQ-cinder-CHAP-name'),
|
'HPQ-cinder-CHAP-name'),
|
||||||
|
mock.call.createSnapshot(snap_name, vol_name, optional),
|
||||||
|
mock.call.getVolume(snap_name),
|
||||||
mock.call.copyVolume(
|
mock.call.copyVolume(
|
||||||
self.VOLUME_NAME_3PAR,
|
snap_name,
|
||||||
'osv-0DM4qZEVSKON-AAAAAAAAA',
|
'osv-0DM4qZEVSKON-AAAAAAAAA',
|
||||||
HPE3PAR_CPG2,
|
HPE3PAR_CPG2,
|
||||||
{'snapCPG': 'OpenStackCPGSnap', 'tpvv': True,
|
{'snapCPG': 'OpenStackCPGSnap', 'tpvv': True,
|
||||||
@@ -2553,11 +2590,18 @@ class HPE3PARBaseDriver(object):
|
|||||||
volume['source_volid'] = HPE3PARBaseDriver.CLONE_ID
|
volume['source_volid'] = HPE3PARBaseDriver.CLONE_ID
|
||||||
model_update = self.driver.create_cloned_volume(volume, src_vref)
|
model_update = self.driver.create_cloned_volume(volume, src_vref)
|
||||||
self.assertIsNone(model_update)
|
self.assertIsNone(model_update)
|
||||||
|
# creation of the temp snapshot
|
||||||
|
common = hpecommon.HPE3PARCommon(None)
|
||||||
|
snap_name = mock.ANY
|
||||||
|
vol_name = common._get_3par_vol_name(src_vref['id'])
|
||||||
|
optional = mock.ANY
|
||||||
|
|
||||||
expected = [
|
expected = [
|
||||||
mock.call.getCPG(expected_cpg),
|
mock.call.getCPG(expected_cpg),
|
||||||
|
mock.call.createSnapshot(snap_name, vol_name, optional),
|
||||||
|
mock.call.getVolume(snap_name),
|
||||||
mock.call.copyVolume(
|
mock.call.copyVolume(
|
||||||
'osv-0DM4qZEVSKON-AAAAAAAAA',
|
snap_name,
|
||||||
self.VOLUME_3PAR_NAME,
|
self.VOLUME_3PAR_NAME,
|
||||||
expected_cpg,
|
expected_cpg,
|
||||||
{'snapCPG': 'OpenStackCPGSnap', 'tpvv': True,
|
{'snapCPG': 'OpenStackCPGSnap', 'tpvv': True,
|
||||||
|
@@ -261,10 +261,12 @@ class HPE3PARCommon(object):
|
|||||||
3.0.34 - Add cloned volume to vvset in online copy. bug #1664464
|
3.0.34 - Add cloned volume to vvset in online copy. bug #1664464
|
||||||
3.0.35 - Add volume to consistency group if flag enabled. bug #1702317
|
3.0.35 - Add volume to consistency group if flag enabled. bug #1702317
|
||||||
3.0.36 - Swap volume name in migration. bug #1699733
|
3.0.36 - Swap volume name in migration. bug #1699733
|
||||||
|
3.0.37 - Fixed image cache enabled capability. bug #1686985
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
VERSION = "3.0.36"
|
VERSION = "3.0.37"
|
||||||
|
|
||||||
stats = {}
|
stats = {}
|
||||||
|
|
||||||
@@ -2151,6 +2153,7 @@ class HPE3PARCommon(object):
|
|||||||
LOG.debug("Creating a clone of volume, using online copy.")
|
LOG.debug("Creating a clone of volume, using online copy.")
|
||||||
|
|
||||||
type_info = self.get_volume_settings_from_type(volume)
|
type_info = self.get_volume_settings_from_type(volume)
|
||||||
|
snapshot = self._create_temp_snapshot(src_vref)
|
||||||
cpg = type_info['cpg']
|
cpg = type_info['cpg']
|
||||||
qos = type_info['qos']
|
qos = type_info['qos']
|
||||||
vvs_name = type_info['vvs_name']
|
vvs_name = type_info['vvs_name']
|
||||||
@@ -2161,7 +2164,7 @@ class HPE3PARCommon(object):
|
|||||||
type_info['hpe3par_keys'])
|
type_info['hpe3par_keys'])
|
||||||
# make the 3PAR copy the contents.
|
# make the 3PAR copy the contents.
|
||||||
# can't delete the original until the copy is done.
|
# can't delete the original until the copy is done.
|
||||||
self._copy_volume(src_vol_name, vol_name, cpg=cpg,
|
self._copy_volume(snapshot['name'], vol_name, cpg=cpg,
|
||||||
snap_cpg=type_info['snap_cpg'],
|
snap_cpg=type_info['snap_cpg'],
|
||||||
tpvv=type_info['tpvv'],
|
tpvv=type_info['tpvv'],
|
||||||
tdvv=type_info['tdvv'],
|
tdvv=type_info['tdvv'],
|
||||||
@@ -3054,10 +3057,32 @@ class HPE3PARCommon(object):
|
|||||||
'new_type': new_type,
|
'new_type': new_type,
|
||||||
'diff': diff,
|
'diff': diff,
|
||||||
'host': host})
|
'host': host})
|
||||||
|
self.remove_temporary_snapshots(volume)
|
||||||
old_volume_settings = self.get_volume_settings_from_type(volume, host)
|
old_volume_settings = self.get_volume_settings_from_type(volume, host)
|
||||||
return self._retype_from_old_to_new(volume, new_type,
|
return self._retype_from_old_to_new(volume, new_type,
|
||||||
old_volume_settings, host)
|
old_volume_settings, host)
|
||||||
|
|
||||||
|
def remove_temporary_snapshots(self, volume):
|
||||||
|
vol_name = self._get_3par_vol_name(volume['id'])
|
||||||
|
snapshots_list = self.client.getVolumeSnapshots(vol_name)
|
||||||
|
tmp_snapshots_list = [snap
|
||||||
|
for snap in snapshots_list
|
||||||
|
if snap.startswith('tss-')]
|
||||||
|
LOG.debug("temporary snapshot list %(name)s",
|
||||||
|
{'name': tmp_snapshots_list})
|
||||||
|
for temp_snap in tmp_snapshots_list:
|
||||||
|
LOG.debug("Found a temporary snapshot %(name)s",
|
||||||
|
{'name': temp_snap})
|
||||||
|
try:
|
||||||
|
self.client.deleteVolume(temp_snap)
|
||||||
|
except hpeexceptions.HTTPNotFound:
|
||||||
|
# if the volume is gone, it's as good as a
|
||||||
|
# successful delete
|
||||||
|
pass
|
||||||
|
except Exception:
|
||||||
|
msg = _("Volume has a temporary snapshot.")
|
||||||
|
raise exception.VolumeIsBusy(message=msg)
|
||||||
|
|
||||||
def find_existing_vlun(self, volume, host):
|
def find_existing_vlun(self, volume, host):
|
||||||
"""Finds an existing VLUN for a volume on a host.
|
"""Finds an existing VLUN for a volume on a host.
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user