On 07/27/2012 01:32 PM, Daniel P. Berrange wrote:
On Thu, Jul 26, 2012 at 10:32:02PM +0400, Dmitry Guryanov wrote:Add functions for create/shutdown/destroy and suspend/resume domain. Signed-off-by: Dmitry Guryanov <dguryanov@xxxxxxxxxxxxx> --- src/parallels/parallels_driver.c | 143 ++++++++++++++++++++++++++++++++++++++ src/parallels/parallels_utils.c | 18 +++++ src/parallels/parallels_utils.h | 2 + 3 files changed, 163 insertions(+), 0 deletions(-) diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c index c716b25..8c20d27 100644 --- a/src/parallels/parallels_driver.c +++ b/src/parallels/parallels_driver.c @@ -128,6 +128,12 @@ parallelsDomObjFreePrivate(void *p) VIR_FREE(p); };+static void+parallelsDomainEventQueue(parallelsConnPtr driver, virDomainEventPtr event) +{ + virDomainEventStateQueue(driver->domainEventState, event); +}I don't see any code which ever deals with dispatching of the domain event state. Is this something you're just preparing now, so that you can wire up events in a future patch ?+ static virCapsPtr parallelsBuildCapabilities(void) { @@ -805,6 +811,138 @@ parallelsDomainGetAutostart(virDomainPtr domain, int *autostart) return ret; }+typedef int (*parallelsChangeStateFunc) (virDomainObjPtr privdom);+#define PARALLELS_UUID(x) (((parallelsDomObjPtr)(x->privateData))->uuid) + +static int +parallelsDomainChangeState(virDomainPtr domain, + virDomainState req_state, const char *req_state_name, + parallelsChangeStateFunc chstate, + virDomainState new_state, int reason, + int event_type, int event_detail) +{ + parallelsConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + virDomainEventPtr event = NULL; + int state; + int ret = -1; + + parallelsDriverLock(privconn); + privdom = virDomainFindByUUID(&privconn->domains, domain->uuid); + parallelsDriverUnlock(privconn); + + if (privdom == NULL) { + parallelsDomNotFoundError(domain); + goto cleanup; + } + + state = virDomainObjGetState(privdom, NULL); + if (state != req_state) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("domain '%s' not %s"), + privdom->def->name, req_state_name); + goto cleanup; + } + + if (chstate(privdom)) + goto cleanup; + + virDomainObjSetState(privdom, new_state, reason); + + event = virDomainEventNewFromObj(privdom, event_type, event_detail); + ret = 0; + + cleanup: + if (privdom) + virDomainObjUnlock(privdom); + + if (event) { + parallelsDriverLock(privconn); + parallelsDomainEventQueue(privconn, event); + parallelsDriverUnlock(privconn); + } + return ret; +}One comment I'd have here is that the event dispatch only works within the context of this single virConnectPtr instance. If you have 2 active connections to libvirt and one starts a guest, the other connection won't see any event. Likewise if someone starts/stops something using the parallels tools directly no events will get queued. Is there any way we can obtain some kind of notification from the core parallels software stack ? Even if it is indirect eg with UserModeLinux we detect stop/start events only, using an inotify watch on the directory containing the UML monitor socket :-)
I thought that events, issued with virDomainEventStateQueue affect all connections ... I think it's better to remove all code, which deals with evens then. It's possible now to listen for event using proprietary SDK, but not with prlctl utility. We can add some mode to prlctl, in which it will print all events to stdout for example, until terminated by signal.
+ +static int parallelsPause(virDomainObjPtr privdom) +{ + return parallelsCmdRun(PRLCTL, "pause", PARALLELS_UUID(privdom), NULL); +} + +static int +parallelsPauseDomain(virDomainPtr domain) +{ + return parallelsDomainChangeState(domain, + VIR_DOMAIN_RUNNING, "running", + parallelsPause, + VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER, + VIR_DOMAIN_EVENT_SUSPENDED, + VIR_DOMAIN_EVENT_SUSPENDED_PAUSED); +} + +static int parallelsResume(virDomainObjPtr privdom) +{ + return parallelsCmdRun(PRLCTL, "resume", PARALLELS_UUID(privdom), NULL); +} + +static int +parallelsResumeDomain(virDomainPtr domain) +{ + return parallelsDomainChangeState(domain, + VIR_DOMAIN_PAUSED, "paused", + parallelsResume, + VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNPAUSED, + VIR_DOMAIN_EVENT_RESUMED, + VIR_DOMAIN_EVENT_RESUMED_UNPAUSED); +} + +static int parallelsStart(virDomainObjPtr privdom) +{ + return parallelsCmdRun(PRLCTL, "start", PARALLELS_UUID(privdom), NULL); +} + +static int +parallelsDomainCreate(virDomainPtr domain) +{ + return parallelsDomainChangeState(domain, + VIR_DOMAIN_SHUTOFF, "stopped", + parallelsStart, + VIR_DOMAIN_RUNNING, VIR_DOMAIN_EVENT_STARTED_BOOTED, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_BOOTED); +} + +static int parallelsKill(virDomainObjPtr privdom) +{ + return parallelsCmdRun(PRLCTL, "stop", PARALLELS_UUID(privdom), "--kill", NULL); +} + +static int +parallelsDestroyDomain(virDomainPtr domain) +{ + return parallelsDomainChangeState(domain, + VIR_DOMAIN_RUNNING, "running", + parallelsKill, + VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_DESTROYED, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_DESTROYED); +} + +static int parallelsStop(virDomainObjPtr privdom) +{ + return parallelsCmdRun(PRLCTL, "stop", PARALLELS_UUID(privdom), NULL); +} + +static int +parallelsShutdownDomain(virDomainPtr domain) +{ + return parallelsDomainChangeState(domain, + VIR_DOMAIN_RUNNING, "running", + parallelsStop, + VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_SHUTDOWN, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); +} + static virDriver parallelsDriver = { .no = VIR_DRV_PARALLELS, .name = "Parallels", @@ -828,6 +966,11 @@ static virDriver parallelsDriver = { .domainGetXMLDesc = parallelsDomainGetXMLDesc, /* 0.10.0 */ .domainIsPersistent = parallelsDomainIsPersistent, /* 0.10.0 */ .domainGetAutostart = parallelsDomainGetAutostart, /* 0.10.0 */ + .domainSuspend = parallelsPauseDomain, /* 0.10.0 */ + .domainResume = parallelsResumeDomain, /* 0.10.0 */ + .domainDestroy = parallelsDestroyDomain, /* 0.10.0 */ + .domainShutdown = parallelsShutdownDomain, /* 0.10.0 */ + .domainCreate = parallelsDomainCreate, /* 0.10.0 */ };I think I'd be happier if the creation /queueing of the virDomainEventPtr parts where commented out, at least until we have dispatch of them wired up, so the queue doesn't build up unbounded Daniel
-- Dmitry Guryanov -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list