[libvirt] [PATCH v3 0/9] qemu: support hot-plug/unplug RNG device

qemu already support hot-plug and hot-unplug RNG device. These patch will make libvirt support hot-plug/unplug RNG device for qemu driver. v3: -fix a wrong use of virJSONValueObjectCreate -merge some new functions use qemu monitor in one patch -merge tests fix in the patch which need fix tests v2: -remove a commit about add 4 new func in libvirt_private.syms and move them to the commit which use these functions -impove some commit subject -improve the logic in virDomainRNGRemove -remove qemuDomainRNGInsert -unexport qemuDomainRNGRemove -add a check if chardev and backend object ID have the same basic alias name -rename need_remove to remove_chardev in qemuDomainAttachRNGDevice -add qemu capability check for RNG device backend Luyao Huang (9): qemu: Add helper to assign RNG device aliases qemu: refactor qemuBuildRNGDeviceArgs to allow reuse in RNG hotplug conf: Introduce function to compare RNG devices. conf: add 3 functions for insert,remove and find a RNG device qemu: add id when build RNG device and rename object id qemu: add functions for attach/detach RNG device via qemu monitor audit: export virDomainAuditRNG qemu: Implement RNG device hotplug on live level qemu: Implement RNG device hotunplug on live level src/conf/domain_audit.c | 2 +- src/conf/domain_audit.h | 7 + src/conf/domain_conf.c | 76 +++++++ src/conf/domain_conf.h | 9 + src/libvirt_private.syms | 6 + src/qemu/qemu_command.c | 69 ++++--- src/qemu/qemu_command.h | 5 + src/qemu/qemu_driver.c | 12 +- src/qemu/qemu_hotplug.c | 218 ++++++++++++++++++++- src/qemu/qemu_hotplug.h | 7 +- src/qemu/qemu_monitor.c | 43 ++++ src/qemu/qemu_monitor.h | 7 + src/qemu/qemu_monitor_json.c | 43 ++++ src/qemu/qemu_monitor_json.h | 5 + .../qemuxml2argv-aarch64-virt-virtio.args | 4 +- .../qemuxml2argv-arm-vexpressa9-virtio.args | 4 +- .../qemuxml2argv-arm-virt-virtio.args | 4 +- .../qemuxml2argv-s390-piix-controllers.args | 2 +- .../qemuxml2argv-s390-usb-none.args | 2 +- .../qemuxml2argv-virtio-rng-ccw.args | 4 +- .../qemuxml2argv-virtio-rng-default.args | 4 +- .../qemuxml2argv-virtio-rng-egd.args | 4 +- .../qemuxml2argv-virtio-rng-multiple.args | 8 +- .../qemuxml2argv-virtio-rng-random.args | 4 +- 24 files changed, 501 insertions(+), 48 deletions(-) -- 1.8.3.1

This function is used to assign an alias for a RNG device. It will be later reused when hotplugging RNGs. Signed-off-by: Luyao Huang <lhuang@redhat.com> --- src/qemu/qemu_command.c | 25 ++++++++++++++++++++++++- src/qemu/qemu_command.h | 1 + 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index c041ee7..52741fe 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -910,6 +910,29 @@ qemuGetNextChrDevIndex(virDomainDefPtr def, return idx; } +int +qemuAssignDeviceRNGAlias(virDomainDefPtr def, virDomainRNGDefPtr rng, int idx) +{ + if (idx == -1) { + size_t i; + idx = 0; + for (i = 0; i < def->nrngs; i++) { + int thisidx; + if ((thisidx = qemuDomainDeviceAliasIndex(&def->rngs[i]->info, "rng")) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to determine device index for RNG device")); + return -1; + } + if (thisidx >= idx) + idx = thisidx + 1; + } + } + + if (virAsprintf(&rng->info.alias, "rng%d", idx) < 0) + return -1; + + return 0; +} int qemuAssignDeviceChrAlias(virDomainDefPtr def, @@ -1036,7 +1059,7 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) return -1; } for (i = 0; i < def->nrngs; i++) { - if (virAsprintf(&def->rngs[i]->info.alias, "rng%zu", i) < 0) + if (qemuAssignDeviceRNGAlias(def, def->rngs[i], i) < 0) return -1; } if (def->tpm) { diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index dcc7127..fc5f50a 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -264,6 +264,7 @@ int qemuAssignDeviceRedirdevAlias(virDomainDefPtr def, virDomainRedirdevDefPtr r int qemuAssignDeviceChrAlias(virDomainDefPtr def, virDomainChrDefPtr chr, ssize_t idx); +int qemuAssignDeviceRNGAlias(virDomainDefPtr def, virDomainRNGDefPtr rng, int idx); int qemuParseKeywords(const char *str, -- 1.8.3.1

Rename qemuBuildRNGDeviceArgs to qemuBuildRNGDevStr and change the return type so that it can be reused in the device hotplug code later. Signed-off-by: Luyao Huang <lhuang@redhat.com> --- src/qemu/qemu_command.c | 32 ++++++++++++++++---------------- src/qemu/qemu_command.h | 4 ++++ 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 52741fe..c0cd3eb 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5820,21 +5820,19 @@ qemuBuildRNGBackendArgs(virCommandPtr cmd, } -static int -qemuBuildRNGDeviceArgs(virCommandPtr cmd, - virDomainDefPtr def, - virDomainRNGDefPtr dev, - virQEMUCapsPtr qemuCaps) +char * +qemuBuildRNGDevStr(virDomainDefPtr def, + virDomainRNGDefPtr dev, + virQEMUCapsPtr qemuCaps) { virBuffer buf = VIR_BUFFER_INITIALIZER; - int ret = -1; if (dev->model != VIR_DOMAIN_RNG_MODEL_VIRTIO || !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_RNG)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("this qemu doesn't support RNG device type '%s'"), virDomainRNGModelTypeToString(dev->model)); - goto cleanup; + goto error; } if (dev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) @@ -5855,16 +5853,14 @@ qemuBuildRNGDeviceArgs(virCommandPtr cmd, } if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0) - goto cleanup; - - virCommandAddArg(cmd, "-device"); - virCommandAddArgBuffer(cmd, &buf); - - ret = 0; + goto error; + if (virBufferCheckError(&buf) < 0) + goto error; - cleanup: + return virBufferContentAndReset(&buf); + error: virBufferFreeAndReset(&buf); - return ret; + return NULL; } @@ -9845,13 +9841,17 @@ qemuBuildCommandLine(virConnectPtr conn, } for (i = 0; i < def->nrngs; i++) { + char *devstr; /* add the RNG source backend */ if (qemuBuildRNGBackendArgs(cmd, def->rngs[i], qemuCaps) < 0) goto error; /* add the device */ - if (qemuBuildRNGDeviceArgs(cmd, def, def->rngs[i], qemuCaps) < 0) + virCommandAddArg(cmd, "-device"); + if (!(devstr = qemuBuildRNGDevStr(def, def->rngs[i], qemuCaps))) goto error; + virCommandAddArg(cmd, devstr); + VIR_FREE(devstr); } if (def->nvram) { diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index fc5f50a..3959677 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -165,6 +165,10 @@ char *qemuBuildPCIHostdevDevStr(virDomainDefPtr def, const char *configfd, virQEMUCapsPtr qemuCaps); +char *qemuBuildRNGDevStr(virDomainDefPtr def, + virDomainRNGDefPtr dev, + virQEMUCapsPtr qemuCaps); + int qemuOpenPCIConfig(virDomainHostdevDefPtr dev); /* Legacy, pre device support */ -- 1.8.3.1

virDomainRNGEquals is a func which check if two rng device are the same. Signed-off-by: Luyao Huang <lhuang@redhat.com> --- src/conf/domain_conf.c | 34 ++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 3 +++ src/libvirt_private.syms | 1 + 3 files changed, 38 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 8792f5e..81e4030 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -12061,6 +12061,40 @@ virDomainChrRemove(virDomainDefPtr vmdef, return ret; } +bool +virDomainRNGEquals(virDomainRNGDefPtr src, + virDomainRNGDefPtr tgt) +{ + if (!src || !tgt) + return src == tgt; + + if (src->model != tgt->model) + return false; + + if (src->rate != tgt->rate || src->period != tgt->period) + return false; + + switch ((virDomainRNGModel) src->model) { + case VIR_DOMAIN_RNG_MODEL_VIRTIO: + switch ((virDomainRNGBackend) src->backend) { + case VIR_DOMAIN_RNG_BACKEND_RANDOM: + return STREQ_NULLABLE(src->source.file, tgt->source.file); + break; + case VIR_DOMAIN_RNG_BACKEND_EGD: + return virDomainChrSourceDefIsEqual(src->source.chardev, + tgt->source.chardev); + break; + case VIR_DOMAIN_RNG_BACKEND_LAST: + break; + } + break; + + case VIR_DOMAIN_RNG_MODEL_LAST: + break; + } + return false; +} + char * virDomainDefGetDefaultEmulator(virDomainDefPtr def, virCapsPtr caps) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 09ab194..b3843e8 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2653,6 +2653,9 @@ virDomainChrDefPtr virDomainChrRemove(virDomainDefPtr vmdef, virDomainChrDefPtr chr); +bool virDomainRNGEquals(virDomainRNGDefPtr src, + virDomainRNGDefPtr tgt); + int virDomainSaveXML(const char *configDir, virDomainDefPtr def, const char *xml); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index a2eec83..653655f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -377,6 +377,7 @@ virDomainPMSuspendedReasonTypeToString; virDomainRedirdevBusTypeFromString; virDomainRedirdevBusTypeToString; virDomainRNGBackendTypeToString; +virDomainRNGEquals; virDomainRNGModelTypeToString; virDomainRunningReasonTypeFromString; virDomainRunningReasonTypeToString; -- 1.8.3.1

the 3 functions are: virDomainRNGInsert: Insert a RNG device to vm->def. virDomainRNGRemove: remove a RNG device in vm->def. virDomainRNGFind: find a RNG device in vm->def. Signed-off-by: Luyao Huang <lhuang@redhat.com> --- src/conf/domain_conf.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 6 ++++++ src/libvirt_private.syms | 3 +++ 3 files changed, 51 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 81e4030..659864c 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -12095,6 +12095,48 @@ virDomainRNGEquals(virDomainRNGDefPtr src, return false; } +int +virDomainRNGInsert(virDomainDefPtr vmdef, + virDomainRNGDefPtr rng) +{ + return VIR_APPEND_ELEMENT(vmdef->rngs, vmdef->nrngs, rng); +} + +virDomainRNGDefPtr +virDomainRNGRemove(virDomainDefPtr vmdef, + virDomainRNGDefPtr rng) +{ + virDomainRNGDefPtr ret; + size_t i; + + for (i = 0; i < vmdef->nrngs; i++) { + ret = vmdef->rngs[i]; + + if (virDomainRNGEquals(ret, rng)) { + VIR_DELETE_ELEMENT(vmdef->rngs, i, vmdef->nrngs); + return ret; + } + } + + return NULL; +} + +virDomainRNGDefPtr +virDomainRNGFind(virDomainDefPtr vmdef, + virDomainRNGDefPtr rng) +{ + virDomainRNGDefPtr ret; + size_t i; + + for (i = 0; i < vmdef->nrngs; i++) { + ret = vmdef->rngs[i]; + + if (virDomainRNGEquals(ret, rng)) + return ret; + } + return NULL; +} + char * virDomainDefGetDefaultEmulator(virDomainDefPtr def, virCapsPtr caps) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index b3843e8..10cb09b 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2655,6 +2655,12 @@ virDomainChrRemove(virDomainDefPtr vmdef, bool virDomainRNGEquals(virDomainRNGDefPtr src, virDomainRNGDefPtr tgt); +int virDomainRNGInsert(virDomainDefPtr vmdef, + virDomainRNGDefPtr rng); +virDomainRNGDefPtr virDomainRNGRemove(virDomainDefPtr vmdef, + virDomainRNGDefPtr rng); +virDomainRNGDefPtr virDomainRNGFind(virDomainDefPtr vmdef, + virDomainRNGDefPtr rng); int virDomainSaveXML(const char *configDir, virDomainDefPtr def, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 653655f..a635652 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -378,7 +378,10 @@ virDomainRedirdevBusTypeFromString; virDomainRedirdevBusTypeToString; virDomainRNGBackendTypeToString; virDomainRNGEquals; +virDomainRNGFind; +virDomainRNGInsert; virDomainRNGModelTypeToString; +virDomainRNGRemove; virDomainRunningReasonTypeFromString; virDomainRunningReasonTypeToString; virDomainSaveConfig; -- 1.8.3.1

We didn't set a id when we build RNG device cmdline before. Give a id to every RNG device and we can hotunplug it via QMP cmd device_del. And fix the tests. Signed-off-by: Luyao Huang <lhuang@redhat.com> --- src/qemu/qemu_command.c | 12 ++++++------ tests/qemuxml2argvdata/qemuxml2argv-aarch64-virt-virtio.args | 4 ++-- .../qemuxml2argvdata/qemuxml2argv-arm-vexpressa9-virtio.args | 4 ++-- tests/qemuxml2argvdata/qemuxml2argv-arm-virt-virtio.args | 4 ++-- .../qemuxml2argvdata/qemuxml2argv-s390-piix-controllers.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-s390-usb-none.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-ccw.args | 4 ++-- tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-default.args | 4 ++-- tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-egd.args | 4 ++-- tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-multiple.args | 8 ++++---- tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.args | 4 ++-- 11 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index c0cd3eb..57f73be 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5780,7 +5780,7 @@ qemuBuildRNGBackendArgs(virCommandPtr cmd, goto cleanup; } - virBufferAsprintf(&buf, "rng-random,id=%s,filename=%s", + virBufferAsprintf(&buf, "rng-random,id=obj%s,filename=%s", dev->info.alias, dev->source.file); virCommandAddArg(cmd, "-object"); @@ -5803,7 +5803,7 @@ qemuBuildRNGBackendArgs(virCommandPtr cmd, virCommandAddArgList(cmd, "-chardev", backend, NULL); virCommandAddArg(cmd, "-object"); - virCommandAddArgFormat(cmd, "rng-egd,chardev=char%s,id=%s", + virCommandAddArgFormat(cmd, "rng-egd,chardev=char%s,id=obj%s", dev->info.alias, dev->info.alias); break; @@ -5836,13 +5836,13 @@ qemuBuildRNGDevStr(virDomainDefPtr def, } if (dev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) - virBufferAsprintf(&buf, "virtio-rng-ccw,rng=%s", dev->info.alias); + virBufferAsprintf(&buf, "virtio-rng-ccw,rng=obj%s,id=%s", dev->info.alias, dev->info.alias); else if (dev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) - virBufferAsprintf(&buf, "virtio-rng-s390,rng=%s", dev->info.alias); + virBufferAsprintf(&buf, "virtio-rng-s390,rng=obj%s,id=%s", dev->info.alias, dev->info.alias); else if (dev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO) - virBufferAsprintf(&buf, "virtio-rng-device,rng=%s", dev->info.alias); + virBufferAsprintf(&buf, "virtio-rng-device,rng=obj%s,id=%s", dev->info.alias, dev->info.alias); else - virBufferAsprintf(&buf, "virtio-rng-pci,rng=%s", dev->info.alias); + virBufferAsprintf(&buf, "virtio-rng-pci,rng=obj%s,id=%s", dev->info.alias, dev->info.alias); if (dev->rate > 0) { virBufferAsprintf(&buf, ",max-bytes=%u", dev->rate); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virt-virtio.args b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virt-virtio.args index 05f3629..d12e6e2 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virt-virtio.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virt-virtio.args @@ -11,5 +11,5 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ -net user,vlan=0,name=hostnet0 -serial pty -chardev pty,id=charconsole1 \ -device virtconsole,chardev=charconsole1,id=console1 \ -device virtio-balloon-device,id=balloon0 \ --object rng-random,id=rng0,filename=/dev/random \ --device virtio-rng-device,rng=rng0 +-object rng-random,id=objrng0,filename=/dev/random \ +-device virtio-rng-device,rng=objrng0,id=rng0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-arm-vexpressa9-virtio.args b/tests/qemuxml2argvdata/qemuxml2argv-arm-vexpressa9-virtio.args index 62de9d3..dba74e1 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-arm-vexpressa9-virtio.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-arm-vexpressa9-virtio.args @@ -10,5 +10,5 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ -net user,vlan=0,name=hostnet0 -serial pty -chardev pty,id=charconsole1 \ -device virtconsole,chardev=charconsole1,id=console1 \ -device virtio-balloon-device,id=balloon0 \ --object rng-random,id=rng0,filename=/dev/random \ --device virtio-rng-device,rng=rng0 +-object rng-random,id=objrng0,filename=/dev/random \ +-device virtio-rng-device,rng=objrng0,id=rng0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-arm-virt-virtio.args b/tests/qemuxml2argvdata/qemuxml2argv-arm-virt-virtio.args index 5206ad8..c73022b 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-arm-virt-virtio.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-arm-virt-virtio.args @@ -10,5 +10,5 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ -net user,vlan=0,name=hostnet0 -serial pty -chardev pty,id=charconsole1 \ -device virtconsole,chardev=charconsole1,id=console1 \ -device virtio-balloon-device,id=balloon0 \ --object rng-random,id=rng0,filename=/dev/random \ --device virtio-rng-device,rng=rng0 +-object rng-random,id=objrng0,filename=/dev/random \ +-device virtio-rng-device,rng=objrng0,id=rng0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-s390-piix-controllers.args b/tests/qemuxml2argvdata/qemuxml2argv-s390-piix-controllers.args index c09382f..a8a0537 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-s390-piix-controllers.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-s390-piix-controllers.args @@ -8,4 +8,4 @@ file=/dev/HostVG/QEMUGuest1,if=none,id=drive-virtio-disk0 \ -device virtio-blk-s390,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 \ -chardev pty,id=charconsole0 \ -device virtconsole,chardev=charconsole0,id=console0 \ --object rng-random,id=rng0,filename=/dev/hwrng -device virtio-rng-s390,rng=rng0 +-object rng-random,id=objrng0,filename=/dev/hwrng -device virtio-rng-s390,rng=objrng0,id=rng0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-s390-usb-none.args b/tests/qemuxml2argvdata/qemuxml2argv-s390-usb-none.args index 6d97156..44ad072 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-s390-usb-none.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-s390-usb-none.args @@ -8,4 +8,4 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ -device virtio-blk-s390,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 \ -chardev pty,id=charconsole0 \ -device virtconsole,chardev=charconsole0,id=console0 \ --object rng-random,id=rng0,filename=/dev/hwrng -device virtio-rng-s390,rng=rng0 +-object rng-random,id=objrng0,filename=/dev/hwrng -device virtio-rng-s390,rng=objrng0,id=rng0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-ccw.args b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-ccw.args index a1b2eb6..3a04ed1 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-ccw.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-ccw.args @@ -10,5 +10,5 @@ id=virtio-disk0,bootindex=1 \ -chardev pty,id=charconsole0 \ -device virtconsole,chardev=charconsole0,id=console0 \ -device virtio-balloon-ccw,id=balloon0,devno=fe.0.000a \ --object rng-random,id=rng0,filename=/dev/hwrng \ --device virtio-rng-ccw,rng=rng0,devno=fe.0.0002 +-object rng-random,id=objrng0,filename=/dev/hwrng \ +-device virtio-rng-ccw,rng=objrng0,id=rng0,devno=fe.0.0002 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-default.args b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-default.args index 58cc473..84aa5cd 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-default.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-default.args @@ -3,5 +3,5 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ -S -M pc -m 214 -smp 1 -nographic -nodefaults \ -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \ -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 \ --object rng-random,id=rng0,filename=/dev/random \ --device virtio-rng-pci,rng=rng0,bus=pci.0,addr=0x7 +-object rng-random,id=objrng0,filename=/dev/random \ +-device virtio-rng-pci,rng=objrng0,id=rng0,bus=pci.0,addr=0x7 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-egd.args b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-egd.args index 5530f7d..67c5047 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-egd.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-egd.args @@ -4,5 +4,5 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \ -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 \ -chardev socket,id=charrng0,host=1.2.3.4,port=1234 \ --object rng-egd,chardev=charrng0,id=rng0 \ --device virtio-rng-pci,rng=rng0,bus=pci.0,addr=0x4 +-object rng-egd,chardev=charrng0,id=objrng0 \ +-device virtio-rng-pci,rng=objrng0,id=rng0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-multiple.args b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-multiple.args index d1faf09..aa99384 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-multiple.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-multiple.args @@ -3,8 +3,8 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ -M pc -m 214 -smp 1 -nographic -nodefaults \ -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \ -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 \ --object rng-random,id=rng0,filename=/dev/random \ --device virtio-rng-pci,rng=rng0,bus=pci.0,addr=0x7 \ +-object rng-random,id=objrng0,filename=/dev/random \ +-device virtio-rng-pci,rng=objrng0,id=rng0,bus=pci.0,addr=0x7 \ -chardev socket,id=charrng1,host=1.2.3.4,port=1234 \ --object rng-egd,chardev=charrng1,id=rng1 \ --device virtio-rng-pci,rng=rng1,bus=pci.0,addr=0x4 +-object rng-egd,chardev=charrng1,id=objrng1 \ +-device virtio-rng-pci,rng=objrng1,id=rng1,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.args b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.args index ecd510e..7fca098 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-virtio-rng-random.args @@ -3,5 +3,5 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ -S -M pc -m 214 -smp 1 -nographic -nodefaults \ -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \ -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 \ --object rng-random,id=rng0,filename=/dev/hwrng \ --device virtio-rng-pci,rng=rng0,max-bytes=123,period=1234,bus=pci.0,addr=0x4 +-object rng-random,id=objrng0,filename=/dev/hwrng \ +-device virtio-rng-pci,rng=objrng0,id=rng0,max-bytes=123,period=1234,bus=pci.0,addr=0x4 -- 1.8.3.1

qemuMonitorAttachRNGDev and qemuMonitorDetachRNGDev functions just do some basic check and then call qemuMonitorJSONAttachRNGDev and qemuMonitorDelObject to help us. Signed-off-by: Luyao Huang <lhuang@redhat.com> --- src/qemu/qemu_monitor.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.h | 7 +++++++ src/qemu/qemu_monitor_json.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 5 +++++ 4 files changed, 98 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 6882a50..1e3f8ea 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -4206,6 +4206,49 @@ int qemuMonitorDetachCharDev(qemuMonitorPtr mon, return qemuMonitorJSONDetachCharDev(mon, chrID); } +int qemuMonitorAttachRNGDev(qemuMonitorPtr mon, + const char *chrID, + const char *objID, + virDomainRNGDefPtr rng) +{ + VIR_DEBUG("mon=%p chrID=%s objID=%s rng=%p", mon, chrID, objID, rng); + + if (!mon) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + + if (!mon->json) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("JSON monitor is required")); + return -1; + } + + return qemuMonitorJSONAttachRNGDev(mon, chrID, objID, rng); +} + +int qemuMonitorDetachRNGDev(qemuMonitorPtr mon, + const char *objID) +{ + VIR_DEBUG("mon=%p objID=%s", mon, objID); + + if (!mon) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + + if (!mon->json) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("JSON monitor is required")); + return -1; + } + + return qemuMonitorDelObject(mon, objID); +} + + int qemuMonitorGetDeviceAliases(qemuMonitorPtr mon, char ***aliases) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 133d42d..a767e3e 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -869,6 +869,13 @@ int qemuMonitorAttachCharDev(qemuMonitorPtr mon, int qemuMonitorDetachCharDev(qemuMonitorPtr mon, const char *chrID); +int qemuMonitorAttachRNGDev(qemuMonitorPtr mon, + const char *chrID, + const char *objID, + virDomainRNGDefPtr rng); +int qemuMonitorDetachRNGDev(qemuMonitorPtr mon, + const char *objID); + int qemuMonitorGetDeviceAliases(qemuMonitorPtr mon, char ***aliases); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index da5c14d..33c3866 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6235,6 +6235,49 @@ qemuMonitorJSONDetachCharDev(qemuMonitorPtr mon, return ret; } +int +qemuMonitorJSONAttachRNGDev(qemuMonitorPtr mon, + const char *chrID, + const char *objID, + virDomainRNGDefPtr rng) +{ + const char *type = NULL; + virJSONValuePtr props; + + if (!(props = virJSONValueNewObject())) + goto cleanup; + + switch ((virDomainRNGBackend) rng->backend) { + case VIR_DOMAIN_RNG_BACKEND_RANDOM: + type = "rng-random"; + if (virJSONValueObjectCreate(&props, "s:filename", rng->source.file, NULL) < 0) + goto cleanup; + break; + + case VIR_DOMAIN_RNG_BACKEND_EGD: + if (STRNEQ_NULLABLE(strstr(chrID, "rng"), strstr(objID, "rng"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("chardev id '%s' basic alias name is different from '%s'", + chrID, objID)); + goto cleanup; + } + type = "rng-egd"; + if (virJSONValueObjectCreate(&props, "s:chardev", chrID, NULL) < 0) + goto cleanup; + break; + + case VIR_DOMAIN_RNG_BACKEND_LAST: + /*shouldn't happen*/ + goto cleanup; + } + + return qemuMonitorJSONAddObject(mon, type, objID, props); + + cleanup: + virJSONValueFree(props); + return -1; +} + int qemuMonitorJSONGetDeviceAliases(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 1da1a00..04f7ca2 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -462,6 +462,11 @@ int qemuMonitorJSONAttachCharDev(qemuMonitorPtr mon, virDomainChrSourceDefPtr chr); int qemuMonitorJSONDetachCharDev(qemuMonitorPtr mon, const char *chrID); +int qemuMonitorJSONAttachRNGDev(qemuMonitorPtr mon, + const char *chrID, + const char *objID, + virDomainRNGDefPtr rng); + int qemuMonitorJSONGetDeviceAliases(qemuMonitorPtr mon, char ***aliases); -- 1.8.3.1

On Sat, Jan 17, 2015 at 13:09:35 +0800, Luyao Huang wrote:
qemuMonitorAttachRNGDev and qemuMonitorDetachRNGDev functions just do some basic check and then call qemuMonitorJSONAttachRNGDev and qemuMonitorDelObject to help us.
Signed-off-by: Luyao Huang <lhuang@redhat.com> --- src/qemu/qemu_monitor.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.h | 7 +++++++ src/qemu/qemu_monitor_json.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 5 +++++ 4 files changed, 98 insertions(+)
...
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index da5c14d..33c3866 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6235,6 +6235,49 @@ qemuMonitorJSONDetachCharDev(qemuMonitorPtr mon, return ret; }
+int +qemuMonitorJSONAttachRNGDev(qemuMonitorPtr mon, + const char *chrID, + const char *objID, + virDomainRNGDefPtr rng) +{ + const char *type = NULL; + virJSONValuePtr props; + + if (!(props = virJSONValueNewObject())) + goto cleanup; + + switch ((virDomainRNGBackend) rng->backend) { + case VIR_DOMAIN_RNG_BACKEND_RANDOM: + type = "rng-random"; + if (virJSONValueObjectCreate(&props, "s:filename", rng->source.file, NULL) < 0) + goto cleanup; + break; + + case VIR_DOMAIN_RNG_BACKEND_EGD: + if (STRNEQ_NULLABLE(strstr(chrID, "rng"), strstr(objID, "rng"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("chardev id '%s' basic alias name is different from '%s'", + chrID, objID)); + goto cleanup; + } + type = "rng-egd"; + if (virJSONValueObjectCreate(&props, "s:chardev", chrID, NULL) < 0) + goto cleanup; + break; + + case VIR_DOMAIN_RNG_BACKEND_LAST: + /*shouldn't happen*/ + goto cleanup; + } + + return qemuMonitorJSONAddObject(mon, type, objID, props); + + cleanup: + virJSONValueFree(props); + return -1; +}
My recent series introduces a function that allows to unify the commandline and monitor object creation so that we don't have code duplication as would be introduced here. As my series is not pushed yet and was posted after your series I'll take over the series and refactor it to the new code to save you hassle of re-doing it again and also refactoring the existing code. Peter

On 01/29/2015 05:48 PM, Peter Krempa wrote:
On Sat, Jan 17, 2015 at 13:09:35 +0800, Luyao Huang wrote:
qemuMonitorAttachRNGDev and qemuMonitorDetachRNGDev functions just do some basic check and then call qemuMonitorJSONAttachRNGDev and qemuMonitorDelObject to help us.
Signed-off-by: Luyao Huang <lhuang@redhat.com> --- src/qemu/qemu_monitor.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.h | 7 +++++++ src/qemu/qemu_monitor_json.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 5 +++++ 4 files changed, 98 insertions(+) ...
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index da5c14d..33c3866 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6235,6 +6235,49 @@ qemuMonitorJSONDetachCharDev(qemuMonitorPtr mon, return ret; }
+int +qemuMonitorJSONAttachRNGDev(qemuMonitorPtr mon, + const char *chrID, + const char *objID, + virDomainRNGDefPtr rng) +{ + const char *type = NULL; + virJSONValuePtr props; + + if (!(props = virJSONValueNewObject())) + goto cleanup; + + switch ((virDomainRNGBackend) rng->backend) { + case VIR_DOMAIN_RNG_BACKEND_RANDOM: + type = "rng-random"; + if (virJSONValueObjectCreate(&props, "s:filename", rng->source.file, NULL) < 0) + goto cleanup; + break; + + case VIR_DOMAIN_RNG_BACKEND_EGD: + if (STRNEQ_NULLABLE(strstr(chrID, "rng"), strstr(objID, "rng"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("chardev id '%s' basic alias name is different from '%s'", + chrID, objID)); + goto cleanup; + } + type = "rng-egd"; + if (virJSONValueObjectCreate(&props, "s:chardev", chrID, NULL) < 0) + goto cleanup; + break; + + case VIR_DOMAIN_RNG_BACKEND_LAST: + /*shouldn't happen*/ + goto cleanup; + } + + return qemuMonitorJSONAddObject(mon, type, objID, props); + + cleanup: + virJSONValueFree(props); + return -1; +} My recent series introduces a function that allows to unify the commandline and monitor object creation so that we don't have code duplication as would be introduced here.
Yes, i notice that and your idea looks so cool to me ;)
As my series is not pushed yet and was posted after your series I'll take over the series and refactor it to the new code to save you hassle of re-doing it again and also refactoring the existing code.
Wow, thanks in advance for your help !
Peter
Luyao

Signed-off-by: Luyao Huang <lhuang@redhat.com> --- src/conf/domain_audit.c | 2 +- src/conf/domain_audit.h | 7 +++++++ src/libvirt_private.syms | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c index fcf9df7..159ebf5 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -242,7 +242,7 @@ virDomainAuditDisk(virDomainObjPtr vm, } -static void +void virDomainAuditRNG(virDomainObjPtr vm, virDomainRNGDefPtr oldDef, virDomainRNGDefPtr newDef, const char *reason, bool success) diff --git a/src/conf/domain_audit.h b/src/conf/domain_audit.h index 3434feb..4c1ef90 100644 --- a/src/conf/domain_audit.h +++ b/src/conf/domain_audit.h @@ -117,5 +117,12 @@ void virDomainAuditChardev(virDomainObjPtr vm, const char *reason, bool success) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4); +void virDomainAuditRNG(virDomainObjPtr vm, + virDomainRNGDefPtr oldDef, + virDomainRNGDefPtr newDef, + const char *reason, + bool success) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4); + #endif /* __VIR_DOMAIN_AUDIT_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index a635652..d3754af 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -123,6 +123,7 @@ virDomainAuditMemory; virDomainAuditNet; virDomainAuditNetDevice; virDomainAuditRedirdev; +virDomainAuditRNG; virDomainAuditSecurityLabel; virDomainAuditStart; virDomainAuditStop; -- 1.8.3.1

We have enough patches for hotplug RNG device, maybe we can implement live hotplug of a RNG device. Signed-off-by: Luyao Huang <lhuang@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 9eed81d..28fbf15 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6976,6 +6976,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: @@ -6987,7 +6994,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 6f62345..c20a4ee 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1510,6 +1510,112 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, 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 audit; + + 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, virDomainObjPtr vm, 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

We have enough patches for hotunplug RNG device, maybe we can implement live hotunplug of a RNG device. Signed-off-by: Luyao Huang <lhuang@redhat.com> --- src/libvirt_private.syms | 1 + src/qemu/qemu_driver.c | 4 +- src/qemu/qemu_hotplug.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_hotplug.h | 4 +- 4 files changed, 118 insertions(+), 3 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d3754af..6c76786 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -378,6 +378,7 @@ virDomainPMSuspendedReasonTypeToString; virDomainRedirdevBusTypeFromString; virDomainRedirdevBusTypeToString; virDomainRNGBackendTypeToString; +virDomainRNGDefFree; virDomainRNGEquals; virDomainRNGFind; virDomainRNGInsert; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 28fbf15..b3d9613 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7057,6 +7057,9 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_CHR: ret = qemuDomainDetachChrDevice(driver, vm, dev->data.chr); break; + case VIR_DOMAIN_DEVICE_RNG: + ret = qemuDomainDetachRNGDevice(driver, vm, dev->data.rng); + break; case VIR_DOMAIN_DEVICE_FS: case VIR_DOMAIN_DEVICE_INPUT: case VIR_DOMAIN_DEVICE_SOUND: @@ -7067,7 +7070,6 @@ qemuDomainDetachDeviceLive(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_REDIRDEV: case VIR_DOMAIN_DEVICE_NONE: diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index c20a4ee..2f90534 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1510,6 +1510,21 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, return ret; } +static virDomainRNGDefPtr +qemuDomainRNGRemove(virDomainDefPtr vmdef, + virDomainRNGDefPtr rng) +{ + virDomainRNGDefPtr ret; + + if (!(ret = virDomainRNGRemove(vmdef, rng))) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("device not present in domain configuration")); + return NULL; + } + + return ret; +} + int qemuDomainAttachRNGDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainRNGDefPtr rng) @@ -2922,6 +2937,52 @@ qemuDomainRemoveChrDevice(virQEMUDriverPtr driver, return ret; } +static int +qemuDomainRemoveRNGDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainRNGDefPtr rng) +{ + virObjectEventPtr event; + char *charAlias = NULL; + char *objAlias = NULL; + qemuDomainObjPrivatePtr priv = vm->privateData; + int ret = -1; + int rc; + + VIR_DEBUG("Removing RNG device %s from domain %p %s", + rng->info.alias, vm, vm->def->name); + + if (virAsprintf(&objAlias, "obj%s", rng->info.alias) < 0) + goto cleanup; + + if (virAsprintf(&charAlias, "char%s", rng->info.alias) < 0) + goto cleanup; + + qemuDomainObjEnterMonitor(driver, vm); + rc = qemuMonitorDetachRNGDev(priv->mon, objAlias); + if (rc == 0 && rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD) + ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias)); + qemuDomainObjExitMonitor(driver, vm); + + virDomainAuditRNG(vm, rng, NULL, "detach", rc == 0); + + if (rc < 0) + goto cleanup; + + event = virDomainEventDeviceRemovedNewFromObj(vm, rng->info.alias); + if (event) + qemuDomainEventQueue(driver, event); + + qemuDomainRNGRemove(vm->def, rng); + qemuDomainReleaseDeviceAddress(vm, &rng->info, NULL); + virDomainRNGDefFree(rng); + ret = 0; + + cleanup: + VIR_FREE(charAlias); + VIR_FREE(objAlias); + return ret; +} void qemuDomainRemoveDevice(virQEMUDriverPtr driver, @@ -2945,6 +3006,9 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver, case VIR_DOMAIN_DEVICE_CHR: qemuDomainRemoveChrDevice(driver, vm, dev->data.chr); break; + case VIR_DOMAIN_DEVICE_RNG: + qemuDomainRemoveRNGDevice(driver, vm, dev->data.rng); + break; case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_LEASE: @@ -2959,7 +3023,6 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver, 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: @@ -3831,3 +3894,50 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver, VIR_FREE(devstr); return ret; } + +int qemuDomainDetachRNGDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainRNGDefPtr rng) +{ + int ret = -1; + qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainDefPtr vmdef = vm->def; + virDomainRNGDefPtr tmpRNG; + int rc; + + if (!(tmpRNG = virDomainRNGFind(vmdef, rng))) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("device not present in domain configuration")); + return ret; + } + + if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("qemu does not support -device")); + return ret; + } + + if (!tmpRNG->info.alias && qemuAssignDeviceRNGAlias(vmdef, tmpRNG, -1) < 0) + return ret; + + sa_assert(tmpRNG->info.alias); + + qemuDomainMarkDeviceForRemoval(vm, &tmpRNG->info); + + qemuDomainObjEnterMonitor(driver, vm); + if (qemuMonitorDelDevice(priv->mon, tmpRNG->info.alias) < 0) { + qemuDomainObjExitMonitor(driver, vm); + goto cleanup; + } + qemuDomainObjExitMonitor(driver, vm); + + rc = qemuDomainWaitForDeviceRemoval(vm); + if (rc == 0 || rc == 1) + ret = qemuDomainRemoveRNGDevice(driver, vm, tmpRNG); + else + ret = 0; + + cleanup: + qemuDomainResetDeviceRemoval(vm); + return ret; +} diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h index d66853b..202c5a2 100644 --- a/src/qemu/qemu_hotplug.h +++ b/src/qemu/qemu_hotplug.h @@ -101,7 +101,9 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver, int qemuDomainAttachRNGDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainRNGDefPtr rng); - +int qemuDomainDetachRNGDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainRNGDefPtr rng); int qemuDomainChrInsert(virDomainDefPtr vmdef, -- 1.8.3.1
participants (2)
-
Luyao Huang
-
Peter Krempa