From eea7318d9ef5d5f21a0c582168d21e21efa3017c Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Sat, 23 Feb 2013 15:24:20 +0000 Subject: [PATCH] Clean unused kernels and ramdisks from image cache Fixes bug #1132138 Only unused disk images are currently cleaned up by the image cache manager but it seems logical to clean up unused kernels and ramdisks too. Achieve that by writing kernels and ramdisks to disk using the sha1 sum of their ID as the filename. This is the same scheme as used for disk image filenames and causes the image cache manager to consider them for cleanup. We also make the cache manager take note of in use kernels and ramdisks when iterating over the list of instances. A nasty upgrade concern is that if we immediately switch to writing kernels to disk using this scheme then, where shared storage is used, we can have older image cache managers on remote compute nodes cleaning up kernels because they appear unused. To mitigate that, turn off this behaviour by default and allow it to be enabled using a new config option. This option will be removed in future and the behaviour enabled by default. DocImpact: new remove_unused_kernels option Change-Id: I56bba9fa6596601104498e262c2e657f0eae2fa0 --- nova/tests/test_imagecache.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/nova/tests/test_imagecache.py b/nova/tests/test_imagecache.py index 0c5c6d02..b225a211 100644 --- a/nova/tests/test_imagecache.py +++ b/nova/tests/test_imagecache.py @@ -163,6 +163,8 @@ class ImageCacheManagerTestCase(test.TestCase): 'vm_state': '', 'task_state': ''}, {'image_ref': '2', + 'kernel_id': '21', + 'ramdisk_id': '22', 'host': 'remotehost', 'name': 'inst-3', 'uuid': '789', @@ -174,18 +176,24 @@ class ImageCacheManagerTestCase(test.TestCase): # The argument here should be a context, but it's mocked out image_cache_manager._list_running_instances(None, all_instances) - self.assertEqual(len(image_cache_manager.used_images), 2) + self.assertEqual(len(image_cache_manager.used_images), 4) self.assertTrue(image_cache_manager.used_images['1'] == (1, 0, ['inst-1'])) self.assertTrue(image_cache_manager.used_images['2'] == (1, 1, ['inst-2', 'inst-3'])) + self.assertTrue(image_cache_manager.used_images['21'] == + (0, 1, ['inst-3'])) + self.assertTrue(image_cache_manager.used_images['22'] == + (0, 1, ['inst-3'])) self.assertTrue('inst-1' in image_cache_manager.instance_names) self.assertTrue('123' in image_cache_manager.instance_names) - self.assertEqual(len(image_cache_manager.image_popularity), 2) + self.assertEqual(len(image_cache_manager.image_popularity), 4) self.assertEqual(image_cache_manager.image_popularity['1'], 1) self.assertEqual(image_cache_manager.image_popularity['2'], 2) + self.assertEqual(image_cache_manager.image_popularity['21'], 1) + self.assertEqual(image_cache_manager.image_popularity['22'], 1) def test_list_resizing_instances(self): all_instances = [{'image_ref': '1', @@ -703,6 +711,8 @@ class ImageCacheManagerTestCase(test.TestCase): def test_verify_base_images(self): hashed_1 = '356a192b7913b04c54574d18c28d46e6395428ab' + hashed_21 = '472b07b9fcf2c2451e8781e944bf5f77cd8457c8' + hashed_22 = '12c6fc06c99a462375eeb3f43dfd832b08ca9e17' hashed_42 = '92cfceb39d57d914ed8b14d0e37643de0797ae56' self.flags(instances_path='/instance_path') @@ -715,6 +725,8 @@ class ImageCacheManagerTestCase(test.TestCase): 'e09c675c2d1cfac32dae3c2d83689c8c94bc693b_sm', hashed_42, hashed_1, + hashed_21, + hashed_22, '%s_5368709120' % hashed_1, '%s_10737418240' % hashed_1, '00000004'] @@ -744,8 +756,10 @@ class ImageCacheManagerTestCase(test.TestCase): if path == fq_path(p) + '.info': return False - if path in ['/instance_path/_base/%s_sm' % hashed_1, - '/instance_path/_base/%s_sm' % hashed_42]: + if path in ['/instance_path/_base/%s_sm' % i for i in [hashed_1, + hashed_21, + hashed_22, + hashed_42]]: return False self.fail('Unexpected path existence check: %s' % path) @@ -800,6 +814,8 @@ class ImageCacheManagerTestCase(test.TestCase): 'vm_state': '', 'task_state': ''}, {'image_ref': '1', + 'kernel_id': '21', + 'ramdisk_id': '22', 'host': CONF.host, 'name': 'instance-2', 'uuid': '456', @@ -850,7 +866,8 @@ class ImageCacheManagerTestCase(test.TestCase): image_cache_manager.verify_base_images(None, all_instances) # Verify - active = [fq_path(hashed_1), fq_path('%s_5368709120' % hashed_1)] + active = [fq_path(hashed_1), fq_path('%s_5368709120' % hashed_1), + fq_path(hashed_21), fq_path(hashed_22)] self.assertEquals(image_cache_manager.active_base_files, active) for rem in [fq_path('e97222e91fc4241f49a7f520d1dcf446751129b3_sm'),