Skip to content

Commit f5384ae

Browse files
author
KeithMnemonic
committed
Fix openstack server list --deleted --marker option
This patch removes using the "name" option for a marker when --deleted is also used. The find_resource() function that is being called does not correctly handle using the marker as the "name" in the search when also using deleted=True. One simple way to fix this is force the marker to only be an ID when --deleted is used. This is how the nova client works. Using the --deleted option is available to users with the admin role by default. If you're an admin listing --deleted servers with a marker by name, find_resource() is going to fail to find it since it doesn't apply the --deleted filter to find_resource(). The find_resource() function is trying to find the marker server by name if it's not found by id, and to find it by name it's listing servers with the given marker as the name, but not applying the --deleted filter so it doesn't get back any results. In the story it was suggested modifying find_resource to include the deleted query param when it's specified on the command line but that didn't work because it still results in something like this: http://192.168.1.123/compute/v2.1/servers?deleted=True&name=4cecd49f-bc25-4a7e-826e-4aea6f9267d9 It seems like there are bugs in find_resource(). Restricting the marker to be the server ID when listing deleted servers is probably OK since if you're using --deleted you're an admin and you could be listing across all projects and if you're filtering by a server across all projects anyway (not that you have to, I'm just saying if you are), or even showing a server in another project, you have to do it by id rather than name because find_resource() won't find the server in another project by name, only ID. story: 2006761 Task: 37258 Change-Id: Ib878982b1d469212ca3483dcfaf407a8e1d2b417
1 parent 5b3a827 commit f5384ae

3 files changed

Lines changed: 63 additions & 3 deletions

File tree

openstackclient/compute/v2/server.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,7 +1242,8 @@ def get_parser(self, prog_name):
12421242
default=None,
12431243
help=_('The last server of the previous page. Display '
12441244
'list of servers after marker. Display all servers if not '
1245-
'specified. (name or ID)')
1245+
'specified. When used with ``--deleted``, the marker must '
1246+
'be an ID, otherwise a name or ID can be used.'),
12461247
)
12471248
parser.add_argument(
12481249
'--limit',
@@ -1450,9 +1451,17 @@ def take_action(self, parsed_args):
14501451
mixed_case_fields = []
14511452

14521453
marker_id = None
1454+
14531455
if parsed_args.marker:
1454-
marker_id = utils.find_resource(compute_client.servers,
1455-
parsed_args.marker).id
1456+
# Check if both "--marker" and "--deleted" are used.
1457+
# In that scenario a lookup is not needed as the marker
1458+
# needs to be an ID, because find_resource does not
1459+
# handle deleted resources
1460+
if parsed_args.deleted:
1461+
marker_id = parsed_args.marker
1462+
else:
1463+
marker_id = utils.find_resource(compute_client.servers,
1464+
parsed_args.marker).id
14561465

14571466
data = compute_client.servers.list(search_opts=search_opts,
14581467
marker=marker_id,

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,49 @@ def test_server_list(self):
6363
self.assertNotIn(name1, col_name)
6464
self.assertIn(name2, col_name)
6565

66+
def test_server_list_with_marker_and_deleted(self):
67+
"""Test server list with deleted and marker"""
68+
cmd_output = self.server_create(cleanup=False)
69+
name1 = cmd_output['name']
70+
cmd_output = self.server_create(cleanup=False)
71+
name2 = cmd_output['name']
72+
id2 = cmd_output['id']
73+
self.wait_for_status(name1, "ACTIVE")
74+
self.wait_for_status(name2, "ACTIVE")
75+
76+
# Test list --marker with ID
77+
cmd_output = json.loads(self.openstack(
78+
'server list -f json --marker ' + id2
79+
))
80+
col_name = [x["Name"] for x in cmd_output]
81+
self.assertIn(name1, col_name)
82+
83+
# Test list --marker with Name
84+
cmd_output = json.loads(self.openstack(
85+
'server list -f json --marker ' + name2
86+
))
87+
col_name = [x["Name"] for x in cmd_output]
88+
self.assertIn(name1, col_name)
89+
90+
self.openstack('server delete --wait ' + name1)
91+
self.openstack('server delete --wait ' + name2)
92+
93+
# Test list --deleted --marker with ID
94+
cmd_output = json.loads(self.openstack(
95+
'server list -f json --deleted --marker ' + id2
96+
))
97+
col_name = [x["Name"] for x in cmd_output]
98+
self.assertIn(name1, col_name)
99+
100+
# Test list --deleted --marker with Name
101+
try:
102+
cmd_output = json.loads(self.openstack(
103+
'server list -f json --deleted --marker ' + name2
104+
))
105+
except exceptions.CommandFailed as e:
106+
self.assertIn('marker [%s] not found (HTTP 400)' % (name2),
107+
e.stderr.decode('utf-8'))
108+
66109
def test_server_list_with_changes_before(self):
67110
"""Test server list.
68111
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
fixes:
3+
- |
4+
Fixes the "No server with a name or ID of 'id' exists" error when running
5+
``server list --deleted --marker``. The fix removes using a name for
6+
the marker when both ``--deleted`` and ``--marker`` are used. In
7+
this scenario an ID must be supplied for the marker.
8+
[Story `2006761 <https://storyboard.openstack.org/#!/story/2006761>`_]

0 commit comments

Comments
 (0)