Add the ability to set and unset flavor properties
Added flavor set and unset command which allow manage flavor properties called extra_specs. Command flavor show output was extended with these properties. Closes-Bug: 1434137 Change-Id: Ie469bade802de18aab9d58eda3fff46064008163
This commit is contained in:
parent
a8c44074f9
commit
621434451f
@ -123,3 +123,43 @@ Display flavor details
|
||||
.. describe:: <flavor>
|
||||
|
||||
Flavor to display (name or ID)
|
||||
|
||||
flavor set
|
||||
----------
|
||||
|
||||
Set flavor properties
|
||||
|
||||
.. program:: flavor set
|
||||
.. code:: bash
|
||||
|
||||
os flavor set
|
||||
[--property <key=value> [...] ]
|
||||
<flavor>
|
||||
|
||||
.. option:: --property <key=value>
|
||||
|
||||
Property to add or modify for this flavor (repeat option to set multiple properties)
|
||||
|
||||
.. describe:: <flavor>
|
||||
|
||||
Flavor to modify (name or ID)
|
||||
|
||||
flavor unset
|
||||
------------
|
||||
|
||||
Unset flavor properties
|
||||
|
||||
.. program:: flavor unset
|
||||
.. code:: bash
|
||||
|
||||
os flavor unset
|
||||
[--property <key> [...] ]
|
||||
<flavor>
|
||||
|
||||
.. option:: --property <key>
|
||||
|
||||
Property to remove from flavor (repeat option to remove multiple properties)
|
||||
|
||||
.. describe:: <flavor>
|
||||
|
||||
Flavor to modify (name or ID)
|
||||
|
@ -22,6 +22,7 @@ from cliff import command
|
||||
from cliff import lister
|
||||
from cliff import show
|
||||
|
||||
from openstackclient.common import parseractions
|
||||
from openstackclient.common import utils
|
||||
|
||||
|
||||
@ -237,8 +238,79 @@ class ShowFlavor(show.ShowOne):
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action(%s)", parsed_args)
|
||||
compute_client = self.app.client_manager.compute
|
||||
flavor = utils.find_resource(compute_client.flavors,
|
||||
parsed_args.flavor)._info.copy()
|
||||
flavor.pop("links")
|
||||
resource_flavor = utils.find_resource(compute_client.flavors,
|
||||
parsed_args.flavor)
|
||||
flavor = resource_flavor._info.copy()
|
||||
flavor.pop("links", None)
|
||||
|
||||
flavor['properties'] = utils.format_dict(resource_flavor.get_keys())
|
||||
|
||||
return zip(*sorted(six.iteritems(flavor)))
|
||||
|
||||
|
||||
class SetFlavor(show.ShowOne):
|
||||
"""Set flavor properties"""
|
||||
|
||||
log = logging.getLogger(__name__ + ".SetFlavor")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(SetFlavor, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
"--property",
|
||||
metavar="<key=value>",
|
||||
action=parseractions.KeyValueAction,
|
||||
help='Property to add or modify for this flavor '
|
||||
'(repeat option to set multiple properties)',
|
||||
)
|
||||
parser.add_argument(
|
||||
"flavor",
|
||||
metavar="<flavor>",
|
||||
help="Flavor to modify (name or ID)",
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action(%s)", parsed_args)
|
||||
compute_client = self.app.client_manager.compute
|
||||
resource_flavor = compute_client.flavors.find(name=parsed_args.flavor)
|
||||
|
||||
resource_flavor.set_keys(parsed_args.property)
|
||||
|
||||
flavor = resource_flavor._info.copy()
|
||||
flavor['properties'] = utils.format_dict(resource_flavor.get_keys())
|
||||
flavor.pop("links", None)
|
||||
return zip(*sorted(six.iteritems(flavor)))
|
||||
|
||||
|
||||
class UnsetFlavor(show.ShowOne):
|
||||
"""Unset flavor properties"""
|
||||
|
||||
log = logging.getLogger(__name__ + ".UnsetFlavor")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(UnsetFlavor, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
"--property",
|
||||
metavar="<key>",
|
||||
action='append',
|
||||
help='Property to remove from flavor '
|
||||
'(repeat option to unset multiple properties)',
|
||||
)
|
||||
parser.add_argument(
|
||||
"flavor",
|
||||
metavar="<flavor>",
|
||||
help="Flavor to modify (name or ID)",
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action(%s)", parsed_args)
|
||||
compute_client = self.app.client_manager.compute
|
||||
resource_flavor = compute_client.flavors.find(name=parsed_args.flavor)
|
||||
|
||||
resource_flavor.unset_keys(parsed_args.property)
|
||||
|
||||
flavor = resource_flavor._info.copy()
|
||||
flavor['properties'] = utils.format_dict(resource_flavor.get_keys())
|
||||
flavor.pop("links", None)
|
||||
return zip(*sorted(six.iteritems(flavor)))
|
||||
|
@ -22,8 +22,17 @@ from openstackclient.tests import fakes
|
||||
|
||||
class FakeFlavorResource(fakes.FakeResource):
|
||||
|
||||
_keys = {'property': 'value'}
|
||||
|
||||
def set_keys(self, args):
|
||||
self._keys.update(args)
|
||||
|
||||
def unset_keys(self, keys):
|
||||
for key in keys:
|
||||
self._keys.pop(key, None)
|
||||
|
||||
def get_keys(self):
|
||||
return {'property': 'value'}
|
||||
return self._keys
|
||||
|
||||
|
||||
class TestFlavor(compute_fakes.TestComputev2):
|
||||
@ -272,3 +281,69 @@ class TestFlavorList(TestFlavor):
|
||||
'property=\'value\''
|
||||
), )
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
||||
|
||||
class TestFlavorSet(TestFlavor):
|
||||
|
||||
def setUp(self):
|
||||
super(TestFlavorSet, self).setUp()
|
||||
|
||||
self.flavors_mock.find.return_value = FakeFlavorResource(
|
||||
None,
|
||||
copy.deepcopy(compute_fakes.FLAVOR),
|
||||
loaded=True,
|
||||
)
|
||||
|
||||
self.cmd = flavor.SetFlavor(self.app, None)
|
||||
|
||||
def test_flavor_set(self):
|
||||
arglist = [
|
||||
'--property', 'FOO="B A R"',
|
||||
'baremetal'
|
||||
]
|
||||
verifylist = [
|
||||
('property', {'FOO': '"B A R"'}),
|
||||
('flavor', 'baremetal')
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.flavors_mock.find.assert_called_with(name='baremetal')
|
||||
|
||||
self.assertEqual('properties', columns[2])
|
||||
self.assertIn('FOO=\'"B A R"\'', data[2])
|
||||
|
||||
|
||||
class TestFlavorUnset(TestFlavor):
|
||||
|
||||
def setUp(self):
|
||||
super(TestFlavorUnset, self).setUp()
|
||||
|
||||
self.flavors_mock.find.return_value = FakeFlavorResource(
|
||||
None,
|
||||
copy.deepcopy(compute_fakes.FLAVOR),
|
||||
loaded=True,
|
||||
)
|
||||
|
||||
self.cmd = flavor.UnsetFlavor(self.app, None)
|
||||
|
||||
def test_flavor_unset(self):
|
||||
arglist = [
|
||||
'--property', 'property',
|
||||
'baremetal'
|
||||
]
|
||||
verifylist = [
|
||||
('property', ['property']),
|
||||
('flavor', 'baremetal'),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.flavors_mock.find.assert_called_with(name='baremetal')
|
||||
|
||||
self.assertEqual('properties', columns[2])
|
||||
self.assertNotIn('property', data[2])
|
||||
|
@ -75,6 +75,8 @@ openstack.compute.v2 =
|
||||
flavor_delete = openstackclient.compute.v2.flavor:DeleteFlavor
|
||||
flavor_list = openstackclient.compute.v2.flavor:ListFlavor
|
||||
flavor_show = openstackclient.compute.v2.flavor:ShowFlavor
|
||||
flavor_set = openstackclient.compute.v2.flavor:SetFlavor
|
||||
flavor_unset = openstackclient.compute.v2.flavor:UnsetFlavor
|
||||
|
||||
host_list = openstackclient.compute.v2.host:ListHost
|
||||
host_show = openstackclient.compute.v2.host:ShowHost
|
||||
|
Loading…
Reference in New Issue
Block a user