Merge "Compute: Add description support for flavor"

This commit is contained in:
Zuul 2018-06-28 17:26:03 +00:00 committed by Gerrit Code Review
commit 7b8873dc6b
5 changed files with 177 additions and 4 deletions
doc/source/cli/command-objects
openstackclient
compute/v2
tests/unit/compute/v2
releasenotes/notes

@ -24,6 +24,7 @@ Create new flavor
[--property <key=value> [...] ] [--property <key=value> [...] ]
[--project <project>] [--project <project>]
[--project-domain <project-domain>] [--project-domain <project-domain>]
[--description <description>]
<flavor-name> <flavor-name>
.. option:: --id <id> .. option:: --id <id>
@ -76,6 +77,10 @@ Create new flavor
Domain the project belongs to (name or ID). Domain the project belongs to (name or ID).
This can be used in case collisions between project names exist. This can be used in case collisions between project names exist.
.. option:: --description <description>
Description to add for this flavor
.. _flavor_create-flavor-name: .. _flavor_create-flavor-name:
.. describe:: <flavor-name> .. describe:: <flavor-name>
@ -148,6 +153,7 @@ Set flavor properties
[--property <key=value> [...] ] [--property <key=value> [...] ]
[--project <project>] [--project <project>]
[--project-domain <project-domain>] [--project-domain <project-domain>]
[--description <description>]
<flavor> <flavor>
.. option:: --property <key=value> .. option:: --property <key=value>
@ -168,6 +174,10 @@ Set flavor properties
Remove all properties from this flavor (specify both --no-property and --property Remove all properties from this flavor (specify both --no-property and --property
to remove the current properties before setting new properties.) to remove the current properties before setting new properties.)
.. option:: --description <description>
Set description to this flavor
.. describe:: <flavor> .. describe:: <flavor>
Flavor to modify (name or ID) Flavor to modify (name or ID)

@ -17,6 +17,7 @@
import logging import logging
from novaclient import api_versions
from osc_lib.cli import parseractions from osc_lib.cli import parseractions
from osc_lib.command import command from osc_lib.command import command
from osc_lib import exceptions from osc_lib import exceptions
@ -134,6 +135,12 @@ class CreateFlavor(command.ShowOne):
help=_("Allow <project> to access private flavor (name or ID) " help=_("Allow <project> to access private flavor (name or ID) "
"(Must be used with --private option)"), "(Must be used with --private option)"),
) )
parser.add_argument(
'--description',
metavar='<description>',
help=_("Description for the flavor.(Supported by API versions "
"'2.55' - '2.latest'")
)
identity_common.add_project_domain_option_to_parser(parser) identity_common.add_project_domain_option_to_parser(parser)
return parser return parser
@ -145,6 +152,11 @@ class CreateFlavor(command.ShowOne):
msg = _("--project is only allowed with --private") msg = _("--project is only allowed with --private")
raise exceptions.CommandError(msg) raise exceptions.CommandError(msg)
if parsed_args.description:
if compute_client.api_version < api_versions.APIVersion("2.55"):
msg = _("--os-compute-api-version 2.55 or later is required")
raise exceptions.CommandError(msg)
args = ( args = (
parsed_args.name, parsed_args.name,
parsed_args.ram, parsed_args.ram,
@ -154,7 +166,8 @@ class CreateFlavor(command.ShowOne):
parsed_args.ephemeral, parsed_args.ephemeral,
parsed_args.swap, parsed_args.swap,
parsed_args.rxtx_factor, parsed_args.rxtx_factor,
parsed_args.public parsed_args.public,
parsed_args.description
) )
flavor = compute_client.flavors.create(*args) flavor = compute_client.flavors.create(*args)
@ -332,6 +345,12 @@ class SetFlavor(command.Command):
help=_('Set flavor access to project (name or ID) ' help=_('Set flavor access to project (name or ID) '
'(admin only)'), '(admin only)'),
) )
parser.add_argument(
'--description',
metavar='<description>',
help=_("Set description for the flavor.(Supported by API "
"versions '2.55' - '2.latest'")
)
identity_common.add_project_domain_option_to_parser(parser) identity_common.add_project_domain_option_to_parser(parser)
return parser return parser
@ -380,6 +399,13 @@ class SetFlavor(command.Command):
raise exceptions.CommandError(_("Command Failed: One or more of" raise exceptions.CommandError(_("Command Failed: One or more of"
" the operations failed")) " the operations failed"))
if parsed_args.description:
if compute_client.api_version < api_versions.APIVersion("2.55"):
msg = _("--os-compute-api-version 2.55 or later is required")
raise exceptions.CommandError(msg)
compute_client.flavors.update(flavor=parsed_args.flavor,
description=parsed_args.description)
class ShowFlavor(command.ShowOne): class ShowFlavor(command.ShowOne):
_description = _("Display flavor details") _description = _("Display flavor details")

@ -765,6 +765,7 @@ class FakeFlavor(object):
'rxtx_factor': 1.0, 'rxtx_factor': 1.0,
'OS-FLV-DISABLED:disabled': False, 'OS-FLV-DISABLED:disabled': False,
'os-flavor-access:is_public': True, 'os-flavor-access:is_public': True,
'description': 'description',
'OS-FLV-EXT-DATA:ephemeral': 0, 'OS-FLV-EXT-DATA:ephemeral': 0,
'properties': {'property': 'value'}, 'properties': {'property': 'value'},
} }

@ -16,6 +16,7 @@
import mock import mock
from mock import call from mock import call
import novaclient
from osc_lib import exceptions from osc_lib import exceptions
from osc_lib import utils from osc_lib import utils
@ -50,6 +51,7 @@ class TestFlavorCreate(TestFlavor):
columns = ( columns = (
'OS-FLV-DISABLED:disabled', 'OS-FLV-DISABLED:disabled',
'OS-FLV-EXT-DATA:ephemeral', 'OS-FLV-EXT-DATA:ephemeral',
'description',
'disk', 'disk',
'id', 'id',
'name', 'name',
@ -63,6 +65,7 @@ class TestFlavorCreate(TestFlavor):
data = ( data = (
flavor.disabled, flavor.disabled,
flavor.ephemeral, flavor.ephemeral,
flavor.description,
flavor.disk, flavor.disk,
flavor.id, flavor.id,
flavor.name, flavor.name,
@ -101,7 +104,8 @@ class TestFlavorCreate(TestFlavor):
0, 0,
0, 0,
1.0, 1.0,
True True,
None,
) )
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.flavors_mock.create.assert_called_once_with(*default_args) self.flavors_mock.create.assert_called_once_with(*default_args)
@ -120,6 +124,7 @@ 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',
'--description', str(self.flavor.description),
'--property', 'property=value', '--property', 'property=value',
self.flavor.name, self.flavor.name,
] ]
@ -132,6 +137,7 @@ 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),
('description', self.flavor.description),
('property', {'property': 'value'}), ('property', {'property': 'value'}),
('name', self.flavor.name), ('name', self.flavor.name),
] ]
@ -147,8 +153,13 @@ class TestFlavorCreate(TestFlavor):
self.flavor.swap, self.flavor.swap,
self.flavor.rxtx_factor, self.flavor.rxtx_factor,
self.flavor.is_public, self.flavor.is_public,
self.flavor.description,
) )
columns, data = self.cmd.take_action(parsed_args) self.app.client_manager.compute.api_version = 2.55
with mock.patch.object(novaclient.api_versions,
'APIVersion',
return_value=2.55):
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.set_keys.assert_called_once_with({'property': 'value'})
self.flavor.get_keys.assert_called_once_with() self.flavor.get_keys.assert_called_once_with()
@ -168,6 +179,7 @@ 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),
'--private', '--private',
'--description', str(self.flavor.description),
'--project', self.project.id, '--project', self.project.id,
'--property', 'key1=value1', '--property', 'key1=value1',
'--property', 'key2=value2', '--property', 'key2=value2',
@ -181,6 +193,7 @@ class TestFlavorCreate(TestFlavor):
('vcpus', self.flavor.vcpus), ('vcpus', self.flavor.vcpus),
('rxtx_factor', self.flavor.rxtx_factor), ('rxtx_factor', self.flavor.rxtx_factor),
('public', False), ('public', False),
('description', 'description'),
('project', self.project.id), ('project', self.project.id),
('property', {'key1': 'value1', 'key2': 'value2'}), ('property', {'key1': 'value1', 'key2': 'value2'}),
('name', self.flavor.name), ('name', self.flavor.name),
@ -197,8 +210,13 @@ class TestFlavorCreate(TestFlavor):
self.flavor.swap, self.flavor.swap,
self.flavor.rxtx_factor, self.flavor.rxtx_factor,
self.flavor.is_public, self.flavor.is_public,
self.flavor.description,
) )
columns, data = self.cmd.take_action(parsed_args) self.app.client_manager.compute.api_version = 2.55
with mock.patch.object(novaclient.api_versions,
'APIVersion',
return_value=2.55):
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_access_mock.add_tenant_access.assert_called_with( self.flavor_access_mock.add_tenant_access.assert_called_with(
self.flavor.id, self.flavor.id,
@ -234,6 +252,79 @@ class TestFlavorCreate(TestFlavor):
arglist, arglist,
verifylist) verifylist)
def test_flavor_create_with_description_api_newer(self):
arglist = [
'--id', self.flavor.id,
'--ram', str(self.flavor.ram),
'--disk', str(self.flavor.disk),
'--ephemeral', str(self.flavor.ephemeral),
'--swap', str(self.flavor.swap),
'--vcpus', str(self.flavor.vcpus),
'--rxtx-factor', str(self.flavor.rxtx_factor),
'--private',
'--description', 'fake description',
self.flavor.name,
]
verifylist = [
('id', self.flavor.id),
('ram', self.flavor.ram),
('disk', self.flavor.disk),
('ephemeral', self.flavor.ephemeral),
('swap', self.flavor.swap),
('vcpus', self.flavor.vcpus),
('rxtx_factor', self.flavor.rxtx_factor),
('public', False),
('description', 'fake description'),
('name', self.flavor.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.app.client_manager.compute.api_version = 2.55
with mock.patch.object(novaclient.api_versions,
'APIVersion',
return_value=2.55):
columns, data = self.cmd.take_action(parsed_args)
args = (
self.flavor.name,
self.flavor.ram,
self.flavor.vcpus,
self.flavor.disk,
self.flavor.id,
self.flavor.ephemeral,
self.flavor.swap,
self.flavor.rxtx_factor,
False,
'fake description',
)
self.flavors_mock.create.assert_called_once_with(*args)
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, data)
def test_flavor_create_with_description_api_older(self):
arglist = [
'--id', self.flavor.id,
'--ram', str(self.flavor.ram),
'--vcpus', str(self.flavor.vcpus),
'--description', 'description',
self.flavor.name,
]
verifylist = [
('ram', self.flavor.ram),
('vcpus', self.flavor.vcpus),
('description', 'description'),
('name', self.flavor.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.app.client_manager.compute.api_version = 2.54
with mock.patch.object(novaclient.api_versions,
'APIVersion',
return_value=2.55):
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
parsed_args)
class TestFlavorDelete(TestFlavor): class TestFlavorDelete(TestFlavor):
@ -622,6 +713,42 @@ class TestFlavorSet(TestFlavor):
self.flavor_access_mock.add_tenant_access.assert_not_called() self.flavor_access_mock.add_tenant_access.assert_not_called()
self.assertIsNone(result) self.assertIsNone(result)
def test_flavor_set_description_api_newer(self):
arglist = [
'--description', 'description',
self.flavor.id,
]
verifylist = [
('description', 'description'),
('flavor', self.flavor.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.app.client_manager.compute.api_version = 2.55
with mock.patch.object(novaclient.api_versions,
'APIVersion',
return_value=2.55):
result = self.cmd.take_action(parsed_args)
self.flavors_mock.update.assert_called_with(
flavor=self.flavor.id, description='description')
self.assertIsNone(result)
def test_flavor_set_description_api_older(self):
arglist = [
'--description', 'description',
self.flavor.id,
]
verifylist = [
('description', 'description'),
('flavor', self.flavor.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.app.client_manager.compute.api_version = 2.54
with mock.patch.object(novaclient.api_versions,
'APIVersion',
return_value=2.55):
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
parsed_args)
class TestFlavorShow(TestFlavor): class TestFlavorShow(TestFlavor):
@ -633,6 +760,7 @@ class TestFlavorShow(TestFlavor):
'OS-FLV-DISABLED:disabled', 'OS-FLV-DISABLED:disabled',
'OS-FLV-EXT-DATA:ephemeral', 'OS-FLV-EXT-DATA:ephemeral',
'access_project_ids', 'access_project_ids',
'description',
'disk', 'disk',
'id', 'id',
'name', 'name',
@ -648,6 +776,7 @@ class TestFlavorShow(TestFlavor):
flavor.disabled, flavor.disabled,
flavor.ephemeral, flavor.ephemeral,
None, None,
flavor.description,
flavor.disk, flavor.disk,
flavor.id, flavor.id,
flavor.name, flavor.name,
@ -710,6 +839,7 @@ class TestFlavorShow(TestFlavor):
private_flavor.disabled, private_flavor.disabled,
private_flavor.ephemeral, private_flavor.ephemeral,
self.flavor_access.tenant_id, self.flavor_access.tenant_id,
private_flavor.description,
private_flavor.disk, private_flavor.disk,
private_flavor.id, private_flavor.id,
private_flavor.name, private_flavor.name,

@ -0,0 +1,6 @@
---
features:
- Add ``--description`` option to ``flavor set`` command to update the
description of the server.
- Add ``--description`` option to ``flavor create`` command to set the
description of the server.