[libvirt] [PATCH 3/8] parallels: implement functions for domain life cycle management

Daniel P. Berrange berrange at redhat.com
Fri Jul 27 09:32:06 UTC 2012


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 at 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 :|




More information about the libvir-list mailing list