From 45f8aefcd33b7848d33ae2e8d9801925cf8365e7 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Sat, 7 Jul 2012 02:21:52 +0000 Subject: Remove VDI chain limit for snapshots. Snapshots and migrations were coded with a simplifying assumption that the maximum length of a VDI chain would be 3. Now that fast-cloning has been added, this assumption no longer holds. The goal of this patch is to remove the restriction for snapshots. A follow-on patch will remove the restriction for migrations. This patch changes the image-format for XenAPI images. Instead of naming the VHDs, 'base', 'image', and 'snap', they are now numbered staring with 0 as the leaf and going to N as the base-copy (root). Old-style images are still supported. Change-Id: Ieb073b42dc25db7cee4dfca7ff6525f7e7f46e8e --- nova/tests/xenapi/stubs.py | 2 +- nova/virt/xenapi/vm_utils.py | 16 +++++++++------- nova/virt/xenapi/vmops.py | 13 +++++++------ 3 files changed, 17 insertions(+), 14 deletions(-) (limited to 'nova') diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 83a17af84..ec944d84d 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -320,7 +320,7 @@ class FakeSessionForVolumeFailedTests(FakeSessionForVolumeTests): def stub_out_migration_methods(stubs): @contextlib.contextmanager def fake_snapshot_attached_here(session, instance, vm_ref, label): - yield dict(image='foo', snap='bar') + yield ['bar', 'foo'] def fake_move_disks(self, instance, disk_info): vdi_ref = fake.create_vdi(instance['name'], 'fake') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index bf343f977..4ff1a305d 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -98,6 +98,7 @@ SECTOR_SIZE = 512 MBR_SIZE_SECTORS = 63 MBR_SIZE_BYTES = MBR_SIZE_SECTORS * SECTOR_SIZE KERNEL_DIR = '/boot/guest' +MAX_VDI_CHAIN_SIZE = 16 class ImageType(object): @@ -471,7 +472,7 @@ def snapshot_attached_here(session, instance, vm_ref, label): LOG.debug(_("Starting snapshot for VM"), instance=instance) try: - template_vm_ref, template_vdi_uuids = _create_snapshot( + template_vm_ref, vdi_uuids = _create_snapshot( session, instance, vm_ref, label) except session.XenAPI.Failure, exc: LOG.error(_("Unable to Snapshot instance: %(exc)s"), locals(), @@ -479,7 +480,7 @@ def snapshot_attached_here(session, instance, vm_ref, label): raise try: - yield template_vdi_uuids + yield vdi_uuids finally: _destroy_snapshot(session, instance, template_vm_ref) @@ -505,10 +506,10 @@ def _create_snapshot(session, instance, vm_ref, label): parent_uuid, base_uuid = _wait_for_vhd_coalesce( session, instance, sr_ref, vm_vdi_ref, original_parent_uuid) - template_vdi_uuids = {'base': base_uuid, - 'image': parent_uuid, - 'snap': template_vdi_uuid} - return template_vm_ref, template_vdi_uuids + vdi_uuids = [vdi_rec['uuid'] for vdi_rec in + _walk_vdi_chain(session, template_vdi_uuid)] + + return template_vm_ref, vdi_uuids def _destroy_snapshot(session, instance, vm_ref): @@ -908,8 +909,9 @@ def _fetch_vhd_image(context, session, instance, image_id): # which does not have the `uuid` module. To work around this, # we generate the uuids here (under Python 2.6+) and # pass them as arguments + uuid_stack = [str(uuid.uuid4()) for i in xrange(MAX_VDI_CHAIN_SIZE)] params = {'image_id': image_id, - 'uuid_stack': [str(uuid.uuid4()) for i in xrange(3)], + 'uuid_stack': uuid_stack, 'sr_path': get_sr_path(session), 'auth_token': getattr(context, 'auth_token', None)} diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 23504bffe..f9958ff4c 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -606,9 +606,9 @@ class VMOps(object): label = "%s-snapshot" % instance.name with vm_utils.snapshot_attached_here( - self._session, instance, vm_ref, label) as template_vdi_uuids: - vm_utils.upload_image(context, self._session, instance, - template_vdi_uuids, image_id) + self._session, instance, vm_ref, label) as vdi_uuids: + vm_utils.upload_image( + context, self._session, instance, vdi_uuids, image_id) LOG.debug(_("Finished snapshot and upload for VM"), instance=instance) @@ -674,13 +674,14 @@ class VMOps(object): # 1. Create Snapshot label = "%s-snapshot" % instance.name with vm_utils.snapshot_attached_here( - self._session, instance, vm_ref, label) as template_vdi_uuids: - + self._session, instance, vm_ref, label) as vdi_uuids: self._update_instance_progress(context, instance, step=1, total_steps=RESIZE_TOTAL_STEPS) - base_copy_uuid = template_vdi_uuids['image'] + # FIXME(sirp): this needs to work with VDI chain of arbitrary + # length + base_copy_uuid = vdi_uuids[1] _vdi_info = vm_utils.get_vdi_for_vm_safely(self._session, vm_ref) vdi_ref, vm_vdi_rec = _vdi_info cow_uuid = vm_vdi_rec['uuid'] -- cgit