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(a)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 :-)
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