self.assertFalse(self.array.list_host_connections.called)
self.assertFalse(self.array.delete_host.called)
+ @mock.patch(BASE_DRIVER_OBJ + "._get_host", autospec=True)
+ def test_terminate_connection_host_deleted(self, mock_host):
+ vol_name = VOLUME["name"] + "-cinder"
+ mock_host.return_value = PURE_HOST.copy()
+ self.array.reset_mock()
+ self.array.list_host_connections.return_value = []
+ self.array.delete_host.side_effect = \
+ self.purestorage_module.PureHTTPError(code=400,
+ text='Host does not exist.')
+ self.driver.terminate_connection(VOLUME, ISCSI_CONNECTOR)
+ self.array.disconnect_host.assert_called_with(PURE_HOST_NAME, vol_name)
+ self.array.list_host_connections.assert_called_with(PURE_HOST_NAME,
+ private=True)
+ self.array.delete_host.assert_called_once_with(PURE_HOST_NAME)
+
@mock.patch(BASE_DRIVER_OBJ + ".get_filter_function", autospec=True)
@mock.patch(BASE_DRIVER_OBJ + "._get_provisioned_space", autospec=True)
def test_get_volume_stats(self, mock_space, mock_filter):
ERR_MSG_NOT_EXIST = "does not exist"
ERR_MSG_PENDING_ERADICATION = "has been destroyed"
+CONNECT_LOCK_NAME = 'PureVolumeDriver_connect'
+
def log_debug_trace(f):
def wrapper(*args, **kwargs):
"""
raise NotImplementedError
+ @utils.synchronized(CONNECT_LOCK_NAME, external=True)
def _disconnect(self, volume, connector, **kwargs):
vol_name = self._get_vol_name(volume)
host = self._get_host(connector)
private=True)):
LOG.info(_LI("Deleting unneeded host %(host_name)r."),
{"host_name": host_name})
- self._array.delete_host(host_name)
+ try:
+ self._array.delete_host(host_name)
+ except purestorage.PureHTTPError as err:
+ with excutils.save_and_reraise_exception() as ctxt:
+ if err.code == 400 and ERR_MSG_NOT_EXIST in err.text:
+ # Happens if the host is already deleted.
+ # This is fine though, just treat it as a warning.
+ ctxt.reraise = False
+ LOG.warning(_LW("Purity host deletion failed: "
+ "%(msg)s."), {"msg": err.text})
return True
return False
}
return username, password, initiator_updates
- @utils.synchronized('PureISCSIDriver._connect', external=True)
+ @utils.synchronized(CONNECT_LOCK_NAME, external=True)
def _connect(self, volume, connector, initiator_data):
"""Connect the host and volume; return dict describing connection."""
iqn = connector["initiator"]
return properties
- @utils.synchronized('PureFCDriver._connect', external=True)
+ @utils.synchronized(CONNECT_LOCK_NAME, external=True)
def _connect(self, volume, connector):
"""Connect the host and volume; return dict describing connection."""
wwns = connector["wwpns"]