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@xxxxxxxxxxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list