From 29d4383b166a77595df1b2a24b02a5b2556aaba2 Mon Sep 17 00:00:00 2001 From: Fei Long Wang Date: Mon, 23 Sep 2013 11:45:57 +0800 Subject: [PATCH] Cache cleaner wrongly deletes cache for non invalid images Based on current implement of method delete_stalled_files, it's just deleting all the images located in /incomplete instead of using the param 'older_than' to check if it should be deleted. So this fix will use 'older_than' to confirm brfore deleting. Fixes bug 1228256 Change-Id: Ica27915f8b9b098ecae1e38c8e678d6acf4f2f76 --- glance/image_cache/drivers/sqlite.py | 11 ++++++++-- glance/tests/unit/test_image_cache.py | 31 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/glance/image_cache/drivers/sqlite.py b/glance/image_cache/drivers/sqlite.py index 16ebd62bda..0478af2623 100644 --- a/glance/image_cache/drivers/sqlite.py +++ b/glance/image_cache/drivers/sqlite.py @@ -439,8 +439,15 @@ class Driver(base.Driver): will be deleted. """ for path in self.get_cache_files(self.incomplete_dir): - os.unlink(path) - LOG.info(_("Removed stalled cache file %s"), path) + if os.path.getmtime(path) < older_than: + try: + os.unlink(path) + LOG.info(_("Removed stalled cache file %s"), path) + except Exception as e: + msg = (_("Failed to delete file %(path)s. " + "Got error: %(e)s") % + dict(path=path, e=e)) + LOG.warn(msg) def get_queued_images(self): """ diff --git a/glance/tests/unit/test_image_cache.py b/glance/tests/unit/test_image_cache.py index eefd09cbdb..8dd57428b0 100644 --- a/glance/tests/unit/test_image_cache.py +++ b/glance/tests/unit/test_image_cache.py @@ -16,10 +16,12 @@ # under the License. from contextlib import contextmanager +import datetime import hashlib import os import StringIO import tempfile +import time import fixtures import stubout @@ -147,6 +149,35 @@ class ImageCacheTestCase(object): self.assertFalse(os.path.exists(incomplete_file_path)) + @skip_if_disabled + def test_clean_stalled_nonzero_stall_time(self): + """ + Test the clean method removes the stalled images as expected + """ + incomplete_file_path_1 = os.path.join(self.cache_dir, + 'incomplete', '1') + incomplete_file_path_2 = os.path.join(self.cache_dir, + 'incomplete', '2') + for f in (incomplete_file_path_1, incomplete_file_path_2): + incomplete_file = open(f, 'w') + incomplete_file.write(FIXTURE_DATA) + incomplete_file.close() + + mtime = os.path.getmtime(incomplete_file_path_1) + pastday = datetime.datetime.fromtimestamp(mtime) - \ + datetime.timedelta(days=1) + atime = int(time.mktime(pastday.timetuple())) + mtime = atime + os.utime(incomplete_file_path_1, (atime, mtime)) + + self.assertTrue(os.path.exists(incomplete_file_path_1)) + self.assertTrue(os.path.exists(incomplete_file_path_2)) + + self.cache.clean(stall_time=3600) + + self.assertFalse(os.path.exists(incomplete_file_path_1)) + self.assertTrue(os.path.exists(incomplete_file_path_2)) + @skip_if_disabled def test_prune(self): """