Jump to: navigation, search



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
    elif volume['status'] == 'in-use':
        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
    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
    # 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.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.