[Pure Storage] Manage Volume from GUI fails

Using the command line for volume management works with no issue, as the
method requires specifying ``id-type name``.

When using the GUI the selection of ``name`` as the ID Type actually
translates to ``source-name``, which seems to be the default value.

This patch changes references in the Pure Storage driver from ``name``
to ``source-name``.

This also means that using the CLI no longer requires the specific
selection of ``id-type name`` as the default value can now be used.

Closes-Bug: #2096801

Change-Id: I804ab5a88496b1da82c45ccabdb0fe175aacfbfb
This commit is contained in:
Simon Dodsley 2025-01-27 15:10:56 -05:00
parent 651bb41689
commit f0562c9bb0
3 changed files with 40 additions and 31 deletions

View File

@ -2712,7 +2712,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
@mock.patch(BASE_DRIVER_OBJ + "._rename_volume_object")
def test_manage_existing(self, mock_rename):
ref_name = 'vol1'
volume_ref = {'name': ref_name}
volume_ref = {'source-name': ref_name}
self.array.get_volumes.return_value = MPV
self.array.get_connections.return_value = []
vol, vol_name = self.new_fake_vol(set_provider_id=False)
@ -2730,7 +2730,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
self.assert_error_propagates(
[mock_rename, mock_validate],
self.driver.manage_existing,
vol, {'name': 'vol1'}
vol, {'source-name': 'vol1'}
)
def test_manage_existing_bad_ref(self):
@ -2741,15 +2741,15 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
self.assertRaises(exception.ManageExistingInvalidReference,
self.driver.manage_existing,
vol, {'name': ''})
vol, {'source-name': ''})
self.assertRaises(exception.ManageExistingInvalidReference,
self.driver.manage_existing,
vol, {'name': None})
vol, {'source-name': None})
def test_manage_existing_sync_repl_type(self):
ref_name = 'vol1'
volume_ref = {'name': ref_name}
volume_ref = {'source-name': ref_name}
type_spec = {
'replication_type': '<in> sync',
'replication_enabled': '<is> true',
@ -2764,7 +2764,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
def test_manage_existing_vol_in_pod(self):
ref_name = 'somepod::vol1'
volume_ref = {'name': ref_name}
volume_ref = {'source-name': ref_name}
self.array.get_connections.return_value = []
vol, vol_name = self.new_fake_vol(set_provider_id=False)
@ -2783,12 +2783,12 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
[DotNotation(cvol[0])], {})
self.assertRaises(exception.ManageExistingInvalidReference,
self.driver.manage_existing,
vol, {'name': ref_name})
vol, {'source-name': ref_name})
self.assertFalse(mock_rename.called)
def test_manage_existing_get_size(self):
ref_name = 'vol1'
volume_ref = {'name': ref_name}
volume_ref = {'source-name': ref_name}
expected_size = 3
self.array.get_volumes.return_value = MPV
vol, _ = self.new_fake_vol(set_provider_id=False)
@ -2804,7 +2804,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
vol, _ = self.new_fake_vol(set_provider_id=False)
self.assert_error_propagates([mock_validate],
self.driver.manage_existing_get_size,
vol, {'name': 'vol1'})
vol, {'source-name': 'vol1'})
def test_manage_existing_get_size_bad_ref(self):
vol, _ = self.new_fake_vol(set_provider_id=False)
@ -2814,11 +2814,11 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
self.assertRaises(exception.ManageExistingInvalidReference,
self.driver.manage_existing_get_size,
vol, {'name': ''})
vol, {'source-name': ''})
self.assertRaises(exception.ManageExistingInvalidReference,
self.driver.manage_existing_get_size,
vol, {'name': None})
vol, {'source-name': None})
@mock.patch(BASE_DRIVER_OBJ + "._rename_volume_object")
def test_unmanage(self, mock_rename):
@ -2862,7 +2862,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
@mock.patch(BASE_DRIVER_OBJ + "._rename_volume_object")
def test_manage_existing_snapshot(self, mock_rename):
ref_name = PURE_SNAPSHOT['name']
snap_ref = {'name': ref_name}
snap_ref = {'source-name': ref_name}
snap, snap_name = self.new_fake_snap()
vol_rsp = ValidResponse(200, None, 1,
[DotNotation(PURE_SNAPSHOT)], {})
@ -2879,7 +2879,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
def test_manage_existing_snapshot_multiple_snaps_on_volume(self,
mock_rename):
ref_name = PURE_SNAPSHOT['name']
snap_ref = {'name': ref_name}
snap_ref = {'source-name': ref_name}
pure_snaps = [PURE_SNAPSHOT]
snap, snap_name = self.new_fake_snap()
for i in range(5):
@ -2902,7 +2902,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
self.assert_error_propagates(
[mock_validate],
self.driver.manage_existing_snapshot,
snap, {'name': PURE_SNAPSHOT['name']}
snap, {'source-name': PURE_SNAPSHOT['name']}
)
def test_manage_existing_snapshot_bad_ref(self):
@ -2915,13 +2915,13 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
snap, _ = self.new_fake_snap()
self.assertRaises(exception.ManageExistingInvalidReference,
self.driver.manage_existing_snapshot,
snap, {'name': ''})
snap, {'source-name': ''})
def test_manage_existing_snapshot_none_ref(self):
snap, _ = self.new_fake_snap()
self.assertRaises(exception.ManageExistingInvalidReference,
self.driver.manage_existing_snapshot,
snap, {'name': None})
snap, {'source-name': None})
def test_manage_existing_snapshot_volume_ref_not_exist(self):
snap, _ = self.new_fake_snap()
@ -2930,11 +2930,11 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
self.array.get_volumes.return_value = err_rsp
self.assertRaises(exception.ManageExistingInvalidReference,
self.driver.manage_existing_snapshot,
snap, {'name': 'non-existing-volume.snap1'})
snap, {'source-name': 'non-existing-volume.snap1'})
def test_manage_existing_snapshot_ref_not_exist(self):
ref_name = PURE_SNAPSHOT['name'] + '-fake'
snap_ref = {'name': ref_name}
snap_ref = {'source-name': ref_name}
snap, _ = self.new_fake_snap()
err_rsp = ErrorResponse(400, [DotNotation({'message':
'does not exist'})], {})
@ -2945,7 +2945,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
def test_manage_existing_snapshot_get_size(self):
ref_name = PURE_SNAPSHOT['name']
snap_ref = {'name': ref_name}
snap_ref = {'source-name': ref_name}
self.array.get_volumes.return_value = MPV
self.array.get_volume_snapshots.return_value = MPS
snap, _ = self.new_fake_snap()
@ -2977,13 +2977,13 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
snap, _ = self.new_fake_snap()
self.assertRaises(exception.ManageExistingInvalidReference,
self.driver.manage_existing_snapshot_get_size,
snap, {'name': ''})
snap, {'source-name': ''})
def test_manage_existing_snapshot_get_size_none_ref(self):
snap, _ = self.new_fake_snap()
self.assertRaises(exception.ManageExistingInvalidReference,
self.driver.manage_existing_snapshot_get_size,
snap, {'name': None})
snap, {'source-name': None})
def test_manage_existing_snapshot_get_size_volume_ref_not_exist(self):
snap, _ = self.new_fake_snap()
@ -2992,7 +2992,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
self.array.get_volumes.return_value = err_rsp
self.assertRaises(exception.ManageExistingInvalidReference,
self.driver.manage_existing_snapshot_get_size,
snap, {'name': 'non-existing-volume.snap1'})
snap, {'source-name': 'non-existing-volume.snap1'})
@ddt.data(
# 96 chars, will exceed allowable length
@ -4169,7 +4169,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
mock_qos):
ctxt = context.get_admin_context()
ref_name = 'vol1'
volume_ref = {'name': ref_name}
volume_ref = {'source-name': ref_name}
qos = qos_specs.create(ctxt, "qos-iops-bws", QOS_IOPS_BWS)
vol, vol_name = self.new_fake_vol(set_provider_id=False,
type_qos_specs_id=qos.id)

View File

@ -1484,17 +1484,19 @@ class PureBaseVolumeDriver(san.SanDriver):
Will return volume or snapshot information from the array for
the object specified by existing_ref.
"""
if "name" not in existing_ref or not existing_ref["name"]:
if ("source-name" not in existing_ref
or not existing_ref["source-name"]):
raise exception.ManageExistingInvalidReference(
existing_ref=existing_ref,
reason=_("manage_existing requires a 'name'"
reason=_("manage_existing requires a 'source-name'"
" key to identify an existing volume."))
if is_snap:
# Purity snapshot names are prefixed with the source volume name.
ref_vol_name, ref_snap_suffix = existing_ref['name'].split('.')
ref_vol_name, ref_snap_suffix = existing_ref['source-name'].split(
'.')
else:
ref_vol_name = existing_ref['name']
ref_vol_name = existing_ref['source-name']
if not is_snap and '::' in ref_vol_name:
# Don't allow for managing volumes in a pod
@ -1508,7 +1510,7 @@ class PureBaseVolumeDriver(san.SanDriver):
if volume_info:
if is_snap:
snapres = current_array.get_volume_snapshots(
names=[existing_ref['name']])
names=[existing_ref['source-name']])
if snapres.status_code == 200:
snap = list(snapres.items)[0]
return snap
@ -1528,7 +1530,8 @@ class PureBaseVolumeDriver(san.SanDriver):
# to throw an Invalid Reference exception.
raise exception.ManageExistingInvalidReference(
existing_ref=existing_ref,
reason=_("Unable to find Purity ref with name=%s") % ref_vol_name)
reason=(_("Unable to find Purity ref with source-name=%s")
% ref_vol_name))
def _add_to_group_if_needed(self, volume, vol_name):
if volume['group_id']:
@ -1695,7 +1698,7 @@ class PureBaseVolumeDriver(san.SanDriver):
self._validate_manage_existing_vol_type(volume)
self._validate_manage_existing_ref(existing_ref)
ref_vol_name = existing_ref['name']
ref_vol_name = existing_ref['source-name']
current_array = self._get_current_array()
volume_data = list(current_array.get_volumes(
names=[ref_vol_name]).items)[0]
@ -1807,7 +1810,7 @@ class PureBaseVolumeDriver(san.SanDriver):
Purity.
"""
self._validate_manage_existing_ref(existing_ref, is_snap=True)
ref_snap_name = existing_ref['name']
ref_snap_name = existing_ref['source-name']
new_snap_name = self._get_snap_name(snapshot)
LOG.info("Renaming existing snapshot %(ref_name)s to "
"%(new_name)s", {"ref_name": ref_snap_name,

View File

@ -0,0 +1,6 @@
---
fixes:
- |
Pure Storage driver `bug #2096801
<https://bugs.launchpad.net/cinder/+bug/2096801>`_: Fixed
issue using Manage Volumes from the GUI.