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):
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.
"""
@ -50,7 +65,17 @@ class FakeClient(object):
if body is not None:
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.
"""
@ -77,6 +102,15 @@ class FakeClient(object):
print(body)
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):
self.client.callstack = []

View File

@ -376,7 +376,9 @@ class FakeHTTPClient(base_client.HTTPClient):
return self.post_volumes_1234_action(body, **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):
return (202, {}, None)

View File

@ -14,13 +14,13 @@
# under the License.
import fixtures
import httpretty
from cinderclient import client
from cinderclient import shell
from cinderclient.tests import utils
from cinderclient.tests.v2 import fakes
from cinderclient.tests.fixture_data import keystone_client
import httpretty
class ShellTest(utils.TestCase):
@ -66,11 +66,15 @@ class ShellTest(utils.TestCase):
def run_command(self, cmd):
self.shell.main(cmd.split())
def assert_called(self, method, url, body=None, **kwargs):
return self.shell.cs.assert_called(method, url, body, **kwargs)
def assert_called(self, method, url, body=None,
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):
return self.shell.cs.assert_called_anytime(method, url, body)
def assert_called_anytime(self, method, url, body=None,
partial_body=None):
return self.shell.cs.assert_called_anytime(method, url, body,
partial_body)
@httpretty.activate
def test_list(self):
@ -103,6 +107,41 @@ class ShellTest(utils.TestCase):
self.run_command('availability-zone-list')
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
def test_show(self):
self.register_keystone_auth_fixture()

View File

@ -195,10 +195,21 @@ def do_show(cs, args):
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',
metavar='<size>',
nargs='?',
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',
metavar='<snapshot-id>',
default=None,