Fixes LP Bug#862664 - Improper calls to get_image
The glance.client.Client.get_image() call returns a tuple of (metadata, image_iterator). Unfortunately, Horizon's glance API calls get_image() when it means to call get_image_meta(). Because the call to get_image() simply ignores the image iterator returned from get_image(), when the image iterator is garbage-collected, this causes the connection to Glance to be closed, however by that time the socket bound to the iterator has been switched out by eventlet. The result is lots of these in the Glance API log: 2011-09-28 17:46:12 DEBUG [glance.store.filesystem] Found image at /opt/stack/glance/images/3. Returning in ChunkedFile. 2011-09-28 17:46:12 DEBUG [eventlet.wsgi.server] Traceback (most recent call last): File "/usr/lib/pymodules/python2.7/eventlet/wsgi.py", line 351, in handle_one_response write(''.join(towrite)) File "/usr/lib/pymodules/python2.7/eventlet/wsgi.py", line 301, in write _writelines(towrite) File "/usr/lib/python2.7/socket.py", line 334, in writelines self.flush() File "/usr/lib/python2.7/socket.py", line 303, in flush self._sock.sendall(view[write_offset:write_offset+buffer_size]) File "/usr/lib/pymodules/python2.7/eventlet/greenio.py", line 283, in sendall tail = self.send(data, flags) File "/usr/lib/pymodules/python2.7/eventlet/greenio.py", line 269, in send total_sent += fd.send(data[total_sent:], flags) error: [Errno 104] Connection reset by peer This patch fixes the improper calls to get_image() by replacing them with appropriate calls to get_image_meta(). Change-Id: I741a207ba0e222820492aeb48bab9464d17539ab
This commit is contained in:
parent
6434611696
commit
068c782d03
|
@ -68,7 +68,19 @@ def image_delete(request, image_id):
|
|||
|
||||
|
||||
def image_get(request, image_id):
|
||||
return Image(glance_api(request).get_image(image_id)[0])
|
||||
"""
|
||||
Returns the actual image file from Glance for image with
|
||||
supplied identifier
|
||||
"""
|
||||
return glance_api(request).get_image(image_id)[1]
|
||||
|
||||
|
||||
def image_get_meta(request, image_id):
|
||||
"""
|
||||
Returns an Image object populated with metadata for image
|
||||
with supplied identifier.
|
||||
"""
|
||||
return Image(glance_api(request).get_image_meta(image_id))
|
||||
|
||||
|
||||
def image_list_detailed(request):
|
||||
|
|
|
@ -89,7 +89,7 @@ class Server(APIResourceWrapper):
|
|||
from glance.common import exception as glance_exceptions
|
||||
from horizon.api import glance
|
||||
try:
|
||||
image = glance.image_get(self.request, self.image['id'])
|
||||
image = glance.image_get_meta(self.request, self.image['id'])
|
||||
return image.name
|
||||
except glance_exceptions.NotFound:
|
||||
return "(not found)"
|
||||
|
|
|
@ -57,7 +57,7 @@ class UpdateImageForm(forms.SelfHandlingForm):
|
|||
error_updating = _('Error updating image with id: %s' % image_id)
|
||||
|
||||
try:
|
||||
image = api.image_get(request, image_id)
|
||||
image = api.image_get_meta(request, image_id)
|
||||
except glance_exception.ClientConnectionError, e:
|
||||
LOG.exception(_('Error connecting to glance'))
|
||||
messages.error(request, error_retrieving)
|
||||
|
@ -152,7 +152,7 @@ class LaunchForm(forms.SelfHandlingForm):
|
|||
image_id = data['image_id']
|
||||
tenant_id = data['tenant_id']
|
||||
try:
|
||||
image = api.image_get(request, image_id)
|
||||
image = api.image_get_meta(request, image_id)
|
||||
flavor = api.flavor_get(request, data['flavor'])
|
||||
api.server_create(request,
|
||||
data['name'],
|
||||
|
@ -181,7 +181,7 @@ class DeleteImage(forms.SelfHandlingForm):
|
|||
image_id = data['image_id']
|
||||
tenant_id = request.user.tenant_id
|
||||
try:
|
||||
image = api.image_get(request, image_id)
|
||||
image = api.image_get_meta(request, image_id)
|
||||
if image.owner == request.user.username:
|
||||
api.image_delete(request, image_id)
|
||||
else:
|
||||
|
|
|
@ -153,8 +153,8 @@ class ImageViewTests(test.BaseViewTests):
|
|||
def test_launch_get(self):
|
||||
IMAGE_ID = '1'
|
||||
|
||||
self.mox.StubOutWithMock(api, 'image_get')
|
||||
api.image_get(IsA(http.HttpRequest),
|
||||
self.mox.StubOutWithMock(api, 'image_get_meta')
|
||||
api.image_get_meta(IsA(http.HttpRequest),
|
||||
IMAGE_ID).AndReturn(self.visibleImage)
|
||||
|
||||
self.mox.StubOutWithMock(api, 'tenant_quota_get')
|
||||
|
@ -207,8 +207,8 @@ class ImageViewTests(test.BaseViewTests):
|
|||
'security_groups': 'default',
|
||||
}
|
||||
|
||||
self.mox.StubOutWithMock(api, 'image_get')
|
||||
api.image_get(IsA(http.HttpRequest),
|
||||
self.mox.StubOutWithMock(api, 'image_get_meta')
|
||||
api.image_get_meta(IsA(http.HttpRequest),
|
||||
IMAGE_ID).AndReturn(self.visibleImage)
|
||||
|
||||
self.mox.StubOutWithMock(api, 'tenant_quota_get')
|
||||
|
@ -226,7 +226,7 @@ class ImageViewTests(test.BaseViewTests):
|
|||
self.security_groups)
|
||||
|
||||
# called again by the form
|
||||
api.image_get(IsA(http.HttpRequest),
|
||||
api.image_get_meta(IsA(http.HttpRequest),
|
||||
IMAGE_ID).AndReturn(self.visibleImage)
|
||||
|
||||
self.mox.StubOutWithMock(api, 'flavor_get')
|
||||
|
@ -254,8 +254,8 @@ class ImageViewTests(test.BaseViewTests):
|
|||
def test_launch_flavorlist_error(self):
|
||||
IMAGE_ID = '1'
|
||||
|
||||
self.mox.StubOutWithMock(api, 'image_get')
|
||||
api.image_get(IsA(http.HttpRequest),
|
||||
self.mox.StubOutWithMock(api, 'image_get_meta')
|
||||
api.image_get_meta(IsA(http.HttpRequest),
|
||||
IMAGE_ID).AndReturn(self.visibleImage)
|
||||
|
||||
self.mox.StubOutWithMock(api, 'tenant_quota_get')
|
||||
|
@ -288,8 +288,8 @@ class ImageViewTests(test.BaseViewTests):
|
|||
def test_launch_keypairlist_error(self):
|
||||
IMAGE_ID = '2'
|
||||
|
||||
self.mox.StubOutWithMock(api, 'image_get')
|
||||
api.image_get(IsA(http.HttpRequest),
|
||||
self.mox.StubOutWithMock(api, 'image_get_meta')
|
||||
api.image_get_meta(IsA(http.HttpRequest),
|
||||
IMAGE_ID).AndReturn(self.visibleImage)
|
||||
|
||||
self.mox.StubOutWithMock(api, 'tenant_quota_get')
|
||||
|
@ -336,8 +336,8 @@ class ImageViewTests(test.BaseViewTests):
|
|||
'security_groups': 'default',
|
||||
}
|
||||
|
||||
self.mox.StubOutWithMock(api, 'image_get')
|
||||
api.image_get(IgnoreArg(),
|
||||
self.mox.StubOutWithMock(api, 'image_get_meta')
|
||||
api.image_get_meta(IgnoreArg(),
|
||||
IMAGE_ID).AndReturn(self.visibleImage)
|
||||
|
||||
self.mox.StubOutWithMock(api, 'tenant_quota_get')
|
||||
|
@ -355,7 +355,7 @@ class ImageViewTests(test.BaseViewTests):
|
|||
self.security_groups)
|
||||
|
||||
# called again by the form
|
||||
api.image_get(IgnoreArg(),
|
||||
api.image_get_meta(IgnoreArg(),
|
||||
IMAGE_ID).AndReturn(self.visibleImage)
|
||||
|
||||
self.mox.StubOutWithMock(api, 'flavor_get')
|
||||
|
|
|
@ -110,7 +110,7 @@ def launch(request, image_id):
|
|||
tenant_id = request.user.tenant_id
|
||||
# TODO(mgius): Any reason why these can't be after the launchform logic?
|
||||
# If The form is valid, we've just wasted these two api calls
|
||||
image = api.image_get(request, image_id)
|
||||
image = api.image_get_meta(request, image_id)
|
||||
quotas = api.tenant_quota_get(request, request.user.tenant_id)
|
||||
try:
|
||||
quotas.ram = int(quotas.ram)
|
||||
|
@ -139,7 +139,7 @@ def launch(request, image_id):
|
|||
@login_required
|
||||
def update(request, image_id):
|
||||
try:
|
||||
image = api.image_get(request, image_id)
|
||||
image = api.image_get_meta(request, image_id)
|
||||
except glance_exception.ClientConnectionError, e:
|
||||
LOG.exception("Error connecting to glance")
|
||||
messages.error(request, _("Error connecting to glance: %s")
|
||||
|
|
|
@ -70,7 +70,7 @@ def index(request):
|
|||
@login_required
|
||||
def update(request, image_id):
|
||||
try:
|
||||
image = api.image_get(request, image_id)
|
||||
image = api.image_get_meta(request, image_id)
|
||||
except glance_exception.ClientConnectionError, e:
|
||||
LOG.exception("Error connecting to glance")
|
||||
messages.error(request,
|
||||
|
|
|
@ -79,18 +79,18 @@ class GlanceApiTests(APITestCase):
|
|||
|
||||
self.assertEqual(ret_val, TEST_RETURN)
|
||||
|
||||
def test_image_get(self):
|
||||
def test_image_get_meta(self):
|
||||
IMAGE_ID = '1'
|
||||
|
||||
glance_api = self.stub_glance_api()
|
||||
glance_api.get_image(IMAGE_ID).AndReturn([TEST_RETURN])
|
||||
glance_api.get_image_meta(IMAGE_ID).AndReturn([TEST_RETURN])
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.image_get(self.request, IMAGE_ID)
|
||||
ret_val = api.image_get_meta(self.request, IMAGE_ID)
|
||||
|
||||
self.assertIsInstance(ret_val, api.Image)
|
||||
self.assertEqual(ret_val._apidict, TEST_RETURN)
|
||||
self.assertEqual(ret_val._apidict, [TEST_RETURN])
|
||||
|
||||
def test_image_list_detailed(self):
|
||||
images = (TEST_RETURN, TEST_RETURN + '2')
|
||||
|
|
|
@ -99,8 +99,8 @@ class ServerWrapperTests(test.TestCase):
|
|||
|
||||
def test_image_name(self):
|
||||
image = api.Image({'name': self.IMAGE_NAME})
|
||||
self.mox.StubOutWithMock(api.glance, 'image_get')
|
||||
api.glance.image_get(IsA(http.HttpRequest),
|
||||
self.mox.StubOutWithMock(api.glance, 'image_get_meta')
|
||||
api.glance.image_get_meta(IsA(http.HttpRequest),
|
||||
self.IMAGE_OBJ['id']).AndReturn(image)
|
||||
|
||||
server = api.Server(self.inner_server, self.request)
|
||||
|
|
Loading…
Reference in New Issue