Add "--property" option to "flavor create" command
Add "--property" option to "flavor create" command to support adding properties to a new falvor. Change-Id: I4f06b364375d5a81584fe41122d48e9568fa712a Closes-Bug: #1596798
This commit is contained in:
parent
9e47688e5e
commit
dbed97a24d
@ -21,6 +21,7 @@ Create new flavor
|
|||||||
[--vcpus <num-cpu>]
|
[--vcpus <num-cpu>]
|
||||||
[--rxtx-factor <factor>]
|
[--rxtx-factor <factor>]
|
||||||
[--public | --private]
|
[--public | --private]
|
||||||
|
[--property <key=value> [...] ]
|
||||||
[--project <project>]
|
[--project <project>]
|
||||||
[--project-domain <project-domain>]
|
[--project-domain <project-domain>]
|
||||||
<flavor-name>
|
<flavor-name>
|
||||||
@ -61,6 +62,10 @@ Create new flavor
|
|||||||
|
|
||||||
Flavor is not available to other projects
|
Flavor is not available to other projects
|
||||||
|
|
||||||
|
.. option:: --property <key=value>
|
||||||
|
|
||||||
|
Property to add for this flavor (repeat option to set multiple properties)
|
||||||
|
|
||||||
.. option:: --project <project>
|
.. option:: --project <project>
|
||||||
|
|
||||||
Allow <project> to access private flavor (name or ID)
|
Allow <project> to access private flavor (name or ID)
|
||||||
|
@ -25,7 +25,8 @@ class FlavorTests(test.TestCase):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
opts = cls.get_show_opts(cls.FIELDS)
|
opts = cls.get_show_opts(cls.FIELDS)
|
||||||
raw_output = cls.openstack('flavor create ' + cls.NAME + opts)
|
raw_output = cls.openstack(
|
||||||
|
'flavor create --property a=b --property c=d ' + cls.NAME + opts)
|
||||||
expected = cls.NAME + '\n'
|
expected = cls.NAME + '\n'
|
||||||
cls.assertOutput(expected, raw_output)
|
cls.assertOutput(expected, raw_output)
|
||||||
|
|
||||||
@ -47,19 +48,22 @@ class FlavorTests(test.TestCase):
|
|||||||
|
|
||||||
def test_flavor_properties(self):
|
def test_flavor_properties(self):
|
||||||
opts = self.get_show_opts(['properties'])
|
opts = self.get_show_opts(['properties'])
|
||||||
|
# check the properties we added in create command.
|
||||||
raw_output = self.openstack(
|
|
||||||
'flavor set --property a=b --property c=d ' + self.NAME
|
|
||||||
)
|
|
||||||
self.assertEqual('', raw_output)
|
|
||||||
|
|
||||||
raw_output = self.openstack('flavor show ' + self.NAME + opts)
|
raw_output = self.openstack('flavor show ' + self.NAME + opts)
|
||||||
self.assertEqual("a='b', c='d'\n", raw_output)
|
self.assertEqual("a='b', c='d'\n", raw_output)
|
||||||
|
|
||||||
raw_output = self.openstack(
|
raw_output = self.openstack(
|
||||||
'flavor unset --property a ' + self.NAME
|
'flavor set --property e=f --property g=h ' + self.NAME
|
||||||
)
|
)
|
||||||
self.assertEqual('', raw_output)
|
self.assertEqual('', raw_output)
|
||||||
|
|
||||||
raw_output = self.openstack('flavor show ' + self.NAME + opts)
|
raw_output = self.openstack('flavor show ' + self.NAME + opts)
|
||||||
self.assertEqual("c='d'\n", raw_output)
|
self.assertEqual("a='b', c='d', e='f', g='h'\n", raw_output)
|
||||||
|
|
||||||
|
raw_output = self.openstack(
|
||||||
|
'flavor unset --property a --property c ' + self.NAME
|
||||||
|
)
|
||||||
|
self.assertEqual('', raw_output)
|
||||||
|
|
||||||
|
raw_output = self.openstack('flavor show ' + self.NAME + opts)
|
||||||
|
self.assertEqual("e='f', g='h'\n", raw_output)
|
||||||
|
@ -121,6 +121,13 @@ class CreateFlavor(command.ShowOne):
|
|||||||
action="store_false",
|
action="store_false",
|
||||||
help=_("Flavor is not available to other projects")
|
help=_("Flavor is not available to other projects")
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--property",
|
||||||
|
metavar="<key=value>",
|
||||||
|
action=parseractions.KeyValueAction,
|
||||||
|
help=_("Property to add for this flavor "
|
||||||
|
"(repeat option to set multiple properties)")
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--project',
|
'--project',
|
||||||
metavar='<project>',
|
metavar='<project>',
|
||||||
@ -150,8 +157,7 @@ class CreateFlavor(command.ShowOne):
|
|||||||
parsed_args.public
|
parsed_args.public
|
||||||
)
|
)
|
||||||
|
|
||||||
flavor = compute_client.flavors.create(*args)._info.copy()
|
flavor = compute_client.flavors.create(*args)
|
||||||
flavor.pop("links")
|
|
||||||
|
|
||||||
if parsed_args.project:
|
if parsed_args.project:
|
||||||
try:
|
try:
|
||||||
@ -166,8 +172,17 @@ class CreateFlavor(command.ShowOne):
|
|||||||
msg = _("Failed to add project %(project)s access to "
|
msg = _("Failed to add project %(project)s access to "
|
||||||
"flavor: %(e)s")
|
"flavor: %(e)s")
|
||||||
LOG.error(msg % {'project': parsed_args.project, 'e': e})
|
LOG.error(msg % {'project': parsed_args.project, 'e': e})
|
||||||
|
if parsed_args.property:
|
||||||
|
try:
|
||||||
|
flavor.set_keys(parsed_args.property)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.error(_("Failed to set flavor property: %s"), e)
|
||||||
|
|
||||||
return zip(*sorted(six.iteritems(flavor)))
|
flavor_info = flavor._info.copy()
|
||||||
|
flavor_info.pop("links")
|
||||||
|
flavor_info['properties'] = utils.format_dict(flavor.get_keys())
|
||||||
|
|
||||||
|
return zip(*sorted(six.iteritems(flavor_info)))
|
||||||
|
|
||||||
|
|
||||||
class DeleteFlavor(command.Command):
|
class DeleteFlavor(command.Command):
|
||||||
|
@ -716,6 +716,7 @@ class FakeFlavor(object):
|
|||||||
'OS-FLV-DISABLED:disabled': False,
|
'OS-FLV-DISABLED:disabled': False,
|
||||||
'os-flavor-access:is_public': True,
|
'os-flavor-access:is_public': True,
|
||||||
'OS-FLV-EXT-DATA:ephemeral': 0,
|
'OS-FLV-EXT-DATA:ephemeral': 0,
|
||||||
|
'properties': {'property': 'value'},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Overwrite default attributes.
|
# Overwrite default attributes.
|
||||||
|
@ -56,6 +56,7 @@ class TestFlavorCreate(TestFlavor):
|
|||||||
'id',
|
'id',
|
||||||
'name',
|
'name',
|
||||||
'os-flavor-access:is_public',
|
'os-flavor-access:is_public',
|
||||||
|
'properties',
|
||||||
'ram',
|
'ram',
|
||||||
'rxtx_factor',
|
'rxtx_factor',
|
||||||
'swap',
|
'swap',
|
||||||
@ -68,6 +69,7 @@ class TestFlavorCreate(TestFlavor):
|
|||||||
flavor.id,
|
flavor.id,
|
||||||
flavor.name,
|
flavor.name,
|
||||||
flavor.is_public,
|
flavor.is_public,
|
||||||
|
utils.format_dict(flavor.properties),
|
||||||
flavor.ram,
|
flavor.ram,
|
||||||
flavor.rxtx_factor,
|
flavor.rxtx_factor,
|
||||||
flavor.swap,
|
flavor.swap,
|
||||||
@ -116,7 +118,6 @@ class TestFlavorCreate(TestFlavor):
|
|||||||
def test_flavor_create_all_options(self):
|
def test_flavor_create_all_options(self):
|
||||||
|
|
||||||
arglist = [
|
arglist = [
|
||||||
self.flavor.name,
|
|
||||||
'--id', self.flavor.id,
|
'--id', self.flavor.id,
|
||||||
'--ram', str(self.flavor.ram),
|
'--ram', str(self.flavor.ram),
|
||||||
'--disk', str(self.flavor.disk),
|
'--disk', str(self.flavor.disk),
|
||||||
@ -125,9 +126,10 @@ class TestFlavorCreate(TestFlavor):
|
|||||||
'--vcpus', str(self.flavor.vcpus),
|
'--vcpus', str(self.flavor.vcpus),
|
||||||
'--rxtx-factor', str(self.flavor.rxtx_factor),
|
'--rxtx-factor', str(self.flavor.rxtx_factor),
|
||||||
'--public',
|
'--public',
|
||||||
|
'--property', 'property=value',
|
||||||
|
self.flavor.name,
|
||||||
]
|
]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
('name', self.flavor.name),
|
|
||||||
('id', self.flavor.id),
|
('id', self.flavor.id),
|
||||||
('ram', self.flavor.ram),
|
('ram', self.flavor.ram),
|
||||||
('disk', self.flavor.disk),
|
('disk', self.flavor.disk),
|
||||||
@ -136,6 +138,8 @@ class TestFlavorCreate(TestFlavor):
|
|||||||
('vcpus', self.flavor.vcpus),
|
('vcpus', self.flavor.vcpus),
|
||||||
('rxtx_factor', self.flavor.rxtx_factor),
|
('rxtx_factor', self.flavor.rxtx_factor),
|
||||||
('public', True),
|
('public', True),
|
||||||
|
('property', {'property': 'value'}),
|
||||||
|
('name', self.flavor.name),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -152,6 +156,8 @@ class TestFlavorCreate(TestFlavor):
|
|||||||
)
|
)
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
self.flavors_mock.create.assert_called_once_with(*args)
|
self.flavors_mock.create.assert_called_once_with(*args)
|
||||||
|
self.flavor.set_keys.assert_called_once_with({'property': 'value'})
|
||||||
|
self.flavor.get_keys.assert_called_once_with()
|
||||||
|
|
||||||
self.assertEqual(self.columns, columns)
|
self.assertEqual(self.columns, columns)
|
||||||
self.assertEqual(self.data, data)
|
self.assertEqual(self.data, data)
|
||||||
@ -160,7 +166,6 @@ class TestFlavorCreate(TestFlavor):
|
|||||||
|
|
||||||
self.flavor.is_public = False
|
self.flavor.is_public = False
|
||||||
arglist = [
|
arglist = [
|
||||||
self.flavor.name,
|
|
||||||
'--id', self.flavor.id,
|
'--id', self.flavor.id,
|
||||||
'--ram', str(self.flavor.ram),
|
'--ram', str(self.flavor.ram),
|
||||||
'--disk', str(self.flavor.disk),
|
'--disk', str(self.flavor.disk),
|
||||||
@ -170,9 +175,11 @@ class TestFlavorCreate(TestFlavor):
|
|||||||
'--rxtx-factor', str(self.flavor.rxtx_factor),
|
'--rxtx-factor', str(self.flavor.rxtx_factor),
|
||||||
'--private',
|
'--private',
|
||||||
'--project', identity_fakes.project_id,
|
'--project', identity_fakes.project_id,
|
||||||
|
'--property', 'key1=value1',
|
||||||
|
'--property', 'key2=value2',
|
||||||
|
self.flavor.name,
|
||||||
]
|
]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
('name', self.flavor.name),
|
|
||||||
('id', self.flavor.id),
|
('id', self.flavor.id),
|
||||||
('ram', self.flavor.ram),
|
('ram', self.flavor.ram),
|
||||||
('disk', self.flavor.disk),
|
('disk', self.flavor.disk),
|
||||||
@ -182,6 +189,8 @@ class TestFlavorCreate(TestFlavor):
|
|||||||
('rxtx_factor', self.flavor.rxtx_factor),
|
('rxtx_factor', self.flavor.rxtx_factor),
|
||||||
('public', False),
|
('public', False),
|
||||||
('project', identity_fakes.project_id),
|
('project', identity_fakes.project_id),
|
||||||
|
('property', {'key1': 'value1', 'key2': 'value2'}),
|
||||||
|
('name', self.flavor.name),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -202,6 +211,9 @@ class TestFlavorCreate(TestFlavor):
|
|||||||
self.flavor.id,
|
self.flavor.id,
|
||||||
identity_fakes.project_id,
|
identity_fakes.project_id,
|
||||||
)
|
)
|
||||||
|
self.flavor.set_keys.assert_called_with(
|
||||||
|
{'key1': 'value1', 'key2': 'value2'})
|
||||||
|
self.flavor.get_keys.assert_called_with()
|
||||||
self.assertEqual(self.columns, columns)
|
self.assertEqual(self.columns, columns)
|
||||||
self.assertEqual(self.data, data)
|
self.assertEqual(self.data, data)
|
||||||
|
|
||||||
|
4
releasenotes/notes/bug-1596798-b22fd587bdca8b36.yaml
Normal file
4
releasenotes/notes/bug-1596798-b22fd587bdca8b36.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Add ``--property`` option to ``flavor create`` command.
|
||||||
|
[Bug `1596798 <https://bugs.launchpad.net/bugs/1596798>`_]
|
Loading…
Reference in New Issue
Block a user