summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Prince <dprince@redhat.com>2012-06-06 17:35:18 -0400
committerDan Prince <dprince@redhat.com>2012-06-06 17:35:50 -0400
commitf617896efe466a4080a0061fb1c939b76641043b (patch)
tree43dda9e70d933c5287f64254e6799f553647ab82
parent534e6cf87338d7d47349d6186e622ba73ecb9e40 (diff)
downloadnova-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.py42
-rw-r--r--nova/virt/libvirt/imagecache.py43
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