Merge "Staging area not cleared if image is deleted while importing"

This commit is contained in:
Zuul 2020-01-06 19:50:36 +00:00 committed by Gerrit Code Review
commit 6bdaac00bb
4 changed files with 83 additions and 44 deletions

View File

@ -367,41 +367,41 @@ class ImagesController(object):
image_repo = self.gateway.get_repo(req.context)
try:
image = image_repo.get(image_id)
if image.status == 'uploading':
if CONF.enabled_backends:
file_path = "%s/%s" % (getattr(
CONF, 'os_glance_staging_store'
).filesystem_store_datadir, image_id)
# NOTE(abhishekk): Delete the data from staging area
if CONF.enabled_backends:
separator, staging_dir = store_utils.get_dir_separator()
file_path = "%s%s%s" % (staging_dir,
separator,
image_id)
try:
fn_call = glance_store.get_store_from_store_identifier
staging_store = fn_call('os_glance_staging_store')
loc = location.get_location_from_uri_and_backend(
file_path, 'os_glance_staging_store')
staging_store.delete(loc)
except (glance_store.exceptions.NotFound,
glance_store.exceptions.UnknownScheme):
pass
else:
file_path = str(
CONF.node_staging_uri + '/' + image_id)[7:]
if os.path.exists(file_path):
try:
fn_call = glance_store.get_store_from_store_identifier
staging_store = fn_call('os_glance_staging_store')
loc = location.get_location_from_uri_and_backend(
file_path, 'os_glance_staging_store')
staging_store.delete(loc)
except (glance_store.exceptions.NotFound,
glance_store.exceptions.UnknownScheme):
pass
else:
file_path = str(
CONF.node_staging_uri + '/' + 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:
LOG.warning(_(
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 has failed because "
"it cannot be found at %(fn)s"), {'fn': file_path})
"image data from %(fn)s has failed because "
"[Errno %(en)d]", {'fn': file_path,
'en': e.errno})
else:
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()
self._delete_encryption_key(req.context, image)

View File

@ -29,6 +29,7 @@ import glance.async_.flows.plugins as import_plugins
from glance.common import exception
from glance.common.scripts.image_import import main as image_import
from glance.common.scripts import utils as script_utils
from glance.common import store_utils
from glance.i18n import _, _LE, _LI
@ -344,7 +345,7 @@ def get_flow(**kwargs):
if not uri and import_method == 'glance-direct':
if CONF.enabled_backends:
separator, staging_dir = _get_dir_separator()
separator, staging_dir = store_utils.get_dir_separator()
uri = separator.join((staging_dir, str(image_id)))
else:
uri = separator.join((CONF.node_staging_uri, str(image_id)))
@ -355,7 +356,7 @@ def get_flow(**kwargs):
downloadToStaging = internal_plugins.get_import_plugin(**kwargs)
flow.add(downloadToStaging)
if CONF.enabled_backends:
separator, staging_dir = _get_dir_separator()
separator, staging_dir = store_utils.get_dir_separator()
file_uri = separator.join((staging_dir, str(image_id)))
else:
file_uri = separator.join((CONF.node_staging_uri, str(image_id)))
@ -396,12 +397,3 @@ def get_flow(**kwargs):
image_repo.save(image, from_state=from_state)
return flow
def _get_dir_separator():
separator = ''
staging_dir = "file://%s" % getattr(
CONF, 'os_glance_staging_store').filesystem_store_datadir
if not staging_dir.endswith('/'):
separator = '/'
return separator, staging_dir

View File

@ -193,3 +193,12 @@ def update_store_in_locations(locations, image_id):
'id': image_id})
loc['metadata']['store'] = store_id
def get_dir_separator():
separator = ''
staging_dir = "file://%s" % getattr(
CONF, 'os_glance_staging_store').filesystem_store_datadir
if not staging_dir.endswith('/'):
separator = '/'
return separator, staging_dir

View File

@ -2688,6 +2688,44 @@ class TestImagesController(base.IsolatedUnitTest):
self.assertEqual('deleted', deleted_img['status'])
self.assertNotIn('%s/%s' % (BASE_URI, UUID1), self.store.data)
@mock.patch.object(store, 'get_store_from_store_identifier')
@mock.patch.object(store.location, 'get_location_from_uri_and_backend')
@mock.patch.object(store_utils, 'get_dir_separator')
def test_verify_staging_data_deleted_on_image_delete(
self, mock_get_dir_separator, mock_location,
mock_store):
self.config(enabled_backends={'fake-store': 'file'})
fake_staging_store = mock.Mock()
mock_store.return_value = fake_staging_store
mock_get_dir_separator.return_value = (
"/", "/tmp/os_glance_staging_store")
image_id = str(uuid.uuid4())
self.images = [
_db_fixture(image_id, owner=TENANT1,
name='1',
disk_format='raw',
container_format='bare',
status='importing',
checksum=None,
os_hash_algo=None,
os_hash_value=None),
]
self.db.image_create(None, self.images[0])
request = unit_test_utils.get_fake_request()
try:
self.controller.delete(request, image_id)
self.assertEqual(1, mock_store.call_count)
mock_store.assert_called_once_with("os_glance_staging_store")
self.assertEqual(1, mock_location.call_count)
fake_staging_store.delete.assert_called_once()
except Exception as e:
self.fail("Delete raised exception: %s" % e)
deleted_img = self.db.image_get(request.context, image_id,
force_show_deleted=True)
self.assertTrue(deleted_img['deleted'])
self.assertEqual('deleted', deleted_img['status'])
def test_delete_with_tags(self):
request = unit_test_utils.get_fake_request()
changes = [