[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] [Xen-devel] [PATCH] libxenlight driver



On Fri, 18 Feb 2011, Jim Fehlig wrote:
> +static int
> +libxlMakeDiskList(virDomainDefPtr def, libxl_domain_config *d_config)
> +{
> +    virDomainDiskDefPtr *l_disks = def->disks;
> +    int ndisks = def->ndisks;
> +    libxl_device_disk *x_disks;
> +    int i;
> +
> +    if (VIR_ALLOC_N(x_disks, ndisks) < 0) {
> +        virReportOOMError();
> +        return -1;
> +    }
> +
> +    for (i = 0; i < ndisks; i++) {
> +        if (l_disks[i]->src &&
> +             (x_disks[i].physpath = strdup(l_disks[i]->src)) == NULL) {
> +            virReportOOMError();
> +            goto error;
> +        }
> +
> +        if (l_disks[i]->dst &&
> +            (x_disks[i].virtpath = strdup(l_disks[i]->dst)) == NULL) {
> +            virReportOOMError();
> +            goto error;
> +        }
> +
> +        if (l_disks[i]->driverName) {
> +            if (STREQ(l_disks[i]->driverName, "tap") ||
> +                STREQ(l_disks[i]->driverName, "tap2")) {
> +                if (l_disks[i]->driverType &&
> +                    STREQ(l_disks[i]->driverType, "qcow2"))
> +                    x_disks[i].phystype = PHYSTYPE_QCOW2;
> +                else if (l_disks[i]->driverType &&
> +                         STREQ(l_disks[i]->driverType, "aio"))
> +                    x_disks[i].phystype = PHYSTYPE_AIO;
> +                else if (l_disks[i]->driverType &&
> +                         STREQ(l_disks[i]->driverType, "vhd"))
> +                    x_disks[i].phystype = PHYSTYPE_VHD;
> +            } else if (STREQ(l_disks[i]->driverName, "file")) {
> +                x_disks[i].phystype = PHYSTYPE_FILE;
> +            } else if (STREQ(l_disks[i]->driverName, "phy")) {
> +                x_disks[i].phystype = PHYSTYPE_PHY;
> +            }
> +        } else {
> +            /* Default to file?? */
> +            x_disks[i].phystype = PHYSTYPE_FILE;
> +        }

few days ago the patch that removes phystype and introduces backend and
format has been applied, so this code needs an update

...

> diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
> new file mode 100644
> index 0000000..d581e7b
> --- /dev/null
> +++ b/src/libxl/libxl_driver.c
> @@ -0,0 +1,1280 @@
> +/*---------------------------------------------------------------------------*/
> +/*  Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
> + *  Copyright (C) 2011 Univention GmbH.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
> + */
> +/*---------------------------------------------------------------------------*/
> +
> +#include <config.h>
> +
> +#include <sys/utsname.h>
> +#include <libxl.h>
> +
> +#include "internal.h"
> +#include "logging.h"
> +#include "virterror_internal.h"
> +#include "datatypes.h"
> +#include "files.h"
> +#include "memory.h"
> +#include "event.h"
> +#include "uuid.h"
> +#include "libxl_driver.h"
> +#include "libxl_conf.h"
> +
> +
> +#define VIR_FROM_THIS VIR_FROM_LIBXL
> +
> +#define LIBXL_DOM_REQ_POWEROFF 0
> +#define LIBXL_DOM_REQ_REBOOT   1
> +#define LIBXL_DOM_REQ_SUSPEND  2
> +#define LIBXL_DOM_REQ_CRASH    3
> +#define LIBXL_DOM_REQ_HALT     4
> +
> +static libxlDriverPrivatePtr libxl_driver = NULL;
> +
> +
> +/* Function declarations */
> +static int
> +libxlVmStart(virDomainObjPtr vm, bool start_paused);
> +
> +
> +/* Function definitions */
> +static void
> +libxlDriverLock(libxlDriverPrivatePtr driver)
> +{
> +    virMutexLock(&driver->lock);
> +}
> +
> +static void
> +libxlDriverUnlock(libxlDriverPrivatePtr driver)
> +{
> +    virMutexUnlock(&driver->lock);
> +}
> +
> +static void *libxlDomainObjPrivateAlloc(void)
> +{
> +    libxlDomainObjPrivatePtr priv;
> +
> +    if (VIR_ALLOC(priv) < 0)
> +        return NULL;
> +
> +    libxl_ctx_init(&priv->ctx, LIBXL_VERSION, libxl_driver->logger);
> +    priv->waiterFD = -1;
> +    priv->eventHdl = -1;
> +
> +    return priv;
> +}
> +
> +static void libxlDomainObjPrivateFree(void *data)
> +{
> +    libxlDomainObjPrivatePtr priv = data;
> +
> +    if (priv->dWaiter) {
> +        libxl_free_waiter(priv->dWaiter);
> +        VIR_FREE(priv->dWaiter);
> +    }
> +    libxl_ctx_free(&priv->ctx);
> +    VIR_FREE(priv);
> +}
> +
> +static void libxlEventHandler(int watch,
> +                              int fd,
> +                              int events,
> +                              void *data)
> +{
> +    libxlDriverPrivatePtr driver = libxl_driver;
> +    virDomainObjPtr vm = data;
> +    libxlDomainObjPrivatePtr priv;
> +    libxl_event event;
> +    libxl_dominfo info;
> +
> +    libxlDriverLock(driver);
> +    virDomainObjLock(vm);
> +    libxlDriverUnlock(driver);
> +
> +    priv = vm->privateData;
> +
> +    memset(&event, 0, sizeof(event));
> +    memset(&info, 0, sizeof(info));
> +
> +    if (priv->waiterFD != fd || priv->eventHdl != watch) {
> +        virEventRemoveHandle(watch);
> +        goto cleanup;
> +    }
> +
> +    if (!(events & VIR_EVENT_HANDLE_READABLE)) {
> +        goto cleanup;
> +    }
> +
> +    if (libxl_get_event(&priv->ctx, &event)) {
> +        goto cleanup;
> +    }
> +
> +    if (event.type == LIBXL_EVENT_DOMAIN_DEATH) {
> +        /* libxl_event_get_domain_death_info returns 1 if death
> +         * event was for this domid */
> +        if (libxl_event_get_domain_death_info(&priv->ctx,
> +                                              vm->def->id,
> +                                              &event,
> +                                              &info) != 1) {
> +            goto cleanup;
> +        }
> +
> +        virEventRemoveHandle(watch);
> +        if (info.shutdown_reason == SHUTDOWN_poweroff) {
> +            libxl_domain_destroy(&priv->ctx, vm->def->id, 0);
> +            if (vm->persistent) {
> +                vm->def->id = -1;
> +                vm->state = VIR_DOMAIN_SHUTOFF;
> +            } else {
> +                libxl_free_waiter(priv->dWaiter);
> +                VIR_FREE(priv->dWaiter);
> +                virDomainRemoveInactive(&driver->domains, vm);
> +                vm = NULL;
> +            }
> +        } else if (info.shutdown_reason == SHUTDOWN_reboot) {
> +            libxl_domain_destroy(&priv->ctx, vm->def->id, 0);
> +            vm->def->id = -1;
> +            vm->state = VIR_DOMAIN_SHUTOFF;
> +            sleep(1);
> +            libxlVmStart(vm, 0);

we need to handle at least SHUTDOWN_suspend and SHUTDOWN_crash too

> +        } else {
> +            VIR_INFO("Unhandled shutdown_reason %d", info.shutdown_reason);
> +        }
> +    }

we should call libxl_free_event before returning, otherwise we leak two
strings

> +
> +cleanup:
> +    if (vm)
> +        virDomainObjUnlock(vm);
> +}
> +
> +static int
> +libxlCreateDomEvents(virDomainObjPtr vm)
> +{
> +    libxlDomainObjPrivatePtr priv = vm->privateData;
> +    int fd;
> +
> +    /* Do we already have a waiter for this domain? */
> +    if (priv->dWaiter == NULL) {
> +        if (VIR_ALLOC(priv->dWaiter) < 0) {
> +            virReportOOMError();
> +            return -1;
> +        }
> +
> +        if (libxl_wait_for_domain_death(&priv->ctx, vm->def->id, priv->dWaiter)) {
> +            goto error;
> +        }
> +    }
> +
> +    libxl_get_wait_fd(&priv->ctx, &fd);
> +    if (fd < 0) {
> +        goto error;
> +    }
> +
> +    priv->waiterFD = fd;
> +    if ((priv->eventHdl = virEventAddHandle(
> +             fd,
> +             VIR_EVENT_HANDLE_READABLE | VIR_EVENT_HANDLE_ERROR,
> +             libxlEventHandler,
> +             vm, NULL)) < 0) {
> +        goto error;
> +    }
> +
> +    return 0;
> +
> +error:
> +    libxl_free_waiter(priv->dWaiter);
> +    VIR_FREE(priv->dWaiter);
> +    return -1;
> +}
> +
> +static int
> +libxlVmStart(virDomainObjPtr vm, bool start_paused)
> +{
> +    libxl_domain_config d_config;
> +    virDomainDefPtr def = vm->def;
> +    int ret;
> +    uint32_t domid = 0;
> +    char *dom_xml = NULL;
> +    pid_t child_console_pid = -1;
> +    libxlDomainObjPrivatePtr priv = vm->privateData;
> +
> +    memset(&d_config, 0, sizeof(d_config));
> +
> +    if (libxlBuildDomainConfig(def, &d_config) < 0 )
> +        return -1;
> +
> +    //TODO: Balloon dom0 ??
> +    //ret = freemem(&d_config->b_info, &d_config->dm_info);
> +
> +    ret = libxl_domain_create_new(&priv->ctx, &d_config,
> +                                  NULL, &child_console_pid, &domid);
> +    if (ret) {
> +        libxlError(VIR_ERR_INTERNAL_ERROR,
> +                   _("libxenlight failed to create new domain '%s'"),
> +                   d_config.c_info.name);
> +        goto error;
> +    }
> +
> +    def->id = domid;
> +    if ((dom_xml = virDomainDefFormat(def, 0)) == NULL)
> +        goto error;
> +
> +    if(libxl_userdata_store(&priv->ctx, domid, "libvirt-xml",
> +                            (uint8_t *)dom_xml, strlen(dom_xml) + 1)) {
> +        libxlError(VIR_ERR_INTERNAL_ERROR,
> +                   _("libxenlight failed to store userdata"));
> +        goto error;
> +    }
> +
> +    if (libxlCreateDomEvents(vm) < 0)
> +        goto error;
> +
> +    if (!start_paused) {
> +        libxl_domain_unpause(&priv->ctx, domid);
> +        vm->state = VIR_DOMAIN_RUNNING;
> +    } else {
> +        vm->state = VIR_DOMAIN_PAUSED;
> +    }
> +
> +    libxl_domain_config_destroy(&d_config);
> +    VIR_FREE(dom_xml);
> +    return 0;
> +
> +error:
> +    if (domid > 0) {
> +        libxl_domain_destroy(&priv->ctx, domid, 0);
> +        def->id = -1;
> +    }
> +    libxl_domain_config_destroy(&d_config);
> +    VIR_FREE(dom_xml);
> +    return -1;
> +}
> +
> +static int
> +libxlShutdown(void)
> +{
> +    if (!libxl_driver)
> +        return -1;
> +
> +    libxlDriverLock(libxl_driver);
> +    virCapabilitiesFree(libxl_driver->caps);
> +    libxl_ctx_free(&libxl_driver->ctx);
> +    xtl_logger_destroy(libxl_driver->logger);
> +    if (libxl_driver->logger_file)
> +        VIR_FORCE_FCLOSE(libxl_driver->logger_file);
> +
> +    virDomainObjListDeinit(&libxl_driver->domains);
> +
> +    VIR_FREE(libxl_driver->configDir);
> +    VIR_FREE(libxl_driver->autostartDir);
> +    VIR_FREE(libxl_driver->logDir);
> +    VIR_FREE(libxl_driver->stateDir);
> +    VIR_FREE(libxl_driver->libDir);
> +    VIR_FREE(libxl_driver->saveDir);
> +
> +    libxlDriverUnlock(libxl_driver);
> +    virMutexDestroy(&libxl_driver->lock);
> +    VIR_FREE(libxl_driver);
> +
> +    return 0;
> +}
> +
> +static int
> +libxlStartup(int privileged) {
> +    const libxl_version_info *ver_info;
> +    char *log_file = NULL;
> +
> +    /* Check that the user is root, silently disable if not */
> +    if (!privileged) {
> +        VIR_INFO0("Not running privileged, disabling libxenlight driver");
> +        return 0;
> +    }
> +
> +    if (VIR_ALLOC(libxl_driver) < 0)
> +        return -1;
> +
> +    if (virMutexInit(&libxl_driver->lock) < 0) {
> +        VIR_ERROR0(_("cannot initialize mutex"));
> +        VIR_FREE(libxl_driver);
> +        return -1;
> +    }
> +    libxlDriverLock(libxl_driver);
> +
> +    if (virDomainObjListInit(&libxl_driver->domains) < 0)
> +        goto out_of_memory;
> +
> +    if (virAsprintf(&libxl_driver->configDir,
> +                    "%s", LIBXL_CONFIG_DIR) == -1)
> +        goto out_of_memory;
> +
> +    if (virAsprintf(&libxl_driver->autostartDir,
> +                    "%s", LIBXL_AUTOSTART_DIR) == -1)
> +        goto out_of_memory;
> +
> +    if (virAsprintf(&libxl_driver->logDir,
> +                    "%s", LIBXL_LOG_DIR) == -1)
> +        goto out_of_memory;
> +
> +    if (virAsprintf(&libxl_driver->stateDir,
> +                    "%s", LIBXL_STATE_DIR) == -1)
> +        goto out_of_memory;
> +
> +    if (virAsprintf(&libxl_driver->libDir,
> +                    "%s", LIBXL_LIB_DIR) == -1)
> +        goto out_of_memory;
> +
> +    if (virAsprintf(&libxl_driver->saveDir,
> +                    "%s", LIBXL_SAVE_DIR) == -1)
> +        goto out_of_memory;
> +
> +    if (virFileMakePath(libxl_driver->logDir) != 0) {
> +        char ebuf[1024];
> +        VIR_ERROR(_("Failed to create log dir '%s': %s"),
> +                  libxl_driver->logDir, virStrerror(errno, ebuf, sizeof ebuf));
> +        goto error;
> +    }
> +    if (virFileMakePath(libxl_driver->stateDir) != 0) {
> +        char ebuf[1024];
> +        VIR_ERROR(_("Failed to create state dir '%s': %s"),
> +                  libxl_driver->stateDir, virStrerror(errno, ebuf, sizeof ebuf));
> +        goto error;
> +    }
> +    if (virFileMakePath(libxl_driver->libDir) != 0) {
> +        char ebuf[1024];
> +        VIR_ERROR(_("Failed to create lib dir '%s': %s"),
> +                  libxl_driver->libDir, virStrerror(errno, ebuf, sizeof ebuf));
> +        goto error;
> +    }
> +    if (virFileMakePath(libxl_driver->saveDir) != 0) {
> +        char ebuf[1024];
> +        VIR_ERROR(_("Failed to create save dir '%s': %s"),
> +                  libxl_driver->saveDir, virStrerror(errno, ebuf, sizeof ebuf));
> +        goto error;
> +    }
> +
> +    if (virAsprintf(&log_file, "%s/libxl.log", libxl_driver->logDir) < 0) {
> +        goto out_of_memory;
> +    }
> +
> +    if ((libxl_driver->logger_file = fopen(log_file, "a")) == NULL)  {
> +        virReportSystemError(errno,
> +                             _("failed to create logfile %s"),
> +                             log_file);
> +        goto error;
> +    }
> +    VIR_FREE(log_file);
> +
> +    libxl_driver->logger =
> +            (xentoollog_logger*)xtl_createlogger_stdiostream(libxl_driver->logger_file, XTL_DEBUG,  0);
> +    if (!libxl_driver->logger) {
> +        VIR_ERROR0(_("cannot create logger for libxenlight"));
> +        goto error;
> +    }
> +
> +    if (libxl_ctx_init(&libxl_driver->ctx,
> +                       LIBXL_VERSION,
> +                       libxl_driver->logger)) {
> +        VIR_ERROR0(_("cannot initialize libxenlight context"));
> +        goto error;
> +    }
> +
> +    if ((ver_info = libxl_get_version_info(&libxl_driver->ctx)) == NULL) {
> +        VIR_ERROR0(_("cannot version information from libxenlight"));
> +        goto error;
> +    }
> +    libxl_driver->version = (ver_info->xen_version_major * 1000000) +
> +            (ver_info->xen_version_minor * 1000);
> +
> +    if ((libxl_driver->caps =
> +         libxlMakeCapabilities(&libxl_driver->ctx)) == NULL) {
> +        VIR_ERROR0(_("cannot create capabilities for libxenlight"));
> +        goto error;
> +    }
> +
> +    libxl_driver->caps->privateDataAllocFunc = libxlDomainObjPrivateAlloc;
> +    libxl_driver->caps->privateDataFreeFunc = libxlDomainObjPrivateFree;

If I understand correctly privateDataAllocFunc is called at each domain creation


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]