summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2014-07-24 16:01:34 +0000
committerGerrit Code Review <review@openstack.org>2014-07-24 16:01:34 +0000
commit15cbd66138ba14d1bedc94a793d9ed22b97a518f (patch)
tree8c36162d0adc270f25035f15395b44c723174976
parent0c4010e7fbc9939905e8647afbe1358c384dc658 (diff)
parentbd361644f73b7a688d45f67621b1a08f513fa024 (diff)
downloadpython-cinderclient-15cbd66138ba14d1bedc94a793d9ed22b97a518f.tar.gz
Merge "Optional size parameter for volume creation"
-rw-r--r--cinderclient/tests/fakes.py38
-rw-r--r--cinderclient/tests/v2/fakes.py4
-rw-r--r--cinderclient/tests/v2/test_shell.py49
-rw-r--r--cinderclient/v2/shell.py13
4 files changed, 95 insertions, 9 deletions
diff --git a/cinderclient/tests/fakes.py b/cinderclient/tests/fakes.py
index 5a3937c..eede694 100644
--- a/cinderclient/tests/fakes.py
+++ b/cinderclient/tests/fakes.py
@@ -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 = []
diff --git a/cinderclient/tests/v2/fakes.py b/cinderclient/tests/v2/fakes.py
index 98f3500..b8dfe27 100644
--- a/cinderclient/tests/v2/fakes.py
+++ b/cinderclient/tests/v2/fakes.py
@@ -378,7 +378,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)
diff --git a/cinderclient/tests/v2/test_shell.py b/cinderclient/tests/v2/test_shell.py
index a52bd10..69b3631 100644
--- a/cinderclient/tests/v2/test_shell.py
+++ b/cinderclient/tests/v2/test_shell.py
@@ -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):
@@ -104,6 +108,41 @@ class ShellTest(utils.TestCase):
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()
self.run_command('show 1234')
diff --git a/cinderclient/v2/shell.py b/cinderclient/v2/shell.py
index 4842709..34283f7 100644
--- a/cinderclient/v2/shell.py
+++ b/cinderclient/v2/shell.py
@@ -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,