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)
|
||||
|
||||
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):
|
||||
"""
|
||||
@@ -133,3 +176,73 @@ class VolumeManager(base.ManagerWithFind):
|
||||
"""
|
||||
self._delete("/servers/%s/os-volume_attachments/%s" %
|
||||
(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]}
|
||||
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):
|
||||
assert set(body.keys()) <= set(['server', 'os:scheduler_hints'])
|
||||
fakes.assert_has_keys(body['server'],
|
||||
@@ -168,6 +190,9 @@ class FakeHTTPClient(base_client.HTTPClient):
|
||||
fakes.assert_has_keys(body['server'], optional=['name', 'adminPass'])
|
||||
return (204, None)
|
||||
|
||||
def post_volumes(self, **kw):
|
||||
return (202, {'volume': {}})
|
||||
|
||||
def delete_servers_1234(self, **kw):
|
||||
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