[Unity] Add force detach
support
Add support to force detach a volume from all hosts on Unity. Closes-bug: #1741831 Change-Id: I5f0f3d474b00f3c1f742c1bfa6877911415c32f9
This commit is contained in:
parent
9cbb200ec2
commit
b44721dfac
@ -58,6 +58,14 @@ class DetachIsCalled(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DetachAllIsCalled(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DetachFromIsCalled(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class LunDeleteIsCalled(Exception):
|
class LunDeleteIsCalled(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -140,6 +140,12 @@ class MockClient(object):
|
|||||||
if host.name == 'host1' and lun_or_snap.get_id() in error_ids:
|
if host.name == 'host1' and lun_or_snap.get_id() in error_ids:
|
||||||
raise ex.DetachIsCalled()
|
raise ex.DetachIsCalled()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def detach_all(lun):
|
||||||
|
error_ids = ['lun_44']
|
||||||
|
if lun.get_id() in error_ids:
|
||||||
|
raise ex.DetachAllIsCalled()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_iscsi_target_info(allowed_ports=None):
|
def get_iscsi_target_info(allowed_ports=None):
|
||||||
return [{'portal': '1.2.3.4:1234', 'iqn': 'iqn.1-1.com.e:c.a.a0'},
|
return [{'portal': '1.2.3.4:1234', 'iqn': 'iqn.1-1.com.e:c.a.a0'},
|
||||||
@ -443,6 +449,13 @@ class CommonAdapterTest(test.TestCase):
|
|||||||
|
|
||||||
self.assertRaises(ex.DetachIsCalled, f)
|
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 test_terminate_connection_snapshot(self):
|
||||||
def f():
|
def f():
|
||||||
connector = {'host': 'host1'}
|
connector = {'host': 'host1'}
|
||||||
|
@ -100,6 +100,11 @@ class MockResource(object):
|
|||||||
if lun_or_snap.name == 'detach_failure':
|
if lun_or_snap.name == 'detach_failure':
|
||||||
raise ex.DetachIsCalled()
|
raise ex.DetachIsCalled()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def detach_from(host):
|
||||||
|
if host is None:
|
||||||
|
raise ex.DetachFromIsCalled()
|
||||||
|
|
||||||
def get_hlu(self, lun):
|
def get_hlu(self, lun):
|
||||||
return self.alu_hlu_map.get(lun.get_id(), None)
|
return self.alu_hlu_map.get(lun.get_id(), None)
|
||||||
|
|
||||||
@ -446,6 +451,13 @@ class ClientTest(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertRaises(ex.DetachIsCalled, f)
|
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')
|
@mock.patch.object(coordination.Coordinator, 'get_lock')
|
||||||
def test_create_host(self, fake):
|
def test_create_host(self, fake):
|
||||||
self.assertEqual('host2', self.client.create_host('host2').name)
|
self.assertEqual('host2', self.client.create_host('host2').name)
|
||||||
|
@ -312,6 +312,10 @@ class CommonAdapter(object):
|
|||||||
return self._initialize_connection(lun, connector, volume.id)
|
return self._initialize_connection(lun, connector, volume.id)
|
||||||
|
|
||||||
def _terminate_connection(self, lun_or_snap, connector):
|
def _terminate_connection(self, lun_or_snap, connector):
|
||||||
|
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'])
|
host = self.client.create_host(connector['host'])
|
||||||
self.client.detach(host, lun_or_snap)
|
self.client.detach(host, lun_or_snap)
|
||||||
|
|
||||||
|
@ -253,6 +253,15 @@ class UnityClient(object):
|
|||||||
lun_or_snap.update()
|
lun_or_snap.update()
|
||||||
host.detach(lun_or_snap)
|
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):
|
def get_ethernet_ports(self):
|
||||||
return self.system.get_ethernet_port()
|
return self.system.get_ethernet_port()
|
||||||
|
|
||||||
|
@ -301,6 +301,14 @@ For data path, please follow below steps:
|
|||||||
- If you create a volume using Cinder and attach it to a VM,
|
- If you create a volume using Cinder and attach it to a VM,
|
||||||
the connection between this VM and volume will be IPv6-based iSCSI.
|
the connection between this VM and volume will be IPv6-based iSCSI.
|
||||||
|
|
||||||
|
Force detach volume from all hosts
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The user could use `os-force_detach` action to detach a volume from all its
|
||||||
|
attached hosts.
|
||||||
|
For more detail, please refer to
|
||||||
|
https://developer.openstack.org/api-ref/block-storage/v2/?expanded=force-detach-volume-detail#force-detach-volume
|
||||||
|
|
||||||
Troubleshooting
|
Troubleshooting
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add support to force detach a volume from all hosts on Unity.
|
Loading…
Reference in New Issue
Block a user