提交 6077ae7b 编写于 作者: M Marc-André Lureau 提交者: Michal Privoznik

qemu: add dbus-vmstate helper migration support

Helper processes may have their state migrated with QEMU data stream
thanks to the QEMU "dbus-vmstate".

libvirt maintains the list of helpers to be migrated. The
"dbus-vmstate" is added when required, and given the list of helper
Ids that must be migrated, on save & load sides.

See also:
https://git.qemu.org/?p=qemu.git;a=blob;f=docs/interop/dbus-vmstate.rstSigned-off-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
Reviewed-by: NMichal Privoznik <mprivozn@redhat.com>
上级 db670b8d
...@@ -829,3 +829,10 @@ qemuDomainGetUnmanagedPRAlias(const char *parentalias) ...@@ -829,3 +829,10 @@ qemuDomainGetUnmanagedPRAlias(const char *parentalias)
return ret; return ret;
} }
const char *
qemuDomainGetDBusVMStateAlias(void)
{
return "dbus-vmstate0";
}
...@@ -95,3 +95,5 @@ char *qemuAliasChardevFromDevAlias(const char *devAlias) ...@@ -95,3 +95,5 @@ char *qemuAliasChardevFromDevAlias(const char *devAlias)
const char *qemuDomainGetManagedPRAlias(void); const char *qemuDomainGetManagedPRAlias(void);
char *qemuDomainGetUnmanagedPRAlias(const char *parentalias); char *qemuDomainGetUnmanagedPRAlias(const char *parentalias);
const char *qemuDomainGetDBusVMStateAlias(void);
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "qemu_command.h" #include "qemu_command.h"
#include "qemu_hostdev.h" #include "qemu_hostdev.h"
#include "qemu_capabilities.h" #include "qemu_capabilities.h"
#include "qemu_dbus.h"
#include "qemu_interface.h" #include "qemu_interface.h"
#include "qemu_alias.h" #include "qemu_alias.h"
#include "qemu_security.h" #include "qemu_security.h"
...@@ -9570,6 +9571,56 @@ qemuBuildPflashBlockdevCommandLine(virCommandPtr cmd, ...@@ -9570,6 +9571,56 @@ qemuBuildPflashBlockdevCommandLine(virCommandPtr cmd,
} }
virJSONValuePtr
qemuBuildDBusVMStateInfoProps(virQEMUDriverPtr driver,
virDomainObjPtr vm)
{
virJSONValuePtr ret = NULL;
const char *alias = qemuDomainGetDBusVMStateAlias();
g_autofree char *addr = qemuDBusGetAddress(driver, vm);
if (!addr)
return NULL;
qemuMonitorCreateObjectProps(&ret,
"dbus-vmstate", alias,
"s:addr", addr, NULL);
return ret;
}
static int
qemuBuildDBusVMStateCommandLine(virCommandPtr cmd,
virQEMUDriverPtr driver,
virDomainObjPtr vm)
{
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
g_autoptr(virJSONValue) props = NULL;
qemuDomainObjPrivatePtr priv = QEMU_DOMAIN_PRIVATE(vm);
if (virStringListLength((const char **)priv->dbusVMStateIds) == 0)
return 0;
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DBUS_VMSTATE)) {
VIR_INFO("dbus-vmstate object is not supported by this QEMU binary");
return 0;
}
if (!(props = qemuBuildDBusVMStateInfoProps(driver, vm)))
return -1;
if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0)
return -1;
virCommandAddArg(cmd, "-object");
virCommandAddArgBuffer(cmd, &buf);
priv->dbusVMState = true;
return 0;
}
/** /**
* qemuBuildCommandLineValidate: * qemuBuildCommandLineValidate:
* *
...@@ -9801,6 +9852,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, ...@@ -9801,6 +9852,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
if (qemuBuildMasterKeyCommandLine(cmd, priv) < 0) if (qemuBuildMasterKeyCommandLine(cmd, priv) < 0)
return NULL; return NULL;
if (qemuBuildDBusVMStateCommandLine(cmd, driver, vm) < 0)
return NULL;
if (qemuBuildManagedPRCommandLine(cmd, def, priv) < 0) if (qemuBuildManagedPRCommandLine(cmd, def, priv) < 0)
return NULL; return NULL;
......
...@@ -59,6 +59,9 @@ virCommandPtr qemuBuildCommandLine(virQEMUDriverPtr driver, ...@@ -59,6 +59,9 @@ virCommandPtr qemuBuildCommandLine(virQEMUDriverPtr driver,
virJSONValuePtr qemuBuildPRManagerInfoProps(virStorageSourcePtr src); virJSONValuePtr qemuBuildPRManagerInfoProps(virStorageSourcePtr src);
virJSONValuePtr qemuBuildPRManagedManagerInfoProps(qemuDomainObjPrivatePtr priv); virJSONValuePtr qemuBuildPRManagedManagerInfoProps(qemuDomainObjPrivatePtr priv);
virJSONValuePtr qemuBuildDBusVMStateInfoProps(virQEMUDriverPtr driver,
virDomainObjPtr vm);
/* Generate the object properties for a secret */ /* Generate the object properties for a secret */
int qemuBuildSecretInfoProps(qemuDomainSecretInfoPtr secinfo, int qemuBuildSecretInfoProps(qemuDomainSecretInfoPtr secinfo,
virJSONValuePtr *propsret); virJSONValuePtr *propsret);
......
...@@ -273,3 +273,17 @@ qemuDBusStart(virQEMUDriverPtr driver, ...@@ -273,3 +273,17 @@ qemuDBusStart(virQEMUDriverPtr driver,
} }
return ret; return ret;
} }
int
qemuDBusVMStateAdd(virDomainObjPtr vm, const char *id)
{
return virStringListAdd(&QEMU_DOMAIN_PRIVATE(vm)->dbusVMStateIds, id);
}
void
qemuDBusVMStateRemove(virDomainObjPtr vm, const char *id)
{
virStringListRemove(&QEMU_DOMAIN_PRIVATE(vm)->dbusVMStateIds, id);
}
...@@ -31,3 +31,7 @@ int qemuDBusStart(virQEMUDriverPtr driver, ...@@ -31,3 +31,7 @@ int qemuDBusStart(virQEMUDriverPtr driver,
void qemuDBusStop(virQEMUDriverPtr driver, void qemuDBusStop(virQEMUDriverPtr driver,
virDomainObjPtr vm); virDomainObjPtr vm);
int qemuDBusVMStateAdd(virDomainObjPtr vm, const char *id);
void qemuDBusVMStateRemove(virDomainObjPtr vm, const char *id);
...@@ -2297,6 +2297,13 @@ qemuDomainObjPrivateDataClear(qemuDomainObjPrivatePtr priv) ...@@ -2297,6 +2297,13 @@ qemuDomainObjPrivateDataClear(qemuDomainObjPrivatePtr priv)
/* reset node name allocator */ /* reset node name allocator */
qemuDomainStorageIdReset(priv); qemuDomainStorageIdReset(priv);
priv->dbusDaemonRunning = false;
virStringListFree(priv->dbusVMStateIds);
priv->dbusVMStateIds = NULL;
priv->dbusVMState = false;
} }
...@@ -2974,6 +2981,9 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf, ...@@ -2974,6 +2981,9 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf,
if (priv->dbusDaemonRunning) if (priv->dbusDaemonRunning)
virBufferAddLit(buf, "<dbusDaemon/>\n"); virBufferAddLit(buf, "<dbusDaemon/>\n");
if (priv->dbusVMState)
virBufferAddLit(buf, "<dbusVMState/>\n");
if (priv->namespaces) { if (priv->namespaces) {
ssize_t ns = -1; ssize_t ns = -1;
...@@ -3761,6 +3771,8 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, ...@@ -3761,6 +3771,8 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt,
priv->dbusDaemonRunning = virXPathBoolean("boolean(./dbusDaemon)", ctxt) > 0; priv->dbusDaemonRunning = virXPathBoolean("boolean(./dbusDaemon)", ctxt) > 0;
priv->dbusVMState = virXPathBoolean("boolean(./dbusVMState)", ctxt) > 0;
if ((node = virXPathNode("./namespaces", ctxt))) { if ((node = virXPathNode("./namespaces", ctxt))) {
xmlNodePtr next; xmlNodePtr next;
......
...@@ -423,6 +423,11 @@ struct _qemuDomainObjPrivate { ...@@ -423,6 +423,11 @@ struct _qemuDomainObjPrivate {
virDomainBackupDefPtr backup; virDomainBackupDefPtr backup;
bool dbusDaemonRunning; bool dbusDaemonRunning;
/* list of Ids to migrate */
char **dbusVMStateIds;
/* true if -object dbus-vmstate was added */
bool dbusVMState;
}; };
#define QEMU_DOMAIN_PRIVATE(vm) \ #define QEMU_DOMAIN_PRIVATE(vm) \
......
...@@ -311,6 +311,88 @@ qemuDomainChangeMediaLegacy(virQEMUDriverPtr driver, ...@@ -311,6 +311,88 @@ qemuDomainChangeMediaLegacy(virQEMUDriverPtr driver,
} }
/**
* qemuHotplugAttachDBusVMState:
* @driver: QEMU driver object
* @vm: domain object
* @asyncJob: asynchronous job identifier
*
* Add -object dbus-vmstate if necessary.
*
* Returns: 0 on success, -1 on error.
*/
int
qemuHotplugAttachDBusVMState(virQEMUDriverPtr driver,
virDomainObjPtr vm,
qemuDomainAsyncJob asyncJob)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
g_autoptr(virJSONValue) props = NULL;
int ret;
if (priv->dbusVMState)
return 0;
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DBUS_VMSTATE)) {
VIR_DEBUG("dbus-vmstate object is not supported by this QEMU binary");
return 0;
}
if (!(props = qemuBuildDBusVMStateInfoProps(driver, vm)))
return -1;
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
return -1;
ret = qemuMonitorAddObject(priv->mon, &props, NULL);
if (ret == 0)
priv->dbusVMState = true;
if (qemuDomainObjExitMonitor(driver, vm) < 0)
return -1;
return ret;
}
/**
* qemuHotplugRemoveDBusVMState:
* @driver: QEMU driver object
* @vm: domain object
* @asyncJob: asynchronous job identifier
*
* Remove -object dbus-vmstate from @vm if the configuration does not require
* it any more.
*
* Returns: 0 on success, -1 on error.
*/
int
qemuHotplugRemoveDBusVMState(virQEMUDriverPtr driver,
virDomainObjPtr vm,
qemuDomainAsyncJob asyncJob)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
int ret;
if (!priv->dbusVMState)
return 0;
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
return -1;
ret = qemuMonitorDelObject(priv->mon, qemuDomainGetDBusVMStateAlias(), true);
if (ret == 0)
priv->dbusVMState = false;
if (qemuDomainObjExitMonitor(driver, vm) < 0)
return -1;
return ret;
}
/** /**
* qemuHotplugAttachManagedPR: * qemuHotplugAttachManagedPR:
* @driver: QEMU driver object * @driver: QEMU driver object
......
...@@ -152,3 +152,11 @@ int qemuDomainSetVcpuInternal(virQEMUDriverPtr driver, ...@@ -152,3 +152,11 @@ int qemuDomainSetVcpuInternal(virQEMUDriverPtr driver,
bool state); bool state);
unsigned long long qemuDomainGetUnplugTimeout(virDomainObjPtr vm); unsigned long long qemuDomainGetUnplugTimeout(virDomainObjPtr vm);
int qemuHotplugAttachDBusVMState(virQEMUDriverPtr driver,
virDomainObjPtr vm,
qemuDomainAsyncJob asyncJob);
int qemuHotplugRemoveDBusVMState(virQEMUDriverPtr driver,
virDomainObjPtr vm,
qemuDomainAsyncJob asyncJob);
...@@ -1169,6 +1169,7 @@ qemuMigrationSrcIsAllowed(virQEMUDriverPtr driver, ...@@ -1169,6 +1169,7 @@ qemuMigrationSrcIsAllowed(virQEMUDriverPtr driver,
bool remote, bool remote,
unsigned int flags) unsigned int flags)
{ {
qemuDomainObjPrivatePtr priv = vm->privateData;
int nsnapshots; int nsnapshots;
int pauseReason; int pauseReason;
size_t i; size_t i;
...@@ -1283,6 +1284,13 @@ qemuMigrationSrcIsAllowed(virQEMUDriverPtr driver, ...@@ -1283,6 +1284,13 @@ qemuMigrationSrcIsAllowed(virQEMUDriverPtr driver,
return false; return false;
} }
} }
if (virStringListLength((const char **)priv->dbusVMStateIds) > 0 &&
!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DBUS_VMSTATE)) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("cannot migrate this domain without dbus-vmstate support"));
return false;
}
} }
return true; return true;
...@@ -1948,8 +1956,14 @@ qemuMigrationDstRun(virQEMUDriverPtr driver, ...@@ -1948,8 +1956,14 @@ qemuMigrationDstRun(virQEMUDriverPtr driver,
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
return -1; return -1;
rv = qemuMonitorSetDBusVMStateIdList(priv->mon,
(const char **)priv->dbusVMStateIds);
if (rv < 0)
goto exit_monitor;
rv = qemuMonitorMigrateIncoming(priv->mon, uri); rv = qemuMonitorMigrateIncoming(priv->mon, uri);
exit_monitor:
if (qemuDomainObjExitMonitor(driver, vm) < 0 || rv < 0) if (qemuDomainObjExitMonitor(driver, vm) < 0 || rv < 0)
return -1; return -1;
...@@ -3420,6 +3434,37 @@ qemuMigrationSrcContinue(virQEMUDriverPtr driver, ...@@ -3420,6 +3434,37 @@ qemuMigrationSrcContinue(virQEMUDriverPtr driver,
} }
static int
qemuMigrationSetDBusVMState(virQEMUDriverPtr driver,
virDomainObjPtr vm)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
if (virStringListLength((const char **)priv->dbusVMStateIds) > 0) {
int rv;
if (qemuHotplugAttachDBusVMState(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
return -1;
if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
return -1;
rv = qemuMonitorSetDBusVMStateIdList(priv->mon,
(const char **)priv->dbusVMStateIds);
if (qemuDomainObjExitMonitor(driver, vm) < 0)
rv = -1;
return rv;
} else {
if (qemuHotplugRemoveDBusVMState(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
return -1;
}
return 0;
}
static int static int
qemuMigrationSrcRun(virQEMUDriverPtr driver, qemuMigrationSrcRun(virQEMUDriverPtr driver,
virDomainObjPtr vm, virDomainObjPtr vm,
...@@ -3572,6 +3617,9 @@ qemuMigrationSrcRun(virQEMUDriverPtr driver, ...@@ -3572,6 +3617,9 @@ qemuMigrationSrcRun(virQEMUDriverPtr driver,
} }
} }
if (qemuMigrationSetDBusVMState(driver, vm) < 0)
goto exit_monitor;
/* Before EnterMonitor, since already qemuProcessStopCPUs does that */ /* Before EnterMonitor, since already qemuProcessStopCPUs does that */
if (!(flags & VIR_MIGRATE_LIVE) && if (!(flags & VIR_MIGRATE_LIVE) &&
virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
...@@ -5257,6 +5305,9 @@ qemuMigrationSrcToFile(virQEMUDriverPtr driver, virDomainObjPtr vm, ...@@ -5257,6 +5305,9 @@ qemuMigrationSrcToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
char *errbuf = NULL; char *errbuf = NULL;
virErrorPtr orig_err = NULL; virErrorPtr orig_err = NULL;
if (qemuMigrationSetDBusVMState(driver, vm) < 0)
return -1;
/* Increase migration bandwidth to unlimited since target is a file. /* Increase migration bandwidth to unlimited since target is a file.
* Failure to change migration speed is not fatal. */ * Failure to change migration speed is not fatal. */
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) { if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <gio/gio.h> #include <gio/gio.h>
#include "qemu_alias.h"
#include "qemu_monitor.h" #include "qemu_monitor.h"
#include "qemu_monitor_text.h" #include "qemu_monitor_text.h"
#include "qemu_monitor_json.h" #include "qemu_monitor_json.h"
...@@ -2361,6 +2362,26 @@ qemuMonitorSavePhysicalMemory(qemuMonitorPtr mon, ...@@ -2361,6 +2362,26 @@ qemuMonitorSavePhysicalMemory(qemuMonitorPtr mon,
} }
int
qemuMonitorSetDBusVMStateIdList(qemuMonitorPtr mon,
const char **list)
{
g_autofree char *path = NULL;
VIR_DEBUG("list=%p", list);
if (virStringListLength(list) == 0)
return 0;
path = g_strdup_printf("/objects/%s",
qemuDomainGetDBusVMStateAlias());
QEMU_CHECK_MONITOR(mon);
return qemuMonitorJSONSetDBusVMStateIdList(mon, path, list);
}
int int
qemuMonitorSetMigrationSpeed(qemuMonitorPtr mon, qemuMonitorSetMigrationSpeed(qemuMonitorPtr mon,
unsigned long bandwidth) unsigned long bandwidth)
......
...@@ -737,6 +737,9 @@ int qemuMonitorSavePhysicalMemory(qemuMonitorPtr mon, ...@@ -737,6 +737,9 @@ int qemuMonitorSavePhysicalMemory(qemuMonitorPtr mon,
unsigned long long length, unsigned long long length,
const char *path); const char *path);
int qemuMonitorSetDBusVMStateIdList(qemuMonitorPtr mon,
const char **list);
int qemuMonitorSetMigrationSpeed(qemuMonitorPtr mon, int qemuMonitorSetMigrationSpeed(qemuMonitorPtr mon,
unsigned long bandwidth); unsigned long bandwidth);
......
...@@ -2361,6 +2361,21 @@ qemuMonitorJSONSetMemoryStatsPeriod(qemuMonitorPtr mon, ...@@ -2361,6 +2361,21 @@ qemuMonitorJSONSetMemoryStatsPeriod(qemuMonitorPtr mon,
} }
int
qemuMonitorJSONSetDBusVMStateIdList(qemuMonitorPtr mon,
const char *vmstatepath,
const char **list)
{
g_autofree char *str = virStringListJoin(list, ",");
qemuMonitorJSONObjectProperty prop = {
.type = QEMU_MONITOR_OBJECT_PROPERTY_STRING,
.val.str = str,
};
return qemuMonitorJSONSetObjectProperty(mon, vmstatepath, "id-list", &prop);
}
/* qemuMonitorJSONQueryBlock: /* qemuMonitorJSONQueryBlock:
* @mon: Monitor pointer * @mon: Monitor pointer
* *
......
...@@ -686,3 +686,8 @@ qemuMonitorJSONTransactionBackup(virJSONValuePtr actions, ...@@ -686,3 +686,8 @@ qemuMonitorJSONTransactionBackup(virJSONValuePtr actions,
const char *target, const char *target,
const char *bitmap, const char *bitmap,
qemuMonitorTransactionBackupSyncMode syncmode); qemuMonitorTransactionBackupSyncMode syncmode);
int qemuMonitorJSONSetDBusVMStateIdList(qemuMonitorPtr mon,
const char *vmstatepath,
const char **list)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册