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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 7641fd7..5e787ce 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -84,9 +84,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);
@@ -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},
-- 
1.6.6

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list

[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]