From: Eric Blake <eblake@xxxxxxxxxx> Introduce virsh commands for performing backup jobs. Signed-off-by: Eric Blake <eblake@xxxxxxxxxx> --- tools/Makefile.am | 1 + tools/virsh-backup.c | 209 +++++++++++++++++++++++++++++++++++++++++++ tools/virsh-backup.h | 21 +++++ tools/virsh.c | 2 + tools/virsh.h | 1 + tools/virsh.pod | 37 ++++++++ 6 files changed, 271 insertions(+) create mode 100644 tools/virsh-backup.c create mode 100644 tools/virsh-backup.h diff --git a/tools/Makefile.am b/tools/Makefile.am index 68320c7246..813cfaeb53 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -233,6 +233,7 @@ virt_login_shell_helper_CFLAGS = \ virsh_SOURCES = \ virsh.c virsh.h \ + virsh-backup.c virsh-backup.h\ virsh-checkpoint.c virsh-checkpoint.h \ virsh-completer.c virsh-completer.h \ virsh-completer-domain.c virsh-completer-domain.h \ diff --git a/tools/virsh-backup.c b/tools/virsh-backup.c new file mode 100644 index 0000000000..7719b4f3cc --- /dev/null +++ b/tools/virsh-backup.c @@ -0,0 +1,209 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include "virsh-backup.h" +#include "virsh-util.h" + +#include "internal.h" +#include "virfile.h" + +/* + * "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 = "backupxml", + .type = VSH_OT_STRING, + .help = N_("domain backup XML"), + }, + {.name = "checkpointxml", + .type = VSH_OT_STRING, + .help = N_("domain checkpoint XML"), + }, + {.name = NULL} +}; + +static bool +cmdBackupBegin(vshControl *ctl, + const vshCmd *cmd) +{ + g_autoptr(virshDomain) dom = NULL; + const char *backup_from = NULL; + g_autofree char *backup_buffer = NULL; + const char *check_from = NULL; + g_autofree char *check_buffer = NULL; + unsigned int flags = 0; + int id; + + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) + return false; + + if (vshCommandOptStringReq(ctl, cmd, "backupxml", &backup_from) < 0) + return false; + + if (!backup_from) { + backup_buffer = vshStrdup(ctl, "<domainbackup/>"); + } else { + if (virFileReadAll(backup_from, VSH_MAX_XML_FILE, &backup_buffer) < 0) { + vshSaveLibvirtError(); + return false; + } + } + + if (vshCommandOptStringReq(ctl, cmd, "checkpointxml", &check_from) < 0) + return false; + if (check_from) { + if (virFileReadAll(check_from, VSH_MAX_XML_FILE, &check_buffer) < 0) { + vshSaveLibvirtError(); + return false; + } + } + + if ((id = virDomainBackupBegin(dom, backup_buffer, check_buffer, flags)) < 0) + return false; + + vshPrint(ctl, _("Backup id %d started\n"), id); + + return true; +} + + +/* + * "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, + .help = N_("backup job id"), + }, + {.name = NULL} +}; + +static bool +cmdBackupDumpXML(vshControl *ctl, + const vshCmd *cmd) +{ + g_autoptr(virshDomain) dom = NULL; + g_autofree char *xml = NULL; + unsigned int flags = 0; + int id = 0; + + 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))) + return false; + + vshPrint(ctl, "%s", xml); + return true; +} + + +/* + * "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, + .help = N_("backup job id"), + }, + {.name = NULL} +}; + +static bool +cmdBackupEnd(vshControl *ctl, const vshCmd *cmd) +{ + g_autoptr(virshDomain) dom = NULL; + unsigned int flags = 0; + int id = 0; + int rc; + + if (vshCommandOptInt(ctl, cmd, "id", &id) < 0) + return false; + + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) + return false; + + if ((rc = virDomainBackupEnd(dom, id, flags)) < 0) + return false; + + vshPrint(ctl, _("Backup id %d terminated"), id); + + return true; +} + + +const vshCmdDef backupCmds[] = { + {.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 = NULL} +}; diff --git a/tools/virsh-backup.h b/tools/virsh-backup.h new file mode 100644 index 0000000000..95c2f5a424 --- /dev/null +++ b/tools/virsh-backup.h @@ -0,0 +1,21 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "virsh.h" + +extern const vshCmdDef backupCmds[]; diff --git a/tools/virsh.c b/tools/virsh.c index a3553ddd36..59c3ddb4b7 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -47,6 +47,7 @@ #include "virstring.h" #include "virgettext.h" +#include "virsh-backup.h" #include "virsh-checkpoint.h" #include "virsh-console.h" #include "virsh-domain.h" @@ -831,6 +832,7 @@ static const vshCmdGrp cmdGroups[] = { {VIRSH_CMD_GRP_NODEDEV, "nodedev", nodedevCmds}, {VIRSH_CMD_GRP_SECRET, "secret", secretCmds}, {VIRSH_CMD_GRP_SNAPSHOT, "snapshot", snapshotCmds}, + {VIRSH_CMD_GRP_BACKUP, "backup", backupCmds}, {VIRSH_CMD_GRP_STORAGE_POOL, "pool", storagePoolCmds}, {VIRSH_CMD_GRP_STORAGE_VOL, "volume", storageVolCmds}, {VIRSH_CMD_GRP_VIRSH, "virsh", virshCmds}, diff --git a/tools/virsh.h b/tools/virsh.h index b4e610b2a4..d84659124a 100644 --- a/tools/virsh.h +++ b/tools/virsh.h @@ -51,6 +51,7 @@ #define VIRSH_CMD_GRP_NWFILTER "Network Filter" #define VIRSH_CMD_GRP_SECRET "Secret" #define VIRSH_CMD_GRP_SNAPSHOT "Snapshot" +#define VIRSH_CMD_GRP_BACKUP "Backup" #define VIRSH_CMD_GRP_HOST_AND_HV "Host and Hypervisor" #define VIRSH_CMD_GRP_VIRSH "Virsh itself" diff --git a/tools/virsh.pod b/tools/virsh.pod index cf2798e71a..83cb315506 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1327,6 +1327,43 @@ addresses, currently 'lease' to read DHCP leases, 'agent' to query the guest OS via an agent, or 'arp' to get IP from host's arp tables. If unspecified, 'lease' is the default. +=item B<backup-begin> I<domain> [I<backupxml>] +[I<checkpointxml> + +Begin a new backup job, and output the resulting job id on success. If +I<backupxml> 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>. + +If I<checkpointxml> is specified, a second file with a top-level +element of <domaincheckpoint> is used to create a simultaneous +checkpoint, for doing a later incremental backup relative to the time +the backup was created. See B<checkpoint-create> for more details on +checkpoints. + +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<backup-end>. + +=item B<backup-dumpxml> I<domain> [I<id>] + +Output XML describing the backup job I<id>. The default for I<id> is +0, which works as long as there are no parallel jobs; it is also +possible to use the positive id printed by B<backup-begin> on success. + +=item B<backup-end> I<domain> [I<id>] + +End the current backup job I<id>. The default for I<id> is 0, which +works as long as there are no parallel jobs; it is also possible to +use the positive id printed by B<backup-begin> on success. + =item B<domiflist> I<domain> [I<--inactive>] Print a table showing the brief information of all virtual interfaces -- 2.21.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list