[libvirt] [PATCH 00/29] vbox: Rewrite several APIs.

Put exactly one API into one patch. Add a test case to test with vboxUniformedAPI. Taowei (29): vbox: Begin to rewrite, vboxConnectOpen vbox: Add test case for vboxUniformedAPI vbox: Rewrite vboxConnectClose vbox: Rewrite vboxDomainSave vbox: Rewrite vboxConnectGetVersion vbox: Rewrite vboxConnectGetHostname vbox: Rewrite vboxConnectIsSecure vbox: Rewrite vboxConnectIsEncrypted vbox: Rewrite vboxConnectIsAlive vbox: Rewrite vboxConnectGetMaxVcpus vbox: Rewrite vboxConnectGetCapabilities vbox: Rewrite vboxConnectListDomains vbox: Rewrite vboxConnectNumOfDomains vbox: Rewrite vboxDomainLookupById vbox: Rewrite vboxDomainLookupByUUId vbox: Rewrite vboxDomainUndefineFlags vbox: Rewrite vboxDomainDefineXML vbox: Rewrite vboxDomainCreateWithFlags vbox: Rewrite vboxDomainCreate vbox: Rewrite vboxDomainCreateXML vbox: Rewrite vboxDomainLookupByName vbox: Rewrite vboxDomainIsActive vbox: Rewrite vboxDomainIsPersistent vbox: Rewrite vboxDomainIsUpdated vbox: Rewrite vboxDomainSuspend vbox: Rewrite vboxDomainResume vbox: Rewrite vboxDomainShutdownFlags vbox: Rewrite vboxDomainShutdown vbox: Rewrite vboxDomainReboot po/POTFILES.in | 1 + src/Makefile.am | 4 +- src/vbox/vbox_common.c | 2547 ++++++++++++++++++++++++++ src/vbox/vbox_common.h | 261 +++ src/vbox/vbox_driver.c | 23 +- src/vbox/vbox_tmpl.c | 4041 ++++++++++++++++------------------------- src/vbox/vbox_uniformed_api.h | 461 +++++ tests/Makefile.am | 9 +- tests/vboxuniformedapitest.c | 98 + 9 files changed, 4933 insertions(+), 2512 deletions(-) create mode 100644 src/vbox/vbox_common.c create mode 100644 src/vbox/vbox_common.h create mode 100644 src/vbox/vbox_uniformed_api.h create mode 100644 tests/vboxuniformedapitest.c -- 1.7.9.5

Introduce vbox_uniformed_api to deal with version conflicts. vboxConnectOpen has been rewritten. --- po/POTFILES.in | 1 + src/Makefile.am | 4 +- src/vbox/vbox_common.c | 289 ++++++++++++++++++++++++++++++++ src/vbox/vbox_common.h | 132 +++++++++++++++ src/vbox/vbox_driver.c | 23 ++- src/vbox/vbox_tmpl.c | 364 ++++++++++++++--------------------------- src/vbox/vbox_uniformed_api.h | 152 +++++++++++++++++ 7 files changed, 717 insertions(+), 248 deletions(-) create mode 100644 src/vbox/vbox_common.c create mode 100644 src/vbox/vbox_common.h create mode 100644 src/vbox/vbox_uniformed_api.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 64a987e..93b7e2b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -215,6 +215,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 diff --git a/src/Makefile.am b/src/Makefile.am index e2f76a7..1d66492 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -674,7 +674,9 @@ 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_DRIVER_EXTRA_DIST = \ vbox/vbox_tmpl.c vbox/README \ diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c new file mode 100644 index 0000000..8fb4494 --- /dev/null +++ b/src/vbox/vbox_common.c @@ -0,0 +1,289 @@ +/* + * 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" + +/* 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; + +void vboxRegisterUniformedAPI(uint32_t uVersion) +{ + /* Install gVBoxAPI according to the vbox API version. + * This function don't check the validation of the + * uVersion, it assumes the vboxRegister will do this + * job. + */ + 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); + } +} + +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.fWatchNeedInitialize && gVBoxAPI.initializeFWatch(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(), + 0, 0)) == 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; + /* Introduce registerGlobalData to register + * g_pVBoxGlobalData in vbox_tmpl.c */ + gVBoxAPI.registerGlobalData(data); + } + + conn->privateData = data; + VIR_DEBUG("in vboxOpen"); + + return VIR_DRV_OPEN_SUCCESS; +} diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h new file mode 100644 index 0000000..000f4ca --- /dev/null +++ b/src/vbox/vbox_common.h @@ -0,0 +1,132 @@ +/* + * 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; +typedef void IVirtualBoxCallback; +typedef void nsIEventQueue; + +#endif /* VBOX_COMMON_H */ diff --git a/src/vbox/vbox_driver.c b/src/vbox/vbox_driver.c index 7d004b2..ad36173 100644 --- a/src/vbox/vbox_driver.c +++ b/src/vbox/vbox_driver.c @@ -39,6 +39,10 @@ #include "vbox_glue.h" #include "virerror.h" #include "virutil.h" +#include "domain_event.h" +#include "domain_conf.h" + +#include "vbox_uniformed_api.h" #define VIR_FROM_THIS VIR_FROM_VBOX @@ -161,6 +165,17 @@ int vboxRegister(void) } else { VIR_DEBUG("Unsupported VirtualBox API version: %u", uVersion); } + /* Register vboxUniformedAPI. The dummy driver will not + * use vboxAPI, so the register step is only for validate + * vbox API versions. + * When the vbox driver is fully redesigned, and there is no + * vbox**Driver or vbox**NetworkDriver or vbox**StorageDriver any + * more, the registerAPI function will handle all jobs in this + * vboxRegister (eg. API version check, return a dummy driver + * for unsupported version). + * But the current design is a solution for compatibility. + */ + vboxRegisterUniformedAPI(uVersion); } else { VIR_DEBUG("VBoxCGlueInit failed, using dummy driver"); } @@ -175,9 +190,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 +233,5 @@ static virDrvOpenStatus vboxConnectOpen(virConnectPtr conn, static virDriver vboxDriverDummy = { VIR_DRV_VBOX, "VBOX", - .connectOpen = vboxConnectOpen, + .connectOpen = dummyConnectOpen, }; diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 3825083..cc1733b 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -89,7 +89,7 @@ /* 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 @@ -203,41 +203,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 +831,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(), - 0, 0)) == 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 +849,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 +11256,125 @@ vboxNodeGetFreePages(virConnectPtr conn ATTRIBUTE_UNUSED, return nodeGetFreePages(npages, pages, startCell, cellCount, counts); } +/* Begin of vboxUniformedAPI */ + +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 +_initializeFWatch(vboxGlobalData *data ATTRIBUTE_UNUSED) +{ +#if (VBOX_XPCOMC_VERSION == 0x00010000U) || (VBOX_API_VERSION == 2002000) + /* No event queue functionality in 2.2.* as of now */ + VIR_WARN("There is no fWatch initical in current version"); +#else /* (VBOX_XPCOMC_VERSION != 0x00010000U && VBOX_API_VERSION != 2002000) */ + /* 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_XPCOMC_VERSION != 0x00010000U && VBOX_API_VERSION != 2002000) */ + return 0; +} + +static +void _registerGlobalData(vboxGlobalData *data ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION == 2002000 + VIR_WARN("No g_pVBoxGlobalData in current version"); +#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->initializeFWatch = _initializeFWatch; + pVBoxAPI->registerGlobalData = _registerGlobalData; + pVBoxAPI->UPFN = _UPFN; + pVBoxAPI->UIVirtualBox = _UIVirtualBox; +#if (VBOX_XPCOMC_VERSION == 0x00010000U) || (VBOX_API_VERSION == 2002000) + /* No event queue functionality in 2.2.* as of now */ + pVBoxAPI->fWatchNeedInitialize = 0; +#else /* (VBOX_XPCOMC_VERSION != 0x00010000U && VBOX_API_VERSION != 2002000) */ + pVBoxAPI->fWatchNeedInitialize = 1; +#endif /* (VBOX_XPCOMC_VERSION != 0x00010000U && VBOX_API_VERSION != 2002000) */ + +#if VBOX_API_VERSION == 2002000 + pVBoxAPI->domainEventCallbacks = 0; +#else /* !(VBOX_API_VERSION == 2002000) */ + pVBoxAPI->domainEventCallbacks = 1; +#endif /* !(VBOX_API_VERSION == 2002000) */ + +} + +/* End of vboxUniformedAPI and Begin of common codes */ /** * Function Tables diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h new file mode 100644 index 0000000..fa753d4 --- /dev/null +++ b/src/vbox/vbox_uniformed_api.h @@ -0,0 +1,152 @@ +/* + * 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 when VBOX_API_VERSION > 2002000 */ + /* Async event handling */ + virObjectEventStatePtr domainEvents; + int fdWatch; +# if defined(VBOX_API_VERSION) && VBOX_API_VERSION > 2002000 && VBOX_API_VERSION <= 3002000 + /* IVirtualBoxCallback is used in VirtualBox 3.x only */ + IVirtualBoxCallback *vboxCallback; +# else /* VBOX_API_VERSION == 2002000 || VBOX_API_VERSION > 3002000 or VBOX_API_VERSION undefined */ + void *vboxCallback; +# endif /* VBOX_API_VERSION == 2002000 || VBOX_API_VERSION > 3002000 or VBOX_API_VERSION undefined */ + + +# if defined(VBOX_API_VERSION) && VBOX_API_VERSION > 2002000 + nsIEventQueue *vboxQueue; +# else /* VBOX_API_VERSION == 2002000 or undefined */ + void *vboxQueue; +# endif /* VBOX_API_VERSION == 2002000 or undefined */ + int volatile vboxCallBackRefCount; + + /* pointer back to the connection */ + virConnectPtr conn; + +} 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 (*initializeFWatch)(vboxGlobalData *data); + void (*registerGlobalData)(vboxGlobalData *data); + vboxUniformedPFN UPFN; + vboxUniformedIVirtualBox UIVirtualBox; + /* vbox API features */ + bool fWatchNeedInitialize; + bool domainEventCallbacks; +} 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); + +void vboxRegisterUniformedAPI(uint32_t uVersion); + +#endif /* VBOX_UNIFORMED_API_H */ -- 1.7.9.5

The test case will make sure each API will filled with something. So we will not to define an API, use it, yet forgot to implement. --- tests/Makefile.am | 9 +++- tests/vboxuniformedapitest.c | 98 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 tests/vboxuniformedapitest.c diff --git a/tests/Makefile.am b/tests/Makefile.am index bc1040a..f73d25d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -241,7 +241,7 @@ test_programs += esxutilstest endif WITH_ESX if WITH_VBOX -test_programs += vboxsnapshotxmltest +test_programs += vboxsnapshotxmltest vboxuniformedapitest endif WITH_VBOX if WITH_VMX @@ -638,8 +638,13 @@ vboxsnapshotxmltest_SOURCES = \ testutils.c testutils.h vbox_LDADDS = ../src/libvirt_driver_vbox_impl.la vboxsnapshotxmltest_LDADD = $(LDADDS) $(vbox_LDADDS) + +vboxuniformedapitest_SOURCES = \ + vboxuniformedapitest.c \ + testutils.c testutils.h +vboxuniformedapitest_LDADD = $(vbox_LDADDS) $(LDADDS) else ! WITH_VBOX -EXTRA_DIST += vboxsnapshotxmltest.c +EXTRA_DIST += vboxsnapshotxmltest.c vboxuniformedapitest.c endif ! WITH_VBOX if WITH_VMX diff --git a/tests/vboxuniformedapitest.c b/tests/vboxuniformedapitest.c new file mode 100644 index 0000000..933cdb7 --- /dev/null +++ b/tests/vboxuniformedapitest.c @@ -0,0 +1,98 @@ +/* + * 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 "testutils.h" + +#ifdef WITH_VBOX + +# include "datatypes.h" +# include "domain_event.h" +# include "vbox/vbox_common.h" +# include "vbox/vbox_uniformed_api.h" + +# define VIR_FROM_THIS VIR_FROM_NONE + +static vboxUniformedAPI vboxAPI; +typedef void (*installAPI_f)(vboxUniformedAPI *pVBoxAPI); + +/* This test make sure all APIs in vboxUniformedAPI is + * filled with something (say not null). It helps to + * make sure you will not leave an API defined (and used + * probably) but not implemented yet. + */ + +static int testUniformedAPI(const void *args) +{ + installAPI_f installAPI = (installAPI_f)args; + void **iter; + + memset(&vboxAPI, 0, sizeof(vboxUniformedAPI)); + installAPI(&vboxAPI); + + /* Assuming that the vboxUniformedAPI is in the range + * of [initializeFWatch, fWatchNeedInitialize). + */ + for (iter = (void **)&vboxAPI.initializeFWatch; + iter < (void **)&vboxAPI.fWatchNeedInitialize; + iter ++) + { + if ((void *)(*iter) == NULL) + return -1; + } + return 0; +} + +static int +mymain(void) +{ + int ret = 0; + +# define TEST(version) \ + do { \ + if (virtTestRun("Test uniformedAPI " # version, \ + testUniformedAPI, \ + vbox##version##InstallUniformedAPI) < 0) \ + ret = -1; \ + } while (0) + + TEST(22); + TEST(30); + TEST(31); + TEST(32); + TEST(40); + TEST(41); + TEST(42); + TEST(42_20); + TEST(43); + TEST(43_4); + + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIRT_TEST_MAIN(mymain) + +#else + +int main(void) +{ + return EXIT_AM_SKIP; +} + +#endif /*WITH_VBOX*/ -- 1.7.9.5

--- src/vbox/vbox_common.c | 11 +++++++++++ src/vbox/vbox_tmpl.c | 29 ----------------------------- src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 12 insertions(+), 29 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 8fb4494..2e23d62 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -287,3 +287,14 @@ virDrvOpenStatus vboxConnectOpen(virConnectPtr conn, return VIR_DRV_OPEN_SUCCESS; } + +int vboxConnectClose(virConnectPtr conn) +{ + vboxGlobalData *data = conn->privateData; + VIR_DEBUG("%s: in vboxClose", conn->driver->name); + + vboxUninitialize(data); + conn->privateData = NULL; + + return 0; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index cc1733b..f6890d2 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -831,35 +831,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static void vboxUninitialize(vboxGlobalData *data) -{ - if (!data) - return; - - if (data->pFuncs) - data->pFuncs->pfnComUninitialize(); - - virObjectUnref(data->caps); - virObjectUnref(data->xmlopt); -#if VBOX_API_VERSION == 2002000 - /* No domainEventCallbacks in 2.2.* version */ -#else /* !(VBOX_API_VERSION == 2002000) */ - virObjectEventStateFree(data->domainEvents); -#endif /* !(VBOX_API_VERSION == 2002000) */ - VIR_FREE(data); -} - -static int vboxConnectClose(virConnectPtr conn) -{ - vboxGlobalData *data = conn->privateData; - VIR_DEBUG("%s: in vboxClose", conn->driver->name); - - vboxUninitialize(data); - conn->privateData = NULL; - - return 0; -} - static int vboxConnectGetVersion(virConnectPtr conn, unsigned long *version) { vboxGlobalData *data = conn->privateData; diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index fa753d4..2eda247 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -134,6 +134,7 @@ typedef struct { virDrvOpenStatus vboxConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags); +int vboxConnectClose(virConnectPtr conn); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

vboxIIDUnion is introduced in this patch to fixup vboxIID conflictions. --- src/vbox/vbox_common.c | 95 +++++++++++ src/vbox/vbox_common.h | 40 +++++ src/vbox/vbox_tmpl.c | 346 +++++++++++++++++++++++++++++++---------- src/vbox/vbox_uniformed_api.h | 82 ++++++++++ 4 files changed, 478 insertions(+), 85 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 2e23d62..a74a1de 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -41,6 +41,9 @@ VIR_LOG_INIT("vbox.vbox_common"); +#define RC_SUCCEEDED(rc) NS_SUCCEEDED(rc.resultCode) +#define RC_FAILED(rc) NS_FAILED(rc.resultCode) + #define VBOX_UTF16_FREE(arg) \ do { \ if (arg) { \ @@ -68,6 +71,31 @@ VIR_LOG_INIT("vbox.vbox_common"); #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) +#define VBOX_RELEASE(arg) \ + do { \ + if (arg) { \ + gVBoxAPI.nsUISupports.Release((void *)arg); \ + (arg) = NULL; \ + } \ + } while (0) + +#define VBOX_OBJECT_CHECK(conn, type, value) \ +vboxGlobalData *data = conn->privateData;\ +type ret = value;\ +if (!data->vboxObj) {\ + return ret;\ +} + +#define vboxIIDUnalloc(iid) gVBoxAPI.UIID.vboxIIDUnalloc(data, iid) +#define vboxIIDToUUID(iid, uuid) gVBoxAPI.UIID.vboxIIDToUUID(data, iid, uuid) +#define vboxIIDFromUUID(iid, uuid) gVBoxAPI.UIID.vboxIIDFromUUID(data, iid, uuid) +#define vboxIIDIsEqual(iid1, iid2) gVBoxAPI.UIID.vboxIIDIsEqual(data, iid1, iid2) +#define DEBUGIID(msg, iid) gVBoxAPI.UIID.DEBUGIID(msg, iid) +#define vboxIIDFromArrayItem(iid, array, idx) \ + gVBoxAPI.UUID.vboxIIDFromArrayItem(data, iid, array, idx) + +#define VBOX_IID_INITIALIZE(iid) gVBoxAPI.UIID.vboxIIDInitialize(iid) + /* global vbox API, used for all common codes. */ static vboxUniformedAPI gVBoxAPI; @@ -101,6 +129,22 @@ void vboxRegisterUniformedAPI(uint32_t uVersion) } } +static int openSessionForMachine(vboxGlobalData *data, const unsigned char *dom_uuid, vboxIIDUnion *iid, + IMachine **machine, bool checkflag) +{ + VBOX_IID_INITIALIZE(iid); + vboxIIDFromUUID(iid, dom_uuid); + if (!checkflag || gVBoxAPI.getMachineForSession) { + /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */ + if (NS_FAILED(gVBoxAPI.UIVirtualBox.GetMachine(data, iid, machine))) { + virReportError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + return -1; + } + } + return 0; +} + static virDomainDefParserConfig vboxDomainDefParserConfig = { .macPrefix = { 0x08, 0x00, 0x27 }, }; @@ -298,3 +342,54 @@ int vboxConnectClose(virConnectPtr conn) return 0; } + +int +vboxDomainSave(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IConsole *console = NULL; + vboxIIDUnion iid; + IMachine *machine = NULL; + IProgress *progress = NULL; + resultCodeUnion resultCode; + nsresult rc; + + /* VirtualBox currently doesn't support saving to a file + * at a location other then the machine folder and thus + * setting path to ATTRIBUTE_UNUSED for now, will change + * this behaviour once get the VirtualBox API in right + * shape to do this + */ + + /* Open a Session for the machine */ + if (openSessionForMachine(data, dom->uuid, &iid, &machine, true) < 0) + goto cleanup; + + rc = gVBoxAPI.UISession.OpenExisting(data, &iid, machine); + if (NS_FAILED(rc)) + goto cleanup; + + rc = gVBoxAPI.UISession.GetConsole(data->vboxSession, &console); + if (NS_FAILED(rc) || !console) + goto freeSession; + + rc = gVBoxAPI.UIConsole.SaveState(console, &progress); + if (!progress) + goto freeSession; + + gVBoxAPI.UIProgress.WaitForCompletion(progress, -1); + gVBoxAPI.UIProgress.GetResultCode(progress, &resultCode); + if (RC_SUCCEEDED(resultCode)) + ret = 0; + + freeSession: + gVBoxAPI.UISession.Close(data->vboxSession); + + cleanup: + DEBUGIID("UUID of machine being saved:", &iid); + VBOX_RELEASE(machine); + VBOX_RELEASE(console); + VBOX_RELEASE(progress); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h index 000f4ca..aa6be11 100644 --- a/src/vbox/vbox_common.h +++ b/src/vbox/vbox_common.h @@ -121,11 +121,51 @@ typedef PRUint32 nsresult; # define NS_FAILED(_nsresult) (NS_UNLIKELY((_nsresult) & 0x80000000)) # define NS_SUCCEEDED(_nsresult) (NS_LIKELY(!((_nsresult) & 0x80000000))) +/** + * An "interface id" which can be used to uniquely identify a given + * interface. + * A "unique identifier". This is modeled after OSF DCE UUIDs. + */ + +struct nsID { + PRUint32 m0; + PRUint16 m1; + PRUint16 m2; + PRUint8 m3[8]; +}; + +typedef struct nsID nsID; +typedef nsID nsIID; + +typedef struct _vboxArray vboxArray; + +# ifdef WIN32 + +struct _vboxArray { + void **items; + size_t count; + void *handle; +}; +# define VBOX_ARRAY_INITIALIZER { NULL, 0, NULL } + +# else /* !WIN32 */ + +struct _vboxArray { + void **items; + size_t count; +}; +# define VBOX_ARRAY_INITIALIZER { NULL, 0 } + +# endif /* !WIN32 */ + /* Simplied definitions in vbox_CAPI_*.h */ typedef void const *PCVBOXXPCOM; typedef void IVirtualBox; typedef void ISession; +typedef void IConsole; +typedef void IProgress; +typedef void IMachine; typedef void IVirtualBoxCallback; typedef void nsIEventQueue; diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index f6890d2..54a84bb 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -189,7 +189,7 @@ if (strUtf16) {\ #define DEBUGUUID(msg, iid) \ {\ - VIR_DEBUG(msg ": {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",\ + VIR_DEBUG("%s: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", msg,\ (unsigned)(iid)->m0,\ (unsigned)(iid)->m1,\ (unsigned)(iid)->m2,\ @@ -352,12 +352,8 @@ static void nsIDFromChar(nsID *iid, const unsigned char *uuid) typedef struct _vboxIID_v2_x_WIN32 vboxIID; typedef struct _vboxIID_v2_x_WIN32 vboxIID_v2_x_WIN32; -struct _vboxIID_v2_x_WIN32 { - /* IID is represented by a GUID value. */ - GUID value; -}; - # define VBOX_IID_INITIALIZER { { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } } +# define IID_MEMBER(name) (iidu->vboxIID_v2_x_WIN32.name) static void vboxIIDUnalloc_v2_x_WIN32(vboxGlobalData *data ATTRIBUTE_UNUSED, @@ -367,12 +363,25 @@ vboxIIDUnalloc_v2_x_WIN32(vboxGlobalData *data ATTRIBUTE_UNUSED, } static void +_vboxIIDUnalloc(vboxGlobalData *data ATTRIBUTE_UNUSED, + vboxIIDUnion *iid ATTRIBUTE_UNUSED) +{ + /* Nothing to free */ +} + +static void vboxIIDToUUID_v2_x_WIN32(vboxIID_v2_x_WIN32 *iid, unsigned char *uuid) { nsIDtoChar(uuid, (nsID *)&iid->value); } static void +_vboxIIDToUUID(vboxGlobalData *data ATTRIBUTE_UNUSED, vboxIIDUnion *iidu, unsigned char *uuid) +{ + vboxIIDToUUID_v2_x_WIN32(&iidu->vboxIID_v2_x_WIN32, uuid); +} + +static void vboxIIDFromUUID_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid, const unsigned char *uuid) { @@ -381,12 +390,25 @@ vboxIIDFromUUID_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid, nsIDFromChar((nsID *)&iid->value, uuid); } +static void +_vboxIIDFromUUID(vboxGlobalData *data, vboxIIDUnion *iidu, + const unsigned char *uuid) +{ + vboxIIDFromUUID_v2_x_WIN32(data, &iidu->vboxIID_v2_x_WIN32, uuid); +} + static bool vboxIIDIsEqual_v2_x_WIN32(vboxIID_v2_x_WIN32 *iid1, vboxIID_v2_x_WIN32 *iid2) { return memcmp(&iid1->value, &iid2->value, sizeof(GUID)) == 0; } +static bool +_vboxIIDIsEqual(vboxGlobalData *data ATTRIBUTE_UNUSED, vboxIIDUnion *iidu1, vboxIIDUnion *iidu2) +{ + return vboxIIDIsEqual_v2_x_WIN32(&iidu1->vboxIID_v2_x_WIN32, &iidu2->vboxIID_v2_x_WIN32); +} + static void vboxIIDFromArrayItem_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid, vboxArray *array, int idx) @@ -398,6 +420,13 @@ vboxIIDFromArrayItem_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid, memcpy(&iid->value, &items[idx], sizeof(GUID)); } +static void +_vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu, + vboxArray *array, int idx) +{ + vboxIIDFromArrayItem_v2_x_WIN32(data, &iidu->vboxIID_v2_x_WIN32, array, idx); +} + # define vboxIIDUnalloc(iid) vboxIIDUnalloc_v2_x_WIN32(data, iid) # define vboxIIDToUUID(iid, uuid) vboxIIDToUUID_v2_x_WIN32(iid, uuid) # define vboxIIDFromUUID(iid, uuid) vboxIIDFromUUID_v2_x_WIN32(data, iid, uuid) @@ -411,17 +440,8 @@ vboxIIDFromArrayItem_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid, typedef struct _vboxIID_v2_x vboxIID; typedef struct _vboxIID_v2_x vboxIID_v2_x; -struct _vboxIID_v2_x { - /* IID is represented by a pointer to a nsID. */ - nsID *value; - - /* backing is used in cases where we need to create or copy an IID. - * We cannot allocate memory that can be freed by ComUnallocMem. - * Therefore, we use this stack allocated nsID instead. */ - nsID backing; -}; - # define VBOX_IID_INITIALIZER { NULL, { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } } +# define IID_MEMBER(name) (iidu->vboxIID_v2_x.name) static void vboxIIDUnalloc_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid) @@ -438,12 +458,25 @@ vboxIIDUnalloc_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid) } static void +_vboxIIDUnalloc(vboxGlobalData *data, vboxIIDUnion *iidu) +{ + vboxIIDUnalloc_v2_x(data, &iidu->vboxIID_v2_x); +} + +static void vboxIIDToUUID_v2_x(vboxIID_v2_x *iid, unsigned char *uuid) { nsIDtoChar(uuid, iid->value); } static void +_vboxIIDToUUID(vboxGlobalData *data ATTRIBUTE_UNUSED, + vboxIIDUnion *iidu, unsigned char *uuid) +{ + vboxIIDToUUID_v2_x(&iidu->vboxIID_v2_x, uuid); +} + +static void vboxIIDFromUUID_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid, const unsigned char *uuid) { @@ -455,12 +488,26 @@ vboxIIDFromUUID_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid, nsIDFromChar(iid->value, uuid); } +static void +_vboxIIDFromUUID(vboxGlobalData *data, vboxIIDUnion *iidu, + const unsigned char *uuid) +{ + vboxIIDFromUUID_v2_x(data, &iidu->vboxIID_v2_x, uuid); +} + static bool vboxIIDIsEqual_v2_x(vboxIID_v2_x *iid1, vboxIID_v2_x *iid2) { return memcmp(iid1->value, iid2->value, sizeof(nsID)) == 0; } +static bool +_vboxIIDIsEqual(vboxGlobalData *data ATTRIBUTE_UNUSED, + vboxIIDUnion *iidu1, vboxIIDUnion *iidu2) +{ + return vboxIIDIsEqual_v2_x(&iidu1->vboxIID_v2_x, &iidu2->vboxIID_v2_x); +} + static void vboxIIDFromArrayItem_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid, vboxArray *array, int idx) @@ -472,6 +519,13 @@ vboxIIDFromArrayItem_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid, memcpy(iid->value, array->items[idx], sizeof(nsID)); } +static void +_vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu, + vboxArray *array, int idx) +{ + vboxIIDFromArrayItem_v2_x(data, &iidu->vboxIID_v2_x, array, idx); +} + # define vboxIIDUnalloc(iid) vboxIIDUnalloc_v2_x(data, iid) # define vboxIIDToUUID(iid, uuid) vboxIIDToUUID_v2_x(iid, uuid) # define vboxIIDFromUUID(iid, uuid) vboxIIDFromUUID_v2_x(data, iid, uuid) @@ -487,15 +541,8 @@ vboxIIDFromArrayItem_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid, typedef struct _vboxIID_v3_x vboxIID; typedef struct _vboxIID_v3_x vboxIID_v3_x; -struct _vboxIID_v3_x { - /* IID is represented by a UTF-16 encoded UUID in string form. */ - PRUnichar *value; - - /* owner indicates if we own the value and need to free it. */ - bool owner; -}; - # define VBOX_IID_INITIALIZER { NULL, true } +# define IID_MEMBER(name) (iidu->vboxIID_v3_x.name) static void vboxIIDUnalloc_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid) @@ -509,6 +556,12 @@ vboxIIDUnalloc_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid) } static void +_vboxIIDUnalloc(vboxGlobalData *data, vboxIIDUnion *iidu) +{ + vboxIIDUnalloc_v3_x(data, &iidu->vboxIID_v3_x); +} + +static void vboxIIDToUUID_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, unsigned char *uuid) { @@ -522,6 +575,13 @@ vboxIIDToUUID_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, } static void +_vboxIIDToUUID(vboxGlobalData *data, vboxIIDUnion *iidu, + unsigned char *uuid) +{ + vboxIIDToUUID_v3_x(data, &iidu->vboxIID_v3_x, uuid); +} + +static void vboxIIDFromUUID_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, const unsigned char *uuid) { @@ -534,6 +594,13 @@ vboxIIDFromUUID_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, data->pFuncs->pfnUtf8ToUtf16(utf8, &iid->value); } +static void +_vboxIIDFromUUID(vboxGlobalData *data, vboxIIDUnion *iidu, + const unsigned char *uuid) +{ + vboxIIDFromUUID_v3_x(data, &iidu->vboxIID_v3_x, uuid); +} + static bool vboxIIDIsEqual_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid1, vboxIID_v3_x *iid2) @@ -552,6 +619,12 @@ vboxIIDIsEqual_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid1, return memcmp(uuid1, uuid2, VIR_UUID_BUFLEN) == 0; } +static bool +_vboxIIDIsEqual(vboxGlobalData *data, vboxIIDUnion *iidu1, + vboxIIDUnion *iidu2) +{ + return vboxIIDIsEqual_v3_x(data, &iidu1->vboxIID_v3_x, &iidu2->vboxIID_v3_x); +} static void vboxIIDFromArrayItem_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, @@ -563,6 +636,13 @@ vboxIIDFromArrayItem_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, iid->owner = false; } +static void +_vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu, + vboxArray *array, int idx) +{ + vboxIIDFromArrayItem_v3_x(data, &iidu->vboxIID_v3_x, array, idx); +} + # define vboxIIDUnalloc(iid) vboxIIDUnalloc_v3_x(data, iid) # define vboxIIDToUUID(iid, uuid) vboxIIDToUUID_v3_x(data, iid, uuid) @@ -1823,67 +1903,6 @@ vboxDomainGetState(virDomainPtr dom, return ret; } -static int vboxDomainSave(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IConsole *console = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - nsresult rc; - - /* VirtualBox currently doesn't support saving to a file - * at a location other then the machine folder and thus - * setting path to ATTRIBUTE_UNUSED for now, will change - * this behaviour once get the VirtualBox API in right - * shape to do this - */ - - /* Open a Session for the machine */ - vboxIIDFromUUID(&iid, dom->uuid); -#if VBOX_API_VERSION >= 4000000 - /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */ - rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching uuid")); - return -1; - } -#endif - - rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); - if (NS_SUCCEEDED(rc)) { - rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console); - if (NS_SUCCEEDED(rc) && console) { - IProgress *progress = NULL; - - console->vtbl->SaveState(console, &progress); - - if (progress) { -#if VBOX_API_VERSION == 2002000 - nsresult resultCode; -#else - PRInt32 resultCode; -#endif - - progress->vtbl->WaitForCompletion(progress, -1); - progress->vtbl->GetResultCode(progress, &resultCode); - if (NS_SUCCEEDED(resultCode)) { - ret = 0; - } - VBOX_RELEASE(progress); - } - VBOX_RELEASE(console); - } - VBOX_SESSION_CLOSE(); - } - - DEBUGIID("UUID of machine being saved:", iid.value); - - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - static int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags) @@ -11302,12 +11321,127 @@ static int _pfnUtf8ToUtf16(PCVBOXXPCOM pFuncs, const char *pszString, PRUnichar return pFuncs->pfnUtf8ToUtf16(pszString, ppwszString); } +#if VBOX_API_VERSION == 2002000 + +static void _vboxIIDInitialize(vboxIIDUnion *iidu) +{ + memset(iidu, 0, sizeof(vboxIIDUnion)); +} + +static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu) +{ +# ifdef WIN32 + DEBUGUUID(msg, (nsID *)&IID_MEMBER(value)); +# else /* !WIN32 */ + DEBUGUUID(msg, IID_MEMBER(value)); +# endif /* !WIN32 */ +} + +#else /* VBOX_API_VERSION != 2002000 */ + +static void _vboxIIDInitialize(vboxIIDUnion *iidu) +{ + memset(iidu, 0, sizeof(vboxIIDUnion)); + IID_MEMBER(owner) = true; +} + +static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu) +{ + DEBUGPRUnichar(msg, IID_MEMBER(value)); +} + +#endif /* VBOX_API_VERSION != 2002000 */ + static nsresult _virtualboxGetVersion(IVirtualBox *vboxObj, PRUnichar **versionUtf16) { return vboxObj->vtbl->GetVersion(vboxObj, versionUtf16); } +#if VBOX_API_VERSION < 4000000 + +static nsresult +_virtualboxGetMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine) +{ + return data->vboxObj->vtbl->GetMachine(data->vboxObj, IID_MEMBER(value), machine); +} + +#else /* VBOX_API_VERSION >= 4000000 */ + +static nsresult +_virtualboxGetMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine) +{ + return data->vboxObj->vtbl->FindMachine(data->vboxObj, IID_MEMBER(value), machine); +} + +#endif /* VBOX_API_VERSION >= 4000000 */ + +#if VBOX_API_VERSION < 4000000 + +static nsresult +_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED) +{ + return data->vboxObj->vtbl->OpenExistingSession(data->vboxObj, data->vboxSession, IID_MEMBER(value)); +} + +static nsresult +_sessionClose(ISession *session) +{ + return session->vtbl->Close(session); +} + +#else /* VBOX_API_VERSION >= 4000000 */ + +static nsresult +_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine) +{ + return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Shared); +} + +static nsresult +_sessionClose(ISession *session) +{ + return session->vtbl->UnlockMachine(session); +} + +#endif /* VBOX_API_VERSION >= 4000000 */ + +static nsresult +_sessionGetConsole(ISession *session, IConsole **console) +{ + return session->vtbl->GetConsole(session, console); +} + +static nsresult +_consoleSaveState(IConsole *console, IProgress **progress) +{ + return console->vtbl->SaveState(console, progress); +} + +static nsresult +_progressWaitForCompletion(IProgress *progress, PRInt32 timeout) +{ + return progress->vtbl->WaitForCompletion(progress, timeout); +} + +static nsresult +_progressGetResultCode(IProgress *progress, resultCodeUnion *resultCode) +{ +#if VBOX_API_VERSION == 2002000 + return progress->vtbl->GetResultCode(progress, &resultCode->uResultCode); +#else /* VBOX_API_VERSION != 2002000 */ + return progress->vtbl->GetResultCode(progress, &resultCode->resultCode); +#endif /* VBOX_API_VERSION != 2002000 */ +} + +static nsresult _nsisupportsRelease(void *Ihandle) +{ + /* It is safety to convert a pointer from IVirtual(or structs + * like this) to nsISupports*/ + nsISupports *nsi = (nsISupports *)Ihandle; + return nsi->vtbl->Release(nsi); +} + static vboxUniformedPFN _UPFN = { .Initialize = _pfnInitialize, .Uninitialize = _pfnUninitialize, @@ -11318,8 +11452,38 @@ static vboxUniformedPFN _UPFN = { .Utf8ToUtf16 = _pfnUtf8ToUtf16, }; +static vboxUniformedIID _UIID = { + .vboxIIDInitialize = _vboxIIDInitialize, + .vboxIIDUnalloc = _vboxIIDUnalloc, + .vboxIIDToUUID = _vboxIIDToUUID, + .vboxIIDFromUUID = _vboxIIDFromUUID, + .vboxIIDIsEqual = _vboxIIDIsEqual, + .vboxIIDFromArrayItem = _vboxIIDFromArrayItem, + .DEBUGIID = _DEBUGIID, +}; + static vboxUniformedIVirtualBox _UIVirtualBox = { .GetVersion = _virtualboxGetVersion, + .GetMachine = _virtualboxGetMachine, +}; + +static vboxUniformedISession _UISession = { + .OpenExisting = _sessionOpenExisting, + .GetConsole = _sessionGetConsole, + .Close = _sessionClose, +}; + +static vboxUniformedIConsole _UIConsole = { + .SaveState = _consoleSaveState, +}; + +static vboxUniformedIProgress _UIProgress = { + .WaitForCompletion = _progressWaitForCompletion, + .GetResultCode = _progressGetResultCode, +}; + +static vboxUniformednsISupports _nsUISupports = { + .Release = _nsisupportsRelease, }; void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) @@ -11329,7 +11493,13 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->initializeFWatch = _initializeFWatch; pVBoxAPI->registerGlobalData = _registerGlobalData; pVBoxAPI->UPFN = _UPFN; + pVBoxAPI->UIID = _UIID; pVBoxAPI->UIVirtualBox = _UIVirtualBox; + pVBoxAPI->UISession = _UISession; + pVBoxAPI->UIConsole = _UIConsole; + pVBoxAPI->UIProgress = _UIProgress; + pVBoxAPI->nsUISupports = _nsUISupports; + #if (VBOX_XPCOMC_VERSION == 0x00010000U) || (VBOX_API_VERSION == 2002000) /* No event queue functionality in 2.2.* as of now */ pVBoxAPI->fWatchNeedInitialize = 0; @@ -11343,6 +11513,12 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->domainEventCallbacks = 1; #endif /* !(VBOX_API_VERSION == 2002000) */ +#if VBOX_API_VERSION >= 4000000 + /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */ + pVBoxAPI->getMachineForSession = 1; +#else /* VBOX_API_VERSION < 4000000 */ + pVBoxAPI->getMachineForSession = 0; +#endif /* VBOX_API_VERSION < 4000000 */ } /* End of vboxUniformedAPI and Begin of common codes */ diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 2eda247..44bb3bc 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -56,6 +56,46 @@ * */ +/* Extracted define from vbox_tmpl.c */ + +# ifdef WIN32 +struct _vboxIID_v2_x_WIN32 { + /* IID is represented by a GUID value. */ + GUID value; +}; +# endif /* !WIN32 */ + +struct _vboxIID_v2_x { + /* IID is represented by a pointer to a nsID. */ + nsID *value; + + /* backing is used in cases where we need to create or copy an IID. + * We cannot allocate memory that can be freed by ComUnallocMem. + * Therefore, we use this stack allocated nsID instead. */ + nsID backing; +}; + +struct _vboxIID_v3_x { + /* IID is represented by a UTF-16 encoded UUID in string form. */ + PRUnichar *value; + + /* owner indicates if we own the value and need to free it. */ + bool owner; +}; + +typedef union { +# ifdef WIN32 + struct _vboxIID_v2_x_WIN32 vboxIID_v2_x_WIN32; +# endif /* !WIN32 */ + struct _vboxIID_v2_x vboxIID_v2_x; + struct _vboxIID_v3_x vboxIID_v3_x; +} vboxIIDUnion; + +typedef union { + nsresult uResultCode; + PRInt32 resultCode; +} resultCodeUnion; + typedef struct { virMutex lock; unsigned long version; @@ -108,11 +148,46 @@ typedef struct { int (*Utf8ToUtf16)(PCVBOXXPCOM pFuncs, const char *pszString, PRUnichar **ppwszString); } vboxUniformedPFN; +/* Functions for vboxIID */ +typedef struct { + void (*vboxIIDInitialize)(vboxIIDUnion *iidu); + void (*vboxIIDUnalloc)(vboxGlobalData *data, vboxIIDUnion *iidu); + void (*vboxIIDToUUID)(vboxGlobalData *data, vboxIIDUnion *iidu, unsigned char *uuid); + void (*vboxIIDFromUUID)(vboxGlobalData *data, vboxIIDUnion *iidu, const unsigned char *uuid); + bool (*vboxIIDIsEqual)(vboxGlobalData *data, vboxIIDUnion *iidu1, vboxIIDUnion *iidu2); + void (*vboxIIDFromArrayItem)(vboxGlobalData *data, vboxIIDUnion *iidu, vboxArray *array, int idx); + void (*DEBUGIID)(const char *msg, vboxIIDUnion *iidu); +} vboxUniformedIID; + /* Functions for IVirtualBox */ typedef struct { nsresult (*GetVersion)(IVirtualBox *vboxObj, PRUnichar **versionUtf16); + nsresult (*GetMachine)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine); } vboxUniformedIVirtualBox; +/* Functions for ISession */ +typedef struct { + nsresult (*OpenExisting)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine); + nsresult (*GetConsole)(ISession *session, IConsole **console); + nsresult (*Close)(ISession *session); +} vboxUniformedISession; + +/* Functions for IConsole */ +typedef struct { + nsresult (*SaveState)(IConsole *console, IProgress **progress); +} vboxUniformedIConsole; + +/* Functions for IProgress */ +typedef struct { + nsresult (*WaitForCompletion)(IProgress *progress, PRInt32 timeout); + nsresult (*GetResultCode)(IProgress *progress, resultCodeUnion *resultCode); +} vboxUniformedIProgress; + +/* Functions for nsISupports */ +typedef struct { + nsresult (*Release)(void *Ihandle); +} vboxUniformednsISupports; + typedef struct { /* vbox API version */ uint32_t APIVersion; @@ -121,10 +196,16 @@ typedef struct { int (*initializeFWatch)(vboxGlobalData *data); void (*registerGlobalData)(vboxGlobalData *data); vboxUniformedPFN UPFN; + vboxUniformedIID UIID; vboxUniformedIVirtualBox UIVirtualBox; + vboxUniformedISession UISession; + vboxUniformedIConsole UIConsole; + vboxUniformedIProgress UIProgress; + vboxUniformednsISupports nsUISupports; /* vbox API features */ bool fWatchNeedInitialize; bool domainEventCallbacks; + bool getMachineForSession; } vboxUniformedAPI; /* libvirt API @@ -135,6 +216,7 @@ virDrvOpenStatus vboxConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags); int vboxConnectClose(virConnectPtr conn); +int vboxDomainSave(virDomainPtr dom, const char *path); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 22 ++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 13 ------------- src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index a74a1de..3edadce 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -393,3 +393,25 @@ vboxDomainSave(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED) vboxIIDUnalloc(&iid); return ret; } + +static void vboxDriverLock(vboxGlobalData *data) +{ + virMutexLock(&data->lock); +} + +static void vboxDriverUnlock(vboxGlobalData *data) +{ + virMutexUnlock(&data->lock); +} + +int vboxConnectGetVersion(virConnectPtr conn, unsigned long *version) +{ + vboxGlobalData *data = conn->privateData; + VIR_DEBUG("%s: in vboxGetVersion", conn->driver->name); + + vboxDriverLock(data); + *version = data->version; + vboxDriverUnlock(data); + + return 0; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 54a84bb..34ac5fc 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -911,19 +911,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxConnectGetVersion(virConnectPtr conn, unsigned long *version) -{ - vboxGlobalData *data = conn->privateData; - VIR_DEBUG("%s: in vboxGetVersion", conn->driver->name); - - vboxDriverLock(data); - *version = data->version; - vboxDriverUnlock(data); - - return 0; -} - - static char *vboxConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED) { return virGetHostname(); diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 44bb3bc..94afe16 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -217,6 +217,7 @@ virDrvOpenStatus vboxConnectOpen(virConnectPtr conn, unsigned int flags); int vboxConnectClose(virConnectPtr conn); int vboxDomainSave(virDomainPtr dom, const char *path); +int vboxConnectGetVersion(virConnectPtr conn, unsigned long *version); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 5 +++++ src/vbox/vbox_tmpl.c | 6 ------ src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 3edadce..2588379 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -415,3 +415,8 @@ int vboxConnectGetVersion(virConnectPtr conn, unsigned long *version) return 0; } + +char *vboxConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED) +{ + return virGetHostname(); +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 34ac5fc..12da7d2 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -911,12 +911,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static char *vboxConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED) -{ - return virGetHostname(); -} - - static int vboxConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED) { /* Driver is using local, non-network based transport */ diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 94afe16..8c44f01 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -218,6 +218,7 @@ virDrvOpenStatus vboxConnectOpen(virConnectPtr conn, int vboxConnectClose(virConnectPtr conn); int vboxDomainSave(virDomainPtr dom, const char *path); int vboxConnectGetVersion(virConnectPtr conn, unsigned long *version); +char *vboxConnectGetHostname(virConnectPtr conn); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 6 ++++++ src/vbox/vbox_tmpl.c | 6 ------ src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 2588379..cdc3664 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -420,3 +420,9 @@ char *vboxConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED) { return virGetHostname(); } + +int vboxConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED) +{ + /* Driver is using local, non-network based transport */ + return 1; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 12da7d2..745e1d0 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -911,12 +911,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED) -{ - /* Driver is using local, non-network based transport */ - return 1; -} - static int vboxConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED) { /* No encryption is needed, or used on the local transport*/ diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 8c44f01..f09eda4 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -219,6 +219,7 @@ int vboxConnectClose(virConnectPtr conn); int vboxDomainSave(virDomainPtr dom, const char *path); int vboxConnectGetVersion(virConnectPtr conn, unsigned long *version); char *vboxConnectGetHostname(virConnectPtr conn); +int vboxConnectIsSecure(virConnectPtr conn); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 6 ++++++ src/vbox/vbox_tmpl.c | 6 ------ src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index cdc3664..188b878 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -426,3 +426,9 @@ int vboxConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED) /* Driver is using local, non-network based transport */ return 1; } + +int vboxConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED) +{ + /* No encryption is needed, or used on the local transport*/ + return 0; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 745e1d0..a1d3918 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -911,12 +911,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED) -{ - /* No encryption is needed, or used on the local transport*/ - return 0; -} - static int vboxConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED) { return 1; diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index f09eda4..0d46a7a 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -220,6 +220,7 @@ int vboxDomainSave(virDomainPtr dom, const char *path); int vboxConnectGetVersion(virConnectPtr conn, unsigned long *version); char *vboxConnectGetHostname(virConnectPtr conn); int vboxConnectIsSecure(virConnectPtr conn); +int vboxConnectIsEncrypted(virConnectPtr conn); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 5 +++++ src/vbox/vbox_tmpl.c | 5 ----- src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 188b878..f380c78 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -432,3 +432,8 @@ int vboxConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED) /* No encryption is needed, or used on the local transport*/ return 0; } + +int vboxConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED) +{ + return 1; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index a1d3918..e08d7cc 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -911,11 +911,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED) -{ - return 1; -} - static int vboxConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED) { diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 0d46a7a..e586c3c 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -221,6 +221,7 @@ int vboxConnectGetVersion(virConnectPtr conn, unsigned long *version); char *vboxConnectGetHostname(virConnectPtr conn); int vboxConnectIsSecure(virConnectPtr conn); int vboxConnectIsEncrypted(virConnectPtr conn); +int vboxConnectIsAlive(virConnectPtr conn); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 24 +++++++++++++++++++++++ src/vbox/vbox_common.h | 1 + src/vbox/vbox_tmpl.c | 42 ++++++++++++++++++----------------------- src/vbox/vbox_uniformed_api.h | 8 ++++++++ 4 files changed, 51 insertions(+), 24 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index f380c78..1c67eea 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -437,3 +437,27 @@ int vboxConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED) { return 1; } + +int +vboxConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED) +{ + VBOX_OBJECT_CHECK(conn, int, -1); + PRUint32 maxCPUCount = 0; + + /* VirtualBox Supports only hvm and thus the type passed to it + * has no meaning, setting it to ATTRIBUTE_UNUSED + */ + ISystemProperties *systemProperties = NULL; + + gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties); + if (!systemProperties) + goto cleanup; + gVBoxAPI.UISystemProperties.GetMaxGuestCPUCount(systemProperties, &maxCPUCount); + + if (maxCPUCount > 0) + ret = maxCPUCount; + + cleanup: + VBOX_RELEASE(systemProperties); + return ret; +} diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h index aa6be11..e01fa51 100644 --- a/src/vbox/vbox_common.h +++ b/src/vbox/vbox_common.h @@ -166,6 +166,7 @@ typedef void ISession; typedef void IConsole; typedef void IProgress; typedef void IMachine; +typedef void ISystemProperties; typedef void IVirtualBoxCallback; typedef void nsIEventQueue; diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index e08d7cc..e17b06f 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -911,30 +911,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int -vboxConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED) -{ - VBOX_OBJECT_CHECK(conn, int, -1); - PRUint32 maxCPUCount = 0; - - /* VirtualBox Supports only hvm and thus the type passed to it - * has no meaning, setting it to ATTRIBUTE_UNUSED - */ - ISystemProperties *systemProperties = NULL; - - data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties); - if (systemProperties) { - systemProperties->vtbl->GetMaxGuestCPUCount(systemProperties, &maxCPUCount); - VBOX_RELEASE(systemProperties); - } - - if (maxCPUCount > 0) - ret = maxCPUCount; - - return ret; -} - - static char *vboxConnectGetCapabilities(virConnectPtr conn) { VBOX_OBJECT_CHECK(conn, char *, NULL); @@ -11340,6 +11316,12 @@ _virtualboxGetMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machi #endif /* VBOX_API_VERSION >= 4000000 */ +static nsresult +_virtualboxGetSystemProperties(IVirtualBox *vboxObj, ISystemProperties **systemProperties) +{ + return vboxObj->vtbl->GetSystemProperties(vboxObj, systemProperties); +} + #if VBOX_API_VERSION < 4000000 static nsresult @@ -11398,6 +11380,12 @@ _progressGetResultCode(IProgress *progress, resultCodeUnion *resultCode) #endif /* VBOX_API_VERSION != 2002000 */ } +static nsresult +_systemPropertiesGetMaxGuestCPUCount(ISystemProperties *systemProperties, PRUint32 *maxCPUCount) +{ + return systemProperties->vtbl->GetMaxGuestCPUCount(systemProperties, maxCPUCount); +} + static nsresult _nsisupportsRelease(void *Ihandle) { /* It is safety to convert a pointer from IVirtual(or structs @@ -11429,6 +11417,7 @@ static vboxUniformedIID _UIID = { static vboxUniformedIVirtualBox _UIVirtualBox = { .GetVersion = _virtualboxGetVersion, .GetMachine = _virtualboxGetMachine, + .GetSystemProperties = _virtualboxGetSystemProperties, }; static vboxUniformedISession _UISession = { @@ -11446,6 +11435,10 @@ static vboxUniformedIProgress _UIProgress = { .GetResultCode = _progressGetResultCode, }; +static vboxUniformedISystemProperties _UISystemProperties = { + .GetMaxGuestCPUCount = _systemPropertiesGetMaxGuestCPUCount, +}; + static vboxUniformednsISupports _nsUISupports = { .Release = _nsisupportsRelease, }; @@ -11462,6 +11455,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->UISession = _UISession; pVBoxAPI->UIConsole = _UIConsole; pVBoxAPI->UIProgress = _UIProgress; + pVBoxAPI->UISystemProperties = _UISystemProperties; pVBoxAPI->nsUISupports = _nsUISupports; #if (VBOX_XPCOMC_VERSION == 0x00010000U) || (VBOX_API_VERSION == 2002000) diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index e586c3c..4bd0cf7 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -163,6 +163,7 @@ typedef struct { typedef struct { nsresult (*GetVersion)(IVirtualBox *vboxObj, PRUnichar **versionUtf16); nsresult (*GetMachine)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine); + nsresult (*GetSystemProperties)(IVirtualBox *vboxObj, ISystemProperties **systemProperties); } vboxUniformedIVirtualBox; /* Functions for ISession */ @@ -183,6 +184,11 @@ typedef struct { nsresult (*GetResultCode)(IProgress *progress, resultCodeUnion *resultCode); } vboxUniformedIProgress; +/* Functions for ISystemProperties */ +typedef struct { + nsresult (*GetMaxGuestCPUCount)(ISystemProperties *systemProperties, PRUint32 *maxCPUCount); +} vboxUniformedISystemProperties; + /* Functions for nsISupports */ typedef struct { nsresult (*Release)(void *Ihandle); @@ -201,6 +207,7 @@ typedef struct { vboxUniformedISession UISession; vboxUniformedIConsole UIConsole; vboxUniformedIProgress UIProgress; + vboxUniformedISystemProperties UISystemProperties; vboxUniformednsISupports nsUISupports; /* vbox API features */ bool fWatchNeedInitialize; @@ -222,6 +229,7 @@ char *vboxConnectGetHostname(virConnectPtr conn); int vboxConnectIsSecure(virConnectPtr conn); int vboxConnectIsEncrypted(virConnectPtr conn); int vboxConnectIsAlive(virConnectPtr conn); +int vboxConnectGetMaxVcpus(virConnectPtr conn, const char *type); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 11 +++++++++++ src/vbox/vbox_tmpl.c | 16 ++++++---------- src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 1c67eea..ed6597c 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -461,3 +461,14 @@ vboxConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED) VBOX_RELEASE(systemProperties); return ret; } + +char *vboxConnectGetCapabilities(virConnectPtr conn) +{ + VBOX_OBJECT_CHECK(conn, char *, NULL); + + vboxDriverLock(data); + ret = virCapabilitiesFormatXML(data->caps); + vboxDriverUnlock(data); + + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index e17b06f..569ae29 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -253,6 +253,10 @@ static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml); static int vboxDomainCreate(virDomainPtr dom); static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags); +#if VBOX_API_VERSION > 2002000 && VBOX_API_VERSION < 4000000 +/* Since vboxConnectGetCapabilities has been rewriten, + * vboxDiverLock and Unlock only be used in 3.* */ + static void vboxDriverLock(vboxGlobalData *data) { virMutexLock(&data->lock); @@ -263,6 +267,8 @@ static void vboxDriverUnlock(vboxGlobalData *data) virMutexUnlock(&data->lock); } +#endif + #if VBOX_API_VERSION == 2002000 static void nsIDtoChar(unsigned char *uuid, const nsID *iid) @@ -911,16 +917,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static char *vboxConnectGetCapabilities(virConnectPtr conn) { - VBOX_OBJECT_CHECK(conn, char *, NULL); - - vboxDriverLock(data); - ret = virCapabilitiesFormatXML(data->caps); - vboxDriverUnlock(data); - - return ret; -} - static int vboxConnectListDomains(virConnectPtr conn, int *ids, int nids) { VBOX_OBJECT_CHECK(conn, int, -1); diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 4bd0cf7..18f6870 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -230,6 +230,7 @@ int vboxConnectIsSecure(virConnectPtr conn); int vboxConnectIsEncrypted(virConnectPtr conn); int vboxConnectIsAlive(virConnectPtr conn); int vboxConnectGetMaxVcpus(virConnectPtr conn, const char *type); +char *vboxConnectGetCapabilities(virConnectPtr conn); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 42 ++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 80 +++++++++++++++++++++-------------------- src/vbox/vbox_uniformed_api.h | 22 ++++++++++++ 3 files changed, 105 insertions(+), 39 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index ed6597c..8eedd4d 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -96,6 +96,10 @@ if (!data->vboxObj) {\ #define VBOX_IID_INITIALIZE(iid) gVBoxAPI.UIID.vboxIIDInitialize(iid) +#define ARRAY_GET_MACHINES \ + (gVBoxAPI.UArray.handleGetMachines(data->vboxObj)) + + /* global vbox API, used for all common codes. */ static vboxUniformedAPI gVBoxAPI; @@ -472,3 +476,41 @@ char *vboxConnectGetCapabilities(virConnectPtr conn) return ret; } + +int vboxConnectListDomains(virConnectPtr conn, int *ids, int nids) +{ + VBOX_OBJECT_CHECK(conn, int, -1); + vboxArray machines = VBOX_ARRAY_INITIALIZER; + PRUint32 state; + nsresult rc; + size_t i, j; + + rc = gVBoxAPI.UArray.vboxArrayGet(&machines, data->vboxObj, ARRAY_GET_MACHINES); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get list of Domains, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + + ret = 0; + for (i = 0, j = 0; (i < machines.count) && (j < nids); ++i) { + IMachine *machine = machines.items[i]; + + if (machine) { + PRBool isAccessible = PR_FALSE; + gVBoxAPI.UIMachine.GetAccessible(machine, &isAccessible); + if (isAccessible) { + gVBoxAPI.UIMachine.GetState(machine, &state); + if (gVBoxAPI.machineStateChecker.Online(state)) { + ret++; + ids[j++] = i + 1; + } + } + } + } + + cleanup: + gVBoxAPI.UArray.vboxArrayRelease(&machines); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 569ae29..1138566 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -917,45 +917,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxConnectListDomains(virConnectPtr conn, int *ids, int nids) -{ - VBOX_OBJECT_CHECK(conn, int, -1); - vboxArray machines = VBOX_ARRAY_INITIALIZER; - PRUint32 state; - nsresult rc; - size_t i, j; - - rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not get list of Domains, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - - ret = 0; - for (i = 0, j = 0; (i < machines.count) && (j < nids); ++i) { - IMachine *machine = machines.items[i]; - - if (machine) { - PRBool isAccessible = PR_FALSE; - machine->vtbl->GetAccessible(machine, &isAccessible); - if (isAccessible) { - machine->vtbl->GetState(machine, &state); - if ((state >= MachineState_FirstOnline) && - (state <= MachineState_LastOnline)) { - ret++; - ids[j++] = i + 1; - } - } - } - } - - cleanup: - vboxArrayRelease(&machines); - return ret; -} - static int vboxConnectNumOfDomains(virConnectPtr conn) { VBOX_OBJECT_CHECK(conn, int, -1); @@ -11288,6 +11249,11 @@ static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu) #endif /* VBOX_API_VERSION != 2002000 */ +static void* _handleGetMachines(IVirtualBox *vboxObj) +{ + return vboxObj->vtbl->GetMachines; +} + static nsresult _virtualboxGetVersion(IVirtualBox *vboxObj, PRUnichar **versionUtf16) { @@ -11318,6 +11284,18 @@ _virtualboxGetSystemProperties(IVirtualBox *vboxObj, ISystemProperties **systemP return vboxObj->vtbl->GetSystemProperties(vboxObj, systemProperties); } +static nsresult +_machineGetAccessible(IMachine *machine, PRBool *isAccessible) +{ + return machine->vtbl->GetAccessible(machine, isAccessible); +} + +static nsresult +_machineGetState(IMachine *machine, PRUint32 *state) +{ + return machine->vtbl->GetState(machine, state); +} + #if VBOX_API_VERSION < 4000000 static nsresult @@ -11390,6 +11368,12 @@ static nsresult _nsisupportsRelease(void *Ihandle) return nsi->vtbl->Release(nsi); } +static bool _machineStateOnline(PRUint32 state) +{ + return ((state >= MachineState_FirstOnline) && + (state <= MachineState_LastOnline)); +} + static vboxUniformedPFN _UPFN = { .Initialize = _pfnInitialize, .Uninitialize = _pfnUninitialize, @@ -11410,12 +11394,23 @@ static vboxUniformedIID _UIID = { .DEBUGIID = _DEBUGIID, }; +static vboxUniformedArray _UArray = { + .vboxArrayGet = vboxArrayGet, + .vboxArrayRelease = vboxArrayRelease, + .handleGetMachines = _handleGetMachines, +}; + static vboxUniformedIVirtualBox _UIVirtualBox = { .GetVersion = _virtualboxGetVersion, .GetMachine = _virtualboxGetMachine, .GetSystemProperties = _virtualboxGetSystemProperties, }; +static vboxUniformedIMachine _UIMachine = { + .GetAccessible = _machineGetAccessible, + .GetState = _machineGetState, +}; + static vboxUniformedISession _UISession = { .OpenExisting = _sessionOpenExisting, .GetConsole = _sessionGetConsole, @@ -11439,6 +11434,10 @@ static vboxUniformednsISupports _nsUISupports = { .Release = _nsisupportsRelease, }; +static uniformedMachineStateChecker _machineStateChecker = { + .Online = _machineStateOnline, +}; + void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) { pVBoxAPI->APIVersion = VBOX_API_VERSION; @@ -11447,12 +11446,15 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->registerGlobalData = _registerGlobalData; pVBoxAPI->UPFN = _UPFN; pVBoxAPI->UIID = _UIID; + pVBoxAPI->UArray = _UArray; pVBoxAPI->UIVirtualBox = _UIVirtualBox; + pVBoxAPI->UIMachine = _UIMachine; pVBoxAPI->UISession = _UISession; pVBoxAPI->UIConsole = _UIConsole; pVBoxAPI->UIProgress = _UIProgress; pVBoxAPI->UISystemProperties = _UISystemProperties; pVBoxAPI->nsUISupports = _nsUISupports; + pVBoxAPI->machineStateChecker = _machineStateChecker; #if (VBOX_XPCOMC_VERSION == 0x00010000U) || (VBOX_API_VERSION == 2002000) /* No event queue functionality in 2.2.* as of now */ diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 18f6870..1035ce8 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -159,6 +159,14 @@ typedef struct { void (*DEBUGIID)(const char *msg, vboxIIDUnion *iidu); } vboxUniformedIID; +/* Functions for vboxArray */ +typedef struct { + nsresult (*vboxArrayGet)(vboxArray *array, void *self, void *getter); + void (*vboxArrayRelease)(vboxArray *array); + /* Generate function pointers for vboxArrayGet */ + void* (*handleGetMachines)(IVirtualBox *vboxObj); +} vboxUniformedArray; + /* Functions for IVirtualBox */ typedef struct { nsresult (*GetVersion)(IVirtualBox *vboxObj, PRUnichar **versionUtf16); @@ -166,6 +174,12 @@ typedef struct { nsresult (*GetSystemProperties)(IVirtualBox *vboxObj, ISystemProperties **systemProperties); } vboxUniformedIVirtualBox; +/* Functions for IMachine */ +typedef struct { + nsresult (*GetAccessible)(IMachine *machine, PRBool *isAccessible); + nsresult (*GetState)(IMachine *machine, PRUint32 *state); +} vboxUniformedIMachine; + /* Functions for ISession */ typedef struct { nsresult (*OpenExisting)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine); @@ -195,6 +209,10 @@ typedef struct { } vboxUniformednsISupports; typedef struct { + bool (*Online)(PRUint32 state); +} uniformedMachineStateChecker; + +typedef struct { /* vbox API version */ uint32_t APIVersion; uint32_t XPCOMCVersion; @@ -203,12 +221,15 @@ typedef struct { void (*registerGlobalData)(vboxGlobalData *data); vboxUniformedPFN UPFN; vboxUniformedIID UIID; + vboxUniformedArray UArray; vboxUniformedIVirtualBox UIVirtualBox; + vboxUniformedIMachine UIMachine; vboxUniformedISession UISession; vboxUniformedIConsole UIConsole; vboxUniformedIProgress UIProgress; vboxUniformedISystemProperties UISystemProperties; vboxUniformednsISupports nsUISupports; + uniformedMachineStateChecker machineStateChecker; /* vbox API features */ bool fWatchNeedInitialize; bool domainEventCallbacks; @@ -231,6 +252,7 @@ int vboxConnectIsEncrypted(virConnectPtr conn); int vboxConnectIsAlive(virConnectPtr conn); int vboxConnectGetMaxVcpus(virConnectPtr conn, const char *type); char *vboxConnectGetCapabilities(virConnectPtr conn); +int vboxConnectListDomains(virConnectPtr conn, int *ids, int nids); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 35 +++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 36 ------------------------------------ src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 8eedd4d..4acf0c8 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -514,3 +514,38 @@ int vboxConnectListDomains(virConnectPtr conn, int *ids, int nids) gVBoxAPI.UArray.vboxArrayRelease(&machines); return ret; } + +int vboxConnectNumOfDomains(virConnectPtr conn) +{ + VBOX_OBJECT_CHECK(conn, int, -1); + vboxArray machines = VBOX_ARRAY_INITIALIZER; + PRUint32 state; + nsresult rc; + size_t i; + + rc = gVBoxAPI.UArray.vboxArrayGet(&machines, data->vboxObj, ARRAY_GET_MACHINES); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get number of Domains, rc=%08x"), (unsigned)rc); + goto cleanup; + } + + ret = 0; + for (i = 0; i < machines.count; ++i) { + IMachine *machine = machines.items[i]; + + if (machine) { + PRBool isAccessible = PR_FALSE; + gVBoxAPI.UIMachine.GetAccessible(machine, &isAccessible); + if (isAccessible) { + gVBoxAPI.UIMachine.GetState(machine, &state); + if (gVBoxAPI.machineStateChecker.Online(state)) + ret++; + } + } + } + + cleanup: + gVBoxAPI.UArray.vboxArrayRelease(&machines); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 1138566..ffd523f 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -917,42 +917,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxConnectNumOfDomains(virConnectPtr conn) -{ - VBOX_OBJECT_CHECK(conn, int, -1); - vboxArray machines = VBOX_ARRAY_INITIALIZER; - PRUint32 state; - nsresult rc; - size_t i; - - rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not get number of Domains, rc=%08x"), (unsigned)rc); - goto cleanup; - } - - ret = 0; - for (i = 0; i < machines.count; ++i) { - IMachine *machine = machines.items[i]; - - if (machine) { - PRBool isAccessible = PR_FALSE; - machine->vtbl->GetAccessible(machine, &isAccessible); - if (isAccessible) { - machine->vtbl->GetState(machine, &state); - if ((state >= MachineState_FirstOnline) && - (state <= MachineState_LastOnline)) - ret++; - } - } - } - - cleanup: - vboxArrayRelease(&machines); - return ret; -} - static virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml, unsigned int flags) { diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 1035ce8..78dd1e7 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -253,6 +253,7 @@ int vboxConnectIsAlive(virConnectPtr conn); int vboxConnectGetMaxVcpus(virConnectPtr conn, const char *type); char *vboxConnectGetCapabilities(virConnectPtr conn); int vboxConnectListDomains(virConnectPtr conn, int *ids, int nids); +int vboxConnectNumOfDomains(virConnectPtr conn); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 73 ++++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 82 +++++++---------------------------------- src/vbox/vbox_uniformed_api.h | 3 ++ 3 files changed, 90 insertions(+), 68 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 4acf0c8..51e07eb 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -549,3 +549,76 @@ int vboxConnectNumOfDomains(virConnectPtr conn) gVBoxAPI.UArray.vboxArrayRelease(&machines); return ret; } + +virDomainPtr vboxDomainLookupByID(virConnectPtr conn, int id) +{ + VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL); + vboxArray machines = VBOX_ARRAY_INITIALIZER; + IMachine *machine; + PRBool isAccessible = PR_FALSE; + PRUnichar *machineNameUtf16 = NULL; + char *machineNameUtf8 = NULL; + vboxIIDUnion iid; + unsigned char uuid[VIR_UUID_BUFLEN]; + PRUint32 state; + nsresult rc; + + VBOX_IID_INITIALIZE(&iid); + /* Internal vbox IDs start from 0, the public libvirt ID + * starts from 1, so refuse id == 0, and adjust the rest*/ + if (id == 0) { + virReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching id %d"), id); + return NULL; + } + id = id - 1; + + rc = gVBoxAPI.UArray.vboxArrayGet(&machines, data->vboxObj, ARRAY_GET_MACHINES); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get list of machines, rc=%08x"), (unsigned)rc); + return NULL; + } + + if (id >= machines.count) + goto cleanup; + + machine = machines.items[id]; + + if (!machine) + goto cleanup; + + isAccessible = PR_FALSE; + gVBoxAPI.UIMachine.GetAccessible(machine, &isAccessible); + if (!isAccessible) + goto cleanup; + + gVBoxAPI.UIMachine.GetState(machine, &state); + if (!gVBoxAPI.machineStateChecker.Online(state)) + goto cleanup; + + gVBoxAPI.UIMachine.GetName(machine, &machineNameUtf16); + VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8); + + gVBoxAPI.UIMachine.GetId(machine, &iid); + vboxIIDToUUID(&iid, uuid); + vboxIIDUnalloc(&iid); + + /* get a new domain pointer from virGetDomain, if it fails + * then no need to assign the id, else assign the id, cause + * it is -1 by default. rest is taken care by virGetDomain + * itself, so need not worry. + */ + + ret = virGetDomain(conn, machineNameUtf8, uuid); + if (ret) + ret->id = id + 1; + + /* Cleanup all the XPCOM allocated stuff here */ + VBOX_UTF8_FREE(machineNameUtf8); + VBOX_UTF16_FREE(machineNameUtf16); + + cleanup: + gVBoxAPI.UArray.vboxArrayRelease(&machines); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index ffd523f..6c3e070 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -945,74 +945,6 @@ static virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml, return dom; } -static virDomainPtr vboxDomainLookupByID(virConnectPtr conn, int id) -{ - VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL); - vboxArray machines = VBOX_ARRAY_INITIALIZER; - vboxIID iid = VBOX_IID_INITIALIZER; - unsigned char uuid[VIR_UUID_BUFLEN]; - PRUint32 state; - nsresult rc; - - /* Internal vbox IDs start from 0, the public libvirt ID - * starts from 1, so refuse id == 0, and adjust the rest*/ - if (id == 0) { - virReportError(VIR_ERR_NO_DOMAIN, - _("no domain with matching id %d"), id); - return NULL; - } - id = id - 1; - - rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not get list of machines, rc=%08x"), (unsigned)rc); - return NULL; - } - - if (id < machines.count) { - IMachine *machine = machines.items[id]; - - if (machine) { - PRBool isAccessible = PR_FALSE; - machine->vtbl->GetAccessible(machine, &isAccessible); - if (isAccessible) { - machine->vtbl->GetState(machine, &state); - if ((state >= MachineState_FirstOnline) && - (state <= MachineState_LastOnline)) { - PRUnichar *machineNameUtf16 = NULL; - char *machineNameUtf8 = NULL; - - machine->vtbl->GetName(machine, &machineNameUtf16); - VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8); - - machine->vtbl->GetId(machine, &iid.value); - vboxIIDToUUID(&iid, uuid); - vboxIIDUnalloc(&iid); - - /* get a new domain pointer from virGetDomain, if it fails - * then no need to assign the id, else assign the id, cause - * it is -1 by default. rest is taken care by virGetDomain - * itself, so need not worry. - */ - - ret = virGetDomain(conn, machineNameUtf8, uuid); - if (ret) - ret->id = id + 1; - - /* Cleanup all the XPCOM allocated stuff here */ - VBOX_UTF8_FREE(machineNameUtf8); - VBOX_UTF16_FREE(machineNameUtf16); - } - } - } - } - - vboxArrayRelease(&machines); - - return ret; -} - static virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { @@ -11260,6 +11192,18 @@ _machineGetState(IMachine *machine, PRUint32 *state) return machine->vtbl->GetState(machine, state); } +static nsresult +_machineGetName(IMachine *machine, PRUnichar **name) +{ + return machine->vtbl->GetName(machine, name); +} + +static nsresult +_machineGetId(IMachine *machine, vboxIIDUnion *iidu) +{ + return machine->vtbl->GetId(machine, &IID_MEMBER(value)); +} + #if VBOX_API_VERSION < 4000000 static nsresult @@ -11373,6 +11317,8 @@ static vboxUniformedIVirtualBox _UIVirtualBox = { static vboxUniformedIMachine _UIMachine = { .GetAccessible = _machineGetAccessible, .GetState = _machineGetState, + .GetName = _machineGetName, + .GetId = _machineGetId, }; static vboxUniformedISession _UISession = { diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 78dd1e7..2e264c0 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -178,6 +178,8 @@ typedef struct { typedef struct { nsresult (*GetAccessible)(IMachine *machine, PRBool *isAccessible); nsresult (*GetState)(IMachine *machine, PRUint32 *state); + nsresult (*GetName)(IMachine *machine, PRUnichar **name); + nsresult (*GetId)(IMachine *machine, vboxIIDUnion *iidu); } vboxUniformedIMachine; /* Functions for ISession */ @@ -254,6 +256,7 @@ int vboxConnectGetMaxVcpus(virConnectPtr conn, const char *type); char *vboxConnectGetCapabilities(virConnectPtr conn); int vboxConnectListDomains(virConnectPtr conn, int *ids, int nids); int vboxConnectNumOfDomains(virConnectPtr conn); +virDomainPtr vboxDomainLookupByID(virConnectPtr conn, int id); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 73 +++++++++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 73 ----------------------------------------- src/vbox/vbox_uniformed_api.h | 2 ++ 3 files changed, 75 insertions(+), 73 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 51e07eb..8993519 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -622,3 +622,76 @@ virDomainPtr vboxDomainLookupByID(virConnectPtr conn, int id) gVBoxAPI.UArray.vboxArrayRelease(&machines); return ret; } + +virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn, + const unsigned char *uuid) +{ + VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL); + vboxArray machines = VBOX_ARRAY_INITIALIZER; + vboxIIDUnion iid; + char *machineNameUtf8 = NULL; + PRUnichar *machineNameUtf16 = NULL; + unsigned char iid_as_uuid[VIR_UUID_BUFLEN]; + size_t i; + int matched = 0; + nsresult rc; + + VBOX_IID_INITIALIZE(&iid); + rc = gVBoxAPI.UArray.vboxArrayGet(&machines, data->vboxObj, ARRAY_GET_MACHINES); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get list of machines, rc=%08x"), (unsigned)rc); + return NULL; + } + + for (i = 0; i < machines.count; ++i) { + IMachine *machine = machines.items[i]; + PRBool isAccessible = PR_FALSE; + + if (!machine) + continue; + + gVBoxAPI.UIMachine.GetAccessible(machine, &isAccessible); + if (!isAccessible) + continue; + + rc = gVBoxAPI.UIMachine.GetId(machine, &iid); + if (NS_FAILED(rc)) + continue; + vboxIIDToUUID(&iid, iid_as_uuid); + vboxIIDUnalloc(&iid); + + if (memcmp(uuid, iid_as_uuid, VIR_UUID_BUFLEN) == 0) { + + PRUint32 state; + + matched = 1; + + gVBoxAPI.UIMachine.GetName(machine, &machineNameUtf16); + VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8); + + gVBoxAPI.UIMachine.GetState(machine, &state); + + /* get a new domain pointer from virGetDomain, if it fails + * then no need to assign the id, else assign the id, cause + * it is -1 by default. rest is taken care by virGetDomain + * itself, so need not worry. + */ + + ret = virGetDomain(conn, machineNameUtf8, iid_as_uuid); + if (ret && + gVBoxAPI.machineStateChecker.Online(state)) + ret->id = i + 1; + } + + if (matched == 1) + break; + } + + /* Do the cleanup and take care you dont leak any memory */ + VBOX_UTF8_FREE(machineNameUtf8); + VBOX_COM_UNALLOC_MEM(machineNameUtf16); + gVBoxAPI.UArray.vboxArrayRelease(&machines); + + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 6c3e070..219e44a 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -946,79 +946,6 @@ static virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml, } static virDomainPtr -vboxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) -{ - VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL); - vboxArray machines = VBOX_ARRAY_INITIALIZER; - vboxIID iid = VBOX_IID_INITIALIZER; - char *machineNameUtf8 = NULL; - PRUnichar *machineNameUtf16 = NULL; - unsigned char iid_as_uuid[VIR_UUID_BUFLEN]; - size_t i; - int matched = 0; - nsresult rc; - - rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not get list of machines, rc=%08x"), (unsigned)rc); - return NULL; - } - - for (i = 0; i < machines.count; ++i) { - IMachine *machine = machines.items[i]; - PRBool isAccessible = PR_FALSE; - - if (!machine) - continue; - - machine->vtbl->GetAccessible(machine, &isAccessible); - if (isAccessible) { - - rc = machine->vtbl->GetId(machine, &iid.value); - if (NS_FAILED(rc)) - continue; - vboxIIDToUUID(&iid, iid_as_uuid); - vboxIIDUnalloc(&iid); - - if (memcmp(uuid, iid_as_uuid, VIR_UUID_BUFLEN) == 0) { - - PRUint32 state; - - matched = 1; - - machine->vtbl->GetName(machine, &machineNameUtf16); - VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8); - - machine->vtbl->GetState(machine, &state); - - /* get a new domain pointer from virGetDomain, if it fails - * then no need to assign the id, else assign the id, cause - * it is -1 by default. rest is taken care by virGetDomain - * itself, so need not worry. - */ - - ret = virGetDomain(conn, machineNameUtf8, iid_as_uuid); - if (ret && - (state >= MachineState_FirstOnline) && - (state <= MachineState_LastOnline)) - ret->id = i + 1; - } - - if (matched == 1) - break; - } - } - - /* Do the cleanup and take care you dont leak any memory */ - VBOX_UTF8_FREE(machineNameUtf8); - VBOX_COM_UNALLOC_MEM(machineNameUtf16); - vboxArrayRelease(&machines); - - return ret; -} - -static virDomainPtr vboxDomainLookupByName(virConnectPtr conn, const char *name) { VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL); diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 2e264c0..3ab98b5 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -257,6 +257,8 @@ char *vboxConnectGetCapabilities(virConnectPtr conn); int vboxConnectListDomains(virConnectPtr conn, int *ids, int nids); int vboxConnectNumOfDomains(virConnectPtr conn); virDomainPtr vboxDomainLookupByID(virConnectPtr conn, int id); +virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn, + const unsigned char *uuid); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 67 ++++++++ src/vbox/vbox_tmpl.c | 356 +++++++++++++++++++++-------------------- src/vbox/vbox_uniformed_api.h | 8 + 3 files changed, 255 insertions(+), 176 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 8993519..436b6b0 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -27,6 +27,7 @@ #include "virlog.h" #include "viralloc.h" #include "nodeinfo.h" +#include "virstring.h" #include "vbox_common.h" #include "vbox_uniformed_api.h" @@ -695,3 +696,69 @@ virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn, return ret; } + +static void +detachDevices_common(vboxGlobalData *data, vboxIIDUnion *iidu) +{ + /* Block for checking if HDD's are attched to VM. + * considering just IDE bus for now. Also skipped + * chanel=1 and device=0 (Secondary Master) as currenlty + * it is allocated to CD/DVD Drive by default. + * + * Only do this for VirtualBox 3.x and before. Since + * VirtualBox 4.0 the Unregister method can do this for use. + */ + IMachine *machine = NULL; + PRUnichar *hddcnameUtf16 = NULL; + nsresult rc; + + char *hddcname; + ignore_value(VIR_STRDUP(hddcname, "IDE")); + VBOX_UTF8_TO_UTF16(hddcname, &hddcnameUtf16); + VIR_FREE(hddcname); + + /* Open a Session for the machine */ + rc = gVBoxAPI.UISession.Open(data, iidu, machine); + if (NS_SUCCEEDED(rc)) { + rc = gVBoxAPI.UISession.GetMachine(data->vboxSession, &machine); + if (NS_SUCCEEDED(rc) && machine) { + gVBoxAPI.detachDevices(data, machine, hddcnameUtf16); + gVBoxAPI.UIMachine.SaveSettings(machine); + } + gVBoxAPI.UISession.Close(data->vboxSession); + } + VBOX_UTF16_FREE(hddcnameUtf16); +} + +int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IMachine *machine = NULL; + vboxIIDUnion iid; + nsresult rc; + + gVBoxAPI.UIID.vboxIIDInitialize(&iid); + /* No managed save, so we explicitly reject + * VIR_DOMAIN_UNDEFINE_MANAGED_SAVE. No snapshot metadata for + * VBox, so we can trivially ignore that flag. */ + virCheckFlags(VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1); + vboxIIDFromUUID(&iid, dom->uuid); + if (gVBoxAPI.detachDevicesExplicitly) + detachDevices_common(data, &iid); + rc = gVBoxAPI.unregisterMachine(data, &iid, &machine); + + DEBUGIID("UUID of machine being undefined", &iid); + + if (NS_SUCCEEDED(rc)) { + gVBoxAPI.deleteConfig(machine); + ret = 0; + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not delete the domain, rc=%08x"), (unsigned)rc); + } + + vboxIIDUnalloc(&iid); + VBOX_RELEASE(machine); + + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 219e44a..315feba 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -251,7 +251,6 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL; static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml); static int vboxDomainCreate(virDomainPtr dom); -static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags); #if VBOX_API_VERSION > 2002000 && VBOX_API_VERSION < 4000000 /* Since vboxConnectGetCapabilities has been rewriten, @@ -4781,181 +4780,6 @@ static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml) } static int -vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IMachine *machine = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - nsresult rc; -#if VBOX_API_VERSION >= 4000000 - vboxArray media = VBOX_ARRAY_INITIALIZER; -#endif - /* No managed save, so we explicitly reject - * VIR_DOMAIN_UNDEFINE_MANAGED_SAVE. No snapshot metadata for - * VBox, so we can trivially ignore that flag. */ - virCheckFlags(VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1); - - vboxIIDFromUUID(&iid, dom->uuid); - -#if VBOX_API_VERSION < 4000000 - /* Block for checking if HDD's are attched to VM. - * considering just IDE bus for now. Also skipped - * chanel=1 and device=0 (Secondary Master) as currenlty - * it is allocated to CD/DVD Drive by default. - * - * Only do this for VirtualBox 3.x and before. Since - * VirtualBox 4.0 the Unregister method can do this for use. - */ - { - PRUnichar *hddcnameUtf16 = NULL; - - char *hddcname; - ignore_value(VIR_STRDUP(hddcname, "IDE")); - VBOX_UTF8_TO_UTF16(hddcname, &hddcnameUtf16); - VIR_FREE(hddcname); - - /* Open a Session for the machine */ - rc = VBOX_SESSION_OPEN(iid.value, machine); - if (NS_SUCCEEDED(rc)) { - rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); - if (NS_SUCCEEDED(rc) && machine) { - -# if VBOX_API_VERSION < 3001000 - /* Disconnect all the drives if present */ - machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 0, 0); - machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 0, 1); - machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 1, 1); -# else /* VBOX_API_VERSION >= 3001000 */ - /* get all the controller first, then the attachments and - * remove them all so that the machine can be undefined - */ - vboxArray storageControllers = VBOX_ARRAY_INITIALIZER; - size_t i = 0, j = 0; - - vboxArrayGet(&storageControllers, machine, - machine->vtbl->GetStorageControllers); - - for (i = 0; i < storageControllers.count; i++) { - IStorageController *strCtl = storageControllers.items[i]; - PRUnichar *strCtlName = NULL; - vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER; - - if (!strCtl) - continue; - - strCtl->vtbl->GetName(strCtl, &strCtlName); - vboxArrayGetWithPtrArg(&mediumAttachments, machine, - machine->vtbl->GetMediumAttachmentsOfController, - strCtlName); - - for (j = 0; j < mediumAttachments.count; j++) { - IMediumAttachment *medAtt = mediumAttachments.items[j]; - PRInt32 port = ~0U; - PRInt32 device = ~0U; - - if (!medAtt) - continue; - - medAtt->vtbl->GetPort(medAtt, &port); - medAtt->vtbl->GetDevice(medAtt, &device); - - if ((port != ~0U) && (device != ~0U)) { - machine->vtbl->DetachDevice(machine, - strCtlName, - port, - device); - } - } - - vboxArrayRelease(&storageControllers); - - machine->vtbl->RemoveStorageController(machine, strCtlName); - VBOX_UTF16_FREE(strCtlName); - } - - vboxArrayRelease(&storageControllers); -# endif /* VBOX_API_VERSION >= 3001000 */ - - machine->vtbl->SaveSettings(machine); - } - VBOX_SESSION_CLOSE(); - } - VBOX_UTF16_FREE(hddcnameUtf16); - } -#endif - -#if VBOX_API_VERSION < 4000000 - rc = data->vboxObj->vtbl->UnregisterMachine(data->vboxObj, iid.value, &machine); -#else /* VBOX_API_VERSION >= 4000000 */ - rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching uuid")); - return -1; - } - - /* We're not interested in the array returned by the Unregister method, - * but in the side effect of unregistering the virtual machine. In order - * to call the Unregister method correctly we need to use the vboxArray - * wrapper here. */ - rc = vboxArrayGetWithUintArg(&media, machine, machine->vtbl->Unregister, - CleanupMode_DetachAllReturnNone); -#endif /* VBOX_API_VERSION >= 4000000 */ - DEBUGIID("UUID of machine being undefined", iid.value); - - if (NS_SUCCEEDED(rc)) { -#if VBOX_API_VERSION < 4000000 - machine->vtbl->DeleteSettings(machine); -#else /* VBOX_API_VERSION >= 4000000 */ - IProgress *progress = NULL; - - /* The IMachine Delete method takes an array of IMedium items to be - * deleted along with the virtual machine. We just want to pass an - * empty array. But instead of adding a full vboxArraySetWithReturn to - * the glue layer (in order to handle the required signature of the - * Delete method) we use a local solution here. */ -# ifdef WIN32 - SAFEARRAY *safeArray = NULL; - typedef HRESULT __stdcall (*IMachine_Delete)(IMachine *self, - SAFEARRAY **media, - IProgress **progress); - -# if VBOX_API_VERSION < 4003000 - ((IMachine_Delete)machine->vtbl->Delete)(machine, &safeArray, &progress); -# else - ((IMachine_Delete)machine->vtbl->DeleteConfig)(machine, &safeArray, &progress); -# endif -# else - /* XPCOM doesn't like NULL as an array, even when the array size is 0. - * Instead pass it a dummy array to avoid passing NULL. */ - IMedium *array[] = { NULL }; -# if VBOX_API_VERSION < 4003000 - machine->vtbl->Delete(machine, 0, array, &progress); -# else - machine->vtbl->DeleteConfig(machine, 0, array, &progress); -# endif -# endif - if (progress != NULL) { - progress->vtbl->WaitForCompletion(progress, -1); - VBOX_RELEASE(progress); - } -#endif /* VBOX_API_VERSION >= 4000000 */ - ret = 0; - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not delete the domain, rc=%08x"), (unsigned)rc); - } - -#if VBOX_API_VERSION >= 4000000 - vboxArrayUnalloc(&media); -#endif - vboxIIDUnalloc(&iid); - VBOX_RELEASE(machine); - - return ret; -} - -static int vboxDomainUndefine(virDomainPtr dom) { return vboxDomainUndefineFlags(dom, 0); @@ -11010,6 +10834,154 @@ void _registerGlobalData(vboxGlobalData *data ATTRIBUTE_UNUSED) #endif /* VBOX_API_VERSION != 2002000 */ } +#if VBOX_API_VERSION < 4000000 + +# if VBOX_API_VERSION < 3001000 +static void +_detachDevices(vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine, PRUnichar *hddcnameUtf16) +{ + /* Disconnect all the drives if present */ + machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 0, 0); + machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 0, 1); + machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 1, 1); +} +# else /* VBOX_API_VERSION >= 3001000 */ +static void +_detachDevices(vboxGlobalData *data, IMachine *machine, + PRUnichar *hddcnameUtf16 ATTRIBUTE_UNUSED) +{ + /* get all the controller first, then the attachments and + * remove them all so that the machine can be undefined + */ + vboxArray storageControllers = VBOX_ARRAY_INITIALIZER; + size_t i = 0, j = 0; + + vboxArrayGet(&storageControllers, machine, + machine->vtbl->GetStorageControllers); + + for (i = 0; i < storageControllers.count; i++) { + IStorageController *strCtl = storageControllers.items[i]; + PRUnichar *strCtlName = NULL; + vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER; + + if (!strCtl) + continue; + + strCtl->vtbl->GetName(strCtl, &strCtlName); + vboxArrayGetWithPtrArg(&mediumAttachments, machine, + machine->vtbl->GetMediumAttachmentsOfController, + strCtlName); + + for (j = 0; j < mediumAttachments.count; j++) { + IMediumAttachment *medAtt = mediumAttachments.items[j]; + PRInt32 port = ~0U; + PRInt32 device = ~0U; + + if (!medAtt) + continue; + + medAtt->vtbl->GetPort(medAtt, &port); + medAtt->vtbl->GetDevice(medAtt, &device); + + if ((port != ~0U) && (device != ~0U)) { + machine->vtbl->DetachDevice(machine, + strCtlName, + port, + device); + } + } + vboxArrayRelease(&storageControllers); + machine->vtbl->RemoveStorageController(machine, strCtlName); + VBOX_UTF16_FREE(strCtlName); + } + vboxArrayRelease(&storageControllers); +} +# endif /* VBOX_API_VERSION >= 3001000 */ + +static nsresult +_unregisterMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine) +{ + return data->vboxObj->vtbl->UnregisterMachine(data->vboxObj, IID_MEMBER(value), machine); +} + +static void +_deleteConfig(IMachine *machine) +{ + machine->vtbl->DeleteSettings(machine); +} + +#else /* VBOX_API_VERSION >= 4000000 */ + +static void +_detachDevices(vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine ATTRIBUTE_UNUSED, + PRUnichar *hddcnameUtf16 ATTRIBUTE_UNUSED) +{ + VIR_WARN("There is no detachDevice in current version"); +} + +static nsresult +_unregisterMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine) +{ + nsresult rc; + vboxArray media = VBOX_ARRAY_INITIALIZER; + rc = VBOX_OBJECT_GET_MACHINE(IID_MEMBER(value), machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + return rc; + } + + /* We're not interested in the array returned by the Unregister method, + * but in the side effect of unregistering the virtual machine. In order + * to call the Unregister method correctly we need to use the vboxArray + * wrapper here. */ + rc = vboxArrayGetWithUintArg(&media, *machine, (*machine)->vtbl->Unregister, + CleanupMode_DetachAllReturnNone); + vboxArrayUnalloc(&media); + return rc; +} + +static void +_deleteConfig(IMachine *machine) +{ + IProgress *progress = NULL; + + /* The IMachine Delete method takes an array of IMedium items to be + * deleted along with the virtual machine. We just want to pass an + * empty array. But instead of adding a full vboxArraySetWithReturn to + * the glue layer (in order to handle the required signature of the + * Delete method) we use a local solution here. */ +# ifdef WIN32 + SAFEARRAY *safeArray = NULL; + typedef HRESULT __stdcall (*IMachine_Delete)(IMachine *self, + SAFEARRAY **media, + IProgress **progress); + +# if VBOX_API_VERSION < 4003000 + ((IMachine_Delete)machine->vtbl->Delete)(machine, &safeArray, &progress); +# else + ((IMachine_Delete)machine->vtbl->DeleteConfig)(machine, &safeArray, &progress); +# endif +# else + /* XPCOM doesn't like NULL as an array, even when the array size is 0. + * Instead pass it a dummy array to avoid passing NULL. */ + IMedium *array[] = { NULL }; +# if VBOX_API_VERSION < 4003000 + machine->vtbl->Delete(machine, 0, array, &progress); +# else + machine->vtbl->DeleteConfig(machine, 0, array, &progress); +# endif +# endif + if (progress != NULL) { + progress->vtbl->WaitForCompletion(progress, -1); + VBOX_RELEASE(progress); + } +} + +#endif /* VBOX_API_VERSION >= 4000000 */ + static void _pfnUninitialize(vboxGlobalData *data) { if (data->pFuncs) @@ -11131,9 +11103,21 @@ _machineGetId(IMachine *machine, vboxIIDUnion *iidu) return machine->vtbl->GetId(machine, &IID_MEMBER(value)); } +static nsresult +_machineSaveSettings(IMachine *machine) +{ + return machine->vtbl->SaveSettings(machine); +} + #if VBOX_API_VERSION < 4000000 static nsresult +_sessionOpen(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED) +{ + return data->vboxObj->vtbl->OpenSession(data->vboxObj, data->vboxSession, IID_MEMBER(value)); +} + +static nsresult _sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED) { return data->vboxObj->vtbl->OpenExistingSession(data->vboxObj, data->vboxSession, IID_MEMBER(value)); @@ -11148,6 +11132,12 @@ _sessionClose(ISession *session) #else /* VBOX_API_VERSION >= 4000000 */ static nsresult +_sessionOpen(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine) +{ + return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Write); +} + +static nsresult _sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine) { return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Shared); @@ -11168,6 +11158,12 @@ _sessionGetConsole(ISession *session, IConsole **console) } static nsresult +_sessionGetMachine(ISession *session, IMachine **machine) +{ + return session->vtbl->GetMachine(session, machine); +} + +static nsresult _consoleSaveState(IConsole *console, IProgress **progress) { return console->vtbl->SaveState(console, progress); @@ -11246,11 +11242,14 @@ static vboxUniformedIMachine _UIMachine = { .GetState = _machineGetState, .GetName = _machineGetName, .GetId = _machineGetId, + .SaveSettings = _machineSaveSettings, }; static vboxUniformedISession _UISession = { + .Open = _sessionOpen, .OpenExisting = _sessionOpenExisting, .GetConsole = _sessionGetConsole, + .GetMachine = _sessionGetMachine, .Close = _sessionClose, }; @@ -11281,6 +11280,9 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->XPCOMCVersion = VBOX_XPCOMC_VERSION; pVBoxAPI->initializeFWatch = _initializeFWatch; pVBoxAPI->registerGlobalData = _registerGlobalData; + pVBoxAPI->detachDevices = _detachDevices; + pVBoxAPI->unregisterMachine = _unregisterMachine; + pVBoxAPI->deleteConfig = _deleteConfig; pVBoxAPI->UPFN = _UPFN; pVBoxAPI->UIID = _UIID; pVBoxAPI->UArray = _UArray; @@ -11309,8 +11311,10 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) #if VBOX_API_VERSION >= 4000000 /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */ pVBoxAPI->getMachineForSession = 1; + pVBoxAPI->detachDevicesExplicitly = 0; #else /* VBOX_API_VERSION < 4000000 */ pVBoxAPI->getMachineForSession = 0; + pVBoxAPI->detachDevicesExplicitly = 1; #endif /* VBOX_API_VERSION < 4000000 */ } diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 3ab98b5..e68add6 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -180,12 +180,15 @@ typedef struct { nsresult (*GetState)(IMachine *machine, PRUint32 *state); nsresult (*GetName)(IMachine *machine, PRUnichar **name); nsresult (*GetId)(IMachine *machine, vboxIIDUnion *iidu); + nsresult (*SaveSettings)(IMachine *machine); } vboxUniformedIMachine; /* Functions for ISession */ typedef struct { + nsresult (*Open)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine); nsresult (*OpenExisting)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine); nsresult (*GetConsole)(ISession *session, IConsole **console); + nsresult (*GetMachine)(ISession *session, IMachine **machine); nsresult (*Close)(ISession *session); } vboxUniformedISession; @@ -221,6 +224,9 @@ typedef struct { /* vbox APIs */ int (*initializeFWatch)(vboxGlobalData *data); void (*registerGlobalData)(vboxGlobalData *data); + void (*detachDevices)(vboxGlobalData *data, IMachine *machine, PRUnichar *hddcnameUtf16); + nsresult (*unregisterMachine)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine); + void (*deleteConfig)(IMachine *machine); vboxUniformedPFN UPFN; vboxUniformedIID UIID; vboxUniformedArray UArray; @@ -236,6 +242,7 @@ typedef struct { bool fWatchNeedInitialize; bool domainEventCallbacks; bool getMachineForSession; + bool detachDevicesExplicitly; } vboxUniformedAPI; /* libvirt API @@ -259,6 +266,7 @@ int vboxConnectNumOfDomains(virConnectPtr conn); virDomainPtr vboxDomainLookupByID(virConnectPtr conn, int id); virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid); +int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

This is a huge patch. (Maybe the biggest one during rewriting vbox drivers.) It contains lots of device settings in this function, like AttachDrivers, AttachNetwork and so on. The good news is that the method to rewrite is the existing one. There is nothing new but mechanical code moving jobs. --- src/vbox/vbox_common.c | 1166 ++++++++++++++++++++++++++ src/vbox/vbox_common.h | 88 ++ src/vbox/vbox_tmpl.c | 1827 ++++++++++++++++++----------------------- src/vbox/vbox_uniformed_api.h | 148 ++++ 4 files changed, 2211 insertions(+), 1018 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 436b6b0..0d57b2c 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -80,6 +80,14 @@ VIR_LOG_INIT("vbox.vbox_common"); } \ } while (0) +#define VBOX_MEDIUM_RELEASE(arg) \ + do { \ + if (arg) { \ + gVBoxAPI.UIMedium.Release(arg); \ + (arg) = NULL; \ + } \ + } while (0) + #define VBOX_OBJECT_CHECK(conn, type, value) \ vboxGlobalData *data = conn->privateData;\ type ret = value;\ @@ -150,6 +158,123 @@ static int openSessionForMachine(vboxGlobalData *data, const unsigned char *dom_ return 0; } +/** + * function to get the values for max port per + * instance and max slots per port for the devices + * + * @returns true on Success, false on failure. + * @param vbox Input IVirtualBox pointer + * @param maxPortPerInst Output array of max port per instance + * @param maxSlotPerPort Output array of max slot per port + * + */ + +static bool vboxGetMaxPortSlotValues(IVirtualBox *vbox, + PRUint32 *maxPortPerInst, + PRUint32 *maxSlotPerPort) +{ + ISystemProperties *sysProps = NULL; + + if (!vbox) + return false; + + gVBoxAPI.UIVirtualBox.GetSystemProperties(vbox, &sysProps); + + if (!sysProps) + return false; + + gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps, + StorageBus_IDE, + &maxPortPerInst[StorageBus_IDE]); + gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps, + StorageBus_SATA, + &maxPortPerInst[StorageBus_SATA]); + gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps, + StorageBus_SCSI, + &maxPortPerInst[StorageBus_SCSI]); + gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps, + StorageBus_Floppy, + &maxPortPerInst[StorageBus_Floppy]); + + gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps, + StorageBus_IDE, + &maxSlotPerPort[StorageBus_IDE]); + gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps, + StorageBus_SATA, + &maxSlotPerPort[StorageBus_SATA]); + gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps, + StorageBus_SCSI, + &maxSlotPerPort[StorageBus_SCSI]); + gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps, + StorageBus_Floppy, + &maxSlotPerPort[StorageBus_Floppy]); + + VBOX_RELEASE(sysProps); + + return true; +} + +/** + * function to get the StorageBus, Port number + * and Device number for the given devicename + * e.g: hda has StorageBus = IDE, port = 0, + * device = 0 + * + * @returns true on Success, false on failure. + * @param deviceName Input device name + * @param aMaxPortPerInst Input array of max port per device instance + * @param aMaxSlotPerPort Input array of max slot per device port + * @param storageBus Input storage bus type + * @param deviceInst Output device instance number + * @param devicePort Output port number + * @param deviceSlot Output slot number + * + */ +static bool vboxGetDeviceDetails(const char *deviceName, + PRUint32 *aMaxPortPerInst, + PRUint32 *aMaxSlotPerPort, + PRUint32 storageBus, + PRInt32 *deviceInst, + PRInt32 *devicePort, + PRInt32 *deviceSlot) { + int total = 0; + PRUint32 maxPortPerInst = 0; + PRUint32 maxSlotPerPort = 0; + + if (!deviceName || + !deviceInst || + !devicePort || + !deviceSlot || + !aMaxPortPerInst || + !aMaxSlotPerPort) + return false; + + if ((storageBus < StorageBus_IDE) || + (storageBus > StorageBus_Floppy)) + return false; + + total = virDiskNameToIndex(deviceName); + + maxPortPerInst = aMaxPortPerInst[storageBus]; + maxSlotPerPort = aMaxSlotPerPort[storageBus]; + + if (!maxPortPerInst || + !maxSlotPerPort || + (total < 0)) + return false; + + *deviceInst = total / (maxPortPerInst * maxSlotPerPort); + *devicePort = (total % (maxPortPerInst * maxSlotPerPort)) / maxSlotPerPort; + *deviceSlot = (total % (maxPortPerInst * maxSlotPerPort)) % maxSlotPerPort; + + VIR_DEBUG("name=%s, total=%d, storageBus=%u, deviceInst=%d, " + "devicePort=%d deviceSlot=%d, maxPortPerInst=%u maxSlotPerPort=%u", + deviceName, total, storageBus, *deviceInst, *devicePort, + *deviceSlot, maxPortPerInst, maxSlotPerPort); + + return true; +} + static virDomainDefParserConfig vboxDomainDefParserConfig = { .macPrefix = { 0x08, 0x00, 0x27 }, }; @@ -698,6 +823,1047 @@ virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn, } static void +vboxSetBootDeviceOrder(virDomainDefPtr def, vboxGlobalData *data, + IMachine *machine) +{ + ISystemProperties *systemProperties = NULL; + PRUint32 maxBootPosition = 0; + size_t i = 0; + + VIR_DEBUG("def->os.type %s", def->os.type); + VIR_DEBUG("def->os.arch %s", virArchToString(def->os.arch)); + VIR_DEBUG("def->os.machine %s", def->os.machine); + VIR_DEBUG("def->os.nBootDevs %zu", def->os.nBootDevs); + VIR_DEBUG("def->os.bootDevs[0] %d", def->os.bootDevs[0]); + VIR_DEBUG("def->os.bootDevs[1] %d", def->os.bootDevs[1]); + VIR_DEBUG("def->os.bootDevs[2] %d", def->os.bootDevs[2]); + VIR_DEBUG("def->os.bootDevs[3] %d", def->os.bootDevs[3]); + VIR_DEBUG("def->os.init %s", def->os.init); + VIR_DEBUG("def->os.kernel %s", def->os.kernel); + VIR_DEBUG("def->os.initrd %s", def->os.initrd); + VIR_DEBUG("def->os.cmdline %s", def->os.cmdline); + VIR_DEBUG("def->os.root %s", def->os.root); + VIR_DEBUG("def->os.loader %s", def->os.loader); + VIR_DEBUG("def->os.bootloader %s", def->os.bootloader); + VIR_DEBUG("def->os.bootloaderArgs %s", def->os.bootloaderArgs); + + gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties); + if (systemProperties) { + gVBoxAPI.UISystemProperties.GetMaxBootPosition(systemProperties, + &maxBootPosition); + VBOX_RELEASE(systemProperties); + } + + /* Clear the defaults first */ + for (i = 0; i < maxBootPosition; i++) { + gVBoxAPI.UIMachine.SetBootOrder(machine, i+1, DeviceType_Null); + } + + for (i = 0; (i < def->os.nBootDevs) && (i < maxBootPosition); i++) { + PRUint32 device = DeviceType_Null; + + if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_FLOPPY) { + device = DeviceType_Floppy; + } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_CDROM) { + device = DeviceType_DVD; + } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_DISK) { + device = DeviceType_HardDisk; + } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_NET) { + device = DeviceType_Network; + } + gVBoxAPI.UIMachine.SetBootOrder(machine, i+1, device); + } +} + +static void +vboxAttachDrivesNew(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + /* AttachDrives for 3.0 and later */ + size_t i; + nsresult rc; + PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {}; + PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {}; + PRUnichar *storageCtlName = NULL; + bool error = false; + + /* get the max port/slots/etc for the given storage bus */ + error = !vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, + maxSlotPerPort); + + /* add a storage controller for the mediums to be attached */ + /* this needs to change when multiple controller are supported for + * ver > 3.1 */ + { + IStorageController *storageCtl = NULL; + PRUnichar *sName = NULL; + + VBOX_UTF8_TO_UTF16("IDE Controller", &sName); + gVBoxAPI.UIMachine.AddStorageController(machine, + sName, + StorageBus_IDE, + &storageCtl); + VBOX_UTF16_FREE(sName); + VBOX_RELEASE(storageCtl); + + VBOX_UTF8_TO_UTF16("SATA Controller", &sName); + gVBoxAPI.UIMachine.AddStorageController(machine, + sName, + StorageBus_SATA, + &storageCtl); + VBOX_UTF16_FREE(sName); + VBOX_RELEASE(storageCtl); + + VBOX_UTF8_TO_UTF16("SCSI Controller", &sName); + gVBoxAPI.UIMachine.AddStorageController(machine, + sName, + StorageBus_SCSI, + &storageCtl); + VBOX_UTF16_FREE(sName); + VBOX_RELEASE(storageCtl); + + VBOX_UTF8_TO_UTF16("Floppy Controller", &sName); + gVBoxAPI.UIMachine.AddStorageController(machine, + sName, + StorageBus_Floppy, + &storageCtl); + VBOX_UTF16_FREE(sName); + VBOX_RELEASE(storageCtl); + } + + for (i = 0; i < def->ndisks && !error; i++) { + const char *src = virDomainDiskGetSource(def->disks[i]); + int type = virDomainDiskGetType(def->disks[i]); + int format = virDomainDiskGetFormat(def->disks[i]); + + VIR_DEBUG("disk(%zu) type: %d", i, type); + VIR_DEBUG("disk(%zu) device: %d", i, def->disks[i]->device); + VIR_DEBUG("disk(%zu) bus: %d", i, def->disks[i]->bus); + VIR_DEBUG("disk(%zu) src: %s", i, src); + VIR_DEBUG("disk(%zu) dst: %s", i, def->disks[i]->dst); + VIR_DEBUG("disk(%zu) driverName: %s", i, + virDomainDiskGetDriver(def->disks[i])); + VIR_DEBUG("disk(%zu) driverType: %s", i, + virStorageFileFormatTypeToString(format)); + VIR_DEBUG("disk(%zu) cachemode: %d", i, def->disks[i]->cachemode); + VIR_DEBUG("disk(%zu) readonly: %s", i, (def->disks[i]->src->readonly + ? "True" : "False")); + VIR_DEBUG("disk(%zu) shared: %s", i, (def->disks[i]->src->shared + ? "True" : "False")); + + if (type == VIR_STORAGE_TYPE_FILE && src) { + IMedium *medium = NULL; + vboxIIDUnion mediumUUID; + PRUnichar *mediumFileUtf16 = NULL; + PRUint32 storageBus = StorageBus_Null; + PRUint32 deviceType = DeviceType_Null; + PRUint32 accessMode = AccessMode_ReadOnly; + PRInt32 deviceInst = 0; + PRInt32 devicePort = 0; + PRInt32 deviceSlot = 0; + + VBOX_IID_INITIALIZE(&mediumUUID); + VBOX_UTF8_TO_UTF16(src, &mediumFileUtf16); + + if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) { + deviceType = DeviceType_HardDisk; + accessMode = AccessMode_ReadWrite; + } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { + deviceType = DeviceType_DVD; + accessMode = AccessMode_ReadOnly; + } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { + deviceType = DeviceType_Floppy; + accessMode = AccessMode_ReadWrite; + } else { + VBOX_UTF16_FREE(mediumFileUtf16); + continue; + } + + gVBoxAPI.UIVirtualBox.FindMedium(data->vboxObj, mediumFileUtf16, + deviceType, accessMode, &medium); + + if (!medium) { + PRUnichar *mediumEmpty = NULL; + + VBOX_UTF8_TO_UTF16("", &mediumEmpty); + + rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj, + mediumFileUtf16, + deviceType, accessMode, + &medium); + VBOX_UTF16_FREE(mediumEmpty); + } + + if (!medium) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to attach the following disk/dvd/floppy " + "to the machine: %s, rc=%08x"), + src, (unsigned)rc); + VBOX_UTF16_FREE(mediumFileUtf16); + continue; + } + + rc = gVBoxAPI.UIMedium.GetId(medium, &mediumUUID); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("can't get the uuid of the file to be attached " + "as harddisk/dvd/floppy: %s, rc=%08x"), + src, (unsigned)rc); + VBOX_MEDIUM_RELEASE(medium); + VBOX_UTF16_FREE(mediumFileUtf16); + continue; + } + + if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) { + if (def->disks[i]->src->readonly) { + gVBoxAPI.UIMedium.SetType(medium, MediumType_Immutable); + VIR_DEBUG("setting harddisk to immutable"); + } else if (!def->disks[i]->src->readonly) { + gVBoxAPI.UIMedium.SetType(medium, MediumType_Normal); + VIR_DEBUG("setting harddisk type to normal"); + } + } + + if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_IDE) { + VBOX_UTF8_TO_UTF16("IDE Controller", &storageCtlName); + storageBus = StorageBus_IDE; + } else if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_SATA) { + VBOX_UTF8_TO_UTF16("SATA Controller", &storageCtlName); + storageBus = StorageBus_SATA; + } else if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_SCSI) { + VBOX_UTF8_TO_UTF16("SCSI Controller", &storageCtlName); + storageBus = StorageBus_SCSI; + } else if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_FDC) { + VBOX_UTF8_TO_UTF16("Floppy Controller", &storageCtlName); + storageBus = StorageBus_Floppy; + } + + /* get the device details i.e instance, port and slot */ + if (!vboxGetDeviceDetails(def->disks[i]->dst, + maxPortPerInst, + maxSlotPerPort, + storageBus, + &deviceInst, + &devicePort, + &deviceSlot)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("can't get the port/slot number of " + "harddisk/dvd/floppy to be attached: " + "%s, rc=%08x"), + src, (unsigned)rc); + VBOX_MEDIUM_RELEASE(medium); + vboxIIDUnalloc(&mediumUUID); + VBOX_UTF16_FREE(mediumFileUtf16); + continue; + } + + /* attach the harddisk/dvd/Floppy to the storage controller */ + rc = gVBoxAPI.UIMachine.AttachDevice(machine, + storageCtlName, + devicePort, + deviceSlot, + deviceType, + medium); + + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not attach the file as " + "harddisk/dvd/floppy: %s, rc=%08x"), + src, (unsigned)rc); + } else { + DEBUGIID("Attached HDD/DVD/Floppy with UUID", &mediumUUID); + } + + VBOX_MEDIUM_RELEASE(medium); + vboxIIDUnalloc(&mediumUUID); + VBOX_UTF16_FREE(mediumFileUtf16); + VBOX_UTF16_FREE(storageCtlName); + } + } +} + +static void +vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + /* Here, About the vboxAttachDrives. In fact,there is + * three different implementations. We name it as + * v1, v2 and v3. + * + * The first version(v1) is only used in vbox 2.2 and 3.0, + * v2 is used by 3.1 and 3.2, and v3 is used for later + * vbox versions. In sight of implementation, the v1 is + * totally different with v2 and v3. The v2 shares the same + * outline with v3, meanwhile the API they used has much + * difference. + * + * It seems we have no thing to do with old versions such as + * v1 and v2 when developing new vbox drivers. What's more, + * most of the vbox APIs used in v1 and v2 is incompatible with + * new vbox versions. It is a burden to put these APIs into + * vboxUniformedAPI, I prefer not to do that. + * + * After balancing the code size and the complied code size, + * I put my solution here. The v1 and v2 is a version specified + * code, which only be generated for first four version. The v3 + * will be put in vbox_common.c, it be complied only once, then + * be used by all next vbox drivers. + * + * Check the flag vboxAttachDrivesUseOld can tell you which + * implementation to use. When the flag is set, we need use + * the old version though gVBoxAPI.vboxAttachDrivesOld. It + * will automatically point to v1 or v2 deponds on you version. + * If the flag is clear, just call vboxAttachDrivesNew, which + * is the v3 implementation. + */ + if (gVBoxAPI.vboxAttachDrivesUseOld) + gVBoxAPI.vboxAttachDrivesOld(def, data, machine); + else + vboxAttachDrivesNew(def, data, machine); +} + +static void +vboxAttachSound(virDomainDefPtr def, IMachine *machine) +{ + nsresult rc; + IAudioAdapter *audioAdapter = NULL; + + /* Check if def->nsounds is one as VirtualBox currently supports + * only one sound card + */ + if (def->nsounds != 1) + return; + + gVBoxAPI.UIMachine.GetAudioAdapter(machine, &audioAdapter); + if (!audioAdapter) + return; + + rc = gVBoxAPI.UIAudioAdapter.SetEnabled(audioAdapter, 1); + if (NS_FAILED(rc)) + goto cleanup; + + if (def->sounds[0]->model == VIR_DOMAIN_SOUND_MODEL_SB16) { + gVBoxAPI.UIAudioAdapter.SetAudioController(audioAdapter, + AudioControllerType_SB16); + } else + if (def->sounds[0]->model == VIR_DOMAIN_SOUND_MODEL_AC97) { + gVBoxAPI.UIAudioAdapter.SetAudioController(audioAdapter, + AudioControllerType_AC97); + } + + cleanup: + VBOX_RELEASE(audioAdapter); +} + +static void +vboxAttachNetwork(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + ISystemProperties *systemProperties = NULL; + PRUint32 chipsetType = ChipsetType_Null; + PRUint32 networkAdapterCount = 0; + size_t i = 0; + + if (gVBoxAPI.chipsetType) + gVBoxAPI.UIMachine.GetChipsetType(machine, &chipsetType); + + gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties); + if (systemProperties) { + gVBoxAPI.UISystemProperties.GetMaxNetworkAdapters(systemProperties, chipsetType, + &networkAdapterCount); + VBOX_RELEASE(systemProperties); + } + + VIR_DEBUG("Number of Network Cards to be connected: %zu", def->nnets); + VIR_DEBUG("Number of Network Cards available: %d", networkAdapterCount); + + for (i = 0; (i < def->nnets) && (i < networkAdapterCount); i++) { + INetworkAdapter *adapter = NULL; + PRUint32 adapterType = NetworkAdapterType_Null; + char macaddr[VIR_MAC_STRING_BUFLEN] = {0}; + char macaddrvbox[VIR_MAC_STRING_BUFLEN - 5] = {0}; + PRUnichar *MACAddress = NULL; + + virMacAddrFormat(&def->nets[i]->mac, macaddr); + snprintf(macaddrvbox, VIR_MAC_STRING_BUFLEN - 5, + "%02X%02X%02X%02X%02X%02X", + def->nets[i]->mac.addr[0], + def->nets[i]->mac.addr[1], + def->nets[i]->mac.addr[2], + def->nets[i]->mac.addr[3], + def->nets[i]->mac.addr[4], + def->nets[i]->mac.addr[5]); + macaddrvbox[VIR_MAC_STRING_BUFLEN - 6] = '\0'; + + VIR_DEBUG("NIC(%zu): Type: %d", i, def->nets[i]->type); + VIR_DEBUG("NIC(%zu): Model: %s", i, def->nets[i]->model); + VIR_DEBUG("NIC(%zu): Mac: %s", i, macaddr); + VIR_DEBUG("NIC(%zu): ifname: %s", i, def->nets[i]->ifname); + if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + VIR_DEBUG("NIC(%zu): name: %s", i, def->nets[i]->data.network.name); + } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_INTERNAL) { + VIR_DEBUG("NIC(%zu): name: %s", i, def->nets[i]->data.internal.name); + } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_USER) { + VIR_DEBUG("NIC(%zu): NAT.", i); + } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { + VIR_DEBUG("NIC(%zu): brname: %s", i, def->nets[i]->data.bridge.brname); + VIR_DEBUG("NIC(%zu): script: %s", i, def->nets[i]->script); + VIR_DEBUG("NIC(%zu): ipaddr: %s", i, def->nets[i]->data.bridge.ipaddr); + } + + gVBoxAPI.UIMachine.GetNetworkAdapter(machine, i, &adapter); + if (!adapter) + continue; + + gVBoxAPI.UINetworkAdapter.SetEnabled(adapter, 1); + + if (def->nets[i]->model) { + if (STRCASEEQ(def->nets[i]->model, "Am79C970A")) { + adapterType = NetworkAdapterType_Am79C970A; + } else if (STRCASEEQ(def->nets[i]->model, "Am79C973")) { + adapterType = NetworkAdapterType_Am79C973; + } else if (STRCASEEQ(def->nets[i]->model, "82540EM")) { + adapterType = NetworkAdapterType_I82540EM; + } else if (STRCASEEQ(def->nets[i]->model, "82545EM")) { + adapterType = NetworkAdapterType_I82545EM; + } else if (STRCASEEQ(def->nets[i]->model, "82543GC")) { + adapterType = NetworkAdapterType_I82543GC; + } else if (gVBoxAPI.APIVersion >= 3000051 && + STRCASEEQ(def->nets[i]->model, "virtio")) { + /* Only vbox 3.1 and later support NetworkAdapterType_Virto */ + adapterType = NetworkAdapterType_Virtio; + } + } else { + adapterType = NetworkAdapterType_Am79C973; + } + + gVBoxAPI.UINetworkAdapter.SetAdapterType(adapter, adapterType); + + if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { + PRUnichar *hostInterface = NULL; + /* Bridged Network */ + + gVBoxAPI.UINetworkAdapter.AttachToBridgedInterface(adapter); + + if (def->nets[i]->data.bridge.brname) { + VBOX_UTF8_TO_UTF16(def->nets[i]->data.bridge.brname, + &hostInterface); + gVBoxAPI.UINetworkAdapter.SetBridgedInterface(adapter, hostInterface); + VBOX_UTF16_FREE(hostInterface); + } + } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_INTERNAL) { + PRUnichar *internalNetwork = NULL; + /* Internal Network */ + + gVBoxAPI.UINetworkAdapter.AttachToInternalNetwork(adapter); + + if (def->nets[i]->data.internal.name) { + VBOX_UTF8_TO_UTF16(def->nets[i]->data.internal.name, + &internalNetwork); + gVBoxAPI.UINetworkAdapter.SetInternalNetwork(adapter, internalNetwork); + VBOX_UTF16_FREE(internalNetwork); + } + } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + PRUnichar *hostInterface = NULL; + /* Host Only Networking (currently only vboxnet0 available + * on *nix and mac, on windows you can create and configure + * as many as you want) + */ + gVBoxAPI.UINetworkAdapter.AttachToHostOnlyInterface(adapter); + + if (def->nets[i]->data.network.name) { + VBOX_UTF8_TO_UTF16(def->nets[i]->data.network.name, + &hostInterface); + gVBoxAPI.UINetworkAdapter.SetHostOnlyInterface(adapter, hostInterface); + VBOX_UTF16_FREE(hostInterface); + } + } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_USER) { + /* NAT */ + gVBoxAPI.UINetworkAdapter.AttachToNAT(adapter); + } else { + /* else always default to NAT if we don't understand + * what option is been passed to us + */ + gVBoxAPI.UINetworkAdapter.AttachToNAT(adapter); + } + + VBOX_UTF8_TO_UTF16(macaddrvbox, &MACAddress); + gVBoxAPI.UINetworkAdapter.SetMACAddress(adapter, MACAddress); + VBOX_UTF16_FREE(MACAddress); + } +} + +static void +vboxAttachSerial(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + ISystemProperties *systemProperties = NULL; + PRUint32 serialPortCount = 0; + size_t i = 0; + + gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties); + if (systemProperties) { + gVBoxAPI.UISystemProperties.GetSerialPortCount(systemProperties, + &serialPortCount); + VBOX_RELEASE(systemProperties); + } + + VIR_DEBUG("Number of Serial Ports to be connected: %zu", def->nserials); + VIR_DEBUG("Number of Serial Ports available: %d", serialPortCount); + + for (i = 0; (i < def->nserials) && (i < serialPortCount); i++) { + ISerialPort *serialPort = NULL; + PRUnichar *pathUtf16 = NULL; + + VIR_DEBUG("SerialPort(%zu): Type: %d", i, def->serials[i]->source.type); + VIR_DEBUG("SerialPort(%zu): target.port: %d", i, + def->serials[i]->target.port); + + gVBoxAPI.UIMachine.GetSerialPort(machine, i, &serialPort); + if (!serialPort) + continue; + + gVBoxAPI.UISerialPort.SetEnabled(serialPort, 1); + + if (def->serials[i]->source.data.file.path) { + VBOX_UTF8_TO_UTF16(def->serials[i]->source.data.file.path, + &pathUtf16); + gVBoxAPI.UISerialPort.SetPath(serialPort, pathUtf16); + } + + /* For now hard code the serial ports to COM1 and COM2, + * COM1 (Base Addr: 0x3F8 (decimal: 1016), IRQ: 4) + * COM2 (Base Addr: 0x2F8 (decimal: 760), IRQ: 3) + * TODO: make this more flexible + */ + /* TODO: to improve the libvirt XMl handling so + * that def->serials[i]->target.port shows real port + * and not always start at 0 + */ + if (def->serials[i]->target.port == 0) { + gVBoxAPI.UISerialPort.SetIRQ(serialPort, 4); + gVBoxAPI.UISerialPort.SetIOBase(serialPort, 1016); + VIR_DEBUG(" serialPort-%zu irq: %d, iobase 0x%x, path: %s", + i, 4, 1016, def->serials[i]->source.data.file.path); + } else if (def->serials[i]->target.port == 1) { + gVBoxAPI.UISerialPort.SetIRQ(serialPort, 3); + gVBoxAPI.UISerialPort.SetIOBase(serialPort, 760); + VIR_DEBUG(" serialPort-%zu irq: %d, iobase 0x%x, path: %s", + i, 3, 760, def->serials[i]->source.data.file.path); + } + + if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV) { + gVBoxAPI.UISerialPort.SetHostMode(serialPort, PortMode_HostDevice); + } else if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE) { + gVBoxAPI.UISerialPort.SetHostMode(serialPort, PortMode_HostPipe); + } else if (gVBoxAPI.APIVersion >= 2002051 && + def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE) { + /* PortMode RawFile is used for vbox 3.0 or later */ + gVBoxAPI.UISerialPort.SetHostMode(serialPort, PortMode_RawFile); + } else { + gVBoxAPI.UISerialPort.SetHostMode(serialPort, + PortMode_Disconnected); + } + + VBOX_RELEASE(serialPort); + VBOX_UTF16_FREE(pathUtf16); + } +} + +static void +vboxAttachParallel(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + ISystemProperties *systemProperties = NULL; + PRUint32 parallelPortCount = 0; + size_t i = 0; + + gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties); + if (systemProperties) { + gVBoxAPI.UISystemProperties.GetParallelPortCount(systemProperties, + ¶llelPortCount); + VBOX_RELEASE(systemProperties); + } + + VIR_DEBUG("Number of Parallel Ports to be connected: %zu", def->nparallels); + VIR_DEBUG("Number of Parallel Ports available: %d", parallelPortCount); + for (i = 0; (i < def->nparallels) && (i < parallelPortCount); i++) { + IParallelPort *parallelPort = NULL; + PRUnichar *pathUtf16 = NULL; + + VIR_DEBUG("ParallelPort(%zu): Type: %d", i, def->parallels[i]->source.type); + VIR_DEBUG("ParallelPort(%zu): target.port: %d", i, + def->parallels[i]->target.port); + + gVBoxAPI.UIMachine.GetParallelPort(machine, i, ¶llelPort); + if (!parallelPort) + continue; + + VBOX_UTF8_TO_UTF16(def->parallels[i]->source.data.file.path, &pathUtf16); + + /* For now hard code the parallel ports to + * LPT1 (Base Addr: 0x378 (decimal: 888), IRQ: 7) + * LPT2 (Base Addr: 0x278 (decimal: 632), IRQ: 5) + * TODO: make this more flexible + */ + if ((def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV) || + (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_PTY) || + (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE) || + (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE)) { + gVBoxAPI.UIParallelPort.SetPath(parallelPort, pathUtf16); + if (i == 0) { + gVBoxAPI.UIParallelPort.SetIRQ(parallelPort, 7); + gVBoxAPI.UIParallelPort.SetIOBase(parallelPort, 888); + VIR_DEBUG(" parallePort-%zu irq: %d, iobase 0x%x, path: %s", + i, 7, 888, def->parallels[i]->source.data.file.path); + } else if (i == 1) { + gVBoxAPI.UIParallelPort.SetIRQ(parallelPort, 5); + gVBoxAPI.UIParallelPort.SetIOBase(parallelPort, 632); + VIR_DEBUG(" parallePort-%zu irq: %d, iobase 0x%x, path: %s", + i, 5, 632, def->parallels[i]->source.data.file.path); + } + } + + /* like serial port, parallel port can't be enabled unless + * correct IRQ and IOBase values are specified. + */ + gVBoxAPI.UIParallelPort.SetEnabled(parallelPort, 1); + + VBOX_RELEASE(parallelPort); + VBOX_UTF16_FREE(pathUtf16); + } +} + +static void +vboxAttachVideo(virDomainDefPtr def, IMachine *machine) +{ + if ((def->nvideos == 1) && + (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_VBOX)) { + gVBoxAPI.UIMachine.SetVRAMSize(machine, + VIR_DIV_UP(def->videos[0]->vram, 1024)); + gVBoxAPI.UIMachine.SetMonitorCount(machine, def->videos[0]->heads); + if (def->videos[0]->accel) { + gVBoxAPI.UIMachine.SetAccelerate3DEnabled(machine, + def->videos[0]->accel->support3d); + if (gVBoxAPI.accelerate2DVideo) + gVBoxAPI.UIMachine.SetAccelerate2DVideoEnabled(machine, + def->videos[0]->accel->support2d); + } else { + gVBoxAPI.UIMachine.SetAccelerate3DEnabled(machine, 0); + if (gVBoxAPI.accelerate2DVideo) + gVBoxAPI.UIMachine.SetAccelerate2DVideoEnabled(machine, 0); + } + } +} + +static void +vboxAttachDisplay(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + int vrdpPresent = 0; + int sdlPresent = 0; + int guiPresent = 0; + char *guiDisplay = NULL; + char *sdlDisplay = NULL; + size_t i = 0; + + for (i = 0; i < def->ngraphics; i++) { + IVRDxServer *VRDxServer = NULL; + + if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_RDP) && + (vrdpPresent == 0)) { + + vrdpPresent = 1; + gVBoxAPI.UIMachine.GetVRDxServer(machine, &VRDxServer); + if (VRDxServer) { + const char *listenAddr + = virDomainGraphicsListenGetAddress(def->graphics[i], 0); + + gVBoxAPI.UIVRDxServer.SetEnabled(VRDxServer, PR_TRUE); + VIR_DEBUG("VRDP Support turned ON."); + + gVBoxAPI.UIVRDxServer.SetPorts(data, VRDxServer, def->graphics[i]); + + if (def->graphics[i]->data.rdp.replaceUser) { + gVBoxAPI.UIVRDxServer.SetReuseSingleConnection(VRDxServer, + PR_TRUE); + VIR_DEBUG("VRDP set to reuse single connection"); + } + + if (def->graphics[i]->data.rdp.multiUser) { + gVBoxAPI.UIVRDxServer.SetAllowMultiConnection(VRDxServer, + PR_TRUE); + VIR_DEBUG("VRDP set to allow multiple connection"); + } + + if (listenAddr) { + PRUnichar *netAddressUtf16 = NULL; + + VBOX_UTF8_TO_UTF16(listenAddr, &netAddressUtf16); + gVBoxAPI.UIVRDxServer.SetNetAddress(data, VRDxServer, + netAddressUtf16); + VIR_DEBUG("VRDP listen address is set to: %s", + listenAddr); + + VBOX_UTF16_FREE(netAddressUtf16); + } + + VBOX_RELEASE(VRDxServer); + } + } + + if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP) && + (guiPresent == 0)) { + guiPresent = 1; + if (VIR_STRDUP(guiDisplay, def->graphics[i]->data.desktop.display) < 0) { + /* just don't go to cleanup yet as it is ok to have + * guiDisplay as NULL and we check it below if it + * exist and then only use it there + */ + } + } + + if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) && + (sdlPresent == 0)) { + sdlPresent = 1; + if (VIR_STRDUP(sdlDisplay, def->graphics[i]->data.sdl.display) < 0) { + /* just don't go to cleanup yet as it is ok to have + * sdlDisplay as NULL and we check it below if it + * exist and then only use it there + */ + } + } + } + + if ((vrdpPresent == 1) && (guiPresent == 0) && (sdlPresent == 0)) { + /* store extradata key that frontend is set to vrdp */ + PRUnichar *keyTypeUtf16 = NULL; + PRUnichar *valueTypeUtf16 = NULL; + + VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); + VBOX_UTF8_TO_UTF16("vrdp", &valueTypeUtf16); + + gVBoxAPI.UIMachine.SetExtraData(machine, keyTypeUtf16, valueTypeUtf16); + + VBOX_UTF16_FREE(keyTypeUtf16); + VBOX_UTF16_FREE(valueTypeUtf16); + + } else if ((guiPresent == 0) && (sdlPresent == 1)) { + /* store extradata key that frontend is set to sdl */ + PRUnichar *keyTypeUtf16 = NULL; + PRUnichar *valueTypeUtf16 = NULL; + PRUnichar *keyDislpayUtf16 = NULL; + PRUnichar *valueDisplayUtf16 = NULL; + + VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); + VBOX_UTF8_TO_UTF16("sdl", &valueTypeUtf16); + + gVBoxAPI.UIMachine.SetExtraData(machine, keyTypeUtf16, valueTypeUtf16); + + VBOX_UTF16_FREE(keyTypeUtf16); + VBOX_UTF16_FREE(valueTypeUtf16); + + if (sdlDisplay) { + VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16); + VBOX_UTF8_TO_UTF16(sdlDisplay, &valueDisplayUtf16); + + gVBoxAPI.UIMachine.SetExtraData(machine, keyDislpayUtf16, + valueDisplayUtf16); + + VBOX_UTF16_FREE(keyDislpayUtf16); + VBOX_UTF16_FREE(valueDisplayUtf16); + } + + } else { + /* if all are set then default is gui, with vrdp turned on */ + PRUnichar *keyTypeUtf16 = NULL; + PRUnichar *valueTypeUtf16 = NULL; + PRUnichar *keyDislpayUtf16 = NULL; + PRUnichar *valueDisplayUtf16 = NULL; + + VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); + VBOX_UTF8_TO_UTF16("gui", &valueTypeUtf16); + + gVBoxAPI.UIMachine.SetExtraData(machine, keyTypeUtf16, valueTypeUtf16); + + VBOX_UTF16_FREE(keyTypeUtf16); + VBOX_UTF16_FREE(valueTypeUtf16); + + if (guiDisplay) { + VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16); + VBOX_UTF8_TO_UTF16(guiDisplay, &valueDisplayUtf16); + + gVBoxAPI.UIMachine.SetExtraData(machine, keyDislpayUtf16, + valueDisplayUtf16); + + VBOX_UTF16_FREE(keyDislpayUtf16); + VBOX_UTF16_FREE(valueDisplayUtf16); + } + } + + VIR_FREE(guiDisplay); + VIR_FREE(sdlDisplay); +} + +static void +vboxAttachUSB(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + IUSBCommon *USBCommon = NULL; + size_t i = 0; + bool isUSB = false; + nsresult rc; + + if (def->nhostdevs == 0) + return; + + /* Loop through the devices first and see if you + * have a USB Device, only if you have one then + * start the USB controller else just proceed as + * usual + */ + for (i = 0; i < def->nhostdevs; i++) { + if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + + if (def->hostdevs[i]->source.subsys.type != + VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) + continue; + + if (!def->hostdevs[i]->source.subsys.u.usb.vendor && + !def->hostdevs[i]->source.subsys.u.usb.product) + continue; + + VIR_DEBUG("USB Device detected, VendorId:0x%x, ProductId:0x%x", + def->hostdevs[i]->source.subsys.u.usb.vendor, + def->hostdevs[i]->source.subsys.u.usb.product); + isUSB = true; + break; + } + + if (!isUSB) + return; + + /* First Start the USB Controller and then loop + * to attach USB Devices to it + */ + rc = gVBoxAPI.UIMachine.GetUSBCommon(machine, &USBCommon); + if (NS_FAILED(rc) || !USBCommon) + return; + gVBoxAPI.UIUSBCommon.Enable(USBCommon); + + for (i = 0; i < def->nhostdevs; i++) { + char *filtername = NULL; + PRUnichar *filternameUtf16 = NULL; + IUSBDeviceFilter *filter = NULL; + PRUnichar *vendorIdUtf16 = NULL; + char vendorId[40] = {0}; + PRUnichar *productIdUtf16 = NULL; + char productId[40] = {0}; + + if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + + if (def->hostdevs[i]->source.subsys.type != + VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) + continue; + + /* Zero pad for nice alignment when fewer than 9999 + * devices. + */ + if (virAsprintf(&filtername, "filter%04zu", i) >= 0) { + VBOX_UTF8_TO_UTF16(filtername, &filternameUtf16); + VIR_FREE(filtername); + gVBoxAPI.UIUSBCommon.CreateDeviceFilter(USBCommon, + filternameUtf16, + &filter); + } + VBOX_UTF16_FREE(filternameUtf16); + + if (!filter) + continue; + + if (!def->hostdevs[i]->source.subsys.u.usb.vendor && + !def->hostdevs[i]->source.subsys.u.usb.product) + continue; + + if (def->hostdevs[i]->source.subsys.u.usb.vendor) { + snprintf(vendorId, sizeof(vendorId), "%x", + def->hostdevs[i]->source.subsys.u.usb.vendor); + VBOX_UTF8_TO_UTF16(vendorId, &vendorIdUtf16); + gVBoxAPI.UIUSBDeviceFilter.SetVendorId(filter, vendorIdUtf16); + VBOX_UTF16_FREE(vendorIdUtf16); + } + if (def->hostdevs[i]->source.subsys.u.usb.product) { + snprintf(productId, sizeof(productId), "%x", + def->hostdevs[i]->source.subsys.u.usb.product); + VBOX_UTF8_TO_UTF16(productId, &productIdUtf16); + gVBoxAPI.UIUSBDeviceFilter.SetProductId(filter, + productIdUtf16); + VBOX_UTF16_FREE(productIdUtf16); + } + gVBoxAPI.UIUSBDeviceFilter.SetActive(filter, 1); + gVBoxAPI.UIUSBCommon.InsertDeviceFilter(USBCommon, i, filter); + VBOX_RELEASE(filter); + } + + VBOX_RELEASE(USBCommon); +} + +static void +vboxAttachSharedFolder(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + size_t i; + PRUnichar *nameUtf16; + PRUnichar *hostPathUtf16; + PRBool writable; + + if (def->nfss == 0) + return; + + for (i = 0; i < def->nfss; i++) { + if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT) + continue; + + VBOX_UTF8_TO_UTF16(def->fss[i]->dst, &nameUtf16); + VBOX_UTF8_TO_UTF16(def->fss[i]->src, &hostPathUtf16); + writable = !def->fss[i]->readonly; + + gVBoxAPI.UIMachine.CreateSharedFolder(machine, nameUtf16, hostPathUtf16, + writable, PR_FALSE); + + VBOX_UTF16_FREE(nameUtf16); + VBOX_UTF16_FREE(hostPathUtf16); + } +} + +virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml) +{ + VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL); + IMachine *machine = NULL; + IBIOSSettings *bios = NULL; + vboxIIDUnion mchiid; + virDomainDefPtr def = NULL; + nsresult rc; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + + VBOX_IID_INITIALIZE(&mchiid); + if (!(def = virDomainDefParseString(xml, data->caps, data->xmlopt, + 1 << VIR_DOMAIN_VIRT_VBOX, + VIR_DOMAIN_XML_INACTIVE))) { + goto cleanup; + } + + virUUIDFormat(def->uuid, uuidstr); + + rc = gVBoxAPI.UIVirtualBox.CreateMachine(data, def, &machine, uuidstr); + + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not define a domain, rc=%08x"), (unsigned)rc); + goto cleanup; + } + + rc = gVBoxAPI.UIMachine.SetMemorySize(machine, + VIR_DIV_UP(def->mem.cur_balloon, 1024)); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not set the memory size of the domain to: %llu Kb, " + "rc=%08x"), + def->mem.cur_balloon, (unsigned)rc); + } + + if (def->vcpus != def->maxvcpus) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("current vcpu count must equal maximum")); + } + rc = gVBoxAPI.UIMachine.SetCPUCount(machine, def->maxvcpus); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not set the number of virtual CPUs to: %u, rc=%08x"), + def->maxvcpus, (unsigned)rc); + } + + rc = gVBoxAPI.UIMachine.SetCPUProperty(machine, CPUPropertyType_PAE, + def->features[VIR_DOMAIN_FEATURE_PAE] == + VIR_DOMAIN_FEATURE_STATE_ON); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not change PAE status to: %s, rc=%08x"), + (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_DOMAIN_FEATURE_STATE_ON) + ? _("Enabled") : _("Disabled"), (unsigned)rc); + } + + gVBoxAPI.UIMachine.GetBIOSSettings(machine, &bios); + if (bios) { + rc = gVBoxAPI.UIBIOSSettings.SetACPIEnabled(bios, + def->features[VIR_DOMAIN_FEATURE_ACPI] == + VIR_DOMAIN_FEATURE_STATE_ON); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not change ACPI status to: %s, rc=%08x"), + (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_DOMAIN_FEATURE_STATE_ON) + ? _("Enabled") : _("Disabled"), (unsigned)rc); + } + rc = gVBoxAPI.UIBIOSSettings.SetIOAPICEnabled(bios, + def->features[VIR_DOMAIN_FEATURE_APIC] == + VIR_DOMAIN_FEATURE_STATE_ON); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not change APIC status to: %s, rc=%08x"), + (def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_DOMAIN_FEATURE_STATE_ON) + ? _("Enabled") : _("Disabled"), (unsigned)rc); + } + VBOX_RELEASE(bios); + } + + /* Register the machine before attaching other devices to it */ + rc = gVBoxAPI.UIVirtualBox.RegisterMachine(data->vboxObj, machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not define a domain, rc=%08x"), (unsigned)rc); + goto cleanup; + } + + /* Get the uuid of the machine, currently it is immutable + * object so open a session to it and get it back, so that + * you can make changes to the machine setting + */ + gVBoxAPI.UIMachine.GetId(machine, &mchiid); + gVBoxAPI.UISession.Open(data, &mchiid, machine); + gVBoxAPI.UISession.GetMachine(data->vboxSession, &machine); + + vboxSetBootDeviceOrder(def, data, machine); + vboxAttachDrives(def, data, machine); + vboxAttachSound(def, machine); + vboxAttachNetwork(def, data, machine); + vboxAttachSerial(def, data, machine); + vboxAttachParallel(def, data, machine); + vboxAttachVideo(def, machine); + vboxAttachDisplay(def, data, machine); + vboxAttachUSB(def, data, machine); + vboxAttachSharedFolder(def, data, machine); + + /* Save the machine settings made till now and close the + * session. also free up the mchiid variable used. + */ + rc = gVBoxAPI.UIMachine.SaveSettings(machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed no saving settings, rc=%08x"), (unsigned)rc); + goto cleanup; + } + + gVBoxAPI.UISession.Close(data->vboxSession); + vboxIIDUnalloc(&mchiid); + + ret = virGetDomain(conn, def->name, def->uuid); + VBOX_RELEASE(machine); + + virDomainDefFree(def); + + return ret; + + cleanup: + VBOX_RELEASE(machine); + virDomainDefFree(def); + return NULL; +} + +static void detachDevices_common(vboxGlobalData *data, vboxIIDUnion *iidu) { /* Block for checking if HDD's are attched to VM. diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h index e01fa51..1499e63 100644 --- a/src/vbox/vbox_common.h +++ b/src/vbox/vbox_common.h @@ -158,6 +158,86 @@ struct _vboxArray { # endif /* !WIN32 */ +/* We make the assumption that these enum flags + * are compatible in all vbox API version. + * + * Yes it is, as it has been checked from vbox 2.2 to + * vbox 4.3.3. And this rule MAY NOT stands for new + * vbox versions. + * */ +enum CPUPropertyType +{ + CPUPropertyType_Null = 0, + CPUPropertyType_PAE = 1, + CPUPropertyType_Synthetic = 2, +}; + +enum AudioControllerType +{ + AudioControllerType_AC97 = 0, + AudioControllerType_SB16 = 1 +}; + +enum ChipsetType +{ + ChipsetType_Null = 0, + ChipsetType_PIIX3 = 1, + ChipsetType_ICH9 = 2 +}; + +enum NetworkAdapterType +{ + NetworkAdapterType_Null = 0, + NetworkAdapterType_Am79C970A = 1, + NetworkAdapterType_Am79C973 = 2, + NetworkAdapterType_I82540EM = 3, + NetworkAdapterType_I82543GC = 4, + NetworkAdapterType_I82545EM = 5, + NetworkAdapterType_Virtio = 6 +}; + +enum PortMode +{ + PortMode_Disconnected = 0, + PortMode_HostPipe = 1, + PortMode_HostDevice = 2, + PortMode_RawFile = 3 +}; + +enum DeviceType +{ + DeviceType_Null = 0, + DeviceType_Floppy = 1, + DeviceType_DVD = 2, + DeviceType_HardDisk = 3, + DeviceType_Network = 4, + DeviceType_USB = 5, + DeviceType_SharedFolder = 6 +}; + +enum StorageBus +{ + StorageBus_Null = 0, + StorageBus_IDE = 1, + StorageBus_SATA = 2, + StorageBus_SCSI = 3, + StorageBus_Floppy = 4, + StorageBus_SAS = 5 +}; + +enum AccessMode +{ + AccessMode_ReadOnly = 1, + AccessMode_ReadWrite = 2 +}; + +enum MediumType +{ + MediumType_Normal = 0, + MediumType_Immutable = 1, + MediumType_Writethrough = 2, +}; + /* Simplied definitions in vbox_CAPI_*.h */ typedef void const *PCVBOXXPCOM; @@ -167,6 +247,14 @@ typedef void IConsole; typedef void IProgress; typedef void IMachine; typedef void ISystemProperties; +typedef void IBIOSSettings; +typedef void IStorageController; +typedef void IMedium; +typedef void IAudioAdapter; +typedef void INetworkAdapter; +typedef void ISerialPort; +typedef void IParallelPort; +typedef void IUSBDeviceFilter; typedef void IVirtualBoxCallback; typedef void nsIEventQueue; diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 315feba..a5aa3e8 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -249,7 +249,6 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL; #endif /* VBOX_API_VERSION >= 4000000 */ -static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml); static int vboxDomainCreate(virDomainPtr dom); #if VBOX_API_VERSION > 2002000 && VBOX_API_VERSION < 4000000 @@ -657,7 +656,9 @@ _vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu, vboxIIDFromArrayItem_v3_x(data, iid, array, idx) # define DEBUGIID(msg, strUtf16) DEBUGPRUnichar(msg, strUtf16) -# if VBOX_API_VERSION >= 3001000 +#endif /* !(VBOX_API_VERSION == 2002000) */ + +#if VBOX_API_VERSION >= 3001000 /** * function to generate the name for medium, @@ -735,6 +736,8 @@ static char *vboxGenerateMediumName(PRUint32 storageBus, * @param deviceSlot Output slot number * */ +# if VBOX_API_VERSION < 4000000 +/* Only 3.x will use this function. */ static bool vboxGetDeviceDetails(const char *deviceName, PRUint32 *aMaxPortPerInst, PRUint32 *aMaxSlotPerPort, @@ -779,6 +782,7 @@ static bool vboxGetDeviceDetails(const char *deviceName, return true; } +# endif /* VBOX_API_VERSION < 4000000 */ /** * function to get the values for max port per @@ -873,9 +877,7 @@ static PRUnichar *PRUnicharFromInt(int n) { return strUtf16; } -# endif /* VBOX_API_VERSION >= 3001000 */ - -#endif /* !(VBOX_API_VERSION == 2002000) */ +#endif /* VBOX_API_VERSION >= 3001000 */ static PRUnichar * vboxSocketFormatAddrUtf16(vboxGlobalData *data, virSocketAddrPtr addr) @@ -3299,67 +3301,14 @@ static int vboxDomainCreate(virDomainPtr dom) return vboxDomainCreateWithFlags(dom, 0); } -static void -vboxSetBootDeviceOrder(virDomainDefPtr def, vboxGlobalData *data, - IMachine *machine) -{ - ISystemProperties *systemProperties = NULL; - PRUint32 maxBootPosition = 0; - size_t i = 0; - - VIR_DEBUG("def->os.type %s", def->os.type); - VIR_DEBUG("def->os.arch %s", virArchToString(def->os.arch)); - VIR_DEBUG("def->os.machine %s", def->os.machine); - VIR_DEBUG("def->os.nBootDevs %zu", def->os.nBootDevs); - VIR_DEBUG("def->os.bootDevs[0] %d", def->os.bootDevs[0]); - VIR_DEBUG("def->os.bootDevs[1] %d", def->os.bootDevs[1]); - VIR_DEBUG("def->os.bootDevs[2] %d", def->os.bootDevs[2]); - VIR_DEBUG("def->os.bootDevs[3] %d", def->os.bootDevs[3]); - VIR_DEBUG("def->os.init %s", def->os.init); - VIR_DEBUG("def->os.kernel %s", def->os.kernel); - VIR_DEBUG("def->os.initrd %s", def->os.initrd); - VIR_DEBUG("def->os.cmdline %s", def->os.cmdline); - VIR_DEBUG("def->os.root %s", def->os.root); - VIR_DEBUG("def->os.loader %s", def->os.loader); - VIR_DEBUG("def->os.bootloader %s", def->os.bootloader); - VIR_DEBUG("def->os.bootloaderArgs %s", def->os.bootloaderArgs); - - data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties); - if (systemProperties) { - systemProperties->vtbl->GetMaxBootPosition(systemProperties, - &maxBootPosition); - VBOX_RELEASE(systemProperties); - systemProperties = NULL; - } - - /* Clear the defaults first */ - for (i = 0; i < maxBootPosition; i++) { - machine->vtbl->SetBootOrder(machine, i+1, DeviceType_Null); - } - - for (i = 0; (i < def->os.nBootDevs) && (i < maxBootPosition); i++) { - PRUint32 device = DeviceType_Null; - - if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_FLOPPY) { - device = DeviceType_Floppy; - } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_CDROM) { - device = DeviceType_DVD; - } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_DISK) { - device = DeviceType_HardDisk; - } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_NET) { - device = DeviceType_Network; - } - machine->vtbl->SetBootOrder(machine, i+1, device); - } -} +#if VBOX_API_VERSION < 3001000 static void -vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +_vboxAttachDrivesOld(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) { size_t i; nsresult rc; -#if VBOX_API_VERSION < 3001000 if (def->ndisks == 0) return; @@ -3596,7 +3545,16 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) } } } -#else /* VBOX_API_VERSION >= 3001000 */ +} + +#elif VBOX_API_VERSION < 4000000 + +static void +_vboxAttachDrivesOld(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + size_t i; + nsresult rc; + PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {}; PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {}; PRUnichar *storageCtlName = NULL; @@ -3672,9 +3630,6 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) PRUnichar *mediumFileUtf16 = NULL; PRUint32 storageBus = StorageBus_Null; PRUint32 deviceType = DeviceType_Null; -# if VBOX_API_VERSION >= 4000000 - PRUint32 accessMode = AccessMode_ReadOnly; -# endif PRInt32 deviceInst = 0; PRInt32 devicePort = 0; PRInt32 deviceSlot = 0; @@ -3683,47 +3638,26 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) { deviceType = DeviceType_HardDisk; -# if VBOX_API_VERSION < 4000000 data->vboxObj->vtbl->FindHardDisk(data->vboxObj, mediumFileUtf16, &medium); -# else - accessMode = AccessMode_ReadWrite; -# endif } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { deviceType = DeviceType_DVD; -# if VBOX_API_VERSION < 4000000 data->vboxObj->vtbl->FindDVDImage(data->vboxObj, mediumFileUtf16, &medium); -# else - accessMode = AccessMode_ReadOnly; -# endif } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { deviceType = DeviceType_Floppy; -# if VBOX_API_VERSION < 4000000 data->vboxObj->vtbl->FindFloppyImage(data->vboxObj, mediumFileUtf16, &medium); -# else - accessMode = AccessMode_ReadWrite; -# endif } else { VBOX_UTF16_FREE(mediumFileUtf16); continue; } -# if VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 - data->vboxObj->vtbl->FindMedium(data->vboxObj, mediumFileUtf16, - deviceType, &medium); -# elif VBOX_API_VERSION >= 4002000 - data->vboxObj->vtbl->OpenMedium(data->vboxObj, mediumFileUtf16, - deviceType, accessMode, PR_FALSE, &medium); -# endif - if (!medium) { PRUnichar *mediumEmpty = NULL; VBOX_UTF8_TO_UTF16("", &mediumEmpty); -# if VBOX_API_VERSION < 4000000 if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) { rc = data->vboxObj->vtbl->OpenHardDisk(data->vboxObj, mediumFileUtf16, @@ -3748,19 +3682,6 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) } else { rc = 0; } -# elif VBOX_API_VERSION == 4000000 - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, - mediumFileUtf16, - deviceType, accessMode, - &medium); -# elif VBOX_API_VERSION >= 4001000 - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, - mediumFileUtf16, - deviceType, accessMode, - false, - &medium); -# endif /* VBOX_API_VERSION >= 4001000 */ - VBOX_UTF16_FREE(mediumEmpty); } @@ -3833,11 +3754,7 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) devicePort, deviceSlot, deviceType, -# if VBOX_API_VERSION < 4000000 mediumUUID); -# else /* VBOX_API_VERSION >= 4000000 */ - medium); -# endif /* VBOX_API_VERSION >= 4000000 */ if (NS_FAILED(rc)) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -3854,931 +3771,20 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) VBOX_UTF16_FREE(storageCtlName); } } -#endif /* VBOX_API_VERSION >= 3001000 */ -} - -static void -vboxAttachSound(virDomainDefPtr def, IMachine *machine) -{ - nsresult rc; - - /* Check if def->nsounds is one as VirtualBox currently supports - * only one sound card - */ - if (def->nsounds == 1) { - IAudioAdapter *audioAdapter = NULL; - - machine->vtbl->GetAudioAdapter(machine, &audioAdapter); - if (audioAdapter) { - rc = audioAdapter->vtbl->SetEnabled(audioAdapter, 1); - if (NS_SUCCEEDED(rc)) { - if (def->sounds[0]->model == VIR_DOMAIN_SOUND_MODEL_SB16) { - audioAdapter->vtbl->SetAudioController(audioAdapter, - AudioControllerType_SB16); - } else if (def->sounds[0]->model == VIR_DOMAIN_SOUND_MODEL_AC97) { - audioAdapter->vtbl->SetAudioController(audioAdapter, - AudioControllerType_AC97); - } - } - VBOX_RELEASE(audioAdapter); - } - } } -static void -vboxAttachNetwork(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) -{ - ISystemProperties *systemProperties = NULL; -#if VBOX_API_VERSION >= 4001000 - PRUint32 chipsetType = ChipsetType_Null; -#endif /* VBOX_API_VERSION >= 4001000 */ - PRUint32 networkAdapterCount = 0; - size_t i = 0; - -#if VBOX_API_VERSION >= 4001000 - machine->vtbl->GetChipsetType(machine, &chipsetType); -#endif /* VBOX_API_VERSION >= 4001000 */ - - data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties); - if (systemProperties) { -#if VBOX_API_VERSION < 4001000 - systemProperties->vtbl->GetNetworkAdapterCount(systemProperties, - &networkAdapterCount); -#else /* VBOX_API_VERSION >= 4000000 */ - systemProperties->vtbl->GetMaxNetworkAdapters(systemProperties, chipsetType, - &networkAdapterCount); -#endif /* VBOX_API_VERSION >= 4000000 */ - VBOX_RELEASE(systemProperties); - systemProperties = NULL; - } - - VIR_DEBUG("Number of Network Cards to be connected: %zu", def->nnets); - VIR_DEBUG("Number of Network Cards available: %d", networkAdapterCount); - - for (i = 0; (i < def->nnets) && (i < networkAdapterCount); i++) { - INetworkAdapter *adapter = NULL; - PRUint32 adapterType = NetworkAdapterType_Null; - char macaddr[VIR_MAC_STRING_BUFLEN] = {0}; - char macaddrvbox[VIR_MAC_STRING_BUFLEN - 5] = {0}; - - virMacAddrFormat(&def->nets[i]->mac, macaddr); - snprintf(macaddrvbox, VIR_MAC_STRING_BUFLEN - 5, - "%02X%02X%02X%02X%02X%02X", - def->nets[i]->mac.addr[0], - def->nets[i]->mac.addr[1], - def->nets[i]->mac.addr[2], - def->nets[i]->mac.addr[3], - def->nets[i]->mac.addr[4], - def->nets[i]->mac.addr[5]); - macaddrvbox[VIR_MAC_STRING_BUFLEN - 6] = '\0'; - - VIR_DEBUG("NIC(%zu): Type: %d", i, def->nets[i]->type); - VIR_DEBUG("NIC(%zu): Model: %s", i, def->nets[i]->model); - VIR_DEBUG("NIC(%zu): Mac: %s", i, macaddr); - VIR_DEBUG("NIC(%zu): ifname: %s", i, def->nets[i]->ifname); - if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) { - VIR_DEBUG("NIC(%zu): name: %s", i, def->nets[i]->data.network.name); - } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_INTERNAL) { - VIR_DEBUG("NIC(%zu): name: %s", i, def->nets[i]->data.internal.name); - } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_USER) { - VIR_DEBUG("NIC(%zu): NAT.", i); - } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { - VIR_DEBUG("NIC(%zu): brname: %s", i, def->nets[i]->data.bridge.brname); - VIR_DEBUG("NIC(%zu): script: %s", i, def->nets[i]->script); - VIR_DEBUG("NIC(%zu): ipaddr: %s", i, def->nets[i]->data.bridge.ipaddr); - } - - machine->vtbl->GetNetworkAdapter(machine, i, &adapter); - if (adapter) { - PRUnichar *MACAddress = NULL; - - adapter->vtbl->SetEnabled(adapter, 1); - - if (def->nets[i]->model) { - if (STRCASEEQ(def->nets[i]->model, "Am79C970A")) { - adapterType = NetworkAdapterType_Am79C970A; - } else if (STRCASEEQ(def->nets[i]->model, "Am79C973")) { - adapterType = NetworkAdapterType_Am79C973; - } else if (STRCASEEQ(def->nets[i]->model, "82540EM")) { - adapterType = NetworkAdapterType_I82540EM; - } else if (STRCASEEQ(def->nets[i]->model, "82545EM")) { - adapterType = NetworkAdapterType_I82545EM; - } else if (STRCASEEQ(def->nets[i]->model, "82543GC")) { - adapterType = NetworkAdapterType_I82543GC; -#if VBOX_API_VERSION >= 3001000 - } else if (STRCASEEQ(def->nets[i]->model, "virtio")) { - adapterType = NetworkAdapterType_Virtio; -#endif /* VBOX_API_VERSION >= 3001000 */ - } - } else { - adapterType = NetworkAdapterType_Am79C973; - } - - adapter->vtbl->SetAdapterType(adapter, adapterType); - - if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { - PRUnichar *hostInterface = NULL; - /* Bridged Network */ - -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->AttachToBridgedInterface(adapter); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Bridged); -#endif /* VBOX_API_VERSION >= 4001000 */ - - if (def->nets[i]->data.bridge.brname) { - VBOX_UTF8_TO_UTF16(def->nets[i]->data.bridge.brname, - &hostInterface); -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->SetHostInterface(adapter, hostInterface); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->SetBridgedInterface(adapter, hostInterface); -#endif /* VBOX_API_VERSION >= 4001000 */ - VBOX_UTF16_FREE(hostInterface); - } - } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_INTERNAL) { - PRUnichar *internalNetwork = NULL; - /* Internal Network */ - -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->AttachToInternalNetwork(adapter); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Internal); -#endif /* VBOX_API_VERSION >= 4001000 */ - - if (def->nets[i]->data.internal.name) { - VBOX_UTF8_TO_UTF16(def->nets[i]->data.internal.name, - &internalNetwork); - adapter->vtbl->SetInternalNetwork(adapter, internalNetwork); - VBOX_UTF16_FREE(internalNetwork); - } - } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) { - PRUnichar *hostInterface = NULL; - /* Host Only Networking (currently only vboxnet0 available - * on *nix and mac, on windows you can create and configure - * as many as you want) - */ -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->AttachToHostOnlyInterface(adapter); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_HostOnly); -#endif /* VBOX_API_VERSION >= 4001000 */ - - if (def->nets[i]->data.network.name) { - VBOX_UTF8_TO_UTF16(def->nets[i]->data.network.name, - &hostInterface); -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->SetHostInterface(adapter, hostInterface); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->SetHostOnlyInterface(adapter, hostInterface); -#endif /* VBOX_API_VERSION >= 4001000 */ - VBOX_UTF16_FREE(hostInterface); - } - } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_USER) { - /* NAT */ -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->AttachToNAT(adapter); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_NAT); -#endif /* VBOX_API_VERSION >= 4001000 */ - } else { - /* else always default to NAT if we don't understand - * what option is been passed to us - */ -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->AttachToNAT(adapter); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_NAT); -#endif /* VBOX_API_VERSION >= 4001000 */ - } - - VBOX_UTF8_TO_UTF16(macaddrvbox, &MACAddress); - adapter->vtbl->SetMACAddress(adapter, MACAddress); - VBOX_UTF16_FREE(MACAddress); - } - } -} - -static void -vboxAttachSerial(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) -{ - ISystemProperties *systemProperties = NULL; - PRUint32 serialPortCount = 0; - size_t i = 0; - - data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties); - if (systemProperties) { - systemProperties->vtbl->GetSerialPortCount(systemProperties, - &serialPortCount); - VBOX_RELEASE(systemProperties); - systemProperties = NULL; - } - - VIR_DEBUG("Number of Serial Ports to be connected: %zu", def->nserials); - VIR_DEBUG("Number of Serial Ports available: %d", serialPortCount); - for (i = 0; (i < def->nserials) && (i < serialPortCount); i++) { - ISerialPort *serialPort = NULL; - - VIR_DEBUG("SerialPort(%zu): Type: %d", i, def->serials[i]->source.type); - VIR_DEBUG("SerialPort(%zu): target.port: %d", i, - def->serials[i]->target.port); - - machine->vtbl->GetSerialPort(machine, i, &serialPort); - if (serialPort) { - PRUnichar *pathUtf16 = NULL; - - serialPort->vtbl->SetEnabled(serialPort, 1); - - if (def->serials[i]->source.data.file.path) { - VBOX_UTF8_TO_UTF16(def->serials[i]->source.data.file.path, - &pathUtf16); - serialPort->vtbl->SetPath(serialPort, pathUtf16); - } - - /* For now hard code the serial ports to COM1 and COM2, - * COM1 (Base Addr: 0x3F8 (decimal: 1016), IRQ: 4) - * COM2 (Base Addr: 0x2F8 (decimal: 760), IRQ: 3) - * TODO: make this more flexible - */ - /* TODO: to improve the libvirt XMl handling so - * that def->serials[i]->target.port shows real port - * and not always start at 0 - */ - if (def->serials[i]->target.port == 0) { - serialPort->vtbl->SetIRQ(serialPort, 4); - serialPort->vtbl->SetIOBase(serialPort, 1016); - VIR_DEBUG(" serialPort-%zu irq: %d, iobase 0x%x, path: %s", - i, 4, 1016, def->serials[i]->source.data.file.path); - } else if (def->serials[i]->target.port == 1) { - serialPort->vtbl->SetIRQ(serialPort, 3); - serialPort->vtbl->SetIOBase(serialPort, 760); - VIR_DEBUG(" serialPort-%zu irq: %d, iobase 0x%x, path: %s", - i, 3, 760, def->serials[i]->source.data.file.path); - } - - if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV) { - serialPort->vtbl->SetHostMode(serialPort, PortMode_HostDevice); - } else if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE) { - serialPort->vtbl->SetHostMode(serialPort, PortMode_HostPipe); -#if VBOX_API_VERSION >= 3000000 - } else if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE) { - serialPort->vtbl->SetHostMode(serialPort, PortMode_RawFile); -#endif /* VBOX_API_VERSION >= 3000000 */ - } else { - serialPort->vtbl->SetHostMode(serialPort, - PortMode_Disconnected); - } - - VBOX_RELEASE(serialPort); - VBOX_UTF16_FREE(pathUtf16); - } - } -} - -static void -vboxAttachParallel(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) -{ - ISystemProperties *systemProperties = NULL; - PRUint32 parallelPortCount = 0; - size_t i = 0; - - data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties); - if (systemProperties) { - systemProperties->vtbl->GetParallelPortCount(systemProperties, - ¶llelPortCount); - VBOX_RELEASE(systemProperties); - systemProperties = NULL; - } - - VIR_DEBUG("Number of Parallel Ports to be connected: %zu", def->nparallels); - VIR_DEBUG("Number of Parallel Ports available: %d", parallelPortCount); - for (i = 0; (i < def->nparallels) && (i < parallelPortCount); i++) { - IParallelPort *parallelPort = NULL; - - VIR_DEBUG("ParallelPort(%zu): Type: %d", i, def->parallels[i]->source.type); - VIR_DEBUG("ParallelPort(%zu): target.port: %d", i, - def->parallels[i]->target.port); - - machine->vtbl->GetParallelPort(machine, i, ¶llelPort); - if (parallelPort) { - PRUnichar *pathUtf16 = NULL; - - VBOX_UTF8_TO_UTF16(def->parallels[i]->source.data.file.path, &pathUtf16); - - /* For now hard code the parallel ports to - * LPT1 (Base Addr: 0x378 (decimal: 888), IRQ: 7) - * LPT2 (Base Addr: 0x278 (decimal: 632), IRQ: 5) - * TODO: make this more flexible - */ - if ((def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV) || - (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_PTY) || - (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE) || - (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE)) { - parallelPort->vtbl->SetPath(parallelPort, pathUtf16); - if (i == 0) { - parallelPort->vtbl->SetIRQ(parallelPort, 7); - parallelPort->vtbl->SetIOBase(parallelPort, 888); - VIR_DEBUG(" parallePort-%zu irq: %d, iobase 0x%x, path: %s", - i, 7, 888, def->parallels[i]->source.data.file.path); - } else if (i == 1) { - parallelPort->vtbl->SetIRQ(parallelPort, 5); - parallelPort->vtbl->SetIOBase(parallelPort, 632); - VIR_DEBUG(" parallePort-%zu irq: %d, iobase 0x%x, path: %s", - i, 5, 632, def->parallels[i]->source.data.file.path); - } - } - - /* like serial port, parallel port can't be enabled unless - * correct IRQ and IOBase values are specified. - */ - parallelPort->vtbl->SetEnabled(parallelPort, 1); - - VBOX_RELEASE(parallelPort); - VBOX_UTF16_FREE(pathUtf16); - } - } -} - -static void -vboxAttachVideo(virDomainDefPtr def, IMachine *machine) -{ - if ((def->nvideos == 1) && - (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_VBOX)) { - machine->vtbl->SetVRAMSize(machine, - VIR_DIV_UP(def->videos[0]->vram, 1024)); - machine->vtbl->SetMonitorCount(machine, def->videos[0]->heads); - if (def->videos[0]->accel) { - machine->vtbl->SetAccelerate3DEnabled(machine, - def->videos[0]->accel->support3d); -#if VBOX_API_VERSION >= 3001000 - machine->vtbl->SetAccelerate2DVideoEnabled(machine, - def->videos[0]->accel->support2d); -#endif /* VBOX_API_VERSION >= 3001000 */ - } else { - machine->vtbl->SetAccelerate3DEnabled(machine, 0); -#if VBOX_API_VERSION >= 3001000 - machine->vtbl->SetAccelerate2DVideoEnabled(machine, 0); -#endif /* VBOX_API_VERSION >= 3001000 */ - } - } -} - -static void -vboxAttachDisplay(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) -{ - int vrdpPresent = 0; - int sdlPresent = 0; - int guiPresent = 0; - char *guiDisplay = NULL; - char *sdlDisplay = NULL; - size_t i = 0; - - for (i = 0; i < def->ngraphics; i++) { -#if VBOX_API_VERSION < 4000000 - IVRDPServer *VRDxServer = NULL; -#else /* VBOX_API_VERSION >= 4000000 */ - IVRDEServer *VRDxServer = NULL; -#endif /* VBOX_API_VERSION >= 4000000 */ - - if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_RDP) && - (vrdpPresent == 0)) { - - vrdpPresent = 1; -#if VBOX_API_VERSION < 4000000 - machine->vtbl->GetVRDPServer(machine, &VRDxServer); -#else /* VBOX_API_VERSION >= 4000000 */ - machine->vtbl->GetVRDEServer(machine, &VRDxServer); -#endif /* VBOX_API_VERSION >= 4000000 */ - if (VRDxServer) { - const char *listenAddr - = virDomainGraphicsListenGetAddress(def->graphics[i], 0); - - VRDxServer->vtbl->SetEnabled(VRDxServer, PR_TRUE); - VIR_DEBUG("VRDP Support turned ON."); - -#if VBOX_API_VERSION < 3001000 - if (def->graphics[i]->data.rdp.port) { - VRDxServer->vtbl->SetPort(VRDxServer, - def->graphics[i]->data.rdp.port); - VIR_DEBUG("VRDP Port changed to: %d", - def->graphics[i]->data.rdp.port); - } else if (def->graphics[i]->data.rdp.autoport) { - /* Setting the port to 0 will reset its value to - * the default one which is 3389 currently - */ - VRDxServer->vtbl->SetPort(VRDxServer, 0); - VIR_DEBUG("VRDP Port changed to default, which is 3389 currently"); - } -#elif VBOX_API_VERSION < 4000000 /* 3001000 <= VBOX_API_VERSION < 4000000 */ - PRUnichar *portUtf16 = NULL; - portUtf16 = PRUnicharFromInt(def->graphics[i]->data.rdp.port); - VRDxServer->vtbl->SetPorts(VRDxServer, portUtf16); - VBOX_UTF16_FREE(portUtf16); -#else /* VBOX_API_VERSION >= 4000000 */ - PRUnichar *VRDEPortsKey = NULL; - PRUnichar *VRDEPortsValue = NULL; - VBOX_UTF8_TO_UTF16("TCP/Ports", &VRDEPortsKey); - VRDEPortsValue = PRUnicharFromInt(def->graphics[i]->data.rdp.port); - VRDxServer->vtbl->SetVRDEProperty(VRDxServer, VRDEPortsKey, - VRDEPortsValue); - VBOX_UTF16_FREE(VRDEPortsKey); - VBOX_UTF16_FREE(VRDEPortsValue); -#endif /* VBOX_API_VERSION >= 4000000 */ - - if (def->graphics[i]->data.rdp.replaceUser) { - VRDxServer->vtbl->SetReuseSingleConnection(VRDxServer, - PR_TRUE); - VIR_DEBUG("VRDP set to reuse single connection"); - } - - if (def->graphics[i]->data.rdp.multiUser) { - VRDxServer->vtbl->SetAllowMultiConnection(VRDxServer, - PR_TRUE); - VIR_DEBUG("VRDP set to allow multiple connection"); - } - - if (listenAddr) { -#if VBOX_API_VERSION >= 4000000 - PRUnichar *netAddressKey = NULL; -#endif - PRUnichar *netAddressUtf16 = NULL; - - VBOX_UTF8_TO_UTF16(listenAddr, &netAddressUtf16); -#if VBOX_API_VERSION < 4000000 - VRDxServer->vtbl->SetNetAddress(VRDxServer, - netAddressUtf16); #else /* VBOX_API_VERSION >= 4000000 */ - VBOX_UTF8_TO_UTF16("TCP/Address", &netAddressKey); - VRDxServer->vtbl->SetVRDEProperty(VRDxServer, netAddressKey, - netAddressUtf16); - VBOX_UTF16_FREE(netAddressKey); -#endif /* VBOX_API_VERSION >= 4000000 */ - VIR_DEBUG("VRDP listen address is set to: %s", - listenAddr); - - VBOX_UTF16_FREE(netAddressUtf16); - } - - VBOX_RELEASE(VRDxServer); - } - } - - if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP) && - (guiPresent == 0)) { - guiPresent = 1; - if (VIR_STRDUP(guiDisplay, def->graphics[i]->data.desktop.display) < 0) { - /* just don't go to cleanup yet as it is ok to have - * guiDisplay as NULL and we check it below if it - * exist and then only use it there - */ - } - } - - if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) && - (sdlPresent == 0)) { - sdlPresent = 1; - if (VIR_STRDUP(sdlDisplay, def->graphics[i]->data.sdl.display) < 0) { - /* just don't go to cleanup yet as it is ok to have - * sdlDisplay as NULL and we check it below if it - * exist and then only use it there - */ - } - } - } - - if ((vrdpPresent == 1) && (guiPresent == 0) && (sdlPresent == 0)) { - /* store extradata key that frontend is set to vrdp */ - PRUnichar *keyTypeUtf16 = NULL; - PRUnichar *valueTypeUtf16 = NULL; - - VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); - VBOX_UTF8_TO_UTF16("vrdp", &valueTypeUtf16); - - machine->vtbl->SetExtraData(machine, keyTypeUtf16, valueTypeUtf16); - - VBOX_UTF16_FREE(keyTypeUtf16); - VBOX_UTF16_FREE(valueTypeUtf16); - - } else if ((guiPresent == 0) && (sdlPresent == 1)) { - /* store extradata key that frontend is set to sdl */ - PRUnichar *keyTypeUtf16 = NULL; - PRUnichar *valueTypeUtf16 = NULL; - PRUnichar *keyDislpayUtf16 = NULL; - PRUnichar *valueDisplayUtf16 = NULL; - - VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); - VBOX_UTF8_TO_UTF16("sdl", &valueTypeUtf16); - - machine->vtbl->SetExtraData(machine, keyTypeUtf16, valueTypeUtf16); - - VBOX_UTF16_FREE(keyTypeUtf16); - VBOX_UTF16_FREE(valueTypeUtf16); - - if (sdlDisplay) { - VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16); - VBOX_UTF8_TO_UTF16(sdlDisplay, &valueDisplayUtf16); - - machine->vtbl->SetExtraData(machine, keyDislpayUtf16, - valueDisplayUtf16); - - VBOX_UTF16_FREE(keyDislpayUtf16); - VBOX_UTF16_FREE(valueDisplayUtf16); - } - - } else { - /* if all are set then default is gui, with vrdp turned on */ - PRUnichar *keyTypeUtf16 = NULL; - PRUnichar *valueTypeUtf16 = NULL; - PRUnichar *keyDislpayUtf16 = NULL; - PRUnichar *valueDisplayUtf16 = NULL; - - VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); - VBOX_UTF8_TO_UTF16("gui", &valueTypeUtf16); - - machine->vtbl->SetExtraData(machine, keyTypeUtf16, valueTypeUtf16); - - VBOX_UTF16_FREE(keyTypeUtf16); - VBOX_UTF16_FREE(valueTypeUtf16); - - if (guiDisplay) { - VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16); - VBOX_UTF8_TO_UTF16(guiDisplay, &valueDisplayUtf16); - - machine->vtbl->SetExtraData(machine, keyDislpayUtf16, - valueDisplayUtf16); - - VBOX_UTF16_FREE(keyDislpayUtf16); - VBOX_UTF16_FREE(valueDisplayUtf16); - } - } - - VIR_FREE(guiDisplay); - VIR_FREE(sdlDisplay); -} static void -vboxAttachUSB(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +_vboxAttachDrivesOld(virDomainDefPtr def ATTRIBUTE_UNUSED, + vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine ATTRIBUTE_UNUSED) { -#if VBOX_API_VERSION < 4003000 - IUSBController *USBController = NULL; -#else - IUSBDeviceFilters *USBDeviceFilters = NULL; -#endif - size_t i = 0; - bool isUSB = false; - - if (def->nhostdevs == 0) - return; - - /* Loop through the devices first and see if you - * have a USB Device, only if you have one then - * start the USB controller else just proceed as - * usual - */ - for (i = 0; i < def->nhostdevs; i++) { - if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; - - if (def->hostdevs[i]->source.subsys.type != - VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) - continue; - - if (!def->hostdevs[i]->source.subsys.u.usb.vendor && - !def->hostdevs[i]->source.subsys.u.usb.product) - continue; - - VIR_DEBUG("USB Device detected, VendorId:0x%x, ProductId:0x%x", - def->hostdevs[i]->source.subsys.u.usb.vendor, - def->hostdevs[i]->source.subsys.u.usb.product); - isUSB = true; - break; - } - - if (!isUSB) - return; - -#if VBOX_API_VERSION < 4003000 - /* First Start the USB Controller and then loop - * to attach USB Devices to it - */ - machine->vtbl->GetUSBController(machine, &USBController); - - if (!USBController) - return; - - USBController->vtbl->SetEnabled(USBController, 1); -# if VBOX_API_VERSION < 4002000 - USBController->vtbl->SetEnabledEhci(USBController, 1); -# else - USBController->vtbl->SetEnabledEHCI(USBController, 1); -# endif -#else - machine->vtbl->GetUSBDeviceFilters(machine, &USBDeviceFilters); - - if (!USBDeviceFilters) - return; -#endif - - for (i = 0; i < def->nhostdevs; i++) { - char *filtername = NULL; - PRUnichar *filternameUtf16 = NULL; - IUSBDeviceFilter *filter = NULL; - PRUnichar *vendorIdUtf16 = NULL; - char vendorId[40] = {0}; - PRUnichar *productIdUtf16 = NULL; - char productId[40] = {0}; - - if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; - - if (def->hostdevs[i]->source.subsys.type != - VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) - continue; - - /* Zero pad for nice alignment when fewer than 9999 - * devices. - */ - if (virAsprintf(&filtername, "filter%04zu", i) >= 0) { - VBOX_UTF8_TO_UTF16(filtername, &filternameUtf16); - VIR_FREE(filtername); -#if VBOX_API_VERSION < 4003000 - USBController->vtbl->CreateDeviceFilter(USBController, - filternameUtf16, - &filter); -#else - USBDeviceFilters->vtbl->CreateDeviceFilter(USBDeviceFilters, - filternameUtf16, - &filter); -#endif - } - VBOX_UTF16_FREE(filternameUtf16); - - if (!filter) - continue; - - if (!def->hostdevs[i]->source.subsys.u.usb.vendor && - !def->hostdevs[i]->source.subsys.u.usb.product) - continue; - - if (def->hostdevs[i]->source.subsys.u.usb.vendor) { - snprintf(vendorId, sizeof(vendorId), "%x", - def->hostdevs[i]->source.subsys.u.usb.vendor); - VBOX_UTF8_TO_UTF16(vendorId, &vendorIdUtf16); - filter->vtbl->SetVendorId(filter, vendorIdUtf16); - VBOX_UTF16_FREE(vendorIdUtf16); - } - if (def->hostdevs[i]->source.subsys.u.usb.product) { - snprintf(productId, sizeof(productId), "%x", - def->hostdevs[i]->source.subsys.u.usb.product); - VBOX_UTF8_TO_UTF16(productId, &productIdUtf16); - filter->vtbl->SetProductId(filter, - productIdUtf16); - VBOX_UTF16_FREE(productIdUtf16); - } - filter->vtbl->SetActive(filter, 1); -#if VBOX_API_VERSION < 4003000 - USBController->vtbl->InsertDeviceFilter(USBController, - i, - filter); -#else - USBDeviceFilters->vtbl->InsertDeviceFilter(USBDeviceFilters, - i, - filter); -#endif - VBOX_RELEASE(filter); - } - -#if VBOX_API_VERSION < 4003000 - VBOX_RELEASE(USBController); -#else - VBOX_RELEASE(USBDeviceFilters); -#endif + VIR_WARN("Should call vboxAttachDrivesNew for current vbox version"); } -static void -vboxAttachSharedFolder(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) -{ - size_t i; - PRUnichar *nameUtf16; - PRUnichar *hostPathUtf16; - PRBool writable; - - if (def->nfss == 0) - return; - - for (i = 0; i < def->nfss; i++) { - if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT) - continue; - - VBOX_UTF8_TO_UTF16(def->fss[i]->dst, &nameUtf16); - VBOX_UTF8_TO_UTF16(def->fss[i]->src, &hostPathUtf16); - writable = !def->fss[i]->readonly; - -#if VBOX_API_VERSION < 4000000 - machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16, - writable); -#else /* VBOX_API_VERSION >= 4000000 */ - machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16, - writable, PR_FALSE); #endif /* VBOX_API_VERSION >= 4000000 */ - VBOX_UTF16_FREE(nameUtf16); - VBOX_UTF16_FREE(hostPathUtf16); - } -} - -static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml) -{ - VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL); - IMachine *machine = NULL; - IBIOSSettings *bios = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - vboxIID mchiid = VBOX_IID_INITIALIZER; - virDomainDefPtr def = NULL; - PRUnichar *machineNameUtf16 = NULL; -#if VBOX_API_VERSION >= 3002000 && VBOX_API_VERSION < 4002000 - PRBool override = PR_FALSE; -#endif - nsresult rc; - char uuidstr[VIR_UUID_STRING_BUFLEN]; -#if VBOX_API_VERSION >= 4002000 - const char *flagsUUIDPrefix = "UUID="; - const char *flagsForceOverwrite = "forceOverwrite=0"; - const char *flagsSeparator = ","; - char createFlags[strlen(flagsUUIDPrefix) + VIR_UUID_STRING_BUFLEN + strlen(flagsSeparator) + strlen(flagsForceOverwrite) + 1]; - PRUnichar *createFlagsUtf16 = NULL; -#endif - - if (!(def = virDomainDefParseString(xml, data->caps, data->xmlopt, - 1 << VIR_DOMAIN_VIRT_VBOX, - VIR_DOMAIN_XML_INACTIVE))) { - goto cleanup; - } - - VBOX_UTF8_TO_UTF16(def->name, &machineNameUtf16); - vboxIIDFromUUID(&iid, def->uuid); - virUUIDFormat(def->uuid, uuidstr); - -#if VBOX_API_VERSION < 3002000 - rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, - machineNameUtf16, - NULL, - NULL, - iid.value, - &machine); -#elif VBOX_API_VERSION < 4000000 /* 3002000 <= VBOX_API_VERSION < 4000000 */ - rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, - machineNameUtf16, - NULL, - NULL, - iid.value, - override, - &machine); -#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 - rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, - NULL, - machineNameUtf16, - NULL, - iid.value, - override, - &machine); -#else /* VBOX_API_VERSION >= 4002000 */ - snprintf(createFlags, sizeof(createFlags), "%s%s%s%s", - flagsUUIDPrefix, - uuidstr, - flagsSeparator, - flagsForceOverwrite - ); - VBOX_UTF8_TO_UTF16(createFlags, &createFlagsUtf16); - rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, - NULL, - machineNameUtf16, - 0, - nsnull, - nsnull, - createFlagsUtf16, - &machine); -#endif /* VBOX_API_VERSION >= 4002000 */ - VBOX_UTF16_FREE(machineNameUtf16); - - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not define a domain, rc=%08x"), (unsigned)rc); - goto cleanup; - } - - rc = machine->vtbl->SetMemorySize(machine, - VIR_DIV_UP(def->mem.cur_balloon, 1024)); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not set the memory size of the domain to: %llu Kb, " - "rc=%08x"), - def->mem.cur_balloon, (unsigned)rc); - } - - if (def->vcpus != def->maxvcpus) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("current vcpu count must equal maximum")); - } - rc = machine->vtbl->SetCPUCount(machine, def->maxvcpus); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not set the number of virtual CPUs to: %u, rc=%08x"), - def->maxvcpus, (unsigned)rc); - } - -#if VBOX_API_VERSION < 3001000 - rc = machine->vtbl->SetPAEEnabled(machine, - def->features[VIR_DOMAIN_FEATURE_PAE] == - VIR_DOMAIN_FEATURE_STATE_ON); -#elif VBOX_API_VERSION == 3001000 - rc = machine->vtbl->SetCpuProperty(machine, CpuPropertyType_PAE, - def->features[VIR_DOMAIN_FEATURE_PAE] == - VIR_DOMAIN_FEATURE_STATE_ON); -#elif VBOX_API_VERSION >= 3002000 - rc = machine->vtbl->SetCPUProperty(machine, CPUPropertyType_PAE, - def->features[VIR_DOMAIN_FEATURE_PAE] == - VIR_DOMAIN_FEATURE_STATE_ON); -#endif - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not change PAE status to: %s, rc=%08x"), - (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_DOMAIN_FEATURE_STATE_ON) - ? _("Enabled") : _("Disabled"), (unsigned)rc); - } - - machine->vtbl->GetBIOSSettings(machine, &bios); - if (bios) { - rc = bios->vtbl->SetACPIEnabled(bios, - def->features[VIR_DOMAIN_FEATURE_ACPI] == - VIR_DOMAIN_FEATURE_STATE_ON); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not change ACPI status to: %s, rc=%08x"), - (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_DOMAIN_FEATURE_STATE_ON) - ? _("Enabled") : _("Disabled"), (unsigned)rc); - } - rc = bios->vtbl->SetIOAPICEnabled(bios, - def->features[VIR_DOMAIN_FEATURE_APIC] == - VIR_DOMAIN_FEATURE_STATE_ON); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not change APIC status to: %s, rc=%08x"), - (def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_DOMAIN_FEATURE_STATE_ON) - ? _("Enabled") : _("Disabled"), (unsigned)rc); - } - VBOX_RELEASE(bios); - } - - /* Register the machine before attaching other devices to it */ - rc = data->vboxObj->vtbl->RegisterMachine(data->vboxObj, machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not define a domain, rc=%08x"), (unsigned)rc); - goto cleanup; - } - - /* Get the uuid of the machine, currently it is immutable - * object so open a session to it and get it back, so that - * you can make changes to the machine setting - */ - machine->vtbl->GetId(machine, &mchiid.value); - VBOX_SESSION_OPEN(mchiid.value, machine); - data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); - - vboxSetBootDeviceOrder(def, data, machine); - vboxAttachDrives(def, data, machine); - vboxAttachSound(def, machine); - vboxAttachNetwork(def, data, machine); - vboxAttachSerial(def, data, machine); - vboxAttachParallel(def, data, machine); - vboxAttachVideo(def, machine); - vboxAttachDisplay(def, data, machine); - vboxAttachUSB(def, data, machine); - vboxAttachSharedFolder(def, data, machine); - - /* Save the machine settings made till now and close the - * session. also free up the mchiid variable used. - */ - rc = machine->vtbl->SaveSettings(machine); - VBOX_SESSION_CLOSE(); - vboxIIDUnalloc(&mchiid); - - ret = virGetDomain(conn, def->name, def->uuid); - VBOX_RELEASE(machine); - - vboxIIDUnalloc(&iid); - virDomainDefFree(def); - - return ret; - - cleanup: - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - virDomainDefFree(def); - return NULL; -} - static int vboxDomainUndefine(virDomainPtr dom) { @@ -11080,6 +10086,160 @@ _virtualboxGetSystemProperties(IVirtualBox *vboxObj, ISystemProperties **systemP } static nsresult +_virtualboxCreateMachine(vboxGlobalData *data, virDomainDefPtr def, IMachine **machine, char *uuidstr ATTRIBUTE_UNUSED) +{ + vboxIID iid = VBOX_IID_INITIALIZER; + PRUnichar *machineNameUtf16 = NULL; + nsresult rc; + + VBOX_UTF8_TO_UTF16(def->name, &machineNameUtf16); + vboxIIDFromUUID(&iid, def->uuid); + { +#if VBOX_API_VERSION < 3002000 + rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, + machineNameUtf16, + NULL, + NULL, + iid.value, + machine); +#elif VBOX_API_VERSION < 4000000 /* 3002000 <= VBOX_API_VERSION < 4000000 */ + PRBool override = PR_FALSE; + rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, + machineNameUtf16, + NULL, + NULL, + iid.value, + override, + machine); +#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 + PRBool override = PR_FALSE; + rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, + NULL, + machineNameUtf16, + NULL, + iid.value, + override, + machine); +#else /* VBOX_API_VERSION >= 4002000 */ + const char *flagsUUIDPrefix = "UUID="; + const char *flagsForceOverwrite = "forceOverwrite=0"; + const char *flagsSeparator = ","; + char createFlags[strlen(flagsUUIDPrefix) + VIR_UUID_STRING_BUFLEN + strlen(flagsSeparator) + strlen(flagsForceOverwrite) + 1]; + PRUnichar *createFlagsUtf16 = NULL; + + snprintf(createFlags, sizeof(createFlags), "%s%s%s%s", + flagsUUIDPrefix, + uuidstr, + flagsSeparator, + flagsForceOverwrite + ); + VBOX_UTF8_TO_UTF16(createFlags, &createFlagsUtf16); + rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, + NULL, + machineNameUtf16, + 0, + nsnull, + nsnull, + createFlagsUtf16, + machine); +#endif /* VBOX_API_VERSION >= 4002000 */ + } + VBOX_UTF16_FREE(machineNameUtf16); + vboxIIDUnalloc(&iid); + return rc; +} + +static nsresult +_virtualboxRegisterMachine(IVirtualBox *vboxObj, IMachine *machine) +{ + return vboxObj->vtbl->RegisterMachine(vboxObj, machine); +} + +static nsresult +_virtualboxFindMedium(IVirtualBox *vboxObj ATTRIBUTE_UNUSED, + PRUnichar *location ATTRIBUTE_UNUSED, + PRUint32 deviceType ATTRIBUTE_UNUSED, + PRUint32 accessMode ATTRIBUTE_UNUSED, + IMedium **medium ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 + return vboxObj->vtbl->FindMedium(vboxObj, location, + deviceType, medium); +#elif VBOX_API_VERSION >= 4002000 + return vboxObj->vtbl->OpenMedium(vboxObj, location, + deviceType, accessMode, PR_FALSE, medium); +#else + VIR_WARN("There is no virtualbox FindMedium in current version"); + return 0; +#endif +} + +static nsresult +_virtualboxOpenMedium(IVirtualBox *vboxObj ATTRIBUTE_UNUSED, + PRUnichar *location ATTRIBUTE_UNUSED, + PRUint32 deviceType ATTRIBUTE_UNUSED, + PRUint32 accessMode ATTRIBUTE_UNUSED, + IMedium **medium ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION == 4000000 + return vboxObj->vtbl->OpenMedium(vboxObj, + location, + deviceType, accessMode, + medium); +#elif VBOX_API_VERSION >= 4001000 + return vboxObj->vtbl->OpenMedium(vboxObj, + location, + deviceType, accessMode, + false, + medium); +#else + VIR_WARN("There is no virtualbox OpenMedium in current version"); + return 0; +#endif +} + +static nsresult +_machineAddStorageController(IMachine *machine, PRUnichar *name, + PRUint32 connectionType, + IStorageController **controller) +{ + return machine->vtbl->AddStorageController(machine, name, connectionType, + controller); +} + +static nsresult +_machineAttachDevice(IMachine *machine ATTRIBUTE_UNUSED, + PRUnichar *name ATTRIBUTE_UNUSED, + PRInt32 controllerPort ATTRIBUTE_UNUSED, + PRInt32 device ATTRIBUTE_UNUSED, + PRUint32 type ATTRIBUTE_UNUSED, + IMedium * medium ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION >= 4000000 + return machine->vtbl->AttachDevice(machine, name, controllerPort, + device, type, medium); +#else /* VBOX_API_VERSION < 4000000 */ + VIR_WARN("There is no machine AttachDevice in current version"); + return 0; +#endif /* VBOX_API_VERSION < 4000000 */ +} + +static nsresult +_machineCreateSharedFolder(IMachine *machine, PRUnichar *name, + PRUnichar *hostPath, PRBool writable, + PRBool automount ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION < 4000000 + return machine->vtbl->CreateSharedFolder(machine, name, hostPath, + writable); +#else /* VBOX_API_VERSION >= 4000000 */ + return machine->vtbl->CreateSharedFolder(machine, name, hostPath, + writable, automount); +#endif /* VBOX_API_VERSION >= 4000000 */ +} + + +static nsresult _machineGetAccessible(IMachine *machine, PRBool *isAccessible) { return machine->vtbl->GetAccessible(machine, isAccessible); @@ -11104,6 +10264,133 @@ _machineGetId(IMachine *machine, vboxIIDUnion *iidu) } static nsresult +_machineGetBIOSSettings(IMachine *machine, IBIOSSettings **bios) +{ + return machine->vtbl->GetBIOSSettings(machine, bios); +} + +static nsresult +_machineGetAudioAdapter(IMachine *machine, IAudioAdapter **audioadapter) +{ + return machine->vtbl->GetAudioAdapter(machine, audioadapter); +} + +static nsresult +_machineGetNetworkAdapter(IMachine *machine, PRUint32 slot, INetworkAdapter **adapter) +{ + return machine->vtbl->GetNetworkAdapter(machine, slot, adapter); +} + +static nsresult +_machineGetChipsetType(IMachine *machine ATTRIBUTE_UNUSED, PRUint32 *chipsetType ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION >= 4001000 + return machine->vtbl->GetChipsetType(machine, chipsetType); +#else /* VBOX_API_VERSION < 4001000 */ + VIR_WARN("There is no chipsetType in current version"); + return 0; +#endif /* VBOX_API_VERSION < 4001000 */ +} + +static nsresult +_machineGetSerialPort(IMachine *machine, PRUint32 slot, ISerialPort **port) +{ + return machine->vtbl->GetSerialPort(machine, slot, port); +} + +static nsresult +_machineGetParallelPort(IMachine *machine, PRUint32 slot, IParallelPort **port) +{ + return machine->vtbl->GetParallelPort(machine, slot, port); +} + +static nsresult +_machineGetVRDxServer(IMachine *machine, IVRDxServer **VRDxServer) +{ +#if VBOX_API_VERSION < 4000000 + return machine->vtbl->GetVRDPServer(machine, VRDxServer); +#else /* VBOX_API_VERSION >= 4000000 */ + return machine->vtbl->GetVRDEServer(machine, VRDxServer); +#endif /* VBOX_API_VERSION >= 4000000 */ +} + +static nsresult +_machineGetUSBCommon(IMachine *machine, IUSBCommon **USBCommon) +{ +#if VBOX_API_VERSION < 4003000 + return machine->vtbl->GetUSBController(machine, USBCommon); +#else + return machine->vtbl->GetUSBDeviceFilters(machine, USBCommon); +#endif +} + +static nsresult +_machineSetCPUCount(IMachine *machine, PRUint32 CPUCount) +{ + return machine->vtbl->SetCPUCount(machine, CPUCount); +} + +static nsresult +_machineSetMemorySize(IMachine *machine, PRUint32 memorySize) +{ + return machine->vtbl->SetMemorySize(machine, memorySize); +} + +static nsresult +_machineSetCPUProperty(IMachine *machine, PRUint32 property ATTRIBUTE_UNUSED, PRBool value) +{ +#if VBOX_API_VERSION < 3001000 + return machine->vtbl->SetPAEEnabled(machine, value); +#elif VBOX_API_VERSION == 3001000 + return machine->vtbl->SetCpuProperty(machine, property, value); +#elif VBOX_API_VERSION >= 3002000 + return machine->vtbl->SetCPUProperty(machine, property, value); +#endif +} + +static nsresult +_machineSetBootOrder(IMachine *machine, PRUint32 position, PRUint32 device) +{ + return machine->vtbl->SetBootOrder(machine, position, device); +} + +static nsresult +_machineSetVRAMSize(IMachine *machine, PRUint32 VRAMSize) +{ + return machine->vtbl->SetVRAMSize(machine, VRAMSize); +} + +static nsresult +_machineSetMonitorCount(IMachine *machine, PRUint32 monitorCount) +{ + return machine->vtbl->SetMonitorCount(machine, monitorCount); +} + +static nsresult +_machineSetAccelerate3DEnabled(IMachine *machine, PRBool accelerate3DEnabled) +{ + return machine->vtbl->SetAccelerate3DEnabled(machine, accelerate3DEnabled); +} + +static nsresult +_machineSetAccelerate2DVideoEnabled(IMachine *machine ATTRIBUTE_UNUSED, + PRBool accelerate2DVideoEnabled ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION >= 3001000 + return machine->vtbl->SetAccelerate2DVideoEnabled(machine, accelerate2DVideoEnabled); +#else /* VBOX_API_VERSION < 3001000 */ + VIR_WARN("No accelerate2DVideo in current version"); + return 0; +#endif /* VBOX_API_VERSION < 3001000 */ +} + +static nsresult +_machineSetExtraData(IMachine *machine, PRUnichar *key, PRUnichar *value) +{ + return machine->vtbl->SetExtraData(machine, key, value); +} + +static nsresult _machineSaveSettings(IMachine *machine) { return machine->vtbl->SaveSettings(machine); @@ -11191,6 +10478,372 @@ _systemPropertiesGetMaxGuestCPUCount(ISystemProperties *systemProperties, PRUint return systemProperties->vtbl->GetMaxGuestCPUCount(systemProperties, maxCPUCount); } +static nsresult +_systemPropertiesGetMaxBootPosition(ISystemProperties *systemProperties, PRUint32 *maxBootPosition) +{ + return systemProperties->vtbl->GetMaxBootPosition(systemProperties, maxBootPosition); +} + +static nsresult +_systemPropertiesGetMaxNetworkAdapters(ISystemProperties *systemProperties, PRUint32 chipset ATTRIBUTE_UNUSED, + PRUint32 *maxNetworkAdapters) +{ +#if VBOX_API_VERSION < 4001000 + return systemProperties->vtbl->GetNetworkAdapterCount(systemProperties, + maxNetworkAdapters); +#else /* VBOX_API_VERSION >= 4000000 */ + return systemProperties->vtbl->GetMaxNetworkAdapters(systemProperties, chipset, + maxNetworkAdapters); +#endif /* VBOX_API_VERSION >= 4000000 */ +} + +static nsresult +_systemPropertiesGetSerialPortCount(ISystemProperties *systemProperties, PRUint32 *SerialPortCount) +{ + return systemProperties->vtbl->GetSerialPortCount(systemProperties, SerialPortCount); +} + +static nsresult +_systemPropertiesGetParallelPortCount(ISystemProperties *systemProperties, PRUint32 *ParallelPortCount) +{ + return systemProperties->vtbl->GetParallelPortCount(systemProperties, ParallelPortCount); +} + +#if VBOX_API_VERSION >= 3001000 +static nsresult +_systemPropertiesGetMaxPortCountForStorageBus(ISystemProperties *systemProperties, PRUint32 bus, + PRUint32 *maxPortCount) +{ + return systemProperties->vtbl->GetMaxPortCountForStorageBus(systemProperties, bus, maxPortCount); +} + +static nsresult +_systemPropertiesGetMaxDevicesPerPortForStorageBus(ISystemProperties *systemProperties, + PRUint32 bus, PRUint32 *maxDevicesPerPort) +{ + return systemProperties->vtbl->GetMaxDevicesPerPortForStorageBus(systemProperties, + bus, maxDevicesPerPort); +} +#else /* VBOX_API_VERSION < 3001000 */ +static nsresult +_systemPropertiesGetMaxPortCountForStorageBus(ISystemProperties *systemProperties ATTRIBUTE_UNUSED, + PRUint32 bus ATTRIBUTE_UNUSED, + PRUint32 *maxPortCount ATTRIBUTE_UNUSED) +{ + VIR_WARN("No GetMaxPortCountForStorageBus in current version"); + return 0; +} + +static nsresult +_systemPropertiesGetMaxDevicesPerPortForStorageBus(ISystemProperties *systemProperties ATTRIBUTE_UNUSED, + PRUint32 bus ATTRIBUTE_UNUSED, + PRUint32 *maxDevicesPerPort ATTRIBUTE_UNUSED) +{ + VIR_WARN("No GetMaxDevicesPerPortForStorageBus in current version"); + return 0; +} +#endif + +static nsresult +_biosSettingsSetACPIEnabled(IBIOSSettings *bios, PRBool ACPIEnabled) +{ + return bios->vtbl->SetACPIEnabled(bios, ACPIEnabled); +} + +static nsresult +_biosSettingsSetIOAPICEnabled(IBIOSSettings *bios, PRBool IOAPICEnabled) +{ + return bios->vtbl->SetIOAPICEnabled(bios, IOAPICEnabled); +} + +static nsresult +_audioAdapterSetEnabled(IAudioAdapter *audioAdapter, PRBool enabled) +{ + return audioAdapter->vtbl->SetEnabled(audioAdapter, enabled); +} + +static nsresult +_audioAdapterSetAudioController(IAudioAdapter *audioAdapter, PRUint32 audioController) +{ + return audioAdapter->vtbl->SetAudioController(audioAdapter, audioController); +} + +static nsresult +_networkAdapterSetEnabled(INetworkAdapter *adapter, PRBool enabled) +{ + return adapter->vtbl->SetEnabled(adapter, enabled); +} + +static nsresult +_networkAdapterSetAdapterType(INetworkAdapter *adapter, PRUint32 adapterType) +{ + return adapter->vtbl->SetAdapterType(adapter, adapterType); +} + +static nsresult +_networkAdapterSetInternalNetwork(INetworkAdapter *adapter, PRUnichar *internalNetwork) +{ + return adapter->vtbl->SetInternalNetwork(adapter, internalNetwork); +} + +static nsresult +_networkAdapterSetMACAddress(INetworkAdapter *adapter, PRUnichar *MACAddress) +{ + return adapter->vtbl->SetMACAddress(adapter, MACAddress); +} + +#if VBOX_API_VERSION < 4001000 + +static nsresult +_networkAdapterSetBridgedInterface(INetworkAdapter *adapter, PRUnichar *hostInterface) +{ + return adapter->vtbl->SetHostInterface(adapter, hostInterface); +} + +static nsresult +_networkAdapterSetHostOnlyInterface(INetworkAdapter *adapter, PRUnichar *hostOnlyInterface) +{ + return adapter->vtbl->SetHostInterface(adapter, hostOnlyInterface); +} + +static nsresult +_networkAdapterAttachToBridgedInterface(INetworkAdapter *adapter) +{ + return adapter->vtbl->AttachToBridgedInterface(adapter); +} + +static nsresult +_networkAdapterAttachToInternalNetwork(INetworkAdapter *adapter) +{ + return adapter->vtbl->AttachToInternalNetwork(adapter); +} + +static nsresult +_networkAdapterAttachToHostOnlyInterface(INetworkAdapter *adapter) +{ + return adapter->vtbl->AttachToHostOnlyInterface(adapter); +} + +static nsresult +_networkAdapterAttachToNAT(INetworkAdapter *adapter) +{ + return adapter->vtbl->AttachToNAT(adapter); +} + +#else /* VBOX_API_VERSION >= 4001000 */ + +static nsresult +_networkAdapterSetBridgedInterface(INetworkAdapter *adapter, PRUnichar *bridgedInterface) +{ + return adapter->vtbl->SetBridgedInterface(adapter, bridgedInterface); +} + +static nsresult +_networkAdapterSetHostOnlyInterface(INetworkAdapter *adapter, PRUnichar *hostOnlyInterface) +{ + return adapter->vtbl->SetHostOnlyInterface(adapter, hostOnlyInterface); +} + +static nsresult +_networkAdapterAttachToBridgedInterface(INetworkAdapter *adapter) +{ + return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Bridged); +} + +static nsresult +_networkAdapterAttachToInternalNetwork(INetworkAdapter *adapter) +{ + return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Internal); +} + +static nsresult +_networkAdapterAttachToHostOnlyInterface(INetworkAdapter *adapter) +{ + return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_HostOnly); +} + +static nsresult +_networkAdapterAttachToNAT(INetworkAdapter *adapter) +{ + return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_NAT); +} + +#endif /* VBOX_API_VERSION >= 4001000 */ + +static nsresult +_serialPortSetEnabled(ISerialPort *port, PRBool enabled) +{ + return port->vtbl->SetEnabled(port, enabled); +} + +static nsresult +_serialPortSetPath(ISerialPort *port, PRUnichar *path) +{ + return port->vtbl->SetPath(port, path); +} + +static nsresult +_serialPortSetIRQ(ISerialPort *port, PRUint32 IRQ) +{ + return port->vtbl->SetIRQ(port, IRQ); +} + +static nsresult +_serialPortSetIOBase(ISerialPort *port, PRUint32 IOBase) +{ + return port->vtbl->SetIOBase(port, IOBase); +} + +static nsresult +_serialPortSetHostMode(ISerialPort *port, PRUint32 hostMode) +{ + return port->vtbl->SetHostMode(port, hostMode); +} + +static nsresult +_parallelPortSetEnabled(IParallelPort *port, PRBool enabled) +{ + return port->vtbl->SetEnabled(port, enabled); +} + +static nsresult +_parallelPortSetPath(IParallelPort *port, PRUnichar *path) +{ + return port->vtbl->SetPath(port, path); +} + +static nsresult +_parallelPortSetIRQ(IParallelPort *port, PRUint32 IRQ) +{ + return port->vtbl->SetIRQ(port, IRQ); +} + +static nsresult +_parallelPortSetIOBase(IParallelPort *port, PRUint32 IOBase) +{ + return port->vtbl->SetIOBase(port, IOBase); +} + +static nsresult +_vrdxServerSetEnabled(IVRDxServer *VRDxServer, PRBool enabled) +{ + return VRDxServer->vtbl->SetEnabled(VRDxServer, enabled); +} + +static nsresult +_vrdxServerSetPorts(vboxGlobalData *data ATTRIBUTE_UNUSED, + IVRDxServer *VRDxServer, virDomainGraphicsDefPtr graphics) +{ + nsresult rc = 0; +#if VBOX_API_VERSION < 3001000 + if (graphics->data.rdp.port) { + rc = VRDxServer->vtbl->SetPort(VRDxServer, + graphics->data.rdp.port); + VIR_DEBUG("VRDP Port changed to: %d", + graphics->data.rdp.port); + } else if (graphics->data.rdp.autoport) { + /* Setting the port to 0 will reset its value to + * the default one which is 3389 currently + */ + rc = VRDxServer->vtbl->SetPort(VRDxServer, 0); + VIR_DEBUG("VRDP Port changed to default, which is 3389 currently"); + } +#elif VBOX_API_VERSION < 4000000 /* 3001000 <= VBOX_API_VERSION < 4000000 */ + PRUnichar *portUtf16 = NULL; + portUtf16 = PRUnicharFromInt(graphics->data.rdp.port); + rc = VRDxServer->vtbl->SetPorts(VRDxServer, portUtf16); + VBOX_UTF16_FREE(portUtf16); +#else /* VBOX_API_VERSION >= 4000000 */ + PRUnichar *VRDEPortsKey = NULL; + PRUnichar *VRDEPortsValue = NULL; + VBOX_UTF8_TO_UTF16("TCP/Ports", &VRDEPortsKey); + VRDEPortsValue = PRUnicharFromInt(graphics->data.rdp.port); + rc = VRDxServer->vtbl->SetVRDEProperty(VRDxServer, VRDEPortsKey, + VRDEPortsValue); + VBOX_UTF16_FREE(VRDEPortsKey); + VBOX_UTF16_FREE(VRDEPortsValue); +#endif /* VBOX_API_VERSION >= 4000000 */ + return rc; +} + +static nsresult +_vrdxServerSetReuseSingleConnection(IVRDxServer *VRDxServer, PRBool enabled) +{ + return VRDxServer->vtbl->SetReuseSingleConnection(VRDxServer, enabled); +} + +static nsresult +_vrdxServerSetAllowMultiConnection(IVRDxServer *VRDxServer, PRBool enabled) +{ + return VRDxServer->vtbl->SetAllowMultiConnection(VRDxServer, enabled); +} + +static nsresult +_vrdxServerSetNetAddress(vboxGlobalData *data ATTRIBUTE_UNUSED, + IVRDxServer *VRDxServer, PRUnichar *netAddress) +{ +#if VBOX_API_VERSION < 4000000 + return VRDxServer->vtbl->SetNetAddress(VRDxServer, + netAddress); +#else /* VBOX_API_VERSION >= 4000000 */ + PRUnichar *netAddressKey = NULL; + nsresult rc; + VBOX_UTF8_TO_UTF16("TCP/Address", &netAddressKey); + rc = VRDxServer->vtbl->SetVRDEProperty(VRDxServer, netAddressKey, + netAddress); + VBOX_UTF16_FREE(netAddressKey); + return rc; +#endif /* VBOX_API_VERSION >= 4000000 */ +} + +static nsresult +_usbCommonEnable(IUSBCommon *USBCommon ATTRIBUTE_UNUSED) +{ + nsresult rc = 0; +#if VBOX_API_VERSION < 4003000 + USBCommon->vtbl->SetEnabled(USBCommon, 1); +# if VBOX_API_VERSION < 4002000 + rc = USBCommon->vtbl->SetEnabledEhci(USBCommon, 1); +# else /* VBOX_API_VERSION >= 4002000 */ + rc = USBCommon->vtbl->SetEnabledEHCI(USBCommon, 1); +# endif /* VBOX_API_VERSION >= 4002000 */ +#endif /* VBOX_API_VERSION >= 4003000 */ + /* We don't need to set usb enabled for vbox 4.3 and later */ + return rc; +} + +static nsresult +_usbCommonCreateDeviceFilter(IUSBCommon *USBCommon, PRUnichar *name, + IUSBDeviceFilter **filter) +{ + return USBCommon->vtbl->CreateDeviceFilter(USBCommon, name, filter); +} + +static nsresult +_usbCommonInsertDeviceFilter(IUSBCommon *USBCommon, PRUint32 position, + IUSBDeviceFilter *filter) +{ + return USBCommon->vtbl->InsertDeviceFilter(USBCommon, position, filter); +} + +static nsresult +_usbDeviceFilterSetProductId(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *productId) +{ + return USBDeviceFilter->vtbl->SetProductId(USBDeviceFilter, productId); +} + +static nsresult +_usbDeviceFilterSetActive(IUSBDeviceFilter *USBDeviceFilter, PRBool active) +{ + return USBDeviceFilter->vtbl->SetActive(USBDeviceFilter, active); +} + +static nsresult +_usbDeviceFilterSetVendorId(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *vendorId) +{ + return USBDeviceFilter->vtbl->SetVendorId(USBDeviceFilter, vendorId); +} + static nsresult _nsisupportsRelease(void *Ihandle) { /* It is safety to convert a pointer from IVirtual(or structs @@ -11199,6 +10852,27 @@ static nsresult _nsisupportsRelease(void *Ihandle) return nsi->vtbl->Release(nsi); } +static nsresult _mediumGetId(IMedium *medium, vboxIIDUnion *iidu) +{ + return medium->vtbl->GetId(medium, &IID_MEMBER(value)); +} + +static nsresult _mediumRelease(IMedium *medium) +{ + return _nsisupportsRelease(medium); +} + +static nsresult _mediumSetType(IMedium *medium ATTRIBUTE_UNUSED, + PRUint32 type ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION > 3000000 + return medium->vtbl->SetType(medium, type); +#else + VIR_WARN("There is no medium SetType in current version."); + return 0; +#endif +} + static bool _machineStateOnline(PRUint32 state) { return ((state >= MachineState_FirstOnline) && @@ -11235,13 +10909,37 @@ static vboxUniformedIVirtualBox _UIVirtualBox = { .GetVersion = _virtualboxGetVersion, .GetMachine = _virtualboxGetMachine, .GetSystemProperties = _virtualboxGetSystemProperties, + .CreateMachine = _virtualboxCreateMachine, + .RegisterMachine = _virtualboxRegisterMachine, + .FindMedium = _virtualboxFindMedium, + .OpenMedium = _virtualboxOpenMedium, }; static vboxUniformedIMachine _UIMachine = { + .AddStorageController = _machineAddStorageController, + .AttachDevice = _machineAttachDevice, + .CreateSharedFolder = _machineCreateSharedFolder, .GetAccessible = _machineGetAccessible, .GetState = _machineGetState, .GetName = _machineGetName, .GetId = _machineGetId, + .GetBIOSSettings = _machineGetBIOSSettings, + .GetAudioAdapter = _machineGetAudioAdapter, + .GetNetworkAdapter = _machineGetNetworkAdapter, + .GetChipsetType = _machineGetChipsetType, + .GetSerialPort = _machineGetSerialPort, + .GetParallelPort = _machineGetParallelPort, + .GetVRDxServer = _machineGetVRDxServer, + .GetUSBCommon = _machineGetUSBCommon, + .SetCPUCount = _machineSetCPUCount, + .SetMemorySize = _machineSetMemorySize, + .SetCPUProperty = _machineSetCPUProperty, + .SetBootOrder = _machineSetBootOrder, + .SetVRAMSize = _machineSetVRAMSize, + .SetMonitorCount = _machineSetMonitorCount, + .SetAccelerate3DEnabled = _machineSetAccelerate3DEnabled, + .SetAccelerate2DVideoEnabled = _machineSetAccelerate2DVideoEnabled, + .SetExtraData = _machineSetExtraData, .SaveSettings = _machineSaveSettings, }; @@ -11264,12 +10962,82 @@ static vboxUniformedIProgress _UIProgress = { static vboxUniformedISystemProperties _UISystemProperties = { .GetMaxGuestCPUCount = _systemPropertiesGetMaxGuestCPUCount, + .GetMaxBootPosition = _systemPropertiesGetMaxBootPosition, + .GetMaxNetworkAdapters = _systemPropertiesGetMaxNetworkAdapters, + .GetSerialPortCount = _systemPropertiesGetSerialPortCount, + .GetParallelPortCount = _systemPropertiesGetParallelPortCount, + .GetMaxPortCountForStorageBus = _systemPropertiesGetMaxPortCountForStorageBus, + .GetMaxDevicesPerPortForStorageBus = _systemPropertiesGetMaxDevicesPerPortForStorageBus, +}; + +static vboxUniformedIBIOSSettings _UIBIOSSettings = { + .SetACPIEnabled = _biosSettingsSetACPIEnabled, + .SetIOAPICEnabled = _biosSettingsSetIOAPICEnabled, +}; + +static vboxUniformedIAudioAdapter _UIAudioAdapter = { + .SetEnabled = _audioAdapterSetEnabled, + .SetAudioController = _audioAdapterSetAudioController, +}; + +static vboxUniformedINetworkAdapter _UINetworkAdapter = { + .SetEnabled = _networkAdapterSetEnabled, + .SetAdapterType = _networkAdapterSetAdapterType, + .SetBridgedInterface = _networkAdapterSetBridgedInterface, + .SetInternalNetwork = _networkAdapterSetInternalNetwork, + .SetHostOnlyInterface = _networkAdapterSetHostOnlyInterface, + .SetMACAddress = _networkAdapterSetMACAddress, + .AttachToBridgedInterface = _networkAdapterAttachToBridgedInterface, + .AttachToInternalNetwork = _networkAdapterAttachToInternalNetwork, + .AttachToHostOnlyInterface = _networkAdapterAttachToHostOnlyInterface, + .AttachToNAT = _networkAdapterAttachToNAT, +}; + +static vboxUniformedISerialPort _UISerialPort = { + .SetEnabled = _serialPortSetEnabled, + .SetPath = _serialPortSetPath, + .SetIRQ = _serialPortSetIRQ, + .SetIOBase = _serialPortSetIOBase, + .SetHostMode = _serialPortSetHostMode, +}; + +static vboxUniformedIParallelPort _UIParallelPort = { + .SetEnabled = _parallelPortSetEnabled, + .SetPath = _parallelPortSetPath, + .SetIRQ = _parallelPortSetIRQ, + .SetIOBase = _parallelPortSetIOBase, +}; + +static vboxUniformedIVRDxServer _UIVRDxServer = { + .SetEnabled = _vrdxServerSetEnabled, + .SetPorts = _vrdxServerSetPorts, + .SetReuseSingleConnection = _vrdxServerSetReuseSingleConnection, + .SetAllowMultiConnection = _vrdxServerSetAllowMultiConnection, + .SetNetAddress = _vrdxServerSetNetAddress, +}; + +static vboxUniformedIUSBCommon _UIUSBCommon = { + .Enable = _usbCommonEnable, + .CreateDeviceFilter = _usbCommonCreateDeviceFilter, + .InsertDeviceFilter = _usbCommonInsertDeviceFilter, +}; + +static vboxUniformedIUSBDeviceFilter _UIUSBDeviceFilter = { + .SetProductId = _usbDeviceFilterSetProductId, + .SetActive = _usbDeviceFilterSetActive, + .SetVendorId = _usbDeviceFilterSetVendorId, }; static vboxUniformednsISupports _nsUISupports = { .Release = _nsisupportsRelease, }; +static vboxUniformedIMedium _UIMedium = { + .GetId = _mediumGetId, + .Release = _mediumRelease, + .SetType = _mediumSetType, +}; + static uniformedMachineStateChecker _machineStateChecker = { .Online = _machineStateOnline, }; @@ -11283,6 +11051,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->detachDevices = _detachDevices; pVBoxAPI->unregisterMachine = _unregisterMachine; pVBoxAPI->deleteConfig = _deleteConfig; + pVBoxAPI->vboxAttachDrivesOld = _vboxAttachDrivesOld; pVBoxAPI->UPFN = _UPFN; pVBoxAPI->UIID = _UIID; pVBoxAPI->UArray = _UArray; @@ -11292,7 +11061,16 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->UIConsole = _UIConsole; pVBoxAPI->UIProgress = _UIProgress; pVBoxAPI->UISystemProperties = _UISystemProperties; + pVBoxAPI->UIBIOSSettings = _UIBIOSSettings; + pVBoxAPI->UIAudioAdapter = _UIAudioAdapter; + pVBoxAPI->UINetworkAdapter = _UINetworkAdapter; + pVBoxAPI->UISerialPort = _UISerialPort; + pVBoxAPI->UIParallelPort = _UIParallelPort; + pVBoxAPI->UIVRDxServer = _UIVRDxServer; + pVBoxAPI->UIUSBCommon = _UIUSBCommon; + pVBoxAPI->UIUSBDeviceFilter = _UIUSBDeviceFilter; pVBoxAPI->nsUISupports = _nsUISupports; + pVBoxAPI->UIMedium = _UIMedium; pVBoxAPI->machineStateChecker = _machineStateChecker; #if (VBOX_XPCOMC_VERSION == 0x00010000U) || (VBOX_API_VERSION == 2002000) @@ -11309,13 +11087,26 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) #endif /* !(VBOX_API_VERSION == 2002000) */ #if VBOX_API_VERSION >= 4000000 - /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */ pVBoxAPI->getMachineForSession = 1; pVBoxAPI->detachDevicesExplicitly = 0; + pVBoxAPI->vboxAttachDrivesUseOld = 0; #else /* VBOX_API_VERSION < 4000000 */ pVBoxAPI->getMachineForSession = 0; pVBoxAPI->detachDevicesExplicitly = 1; + pVBoxAPI->vboxAttachDrivesUseOld = 1; #endif /* VBOX_API_VERSION < 4000000 */ + +#if VBOX_API_VERSION >= 4001000 + pVBoxAPI->chipsetType = 1; +#else /* VBOX_API_VERSION < 4001000 */ + pVBoxAPI->chipsetType = 0; +#endif /* VBOX_API_VERSION < 4001000 */ + +#if VBOX_API_VERSION >= 3001000 + pVBoxAPI->accelerate2DVideo = 1; +#else /* VBOX_API_VERSION < 3001000 */ + pVBoxAPI->accelerate2DVideo = 0; +#endif /* VBOX_API_VERSION < 3001000 */ } /* End of vboxUniformedAPI and Begin of common codes */ diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index e68add6..5a12dfc 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -133,6 +133,26 @@ typedef struct { } vboxGlobalData; +/* Introducing new type to Handle interface conflict */ +# if defined(VBOX_API_VERSION) + +# if VBOX_API_VERSION < 4000000 +typedef IVRDPServer IVRDxServer; +# else /* VBOX_API_VERSION >= 4000000 */ +typedef IVRDEServer IVRDxServer; +# endif /* VBOX_API_VERSION >= 4000000 */ + +# if VBOX_API_VERSION < 4003000 +typedef IUSBController IUSBCommon; +# else /* VBOX_API_VERSION >= 4003000 */ +typedef IUSBDeviceFilters IUSBCommon; +# endif /* VBOX_API_VERSION >= 4003000 */ + +# else /* !defined(VBOX_API_VERSION) */ +typedef void IVRDxServer; +typedef void IUSBCommon; +# endif /* !defined(VBOX_API_VERSION) */ + /* vboxUniformedAPI gives vbox_common.c a uniformed layer to see * vbox API. */ @@ -172,14 +192,43 @@ typedef struct { nsresult (*GetVersion)(IVirtualBox *vboxObj, PRUnichar **versionUtf16); nsresult (*GetMachine)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine); nsresult (*GetSystemProperties)(IVirtualBox *vboxObj, ISystemProperties **systemProperties); + nsresult (*CreateMachine)(vboxGlobalData *data, virDomainDefPtr def, IMachine **machine, char *uuidstr); + nsresult (*RegisterMachine)(IVirtualBox *vboxObj, IMachine *machine); + nsresult (*FindMedium)(IVirtualBox *vboxObj, PRUnichar *location, PRUint32 deviceType, PRUint32 accessMode, IMedium **medium); + nsresult (*OpenMedium)(IVirtualBox *vboxObj, PRUnichar *location, PRUint32 deviceType, PRUint32 accessMode, IMedium **medium); } vboxUniformedIVirtualBox; /* Functions for IMachine */ typedef struct { + nsresult (*AddStorageController)(IMachine *machine, PRUnichar *name, + PRUint32 connectionType, IStorageController **controller); + nsresult (*AttachDevice)(IMachine *machine, PRUnichar *name, + PRInt32 controllerPort, PRInt32 device, + PRUint32 type, IMedium *medium); + nsresult (*CreateSharedFolder)(IMachine *machine, PRUnichar *name, + PRUnichar *hostPath, PRBool writable, + PRBool automount); nsresult (*GetAccessible)(IMachine *machine, PRBool *isAccessible); nsresult (*GetState)(IMachine *machine, PRUint32 *state); nsresult (*GetName)(IMachine *machine, PRUnichar **name); nsresult (*GetId)(IMachine *machine, vboxIIDUnion *iidu); + nsresult (*GetBIOSSettings)(IMachine *machine, IBIOSSettings **bios); + nsresult (*GetAudioAdapter)(IMachine *machine, IAudioAdapter **audioAdapter); + nsresult (*GetNetworkAdapter)(IMachine *machine, PRUint32 slot, INetworkAdapter **adapter); + nsresult (*GetChipsetType)(IMachine *machine, PRUint32 *chipsetType); + nsresult (*GetSerialPort)(IMachine *machine, PRUint32 slot, ISerialPort **port); + nsresult (*GetParallelPort)(IMachine *machine, PRUint32 slot, IParallelPort **port); + nsresult (*GetVRDxServer)(IMachine *machine, IVRDxServer **VRDxServer); + nsresult (*GetUSBCommon)(IMachine *machine, IUSBCommon **USBCommon); + nsresult (*SetCPUCount)(IMachine *machine, PRUint32 CPUCount); + nsresult (*SetMemorySize)(IMachine *machine, PRUint32 memorySize); + nsresult (*SetCPUProperty)(IMachine *machine, PRUint32 property, PRBool value); + nsresult (*SetBootOrder)(IMachine *machine, PRUint32 position, PRUint32 device); + nsresult (*SetVRAMSize)(IMachine *machine, PRUint32 VRAMSize); + nsresult (*SetMonitorCount)(IMachine *machine, PRUint32 monitorCount); + nsresult (*SetAccelerate3DEnabled)(IMachine *machine, PRBool accelerate3DEnabled); + nsresult (*SetAccelerate2DVideoEnabled)(IMachine *machine, PRBool accelerate2DVideoEnabled); + nsresult (*SetExtraData)(IMachine *machine, PRUnichar *key, PRUnichar *value); nsresult (*SaveSettings)(IMachine *machine); } vboxUniformedIMachine; @@ -206,13 +255,98 @@ typedef struct { /* Functions for ISystemProperties */ typedef struct { nsresult (*GetMaxGuestCPUCount)(ISystemProperties *systemProperties, PRUint32 *maxCPUCount); + nsresult (*GetMaxBootPosition)(ISystemProperties *systemProperties, PRUint32 *maxBootPosition); + nsresult (*GetMaxNetworkAdapters)(ISystemProperties *systemProperties, PRUint32 chipset, + PRUint32 *maxNetworkAdapters); + nsresult (*GetSerialPortCount)(ISystemProperties *systemProperties, PRUint32 *SerialPortCount); + nsresult (*GetParallelPortCount)(ISystemProperties *systemProperties, PRUint32 *ParallelPortCount); + nsresult (*GetMaxPortCountForStorageBus)(ISystemProperties *systemProperties, PRUint32 bus, + PRUint32 *maxPortCount); + nsresult (*GetMaxDevicesPerPortForStorageBus)(ISystemProperties *systemProperties, + PRUint32 bus, PRUint32 *maxDevicesPerPort); } vboxUniformedISystemProperties; +/* Functions for IBIOSSettings */ +typedef struct { + nsresult (*SetACPIEnabled)(IBIOSSettings *bios, PRBool ACPIEnabled); + nsresult (*SetIOAPICEnabled)(IBIOSSettings *bios, PRBool IOAPICEnabled); +} vboxUniformedIBIOSSettings; + +/* Functions for IAudioAdapter */ +typedef struct { + nsresult (*SetEnabled)(IAudioAdapter *audioAdapter, PRBool enabled); + nsresult (*SetAudioController)(IAudioAdapter *audioAdapter, PRUint32 audioController); +} vboxUniformedIAudioAdapter; + +/* Functions for INetworkAdapter */ +typedef struct { + nsresult (*SetEnabled)(INetworkAdapter *adapter, PRBool enabled); + nsresult (*SetAdapterType)(INetworkAdapter *adapter, PRUint32 adapterType); + nsresult (*SetBridgedInterface)(INetworkAdapter *adapter, PRUnichar *bridgedInterface); + nsresult (*SetInternalNetwork)(INetworkAdapter *adapter, PRUnichar *internalNetwork); + nsresult (*SetHostOnlyInterface)(INetworkAdapter *adapter, PRUnichar *hostOnlyInterface); + nsresult (*SetMACAddress)(INetworkAdapter *adapter, PRUnichar *MACAddress); + nsresult (*AttachToBridgedInterface)(INetworkAdapter *adapter); + nsresult (*AttachToInternalNetwork)(INetworkAdapter *adapter); + nsresult (*AttachToHostOnlyInterface)(INetworkAdapter *adapter); + nsresult (*AttachToNAT)(INetworkAdapter *adapter); +} vboxUniformedINetworkAdapter; + +/* Functions for ISerialPort */ +typedef struct { + nsresult (*SetEnabled)(ISerialPort *port, PRBool enabled); + nsresult (*SetPath)(ISerialPort *port, PRUnichar *path); + nsresult (*SetIRQ)(ISerialPort *port, PRUint32 IRQ); + nsresult (*SetIOBase)(ISerialPort *port, PRUint32 IOBase); + nsresult (*SetHostMode)(ISerialPort *port, PRUint32 hostMode); +} vboxUniformedISerialPort; + +/* Functions for IParallelPort */ +typedef struct { + nsresult (*SetEnabled)(IParallelPort *port, PRBool enabled); + nsresult (*SetPath)(IParallelPort *port, PRUnichar *path); + nsresult (*SetIRQ)(IParallelPort *port, PRUint32 IRQ); + nsresult (*SetIOBase)(IParallelPort *port, PRUint32 IOBase); +} vboxUniformedIParallelPort; + +/* Functions for IVRDPServer and IVRDEServer */ +typedef struct { + nsresult (*SetEnabled)(IVRDxServer *VRDxServer, PRBool enabled); + nsresult (*SetPorts)(vboxGlobalData *data, IVRDxServer *VRDxServer, + virDomainGraphicsDefPtr graphics); + nsresult (*SetReuseSingleConnection)(IVRDxServer *VRDxServer, PRBool enabled); + nsresult (*SetAllowMultiConnection)(IVRDxServer *VRDxServer, PRBool enabled); + nsresult (*SetNetAddress)(vboxGlobalData *data, IVRDxServer *VRDxServer, + PRUnichar *netAddress); +} vboxUniformedIVRDxServer; + +/* Common Functions for IUSBController and IUSBDeviceFilters */ +typedef struct { + nsresult (*Enable)(IUSBCommon *USBCommon); + nsresult (*CreateDeviceFilter)(IUSBCommon *USBCommon, PRUnichar *name, + IUSBDeviceFilter **filter); + nsresult (*InsertDeviceFilter)(IUSBCommon *USBCommon, PRUint32 position, + IUSBDeviceFilter *filter); +} vboxUniformedIUSBCommon; + +typedef struct { + nsresult (*SetProductId)(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *productId); + nsresult (*SetActive)(IUSBDeviceFilter *USBDeviceFilter, PRBool active); + nsresult (*SetVendorId)(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *vendorId); +} vboxUniformedIUSBDeviceFilter; + /* Functions for nsISupports */ typedef struct { nsresult (*Release)(void *Ihandle); } vboxUniformednsISupports; +/* Functions for IMedium */ +typedef struct { + nsresult (*GetId)(IMedium *medium, vboxIIDUnion *iidu); + nsresult (*Release)(IMedium *medium); + nsresult (*SetType)(IMedium *medium, PRUint32 type); +} vboxUniformedIMedium; + typedef struct { bool (*Online)(PRUint32 state); } uniformedMachineStateChecker; @@ -227,6 +361,7 @@ typedef struct { void (*detachDevices)(vboxGlobalData *data, IMachine *machine, PRUnichar *hddcnameUtf16); nsresult (*unregisterMachine)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine); void (*deleteConfig)(IMachine *machine); + void (*vboxAttachDrivesOld)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine); vboxUniformedPFN UPFN; vboxUniformedIID UIID; vboxUniformedArray UArray; @@ -236,13 +371,25 @@ typedef struct { vboxUniformedIConsole UIConsole; vboxUniformedIProgress UIProgress; vboxUniformedISystemProperties UISystemProperties; + vboxUniformedIBIOSSettings UIBIOSSettings; + vboxUniformedIAudioAdapter UIAudioAdapter; + vboxUniformedINetworkAdapter UINetworkAdapter; + vboxUniformedISerialPort UISerialPort; + vboxUniformedIParallelPort UIParallelPort; + vboxUniformedIVRDxServer UIVRDxServer; + vboxUniformedIUSBCommon UIUSBCommon; + vboxUniformedIUSBDeviceFilter UIUSBDeviceFilter; vboxUniformednsISupports nsUISupports; + vboxUniformedIMedium UIMedium; uniformedMachineStateChecker machineStateChecker; /* vbox API features */ bool fWatchNeedInitialize; bool domainEventCallbacks; bool getMachineForSession; bool detachDevicesExplicitly; + bool chipsetType; + bool accelerate2DVideo; + bool vboxAttachDrivesUseOld; } vboxUniformedAPI; /* libvirt API @@ -266,6 +413,7 @@ int vboxConnectNumOfDomains(virConnectPtr conn); virDomainPtr vboxDomainLookupByID(virConnectPtr conn, int id); virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid); +virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml); int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags); /* Version specified functions for installing uniformed API */ -- 1.7.9.5

--- src/vbox/vbox_common.c | 219 ++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 274 +++++++---------------------------------- src/vbox/vbox_uniformed_api.h | 8 ++ 3 files changed, 269 insertions(+), 232 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 0d57b2c..c5b6c4e 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -1928,3 +1928,222 @@ int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags) return ret; } + +static int +vboxStartMachine(virDomainPtr dom, int maxDomID, IMachine *machine, vboxIIDUnion *iid) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + int vrdpPresent = 0; + int sdlPresent = 0; + int guiPresent = 0; + char *guiDisplay = NULL; + char *sdlDisplay = NULL; + PRUnichar *keyTypeUtf16 = NULL; + PRUnichar *valueTypeUtf16 = NULL; + char *valueTypeUtf8 = NULL; + PRUnichar *keyDislpayUtf16 = NULL; + PRUnichar *valueDisplayUtf16 = NULL; + char *valueDisplayUtf8 = NULL; + IProgress *progress = NULL; + PRUnichar *env = NULL; + PRUnichar *sessionType = NULL; + nsresult rc; + + VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); + gVBoxAPI.UIMachine.GetExtraData(machine, keyTypeUtf16, &valueTypeUtf16); + VBOX_UTF16_FREE(keyTypeUtf16); + + if (valueTypeUtf16) { + VBOX_UTF16_TO_UTF8(valueTypeUtf16, &valueTypeUtf8); + VBOX_UTF16_FREE(valueTypeUtf16); + + if (STREQ(valueTypeUtf8, "sdl") || STREQ(valueTypeUtf8, "gui")) { + + VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16); + gVBoxAPI.UIMachine.GetExtraData(machine, keyDislpayUtf16, + &valueDisplayUtf16); + VBOX_UTF16_FREE(keyDislpayUtf16); + + if (valueDisplayUtf16) { + VBOX_UTF16_TO_UTF8(valueDisplayUtf16, &valueDisplayUtf8); + VBOX_UTF16_FREE(valueDisplayUtf16); + + if (strlen(valueDisplayUtf8) <= 0) + VBOX_UTF8_FREE(valueDisplayUtf8); + } + + if (STREQ(valueTypeUtf8, "sdl")) { + sdlPresent = 1; + if (VIR_STRDUP(sdlDisplay, valueDisplayUtf8) < 0) { + /* just don't go to cleanup yet as it is ok to have + * sdlDisplay as NULL and we check it below if it + * exist and then only use it there + */ + } + } + + if (STREQ(valueTypeUtf8, "gui")) { + guiPresent = 1; + if (VIR_STRDUP(guiDisplay, valueDisplayUtf8) < 0) { + /* just don't go to cleanup yet as it is ok to have + * guiDisplay as NULL and we check it below if it + * exist and then only use it there + */ + } + } + } + + if (STREQ(valueTypeUtf8, "vrdp")) { + vrdpPresent = 1; + } + + if (!vrdpPresent && !sdlPresent && !guiPresent) { + /* if nothing is selected it means either the machine xml + * file is really old or some values are missing so fallback + */ + guiPresent = 1; + } + + VBOX_UTF8_FREE(valueTypeUtf8); + + } else { + guiPresent = 1; + } + VBOX_UTF8_FREE(valueDisplayUtf8); + + if (guiPresent) { + if (guiDisplay) { + char *displayutf8; + if (virAsprintf(&displayutf8, "DISPLAY=%s", guiDisplay) >= 0) { + VBOX_UTF8_TO_UTF16(displayutf8, &env); + VIR_FREE(displayutf8); + } + VIR_FREE(guiDisplay); + } + + VBOX_UTF8_TO_UTF16("gui", &sessionType); + } + + if (sdlPresent) { + if (sdlDisplay) { + char *displayutf8; + if (virAsprintf(&displayutf8, "DISPLAY=%s", sdlDisplay) >= 0) { + VBOX_UTF8_TO_UTF16(displayutf8, &env); + VIR_FREE(displayutf8); + } + VIR_FREE(sdlDisplay); + } + + VBOX_UTF8_TO_UTF16("sdl", &sessionType); + } + + if (vrdpPresent) { + VBOX_UTF8_TO_UTF16("vrdp", &sessionType); + } + + rc = gVBoxAPI.UIMachine.LaunchVMProcess(data, machine, iid, + sessionType, env, + &progress); + + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("OpenRemoteSession/LaunchVMProcess failed, domain can't be started")); + ret = -1; + } else { + PRBool completed = 0; + resultCodeUnion resultCode; + + gVBoxAPI.UIProgress.WaitForCompletion(progress, -1); + rc = gVBoxAPI.UIProgress.GetCompleted(progress, &completed); + if (NS_FAILED(rc)) { + /* error */ + ret = -1; + } + gVBoxAPI.UIProgress.GetResultCode(progress, &resultCode); + if (RC_FAILED(resultCode)) { + /* error */ + ret = -1; + } else { + /* all ok set the domid */ + dom->id = maxDomID + 1; + ret = 0; + } + } + + VBOX_RELEASE(progress); + + gVBoxAPI.UISession.Close(data->vboxSession); + + VBOX_UTF16_FREE(env); + VBOX_UTF16_FREE(sessionType); + + return ret; +} + +int vboxDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxArray machines = VBOX_ARRAY_INITIALIZER; + unsigned char uuid[VIR_UUID_BUFLEN] = {0}; + nsresult rc; + size_t i = 0; + + virCheckFlags(0, -1); + + if (!dom->name) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Error while reading the domain name")); + goto cleanup; + } + + rc = gVBoxAPI.UArray.vboxArrayGet(&machines, data->vboxObj, ARRAY_GET_MACHINES); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get list of machines, rc=%08x"), (unsigned)rc); + goto cleanup; + } + + for (i = 0; i < machines.count; ++i) { + IMachine *machine = machines.items[i]; + PRBool isAccessible = PR_FALSE; + + if (!machine) + continue; + + gVBoxAPI.UIMachine.GetAccessible(machine, &isAccessible); + if (isAccessible) { + vboxIIDUnion iid; + + VBOX_IID_INITIALIZE(&iid); + + rc = gVBoxAPI.UIMachine.GetId(machine, &iid); + if (NS_FAILED(rc)) + continue; + vboxIIDToUUID(&iid, uuid); + + if (memcmp(dom->uuid, uuid, VIR_UUID_BUFLEN) == 0) { + PRUint32 state; + gVBoxAPI.UIMachine.GetState(machine, &state); + + if (gVBoxAPI.machineStateChecker.NotStart(state)) { + ret = vboxStartMachine(dom, i, machine, &iid); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("machine is not in " + "poweroff|saved|aborted state, so " + "couldn't start it")); + ret = -1; + } + } + vboxIIDUnalloc(&iid); + if (ret != -1) + break; + } + } + + /* Do the cleanup and take care you dont leak any memory */ + gVBoxAPI.UArray.vboxArrayRelease(&machines); + + cleanup: + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index a5aa3e8..c13d1a9 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -3064,238 +3064,6 @@ static int vboxConnectNumOfDefinedDomains(virConnectPtr conn) return ret; } - -static int -vboxStartMachine(virDomainPtr dom, int maxDomID, IMachine *machine, - vboxIID *iid ATTRIBUTE_UNUSED /* >= 4.0 */) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - int vrdpPresent = 0; - int sdlPresent = 0; - int guiPresent = 0; - char *guiDisplay = NULL; - char *sdlDisplay = NULL; - PRUnichar *keyTypeUtf16 = NULL; - PRUnichar *valueTypeUtf16 = NULL; - char *valueTypeUtf8 = NULL; - PRUnichar *keyDislpayUtf16 = NULL; - PRUnichar *valueDisplayUtf16 = NULL; - char *valueDisplayUtf8 = NULL; - IProgress *progress = NULL; - PRUnichar *env = NULL; - PRUnichar *sessionType = NULL; - nsresult rc; - - VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); - machine->vtbl->GetExtraData(machine, keyTypeUtf16, &valueTypeUtf16); - VBOX_UTF16_FREE(keyTypeUtf16); - - if (valueTypeUtf16) { - VBOX_UTF16_TO_UTF8(valueTypeUtf16, &valueTypeUtf8); - VBOX_UTF16_FREE(valueTypeUtf16); - - if (STREQ(valueTypeUtf8, "sdl") || STREQ(valueTypeUtf8, "gui")) { - - VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16); - machine->vtbl->GetExtraData(machine, keyDislpayUtf16, - &valueDisplayUtf16); - VBOX_UTF16_FREE(keyDislpayUtf16); - - if (valueDisplayUtf16) { - VBOX_UTF16_TO_UTF8(valueDisplayUtf16, &valueDisplayUtf8); - VBOX_UTF16_FREE(valueDisplayUtf16); - - if (strlen(valueDisplayUtf8) <= 0) - VBOX_UTF8_FREE(valueDisplayUtf8); - } - - if (STREQ(valueTypeUtf8, "sdl")) { - sdlPresent = 1; - if (VIR_STRDUP(sdlDisplay, valueDisplayUtf8) < 0) { - /* just don't go to cleanup yet as it is ok to have - * sdlDisplay as NULL and we check it below if it - * exist and then only use it there - */ - } - } - - if (STREQ(valueTypeUtf8, "gui")) { - guiPresent = 1; - if (VIR_STRDUP(guiDisplay, valueDisplayUtf8) < 0) { - /* just don't go to cleanup yet as it is ok to have - * guiDisplay as NULL and we check it below if it - * exist and then only use it there - */ - } - } - } - - if (STREQ(valueTypeUtf8, "vrdp")) { - vrdpPresent = 1; - } - - if (!vrdpPresent && !sdlPresent && !guiPresent) { - /* if nothing is selected it means either the machine xml - * file is really old or some values are missing so fallback - */ - guiPresent = 1; - } - - VBOX_UTF8_FREE(valueTypeUtf8); - - } else { - guiPresent = 1; - } - VBOX_UTF8_FREE(valueDisplayUtf8); - - if (guiPresent) { - if (guiDisplay) { - char *displayutf8; - if (virAsprintf(&displayutf8, "DISPLAY=%s", guiDisplay) >= 0) { - VBOX_UTF8_TO_UTF16(displayutf8, &env); - VIR_FREE(displayutf8); - } - VIR_FREE(guiDisplay); - } - - VBOX_UTF8_TO_UTF16("gui", &sessionType); - } - - if (sdlPresent) { - if (sdlDisplay) { - char *displayutf8; - if (virAsprintf(&displayutf8, "DISPLAY=%s", sdlDisplay) >= 0) { - VBOX_UTF8_TO_UTF16(displayutf8, &env); - VIR_FREE(displayutf8); - } - VIR_FREE(sdlDisplay); - } - - VBOX_UTF8_TO_UTF16("sdl", &sessionType); - } - - if (vrdpPresent) { - VBOX_UTF8_TO_UTF16("vrdp", &sessionType); - } - -#if VBOX_API_VERSION < 4000000 - rc = data->vboxObj->vtbl->OpenRemoteSession(data->vboxObj, - data->vboxSession, - iid->value, - sessionType, - env, - &progress); -#else /* VBOX_API_VERSION >= 4000000 */ - rc = machine->vtbl->LaunchVMProcess(machine, data->vboxSession, - sessionType, env, &progress); -#endif /* VBOX_API_VERSION >= 4000000 */ - - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("OpenRemoteSession/LaunchVMProcess failed, domain can't be started")); - ret = -1; - } else { - PRBool completed = 0; -#if VBOX_API_VERSION == 2002000 - nsresult resultCode; -#else - PRInt32 resultCode; -#endif - progress->vtbl->WaitForCompletion(progress, -1); - rc = progress->vtbl->GetCompleted(progress, &completed); - if (NS_FAILED(rc)) { - /* error */ - ret = -1; - } - progress->vtbl->GetResultCode(progress, &resultCode); - if (NS_FAILED(resultCode)) { - /* error */ - ret = -1; - } else { - /* all ok set the domid */ - dom->id = maxDomID + 1; - ret = 0; - } - } - - VBOX_RELEASE(progress); - - VBOX_SESSION_CLOSE(); - - VBOX_UTF16_FREE(env); - VBOX_UTF16_FREE(sessionType); - - return ret; -} - -static int vboxDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxArray machines = VBOX_ARRAY_INITIALIZER; - unsigned char uuid[VIR_UUID_BUFLEN] = {0}; - nsresult rc; - size_t i = 0; - - virCheckFlags(0, -1); - - if (!dom->name) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Error while reading the domain name")); - goto cleanup; - } - - rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not get list of machines, rc=%08x"), (unsigned)rc); - goto cleanup; - } - - for (i = 0; i < machines.count; ++i) { - IMachine *machine = machines.items[i]; - PRBool isAccessible = PR_FALSE; - - if (!machine) - continue; - - machine->vtbl->GetAccessible(machine, &isAccessible); - if (isAccessible) { - vboxIID iid = VBOX_IID_INITIALIZER; - - rc = machine->vtbl->GetId(machine, &iid.value); - if (NS_FAILED(rc)) - continue; - vboxIIDToUUID(&iid, uuid); - - if (memcmp(dom->uuid, uuid, VIR_UUID_BUFLEN) == 0) { - PRUint32 state = MachineState_Null; - machine->vtbl->GetState(machine, &state); - - if ((state == MachineState_PoweredOff) || - (state == MachineState_Saved) || - (state == MachineState_Aborted)) { - ret = vboxStartMachine(dom, i, machine, &iid); - } else { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("machine is not in " - "poweroff|saved|aborted state, so " - "couldn't start it")); - ret = -1; - } - } - vboxIIDUnalloc(&iid); - if (ret != -1) - break; - } - } - - /* Do the cleanup and take care you dont leak any memory */ - vboxArrayRelease(&machines); - - cleanup: - return ret; -} - static int vboxDomainCreate(virDomainPtr dom) { return vboxDomainCreateWithFlags(dom, 0); @@ -10238,6 +10006,25 @@ _machineCreateSharedFolder(IMachine *machine, PRUnichar *name, #endif /* VBOX_API_VERSION >= 4000000 */ } +static nsresult +_machineLaunchVMProcess(vboxGlobalData *data, + IMachine *machine ATTRIBUTE_UNUSED, + vboxIIDUnion *iidu ATTRIBUTE_UNUSED, + PRUnichar *sessionType, PRUnichar *env, + IProgress **progress) +{ +#if VBOX_API_VERSION < 4000000 + return data->vboxObj->vtbl->OpenRemoteSession(data->vboxObj, + data->vboxSession, + IID_MEMBER(value), + sessionType, + env, + progress); +#else /* VBOX_API_VERSION >= 4000000 */ + return machine->vtbl->LaunchVMProcess(machine, data->vboxSession, + sessionType, env, progress); +#endif /* VBOX_API_VERSION >= 4000000 */ +} static nsresult _machineGetAccessible(IMachine *machine, PRBool *isAccessible) @@ -10385,6 +10172,12 @@ _machineSetAccelerate2DVideoEnabled(IMachine *machine ATTRIBUTE_UNUSED, } static nsresult +_machineGetExtraData(IMachine *machine, PRUnichar *key, PRUnichar **value) +{ + return machine->vtbl->GetExtraData(machine, key, value); +} + +static nsresult _machineSetExtraData(IMachine *machine, PRUnichar *key, PRUnichar *value) { return machine->vtbl->SetExtraData(machine, key, value); @@ -10473,6 +10266,12 @@ _progressGetResultCode(IProgress *progress, resultCodeUnion *resultCode) } static nsresult +_progressGetCompleted(IProgress *progress, PRBool *completed) +{ + return progress->vtbl->GetCompleted(progress, completed); +} + +static nsresult _systemPropertiesGetMaxGuestCPUCount(ISystemProperties *systemProperties, PRUint32 *maxCPUCount) { return systemProperties->vtbl->GetMaxGuestCPUCount(systemProperties, maxCPUCount); @@ -10879,6 +10678,13 @@ static bool _machineStateOnline(PRUint32 state) (state <= MachineState_LastOnline)); } +static bool _machineStateNotStart(PRUint32 state) +{ + return ((state == MachineState_PoweredOff) || + (state == MachineState_Saved) || + (state == MachineState_Aborted)); +} + static vboxUniformedPFN _UPFN = { .Initialize = _pfnInitialize, .Uninitialize = _pfnUninitialize, @@ -10919,6 +10725,7 @@ static vboxUniformedIMachine _UIMachine = { .AddStorageController = _machineAddStorageController, .AttachDevice = _machineAttachDevice, .CreateSharedFolder = _machineCreateSharedFolder, + .LaunchVMProcess = _machineLaunchVMProcess, .GetAccessible = _machineGetAccessible, .GetState = _machineGetState, .GetName = _machineGetName, @@ -10939,6 +10746,7 @@ static vboxUniformedIMachine _UIMachine = { .SetMonitorCount = _machineSetMonitorCount, .SetAccelerate3DEnabled = _machineSetAccelerate3DEnabled, .SetAccelerate2DVideoEnabled = _machineSetAccelerate2DVideoEnabled, + .GetExtraData = _machineGetExtraData, .SetExtraData = _machineSetExtraData, .SaveSettings = _machineSaveSettings, }; @@ -10958,6 +10766,7 @@ static vboxUniformedIConsole _UIConsole = { static vboxUniformedIProgress _UIProgress = { .WaitForCompletion = _progressWaitForCompletion, .GetResultCode = _progressGetResultCode, + .GetCompleted = _progressGetCompleted, }; static vboxUniformedISystemProperties _UISystemProperties = { @@ -11040,6 +10849,7 @@ static vboxUniformedIMedium _UIMedium = { static uniformedMachineStateChecker _machineStateChecker = { .Online = _machineStateOnline, + .NotStart = _machineStateNotStart, }; void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 5a12dfc..5c406c9 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -208,6 +208,10 @@ typedef struct { nsresult (*CreateSharedFolder)(IMachine *machine, PRUnichar *name, PRUnichar *hostPath, PRBool writable, PRBool automount); + nsresult (*LaunchVMProcess)(vboxGlobalData *data, IMachine *machine, + vboxIIDUnion *iidu, + PRUnichar *sessionType, PRUnichar *env, + IProgress **progress); nsresult (*GetAccessible)(IMachine *machine, PRBool *isAccessible); nsresult (*GetState)(IMachine *machine, PRUint32 *state); nsresult (*GetName)(IMachine *machine, PRUnichar **name); @@ -228,6 +232,7 @@ typedef struct { nsresult (*SetMonitorCount)(IMachine *machine, PRUint32 monitorCount); nsresult (*SetAccelerate3DEnabled)(IMachine *machine, PRBool accelerate3DEnabled); nsresult (*SetAccelerate2DVideoEnabled)(IMachine *machine, PRBool accelerate2DVideoEnabled); + nsresult (*GetExtraData)(IMachine *machine, PRUnichar *key, PRUnichar **value); nsresult (*SetExtraData)(IMachine *machine, PRUnichar *key, PRUnichar *value); nsresult (*SaveSettings)(IMachine *machine); } vboxUniformedIMachine; @@ -250,6 +255,7 @@ typedef struct { typedef struct { nsresult (*WaitForCompletion)(IProgress *progress, PRInt32 timeout); nsresult (*GetResultCode)(IProgress *progress, resultCodeUnion *resultCode); + nsresult (*GetCompleted)(IProgress *progress, PRBool *completed); } vboxUniformedIProgress; /* Functions for ISystemProperties */ @@ -349,6 +355,7 @@ typedef struct { typedef struct { bool (*Online)(PRUint32 state); + bool (*NotStart)(PRUint32 state); } uniformedMachineStateChecker; typedef struct { @@ -415,6 +422,7 @@ virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid); virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml); int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags); +int vboxDomainCreateWithFlags(virDomainPtr dom, unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 5 +++++ src/vbox/vbox_tmpl.c | 7 ------- src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index c5b6c4e..4861d52 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2147,3 +2147,8 @@ int vboxDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) cleanup: return ret; } + +int vboxDomainCreate(virDomainPtr dom) +{ + return vboxDomainCreateWithFlags(dom, 0); +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index c13d1a9..2c3097b 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -249,8 +249,6 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL; #endif /* VBOX_API_VERSION >= 4000000 */ -static int vboxDomainCreate(virDomainPtr dom); - #if VBOX_API_VERSION > 2002000 && VBOX_API_VERSION < 4000000 /* Since vboxConnectGetCapabilities has been rewriten, * vboxDiverLock and Unlock only be used in 3.* */ @@ -3064,11 +3062,6 @@ static int vboxConnectNumOfDefinedDomains(virConnectPtr conn) return ret; } -static int vboxDomainCreate(virDomainPtr dom) -{ - return vboxDomainCreateWithFlags(dom, 0); -} - #if VBOX_API_VERSION < 3001000 static void diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 5c406c9..7e04845 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -423,6 +423,7 @@ virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn, virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml); int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags); int vboxDomainCreateWithFlags(virDomainPtr dom, unsigned int flags); +int vboxDomainCreate(virDomainPtr dom); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 28 ++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 28 ---------------------------- src/vbox/vbox_uniformed_api.h | 2 ++ 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 4861d52..a278a37 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2152,3 +2152,31 @@ int vboxDomainCreate(virDomainPtr dom) { return vboxDomainCreateWithFlags(dom, 0); } + +virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml, + unsigned int flags) +{ + /* VirtualBox currently doesn't have support for running + * virtual machines without actually defining them and thus + * for time being just define new machine and start it. + * + * TODO: After the appropriate API's are added in VirtualBox + * change this behaviour to the expected one. + */ + + virDomainPtr dom; + + virCheckFlags(0, NULL); + + dom = vboxDomainDefineXML(conn, xml); + if (dom == NULL) + return NULL; + + if (vboxDomainCreate(dom) < 0) { + vboxDomainUndefineFlags(dom, 0); + virObjectUnref(dom); + return NULL; + } + + return dom; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 2c3097b..c4232aa 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -916,34 +916,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml, - unsigned int flags) -{ - /* VirtualBox currently doesn't have support for running - * virtual machines without actually defining them and thus - * for time being just define new machine and start it. - * - * TODO: After the appropriate API's are added in VirtualBox - * change this behaviour to the expected one. - */ - - virDomainPtr dom; - - virCheckFlags(0, NULL); - - dom = vboxDomainDefineXML(conn, xml); - if (dom == NULL) - return NULL; - - if (vboxDomainCreate(dom) < 0) { - vboxDomainUndefineFlags(dom, 0); - virObjectUnref(dom); - return NULL; - } - - return dom; -} - static virDomainPtr vboxDomainLookupByName(virConnectPtr conn, const char *name) { diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 7e04845..55f2eec 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -424,6 +424,8 @@ virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml); int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags); int vboxDomainCreateWithFlags(virDomainPtr dom, unsigned int flags); int vboxDomainCreate(virDomainPtr dom); +virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml, + unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 70 ++++++++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 71 ----------------------------------------- src/vbox/vbox_uniformed_api.h | 2 ++ 3 files changed, 72 insertions(+), 71 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index a278a37..b1f0df3 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -822,6 +822,76 @@ virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn, return ret; } +virDomainPtr +vboxDomainLookupByName(virConnectPtr conn, const char *name) +{ + VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL); + vboxArray machines = VBOX_ARRAY_INITIALIZER; + vboxIIDUnion iid; + char *machineNameUtf8 = NULL; + PRUnichar *machineNameUtf16 = NULL; + unsigned char uuid[VIR_UUID_BUFLEN]; + size_t i; + int matched = 0; + nsresult rc; + + VBOX_IID_INITIALIZE(&iid); + rc = gVBoxAPI.UArray.vboxArrayGet(&machines, data->vboxObj, ARRAY_GET_MACHINES); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get list of machines, rc=%08x"), (unsigned)rc); + return NULL; + } + + for (i = 0; i < machines.count; ++i) { + IMachine *machine = machines.items[i]; + PRBool isAccessible = PR_FALSE; + + if (!machine) + continue; + + gVBoxAPI.UIMachine.GetAccessible(machine, &isAccessible); + if (!isAccessible) + continue; + + gVBoxAPI.UIMachine.GetName(machine, &machineNameUtf16); + VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8); + + if (STREQ(name, machineNameUtf8)) { + + PRUint32 state; + + matched = 1; + + gVBoxAPI.UIMachine.GetId(machine, &iid); + vboxIIDToUUID(&iid, uuid); + vboxIIDUnalloc(&iid); + + gVBoxAPI.UIMachine.GetState(machine, &state); + + /* get a new domain pointer from virGetDomain, if it fails + * then no need to assign the id, else assign the id, cause + * it is -1 by default. rest is taken care by virGetDomain + * itself, so need not worry. + */ + + ret = virGetDomain(conn, machineNameUtf8, uuid); + if (ret && + gVBoxAPI.machineStateChecker.Online(state)) + ret->id = i + 1; + } + + VBOX_UTF8_FREE(machineNameUtf8); + VBOX_COM_UNALLOC_MEM(machineNameUtf16); + if (matched == 1) + break; + } + + gVBoxAPI.UArray.vboxArrayRelease(&machines); + + return ret; +} + static void vboxSetBootDeviceOrder(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index c4232aa..9ace580 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -916,77 +916,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static virDomainPtr -vboxDomainLookupByName(virConnectPtr conn, const char *name) -{ - VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL); - vboxArray machines = VBOX_ARRAY_INITIALIZER; - vboxIID iid = VBOX_IID_INITIALIZER; - char *machineNameUtf8 = NULL; - PRUnichar *machineNameUtf16 = NULL; - unsigned char uuid[VIR_UUID_BUFLEN]; - size_t i; - int matched = 0; - nsresult rc; - - rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not get list of machines, rc=%08x"), (unsigned)rc); - return NULL; - } - - for (i = 0; i < machines.count; ++i) { - IMachine *machine = machines.items[i]; - PRBool isAccessible = PR_FALSE; - - if (!machine) - continue; - - machine->vtbl->GetAccessible(machine, &isAccessible); - if (isAccessible) { - - machine->vtbl->GetName(machine, &machineNameUtf16); - VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8); - - if (STREQ(name, machineNameUtf8)) { - - PRUint32 state; - - matched = 1; - - machine->vtbl->GetId(machine, &iid.value); - vboxIIDToUUID(&iid, uuid); - vboxIIDUnalloc(&iid); - - machine->vtbl->GetState(machine, &state); - - /* get a new domain pointer from virGetDomain, if it fails - * then no need to assign the id, else assign the id, cause - * it is -1 by default. rest is taken care by virGetDomain - * itself, so need not worry. - */ - - ret = virGetDomain(conn, machineNameUtf8, uuid); - if (ret && - (state >= MachineState_FirstOnline) && - (state <= MachineState_LastOnline)) - ret->id = i + 1; - } - - VBOX_UTF8_FREE(machineNameUtf8); - VBOX_COM_UNALLOC_MEM(machineNameUtf16); - if (matched == 1) - break; - } - } - - vboxArrayRelease(&machines); - - return ret; -} - - static int vboxDomainIsActive(virDomainPtr dom) { VBOX_OBJECT_CHECK(dom->conn, int, -1); diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 55f2eec..8b84b1f 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -420,6 +420,8 @@ int vboxConnectNumOfDomains(virConnectPtr conn); virDomainPtr vboxDomainLookupByID(virConnectPtr conn, int id); virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid); +virDomainPtr +vboxDomainLookupByName(virConnectPtr conn, const char *name); virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml); int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags); int vboxDomainCreateWithFlags(virDomainPtr dom, unsigned int flags); -- 1.7.9.5

--- src/vbox/vbox_common.c | 66 ++++++++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 67 ----------------------------------------- src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 67 insertions(+), 67 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index b1f0df3..602a468 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2250,3 +2250,69 @@ virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml, return dom; } + +int vboxDomainIsActive(virDomainPtr dom) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxArray machines = VBOX_ARRAY_INITIALIZER; + vboxIIDUnion iid; + char *machineNameUtf8 = NULL; + PRUnichar *machineNameUtf16 = NULL; + unsigned char uuid[VIR_UUID_BUFLEN]; + size_t i; + int matched = 0; + nsresult rc; + + VBOX_IID_INITIALIZE(&iid); + rc = gVBoxAPI.UArray.vboxArrayGet(&machines, data->vboxObj, ARRAY_GET_MACHINES); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get list of machines, rc=%08x"), (unsigned)rc); + return ret; + } + + for (i = 0; i < machines.count; ++i) { + IMachine *machine = machines.items[i]; + PRBool isAccessible = PR_FALSE; + + if (!machine) + continue; + + gVBoxAPI.UIMachine.GetAccessible(machine, &isAccessible); + if (!isAccessible) + continue; + + gVBoxAPI.UIMachine.GetId(machine, &iid); + if (NS_FAILED(rc)) + continue; + vboxIIDToUUID(&iid, uuid); + vboxIIDUnalloc(&iid); + + if (memcmp(dom->uuid, uuid, VIR_UUID_BUFLEN) == 0) { + + PRUint32 state; + + matched = 1; + + gVBoxAPI.UIMachine.GetName(machine, &machineNameUtf16); + VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8); + + gVBoxAPI.UIMachine.GetState(machine, &state); + + if (gVBoxAPI.machineStateChecker.Online(state)) + ret = 1; + else + ret = 0; + } + + if (matched == 1) + break; + } + + /* Do the cleanup and take care you dont leak any memory */ + VBOX_UTF8_FREE(machineNameUtf8); + VBOX_COM_UNALLOC_MEM(machineNameUtf16); + gVBoxAPI.UArray.vboxArrayRelease(&machines); + + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 9ace580..6441cf4 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -916,73 +916,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxDomainIsActive(virDomainPtr dom) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxArray machines = VBOX_ARRAY_INITIALIZER; - vboxIID iid = VBOX_IID_INITIALIZER; - char *machineNameUtf8 = NULL; - PRUnichar *machineNameUtf16 = NULL; - unsigned char uuid[VIR_UUID_BUFLEN]; - size_t i; - int matched = 0; - nsresult rc; - - rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not get list of machines, rc=%08x"), (unsigned)rc); - return ret; - } - - for (i = 0; i < machines.count; ++i) { - IMachine *machine = machines.items[i]; - PRBool isAccessible = PR_FALSE; - - if (!machine) - continue; - - machine->vtbl->GetAccessible(machine, &isAccessible); - if (isAccessible) { - - rc = machine->vtbl->GetId(machine, &iid.value); - if (NS_FAILED(rc)) - continue; - vboxIIDToUUID(&iid, uuid); - vboxIIDUnalloc(&iid); - - if (memcmp(dom->uuid, uuid, VIR_UUID_BUFLEN) == 0) { - - PRUint32 state; - - matched = 1; - - machine->vtbl->GetName(machine, &machineNameUtf16); - VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8); - - machine->vtbl->GetState(machine, &state); - - if ((state >= MachineState_FirstOnline) && - (state <= MachineState_LastOnline)) - ret = 1; - else - ret = 0; - } - - if (matched == 1) - break; - } - } - - /* Do the cleanup and take care you dont leak any memory */ - VBOX_UTF8_FREE(machineNameUtf8); - VBOX_COM_UNALLOC_MEM(machineNameUtf16); - vboxArrayRelease(&machines); - - return ret; -} - - static int vboxDomainIsPersistent(virDomainPtr dom ATTRIBUTE_UNUSED) { /* All domains are persistent. However, we do want to check for diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 8b84b1f..ec5e674 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -428,6 +428,7 @@ int vboxDomainCreateWithFlags(virDomainPtr dom, unsigned int flags); int vboxDomainCreate(virDomainPtr dom); virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml, unsigned int flags); +int vboxDomainIsActive(virDomainPtr dom); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 19 +++++++++++++++++++ src/vbox/vbox_tmpl.c | 26 -------------------------- src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 602a468..3aca1b8 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2316,3 +2316,22 @@ int vboxDomainIsActive(virDomainPtr dom) return ret; } + +int vboxDomainIsPersistent(virDomainPtr dom) +{ + /* All domains are persistent. However, we do want to check for + * existence. */ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIIDUnion iid; + IMachine *machine = NULL; + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + ret = 1; + + cleanup: + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 6441cf4..dfa9dcf 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -916,32 +916,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxDomainIsPersistent(virDomainPtr dom ATTRIBUTE_UNUSED) -{ - /* All domains are persistent. However, we do want to check for - * existence. */ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - nsresult rc; - - vboxIIDFromUUID(&iid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching UUID")); - goto cleanup; - } - - ret = 1; - - cleanup: - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - - static int vboxDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED) { /* VBox domains never have a persistent state that differs from diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index ec5e674..1df6e76 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -429,6 +429,7 @@ int vboxDomainCreate(virDomainPtr dom); virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml, unsigned int flags); int vboxDomainIsActive(virDomainPtr dom); +int vboxDomainIsPersistent(virDomainPtr dom); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 19 +++++++++++++++++++ src/vbox/vbox_tmpl.c | 25 ------------------------- src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 3aca1b8..cc25633 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2335,3 +2335,22 @@ int vboxDomainIsPersistent(virDomainPtr dom) vboxIIDUnalloc(&iid); return ret; } + +int vboxDomainIsUpdated(virDomainPtr dom) +{ + /* VBox domains never have a persistent state that differs from + * current state. However, we do want to check for existence. */ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIIDUnion iid; + IMachine *machine = NULL; + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + ret = 0; + + cleanup: + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index dfa9dcf..96df49c 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -916,31 +916,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED) -{ - /* VBox domains never have a persistent state that differs from - * current state. However, we do want to check for existence. */ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - nsresult rc; - - vboxIIDFromUUID(&iid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching UUID")); - goto cleanup; - } - - ret = 0; - - cleanup: - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - static int vboxDomainSuspend(virDomainPtr dom) { VBOX_OBJECT_CHECK(dom->conn, int, -1); diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 1df6e76..8397d1b 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -430,6 +430,7 @@ virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml, unsigned int flags); int vboxDomainIsActive(virDomainPtr dom); int vboxDomainIsPersistent(virDomainPtr dom); +int vboxDomainIsUpdated(virDomainPtr dom); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 47 +++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 65 +++++++++-------------------------------- src/vbox/vbox_uniformed_api.h | 3 ++ 3 files changed, 63 insertions(+), 52 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index cc25633..62ab43b 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2354,3 +2354,50 @@ int vboxDomainIsUpdated(virDomainPtr dom) vboxIIDUnalloc(&iid); return ret; } + +int vboxDomainSuspend(virDomainPtr dom) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IMachine *machine = NULL; + vboxIIDUnion iid; + IConsole *console = NULL; + PRBool isAccessible = PR_FALSE; + PRUint32 state; + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + if (!machine) + goto cleanup; + + gVBoxAPI.UIMachine.GetAccessible(machine, &isAccessible); + if (!isAccessible) + goto cleanup; + + gVBoxAPI.UIMachine.GetState(machine, &state); + + if (gVBoxAPI.machineStateChecker.Running(state)) { + /* set state pause */ + gVBoxAPI.UISession.OpenExisting(data, &iid, machine); + gVBoxAPI.UISession.GetConsole(data->vboxSession, &console); + if (console) { + gVBoxAPI.UIConsole.Pause(console); + VBOX_RELEASE(console); + ret = 0; + } else { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("error while suspending the domain")); + goto cleanup; + } + gVBoxAPI.UISession.Close(data->vboxSession); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("machine not in running state to suspend it")); + goto cleanup; + } + + cleanup: + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 96df49c..f8d4b8f 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -916,58 +916,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxDomainSuspend(virDomainPtr dom) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IMachine *machine = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - IConsole *console = NULL; - PRBool isAccessible = PR_FALSE; - PRUint32 state; - nsresult rc; - - vboxIIDFromUUID(&iid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, - _("no domain with matching id %d"), dom->id); - goto cleanup; - } - - if (!machine) - goto cleanup; - - machine->vtbl->GetAccessible(machine, &isAccessible); - if (isAccessible) { - machine->vtbl->GetState(machine, &state); - - if (state == MachineState_Running) { - /* set state pause */ - VBOX_SESSION_OPEN_EXISTING(iid.value, machine); - data->vboxSession->vtbl->GetConsole(data->vboxSession, &console); - if (console) { - console->vtbl->Pause(console); - VBOX_RELEASE(console); - ret = 0; - } else { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("error while suspending the domain")); - goto cleanup; - } - VBOX_SESSION_CLOSE(); - } else { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("machine not in running state to suspend it")); - goto cleanup; - } - } - - cleanup: - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - static int vboxDomainResume(virDomainPtr dom) { VBOX_OBJECT_CHECK(dom->conn, int, -1); @@ -10026,6 +9974,12 @@ _consoleSaveState(IConsole *console, IProgress **progress) } static nsresult +_consolePause(IConsole *console) +{ + return console->vtbl->Pause(console); +} + +static nsresult _progressWaitForCompletion(IProgress *progress, PRInt32 timeout) { return progress->vtbl->WaitForCompletion(progress, timeout); @@ -10461,6 +10415,11 @@ static bool _machineStateNotStart(PRUint32 state) (state == MachineState_Aborted)); } +static bool _machineStateRunning(PRUint32 state) +{ + return state == MachineState_Running; +} + static vboxUniformedPFN _UPFN = { .Initialize = _pfnInitialize, .Uninitialize = _pfnUninitialize, @@ -10537,6 +10496,7 @@ static vboxUniformedISession _UISession = { static vboxUniformedIConsole _UIConsole = { .SaveState = _consoleSaveState, + .Pause = _consolePause, }; static vboxUniformedIProgress _UIProgress = { @@ -10626,6 +10586,7 @@ static vboxUniformedIMedium _UIMedium = { static uniformedMachineStateChecker _machineStateChecker = { .Online = _machineStateOnline, .NotStart = _machineStateNotStart, + .Running = _machineStateRunning, }; void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 8397d1b..f7d674e 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -249,6 +249,7 @@ typedef struct { /* Functions for IConsole */ typedef struct { nsresult (*SaveState)(IConsole *console, IProgress **progress); + nsresult (*Pause)(IConsole *console); } vboxUniformedIConsole; /* Functions for IProgress */ @@ -356,6 +357,7 @@ typedef struct { typedef struct { bool (*Online)(PRUint32 state); bool (*NotStart)(PRUint32 state); + bool (*Running)(PRUint32 state); } uniformedMachineStateChecker; typedef struct { @@ -431,6 +433,7 @@ virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml, int vboxDomainIsActive(virDomainPtr dom); int vboxDomainIsPersistent(virDomainPtr dom); int vboxDomainIsUpdated(virDomainPtr dom); +int vboxDomainSuspend(virDomainPtr dom); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 47 +++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 66 ++++++++--------------------------------- src/vbox/vbox_uniformed_api.h | 3 ++ 3 files changed, 63 insertions(+), 53 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 62ab43b..e9a9f36 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2401,3 +2401,50 @@ int vboxDomainSuspend(virDomainPtr dom) vboxIIDUnalloc(&iid); return ret; } + +int vboxDomainResume(virDomainPtr dom) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IMachine *machine = NULL; + vboxIIDUnion iid; + IConsole *console = NULL; + PRUint32 state; + PRBool isAccessible = PR_FALSE; + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + if (!machine) + goto cleanup; + + gVBoxAPI.UIMachine.GetAccessible(machine, &isAccessible); + if (!isAccessible) + goto cleanup; + + gVBoxAPI.UIMachine.GetState(machine, &state); + + if (gVBoxAPI.machineStateChecker.Paused(state)) { + /* resume the machine here */ + gVBoxAPI.UISession.OpenExisting(data, &iid, machine); + gVBoxAPI.UISession.GetConsole(data->vboxSession, &console); + if (console) { + gVBoxAPI.UIConsole.Resume(console); + VBOX_RELEASE(console); + ret = 0; + } else { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("error while resuming the domain")); + goto cleanup; + } + gVBoxAPI.UISession.Close(data->vboxSession); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("machine not paused, so can't resume it")); + goto cleanup; + } + + cleanup: + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index f8d4b8f..c6df403 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -916,59 +916,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxDomainResume(virDomainPtr dom) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IMachine *machine = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - IConsole *console = NULL; - PRUint32 state = MachineState_Null; - nsresult rc; - - PRBool isAccessible = PR_FALSE; - - vboxIIDFromUUID(&iid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, - _("no domain with matching id %d"), dom->id); - goto cleanup; - } - - if (!machine) - goto cleanup; - - machine->vtbl->GetAccessible(machine, &isAccessible); - if (isAccessible) { - machine->vtbl->GetState(machine, &state); - - if (state == MachineState_Paused) { - /* resume the machine here */ - VBOX_SESSION_OPEN_EXISTING(iid.value, machine); - data->vboxSession->vtbl->GetConsole(data->vboxSession, &console); - if (console) { - console->vtbl->Resume(console); - VBOX_RELEASE(console); - ret = 0; - } else { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("error while resuming the domain")); - goto cleanup; - } - VBOX_SESSION_CLOSE(); - } else { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("machine not paused, so can't resume it")); - goto cleanup; - } - } - - cleanup: - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - static int vboxDomainShutdownFlags(virDomainPtr dom, unsigned int flags) { @@ -9980,6 +9927,12 @@ _consolePause(IConsole *console) } static nsresult +_consoleResume(IConsole *console) +{ + return console->vtbl->Resume(console); +} + +static nsresult _progressWaitForCompletion(IProgress *progress, PRInt32 timeout) { return progress->vtbl->WaitForCompletion(progress, timeout); @@ -10420,6 +10373,11 @@ static bool _machineStateRunning(PRUint32 state) return state == MachineState_Running; } +static bool _machineStatePaused(PRUint32 state) +{ + return state == MachineState_Paused; +} + static vboxUniformedPFN _UPFN = { .Initialize = _pfnInitialize, .Uninitialize = _pfnUninitialize, @@ -10497,6 +10455,7 @@ static vboxUniformedISession _UISession = { static vboxUniformedIConsole _UIConsole = { .SaveState = _consoleSaveState, .Pause = _consolePause, + .Resume = _consoleResume, }; static vboxUniformedIProgress _UIProgress = { @@ -10587,6 +10546,7 @@ static uniformedMachineStateChecker _machineStateChecker = { .Online = _machineStateOnline, .NotStart = _machineStateNotStart, .Running = _machineStateRunning, + .Paused = _machineStatePaused, }; void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index f7d674e..55c947d 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -250,6 +250,7 @@ typedef struct { typedef struct { nsresult (*SaveState)(IConsole *console, IProgress **progress); nsresult (*Pause)(IConsole *console); + nsresult (*Resume)(IConsole *console); } vboxUniformedIConsole; /* Functions for IProgress */ @@ -358,6 +359,7 @@ typedef struct { bool (*Online)(PRUint32 state); bool (*NotStart)(PRUint32 state); bool (*Running)(PRUint32 state); + bool (*Paused)(PRUint32 state); } uniformedMachineStateChecker; typedef struct { @@ -434,6 +436,7 @@ int vboxDomainIsActive(virDomainPtr dom); int vboxDomainIsPersistent(virDomainPtr dom); int vboxDomainIsUpdated(virDomainPtr dom); int vboxDomainSuspend(virDomainPtr dom); +int vboxDomainResume(virDomainPtr dom); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 48 +++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 67 ++++++++--------------------------------- src/vbox/vbox_uniformed_api.h | 3 ++ 3 files changed, 64 insertions(+), 54 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index e9a9f36..cc4328e 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2448,3 +2448,51 @@ int vboxDomainResume(virDomainPtr dom) vboxIIDUnalloc(&iid); return ret; } + +int vboxDomainShutdownFlags(virDomainPtr dom, unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IMachine *machine = NULL; + vboxIIDUnion iid; + IConsole *console = NULL; + PRUint32 state; + PRBool isAccessible = PR_FALSE; + + virCheckFlags(0, -1); + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + if (!machine) + goto cleanup; + + gVBoxAPI.UIMachine.GetAccessible(machine, &isAccessible); + if (!isAccessible) + goto cleanup; + + gVBoxAPI.UIMachine.GetState(machine, &state); + + if (gVBoxAPI.machineStateChecker.Paused(state)) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("machine paused, so can't power it down")); + goto cleanup; + } else if (gVBoxAPI.machineStateChecker.PoweredOff(state)) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("machine already powered down")); + goto cleanup; + } + + gVBoxAPI.UISession.OpenExisting(data, &iid, machine); + gVBoxAPI.UISession.GetConsole(data->vboxSession, &console); + if (console) { + gVBoxAPI.UIConsole.PowerButton(console); + VBOX_RELEASE(console); + ret = 0; + } + gVBoxAPI.UISession.Close(data->vboxSession); + + cleanup: + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index c6df403..1ec0a3b 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -916,60 +916,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxDomainShutdownFlags(virDomainPtr dom, - unsigned int flags) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IMachine *machine = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - IConsole *console = NULL; - PRUint32 state = MachineState_Null; - PRBool isAccessible = PR_FALSE; - nsresult rc; - - virCheckFlags(0, -1); - - vboxIIDFromUUID(&iid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, - _("no domain with matching id %d"), dom->id); - goto cleanup; - } - - if (!machine) - goto cleanup; - - machine->vtbl->GetAccessible(machine, &isAccessible); - if (isAccessible) { - machine->vtbl->GetState(machine, &state); - - if (state == MachineState_Paused) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("machine paused, so can't power it down")); - goto cleanup; - } else if (state == MachineState_PoweredOff) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("machine already powered down")); - goto cleanup; - } - - VBOX_SESSION_OPEN_EXISTING(iid.value, machine); - data->vboxSession->vtbl->GetConsole(data->vboxSession, &console); - if (console) { - console->vtbl->PowerButton(console); - VBOX_RELEASE(console); - ret = 0; - } - VBOX_SESSION_CLOSE(); - } - - cleanup: - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - static int vboxDomainShutdown(virDomainPtr dom) { return vboxDomainShutdownFlags(dom, 0); @@ -9933,6 +9879,12 @@ _consoleResume(IConsole *console) } static nsresult +_consolePowerButton(IConsole *console) +{ + return console->vtbl->PowerButton(console); +} + +static nsresult _progressWaitForCompletion(IProgress *progress, PRInt32 timeout) { return progress->vtbl->WaitForCompletion(progress, timeout); @@ -10378,6 +10330,11 @@ static bool _machineStatePaused(PRUint32 state) return state == MachineState_Paused; } +static bool _machineStatePoweredOff(PRUint32 state) +{ + return state == MachineState_PoweredOff; +} + static vboxUniformedPFN _UPFN = { .Initialize = _pfnInitialize, .Uninitialize = _pfnUninitialize, @@ -10456,6 +10413,7 @@ static vboxUniformedIConsole _UIConsole = { .SaveState = _consoleSaveState, .Pause = _consolePause, .Resume = _consoleResume, + .PowerButton = _consolePowerButton, }; static vboxUniformedIProgress _UIProgress = { @@ -10547,6 +10505,7 @@ static uniformedMachineStateChecker _machineStateChecker = { .NotStart = _machineStateNotStart, .Running = _machineStateRunning, .Paused = _machineStatePaused, + .PoweredOff = _machineStatePoweredOff, }; void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 55c947d..52a8cee 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -251,6 +251,7 @@ typedef struct { nsresult (*SaveState)(IConsole *console, IProgress **progress); nsresult (*Pause)(IConsole *console); nsresult (*Resume)(IConsole *console); + nsresult (*PowerButton)(IConsole *console); } vboxUniformedIConsole; /* Functions for IProgress */ @@ -360,6 +361,7 @@ typedef struct { bool (*NotStart)(PRUint32 state); bool (*Running)(PRUint32 state); bool (*Paused)(PRUint32 state); + bool (*PoweredOff)(PRUint32 state); } uniformedMachineStateChecker; typedef struct { @@ -437,6 +439,7 @@ int vboxDomainIsPersistent(virDomainPtr dom); int vboxDomainIsUpdated(virDomainPtr dom); int vboxDomainSuspend(virDomainPtr dom); int vboxDomainResume(virDomainPtr dom); +int vboxDomainShutdownFlags(virDomainPtr dom, unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 5 +++++ src/vbox/vbox_tmpl.c | 6 ------ src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index cc4328e..98d7c8a 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2496,3 +2496,8 @@ int vboxDomainShutdownFlags(virDomainPtr dom, unsigned int flags) vboxIIDUnalloc(&iid); return ret; } + +int vboxDomainShutdown(virDomainPtr dom) +{ + return vboxDomainShutdownFlags(dom, 0); +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 1ec0a3b..28bf9be 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -916,12 +916,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxDomainShutdown(virDomainPtr dom) -{ - return vboxDomainShutdownFlags(dom, 0); -} - - static int vboxDomainReboot(virDomainPtr dom, unsigned int flags) { VBOX_OBJECT_CHECK(dom->conn, int, -1); diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 52a8cee..5926a2a 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -440,6 +440,7 @@ int vboxDomainIsUpdated(virDomainPtr dom); int vboxDomainSuspend(virDomainPtr dom); int vboxDomainResume(virDomainPtr dom); int vboxDomainShutdownFlags(virDomainPtr dom, unsigned int flags); +int vboxDomainShutdown(virDomainPtr dom); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 44 ++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 56 ++++++----------------------------------- src/vbox/vbox_uniformed_api.h | 2 ++ 3 files changed, 53 insertions(+), 49 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 98d7c8a..2551393 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2501,3 +2501,47 @@ int vboxDomainShutdown(virDomainPtr dom) { return vboxDomainShutdownFlags(dom, 0); } + +int vboxDomainReboot(virDomainPtr dom, unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IMachine *machine = NULL; + vboxIIDUnion iid; + IConsole *console = NULL; + PRUint32 state; + PRBool isAccessible = PR_FALSE; + + virCheckFlags(0, -1); + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + if (!machine) + goto cleanup; + + gVBoxAPI.UIMachine.GetAccessible(machine, &isAccessible); + if (!isAccessible) + goto cleanup; + + gVBoxAPI.UIMachine.GetState(machine, &state); + + if (gVBoxAPI.machineStateChecker.Running(state)) { + gVBoxAPI.UISession.OpenExisting(data, &iid, machine); + gVBoxAPI.UISession.GetConsole(data->vboxSession, &console); + if (console) { + gVBoxAPI.UIConsole.Reset(console); + VBOX_RELEASE(console); + ret = 0; + } + gVBoxAPI.UISession.Close(data->vboxSession); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("machine not running, so can't reboot it")); + goto cleanup; + } + + cleanup: + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 28bf9be..a960f56 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -916,55 +916,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxDomainReboot(virDomainPtr dom, unsigned int flags) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IMachine *machine = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - IConsole *console = NULL; - PRUint32 state = MachineState_Null; - PRBool isAccessible = PR_FALSE; - nsresult rc; - - virCheckFlags(0, -1); - - vboxIIDFromUUID(&iid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, - _("no domain with matching id %d"), dom->id); - goto cleanup; - } - - if (!machine) - goto cleanup; - - machine->vtbl->GetAccessible(machine, &isAccessible); - if (isAccessible) { - machine->vtbl->GetState(machine, &state); - - if (state == MachineState_Running) { - VBOX_SESSION_OPEN_EXISTING(iid.value, machine); - data->vboxSession->vtbl->GetConsole(data->vboxSession, &console); - if (console) { - console->vtbl->Reset(console); - VBOX_RELEASE(console); - ret = 0; - } - VBOX_SESSION_CLOSE(); - } else { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("machine not running, so can't reboot it")); - goto cleanup; - } - } - - cleanup: - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - static int vboxDomainDestroyFlags(virDomainPtr dom, unsigned int flags) @@ -9879,6 +9830,12 @@ _consolePowerButton(IConsole *console) } static nsresult +_consoleReset(IConsole *console) +{ + return console->vtbl->Reset(console); +} + +static nsresult _progressWaitForCompletion(IProgress *progress, PRInt32 timeout) { return progress->vtbl->WaitForCompletion(progress, timeout); @@ -10408,6 +10365,7 @@ static vboxUniformedIConsole _UIConsole = { .Pause = _consolePause, .Resume = _consoleResume, .PowerButton = _consolePowerButton, + .Reset = _consoleReset, }; static vboxUniformedIProgress _UIProgress = { diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 5926a2a..d4a590f 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -252,6 +252,7 @@ typedef struct { nsresult (*Pause)(IConsole *console); nsresult (*Resume)(IConsole *console); nsresult (*PowerButton)(IConsole *console); + nsresult (*Reset)(IConsole *console); } vboxUniformedIConsole; /* Functions for IProgress */ @@ -441,6 +442,7 @@ int vboxDomainSuspend(virDomainPtr dom); int vboxDomainResume(virDomainPtr dom); int vboxDomainShutdownFlags(virDomainPtr dom, unsigned int flags); int vboxDomainShutdown(virDomainPtr dom); +int vboxDomainReboot(virDomainPtr dom, unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5
participants (1)
-
Taowei