'Create snapshot from a running VM instance.
:param context: request context
:param instance: instance to be snapshotted
:param image_id: id of image to upload to
Steps involved in a XenServer snapshot:
1. XAPI-Snapshot: Snapshotting the instance using XenAPI. This
creates: Snapshot (Template) VM, Snapshot VBD, Snapshot VDI,
Snapshot VHD
2. Wait-for-coalesce: The Snapshot VDI and Instance VDI both point to
a \'base-copy\' VDI.  The base_copy is immutable and may be chained
with other base_copies.  If chained, the base_copies
coalesce together, so, we must wait for this coalescing to occur to
get a stable representation of the data on disk.
3. Push-to-data-store: Once coalesced, we call
\'image_upload_handler\' to upload the images.'

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

    vm_ref = self._get_vm_opaque_ref(instance)
    label = ('%s-snapshot' % instance['name'])
    start_time = timeutils.utcnow()
    with vm_utils.snapshot_attached_here(self._session, instance, vm_ref, label, post_snapshot_callback=update_task_state) as vdi_uuids:
        update_task_state(task_state=task_states.IMAGE_UPLOADING, expected_state=task_states.IMAGE_PENDING_UPLOAD)
        self.image_upload_handler.upload_image(context, self._session, instance, image_id, vdi_uuids)
    duration = timeutils.delta_seconds(start_time, timeutils.utcnow())
    LOG.debug('Finished    snapshot    and    upload    for    VM,    duration:    %(duration).2f    secs    for    image    %(image_id)s', {'image_id': image_id, 'duration': duration}, instance=instance)
