[Unity] Add `force detach` support

Add support to force detach a volume from all hosts on Unity.

Closes-bug: #1741831
Change-Id: I5f0f3d474b00f3c1f742c1bfa6877911415c32f9
(cherry picked from commit b44721dfac)
(cherry picked from commit 25d76990d0)
This commit is contained in:
Ryan Liang 2018-03-21 10:11:00 +00:00 committed by Ryan Liang
parent 119342ef59
commit 9dbcb24f03
7 changed files with 62 additions and 3 deletions

View File

@ -54,6 +54,14 @@ class DetachIsCalled(Exception):
pass
class DetachAllIsCalled(Exception):
pass
class DetachFromIsCalled(Exception):
pass
class LunDeleteIsCalled(Exception):
pass

View File

@ -129,6 +129,12 @@ class MockClient(object):
if host.name == 'host1' and lun_or_snap.get_id() in error_ids:
raise ex.DetachIsCalled()
@staticmethod
def detach_all(lun):
error_ids = ['lun_44']
if lun.get_id() in error_ids:
raise ex.DetachAllIsCalled()
@staticmethod
def get_iscsi_target_info(allowed_ports=None):
return [{'portal': '1.2.3.4:1234', 'iqn': 'iqn.1-1.com.e:c.a.a0'},
@ -187,6 +193,13 @@ class MockLookupService(object):
}
class MockOSResource(mock.Mock):
def __init__(self, *args, **kwargs):
super(MockOSResource, self).__init__(*args, **kwargs)
if 'name' in kwargs:
self.name = kwargs['name']
def mock_adapter(driver_clz):
ret = driver_clz()
ret._client = MockClient()
@ -382,6 +395,13 @@ class CommonAdapterTest(unittest.TestCase):
self.assertRaises(ex.DetachIsCalled, f)
def test_terminate_connection_force_detach(self):
def f():
volume = MockOSResource(provider_location='id^lun_44', id='id_44')
self.adapter.terminate_connection(volume, None)
self.assertRaises(ex.DetachAllIsCalled, f)
def test_terminate_connection_snapshot(self):
def f():
connector = {'host': 'host1'}

View File

@ -100,6 +100,11 @@ class MockResource(object):
if lun_or_snap.name == 'detach_failure':
raise ex.DetachIsCalled()
@staticmethod
def detach_from(host):
if host is None:
raise ex.DetachFromIsCalled()
def get_hlu(self, lun):
return self.alu_hlu_map.get(lun.get_id(), None)
@ -405,6 +410,13 @@ class ClientTest(unittest.TestCase):
self.assertRaises(ex.DetachIsCalled, f)
def test_detach_all(self):
def f():
lun = MockResource('lun_44')
self.client.detach_all(lun)
self.assertRaises(ex.DetachFromIsCalled, f)
@mock.patch.object(coordination.Coordinator, 'get_lock')
def test_create_host(self, fake):
self.assertEqual('host2', self.client.create_host('host2').name)

View File

@ -223,8 +223,12 @@ class CommonAdapter(object):
@cinder_utils.trace
def _terminate_connection(self, lun_or_snap, connector):
host = self.client.create_host(connector['host'])
self.client.detach(host, lun_or_snap)
is_force_detach = connector is None
if is_force_detach:
self.client.detach_all(lun_or_snap)
else:
host = self.client.create_host(connector['host'])
self.client.detach(host, lun_or_snap)
@cinder_utils.trace
def terminate_connection(self, volume, connector):

View File

@ -239,6 +239,15 @@ class UnityClient(object):
lun_or_snap.update()
host.detach(lun_or_snap)
@staticmethod
def detach_all(lun):
"""Detaches a `UnityLun` from all hosts.
:param lun: `UnityLun` object
"""
lun.update()
lun.detach_from(host=None)
def get_ethernet_ports(self):
return self.system.get_ethernet_port()

View File

@ -53,9 +53,11 @@ class UnityDriver(driver.ManageableVD,
1.0.2 - Fixes bug 1775518 to make sure driver succeed to initialize
even though the value of unity_io_ports and
unity_storage_pool_names are empty
1.0.3 - Fixed bug 1741831: corrected support to force detach a volume
from all its attached hosts.
"""
VERSION = '01.00.02'
VERSION = '01.00.03'
VENDOR = 'Dell EMC'
# ThirdPartySystems wiki page
CI_WIKI_NAME = "EMC_UNITY_CI"

View File

@ -0,0 +1,4 @@
---
fixes:
- |
Corrected support to force detach a volume from all hosts on Unity.