From 1a60d6bcd630d45f35d6d00c29822a7920b9c581 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 12 May 2009 15:35:18 +0000 Subject: [PATCH] Improve driver open URI handling --- ChangeLog | 8 +++++ src/vbox/vbox_driver.c | 62 +++++++++++++++++++++++++++++++++++--- src/vbox/vbox_tmpl.c | 68 +++++++++++++++++++++--------------------- 3 files changed, 100 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index 673f36e4c9..d57c391c9f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Tue May 12 16:35:22 BST 2009 Daniel P. Berrange + + Improve driver open URI handling + * src/vbox/vbox_driver.c: Register dummy no-op driver if + the virtualbox libraries are not avialable + * src/vbox/vbox_tmpl.c: Return fatal error if open fails + for a URI we expect to handle + Tue May 12 17:25:52 CEST 2009 Daniel Veillard * src/network_driver.c: enable bridges which are not up, i.e. diff --git a/src/vbox/vbox_driver.c b/src/vbox/vbox_driver.c index 7db437c63d..76632e71a4 100644 --- a/src/vbox/vbox_driver.c +++ b/src/vbox/vbox_driver.c @@ -34,6 +34,7 @@ #include "logging.h" #include "vbox_driver.h" #include "vbox_XPCOMCGlue.h" +#include "virterror_internal.h" #define VIR_FROM_THIS VIR_FROM_VBOX @@ -43,15 +44,25 @@ extern virDriver vbox22Driver; extern virDriver vbox25Driver; #endif +static virDriver vboxDriverDummy; + +#define VIR_FROM_THIS VIR_FROM_VBOX + +#define vboxError(conn, code, fmt...) \ + virReportErrorHelper(conn, VIR_FROM_VBOX, code, __FILE__, \ + __FUNCTION__, __LINE__, fmt) int vboxRegister(void) { virDriverPtr driver; uint32_t uVersion; - /* vboxRegister() shouldn't fail as that will render libvirt unless. - * So, we use the v2.2 driver as a fallback/dummy. + /* + * If the glue layer does not initialize, we register a driver + * with a dummy open method, so we can report nicer errors + * if the user requests a vbox:// URI which we know will + * never work */ - driver = &vbox22Driver; + driver = &vboxDriverDummy; /* Init the glue and get the API version. */ if (VBoxCGlueInit() == 0) { @@ -79,7 +90,7 @@ int vboxRegister(void) { } } else { - DEBUG0("VBoxCGlueInit failed"); + DEBUG0("VBoxCGlueInit failed, using dummy driver"); } if (virRegisterDriver(driver) < 0) @@ -87,3 +98,46 @@ int vboxRegister(void) { return 0; } + +static virDrvOpenStatus vboxOpenDummy(virConnectPtr conn, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED) { + uid_t uid = getuid(); + + if (conn->uri == NULL || + conn->uri->scheme == NULL || + STRNEQ (conn->uri->scheme, "vbox") || + conn->uri->server != NULL) + return VIR_DRV_OPEN_DECLINED; + + if (conn->uri->path == NULL || STREQ(conn->uri->path, "")) { + vboxError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("no VirtualBox driver path specified (try vbox:///session)")); + return VIR_DRV_OPEN_ERROR; + } + + if (uid != 0) { + if (STRNEQ (conn->uri->path, "/session")) { + vboxError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown driver path '%s' specified (try vbox:///session)"), conn->uri->path); + return VIR_DRV_OPEN_ERROR; + } + } else { /* root */ + if (STRNEQ (conn->uri->path, "/system") && + STRNEQ (conn->uri->path, "/session")) { + vboxError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown driver path '%s' specified (try vbox:///system)"), conn->uri->path); + return VIR_DRV_OPEN_ERROR; + } + } + + vboxError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("unable to initialize VirtualBox driver API")); + return VIR_DRV_OPEN_ERROR; +} + +static virDriver vboxDriverDummy = { + VIR_DRV_VBOX, + "VBOX", + .open = vboxOpenDummy, +}; diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index a27eada67f..a4061ce709 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -216,16 +216,6 @@ no_memory: } static int vboxInitialize(virConnectPtr conn, vboxGlobalData *data) { - - if (VBoxCGlueInit() != 0) { - vboxError(conn, VIR_ERR_INTERNAL_ERROR, "Can't Initialize VirtualBox, VBoxCGlueInit failed."); - goto cleanup; - } - - /* This is for when glue init failed and we're serving as dummy driver. */ - if (g_pfnGetFunctions == NULL) - goto cleanup; - /* Get the API table for out version, g_pVBoxFuncs is for the oldest version of the API that we support so we cannot use that. */ data->pFuncs = g_pfnGetFunctions(VBOX_XPCOMC_VERSION); @@ -291,13 +281,13 @@ static int vboxExtractVersion(virConnectPtr conn, vboxGlobalData *data) { } static void vboxUninitialize(vboxGlobalData *data) { + if (!data) + return; + if (data->pFuncs) data->pFuncs->pfnComUninitialize(); VBoxCGlueTerm(); - if (!data) - return; - virDomainObjListFree(&data->domains); virCapabilitiesFree(data->caps); VIR_FREE(data); @@ -306,52 +296,62 @@ static void vboxUninitialize(vboxGlobalData *data) { static virDrvOpenStatus vboxOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED) { - vboxGlobalData *data; + vboxGlobalData *data = NULL; uid_t uid = getuid(); if (conn->uri == NULL) { conn->uri = xmlParseURI(uid ? "vbox:///session" : "vbox:///system"); if (conn->uri == NULL) { + virReportOOMError(conn); return VIR_DRV_OPEN_ERROR; } - } else if (conn->uri->scheme == NULL || - conn->uri->path == NULL ) { - return VIR_DRV_OPEN_DECLINED; } - if (STRNEQ (conn->uri->scheme, "vbox")) + if (conn->uri->scheme == NULL || + STRNEQ (conn->uri->scheme, "vbox")) return VIR_DRV_OPEN_DECLINED; + /* Leave for remote driver */ + if (conn->uri->server != NULL) + return VIR_DRV_OPEN_DECLINED; + + if (conn->uri->path == NULL || STREQ(conn->uri->path, "")) { + vboxError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("no VirtualBox driver path specified (try vbox:///session)")); + return VIR_DRV_OPEN_ERROR; + } + if (uid != 0) { - if (STRNEQ (conn->uri->path, "/session")) - return VIR_DRV_OPEN_DECLINED; + if (STRNEQ (conn->uri->path, "/session")) { + vboxError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown driver path '%s' specified (try vbox:///session)"), conn->uri->path); + return VIR_DRV_OPEN_ERROR; + } } else { /* root */ if (STRNEQ (conn->uri->path, "/system") && - STRNEQ (conn->uri->path, "/session")) - return VIR_DRV_OPEN_DECLINED; + STRNEQ (conn->uri->path, "/session")) { + vboxError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown driver path '%s' specified (try vbox:///system)"), conn->uri->path); + return VIR_DRV_OPEN_ERROR; + } } if (VIR_ALLOC(data) < 0) { virReportOOMError(conn); - goto cleanup; + return VIR_DRV_OPEN_ERROR; } - if (!(data->caps = vboxCapsInit())) - goto cleanup; - - if (vboxInitialize(conn, data) < 0) - goto cleanup; - - if (vboxExtractVersion(conn, data) < 0) - goto cleanup; + if (!(data->caps = vboxCapsInit()) || + vboxInitialize(conn, data) < 0 || + vboxExtractVersion(conn, data) < 0) { + vboxUninitialize(data); + return VIR_DRV_OPEN_ERROR; + } conn->privateData = data; DEBUG0("in vboxOpen"); return VIR_DRV_OPEN_SUCCESS; -cleanup: - vboxUninitialize(data); - return VIR_DRV_OPEN_DECLINED; } static int vboxClose(virConnectPtr conn) {