Skip to content

Commit c77a962

Browse files
git861Dean Troyer
authored andcommitted
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
1 parent 0a2b01f commit c77a962

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
@@ -502,6 +502,12 @@ def get_parser(self, prog_name):
502502
metavar='<user-data>',
503503
help=_('User data file to serve from the metadata server'),
504504
)
505+
parser.add_argument(
506+
'--description',
507+
metavar='<description>',
508+
help=_('Set description for the server (supported by '
509+
'--os-compute-api-version 2.19 or above)'),
510+
)
505511
parser.add_argument(
506512
'--availability-zone',
507513
metavar='<zone-name>',
@@ -712,6 +718,12 @@ def _match_image(image_api, wanted_properties):
712718
"exception": e}
713719
)
714720

721+
if parsed_args.description:
722+
if compute_client.api_version < api_versions.APIVersion("2.19"):
723+
msg = _("Description is not supported for "
724+
"--os-compute-api-version less than 2.19")
725+
raise exceptions.CommandError(msg)
726+
715727
block_device_mapping_v2 = []
716728
if volume:
717729
block_device_mapping_v2 = [{'uuid': volume,
@@ -872,6 +884,9 @@ def _match_image(image_api, wanted_properties):
872884
scheduler_hints=hints,
873885
config_drive=config_drive)
874886

887+
if parsed_args.description:
888+
boot_kwargs['description'] = parsed_args.description
889+
875890
LOG.debug('boot_args: %s', boot_args)
876891
LOG.debug('boot_kwargs: %s', boot_kwargs)
877892

@@ -1529,6 +1544,12 @@ def get_parser(self, prog_name):
15291544
help=_('Set a property on the rebuilt instance '
15301545
'(repeat option to set multiple values)'),
15311546
)
1547+
parser.add_argument(
1548+
'--description',
1549+
metavar='<description>',
1550+
help=_('New description for the server (supported by '
1551+
'--os-compute-api-version 2.19 or above'),
1552+
)
15321553
parser.add_argument(
15331554
'--wait',
15341555
action='store_true',
@@ -1557,6 +1578,12 @@ def _show_progress(progress):
15571578
kwargs = {}
15581579
if parsed_args.property:
15591580
kwargs['meta'] = parsed_args.property
1581+
if parsed_args.description:
1582+
if server.api_version < api_versions.APIVersion("2.19"):
1583+
msg = _("Description is not supported for "
1584+
"--os-compute-api-version less than 2.19")
1585+
raise exceptions.CommandError(msg)
1586+
kwargs['description'] = parsed_args.description
15601587

15611588
server = server.rebuild(image, parsed_args.password, **kwargs)
15621589
if parsed_args.wait:
@@ -1968,6 +1995,12 @@ def get_parser(self, prog_name):
19681995
choices=['active', 'error'],
19691996
help=_('New server state (valid value: active, error)'),
19701997
)
1998+
parser.add_argument(
1999+
'--description',
2000+
metavar='<description>',
2001+
help=_('New server description (supported by '
2002+
'--os-compute-api-version 2.19 or above)'),
2003+
)
19712004
return parser
19722005

19732006
def take_action(self, parsed_args):
@@ -1999,6 +2032,13 @@ def take_action(self, parsed_args):
19992032
msg = _("Passwords do not match, password unchanged")
20002033
raise exceptions.CommandError(msg)
20012034

2035+
if parsed_args.description:
2036+
if server.api_version < api_versions.APIVersion("2.19"):
2037+
msg = _("Description is not supported for "
2038+
"--os-compute-api-version less than 2.19")
2039+
raise exceptions.CommandError(msg)
2040+
server.update(description=parsed_args.description)
2041+
20022042

20032043
class ShelveServer(command.Command):
20042044
_description = _("Shelve server(s)")
@@ -2358,6 +2398,13 @@ def get_parser(self, prog_name):
23582398
help=_('Property key to remove from server '
23592399
'(repeat option to remove multiple values)'),
23602400
)
2401+
parser.add_argument(
2402+
'--description',
2403+
dest='description',
2404+
action='store_true',
2405+
help=_('Unset server description (supported by '
2406+
'--os-compute-api-version 2.19 or above)'),
2407+
)
23612408
return parser
23622409

23632410
def take_action(self, parsed_args):
@@ -2373,6 +2420,16 @@ def take_action(self, parsed_args):
23732420
parsed_args.property,
23742421
)
23752422

2423+
if parsed_args.description:
2424+
if compute_client.api_version < api_versions.APIVersion("2.19"):
2425+
msg = _("Description is not supported for "
2426+
"--os-compute-api-version less than 2.19")
2427+
raise exceptions.CommandError(msg)
2428+
compute_client.servers.update(
2429+
server,
2430+
description="",
2431+
)
2432+
23762433

23772434
class UnshelveServer(command.Command):
23782435
_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
@@ -1736,6 +1736,90 @@ def test_server_create_image_property_missed(self):
17361736
self.cmd.take_action,
17371737
parsed_args)
17381738

1739+
def test_server_create_with_description_api_newer(self):
1740+
1741+
# Description is supported for nova api version 2.19 or above
1742+
self.app.client_manager.compute.api_version = 2.19
1743+
1744+
arglist = [
1745+
'--image', 'image1',
1746+
'--flavor', 'flavor1',
1747+
'--description', 'description1',
1748+
self.new_server.name,
1749+
]
1750+
verifylist = [
1751+
('image', 'image1'),
1752+
('flavor', 'flavor1'),
1753+
('description', 'description1'),
1754+
('config_drive', False),
1755+
('server_name', self.new_server.name),
1756+
]
1757+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1758+
1759+
with mock.patch.object(api_versions,
1760+
'APIVersion',
1761+
return_value=2.19):
1762+
# In base command class ShowOne in cliff, abstract method
1763+
# take_action() returns a two-part tuple with a tuple of
1764+
# column names and a tuple of data to be shown.
1765+
columns, data = self.cmd.take_action(parsed_args)
1766+
1767+
# Set expected values
1768+
kwargs = dict(
1769+
meta=None,
1770+
files={},
1771+
reservation_id=None,
1772+
min_count=1,
1773+
max_count=1,
1774+
security_groups=[],
1775+
userdata=None,
1776+
key_name=None,
1777+
availability_zone=None,
1778+
block_device_mapping_v2=[],
1779+
nics='auto',
1780+
scheduler_hints={},
1781+
config_drive=None,
1782+
description='description1',
1783+
)
1784+
# ServerManager.create(name, image, flavor, **kwargs)
1785+
self.servers_mock.create.assert_called_with(
1786+
self.new_server.name,
1787+
self.image,
1788+
self.flavor,
1789+
**kwargs
1790+
)
1791+
1792+
self.assertEqual(self.columns, columns)
1793+
self.assertEqual(self.datalist(), data)
1794+
self.assertFalse(self.images_mock.called)
1795+
self.assertFalse(self.flavors_mock.called)
1796+
1797+
def test_server_create_with_description_api_older(self):
1798+
1799+
# Description is not supported for nova api version below 2.19
1800+
self.app.client_manager.compute.api_version = 2.18
1801+
1802+
arglist = [
1803+
'--image', 'image1',
1804+
'--flavor', 'flavor1',
1805+
'--description', 'description1',
1806+
self.new_server.name,
1807+
]
1808+
verifylist = [
1809+
('image', 'image1'),
1810+
('flavor', 'flavor1'),
1811+
('description', 'description1'),
1812+
('config_drive', False),
1813+
('server_name', self.new_server.name),
1814+
]
1815+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1816+
1817+
with mock.patch.object(api_versions,
1818+
'APIVersion',
1819+
return_value=2.19):
1820+
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
1821+
parsed_args)
1822+
17391823

17401824
class TestServerDelete(TestServer):
17411825

@@ -2493,6 +2577,55 @@ def test_rebuild_with_current_image_and_password(self):
24932577
self.images_mock.get.assert_called_with(self.image.id)
24942578
self.server.rebuild.assert_called_with(self.image, password)
24952579

2580+
def test_rebuild_with_description_api_older(self):
2581+
2582+
# Description is not supported for nova api version below 2.19
2583+
self.server.api_version = 2.18
2584+
2585+
description = 'description1'
2586+
arglist = [
2587+
self.server.id,
2588+
'--description', description
2589+
]
2590+
verifylist = [
2591+
('server', self.server.id),
2592+
('description', description)
2593+
]
2594+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
2595+
2596+
with mock.patch.object(api_versions,
2597+
'APIVersion',
2598+
return_value=2.19):
2599+
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
2600+
parsed_args)
2601+
2602+
def test_rebuild_with_description_api_newer(self):
2603+
2604+
# Description is supported for nova api version 2.19 or above
2605+
self.server.api_version = 2.19
2606+
2607+
description = 'description1'
2608+
arglist = [
2609+
self.server.id,
2610+
'--description', description
2611+
]
2612+
verifylist = [
2613+
('server', self.server.id),
2614+
('description', description)
2615+
]
2616+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
2617+
2618+
with mock.patch.object(api_versions,
2619+
'APIVersion',
2620+
return_value=2.19):
2621+
# Get the command object to test
2622+
self.cmd.take_action(parsed_args)
2623+
2624+
self.servers_mock.get.assert_called_with(self.server.id)
2625+
self.images_mock.get.assert_called_with(self.image.id)
2626+
self.server.rebuild.assert_called_with(self.image, None,
2627+
description=description)
2628+
24962629
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
24972630
def test_rebuild_with_wait_ok(self, mock_wait_for_status):
24982631
arglist = [
@@ -3140,6 +3273,10 @@ class TestServerSet(TestServer):
31403273
def setUp(self):
31413274
super(TestServerSet, self).setUp()
31423275

3276+
self.attrs = {
3277+
'api_version': None,
3278+
}
3279+
31433280
self.methods = {
31443281
'update': None,
31453282
'reset_state': None,
@@ -3242,6 +3379,48 @@ def test_server_set_with_root_password(self, mock_getpass):
32423379
mock.sentinel.fake_pass)
32433380
self.assertIsNone(result)
32443381

3382+
def test_server_set_with_description_api_newer(self):
3383+
3384+
# Description is supported for nova api version 2.19 or above
3385+
self.fake_servers[0].api_version = 2.19
3386+
3387+
arglist = [
3388+
'--description', 'foo_description',
3389+
'foo_vm',
3390+
]
3391+
verifylist = [
3392+
('description', 'foo_description'),
3393+
('server', 'foo_vm'),
3394+
]
3395+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
3396+
with mock.patch.object(api_versions,
3397+
'APIVersion',
3398+
return_value=2.19):
3399+
result = self.cmd.take_action(parsed_args)
3400+
self.fake_servers[0].update.assert_called_once_with(
3401+
description='foo_description')
3402+
self.assertIsNone(result)
3403+
3404+
def test_server_set_with_description_api_older(self):
3405+
3406+
# Description is not supported for nova api version below 2.19
3407+
self.fake_servers[0].api_version = 2.18
3408+
3409+
arglist = [
3410+
'--description', 'foo_description',
3411+
'foo_vm',
3412+
]
3413+
verifylist = [
3414+
('description', 'foo_description'),
3415+
('server', 'foo_vm'),
3416+
]
3417+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
3418+
with mock.patch.object(api_versions,
3419+
'APIVersion',
3420+
return_value=2.19):
3421+
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
3422+
parsed_args)
3423+
32453424

32463425
class TestServerShelve(TestServer):
32473426

@@ -3523,6 +3702,50 @@ def test_server_unset_with_property(self):
35233702
self.fake_server, ['key1', 'key2'])
35243703
self.assertIsNone(result)
35253704

3705+
def test_server_unset_with_description_api_newer(self):
3706+
3707+
# Description is supported for nova api version 2.19 or above
3708+
self.app.client_manager.compute.api_version = 2.19
3709+
3710+
arglist = [
3711+
'--description',
3712+
'foo_vm',
3713+
]
3714+
verifylist = [
3715+
('description', True),
3716+
('server', 'foo_vm'),
3717+
]
3718+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
3719+
3720+
with mock.patch.object(api_versions,
3721+
'APIVersion',
3722+
return_value=2.19):
3723+
result = self.cmd.take_action(parsed_args)
3724+
self.servers_mock.update.assert_called_once_with(
3725+
self.fake_server, description="")
3726+
self.assertIsNone(result)
3727+
3728+
def test_server_unset_with_description_api_older(self):
3729+
3730+
# Description is not supported for nova api version below 2.19
3731+
self.app.client_manager.compute.api_version = 2.18
3732+
3733+
arglist = [
3734+
'--description',
3735+
'foo_vm',
3736+
]
3737+
verifylist = [
3738+
('description', True),
3739+
('server', 'foo_vm'),
3740+
]
3741+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
3742+
3743+
with mock.patch.object(api_versions,
3744+
'APIVersion',
3745+
return_value=2.19):
3746+
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
3747+
parsed_args)
3748+
35263749

35273750
class TestServerUnshelve(TestServer):
35283751

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)