Skip to content

Commit bfc34e1

Browse files
committed
Fix BFV server list handling with --name-lookup-one-by-one
When the --name-lookup-one-by-one option passed to the 'server list' command, the image and flavor names will be looked up for each server being listed instead of fetching all image/flavor names. The current code assumes all servers have an image attribute, but servers booted from volumes have no image, so the following error is raised when listing BFV servers with --name-lookup-one-by-one: AttributeError: ('unicode'|'str') object has no attribute 'get' The error occurs when the code attempts server.image.get('id'). This fixes the --name-lookup-one-by-one code not to assume an image for a server. The unit tests for 'server list' have also been robustified to feature one BFV server to enhance our test coverage. Story: #2006063 Task: #34777 Change-Id: I312c971346c7ded93f6fcaa515098554b8580295
1 parent eada2db commit bfc34e1

2 files changed

Lines changed: 30 additions & 9 deletions

File tree

openstackclient/compute/v2/server.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1350,9 +1350,12 @@ def take_action(self, parsed_args):
13501350
# Create a dict that maps image_id to image object.
13511351
# Needed so that we can display the "Image Name" column.
13521352
# "Image Name" is not crucial, so we swallow any exceptions.
1353+
# The 'image' attribute can be an empty string if the server was
1354+
# booted from a volume.
13531355
if parsed_args.name_lookup_one_by_one or image_id:
13541356
for i_id in set(filter(lambda x: x is not None,
1355-
(s.image.get('id') for s in data))):
1357+
(s.image.get('id') for s in data
1358+
if s.image))):
13561359
try:
13571360
images[i_id] = image_client.images.get(i_id)
13581361
except Exception:

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

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#
1515
import argparse
1616
import collections
17+
import copy
1718
import getpass
1819

1920
import mock
@@ -65,9 +66,22 @@ def setUp(self):
6566
self.methods = {}
6667

6768
def setup_servers_mock(self, count):
68-
servers = compute_fakes.FakeServer.create_servers(attrs=self.attrs,
69-
methods=self.methods,
70-
count=count)
69+
# If we are creating more than one server, make one of them
70+
# boot-from-volume
71+
include_bfv = count > 1
72+
servers = compute_fakes.FakeServer.create_servers(
73+
attrs=self.attrs,
74+
methods=self.methods,
75+
count=count - 1 if include_bfv else count
76+
)
77+
if include_bfv:
78+
attrs = copy.deepcopy(self.attrs)
79+
attrs['image'] = ''
80+
bfv_server = compute_fakes.FakeServer.create_one_server(
81+
attrs=attrs,
82+
methods=self.methods
83+
)
84+
servers.append(bfv_server)
7185

7286
# This is the return value for utils.find_resource()
7387
self.servers_mock.get = compute_fakes.FakeServer.get_servers(servers,
@@ -2129,7 +2143,8 @@ def setUp(self):
21292143
Image = collections.namedtuple('Image', 'id name')
21302144
self.images_mock.list.return_value = [
21312145
Image(id=s.image['id'], name=self.image.name)
2132-
for s in self.servers
2146+
# Image will be an empty string if boot-from-volume
2147+
for s in self.servers if s.image
21332148
]
21342149

21352150
Flavor = collections.namedtuple('Flavor', 'id name')
@@ -2144,7 +2159,8 @@ def setUp(self):
21442159
s.name,
21452160
s.status,
21462161
server._format_servers_list_networks(s.networks),
2147-
self.image.name,
2162+
# Image will be an empty string if boot-from-volume
2163+
self.image.name if s.image else s.image,
21482164
self.flavor.name,
21492165
))
21502166
self.data_long.append((
@@ -2156,8 +2172,9 @@ def setUp(self):
21562172
getattr(s, 'OS-EXT-STS:power_state')
21572173
),
21582174
server._format_servers_list_networks(s.networks),
2159-
self.image.name,
2160-
s.image['id'],
2175+
# Image will be an empty string if boot-from-volume
2176+
self.image.name if s.image else s.image,
2177+
s.image['id'] if s.image else s.image,
21612178
self.flavor.name,
21622179
s.flavor['id'],
21632180
getattr(s, 'OS-EXT-AZ:availability_zone'),
@@ -2169,7 +2186,8 @@ def setUp(self):
21692186
s.name,
21702187
s.status,
21712188
server._format_servers_list_networks(s.networks),
2172-
s.image['id'],
2189+
# Image will be an empty string if boot-from-volume
2190+
s.image['id'] if s.image else s.image,
21732191
s.flavor['id']
21742192
))
21752193

0 commit comments

Comments
 (0)