[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [RFC Doc V11 4/5] domain snapshot libxl design



libxl Design

1. New Structures

libxl_disk_snapshot_type = Enumeration("disk_snapshot_type", [
    (0, "invalid"),
    (1, "internal"),
    (2, "external"),
    ])

libxl_disk_snapshot = Struct("disk_snapshot",[
    # target disk
    ("disk", libxl_device_disk),

    # disk snapshot name
    ("name", string),

    ("u", KeyedUnion(None, libxl_disk_snapshot_type, "type",
         [("external", Struct(None, [

            # disk format for external files. Since external disk snapshot is
            # implemented with backing file mechanism, the external file disk
            # format must support backing file. This field can be NULL, then
            # a proper disk format will be used by default according to the
            # orignal disk format.
            ("external_format", libxl_disk_format),

            # external file path. This field should be non-NULL and a new path.
            ("external_path",   string),
            ])),
          ("internal", None),
          ("invalid", None),
         ])),
    ])


2. New Functions

Since there're already APIs for saving memory (libxl_domain_suspend)
and restoring domain from saved memory (libxl_domain_create_restore), to
xl domain snapshot tasks, the missing part is disk snapshot functionality.
And the disk snapshot functionality would be used by libvirt too.

## disk snapshot create

/**
 * libxl_disk_snaphost_create:
 * @ctx: libxl context
 * @domid: domain id
 * @snapshot: array of disk snapshot configuration. Has "nb" members.
 *     - libxl_device_disk:
 *         structure to represent which disk.
 *     - name:
 *         snapshot name.
 *     - type:
 *        disk snapshot type: internal or external.
 *     - u.external.external_format:
 *         Format of external file.
 *         After disk snapshot, original file will become a backing
 *         file, while external file will keep the delta, so
 *         external_format should support backing file, like: cow,
 *         qcow, qcow2, etc.
 *         If it is NULL, then it will use proper format by default
 *         according to original disk format.
 *     - u.external.external_path:
 *         path to external file. non-NULL.
 * @nb: number of disks that need to take disk snapshot.
 *
 * createing internal/external disk snapshot
 *
 * Taking disk snapshots to a group of domain disks according to
 * configuration. Support both internal disk snapshot and external
 * disk snapshot. For qdisk backend type, it will call qmp
 * "transaction" command to do the work. For other disk backend types,
 * might call other external commands.
 *
 * Returns 0 on success, <0 on failure.
 */
int libxl_disk_snapshot_create(libxl_ctx *ctx, uint32_t domid,
                               libxl_disk_snapshot *snapshot, int nb);


## disk snapshot revert

/**
 * libxl_disk_snapshot_revert:
 * @snapshot: array of disk snapshot configuration. Has "nb" members.
 * @nb: number of disks.
 *
 * Revert disks to specified snapshot according to configuration. To
 * different disk backend types, call different external commands to do
 * the work.
 *
 * Returns 0 on success, <0 on failure.
 */
int libxl_disk_snapshot_revert(libxl_disk_snapshot *snapshot, int nb);

For disk snapshot revert, since domain snapshot revert is essentially
destroy, revert disks and restore from RAM. There is no qemu process
to speak to during reverting disks. So, it always calls external
commands to finish the work:


## disk snapshot delete

Since xl won't supply domain snapshot delete functionality, this group
of functions won't be used by xl, but will be used by libvirt.

/**
 * libxl_disk_snaphost_delete:
 * @ctx: libxl context
 * @domid: domain id
 * @snapshot: array of disk snapshot configuration. Has "nb" members.
 * @nb: number of disks.
 *
 * Delete disk snapshot of a group of domain disks according to
 * configuration. Can only handle internal disk snapshot. Currently
 * only valid for 'qcow2' disk, by calling qmp command if it is qdisk
 * backend or by calling qemu-img if it is other backend type.
 * 
 * To delete external disk snapshots, means shorten backing file chain
 * and merge snapshot data, must know snapshot chain info. Functions
 * libxl_domain_block_rebase and libxl_domain_block_commit would help.
 *
 * Returns 0 on success, <0 on failure.
 */
int libxl_disk_snapshot_delete(libxl_ctx *ctx, uint32_t domid,
                               libxl_disk_snapshot *snapshot, int nb);


Following functions would help to delete external disk snapshots.
They are actually two directions to shorten backing file chain. One is
from "base" to "top" merge, the other is from "top" to "base" merge.
Both need caller to know the backing file chain information.

/**
 * libxl_domain_block_rebase:
 * @ctx: libxl context
 * @domid: domain id
 * @disk: path to the block device
 * @base: path to backing file to keep, or NULL for no backing file
 * @bandwidth: (optional) bandwidth limit in B/s, 0 for no limit.
 *
 * Merge data from base to top
 *
 * Populate a disk image with data from its backing image chain, and
 * setting the backing image to @base, or alternatively copy an entire
 * backing chain to a new file @base.
 *
 * @base must be the absolute path of one of the backing images further
 * up the chain, or NULL to convert the disk image so that it has no
 * backing image.  Once all data from its backing image chain has been
 * pulled, the disk no longer depends on those intermediate backing
 * images.
 *
 * The maximum bandwidth that will be used to do the copy can be
 * specified with the @bandwidth parameter, unit is B/s.  If set to 0,
 * there is no limit.
 *
 * e.g.:
 * backing file chain:
 *     RootBase <- A <- B <- disk
 * after libxl_domain_block_rebase(ctx, domid, disk, A, 0):
 *     RootBase <- A <- disk
 * delta in B is merged into disk.
 *
 * Returns 0 on success, <0 on failure.
 */
int libxl_domain_block_rebase(libxl_ctx *ctx, uint32_t domid,
                              const char *disk,
                              const char *base,
                              unsigned long long bandwidth);


/**
 * libxl_domain_block_commit:
 * @ctx: libxl context
 * @domid: domain id
 * @disk: path to the block device
 * @base: path to backing file to merge into, or NULL for default
 * @top: path to file within backing chain that contains data to be merged,
 *       or NULL to merge all possible data
 * @bandwidth: (optional) bandwidth limit in B/s; 0 for no limit
 *
 * Merge data from top to base
 *
 * Commit changes that were made to temporary top-level files within a disk
 * image backing file chain into a lower-level base file.  In other words,
 * take all the difference between @base and @top, and update @base to contain
 * that difference; after the commit, any portion of the chain that previously
 * depended on @top will now depend on @base, and all files after @base up
 * to and including @top will now be invalidated.  A typical use of this
 * command is to reduce the length of a backing file chain after taking an
 * external disk snapshot. To move data in the opposite direction, see
 * libxl_domain_block_commit().
 *
 * e.g.:
 * backing file chain:
 *     RootBase <- A <- B <- disk
 * after libxl_domain_block_commit(ctx, domid, disk, RootBase, B, 0):
 *     RootBase <- B <- disk
 * delta in A is merged to RootBase.
 *
 * Returns 0 on success, <0 on failure.
 */
int libxl_domain_block_commit(libxl_ctx *ctx, uint32_t domid,
                              const char *disk,
                              const char *base,
                              const char *top,
                              unsigned long bandwidth);


In libxl_domain_block_commit, if top == active, qemu job will not be completed
by itself, user needs to complete the job by calling block-job-complete.
(Since qemu 2.0). For this reason, add API libxl_domain_block_abort and
libxl_domain_block_job_query.

/* libxl_domain_block_job_query
 * @ctx: libxl context
 * @domid: domain id
 * @disk: path to the block device
 * @info: block job information
 * 
 * Query a block job status, can get job type, speed, progress status.
 */
int libxl_domain_block_job_query(libxl_ctx *ctx, uint32_t domid,
                                 libxl_device_disk *disk,
                                 libxl_block_job_info *info);

Related libxl_block_job_info structure:

typedef struct libxl_block_job_info
{    
     char *disk_vdev;
     const char *type;
     unsigned long speed;
     /* The following fields provide an indication of block job progress.
      * @current indicates the current position and will be between 0 and @end.
      * @end is the final cursor position for this operation and represents
      * completion.
      * To approximate progress, divide @cur by @end.
      */
      unsigned long long current;
      unsigned long long end;
} libxl_block_job_info;


/* libxl_domain_block_job_abort
 * @ctx: libxl context
 * @domid: domain id
 * @disk: path to the block device
 * @info: block job information
 *
 * Abort a block job. If the job is finished, complete it.
 * otherwise, cancel it.
 */
int libxl_domain_block_job_abort(libxl_ctx *ctx, uint32_t domid,
                                 libxl_device_disk *disk,
                                 bool force);


3. General framework

## Creating domain snapshot:

(* means new functions we will need in libxl)

  "xl snapshot-create"
         |
  parse configuration
         |
  saving memory ----> libxl_domain_suspend
         |
 taking disk snapshot ----> libxl_disk_snapshot_create (*)
         |                     |
         |                     --> libxl_qmp_disk_snapshot_transaction (*)
         |
    unpause domain ---->libxl_domain_unpause
         |
        End


## Reverting to a snapshot:
(* means new functions we will need in libxl)

  "xl snapshot-revert"
         |
   parse configuration
         |
   destroy domain ---->libxl_domain_destroy
         |
 reverting disk snapshot ----> libxl_disk_snapshot_revert (*)
         |                       |
         |                       --> call 'qemu-img' to apply disk snapshot
         |
 restore domain from saved memory ----> libxl_domain_create_restore
         |
        End

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.