Add client work for new cinder extensions.
* #5 of blueprint volume-decoupling * Fix pep8 Change-Id: Icad4eada0cf16a0f49d9a52e593bede0fc0c5289
This commit is contained in:
@@ -33,6 +33,49 @@ class Volume(base.Resource):
|
|||||||
"""
|
"""
|
||||||
self.manager.delete(self)
|
self.manager.delete(self)
|
||||||
|
|
||||||
|
def attach(self, instance_uuid, mountpoint):
|
||||||
|
"""
|
||||||
|
Set attachment metadata.
|
||||||
|
|
||||||
|
:param instance_uuid: uuid of the attaching instance.
|
||||||
|
:param mountpoint: mountpoint on the attaching instance.
|
||||||
|
"""
|
||||||
|
return self.manager.attach(self, instance_uuid, mountpoint)
|
||||||
|
|
||||||
|
def detach(self):
|
||||||
|
"""
|
||||||
|
Clear attachment metadata.
|
||||||
|
"""
|
||||||
|
return self.manager.detach(self)
|
||||||
|
|
||||||
|
def reserve(self, volume):
|
||||||
|
"""
|
||||||
|
Reserve this volume.
|
||||||
|
"""
|
||||||
|
return self.manager.reserve(self)
|
||||||
|
|
||||||
|
def unreserve(self, volume):
|
||||||
|
"""
|
||||||
|
Unreserve this volume.
|
||||||
|
"""
|
||||||
|
return self.manager.unreserve(self)
|
||||||
|
|
||||||
|
def initialize_connection(self, volume, connector):
|
||||||
|
"""
|
||||||
|
Initialize a volume connection.
|
||||||
|
|
||||||
|
:param connector: connector dict from nova.
|
||||||
|
"""
|
||||||
|
return self.manager.initialize_connection(self, connector)
|
||||||
|
|
||||||
|
def terminate_connection(self, volume, connector):
|
||||||
|
"""
|
||||||
|
Terminate a volume connection.
|
||||||
|
|
||||||
|
:param connector: connector dict from nova.
|
||||||
|
"""
|
||||||
|
return self.manager.terminate_connection(self, connector)
|
||||||
|
|
||||||
|
|
||||||
class VolumeManager(base.ManagerWithFind):
|
class VolumeManager(base.ManagerWithFind):
|
||||||
"""
|
"""
|
||||||
@@ -133,3 +176,73 @@ class VolumeManager(base.ManagerWithFind):
|
|||||||
"""
|
"""
|
||||||
self._delete("/servers/%s/os-volume_attachments/%s" %
|
self._delete("/servers/%s/os-volume_attachments/%s" %
|
||||||
(server_id, attachment_id,))
|
(server_id, attachment_id,))
|
||||||
|
|
||||||
|
def _action(self, action, volume, info=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Perform a volume "action."
|
||||||
|
"""
|
||||||
|
body = {action: info}
|
||||||
|
self.run_hooks('modify_body_for_action', body, **kwargs)
|
||||||
|
url = '/volumes/%s/action' % base.getid(volume)
|
||||||
|
return self.api.client.post(url, body=body)
|
||||||
|
|
||||||
|
def attach(self, volume, instance_uuid, mountpoint):
|
||||||
|
"""
|
||||||
|
Set attachment metadata.
|
||||||
|
|
||||||
|
:param server: 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.
|
||||||
|
"""
|
||||||
|
return self._action('os-attach',
|
||||||
|
volume,
|
||||||
|
{'instance_uuid': instance_uuid,
|
||||||
|
'mountpoint': mountpoint})
|
||||||
|
|
||||||
|
def detach(self, volume):
|
||||||
|
"""
|
||||||
|
Clear attachment metadata.
|
||||||
|
|
||||||
|
:param server: The :class:`Volume` (or its ID)
|
||||||
|
you would like to detach.
|
||||||
|
"""
|
||||||
|
return self._action('os-detach', volume)
|
||||||
|
|
||||||
|
def reserve(self, volume):
|
||||||
|
"""
|
||||||
|
Reserve this volume.
|
||||||
|
|
||||||
|
:param server: The :class:`Volume` (or its ID)
|
||||||
|
you would like to reserve.
|
||||||
|
"""
|
||||||
|
return self._action('os-reserve', volume)
|
||||||
|
|
||||||
|
def unreserve(self, volume):
|
||||||
|
"""
|
||||||
|
Unreserve this volume.
|
||||||
|
|
||||||
|
:param server: The :class:`Volume` (or its ID)
|
||||||
|
you would like to unreserve.
|
||||||
|
"""
|
||||||
|
return self._action('os-unreserve', volume)
|
||||||
|
|
||||||
|
def initialize_connection(self, volume, connector):
|
||||||
|
"""
|
||||||
|
Initialize a volume connection.
|
||||||
|
|
||||||
|
:param server: The :class:`Volume` (or its ID).
|
||||||
|
:param connector: connector dict from nova.
|
||||||
|
"""
|
||||||
|
return self._action('os-initialize_connection', volume,
|
||||||
|
{'connector': connector})[1]['connection_info']
|
||||||
|
|
||||||
|
def terminate_connection(self, volume, connector):
|
||||||
|
"""
|
||||||
|
Terminate a volume connection.
|
||||||
|
|
||||||
|
:param server: The :class:`Volume` (or its ID).
|
||||||
|
:param connector: connector dict from nova.
|
||||||
|
"""
|
||||||
|
self._action('os-terminate_connection', volume,
|
||||||
|
{'connector': connector})
|
||||||
|
@@ -145,6 +145,28 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
r = {'volume': self.get_volumes_detail()[1]['volumes'][0]}
|
r = {'volume': self.get_volumes_detail()[1]['volumes'][0]}
|
||||||
return (200, r)
|
return (200, r)
|
||||||
|
|
||||||
|
def post_volumes_1234_action(self, body, **kw):
|
||||||
|
_body = None
|
||||||
|
resp = 202
|
||||||
|
assert len(body.keys()) == 1
|
||||||
|
action = body.keys()[0]
|
||||||
|
if action == 'os-attach':
|
||||||
|
assert body[action].keys() == ['instance_uuid', 'mountpoint']
|
||||||
|
elif action == 'os-detach':
|
||||||
|
assert body[action] == None
|
||||||
|
elif action == 'os-reserve':
|
||||||
|
assert body[action] == None
|
||||||
|
elif action == 'os-unreserve':
|
||||||
|
assert body[action] == None
|
||||||
|
elif action == 'os-initialize_connection':
|
||||||
|
assert body[action].keys() == ['connector']
|
||||||
|
return (202, {'connection_info': 'foos'})
|
||||||
|
elif action == 'os-terminate_connection':
|
||||||
|
assert body[action].keys() == ['connector']
|
||||||
|
else:
|
||||||
|
raise AssertionError("Unexpected server action: %s" % action)
|
||||||
|
return (resp, _body)
|
||||||
|
|
||||||
def post_servers(self, body, **kw):
|
def post_servers(self, body, **kw):
|
||||||
assert set(body.keys()) <= set(['server', 'os:scheduler_hints'])
|
assert set(body.keys()) <= set(['server', 'os:scheduler_hints'])
|
||||||
fakes.assert_has_keys(body['server'],
|
fakes.assert_has_keys(body['server'],
|
||||||
@@ -168,6 +190,9 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
fakes.assert_has_keys(body['server'], optional=['name', 'adminPass'])
|
fakes.assert_has_keys(body['server'], optional=['name', 'adminPass'])
|
||||||
return (204, None)
|
return (204, None)
|
||||||
|
|
||||||
|
def post_volumes(self, **kw):
|
||||||
|
return (202, {'volume': {}})
|
||||||
|
|
||||||
def delete_servers_1234(self, **kw):
|
def delete_servers_1234(self, **kw):
|
||||||
return (202, None)
|
return (202, None)
|
||||||
|
|
||||||
|
52
tests/v1/test_volumes.py
Normal file
52
tests/v1/test_volumes.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
from cinderclient.v1 import volumes
|
||||||
|
from tests import utils
|
||||||
|
from tests.v1 import fakes
|
||||||
|
|
||||||
|
|
||||||
|
cs = fakes.FakeClient()
|
||||||
|
|
||||||
|
|
||||||
|
class VolumesTest(utils.TestCase):
|
||||||
|
|
||||||
|
def test_delete_volume(self):
|
||||||
|
v = cs.volumes.list()[0]
|
||||||
|
v.delete()
|
||||||
|
cs.assert_called('DELETE', '/volumes/1234')
|
||||||
|
cs.volumes.delete('1234')
|
||||||
|
cs.assert_called('DELETE', '/volumes/1234')
|
||||||
|
cs.volumes.delete(v)
|
||||||
|
cs.assert_called('DELETE', '/volumes/1234')
|
||||||
|
|
||||||
|
def test_create_keypair(self):
|
||||||
|
kp = cs.volumes.create(1)
|
||||||
|
cs.assert_called('POST', '/volumes')
|
||||||
|
|
||||||
|
def test_attach(self):
|
||||||
|
v = cs.volumes.get('1234')
|
||||||
|
cs.volumes.attach(v, 1, '/dev/vdc')
|
||||||
|
cs.assert_called('POST', '/volumes/1234/action')
|
||||||
|
|
||||||
|
def test_detach(self):
|
||||||
|
v = cs.volumes.get('1234')
|
||||||
|
cs.volumes.detach(v)
|
||||||
|
cs.assert_called('POST', '/volumes/1234/action')
|
||||||
|
|
||||||
|
def test_reserve(self):
|
||||||
|
v = cs.volumes.get('1234')
|
||||||
|
cs.volumes.reserve(v)
|
||||||
|
cs.assert_called('POST', '/volumes/1234/action')
|
||||||
|
|
||||||
|
def test_unreserve(self):
|
||||||
|
v = cs.volumes.get('1234')
|
||||||
|
cs.volumes.reserve(v)
|
||||||
|
cs.assert_called('POST', '/volumes/1234/action')
|
||||||
|
|
||||||
|
def test_initialize_connection(self):
|
||||||
|
v = cs.volumes.get('1234')
|
||||||
|
cs.volumes.initialize_connection(v, {})
|
||||||
|
cs.assert_called('POST', '/volumes/1234/action')
|
||||||
|
|
||||||
|
def test_terminate_connection(self):
|
||||||
|
v = cs.volumes.get('1234')
|
||||||
|
cs.volumes.terminate_connection(v, {})
|
||||||
|
cs.assert_called('POST', '/volumes/1234/action')
|
Reference in New Issue
Block a user