[libvirt] [PATCH 8/9] Support job cancellation in QEMU driver

Daniel Veillard veillard at redhat.com
Fri Feb 26 18:04:27 UTC 2010


On Thu, Feb 18, 2010 at 03:56:14PM +0000, Daniel P. Berrange wrote:
> This supports cancellation of jobs for the QEMU driver against
> the virDomainMigrate, virDomainSave and virDomainCoreDump APIs.
> It is not yet supported for the virDomainRestore API, although
> it is desirable.
> 
> * src/qemu/qemu_driver.c: Issue 'migrate_cancel' command if
>   virDomainAbortJob is issued during a migration operation
> * tools/virsh.c: Add a domjobabort command
[...]
> -    int jobActive; /* Non-zero if a job is active. Only 1 job is allowed at any time
> -                    * A job includes *all* monitor commands, even those just querying
> -                    * information, not merely actions */
> +    unsigned int jobActive : 1; /* Non-zero if a job is active. Only 1 job is allowed at any time

  ah a cleanup too

> +                                 * A job includes *all* monitor commands, even those just querying
> +                                 * information, not merely actions */
> +    unsigned int jobCancel : 1; /* Non-zero if a cancel request from client has arrived */
>      virDomainJobInfo jobInfo;
>      unsigned long long jobStart;
>  
> @@ -331,6 +332,7 @@ static int qemuDomainObjBeginJob(virDomainObjPtr obj)
>          }
>      }
>      priv->jobActive = 1;
> +    priv->jobCancel = 0;
>      priv->jobStart = (now.tv_sec * 1000ull) + (now.tv_usec / 1000);
>      memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
>  
> @@ -377,6 +379,7 @@ static int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver,
>          }
>      }
>      priv->jobActive = 1;
> +    priv->jobCancel = 0;
>      priv->jobStart = (now.tv_sec * 1000ull) + (now.tv_usec / 1000);
>      memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
>  
> @@ -401,6 +404,7 @@ static int ATTRIBUTE_RETURN_CHECK qemuDomainObjEndJob(virDomainObjPtr obj)
>      qemuDomainObjPrivatePtr priv = obj->privateData;
>  
>      priv->jobActive = 0;
> +    priv->jobCancel = 0;
>      priv->jobStart = 0;
>      memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
>      virCondSignal(&priv->jobCond);
> @@ -3945,6 +3949,17 @@ qemuDomainWaitForMigrationComplete(struct qemud_driver *driver, virDomainObjPtr
>          struct timeval now;
>          int rc;
>  
> +        if (priv->jobCancel) {
> +            priv->jobCancel = 0;
> +            VIR_DEBUG0("Cancelling migration at client request");
> +            qemuDomainObjEnterMonitorWithDriver(driver, vm);
> +            rc = qemuMonitorMigrateCancel(priv->mon);
> +            qemuDomainObjExitMonitorWithDriver(driver, vm);
> +            if (rc < 0) {
> +                VIR_WARN0("Unable to cancel migration");
> +            }
> +        }
> +
>          qemuDomainObjEnterMonitorWithDriver(driver, vm);
>          rc = qemuMonitorGetMigrationStatus(priv->mon,
>                                             &status,
> @@ -8811,6 +8826,49 @@ cleanup:
>  }
>  
>  
> +static int qemuDomainAbortJob(virDomainPtr dom) {
> +    struct qemud_driver *driver = dom->conn->privateData;
> +    virDomainObjPtr vm;
> +    int ret = -1;
> +    qemuDomainObjPrivatePtr priv;
> +
> +    qemuDriverLock(driver);
> +    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
> +    qemuDriverUnlock(driver);
> +    if (!vm) {
> +        char uuidstr[VIR_UUID_STRING_BUFLEN];
> +        virUUIDFormat(dom->uuid, uuidstr);
> +        qemuReportError(VIR_ERR_NO_DOMAIN,
> +                        _("no domain with matching uuid '%s'"), uuidstr);
> +        goto cleanup;
> +    }
> +
> +    priv = vm->privateData;
> +
> +    if (virDomainObjIsActive(vm)) {
> +        if (priv->jobActive) {
> +            VIR_DEBUG("Requesting cancellation of job on vm %s", vm->def->name);
> +            priv->jobCancel = 1;
> +        } else {
> +            qemuReportError(VIR_ERR_OPERATION_INVALID,
> +                            "%s", _("no job is active on the domain"));
> +            goto cleanup;
> +        }
> +    } else {
> +        qemuReportError(VIR_ERR_OPERATION_INVALID,
> +                        "%s", _("domain is not running"));
> +        goto cleanup;
> +    }
> +
> +    ret = 0;
> +
> +cleanup:
> +    if (vm)
> +        virDomainObjUnlock(vm);
> +    return ret;
> +}
> +
> +
>  static virDriver qemuDriver = {
>      VIR_DRV_QEMU,
>      "QEMU",
> @@ -8891,7 +8949,7 @@ static virDriver qemuDriver = {
>      qemuCPUCompare, /* cpuCompare */
>      qemuCPUBaseline, /* cpuBaseline */
>      qemuDomainGetJobInfo, /* domainGetJobInfo */
> -    NULL, /* domainFinishJob */
> +    qemuDomainAbortJob, /* domainAbortJob */
>  };
>  
>  
> diff --git a/tools/virsh.c b/tools/virsh.c
> index 0bf03df..cea92fd 100644
> --- a/tools/virsh.c
> +++ b/tools/virsh.c
> @@ -1899,6 +1899,42 @@ cleanup:
>  }
>  
>  /*
> + * "domjobabort" command
> + */
> +static const vshCmdInfo info_domjobabort[] = {
> +    {"help", gettext_noop("abort active domain job")},
> +    {"desc", gettext_noop("Aborts the currently running domain job")},
> +    {NULL, NULL}
> +};
> +
> +static const vshCmdOptDef opts_domjobabort[] = {
> +    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
> +    {NULL, 0, 0, NULL}
> +};
> +
> +static int
> +cmdDomjobabort(vshControl *ctl, const vshCmd *cmd)
> +{
> +    virDomainPtr dom;
> +    int ret = TRUE;
> +    unsigned int id;
> +    char *str, uuid[VIR_UUID_STRING_BUFLEN];
> +
> +    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
> +        return FALSE;
> +
> +    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
> +        return FALSE;
> +
> +    if (virDomainAbortJob(dom) < 0)
> +        ret = FALSE;
> +
> +cleanup:
> +    virDomainFree(dom);
> +    return ret;
> +}
> +
> +/*
>   * "freecell" command
>   */
>  static const vshCmdInfo info_freecell[] = {
> @@ -7613,6 +7649,7 @@ static const vshCmdDef commands[] = {
>      {"domuuid", cmdDomuuid, opts_domuuid, info_domuuid},
>      {"dominfo", cmdDominfo, opts_dominfo, info_dominfo},
>      {"domjobinfo", cmdDomjobinfo, opts_domjobinfo, info_domjobinfo},
> +    {"domjobabort", cmdDomjobabort, opts_domjobabort, info_domjobabort},
>      {"domname", cmdDomname, opts_domname, info_domname},
>      {"domstate", cmdDomstate, opts_domstate, info_domstate},
>      {"domblkstat", cmdDomblkstat, opts_domblkstat, info_domblkstat},

 ACK, but virsh.pod need to be extended with the new entry points,

Daniel

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list