Merge "Fix error that failed to get image for booting server"

This commit is contained in:
Zuul 2020-01-01 15:15:43 +00:00 committed by Gerrit Code Review
commit 62aae48bd2
6 changed files with 75 additions and 43 deletions

View File

@ -268,6 +268,18 @@ class API(base.Base):
# New novaclient without 'images' API proxy
return client.glance.list()
def image_get(self, context, name):
client = novaclient(context)
try:
# New novaclient without 'images' API proxy
return client.glance.find_image(name)
except nova_exception.NotFound:
raise exception.ServiceInstanceException(
_("Image with name '%s' was not found.") % name)
except nova_exception.NoUniqueMatch:
raise exception.ServiceInstanceException(
_("Found more than one image by name '%s'.") % name)
def add_security_group_to_server(self, context, server, security_group):
return novaclient(context).servers.add_security_group(server,
security_group)

View File

@ -519,19 +519,12 @@ class ServiceInstanceManager(object):
def _get_service_image(self, context):
"""Returns ID of service image for service vm creating."""
service_image_name = self.get_config_option("service_image_name")
images = [image.id for image in self.compute_api.image_list(context)
if image.name == service_image_name
and image.status == 'active']
if len(images) == 1:
return images[0]
elif not images:
image = self.compute_api.image_get(context, service_image_name)
if image.status != 'active':
raise exception.ServiceInstanceException(
_("Image with name '%s' was not found or is not in "
"'active' state.") % service_image_name)
else:
raise exception.ServiceInstanceException(
_("Found more than one image by name '%s'.") %
_("Image with name '%s' is not in 'active' state.") %
service_image_name)
return image
def _create_service_instance(self, context, instance_name, network_info):
"""Creates service vm and sets up networking for it."""

View File

@ -222,6 +222,48 @@ class NovaApiTestCase(test.TestCase):
self.assertEqual(image_list1, result)
def test_image_get_novaclient_has_no_proxy(self):
image = 'fake-image'
class FakeGlanceClient(object):
def find_image(self, name):
return image
self.novaclient.glance = FakeGlanceClient()
result = self.api.image_get(self.ctx, 'fake-image')
self.assertEqual(image, result)
def test_image_get_novaclient_not_found(self):
image = 'fake-image'
class FakeGlanceClient(object):
def find_image(self, image):
return image
self.novaclient.glance = FakeGlanceClient()
self.mock_object(self.novaclient.glance, 'find_image',
mock.Mock(return_value=image,
side_effect=nova_exception.NotFound(404)))
self.assertRaises(exception.ServiceInstanceException,
self.api.image_get, self.ctx, image)
def test_image_get_novaclient_multi_match(self):
image = 'fake-image'
class FakeGlanceClient(object):
def find_image(self, image):
return image
self.novaclient.glance = FakeGlanceClient()
self.mock_object(self.novaclient.glance, 'find_image',
mock.Mock(return_value=image,
side_effect=nova_exception.NoUniqueMatch))
self.assertRaises(exception.ServiceInstanceException,
self.api.image_get, self.ctx, image)
def test_server_create(self):
result = self.api.server_create(self.ctx, 'server_name', 'fake_image',
'fake_flavor', None, None, None)

View File

@ -101,6 +101,9 @@ class API(object):
def image_list(self, *args, **kwargs):
pass
def image_get(self, *args, **kwargs):
pass
def security_group_create(self, *args, **kwargs):
pass

View File

@ -732,46 +732,21 @@ class ServiceInstanceManagerTestCase(test.TestCase):
self.assertEqual((None, None), result)
def test_get_service_image(self):
fake_image1 = fake_compute.FakeImage(
fake_image = fake_compute.FakeImage(
name=self._manager.get_config_option('service_image_name'),
status='active')
fake_image2 = fake_compute.FakeImage(
name='service_image_name',
status='error')
fake_image3 = fake_compute.FakeImage(
name='another-image',
status='active')
self.mock_object(self._manager.compute_api, 'image_list',
mock.Mock(return_value=[fake_image1,
fake_image2,
fake_image3]))
self.mock_object(self._manager.compute_api, 'image_get',
mock.Mock(return_value=fake_image))
result = self._manager._get_service_image(self._manager.admin_context)
self.assertEqual(fake_image1.id, result)
def test_get_service_image_not_found(self):
self.mock_object(self._manager.compute_api, 'image_list',
mock.Mock(return_value=[]))
self.assertRaises(
exception.ServiceInstanceException,
self._manager._get_service_image, self._manager.admin_context)
self.assertEqual(fake_image, result)
def test_get_service_image_not_active(self):
fake_error_image = fake_compute.FakeImage(
name='service_image_name',
status='error')
self.mock_object(self._manager.compute_api, 'image_list',
mock.Mock(return_value=[fake_error_image]))
self.assertRaises(
exception.ServiceInstanceException,
self._manager._get_service_image, self._manager.admin_context)
def test_get_service_image_ambiguous(self):
fake_image = fake_compute.FakeImage(
name=fake_get_config_option('service_image_name'),
status='active')
fake_images = [fake_image, fake_image]
self.mock_object(self._manager.compute_api, 'image_list',
mock.Mock(return_value=fake_images))
self.mock_object(self._manager.compute_api, 'image_get',
mock.Mock(return_value=fake_error_image))
self.assertRaises(
exception.ServiceInstanceException,
self._manager._get_service_image, self._manager.admin_context)

View File

@ -0,0 +1,7 @@
---
fixes:
- |
The Generic driver has been fixed to invoke compute image
retrieval by ID rather than list all images and implement a filter.
This prevents failures in case there are a lot of images available
and the image service returns a paginated response.