[libvirt] [PATCHv12 1/3] libvirt/qemu - support persistent modification of devices

KAMEZAWA Hiroyuki kamezawa.hiroyu at jp.fujitsu.com
Tue Apr 26 02:06:24 UTC 2011


On Fri, 22 Apr 2011 12:07:56 +0900
KAMEZAWA Hiroyuki <kamezawa.hiroyu at jp.fujitsu.com> wrote:

> 
> Rebased ont the latest git tree, which makes this work easier.
> This series adds support for attach/detach/update disks of domain config.

Ping ? 

Thanks,
-Kame


> ==
> 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>
> 
> Changelog: v11 -> v12
>  - rebased and fixed hunks.
>  - renamed qemudDomain....to qemuDomain...
> 
> (virDomainObjCopyPersistentDef): make a copy of persistent vm definition
> (qemuDomainAttach/Detach/UpdateDeviceConfig) : callbacks. now empty
> (qemuDomainModifyDeviceFlags): add support for MODIFY_CONFIG and MODIFY_CURRENT
> ---
>  src/conf/domain_conf.c   |   18 ++++++
>  src/conf/domain_conf.h   |    3 +
>  src/libvirt_private.syms |    1 +
>  src/qemu/qemu_driver.c   |  147 ++++++++++++++++++++++++++++++++++++----------
>  4 files changed, 137 insertions(+), 32 deletions(-)
> 
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 381e692..6c1098a 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -9509,3 +9509,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 771678e..fd85c8a 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -4073,6 +4073,46 @@ qemuDomainUpdateDeviceLive(virDomainObjPtr vm,
>      return ret;
>  }
>  
> +static int
> +qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED,
> +                             virDomainDeviceDefPtr dev)
> +{
> +    switch (dev->type) {
> +    default:
> +         qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                         _("persistent attach of device is not supported"));
> +         return -1;
> +    }
> +    return 0;
> +}
> +
> +
> +static int
> +qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED,
> +                             virDomainDeviceDefPtr dev)
> +{
> +    switch (dev->type) {
> +    default:
> +        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                        _("persistent detach of device is not supported"));
> +        return -1;
> +    }
> +    return 0;
> +}
> +
> +static int
> +qemuDomainUpdateDeviceConfig(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;
> +}
> +
>  /* Actions for qemuDomainModifyDeviceFlags */
>  enum {
>      QEMU_DEVICE_ATTACH,
> @@ -4088,6 +4128,7 @@ qemuDomainModifyDeviceFlags(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;
> @@ -4097,12 +4138,6 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
>                    (action == QEMU_DEVICE_UPDATE ?
>                     VIR_DOMAIN_DEVICE_MODIFY_FORCE : 0), -1);
>  
> -    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) {
> @@ -4116,12 +4151,27 @@ qemuDomainModifyDeviceFlags(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;
> +    } else {
> +        if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
> +            flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
> +        /* check consistency between flags and the vm state */
> +        if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
> +            qemuReportError(VIR_ERR_OPERATION_INVALID,
> +                            "%s",
> +                            _("cannot do live update a 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;
> +    }
>      dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
>                                    VIR_DOMAIN_XML_INACTIVE);
>      if (dev == NULL)
> @@ -4132,35 +4182,68 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
>                                     &qemuCaps) < 0)
>          goto endjob;
>  
> -    switch (action) {
> -    case QEMU_DEVICE_ATTACH:
> -        ret = qemuDomainAttachDeviceLive(vm, dev, dom, qemuCaps);
> -        break;
> -    case QEMU_DEVICE_DETACH:
> -        ret = qemuDomainDetachDeviceLive(vm, dev, dom, qemuCaps);
> -        break;
> -    case QEMU_DEVICE_UPDATE:
> -        ret = qemuDomainUpdateDeviceLive(vm, dev, dom, qemuCaps, force);
> -        break;
> -    default:
> -        qemuReportError(VIR_ERR_INTERNAL_ERROR,
> -                        _("unknown domain modify action %d"), action);
> -        break;
> -    }
> +    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
> +        /* Make a copy for updated domain. */
> +        vmdef = virDomainObjCopyPersistentDef(driver->caps, vm);
> +        if (!vmdef)
> +            goto endjob;
> +        switch (action) {
> +        case QEMU_DEVICE_ATTACH:
> +            ret = qemuDomainAttachDeviceConfig(vmdef, dev);
> +            break;
> +        case QEMU_DEVICE_DETACH:
> +            ret = qemuDomainDetachDeviceConfig(vmdef, dev);
> +            break;
> +        case QEMU_DEVICE_UPDATE:
> +            ret = qemuDomainUpdateDeviceConfig(vmdef, dev);
> +            break;
> +        default:
> +            qemuReportError(VIR_ERR_INTERNAL_ERROR,
> +                            _("unknown domain modify action %d"), action);
> +            break;
> +        }
> +    } else
> +        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 (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
> -        ret = -1;
> +    if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE)) {
> +        switch (action) {
> +        case QEMU_DEVICE_ATTACH:
> +            ret = qemuDomainAttachDeviceLive(vm, dev, dom, qemuCaps);
> +            break;
> +        case QEMU_DEVICE_DETACH:
> +            ret = qemuDomainDetachDeviceLive(vm, dev, dom, qemuCaps);
> +            break;
> +        case QEMU_DEVICE_UPDATE:
> +            ret = qemuDomainUpdateDeviceLive(vm, dev, dom, qemuCaps, force);
> +            break;
> +        default:
> +            qemuReportError(VIR_ERR_INTERNAL_ERROR,
> +                            _("unknown domain modify action %d"), action);
> +            break;
> +        }
> +        /*
> +         * update domain status forcibly because the domain status may be
> +         * changed even if we attach the device failed. For example, a
> +         * For example, a new controller may be created.
> +         */
> +        if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
> +            ret = -1;
> +    }
> +    /* Finally, if no error until here, we can save config. */
> +    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);
> -- 
> 1.7.4.1
> 
> 
> 




More information about the libvir-list mailing list