提交 7f0f415b 编写于 作者: T Taowei 提交者: Michal Privoznik

vbox: Begin to rewrite, vboxConnectOpen

Introduce vbox_uniformed_api to deal with version conflicts. Use
vbox_install_api to register the currect vboxUniformedAPI with
vbox version.

vboxConnectOpen has been rewritten.
上级 78096150
......@@ -217,6 +217,7 @@ src/util/virxml.c
src/vbox/vbox_MSCOMGlue.c
src/vbox/vbox_XPCOMCGlue.c
src/vbox/vbox_driver.c
src/vbox/vbox_common.c
src/vbox/vbox_snapshot_conf.c
src/vbox/vbox_tmpl.c
src/vmware/vmware_conf.c
......
......@@ -675,7 +675,10 @@ VBOX_DRIVER_SOURCES = \
vbox/vbox_V4_2.c vbox/vbox_CAPI_v4_2.h \
vbox/vbox_V4_2_20.c vbox/vbox_CAPI_v4_2_20.h \
vbox/vbox_V4_3.c vbox/vbox_CAPI_v4_3.h \
vbox/vbox_V4_3_4.c vbox/vbox_CAPI_v4_3_4.h
vbox/vbox_V4_3_4.c vbox/vbox_CAPI_v4_3_4.h \
vbox/vbox_common.c vbox/vbox_common.h \
vbox/vbox_uniformed_api.h \
vbox/vbox_install_api.h
VBOX_DRIVER_EXTRA_DIST = \
vbox/vbox_tmpl.c vbox/README \
......
/*
* Copyright 2014, Taowei Luo (uaedante@gmail.com)
*
* 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, see
* <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <unistd.h>
#include "internal.h"
#include "datatypes.h"
#include "domain_conf.h"
#include "domain_event.h"
#include "virlog.h"
#include "viralloc.h"
#include "nodeinfo.h"
#include "vbox_common.h"
#include "vbox_uniformed_api.h"
#include "vbox_install_api.h"
/* Common codes for vbox driver. With the definitions in vbox_common.h,
* it treats vbox structs as a void*. Though vboxUniformedAPI
* it call vbox functions. This file is a high level implement about
* the vbox driver.
*/
#define VIR_FROM_THIS VIR_FROM_VBOX
VIR_LOG_INIT("vbox.vbox_common");
#define VBOX_UTF16_FREE(arg) \
do { \
if (arg) { \
gVBoxAPI.UPFN.Utf16Free(data->pFuncs, arg); \
(arg) = NULL; \
} \
} while (0)
#define VBOX_UTF8_FREE(arg) \
do { \
if (arg) { \
gVBoxAPI.UPFN.Utf8Free(data->pFuncs, arg); \
(arg) = NULL; \
} \
} while (0)
#define VBOX_COM_UNALLOC_MEM(arg) \
do { \
if (arg) { \
gVBoxAPI.UPFN.ComUnallocMem(data->pFuncs, arg); \
(arg) = NULL; \
} \
} while (0)
#define VBOX_UTF16_TO_UTF8(arg1, arg2) gVBoxAPI.UPFN.Utf16ToUtf8(data->pFuncs, arg1, arg2)
#define VBOX_UTF8_TO_UTF16(arg1, arg2) gVBoxAPI.UPFN.Utf8ToUtf16(data->pFuncs, arg1, arg2)
/* global vbox API, used for all common codes. */
static vboxUniformedAPI gVBoxAPI;
int vboxRegisterUniformedAPI(uint32_t uVersion)
{
/* Install gVBoxAPI according to the vbox API version.
* Return -1 for unsupported version.
*/
if (uVersion >= 2001052 && uVersion < 2002051) {
vbox22InstallUniformedAPI(&gVBoxAPI);
} else if (uVersion >= 2002051 && uVersion < 3000051) {
vbox30InstallUniformedAPI(&gVBoxAPI);
} else if (uVersion >= 3000051 && uVersion < 3001051) {
vbox31InstallUniformedAPI(&gVBoxAPI);
} else if (uVersion >= 3001051 && uVersion < 3002051) {
vbox32InstallUniformedAPI(&gVBoxAPI);
} else if (uVersion >= 3002051 && uVersion < 4000051) {
vbox40InstallUniformedAPI(&gVBoxAPI);
} else if (uVersion >= 4000051 && uVersion < 4001051) {
vbox41InstallUniformedAPI(&gVBoxAPI);
} else if (uVersion >= 4001051 && uVersion < 4002020) {
vbox42InstallUniformedAPI(&gVBoxAPI);
} else if (uVersion >= 4002020 && uVersion < 4002051) {
vbox42_20InstallUniformedAPI(&gVBoxAPI);
} else if (uVersion >= 4002051 && uVersion < 4003004) {
vbox43InstallUniformedAPI(&gVBoxAPI);
} else if (uVersion >= 4003004 && uVersion < 4003051) {
vbox43_4InstallUniformedAPI(&gVBoxAPI);
} else {
return -1;
}
return 0;
}
static virDomainDefParserConfig vboxDomainDefParserConfig = {
.macPrefix = { 0x08, 0x00, 0x27 },
};
static virDomainXMLOptionPtr
vboxXMLConfInit(void)
{
return virDomainXMLOptionNew(&vboxDomainDefParserConfig,
NULL, NULL);
}
static int vboxInitialize(vboxGlobalData *data)
{
if (gVBoxAPI.UPFN.Initialize(data) != 0)
goto cleanup;
if (gVBoxAPI.domainEventCallbacks && gVBoxAPI.initializeDomainEvent(data) != 0)
goto cleanup;
if (data->vboxObj == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("IVirtualBox object is null"));
goto cleanup;
}
if (data->vboxSession == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("ISession object is null"));
goto cleanup;
}
return 0;
cleanup:
return -1;
}
static virCapsPtr vboxCapsInit(void)
{
virCapsPtr caps;
virCapsGuestPtr guest;
if ((caps = virCapabilitiesNew(virArchFromHost(),
false, false)) == NULL)
goto no_memory;
if (nodeCapsInitNUMA(caps) < 0)
goto no_memory;
if ((guest = virCapabilitiesAddGuest(caps,
"hvm",
caps->host.arch,
NULL,
NULL,
0,
NULL)) == NULL)
goto no_memory;
if (virCapabilitiesAddGuestDomain(guest,
"vbox",
NULL,
NULL,
0,
NULL) == NULL)
goto no_memory;
return caps;
no_memory:
virObjectUnref(caps);
return NULL;
}
static int vboxExtractVersion(vboxGlobalData *data)
{
int ret = -1;
PRUnichar *versionUtf16 = NULL;
char *vboxVersion = NULL;
nsresult rc;
if (data->version > 0)
return 0;
rc = gVBoxAPI.UIVirtualBox.GetVersion(data->vboxObj, &versionUtf16);
if (NS_FAILED(rc))
goto failed;
VBOX_UTF16_TO_UTF8(versionUtf16, &vboxVersion);
if (virParseVersionString(vboxVersion, &data->version, false) >= 0)
ret = 0;
VBOX_UTF8_FREE(vboxVersion);
VBOX_COM_UNALLOC_MEM(versionUtf16);
failed:
if (ret != 0)
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not extract VirtualBox version"));
return ret;
}
static void vboxUninitialize(vboxGlobalData *data)
{
if (!data)
return;
gVBoxAPI.UPFN.Uninitialize(data);
virObjectUnref(data->caps);
virObjectUnref(data->xmlopt);
if (gVBoxAPI.domainEventCallbacks)
virObjectEventStateFree(data->domainEvents);
VIR_FREE(data);
}
virDrvOpenStatus vboxConnectOpen(virConnectPtr conn,
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
unsigned int flags)
{
vboxGlobalData *data = NULL;
uid_t uid = geteuid();
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
if (conn->uri == NULL &&
!(conn->uri = virURIParse(uid ? "vbox:///session" : "vbox:///system")))
return VIR_DRV_OPEN_ERROR;
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, "")) {
virReportError(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")) {
virReportError(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")) {
virReportError(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)
return VIR_DRV_OPEN_ERROR;
if (!(data->caps = vboxCapsInit()) ||
vboxInitialize(data) < 0 ||
vboxExtractVersion(data) < 0 ||
!(data->xmlopt = vboxXMLConfInit())) {
vboxUninitialize(data);
return VIR_DRV_OPEN_ERROR;
}
if (gVBoxAPI.domainEventCallbacks) {
if (!(data->domainEvents = virObjectEventStateNew())) {
vboxUninitialize(data);
return VIR_DRV_OPEN_ERROR;
}
data->conn = conn;
}
if (gVBoxAPI.hasStaticGlobalData)
gVBoxAPI.registerGlobalData(data);
conn->privateData = data;
VIR_DEBUG("in vboxOpen");
return VIR_DRV_OPEN_SUCCESS;
}
/*
* Copyright 2014, Taowei Luo (uaedante@gmail.com)
*
* 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, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef VBOX_COMMON_H
# define VBOX_COMMON_H
# ifdef ___VirtualBox_CXPCOM_h
# error this file should not be included after vbox_CAPI_v*.h
# endif
# include "internal.h"
# include <stddef.h>
# include "wchar.h"
/* This file extracts some symbols defined in
* vbox_CAPI_v*.h. It tells the vbox_common.c
* how to treat with this symbols. This file
* can't be included with files such as
* vbox_CAPI_v*.h, or it would casue multiple
* definitions.
*
* You can see the more informations in vbox_api.h
*/
/* Copied definitions from vbox_CAPI_*.h.
* We must MAKE SURE these codes are compatible. */
typedef unsigned char PRUint8;
# if (defined(HPUX) && defined(__cplusplus) \
&& !defined(__GNUC__) && __cplusplus < 199707L) \
|| (defined(SCO) && defined(__cplusplus) \
&& !defined(__GNUC__) && __cplusplus == 1L)
typedef char PRInt8;
# else
typedef signed char PRInt8;
# endif
# define PR_INT8_MAX 127
# define PR_INT8_MIN (-128)
# define PR_UINT8_MAX 255U
typedef unsigned short PRUint16;
typedef short PRInt16;
# define PR_INT16_MAX 32767
# define PR_INT16_MIN (-32768)
# define PR_UINT16_MAX 65535U
typedef unsigned int PRUint32;
typedef int PRInt32;
# define PR_INT32(x) x
# define PR_UINT32(x) x ## U
# define PR_INT32_MAX PR_INT32(2147483647)
# define PR_INT32_MIN (-PR_INT32_MAX - 1)
# define PR_UINT32_MAX PR_UINT32(4294967295)
typedef long PRInt64;
typedef unsigned long PRUint64;
typedef int PRIntn;
typedef unsigned int PRUintn;
typedef double PRFloat64;
typedef size_t PRSize;
typedef ptrdiff_t PRPtrdiff;
typedef unsigned long PRUptrdiff;
typedef PRIntn PRBool;
# define PR_TRUE 1
# define PR_FALSE 0
typedef PRUint8 PRPackedBool;
/*
** Status code used by some routines that have a single point of failure or
** special status return.
*/
typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus;
# ifndef __PRUNICHAR__
# define __PRUNICHAR__
# if defined(WIN32) || defined(XP_MAC)
typedef wchar_t PRUnichar;
# else
typedef PRUint16 PRUnichar;
# endif
# endif
typedef long PRWord;
typedef unsigned long PRUword;
# define nsnull 0
typedef PRUint32 nsresult;
# if defined(__GNUC__) && (__GNUC__ > 2)
# define NS_LIKELY(x) (__builtin_expect((x), 1))
# define NS_UNLIKELY(x) (__builtin_expect((x), 0))
# else
# define NS_LIKELY(x) (x)
# define NS_UNLIKELY(x) (x)
# endif
# define NS_FAILED(_nsresult) (NS_UNLIKELY((_nsresult) & 0x80000000))
# define NS_SUCCEEDED(_nsresult) (NS_LIKELY(!((_nsresult) & 0x80000000)))
/* Simplied definitions in vbox_CAPI_*.h */
typedef void const *PCVBOXXPCOM;
typedef void IVirtualBox;
typedef void ISession;
#endif /* VBOX_COMMON_H */
......@@ -39,6 +39,10 @@
#include "vbox_glue.h"
#include "virerror.h"
#include "virutil.h"
#include "domain_event.h"
#include "domain_conf.h"
#include "vbox_install_api.h"
#define VIR_FROM_THIS VIR_FROM_VBOX
......@@ -161,6 +165,8 @@ int vboxRegister(void)
} else {
VIR_DEBUG("Unsupported VirtualBox API version: %u", uVersion);
}
/* Register vboxUniformedAPI. */
vboxRegisterUniformedAPI(uVersion);
} else {
VIR_DEBUG("VBoxCGlueInit failed, using dummy driver");
}
......@@ -175,9 +181,9 @@ int vboxRegister(void)
return 0;
}
static virDrvOpenStatus vboxConnectOpen(virConnectPtr conn,
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
unsigned int flags)
static virDrvOpenStatus dummyConnectOpen(virConnectPtr conn,
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
unsigned int flags)
{
uid_t uid = geteuid();
......@@ -218,5 +224,5 @@ static virDrvOpenStatus vboxConnectOpen(virConnectPtr conn,
static virDriver vboxDriverDummy = {
VIR_DRV_VBOX,
"VBOX",
.connectOpen = vboxConnectOpen,
.connectOpen = dummyConnectOpen,
};
/*
* Copyright 2014, Taowei Luo (uaedante@gmail.com)
*
* 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, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef VBOX_INSTALL_API_H
# define VBOX_INSTALL_API_H
# include "internal.h"
int vboxRegisterUniformedAPI(uint32_t uVersion);
#endif /* VBOX_INSTALL_API_H */
......@@ -89,12 +89,15 @@
/* Include this *last* or we'll get the wrong vbox_CAPI_*.h. */
#include "vbox_glue.h"
#include "vbox_uniformed_api.h"
#define VIR_FROM_THIS VIR_FROM_VBOX
VIR_LOG_INIT("vbox.vbox_tmpl");
#define vboxUnsupported() \
VIR_WARN("No %s in current vbox version %d.", __FUNCTION__, VBOX_API_VERSION);
#define VBOX_UTF16_FREE(arg) \
do { \
if (arg) { \
......@@ -203,41 +206,7 @@ if (strUtf16) {\
(unsigned)(iid)->m3[7]);\
}\
typedef struct {
virMutex lock;
unsigned long version;
virCapsPtr caps;
virDomainXMLOptionPtr xmlopt;
IVirtualBox *vboxObj;
ISession *vboxSession;
/** Our version specific API table pointer. */
PCVBOXXPCOM pFuncs;
#if VBOX_API_VERSION == 2002000
} vboxGlobalData;
#else /* !(VBOX_API_VERSION == 2002000) */
/* Async event handling */
virObjectEventStatePtr domainEvents;
int fdWatch;
# if VBOX_API_VERSION <= 3002000
/* IVirtualBoxCallback is used in VirtualBox 3.x only */
IVirtualBoxCallback *vboxCallback;
# endif /* VBOX_API_VERSION <= 3002000 */
nsIEventQueue *vboxQueue;
int volatile vboxCallBackRefCount;
/* pointer back to the connection */
virConnectPtr conn;
} vboxGlobalData;
#if VBOX_API_VERSION > 2002000
/* g_pVBoxGlobalData has to be global variable,
* there is no other way to make the callbacks
......@@ -865,137 +834,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16,
return result;
}
static virDomainDefParserConfig vboxDomainDefParserConfig = {
.macPrefix = { 0x08, 0x00, 0x27 },
};
static virDomainXMLOptionPtr
vboxXMLConfInit(void)
{
return virDomainXMLOptionNew(&vboxDomainDefParserConfig,
NULL, NULL);
}
static virCapsPtr vboxCapsInit(void)
{
virCapsPtr caps;
virCapsGuestPtr guest;
if ((caps = virCapabilitiesNew(virArchFromHost(),
false, false)) == NULL)
goto no_memory;
if (nodeCapsInitNUMA(caps) < 0)
goto no_memory;
if ((guest = virCapabilitiesAddGuest(caps,
"hvm",
caps->host.arch,
NULL,
NULL,
0,
NULL)) == NULL)
goto no_memory;
if (virCapabilitiesAddGuestDomain(guest,
"vbox",
NULL,
NULL,
0,
NULL) == NULL)
goto no_memory;
return caps;
no_memory:
virObjectUnref(caps);
return NULL;
}
static int
vboxInitialize(vboxGlobalData *data)
{
data->pFuncs = g_pfnGetFunctions(VBOX_XPCOMC_VERSION);
if (data->pFuncs == NULL)
goto cleanup;
#if VBOX_XPCOMC_VERSION == 0x00010000U
data->pFuncs->pfnComInitialize(&data->vboxObj, &data->vboxSession);
#else /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */
data->pFuncs->pfnComInitialize(IVIRTUALBOX_IID_STR, &data->vboxObj,
ISESSION_IID_STR, &data->vboxSession);
# if VBOX_API_VERSION == 2002000
/* No event queue functionality in 2.2.* as of now */
# else /* !(VBOX_API_VERSION == 2002000) */
/* Initial the fWatch needed for Event Callbacks */
data->fdWatch = -1;
data->pFuncs->pfnGetEventQueue(&data->vboxQueue);
if (data->vboxQueue == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("nsIEventQueue object is null"));
goto cleanup;
}
# endif /* !(VBOX_API_VERSION == 2002000) */
#endif /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */
if (data->vboxObj == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("IVirtualBox object is null"));
goto cleanup;
}
if (data->vboxSession == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("ISession object is null"));
goto cleanup;
}
return 0;
cleanup:
return -1;
}
static int vboxExtractVersion(vboxGlobalData *data)
{
int ret = -1;
PRUnichar *versionUtf16 = NULL;
nsresult rc;
if (data->version > 0)
return 0;
rc = data->vboxObj->vtbl->GetVersion(data->vboxObj, &versionUtf16);
if (NS_SUCCEEDED(rc)) {
char *vboxVersion = NULL;
VBOX_UTF16_TO_UTF8(versionUtf16, &vboxVersion);
if (virParseVersionString(vboxVersion, &data->version, false) >= 0)
ret = 0;
VBOX_UTF8_FREE(vboxVersion);
VBOX_COM_UNALLOC_MEM(versionUtf16);
}
if (ret != 0)
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not extract VirtualBox version"));
return ret;
}
static void vboxUninitialize(vboxGlobalData *data)
{
if (!data)
......@@ -1014,82 +852,6 @@ static void vboxUninitialize(vboxGlobalData *data)
VIR_FREE(data);
}
static virDrvOpenStatus vboxConnectOpen(virConnectPtr conn,
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
unsigned int flags)
{
vboxGlobalData *data = NULL;
uid_t uid = geteuid();
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
if (conn->uri == NULL &&
!(conn->uri = virURIParse(uid ? "vbox:///session" : "vbox:///system")))
return VIR_DRV_OPEN_ERROR;
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, "")) {
virReportError(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")) {
virReportError(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")) {
virReportError(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)
return VIR_DRV_OPEN_ERROR;
if (!(data->caps = vboxCapsInit()) ||
vboxInitialize(data) < 0 ||
vboxExtractVersion(data) < 0 ||
!(data->xmlopt = vboxXMLConfInit())) {
vboxUninitialize(data);
return VIR_DRV_OPEN_ERROR;
}
#if VBOX_API_VERSION == 2002000
/* No domainEventCallbacks in 2.2.* version */
#else /* !(VBOX_API_VERSION == 2002000) */
if (!(data->domainEvents = virObjectEventStateNew())) {
vboxUninitialize(data);
return VIR_DRV_OPEN_ERROR;
}
data->conn = conn;
g_pVBoxGlobalData = data;
#endif /* !(VBOX_API_VERSION == 2002000) */
conn->privateData = data;
VIR_DEBUG("in vboxOpen");
return VIR_DRV_OPEN_SUCCESS;
}
static int vboxConnectClose(virConnectPtr conn)
{
vboxGlobalData *data = conn->privateData;
......@@ -11497,6 +11259,121 @@ vboxNodeGetFreePages(virConnectPtr conn ATTRIBUTE_UNUSED,
return nodeGetFreePages(npages, pages, startCell, cellCount, counts);
}
static int _pfnInitialize(vboxGlobalData *data)
{
data->pFuncs = g_pfnGetFunctions(VBOX_XPCOMC_VERSION);
if (data->pFuncs == NULL)
return -1;
#if VBOX_XPCOMC_VERSION == 0x00010000U
data->pFuncs->pfnComInitialize(&data->vboxObj, &data->vboxSession);
#else /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */
data->pFuncs->pfnComInitialize(IVIRTUALBOX_IID_STR, &data->vboxObj, ISESSION_IID_STR, &data->vboxSession);
#endif /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */
return 0;
}
static int
_initializeDomainEvent(vboxGlobalData *data ATTRIBUTE_UNUSED)
{
#if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000
/* No event queue functionality in 2.2.* and 4.* as of now */
vboxUnsupported();
#else /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */
/* Initialize the fWatch needed for Event Callbacks */
data->fdWatch = -1;
data->pFuncs->pfnGetEventQueue(&data->vboxQueue);
if (data->vboxQueue == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("nsIEventQueue object is null"));
return -1;
}
#endif /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */
return 0;
}
static
void _registerGlobalData(vboxGlobalData *data ATTRIBUTE_UNUSED)
{
#if VBOX_API_VERSION == 2002000
vboxUnsupported();
#else /* VBOX_API_VERSION != 2002000 */
g_pVBoxGlobalData = data;
#endif /* VBOX_API_VERSION != 2002000 */
}
static void _pfnUninitialize(vboxGlobalData *data)
{
if (data->pFuncs)
data->pFuncs->pfnComUninitialize();
}
static void _pfnComUnallocMem(PCVBOXXPCOM pFuncs, void *pv)
{
pFuncs->pfnComUnallocMem(pv);
}
static void _pfnUtf16Free(PCVBOXXPCOM pFuncs, PRUnichar *pwszString)
{
pFuncs->pfnUtf16Free(pwszString);
}
static void _pfnUtf8Free(PCVBOXXPCOM pFuncs, char *pszString)
{
pFuncs->pfnUtf8Free(pszString);
}
static int _pfnUtf16ToUtf8(PCVBOXXPCOM pFuncs, const PRUnichar *pwszString, char **ppszString)
{
return pFuncs->pfnUtf16ToUtf8(pwszString, ppszString);
}
static int _pfnUtf8ToUtf16(PCVBOXXPCOM pFuncs, const char *pszString, PRUnichar **ppwszString)
{
return pFuncs->pfnUtf8ToUtf16(pszString, ppwszString);
}
static nsresult
_virtualboxGetVersion(IVirtualBox *vboxObj, PRUnichar **versionUtf16)
{
return vboxObj->vtbl->GetVersion(vboxObj, versionUtf16);
}
static vboxUniformedPFN _UPFN = {
.Initialize = _pfnInitialize,
.Uninitialize = _pfnUninitialize,
.ComUnallocMem = _pfnComUnallocMem,
.Utf16Free = _pfnUtf16Free,
.Utf8Free = _pfnUtf8Free,
.Utf16ToUtf8 = _pfnUtf16ToUtf8,
.Utf8ToUtf16 = _pfnUtf8ToUtf16,
};
static vboxUniformedIVirtualBox _UIVirtualBox = {
.GetVersion = _virtualboxGetVersion,
};
void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI)
{
pVBoxAPI->APIVersion = VBOX_API_VERSION;
pVBoxAPI->XPCOMCVersion = VBOX_XPCOMC_VERSION;
pVBoxAPI->initializeDomainEvent = _initializeDomainEvent;
pVBoxAPI->registerGlobalData = _registerGlobalData;
pVBoxAPI->UPFN = _UPFN;
pVBoxAPI->UIVirtualBox = _UIVirtualBox;
#if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000
pVBoxAPI->domainEventCallbacks = 0;
#else /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */
pVBoxAPI->domainEventCallbacks = 1;
#endif /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */
#if VBOX_API_VERSION == 2002000
pVBoxAPI->hasStaticGlobalData = 0;
#else /* VBOX_API_VERSION > 2002000 */
pVBoxAPI->hasStaticGlobalData = 1;
#endif /* VBOX_API_VERSION > 2002000 */
}
/**
* Function Tables
......
/*
* Copyright 2014, Taowei Luo (uaedante@gmail.com)
*
* 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, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef VBOX_UNIFORMED_API_H
# define VBOX_UNIFORMED_API_H
# include "internal.h"
/* This file may be used in three place. That is vbox_tmpl.c,
* vbox_common.c and vbox_driver.c. The vboxUniformedAPI and some
* types used for vboxUniformedAPI is defined here.
*
* The vbox_tmpl.c is the only place where the driver knows the inside
* architecture of those vbox structs(vboxObj, vboxSession,
* pFuncs, vboxCallback and vboxQueue). The file should be included
* after the currect vbox_CAPI_v*.h, then we can use the vbox structs
* in vboxGlobalData. The vbox_tmpl.c should implement functions
* defined in vboxUniformedAPI.
*
* In vbox_driver.c, it is used to define the struct vboxUniformedAPI.
* The vbox_driver.c collects vboxUniformedAPI for all versions.
* Then vboxRegister calls the vboxRegisterUniformedAPI to register.
* Note: In vbox_driver.c, the vbox structs in vboxGlobalData is
* defined by vbox_CAPI_v2.2.h.
*
* The vbox_common.c, it is used to generate common codes for all vbox
* versions. Bacause the same member varible's offset in a vbox struct
* may change between different vbox versions. The vbox_common.c
* shouldn't directly use struct's member varibles defined in
* vbox_CAPI_v*.h. To make things safety, we include the
* vbox_common.h in vbox_common.c. In this case, we treat structs
* defined by vbox as a void*. The common codes don't concern about
* the inside of this structs(actually, we can't, in the common level).
* With the help of vboxUniformed API, we call VirtualBox's API and
* implement the vbox driver in a high level.
*
* In conclusion:
* * In vbox_tmpl.c, this file is included after vbox_CAPI_v*.h
* * In vbox_driver.c, this file is included after vbox_glue.h
* * In vbox_common.c, this file is included after vbox_common.h
*
*/
typedef struct {
virMutex lock;
unsigned long version;
virCapsPtr caps;
virDomainXMLOptionPtr xmlopt;
IVirtualBox *vboxObj;
ISession *vboxSession;
/** Our version specific API table pointer. */
PCVBOXXPCOM pFuncs;
/* The next is used for domainEvent */
# if defined(VBOX_API_VERSION) && VBOX_API_VERSION > 2002000 && VBOX_API_VERSION < 4000000
/* Async event handling */
virObjectEventStatePtr domainEvents;
int fdWatch;
IVirtualBoxCallback *vboxCallback;
nsIEventQueue *vboxQueue;
int volatile vboxCallBackRefCount;
/* pointer back to the connection */
virConnectPtr conn;
# else /* VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 || VBOX_API_VERSION undefined */
virObjectEventStatePtr domainEvents;
int fdWatch;
void *vboxCallback;
void *vboxQueue;
int volatile vboxCallBackRefCount;
virConnectPtr conn;
# endif /* VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 || VBOX_API_VERSION undefined */
} vboxGlobalData;
/* vboxUniformedAPI gives vbox_common.c a uniformed layer to see
* vbox API.
*/
/* Functions for pFuncs */
typedef struct {
int (*Initialize)(vboxGlobalData *data);
void (*Uninitialize)(vboxGlobalData *data);
void (*ComUnallocMem)(PCVBOXXPCOM pFuncs, void *pv);
void (*Utf16Free)(PCVBOXXPCOM pFuncs, PRUnichar *pwszString);
void (*Utf8Free)(PCVBOXXPCOM pFuncs, char *pszString);
int (*Utf16ToUtf8)(PCVBOXXPCOM pFuncs, const PRUnichar *pwszString, char **ppszString);
int (*Utf8ToUtf16)(PCVBOXXPCOM pFuncs, const char *pszString, PRUnichar **ppwszString);
} vboxUniformedPFN;
/* Functions for IVirtualBox */
typedef struct {
nsresult (*GetVersion)(IVirtualBox *vboxObj, PRUnichar **versionUtf16);
} vboxUniformedIVirtualBox;
typedef struct {
/* vbox API version */
uint32_t APIVersion;
uint32_t XPCOMCVersion;
/* vbox APIs */
int (*initializeDomainEvent)(vboxGlobalData *data);
void (*registerGlobalData)(vboxGlobalData *data);
vboxUniformedPFN UPFN;
vboxUniformedIVirtualBox UIVirtualBox;
/* vbox API features */
bool domainEventCallbacks;
bool hasStaticGlobalData;
} vboxUniformedAPI;
/* libvirt API
* These API would be removed after we generate the
* vboxDriver in common code.
*/
virDrvOpenStatus vboxConnectOpen(virConnectPtr conn,
virConnectAuthPtr auth,
unsigned int flags);
/* Version specified functions for installing uniformed API */
void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI);
void vbox30InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI);
void vbox31InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI);
void vbox32InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI);
void vbox40InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI);
void vbox41InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI);
void vbox42InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI);
void vbox42_20InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI);
void vbox43InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI);
void vbox43_4InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI);
#endif /* VBOX_UNIFORMED_API_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册