提交 ed2a10a1 编写于 作者: D Daniel P. Berrange

Add API for issuing 'migrate' command with exec protocol

* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new
  qemuMonitorMigrateToCommand() API
* src/qemu/qemu_driver.c: Switch over to using the
  qemuMonitorMigrateToCommand() API for core dumps and save
  to file APIs
上级 81f3edea
...@@ -453,6 +453,7 @@ virGetGroupID; ...@@ -453,6 +453,7 @@ virGetGroupID;
virFileFindMountPoint; virFileFindMountPoint;
virFileWaitForDevices; virFileWaitForDevices;
virFileMatchesNameSuffix; virFileMatchesNameSuffix;
virArgvToString;
# usb.h # usb.h
......
...@@ -3170,11 +3170,6 @@ static char *qemudEscapeMonitorArg(const char *in) ...@@ -3170,11 +3170,6 @@ static char *qemudEscapeMonitorArg(const char *in)
return qemudEscape(in, 0); return qemudEscape(in, 0);
} }
static char *qemudEscapeShellArg(const char *in)
{
return qemudEscape(in, 1);
}
#define QEMUD_SAVE_MAGIC "LibvirtQemudSave" #define QEMUD_SAVE_MAGIC "LibvirtQemudSave"
#define QEMUD_SAVE_VERSION 2 #define QEMUD_SAVE_VERSION 2
...@@ -3217,15 +3212,11 @@ static int qemudDomainSave(virDomainPtr dom, ...@@ -3217,15 +3212,11 @@ static int qemudDomainSave(virDomainPtr dom,
{ {
struct qemud_driver *driver = dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = NULL; virDomainObjPtr vm = NULL;
char *command = NULL;
char *info = NULL;
int fd = -1; int fd = -1;
char *safe_path = NULL;
char *xml = NULL; char *xml = NULL;
struct qemud_save_header header; struct qemud_save_header header;
int ret = -1; int ret = -1;
virDomainEventPtr event = NULL; virDomainEventPtr event = NULL;
int internalret;
memset(&header, 0, sizeof(header)); memset(&header, 0, sizeof(header));
memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)); memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
...@@ -3305,55 +3296,21 @@ static int qemudDomainSave(virDomainPtr dom, ...@@ -3305,55 +3296,21 @@ static int qemudDomainSave(virDomainPtr dom,
} }
fd = -1; fd = -1;
/* Migrate to file */ if (header.compressed == QEMUD_SAVE_FORMAT_RAW) {
safe_path = qemudEscapeShellArg(path); const char *args[] = { "cat", NULL };
if (!safe_path) { ret = qemuMonitorMigrateToCommand(vm, args, path);
virReportOOMError(dom->conn); } else {
goto cleanup;
}
{
const char *prog = qemudSaveCompressionTypeToString(header.compressed); const char *prog = qemudSaveCompressionTypeToString(header.compressed);
const char *args; const char *args[] = {
prog,
if (prog == NULL) { "-c",
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, NULL
_("Invalid compress format %d"), header.compressed); };
goto cleanup; ret = qemuMonitorMigrateToCommand(vm, args, path);
}
if (STREQ (prog, "raw")) {
prog = "cat";
args = "";
} else {
args = "-c";
}
internalret = virAsprintf(&command, "migrate \"exec:"
"%s %s >> '%s' 2>/dev/null\"", prog, args,
safe_path);
}
if (internalret < 0) {
virReportOOMError(dom->conn);
goto cleanup;
}
if (qemudMonitorCommand(vm, command, &info) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("migrate operation failed"));
goto cleanup;
} }
DEBUG ("%s: migrate reply: %s", vm->def->name, info); if (ret < 0)
/* If the command isn't supported then qemu prints:
* unknown command: migrate" */
if (strstr(info, "unknown command:")) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s",
_("'migrate' not supported by this qemu"));
goto cleanup; goto cleanup;
}
/* Shut it down */ /* Shut it down */
qemudShutdownVMDaemon(dom->conn, driver, vm); qemudShutdownVMDaemon(dom->conn, driver, vm);
...@@ -3365,15 +3322,11 @@ static int qemudDomainSave(virDomainPtr dom, ...@@ -3365,15 +3322,11 @@ static int qemudDomainSave(virDomainPtr dom,
vm); vm);
vm = NULL; vm = NULL;
} }
ret = 0;
cleanup: cleanup:
if (fd != -1) if (fd != -1)
close(fd); close(fd);
VIR_FREE(xml); VIR_FREE(xml);
VIR_FREE(safe_path);
VIR_FREE(command);
VIR_FREE(info);
if (ret != 0) if (ret != 0)
unlink(path); unlink(path);
if (vm) if (vm)
...@@ -3390,11 +3343,12 @@ static int qemudDomainCoreDump(virDomainPtr dom, ...@@ -3390,11 +3343,12 @@ static int qemudDomainCoreDump(virDomainPtr dom,
int flags ATTRIBUTE_UNUSED) { int flags ATTRIBUTE_UNUSED) {
struct qemud_driver *driver = dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm; virDomainObjPtr vm;
char *command = NULL;
char *info = NULL;
char *safe_path = NULL;
int resume = 0, paused = 0; int resume = 0, paused = 0;
int ret = -1; int ret = -1;
const char *args[] = {
"cat",
NULL,
};
qemuDriverLock(driver); qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid); vm = virDomainFindByUUID(&driver->domains, dom->uuid);
...@@ -3426,43 +3380,9 @@ static int qemudDomainCoreDump(virDomainPtr dom, ...@@ -3426,43 +3380,9 @@ static int qemudDomainCoreDump(virDomainPtr dom,
paused = 1; paused = 1;
} }
/* Migrate to file */ ret = qemuMonitorMigrateToCommand(vm, args, path);
safe_path = qemudEscapeShellArg(path);
if (!safe_path) {
virReportOOMError(dom->conn);
goto cleanup;
}
if (virAsprintf(&command, "migrate \"exec:"
"dd of='%s' 2>/dev/null"
"\"", safe_path) == -1) {
virReportOOMError(dom->conn);
command = NULL;
goto cleanup;
}
if (qemudMonitorCommand(vm, command, &info) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("migrate operation failed"));
goto cleanup;
}
DEBUG ("%s: migrate reply: %s", vm->def->name, info);
/* If the command isn't supported then qemu prints:
* unknown command: migrate" */
if (strstr(info, "unknown command:")) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s",
_("'migrate' not supported by this qemu"));
goto cleanup;
}
paused = 1; paused = 1;
ret = 0;
cleanup: cleanup:
VIR_FREE(safe_path);
VIR_FREE(command);
VIR_FREE(info);
/* Since the monitor is always attached to a pty for libvirt, it /* Since the monitor is always attached to a pty for libvirt, it
will support synchronous operations so we always get here after will support synchronous operations so we always get here after
...@@ -6369,6 +6289,11 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, ...@@ -6369,6 +6289,11 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
goto cleanup; goto cleanup;
} }
/* XXX this really should have been a properly well-formed
* URI, but we can't add in tcp:// now without breaking
* compatability with old targets. We at least make the
* new targets accept both syntaxes though.
*/
/* Caller frees */ /* Caller frees */
internalret = virAsprintf(uri_out, "tcp:%s:%d", hostname, this_port); internalret = virAsprintf(uri_out, "tcp:%s:%d", hostname, this_port);
VIR_FREE(hostname); VIR_FREE(hostname);
...@@ -6535,6 +6460,7 @@ qemudDomainMigratePerform (virDomainPtr dom, ...@@ -6535,6 +6460,7 @@ qemudDomainMigratePerform (virDomainPtr dom,
/* Issue the migrate command. */ /* Issue the migrate command. */
if (STRPREFIX(uri, "tcp:") && !STRPREFIX(uri, "tcp://")) { if (STRPREFIX(uri, "tcp:") && !STRPREFIX(uri, "tcp://")) {
/* HACK: source host generates bogus URIs, so fix them up */
char *tmpuri; char *tmpuri;
if (virAsprintf(&tmpuri, "tcp://%s", uri + strlen("tcp:")) < 0) { if (virAsprintf(&tmpuri, "tcp://%s", uri + strlen("tcp:")) < 0) {
virReportOOMError(dom->conn); virReportOOMError(dom->conn);
......
...@@ -118,6 +118,10 @@ static char *qemudEscapeMonitorArg(const char *in) ...@@ -118,6 +118,10 @@ static char *qemudEscapeMonitorArg(const char *in)
return qemudEscape(in, 0); return qemudEscape(in, 0);
} }
static char *qemudEscapeShellArg(const char *in)
{
return qemudEscape(in, 1);
}
/* Throw away any data available on the monitor /* Throw away any data available on the monitor
* This is done before executing a command, in order * This is done before executing a command, in order
...@@ -1096,12 +1100,18 @@ static int qemuMonitorMigrate(const virDomainObjPtr vm, ...@@ -1096,12 +1100,18 @@ static int qemuMonitorMigrate(const virDomainObjPtr vm,
char *cmd = NULL; char *cmd = NULL;
char *info = NULL; char *info = NULL;
int ret = -1; int ret = -1;
char *safedest = qemudEscapeMonitorArg(dest);
if (virAsprintf(&cmd, "migrate %s", dest) < 0) { if (!safedest) {
virReportOOMError(NULL); virReportOOMError(NULL);
return -1; return -1;
} }
if (virAsprintf(&cmd, "migrate \"%s\"", safedest) < 0) {
virReportOOMError(NULL);
goto cleanup;
}
if (qemudMonitorCommand(vm, cmd, &info) < 0) { if (qemudMonitorCommand(vm, cmd, &info) < 0) {
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("unable to start migration to %s"), dest); _("unable to start migration to %s"), dest);
...@@ -1112,8 +1122,15 @@ static int qemuMonitorMigrate(const virDomainObjPtr vm, ...@@ -1112,8 +1122,15 @@ static int qemuMonitorMigrate(const virDomainObjPtr vm,
/* Now check for "fail" in the output string */ /* Now check for "fail" in the output string */
if (strstr(info, "fail") != NULL) { if (strstr(info, "fail") != NULL) {
qemudReportError (NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("migration to '%s' failed: %s"), dest, info); _("migration to '%s' failed: %s"), dest, info);
goto cleanup;
}
/* If the command isn't supported then qemu prints:
* unknown command: migrate" */
if (strstr(info, "unknown command:")) {
qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_SUPPORT,
_("migration to '%s' not supported by this qemu: %s"), dest, info);
goto cleanup; goto cleanup;
} }
...@@ -1121,6 +1138,7 @@ static int qemuMonitorMigrate(const virDomainObjPtr vm, ...@@ -1121,6 +1138,7 @@ static int qemuMonitorMigrate(const virDomainObjPtr vm,
ret = 0; ret = 0;
cleanup: cleanup:
VIR_FREE(safedest);
VIR_FREE(info); VIR_FREE(info);
VIR_FREE(cmd); VIR_FREE(cmd);
return ret; return ret;
...@@ -1130,7 +1148,7 @@ int qemuMonitorMigrateToHost(const virDomainObjPtr vm, ...@@ -1130,7 +1148,7 @@ int qemuMonitorMigrateToHost(const virDomainObjPtr vm,
const char *hostname, const char *hostname,
int port) int port)
{ {
char *uri; char *uri = NULL;
int ret; int ret;
if (virAsprintf(&uri, "tcp:%s:%d", hostname, port) < 0) { if (virAsprintf(&uri, "tcp:%s:%d", hostname, port) < 0) {
...@@ -1144,3 +1162,40 @@ int qemuMonitorMigrateToHost(const virDomainObjPtr vm, ...@@ -1144,3 +1162,40 @@ int qemuMonitorMigrateToHost(const virDomainObjPtr vm,
return ret; return ret;
} }
int qemuMonitorMigrateToCommand(const virDomainObjPtr vm,
const char * const *argv,
const char *target)
{
char *argstr;
char *dest = NULL;
int ret = -1;
char *safe_target = NULL;
argstr = virArgvToString(argv);
if (!argstr) {
virReportOOMError(NULL);
goto cleanup;
}
/* Migrate to file */
safe_target = qemudEscapeShellArg(target);
if (!safe_target) {
virReportOOMError(NULL);
goto cleanup;
}
if (virAsprintf(&dest, "exec:%s >>%s 2>/dev/null", argstr, safe_target) < 0) {
virReportOOMError(NULL);
goto cleanup;
}
ret = qemuMonitorMigrate(vm, dest);
cleanup:
VIR_FREE(safe_target);
VIR_FREE(argstr);
VIR_FREE(dest);
return ret;
}
...@@ -132,4 +132,8 @@ int qemuMonitorMigrateToHost(const virDomainObjPtr vm, ...@@ -132,4 +132,8 @@ int qemuMonitorMigrateToHost(const virDomainObjPtr vm,
const char *hostname, const char *hostname,
int port); int port);
int qemuMonitorMigrateToCommand(const virDomainObjPtr vm,
const char * const *argv,
const char *target);
#endif /* QEMU_MONITOR_TEXT_H */ #endif /* QEMU_MONITOR_TEXT_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册