Compute: Add description support for server
This patch adds functionality to configure server's description with: 1 server create 2 server set 3 server unset 4 server rebuild Change-Id: Ic06d97b29e51828b29d7ac5172645c288e4ada9e Story: 2002005 Task: 19640
This commit is contained in:
parent
0a2b01fb40
commit
c77a9621be
@ -125,7 +125,8 @@ unlock,server unlock,Unlock a server.
|
|||||||
unpause,server unpause,Unpause a server.
|
unpause,server unpause,Unpause a server.
|
||||||
unrescue,server unrescue,Restart the server from normal boot disk again.
|
unrescue,server unrescue,Restart the server from normal boot disk again.
|
||||||
unshelve,server unshelve,Unshelve a server.
|
unshelve,server unshelve,Unshelve a server.
|
||||||
update,server set / unset,Update the name or the description for a server.
|
update,server set / unset --description,Update or unset the description for a server.
|
||||||
|
update,server set --name,Update the name for a server.
|
||||||
usage,usage show,Show usage data for a single tenant.
|
usage,usage show,Show usage data for a single tenant.
|
||||||
usage-list,usage list,List usage data for all tenants.
|
usage-list,usage list,List usage data for all tenants.
|
||||||
version-list,,List all API versions.
|
version-list,,List all API versions.
|
||||||
|
|
@ -502,6 +502,12 @@ class CreateServer(command.ShowOne):
|
|||||||
metavar='<user-data>',
|
metavar='<user-data>',
|
||||||
help=_('User data file to serve from the metadata server'),
|
help=_('User data file to serve from the metadata server'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--description',
|
||||||
|
metavar='<description>',
|
||||||
|
help=_('Set description for the server (supported by '
|
||||||
|
'--os-compute-api-version 2.19 or above)'),
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--availability-zone',
|
'--availability-zone',
|
||||||
metavar='<zone-name>',
|
metavar='<zone-name>',
|
||||||
@ -712,6 +718,12 @@ class CreateServer(command.ShowOne):
|
|||||||
"exception": e}
|
"exception": e}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if parsed_args.description:
|
||||||
|
if compute_client.api_version < api_versions.APIVersion("2.19"):
|
||||||
|
msg = _("Description is not supported for "
|
||||||
|
"--os-compute-api-version less than 2.19")
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
block_device_mapping_v2 = []
|
block_device_mapping_v2 = []
|
||||||
if volume:
|
if volume:
|
||||||
block_device_mapping_v2 = [{'uuid': volume,
|
block_device_mapping_v2 = [{'uuid': volume,
|
||||||
@ -872,6 +884,9 @@ class CreateServer(command.ShowOne):
|
|||||||
scheduler_hints=hints,
|
scheduler_hints=hints,
|
||||||
config_drive=config_drive)
|
config_drive=config_drive)
|
||||||
|
|
||||||
|
if parsed_args.description:
|
||||||
|
boot_kwargs['description'] = parsed_args.description
|
||||||
|
|
||||||
LOG.debug('boot_args: %s', boot_args)
|
LOG.debug('boot_args: %s', boot_args)
|
||||||
LOG.debug('boot_kwargs: %s', boot_kwargs)
|
LOG.debug('boot_kwargs: %s', boot_kwargs)
|
||||||
|
|
||||||
@ -1529,6 +1544,12 @@ class RebuildServer(command.ShowOne):
|
|||||||
help=_('Set a property on the rebuilt instance '
|
help=_('Set a property on the rebuilt instance '
|
||||||
'(repeat option to set multiple values)'),
|
'(repeat option to set multiple values)'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--description',
|
||||||
|
metavar='<description>',
|
||||||
|
help=_('New description for the server (supported by '
|
||||||
|
'--os-compute-api-version 2.19 or above'),
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--wait',
|
'--wait',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
@ -1557,6 +1578,12 @@ class RebuildServer(command.ShowOne):
|
|||||||
kwargs = {}
|
kwargs = {}
|
||||||
if parsed_args.property:
|
if parsed_args.property:
|
||||||
kwargs['meta'] = parsed_args.property
|
kwargs['meta'] = parsed_args.property
|
||||||
|
if parsed_args.description:
|
||||||
|
if server.api_version < api_versions.APIVersion("2.19"):
|
||||||
|
msg = _("Description is not supported for "
|
||||||
|
"--os-compute-api-version less than 2.19")
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
kwargs['description'] = parsed_args.description
|
||||||
|
|
||||||
server = server.rebuild(image, parsed_args.password, **kwargs)
|
server = server.rebuild(image, parsed_args.password, **kwargs)
|
||||||
if parsed_args.wait:
|
if parsed_args.wait:
|
||||||
@ -1968,6 +1995,12 @@ class SetServer(command.Command):
|
|||||||
choices=['active', 'error'],
|
choices=['active', 'error'],
|
||||||
help=_('New server state (valid value: active, error)'),
|
help=_('New server state (valid value: active, error)'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--description',
|
||||||
|
metavar='<description>',
|
||||||
|
help=_('New server description (supported by '
|
||||||
|
'--os-compute-api-version 2.19 or above)'),
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
@ -1999,6 +2032,13 @@ class SetServer(command.Command):
|
|||||||
msg = _("Passwords do not match, password unchanged")
|
msg = _("Passwords do not match, password unchanged")
|
||||||
raise exceptions.CommandError(msg)
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
if parsed_args.description:
|
||||||
|
if server.api_version < api_versions.APIVersion("2.19"):
|
||||||
|
msg = _("Description is not supported for "
|
||||||
|
"--os-compute-api-version less than 2.19")
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
server.update(description=parsed_args.description)
|
||||||
|
|
||||||
|
|
||||||
class ShelveServer(command.Command):
|
class ShelveServer(command.Command):
|
||||||
_description = _("Shelve server(s)")
|
_description = _("Shelve server(s)")
|
||||||
@ -2358,6 +2398,13 @@ class UnsetServer(command.Command):
|
|||||||
help=_('Property key to remove from server '
|
help=_('Property key to remove from server '
|
||||||
'(repeat option to remove multiple values)'),
|
'(repeat option to remove multiple values)'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--description',
|
||||||
|
dest='description',
|
||||||
|
action='store_true',
|
||||||
|
help=_('Unset server description (supported by '
|
||||||
|
'--os-compute-api-version 2.19 or above)'),
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
@ -2373,6 +2420,16 @@ class UnsetServer(command.Command):
|
|||||||
parsed_args.property,
|
parsed_args.property,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if parsed_args.description:
|
||||||
|
if compute_client.api_version < api_versions.APIVersion("2.19"):
|
||||||
|
msg = _("Description is not supported for "
|
||||||
|
"--os-compute-api-version less than 2.19")
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
compute_client.servers.update(
|
||||||
|
server,
|
||||||
|
description="",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class UnshelveServer(command.Command):
|
class UnshelveServer(command.Command):
|
||||||
_description = _("Unshelve server(s)")
|
_description = _("Unshelve server(s)")
|
||||||
|
@ -1736,6 +1736,90 @@ class TestServerCreate(TestServer):
|
|||||||
self.cmd.take_action,
|
self.cmd.take_action,
|
||||||
parsed_args)
|
parsed_args)
|
||||||
|
|
||||||
|
def test_server_create_with_description_api_newer(self):
|
||||||
|
|
||||||
|
# Description is supported for nova api version 2.19 or above
|
||||||
|
self.app.client_manager.compute.api_version = 2.19
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
'--image', 'image1',
|
||||||
|
'--flavor', 'flavor1',
|
||||||
|
'--description', 'description1',
|
||||||
|
self.new_server.name,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('image', 'image1'),
|
||||||
|
('flavor', 'flavor1'),
|
||||||
|
('description', 'description1'),
|
||||||
|
('config_drive', False),
|
||||||
|
('server_name', self.new_server.name),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
with mock.patch.object(api_versions,
|
||||||
|
'APIVersion',
|
||||||
|
return_value=2.19):
|
||||||
|
# In base command class ShowOne in cliff, abstract method
|
||||||
|
# take_action() returns a two-part tuple with a tuple of
|
||||||
|
# column names and a tuple of data to be shown.
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
# Set expected values
|
||||||
|
kwargs = dict(
|
||||||
|
meta=None,
|
||||||
|
files={},
|
||||||
|
reservation_id=None,
|
||||||
|
min_count=1,
|
||||||
|
max_count=1,
|
||||||
|
security_groups=[],
|
||||||
|
userdata=None,
|
||||||
|
key_name=None,
|
||||||
|
availability_zone=None,
|
||||||
|
block_device_mapping_v2=[],
|
||||||
|
nics='auto',
|
||||||
|
scheduler_hints={},
|
||||||
|
config_drive=None,
|
||||||
|
description='description1',
|
||||||
|
)
|
||||||
|
# ServerManager.create(name, image, flavor, **kwargs)
|
||||||
|
self.servers_mock.create.assert_called_with(
|
||||||
|
self.new_server.name,
|
||||||
|
self.image,
|
||||||
|
self.flavor,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(self.columns, columns)
|
||||||
|
self.assertEqual(self.datalist(), data)
|
||||||
|
self.assertFalse(self.images_mock.called)
|
||||||
|
self.assertFalse(self.flavors_mock.called)
|
||||||
|
|
||||||
|
def test_server_create_with_description_api_older(self):
|
||||||
|
|
||||||
|
# Description is not supported for nova api version below 2.19
|
||||||
|
self.app.client_manager.compute.api_version = 2.18
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
'--image', 'image1',
|
||||||
|
'--flavor', 'flavor1',
|
||||||
|
'--description', 'description1',
|
||||||
|
self.new_server.name,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('image', 'image1'),
|
||||||
|
('flavor', 'flavor1'),
|
||||||
|
('description', 'description1'),
|
||||||
|
('config_drive', False),
|
||||||
|
('server_name', self.new_server.name),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
with mock.patch.object(api_versions,
|
||||||
|
'APIVersion',
|
||||||
|
return_value=2.19):
|
||||||
|
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
|
||||||
class TestServerDelete(TestServer):
|
class TestServerDelete(TestServer):
|
||||||
|
|
||||||
@ -2493,6 +2577,55 @@ class TestServerRebuild(TestServer):
|
|||||||
self.images_mock.get.assert_called_with(self.image.id)
|
self.images_mock.get.assert_called_with(self.image.id)
|
||||||
self.server.rebuild.assert_called_with(self.image, password)
|
self.server.rebuild.assert_called_with(self.image, password)
|
||||||
|
|
||||||
|
def test_rebuild_with_description_api_older(self):
|
||||||
|
|
||||||
|
# Description is not supported for nova api version below 2.19
|
||||||
|
self.server.api_version = 2.18
|
||||||
|
|
||||||
|
description = 'description1'
|
||||||
|
arglist = [
|
||||||
|
self.server.id,
|
||||||
|
'--description', description
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('server', self.server.id),
|
||||||
|
('description', description)
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
with mock.patch.object(api_versions,
|
||||||
|
'APIVersion',
|
||||||
|
return_value=2.19):
|
||||||
|
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
def test_rebuild_with_description_api_newer(self):
|
||||||
|
|
||||||
|
# Description is supported for nova api version 2.19 or above
|
||||||
|
self.server.api_version = 2.19
|
||||||
|
|
||||||
|
description = 'description1'
|
||||||
|
arglist = [
|
||||||
|
self.server.id,
|
||||||
|
'--description', description
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('server', self.server.id),
|
||||||
|
('description', description)
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
with mock.patch.object(api_versions,
|
||||||
|
'APIVersion',
|
||||||
|
return_value=2.19):
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.servers_mock.get.assert_called_with(self.server.id)
|
||||||
|
self.images_mock.get.assert_called_with(self.image.id)
|
||||||
|
self.server.rebuild.assert_called_with(self.image, None,
|
||||||
|
description=description)
|
||||||
|
|
||||||
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
|
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
|
||||||
def test_rebuild_with_wait_ok(self, mock_wait_for_status):
|
def test_rebuild_with_wait_ok(self, mock_wait_for_status):
|
||||||
arglist = [
|
arglist = [
|
||||||
@ -3140,6 +3273,10 @@ class TestServerSet(TestServer):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestServerSet, self).setUp()
|
super(TestServerSet, self).setUp()
|
||||||
|
|
||||||
|
self.attrs = {
|
||||||
|
'api_version': None,
|
||||||
|
}
|
||||||
|
|
||||||
self.methods = {
|
self.methods = {
|
||||||
'update': None,
|
'update': None,
|
||||||
'reset_state': None,
|
'reset_state': None,
|
||||||
@ -3242,6 +3379,48 @@ class TestServerSet(TestServer):
|
|||||||
mock.sentinel.fake_pass)
|
mock.sentinel.fake_pass)
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
def test_server_set_with_description_api_newer(self):
|
||||||
|
|
||||||
|
# Description is supported for nova api version 2.19 or above
|
||||||
|
self.fake_servers[0].api_version = 2.19
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
'--description', 'foo_description',
|
||||||
|
'foo_vm',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('description', 'foo_description'),
|
||||||
|
('server', 'foo_vm'),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
with mock.patch.object(api_versions,
|
||||||
|
'APIVersion',
|
||||||
|
return_value=2.19):
|
||||||
|
result = self.cmd.take_action(parsed_args)
|
||||||
|
self.fake_servers[0].update.assert_called_once_with(
|
||||||
|
description='foo_description')
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
def test_server_set_with_description_api_older(self):
|
||||||
|
|
||||||
|
# Description is not supported for nova api version below 2.19
|
||||||
|
self.fake_servers[0].api_version = 2.18
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
'--description', 'foo_description',
|
||||||
|
'foo_vm',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('description', 'foo_description'),
|
||||||
|
('server', 'foo_vm'),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
with mock.patch.object(api_versions,
|
||||||
|
'APIVersion',
|
||||||
|
return_value=2.19):
|
||||||
|
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
|
||||||
class TestServerShelve(TestServer):
|
class TestServerShelve(TestServer):
|
||||||
|
|
||||||
@ -3523,6 +3702,50 @@ class TestServerUnset(TestServer):
|
|||||||
self.fake_server, ['key1', 'key2'])
|
self.fake_server, ['key1', 'key2'])
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
def test_server_unset_with_description_api_newer(self):
|
||||||
|
|
||||||
|
# Description is supported for nova api version 2.19 or above
|
||||||
|
self.app.client_manager.compute.api_version = 2.19
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
'--description',
|
||||||
|
'foo_vm',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('description', True),
|
||||||
|
('server', 'foo_vm'),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
with mock.patch.object(api_versions,
|
||||||
|
'APIVersion',
|
||||||
|
return_value=2.19):
|
||||||
|
result = self.cmd.take_action(parsed_args)
|
||||||
|
self.servers_mock.update.assert_called_once_with(
|
||||||
|
self.fake_server, description="")
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
def test_server_unset_with_description_api_older(self):
|
||||||
|
|
||||||
|
# Description is not supported for nova api version below 2.19
|
||||||
|
self.app.client_manager.compute.api_version = 2.18
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
'--description',
|
||||||
|
'foo_vm',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('description', True),
|
||||||
|
('server', 'foo_vm'),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
with mock.patch.object(api_versions,
|
||||||
|
'APIVersion',
|
||||||
|
return_value=2.19):
|
||||||
|
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
|
||||||
class TestServerUnshelve(TestServer):
|
class TestServerUnshelve(TestServer):
|
||||||
|
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add ``--description`` option to ``server create``, ``server rebuild``,
|
||||||
|
``server set`` and ``server unset`` commands.
|
||||||
|
[Bug `2002005 <https://storyboard.openstack.org/#!/story/2002005>`_]
|
Loading…
Reference in New Issue
Block a user