Image deletion returns 500 if 'file' store is not enabled

When image import fails during image is uploading from staging area,
image remains in uploading state and data remains in staging area. In
this scenario if 'file' store is not enabled then while deleting the
image glance-api returns 500 status code with error 'file' scheme is
Unknwon.

Used os module to unlink the file present in staging area explicitly to
delete the data from staging area.

Change-Id: I57dcd6b18b0039e824e8adbe77de59079360a34f
Closes-Bug: #1836140
This commit is contained in:
Abhishek Kekane 2019-07-11 06:06:04 +00:00
parent 9bb432c30d
commit 7f74a92338
2 changed files with 51 additions and 10 deletions

View File

@ -14,6 +14,7 @@
# under the License.
import hashlib
import os
import re
import glance_store
@ -336,11 +337,25 @@ class ImagesController(object):
image = image_repo.get(image_id)
if image.status == 'uploading':
file_path = str(CONF.node_staging_uri + '/' + image.image_id)
if CONF.enabled_backends:
self.store_api.delete(file_path, None)
file_path = str(
CONF.node_staging_uri + '/' + image.image_id)[7:]
if os.path.exists(file_path):
try:
LOG.debug(
"After upload to the backend, deleting staged "
"image data from %(fn)s", {'fn': file_path})
os.unlink(file_path)
except OSError as e:
LOG.error(
"After upload to backend, deletion of staged "
"image data from %(fn)s has failed because "
"[Errno %(en)d]", {'fn': file_path,
'en': e.errno})
else:
self.store_api.delete_from_backend(file_path)
LOG.warning(_(
"After upload to backend, deletion of staged "
"image data has failed because "
"it cannot be found at %(fn)s"), {'fn': file_path})
image.delete()
image_repo.remove(image)

View File

@ -16,6 +16,7 @@
import datetime
import eventlet
import hashlib
import os
import uuid
import glance_store as store
@ -2643,17 +2644,42 @@ class TestImagesController(base.IsolatedUnitTest):
request, UUID1)
def test_delete_uploading_status_image(self):
"""Ensure status of uploading image is updated (LP bug #1733289)"""
"""Ensure uploading image is deleted (LP bug #1733289)
Ensure image stuck in uploading state is deleted (LP bug #1836140)
"""
request = unit_test_utils.get_fake_request(is_admin=True)
image = self.db.image_create(request.context, {'status': 'uploading'})
image_id = image['id']
with mock.patch.object(self.store,
'delete_from_backend') as mock_store:
self.controller.delete(request, image_id)
with mock.patch.object(os.path, 'exists') as mock_exists:
mock_exists.return_value = True
with mock.patch.object(os, "unlink") as mock_unlik:
self.controller.delete(request, image_id)
# Ensure delete_from_backend is called
self.assertEqual(1, mock_store.call_count)
self.assertEqual(1, mock_exists.call_count)
self.assertEqual(1, mock_unlik.call_count)
# Ensure that image is deleted
image = self.db.image_get(request.context, image_id,
force_show_deleted=True)
self.assertTrue(image['deleted'])
self.assertEqual('deleted', image['status'])
def test_deletion_of_staging_data_failed(self):
"""Ensure uploading image is deleted (LP bug #1733289)
Ensure image stuck in uploading state is deleted (LP bug #1836140)
"""
request = unit_test_utils.get_fake_request(is_admin=True)
image = self.db.image_create(request.context, {'status': 'uploading'})
image_id = image['id']
with mock.patch.object(os.path, 'exists') as mock_exists:
mock_exists.return_value = False
with mock.patch.object(os, "unlink") as mock_unlik:
self.controller.delete(request, image_id)
self.assertEqual(1, mock_exists.call_count)
self.assertEqual(0, mock_unlik.call_count)
# Ensure that image is deleted
image = self.db.image_get(request.context, image_id,
force_show_deleted=True)
self.assertTrue(image['deleted'])