summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nova/tests/virt/libvirt/test_imagebackend.py31
-rwxr-xr-xnova/virt/libvirt/imagebackend.py25
2 files changed, 56 insertions, 0 deletions
diff --git a/nova/tests/virt/libvirt/test_imagebackend.py b/nova/tests/virt/libvirt/test_imagebackend.py
index 50aacba2f..fa708f4f4 100644
--- a/nova/tests/virt/libvirt/test_imagebackend.py
+++ b/nova/tests/virt/libvirt/test_imagebackend.py
@@ -258,6 +258,7 @@ class Qcow2TestCase(_ImageTestCase, test.TestCase):
if self.OLD_STYLE_INSTANCE_PATH:
os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False)
os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
+ os.path.exists(self.PATH).AndReturn(False)
imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
).AndReturn(self.SIZE)
os.path.exists(self.PATH).AndReturn(False)
@@ -279,6 +280,7 @@ class Qcow2TestCase(_ImageTestCase, test.TestCase):
if self.OLD_STYLE_INSTANCE_PATH:
os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False)
os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
+ os.path.exists(self.PATH).AndReturn(False)
imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
).AndReturn(self.SIZE)
self.mox.ReplayAll()
@@ -288,6 +290,35 @@ class Qcow2TestCase(_ImageTestCase, test.TestCase):
image.create_image, fn, self.TEMPLATE_PATH, 1)
self.mox.VerifyAll()
+ def test_generate_resized_backing_files(self):
+ fn = self.prepare_mocks()
+ fn(target=self.TEMPLATE_PATH)
+ self.mox.StubOutWithMock(os.path, 'exists')
+ self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
+ self.mox.StubOutWithMock(imagebackend.libvirt_utils,
+ 'get_disk_backing_file')
+ if self.OLD_STYLE_INSTANCE_PATH:
+ os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False)
+ os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
+ os.path.exists(self.PATH).AndReturn(True)
+
+ imagebackend.libvirt_utils.get_disk_backing_file(self.PATH)\
+ .AndReturn(self.QCOW2_BASE)
+ os.path.exists(self.QCOW2_BASE).AndReturn(False)
+ imagebackend.libvirt_utils.copy_image(self.TEMPLATE_PATH,
+ self.QCOW2_BASE)
+ imagebackend.disk.extend(self.QCOW2_BASE, self.SIZE)
+
+ imagebackend.disk.get_disk_size(self.TEMPLATE_PATH
+ ).AndReturn(self.SIZE)
+ os.path.exists(self.PATH).AndReturn(True)
+ self.mox.ReplayAll()
+
+ image = self.image_class(self.INSTANCE, self.NAME)
+ image.create_image(fn, self.TEMPLATE_PATH, self.SIZE)
+
+ self.mox.VerifyAll()
+
class LvmTestCase(_ImageTestCase, test.TestCase):
VG = 'FakeVG'
diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py
index 3d394fb79..844d9dfde 100755
--- a/nova/virt/libvirt/imagebackend.py
+++ b/nova/virt/libvirt/imagebackend.py
@@ -250,8 +250,33 @@ class Qcow2(Image):
if size:
disk.extend(target, size)
+ # Download the unmodified base image unless we already have a copy.
if not os.path.exists(base):
prepare_template(target=base, *args, **kwargs)
+
+ legacy_backing_size = None
+ legacy_base = base
+
+ # Determine whether an existing qcow2 disk uses a legacy backing by
+ # actually looking at the image itself and parsing the output of the
+ # backing file it expects to be using.
+ if os.path.exists(self.path):
+ backing_path = libvirt_utils.get_disk_backing_file(self.path)
+ backing_file = os.path.basename(backing_path)
+ backing_parts = backing_file.rpartition('_')
+ if backing_file != backing_parts[-1] and \
+ backing_parts[-1].isdigit():
+ legacy_backing_size = int(backing_parts[-1])
+ legacy_base += '_%d' % legacy_backing_size
+ legacy_backing_size *= 1024 * 1024 * 1024
+
+ # Create the legacy backing file if necessary.
+ if legacy_backing_size:
+ if not os.path.exists(legacy_base):
+ with utils.remove_path_on_error(legacy_base):
+ libvirt_utils.copy_image(base, legacy_base)
+ disk.extend(legacy_base, legacy_backing_size)
+
# NOTE(cfb): Having a flavor that sets the root size to 0 and having
# nova effectively ignore that size and use the size of the
# image is considered a feature at this time, not a bug.