diff options
author | Dan Prince <dprince@redhat.com> | 2012-06-06 17:35:18 -0400 |
---|---|---|
committer | Dan Prince <dprince@redhat.com> | 2012-06-06 17:35:50 -0400 |
commit | f617896efe466a4080a0061fb1c939b76641043b (patch) | |
tree | 43dda9e70d933c5287f64254e6799f553647ab82 | |
parent | 534e6cf87338d7d47349d6186e622ba73ecb9e40 (diff) | |
download | nova-f617896efe466a4080a0061fb1c939b76641043b.tar.gz nova-f617896efe466a4080a0061fb1c939b76641043b.tar.xz nova-f617896efe466a4080a0061fb1c939b76641043b.zip |
Update libvirt imagecache to support resizes.
Updates the libvirt image cache manage so that it accounts
for instances which are resizing.
Also fixes an issue where an exception was thrown when
the image cache manager ran while instances were resizing.
This is because instances which are resizing may have files in the
Nova instances directory which are missing backing files.
Fixes LP Bug #1006616.
Change-Id: I724c6855b68eca24a00893fd96b26b1443f9da5c
-rw-r--r-- | nova/tests/test_imagecache.py | 42 | ||||
-rw-r--r-- | nova/virt/libvirt/imagecache.py | 43 |
2 files changed, 63 insertions, 22 deletions
diff --git a/nova/tests/test_imagecache.py b/nova/tests/test_imagecache.py index bf08a7ea3..4b1b5dac4 100644 --- a/nova/tests/test_imagecache.py +++ b/nova/tests/test_imagecache.py @@ -26,6 +26,7 @@ import time from nova import test +from nova.compute import task_states from nova import db from nova import flags from nova import log @@ -148,15 +149,18 @@ class ImageCacheManagerTestCase(test.TestCase): lambda x: [{'image_ref': '1', 'host': FLAGS.host, 'name': 'inst-1', - 'uuid': '123'}, + 'uuid': '123', + 'task_state': ''}, {'image_ref': '2', 'host': FLAGS.host, 'name': 'inst-2', - 'uuid': '456'}, + 'uuid': '456', + 'task_state': ''}, {'image_ref': '2', 'host': 'remotehost', 'name': 'inst-3', - 'uuid': '789'}]) + 'uuid': '789', + 'task_state': ''}]) image_cache_manager = imagecache.ImageCacheManager() @@ -173,6 +177,26 @@ class ImageCacheManagerTestCase(test.TestCase): self.assertEqual(image_cache_manager.image_popularity['1'], 1) self.assertEqual(image_cache_manager.image_popularity['2'], 2) + def test_list_resizing_instances(self): + self.stubs.Set(db, 'instance_get_all', + lambda x: [{'image_ref': '1', + 'host': FLAGS.host, + 'name': 'inst-1', + 'uuid': '123', + 'task_state': task_states.RESIZE_VERIFY}]) + + image_cache_manager = imagecache.ImageCacheManager() + image_cache_manager._list_running_instances(None) + + self.assertEqual(len(image_cache_manager.used_images), 1) + self.assertTrue(image_cache_manager.used_images['1'] == + (1, 0, ['inst-1'])) + self.assertTrue(image_cache_manager.instance_names == + set(['inst-1', 'inst-1_resize'])) + + self.assertEqual(len(image_cache_manager.image_popularity), 1) + self.assertEqual(image_cache_manager.image_popularity['1'], 1) + def test_list_backing_images_small(self): self.stubs.Set(os, 'listdir', lambda x: ['_base', 'instance-00000001', @@ -741,11 +765,13 @@ class ImageCacheManagerTestCase(test.TestCase): lambda x: [{'image_ref': '1', 'host': FLAGS.host, 'name': 'instance-1', - 'uuid': '123'}, + 'uuid': '123', + 'task_state': ''}, {'image_ref': '1', 'host': FLAGS.host, 'name': 'instance-2', - 'uuid': '456'}]) + 'uuid': '456', + 'task_state': ''}]) image_cache_manager = imagecache.ImageCacheManager() @@ -838,11 +864,13 @@ class ImageCacheManagerTestCase(test.TestCase): lambda x: [{'image_ref': '1', 'host': FLAGS.host, 'name': 'instance-1', - 'uuid': '123'}, + 'uuid': '123', + 'task_state': ''}, {'image_ref': '1', 'host': FLAGS.host, 'name': 'instance-2', - 'uuid': '456'}]) + 'uuid': '456', + 'task_state': ''}]) def touch(filename): f = open(filename, 'w') diff --git a/nova/virt/libvirt/imagecache.py b/nova/virt/libvirt/imagecache.py index e65d61067..e8536bb46 100644 --- a/nova/virt/libvirt/imagecache.py +++ b/nova/virt/libvirt/imagecache.py @@ -28,6 +28,7 @@ import os import re import time +from nova.compute import task_states from nova import db from nova import flags from nova import log as logging @@ -130,11 +131,21 @@ class ImageCacheManager(object): """List running instances (on all compute nodes).""" self.used_images = {} self.image_popularity = {} - self.instance_names = {} + self.instance_names = set() instances = db.instance_get_all(context) for instance in instances: - self.instance_names[instance['name']] = instance['uuid'] + self.instance_names.add(instance['name']) + + resize_states = [task_states.RESIZE_PREP, + task_states.RESIZE_MIGRATING, + task_states.RESIZE_MIGRATED, + task_states.RESIZE_FINISH, + task_states.RESIZE_REVERTING, + task_states.RESIZE_CONFIRMING, + task_states.RESIZE_VERIFY] + if instance['task_state'] in resize_states: + self.instance_names.add(instance['name'] + '_resize') image_ref_str = str(instance['image_ref']) local, remote, insts = self.used_images.get(image_ref_str, @@ -164,19 +175,21 @@ class ImageCacheManager(object): {'instance': ent, 'backing': backing_file}) - backing_path = os.path.join(FLAGS.instances_path, - FLAGS.base_dir_name, - backing_file) - if not backing_path in inuse_images: - inuse_images.append(backing_path) - - if backing_path in self.unexplained_images: - LOG.warning(_('Instance %(instance)s is using a ' - 'backing file %(backing)s which does ' - 'not appear in the image service'), - {'instance': ent, - 'backing': backing_file}) - self.unexplained_images.remove(backing_path) + if backing_file: + backing_path = os.path.join(FLAGS.instances_path, + FLAGS.base_dir_name, + backing_file) + if not backing_path in inuse_images: + inuse_images.append(backing_path) + + if backing_path in self.unexplained_images: + LOG.warning(_('Instance %(instance)s is using a ' + 'backing file %(backing)s which ' + 'does not appear in the image ' + 'service'), + {'instance': ent, + 'backing': backing_file}) + self.unexplained_images.remove(backing_path) return inuse_images |