protocol = 'fibre_channel'
exp_result = {}
exp_result = {'vendor_name': "X-IO",
- 'driver_version': "1.1.1",
+ 'driver_version': "1.1.2",
'volume_backend_name': backend_name,
'reserved_percentage': 0,
'total_capacity_gb': 100,
mock_req.side_effect = iter([ISE_GET_QUERY_RESP,
ISE_GET_HOSTS_HOST1_RESP,
ISE_GET_ALLOC_WITH_EP_RESP,
+ ISE_DELETE_ALLOC_RESP,
+ ISE_GET_ALLOC_WITH_EP_RESP,
+ ISE_GET_HOSTS_HOST1_RESP,
ISE_DELETE_ALLOC_RESP])
elif self.configuration.ise_protocol == 'fibre_channel':
mock_req.side_effect = iter([ISE_GET_QUERY_RESP,
ISE_GET_ALLOC_WITH_EP_RESP,
ISE_DELETE_ALLOC_RESP,
ISE_GET_ALLOC_WITH_EP_RESP,
- ISE_GET_CONTROLLERS_RESP])
+ ISE_GET_CONTROLLERS_RESP,
+ ISE_GET_HOSTS_HOST1_RESP,
+ ISE_DELETE_ALLOC_RESP])
self.driver.terminate_connection(VOLUME1, self.connector)
def test_terminate_connection_positive_noalloc(self, mock_req):
if self.configuration.ise_protocol == 'iscsi':
mock_req.side_effect = iter([ISE_GET_QUERY_RESP,
ISE_GET_HOSTS_HOST1_RESP,
- ISE_GET_ALLOC_WITH_NO_ALLOC_RESP])
+ ISE_GET_ALLOC_WITH_NO_ALLOC_RESP,
+ ISE_GET_ALLOC_WITH_NO_ALLOC_RESP,
+ ISE_GET_HOSTS_HOST1_RESP,
+ ISE_DELETE_ALLOC_RESP])
elif self.configuration.ise_protocol == 'fibre_channel':
mock_req.side_effect = iter([ISE_GET_QUERY_RESP,
ISE_GET_HOSTS_HOST1_RESP,
ISE_GET_ALLOC_WITH_NO_ALLOC_RESP,
ISE_GET_ALLOC_WITH_NO_ALLOC_RESP,
- ISE_GET_CONTROLLERS_RESP])
+ ISE_GET_CONTROLLERS_RESP,
+ ISE_GET_HOSTS_HOST1_RESP,
+ ISE_DELETE_ALLOC_RESP])
self.driver.terminate_connection(VOLUME1, self.connector)
def test_negative_terminate_connection_bad_host(self, mock_req):
class XIOISEDriver(object):
- VERSION = '1.1.1'
+ VERSION = '1.1.2'
# Version Changes
# 1.0.0 Base driver
# 1.1.0 QoS, affinity, retype and thin support
# 1.1.1 Fix retry loop (Bug 1429283)
+ # 1.1.2 Fix host object deletion (Bug 1433450).
def __init__(self, *args, **kwargs):
super(XIOISEDriver, self).__init__()
def local_path(self, volume):
LOG.debug("X-IO local_path called.")
+ def delete_host(self, endpoints):
+ """Delete ISE host object"""
+ host = self._find_host(endpoints)
+ if host['locator'] != '':
+ # Delete host
+ self._send_cmd('DELETE', host['locator'], {})
+ LOG.debug("X-IO: host %s deleted", host['name'])
+
# Protocol specific classes for entry. They are wrappers around base class
# above and every external API resuslts in a call to common function in base
'data': data}
def terminate_connection(self, volume, connector, **kwargs):
- return self.driver.ise_unpresent(volume, connector['initiator'])
+ hostname = self.driver.ise_unpresent(volume, connector['initiator'])
+ alloc_cnt = 0
+ if hostname != '':
+ alloc_cnt = self.driver.find_allocations(hostname)
+ if alloc_cnt == 0:
+ # delete host object
+ self.driver.delete_host(connector['initiator'])
def create_snapshot(self, snapshot):
return self.driver.create_snapshot(snapshot)
alloc_cnt = 0
if hostname != '':
alloc_cnt = self.driver.find_allocations(hostname)
- if alloc_cnt == 0:
- target_wwns = self.driver.find_target_wwns()
- data['target_wwn'] = target_wwns
- # build target initiator map
- target_map = {}
- for initiator in connector['wwpns']:
- target_map[initiator] = target_wwns
- data['initiator_target_map'] = target_map
+ if alloc_cnt == 0:
+ target_wwns = self.driver.find_target_wwns()
+ data['target_wwn'] = target_wwns
+ # build target initiator map
+ target_map = {}
+ for initiator in connector['wwpns']:
+ target_map[initiator] = target_wwns
+ data['initiator_target_map'] = target_map
+ # delete host object
+ self.driver.delete_host(connector['wwpns'])
+
return {'driver_volume_type': 'fibre_channel',
'data': data}