diff options
-rw-r--r-- | nova/tests/virt/libvirt/test_imagebackend.py | 31 | ||||
-rwxr-xr-x | nova/virt/libvirt/imagebackend.py | 25 |
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. |