Optional size parameter for volume creation

This patch makes optional the parameter size
for creating a volume from a snapshot or other
volume.
The parameter is still required for other
kind of volume creation.

Change-Id: I75dcf0e647f6e82a2407bcf23ef359f5f87323e8
Closes-Bug: #1304463
This commit is contained in:
Juan Manuel Olle 2014-04-08 16:38:36 -03:00
parent 9485337b0e
commit bd361644f7
4 changed files with 95 additions and 9 deletions

View File

@ -34,7 +34,22 @@ def assert_has_keys(dict, required=[], optional=[]):
class FakeClient(object): class FakeClient(object):
def assert_called(self, method, url, body=None, pos=-1, **kwargs): def _dict_match(self, partial, real):
result = True
try:
for key, value in partial.items():
if type(value) is dict:
result = self._dict_match(value, real[key])
else:
assert real[key] == value
result = True
except (AssertionError, KeyError):
result = False
return result
def assert_called(self, method, url, body=None,
partial_body=None, pos=-1, **kwargs):
""" """
Assert than an API method was just called. Assert than an API method was just called.
""" """
@ -50,7 +65,17 @@ class FakeClient(object):
if body is not None: if body is not None:
assert self.client.callstack[pos][2] == body assert self.client.callstack[pos][2] == body
def assert_called_anytime(self, method, url, body=None): if partial_body is not None:
try:
assert self._dict_match(partial_body,
self.client.callstack[pos][2])
except AssertionError:
print(self.client.callstack[pos][2])
print("does not contain")
print(partial_body)
raise
def assert_called_anytime(self, method, url, body=None, partial_body=None):
""" """
Assert than an API method was called anytime in the test. Assert than an API method was called anytime in the test.
""" """
@ -77,6 +102,15 @@ class FakeClient(object):
print(body) print(body)
raise raise
if partial_body is not None:
try:
assert self._dict_match(partial_body, entry[2])
except AssertionError:
print(entry[2])
print("does not contain")
print(partial_body)
raise
def clear_callstack(self): def clear_callstack(self):
self.client.callstack = [] self.client.callstack = []

View File

@ -376,7 +376,9 @@ class FakeHTTPClient(base_client.HTTPClient):
return self.post_volumes_1234_action(body, **kw) return self.post_volumes_1234_action(body, **kw)
def post_volumes(self, **kw): def post_volumes(self, **kw):
return (202, {}, {'volume': {}}) size = kw['body']['volume'].get('size', 1)
volume = _stub_volume(id='1234', size=size)
return (202, {}, {'volume': volume})
def delete_volumes_1234(self, **kw): def delete_volumes_1234(self, **kw):
return (202, {}, None) return (202, {}, None)

View File

@ -14,13 +14,13 @@
# under the License. # under the License.
import fixtures import fixtures
import httpretty
from cinderclient import client from cinderclient import client
from cinderclient import shell from cinderclient import shell
from cinderclient.tests import utils from cinderclient.tests import utils
from cinderclient.tests.v2 import fakes from cinderclient.tests.v2 import fakes
from cinderclient.tests.fixture_data import keystone_client from cinderclient.tests.fixture_data import keystone_client
import httpretty
class ShellTest(utils.TestCase): class ShellTest(utils.TestCase):
@ -66,11 +66,15 @@ class ShellTest(utils.TestCase):
def run_command(self, cmd): def run_command(self, cmd):
self.shell.main(cmd.split()) self.shell.main(cmd.split())
def assert_called(self, method, url, body=None, **kwargs): def assert_called(self, method, url, body=None,
return self.shell.cs.assert_called(method, url, body, **kwargs) partial_body=None, **kwargs):
return self.shell.cs.assert_called(method, url, body,
partial_body, **kwargs)
def assert_called_anytime(self, method, url, body=None): def assert_called_anytime(self, method, url, body=None,
return self.shell.cs.assert_called_anytime(method, url, body) partial_body=None):
return self.shell.cs.assert_called_anytime(method, url, body,
partial_body)
@httpretty.activate @httpretty.activate
def test_list(self): def test_list(self):
@ -103,6 +107,41 @@ class ShellTest(utils.TestCase):
self.run_command('availability-zone-list') self.run_command('availability-zone-list')
self.assert_called('GET', '/os-availability-zone') self.assert_called('GET', '/os-availability-zone')
@httpretty.activate
def test_create_volume_from_snapshot(self):
self.register_keystone_auth_fixture()
expected = {'volume': {'size': None}}
expected['volume']['snapshot_id'] = '1234'
self.run_command('create --snapshot-id=1234')
self.assert_called_anytime('POST', '/volumes', partial_body=expected)
self.assert_called('GET', '/volumes/1234')
expected['volume']['size'] = 2
self.run_command('create --snapshot-id=1234 2')
self.assert_called_anytime('POST', '/volumes', partial_body=expected)
self.assert_called('GET', '/volumes/1234')
@httpretty.activate
def test_create_volume_from_volume(self):
self.register_keystone_auth_fixture()
expected = {'volume': {'size': None}}
expected['volume']['source_volid'] = '1234'
self.run_command('create --source-volid=1234')
self.assert_called_anytime('POST', '/volumes', partial_body=expected)
self.assert_called('GET', '/volumes/1234')
expected['volume']['size'] = 2
self.run_command('create --source-volid=1234 2')
self.assert_called_anytime('POST', '/volumes', partial_body=expected)
self.assert_called('GET', '/volumes/1234')
@httpretty.activate
def test_create_size_required_if_not_snapshot_or_clone(self):
self.register_keystone_auth_fixture()
self.assertRaises(SystemExit, self.run_command, 'create')
@httpretty.activate @httpretty.activate
def test_show(self): def test_show(self):
self.register_keystone_auth_fixture() self.register_keystone_auth_fixture()

View File

@ -195,10 +195,21 @@ def do_show(cs, args):
utils.print_dict(info) utils.print_dict(info)
class CheckSizeArgForCreate(argparse.Action):
def __call__(self, parser, args, values, option_string=None):
if (values or args.snapshot_id or args.source_volid) is None:
parser.error('Size is a required parameter if snapshot '
'or source volume is not specified.')
setattr(args, self.dest, values)
@utils.arg('size', @utils.arg('size',
metavar='<size>', metavar='<size>',
nargs='?',
type=int, type=int,
help='Size of volume, in GBs.') action=CheckSizeArgForCreate,
help='Size of volume, in GBs. (Required unless '
'snapshot-id/source-volid is specified).')
@utils.arg('--snapshot-id', @utils.arg('--snapshot-id',
metavar='<snapshot-id>', metavar='<snapshot-id>',
default=None, default=None,