summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormelanie witt <melwittt@gmail.com>2019-06-28 18:17:10 +0000
committermelanie witt <melwittt@gmail.com>2020-07-21 03:26:42 +0000
commit13bab18888f56ae076250a0c90a09a05152be675 (patch)
tree284479e4d0d09239eb692a07952e7cf727cae629
parentdefa0f562b8efc8fc917f1b195c998e2d6224260 (diff)
downloadpython-openstackclient-13bab18888f56ae076250a0c90a09a05152be675.tar.gz
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 (cherry picked from commit bfc34e11b3437506508b3e120accc0e212268ac6) (cherry picked from commit 83359fbe4fd7e5850abd45a467bf197c284519b1) (cherry picked from commit 9698c6675033664fd262bad7844af12067ff3bea)
-rw-r--r--openstackclient/compute/v2/server.py5
-rw-r--r--openstackclient/tests/unit/compute/v2/test_server.py34
2 files changed, 30 insertions, 9 deletions
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index d522135b..1f581537 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -1222,9 +1222,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 d9969d00..2db408a4 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
@@ -64,9 +65,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,
@@ -1878,7 +1892,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')
@@ -1893,7 +1908,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((
@@ -1905,8 +1921,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'),
@@ -1918,7 +1935,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']
))