Support forceful snapshot of an attached volume
The VMDK driver in Havana would simply fail the operation when user tries to snapshot a volume that is attached to an instance with --force=True. This blueprint is to support and allow user to be able to perform snapshot of the volume when it is attached to an instance.
Work Flow 1
The snapshot of volume can be achieved using the following pseudo-code:
def create_snapshot(self, snapshot): volume = snapshot['volume'] if volume['status'] == 'available': # Simply call vsphere API to snapshot self._create_snapshot_of_non_attached_volume(snapshot) elif volume['status'] == 'in-use': self._create_snapshot_of_attached_volume(snapshot) else: raise CinderException("Not supported") def create_snapshot_of_attached_volume(self, snapshot): """Create snapshot of an attached volume. The method works in 5 steps as follows: 1. Consolidate volume chains in-case it has moved. 2. Snapshot the instance VM. 3. Snapshot the volume backing. 4. Delete the VMDK version that is attached to the volume backing and add the VMDK version that is with the instance VM to the volume backing. 5. Delete the instance VM snapshot taken in point 2. retaining the disk chain. """ volume = snapshot['volume'] backing = volumeops.get_backing(volume['name']) instance = volumeops.get_backing(volume['instance_uuid']) # 1. Consolidate self.consolidate_backing(volume, backing, instance) # 2. Snapshot VM instance volumeops.create_snapshot(instance, snapshot['name']) # 3. Snapshot volume backing volumeops.create_snapshot(volume, snapshot['name']) # 4. Replace older version VMDK disk chain with newer version volumeops.delete_vmdk(backing) volume_vmdk = volumeops.get_volume_vmdk(instance, volume) volumeops.add_vmdk(backing, volume_vmdk) # 5. Delete VM instance snapshot retaining the disk chain volumeops.delete_snapshot(instance, consolidate=False)
The following image summarizes the above 5 steps for a simpler workflow of snapshotting an attached volume. We have VM instance and VOL volume that is attached to the VM.
When the volume's VMDK disk chain that is also attached to the VM instance is moved around, then a copy of it is retained with the volume backing. The version that is attached to the volume is older version and the version that is attached to the moved VM instance is the newer version. Consolidate is the operation that tries to attach the newer version of the VMDK disk chain to the volume and deletes the older version that is already attached to the volume retaining the snapshots. After the end of this operation we will have volume and VM instance under a common ESX host and datastore and both sharing a common VMDK disk chain. The following pseudo-code captures the consolidate operation.
def consolidate_backing(volume, backing, instance): """Consolidate the VMDK disk chain duplicates. Checks whether the volume's VMDK disk chain has been duplicated by looking at the datastore paths of the versions attached to volume backing and VM instance. If duplication occurred, then it tries to move the volume backing under the ESX host and datastore where the VM instance is present and replaces older VMDK disk chain version with newer version. """ older_vmdk_path = volumeops.get_vmdk_path(backing) volume_disk = volumeops.get_volume_disk(instance, volume) newer_vmdk_path = volumeops.get_path(volume_disk) if older_vmdk_path == newer_vmdk_path: # Both the versions are same return # The volume disk chain has moved host = volumeops.get_host(instance) datastore = volumeops.get_datastore(volume_disk) rp = volumeops.get_rp(host) # Relocates with moveAllDiskBackingsAndAllowSharing volumeops.relocate_backing(backing, datastore, rp, host) # Delete the existing device and add new device volumeops.delete_vmdk(backing) volumeops.add_vmdk(backing, newer_vmdk_path)
Work Flow 2
The following image summarizes scenario where two volumes are attached to a VM instance and one volume needs to snapshotted and others needs to be detached. Also we have SDRS moving the instance VM onto another datastore.