We have enough patches for hotplug RNG device, maybe we can
implement live hotplug of a RNG device.
Signed-off-by: Luyao Huang <lhuang(a)redhat.com>
---
src/qemu/qemu_driver.c | 8 +++-
src/qemu/qemu_hotplug.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_hotplug.h | 3 ++
3 files changed, 116 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index cdf4173..f9d404b 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6952,6 +6952,13 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
dev->data.chr = NULL;
break;
+ case VIR_DOMAIN_DEVICE_RNG:
+ ret = qemuDomainAttachRNGDevice(driver, vm,
+ dev->data.rng);
+ if (!ret)
+ dev->data.rng = NULL;
+ break;
+
case VIR_DOMAIN_DEVICE_NONE:
case VIR_DOMAIN_DEVICE_FS:
case VIR_DOMAIN_DEVICE_INPUT:
@@ -6963,7 +6970,6 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
case VIR_DOMAIN_DEVICE_SMARTCARD:
case VIR_DOMAIN_DEVICE_MEMBALLOON:
case VIR_DOMAIN_DEVICE_NVRAM:
- case VIR_DOMAIN_DEVICE_RNG:
case VIR_DOMAIN_DEVICE_SHMEM:
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index e54a541..afa9618 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1517,6 +1517,112 @@ qemuDomainRNGRemove(virDomainDefPtr vmdef,
return ret;
}
+int qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainRNGDefPtr rng)
+{
+ int ret = -1;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virDomainDefPtr vmdef = vm->def;
+ char *devstr = NULL;
+ char *charAlias = NULL;
+ char *objAlias = NULL;
+ bool remove_chardev = false;
+ bool releaseaddr = false;
+
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("qemu does not support -device"));
+ return ret;
+ }
+
+ if (rng->backend == VIR_DOMAIN_RNG_BACKEND_RANDOM &&
+ !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_RNG_RANDOM)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("this qemu doesn't support the rng-random "
+ "backend"));
+ return ret;
+ } else if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD &&
+ !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_RNG_EGD)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("this qemu doesn't support the rng-egd "
+ "backend"));
+ return ret;
+ }
+
+ if (qemuAssignDeviceRNGAlias(vmdef, rng, -1) < 0)
+ return ret;
+
+ if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+ if (STRPREFIX(vm->def->os.machine, "s390-ccw") &&
+ virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW)) {
+ rng->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW;
+ } else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_S390)) {
+ rng->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390;
+ }
+ }
+
+ if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
+ rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+ if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &rng->info) < 0)
+ return ret;
+ } else if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
+ if (virDomainCCWAddressAssign(&rng->info, priv->ccwaddrs,
+ !rng->info.addr.ccw.assigned) < 0)
+ return ret;
+ }
+ releaseaddr = true;
+ if (!(devstr = qemuBuildRNGDevStr(vmdef, rng, priv->qemuCaps)))
+ goto cleanup;
+
+ if (virAsprintf(&objAlias, "obj%s", rng->info.alias) < 0)
+ goto cleanup;
+
+ if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD) {
+ if (virAsprintf(&charAlias, "char%s", rng->info.alias) < 0)
+ goto cleanup;
+
+ qemuDomainObjEnterMonitor(driver, vm);
+ if (qemuMonitorAttachCharDev(priv->mon, charAlias, rng->source.chardev)
< 0) {
+ qemuDomainObjExitMonitor(driver, vm);
+ goto audit;
+ }
+ remove_chardev = true;
+ } else {
+ qemuDomainObjEnterMonitor(driver, vm);
+ }
+
+ if (qemuMonitorAttachRNGDev(priv->mon, charAlias, objAlias, rng) < 0) {
+ if (remove_chardev)
+ qemuMonitorDetachCharDev(priv->mon, charAlias);
+ qemuDomainObjExitMonitor(driver, vm);
+ goto audit;
+ }
+
+ if (devstr && qemuMonitorAddDevice(priv->mon, devstr) < 0) {
+ qemuMonitorDetachRNGDev(priv->mon, objAlias);
+ if (remove_chardev)
+ qemuMonitorDetachCharDev(priv->mon, charAlias);
+ qemuDomainObjExitMonitor(driver, vm);
+ goto audit;
+ }
+ qemuDomainObjExitMonitor(driver, vm);
+
+ if (virDomainRNGInsert(vmdef, rng) < 0)
+ goto cleanup;
+
+ ret = 0;
+ audit:
+ virDomainAuditRNG(vm, NULL, rng, "attach", ret == 0);
+ cleanup:
+ if (releaseaddr)
+ qemuDomainReleaseDeviceAddress(vm, &rng->info, NULL);
+ VIR_FREE(charAlias);
+ VIR_FREE(objAlias);
+ VIR_FREE(devstr);
+ return ret;
+}
+
static int
qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver,
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index d13c532..d66853b 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -98,6 +98,9 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainChrDefPtr chr);
+int qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainRNGDefPtr rng);
int
--
1.8.3.1