summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-07-20 22:28:10 +0000
committerGerrit Code Review <review@openstack.org>2015-07-20 22:28:10 +0000
commit26ea98b30e2c9573eb96378e3689f577d11940a8 (patch)
tree6c48281190d24660ea6726e5a0db186efd7ed287
parent7442c018d2b52cc88372ecc966436a88fe7c96ac (diff)
parent659abf492825b71b99e6f4be58447d6f393e33ef (diff)
downloadpython-openstackclient-26ea98b30e2c9573eb96378e3689f577d11940a8.tar.gz
Merge "Add create and list for volume type v2"
-rw-r--r--doc/source/command-objects/volume-type.rst26
-rw-r--r--openstackclient/tests/volume/v2/test_type.py129
-rw-r--r--openstackclient/volume/v2/volume_type.py97
-rw-r--r--setup.cfg2
4 files changed, 253 insertions, 1 deletions
diff --git a/doc/source/command-objects/volume-type.rst b/doc/source/command-objects/volume-type.rst
index 0898df52..4d5651ac 100644
--- a/doc/source/command-objects/volume-type.rst
+++ b/doc/source/command-objects/volume-type.rst
@@ -2,7 +2,7 @@
volume type
===========
-Volume v1
+Volume v1, v2
volume type create
------------------
@@ -13,9 +13,29 @@ Create new volume type
.. code:: bash
os volume type create
+ [--description <description>]
+ [--public | --private]
[--property <key=value> [...] ]
<name>
+.. option:: --description <description>
+
+ New volume type description
+
+ .. versionadded:: 2
+
+.. option:: --public
+
+ Volume type is accessible to the public
+
+ .. versionadded:: 2
+
+.. option:: --private
+
+ Volume type is not accessible to the public
+
+ .. versionadded:: 2
+
.. option:: --property <key=value>
Set a property on this volume type (repeat option to set multiple properties)
@@ -57,6 +77,8 @@ List volume types
volume type set
---------------
+*Only supported for Volume API v1*
+
Set volume type properties
.. program:: volume type set
@@ -77,6 +99,8 @@ Set volume type properties
volume type unset
-----------------
+*Only supported for Volume API v1*
+
Unset volume type properties
.. program:: volume type unset
diff --git a/openstackclient/tests/volume/v2/test_type.py b/openstackclient/tests/volume/v2/test_type.py
index a6e91e8d..c5b27fa5 100644
--- a/openstackclient/tests/volume/v2/test_type.py
+++ b/openstackclient/tests/volume/v2/test_type.py
@@ -28,6 +28,135 @@ class TestType(volume_fakes.TestVolume):
self.types_mock.reset_mock()
+class TestTypeCreate(TestType):
+
+ def setUp(self):
+ super(TestTypeCreate, self).setUp()
+
+ self.types_mock.create.return_value = fakes.FakeResource(
+ None,
+ copy.deepcopy(volume_fakes.TYPE),
+ loaded=True,
+ )
+ # Get the command object to test
+ self.cmd = volume_type.CreateVolumeType(self.app, None)
+
+ def test_type_create_public(self):
+ arglist = [
+ volume_fakes.type_name,
+ "--description", volume_fakes.type_description,
+ "--public"
+ ]
+ verifylist = [
+ ("name", volume_fakes.type_name),
+ ("description", volume_fakes.type_description),
+ ("public", True),
+ ("private", False),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+ self.types_mock.create.assert_called_with(
+ volume_fakes.type_name,
+ description=volume_fakes.type_description,
+ public=True,
+ )
+
+ collist = (
+ 'description',
+ 'id',
+ 'name',
+ )
+ self.assertEqual(collist, columns)
+ datalist = (
+ volume_fakes.type_description,
+ volume_fakes.type_id,
+ volume_fakes.type_name,
+ )
+ self.assertEqual(datalist, data)
+
+ def test_type_create_private(self):
+ arglist = [
+ volume_fakes.type_name,
+ "--description", volume_fakes.type_description,
+ "--private"
+ ]
+ verifylist = [
+ ("name", volume_fakes.type_name),
+ ("description", volume_fakes.type_description),
+ ("public", False),
+ ("private", True),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+ self.types_mock.create.assert_called_with(
+ volume_fakes.type_name,
+ description=volume_fakes.type_description,
+ private=True,
+ )
+
+ collist = (
+ 'description',
+ 'id',
+ 'name',
+ )
+ self.assertEqual(collist, columns)
+ datalist = (
+ volume_fakes.type_description,
+ volume_fakes.type_id,
+ volume_fakes.type_name,
+ )
+ self.assertEqual(datalist, data)
+
+
+class TestTypeList(TestType):
+ def setUp(self):
+ super(TestTypeList, self).setUp()
+
+ self.types_mock.list.return_value = [
+ fakes.FakeResource(
+ None,
+ copy.deepcopy(volume_fakes.TYPE),
+ loaded=True
+ )
+ ]
+ # get the command to test
+ self.cmd = volume_type.ListVolumeType(self.app, None)
+
+ def test_type_list_without_options(self):
+ arglist = []
+ verifylist = [
+ ("long", False)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+ collist = ["ID", "Name"]
+ self.assertEqual(collist, columns)
+ datalist = ((
+ volume_fakes.type_id,
+ volume_fakes.type_name,
+ ),)
+ self.assertEqual(datalist, tuple(data))
+
+ def test_type_list_with_options(self):
+ arglist = ["--long"]
+ verifylist = [("long", True)]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+ collist = ["ID", "Name", "Description", "Properties"]
+ self.assertEqual(collist, columns)
+ datalist = ((
+ volume_fakes.type_id,
+ volume_fakes.type_name,
+ volume_fakes.type_description,
+ "foo='bar'"
+ ),)
+ self.assertEqual(datalist, tuple(data))
+
+
class TestTypeShow(TestType):
def setUp(self):
super(TestTypeShow, self).setUp()
diff --git a/openstackclient/volume/v2/volume_type.py b/openstackclient/volume/v2/volume_type.py
index c724d867..7f9a1c4b 100644
--- a/openstackclient/volume/v2/volume_type.py
+++ b/openstackclient/volume/v2/volume_type.py
@@ -17,12 +17,79 @@
import logging
from cliff import command
+from cliff import lister
from cliff import show
import six
+from openstackclient.common import parseractions
from openstackclient.common import utils
+class CreateVolumeType(show.ShowOne):
+ """Create new volume type"""
+
+ log = logging.getLogger(__name__ + ".CreateVolumeType")
+
+ def get_parser(self, prog_name):
+ parser = super(CreateVolumeType, self).get_parser(prog_name)
+ parser.add_argument(
+ "name",
+ metavar="<name>",
+ help="New volume type name"
+ )
+ parser.add_argument(
+ "--description",
+ metavar="<description>",
+ help="New volume type description",
+ )
+ public_group = parser.add_mutually_exclusive_group()
+ public_group.add_argument(
+ "--public",
+ dest="public",
+ action="store_true",
+ default=False,
+ help="Volume type is accessible to the public",
+ )
+ public_group.add_argument(
+ "--private",
+ dest="private",
+ action="store_true",
+ default=False,
+ help="Volume type is not accessible to the public",
+ )
+ parser.add_argument(
+ '--property',
+ metavar='<key=value>',
+ action=parseractions.KeyValueAction,
+ help='Property to add for this volume type'
+ '(repeat option to set multiple properties)',
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ self.log.debug('take_action(%s)', parsed_args)
+
+ volume_client = self.app.client_manager.volume
+
+ kwargs = {}
+ if parsed_args.public:
+ kwargs['public'] = True
+ if parsed_args.private:
+ kwargs['private'] = True
+
+ volume_type = volume_client.volume_types.create(
+ parsed_args.name,
+ description=parsed_args.description,
+ **kwargs
+ )
+ volume_type._info.pop('extra_specs')
+ if parsed_args.property:
+ result = volume_type.set_keys(parsed_args.property)
+ volume_type._info.update({'properties': utils.format_dict(result)})
+
+ return zip(*sorted(six.iteritems(volume_type._info)))
+
+
class DeleteVolumeType(command.Command):
"""Delete volume type"""
@@ -46,6 +113,36 @@ class DeleteVolumeType(command.Command):
return
+class ListVolumeType(lister.Lister):
+ """List volume types"""
+
+ log = logging.getLogger(__name__ + '.ListVolumeType')
+
+ def get_parser(self, prog_name):
+ parser = super(ListVolumeType, self).get_parser(prog_name)
+ parser.add_argument(
+ '--long',
+ action='store_true',
+ default=False,
+ help='List additional fields in output')
+ return parser
+
+ def take_action(self, parsed_args):
+ self.log.debug('take_action(%s)', parsed_args)
+ if parsed_args.long:
+ columns = ['ID', 'Name', 'Description', 'Extra Specs']
+ column_headers = ['ID', 'Name', 'Description', 'Properties']
+ else:
+ columns = ['ID', 'Name']
+ column_headers = columns
+ data = self.app.client_manager.volume.volume_types.list()
+ return (column_headers,
+ (utils.get_item_properties(
+ s, columns,
+ formatters={'Extra Specs': utils.format_dict},
+ ) for s in data))
+
+
class ShowVolumeType(show.ShowOne):
"""Display volume type details"""
diff --git a/setup.cfg b/setup.cfg
index 314de371..c9540732 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -395,7 +395,9 @@ openstack.volume.v2 =
volume_delete = openstackclient.volume.v2.volume:DeleteVolume
volume_show = openstackclient.volume.v2.volume:ShowVolume
+ volume_type_create = openstackclient.volume.v2.volume_type:CreateVolumeType
volume_type_delete = openstackclient.volume.v2.volume_type:DeleteVolumeType
+ volume_type_list = openstackclient.volume.v2.volume_type:ListVolumeType
volume_type_show = openstackclient.volume.v2.volume_type:ShowVolumeType
volume_qos_associate = openstackclient.volume.v2.qos_specs:AssociateQos