return net;
}
+
+/**
+ * virDomainDeviceDefCopy:
+ * @caps: Capabilities
+ * @def: Domain definition to which @src belongs
+ * @src: source to be copied
+ *
+ * virDomainDeviceDefCopy does a deep copy of only the parts of a
+ * DeviceDef that are valid when just the flag VIR_DOMAIN_XML_INACTIVE is
+ * set. This means that any part of the device xml that is conditionally
+ * parsed/formatted based on some other flag being set (or on the INACTIVE
+ * flag being reset) *will not* be copied to the destination. Caveat emptor.
+ *
+ * Returns a pointer to copied @src or NULL in case of error.
+ */
+virDomainDeviceDefPtr
+virDomainDeviceDefCopy(virCapsPtr caps,
+ const virDomainDefPtr def,
+ virDomainDeviceDefPtr src)
+{
+ virDomainDeviceDefPtr ret = NULL;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ int flags = VIR_DOMAIN_XML_INACTIVE;
+ char *xmlStr = NULL;
+ int rc = -1;
+
+ switch(src->type) {
+ case VIR_DOMAIN_DEVICE_DISK:
+ rc = virDomainDiskDefFormat(&buf, src->data.disk, flags);
+ break;
+ case VIR_DOMAIN_DEVICE_LEASE:
+ rc = virDomainLeaseDefFormat(&buf, src->data.lease);
+ break;
+ case VIR_DOMAIN_DEVICE_FS:
+ rc = virDomainFSDefFormat(&buf, src->data.fs, flags);
+ break;
+ case VIR_DOMAIN_DEVICE_NET:
+ rc = virDomainNetDefFormat(&buf, src->data.net, flags);
+ break;
+ case VIR_DOMAIN_DEVICE_INPUT:
+ rc = virDomainInputDefFormat(&buf, src->data.input, flags);
+ break;
+ case VIR_DOMAIN_DEVICE_SOUND:
+ rc = virDomainSoundDefFormat(&buf, src->data.sound, flags);
+ break;
+ case VIR_DOMAIN_DEVICE_VIDEO:
+ rc = virDomainVideoDefFormat(&buf, src->data.video, flags);
+ break;
+ case VIR_DOMAIN_DEVICE_HOSTDEV:
+ rc = virDomainHostdevDefFormat(&buf, src->data.hostdev, flags);
+ break;
+ case VIR_DOMAIN_DEVICE_WATCHDOG:
+ rc = virDomainWatchdogDefFormat(&buf, src->data.watchdog, flags);
+ break;
+ case VIR_DOMAIN_DEVICE_CONTROLLER:
+ rc = virDomainControllerDefFormat(&buf, src->data.controller, flags);
+ break;
+ case VIR_DOMAIN_DEVICE_GRAPHICS:
+ rc = virDomainGraphicsDefFormat(&buf, src->data.graphics, flags);
+ break;
+ case VIR_DOMAIN_DEVICE_HUB:
+ rc = virDomainHubDefFormat(&buf, src->data.hub, flags);
+ break;
+ case VIR_DOMAIN_DEVICE_REDIRDEV:
+ rc = virDomainRedirdevDefFormat(&buf, src->data.redirdev, flags);
+ break;
+ default:
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Copying definition of '%d' type "
+ "is not implemented yet."),
+ src->type);
+ goto cleanup;
+ }
+
+ if (rc < 0)
+ goto cleanup;
+
+ xmlStr = virBufferContentAndReset(&buf);
+ ret = virDomainDeviceDefParse(caps, def, xmlStr, flags);
+
+cleanup:
+ VIR_FREE(xmlStr);
+ return ret;
+}
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = NULL;
virDomainDefPtr vmdef = NULL;
- virDomainDeviceDefPtr dev = NULL;
+ virDomainDeviceDefPtr dev = NULL, dev_copy = NULL;
bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0;
int ret = -1;
unsigned int affect;
goto endjob;
}
- if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
- dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
- VIR_DOMAIN_XML_INACTIVE);
- if (dev == NULL)
+ dev = dev_copy = virDomainDeviceDefParse(driver->caps, vm->def, xml,
+ VIR_DOMAIN_XML_INACTIVE);
+ if (dev == NULL)
+ goto endjob;
+
+ if (flags & VIR_DOMAIN_AFFECT_CONFIG &&
+ flags & VIR_DOMAIN_AFFECT_LIVE) {
+ /* If we are affecting both CONFIG and LIVE
+ * create a deep copy of device as adding
+ * to CONFIG takes one instance.
+ */
+ dev_copy = virDomainDeviceDefCopy(driver->caps, vm->def, dev);
+ if (!dev_copy)
goto endjob;
+ }
+ if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
/* Make a copy for updated domain. */
vmdef = virDomainObjCopyPersistentDef(driver->caps, vm);
if (!vmdef)
}
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
- /* If dev exists it was created to modify the domain config. Free it. */
- virDomainDeviceDefFree(dev);
- dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
- VIR_DOMAIN_XML_INACTIVE);
- if (dev == NULL) {
- ret = -1;
- goto endjob;
- }
-
switch (action) {
case QEMU_DEVICE_ATTACH:
- ret = qemuDomainAttachDeviceLive(vm, dev, dom);
+ ret = qemuDomainAttachDeviceLive(vm, dev_copy, dom);
break;
case QEMU_DEVICE_DETACH:
- ret = qemuDomainDetachDeviceLive(vm, dev, dom);
+ ret = qemuDomainDetachDeviceLive(vm, dev_copy, dom);
break;
case QEMU_DEVICE_UPDATE:
- ret = qemuDomainUpdateDeviceLive(vm, dev, dom, force);
+ ret = qemuDomainUpdateDeviceLive(vm, dev_copy, dom, force);
break;
default:
qemuReportError(VIR_ERR_INTERNAL_ERROR,
cleanup:
virDomainDefFree(vmdef);
+ if (dev != dev_copy)
+ virDomainDeviceDefFree(dev_copy);
virDomainDeviceDefFree(dev);
if (vm)
virDomainObjUnlock(vm);