'Create snapshot from a running VM instance.
Steps followed are:
1. Get the name of the vmdk file which the VM points to right now.
Can be a chain of snapshots, so we need to know the last in the
chain.
2. Create the snapshot. A new vmdk is created which the VM points to
now. The earlier vmdk becomes read-only.
3. Creates a linked clone VM from the snapshot
4. Exports the disk in the link clone VM as a streamOptimized disk.
5. Delete the linked clone VM
6. Deletes the snapshot in original instance.'

def snapshot(self, context, instance, image_id, update_task_state):

    vm_ref = vm_util.get_vm_ref(self._session, instance)
    def _get_vm_and_vmdk_attribs():
        vmdk = vm_util.get_vmdk_info(self._session, vm_ref, instance.uuid)
        if (not vmdk.path):
            LOG.debug('No    root    disk    defined.    Unable    to    snapshot.', instance=instance)
            raise error_util.NoRootDiskDefined()
        lst_properties = ['datastore', 'summary.config.guestId']
        props = self._session._call_method(vutil, 'get_object_properties_dict', vm_ref, lst_properties)
        os_type = props['summary.config.guestId']
        datastores = props['datastore']
        return (vmdk, datastores, os_type)
    (vmdk, datastores, os_type) = _get_vm_and_vmdk_attribs()
    ds_ref = datastores.ManagedObjectReference[0]
    dc_info = self.get_datacenter_ref_and_name(ds_ref)
    update_task_state(task_state=task_states.IMAGE_PENDING_UPLOAD)
    snapshot_ref = self._create_vm_snapshot(instance, vm_ref)
    update_task_state(task_state=task_states.IMAGE_UPLOADING, expected_state=task_states.IMAGE_PENDING_UPLOAD)
    snapshot_vm_ref = None
    try:
        snapshot_vm_ref = self._create_linked_clone_from_snapshot(instance, vm_ref, snapshot_ref, dc_info)
        images.upload_image_stream_optimized(context, image_id, instance, self._session, vm=snapshot_vm_ref, vmdk_size=vmdk.capacity_in_bytes)
    finally:
        if snapshot_vm_ref:
            vm_util.destroy_vm(self._session, instance, snapshot_vm_ref)
        self._delete_vm_snapshot(instance, vm_ref, snapshot_ref)
