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