Merge "[Pure Storage] Remove all REST version checks"
This commit is contained in:
commit
8e3bf3af21
@ -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