[Pure Storage] Remove all REST version checks
Enforce a minimum FlashArray Purity version that will make all REST version checking renudant as the enforced minimum version supports all the features that are currently version-gated. Remove any code that checks for different REST responses based on REST response due to old REST code. Enforced minimum Purity version matches the minimum supported Purity version for FlashArray as of December 2021. No change required to the purestorage pypi package used by this driver. Change-Id: I9fd03186b77ca442b62b1bfa28eed9026d91949b
This commit is contained in:
parent
f2620a1fe4
commit
8bb216dc16
@ -582,7 +582,6 @@ class PureDriverTestCase(test.TestCase):
|
||||
self.async_array2.get.return_value = GET_ARRAY_SECONDARY
|
||||
self.async_array2.replication_type = 'async'
|
||||
self.purestorage_module = pure.purestorage
|
||||
self.purestorage_module.VERSION = '1.4.0'
|
||||
self.purestorage_module.PureHTTPError = FakePureStorageHTTPError
|
||||
|
||||
def fake_get_array(self, *args, **kwargs):
|
||||
@ -627,15 +626,7 @@ class PureBaseSharedDriverTestCase(PureDriverTestCase):
|
||||
self.driver._array = self.array
|
||||
self.driver._replication_pod_name = 'cinder-pod'
|
||||
self.driver._replication_pg_name = 'cinder-group'
|
||||
self.array._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
self.purestorage_module.FlashArray.side_effect = None
|
||||
self.async_array2._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
|
||||
def new_fake_vol(self, set_provider_id=True, fake_context=None,
|
||||
spec=None, type_extra_specs=None, type_qos_specs_id=None,
|
||||
@ -808,10 +799,6 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
]
|
||||
mock_target = mock.MagicMock()
|
||||
mock_target.get.return_value = GET_ARRAY_PRIMARY
|
||||
mock_target._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
|
||||
self.purestorage_module.FlashArray.return_value = mock_target
|
||||
self.driver.parse_replication_configs()
|
||||
@ -848,10 +835,6 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
]
|
||||
mock_target = mock.MagicMock()
|
||||
mock_target.get.return_value = GET_ARRAY_PRIMARY
|
||||
mock_target._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
|
||||
self.purestorage_module.FlashArray.return_value = mock_target
|
||||
self.driver.parse_replication_configs()
|
||||
@ -912,15 +895,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
]
|
||||
mock_sync_target = mock.MagicMock()
|
||||
mock_sync_target.get.return_value = GET_ARRAY_SECONDARY
|
||||
mock_sync_target._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
self.array.get.return_value = GET_ARRAY_PRIMARY
|
||||
self.array._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
self.purestorage_module.FlashArray.side_effect = [self.array,
|
||||
mock_sync_target]
|
||||
self.driver.do_setup(None)
|
||||
@ -1287,10 +1262,6 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
vol, vol_name = self.new_fake_vol(type_extra_specs=type_spec)
|
||||
self.array.list_volume_private_connections.return_value = []
|
||||
# Set the array to be in a sync-rep enabled version
|
||||
self.array._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
|
||||
self.driver.delete_volume(vol)
|
||||
|
||||
@ -1330,14 +1301,9 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
]
|
||||
|
||||
# Set the array to be in a sync-rep enabled version
|
||||
self.array._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
|
||||
self.driver.delete_volume(vol)
|
||||
expected = [
|
||||
mock.call._list_available_rest_versions(),
|
||||
mock.call.list_volume_private_connections(vol_name, remote=True),
|
||||
mock.call.disconnect_host(host_name_a, vol_name),
|
||||
mock.call.list_host_connections(host_name_a, private=True),
|
||||
@ -2203,14 +2169,6 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
self.driver.manage_existing_snapshot,
|
||||
snap, snap_ref)
|
||||
|
||||
def test_manage_existing_snapshot_bad_api_version(self):
|
||||
self.array._list_available_rest_versions.return_value = ['1.0', '1.1',
|
||||
'1.2']
|
||||
snap, _ = self.new_fake_snap()
|
||||
self.assertRaises(pure.PureDriverException,
|
||||
self.driver.manage_existing_snapshot,
|
||||
snap, {'name': PURE_SNAPSHOT['name']})
|
||||
|
||||
def test_manage_existing_snapshot_get_size(self):
|
||||
ref_name = PURE_SNAPSHOT['name']
|
||||
snap_ref = {'name': ref_name}
|
||||
@ -2262,14 +2220,6 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
self.driver.manage_existing_snapshot_get_size,
|
||||
snap, {'name': 'non-existing-volume.snap1'})
|
||||
|
||||
def test_manage_existing_snapshot_get_size_bad_api_version(self):
|
||||
snap, _ = self.new_fake_snap()
|
||||
self.array._list_available_rest_versions.return_value = ['1.0', '1.1',
|
||||
'1.2']
|
||||
self.assertRaises(pure.PureDriverException,
|
||||
self.driver.manage_existing_snapshot_get_size,
|
||||
snap, {'name': PURE_SNAPSHOT['name']})
|
||||
|
||||
@ddt.data(
|
||||
# 96 chars, will exceed allowable length
|
||||
'volume-1e5177e7-95e5-4a0f-b170-e45f4b469f6a-cinder.'
|
||||
@ -2312,14 +2262,6 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
self.array.rename_volume.assert_called_with(snap_name,
|
||||
unmanaged_snap_name)
|
||||
|
||||
def test_unmanage_snapshot_bad_api_version(self):
|
||||
snap, _ = self.new_fake_snap()
|
||||
self.array._list_available_rest_versions.return_value = ['1.0', '1.1',
|
||||
'1.2']
|
||||
self.assertRaises(pure.PureDriverException,
|
||||
self.driver.unmanage_snapshot,
|
||||
snap)
|
||||
|
||||
def _test_get_manageable_things(self,
|
||||
pure_objs=MANAGEABLE_PURE_VOLS,
|
||||
expected_refs=MANAGEABLE_PURE_VOL_REFS,
|
||||
@ -2922,12 +2864,11 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
self.async_array2.backend_id = secondary_device_id
|
||||
self.driver._replication_target_arrays = [self.async_array2]
|
||||
|
||||
array2_v1_3 = mock.Mock()
|
||||
array2_v1_3.backend_id = secondary_device_id
|
||||
array2_v1_3.array_name = GET_ARRAY_SECONDARY['array_name']
|
||||
array2_v1_3.array_id = GET_ARRAY_SECONDARY['id']
|
||||
array2_v1_3.version = '1.3'
|
||||
mock_get_array.return_value = array2_v1_3
|
||||
array2 = mock.Mock()
|
||||
array2.backend_id = secondary_device_id
|
||||
array2.array_name = GET_ARRAY_SECONDARY['array_name']
|
||||
array2.array_id = GET_ARRAY_SECONDARY['id']
|
||||
mock_get_array.return_value = array2
|
||||
|
||||
target_array = self.async_array2
|
||||
target_array.copy_volume = mock.Mock()
|
||||
@ -2937,7 +2878,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
REPLICATED_PGSNAPS[1]
|
||||
)
|
||||
|
||||
array2_v1_3.get_volume.return_value = REPLICATED_VOLUME_SNAPS
|
||||
array2.get_volume.return_value = REPLICATED_VOLUME_SNAPS
|
||||
|
||||
context = mock.MagicMock()
|
||||
new_active_id, volume_updates, __ = self.driver.failover_host(
|
||||
@ -3070,17 +3011,16 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
REPLICATED_PGSNAPS[1]
|
||||
)
|
||||
|
||||
array2_v1_3 = mock.Mock()
|
||||
array2_v1_3.array_name = GET_ARRAY_SECONDARY['array_name']
|
||||
array2_v1_3.array_id = GET_ARRAY_SECONDARY['id']
|
||||
array2_v1_3.version = '1.3'
|
||||
mock_get_array.return_value = array2_v1_3
|
||||
array2 = mock.Mock()
|
||||
array2.array_name = GET_ARRAY_SECONDARY['array_name']
|
||||
array2.array_id = GET_ARRAY_SECONDARY['id']
|
||||
mock_get_array.return_value = array2
|
||||
|
||||
array2_v1_3.get_volume.return_value = REPLICATED_VOLUME_SNAPS
|
||||
array2.get_volume.return_value = REPLICATED_VOLUME_SNAPS
|
||||
self.assert_error_propagates(
|
||||
[mock_find_failover_target,
|
||||
mock_get_array,
|
||||
array2_v1_3.get_volume,
|
||||
array2.get_volume,
|
||||
self.async_array2.copy_volume],
|
||||
self.driver.failover_host,
|
||||
mock.Mock(), REPLICATED_VOLUME_OBJS, None
|
||||
@ -3129,43 +3069,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
verify_https=True,
|
||||
ssl_cert=cert_path,
|
||||
user_agent=self.driver._user_agent,
|
||||
)
|
||||
|
||||
def test_get_flasharray_with_request_kwargs_success(self):
|
||||
san_ip = '1.2.3.4'
|
||||
api_token = 'abcdef'
|
||||
self.purestorage_module.FlashArray.return_value = mock.MagicMock()
|
||||
self.purestorage_module.VERSION = "1.17.0"
|
||||
|
||||
self.driver._get_flasharray(san_ip,
|
||||
api_token,
|
||||
request_kwargs={"some": "arg"})
|
||||
self.purestorage_module.FlashArray.assert_called_with(
|
||||
san_ip,
|
||||
api_token=api_token,
|
||||
rest_version=None,
|
||||
verify_https=None,
|
||||
ssl_cert=None,
|
||||
user_agent=self.driver._user_agent,
|
||||
request_kwargs={"some": "arg"}
|
||||
)
|
||||
|
||||
def test_get_flasharray_with_request_kwargs_version_too_old(self):
|
||||
san_ip = '1.2.3.4'
|
||||
api_token = 'abcdef'
|
||||
self.purestorage_module.FlashArray.return_value = mock.MagicMock()
|
||||
self.purestorage_module.VERSION = "1.10.0"
|
||||
|
||||
self.driver._get_flasharray(san_ip,
|
||||
api_token,
|
||||
request_kwargs={"some": "arg"})
|
||||
self.purestorage_module.FlashArray.assert_called_with(
|
||||
san_ip,
|
||||
api_token=api_token,
|
||||
rest_version=None,
|
||||
verify_https=None,
|
||||
ssl_cert=None,
|
||||
user_agent=self.driver._user_agent
|
||||
request_kwargs=None,
|
||||
)
|
||||
|
||||
def test_get_wwn(self):
|
||||
@ -3244,10 +3148,6 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
type_qos_specs_id=qos.id)
|
||||
|
||||
mock_get_volume_type.return_value = vol.volume_type
|
||||
self.array._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
mock_get_qos_specs.return_value = qos
|
||||
mock_get_repl_type.return_value = None
|
||||
|
||||
@ -3277,10 +3177,6 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
type_qos_specs_id=qos.id)
|
||||
|
||||
mock_get_volume_type.return_value = vol.volume_type
|
||||
self.array._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
mock_get_qos_specs.return_value = qos
|
||||
mock_get_repl_type.return_value = None
|
||||
|
||||
@ -3310,10 +3206,6 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
mock_get_volume_type.return_value = vol.volume_type
|
||||
mock_get_qos_specs.return_value = qos
|
||||
self.array.list_volume_private_connections.return_value = []
|
||||
self.array._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
|
||||
self.driver.manage_existing(vol, volume_ref)
|
||||
self.array.list_volume_private_connections.assert_called_with(ref_name)
|
||||
@ -3330,10 +3222,6 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
new_type = fake_volume.fake_volume_type_obj(mock_context)
|
||||
new_type.qos_specs_id = qos.id
|
||||
|
||||
self.array._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
get_voltype = "cinder.objects.volume_type.VolumeType.get_by_name_or_id"
|
||||
with mock.patch(get_voltype) as mock_get_vol_type:
|
||||
mock_get_vol_type.return_value = new_type
|
||||
@ -3357,10 +3245,6 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
vol, vol_name = self.new_fake_vol()
|
||||
new_type = fake_volume.fake_volume_type_obj(mock_context)
|
||||
|
||||
self.array._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
get_voltype = "cinder.objects.volume_type.VolumeType.get_by_name_or_id"
|
||||
with mock.patch(get_voltype) as mock_get_vol_type:
|
||||
mock_get_vol_type.return_value = new_type
|
||||
@ -3739,20 +3623,6 @@ class PureISCSIDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
self.mock_config.use_chap_auth = False
|
||||
self.mock_config.safe_get.return_value = 'oracle-vm-server'
|
||||
|
||||
self.array._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11']
|
||||
# Branch where we fail due to invalid version for setting personality
|
||||
self.assertRaises(pure.PureDriverException, self.driver._connect,
|
||||
self.array, vol_name, ISCSI_CONNECTOR, None, None)
|
||||
self.assertFalse(self.array.create_host.called)
|
||||
self.assertFalse(self.array.set_host.called)
|
||||
|
||||
self.array._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
|
||||
# Branch where personality is set
|
||||
self.driver._connect(self.array, vol_name, ISCSI_CONNECTOR,
|
||||
None, None)
|
||||
@ -4009,20 +3879,6 @@ class PureFCDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
self.driver._connect, self.array, vol_name, FC_CONNECTOR)
|
||||
|
||||
self.mock_config.safe_get.return_value = 'oracle-vm-server'
|
||||
self.array._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11']
|
||||
|
||||
# Branch where we fail due to invalid version for setting personality
|
||||
self.assertRaises(pure.PureDriverException, self.driver._connect,
|
||||
self.array, vol_name, FC_CONNECTOR)
|
||||
self.assertTrue(self.array.create_host.called)
|
||||
self.assertFalse(self.array.set_host.called)
|
||||
|
||||
self.array._list_available_rest_versions.return_value = [
|
||||
'1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8',
|
||||
'1.9', '1.10', '1.11', '1.12', '1.13', '1.14', '1.15', '1.16',
|
||||
'1.17', '1.18', '1.19']
|
||||
|
||||
# Branch where personality is set
|
||||
self.driver._connect(self.array, vol_name, FC_CONNECTOR)
|
||||
|
@ -137,11 +137,6 @@ EXTRA_SPECS_REPL_TYPE = "replication_type"
|
||||
MAX_VOL_LENGTH = 63
|
||||
MAX_SNAP_LENGTH = 96
|
||||
UNMANAGED_SUFFIX = '-unmanaged'
|
||||
QOS_REQUIRED_API_VERSION = '1.17'
|
||||
SYNC_REPLICATION_REQUIRED_API_VERSION = '1.13'
|
||||
ASYNC_REPLICATION_REQUIRED_API_VERSION = '1.3'
|
||||
MANAGE_SNAP_REQUIRED_API_VERSION = '1.4'
|
||||
PERSONALITY_REQUIRED_API_VERSION = '1.14'
|
||||
|
||||
REPL_SETTINGS_PROPAGATE_RETRY_INTERVAL = 5 # 5 seconds
|
||||
REPL_SETTINGS_PROPAGATE_MAX_RETRIES = 36 # 36 * 5 = 180 seconds
|
||||
@ -279,24 +274,6 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
ssl_cert_path=ssl_cert_path
|
||||
)
|
||||
|
||||
api_versions = target_array._list_available_rest_versions()
|
||||
|
||||
if repl_type == REPLICATION_TYPE_ASYNC:
|
||||
req_api_version = ASYNC_REPLICATION_REQUIRED_API_VERSION
|
||||
elif repl_type == REPLICATION_TYPE_SYNC:
|
||||
req_api_version = SYNC_REPLICATION_REQUIRED_API_VERSION
|
||||
else:
|
||||
msg = _('Invalid replication type specified:') % repl_type
|
||||
raise PureDriverException(reason=msg)
|
||||
|
||||
if req_api_version not in api_versions:
|
||||
msg = _('Unable to do replication with Purity REST '
|
||||
'API version, requires minimum of '
|
||||
'%(required_version)s.') % {
|
||||
'required_version': req_api_version
|
||||
}
|
||||
raise PureDriverException(reason=msg)
|
||||
|
||||
target_array_info = target_array.get()
|
||||
target_array.array_name = target_array_info["array_name"]
|
||||
target_array.array_id = target_array_info["id"]
|
||||
@ -378,6 +355,13 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
)
|
||||
|
||||
array_info = self._array.get()
|
||||
if version.LooseVersion(array_info["version"]) < version.LooseVersion(
|
||||
'5.3.0'
|
||||
):
|
||||
msg = _("FlashArray Purity version less than 5.3.0 unsupported."
|
||||
" Please upgrade your backend to a supported version.")
|
||||
raise PureDriverException(msg)
|
||||
|
||||
self._array.array_name = array_info["array_name"]
|
||||
self._array.array_id = array_info["id"]
|
||||
self._array.replication_type = None
|
||||
@ -484,11 +468,9 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
ctxt = context.get_admin_context()
|
||||
type_id = volume.get('volume_type_id')
|
||||
current_array = self._get_current_array()
|
||||
rest_versions = current_array._list_available_rest_versions()
|
||||
if type_id is not None:
|
||||
volume_type = volume_types.get_volume_type(ctxt, type_id)
|
||||
if QOS_REQUIRED_API_VERSION in rest_versions:
|
||||
qos = self._get_qos_settings(volume_type)
|
||||
qos = self._get_qos_settings(volume_type)
|
||||
if qos is not None:
|
||||
self.create_with_qos(current_array, vol_name, vol_size, qos)
|
||||
else:
|
||||
@ -509,11 +491,9 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
current_array = self._get_current_array()
|
||||
ctxt = context.get_admin_context()
|
||||
type_id = volume.get('volume_type_id')
|
||||
rest_versions = current_array._list_available_rest_versions()
|
||||
if type_id is not None:
|
||||
volume_type = volume_types.get_volume_type(ctxt, type_id)
|
||||
if QOS_REQUIRED_API_VERSION in rest_versions:
|
||||
qos = self._get_qos_settings(volume_type)
|
||||
qos = self._get_qos_settings(volume_type)
|
||||
|
||||
current_array.copy_volume(snap_name, vol_name)
|
||||
self._extend_if_needed(current_array,
|
||||
@ -606,16 +586,11 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
"""Disconnect all hosts and delete the volume"""
|
||||
vol_name = self._get_vol_name(volume)
|
||||
current_array = self._get_current_array()
|
||||
rest_versions = current_array._list_available_rest_versions()
|
||||
try:
|
||||
# Do a pass over remaining connections on the current array, if
|
||||
# we can try and remove any remote connections too.
|
||||
if SYNC_REPLICATION_REQUIRED_API_VERSION in rest_versions:
|
||||
hosts = current_array.list_volume_private_connections(
|
||||
vol_name, remote=True)
|
||||
else:
|
||||
hosts = current_array.list_volume_private_connections(
|
||||
vol_name)
|
||||
hosts = current_array.list_volume_private_connections(
|
||||
vol_name, remote=True)
|
||||
for host_info in hosts:
|
||||
host_name = host_info["host"]
|
||||
self._disconnect_host(current_array, host_name, vol_name)
|
||||
@ -710,18 +685,13 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
Returns True if it was the hosts last connection.
|
||||
"""
|
||||
vol_name = self._get_vol_name(volume)
|
||||
rest_versions = array._list_available_rest_versions()
|
||||
if connector is None:
|
||||
# If no connector was provided it is a force-detach, remove all
|
||||
# host connections for the volume
|
||||
LOG.warning("Removing ALL host connections for volume %s",
|
||||
vol_name)
|
||||
if SYNC_REPLICATION_REQUIRED_API_VERSION in rest_versions:
|
||||
# Remote connections are only allowed in newer API versions
|
||||
connections = array.list_volume_private_connections(
|
||||
vol_name, remote=True)
|
||||
else:
|
||||
connections = array.list_volume_private_connections(vol_name)
|
||||
connections = array.list_volume_private_connections(
|
||||
vol_name, remote=True)
|
||||
|
||||
for connection in connections:
|
||||
self._disconnect_host(array, connection['host'], vol_name)
|
||||
@ -1332,15 +1302,13 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
# Check if the volume_type has QoS settings and if so
|
||||
# apply them to the newly managed volume
|
||||
qos = None
|
||||
rest_versions = current_array._list_available_rest_versions()
|
||||
if QOS_REQUIRED_API_VERSION in rest_versions:
|
||||
qos = self._get_qos_settings(volume.volume_type)
|
||||
if qos is not None:
|
||||
self.set_qos(current_array, new_vol_name, qos)
|
||||
else:
|
||||
current_array.set_volume(new_vol_name,
|
||||
iops_limit='',
|
||||
bandwidth_limit='')
|
||||
qos = self._get_qos_settings(volume.volume_type)
|
||||
if qos is not None:
|
||||
self.set_qos(current_array, new_vol_name, qos)
|
||||
else:
|
||||
current_array.set_volume(new_vol_name,
|
||||
iops_limit='',
|
||||
bandwidth_limit='')
|
||||
volume.provider_id = new_vol_name
|
||||
async_enabled = self._enable_async_replication_if_needed(current_array,
|
||||
volume)
|
||||
@ -1400,24 +1368,12 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
{"ref_name": vol_name, "new_name": unmanaged_vol_name})
|
||||
self._rename_volume_object(vol_name, unmanaged_vol_name)
|
||||
|
||||
def _verify_manage_snap_api_requirements(self):
|
||||
current_array = self._get_current_array()
|
||||
rest_versions = current_array._list_available_rest_versions()
|
||||
if MANAGE_SNAP_REQUIRED_API_VERSION not in rest_versions:
|
||||
msg = _('Unable to do manage snapshot operations with Purity REST '
|
||||
'API version, requires '
|
||||
'%(required_version)s.') % {
|
||||
'required_version': MANAGE_SNAP_REQUIRED_API_VERSION
|
||||
}
|
||||
raise PureDriverException(reason=msg)
|
||||
|
||||
def manage_existing_snapshot(self, snapshot, existing_ref):
|
||||
"""Brings an existing backend storage object under Cinder management.
|
||||
|
||||
We expect a snapshot name in the existing_ref that matches one in
|
||||
Purity.
|
||||
"""
|
||||
self._verify_manage_snap_api_requirements()
|
||||
self._validate_manage_existing_ref(existing_ref, is_snap=True)
|
||||
ref_snap_name = existing_ref['name']
|
||||
new_snap_name = self._get_snap_name(snapshot)
|
||||
@ -1435,7 +1391,6 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
We expect a snapshot name in the existing_ref that matches one in
|
||||
Purity.
|
||||
"""
|
||||
self._verify_manage_snap_api_requirements()
|
||||
snap_info = self._validate_manage_existing_ref(existing_ref,
|
||||
is_snap=True)
|
||||
size = self._round_bytes_to_gib(snap_info['size'])
|
||||
@ -1449,7 +1404,6 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
We expect a snapshot name in the existing_ref that matches one in
|
||||
Purity.
|
||||
"""
|
||||
self._verify_manage_snap_api_requirements()
|
||||
snap_name = self._get_snap_name(snapshot)
|
||||
if len(snap_name + UNMANAGED_SUFFIX) > MAX_SNAP_LENGTH:
|
||||
unmanaged_snap_name = snap_name[:-len(UNMANAGED_SUFFIX)] + \
|
||||
@ -1573,28 +1527,13 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
verify_https=None, ssl_cert_path=None,
|
||||
request_kwargs=None):
|
||||
|
||||
if (version.LooseVersion(purestorage.VERSION) <
|
||||
version.LooseVersion('1.17.0')):
|
||||
if request_kwargs is not None:
|
||||
LOG.warning("Unable to specify request_kwargs='%s' on "
|
||||
"purestorage.FlashArray using 'purestorage' "
|
||||
"python module <1.17.0. Current version: %s",
|
||||
request_kwargs,
|
||||
purestorage.VERSION)
|
||||
array = purestorage.FlashArray(san_ip,
|
||||
api_token=api_token,
|
||||
rest_version=rest_version,
|
||||
verify_https=verify_https,
|
||||
ssl_cert=ssl_cert_path,
|
||||
user_agent=self._user_agent)
|
||||
else:
|
||||
array = purestorage.FlashArray(san_ip,
|
||||
api_token=api_token,
|
||||
rest_version=rest_version,
|
||||
verify_https=verify_https,
|
||||
ssl_cert=ssl_cert_path,
|
||||
user_agent=self._user_agent,
|
||||
request_kwargs=request_kwargs)
|
||||
array = purestorage.FlashArray(san_ip,
|
||||
api_token=api_token,
|
||||
rest_version=rest_version,
|
||||
verify_https=verify_https,
|
||||
ssl_cert=ssl_cert_path,
|
||||
user_agent=self._user_agent,
|
||||
request_kwargs=request_kwargs)
|
||||
array_info = array.get()
|
||||
array.array_name = array_info["array_name"]
|
||||
array.array_id = array_info["id"]
|
||||
@ -1928,16 +1867,14 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
# make sure the volume gets the correct new QoS settings.
|
||||
# This could mean removing existing QoS settings.
|
||||
current_array = self._get_current_array()
|
||||
rest_versions = current_array._list_available_rest_versions()
|
||||
if QOS_REQUIRED_API_VERSION in rest_versions:
|
||||
qos = self._get_qos_settings(new_type)
|
||||
vol_name = self._generate_purity_vol_name(volume)
|
||||
if qos is not None:
|
||||
self.set_qos(current_array, vol_name, qos)
|
||||
else:
|
||||
current_array.set_volume(vol_name,
|
||||
iops_limit='',
|
||||
bandwidth_limit='')
|
||||
qos = self._get_qos_settings(new_type)
|
||||
vol_name = self._generate_purity_vol_name(volume)
|
||||
if qos is not None:
|
||||
self.set_qos(current_array, vol_name, qos)
|
||||
else:
|
||||
current_array.set_volume(vol_name,
|
||||
iops_limit='',
|
||||
bandwidth_limit='')
|
||||
|
||||
return True, model_update
|
||||
|
||||
@ -2078,23 +2015,6 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
|
||||
return secondary_array.backend_id, model_updates, []
|
||||
|
||||
@pure_driver_debug_trace
|
||||
def get_check_personality(self, array):
|
||||
personality = self.configuration.safe_get('pure_host_personality')
|
||||
rest_versions = array._list_available_rest_versions()
|
||||
if personality:
|
||||
if PERSONALITY_REQUIRED_API_VERSION not in rest_versions:
|
||||
# Continuing here would mean creating a host not according
|
||||
# to specificiations, possibly leading to unexpected
|
||||
# behavior later on.
|
||||
msg = _('Unable to set host personality with Purity REST '
|
||||
'API version, requires '
|
||||
'%(required_version)s.') % {
|
||||
'required_version': PERSONALITY_REQUIRED_API_VERSION
|
||||
}
|
||||
raise PureDriverException(reason=msg)
|
||||
return personality
|
||||
|
||||
@pure_driver_debug_trace
|
||||
def set_personality(self, array, host_name, personality):
|
||||
try:
|
||||
@ -2446,28 +2366,12 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
return secondary_array
|
||||
|
||||
def _async_failover_host(self, volumes, secondary_array, pg_snap):
|
||||
# NOTE(patrickeast): This currently requires a call with REST API 1.3.
|
||||
# If we need to, create a temporary FlashArray for this operation.
|
||||
api_version = secondary_array.get_rest_version()
|
||||
LOG.debug("Current REST API for array id %(id)s is %(api_version)s",
|
||||
{"id": secondary_array.array_id, "api_version": api_version})
|
||||
if api_version != '1.3':
|
||||
# Try to copy the flasharray as close as we can..
|
||||
if hasattr(secondary_array, '_request_kwargs'):
|
||||
target_array = self._get_flasharray(
|
||||
secondary_array._target,
|
||||
api_token=secondary_array._api_token,
|
||||
rest_version='1.3',
|
||||
request_kwargs=secondary_array._request_kwargs,
|
||||
)
|
||||
else:
|
||||
target_array = self._get_flasharray(
|
||||
secondary_array._target,
|
||||
api_token=secondary_array._api_token,
|
||||
rest_version='1.3',
|
||||
)
|
||||
else:
|
||||
target_array = secondary_array
|
||||
# Try to copy the flasharray as close as we can.
|
||||
target_array = self._get_flasharray(
|
||||
secondary_array._target,
|
||||
api_token=secondary_array._api_token,
|
||||
request_kwargs=secondary_array._request_kwargs,
|
||||
)
|
||||
|
||||
volume_snaps = target_array.get_volume(pg_snap['name'],
|
||||
snap=True,
|
||||
@ -2579,11 +2483,7 @@ class PureISCSIDriver(PureBaseVolumeDriver, san.SanISCSIDriver):
|
||||
|
||||
def _get_host(self, array, connector, remote=False):
|
||||
"""Return dict describing existing Purity host object or None."""
|
||||
rest_versions = array._list_available_rest_versions()
|
||||
if remote and SYNC_REPLICATION_REQUIRED_API_VERSION in rest_versions:
|
||||
hosts = array.list_hosts(remote=True)
|
||||
else:
|
||||
hosts = array.list_hosts()
|
||||
hosts = array.list_hosts(remote=remote)
|
||||
matching_hosts = []
|
||||
for host in hosts:
|
||||
if connector["initiator"] in host["iqn"]:
|
||||
@ -2746,7 +2646,7 @@ class PureISCSIDriver(PureBaseVolumeDriver, san.SanISCSIDriver):
|
||||
reason=_("Unable to re-use host with unknown CHAP "
|
||||
"credentials configured."))
|
||||
else:
|
||||
personality = self.get_check_personality(array)
|
||||
personality = self.configuration.safe_get('pure_host_personality')
|
||||
host_name = self._generate_purity_host_name(connector["host"])
|
||||
LOG.info("Creating host object %(host_name)r with IQN:"
|
||||
" %(iqn)s.", {"host_name": host_name, "iqn": iqn})
|
||||
@ -2806,11 +2706,7 @@ class PureFCDriver(PureBaseVolumeDriver, driver.FibreChannelDriver):
|
||||
|
||||
def _get_host(self, array, connector, remote=False):
|
||||
"""Return dict describing existing Purity host object or None."""
|
||||
rest_versions = array._list_available_rest_versions()
|
||||
if remote and SYNC_REPLICATION_REQUIRED_API_VERSION in rest_versions:
|
||||
hosts = array.list_hosts(remote=True)
|
||||
else:
|
||||
hosts = array.list_hosts()
|
||||
hosts = array.list_hosts(remote=remote)
|
||||
matching_hosts = []
|
||||
for host in hosts:
|
||||
for wwn in connector["wwpns"]:
|
||||
@ -2821,18 +2717,18 @@ class PureFCDriver(PureBaseVolumeDriver, driver.FibreChannelDriver):
|
||||
|
||||
@staticmethod
|
||||
def _get_array_wwns(array):
|
||||
"""Return list of wwns from the array"""
|
||||
"""Return list of wwns from the array
|
||||
|
||||
Ensure that only true scsi FC ports are selected
|
||||
and not any that are enabled for NVMe-based FC with
|
||||
an associated NQN.
|
||||
"""
|
||||
ports = array.list_ports()
|
||||
try:
|
||||
valid_ports = [
|
||||
port["wwn"]
|
||||
for port in ports
|
||||
if port["wwn"] and not port["nqn"]
|
||||
]
|
||||
except KeyError: # Older array code versions will not return nqn
|
||||
valid_ports = [
|
||||
port["wwn"] for port in ports if port["wwn"]
|
||||
]
|
||||
valid_ports = [
|
||||
port["wwn"]
|
||||
for port in ports
|
||||
if port["wwn"] and not port["nqn"]
|
||||
]
|
||||
return valid_ports
|
||||
|
||||
@pure_driver_debug_trace
|
||||
@ -2888,7 +2784,7 @@ class PureFCDriver(PureBaseVolumeDriver, driver.FibreChannelDriver):
|
||||
LOG.info("Re-using existing purity host %(host_name)r",
|
||||
{"host_name": host_name})
|
||||
else:
|
||||
personality = self.get_check_personality(array)
|
||||
personality = self.configuration.safe_get('pure_host_personality')
|
||||
host_name = self._generate_purity_host_name(connector["host"])
|
||||
LOG.info("Creating host object %(host_name)r with WWN:"
|
||||
" %(wwn)s.", {"host_name": host_name, "wwn": wwns})
|
||||
|
@ -0,0 +1,16 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
Pure Storage: Minimum supported FlashArray Purity//FA is changed to 5.3.0.
|
||||
All FlashArray backends must be at at least this minimum version or the
|
||||
driver will not initialize.
|
||||
fixes:
|
||||
- |
|
||||
Pure Storage: Remove all API version checks in driver as the new minimum
|
||||
FlashArray Purity//FA version supports all previously version-gated
|
||||
features and functionality support.
|
||||
other:
|
||||
- |
|
||||
Pure Storage: FlashArray minimum Purity//FA version is increased to 5.3.0.
|
||||
All FlashArray backends must be at at least this minimum version or the
|
||||
driver will not initialize.
|
Loading…
Reference in New Issue
Block a user