Define two new virsh commands: one to control disk streaming and one to print
the status of active disk streams.
* tools/virsh.c: implement the new commands
Signed-off-by: Adam Litke <agl(a)us.ibm.com>
---
tools/virsh.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 133 insertions(+), 1 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index f2d2c9d..edffc61 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -3999,6 +3999,137 @@ done:
}
/*
+ * "domstreamdisk" command
+ */
+static const vshCmdInfo info_domstreamdisk[] = {
+ {"help", gettext_noop("Stream data to a disk")},
+ {"desc", gettext_noop("Stream data to a disk connected to a running
domain")},
+ { NULL, NULL },
+};
+
+static const vshCmdOptDef opts_domstreamdisk[] = {
+ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id
or uuid")},
+ {"start", VSH_OT_BOOL, VSH_OFLAG_NONE, N_("Start streaming a
disk") },
+ {"stop", VSH_OT_BOOL, VSH_OFLAG_NONE, N_("Stop streaming a disk")
},
+ {"incremental", VSH_OT_BOOL, VSH_OFLAG_NONE, N_("Perform an
incremental stream") },
+ {"path", VSH_OT_DATA, VSH_OFLAG_REQ, N_("block device")},
+ {"offset", VSH_OT_DATA, VSH_OFLAG_NONE, N_("Device offset for
incremental stream")},
+ { NULL, 0, 0, NULL },
+};
+
+static int
+cmdDomStreamDisk(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom;
+ const char *name, *path;
+ unsigned long long offset, next;
+ unsigned int flags, start, stop, incr;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return FALSE;
+
+ flags = start = stop = incr = 0;
+ if (vshCommandOptBool(cmd, "start")) {
+ start = 1;
+ flags = VIR_STREAM_DISK_START;
+ }
+ if (vshCommandOptBool(cmd, "stop")) {
+ stop = 1;
+ flags = VIR_STREAM_DISK_STOP;
+ }
+ if (vshCommandOptBool(cmd, "incremental")) {
+ incr = 1;
+ flags = VIR_STREAM_DISK_ONE;
+ }
+ if (start + stop + incr != 1) {
+ vshError(ctl, _("Exactly one mode: --start, --stop, --incremental, "
+ "is required"));
+ return FALSE;
+ }
+
+ if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ return FALSE;
+
+ if (vshCommandOptString(cmd, "path", &path) < 0)
+ return FALSE;
+
+ if (flags == VIR_STREAM_DISK_ONE) {
+ if (vshCommandOptULongLong(cmd, "offset", &offset) < 0) {
+ vshError(ctl, _("An offset is required for incremental
streaming"));
+ virDomainFree(dom);
+ return FALSE;
+ }
+ } else {
+ offset = 0;
+ }
+
+ next = virDomainStreamDisk(dom, path, offset, flags);
+ if (next == (unsigned long long) -1) {
+ virDomainFree(dom);
+ return FALSE;
+ }
+
+ if (flags == VIR_STREAM_DISK_START)
+ vshPrint (ctl, "Stream successfully started\n");
+ else if (flags == VIR_STREAM_DISK_STOP)
+ vshPrint (ctl, "Stream successfully stopped\n");
+ else
+ vshPrint (ctl, "Strem successful. Continue at offset %llu\n", next);
+
+ virDomainFree(dom);
+ return TRUE;
+}
+
+/*
+ * "domstreamdiskinfo" command
+ */
+static const vshCmdInfo info_domstreamdiskinfo[] = {
+ {"help", gettext_noop("Get disk streaming status for a
domain")},
+ {"desc", gettext_noop("Get disk streaming status for a running
domain")},
+ { NULL, NULL },
+};
+
+static const vshCmdOptDef opts_domstreamdiskinfo[] = {
+ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id
or uuid")},
+ { NULL, 0, 0, NULL },
+};
+
+static int
+cmdDomStreamDiskInfo(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom;
+ const char *name;
+ struct _virStreamDiskState streams[VIR_STREAM_DISK_MAX_STREAMS];
+ int nr_streams, i;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return FALSE;
+
+ if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
+ return FALSE;
+
+ nr_streams = virDomainStreamDiskInfo(dom, streams,
+ VIR_STREAM_DISK_MAX_STREAMS, 0);
+ if (nr_streams < 0) {
+ vshError(ctl, _("Failed to get disk stream information for domain
%s"),
+ name);
+ virDomainFree(dom);
+ return FALSE;
+ }
+
+ vshPrint (ctl, "%-30s %-10s %-10s\n", _("Device"),
_("Offset"),
+ _("Size"));
+ vshPrint (ctl, "----------------------------------------------------\n");
+ for (i = 0; i < nr_streams; i++) {
+ vshPrint (ctl, "%-30s %-10llu %-10llu\n", streams[i].path,
+ streams[i].offset, streams[i].size);
+ }
+
+ virDomainFree(dom);
+ return TRUE;
+}
+
+/*
* "net-autostart" command
*/
static const vshCmdInfo info_network_autostart[] = {
@@ -10682,6 +10813,8 @@ static const vshCmdDef domManagementCmds[] = {
{"domjobabort", cmdDomjobabort, opts_domjobabort, info_domjobabort},
{"domjobinfo", cmdDomjobinfo, opts_domjobinfo, info_domjobinfo},
{"domname", cmdDomname, opts_domname, info_domname},
+ {"domstreamdisk", cmdDomStreamDisk, opts_domstreamdisk,
info_domstreamdisk},
+ {"domstreamdiskinfo", cmdDomStreamDiskInfo, opts_domstreamdiskinfo,
info_domstreamdiskinfo},
{"domuuid", cmdDomuuid, opts_domuuid, info_domuuid},
{"domxml-from-native", cmdDomXMLFromNative, opts_domxmlfromnative,
info_domxmlfromnative},
{"domxml-to-native", cmdDomXMLToNative, opts_domxmltonative,
info_domxmltonative},
@@ -11279,7 +11412,6 @@ vshCommandOptULongLong(const vshCmd *cmd, const char *name,
return ret;
}
-
/*
* Returns TRUE/FALSE if the option exists
*/
--
1.7.3