[Pure Storage] Fix minimum SDK version required
Change method to check supported REST version on the backend. This will mkae it easier to specify minimum REST versions for specific feature support. Closes-Bug: #1929219 Change-Id: Ibab932d3536d44dd7414560768ed5bdeaa9e61e1
This commit is contained in:
parent
0caaa1fee5
commit
49848a7674
@ -104,7 +104,6 @@ PURE_HOST = {
|
|||||||
"iqn": [],
|
"iqn": [],
|
||||||
"wwn": [],
|
"wwn": [],
|
||||||
}
|
}
|
||||||
REST_VERSION = "1.2"
|
|
||||||
INITIATOR_IQN = "iqn.1993-08.org.debian:01:222"
|
INITIATOR_IQN = "iqn.1993-08.org.debian:01:222"
|
||||||
INITIATOR_WWN = "5001500150015081abc"
|
INITIATOR_WWN = "5001500150015081abc"
|
||||||
ISCSI_CONNECTOR = {"initiator": INITIATOR_IQN, "host": HOSTNAME}
|
ISCSI_CONNECTOR = {"initiator": INITIATOR_IQN, "host": HOSTNAME}
|
||||||
@ -626,9 +625,15 @@ class PureBaseSharedDriverTestCase(PureDriverTestCase):
|
|||||||
self.driver._array = self.array
|
self.driver._array = self.array
|
||||||
self.driver._replication_pod_name = 'cinder-pod'
|
self.driver._replication_pod_name = 'cinder-pod'
|
||||||
self.driver._replication_pg_name = 'cinder-group'
|
self.driver._replication_pg_name = 'cinder-group'
|
||||||
self.array.get_rest_version.return_value = '1.4'
|
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.purestorage_module.FlashArray.side_effect = None
|
||||||
self.async_array2.get_rest_version.return_value = '1.4'
|
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,
|
def new_fake_vol(self, set_provider_id=True, fake_context=None,
|
||||||
spec=None, type_extra_specs=None, type_qos_specs_id=None,
|
spec=None, type_extra_specs=None, type_qos_specs_id=None,
|
||||||
@ -801,7 +806,10 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
]
|
]
|
||||||
mock_target = mock.MagicMock()
|
mock_target = mock.MagicMock()
|
||||||
mock_target.get.return_value = GET_ARRAY_PRIMARY
|
mock_target.get.return_value = GET_ARRAY_PRIMARY
|
||||||
mock_target.get_rest_version.return_value = '1.14'
|
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.purestorage_module.FlashArray.return_value = mock_target
|
||||||
self.driver.parse_replication_configs()
|
self.driver.parse_replication_configs()
|
||||||
@ -838,7 +846,10 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
]
|
]
|
||||||
mock_target = mock.MagicMock()
|
mock_target = mock.MagicMock()
|
||||||
mock_target.get.return_value = GET_ARRAY_PRIMARY
|
mock_target.get.return_value = GET_ARRAY_PRIMARY
|
||||||
mock_target.get_rest_version.return_value = '1.14'
|
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.purestorage_module.FlashArray.return_value = mock_target
|
||||||
self.driver.parse_replication_configs()
|
self.driver.parse_replication_configs()
|
||||||
@ -899,9 +910,15 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
]
|
]
|
||||||
mock_sync_target = mock.MagicMock()
|
mock_sync_target = mock.MagicMock()
|
||||||
mock_sync_target.get.return_value = GET_ARRAY_SECONDARY
|
mock_sync_target.get.return_value = GET_ARRAY_SECONDARY
|
||||||
mock_sync_target.get_rest_version.return_value = '1.14'
|
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.get.return_value = GET_ARRAY_PRIMARY
|
||||||
self.array.get_rest_version.return_value = '1.14'
|
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,
|
self.purestorage_module.FlashArray.side_effect = [self.array,
|
||||||
mock_sync_target]
|
mock_sync_target]
|
||||||
self.driver.do_setup(None)
|
self.driver.do_setup(None)
|
||||||
@ -1251,7 +1268,8 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
}]
|
}]
|
||||||
|
|
||||||
self.driver.delete_volume(vol)
|
self.driver.delete_volume(vol)
|
||||||
expected = [mock.call.list_volume_private_connections(vol_name),
|
expected = [mock.call.list_volume_private_connections(vol_name,
|
||||||
|
remote=True),
|
||||||
mock.call.disconnect_host(host_name_a, vol_name),
|
mock.call.disconnect_host(host_name_a, vol_name),
|
||||||
mock.call.list_host_connections(host_name_a, private=True),
|
mock.call.list_host_connections(host_name_a, private=True),
|
||||||
mock.call.disconnect_host(host_name_b, vol_name),
|
mock.call.disconnect_host(host_name_b, vol_name),
|
||||||
@ -1267,7 +1285,10 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
vol, vol_name = self.new_fake_vol(type_extra_specs=type_spec)
|
vol, vol_name = self.new_fake_vol(type_extra_specs=type_spec)
|
||||||
self.array.list_volume_private_connections.return_value = []
|
self.array.list_volume_private_connections.return_value = []
|
||||||
# Set the array to be in a sync-rep enabled version
|
# Set the array to be in a sync-rep enabled version
|
||||||
self.array.get_rest_version.return_value = "1.14"
|
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)
|
self.driver.delete_volume(vol)
|
||||||
|
|
||||||
@ -1307,11 +1328,14 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Set the array to be in a sync-rep enabled version
|
# Set the array to be in a sync-rep enabled version
|
||||||
self.array.get_rest_version.return_value = "1.14"
|
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)
|
self.driver.delete_volume(vol)
|
||||||
expected = [
|
expected = [
|
||||||
mock.call.get_rest_version(),
|
mock.call._list_available_rest_versions(),
|
||||||
mock.call.list_volume_private_connections(vol_name, remote=True),
|
mock.call.list_volume_private_connections(vol_name, remote=True),
|
||||||
mock.call.disconnect_host(host_name_a, vol_name),
|
mock.call.disconnect_host(host_name_a, vol_name),
|
||||||
mock.call.list_host_connections(host_name_a, private=True),
|
mock.call.list_host_connections(host_name_a, private=True),
|
||||||
@ -2180,7 +2204,8 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
snap, snap_ref)
|
snap, snap_ref)
|
||||||
|
|
||||||
def test_manage_existing_snapshot_bad_api_version(self):
|
def test_manage_existing_snapshot_bad_api_version(self):
|
||||||
self.array.get_rest_version.return_value = '1.3'
|
self.array._list_available_rest_versions.return_value = ['1.0', '1.1',
|
||||||
|
'1.2']
|
||||||
snap, _ = self.new_fake_snap()
|
snap, _ = self.new_fake_snap()
|
||||||
self.assertRaises(pure.PureDriverException,
|
self.assertRaises(pure.PureDriverException,
|
||||||
self.driver.manage_existing_snapshot,
|
self.driver.manage_existing_snapshot,
|
||||||
@ -2239,7 +2264,8 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
|
|
||||||
def test_manage_existing_snapshot_get_size_bad_api_version(self):
|
def test_manage_existing_snapshot_get_size_bad_api_version(self):
|
||||||
snap, _ = self.new_fake_snap()
|
snap, _ = self.new_fake_snap()
|
||||||
self.array.get_rest_version.return_value = '1.3'
|
self.array._list_available_rest_versions.return_value = ['1.0', '1.1',
|
||||||
|
'1.2']
|
||||||
self.assertRaises(pure.PureDriverException,
|
self.assertRaises(pure.PureDriverException,
|
||||||
self.driver.manage_existing_snapshot_get_size,
|
self.driver.manage_existing_snapshot_get_size,
|
||||||
snap, {'name': PURE_SNAPSHOT['name']})
|
snap, {'name': PURE_SNAPSHOT['name']})
|
||||||
@ -2288,7 +2314,8 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
|
|
||||||
def test_unmanage_snapshot_bad_api_version(self):
|
def test_unmanage_snapshot_bad_api_version(self):
|
||||||
snap, _ = self.new_fake_snap()
|
snap, _ = self.new_fake_snap()
|
||||||
self.array.get_rest_version.return_value = '1.3'
|
self.array._list_available_rest_versions.return_value = ['1.0', '1.1',
|
||||||
|
'1.2']
|
||||||
self.assertRaises(pure.PureDriverException,
|
self.assertRaises(pure.PureDriverException,
|
||||||
self.driver.unmanage_snapshot,
|
self.driver.unmanage_snapshot,
|
||||||
snap)
|
snap)
|
||||||
@ -3108,7 +3135,7 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
san_ip = '1.2.3.4'
|
san_ip = '1.2.3.4'
|
||||||
api_token = 'abcdef'
|
api_token = 'abcdef'
|
||||||
self.purestorage_module.FlashArray.return_value = mock.MagicMock()
|
self.purestorage_module.FlashArray.return_value = mock.MagicMock()
|
||||||
self.purestorage_module.VERSION = "1.14.0"
|
self.purestorage_module.VERSION = "1.17.0"
|
||||||
|
|
||||||
self.driver._get_flasharray(san_ip,
|
self.driver._get_flasharray(san_ip,
|
||||||
api_token,
|
api_token,
|
||||||
@ -3217,7 +3244,10 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
type_qos_specs_id=qos.id)
|
type_qos_specs_id=qos.id)
|
||||||
|
|
||||||
mock_get_volume_type.return_value = vol.volume_type
|
mock_get_volume_type.return_value = vol.volume_type
|
||||||
self.array.get_rest_version.return_value = '1.17'
|
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_qos_specs.return_value = qos
|
||||||
mock_get_repl_type.return_value = None
|
mock_get_repl_type.return_value = None
|
||||||
|
|
||||||
@ -3247,7 +3277,10 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
type_qos_specs_id=qos.id)
|
type_qos_specs_id=qos.id)
|
||||||
|
|
||||||
mock_get_volume_type.return_value = vol.volume_type
|
mock_get_volume_type.return_value = vol.volume_type
|
||||||
self.array.get_rest_version.return_value = '1.17'
|
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_qos_specs.return_value = qos
|
||||||
mock_get_repl_type.return_value = None
|
mock_get_repl_type.return_value = None
|
||||||
|
|
||||||
@ -3277,7 +3310,10 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
mock_get_volume_type.return_value = vol.volume_type
|
mock_get_volume_type.return_value = vol.volume_type
|
||||||
mock_get_qos_specs.return_value = qos
|
mock_get_qos_specs.return_value = qos
|
||||||
self.array.list_volume_private_connections.return_value = []
|
self.array.list_volume_private_connections.return_value = []
|
||||||
self.array.get_rest_version.return_value = '1.17'
|
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.driver.manage_existing(vol, volume_ref)
|
||||||
self.array.list_volume_private_connections.assert_called_with(ref_name)
|
self.array.list_volume_private_connections.assert_called_with(ref_name)
|
||||||
@ -3294,7 +3330,10 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
new_type = fake_volume.fake_volume_type_obj(mock_context)
|
new_type = fake_volume.fake_volume_type_obj(mock_context)
|
||||||
new_type.qos_specs_id = qos.id
|
new_type.qos_specs_id = qos.id
|
||||||
|
|
||||||
self.array.get_rest_version.return_value = '1.17'
|
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"
|
get_voltype = "cinder.objects.volume_type.VolumeType.get_by_name_or_id"
|
||||||
with mock.patch(get_voltype) as mock_get_vol_type:
|
with mock.patch(get_voltype) as mock_get_vol_type:
|
||||||
mock_get_vol_type.return_value = new_type
|
mock_get_vol_type.return_value = new_type
|
||||||
@ -3318,7 +3357,10 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
vol, vol_name = self.new_fake_vol()
|
vol, vol_name = self.new_fake_vol()
|
||||||
new_type = fake_volume.fake_volume_type_obj(mock_context)
|
new_type = fake_volume.fake_volume_type_obj(mock_context)
|
||||||
|
|
||||||
self.array.get_rest_version.return_value = '1.17'
|
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"
|
get_voltype = "cinder.objects.volume_type.VolumeType.get_by_name_or_id"
|
||||||
with mock.patch(get_voltype) as mock_get_vol_type:
|
with mock.patch(get_voltype) as mock_get_vol_type:
|
||||||
mock_get_vol_type.return_value = new_type
|
mock_get_vol_type.return_value = new_type
|
||||||
@ -3697,13 +3739,19 @@ class PureISCSIDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
self.mock_config.use_chap_auth = False
|
self.mock_config.use_chap_auth = False
|
||||||
self.mock_config.safe_get.return_value = 'oracle-vm-server'
|
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
|
# Branch where we fail due to invalid version for setting personality
|
||||||
self.assertRaises(pure.PureDriverException, self.driver._connect,
|
self.assertRaises(pure.PureDriverException, self.driver._connect,
|
||||||
self.array, vol_name, ISCSI_CONNECTOR, None, None)
|
self.array, vol_name, ISCSI_CONNECTOR, None, None)
|
||||||
self.assertFalse(self.array.create_host.called)
|
self.assertFalse(self.array.create_host.called)
|
||||||
self.assertFalse(self.array.set_host.called)
|
self.assertFalse(self.array.set_host.called)
|
||||||
|
|
||||||
self.array.get_rest_version.return_value = '1.14'
|
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
|
# Branch where personality is set
|
||||||
self.driver._connect(self.array, vol_name, ISCSI_CONNECTOR,
|
self.driver._connect(self.array, vol_name, ISCSI_CONNECTOR,
|
||||||
@ -3961,6 +4009,9 @@ class PureFCDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
self.driver._connect, self.array, vol_name, FC_CONNECTOR)
|
self.driver._connect, self.array, vol_name, FC_CONNECTOR)
|
||||||
|
|
||||||
self.mock_config.safe_get.return_value = 'oracle-vm-server'
|
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
|
# Branch where we fail due to invalid version for setting personality
|
||||||
self.assertRaises(pure.PureDriverException, self.driver._connect,
|
self.assertRaises(pure.PureDriverException, self.driver._connect,
|
||||||
@ -3968,7 +4019,10 @@ class PureFCDriverTestCase(PureBaseSharedDriverTestCase):
|
|||||||
self.assertTrue(self.array.create_host.called)
|
self.assertTrue(self.array.create_host.called)
|
||||||
self.assertFalse(self.array.set_host.called)
|
self.assertFalse(self.array.set_host.called)
|
||||||
|
|
||||||
self.array.get_rest_version.return_value = '1.14'
|
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
|
# Branch where personality is set
|
||||||
self.driver._connect(self.array, vol_name, FC_CONNECTOR)
|
self.driver._connect(self.array, vol_name, FC_CONNECTOR)
|
||||||
|
@ -137,13 +137,11 @@ EXTRA_SPECS_REPL_TYPE = "replication_type"
|
|||||||
MAX_VOL_LENGTH = 63
|
MAX_VOL_LENGTH = 63
|
||||||
MAX_SNAP_LENGTH = 96
|
MAX_SNAP_LENGTH = 96
|
||||||
UNMANAGED_SUFFIX = '-unmanaged'
|
UNMANAGED_SUFFIX = '-unmanaged'
|
||||||
QOS_REQUIRED_API_VERSION = ['1.17']
|
QOS_REQUIRED_API_VERSION = '1.17'
|
||||||
SYNC_REPLICATION_REQUIRED_API_VERSIONS = ['1.13', '1.14', '1.17']
|
SYNC_REPLICATION_REQUIRED_API_VERSION = '1.13'
|
||||||
ASYNC_REPLICATION_REQUIRED_API_VERSIONS = [
|
ASYNC_REPLICATION_REQUIRED_API_VERSION = '1.3'
|
||||||
'1.3', '1.4', '1.5'] + SYNC_REPLICATION_REQUIRED_API_VERSIONS
|
MANAGE_SNAP_REQUIRED_API_VERSION = '1.4'
|
||||||
MANAGE_SNAP_REQUIRED_API_VERSIONS = [
|
PERSONALITY_REQUIRED_API_VERSION = '1.14'
|
||||||
'1.4', '1.5'] + SYNC_REPLICATION_REQUIRED_API_VERSIONS
|
|
||||||
PERSONALITY_REQUIRED_API_VERSIONS = ['1.14']
|
|
||||||
|
|
||||||
REPL_SETTINGS_PROPAGATE_RETRY_INTERVAL = 5 # 5 seconds
|
REPL_SETTINGS_PROPAGATE_RETRY_INTERVAL = 5 # 5 seconds
|
||||||
REPL_SETTINGS_PROPAGATE_MAX_RETRIES = 36 # 36 * 5 = 180 seconds
|
REPL_SETTINGS_PROPAGATE_MAX_RETRIES = 36 # 36 * 5 = 180 seconds
|
||||||
@ -197,9 +195,6 @@ def pure_driver_debug_trace(f):
|
|||||||
class PureBaseVolumeDriver(san.SanDriver):
|
class PureBaseVolumeDriver(san.SanDriver):
|
||||||
"""Performs volume management on Pure Storage FlashArray."""
|
"""Performs volume management on Pure Storage FlashArray."""
|
||||||
|
|
||||||
SUPPORTED_REST_API_VERSIONS = ['1.2', '1.3', '1.4', '1.5',
|
|
||||||
'1.13', '1.14', '1.17']
|
|
||||||
|
|
||||||
SUPPORTS_ACTIVE_ACTIVE = True
|
SUPPORTS_ACTIVE_ACTIVE = True
|
||||||
PURE_QOS_KEYS = ['maxIOPS', 'maxBWS']
|
PURE_QOS_KEYS = ['maxIOPS', 'maxBWS']
|
||||||
# ThirdPartySystems wiki page
|
# ThirdPartySystems wiki page
|
||||||
@ -284,23 +279,21 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
ssl_cert_path=ssl_cert_path
|
ssl_cert_path=ssl_cert_path
|
||||||
)
|
)
|
||||||
|
|
||||||
api_version = target_array.get_rest_version()
|
api_versions = target_array._list_available_rest_versions()
|
||||||
|
|
||||||
if repl_type == REPLICATION_TYPE_ASYNC:
|
if repl_type == REPLICATION_TYPE_ASYNC:
|
||||||
req_api_versions = ASYNC_REPLICATION_REQUIRED_API_VERSIONS
|
req_api_version = ASYNC_REPLICATION_REQUIRED_API_VERSION
|
||||||
elif repl_type == REPLICATION_TYPE_SYNC:
|
elif repl_type == REPLICATION_TYPE_SYNC:
|
||||||
req_api_versions = SYNC_REPLICATION_REQUIRED_API_VERSIONS
|
req_api_version = SYNC_REPLICATION_REQUIRED_API_VERSION
|
||||||
else:
|
else:
|
||||||
msg = _('Invalid replication type specified:') % repl_type
|
msg = _('Invalid replication type specified:') % repl_type
|
||||||
raise PureDriverException(reason=msg)
|
raise PureDriverException(reason=msg)
|
||||||
|
|
||||||
if api_version not in req_api_versions:
|
if req_api_version not in api_versions:
|
||||||
msg = _('Unable to do replication with Purity REST '
|
msg = _('Unable to do replication with Purity REST '
|
||||||
'API version %(api_version)s, requires one of '
|
'API version, requires minimum of '
|
||||||
'%(required_versions)s.') % {
|
'%(required_version)s.') % {
|
||||||
'api_version': api_version,
|
'required_version': req_api_version
|
||||||
'required_versions':
|
|
||||||
ASYNC_REPLICATION_REQUIRED_API_VERSIONS
|
|
||||||
}
|
}
|
||||||
raise PureDriverException(reason=msg)
|
raise PureDriverException(reason=msg)
|
||||||
|
|
||||||
@ -377,8 +370,6 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
|
|
||||||
# Raises PureDriverException if unable to connect and PureHTTPError
|
# Raises PureDriverException if unable to connect and PureHTTPError
|
||||||
# if unable to authenticate.
|
# if unable to authenticate.
|
||||||
purestorage.FlashArray.supported_rest_versions = \
|
|
||||||
self.SUPPORTED_REST_API_VERSIONS
|
|
||||||
self._array = self._get_flasharray(
|
self._array = self._get_flasharray(
|
||||||
self.configuration.san_ip,
|
self.configuration.san_ip,
|
||||||
api_token=self.configuration.pure_api_token,
|
api_token=self.configuration.pure_api_token,
|
||||||
@ -492,9 +483,10 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
ctxt = context.get_admin_context()
|
ctxt = context.get_admin_context()
|
||||||
type_id = volume.get('volume_type_id')
|
type_id = volume.get('volume_type_id')
|
||||||
current_array = self._get_current_array()
|
current_array = self._get_current_array()
|
||||||
|
rest_versions = current_array._list_available_rest_versions()
|
||||||
if type_id is not None:
|
if type_id is not None:
|
||||||
volume_type = volume_types.get_volume_type(ctxt, type_id)
|
volume_type = volume_types.get_volume_type(ctxt, type_id)
|
||||||
if (current_array.get_rest_version() in QOS_REQUIRED_API_VERSION):
|
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:
|
if qos is not None:
|
||||||
self.create_with_qos(current_array, vol_name, vol_size, qos)
|
self.create_with_qos(current_array, vol_name, vol_size, qos)
|
||||||
@ -516,9 +508,10 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
current_array = self._get_current_array()
|
current_array = self._get_current_array()
|
||||||
ctxt = context.get_admin_context()
|
ctxt = context.get_admin_context()
|
||||||
type_id = volume.get('volume_type_id')
|
type_id = volume.get('volume_type_id')
|
||||||
|
rest_versions = current_array._list_available_rest_versions()
|
||||||
if type_id is not None:
|
if type_id is not None:
|
||||||
volume_type = volume_types.get_volume_type(ctxt, type_id)
|
volume_type = volume_types.get_volume_type(ctxt, type_id)
|
||||||
if (current_array.get_rest_version() in QOS_REQUIRED_API_VERSION):
|
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)
|
current_array.copy_volume(snap_name, vol_name)
|
||||||
@ -611,11 +604,11 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
"""Disconnect all hosts and delete the volume"""
|
"""Disconnect all hosts and delete the volume"""
|
||||||
vol_name = self._get_vol_name(volume)
|
vol_name = self._get_vol_name(volume)
|
||||||
current_array = self._get_current_array()
|
current_array = self._get_current_array()
|
||||||
|
rest_versions = current_array._list_available_rest_versions()
|
||||||
try:
|
try:
|
||||||
# Do a pass over remaining connections on the current array, if
|
# Do a pass over remaining connections on the current array, if
|
||||||
# we can try and remove any remote connections too.
|
# we can try and remove any remote connections too.
|
||||||
if (current_array.get_rest_version() in
|
if SYNC_REPLICATION_REQUIRED_API_VERSION in rest_versions:
|
||||||
SYNC_REPLICATION_REQUIRED_API_VERSIONS):
|
|
||||||
hosts = current_array.list_volume_private_connections(
|
hosts = current_array.list_volume_private_connections(
|
||||||
vol_name, remote=True)
|
vol_name, remote=True)
|
||||||
else:
|
else:
|
||||||
@ -715,13 +708,13 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
Returns True if it was the hosts last connection.
|
Returns True if it was the hosts last connection.
|
||||||
"""
|
"""
|
||||||
vol_name = self._get_vol_name(volume)
|
vol_name = self._get_vol_name(volume)
|
||||||
|
rest_versions = array._list_available_rest_versions()
|
||||||
if connector is None:
|
if connector is None:
|
||||||
# If no connector was provided it is a force-detach, remove all
|
# If no connector was provided it is a force-detach, remove all
|
||||||
# host connections for the volume
|
# host connections for the volume
|
||||||
LOG.warning("Removing ALL host connections for volume %s",
|
LOG.warning("Removing ALL host connections for volume %s",
|
||||||
vol_name)
|
vol_name)
|
||||||
if (array.get_rest_version() in
|
if SYNC_REPLICATION_REQUIRED_API_VERSION in rest_versions:
|
||||||
SYNC_REPLICATION_REQUIRED_API_VERSIONS):
|
|
||||||
# Remote connections are only allowed in newer API versions
|
# Remote connections are only allowed in newer API versions
|
||||||
connections = array.list_volume_private_connections(
|
connections = array.list_volume_private_connections(
|
||||||
vol_name, remote=True)
|
vol_name, remote=True)
|
||||||
@ -1331,7 +1324,8 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
# Check if the volume_type has QoS settings and if so
|
# Check if the volume_type has QoS settings and if so
|
||||||
# apply them to the newly managed volume
|
# apply them to the newly managed volume
|
||||||
qos = None
|
qos = None
|
||||||
if (current_array.get_rest_version() in QOS_REQUIRED_API_VERSION):
|
rest_versions = current_array._list_available_rest_versions()
|
||||||
|
if QOS_REQUIRED_API_VERSION in rest_versions:
|
||||||
qos = self._get_qos_settings(volume.volume_type)
|
qos = self._get_qos_settings(volume.volume_type)
|
||||||
if qos is not None:
|
if qos is not None:
|
||||||
self.set_qos(current_array, new_vol_name, qos)
|
self.set_qos(current_array, new_vol_name, qos)
|
||||||
@ -1400,13 +1394,12 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
|
|
||||||
def _verify_manage_snap_api_requirements(self):
|
def _verify_manage_snap_api_requirements(self):
|
||||||
current_array = self._get_current_array()
|
current_array = self._get_current_array()
|
||||||
api_version = current_array.get_rest_version()
|
rest_versions = current_array._list_available_rest_versions()
|
||||||
if api_version not in MANAGE_SNAP_REQUIRED_API_VERSIONS:
|
if MANAGE_SNAP_REQUIRED_API_VERSION not in rest_versions:
|
||||||
msg = _('Unable to do manage snapshot operations with Purity REST '
|
msg = _('Unable to do manage snapshot operations with Purity REST '
|
||||||
'API version %(api_version)s, requires '
|
'API version, requires '
|
||||||
'%(required_versions)s.') % {
|
'%(required_version)s.') % {
|
||||||
'api_version': api_version,
|
'required_version': MANAGE_SNAP_REQUIRED_API_VERSION
|
||||||
'required_versions': MANAGE_SNAP_REQUIRED_API_VERSIONS
|
|
||||||
}
|
}
|
||||||
raise PureDriverException(reason=msg)
|
raise PureDriverException(reason=msg)
|
||||||
|
|
||||||
@ -1573,11 +1566,11 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
request_kwargs=None):
|
request_kwargs=None):
|
||||||
|
|
||||||
if (version.LooseVersion(purestorage.VERSION) <
|
if (version.LooseVersion(purestorage.VERSION) <
|
||||||
version.LooseVersion('1.14.0')):
|
version.LooseVersion('1.17.0')):
|
||||||
if request_kwargs is not None:
|
if request_kwargs is not None:
|
||||||
LOG.warning("Unable to specify request_kwargs='%s' on "
|
LOG.warning("Unable to specify request_kwargs='%s' on "
|
||||||
"purestorage.FlashArray using 'purestorage' "
|
"purestorage.FlashArray using 'purestorage' "
|
||||||
"python module <1.14.0. Current version: %s",
|
"python module <1.17.0. Current version: %s",
|
||||||
request_kwargs,
|
request_kwargs,
|
||||||
purestorage.VERSION)
|
purestorage.VERSION)
|
||||||
array = purestorage.FlashArray(san_ip,
|
array = purestorage.FlashArray(san_ip,
|
||||||
@ -1927,7 +1920,8 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
# make sure the volume gets the correct new QoS settings.
|
# make sure the volume gets the correct new QoS settings.
|
||||||
# This could mean removing existing QoS settings.
|
# This could mean removing existing QoS settings.
|
||||||
current_array = self._get_current_array()
|
current_array = self._get_current_array()
|
||||||
if (current_array.get_rest_version() in QOS_REQUIRED_API_VERSION):
|
rest_versions = current_array._list_available_rest_versions()
|
||||||
|
if QOS_REQUIRED_API_VERSION in rest_versions:
|
||||||
qos = self._get_qos_settings(new_type)
|
qos = self._get_qos_settings(new_type)
|
||||||
vol_name = self._generate_purity_vol_name(volume)
|
vol_name = self._generate_purity_vol_name(volume)
|
||||||
if qos is not None:
|
if qos is not None:
|
||||||
@ -2079,17 +2073,16 @@ class PureBaseVolumeDriver(san.SanDriver):
|
|||||||
@pure_driver_debug_trace
|
@pure_driver_debug_trace
|
||||||
def get_check_personality(self, array):
|
def get_check_personality(self, array):
|
||||||
personality = self.configuration.safe_get('pure_host_personality')
|
personality = self.configuration.safe_get('pure_host_personality')
|
||||||
|
rest_versions = array._list_available_rest_versions()
|
||||||
if personality:
|
if personality:
|
||||||
api_version = array.get_rest_version()
|
if PERSONALITY_REQUIRED_API_VERSION not in rest_versions:
|
||||||
if api_version not in PERSONALITY_REQUIRED_API_VERSIONS:
|
|
||||||
# Continuing here would mean creating a host not according
|
# Continuing here would mean creating a host not according
|
||||||
# to specificiations, possibly leading to unexpected
|
# to specificiations, possibly leading to unexpected
|
||||||
# behavior later on.
|
# behavior later on.
|
||||||
msg = _('Unable to set host personality with Purity REST '
|
msg = _('Unable to set host personality with Purity REST '
|
||||||
'API version %(api_version)s, requires '
|
'API version, requires '
|
||||||
'%(required_versions)s.') % {
|
'%(required_version)s.') % {
|
||||||
'api_version': api_version,
|
'required_version': PERSONALITY_REQUIRED_API_VERSION
|
||||||
'required_versions': PERSONALITY_REQUIRED_API_VERSIONS
|
|
||||||
}
|
}
|
||||||
raise PureDriverException(reason=msg)
|
raise PureDriverException(reason=msg)
|
||||||
return personality
|
return personality
|
||||||
@ -2578,8 +2571,8 @@ class PureISCSIDriver(PureBaseVolumeDriver, san.SanISCSIDriver):
|
|||||||
|
|
||||||
def _get_host(self, array, connector, remote=False):
|
def _get_host(self, array, connector, remote=False):
|
||||||
"""Return dict describing existing Purity host object or None."""
|
"""Return dict describing existing Purity host object or None."""
|
||||||
if (remote and array.get_rest_version() in
|
rest_versions = array._list_available_rest_versions()
|
||||||
SYNC_REPLICATION_REQUIRED_API_VERSIONS):
|
if remote and SYNC_REPLICATION_REQUIRED_API_VERSION in rest_versions:
|
||||||
hosts = array.list_hosts(remote=True)
|
hosts = array.list_hosts(remote=True)
|
||||||
else:
|
else:
|
||||||
hosts = array.list_hosts()
|
hosts = array.list_hosts()
|
||||||
@ -2805,8 +2798,8 @@ class PureFCDriver(PureBaseVolumeDriver, driver.FibreChannelDriver):
|
|||||||
|
|
||||||
def _get_host(self, array, connector, remote=False):
|
def _get_host(self, array, connector, remote=False):
|
||||||
"""Return dict describing existing Purity host object or None."""
|
"""Return dict describing existing Purity host object or None."""
|
||||||
if (remote and array.get_rest_version() in
|
rest_versions = array._list_available_rest_versions()
|
||||||
SYNC_REPLICATION_REQUIRED_API_VERSIONS):
|
if remote and SYNC_REPLICATION_REQUIRED_API_VERSION in rest_versions:
|
||||||
hosts = array.list_hosts(remote=True)
|
hosts = array.list_hosts(remote=True)
|
||||||
else:
|
else:
|
||||||
hosts = array.list_hosts()
|
hosts = array.list_hosts()
|
||||||
|
@ -9,7 +9,7 @@ python-3parclient>=4.2.10 # Apache-2.0
|
|||||||
krest>=1.3.0 # Apache-2.0
|
krest>=1.3.0 # Apache-2.0
|
||||||
|
|
||||||
# Pure Storage
|
# Pure Storage
|
||||||
purestorage>=1.6.0 # BSD
|
purestorage>=1.17.0 # BSD
|
||||||
|
|
||||||
# Dell EMC VMAX, IBM DS8K
|
# Dell EMC VMAX, IBM DS8K
|
||||||
pyOpenSSL>=1.0.0 # Apache-2.0
|
pyOpenSSL>=1.0.0 # Apache-2.0
|
||||||
|
@ -147,7 +147,7 @@ infinisdk==103.0.1
|
|||||||
capacity==1.3.10
|
capacity==1.3.10
|
||||||
info.dtypes.wwn==0.1.1
|
info.dtypes.wwn==0.1.1
|
||||||
info.dtypes.iqn==0.4.0
|
info.dtypes.iqn==0.4.0
|
||||||
purestorage==1.6.0
|
purestorage==1.17.0
|
||||||
rsd-lib==1.1.0
|
rsd-lib==1.1.0
|
||||||
storpool==4.0.0
|
storpool==4.0.0
|
||||||
storpool.spopenstack==2.2.1
|
storpool.spopenstack==2.2.1
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
Pure Storage FlashArray minimum ``purestorage`` SDK version increased
|
||||||
|
to 1.17.0
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Pure Storage FlashArray driver `bug #1929219
|
||||||
|
<https://bugs.launchpad.net/cinder/+bug/1929219>`_: Fixes issue with
|
||||||
|
incorrect internal mechanism for checking REST API of backend array.
|
||||||
|
This has no external effect for users.
|
@ -85,7 +85,7 @@ all =
|
|||||||
python-3parclient>=4.1.0 # Apache-2.0
|
python-3parclient>=4.1.0 # Apache-2.0
|
||||||
krest>=1.3.0 # Apache-2.0
|
krest>=1.3.0 # Apache-2.0
|
||||||
infinisdk>=103.0.1 # BSD-3
|
infinisdk>=103.0.1 # BSD-3
|
||||||
purestorage>=1.6.0 # BSD
|
purestorage>=1.17.0 # BSD
|
||||||
rsd-lib>=1.1.0 # Apache-2.0
|
rsd-lib>=1.1.0 # Apache-2.0
|
||||||
storpool>=4.0.0 # Apache-2.0
|
storpool>=4.0.0 # Apache-2.0
|
||||||
storpool.spopenstack>=2.2.1 # Apache-2.0
|
storpool.spopenstack>=2.2.1 # Apache-2.0
|
||||||
@ -110,7 +110,7 @@ ds8k =
|
|||||||
infinidat =
|
infinidat =
|
||||||
infinisdk>=103.0.1 # BSD-3
|
infinisdk>=103.0.1 # BSD-3
|
||||||
pure =
|
pure =
|
||||||
purestorage>=1.6.0 # BSD
|
purestorage>=1.17.0 # BSD
|
||||||
rsd =
|
rsd =
|
||||||
rsd-lib>=1.1.0 # Apache-2.0
|
rsd-lib>=1.1.0 # Apache-2.0
|
||||||
storpool =
|
storpool =
|
||||||
|
Loading…
Reference in New Issue
Block a user