Merge "Staging area not cleared if image is deleted while importing"
This commit is contained in:
commit
6bdaac00bb
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 = [
|
||||
|
Loading…
Reference in New Issue
Block a user