[libvirt] [PATCHv10 4/6] libvirt/qemu support persistent device modification
Wen Congyang
wency at cn.fujitsu.com
Wed Apr 20 02:52:41 UTC 2011
At 04/19/2011 03:46 PM, KAMEZAWA Hiroyuki Write:
> This patch adds functions for modify domain's persistent definition.
> To do error recovery in easy way, we use a copy of vmdef and update it.
>
> The whole sequence will be:
>
> make a copy of domain definition.
>
> if (flags & MODIFY_CONFIG)
> update copied domain definition
> if (flags & MODIF_LIVE)
> do hotplug.
> if (no error)
> save copied one to the file and update cached definition.
> else
> discard copied definition.
>
> This patch is mixuture of Eric Blake's work and mine.
> From: Eric Blake <eblake at redhat.com>
> Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu at jp.fujitsu.com>
>
> (virDomainObjCopyPersistentDef): make a copy of persistent vm definition
> (qemudDomainModifyDeviceFlags): add support for MODIFY_CONFIG and MODIFY_CURRENT
> (qemudDomainAttach/Detach/UpdateDeviceConfig) : callbacks. now empty
> ---
> src/conf/domain_conf.c | 18 ++++++
> src/conf/domain_conf.h | 3 +
> src/libvirt_private.syms | 1 +
> src/qemu/qemu_driver.c | 148 ++++++++++++++++++++++++++++++++++++----------
> 4 files changed, 139 insertions(+), 31 deletions(-)
>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 6b733d4..bb8f0a4 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -9510,3 +9510,21 @@ cleanup:
>
> return ret;
> }
> +
> +
> +virDomainDefPtr
> +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom)
> +{
> + char *xml;
> + virDomainDefPtr cur, ret;
> +
> + cur = virDomainObjGetPersistentDef(caps, dom);
> +
> + xml = virDomainDefFormat(cur, VIR_DOMAIN_XML_WRITE_FLAGS);
> + if (!xml)
> + return NULL;
> +
> + ret = virDomainDefParseString(caps, xml, VIR_DOMAIN_XML_READ_FLAGS);
> +
> + return ret;
> +}
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index 6ea30b9..ddf111a 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -1288,6 +1288,9 @@ int virDomainObjSetDefTransient(virCapsPtr caps,
> virDomainDefPtr
> virDomainObjGetPersistentDef(virCapsPtr caps,
> virDomainObjPtr domain);
> +virDomainDefPtr
> +virDomainObjCopyPersistentDef(virCapsPtr caps, virDomainObjPtr dom);
> +
> void virDomainRemoveInactive(virDomainObjListPtr doms,
> virDomainObjPtr dom);
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index ba7739d..f732431 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -287,6 +287,7 @@ virDomainMemballoonModelTypeToString;
> virDomainNetDefFree;
> virDomainNetTypeToString;
> virDomainObjAssignDef;
> +virDomainObjCopyPersistentDef;
> virDomainObjSetDefTransient;
> virDomainObjGetPersistentDef;
> virDomainObjIsDuplicate;
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 2bdf42e..4ac8f7e 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -4059,6 +4059,48 @@ static int qemudDomainUpdateDeviceLive(virDomainObjPtr vm,
> return ret;
> }
>
> +static int
> +qemudDomainAttachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED,
> + virDomainDeviceDefPtr dev)
> +{
> + switch (dev->type) {
> + default:
> + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> + _("persistent update of device is not supported"));
> + return -1;
> + }
> + return 0;
> +}
> +
> +
> +static int
> +qemudDomainDetachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED,
> + virDomainDeviceDefPtr dev)
> +{
> + switch (dev->type) {
> + default:
> + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> + _("persistent update of device is not supported"));
> + return -1;
> + }
> + return 0;
> +}
> +
> +static int
> +qemudDomainUpdateDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED,
> + virDomainDeviceDefPtr dev,
> + bool force ATTRIBUTE_UNUSED)
> +{
> + switch (dev->type) {
> + default:
> + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> + _("persistent update of device is not supported"));
> + return -1;
> + }
> + return 0;
> +
> +}
> +
> enum {
> QEMUD_DEVICE_ATTACH, QEMUD_DEVICE_DETACH, QEMUD_DEVICE_UPDATE,
> };
> @@ -4069,6 +4111,7 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
> struct qemud_driver *driver = dom->conn->privateData;
> virBitmapPtr qemuCaps = NULL;
> virDomainObjPtr vm = NULL;
> + virDomainDefPtr vmdef = NULL;
> virDomainDeviceDefPtr dev = NULL;
> bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0;
> int ret = -1;
> @@ -4077,7 +4120,8 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
> case QEMUD_DEVICE_ATTACH:
> case QEMUD_DEVICE_DETACH:
> virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE |
> - VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1);
> + VIR_DOMAIN_DEVICE_MODIFY_CONFIG |
> + VIR_DOMAIN_DEVICE_MODIFY_CURRENT, -1);
> break;
> case QEMUD_DEVICE_UPDATE:
> virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_CURRENT |
> @@ -4089,12 +4133,6 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
> break;
> }
>
> - if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
> - qemuReportError(VIR_ERR_OPERATION_INVALID,
> - "%s", _("cannot modify the persistent configuration of a domain"));
> - return -1;
> - }
> -
> qemuDriverLock(driver);
> vm = virDomainFindByUUID(&driver->domains, dom->uuid);
> if (!vm) {
> @@ -4108,11 +4146,29 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
> if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
> goto cleanup;
>
> - if (!virDomainObjIsActive(vm)) {
> - qemuReportError(VIR_ERR_OPERATION_INVALID,
> - "%s", _("cannot attach device on inactive domain"));
> - goto endjob;
> + if (virDomainObjIsActive(vm)) {
> + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
> + flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
VIR_DOMAIN_DEVICE_MODIFY_CURRENT is 0. So you should check 'flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT'
instead of 'flags & VIR_DOMAIN_DEVICE_MODIFY_CURRENT'.
> + } else {
> + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
> + flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
Tha same as above.
> + /* check consistency between flags and the vm state */
> + if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
> + qemuReportError(VIR_ERR_OPERATION_INVALID,
> + "%s",
> + _("cannot modify device on inactive domain"));
> + goto endjob;
> + }
> + }
> +
> + if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) {
> + qemuReportError(VIR_ERR_OPERATION_INVALID,
> + "%s", _("cannot modify device on transient domain"));
> + goto endjob;
> }
> + /* At updating config, we update a copy */
> + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)
> + vmdef = virDomainObjCopyPersistentDef(driver->caps, vm);
>
> dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
> VIR_DOMAIN_XML_INACTIVE);
> @@ -4124,33 +4180,63 @@ static int qemudDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
> &qemuCaps) < 0)
> goto endjob;
>
> - switch (action) {
> - case QEMUD_DEVICE_ATTACH:
> - ret = qemudDomainAttachDeviceLive(vm, dev, dom, qemuCaps);
> - break;
> - case QEMUD_DEVICE_DETACH:
> - ret = qemudDomainDetachDeviceLive(vm, dev, dom, qemuCaps);
> - break;
> - case QEMUD_DEVICE_UPDATE:
> - ret = qemudDomainUpdateDeviceLive(vm, dev, dom, qemuCaps, force);
> - break;
> - default:
> - break;
> - }
> + ret = 0;
>
> - /*
> - * update domain status forcibly because the domain status may be changed
> - * even if we attach the device failed. For example, a new controller may
> - * be created.
> - */
> - if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
> - ret = -1;
> + /* Update a copy of persistent definition */
> + if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
> + switch (action) {
> + case QEMUD_DEVICE_ATTACH:
> + ret = qemudDomainAttachDeviceConfig(vmdef, dev);
> + break;
> + case QEMUD_DEVICE_DETACH:
> + ret = qemudDomainDetachDeviceConfig(vmdef, dev);
> + break;
> + case QEMUD_DEVICE_UPDATE:
> + ret = qemudDomainUpdateDeviceConfig(vmdef, dev, force);
> + break;
> + default:
> + break;
> + }
> + }
> + /* Update Live */
> + if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE)) {
> + switch (action) {
> + case QEMUD_DEVICE_ATTACH:
> + ret = qemudDomainAttachDeviceLive(vm, dev, dom, qemuCaps);
> + break;
> + case QEMUD_DEVICE_DETACH:
> + ret = qemudDomainDetachDeviceLive(vm, dev, dom, qemuCaps);
> + break;
> + case QEMUD_DEVICE_UPDATE:
> + ret = qemudDomainUpdateDeviceLive(vm, dev, dom, qemuCaps, force);
> + break;
> + default:
> + break;
> + }
> + /*
> + * update domain status forcibly because the domain status may be
> + * changed even if we attach the device failed. For example, a new
> + * controller may be created.
> + */
> + if (!ret &&
> + virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
> + ret = -1;
> + }
> + /* No error until here, we can save persistent definition */
> + if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
> + ret = virDomainSaveConfig(driver->configDir, vmdef);
> + if (!ret) {
> + virDomainObjAssignDef(vm, vmdef, false);
> + vmdef = NULL;
> + }
> + }
>
> endjob:
> if (qemuDomainObjEndJob(vm) == 0)
> vm = NULL;
>
> cleanup:
> + virDomainDefFree(vmdef);
> virDomainDeviceDefFree(dev);
> if (vm)
> virDomainObjUnlock(vm);
More information about the libvir-list
mailing list