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

Daniel P. Berrange berrange at redhat.com
Thu Feb 4 17:25:30 UTC 2010


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
---
 src/qemu/qemu_driver.c |   66 +++++++++++++++++++++++++++++++++++++++++++++---
 tools/virsh.c          |   37 +++++++++++++++++++++++++++
 2 files changed, 99 insertions(+), 4 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 171670a..09412f9 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -83,9 +83,10 @@ typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate;
 typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr;
 struct _qemuDomainObjPrivate {
     virCond jobCond; /* Use in conjunction with main virDomainObjPtr lock */
-    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
+                                 * 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);
@@ -3826,6 +3830,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,
@@ -8670,6 +8685,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);
+        qemudReportError(dom->conn, dom, NULL, 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 {
+            qemudReportError(dom->conn, NULL, NULL, VIR_ERR_OPERATION_INVALID,
+                             "%s", _("no job is active on the domain"));
+            goto cleanup;
+        }
+    } else {
+        qemudReportError(dom->conn, NULL, NULL, 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,
@@ -8748,7 +8806,7 @@ static virDriver qemuDriver = {
     qemuDomainIsPersistent,
     qemuCPUCompare, /* cpuCompare */
     qemuDomainGetJobInfo, /* domainGetJobInfo */
-    NULL, /* domainFinishJob */
+    qemuDomainAbortJob, /* domainAbortJob */
 };
 
 
diff --git a/tools/virsh.c b/tools/virsh.c
index bb8190c..22503cd 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -1865,6 +1865,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[] = {
@@ -7415,6 +7451,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},
-- 
1.6.6




More information about the libvir-list mailing list