Support host-attach of volumes

This patch adds the host_name optional argument to attach API
in order to enable users of cinderclient to attach volumes
not only to the instances but also to the hosts.

The API interface is implemented in
https://review.openstack.org/#/c/34125/ .

Change-Id: I0ff8ef19d1e3073fee1b9ec0f60609c37dfab9ab
Implements: blueprint host-attach
This commit is contained in:
Tomoki Sekiyama
2015-03-31 18:30:14 -04:00
parent 2f97e1e3ca
commit e1ff87378a
6 changed files with 47 additions and 26 deletions

View File

@@ -330,9 +330,9 @@ class FakeHTTPClient(base_client.HTTPClient):
assert len(list(body)) == 1
action = list(body)[0]
if action == 'os-attach':
assert sorted(list(body[action])) == ['instance_uuid',
'mode',
'mountpoint']
keys = sorted(list(body[action]))
assert (keys == ['instance_uuid', 'mode', 'mountpoint'] or
keys == ['host_name', 'mode', 'mountpoint'])
elif action == 'os-detach':
assert body[action] is None
elif action == 'os-reserve':

View File

@@ -38,6 +38,11 @@ class VolumesTest(utils.TestCase):
cs.volumes.attach(v, 1, '/dev/vdc', mode='rw')
cs.assert_called('POST', '/volumes/1234/action')
def test_attach_to_host(self):
v = cs.volumes.get('1234')
cs.volumes.attach(v, None, None, host_name='test', mode='rw')
cs.assert_called('POST', '/volumes/1234/action')
def test_detach(self):
v = cs.volumes.get('1234')
cs.volumes.detach(v)

View File

@@ -411,9 +411,9 @@ class FakeHTTPClient(base_client.HTTPClient):
assert len(list(body)) == 1
action = list(body)[0]
if action == 'os-attach':
assert sorted(list(body[action])) == ['instance_uuid',
'mode',
'mountpoint']
keys = sorted(list(body[action]))
assert (keys == ['instance_uuid', 'mode', 'mountpoint'] or
keys == ['host_name', 'mode', 'mountpoint'])
elif action == 'os-detach':
assert body[action] is None
elif action == 'os-reserve':

View File

@@ -104,6 +104,11 @@ class VolumesTest(utils.TestCase):
cs.volumes.attach(v, 1, '/dev/vdc', mode='ro')
cs.assert_called('POST', '/volumes/1234/action')
def test_attach_to_host(self):
v = cs.volumes.get('1234')
cs.volumes.attach(v, None, None, host_name='test', mode='rw')
cs.assert_called('POST', '/volumes/1234/action')
def test_detach(self):
v = cs.volumes.get('1234')
cs.volumes.detach(v)

View File

@@ -40,14 +40,17 @@ class Volume(base.Resource):
"""Update the display_name or display_description for this volume."""
self.manager.update(self, **kwargs)
def attach(self, instance_uuid, mountpoint, mode='rw'):
def attach(self, instance_uuid, mountpoint, mode='rw',
host_name=None):
"""Set attachment metadata.
:param instance_uuid: uuid of the attaching instance.
:param mountpoint: mountpoint on the attaching instance.
:param mountpoint: mountpoint on the attaching instance or host.
:param mode: the access mode
:param host_name: name of the attaching host.
"""
return self.manager.attach(self, instance_uuid, mountpoint, mode)
return self.manager.attach(self, instance_uuid, mountpoint, mode,
host_name)
def detach(self):
"""Clear attachment metadata."""
@@ -255,21 +258,24 @@ class VolumeManager(base.ManagerWithFind):
url = '/volumes/%s/action' % base.getid(volume)
return self.api.client.post(url, body=body)
def attach(self, volume, instance_uuid, mountpoint, mode='rw'):
def attach(self, volume, instance_uuid, mountpoint, mode='rw',
host_name=None):
"""
Set attachment metadata.
:param volume: The :class:`Volume` (or its ID)
you would like to attach.
:param instance_uuid: uuid of the attaching instance.
:param instance_uuid: uuid of the attaching instance or host.
:param mountpoint: mountpoint on the attaching instance.
:param mode: the access mode.
:param host_name: name of the attaching host.
"""
return self._action('os-attach',
volume,
{'instance_uuid': instance_uuid,
'mountpoint': mountpoint,
'mode': mode})
body = {'mountpoint': mountpoint, 'mode': mode}
if instance_uuid is not None:
body.update({'instance_uuid': instance_uuid})
if host_name is not None:
body.update({'host_name': host_name})
return self._action('os-attach', volume, body)
def detach(self, volume):
"""

View File

@@ -45,14 +45,16 @@ class Volume(base.Resource):
"""Update the name or description for this volume."""
self.manager.update(self, **kwargs)
def attach(self, instance_uuid, mountpoint, mode='rw'):
def attach(self, instance_uuid, mountpoint, mode='rw', host_name=None):
"""Set attachment metadata.
:param instance_uuid: uuid of the attaching instance.
:param mountpoint: mountpoint on the attaching instance.
:param mountpoint: mountpoint on the attaching instance or host.
:param mode: the access mode.
:param host_name: name of the attaching host.
"""
return self.manager.attach(self, instance_uuid, mountpoint, mode)
return self.manager.attach(self, instance_uuid, mountpoint, mode,
host_name)
def detach(self):
"""Clear attachment metadata."""
@@ -374,20 +376,23 @@ class VolumeManager(base.ManagerWithFind):
url = '/volumes/%s/action' % base.getid(volume)
return self.api.client.post(url, body=body)
def attach(self, volume, instance_uuid, mountpoint, mode='rw'):
def attach(self, volume, instance_uuid, mountpoint, mode='rw',
host_name=None):
"""Set attachment metadata.
:param volume: The :class:`Volume` (or its ID)
you would like to attach.
:param instance_uuid: uuid of the attaching instance.
:param mountpoint: mountpoint on the attaching instance.
:param mountpoint: mountpoint on the attaching instance or host.
:param mode: the access mode.
:param host_name: name of the attaching host.
"""
return self._action('os-attach',
volume,
{'instance_uuid': instance_uuid,
'mountpoint': mountpoint,
'mode': mode})
body = {'mountpoint': mountpoint, 'mode': mode}
if instance_uuid is not None:
body.update({'instance_uuid': instance_uuid})
if host_name is not None:
body.update({'host_name': host_name})
return self._action('os-attach', volume, body)
def detach(self, volume):
"""Clear attachment metadata.