
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@parallels.com> --- 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 :-)
+ +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 -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|