--- tools/virsh-domain.c | 247 +++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 32 ++++++ 2 files changed, 279 insertions(+) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 23169f0569..8a06168f6f 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -14034,6 +14034,235 @@ cmdDomFSInfo(vshControl *ctl, const vshCmd *cmd) return ret; } + +/* + * "backup-begin" command + */ +static const vshCmdInfo info_backup_begin[] = { + {.name = "help", + .data = N_("Start a disk backup of a live domain") + }, + {.name = "desc", + .data = N_("Use XML to start a full or incremental disk backup of a live " + "domain, optionally creating a checkpoint") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_backup_begin[] = { + VIRSH_COMMON_OPT_DOMAIN_FULL(0), + {.name = "xmlfile", + .type = VSH_OT_STRING, + .help = N_("domain backup XML"), + }, + {.name = "checkpointxml", + .type = VSH_OT_STRING, + .help = N_("domain checkpoint XML"), + }, + {.name = "no-metadata", + .type = VSH_OT_BOOL, + .help = N_("create checkpoint but don't track metadata"), + }, + {.name = "quiesce", + .type = VSH_OT_BOOL, + .help = N_("quiesce guest's file systems"), + }, + /* TODO: --wait/--verbose/--timeout flags for push model backups? */ + {.name = NULL} +}; + +static bool +cmdBackupBegin(vshControl *ctl, + const vshCmd *cmd) +{ + virDomainPtr dom = NULL; + bool ret = false; + const char *backup_from = NULL; + char *backup_buffer = NULL; + const char *check_from = NULL; + char *check_buffer = NULL; + unsigned int flags = 0; + int id; + + if (vshCommandOptBool(cmd, "no-metadata")) + flags |= VIR_DOMAIN_BACKUP_BEGIN_NO_METADATA; + if (vshCommandOptBool(cmd, "quiesce")) + flags |= VIR_DOMAIN_BACKUP_BEGIN_QUIESCE; + + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) + goto cleanup; + + if (vshCommandOptStringReq(ctl, cmd, "xmlfile", &backup_from) < 0) + goto cleanup; + if (!backup_from) { + backup_buffer = vshStrdup(ctl, "<domainbackup/>"); + } else { + if (virFileReadAll(backup_from, VSH_MAX_XML_FILE, &backup_buffer) < 0) { + vshSaveLibvirtError(); + goto cleanup; + } + } + + if (vshCommandOptStringReq(ctl, cmd, "checkpointxml", &check_from) < 0) + goto cleanup; + if (check_from) { + if (virFileReadAll(check_from, VSH_MAX_XML_FILE, &check_buffer) < 0) { + vshSaveLibvirtError(); + goto cleanup; + } + } + + id = virDomainBackupBegin(dom, backup_buffer, check_buffer, flags); + + if (id < 0) + goto cleanup; + + vshPrint(ctl, _("Backup id %d started\n"), id); + if (backup_from) + vshPrintExtra(ctl, _("backup used description from '%s'\n"), + backup_from); + if (check_buffer) + vshPrintExtra(ctl, _("checkpoint created from '%s'\n"), check_from); + + ret = true; + + cleanup: + VIR_FREE(backup_buffer); + VIR_FREE(check_buffer); + virshDomainFree(dom); + + return ret; +} + +/* TODO: backup-begin-as? */ + +/* + * "backup-dumpxml" command + */ +static const vshCmdInfo info_backup_dumpxml[] = { + {.name = "help", + .data = N_("Dump XML for an ongoing domain block backup job") + }, + {.name = "desc", + .data = N_("Backup Dump XML") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_backup_dumpxml[] = { + VIRSH_COMMON_OPT_DOMAIN_FULL(0), + {.name = "id", + .type = VSH_OT_INT, + .flags = VSH_OFLAG_REQ, + .help = N_("backup job id"), + /* TODO: Add API for listing active jobs, then adding a completer? */ + }, + /* TODO - worth adding this flag? + {.name = "checkpoint", + .type = VSH_OT_BOOL, + .help = N_("if the backup created a checkpoint, also dump that XML") + }, + */ + {.name = NULL} +}; + +static bool +cmdBackupDumpXML(vshControl *ctl, + const vshCmd *cmd) +{ + virDomainPtr dom = NULL; + bool ret = false; + char *xml = NULL; + unsigned int flags = 0; + int id; + + if (vshCommandOptBool(cmd, "security-info")) + flags |= VIR_DOMAIN_XML_SECURE; + + if (vshCommandOptInt(ctl, cmd, "id", &id) < 0) + return false; + + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) + return false; + + if (!(xml = virDomainBackupGetXMLDesc(dom, id, flags))) + goto cleanup; + + vshPrint(ctl, "%s", xml); + ret = true; + + cleanup: + VIR_FREE(xml); + virshDomainFree(dom); + + return ret; +} + + +/* + * "backup-end" command + */ +static const vshCmdInfo info_backup_end[] = { + {.name = "help", + .data = N_("Conclude a disk backup of a live domain") + }, + {.name = "desc", + .data = N_("End a domain block backup job") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_backup_end[] = { + VIRSH_COMMON_OPT_DOMAIN_FULL(0), + {.name = "id", + .type = VSH_OT_INT, + .flags = VSH_OFLAG_REQ, + .help = N_("backup job id"), + /* TODO: Add API for listing active jobs, then adding a completer? */ + }, + {.name = "abort", + .type = VSH_OT_BOOL, + .help = N_("abandon a push model backup that has not yet completed") + }, + {.name = NULL} +}; + +static bool +cmdBackupEnd(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom = NULL; + bool ret = false; + unsigned int flags = 0; + int id; + int rc; + + if (vshCommandOptBool(cmd, "abort")) + flags |= VIR_DOMAIN_BACKUP_END_ABORT; + + if (vshCommandOptInt(ctl, cmd, "id", &id) < 0) + return false; + + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) + goto cleanup; + + rc = virDomainBackupEnd(dom, id, flags); + + if (rc < 0) + goto cleanup; + if (rc == 0) + vshPrint(ctl, _("Backup id %d aborted"), id); + else + vshPrint(ctl, _("Backup id %d completed"), id); + + ret = true; + + cleanup: + virshDomainFree(dom); + + return ret; +} + + const vshCmdDef domManagementCmds[] = { {.name = "attach-device", .handler = cmdAttachDevice, @@ -14059,6 +14288,24 @@ const vshCmdDef domManagementCmds[] = { .info = info_autostart, .flags = 0 }, + {.name = "backup-begin", + .handler = cmdBackupBegin, + .opts = opts_backup_begin, + .info = info_backup_begin, + .flags = 0 + }, + {.name = "backup-dumpxml", + .handler = cmdBackupDumpXML, + .opts = opts_backup_dumpxml, + .info = info_backup_dumpxml, + .flags = 0 + }, + {.name = "backup-end", + .handler = cmdBackupEnd, + .opts = opts_backup_end, + .info = info_backup_end, + .flags = 0 + }, {.name = "blkdeviotune", .handler = cmdBlkdeviotune, .opts = opts_blkdeviotune, diff --git a/tools/virsh.pod b/tools/virsh.pod index d70f2ecd0c..2edcecec4e 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1344,6 +1344,38 @@ I<bandwidth> specifies copying bandwidth limit in MiB/s. For further information on the I<bandwidth> argument see the corresponding section for the B<blockjob> command. +=item B<backup-begin> I<domain> [I<xmlfile>] +[I<checkpointxml> [I<--no-metadata>]] [I<--quiesce>] + +Begin a new backup job, and output the resulting job id on success. If +I<xmlfile> is omitted, this defaults to a full backup using a push +model to filenames generated by libvirt; supplying XML allows +fine-tuning such as requesting an incremental backup relative to an +earlier checkpoint, controlling which disks participate or which +filenames are involved, or requesting the use of a pull model backup. +The B<backup-dumpxml> command shows any resulting values assigned by +libvirt. For more information on backup XML, see: +L<https://libvirt.org/formatbackup.html>. + +This command returns as soon as possible, and the backup job runs in +the background; the progress of a push model backup can be checked +with B<domjobinfo> or by waiting for an event with B<event> (the +progress of a pull model backup is under the control of whatever third +party connects to the NBD export). The job is ended with B<block-end>. + +FIXME +I<--checkpointxml> +I<--no-metadata> +I<--quiesce> + +=item B<backup-dumpxml> I<domain> I<id> + +FIXME + +=item B<backup-end> I<domain> I<id> [I<--abort>] + +FIXME + =item B<blkdeviotune> I<domain> I<device> [[I<--config>] [I<--live>] | [I<--current>]] [[I<total-bytes-sec>] | [I<read-bytes-sec>] [I<write-bytes-sec>]] -- 2.20.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list