qemu: Pass correct qemuCaps to virDomainDefCopy

Since qemuDomainDefPostParse callback requires qemuCaps, we need to make
sure it gets the capabilities stored in the domain's private data if the
domain is running. Passing NULL may cause QEMU capabilities probing to
be triggered in case QEMU binary changed in the meantime. When this
happens while a running domain object is locked, QMP event delivered to
the domain before QEMU capabilities probing finishes will deadlock the
event loop.

Several general functions from domain_conf.c were lazily passing NULL as
the parseOpaque pointer instead of letting their callers pass the right
data. This patch fixes all paths leading to virDomainDefCopy to do the
right thing.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Jiri Denemark 2019-08-06 13:41:42 +02:00
parent bf15b145ec
commit bbcfa07bea
12 changed files with 56 additions and 34 deletions

View File

@ -3674,7 +3674,8 @@ virDomainObjWaitUntil(virDomainObjPtr vm,
int int
virDomainObjSetDefTransient(virCapsPtr caps, virDomainObjSetDefTransient(virCapsPtr caps,
virDomainXMLOptionPtr xmlopt, virDomainXMLOptionPtr xmlopt,
virDomainObjPtr domain) virDomainObjPtr domain,
void *parseOpaque)
{ {
int ret = -1; int ret = -1;
@ -3684,7 +3685,8 @@ virDomainObjSetDefTransient(virCapsPtr caps,
if (domain->newDef) if (domain->newDef)
return 0; return 0;
if (!(domain->newDef = virDomainDefCopy(domain->def, caps, xmlopt, NULL, false))) if (!(domain->newDef = virDomainDefCopy(domain->def, caps, xmlopt,
parseOpaque, false)))
goto out; goto out;
ret = 0; ret = 0;
@ -3723,10 +3725,11 @@ virDomainObjRemoveTransientDef(virDomainObjPtr domain)
virDomainDefPtr virDomainDefPtr
virDomainObjGetPersistentDef(virCapsPtr caps, virDomainObjGetPersistentDef(virCapsPtr caps,
virDomainXMLOptionPtr xmlopt, virDomainXMLOptionPtr xmlopt,
virDomainObjPtr domain) virDomainObjPtr domain,
void *parseOpaque)
{ {
if (virDomainObjIsActive(domain) && if (virDomainObjIsActive(domain) &&
virDomainObjSetDefTransient(caps, xmlopt, domain) < 0) virDomainObjSetDefTransient(caps, xmlopt, domain, parseOpaque) < 0)
return NULL; return NULL;
if (domain->newDef) if (domain->newDef)
@ -29341,12 +29344,13 @@ virDomainDefCopy(virDomainDefPtr src,
virDomainDefPtr virDomainDefPtr
virDomainObjCopyPersistentDef(virDomainObjPtr dom, virDomainObjCopyPersistentDef(virDomainObjPtr dom,
virCapsPtr caps, virCapsPtr caps,
virDomainXMLOptionPtr xmlopt) virDomainXMLOptionPtr xmlopt,
void *parseOpaque)
{ {
virDomainDefPtr cur; virDomainDefPtr cur;
cur = virDomainObjGetPersistentDef(caps, xmlopt, dom); cur = virDomainObjGetPersistentDef(caps, xmlopt, dom, parseOpaque);
return virDomainDefCopy(cur, caps, xmlopt, NULL, false); return virDomainDefCopy(cur, caps, xmlopt, parseOpaque, false);
} }

View File

@ -2902,12 +2902,14 @@ void virDomainObjAssignDef(virDomainObjPtr domain,
virDomainDefPtr *oldDef); virDomainDefPtr *oldDef);
int virDomainObjSetDefTransient(virCapsPtr caps, int virDomainObjSetDefTransient(virCapsPtr caps,
virDomainXMLOptionPtr xmlopt, virDomainXMLOptionPtr xmlopt,
virDomainObjPtr domain); virDomainObjPtr domain,
void *parseOpaque);
void virDomainObjRemoveTransientDef(virDomainObjPtr domain); void virDomainObjRemoveTransientDef(virDomainObjPtr domain);
virDomainDefPtr virDomainDefPtr
virDomainObjGetPersistentDef(virCapsPtr caps, virDomainObjGetPersistentDef(virCapsPtr caps,
virDomainXMLOptionPtr xmlopt, virDomainXMLOptionPtr xmlopt,
virDomainObjPtr domain); virDomainObjPtr domain,
void *parseOpaque);
int virDomainObjUpdateModificationImpact(virDomainObjPtr vm, int virDomainObjUpdateModificationImpact(virDomainObjPtr vm,
unsigned int *flags); unsigned int *flags);
@ -2928,7 +2930,8 @@ virDomainDefPtr virDomainDefCopy(virDomainDefPtr src,
bool migratable); bool migratable);
virDomainDefPtr virDomainObjCopyPersistentDef(virDomainObjPtr dom, virDomainDefPtr virDomainObjCopyPersistentDef(virDomainObjPtr dom,
virCapsPtr caps, virCapsPtr caps,
virDomainXMLOptionPtr xmlopt); virDomainXMLOptionPtr xmlopt,
void *parseOpaque);
typedef enum { typedef enum {
/* parse internal domain status information */ /* parse internal domain status information */

View File

@ -1340,7 +1340,7 @@ libxlDomainStart(libxlDriverPrivatePtr driver,
VIR_FREE(managed_save_path); VIR_FREE(managed_save_path);
} }
if (virDomainObjSetDefTransient(cfg->caps, driver->xmlopt, vm) < 0) if (virDomainObjSetDefTransient(cfg->caps, driver->xmlopt, vm, NULL) < 0)
goto cleanup; goto cleanup;
/* Run an early hook to set-up missing devices */ /* Run an early hook to set-up missing devices */

View File

@ -1607,7 +1607,7 @@ virDomainLiveConfigHelperMethod(virCapsPtr caps,
return -1; return -1;
if (*flags & VIR_DOMAIN_AFFECT_CONFIG) { if (*flags & VIR_DOMAIN_AFFECT_CONFIG) {
if (!(*persistentDef = virDomainObjGetPersistentDef(caps, xmlopt, dom))) { if (!(*persistentDef = virDomainObjGetPersistentDef(caps, xmlopt, dom, NULL))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Get persistent config failed")); _("Get persistent config failed"));
return -1; return -1;
@ -2294,7 +2294,7 @@ libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
goto endjob; goto endjob;
} }
if (!(def = virDomainObjGetPersistentDef(cfg->caps, driver->xmlopt, vm))) if (!(def = virDomainObjGetPersistentDef(cfg->caps, driver->xmlopt, vm, NULL)))
goto endjob; goto endjob;
maplen = VIR_CPU_MAPLEN(nvcpus); maplen = VIR_CPU_MAPLEN(nvcpus);
@ -4126,7 +4126,7 @@ libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
/* Make a copy for updated domain. */ /* Make a copy for updated domain. */
if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps, if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
driver->xmlopt))) driver->xmlopt, NULL)))
goto endjob; goto endjob;
if (libxlDomainAttachDeviceConfig(vmdef, dev) < 0) if (libxlDomainAttachDeviceConfig(vmdef, dev) < 0)
@ -4216,7 +4216,7 @@ libxlDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
/* Make a copy for updated domain. */ /* Make a copy for updated domain. */
if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps, if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
driver->xmlopt))) driver->xmlopt, NULL)))
goto endjob; goto endjob;
if (libxlDomainDetachDeviceConfig(vmdef, dev) < 0) if (libxlDomainDetachDeviceConfig(vmdef, dev) < 0)
@ -4303,7 +4303,7 @@ libxlDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
/* Make a copy for updated domain. */ /* Make a copy for updated domain. */
if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps, if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
driver->xmlopt))) driver->xmlopt, NULL)))
goto cleanup; goto cleanup;
if ((ret = libxlDomainUpdateDeviceConfig(vmdef, dev)) < 0) if ((ret = libxlDomainUpdateDeviceConfig(vmdef, dev)) < 0)

View File

@ -1343,7 +1343,7 @@ libxlDomainMigrationDstFinish(virConnectPtr dconn,
vm->persistent = 1; vm->persistent = 1;
if (!(vmdef = virDomainObjGetPersistentDef(cfg->caps, if (!(vmdef = virDomainObjGetPersistentDef(cfg->caps,
driver->xmlopt, vm))) driver->xmlopt, vm, NULL)))
goto cleanup; goto cleanup;
if (virDomainSaveConfig(cfg->configDir, cfg->caps, vmdef) < 0) if (virDomainSaveConfig(cfg->configDir, cfg->caps, vmdef) < 0)

View File

@ -1913,7 +1913,7 @@ lxcDomainSetSchedulerParametersFlags(virDomainPtr dom,
if (persistentDef) { if (persistentDef) {
/* Make a copy for updated domain. */ /* Make a copy for updated domain. */
persistentDefCopy = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt); persistentDefCopy = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt, NULL);
if (!persistentDefCopy) if (!persistentDefCopy)
goto endjob; goto endjob;
} }
@ -4735,7 +4735,7 @@ static int lxcDomainAttachDeviceFlags(virDomainPtr dom,
if (flags & VIR_DOMAIN_AFFECT_CONFIG) { if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
/* Make a copy for updated domain. */ /* Make a copy for updated domain. */
vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt); vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt, NULL);
if (!vmdef) if (!vmdef)
goto endjob; goto endjob;
@ -4840,7 +4840,7 @@ static int lxcDomainUpdateDeviceFlags(virDomainPtr dom,
goto endjob; goto endjob;
/* Make a copy for updated domain. */ /* Make a copy for updated domain. */
if (!(vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt))) if (!(vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt, NULL)))
goto endjob; goto endjob;
/* virDomainDefCompatibleDevice call is delayed until we know the /* virDomainDefCompatibleDevice call is delayed until we know the
@ -4919,7 +4919,7 @@ static int lxcDomainDetachDeviceFlags(virDomainPtr dom,
if (flags & VIR_DOMAIN_AFFECT_CONFIG) { if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
/* Make a copy for updated domain. */ /* Make a copy for updated domain. */
vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt); vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt, NULL);
if (!vmdef) if (!vmdef)
goto endjob; goto endjob;

View File

@ -1289,7 +1289,7 @@ int virLXCProcessStart(virConnectPtr conn,
* report implicit runtime defaults in the XML, like vnc listen/socket * report implicit runtime defaults in the XML, like vnc listen/socket
*/ */
VIR_DEBUG("Setting current domain def as transient"); VIR_DEBUG("Setting current domain def as transient");
if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm) < 0) if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, NULL) < 0)
goto cleanup; goto cleanup;
/* Run an early hook to set-up missing devices */ /* Run an early hook to set-up missing devices */

View File

@ -8826,6 +8826,7 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm,
const char *xml, const char *xml,
unsigned int flags) unsigned int flags)
{ {
qemuDomainObjPrivatePtr priv = vm->privateData;
virDomainDefPtr vmdef = NULL; virDomainDefPtr vmdef = NULL;
virQEMUDriverConfigPtr cfg = NULL; virQEMUDriverConfigPtr cfg = NULL;
virDomainDeviceDefPtr devConf = NULL; virDomainDeviceDefPtr devConf = NULL;
@ -8847,7 +8848,8 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr vm,
* rely on the correct vm->def or vm->newDef being passed, so call the * rely on the correct vm->def or vm->newDef being passed, so call the
* device parse based on which definition is in use */ * device parse based on which definition is in use */
if (flags & VIR_DOMAIN_AFFECT_CONFIG) { if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt); vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt,
priv->qemuCaps);
if (!vmdef) if (!vmdef)
goto cleanup; goto cleanup;
@ -8965,6 +8967,7 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
{ {
virQEMUDriverPtr driver = dom->conn->privateData; virQEMUDriverPtr driver = dom->conn->privateData;
virDomainObjPtr vm = NULL; virDomainObjPtr vm = NULL;
qemuDomainObjPrivatePtr priv;
virDomainDefPtr vmdef = NULL; virDomainDefPtr vmdef = NULL;
virDomainDeviceDefPtr dev = NULL, dev_copy = NULL; virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0; bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0;
@ -8987,6 +8990,8 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
if (!(vm = qemuDomObjFromDomain(dom))) if (!(vm = qemuDomObjFromDomain(dom)))
goto cleanup; goto cleanup;
priv = vm->privateData;
if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0) if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
goto cleanup; goto cleanup;
@ -9019,7 +9024,8 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
if (flags & VIR_DOMAIN_AFFECT_CONFIG) { if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
/* Make a copy for updated domain. */ /* Make a copy for updated domain. */
vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt); vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt,
priv->qemuCaps);
if (!vmdef) if (!vmdef)
goto endjob; goto endjob;
@ -9077,6 +9083,7 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriverPtr driver,
const char *xml, const char *xml,
unsigned int flags) unsigned int flags)
{ {
qemuDomainObjPrivatePtr priv = vm->privateData;
virCapsPtr caps = NULL; virCapsPtr caps = NULL;
virQEMUDriverConfigPtr cfg = NULL; virQEMUDriverConfigPtr cfg = NULL;
virDomainDeviceDefPtr dev = NULL, dev_copy = NULL; virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
@ -9115,7 +9122,7 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriverPtr driver,
if (flags & VIR_DOMAIN_AFFECT_CONFIG) { if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
/* Make a copy for updated domain. */ /* Make a copy for updated domain. */
vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt); vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt, priv->qemuCaps);
if (!vmdef) if (!vmdef)
goto cleanup; goto cleanup;
@ -9171,6 +9178,7 @@ qemuDomainDetachDeviceAliasLiveAndConfig(virQEMUDriverPtr driver,
const char *alias, const char *alias,
unsigned int flags) unsigned int flags)
{ {
qemuDomainObjPrivatePtr priv = vm->privateData;
virCapsPtr caps = NULL; virCapsPtr caps = NULL;
virQEMUDriverConfigPtr cfg = NULL; virQEMUDriverConfigPtr cfg = NULL;
virDomainDefPtr def = NULL; virDomainDefPtr def = NULL;
@ -9197,7 +9205,8 @@ qemuDomainDetachDeviceAliasLiveAndConfig(virQEMUDriverPtr driver,
if (persistentDef) { if (persistentDef) {
virDomainDeviceDef dev; virDomainDeviceDef dev;
if (!(vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt))) if (!(vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt,
priv->qemuCaps)))
goto cleanup; goto cleanup;
if (virDomainDefFindDevice(vmdef, alias, &dev, true) < 0) if (virDomainDefFindDevice(vmdef, alias, &dev, true) < 0)
@ -10810,7 +10819,8 @@ qemuDomainSetSchedulerParametersFlags(virDomainPtr dom,
if (persistentDef) { if (persistentDef) {
/* Make a copy for updated domain. */ /* Make a copy for updated domain. */
if (!(persistentDefCopy = virDomainObjCopyPersistentDef(vm, caps, if (!(persistentDefCopy = virDomainObjCopyPersistentDef(vm, caps,
driver->xmlopt))) driver->xmlopt,
priv->qemuCaps)))
goto endjob; goto endjob;
} }
@ -16477,6 +16487,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
if (!(vm = qemuDomObjFromSnapshot(snapshot))) if (!(vm = qemuDomObjFromSnapshot(snapshot)))
goto cleanup; goto cleanup;
priv = vm->privateData;
cfg = virQEMUDriverGetConfig(driver); cfg = virQEMUDriverGetConfig(driver);
if (virDomainRevertToSnapshotEnsureACL(snapshot->domain->conn, vm->def) < 0) if (virDomainRevertToSnapshotEnsureACL(snapshot->domain->conn, vm->def) < 0)
@ -16553,7 +16564,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
* than inactive xml? */ * than inactive xml? */
if (snap->def->dom) { if (snap->def->dom) {
config = virDomainDefCopy(snap->def->dom, caps, config = virDomainDefCopy(snap->def->dom, caps,
driver->xmlopt, NULL, true); driver->xmlopt, priv->qemuCaps, true);
if (!config) if (!config)
goto endjob; goto endjob;
} }
@ -16563,7 +16574,6 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
switch ((virDomainSnapshotState) snapdef->state) { switch ((virDomainSnapshotState) snapdef->state) {
case VIR_DOMAIN_SNAPSHOT_RUNNING: case VIR_DOMAIN_SNAPSHOT_RUNNING:
case VIR_DOMAIN_SNAPSHOT_PAUSED: case VIR_DOMAIN_SNAPSHOT_PAUSED:
priv = vm->privateData;
start_flags |= VIR_QEMU_PROCESS_START_PAUSED; start_flags |= VIR_QEMU_PROCESS_START_PAUSED;
/* Transitions 2, 3, 5, 6, 8, 9 */ /* Transitions 2, 3, 5, 6, 8, 9 */
@ -22016,6 +22026,7 @@ qemuDomainGetFSInfo(virDomainPtr dom,
unsigned int flags) unsigned int flags)
{ {
virQEMUDriverPtr driver = dom->conn->privateData; virQEMUDriverPtr driver = dom->conn->privateData;
qemuDomainObjPrivatePtr priv;
virDomainObjPtr vm; virDomainObjPtr vm;
qemuAgentPtr agent; qemuAgentPtr agent;
virCapsPtr caps = NULL; virCapsPtr caps = NULL;
@ -22027,6 +22038,8 @@ qemuDomainGetFSInfo(virDomainPtr dom,
if (!(vm = qemuDomObjFromDomain(dom))) if (!(vm = qemuDomObjFromDomain(dom)))
return ret; return ret;
priv = vm->privateData;
if (virDomainGetFSInfoEnsureACL(dom->conn, vm->def) < 0) if (virDomainGetFSInfoEnsureACL(dom->conn, vm->def) < 0)
goto cleanup; goto cleanup;
@ -22042,7 +22055,7 @@ qemuDomainGetFSInfo(virDomainPtr dom,
if (!(caps = virQEMUDriverGetCapabilities(driver, false))) if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
goto endjob; goto endjob;
if (!(def = virDomainDefCopy(vm->def, caps, driver->xmlopt, NULL, false))) if (!(def = virDomainDefCopy(vm->def, caps, driver->xmlopt, priv->qemuCaps, false)))
goto endjob; goto endjob;
agent = qemuDomainObjEnterAgent(vm); agent = qemuDomainObjEnterAgent(vm);

View File

@ -4853,6 +4853,7 @@ qemuMigrationDstPersist(virQEMUDriverPtr driver,
bool ignoreSaveError) bool ignoreSaveError)
{ {
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
qemuDomainObjPrivatePtr priv = vm->privateData;
virCapsPtr caps = NULL; virCapsPtr caps = NULL;
virDomainDefPtr vmdef; virDomainDefPtr vmdef;
virDomainDefPtr oldDef = NULL; virDomainDefPtr oldDef = NULL;
@ -4867,7 +4868,8 @@ qemuMigrationDstPersist(virQEMUDriverPtr driver,
oldDef = vm->newDef; oldDef = vm->newDef;
vm->newDef = qemuMigrationCookieGetPersistent(mig); vm->newDef = qemuMigrationCookieGetPersistent(mig);
if (!(vmdef = virDomainObjGetPersistentDef(caps, driver->xmlopt, vm))) if (!(vmdef = virDomainObjGetPersistentDef(caps, driver->xmlopt, vm,
priv->qemuCaps)))
goto error; goto error;
if (virDomainSaveConfig(cfg->configDir, driver->caps, vmdef) < 0 && if (virDomainSaveConfig(cfg->configDir, driver->caps, vmdef) < 0 &&

View File

@ -5637,7 +5637,7 @@ qemuProcessInit(virQEMUDriverPtr driver,
* report implicit runtime defaults in the XML, like vnc listen/socket * report implicit runtime defaults in the XML, like vnc listen/socket
*/ */
VIR_DEBUG("Setting current domain def as transient"); VIR_DEBUG("Setting current domain def as transient");
if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm) < 0) if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, priv->qemuCaps) < 0)
goto cleanup; goto cleanup;
/* Update qemu capabilities according to lists passed in via namespace */ /* Update qemu capabilities according to lists passed in via namespace */

View File

@ -713,7 +713,7 @@ testDomainStartState(testDriverPtr privconn,
if (virDomainObjSetDefTransient(privconn->caps, if (virDomainObjSetDefTransient(privconn->caps,
privconn->xmlopt, privconn->xmlopt,
dom) < 0) { dom, NULL) < 0) {
goto cleanup; goto cleanup;
} }

View File

@ -427,7 +427,7 @@ testQemuHotplugCpuPrepare(const char *test,
/* create vm->newDef */ /* create vm->newDef */
data->vm->persistent = true; data->vm->persistent = true;
if (virDomainObjSetDefTransient(caps, driver.xmlopt, data->vm) < 0) if (virDomainObjSetDefTransient(caps, driver.xmlopt, data->vm, NULL) < 0)
goto error; goto error;
priv = data->vm->privateData; priv = data->vm->privateData;