New virsh commands:
. save-image-list
. save-image-remove <file>
. save-image-download <file> <local-file>
. dump-list
. dump-remove <file>
. dump-download <file> <local-file>
* tools/virsh.c: new commands implementations
Signed-off-by: Hong Xiang <hxiang(a)linux.vnet.ibm.com>
---
tools/virsh.c | 309 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 309 insertions(+), 0 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 72344f0..a1cafbe 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -300,6 +300,8 @@ static int vshCommandOptULongLong(const vshCmd *cmd, const char
*name,
static bool vshCommandOptBool(const vshCmd *cmd, const char *name);
static const vshCmdOpt *vshCommandOptArgv(const vshCmd *cmd,
const vshCmdOpt *opt);
+static int vshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED,
+ const char *bytes, size_t nbytes, void *opaque);
#define VSH_BYID (1 << 1)
#define VSH_BYUUID (1 << 2)
@@ -2445,6 +2447,155 @@ cleanup:
}
/*
+ * "save-image-list" command
+ */
+static const vshCmdInfo info_save_image_list[] = {
+ {"help", N_("list saved state files")},
+ {"desc", N_("Output the list of saved state files.\n")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_save_image_list[] = {
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdSaveImageList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+ int maxfiles = 0, i;
+ char ** files = NULL;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if(0 > (maxfiles = virConnectNumOfSavedImages(ctl->conn))) {
+ vshError(ctl, "%s", _("Failed to list saved state files"));
+ return false;
+ }
+ if(maxfiles) {
+ files = vshMalloc(ctl, sizeof(char *) * maxfiles);
+ if(0 > (maxfiles = virConnectListSavedImages(ctl->conn, files,
+ maxfiles))) {
+ vshError(ctl, "%s", _("Failed to list saved state
files"));
+ VIR_FREE(files);
+ return false;
+ }
+ qsort(files, maxfiles, sizeof(char *), namesorter);
+ }
+ for(i = 0; i < maxfiles; i ++) {
+ vshPrint(ctl, "%s\n", files[i]);
+ VIR_FREE(files[i]);
+ }
+
+ VIR_FREE(files);
+ return true;
+}
+
+/*
+ * "save-image-remove" command
+ */
+static const vshCmdInfo info_save_image_remove[] = {
+ {"help", N_("remove a saved state file")},
+ {"desc", N_("Remove the specified saved state file")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_save_image_remove[] = {
+ {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("saved state file to
remove")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdSaveImageRemove(vshControl *ctl, const vshCmd *cmd)
+{
+ const char *file = NULL;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (vshCommandOptString(cmd, "file", &file) <= 0)
+ return false;
+
+ if(virSavedImageRemove(ctl->conn, file)) {
+ vshPrint(ctl, _("Failed to remove saved state file '%s'.\n"),
+ file);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * "save-image-download" command
+ */
+static const vshCmdInfo info_save_image_download[] = {
+ {"help", N_("download a saved state file to local")},
+ {"desc", N_("Download the specified saved state file to
local.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_save_image_download[] = {
+ {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("saved state file to
download")},
+ {"local-file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("local file")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdSaveImageDownload(vshControl *ctl, const vshCmd *cmd)
+{
+ const char *file = NULL;
+ const char *local_file = NULL;
+ bool ret = false;
+ int fd = -1;
+ virStreamPtr stream = NULL;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (vshCommandOptString(cmd, "file", &file) <= 0)
+ return false;
+ if (vshCommandOptString(cmd, "local-file", &local_file) <= 0)
+ return false;
+
+ if (0 > (fd = open(local_file, O_WRONLY | O_CREAT | O_TRUNC, 0666))) {
+ vshError(ctl, _("cannot open file %s"), local_file);
+ goto cleanup;
+ }
+ if (NULL == (stream = virStreamNew(ctl->conn, 0))) {
+ vshError(ctl, _("cannot open stream"));
+ goto cleanup;
+ }
+ if (0 > virSavedImageDownload(ctl->conn, stream, file)) {
+ vshError(ctl, _("cannot download saved state file %s"), file);
+ goto cleanup;
+ }
+ if (0 > virStreamRecvAll(stream, vshStreamSink, &fd)) {
+ vshError(ctl, _("cannot receive data from saved state file %s"),
file);
+ goto cleanup;
+ }
+
+ if (0 > VIR_CLOSE(fd)) {
+ vshError(ctl, _("cannot close file %s"), local_file);
+ virStreamAbort(stream);
+ goto cleanup;
+ }
+ if (0 > virStreamFinish(stream)) {
+ vshError(ctl, _("cannot close saved state file %s"), file);
+ goto cleanup;
+ }
+
+ ret = true;
+
+cleanup:
+ VIR_FORCE_CLOSE(fd);
+ if(!ret)
+ ignore_value(unlink(local_file));
+ if(stream)
+ virStreamFree(stream);
+ return ret;
+}
+
+/*
* "managedsave" command
*/
static const vshCmdInfo info_managedsave[] = {
@@ -2935,6 +3086,155 @@ cleanup:
return ret;
}
+/*
+ * "dump-list" command
+ */
+static const vshCmdInfo info_dump_list[] = {
+ {"help", N_("list core dump files")},
+ {"desc", N_("Output the list of core dump files.\n")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_dump_list[] = {
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDumpList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+ int maxfiles = 0, i;
+ char ** files = NULL;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if(0 > (maxfiles = virConnectNumOfCoreDumps(ctl->conn))) {
+ vshError(ctl, "%s", _("Failed to list core dump files"));
+ return false;
+ }
+ if(maxfiles) {
+ files = vshMalloc(ctl, sizeof(char *) * maxfiles);
+ if(0 > (maxfiles = virConnectListCoreDumps(ctl->conn, files,
+ maxfiles))) {
+ vshError(ctl, "%s", _("Failed to list core dump
files"));
+ VIR_FREE(files);
+ return false;
+ }
+ qsort(files, maxfiles, sizeof(char *), namesorter);
+ }
+ for(i = 0; i < maxfiles; i ++) {
+ vshPrint(ctl, "%s\n", files[i]);
+ VIR_FREE(files[i]);
+ }
+
+ VIR_FREE(files);
+ return true;
+}
+
+/*
+ * "dump-remove" command
+ */
+static const vshCmdInfo info_dump_remove[] = {
+ {"help", N_("remove a core dump file")},
+ {"desc", N_("Remove the specified core dump file")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_dump_remove[] = {
+ {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("core dump file to
remove")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDumpRemove(vshControl *ctl, const vshCmd *cmd)
+{
+ const char *file = NULL;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (vshCommandOptString(cmd, "file", &file) <= 0)
+ return false;
+
+ if(virCoreDumpRemove(ctl->conn, file)) {
+ vshPrint(ctl, _("Failed to remove core dump file %s.\n"),
+ file);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * "dump-download" command
+ */
+static const vshCmdInfo info_dump_download[] = {
+ {"help", N_("download a core dump file to local")},
+ {"desc", N_("Download the specified core dump file to local.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_dump_download[] = {
+ {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("core dump file to
download")},
+ {"local-file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("local file")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdDumpDownload(vshControl *ctl, const vshCmd *cmd)
+{
+ const char *file = NULL;
+ const char *local_file = NULL;
+ bool ret = false;
+ int fd = -1;
+ virStreamPtr stream = NULL;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (vshCommandOptString(cmd, "file", &file) <= 0)
+ return false;
+ if (vshCommandOptString(cmd, "local-file", &local_file) <= 0)
+ return false;
+
+ if (0 > (fd = open(local_file, O_WRONLY | O_CREAT | O_TRUNC, 0666))) {
+ vshError(ctl, _("cannot open file %s"), local_file);
+ goto cleanup;
+ }
+ if(NULL == (stream = virStreamNew(ctl->conn, 0))) {
+ vshError(ctl, _("cannot open stream"));
+ goto cleanup;
+ }
+ if (0 > virCoreDumpDownload(ctl->conn, stream, file)) {
+ vshError(ctl, _("cannot download core dump file %s"), file);
+ goto cleanup;
+ }
+ if (0 > virStreamRecvAll(stream, vshStreamSink, &fd)) {
+ vshError(ctl, _("cannot receive data from core dump file %s"), file);
+ goto cleanup;
+ }
+
+ if (0 > VIR_CLOSE(fd)) {
+ vshError(ctl, _("cannot close file %s"), local_file);
+ virStreamAbort(stream);
+ goto cleanup;
+ }
+ if (0 > virStreamFinish(stream)) {
+ vshError(ctl, _("cannot close core dump file %s"), file);
+ goto cleanup;
+ }
+
+ ret = true;
+
+cleanup:
+ VIR_FORCE_CLOSE(fd);
+ if(!ret)
+ ignore_value(unlink(local_file));
+ if(stream)
+ virStreamFree(stream);
+ return ret;
+}
+
static const vshCmdInfo info_screenshot[] = {
{"help", N_("take a screenshot of a current domain console and store
it "
"into a file")},
@@ -14041,6 +14341,9 @@ static const vshCmdDef domManagementCmds[] = {
{"domxml-to-native", cmdDomXMLToNative, opts_domxmltonative,
info_domxmltonative, 0},
{"dump", cmdDump, opts_dump, info_dump, 0},
+ {"dump-list", cmdDumpList, opts_dump_list, info_dump_list, 0},
+ {"dump-remove", cmdDumpRemove, opts_dump_remove, info_dump_remove, 0},
+ {"dump-download", cmdDumpDownload, opts_dump_download, info_dump_download,
0},
{"dumpxml", cmdDumpXML, opts_dumpxml, info_dumpxml, 0},
{"edit", cmdEdit, opts_edit, info_edit, 0},
{"inject-nmi", cmdInjectNMI, opts_inject_nmi, info_inject_nmi, 0},
@@ -14068,6 +14371,12 @@ static const vshCmdDef domManagementCmds[] = {
info_save_image_dumpxml, 0},
{"save-image-edit", cmdSaveImageEdit, opts_save_image_edit,
info_save_image_edit, 0},
+ {"save-image-list", cmdSaveImageList, opts_save_image_list,
+ info_save_image_list, 0},
+ {"save-image-remove", cmdSaveImageRemove, opts_save_image_remove,
+ info_save_image_remove, 0},
+ {"save-image-download", cmdSaveImageDownload, opts_save_image_download,
+ info_save_image_download, 0},
{"schedinfo", cmdSchedinfo, opts_schedinfo, info_schedinfo, 0},
{"screenshot", cmdScreenshot, opts_screenshot, info_screenshot, 0},
{"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem, 0},
--
1.7.1