diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py index 2792e315f6..a4216e65dc 100644 --- a/openstackclient/compute/v2/server.py +++ b/openstackclient/compute/v2/server.py @@ -1350,9 +1350,12 @@ class ListServer(command.Lister): # Create a dict that maps image_id to image object. # Needed so that we can display the "Image Name" column. # "Image Name" is not crucial, so we swallow any exceptions. + # The 'image' attribute can be an empty string if the server was + # booted from a volume. if parsed_args.name_lookup_one_by_one or image_id: for i_id in set(filter(lambda x: x is not None, - (s.image.get('id') for s in data))): + (s.image.get('id') for s in data + if s.image))): try: images[i_id] = image_client.images.get(i_id) except Exception: diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py index 8ea59a3850..713bf07aa7 100644 --- a/openstackclient/tests/unit/compute/v2/test_server.py +++ b/openstackclient/tests/unit/compute/v2/test_server.py @@ -14,6 +14,7 @@ # import argparse import collections +import copy import getpass import mock @@ -65,9 +66,22 @@ class TestServer(compute_fakes.TestComputev2): self.methods = {} def setup_servers_mock(self, count): - servers = compute_fakes.FakeServer.create_servers(attrs=self.attrs, - methods=self.methods, - count=count) + # If we are creating more than one server, make one of them + # boot-from-volume + include_bfv = count > 1 + servers = compute_fakes.FakeServer.create_servers( + attrs=self.attrs, + methods=self.methods, + count=count - 1 if include_bfv else count + ) + if include_bfv: + attrs = copy.deepcopy(self.attrs) + attrs['image'] = '' + bfv_server = compute_fakes.FakeServer.create_one_server( + attrs=attrs, + methods=self.methods + ) + servers.append(bfv_server) # This is the return value for utils.find_resource() self.servers_mock.get = compute_fakes.FakeServer.get_servers(servers, @@ -2129,7 +2143,8 @@ class TestServerList(TestServer): Image = collections.namedtuple('Image', 'id name') self.images_mock.list.return_value = [ Image(id=s.image['id'], name=self.image.name) - for s in self.servers + # Image will be an empty string if boot-from-volume + for s in self.servers if s.image ] Flavor = collections.namedtuple('Flavor', 'id name') @@ -2144,7 +2159,8 @@ class TestServerList(TestServer): s.name, s.status, server._format_servers_list_networks(s.networks), - self.image.name, + # Image will be an empty string if boot-from-volume + self.image.name if s.image else s.image, self.flavor.name, )) self.data_long.append(( @@ -2156,8 +2172,9 @@ class TestServerList(TestServer): getattr(s, 'OS-EXT-STS:power_state') ), server._format_servers_list_networks(s.networks), - self.image.name, - s.image['id'], + # Image will be an empty string if boot-from-volume + self.image.name if s.image else s.image, + s.image['id'] if s.image else s.image, self.flavor.name, s.flavor['id'], getattr(s, 'OS-EXT-AZ:availability_zone'), @@ -2169,7 +2186,8 @@ class TestServerList(TestServer): s.name, s.status, server._format_servers_list_networks(s.networks), - s.image['id'], + # Image will be an empty string if boot-from-volume + s.image['id'] if s.image else s.image, s.flavor['id'] ))