diff --git a/cinder/tests/unit/volume/drivers/test_pure.py b/cinder/tests/unit/volume/drivers/test_pure.py index 08ff0b6e6fd..1c1f3af0f02 100644 --- a/cinder/tests/unit/volume/drivers/test_pure.py +++ b/cinder/tests/unit/volume/drivers/test_pure.py @@ -3642,6 +3642,22 @@ class PureFCDriverTestCase(PureBaseSharedDriverTestCase): self.array.create_host], self.driver._connect, self.array, vol_name, FC_CONNECTOR) + self.mock_config.safe_get.return_value = 'oracle-vm-server' + + # 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.get_rest_version.return_value = '1.14' + + # Branch where personality is set + self.driver._connect(self.array, vol_name, FC_CONNECTOR) + self.assertDictEqual(result, real_result) + self.array.set_host.assert_called_with(PURE_HOST_NAME, + personality='oracle-vm-server') + @mock.patch(FC_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 5ffc00db121..daa27eb71a9 100644 --- a/cinder/volume/drivers/pure.py +++ b/cinder/volume/drivers/pure.py @@ -1892,6 +1892,38 @@ 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') + 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 PureDriverException(reason=msg) + return personality + + @pure_driver_debug_trace + def set_personality(self, array, host_name, 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 PureRetryableException() + return + def _swap_replication_state(self, current_array, secondary_array, failback=False): # After failover we want our current array to be swapped for the @@ -2527,21 +2559,7 @@ 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 PureDriverException(reason=msg) - + personality = self.get_check_personality(array) 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}) @@ -2557,16 +2575,7 @@ class PureISCSIDriver(PureBaseVolumeDriver, san.SanISCSIDriver): raise 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 PureRetryableException() + self.set_personality(array, host_name, personality) if self.configuration.use_chap_auth: try: @@ -2682,6 +2691,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) 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}) @@ -2696,6 +2706,9 @@ class PureFCDriver(PureBaseVolumeDriver, driver.FibreChannelDriver): LOG.debug('Unable to create host: %s', err.text) raise PureRetryableException() + if personality: + self.set_personality(array, host_name, personality) + # TODO(patrickeast): Ensure that the host has the correct preferred # arrays configured for it. diff --git a/releasenotes/notes/pure_fc_personality-3cada97fc940e498.yaml b/releasenotes/notes/pure_fc_personality-3cada97fc940e498.yaml new file mode 100644 index 00000000000..429e8a55780 --- /dev/null +++ b/releasenotes/notes/pure_fc_personality-3cada97fc940e498.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Pure Storage driver: Add missing support for ``host_personality`` setting + for FC-based hosts