mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 04:25:18 +00:00
* 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 Daniel
This commit is contained in:
parent
6e9443aeb1
commit
474e4b8425
@ -1,3 +1,11 @@
|
||||
Fri Jan 20 10:57:44 CET 2006 Daniel Veillard <veillard@redhat.com>
|
||||
|
||||
* 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 <veillard@redhat.com>
|
||||
|
||||
* src/libvir.c src/xend_internal.c src/xend_internal.h: continue
|
||||
|
@ -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);
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
||||
/*
|
||||
|
59
src/libvir.c
59
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);
|
||||
}
|
||||
|
||||
|
86
src/virsh.c
86
src/virsh.c
@ -386,6 +386,88 @@ cmdSuspend(vshControl *ctl, vshCmd *cmd) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* "save" command
|
||||
*/
|
||||
static vshCmdInfo info_save[] = {
|
||||
{ "syntax", "save <domain> to <file>" },
|
||||
{ "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 <file>" },
|
||||
{ "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 },
|
||||
|
Loading…
x
Reference in New Issue
Block a user