Add volume multi attach support
This patch adds the new multiattach flag during volume creation time. This patch adds the attachment_uuid during detach time so cinder knows which attachment it should detach. This patch is needed by Cinder's multi-attach-volume https://review.openstack.org/#/c/85847/ Change-Id: I98c6150cf548e9d1d8557770dbd3f88ec17a9b41 Implements: blueprint multi-attach-volume
This commit is contained in:

committed by
Walter A. Boring IV (hemna)

parent
9cb7232655
commit
480afa893a
@@ -40,6 +40,7 @@ def _stub_volume(**kwargs):
|
||||
"snapshot_id": None,
|
||||
"status": "available",
|
||||
"volume_type": "None",
|
||||
"multiattach": "false",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://localhost/v2/fake/volumes/1234",
|
||||
@@ -415,7 +416,7 @@ class FakeHTTPClient(base_client.HTTPClient):
|
||||
assert (keys == ['instance_uuid', 'mode', 'mountpoint'] or
|
||||
keys == ['host_name', 'mode', 'mountpoint'])
|
||||
elif action == 'os-detach':
|
||||
assert body[action] is None
|
||||
assert list(body[action]) == ['attachment_id']
|
||||
elif action == 'os-reserve':
|
||||
assert body[action] is None
|
||||
elif action == 'os-unreserve':
|
||||
|
@@ -125,7 +125,8 @@ class ShellTest(utils.TestCase):
|
||||
'snapshot_id': None,
|
||||
'metadata': {'key1': '"--test1"'},
|
||||
'volume_type': None,
|
||||
'description': None}}
|
||||
'description': None,
|
||||
'multiattach': False}}
|
||||
self.assert_called_anytime('POST', '/volumes', expected)
|
||||
|
||||
def test_metadata_args_limiter_display_name(self):
|
||||
@@ -145,7 +146,8 @@ class ShellTest(utils.TestCase):
|
||||
'snapshot_id': None,
|
||||
'metadata': {'key1': '"--t1"'},
|
||||
'volume_type': None,
|
||||
'description': None}}
|
||||
'description': None,
|
||||
'multiattach': False}}
|
||||
self.assert_called_anytime('POST', '/volumes', expected)
|
||||
|
||||
def test_delimit_metadata_args(self):
|
||||
@@ -165,7 +167,8 @@ class ShellTest(utils.TestCase):
|
||||
'metadata': {'key1': '"test1"',
|
||||
'key2': '"test2"'},
|
||||
'volume_type': None,
|
||||
'description': None}}
|
||||
'description': None,
|
||||
'multiattach': False}}
|
||||
self.assert_called_anytime('POST', '/volumes', expected)
|
||||
|
||||
def test_delimit_metadata_args_display_name(self):
|
||||
@@ -185,7 +188,8 @@ class ShellTest(utils.TestCase):
|
||||
'snapshot_id': None,
|
||||
'metadata': {'key1': '"t1"'},
|
||||
'volume_type': None,
|
||||
'description': None}}
|
||||
'description': None,
|
||||
'multiattach': False}}
|
||||
self.assert_called_anytime('POST', '/volumes', expected)
|
||||
|
||||
def test_list_filter_status(self):
|
||||
|
@@ -95,7 +95,8 @@ class VolumesTest(utils.TestCase):
|
||||
'project_id': None,
|
||||
'metadata': {},
|
||||
'source_replica': None,
|
||||
'consistencygroup_id': None},
|
||||
'consistencygroup_id': None,
|
||||
'multiattach': False},
|
||||
'OS-SCH-HNT:scheduler_hints': 'uuid'}
|
||||
cs.assert_called('POST', '/volumes', body=expected)
|
||||
|
||||
@@ -111,7 +112,7 @@ class VolumesTest(utils.TestCase):
|
||||
|
||||
def test_detach(self):
|
||||
v = cs.volumes.get('1234')
|
||||
cs.volumes.detach(v)
|
||||
cs.volumes.detach(v, 'abc123')
|
||||
cs.assert_called('POST', '/volumes/1234/action')
|
||||
|
||||
def test_reserve(self):
|
||||
|
@@ -234,10 +234,12 @@ def do_list(cs, args):
|
||||
|
||||
if all_tenants:
|
||||
key_list = ['ID', 'Tenant ID', 'Status', 'Name',
|
||||
'Size', 'Volume Type', 'Bootable', 'Attached to']
|
||||
'Size', 'Volume Type', 'Bootable', 'Multiattach',
|
||||
'Attached to']
|
||||
else:
|
||||
key_list = ['ID', 'Status', 'Name',
|
||||
'Size', 'Volume Type', 'Bootable', 'Attached to']
|
||||
'Size', 'Volume Type', 'Bootable',
|
||||
'Multiattach', 'Attached to']
|
||||
if args.sort_key or args.sort_dir or args.sort:
|
||||
sortby_index = None
|
||||
else:
|
||||
@@ -348,6 +350,12 @@ class CheckSizeArgForCreate(argparse.Action):
|
||||
action='append',
|
||||
default=[],
|
||||
help='Scheduler hint, like in nova.')
|
||||
@utils.arg('--allow-multiattach',
|
||||
dest='multiattach',
|
||||
action="store_true",
|
||||
help=('Allow volume to be attached more than once.'
|
||||
' Default=False'),
|
||||
default=False)
|
||||
@utils.service_type('volumev2')
|
||||
def do_create(cs, args):
|
||||
"""Creates a volume."""
|
||||
@@ -391,7 +399,8 @@ def do_create(cs, args):
|
||||
imageRef=image_ref,
|
||||
metadata=volume_metadata,
|
||||
scheduler_hints=hints,
|
||||
source_replica=args.source_replica)
|
||||
source_replica=args.source_replica,
|
||||
multiattach=args.multiattach)
|
||||
|
||||
info = dict()
|
||||
volume = cs.volumes.get(volume.id)
|
||||
|
@@ -179,8 +179,8 @@ class VolumeManager(base.ManagerWithFind):
|
||||
volume_type=None, user_id=None,
|
||||
project_id=None, availability_zone=None,
|
||||
metadata=None, imageRef=None, scheduler_hints=None,
|
||||
source_replica=None):
|
||||
"""Creates a volume.
|
||||
source_replica=None, multiattach=False):
|
||||
"""Create a volume.
|
||||
|
||||
:param size: Size of volume in GB
|
||||
:param consistencygroup_id: ID of the consistencygroup
|
||||
@@ -197,6 +197,8 @@ class VolumeManager(base.ManagerWithFind):
|
||||
:param source_replica: ID of source volume to clone replica
|
||||
:param scheduler_hints: (optional extension) arbitrary key-value pairs
|
||||
specified by the client to help boot an instance
|
||||
:param multiattach: Allow the volume to be attached to more than
|
||||
one instance
|
||||
:rtype: :class:`Volume`
|
||||
"""
|
||||
if metadata is None:
|
||||
@@ -219,6 +221,7 @@ class VolumeManager(base.ManagerWithFind):
|
||||
'imageRef': imageRef,
|
||||
'source_volid': source_volid,
|
||||
'source_replica': source_replica,
|
||||
'multiattach': multiattach,
|
||||
}}
|
||||
|
||||
if scheduler_hints:
|
||||
@@ -393,13 +396,15 @@ class VolumeManager(base.ManagerWithFind):
|
||||
body.update({'host_name': host_name})
|
||||
return self._action('os-attach', volume, body)
|
||||
|
||||
def detach(self, volume):
|
||||
def detach(self, volume, attachment_uuid=None):
|
||||
"""Clear attachment metadata.
|
||||
|
||||
:param volume: The :class:`Volume` (or its ID)
|
||||
you would like to detach.
|
||||
:param attachment_uuid: The uuid of the volume attachment.
|
||||
"""
|
||||
return self._action('os-detach', volume)
|
||||
return self._action('os-detach', volume,
|
||||
{'attachment_id': attachment_uuid})
|
||||
|
||||
def reserve(self, volume):
|
||||
"""Reserve this volume.
|
||||
|
Reference in New Issue
Block a user