diff --git a/ChangeLog b/ChangeLog index f1fd36d062..0a7a8d81c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Fri Jan 20 10:57:44 CET 2006 Daniel Veillard + + * include/libvir.h include/libvir.h.in src/libvir.c: revamped the + restore API (though it would be better if it was returning + a domain pointer in case of success) + * src/virsh.c: added save and restore to the commands, tested, + the option handling need work though + Thu Jan 19 11:21:57 CET 2006 Daniel Veillard * src/libvir.c src/xend_internal.c src/xend_internal.h: continue diff --git a/include/libvir.h b/include/libvir.h index 07bc91e2b9..ddba307ec6 100644 --- a/include/libvir.h +++ b/include/libvir.h @@ -224,7 +224,7 @@ int virDomainResume (virDomainPtr domain); */ int virDomainSave (virDomainPtr domain, const char *to); -int virDomainRestore (virDomainPtr domain, +int virDomainRestore (virConnectPtr conn, const char *from); /* diff --git a/include/libvir.h.in b/include/libvir.h.in index 92bb6aa8d0..5ad010cb5b 100644 --- a/include/libvir.h.in +++ b/include/libvir.h.in @@ -224,7 +224,7 @@ int virDomainResume (virDomainPtr domain); */ int virDomainSave (virDomainPtr domain, const char *to); -int virDomainRestore (virDomainPtr domain, +int virDomainRestore (virConnectPtr conn, const char *from); /* diff --git a/src/libvir.c b/src/libvir.c index 85fa5b6121..9e5aed6ec2 100644 --- a/src/libvir.c +++ b/src/libvir.c @@ -890,27 +890,47 @@ virDomainResume(virDomainPtr domain) { * @to: path for the output file * * This method will suspend a domain and save its memory contents to - * a file on disk. Use virDomainRestore() to restore a domain after - * saving. + * a file on disk. After the call, if successful, the domain is not + * listed as running anymore (this may be a problem). + * Use virDomainRestore() to restore a domain after saving. * * Returns 0 in case of success and -1 in case of failure. */ int virDomainSave(virDomainPtr domain, const char *to) { int ret; + char filepath[4096]; - if (!VIR_IS_CONNECTED_DOMAIN(domain)) - return(-1); - if ((to == NULL) || (to[0] != '/')) + if ((!VIR_IS_CONNECTED_DOMAIN(domain)) || (to == NULL)) return(-1); + /* + * We must absolutize the file path as the save is done out of process + * TODO: check for URI when libxml2 is linked in. + */ + if (to[0] != '/') { + unsigned int len, t; + + t = strlen(to); + if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) + return(-1); + len = strlen(filepath); + /* that should be covered by getcwd() semantic, but be 100% sure */ + if (len > sizeof(filepath) - (t + 3)) + return(-1); + filepath[len] = '/'; + strcpy(&filepath[len + 1], to); + to = &filepath[0]; + + } + ret = xend_save(domain->conn, domain->name, to); return(ret); } /** * virDomainRestore: - * @domain: a domain object + * @conn: pointer to the hypervisor connection * @from: path to the * * This method will restore a domain saved to disk by virDomainSave(). @@ -918,15 +938,32 @@ virDomainSave(virDomainPtr domain, const char *to) { * Returns 0 in case of success and -1 in case of failure. */ int -virDomainRestore(virDomainPtr domain, const char *from) { +virDomainRestore(virConnectPtr conn, const char *from) { int ret; + char filepath[4096]; - if (!VIR_IS_CONNECTED_DOMAIN(domain)) - return(-1); - if ((from == NULL) || (from[0] != '/')) + if ((!VIR_IS_CONNECT(conn)) || (from == NULL)) return(-1); + /* + * We must absolutize the file path as the restore is done out of process + * TODO: check for URI when libxml2 is linked in. + */ + if (from[0] != '/') { + unsigned int len, t; + + t = strlen(from); + if (getcwd(filepath, sizeof(filepath) - (t + 3)) == NULL) + return(-1); + len = strlen(filepath); + /* that should be covered by getcwd() semantic, but be 100% sure */ + if (len > sizeof(filepath) - (t + 3)) + return(-1); + filepath[len] = '/'; + strcpy(&filepath[len + 1], from); + from = &filepath[0]; + } - ret = xend_restore(domain->conn, from); + ret = xend_restore(conn, from); return(ret); } diff --git a/src/virsh.c b/src/virsh.c index 9bbf0d773f..08ab7226bc 100644 --- a/src/virsh.c +++ b/src/virsh.c @@ -386,6 +386,88 @@ cmdSuspend(vshControl *ctl, vshCmd *cmd) { return ret; } +/* + * "save" command + */ +static vshCmdInfo info_save[] = { + { "syntax", "save to " }, + { "help", "save a domain state to a file" }, + { "desc", "Save a running domain." }, + { NULL, NULL } +}; + +static vshCmdOptDef opts_save[] = { + { "file", VSH_OT_STRING, VSH_OFLAG_REQ, "where to save the data" }, + { "domain", VSH_OT_DATA, 0, "domain name or id" }, + { NULL, 0, 0, NULL } +}; + +static int +cmdSave(vshControl *ctl, vshCmd *cmd) { + virDomainPtr dom; + char *name; + char *to; + int found; + int ret = TRUE; + + if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) + return FALSE; + + to = vshCommandOptString(cmd, "file", &found); + if (!found) + return FALSE; + + if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name))) + return FALSE; + + if (virDomainSave(dom, to)==0) { + vshPrint(ctl, VSH_MESG, "Domain %s saved\n", name); + } else { + vshError(ctl, FALSE, "Failed to save domain\n"); + ret = FALSE; + } + + virDomainFree(dom); + return ret; +} + +/* + * "restore" command + */ +static vshCmdInfo info_restore[] = { + { "syntax", "restore a domain from " }, + { "help", "restore a domain from a saved state in a file" }, + { "desc", "Restore a domain." }, + { NULL, NULL } +}; + +static vshCmdOptDef opts_restore[] = { + { "file", VSH_OT_DATA, 0, "the state to restore" }, + { NULL, 0, 0, NULL } +}; + +static int +cmdRestore(vshControl *ctl, vshCmd *cmd) { + char *from; + int found; + int ret = TRUE; + + if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) + return FALSE; + + from = vshCommandOptString(cmd, "file", &found); + if (!found) + return FALSE; + + if (virDomainRestore(ctl->conn, from)==0) { + vshPrint(ctl, VSH_MESG, "Domain restored from %s\n", from); + } else { + vshError(ctl, FALSE, "Failed to restore domain\n"); + ret = FALSE; + } + return ret; +} + /* * "resume" command */ @@ -616,7 +698,7 @@ static vshCmdInfo info_nameof[] = { static vshCmdOptDef opts_nameof[] = { { "id", VSH_OT_DATA, 0, "domain Id" }, - { NULL, 0, 0, NULL } + { NULL, 0, 0, NULL } }; static int @@ -781,6 +863,8 @@ static vshCmdDef commands[] = { { "dstate", cmdDstate, opts_dstate, info_dstate }, { "suspend", cmdSuspend, opts_suspend, info_suspend }, { "resume", cmdResume, opts_resume, info_resume }, + { "save", cmdSave, opts_save, info_save }, + { "restore", cmdRestore, opts_restore, info_restore }, { "shutdown", cmdShutdown, opts_shutdown, info_shutdown }, { "destroy", cmdDestroy, opts_destroy, info_destroy }, { "help", cmdHelp, opts_help, info_help },