diff --git a/cinder/tests/unit/volume/drivers/test_pure.py b/cinder/tests/unit/volume/drivers/test_pure.py index dbd99c65a05..06d0cc818a2 100644 --- a/cinder/tests/unit/volume/drivers/test_pure.py +++ b/cinder/tests/unit/volume/drivers/test_pure.py @@ -3229,6 +3229,7 @@ class PureISCSIDriverTestCase(PureBaseSharedDriverTestCase): mock_generate.assert_called_with(HOSTNAME) self.array.create_host.assert_called_with(PURE_HOST_NAME, iqnlist=[INITIATOR_IQN]) + self.assertFalse(self.array.set_host.called) self.assertEqual(result, real_result) mock_generate.reset_mock() @@ -3250,6 +3251,25 @@ class PureISCSIDriverTestCase(PureBaseSharedDriverTestCase): host_user=chap_user, host_password=chap_password) + self.array.reset_mock() + self.mock_config.use_chap_auth = False + self.mock_config.safe_get.return_value = 'oracle-vm-server' + + # Branch where we fail due to invalid version for setting personality + self.assertRaises(exception.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.get_rest_version.return_value = '1.14' + + # Branch where personality is set + self.driver._connect(self.array, vol_name, ISCSI_CONNECTOR, + None, None) + self.assertDictEqual(result, real_result) + self.array.set_host.assert_called_with(PURE_HOST_NAME, + personality='oracle-vm-server') + @mock.patch(ISCSI_DRIVER_OBJ + "._get_host", autospec=True) def test_connect_already_connected(self, mock_host): vol, vol_name = self.new_fake_vol() diff --git a/cinder/volume/drivers/pure.py b/cinder/volume/drivers/pure.py index 1fec72235a1..23cb8483c53 100644 --- a/cinder/volume/drivers/pure.py +++ b/cinder/volume/drivers/pure.py @@ -60,6 +60,11 @@ PURE_OPTS = [ "on the current total data reduction values. If used " "this calculated value will override the " "max_over_subscription_ratio config option."), + cfg.StrOpt("pure_host_personality", + choices=['aix', 'esxi', 'hitachi-vsp', 'hpux', + 'oracle-vm-server', 'solaris', 'vms'], + help="Determines how the Purity system tunes the protocol used " + "between the array and the initiator."), # These are used as default settings. In future these can be overridden # by settings in volume-type. cfg.IntOpt("pure_replica_interval_default", default=3600, @@ -123,6 +128,7 @@ ASYNC_REPLICATION_REQUIRED_API_VERSIONS = [ '1.3', '1.4', '1.5'] + SYNC_REPLICATION_REQUIRED_API_VERSIONS MANAGE_SNAP_REQUIRED_API_VERSIONS = [ '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_MAX_RETRIES = 36 # 36 * 5 = 180 seconds @@ -2468,6 +2474,21 @@ class PureISCSIDriver(PureBaseVolumeDriver, san.SanISCSIDriver): reason=_("Unable to re-use host with unknown CHAP " "credentials configured.")) else: + personality = self.configuration.safe_get('pure_host_personality') + if personality: + api_version = array.get_rest_version() + if api_version not in PERSONALITY_REQUIRED_API_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 %(api_version)s, requires ' + '%(required_versions)s.') % { + 'api_version': api_version, + 'required_versions': PERSONALITY_REQUIRED_API_VERSIONS + } + raise exception.PureDriverException(reason=msg) + 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}) @@ -2482,6 +2503,18 @@ class PureISCSIDriver(PureBaseVolumeDriver, san.SanISCSIDriver): LOG.debug('Unable to create host: %s', err.text) raise exception.PureRetryableException() + if personality: + try: + array.set_host(host_name, personality=personality) + except purestorage.PureHTTPError as err: + if (err.code == 400 and + ERR_MSG_HOST_NOT_EXIST in err.text): + # If the host disappeared out from under us that's + # ok, we will just retry and snag a new host. + LOG.debug('Unable to set host personality: %s', + err.text) + raise exception.PureRetryableException() + if self.configuration.use_chap_auth: try: array.set_host(host_name, diff --git a/doc/source/configuration/block-storage/drivers/pure-storage-driver.rst b/doc/source/configuration/block-storage/drivers/pure-storage-driver.rst index 9f7f4ac5322..c152e0ad057 100644 --- a/doc/source/configuration/block-storage/drivers/pure-storage-driver.rst +++ b/doc/source/configuration/block-storage/drivers/pure-storage-driver.rst @@ -176,6 +176,28 @@ By default, auto-eradication is disabled and all deleted volumes, snapshots, and consistency groups are retained on the Pure Storage array in a recoverable state for 24 hours from time of deletion. +Setting host personality +~~~~~~~~~~~~~~~~~~~~~~~~ + +The host personality determines how the Purity system tunes the protocol used +between the array and the initiator. To ensure the array works optimally with +the host, set the personality to the name of the host operating or virtual +memory system. Valid values are aix, esxi, hitachi-vsp, hpux, oracle-vm-server, +solaris, and vms. If your system is not listed as one of the valid host +personalities, do not set the option. By default, the host personality is not +set. + +To set the host personality, modify the following option in the ``cinder.conf`` +file: + +.. code-block:: ini + + pure_host_personality = + +.. note:: + ``pure_host_personality`` is available from Purity REST API version 1.14, + and affects only newly-created hosts. + SSL certification ~~~~~~~~~~~~~~~~~ diff --git a/releasenotes/notes/pure-host-personality-3512f7ccd961d4ad.yaml b/releasenotes/notes/pure-host-personality-3512f7ccd961d4ad.yaml new file mode 100644 index 00000000000..7bf7e5d1491 --- /dev/null +++ b/releasenotes/notes/pure-host-personality-3512f7ccd961d4ad.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Pure Storage FlashArray driver has added configuration option + ``pure_host_personality`` for setting the host personality upon host + creation (existing hosts are not affected).