Skip to content

Commit 95626f1

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Compute: Add description support for server"
2 parents 91bc0f3 + c77a962 commit 95626f1

4 files changed

Lines changed: 288 additions & 1 deletion

File tree

doc/source/cli/data/nova.csv

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ unlock,server unlock,Unlock a server.
125125
unpause,server unpause,Unpause a server.
126126
unrescue,server unrescue,Restart the server from normal boot disk again.
127127
unshelve,server unshelve,Unshelve a server.
128-
update,server set / unset,Update the name or the description for a server.
128+
update,server set / unset --description,Update or unset the description for a server.
129+
update,server set --name,Update the name for a server.
129130
usage,usage show,Show usage data for a single tenant.
130131
usage-list,usage list,List usage data for all tenants.
131132
version-list,,List all API versions.

openstackclient/compute/v2/server.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,12 @@ def get_parser(self, prog_name):
539539
metavar='<user-data>',
540540
help=_('User data file to serve from the metadata server'),
541541
)
542+
parser.add_argument(
543+
'--description',
544+
metavar='<description>',
545+
help=_('Set description for the server (supported by '
546+
'--os-compute-api-version 2.19 or above)'),
547+
)
542548
parser.add_argument(
543549
'--availability-zone',
544550
metavar='<zone-name>',
@@ -749,6 +755,12 @@ def _match_image(image_api, wanted_properties):
749755
"exception": e}
750756
)
751757

758+
if parsed_args.description:
759+
if compute_client.api_version < api_versions.APIVersion("2.19"):
760+
msg = _("Description is not supported for "
761+
"--os-compute-api-version less than 2.19")
762+
raise exceptions.CommandError(msg)
763+
752764
block_device_mapping_v2 = []
753765
if volume:
754766
block_device_mapping_v2 = [{'uuid': volume,
@@ -909,6 +921,9 @@ def _match_image(image_api, wanted_properties):
909921
scheduler_hints=hints,
910922
config_drive=config_drive)
911923

924+
if parsed_args.description:
925+
boot_kwargs['description'] = parsed_args.description
926+
912927
LOG.debug('boot_args: %s', boot_args)
913928
LOG.debug('boot_kwargs: %s', boot_kwargs)
914929

@@ -1600,6 +1615,12 @@ def get_parser(self, prog_name):
16001615
help=_('Set a property on the rebuilt instance '
16011616
'(repeat option to set multiple values)'),
16021617
)
1618+
parser.add_argument(
1619+
'--description',
1620+
metavar='<description>',
1621+
help=_('New description for the server (supported by '
1622+
'--os-compute-api-version 2.19 or above'),
1623+
)
16031624
parser.add_argument(
16041625
'--wait',
16051626
action='store_true',
@@ -1644,6 +1665,12 @@ def _show_progress(progress):
16441665
kwargs = {}
16451666
if parsed_args.property:
16461667
kwargs['meta'] = parsed_args.property
1668+
if parsed_args.description:
1669+
if server.api_version < api_versions.APIVersion("2.19"):
1670+
msg = _("Description is not supported for "
1671+
"--os-compute-api-version less than 2.19")
1672+
raise exceptions.CommandError(msg)
1673+
kwargs['description'] = parsed_args.description
16471674

16481675
if parsed_args.key_name or parsed_args.key_unset:
16491676
if compute_client.api_version < api_versions.APIVersion('2.54'):
@@ -2065,6 +2092,12 @@ def get_parser(self, prog_name):
20652092
choices=['active', 'error'],
20662093
help=_('New server state (valid value: active, error)'),
20672094
)
2095+
parser.add_argument(
2096+
'--description',
2097+
metavar='<description>',
2098+
help=_('New server description (supported by '
2099+
'--os-compute-api-version 2.19 or above)'),
2100+
)
20682101
return parser
20692102

20702103
def take_action(self, parsed_args):
@@ -2096,6 +2129,13 @@ def take_action(self, parsed_args):
20962129
msg = _("Passwords do not match, password unchanged")
20972130
raise exceptions.CommandError(msg)
20982131

2132+
if parsed_args.description:
2133+
if server.api_version < api_versions.APIVersion("2.19"):
2134+
msg = _("Description is not supported for "
2135+
"--os-compute-api-version less than 2.19")
2136+
raise exceptions.CommandError(msg)
2137+
server.update(description=parsed_args.description)
2138+
20992139

21002140
class ShelveServer(command.Command):
21012141
_description = _("Shelve server(s)")
@@ -2455,6 +2495,13 @@ def get_parser(self, prog_name):
24552495
help=_('Property key to remove from server '
24562496
'(repeat option to remove multiple values)'),
24572497
)
2498+
parser.add_argument(
2499+
'--description',
2500+
dest='description',
2501+
action='store_true',
2502+
help=_('Unset server description (supported by '
2503+
'--os-compute-api-version 2.19 or above)'),
2504+
)
24582505
return parser
24592506

24602507
def take_action(self, parsed_args):
@@ -2470,6 +2517,16 @@ def take_action(self, parsed_args):
24702517
parsed_args.property,
24712518
)
24722519

2520+
if parsed_args.description:
2521+
if compute_client.api_version < api_versions.APIVersion("2.19"):
2522+
msg = _("Description is not supported for "
2523+
"--os-compute-api-version less than 2.19")
2524+
raise exceptions.CommandError(msg)
2525+
compute_client.servers.update(
2526+
server,
2527+
description="",
2528+
)
2529+
24732530

24742531
class UnshelveServer(command.Command):
24752532
_description = _("Unshelve server(s)")

openstackclient/tests/unit/compute/v2/test_server.py

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1834,6 +1834,90 @@ def test_server_create_image_property_missed(self):
18341834
self.cmd.take_action,
18351835
parsed_args)
18361836

1837+
def test_server_create_with_description_api_newer(self):
1838+
1839+
# Description is supported for nova api version 2.19 or above
1840+
self.app.client_manager.compute.api_version = 2.19
1841+
1842+
arglist = [
1843+
'--image', 'image1',
1844+
'--flavor', 'flavor1',
1845+
'--description', 'description1',
1846+
self.new_server.name,
1847+
]
1848+
verifylist = [
1849+
('image', 'image1'),
1850+
('flavor', 'flavor1'),
1851+
('description', 'description1'),
1852+
('config_drive', False),
1853+
('server_name', self.new_server.name),
1854+
]
1855+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1856+
1857+
with mock.patch.object(api_versions,
1858+
'APIVersion',
1859+
return_value=2.19):
1860+
# In base command class ShowOne in cliff, abstract method
1861+
# take_action() returns a two-part tuple with a tuple of
1862+
# column names and a tuple of data to be shown.
1863+
columns, data = self.cmd.take_action(parsed_args)
1864+
1865+
# Set expected values
1866+
kwargs = dict(
1867+
meta=None,
1868+
files={},
1869+
reservation_id=None,
1870+
min_count=1,
1871+
max_count=1,
1872+
security_groups=[],
1873+
userdata=None,
1874+
key_name=None,
1875+
availability_zone=None,
1876+
block_device_mapping_v2=[],
1877+
nics='auto',
1878+
scheduler_hints={},
1879+
config_drive=None,
1880+
description='description1',
1881+
)
1882+
# ServerManager.create(name, image, flavor, **kwargs)
1883+
self.servers_mock.create.assert_called_with(
1884+
self.new_server.name,
1885+
self.image,
1886+
self.flavor,
1887+
**kwargs
1888+
)
1889+
1890+
self.assertEqual(self.columns, columns)
1891+
self.assertEqual(self.datalist(), data)
1892+
self.assertFalse(self.images_mock.called)
1893+
self.assertFalse(self.flavors_mock.called)
1894+
1895+
def test_server_create_with_description_api_older(self):
1896+
1897+
# Description is not supported for nova api version below 2.19
1898+
self.app.client_manager.compute.api_version = 2.18
1899+
1900+
arglist = [
1901+
'--image', 'image1',
1902+
'--flavor', 'flavor1',
1903+
'--description', 'description1',
1904+
self.new_server.name,
1905+
]
1906+
verifylist = [
1907+
('image', 'image1'),
1908+
('flavor', 'flavor1'),
1909+
('description', 'description1'),
1910+
('config_drive', False),
1911+
('server_name', self.new_server.name),
1912+
]
1913+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1914+
1915+
with mock.patch.object(api_versions,
1916+
'APIVersion',
1917+
return_value=2.19):
1918+
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
1919+
parsed_args)
1920+
18371921

18381922
class TestServerDelete(TestServer):
18391923

@@ -2663,6 +2747,55 @@ def test_rebuild_with_current_image_and_password(self):
26632747
self.images_mock.get.assert_called_with(self.image.id)
26642748
self.server.rebuild.assert_called_with(self.image, password)
26652749

2750+
def test_rebuild_with_description_api_older(self):
2751+
2752+
# Description is not supported for nova api version below 2.19
2753+
self.server.api_version = 2.18
2754+
2755+
description = 'description1'
2756+
arglist = [
2757+
self.server.id,
2758+
'--description', description
2759+
]
2760+
verifylist = [
2761+
('server', self.server.id),
2762+
('description', description)
2763+
]
2764+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
2765+
2766+
with mock.patch.object(api_versions,
2767+
'APIVersion',
2768+
return_value=2.19):
2769+
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
2770+
parsed_args)
2771+
2772+
def test_rebuild_with_description_api_newer(self):
2773+
2774+
# Description is supported for nova api version 2.19 or above
2775+
self.server.api_version = 2.19
2776+
2777+
description = 'description1'
2778+
arglist = [
2779+
self.server.id,
2780+
'--description', description
2781+
]
2782+
verifylist = [
2783+
('server', self.server.id),
2784+
('description', description)
2785+
]
2786+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
2787+
2788+
with mock.patch.object(api_versions,
2789+
'APIVersion',
2790+
return_value=2.19):
2791+
# Get the command object to test
2792+
self.cmd.take_action(parsed_args)
2793+
2794+
self.servers_mock.get.assert_called_with(self.server.id)
2795+
self.images_mock.get.assert_called_with(self.image.id)
2796+
self.server.rebuild.assert_called_with(self.image, None,
2797+
description=description)
2798+
26662799
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
26672800
def test_rebuild_with_wait_ok(self, mock_wait_for_status):
26682801
arglist = [
@@ -3400,6 +3533,10 @@ class TestServerSet(TestServer):
34003533
def setUp(self):
34013534
super(TestServerSet, self).setUp()
34023535

3536+
self.attrs = {
3537+
'api_version': None,
3538+
}
3539+
34033540
self.methods = {
34043541
'update': None,
34053542
'reset_state': None,
@@ -3502,6 +3639,48 @@ def test_server_set_with_root_password(self, mock_getpass):
35023639
mock.sentinel.fake_pass)
35033640
self.assertIsNone(result)
35043641

3642+
def test_server_set_with_description_api_newer(self):
3643+
3644+
# Description is supported for nova api version 2.19 or above
3645+
self.fake_servers[0].api_version = 2.19
3646+
3647+
arglist = [
3648+
'--description', 'foo_description',
3649+
'foo_vm',
3650+
]
3651+
verifylist = [
3652+
('description', 'foo_description'),
3653+
('server', 'foo_vm'),
3654+
]
3655+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
3656+
with mock.patch.object(api_versions,
3657+
'APIVersion',
3658+
return_value=2.19):
3659+
result = self.cmd.take_action(parsed_args)
3660+
self.fake_servers[0].update.assert_called_once_with(
3661+
description='foo_description')
3662+
self.assertIsNone(result)
3663+
3664+
def test_server_set_with_description_api_older(self):
3665+
3666+
# Description is not supported for nova api version below 2.19
3667+
self.fake_servers[0].api_version = 2.18
3668+
3669+
arglist = [
3670+
'--description', 'foo_description',
3671+
'foo_vm',
3672+
]
3673+
verifylist = [
3674+
('description', 'foo_description'),
3675+
('server', 'foo_vm'),
3676+
]
3677+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
3678+
with mock.patch.object(api_versions,
3679+
'APIVersion',
3680+
return_value=2.19):
3681+
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
3682+
parsed_args)
3683+
35053684

35063685
class TestServerShelve(TestServer):
35073686

@@ -3783,6 +3962,50 @@ def test_server_unset_with_property(self):
37833962
self.fake_server, ['key1', 'key2'])
37843963
self.assertIsNone(result)
37853964

3965+
def test_server_unset_with_description_api_newer(self):
3966+
3967+
# Description is supported for nova api version 2.19 or above
3968+
self.app.client_manager.compute.api_version = 2.19
3969+
3970+
arglist = [
3971+
'--description',
3972+
'foo_vm',
3973+
]
3974+
verifylist = [
3975+
('description', True),
3976+
('server', 'foo_vm'),
3977+
]
3978+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
3979+
3980+
with mock.patch.object(api_versions,
3981+
'APIVersion',
3982+
return_value=2.19):
3983+
result = self.cmd.take_action(parsed_args)
3984+
self.servers_mock.update.assert_called_once_with(
3985+
self.fake_server, description="")
3986+
self.assertIsNone(result)
3987+
3988+
def test_server_unset_with_description_api_older(self):
3989+
3990+
# Description is not supported for nova api version below 2.19
3991+
self.app.client_manager.compute.api_version = 2.18
3992+
3993+
arglist = [
3994+
'--description',
3995+
'foo_vm',
3996+
]
3997+
verifylist = [
3998+
('description', True),
3999+
('server', 'foo_vm'),
4000+
]
4001+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
4002+
4003+
with mock.patch.object(api_versions,
4004+
'APIVersion',
4005+
return_value=2.19):
4006+
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
4007+
parsed_args)
4008+
37864009

37874010
class TestServerUnshelve(TestServer):
37884011

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
features:
3+
- |
4+
Add ``--description`` option to ``server create``, ``server rebuild``,
5+
``server set`` and ``server unset`` commands.
6+
[Bug `2002005 <https://storyboard.openstack.org/#!/story/2002005>`_]

0 commit comments

Comments
 (0)