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@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list