[libvirt] [PATCH 00/66] vbox: Rewrite vbox domain driver

This series of patches rewrite the vbox's domain driver. The driver is separated into two parts: the version specified and the common part. The common driver use vboxUniformedAPI to build a general driver for all vbox versions. The vboxUniformedAPI take the responsiblity to communicate with virtualbox. Since there are some incompatible changes in virtualbox, vboxUniformedAPI should be aware of these changes and provide a uniformed api for the upper layer. The significant result of this patch is that we replace all vir${vbox_version}Driver into one virCommonDriver. So, we will have only one vbox driver implementation for all vbox versions in libvirt. PS: I have send part of my patches before: https://www.redhat.com/archives/libvir-list/2014-July/msg00937.html But I have to resend it beacuse I did some improvement on previous patches: *Remove the test case for vboxUniformedAPI, because it would raise "break strict-aliasing rules" warning in some distibutions *Merged the flag fdWatchNeedInitialize into domainEventCallbacks, So, we use one flag to indicate whether vbox support callbacks as well as we need to initialize variables for it. Taowei (66): vbox: Begin to rewrite, vboxConnectOpen 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 vbox: Rewrite vboxDomainDestroyFlags vbox: Rewrite vboxDomainDestroy vbox: Rewrite vboxDomainGetOSType vbox: Rewrite vboxDomainSetMemory vbox: Rewrite vboxDomainGetInfo vbox: Rewrite vboxDomainGetState vbox: Rewrite vboxDomainSetVcpusFlags vbox: Rewrite vboxDomainSetVcpus vbox: Rewrite vboxDomainGetVcpusFlags vbox: Rewrite vboxDomainGetMaxVcpus vbox: Add API for vboxDomainGetXMLDesc vbox: Rewrite vboxDomainGetXMLDesc vbox: Rewrite vboxConnectListDefinedDomains vbox: Rewrite vboxConnectNumOfDefinedDomains vbox: Rewrite vboxDomainUndefine vbox: Rewrite vboxDomainAttachDevice vbox: Rewrite vboxDomainAttachDeviceFlags vbox: Rewrite vboxDomainUpdateDeviceFlags vbox: Rewrite vboxDomainDetachDevice vbox: Rewrite vboxDomainDetachDeviceFlags vbox: Add API for vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotGetXMLDesc vbox: Rewrite vboxDomainSnapshotNum vbox: Rewrite vboxDomainSnapshotListNames vbox: Rewrite vboxSnapshotLookupByName vbox: Rewrite vboxDomainHasCurrentSnapshot vbox: Rewrite vboxDomainSnapshotGetParent vbox: Rewrite vboxDomainSnapshotCurrent vbox: Rewrite vboxDomainSnapshotIsCurrent vbox: Rewrite vboxDomainSnapshotHasMetadata vbox: Rewrite vboxDomainRevertToSnapshot vbox: Rewrite vboxDomainSnapshotDelete vbox: Rewrite vboxDomainScreenshot vbox: Rewrite vboxConnectListAllDomains vbox: Rewrite vboxNode functions vbox: Add registerDomainEvent vbox: Introducing vboxCommonDriver po/POTFILES.in | 1 + src/Makefile.am | 5 +- src/vbox/README | 7 +- src/vbox/vbox_common.c | 7550 +++++++++++++++++++++ src/vbox/vbox_common.h | 306 + src/vbox/vbox_driver.c | 40 +- src/vbox/vbox_install_api.h | 26 + src/vbox/vbox_tmpl.c |14557 +++++++++++++---------------------------- src/vbox/vbox_uniformed_api.h | 551 ++ 9 files changed, 13186 insertions(+), 9857 deletions(-) create mode 100644 src/vbox/vbox_common.c create mode 100644 src/vbox/vbox_common.h create mode 100644 src/vbox/vbox_install_api.h create mode 100644 src/vbox/vbox_uniformed_api.h -- 1.7.9.5

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

All vbox objects are child objects from the nsISupports in vbox's C++ API version. Since the CAPI is generated from the C++ API, I kept their relationship here, by the definitations below: typedef struct nsISupports nsISupports; typedef nsISupports IVirtualBox; typedef nsISupports ISession; and so on... So, when calling the API from nsISupports, we don't need to do typecasting, and things work still work well. --- src/vbox/vbox_common.c | 95 ++++++++++++ src/vbox/vbox_common.h | 45 +++++- src/vbox/vbox_tmpl.c | 342 +++++++++++++++++++++++++++++++---------- src/vbox/vbox_uniformed_api.h | 82 ++++++++++ 4 files changed, 477 insertions(+), 87 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 06f1524..28d8668 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -42,6 +42,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) { \ @@ -69,6 +72,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.UIID.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; @@ -103,6 +131,22 @@ int vboxRegisterUniformedAPI(uint32_t uVersion) return 0; } +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->vboxObj, iid, machine))) { + virReportError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + return -1; + } + } + return 0; +} + static virDomainDefParserConfig vboxDomainDefParserConfig = { .macPrefix = { 0x08, 0x00, 0x27 }, }; @@ -300,3 +344,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 61f410d..800e7cc 100644 --- a/src/vbox/vbox_common.h +++ b/src/vbox/vbox_common.h @@ -121,10 +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 struct nsISupports nsISupports; +typedef nsISupports IVirtualBox; +typedef nsISupports ISession; +typedef nsISupports IConsole; +typedef nsISupports IProgress; +typedef nsISupports IMachine; #endif /* VBOX_COMMON_H */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 6315a64..0e9b6c8 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -192,7 +192,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,\ @@ -355,12 +355,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, @@ -370,12 +366,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) { @@ -384,12 +393,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) @@ -401,6 +423,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) @@ -414,17 +443,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) @@ -441,12 +461,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) { @@ -458,12 +491,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) @@ -475,6 +522,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) @@ -490,15 +544,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) @@ -512,6 +559,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) { @@ -525,6 +578,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) { @@ -537,6 +597,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) @@ -555,6 +622,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, @@ -566,6 +639,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) @@ -1826,67 +1906,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) @@ -11303,12 +11322,124 @@ 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 _nsisupportsRelease(nsISupports *nsi) +{ + return nsi->vtbl->Release(nsi); +} + static nsresult _virtualboxGetVersion(IVirtualBox *vboxObj, PRUnichar **versionUtf16) { return vboxObj->vtbl->GetVersion(vboxObj, versionUtf16); } +#if VBOX_API_VERSION < 4000000 + +static nsresult +_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine) +{ + return vboxObj->vtbl->GetMachine(vboxObj, IID_MEMBER(value), machine); +} + +#else /* VBOX_API_VERSION >= 4000000 */ + +static nsresult +_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine) +{ + return vboxObj->vtbl->FindMachine(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 vboxUniformedPFN _UPFN = { .Initialize = _pfnInitialize, .Uninitialize = _pfnUninitialize, @@ -11319,8 +11450,38 @@ static vboxUniformedPFN _UPFN = { .Utf8ToUtf16 = _pfnUtf8ToUtf16, }; +static vboxUniformedIID _UIID = { + .vboxIIDInitialize = _vboxIIDInitialize, + .vboxIIDUnalloc = _vboxIIDUnalloc, + .vboxIIDToUUID = _vboxIIDToUUID, + .vboxIIDFromUUID = _vboxIIDFromUUID, + .vboxIIDIsEqual = _vboxIIDIsEqual, + .vboxIIDFromArrayItem = _vboxIIDFromArrayItem, + .DEBUGIID = _DEBUGIID, +}; + +static vboxUniformednsISupports _nsUISupports = { + .Release = _nsisupportsRelease, +}; + 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, }; void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) @@ -11330,7 +11491,12 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->initializeDomainEvent = _initializeDomainEvent; pVBoxAPI->registerGlobalData = _registerGlobalData; pVBoxAPI->UPFN = _UPFN; + pVBoxAPI->UIID = _UIID; + pVBoxAPI->nsUISupports = _nsUISupports; pVBoxAPI->UIVirtualBox = _UIVirtualBox; + pVBoxAPI->UISession = _UISession; + pVBoxAPI->UIConsole = _UIConsole; + pVBoxAPI->UIProgress = _UIProgress; #if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 pVBoxAPI->domainEventCallbacks = 0; @@ -11344,6 +11510,12 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->hasStaticGlobalData = 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 */ } /** diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index f424047..8538754 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; @@ -111,11 +151,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 nsISupports */ +typedef struct { + nsresult (*Release)(nsISupports *nsi); +} vboxUniformednsISupports; + /* Functions for IVirtualBox */ typedef struct { nsresult (*GetVersion)(IVirtualBox *vboxObj, PRUnichar **versionUtf16); + nsresult (*GetMachine)(IVirtualBox *vboxObj, 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; + typedef struct { /* vbox API version */ uint32_t APIVersion; @@ -124,10 +199,16 @@ typedef struct { int (*initializeDomainEvent)(vboxGlobalData *data); void (*registerGlobalData)(vboxGlobalData *data); vboxUniformedPFN UPFN; + vboxUniformedIID UIID; + vboxUniformednsISupports nsUISupports; vboxUniformedIVirtualBox UIVirtualBox; + vboxUniformedISession UISession; + vboxUniformedIConsole UIConsole; + vboxUniformedIProgress UIProgress; /* vbox API features */ bool domainEventCallbacks; bool hasStaticGlobalData; + bool getMachineForSession; } vboxUniformedAPI; /* libvirt API @@ -138,6 +219,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 28d8668..f4f0d6d 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -395,3 +395,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 0e9b6c8..60e6098 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -914,19 +914,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 8538754..5bb2e65 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -220,6 +220,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 f4f0d6d..585e6b5 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -417,3 +417,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 60e6098..ad01524 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -914,12 +914,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 5bb2e65..f56fe7a 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -221,6 +221,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 585e6b5..f40f14d 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -422,3 +422,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 ad01524..75eff4c 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -914,12 +914,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 f56fe7a..d688403 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -222,6 +222,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 f40f14d..2a3ab1e 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -428,3 +428,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 75eff4c..690c614 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -914,12 +914,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 d688403..15cac24 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -223,6 +223,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 2a3ab1e..4a75b88 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -434,3 +434,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 690c614..857640c 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -914,11 +914,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 15cac24..434b8d7 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -224,6 +224,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 4a75b88..cb73f97 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -439,3 +439,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 800e7cc..c4147a1 100644 --- a/src/vbox/vbox_common.h +++ b/src/vbox/vbox_common.h @@ -167,5 +167,6 @@ typedef nsISupports ISession; typedef nsISupports IConsole; typedef nsISupports IProgress; typedef nsISupports IMachine; +typedef nsISupports ISystemProperties; #endif /* VBOX_COMMON_H */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 857640c..deb3067 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -914,30 +914,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); @@ -11346,6 +11322,12 @@ _virtualboxGetMachine(IVirtualBox *vboxObj, 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 @@ -11404,6 +11386,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 vboxUniformedPFN _UPFN = { .Initialize = _pfnInitialize, .Uninitialize = _pfnUninitialize, @@ -11431,6 +11419,7 @@ static vboxUniformednsISupports _nsUISupports = { static vboxUniformedIVirtualBox _UIVirtualBox = { .GetVersion = _virtualboxGetVersion, .GetMachine = _virtualboxGetMachine, + .GetSystemProperties = _virtualboxGetSystemProperties, }; static vboxUniformedISession _UISession = { @@ -11448,6 +11437,10 @@ static vboxUniformedIProgress _UIProgress = { .GetResultCode = _progressGetResultCode, }; +static vboxUniformedISystemProperties _UISystemProperties = { + .GetMaxGuestCPUCount = _systemPropertiesGetMaxGuestCPUCount, +}; + void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) { pVBoxAPI->APIVersion = VBOX_API_VERSION; @@ -11461,6 +11454,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->UISession = _UISession; pVBoxAPI->UIConsole = _UIConsole; pVBoxAPI->UIProgress = _UIProgress; + pVBoxAPI->UISystemProperties = _UISystemProperties; #if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 pVBoxAPI->domainEventCallbacks = 0; diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 434b8d7..2cc0674 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -171,6 +171,7 @@ typedef struct { typedef struct { nsresult (*GetVersion)(IVirtualBox *vboxObj, PRUnichar **versionUtf16); nsresult (*GetMachine)(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine); + nsresult (*GetSystemProperties)(IVirtualBox *vboxObj, ISystemProperties **systemProperties); } vboxUniformedIVirtualBox; /* Functions for ISession */ @@ -191,6 +192,11 @@ typedef struct { nsresult (*GetResultCode)(IProgress *progress, resultCodeUnion *resultCode); } vboxUniformedIProgress; +/* Functions for ISystemProperties */ +typedef struct { + nsresult (*GetMaxGuestCPUCount)(ISystemProperties *systemProperties, PRUint32 *maxCPUCount); +} vboxUniformedISystemProperties; + typedef struct { /* vbox API version */ uint32_t APIVersion; @@ -205,6 +211,7 @@ typedef struct { vboxUniformedISession UISession; vboxUniformedIConsole UIConsole; vboxUniformedIProgress UIProgress; + vboxUniformedISystemProperties UISystemProperties; /* vbox API features */ bool domainEventCallbacks; bool hasStaticGlobalData; @@ -225,6 +232,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 cb73f97..eaefe81 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -463,3 +463,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 deb3067..7f9b4cc 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -256,6 +256,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); @@ -266,6 +270,8 @@ static void vboxDriverUnlock(vboxGlobalData *data) virMutexUnlock(&data->lock); } +#endif + #if VBOX_API_VERSION == 2002000 static void nsIDtoChar(unsigned char *uuid, const nsID *iid) @@ -914,16 +920,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 2cc0674..e49b881 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -233,6 +233,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

On 11.08.2014 12:06, Taowei wrote:
--- 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 cb73f97..eaefe81 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -463,3 +463,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 deb3067..7f9b4cc 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -256,6 +256,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.* */ +
s/rewriten/rewritten/ s/vboxDiverLock/vboxDriverLock/ we are not locking any diver but the driver :-P
static void vboxDriverLock(vboxGlobalData *data) { virMutexLock(&data->lock); @@ -266,6 +270,8 @@ static void vboxDriverUnlock(vboxGlobalData *data) virMutexUnlock(&data->lock); }
+#endif + #if VBOX_API_VERSION == 2002000
static void nsIDtoChar(unsigned char *uuid, const nsID *iid) @@ -914,16 +920,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 2cc0674..e49b881 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -233,6 +233,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);
Michal

--- 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 eaefe81..6de5757 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -97,6 +97,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; @@ -474,3 +478,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 7f9b4cc..e0033b9 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -920,45 +920,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); @@ -11289,6 +11250,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 _nsisupportsRelease(nsISupports *nsi) { return nsi->vtbl->Release(nsi); @@ -11324,6 +11290,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 @@ -11388,6 +11366,12 @@ _systemPropertiesGetMaxGuestCPUCount(ISystemProperties *systemProperties, PRUint return systemProperties->vtbl->GetMaxGuestCPUCount(systemProperties, maxCPUCount); } +static bool _machineStateOnline(PRUint32 state) +{ + return ((state >= MachineState_FirstOnline) && + (state <= MachineState_LastOnline)); +} + static vboxUniformedPFN _UPFN = { .Initialize = _pfnInitialize, .Uninitialize = _pfnUninitialize, @@ -11408,6 +11392,12 @@ static vboxUniformedIID _UIID = { .DEBUGIID = _DEBUGIID, }; +static vboxUniformedArray _UArray = { + .vboxArrayGet = vboxArrayGet, + .vboxArrayRelease = vboxArrayRelease, + .handleGetMachines = _handleGetMachines, +}; + static vboxUniformednsISupports _nsUISupports = { .Release = _nsisupportsRelease, }; @@ -11418,6 +11408,11 @@ static vboxUniformedIVirtualBox _UIVirtualBox = { .GetSystemProperties = _virtualboxGetSystemProperties, }; +static vboxUniformedIMachine _UIMachine = { + .GetAccessible = _machineGetAccessible, + .GetState = _machineGetState, +}; + static vboxUniformedISession _UISession = { .OpenExisting = _sessionOpenExisting, .GetConsole = _sessionGetConsole, @@ -11437,6 +11432,10 @@ static vboxUniformedISystemProperties _UISystemProperties = { .GetMaxGuestCPUCount = _systemPropertiesGetMaxGuestCPUCount, }; +static uniformedMachineStateChecker _machineStateChecker = { + .Online = _machineStateOnline, +}; + void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) { pVBoxAPI->APIVersion = VBOX_API_VERSION; @@ -11445,12 +11444,15 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->registerGlobalData = _registerGlobalData; pVBoxAPI->UPFN = _UPFN; pVBoxAPI->UIID = _UIID; + pVBoxAPI->UArray = _UArray; pVBoxAPI->nsUISupports = _nsUISupports; pVBoxAPI->UIVirtualBox = _UIVirtualBox; + pVBoxAPI->UIMachine = _UIMachine; pVBoxAPI->UISession = _UISession; pVBoxAPI->UIConsole = _UIConsole; pVBoxAPI->UIProgress = _UIProgress; pVBoxAPI->UISystemProperties = _UISystemProperties; + pVBoxAPI->machineStateChecker = _machineStateChecker; #if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 pVBoxAPI->domainEventCallbacks = 0; diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index e49b881..b72429b 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -162,6 +162,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 nsISupports */ typedef struct { nsresult (*Release)(nsISupports *nsi); @@ -174,6 +182,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); @@ -198,6 +212,10 @@ typedef struct { } vboxUniformedISystemProperties; typedef struct { + bool (*Online)(PRUint32 state); +} uniformedMachineStateChecker; + +typedef struct { /* vbox API version */ uint32_t APIVersion; uint32_t XPCOMCVersion; @@ -206,12 +224,15 @@ typedef struct { void (*registerGlobalData)(vboxGlobalData *data); vboxUniformedPFN UPFN; vboxUniformedIID UIID; + vboxUniformedArray UArray; vboxUniformednsISupports nsUISupports; vboxUniformedIVirtualBox UIVirtualBox; + vboxUniformedIMachine UIMachine; vboxUniformedISession UISession; vboxUniformedIConsole UIConsole; vboxUniformedIProgress UIProgress; vboxUniformedISystemProperties UISystemProperties; + uniformedMachineStateChecker machineStateChecker; /* vbox API features */ bool domainEventCallbacks; bool hasStaticGlobalData; @@ -234,6 +255,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 6de5757..3023fe6 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -516,3 +516,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 e0033b9..83ea370 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -920,42 +920,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 b72429b..0b95459 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -256,6 +256,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 3023fe6..d901b7f 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -551,3 +551,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 83ea370..9018589 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -948,74 +948,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) { @@ -11266,6 +11198,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 @@ -11375,6 +11319,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 0b95459..26aec76 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -186,6 +186,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 */ @@ -257,6 +259,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 d901b7f..5d9a4f0 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -624,3 +624,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 9018589..0f33605 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -949,79 +949,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 26aec76..2541fba 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -260,6 +260,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

On 11.08.2014 12:06, Taowei wrote:
--- 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 d901b7f..5d9a4f0 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -624,3 +624,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;
When you're at this, s/int matched/bool matched/. It's used as a boolean anyway. Here and in the following patches too.
+ 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; +}
Michal

--- src/vbox/vbox_common.c | 70 ++++++++ src/vbox/vbox_tmpl.c | 356 +++++++++++++++++++++-------------------- src/vbox/vbox_uniformed_api.h | 8 + 3 files changed, 258 insertions(+), 176 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 5d9a4f0..efcda7a 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" @@ -697,3 +698,72 @@ 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; + + if (!gVBoxAPI.detachDevicesExplicitly) + VIR_WARN("This function may not work in current vbox version"); + + 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 0f33605..86c02f1 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -254,7 +254,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, @@ -4784,181 +4783,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); @@ -11011,6 +10835,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) +{ + vboxUnsupported(); +} + +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) @@ -11137,9 +11109,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)); @@ -11154,6 +11138,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); @@ -11174,6 +11164,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); @@ -11248,11 +11244,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, }; @@ -11279,6 +11278,9 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->XPCOMCVersion = VBOX_XPCOMC_VERSION; pVBoxAPI->initializeDomainEvent = _initializeDomainEvent; pVBoxAPI->registerGlobalData = _registerGlobalData; + pVBoxAPI->detachDevices = _detachDevices; + pVBoxAPI->unregisterMachine = _unregisterMachine; + pVBoxAPI->deleteConfig = _deleteConfig; pVBoxAPI->UPFN = _UPFN; pVBoxAPI->UIID = _UIID; pVBoxAPI->UArray = _UArray; @@ -11306,8 +11308,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 2541fba..01b91fc 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -188,12 +188,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; @@ -224,6 +227,9 @@ typedef struct { /* vbox APIs */ int (*initializeDomainEvent)(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; @@ -239,6 +245,7 @@ typedef struct { bool domainEventCallbacks; bool hasStaticGlobalData; bool getMachineForSession; + bool detachDevicesExplicitly; } vboxUniformedAPI; /* libvirt API @@ -262,6 +269,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

--- src/vbox/vbox_common.c | 1169 +++++++++++ src/vbox/vbox_common.h | 90 + src/vbox/vbox_tmpl.c | 4535 ++++++++++++++++++++--------------------- src/vbox/vbox_uniformed_api.h | 128 ++ 4 files changed, 3557 insertions(+), 2365 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index efcda7a..f4e992d 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -81,6 +81,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;\ @@ -152,6 +160,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 }, }; @@ -700,6 +825,1050 @@ 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; + + if (gVBoxAPI.vboxAttachDrivesUseOld) + VIR_WARN("This function may not work in current vbox version"); + + /* 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_TRISTATE_SWITCH_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_TRISTATE_SWITCH_ON) + ? _("Enabled") : _("Disabled"), (unsigned)rc); + } + + gVBoxAPI.UIMachine.GetBIOSSettings(machine, &bios); + if (bios) { + rc = gVBoxAPI.UIBIOSSettings.SetACPIEnabled(bios, + def->features[VIR_DOMAIN_FEATURE_ACPI] == + VIR_TRISTATE_SWITCH_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_TRISTATE_SWITCH_ON) + ? _("Enabled") : _("Disabled"), (unsigned)rc); + } + rc = gVBoxAPI.UIBIOSSettings.SetIOAPICEnabled(bios, + def->features[VIR_DOMAIN_FEATURE_APIC] == + VIR_TRISTATE_SWITCH_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_TRISTATE_SWITCH_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 c4147a1..eedd755 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; @@ -168,5 +248,15 @@ typedef nsISupports IConsole; typedef nsISupports IProgress; typedef nsISupports IMachine; typedef nsISupports ISystemProperties; +typedef nsISupports IBIOSSettings; +typedef nsISupports IAudioAdapter; +typedef nsISupports INetworkAdapter; +typedef nsISupports ISerialPort; +typedef nsISupports IParallelPort; +typedef nsISupports IVRDxServer; +typedef nsISupports IUSBCommon; +typedef nsISupports IUSBDeviceFilter; +typedef nsISupports IMedium; +typedef nsISupports IStorageController; #endif /* VBOX_COMMON_H */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 86c02f1..537616d 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -89,6 +89,19 @@ /* Include this *last* or we'll get the wrong vbox_CAPI_*.h. */ #include "vbox_glue.h" + +#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 */ + #include "vbox_uniformed_api.h" #define VIR_FROM_THIS VIR_FROM_VBOX @@ -252,7 +265,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 @@ -660,7 +672,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, @@ -738,6 +752,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, @@ -782,6 +798,7 @@ static bool vboxGetDeviceDetails(const char *deviceName, return true; } +# endif /* VBOX_API_VERSION < 4000000 */ /** * function to get the values for max port per @@ -876,9 +893,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) @@ -3302,67 +3317,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; @@ -3599,7 +3561,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; @@ -3675,9 +3646,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; @@ -3686,47 +3654,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, @@ -3751,19 +3698,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); } @@ -3836,11 +3770,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, @@ -3857,1421 +3787,510 @@ 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); - } - } -} +#else /* VBOX_API_VERSION >= 4000000 */ static void -vboxAttachNetwork(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +_vboxAttachDrivesOld(virDomainDefPtr def ATTRIBUTE_UNUSED, + vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine ATTRIBUTE_UNUSED) { - 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 */ + vboxUnsupported(); +} - 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) +static int +vboxDomainUndefine(virDomainPtr dom) { - 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); - } - } + return vboxDomainUndefineFlags(dom, 0); } -static void -vboxAttachParallel(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +static int vboxDomainAttachDeviceImpl(virDomainPtr dom, + const char *xml, + int mediaChangeOnly ATTRIBUTE_UNUSED) { - 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_OBJECT_CHECK(dom->conn, int, -1); + IMachine *machine = NULL; + vboxIID iid = VBOX_IID_INITIALIZER; + PRUint32 state = MachineState_Null; + virDomainDefPtr def = NULL; + virDomainDeviceDefPtr dev = NULL; + nsresult rc; - VBOX_UTF8_TO_UTF16(def->parallels[i]->source.data.file.path, &pathUtf16); + if (VIR_ALLOC(def) < 0) + return ret; - /* 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); - } - } + if (VIR_STRDUP(def->os.type, "hvm") < 0) + goto cleanup; - /* like serial port, parallel port can't be enabled unless - * correct IRQ and IOBase values are specified. - */ - parallelPort->vtbl->SetEnabled(parallelPort, 1); + dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, + VIR_DOMAIN_XML_INACTIVE); + if (dev == NULL) + goto cleanup; - VBOX_RELEASE(parallelPort); - VBOX_UTF16_FREE(pathUtf16); - } + 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; } -} -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 */ + if (machine) { + machine->vtbl->GetState(machine, &state); + + if ((state == MachineState_Running) || + (state == MachineState_Paused)) { + rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); } else { - machine->vtbl->SetAccelerate3DEnabled(machine, 0); -#if VBOX_API_VERSION >= 3001000 - machine->vtbl->SetAccelerate2DVideoEnabled(machine, 0); -#endif /* VBOX_API_VERSION >= 3001000 */ + rc = VBOX_SESSION_OPEN(iid.value, machine); } - } -} - -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)) { + if (NS_SUCCEEDED(rc)) { + rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); + if (NS_SUCCEEDED(rc) && machine) { + if (dev->type == VIR_DOMAIN_DEVICE_DISK) { +#if VBOX_API_VERSION < 3001000 + const char *src = virDomainDiskGetSource(dev->data.disk); + int type = virDomainDiskGetType(dev->data.disk); - 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); + if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { + if (type == VIR_STORAGE_TYPE_FILE && src) { + IDVDDrive *dvdDrive = NULL; + /* Currently CDROM/DVD Drive is always IDE + * Secondary Master so neglecting the following + * parameter dev->data.disk->bus + */ + machine->vtbl->GetDVDDrive(machine, &dvdDrive); + if (dvdDrive) { + IDVDImage *dvdImage = NULL; + PRUnichar *dvdfileUtf16 = NULL; + vboxIID dvduuid = VBOX_IID_INITIALIZER; + vboxIID dvdemptyuuid = VBOX_IID_INITIALIZER; - VRDxServer->vtbl->SetEnabled(VRDxServer, PR_TRUE); - VIR_DEBUG("VRDP Support turned ON."); + VBOX_UTF8_TO_UTF16(src, &dvdfileUtf16); -#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 */ + data->vboxObj->vtbl->FindDVDImage(data->vboxObj, dvdfileUtf16, &dvdImage); + if (!dvdImage) { + data->vboxObj->vtbl->OpenDVDImage(data->vboxObj, dvdfileUtf16, dvdemptyuuid.value, &dvdImage); + } + if (dvdImage) { + rc = dvdImage->vtbl->imedium.GetId((IMedium *)dvdImage, &dvduuid.value); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("can't get the uuid of the file to " + "be attached to cdrom: %s, rc=%08x"), + src, (unsigned)rc); + } else { + /* unmount the previous mounted image */ + dvdDrive->vtbl->Unmount(dvdDrive); + rc = dvdDrive->vtbl->MountImage(dvdDrive, dvduuid.value); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not attach the file to cdrom: %s, rc=%08x"), + src, (unsigned)rc); + } else { + ret = 0; + DEBUGIID("CD/DVD Image UUID:", dvduuid.value); + } + } - if (def->graphics[i]->data.rdp.replaceUser) { - VRDxServer->vtbl->SetReuseSingleConnection(VRDxServer, - PR_TRUE); - VIR_DEBUG("VRDP set to reuse single connection"); - } + VBOX_MEDIUM_RELEASE(dvdImage); + } + vboxIIDUnalloc(&dvduuid); + VBOX_UTF16_FREE(dvdfileUtf16); + VBOX_RELEASE(dvdDrive); + } + } else if (type == VIR_STORAGE_TYPE_BLOCK) { + } + } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { + if (type == VIR_STORAGE_TYPE_FILE && src) { + IFloppyDrive *floppyDrive; + machine->vtbl->GetFloppyDrive(machine, &floppyDrive); + if (floppyDrive) { + rc = floppyDrive->vtbl->SetEnabled(floppyDrive, 1); + if (NS_SUCCEEDED(rc)) { + IFloppyImage *floppyImage = NULL; + PRUnichar *fdfileUtf16 = NULL; + vboxIID fduuid = VBOX_IID_INITIALIZER; + vboxIID fdemptyuuid = VBOX_IID_INITIALIZER; + VBOX_UTF8_TO_UTF16(src, &fdfileUtf16); + rc = data->vboxObj->vtbl->FindFloppyImage(data->vboxObj, + fdfileUtf16, + &floppyImage); - if (def->graphics[i]->data.rdp.multiUser) { - VRDxServer->vtbl->SetAllowMultiConnection(VRDxServer, - PR_TRUE); - VIR_DEBUG("VRDP set to allow multiple connection"); - } + if (!floppyImage) { + data->vboxObj->vtbl->OpenFloppyImage(data->vboxObj, + fdfileUtf16, + fdemptyuuid.value, + &floppyImage); + } - if (listenAddr) { -#if VBOX_API_VERSION >= 4000000 - PRUnichar *netAddressKey = NULL; -#endif - PRUnichar *netAddressUtf16 = NULL; + if (floppyImage) { + rc = floppyImage->vtbl->imedium.GetId((IMedium *)floppyImage, &fduuid.value); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("can't get the uuid of the file to be " + "attached to floppy drive: %s, rc=%08x"), + src, (unsigned)rc); + } else { + rc = floppyDrive->vtbl->MountImage(floppyDrive, fduuid.value); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not attach the file to floppy drive: %s, rc=%08x"), + src, (unsigned)rc); + } else { + ret = 0; + DEBUGIID("attached floppy, UUID:", fduuid.value); + } + } + VBOX_MEDIUM_RELEASE(floppyImage); + } + vboxIIDUnalloc(&fduuid); + VBOX_UTF16_FREE(fdfileUtf16); + } + VBOX_RELEASE(floppyDrive); + } + } else if (type == VIR_STORAGE_TYPE_BLOCK) { + } + } +#else /* VBOX_API_VERSION >= 3001000 */ +#endif /* VBOX_API_VERSION >= 3001000 */ + } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { + } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { + if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { + if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { + } + } + } else if (dev->type == VIR_DOMAIN_DEVICE_FS && + dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) { + PRUnichar *nameUtf16; + PRUnichar *hostPathUtf16; + PRBool writable; + + VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16); + VBOX_UTF8_TO_UTF16(dev->data.fs->src, &hostPathUtf16); + writable = !dev->data.fs->readonly; - VBOX_UTF8_TO_UTF16(listenAddr, &netAddressUtf16); #if VBOX_API_VERSION < 4000000 - VRDxServer->vtbl->SetNetAddress(VRDxServer, - netAddressUtf16); + rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16, + writable); #else /* VBOX_API_VERSION >= 4000000 */ - VBOX_UTF8_TO_UTF16("TCP/Address", &netAddressKey); - VRDxServer->vtbl->SetVRDEProperty(VRDxServer, netAddressKey, - netAddressUtf16); - VBOX_UTF16_FREE(netAddressKey); + rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16, + writable, PR_FALSE); #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 (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not attach shared folder '%s', rc=%08x"), + dev->data.fs->dst, (unsigned)rc); + } else { + ret = 0; + } - 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 - */ + VBOX_UTF16_FREE(nameUtf16); + VBOX_UTF16_FREE(hostPathUtf16); + } + machine->vtbl->SaveSettings(machine); + VBOX_RELEASE(machine); } + VBOX_SESSION_CLOSE(); } } - 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; + cleanup: + vboxIIDUnalloc(&iid); + virDomainDefFree(def); + virDomainDeviceDefFree(dev); + return ret; +} - VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); - VBOX_UTF8_TO_UTF16("gui", &valueTypeUtf16); +static int vboxDomainAttachDevice(virDomainPtr dom, const char *xml) +{ + return vboxDomainAttachDeviceImpl(dom, xml, 0); +} - machine->vtbl->SetExtraData(machine, keyTypeUtf16, valueTypeUtf16); +static int +vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) +{ + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); - VBOX_UTF16_FREE(keyTypeUtf16); - VBOX_UTF16_FREE(valueTypeUtf16); + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify the persistent configuration of a domain")); + return -1; + } - if (guiDisplay) { - VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16); - VBOX_UTF8_TO_UTF16(guiDisplay, &valueDisplayUtf16); + return vboxDomainAttachDeviceImpl(dom, xml, 0); +} - machine->vtbl->SetExtraData(machine, keyDislpayUtf16, - valueDisplayUtf16); +static int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) +{ + virCheckFlags(VIR_DOMAIN_AFFECT_CURRENT | + VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); - VBOX_UTF16_FREE(keyDislpayUtf16); - VBOX_UTF16_FREE(valueDisplayUtf16); - } + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify the persistent configuration of a domain")); + return -1; } - VIR_FREE(guiDisplay); - VIR_FREE(sdlDisplay); + return vboxDomainAttachDeviceImpl(dom, xml, 1); } -static void -vboxAttachUSB(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +static int vboxDomainDetachDevice(virDomainPtr dom, const char *xml) { -#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; + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IMachine *machine = NULL; + vboxIID iid = VBOX_IID_INITIALIZER; + PRUint32 state = MachineState_Null; + virDomainDefPtr def = NULL; + virDomainDeviceDefPtr dev = NULL; + nsresult rc; - /* 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 (VIR_ALLOC(def) < 0) + return ret; - if (def->hostdevs[i]->source.subsys.type != - VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) - continue; + if (VIR_STRDUP(def->os.type, "hvm") < 0) + goto cleanup; - if (!def->hostdevs[i]->source.subsys.u.usb.vendor && - !def->hostdevs[i]->source.subsys.u.usb.product) - continue; + dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, + VIR_DOMAIN_XML_INACTIVE); + if (dev == NULL) + goto cleanup; - 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; + 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; } - 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; + if (machine) { + machine->vtbl->GetState(machine, &state); - 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 ((state == MachineState_Running) || + (state == MachineState_Paused)) { + rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); + } else { + rc = VBOX_SESSION_OPEN(iid.value, machine); + } - if (!USBDeviceFilters) - return; -#endif + if (NS_SUCCEEDED(rc)) { + rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); + if (NS_SUCCEEDED(rc) && machine) { + if (dev->type == VIR_DOMAIN_DEVICE_DISK) { +#if VBOX_API_VERSION < 3001000 + int type = virDomainDiskGetType(dev->data.disk); - 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 (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { + if (type == VIR_STORAGE_TYPE_FILE) { + IDVDDrive *dvdDrive = NULL; + /* Currently CDROM/DVD Drive is always IDE + * Secondary Master so neglecting the following + * parameter dev->data.disk->bus + */ + machine->vtbl->GetDVDDrive(machine, &dvdDrive); + if (dvdDrive) { + rc = dvdDrive->vtbl->Unmount(dvdDrive); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not de-attach the mounted ISO, rc=%08x"), + (unsigned)rc); + } else { + ret = 0; + } + VBOX_RELEASE(dvdDrive); + } + } else if (type == VIR_STORAGE_TYPE_BLOCK) { + } + } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { + if (type == VIR_STORAGE_TYPE_FILE) { + IFloppyDrive *floppyDrive; + machine->vtbl->GetFloppyDrive(machine, &floppyDrive); + if (floppyDrive) { + PRBool enabled = PR_FALSE; - if (def->hostdevs[i]->source.subsys.type != - VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) - continue; + floppyDrive->vtbl->GetEnabled(floppyDrive, &enabled); + if (enabled) { + rc = floppyDrive->vtbl->Unmount(floppyDrive); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not attach the file " + "to floppy drive, rc=%08x"), + (unsigned)rc); + } else { + ret = 0; + } + } else { + /* If you are here means floppy drive is already unmounted + * so don't flag error, just say everything is fine and quit + */ + ret = 0; + } + VBOX_RELEASE(floppyDrive); + } + } else if (type == VIR_STORAGE_TYPE_BLOCK) { + } + } +#else /* VBOX_API_VERSION >= 3001000 */ +#endif /* VBOX_API_VERSION >= 3001000 */ + } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { + } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { + if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { + if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { + } + } + } else if (dev->type == VIR_DOMAIN_DEVICE_FS && + dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) { + PRUnichar *nameUtf16; - /* 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); + VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16); - if (!filter) - continue; + rc = machine->vtbl->RemoveSharedFolder(machine, nameUtf16); - if (!def->hostdevs[i]->source.subsys.u.usb.vendor && - !def->hostdevs[i]->source.subsys.u.usb.product) - continue; + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not detach shared folder '%s', rc=%08x"), + dev->data.fs->dst, (unsigned)rc); + } else { + ret = 0; + } - 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); + VBOX_UTF16_FREE(nameUtf16); + } + machine->vtbl->SaveSettings(machine); + VBOX_RELEASE(machine); + } + VBOX_SESSION_CLOSE(); + } } -#if VBOX_API_VERSION < 4003000 - VBOX_RELEASE(USBController); -#else - VBOX_RELEASE(USBDeviceFilters); -#endif + cleanup: + vboxIIDUnalloc(&iid); + virDomainDefFree(def); + virDomainDeviceDefFree(dev); + return ret; } -static void -vboxAttachSharedFolder(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +static int +vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) { - 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 */ + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); - VBOX_UTF16_FREE(nameUtf16); - VBOX_UTF16_FREE(hostPathUtf16); + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify the persistent configuration of a domain")); + return -1; } + + return vboxDomainDetachDevice(dom, xml); } -static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml) +static int +vboxDomainSnapshotGetAll(virDomainPtr dom, + IMachine *machine, + ISnapshot ***snapshots) { - 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 + vboxIID empty = VBOX_IID_INITIALIZER; + ISnapshot **list = NULL; + PRUint32 count; 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); + unsigned int next; + unsigned int top; + rc = machine->vtbl->GetSnapshotCount(machine, &count); if (NS_FAILED(rc)) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not define a domain, rc=%08x"), (unsigned)rc); - goto cleanup; + _("could not get snapshot count for domain %s"), + dom->name); + goto error; } - 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 (count == 0) + goto out; - 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 (VIR_ALLOC_N(list, count) < 0) + goto error; -#if VBOX_API_VERSION < 3001000 - rc = machine->vtbl->SetPAEEnabled(machine, - def->features[VIR_DOMAIN_FEATURE_PAE] == - VIR_TRISTATE_SWITCH_ON); -#elif VBOX_API_VERSION == 3001000 - rc = machine->vtbl->SetCpuProperty(machine, CpuPropertyType_PAE, - def->features[VIR_DOMAIN_FEATURE_PAE] == - VIR_TRISTATE_SWITCH_ON); -#elif VBOX_API_VERSION >= 3002000 - rc = machine->vtbl->SetCPUProperty(machine, CPUPropertyType_PAE, - def->features[VIR_DOMAIN_FEATURE_PAE] == - VIR_TRISTATE_SWITCH_ON); -#endif - if (NS_FAILED(rc)) { +#if VBOX_API_VERSION < 4000000 + rc = machine->vtbl->GetSnapshot(machine, empty.value, list); +#else /* VBOX_API_VERSION >= 4000000 */ + rc = machine->vtbl->FindSnapshot(machine, empty.value, list); +#endif /* VBOX_API_VERSION >= 4000000 */ + if (NS_FAILED(rc) || !list[0]) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not change PAE status to: %s, rc=%08x"), - (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_TRISTATE_SWITCH_ON) - ? _("Enabled") : _("Disabled"), (unsigned)rc); + _("could not get root snapshot for domain %s"), + dom->name); + goto error; } - machine->vtbl->GetBIOSSettings(machine, &bios); - if (bios) { - rc = bios->vtbl->SetACPIEnabled(bios, - def->features[VIR_DOMAIN_FEATURE_ACPI] == - VIR_TRISTATE_SWITCH_ON); - if (NS_FAILED(rc)) { + /* BFS walk through snapshot tree */ + top = 1; + for (next = 0; next < count; next++) { + vboxArray children = VBOX_ARRAY_INITIALIZER; + size_t i; + + if (!list[next]) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not change ACPI status to: %s, rc=%08x"), - (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_TRISTATE_SWITCH_ON) - ? _("Enabled") : _("Disabled"), (unsigned)rc); + _("unexpected number of snapshots < %u"), count); + goto error; } - rc = bios->vtbl->SetIOAPICEnabled(bios, - def->features[VIR_DOMAIN_FEATURE_APIC] == - VIR_TRISTATE_SWITCH_ON); + + rc = vboxArrayGet(&children, list[next], + list[next]->vtbl->GetChildren); 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_TRISTATE_SWITCH_ON) - ? _("Enabled") : _("Disabled"), (unsigned)rc); + "%s", _("could not get children snapshots")); + goto error; } - 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; + for (i = 0; i < children.count; i++) { + ISnapshot *child = children.items[i]; + if (!child) + continue; + if (top == count) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected number of snapshots > %u"), count); + vboxArrayRelease(&children); + goto error; + } + VBOX_ADDREF(child); + list[top++] = child; + } + vboxArrayRelease(&children); } - /* 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); + out: + *snapshots = list; + return count; - return ret; + error: + if (list) { + for (next = 0; next < count; next++) + VBOX_RELEASE(list[next]); + } + VIR_FREE(list); - cleanup: - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - virDomainDefFree(def); - return NULL; + return -1; } -static int -vboxDomainUndefine(virDomainPtr dom) +static ISnapshot * +vboxDomainSnapshotGet(vboxGlobalData *data, + virDomainPtr dom, + IMachine *machine, + const char *name) { - return vboxDomainUndefineFlags(dom, 0); -} - -static int vboxDomainAttachDeviceImpl(virDomainPtr dom, - const char *xml, - int mediaChangeOnly ATTRIBUTE_UNUSED) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IMachine *machine = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - PRUint32 state = MachineState_Null; - virDomainDefPtr def = NULL; - virDomainDeviceDefPtr dev = NULL; - nsresult rc; - - if (VIR_ALLOC(def) < 0) - return ret; - - if (VIR_STRDUP(def->os.type, "hvm") < 0) - goto cleanup; - - dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, - VIR_DOMAIN_XML_INACTIVE); - if (dev == NULL) - goto cleanup; - - 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; - } - - if (machine) { - machine->vtbl->GetState(machine, &state); - - if ((state == MachineState_Running) || - (state == MachineState_Paused)) { - rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); - } else { - 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 (dev->type == VIR_DOMAIN_DEVICE_DISK) { -#if VBOX_API_VERSION < 3001000 - const char *src = virDomainDiskGetSource(dev->data.disk); - int type = virDomainDiskGetType(dev->data.disk); - - if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { - if (type == VIR_STORAGE_TYPE_FILE && src) { - IDVDDrive *dvdDrive = NULL; - /* Currently CDROM/DVD Drive is always IDE - * Secondary Master so neglecting the following - * parameter dev->data.disk->bus - */ - machine->vtbl->GetDVDDrive(machine, &dvdDrive); - if (dvdDrive) { - IDVDImage *dvdImage = NULL; - PRUnichar *dvdfileUtf16 = NULL; - vboxIID dvduuid = VBOX_IID_INITIALIZER; - vboxIID dvdemptyuuid = VBOX_IID_INITIALIZER; - - VBOX_UTF8_TO_UTF16(src, &dvdfileUtf16); - - data->vboxObj->vtbl->FindDVDImage(data->vboxObj, dvdfileUtf16, &dvdImage); - if (!dvdImage) { - data->vboxObj->vtbl->OpenDVDImage(data->vboxObj, dvdfileUtf16, dvdemptyuuid.value, &dvdImage); - } - if (dvdImage) { - rc = dvdImage->vtbl->imedium.GetId((IMedium *)dvdImage, &dvduuid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("can't get the uuid of the file to " - "be attached to cdrom: %s, rc=%08x"), - src, (unsigned)rc); - } else { - /* unmount the previous mounted image */ - dvdDrive->vtbl->Unmount(dvdDrive); - rc = dvdDrive->vtbl->MountImage(dvdDrive, dvduuid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not attach the file to cdrom: %s, rc=%08x"), - src, (unsigned)rc); - } else { - ret = 0; - DEBUGIID("CD/DVD Image UUID:", dvduuid.value); - } - } - - VBOX_MEDIUM_RELEASE(dvdImage); - } - vboxIIDUnalloc(&dvduuid); - VBOX_UTF16_FREE(dvdfileUtf16); - VBOX_RELEASE(dvdDrive); - } - } else if (type == VIR_STORAGE_TYPE_BLOCK) { - } - } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { - if (type == VIR_STORAGE_TYPE_FILE && src) { - IFloppyDrive *floppyDrive; - machine->vtbl->GetFloppyDrive(machine, &floppyDrive); - if (floppyDrive) { - rc = floppyDrive->vtbl->SetEnabled(floppyDrive, 1); - if (NS_SUCCEEDED(rc)) { - IFloppyImage *floppyImage = NULL; - PRUnichar *fdfileUtf16 = NULL; - vboxIID fduuid = VBOX_IID_INITIALIZER; - vboxIID fdemptyuuid = VBOX_IID_INITIALIZER; - VBOX_UTF8_TO_UTF16(src, &fdfileUtf16); - rc = data->vboxObj->vtbl->FindFloppyImage(data->vboxObj, - fdfileUtf16, - &floppyImage); - - if (!floppyImage) { - data->vboxObj->vtbl->OpenFloppyImage(data->vboxObj, - fdfileUtf16, - fdemptyuuid.value, - &floppyImage); - } - - if (floppyImage) { - rc = floppyImage->vtbl->imedium.GetId((IMedium *)floppyImage, &fduuid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("can't get the uuid of the file to be " - "attached to floppy drive: %s, rc=%08x"), - src, (unsigned)rc); - } else { - rc = floppyDrive->vtbl->MountImage(floppyDrive, fduuid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not attach the file to floppy drive: %s, rc=%08x"), - src, (unsigned)rc); - } else { - ret = 0; - DEBUGIID("attached floppy, UUID:", fduuid.value); - } - } - VBOX_MEDIUM_RELEASE(floppyImage); - } - vboxIIDUnalloc(&fduuid); - VBOX_UTF16_FREE(fdfileUtf16); - } - VBOX_RELEASE(floppyDrive); - } - } else if (type == VIR_STORAGE_TYPE_BLOCK) { - } - } -#else /* VBOX_API_VERSION >= 3001000 */ -#endif /* VBOX_API_VERSION >= 3001000 */ - } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { - } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { - if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { - if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { - } - } - } else if (dev->type == VIR_DOMAIN_DEVICE_FS && - dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) { - PRUnichar *nameUtf16; - PRUnichar *hostPathUtf16; - PRBool writable; - - VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16); - VBOX_UTF8_TO_UTF16(dev->data.fs->src, &hostPathUtf16); - writable = !dev->data.fs->readonly; - -#if VBOX_API_VERSION < 4000000 - rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16, - writable); -#else /* VBOX_API_VERSION >= 4000000 */ - rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16, - writable, PR_FALSE); -#endif /* VBOX_API_VERSION >= 4000000 */ - - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not attach shared folder '%s', rc=%08x"), - dev->data.fs->dst, (unsigned)rc); - } else { - ret = 0; - } - - VBOX_UTF16_FREE(nameUtf16); - VBOX_UTF16_FREE(hostPathUtf16); - } - machine->vtbl->SaveSettings(machine); - VBOX_RELEASE(machine); - } - VBOX_SESSION_CLOSE(); - } - } - - cleanup: - vboxIIDUnalloc(&iid); - virDomainDefFree(def); - virDomainDeviceDefFree(dev); - return ret; -} - -static int vboxDomainAttachDevice(virDomainPtr dom, const char *xml) -{ - return vboxDomainAttachDeviceImpl(dom, xml, 0); -} - -static int -vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) -{ - virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); - - if (flags & VIR_DOMAIN_AFFECT_CONFIG) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return vboxDomainAttachDeviceImpl(dom, xml, 0); -} - -static int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) -{ - virCheckFlags(VIR_DOMAIN_AFFECT_CURRENT | - VIR_DOMAIN_AFFECT_LIVE | - VIR_DOMAIN_AFFECT_CONFIG, -1); - - if (flags & VIR_DOMAIN_AFFECT_CONFIG) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return vboxDomainAttachDeviceImpl(dom, xml, 1); -} - -static int vboxDomainDetachDevice(virDomainPtr dom, const char *xml) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IMachine *machine = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - PRUint32 state = MachineState_Null; - virDomainDefPtr def = NULL; - virDomainDeviceDefPtr dev = NULL; - nsresult rc; - - if (VIR_ALLOC(def) < 0) - return ret; - - if (VIR_STRDUP(def->os.type, "hvm") < 0) - goto cleanup; - - dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, - VIR_DOMAIN_XML_INACTIVE); - if (dev == NULL) - goto cleanup; - - 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; - } - - if (machine) { - machine->vtbl->GetState(machine, &state); - - if ((state == MachineState_Running) || - (state == MachineState_Paused)) { - rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); - } else { - 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 (dev->type == VIR_DOMAIN_DEVICE_DISK) { -#if VBOX_API_VERSION < 3001000 - int type = virDomainDiskGetType(dev->data.disk); - - if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { - if (type == VIR_STORAGE_TYPE_FILE) { - IDVDDrive *dvdDrive = NULL; - /* Currently CDROM/DVD Drive is always IDE - * Secondary Master so neglecting the following - * parameter dev->data.disk->bus - */ - machine->vtbl->GetDVDDrive(machine, &dvdDrive); - if (dvdDrive) { - rc = dvdDrive->vtbl->Unmount(dvdDrive); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not de-attach the mounted ISO, rc=%08x"), - (unsigned)rc); - } else { - ret = 0; - } - VBOX_RELEASE(dvdDrive); - } - } else if (type == VIR_STORAGE_TYPE_BLOCK) { - } - } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { - if (type == VIR_STORAGE_TYPE_FILE) { - IFloppyDrive *floppyDrive; - machine->vtbl->GetFloppyDrive(machine, &floppyDrive); - if (floppyDrive) { - PRBool enabled = PR_FALSE; - - floppyDrive->vtbl->GetEnabled(floppyDrive, &enabled); - if (enabled) { - rc = floppyDrive->vtbl->Unmount(floppyDrive); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not attach the file " - "to floppy drive, rc=%08x"), - (unsigned)rc); - } else { - ret = 0; - } - } else { - /* If you are here means floppy drive is already unmounted - * so don't flag error, just say everything is fine and quit - */ - ret = 0; - } - VBOX_RELEASE(floppyDrive); - } - } else if (type == VIR_STORAGE_TYPE_BLOCK) { - } - } -#else /* VBOX_API_VERSION >= 3001000 */ -#endif /* VBOX_API_VERSION >= 3001000 */ - } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { - } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { - if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { - if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { - } - } - } else if (dev->type == VIR_DOMAIN_DEVICE_FS && - dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) { - PRUnichar *nameUtf16; - - VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16); - - rc = machine->vtbl->RemoveSharedFolder(machine, nameUtf16); - - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not detach shared folder '%s', rc=%08x"), - dev->data.fs->dst, (unsigned)rc); - } else { - ret = 0; - } - - VBOX_UTF16_FREE(nameUtf16); - } - machine->vtbl->SaveSettings(machine); - VBOX_RELEASE(machine); - } - VBOX_SESSION_CLOSE(); - } - } - - cleanup: - vboxIIDUnalloc(&iid); - virDomainDefFree(def); - virDomainDeviceDefFree(dev); - return ret; -} - -static int -vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) -{ - virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); - - if (flags & VIR_DOMAIN_AFFECT_CONFIG) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return vboxDomainDetachDevice(dom, xml); -} - -static int -vboxDomainSnapshotGetAll(virDomainPtr dom, - IMachine *machine, - ISnapshot ***snapshots) -{ - vboxIID empty = VBOX_IID_INITIALIZER; - ISnapshot **list = NULL; - PRUint32 count; - nsresult rc; - unsigned int next; - unsigned int top; - - rc = machine->vtbl->GetSnapshotCount(machine, &count); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get snapshot count for domain %s"), - dom->name); - goto error; - } - - if (count == 0) - goto out; - - if (VIR_ALLOC_N(list, count) < 0) - goto error; - -#if VBOX_API_VERSION < 4000000 - rc = machine->vtbl->GetSnapshot(machine, empty.value, list); -#else /* VBOX_API_VERSION >= 4000000 */ - rc = machine->vtbl->FindSnapshot(machine, empty.value, list); -#endif /* VBOX_API_VERSION >= 4000000 */ - if (NS_FAILED(rc) || !list[0]) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get root snapshot for domain %s"), - dom->name); - goto error; - } - - /* BFS walk through snapshot tree */ - top = 1; - for (next = 0; next < count; next++) { - vboxArray children = VBOX_ARRAY_INITIALIZER; - size_t i; - - if (!list[next]) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unexpected number of snapshots < %u"), count); - goto error; - } - - rc = vboxArrayGet(&children, list[next], - list[next]->vtbl->GetChildren); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("could not get children snapshots")); - goto error; - } - for (i = 0; i < children.count; i++) { - ISnapshot *child = children.items[i]; - if (!child) - continue; - if (top == count) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unexpected number of snapshots > %u"), count); - vboxArrayRelease(&children); - goto error; - } - VBOX_ADDREF(child); - list[top++] = child; - } - vboxArrayRelease(&children); - } - - out: - *snapshots = list; - return count; - - error: - if (list) { - for (next = 0; next < count; next++) - VBOX_RELEASE(list[next]); - } - VIR_FREE(list); - - return -1; -} - -static ISnapshot * -vboxDomainSnapshotGet(vboxGlobalData *data, - virDomainPtr dom, - IMachine *machine, - const char *name) -{ - ISnapshot **snapshots = NULL; - ISnapshot *snapshot = NULL; - nsresult rc; - int count = 0; - size_t i; + ISnapshot **snapshots = NULL; + ISnapshot *snapshot = NULL; + nsresult rc; + int count = 0; + size_t i; if ((count = vboxDomainSnapshotGetAll(dom, machine, &snapshots)) < 0) goto cleanup; @@ -9801,22 +8820,265 @@ vboxStorageVolLookupByName(virStoragePoolPtr pool, const char *name) return ret; } -static virStorageVolPtr -vboxStorageVolLookupByKey(virConnectPtr conn, const char *key) +static virStorageVolPtr +vboxStorageVolLookupByKey(virConnectPtr conn, const char *key) +{ + VBOX_OBJECT_CHECK(conn, virStorageVolPtr, NULL); + vboxIID hddIID = VBOX_IID_INITIALIZER; + unsigned char uuid[VIR_UUID_BUFLEN]; + IHardDisk *hardDisk = NULL; + nsresult rc; + + if (!key) + return ret; + + if (virUUIDParse(key, uuid) < 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("Could not parse UUID from '%s'"), key); + return NULL; + } + + vboxIIDFromUUID(&hddIID, uuid); +#if VBOX_API_VERSION < 4000000 + rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk); +#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 + rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value, + DeviceType_HardDisk, &hardDisk); +#else + rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value, + DeviceType_HardDisk, AccessMode_ReadWrite, + PR_FALSE, &hardDisk); +#endif /* VBOX_API_VERSION >= 4000000 */ + if (NS_SUCCEEDED(rc)) { + PRUint32 hddstate; + + VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); + if (hddstate != MediaState_Inaccessible) { + PRUnichar *hddNameUtf16 = NULL; + char *hddNameUtf8 = NULL; + + VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &hddNameUtf16); + VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8); + + if (hddNameUtf8) { + if (vboxConnectNumOfStoragePools(conn) == 1) { + ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key, + NULL, NULL); + VIR_DEBUG("Storage Volume Pool: %s", "default-pool"); + } else { + /* TODO: currently only one default pool and thus + * nothing here, change it when pools are supported + */ + } + + VIR_DEBUG("Storage Volume Name: %s", key); + VIR_DEBUG("Storage Volume key : %s", hddNameUtf8); + + VBOX_UTF8_FREE(hddNameUtf8); + VBOX_UTF16_FREE(hddNameUtf16); + } + } + + VBOX_MEDIUM_RELEASE(hardDisk); + } + + vboxIIDUnalloc(&hddIID); + return ret; +} + +static virStorageVolPtr +vboxStorageVolLookupByPath(virConnectPtr conn, const char *path) +{ + VBOX_OBJECT_CHECK(conn, virStorageVolPtr, NULL); + PRUnichar *hddPathUtf16 = NULL; + IHardDisk *hardDisk = NULL; + nsresult rc; + + if (!path) + return ret; + + VBOX_UTF8_TO_UTF16(path, &hddPathUtf16); + + if (!hddPathUtf16) + return ret; + +#if VBOX_API_VERSION < 4000000 + rc = data->vboxObj->vtbl->FindHardDisk(data->vboxObj, hddPathUtf16, &hardDisk); +#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 + rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddPathUtf16, + DeviceType_HardDisk, &hardDisk); +#else + rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddPathUtf16, + DeviceType_HardDisk, AccessMode_ReadWrite, + PR_FALSE, &hardDisk); +#endif /* VBOX_API_VERSION >= 4000000 */ + if (NS_SUCCEEDED(rc)) { + PRUint32 hddstate; + + VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); + if (hddstate != MediaState_Inaccessible) { + PRUnichar *hddNameUtf16 = NULL; + char *hddNameUtf8 = NULL; + + VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &hddNameUtf16); + + if (hddNameUtf16) { + VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8); + VBOX_UTF16_FREE(hddNameUtf16); + } + + if (hddNameUtf8) { + vboxIID hddIID = VBOX_IID_INITIALIZER; + unsigned char uuid[VIR_UUID_BUFLEN]; + char key[VIR_UUID_STRING_BUFLEN] = ""; + + rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value); + if (NS_SUCCEEDED(rc)) { + vboxIIDToUUID(&hddIID, uuid); + virUUIDFormat(uuid, key); + + /* TODO: currently only one default pool and thus + * the check below, change it when pools are supported + */ + if (vboxConnectNumOfStoragePools(conn) == 1) + ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key, + NULL, NULL); + + VIR_DEBUG("Storage Volume Pool: %s", "default-pool"); + VIR_DEBUG("Storage Volume Name: %s", hddNameUtf8); + VIR_DEBUG("Storage Volume key : %s", key); + } + + vboxIIDUnalloc(&hddIID); + } + + VBOX_UTF8_FREE(hddNameUtf8); + } + + VBOX_MEDIUM_RELEASE(hardDisk); + } + + VBOX_UTF16_FREE(hddPathUtf16); + + return ret; +} + +static virStorageVolPtr vboxStorageVolCreateXML(virStoragePoolPtr pool, + const char *xml, + unsigned int flags) +{ + VBOX_OBJECT_CHECK(pool->conn, virStorageVolPtr, NULL); + virStorageVolDefPtr def = NULL; + PRUnichar *hddFormatUtf16 = NULL; + PRUnichar *hddNameUtf16 = NULL; + virStoragePoolDef poolDef; + nsresult rc; + + virCheckFlags(0, NULL); + + /* since there is currently one default pool now + * and virStorageVolDefFormat() just checks it type + * so just assign it for now, change the behaviour + * when vbox supports pools. + */ + memset(&poolDef, 0, sizeof(poolDef)); + poolDef.type = VIR_STORAGE_POOL_DIR; + + if ((def = virStorageVolDefParseString(&poolDef, xml)) == NULL) + goto cleanup; + + if (!def->name || + (def->type != VIR_STORAGE_VOL_FILE)) + goto cleanup; + + /* For now only the vmdk, vpc and vdi type harddisk + * variants can be created. For historical reason, we default to vdi */ + if (def->target.format == VIR_STORAGE_FILE_VMDK) { + VBOX_UTF8_TO_UTF16("VMDK", &hddFormatUtf16); + } else if (def->target.format == VIR_STORAGE_FILE_VPC) { + VBOX_UTF8_TO_UTF16("VHD", &hddFormatUtf16); + } else { + VBOX_UTF8_TO_UTF16("VDI", &hddFormatUtf16); + } + + VBOX_UTF8_TO_UTF16(def->name, &hddNameUtf16); + + if (hddFormatUtf16 && hddNameUtf16) { + IHardDisk *hardDisk = NULL; + + rc = data->vboxObj->vtbl->CreateHardDisk(data->vboxObj, hddFormatUtf16, hddNameUtf16, &hardDisk); + if (NS_SUCCEEDED(rc)) { + IProgress *progress = NULL; + PRUint64 logicalSize = VIR_DIV_UP(def->target.capacity, + 1024 * 1024); + PRUint32 variant = HardDiskVariant_Standard; + + if (def->target.capacity == def->target.allocation) + variant = HardDiskVariant_Fixed; + +#if VBOX_API_VERSION < 4003000 + rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, variant, &progress); +#else + rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, 1, &variant, &progress); +#endif + if (NS_SUCCEEDED(rc) && 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)) { + vboxIID hddIID = VBOX_IID_INITIALIZER; + unsigned char uuid[VIR_UUID_BUFLEN]; + char key[VIR_UUID_STRING_BUFLEN] = ""; + + rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value); + if (NS_SUCCEEDED(rc)) { + vboxIIDToUUID(&hddIID, uuid); + virUUIDFormat(uuid, key); + + ret = virGetStorageVol(pool->conn, pool->name, def->name, key, + NULL, NULL); + } + + vboxIIDUnalloc(&hddIID); + } + + VBOX_RELEASE(progress); + } + } + } + + VBOX_UTF16_FREE(hddFormatUtf16); + VBOX_UTF16_FREE(hddNameUtf16); + + cleanup: + virStorageVolDefFree(def); + return ret; +} + +static int vboxStorageVolDelete(virStorageVolPtr vol, + unsigned int flags) { - VBOX_OBJECT_CHECK(conn, virStorageVolPtr, NULL); + VBOX_OBJECT_CHECK(vol->conn, int, -1); vboxIID hddIID = VBOX_IID_INITIALIZER; unsigned char uuid[VIR_UUID_BUFLEN]; IHardDisk *hardDisk = NULL; + int deregister = 0; nsresult rc; + size_t i = 0; + size_t j = 0; - if (!key) - return ret; + virCheckFlags(0, -1); - if (virUUIDParse(key, uuid) < 0) { + if (virUUIDParse(vol->key, uuid) < 0) { virReportError(VIR_ERR_INVALID_ARG, - _("Could not parse UUID from '%s'"), key); - return NULL; + _("Could not parse UUID from '%s'"), vol->key); + return -1; } vboxIIDFromUUID(&hddIID, uuid); @@ -9835,28 +9097,134 @@ vboxStorageVolLookupByKey(virConnectPtr conn, const char *key) VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); if (hddstate != MediaState_Inaccessible) { - PRUnichar *hddNameUtf16 = NULL; - char *hddNameUtf8 = NULL; + PRUint32 machineIdsSize = 0; + vboxArray machineIds = VBOX_ARRAY_INITIALIZER; - VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &hddNameUtf16); - VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8); +#if VBOX_API_VERSION < 3001000 + vboxArrayGet(&machineIds, hardDisk, hardDisk->vtbl->imedium.GetMachineIds); +#else /* VBOX_API_VERSION >= 3001000 */ + vboxArrayGet(&machineIds, hardDisk, hardDisk->vtbl->GetMachineIds); +#endif /* VBOX_API_VERSION >= 3001000 */ - if (hddNameUtf8) { - if (vboxConnectNumOfStoragePools(conn) == 1) { - ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key, - NULL, NULL); - VIR_DEBUG("Storage Volume Pool: %s", "default-pool"); - } else { - /* TODO: currently only one default pool and thus - * nothing here, change it when pools are supported - */ +#if VBOX_API_VERSION == 2002000 && defined WIN32 + /* VirtualBox 2.2 on Windows represents IIDs as GUIDs and the + * machineIds array contains direct instances of the GUID struct + * instead of pointers to the actual struct instances. But there + * is no 128bit width simple item type for a SafeArray to fit a + * GUID in. The largest simple type it 64bit width and VirtualBox + * uses two of this 64bit items to represents one GUID. Therefore, + * we divide the size of the SafeArray by two, to compensate for + * this workaround in VirtualBox */ + machineIds.count /= 2; +#endif /* VBOX_API_VERSION >= 2002000 */ + + machineIdsSize = machineIds.count; + + for (i = 0; i < machineIds.count; i++) { + IMachine *machine = NULL; + vboxIID machineId = VBOX_IID_INITIALIZER; + + vboxIIDFromArrayItem(&machineId, &machineIds, i); + +#if VBOX_API_VERSION >= 4000000 + rc = VBOX_OBJECT_GET_MACHINE(machineId.value, &machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + break; } +#endif - VIR_DEBUG("Storage Volume Name: %s", key); - VIR_DEBUG("Storage Volume key : %s", hddNameUtf8); + rc = VBOX_SESSION_OPEN(machineId.value, machine); - VBOX_UTF8_FREE(hddNameUtf8); - VBOX_UTF16_FREE(hddNameUtf16); + if (NS_SUCCEEDED(rc)) { + + rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); + if (NS_SUCCEEDED(rc)) { + vboxArray hddAttachments = VBOX_ARRAY_INITIALIZER; + +#if VBOX_API_VERSION < 3001000 + vboxArrayGet(&hddAttachments, machine, + machine->vtbl->GetHardDiskAttachments); +#else /* VBOX_API_VERSION >= 3001000 */ + vboxArrayGet(&hddAttachments, machine, + machine->vtbl->GetMediumAttachments); +#endif /* VBOX_API_VERSION >= 3001000 */ + for (j = 0; j < hddAttachments.count; j++) { + IHardDiskAttachment *hddAttachment = hddAttachments.items[j]; + + if (hddAttachment) { + IHardDisk *hdd = NULL; + +#if VBOX_API_VERSION < 3001000 + rc = hddAttachment->vtbl->GetHardDisk(hddAttachment, &hdd); +#else /* VBOX_API_VERSION >= 3001000 */ + rc = hddAttachment->vtbl->GetMedium(hddAttachment, &hdd); +#endif /* VBOX_API_VERSION >= 3001000 */ + if (NS_SUCCEEDED(rc) && hdd) { + vboxIID iid = VBOX_IID_INITIALIZER; + + rc = VBOX_MEDIUM_FUNC_ARG1(hdd, GetId, &iid.value); + if (NS_SUCCEEDED(rc)) { + + DEBUGIID("HardDisk (to delete) UUID", hddIID.value); + DEBUGIID("HardDisk (currently processing) UUID", iid.value); + + if (vboxIIDIsEqual(&hddIID, &iid)) { + PRUnichar *controller = NULL; + PRInt32 port = 0; + PRInt32 device = 0; + + DEBUGIID("Found HardDisk to delete, UUID", hddIID.value); + + hddAttachment->vtbl->GetController(hddAttachment, &controller); + hddAttachment->vtbl->GetPort(hddAttachment, &port); + hddAttachment->vtbl->GetDevice(hddAttachment, &device); + +#if VBOX_API_VERSION < 3001000 + rc = machine->vtbl->DetachHardDisk(machine, controller, port, device); +#else /* VBOX_API_VERSION >= 3001000 */ + rc = machine->vtbl->DetachDevice(machine, controller, port, device); +#endif /* VBOX_API_VERSION >= 3001000 */ + if (NS_SUCCEEDED(rc)) { + rc = machine->vtbl->SaveSettings(machine); + VIR_DEBUG("saving machine settings"); + } + + if (NS_SUCCEEDED(rc)) { + deregister++; + VIR_DEBUG("deregistering hdd:%d", deregister); + } + + VBOX_UTF16_FREE(controller); + } + vboxIIDUnalloc(&iid); + } + VBOX_MEDIUM_RELEASE(hdd); + } + } + } + vboxArrayRelease(&hddAttachments); + VBOX_RELEASE(machine); + } + VBOX_SESSION_CLOSE(); + } + + vboxIIDUnalloc(&machineId); + } + + vboxArrayUnalloc(&machineIds); + + if (machineIdsSize == 0 || machineIdsSize == deregister) { + IProgress *progress = NULL; + rc = hardDisk->vtbl->DeleteStorage(hardDisk, &progress); + + if (NS_SUCCEEDED(rc) && progress) { + progress->vtbl->WaitForCompletion(progress, -1); + VBOX_RELEASE(progress); + DEBUGIID("HardDisk deleted, UUID", hddIID.value); + ret = 0; + } } } @@ -9864,32 +9232,36 @@ vboxStorageVolLookupByKey(virConnectPtr conn, const char *key) } vboxIIDUnalloc(&hddIID); + return ret; } -static virStorageVolPtr -vboxStorageVolLookupByPath(virConnectPtr conn, const char *path) +static int +vboxStorageVolGetInfo(virStorageVolPtr vol, virStorageVolInfoPtr info) { - VBOX_OBJECT_CHECK(conn, virStorageVolPtr, NULL); - PRUnichar *hddPathUtf16 = NULL; - IHardDisk *hardDisk = NULL; + VBOX_OBJECT_CHECK(vol->conn, int, -1); + IHardDisk *hardDisk = NULL; + unsigned char uuid[VIR_UUID_BUFLEN]; + vboxIID hddIID = VBOX_IID_INITIALIZER; nsresult rc; - if (!path) + if (!info) return ret; - VBOX_UTF8_TO_UTF16(path, &hddPathUtf16); - - if (!hddPathUtf16) + if (virUUIDParse(vol->key, uuid) < 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("Could not parse UUID from '%s'"), vol->key); return ret; + } + vboxIIDFromUUID(&hddIID, uuid); #if VBOX_API_VERSION < 4000000 - rc = data->vboxObj->vtbl->FindHardDisk(data->vboxObj, hddPathUtf16, &hardDisk); + rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk); #elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 - rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddPathUtf16, + rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value, DeviceType_HardDisk, &hardDisk); #else - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddPathUtf16, + rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value, DeviceType_HardDisk, AccessMode_ReadWrite, PR_FALSE, &hardDisk); #endif /* VBOX_API_VERSION >= 4000000 */ @@ -9898,168 +9270,169 @@ vboxStorageVolLookupByPath(virConnectPtr conn, const char *path) VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); if (hddstate != MediaState_Inaccessible) { - PRUnichar *hddNameUtf16 = NULL; - char *hddNameUtf8 = NULL; - - VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &hddNameUtf16); - - if (hddNameUtf16) { - VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8); - VBOX_UTF16_FREE(hddNameUtf16); - } - - if (hddNameUtf8) { - vboxIID hddIID = VBOX_IID_INITIALIZER; - unsigned char uuid[VIR_UUID_BUFLEN]; - char key[VIR_UUID_STRING_BUFLEN] = ""; +#if VBOX_API_VERSION < 4000000 + PRUint64 hddLogicalSize; + PRUint64 hddActualSize; +#else /* VBOX_API_VERSION >= 4000000 */ + PRInt64 hddLogicalSize; + PRInt64 hddActualSize; +#endif /* VBOX_API_VERSION >= 4000000 */ - rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value); - if (NS_SUCCEEDED(rc)) { - vboxIIDToUUID(&hddIID, uuid); - virUUIDFormat(uuid, key); + info->type = VIR_STORAGE_VOL_FILE; - /* TODO: currently only one default pool and thus - * the check below, change it when pools are supported - */ - if (vboxConnectNumOfStoragePools(conn) == 1) - ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key, - NULL, NULL); + hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize); +#if VBOX_API_VERSION < 4000000 + info->capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */ +#else /* VBOX_API_VERSION >= 4000000 */ + info->capacity = hddLogicalSize; +#endif /* VBOX_API_VERSION >= 4000000 */ - VIR_DEBUG("Storage Volume Pool: %s", "default-pool"); - VIR_DEBUG("Storage Volume Name: %s", hddNameUtf8); - VIR_DEBUG("Storage Volume key : %s", key); - } + VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetSize, &hddActualSize); + info->allocation = hddActualSize; - vboxIIDUnalloc(&hddIID); - } + ret = 0; - VBOX_UTF8_FREE(hddNameUtf8); + VIR_DEBUG("Storage Volume Name: %s", vol->name); + VIR_DEBUG("Storage Volume Type: %s", info->type == VIR_STORAGE_VOL_BLOCK ? "Block" : "File"); + VIR_DEBUG("Storage Volume Capacity: %llu", info->capacity); + VIR_DEBUG("Storage Volume Allocation: %llu", info->allocation); } VBOX_MEDIUM_RELEASE(hardDisk); } - VBOX_UTF16_FREE(hddPathUtf16); + vboxIIDUnalloc(&hddIID); return ret; } -static virStorageVolPtr vboxStorageVolCreateXML(virStoragePoolPtr pool, - const char *xml, - unsigned int flags) +static char *vboxStorageVolGetXMLDesc(virStorageVolPtr vol, unsigned int flags) { - VBOX_OBJECT_CHECK(pool->conn, virStorageVolPtr, NULL); - virStorageVolDefPtr def = NULL; - PRUnichar *hddFormatUtf16 = NULL; - PRUnichar *hddNameUtf16 = NULL; - virStoragePoolDef poolDef; + VBOX_OBJECT_CHECK(vol->conn, char *, NULL); + IHardDisk *hardDisk = NULL; + unsigned char uuid[VIR_UUID_BUFLEN]; + vboxIID hddIID = VBOX_IID_INITIALIZER; + virStoragePoolDef pool; + virStorageVolDef def; + int defOk = 0; nsresult rc; virCheckFlags(0, NULL); - /* since there is currently one default pool now - * and virStorageVolDefFormat() just checks it type - * so just assign it for now, change the behaviour - * when vbox supports pools. - */ - memset(&poolDef, 0, sizeof(poolDef)); - poolDef.type = VIR_STORAGE_POOL_DIR; + memset(&pool, 0, sizeof(pool)); + memset(&def, 0, sizeof(def)); - if ((def = virStorageVolDefParseString(&poolDef, xml)) == NULL) - goto cleanup; + if (virUUIDParse(vol->key, uuid) < 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("Could not parse UUID from '%s'"), vol->key); + return ret; + } - if (!def->name || - (def->type != VIR_STORAGE_VOL_FILE)) - goto cleanup; + vboxIIDFromUUID(&hddIID, uuid); +#if VBOX_API_VERSION < 4000000 + rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk); +#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 + rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value, + DeviceType_HardDisk, &hardDisk); +#else + rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value, + DeviceType_HardDisk, AccessMode_ReadWrite, + PR_FALSE, &hardDisk); +#endif /* VBOX_API_VERSION >= 4000000 */ + if (NS_SUCCEEDED(rc)) { + PRUint32 hddstate; - /* For now only the vmdk, vpc and vdi type harddisk - * variants can be created. For historical reason, we default to vdi */ - if (def->target.format == VIR_STORAGE_FILE_VMDK) { - VBOX_UTF8_TO_UTF16("VMDK", &hddFormatUtf16); - } else if (def->target.format == VIR_STORAGE_FILE_VPC) { - VBOX_UTF8_TO_UTF16("VHD", &hddFormatUtf16); - } else { - VBOX_UTF8_TO_UTF16("VDI", &hddFormatUtf16); - } + VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); + if (NS_SUCCEEDED(rc) && hddstate != MediaState_Inaccessible) { + PRUnichar *hddFormatUtf16 = NULL; +#if VBOX_API_VERSION < 4000000 + PRUint64 hddLogicalSize; + PRUint64 hddActualSize; +#else /* VBOX_API_VERSION >= 4000000 */ + PRInt64 hddLogicalSize; + PRInt64 hddActualSize; +#endif /* VBOX_API_VERSION >= 4000000 */ - VBOX_UTF8_TO_UTF16(def->name, &hddNameUtf16); + /* since there is currently one default pool now + * and virStorageVolDefFormat() just checks it type + * so just assign it for now, change the behaviour + * when vbox supports pools. + */ + pool.type = VIR_STORAGE_POOL_DIR; + def.type = VIR_STORAGE_VOL_FILE; + defOk = 1; - if (hddFormatUtf16 && hddNameUtf16) { - IHardDisk *hardDisk = NULL; + rc = hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize); + if (NS_SUCCEEDED(rc) && defOk) { +#if VBOX_API_VERSION < 4000000 + def.target.capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */ +#else /* VBOX_API_VERSION >= 4000000 */ + def.target.capacity = hddLogicalSize; +#endif /* VBOX_API_VERSION >= 4000000 */ + } else + defOk = 0; - rc = data->vboxObj->vtbl->CreateHardDisk(data->vboxObj, hddFormatUtf16, hddNameUtf16, &hardDisk); - if (NS_SUCCEEDED(rc)) { - IProgress *progress = NULL; - PRUint64 logicalSize = VIR_DIV_UP(def->target.capacity, - 1024 * 1024); - PRUint32 variant = HardDiskVariant_Standard; + rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetSize, &hddActualSize); + if (NS_SUCCEEDED(rc) && defOk) + def.target.allocation = hddActualSize; + else + defOk = 0; - if (def->target.capacity == def->target.allocation) - variant = HardDiskVariant_Fixed; + if (VIR_STRDUP(def.name, vol->name) < 0) + defOk = 0; -#if VBOX_API_VERSION < 4003000 - rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, variant, &progress); -#else - rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, 1, &variant, &progress); -#endif - if (NS_SUCCEEDED(rc) && progress) { -#if VBOX_API_VERSION == 2002000 - nsresult resultCode; -#else - PRInt32 resultCode; -#endif + if (VIR_STRDUP(def.key, vol->key) < 0) + defOk = 0; - progress->vtbl->WaitForCompletion(progress, -1); - progress->vtbl->GetResultCode(progress, &resultCode); + rc = hardDisk->vtbl->GetFormat(hardDisk, &hddFormatUtf16); + if (NS_SUCCEEDED(rc) && defOk) { + char *hddFormatUtf8 = NULL; - if (NS_SUCCEEDED(resultCode)) { - vboxIID hddIID = VBOX_IID_INITIALIZER; - unsigned char uuid[VIR_UUID_BUFLEN]; - char key[VIR_UUID_STRING_BUFLEN] = ""; + VBOX_UTF16_TO_UTF8(hddFormatUtf16, &hddFormatUtf8); + if (hddFormatUtf8) { - rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value); - if (NS_SUCCEEDED(rc)) { - vboxIIDToUUID(&hddIID, uuid); - virUUIDFormat(uuid, key); + VIR_DEBUG("Storage Volume Format: %s", hddFormatUtf8); - ret = virGetStorageVol(pool->conn, pool->name, def->name, key, - NULL, NULL); - } + if (STRCASEEQ("vmdk", hddFormatUtf8)) + def.target.format = VIR_STORAGE_FILE_VMDK; + else if (STRCASEEQ("vhd", hddFormatUtf8)) + def.target.format = VIR_STORAGE_FILE_VPC; + else if (STRCASEEQ("vdi", hddFormatUtf8)) + def.target.format = VIR_STORAGE_FILE_VDI; + else + def.target.format = VIR_STORAGE_FILE_RAW; - vboxIIDUnalloc(&hddIID); + VBOX_UTF8_FREE(hddFormatUtf8); } - VBOX_RELEASE(progress); + VBOX_UTF16_FREE(hddFormatUtf16); + } else { + defOk = 0; } } + + VBOX_MEDIUM_RELEASE(hardDisk); } - VBOX_UTF16_FREE(hddFormatUtf16); - VBOX_UTF16_FREE(hddNameUtf16); + vboxIIDUnalloc(&hddIID); + + if (defOk) + ret = virStorageVolDefFormat(&pool, &def); - cleanup: - virStorageVolDefFree(def); return ret; } -static int vboxStorageVolDelete(virStorageVolPtr vol, - unsigned int flags) -{ - VBOX_OBJECT_CHECK(vol->conn, int, -1); - vboxIID hddIID = VBOX_IID_INITIALIZER; - unsigned char uuid[VIR_UUID_BUFLEN]; +static char *vboxStorageVolGetPath(virStorageVolPtr vol) { + VBOX_OBJECT_CHECK(vol->conn, char *, NULL); IHardDisk *hardDisk = NULL; - int deregister = 0; + unsigned char uuid[VIR_UUID_BUFLEN]; + vboxIID hddIID = VBOX_IID_INITIALIZER; nsresult rc; - size_t i = 0; - size_t j = 0; - - virCheckFlags(0, -1); if (virUUIDParse(vol->key, uuid) < 0) { virReportError(VIR_ERR_INVALID_ARG, _("Could not parse UUID from '%s'"), vol->key); - return -1; + return ret; } vboxIIDFromUUID(&hddIID, uuid); @@ -10078,1123 +9451,1437 @@ static int vboxStorageVolDelete(virStorageVolPtr vol, VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); if (hddstate != MediaState_Inaccessible) { - PRUint32 machineIdsSize = 0; - vboxArray machineIds = VBOX_ARRAY_INITIALIZER; + PRUnichar *hddLocationUtf16 = NULL; + char *hddLocationUtf8 = NULL; -#if VBOX_API_VERSION < 3001000 - vboxArrayGet(&machineIds, hardDisk, hardDisk->vtbl->imedium.GetMachineIds); -#else /* VBOX_API_VERSION >= 3001000 */ - vboxArrayGet(&machineIds, hardDisk, hardDisk->vtbl->GetMachineIds); -#endif /* VBOX_API_VERSION >= 3001000 */ + VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetLocation, &hddLocationUtf16); -#if VBOX_API_VERSION == 2002000 && defined WIN32 - /* VirtualBox 2.2 on Windows represents IIDs as GUIDs and the - * machineIds array contains direct instances of the GUID struct - * instead of pointers to the actual struct instances. But there - * is no 128bit width simple item type for a SafeArray to fit a - * GUID in. The largest simple type it 64bit width and VirtualBox - * uses two of this 64bit items to represents one GUID. Therefore, - * we divide the size of the SafeArray by two, to compensate for - * this workaround in VirtualBox */ - machineIds.count /= 2; -#endif /* VBOX_API_VERSION >= 2002000 */ + VBOX_UTF16_TO_UTF8(hddLocationUtf16, &hddLocationUtf8); + if (hddLocationUtf8) { - machineIdsSize = machineIds.count; + ignore_value(VIR_STRDUP(ret, hddLocationUtf8)); - for (i = 0; i < machineIds.count; i++) { - IMachine *machine = NULL; - vboxIID machineId = VBOX_IID_INITIALIZER; + VIR_DEBUG("Storage Volume Name: %s", vol->name); + VIR_DEBUG("Storage Volume Path: %s", hddLocationUtf8); + VIR_DEBUG("Storage Volume Pool: %s", vol->pool); - vboxIIDFromArrayItem(&machineId, &machineIds, i); + VBOX_UTF8_FREE(hddLocationUtf8); + } -#if VBOX_API_VERSION >= 4000000 - rc = VBOX_OBJECT_GET_MACHINE(machineId.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching uuid")); - break; - } -#endif + VBOX_UTF16_FREE(hddLocationUtf16); + } - rc = VBOX_SESSION_OPEN(machineId.value, machine); + VBOX_MEDIUM_RELEASE(hardDisk); + } - if (NS_SUCCEEDED(rc)) { + vboxIIDUnalloc(&hddIID); - rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); - if (NS_SUCCEEDED(rc)) { - vboxArray hddAttachments = VBOX_ARRAY_INITIALIZER; + return ret; +} -#if VBOX_API_VERSION < 3001000 - vboxArrayGet(&hddAttachments, machine, - machine->vtbl->GetHardDiskAttachments); -#else /* VBOX_API_VERSION >= 3001000 */ - vboxArrayGet(&hddAttachments, machine, - machine->vtbl->GetMediumAttachments); -#endif /* VBOX_API_VERSION >= 3001000 */ - for (j = 0; j < hddAttachments.count; j++) { - IHardDiskAttachment *hddAttachment = hddAttachments.items[j]; +#if VBOX_API_VERSION >= 4000000 +static char * +vboxDomainScreenshot(virDomainPtr dom, + virStreamPtr st, + unsigned int screen, + unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, char *, NULL); + IConsole *console = NULL; + vboxIID iid = VBOX_IID_INITIALIZER; + IMachine *machine = NULL; + nsresult rc; + char *tmp; + int tmp_fd = -1; + unsigned int max_screen; + + virCheckFlags(0, NULL); + + 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")); + return NULL; + } + + rc = machine->vtbl->GetMonitorCount(machine, &max_screen); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("unable to get monitor count")); + VBOX_RELEASE(machine); + return NULL; + } - if (hddAttachment) { - IHardDisk *hdd = NULL; + if (screen >= max_screen) { + virReportError(VIR_ERR_INVALID_ARG, + _("screen ID higher than monitor " + "count (%d)"), max_screen); + VBOX_RELEASE(machine); + return NULL; + } -#if VBOX_API_VERSION < 3001000 - rc = hddAttachment->vtbl->GetHardDisk(hddAttachment, &hdd); -#else /* VBOX_API_VERSION >= 3001000 */ - rc = hddAttachment->vtbl->GetMedium(hddAttachment, &hdd); -#endif /* VBOX_API_VERSION >= 3001000 */ - if (NS_SUCCEEDED(rc) && hdd) { - vboxIID iid = VBOX_IID_INITIALIZER; + if (virAsprintf(&tmp, "%s/cache/libvirt/vbox.screendump.XXXXXX", LOCALSTATEDIR) < 0) { + VBOX_RELEASE(machine); + return NULL; + } - rc = VBOX_MEDIUM_FUNC_ARG1(hdd, GetId, &iid.value); - if (NS_SUCCEEDED(rc)) { + if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) { + virReportSystemError(errno, _("mkostemp(\"%s\") failed"), tmp); + VIR_FREE(tmp); + VBOX_RELEASE(machine); + return NULL; + } - DEBUGIID("HardDisk (to delete) UUID", hddIID.value); - DEBUGIID("HardDisk (currently processing) UUID", iid.value); - if (vboxIIDIsEqual(&hddIID, &iid)) { - PRUnichar *controller = NULL; - PRInt32 port = 0; - PRInt32 device = 0; + 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) { + IDisplay *display = NULL; - DEBUGIID("Found HardDisk to delete, UUID", hddIID.value); + console->vtbl->GetDisplay(console, &display); - hddAttachment->vtbl->GetController(hddAttachment, &controller); - hddAttachment->vtbl->GetPort(hddAttachment, &port); - hddAttachment->vtbl->GetDevice(hddAttachment, &device); + if (display) { + PRUint32 width, height, bitsPerPixel; + PRUint32 screenDataSize; + PRUint8 *screenData; +# if VBOX_API_VERSION >= 4003000 + PRInt32 xOrigin, yOrigin; +# endif -#if VBOX_API_VERSION < 3001000 - rc = machine->vtbl->DetachHardDisk(machine, controller, port, device); -#else /* VBOX_API_VERSION >= 3001000 */ - rc = machine->vtbl->DetachDevice(machine, controller, port, device); -#endif /* VBOX_API_VERSION >= 3001000 */ - if (NS_SUCCEEDED(rc)) { - rc = machine->vtbl->SaveSettings(machine); - VIR_DEBUG("saving machine settings"); - } + rc = display->vtbl->GetScreenResolution(display, screen, + &width, &height, +# if VBOX_API_VERSION < 4003000 + &bitsPerPixel); +# else + &bitsPerPixel, + &xOrigin, &yOrigin); +# endif - if (NS_SUCCEEDED(rc)) { - deregister++; - VIR_DEBUG("deregistering hdd:%d", deregister); - } + if (NS_FAILED(rc) || !width || !height) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("unable to get screen resolution")); + goto endjob; + } - VBOX_UTF16_FREE(controller); - } - vboxIIDUnalloc(&iid); - } - VBOX_MEDIUM_RELEASE(hdd); - } - } - } - vboxArrayRelease(&hddAttachments); - VBOX_RELEASE(machine); - } - VBOX_SESSION_CLOSE(); + rc = display->vtbl->TakeScreenShotPNGToArray(display, screen, + width, height, + &screenDataSize, + &screenData); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("failed to take screenshot")); + goto endjob; } - vboxIIDUnalloc(&machineId); - } + if (safewrite(tmp_fd, (char *) screenData, + screenDataSize) < 0) { + virReportSystemError(errno, _("unable to write data " + "to '%s'"), tmp); + goto endjob; + } - vboxArrayUnalloc(&machineIds); + if (VIR_CLOSE(tmp_fd) < 0) { + virReportSystemError(errno, _("unable to close %s"), tmp); + goto endjob; + } - if (machineIdsSize == 0 || machineIdsSize == deregister) { - IProgress *progress = NULL; - rc = hardDisk->vtbl->DeleteStorage(hardDisk, &progress); + if (VIR_STRDUP(ret, "image/png") < 0) + goto endjob; - if (NS_SUCCEEDED(rc) && progress) { - progress->vtbl->WaitForCompletion(progress, -1); - VBOX_RELEASE(progress); - DEBUGIID("HardDisk deleted, UUID", hddIID.value); - ret = 0; + if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("unable to open stream")); + VIR_FREE(ret); } + endjob: + VIR_FREE(screenData); + VBOX_RELEASE(display); } + VBOX_RELEASE(console); } - - VBOX_MEDIUM_RELEASE(hardDisk); + VBOX_SESSION_CLOSE(); } - vboxIIDUnalloc(&hddIID); - + VIR_FORCE_CLOSE(tmp_fd); + unlink(tmp); + VIR_FREE(tmp); + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); return ret; } +#endif /* VBOX_API_VERSION >= 4000000 */ + +#define MATCH(FLAG) (flags & (FLAG)) static int -vboxStorageVolGetInfo(virStorageVolPtr vol, virStorageVolInfoPtr info) +vboxConnectListAllDomains(virConnectPtr conn, + virDomainPtr **domains, + unsigned int flags) { - VBOX_OBJECT_CHECK(vol->conn, int, -1); - IHardDisk *hardDisk = NULL; + VBOX_OBJECT_CHECK(conn, int, -1); + vboxArray machines = VBOX_ARRAY_INITIALIZER; + char *machineNameUtf8 = NULL; + PRUnichar *machineNameUtf16 = NULL; unsigned char uuid[VIR_UUID_BUFLEN]; - vboxIID hddIID = VBOX_IID_INITIALIZER; + vboxIID iid = VBOX_IID_INITIALIZER; + PRUint32 state; nsresult rc; + size_t i; + virDomainPtr dom; + virDomainPtr *doms = NULL; + int count = 0; + bool active; + PRUint32 snapshotCount; - if (!info) - return ret; + virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); - if (virUUIDParse(vol->key, uuid) < 0) { - virReportError(VIR_ERR_INVALID_ARG, - _("Could not parse UUID from '%s'"), vol->key); - return ret; + /* filter out flag options that will produce 0 results in vbox driver: + * - managed save: vbox guests don't have managed save images + * - autostart: vbox doesn't support autostarting guests + * - persistance: vbox doesn't support transient guests + */ + if ((MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) && + !MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT)) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) && + !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART)) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && + !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE))) { + if (domains && + VIR_ALLOC_N(*domains, 1) < 0) + goto cleanup; + + ret = 0; + goto cleanup; } - vboxIIDFromUUID(&hddIID, uuid); -#if VBOX_API_VERSION < 4000000 - rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk); -#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 - rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value, - DeviceType_HardDisk, &hardDisk); -#else - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value, - DeviceType_HardDisk, AccessMode_ReadWrite, - PR_FALSE, &hardDisk); -#endif /* VBOX_API_VERSION >= 4000000 */ - if (NS_SUCCEEDED(rc)) { - PRUint32 hddstate; + 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; + } + + if (domains && + VIR_ALLOC_N(doms, machines.count + 1) < 0) + goto cleanup; + + 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) + active = true; + else + active = false; + + /* filter by active state */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) && + !((MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE) && active) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE) && !active))) + continue; + + /* filter by snapshot existence */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_SNAPSHOT)) { + rc = machine->vtbl->GetSnapshotCount(machine, &snapshotCount); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get snapshot count for listed domains")); + goto cleanup; + } + if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) && + snapshotCount > 0) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) && + snapshotCount == 0))) + continue; + } + + /* filter by machine state */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE) && + !((MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) && + state == MachineState_Running) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) && + state == MachineState_Paused) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) && + state == MachineState_PoweredOff) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) && + (state != MachineState_Running && + state != MachineState_Paused && + state != MachineState_PoweredOff)))) + continue; - VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); - if (hddstate != MediaState_Inaccessible) { -#if VBOX_API_VERSION < 4000000 - PRUint64 hddLogicalSize; - PRUint64 hddActualSize; -#else /* VBOX_API_VERSION >= 4000000 */ - PRInt64 hddLogicalSize; - PRInt64 hddActualSize; -#endif /* VBOX_API_VERSION >= 4000000 */ + /* just count the machines */ + if (!doms) { + count++; + continue; + } - info->type = VIR_STORAGE_VOL_FILE; + machine->vtbl->GetName(machine, &machineNameUtf16); + VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8); + machine->vtbl->GetId(machine, &iid.value); + vboxIIDToUUID(&iid, uuid); + vboxIIDUnalloc(&iid); - hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize); -#if VBOX_API_VERSION < 4000000 - info->capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */ -#else /* VBOX_API_VERSION >= 4000000 */ - info->capacity = hddLogicalSize; -#endif /* VBOX_API_VERSION >= 4000000 */ + dom = virGetDomain(conn, machineNameUtf8, uuid); - VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetSize, &hddActualSize); - info->allocation = hddActualSize; + VBOX_UTF8_FREE(machineNameUtf8); + VBOX_UTF16_FREE(machineNameUtf16); - ret = 0; + if (!dom) + goto cleanup; - VIR_DEBUG("Storage Volume Name: %s", vol->name); - VIR_DEBUG("Storage Volume Type: %s", info->type == VIR_STORAGE_VOL_BLOCK ? "Block" : "File"); - VIR_DEBUG("Storage Volume Capacity: %llu", info->capacity); - VIR_DEBUG("Storage Volume Allocation: %llu", info->allocation); + if (active) + dom->id = i + 1; + + doms[count++] = dom; + } } + } - VBOX_MEDIUM_RELEASE(hardDisk); + if (doms) { + /* safe to ignore, new size will be equal or less than + * previous allocation*/ + ignore_value(VIR_REALLOC_N(doms, count + 1)); + *domains = doms; + doms = NULL; } - vboxIIDUnalloc(&hddIID); + ret = count; + + cleanup: + if (doms) { + for (i = 0; i < count; i++) { + if (doms[i]) + virDomainFree(doms[i]); + } + } + VIR_FREE(doms); + vboxArrayRelease(&machines); return ret; } +#undef MATCH -static char *vboxStorageVolGetXMLDesc(virStorageVolPtr vol, unsigned int flags) -{ - VBOX_OBJECT_CHECK(vol->conn, char *, NULL); - IHardDisk *hardDisk = NULL; - unsigned char uuid[VIR_UUID_BUFLEN]; - vboxIID hddIID = VBOX_IID_INITIALIZER; - virStoragePoolDef pool; - virStorageVolDef def; - int defOk = 0; - nsresult rc; - - virCheckFlags(0, NULL); - memset(&pool, 0, sizeof(pool)); - memset(&def, 0, sizeof(def)); +static int +vboxNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, + virNodeInfoPtr nodeinfo) +{ + return nodeGetInfo(nodeinfo); +} - if (virUUIDParse(vol->key, uuid) < 0) { - virReportError(VIR_ERR_INVALID_ARG, - _("Could not parse UUID from '%s'"), vol->key); - return ret; - } - vboxIIDFromUUID(&hddIID, uuid); -#if VBOX_API_VERSION < 4000000 - rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk); -#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 - rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value, - DeviceType_HardDisk, &hardDisk); -#else - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value, - DeviceType_HardDisk, AccessMode_ReadWrite, - PR_FALSE, &hardDisk); -#endif /* VBOX_API_VERSION >= 4000000 */ - if (NS_SUCCEEDED(rc)) { - PRUint32 hddstate; +static int +vboxNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, + unsigned long long *freeMems, + int startCell, + int maxCells) +{ + return nodeGetCellsFreeMemory(freeMems, startCell, maxCells); +} - VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); - if (NS_SUCCEEDED(rc) && hddstate != MediaState_Inaccessible) { - PRUnichar *hddFormatUtf16 = NULL; -#if VBOX_API_VERSION < 4000000 - PRUint64 hddLogicalSize; - PRUint64 hddActualSize; -#else /* VBOX_API_VERSION >= 4000000 */ - PRInt64 hddLogicalSize; - PRInt64 hddActualSize; -#endif /* VBOX_API_VERSION >= 4000000 */ - /* since there is currently one default pool now - * and virStorageVolDefFormat() just checks it type - * so just assign it for now, change the behaviour - * when vbox supports pools. - */ - pool.type = VIR_STORAGE_POOL_DIR; - def.type = VIR_STORAGE_VOL_FILE; - defOk = 1; +static unsigned long long +vboxNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) +{ + unsigned long long freeMem; + if (nodeGetMemory(NULL, &freeMem) < 0) + return 0; + return freeMem; +} - rc = hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize); - if (NS_SUCCEEDED(rc) && defOk) { -#if VBOX_API_VERSION < 4000000 - def.target.capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */ -#else /* VBOX_API_VERSION >= 4000000 */ - def.target.capacity = hddLogicalSize; -#endif /* VBOX_API_VERSION >= 4000000 */ - } else - defOk = 0; - rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetSize, &hddActualSize); - if (NS_SUCCEEDED(rc) && defOk) - def.target.allocation = hddActualSize; - else - defOk = 0; +static int +vboxNodeGetFreePages(virConnectPtr conn ATTRIBUTE_UNUSED, + unsigned int npages, + unsigned int *pages, + int startCell, + unsigned int cellCount, + unsigned long long *counts, + unsigned int flags) +{ + virCheckFlags(0, -1); - if (VIR_STRDUP(def.name, vol->name) < 0) - defOk = 0; + return nodeGetFreePages(npages, pages, startCell, cellCount, counts); +} - if (VIR_STRDUP(def.key, vol->key) < 0) - defOk = 0; +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; +} - rc = hardDisk->vtbl->GetFormat(hardDisk, &hddFormatUtf16); - if (NS_SUCCEEDED(rc) && defOk) { - char *hddFormatUtf8 = NULL; +static int +_initializeDomainEvent(vboxGlobalData *data ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 + /* No event queue functionality in 2.2.* and 4.* as of now */ + vboxUnsupported(); +#else /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */ + /* Initialize the fWatch needed for Event Callbacks */ + data->fdWatch = -1; + data->pFuncs->pfnGetEventQueue(&data->vboxQueue); + if (data->vboxQueue == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("nsIEventQueue object is null")); + return -1; + } +#endif /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */ + return 0; +} - VBOX_UTF16_TO_UTF8(hddFormatUtf16, &hddFormatUtf8); - if (hddFormatUtf8) { +static +void _registerGlobalData(vboxGlobalData *data ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION == 2002000 + vboxUnsupported(); +#else /* VBOX_API_VERSION != 2002000 */ + g_pVBoxGlobalData = data; +#endif /* VBOX_API_VERSION != 2002000 */ +} - VIR_DEBUG("Storage Volume Format: %s", hddFormatUtf8); +#if VBOX_API_VERSION < 4000000 - if (STRCASEEQ("vmdk", hddFormatUtf8)) - def.target.format = VIR_STORAGE_FILE_VMDK; - else if (STRCASEEQ("vhd", hddFormatUtf8)) - def.target.format = VIR_STORAGE_FILE_VPC; - else if (STRCASEEQ("vdi", hddFormatUtf8)) - def.target.format = VIR_STORAGE_FILE_VDI; - else - def.target.format = VIR_STORAGE_FILE_RAW; +# 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; - VBOX_UTF8_FREE(hddFormatUtf8); - } + vboxArrayGet(&storageControllers, machine, + machine->vtbl->GetStorageControllers); - VBOX_UTF16_FREE(hddFormatUtf16); - } else { - defOk = 0; - } - } + for (i = 0; i < storageControllers.count; i++) { + IStorageController *strCtl = storageControllers.items[i]; + PRUnichar *strCtlName = NULL; + vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER; - VBOX_MEDIUM_RELEASE(hardDisk); - } + if (!strCtl) + continue; - vboxIIDUnalloc(&hddIID); + strCtl->vtbl->GetName(strCtl, &strCtlName); + vboxArrayGetWithPtrArg(&mediumAttachments, machine, + machine->vtbl->GetMediumAttachmentsOfController, + strCtlName); - if (defOk) - ret = virStorageVolDefFormat(&pool, &def); + for (j = 0; j < mediumAttachments.count; j++) { + IMediumAttachment *medAtt = mediumAttachments.items[j]; + PRInt32 port = ~0U; + PRInt32 device = ~0U; - return ret; -} + if (!medAtt) + continue; -static char *vboxStorageVolGetPath(virStorageVolPtr vol) { - VBOX_OBJECT_CHECK(vol->conn, char *, NULL); - IHardDisk *hardDisk = NULL; - unsigned char uuid[VIR_UUID_BUFLEN]; - vboxIID hddIID = VBOX_IID_INITIALIZER; - nsresult rc; + medAtt->vtbl->GetPort(medAtt, &port); + medAtt->vtbl->GetDevice(medAtt, &device); - if (virUUIDParse(vol->key, uuid) < 0) { - virReportError(VIR_ERR_INVALID_ARG, - _("Could not parse UUID from '%s'"), vol->key); - return ret; - } + 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 */ - vboxIIDFromUUID(&hddIID, uuid); -#if VBOX_API_VERSION < 4000000 - rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk); -#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 - rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value, - DeviceType_HardDisk, &hardDisk); -#else - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value, - DeviceType_HardDisk, AccessMode_ReadWrite, - PR_FALSE, &hardDisk); -#endif /* VBOX_API_VERSION >= 4000000 */ - if (NS_SUCCEEDED(rc)) { - PRUint32 hddstate; +static nsresult +_unregisterMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine) +{ + return data->vboxObj->vtbl->UnregisterMachine(data->vboxObj, IID_MEMBER(value), machine); +} - VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); - if (hddstate != MediaState_Inaccessible) { - PRUnichar *hddLocationUtf16 = NULL; - char *hddLocationUtf8 = NULL; +static void +_deleteConfig(IMachine *machine) +{ + machine->vtbl->DeleteSettings(machine); +} - VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetLocation, &hddLocationUtf16); +#else /* VBOX_API_VERSION >= 4000000 */ - VBOX_UTF16_TO_UTF8(hddLocationUtf16, &hddLocationUtf8); - if (hddLocationUtf8) { +static void +_detachDevices(vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine ATTRIBUTE_UNUSED, + PRUnichar *hddcnameUtf16 ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); +} - ignore_value(VIR_STRDUP(ret, hddLocationUtf8)); +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; + } - VIR_DEBUG("Storage Volume Name: %s", vol->name); - VIR_DEBUG("Storage Volume Path: %s", hddLocationUtf8); - VIR_DEBUG("Storage Volume Pool: %s", vol->pool); + /* 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; +} - VBOX_UTF8_FREE(hddLocationUtf8); - } +static void +_deleteConfig(IMachine *machine) +{ + IProgress *progress = NULL; - VBOX_UTF16_FREE(hddLocationUtf16); - } + /* 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); - VBOX_MEDIUM_RELEASE(hardDisk); +# 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); } +} - vboxIIDUnalloc(&hddIID); +#endif /* VBOX_API_VERSION >= 4000000 */ - return ret; +static void _pfnUninitialize(vboxGlobalData *data) +{ + if (data->pFuncs) + data->pFuncs->pfnComUninitialize(); } -#if VBOX_API_VERSION >= 4000000 -static char * -vboxDomainScreenshot(virDomainPtr dom, - virStreamPtr st, - unsigned int screen, - unsigned int flags) +static void _pfnComUnallocMem(PCVBOXXPCOM pFuncs, void *pv) { - VBOX_OBJECT_CHECK(dom->conn, char *, NULL); - IConsole *console = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - nsresult rc; - char *tmp; - int tmp_fd = -1; - unsigned int max_screen; + pFuncs->pfnComUnallocMem(pv); +} - virCheckFlags(0, NULL); +static void _pfnUtf16Free(PCVBOXXPCOM pFuncs, PRUnichar *pwszString) +{ + pFuncs->pfnUtf16Free(pwszString); +} - 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")); - return NULL; - } +static void _pfnUtf8Free(PCVBOXXPCOM pFuncs, char *pszString) +{ + pFuncs->pfnUtf8Free(pszString); +} - rc = machine->vtbl->GetMonitorCount(machine, &max_screen); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("unable to get monitor count")); - VBOX_RELEASE(machine); - return NULL; - } +static int _pfnUtf16ToUtf8(PCVBOXXPCOM pFuncs, const PRUnichar *pwszString, char **ppszString) +{ + return pFuncs->pfnUtf16ToUtf8(pwszString, ppszString); +} - if (screen >= max_screen) { - virReportError(VIR_ERR_INVALID_ARG, - _("screen ID higher than monitor " - "count (%d)"), max_screen); - VBOX_RELEASE(machine); - return NULL; - } +static int _pfnUtf8ToUtf16(PCVBOXXPCOM pFuncs, const char *pszString, PRUnichar **ppwszString) +{ + return pFuncs->pfnUtf8ToUtf16(pszString, ppwszString); +} - if (virAsprintf(&tmp, "%s/cache/libvirt/vbox.screendump.XXXXXX", LOCALSTATEDIR) < 0) { - VBOX_RELEASE(machine); - return NULL; - } +#if VBOX_API_VERSION == 2002000 - if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) { - virReportSystemError(errno, _("mkostemp(\"%s\") failed"), tmp); - VIR_FREE(tmp); - VBOX_RELEASE(machine); - return NULL; - } +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 */ +} - 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) { - IDisplay *display = NULL; +#else /* VBOX_API_VERSION != 2002000 */ - console->vtbl->GetDisplay(console, &display); +static void _vboxIIDInitialize(vboxIIDUnion *iidu) +{ + memset(iidu, 0, sizeof(vboxIIDUnion)); + IID_MEMBER(owner) = true; +} - if (display) { - PRUint32 width, height, bitsPerPixel; - PRUint32 screenDataSize; - PRUint8 *screenData; -# if VBOX_API_VERSION >= 4003000 - PRInt32 xOrigin, yOrigin; -# endif +static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu) +{ + DEBUGPRUnichar(msg, IID_MEMBER(value)); +} - rc = display->vtbl->GetScreenResolution(display, screen, - &width, &height, -# if VBOX_API_VERSION < 4003000 - &bitsPerPixel); -# else - &bitsPerPixel, - &xOrigin, &yOrigin); -# endif +#endif /* VBOX_API_VERSION != 2002000 */ - if (NS_FAILED(rc) || !width || !height) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("unable to get screen resolution")); - goto endjob; - } +static void* _handleGetMachines(IVirtualBox *vboxObj) +{ + return vboxObj->vtbl->GetMachines; +} - rc = display->vtbl->TakeScreenShotPNGToArray(display, screen, - width, height, - &screenDataSize, - &screenData); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("failed to take screenshot")); - goto endjob; - } +static nsresult _nsisupportsRelease(nsISupports *nsi) +{ + return nsi->vtbl->Release(nsi); +} - if (safewrite(tmp_fd, (char *) screenData, - screenDataSize) < 0) { - virReportSystemError(errno, _("unable to write data " - "to '%s'"), tmp); - goto endjob; - } +static nsresult +_virtualboxGetVersion(IVirtualBox *vboxObj, PRUnichar **versionUtf16) +{ + return vboxObj->vtbl->GetVersion(vboxObj, versionUtf16); +} - if (VIR_CLOSE(tmp_fd) < 0) { - virReportSystemError(errno, _("unable to close %s"), tmp); - goto endjob; - } +#if VBOX_API_VERSION < 4000000 - if (VIR_STRDUP(ret, "image/png") < 0) - goto endjob; +static nsresult +_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine) +{ + return vboxObj->vtbl->GetMachine(vboxObj, IID_MEMBER(value), machine); +} - if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("unable to open stream")); - VIR_FREE(ret); - } - endjob: - VIR_FREE(screenData); - VBOX_RELEASE(display); - } - VBOX_RELEASE(console); - } - VBOX_SESSION_CLOSE(); - } +#else /* VBOX_API_VERSION >= 4000000 */ - VIR_FORCE_CLOSE(tmp_fd); - unlink(tmp); - VIR_FREE(tmp); - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; +static nsresult +_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine) +{ + return vboxObj->vtbl->FindMachine(vboxObj, IID_MEMBER(value), machine); } + #endif /* VBOX_API_VERSION >= 4000000 */ +static nsresult +_virtualboxGetSystemProperties(IVirtualBox *vboxObj, ISystemProperties **systemProperties) +{ + return vboxObj->vtbl->GetSystemProperties(vboxObj, systemProperties); +} -#define MATCH(FLAG) (flags & (FLAG)) -static int -vboxConnectListAllDomains(virConnectPtr conn, - virDomainPtr **domains, - unsigned int flags) +static nsresult +_virtualboxCreateMachine(vboxGlobalData *data, virDomainDefPtr def, IMachine **machine, char *uuidstr ATTRIBUTE_UNUSED) { - VBOX_OBJECT_CHECK(conn, int, -1); - vboxArray machines = VBOX_ARRAY_INITIALIZER; - char *machineNameUtf8 = NULL; - PRUnichar *machineNameUtf16 = NULL; - unsigned char uuid[VIR_UUID_BUFLEN]; vboxIID iid = VBOX_IID_INITIALIZER; - PRUint32 state; + PRUnichar *machineNameUtf16 = NULL; nsresult rc; - size_t i; - virDomainPtr dom; - virDomainPtr *doms = NULL; - int count = 0; - bool active; - PRUint32 snapshotCount; - - virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); - - /* filter out flag options that will produce 0 results in vbox driver: - * - managed save: vbox guests don't have managed save images - * - autostart: vbox doesn't support autostarting guests - * - persistance: vbox doesn't support transient guests - */ - if ((MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) && - !MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT)) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) && - !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART)) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && - !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE))) { - if (domains && - VIR_ALLOC_N(*domains, 1) < 0) - goto cleanup; - - ret = 0; - 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 domains, rc=%08x"), (unsigned)rc); - goto cleanup; + 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; +} - if (domains && - VIR_ALLOC_N(doms, machines.count + 1) < 0) - goto cleanup; - - 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); +static nsresult +_virtualboxRegisterMachine(IVirtualBox *vboxObj, IMachine *machine) +{ + return vboxObj->vtbl->RegisterMachine(vboxObj, machine); +} - if (state >= MachineState_FirstOnline && - state <= MachineState_LastOnline) - active = true; - else - active = false; +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 + vboxUnsupported(); + return 0; +#endif +} - /* filter by active state */ - if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) && - !((MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE) && active) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE) && !active))) - continue; +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 + vboxUnsupported(); + return 0; +#endif +} - /* filter by snapshot existence */ - if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_SNAPSHOT)) { - rc = machine->vtbl->GetSnapshotCount(machine, &snapshotCount); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get snapshot count for listed domains")); - goto cleanup; - } - if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) && - snapshotCount > 0) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) && - snapshotCount == 0))) - continue; - } +static nsresult +_machineAddStorageController(IMachine *machine, PRUnichar *name, + PRUint32 connectionType, + IStorageController **controller) +{ + return machine->vtbl->AddStorageController(machine, name, connectionType, + controller); +} - /* filter by machine state */ - if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE) && - !((MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) && - state == MachineState_Running) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) && - state == MachineState_Paused) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) && - state == MachineState_PoweredOff) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) && - (state != MachineState_Running && - state != MachineState_Paused && - state != MachineState_PoweredOff)))) - continue; +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 */ + vboxUnsupported(); + return 0; +#endif /* VBOX_API_VERSION < 4000000 */ +} - /* just count the machines */ - if (!doms) { - count++; - continue; - } +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 */ +} - machine->vtbl->GetName(machine, &machineNameUtf16); - VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8); - machine->vtbl->GetId(machine, &iid.value); - vboxIIDToUUID(&iid, uuid); - vboxIIDUnalloc(&iid); - dom = virGetDomain(conn, machineNameUtf8, uuid); +static nsresult +_machineGetAccessible(IMachine *machine, PRBool *isAccessible) +{ + return machine->vtbl->GetAccessible(machine, isAccessible); +} - VBOX_UTF8_FREE(machineNameUtf8); - VBOX_UTF16_FREE(machineNameUtf16); +static nsresult +_machineGetState(IMachine *machine, PRUint32 *state) +{ + return machine->vtbl->GetState(machine, state); +} - if (!dom) - goto cleanup; +static nsresult +_machineGetName(IMachine *machine, PRUnichar **name) +{ + return machine->vtbl->GetName(machine, name); +} - if (active) - dom->id = i + 1; +static nsresult +_machineGetId(IMachine *machine, vboxIIDUnion *iidu) +{ + return machine->vtbl->GetId(machine, &IID_MEMBER(value)); +} - doms[count++] = dom; - } - } - } +static nsresult +_machineGetBIOSSettings(IMachine *machine, IBIOSSettings **bios) +{ + return machine->vtbl->GetBIOSSettings(machine, bios); +} - if (doms) { - /* safe to ignore, new size will be equal or less than - * previous allocation*/ - ignore_value(VIR_REALLOC_N(doms, count + 1)); - *domains = doms; - doms = NULL; - } +static nsresult +_machineGetAudioAdapter(IMachine *machine, IAudioAdapter **audioadapter) +{ + return machine->vtbl->GetAudioAdapter(machine, audioadapter); +} - ret = count; +static nsresult +_machineGetNetworkAdapter(IMachine *machine, PRUint32 slot, INetworkAdapter **adapter) +{ + return machine->vtbl->GetNetworkAdapter(machine, slot, adapter); +} - cleanup: - if (doms) { - for (i = 0; i < count; i++) { - if (doms[i]) - virDomainFree(doms[i]); - } - } - VIR_FREE(doms); +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 */ + vboxUnsupported(); + return 0; +#endif /* VBOX_API_VERSION < 4001000 */ +} - vboxArrayRelease(&machines); - return ret; +static nsresult +_machineGetSerialPort(IMachine *machine, PRUint32 slot, ISerialPort **port) +{ + return machine->vtbl->GetSerialPort(machine, slot, port); } -#undef MATCH +static nsresult +_machineGetParallelPort(IMachine *machine, PRUint32 slot, IParallelPort **port) +{ + return machine->vtbl->GetParallelPort(machine, slot, port); +} -static int -vboxNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, - virNodeInfoPtr nodeinfo) +static nsresult +_machineGetVRDxServer(IMachine *machine, IVRDxServer **VRDxServer) { - return nodeGetInfo(nodeinfo); +#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 int -vboxNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, - unsigned long long *freeMems, - int startCell, - int maxCells) +static nsresult +_machineSetCPUCount(IMachine *machine, PRUint32 CPUCount) { - return nodeGetCellsFreeMemory(freeMems, startCell, maxCells); + return machine->vtbl->SetCPUCount(machine, CPUCount); } +static nsresult +_machineSetMemorySize(IMachine *machine, PRUint32 memorySize) +{ + return machine->vtbl->SetMemorySize(machine, memorySize); +} -static unsigned long long -vboxNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) +static nsresult +_machineSetCPUProperty(IMachine *machine, PRUint32 property ATTRIBUTE_UNUSED, PRBool value) { - unsigned long long freeMem; - if (nodeGetMemory(NULL, &freeMem) < 0) - return 0; - return freeMem; +#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 int -vboxNodeGetFreePages(virConnectPtr conn ATTRIBUTE_UNUSED, - unsigned int npages, - unsigned int *pages, - int startCell, - unsigned int cellCount, - unsigned long long *counts, - unsigned int flags) +static nsresult +_machineSetVRAMSize(IMachine *machine, PRUint32 VRAMSize) { - virCheckFlags(0, -1); + return machine->vtbl->SetVRAMSize(machine, VRAMSize); +} - return nodeGetFreePages(npages, pages, startCell, cellCount, counts); +static nsresult +_machineSetMonitorCount(IMachine *machine, PRUint32 monitorCount) +{ + return machine->vtbl->SetMonitorCount(machine, monitorCount); } -static int _pfnInitialize(vboxGlobalData *data) +static nsresult +_machineSetAccelerate3DEnabled(IMachine *machine, PRBool accelerate3DEnabled) { - 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; + return machine->vtbl->SetAccelerate3DEnabled(machine, accelerate3DEnabled); } -static int -_initializeDomainEvent(vboxGlobalData *data ATTRIBUTE_UNUSED) +static nsresult +_machineSetAccelerate2DVideoEnabled(IMachine *machine ATTRIBUTE_UNUSED, + PRBool accelerate2DVideoEnabled ATTRIBUTE_UNUSED) { -#if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 - /* No event queue functionality in 2.2.* and 4.* as of now */ +#if VBOX_API_VERSION >= 3001000 + return machine->vtbl->SetAccelerate2DVideoEnabled(machine, accelerate2DVideoEnabled); +#else /* VBOX_API_VERSION < 3001000 */ vboxUnsupported(); -#else /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */ - /* Initialize the fWatch needed for Event Callbacks */ - data->fdWatch = -1; - data->pFuncs->pfnGetEventQueue(&data->vboxQueue); - if (data->vboxQueue == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("nsIEventQueue object is null")); - return -1; - } -#endif /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */ return 0; +#endif /* VBOX_API_VERSION < 3001000 */ } -static -void _registerGlobalData(vboxGlobalData *data ATTRIBUTE_UNUSED) +static nsresult +_machineSetExtraData(IMachine *machine, PRUnichar *key, PRUnichar *value) { -#if VBOX_API_VERSION == 2002000 - vboxUnsupported(); -#else /* VBOX_API_VERSION != 2002000 */ - g_pVBoxGlobalData = data; -#endif /* VBOX_API_VERSION != 2002000 */ + return machine->vtbl->SetExtraData(machine, key, value); +} + +static nsresult +_machineSaveSettings(IMachine *machine) +{ + return machine->vtbl->SaveSettings(machine); } #if VBOX_API_VERSION < 4000000 -# if VBOX_API_VERSION < 3001000 -static void -_detachDevices(vboxGlobalData *data ATTRIBUTE_UNUSED, - IMachine *machine, PRUnichar *hddcnameUtf16) +static nsresult +_sessionOpen(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED) { - /* 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); + return data->vboxObj->vtbl->OpenSession(data->vboxObj, data->vboxSession, IID_MEMBER(value)); } -# else /* VBOX_API_VERSION >= 3001000 */ -static void -_detachDevices(vboxGlobalData *data, IMachine *machine, - PRUnichar *hddcnameUtf16 ATTRIBUTE_UNUSED) + +static nsresult +_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine 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; + return data->vboxObj->vtbl->OpenExistingSession(data->vboxObj, data->vboxSession, IID_MEMBER(value)); +} - vboxArrayGet(&storageControllers, machine, - machine->vtbl->GetStorageControllers); +static nsresult +_sessionClose(ISession *session) +{ + return session->vtbl->Close(session); +} - for (i = 0; i < storageControllers.count; i++) { - IStorageController *strCtl = storageControllers.items[i]; - PRUnichar *strCtlName = NULL; - vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER; +#else /* VBOX_API_VERSION >= 4000000 */ - if (!strCtl) - continue; +static nsresult +_sessionOpen(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine) +{ + return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Write); +} - strCtl->vtbl->GetName(strCtl, &strCtlName); - vboxArrayGetWithPtrArg(&mediumAttachments, machine, - machine->vtbl->GetMediumAttachmentsOfController, - strCtlName); +static nsresult +_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine) +{ + return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Shared); +} - for (j = 0; j < mediumAttachments.count; j++) { - IMediumAttachment *medAtt = mediumAttachments.items[j]; - PRInt32 port = ~0U; - PRInt32 device = ~0U; +static nsresult +_sessionClose(ISession *session) +{ + return session->vtbl->UnlockMachine(session); +} - if (!medAtt) - continue; +#endif /* VBOX_API_VERSION >= 4000000 */ - medAtt->vtbl->GetPort(medAtt, &port); - medAtt->vtbl->GetDevice(medAtt, &device); +static nsresult +_sessionGetConsole(ISession *session, IConsole **console) +{ + return session->vtbl->GetConsole(session, console); +} - 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); +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); +} + +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 +_systemPropertiesGetMaxGuestCPUCount(ISystemProperties *systemProperties, PRUint32 *maxCPUCount) +{ + return systemProperties->vtbl->GetMaxGuestCPUCount(systemProperties, maxCPUCount); } -# endif /* VBOX_API_VERSION >= 3001000 */ static nsresult -_unregisterMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine) +_systemPropertiesGetMaxBootPosition(ISystemProperties *systemProperties, PRUint32 *maxBootPosition) { - return data->vboxObj->vtbl->UnregisterMachine(data->vboxObj, IID_MEMBER(value), machine); + return systemProperties->vtbl->GetMaxBootPosition(systemProperties, maxBootPosition); } -static void -_deleteConfig(IMachine *machine) +static nsresult +_systemPropertiesGetMaxNetworkAdapters(ISystemProperties *systemProperties, PRUint32 chipset ATTRIBUTE_UNUSED, + PRUint32 *maxNetworkAdapters) { - machine->vtbl->DeleteSettings(machine); +#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 */ } -#else /* VBOX_API_VERSION >= 4000000 */ - -static void -_detachDevices(vboxGlobalData *data ATTRIBUTE_UNUSED, - IMachine *machine ATTRIBUTE_UNUSED, - PRUnichar *hddcnameUtf16 ATTRIBUTE_UNUSED) +static nsresult +_systemPropertiesGetSerialPortCount(ISystemProperties *systemProperties, PRUint32 *SerialPortCount) { - vboxUnsupported(); + return systemProperties->vtbl->GetSerialPortCount(systemProperties, SerialPortCount); } static nsresult -_unregisterMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine) +_systemPropertiesGetParallelPortCount(ISystemProperties *systemProperties, PRUint32 *ParallelPortCount) { - 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; - } + return systemProperties->vtbl->GetParallelPortCount(systemProperties, ParallelPortCount); +} - /* 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; +#if VBOX_API_VERSION >= 3001000 +static nsresult +_systemPropertiesGetMaxPortCountForStorageBus(ISystemProperties *systemProperties, PRUint32 bus, + PRUint32 *maxPortCount) +{ + return systemProperties->vtbl->GetMaxPortCountForStorageBus(systemProperties, bus, maxPortCount); } -static void -_deleteConfig(IMachine *machine) +static nsresult +_systemPropertiesGetMaxDevicesPerPortForStorageBus(ISystemProperties *systemProperties, + PRUint32 bus, PRUint32 *maxDevicesPerPort) { - IProgress *progress = NULL; + 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) +{ + vboxUnsupported(); + return 0; +} - /* 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); +static nsresult +_systemPropertiesGetMaxDevicesPerPortForStorageBus(ISystemProperties *systemProperties ATTRIBUTE_UNUSED, + PRUint32 bus ATTRIBUTE_UNUSED, + PRUint32 *maxDevicesPerPort ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); + return 0; +} +#endif -# 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); - } +static nsresult +_biosSettingsSetACPIEnabled(IBIOSSettings *bios, PRBool ACPIEnabled) +{ + return bios->vtbl->SetACPIEnabled(bios, ACPIEnabled); } -#endif /* VBOX_API_VERSION >= 4000000 */ +static nsresult +_biosSettingsSetIOAPICEnabled(IBIOSSettings *bios, PRBool IOAPICEnabled) +{ + return bios->vtbl->SetIOAPICEnabled(bios, IOAPICEnabled); +} -static void _pfnUninitialize(vboxGlobalData *data) +static nsresult +_audioAdapterSetEnabled(IAudioAdapter *audioAdapter, PRBool enabled) { - if (data->pFuncs) - data->pFuncs->pfnComUninitialize(); + return audioAdapter->vtbl->SetEnabled(audioAdapter, enabled); } -static void _pfnComUnallocMem(PCVBOXXPCOM pFuncs, void *pv) +static nsresult +_audioAdapterSetAudioController(IAudioAdapter *audioAdapter, PRUint32 audioController) { - pFuncs->pfnComUnallocMem(pv); + return audioAdapter->vtbl->SetAudioController(audioAdapter, audioController); } -static void _pfnUtf16Free(PCVBOXXPCOM pFuncs, PRUnichar *pwszString) +static nsresult +_networkAdapterSetEnabled(INetworkAdapter *adapter, PRBool enabled) { - pFuncs->pfnUtf16Free(pwszString); + return adapter->vtbl->SetEnabled(adapter, enabled); } -static void _pfnUtf8Free(PCVBOXXPCOM pFuncs, char *pszString) +static nsresult +_networkAdapterSetAdapterType(INetworkAdapter *adapter, PRUint32 adapterType) { - pFuncs->pfnUtf8Free(pszString); + return adapter->vtbl->SetAdapterType(adapter, adapterType); } -static int _pfnUtf16ToUtf8(PCVBOXXPCOM pFuncs, const PRUnichar *pwszString, char **ppszString) +static nsresult +_networkAdapterSetInternalNetwork(INetworkAdapter *adapter, PRUnichar *internalNetwork) { - return pFuncs->pfnUtf16ToUtf8(pwszString, ppszString); + return adapter->vtbl->SetInternalNetwork(adapter, internalNetwork); } -static int _pfnUtf8ToUtf16(PCVBOXXPCOM pFuncs, const char *pszString, PRUnichar **ppwszString) +static nsresult +_networkAdapterSetMACAddress(INetworkAdapter *adapter, PRUnichar *MACAddress) { - return pFuncs->pfnUtf8ToUtf16(pszString, ppwszString); + return adapter->vtbl->SetMACAddress(adapter, MACAddress); } -#if VBOX_API_VERSION == 2002000 +#if VBOX_API_VERSION < 4001000 -static void _vboxIIDInitialize(vboxIIDUnion *iidu) +static nsresult +_networkAdapterSetBridgedInterface(INetworkAdapter *adapter, PRUnichar *hostInterface) { - memset(iidu, 0, sizeof(vboxIIDUnion)); + return adapter->vtbl->SetHostInterface(adapter, hostInterface); } -static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu) +static nsresult +_networkAdapterSetHostOnlyInterface(INetworkAdapter *adapter, PRUnichar *hostOnlyInterface) { -# ifdef WIN32 - DEBUGUUID(msg, (nsID *)&IID_MEMBER(value)); -# else /* !WIN32 */ - DEBUGUUID(msg, IID_MEMBER(value)); -# endif /* !WIN32 */ + return adapter->vtbl->SetHostInterface(adapter, hostOnlyInterface); } -#else /* VBOX_API_VERSION != 2002000 */ - -static void _vboxIIDInitialize(vboxIIDUnion *iidu) +static nsresult +_networkAdapterAttachToBridgedInterface(INetworkAdapter *adapter) { - memset(iidu, 0, sizeof(vboxIIDUnion)); - IID_MEMBER(owner) = true; + return adapter->vtbl->AttachToBridgedInterface(adapter); } -static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu) +static nsresult +_networkAdapterAttachToInternalNetwork(INetworkAdapter *adapter) { - DEBUGPRUnichar(msg, IID_MEMBER(value)); + return adapter->vtbl->AttachToInternalNetwork(adapter); } -#endif /* VBOX_API_VERSION != 2002000 */ +static nsresult +_networkAdapterAttachToHostOnlyInterface(INetworkAdapter *adapter) +{ + return adapter->vtbl->AttachToHostOnlyInterface(adapter); +} -static void* _handleGetMachines(IVirtualBox *vboxObj) +static nsresult +_networkAdapterAttachToNAT(INetworkAdapter *adapter) { - return vboxObj->vtbl->GetMachines; + return adapter->vtbl->AttachToNAT(adapter); } -static nsresult _nsisupportsRelease(nsISupports *nsi) +#else /* VBOX_API_VERSION >= 4001000 */ + +static nsresult +_networkAdapterSetBridgedInterface(INetworkAdapter *adapter, PRUnichar *bridgedInterface) { - return nsi->vtbl->Release(nsi); + return adapter->vtbl->SetBridgedInterface(adapter, bridgedInterface); } static nsresult -_virtualboxGetVersion(IVirtualBox *vboxObj, PRUnichar **versionUtf16) +_networkAdapterSetHostOnlyInterface(INetworkAdapter *adapter, PRUnichar *hostOnlyInterface) { - return vboxObj->vtbl->GetVersion(vboxObj, versionUtf16); + return adapter->vtbl->SetHostOnlyInterface(adapter, hostOnlyInterface); } -#if VBOX_API_VERSION < 4000000 +static nsresult +_networkAdapterAttachToBridgedInterface(INetworkAdapter *adapter) +{ + return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Bridged); +} static nsresult -_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine) +_networkAdapterAttachToInternalNetwork(INetworkAdapter *adapter) { - return vboxObj->vtbl->GetMachine(vboxObj, IID_MEMBER(value), machine); + return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Internal); } -#else /* VBOX_API_VERSION >= 4000000 */ +static nsresult +_networkAdapterAttachToHostOnlyInterface(INetworkAdapter *adapter) +{ + return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_HostOnly); +} static nsresult -_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine) +_networkAdapterAttachToNAT(INetworkAdapter *adapter) { - return vboxObj->vtbl->FindMachine(vboxObj, IID_MEMBER(value), machine); + return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_NAT); } -#endif /* VBOX_API_VERSION >= 4000000 */ +#endif /* VBOX_API_VERSION >= 4001000 */ static nsresult -_virtualboxGetSystemProperties(IVirtualBox *vboxObj, ISystemProperties **systemProperties) +_serialPortSetEnabled(ISerialPort *port, PRBool enabled) { - return vboxObj->vtbl->GetSystemProperties(vboxObj, systemProperties); + return port->vtbl->SetEnabled(port, enabled); } static nsresult -_machineGetAccessible(IMachine *machine, PRBool *isAccessible) +_serialPortSetPath(ISerialPort *port, PRUnichar *path) { - return machine->vtbl->GetAccessible(machine, isAccessible); + return port->vtbl->SetPath(port, path); } static nsresult -_machineGetState(IMachine *machine, PRUint32 *state) +_serialPortSetIRQ(ISerialPort *port, PRUint32 IRQ) { - return machine->vtbl->GetState(machine, state); + return port->vtbl->SetIRQ(port, IRQ); } static nsresult -_machineGetName(IMachine *machine, PRUnichar **name) +_serialPortSetIOBase(ISerialPort *port, PRUint32 IOBase) { - return machine->vtbl->GetName(machine, name); + return port->vtbl->SetIOBase(port, IOBase); } static nsresult -_machineGetId(IMachine *machine, vboxIIDUnion *iidu) +_serialPortSetHostMode(ISerialPort *port, PRUint32 hostMode) { - return machine->vtbl->GetId(machine, &IID_MEMBER(value)); + return port->vtbl->SetHostMode(port, hostMode); } static nsresult -_machineSaveSettings(IMachine *machine) +_parallelPortSetEnabled(IParallelPort *port, PRBool enabled) { - return machine->vtbl->SaveSettings(machine); + return port->vtbl->SetEnabled(port, enabled); } -#if VBOX_API_VERSION < 4000000 - static nsresult -_sessionOpen(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED) +_parallelPortSetPath(IParallelPort *port, PRUnichar *path) { - return data->vboxObj->vtbl->OpenSession(data->vboxObj, data->vboxSession, IID_MEMBER(value)); + return port->vtbl->SetPath(port, path); } static nsresult -_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED) +_parallelPortSetIRQ(IParallelPort *port, PRUint32 IRQ) { - return data->vboxObj->vtbl->OpenExistingSession(data->vboxObj, data->vboxSession, IID_MEMBER(value)); + return port->vtbl->SetIRQ(port, IRQ); } static nsresult -_sessionClose(ISession *session) +_parallelPortSetIOBase(IParallelPort *port, PRUint32 IOBase) { - return session->vtbl->Close(session); + return port->vtbl->SetIOBase(port, IOBase); } -#else /* VBOX_API_VERSION >= 4000000 */ +static nsresult +_vrdxServerSetEnabled(IVRDxServer *VRDxServer, PRBool enabled) +{ + return VRDxServer->vtbl->SetEnabled(VRDxServer, enabled); +} static nsresult -_sessionOpen(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine) +_vrdxServerSetPorts(vboxGlobalData *data ATTRIBUTE_UNUSED, + IVRDxServer *VRDxServer, virDomainGraphicsDefPtr graphics) { - return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Write); + 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 -_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine) +_vrdxServerSetReuseSingleConnection(IVRDxServer *VRDxServer, PRBool enabled) { - return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Shared); + return VRDxServer->vtbl->SetReuseSingleConnection(VRDxServer, enabled); } static nsresult -_sessionClose(ISession *session) +_vrdxServerSetAllowMultiConnection(IVRDxServer *VRDxServer, PRBool enabled) { - return session->vtbl->UnlockMachine(session); + 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 -_sessionGetConsole(ISession *session, IConsole **console) +_usbCommonEnable(IUSBCommon *USBCommon ATTRIBUTE_UNUSED) { - return session->vtbl->GetConsole(session, console); + 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 -_sessionGetMachine(ISession *session, IMachine **machine) +_usbCommonCreateDeviceFilter(IUSBCommon *USBCommon, PRUnichar *name, + IUSBDeviceFilter **filter) { - return session->vtbl->GetMachine(session, machine); + return USBCommon->vtbl->CreateDeviceFilter(USBCommon, name, filter); } static nsresult -_consoleSaveState(IConsole *console, IProgress **progress) +_usbCommonInsertDeviceFilter(IUSBCommon *USBCommon, PRUint32 position, + IUSBDeviceFilter *filter) { - return console->vtbl->SaveState(console, progress); + return USBCommon->vtbl->InsertDeviceFilter(USBCommon, position, filter); } static nsresult -_progressWaitForCompletion(IProgress *progress, PRInt32 timeout) +_usbDeviceFilterSetProductId(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *productId) { - return progress->vtbl->WaitForCompletion(progress, timeout); + return USBDeviceFilter->vtbl->SetProductId(USBDeviceFilter, productId); } static nsresult -_progressGetResultCode(IProgress *progress, resultCodeUnion *resultCode) +_usbDeviceFilterSetActive(IUSBDeviceFilter *USBDeviceFilter, PRBool active) { -#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 */ + return USBDeviceFilter->vtbl->SetActive(USBDeviceFilter, active); } static nsresult -_systemPropertiesGetMaxGuestCPUCount(ISystemProperties *systemProperties, PRUint32 *maxCPUCount) +_usbDeviceFilterSetVendorId(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *vendorId) { - return systemProperties->vtbl->GetMaxGuestCPUCount(systemProperties, maxCPUCount); + return USBDeviceFilter->vtbl->SetVendorId(USBDeviceFilter, vendorId); +} + +static nsresult _mediumGetId(IMedium *medium, vboxIIDUnion *iidu) +{ + return medium->vtbl->GetId(medium, &IID_MEMBER(value)); +} + +static nsresult _mediumRelease(IMedium *medium) +{ + return medium->vtbl->nsisupports.Release((nsISupports *)medium); +} + +static nsresult _mediumSetType(IMedium *medium ATTRIBUTE_UNUSED, + PRUint32 type ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION > 3000000 + return medium->vtbl->SetType(medium, type); +#else + vboxUnsupported(); + return 0; +#endif } static bool _machineStateOnline(PRUint32 state) @@ -11237,13 +10924,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, }; @@ -11266,6 +10977,76 @@ 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 vboxUniformedIMedium _UIMedium = { + .GetId = _mediumGetId, + .Release = _mediumRelease, + .SetType = _mediumSetType, }; static uniformedMachineStateChecker _machineStateChecker = { @@ -11281,6 +11062,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; @@ -11291,6 +11073,15 @@ 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->UIMedium = _UIMedium; pVBoxAPI->machineStateChecker = _machineStateChecker; #if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 @@ -11309,10 +11100,24 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) /* 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 */ } /** diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 01b91fc..439b1ed 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -180,14 +180,43 @@ typedef struct { nsresult (*GetVersion)(IVirtualBox *vboxObj, PRUnichar **versionUtf16); nsresult (*GetMachine)(IVirtualBox *vboxObj, 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; @@ -214,8 +243,93 @@ 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 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; @@ -230,6 +344,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; @@ -240,12 +355,24 @@ typedef struct { vboxUniformedIConsole UIConsole; vboxUniformedIProgress UIProgress; vboxUniformedISystemProperties UISystemProperties; + vboxUniformedIBIOSSettings UIBIOSSettings; + vboxUniformedIAudioAdapter UIAudioAdapter; + vboxUniformedINetworkAdapter UINetworkAdapter; + vboxUniformedISerialPort UISerialPort; + vboxUniformedIParallelPort UIParallelPort; + vboxUniformedIVRDxServer UIVRDxServer; + vboxUniformedIUSBCommon UIUSBCommon; + vboxUniformedIUSBDeviceFilter UIUSBDeviceFilter; + vboxUniformedIMedium UIMedium; uniformedMachineStateChecker machineStateChecker; /* vbox API features */ bool domainEventCallbacks; bool hasStaticGlobalData; bool getMachineForSession; bool detachDevicesExplicitly; + bool chipsetType; + bool accelerate2DVideo; + bool vboxAttachDrivesUseOld; } vboxUniformedAPI; /* libvirt API @@ -269,6 +396,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 f4e992d..16c8f44 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -1936,3 +1936,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 537616d..177dc55 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -3080,238 +3080,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); @@ -10257,6 +10025,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) @@ -10404,6 +10191,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); @@ -10492,6 +10285,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); @@ -10890,6 +10689,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, @@ -10934,6 +10740,7 @@ static vboxUniformedIMachine _UIMachine = { .AddStorageController = _machineAddStorageController, .AttachDevice = _machineAttachDevice, .CreateSharedFolder = _machineCreateSharedFolder, + .LaunchVMProcess = _machineLaunchVMProcess, .GetAccessible = _machineGetAccessible, .GetState = _machineGetState, .GetName = _machineGetName, @@ -10954,6 +10761,7 @@ static vboxUniformedIMachine _UIMachine = { .SetMonitorCount = _machineSetMonitorCount, .SetAccelerate3DEnabled = _machineSetAccelerate3DEnabled, .SetAccelerate2DVideoEnabled = _machineSetAccelerate2DVideoEnabled, + .GetExtraData = _machineGetExtraData, .SetExtraData = _machineSetExtraData, .SaveSettings = _machineSaveSettings, }; @@ -10973,6 +10781,7 @@ static vboxUniformedIConsole _UIConsole = { static vboxUniformedIProgress _UIProgress = { .WaitForCompletion = _progressWaitForCompletion, .GetResultCode = _progressGetResultCode, + .GetCompleted = _progressGetCompleted, }; static vboxUniformedISystemProperties _UISystemProperties = { @@ -11051,6 +10860,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 439b1ed..ff03749 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -196,6 +196,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); @@ -216,6 +220,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; @@ -238,6 +243,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 */ @@ -332,6 +338,7 @@ typedef struct { typedef struct { bool (*Online)(PRUint32 state); + bool (*NotStart)(PRUint32 state); } uniformedMachineStateChecker; typedef struct { @@ -398,6 +405,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 16c8f44..4957655 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2155,3 +2155,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 177dc55..d9d0c3d 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -265,8 +265,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.* */ @@ -3080,11 +3078,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 ff03749..e745bc7 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -406,6 +406,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 4957655..9dc95a4 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2160,3 +2160,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 d9d0c3d..51fb7bd 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -932,34 +932,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 e745bc7..1c11caa 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -407,6 +407,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 9dc95a4..fbb90ac 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -824,6 +824,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 51fb7bd..7bb6896 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -932,77 +932,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 1c11caa..41b2d90 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -403,6 +403,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 fbb90ac..89095f5 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2258,3 +2258,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 7bb6896..2971af2 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -932,73 +932,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 41b2d90..6fc97ed 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -411,6 +411,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 89095f5..d29539d 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2324,3 +2324,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 2971af2..1bec175 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -932,32 +932,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 6fc97ed..72b29e2 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -412,6 +412,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 d29539d..01d0104 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2343,3 +2343,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 1bec175..669a89d 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -932,31 +932,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 72b29e2..1568948 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -413,6 +413,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 01d0104..d796be7 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2362,3 +2362,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 669a89d..df7c290 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -932,58 +932,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); @@ -10045,6 +9993,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); @@ -10472,6 +10426,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, @@ -10552,6 +10511,7 @@ static vboxUniformedISession _UISession = { static vboxUniformedIConsole _UIConsole = { .SaveState = _consoleSaveState, + .Pause = _consolePause, }; static vboxUniformedIProgress _UIProgress = { @@ -10637,6 +10597,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 1568948..8334437 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -237,6 +237,7 @@ typedef struct { /* Functions for IConsole */ typedef struct { nsresult (*SaveState)(IConsole *console, IProgress **progress); + nsresult (*Pause)(IConsole *console); } vboxUniformedIConsole; /* Functions for IProgress */ @@ -339,6 +340,7 @@ typedef struct { typedef struct { bool (*Online)(PRUint32 state); bool (*NotStart)(PRUint32 state); + bool (*Running)(PRUint32 state); } uniformedMachineStateChecker; typedef struct { @@ -414,6 +416,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 d796be7..6b8a9e7 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2409,3 +2409,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 df7c290..95c38d4 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -932,59 +932,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) { @@ -9999,6 +9946,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); @@ -10431,6 +10384,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, @@ -10512,6 +10470,7 @@ static vboxUniformedISession _UISession = { static vboxUniformedIConsole _UIConsole = { .SaveState = _consoleSaveState, .Pause = _consolePause, + .Resume = _consoleResume, }; static vboxUniformedIProgress _UIProgress = { @@ -10598,6 +10557,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 8334437..b370e4f 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -238,6 +238,7 @@ typedef struct { typedef struct { nsresult (*SaveState)(IConsole *console, IProgress **progress); nsresult (*Pause)(IConsole *console); + nsresult (*Resume)(IConsole *console); } vboxUniformedIConsole; /* Functions for IProgress */ @@ -341,6 +342,7 @@ typedef struct { bool (*Online)(PRUint32 state); bool (*NotStart)(PRUint32 state); bool (*Running)(PRUint32 state); + bool (*Paused)(PRUint32 state); } uniformedMachineStateChecker; typedef struct { @@ -417,6 +419,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 6b8a9e7..6371eb2 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2456,3 +2456,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 95c38d4..3a25185 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -932,60 +932,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); @@ -9952,6 +9898,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); @@ -10389,6 +10341,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, @@ -10471,6 +10428,7 @@ static vboxUniformedIConsole _UIConsole = { .SaveState = _consoleSaveState, .Pause = _consolePause, .Resume = _consoleResume, + .PowerButton = _consolePowerButton, }; static vboxUniformedIProgress _UIProgress = { @@ -10558,6 +10516,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 b370e4f..bfd5339 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -239,6 +239,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 */ @@ -343,6 +344,7 @@ typedef struct { bool (*NotStart)(PRUint32 state); bool (*Running)(PRUint32 state); bool (*Paused)(PRUint32 state); + bool (*PoweredOff)(PRUint32 state); } uniformedMachineStateChecker; typedef struct { @@ -420,6 +422,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 6371eb2..b15e8a3 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2504,3 +2504,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 3a25185..4c008c9 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -932,12 +932,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 bfd5339..bf53b27 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -423,6 +423,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 b15e8a3..0527fea 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2509,3 +2509,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 4c008c9..ef734c9 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -932,55 +932,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) @@ -9898,6 +9849,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); @@ -10423,6 +10380,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 bf53b27..d5c6fb4 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -240,6 +240,7 @@ typedef struct { nsresult (*Pause)(IConsole *console); nsresult (*Resume)(IConsole *console); nsresult (*PowerButton)(IConsole *console); + nsresult (*Reset)(IConsole *console); } vboxUniformedIConsole; /* Functions for IProgress */ @@ -424,6 +425,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

--- src/vbox/vbox_common.c | 45 +++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 80 ++++++++++------------------------------- src/vbox/vbox_uniformed_api.h | 2 ++ 3 files changed, 65 insertions(+), 62 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 0527fea..aaebc44 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2553,3 +2553,48 @@ int vboxDomainReboot(virDomainPtr dom, unsigned int flags) vboxIIDUnalloc(&iid); return ret; } + +int vboxDomainDestroyFlags(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.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.PowerDown(console); + VBOX_RELEASE(console); + dom->id = -1; + 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 ef734c9..c3f14be 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -933,68 +933,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, } static int -vboxDomainDestroyFlags(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_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) { - -#if VBOX_API_VERSION == 2002000 - console->vtbl->PowerDown(console); -#else - IProgress *progress = NULL; - console->vtbl->PowerDown(console, &progress); - if (progress) { - progress->vtbl->WaitForCompletion(progress, -1); - VBOX_RELEASE(progress); - } -#endif - VBOX_RELEASE(console); - dom->id = -1; - ret = 0; - } - VBOX_SESSION_CLOSE(); - } - - cleanup: - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - -static int vboxDomainDestroy(virDomainPtr dom) { return vboxDomainDestroyFlags(dom, 0); @@ -9849,6 +9787,23 @@ _consolePowerButton(IConsole *console) } static nsresult +_consolePowerDown(IConsole *console) +{ + nsresult rc; +#if VBOX_API_VERSION == 2002000 + rc = console->vtbl->PowerDown(console); +#else + IProgress *progress = NULL; + rc = console->vtbl->PowerDown(console, &progress); + if (progress) { + rc = progress->vtbl->WaitForCompletion(progress, -1); + VBOX_RELEASE(progress); + } +#endif + return rc; +} + +static nsresult _consoleReset(IConsole *console) { return console->vtbl->Reset(console); @@ -10380,6 +10335,7 @@ static vboxUniformedIConsole _UIConsole = { .Pause = _consolePause, .Resume = _consoleResume, .PowerButton = _consolePowerButton, + .PowerDown = _consolePowerDown, .Reset = _consoleReset, }; diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index d5c6fb4..b9c2068 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -240,6 +240,7 @@ typedef struct { nsresult (*Pause)(IConsole *console); nsresult (*Resume)(IConsole *console); nsresult (*PowerButton)(IConsole *console); + nsresult (*PowerDown)(IConsole *console); nsresult (*Reset)(IConsole *console); } vboxUniformedIConsole; @@ -426,6 +427,7 @@ int vboxDomainResume(virDomainPtr dom); int vboxDomainShutdownFlags(virDomainPtr dom, unsigned int flags); int vboxDomainShutdown(virDomainPtr dom); int vboxDomainReboot(virDomainPtr dom, unsigned int flags); +int vboxDomainDestroyFlags(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 aaebc44..f889384 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2598,3 +2598,8 @@ int vboxDomainDestroyFlags(virDomainPtr dom, unsigned int flags) vboxIIDUnalloc(&iid); return ret; } + +int vboxDomainDestroy(virDomainPtr dom) +{ + return vboxDomainDestroyFlags(dom, 0); +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index c3f14be..3c4cd35 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -932,12 +932,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int -vboxDomainDestroy(virDomainPtr dom) -{ - return vboxDomainDestroyFlags(dom, 0); -} - static char *vboxDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) { /* Returning "hvm" always as suggested on list, cause * this functions seems to be badly named and it diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index b9c2068..935697f 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -428,6 +428,7 @@ int vboxDomainShutdownFlags(virDomainPtr dom, unsigned int flags); int vboxDomainShutdown(virDomainPtr dom); int vboxDomainReboot(virDomainPtr dom, unsigned int flags); int vboxDomainDestroyFlags(virDomainPtr dom, unsigned int flags); +int vboxDomainDestroy(virDomainPtr dom); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 12 ++++++++++++ src/vbox/vbox_tmpl.c | 12 ------------ src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index f889384..102500a 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2603,3 +2603,15 @@ int vboxDomainDestroy(virDomainPtr dom) { return vboxDomainDestroyFlags(dom, 0); } + +char *vboxDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) { + /* Returning "hvm" always as suggested on list, cause + * this functions seems to be badly named and it + * is supposed to pass the ABI name and not the domain + * operating system driver as I had imagined ;) + */ + char *osType; + + ignore_value(VIR_STRDUP(osType, "hvm")); + return osType; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 3c4cd35..58f921a 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -932,18 +932,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static char *vboxDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) { - /* Returning "hvm" always as suggested on list, cause - * this functions seems to be badly named and it - * is supposed to pass the ABI name and not the domain - * operating system driver as I had imagined ;) - */ - char *osType; - - ignore_value(VIR_STRDUP(osType, "hvm")); - return osType; -} - static int vboxDomainSetMemory(virDomainPtr dom, unsigned long memory) { VBOX_OBJECT_CHECK(dom->conn, int, -1); diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 935697f..31a0e45 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -429,6 +429,7 @@ int vboxDomainShutdown(virDomainPtr dom); int vboxDomainReboot(virDomainPtr dom, unsigned int flags); int vboxDomainDestroyFlags(virDomainPtr dom, unsigned int flags); int vboxDomainDestroy(virDomainPtr dom); +char *vboxDomainGetOSType(virDomainPtr dom); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 54 ++++++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 57 ----------------------------------------- src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 55 insertions(+), 57 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 102500a..b457c00 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2615,3 +2615,57 @@ char *vboxDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) { ignore_value(VIR_STRDUP(osType, "hvm")); return osType; } + +int vboxDomainSetMemory(virDomainPtr dom, unsigned long memory) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IMachine *machine = NULL; + vboxIIDUnion iid; + PRUint32 state; + PRBool isAccessible = PR_FALSE; + nsresult rc; + + 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.PoweredOff(state)) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("memory size can't be changed unless domain is powered down")); + goto cleanup; + } + + rc = gVBoxAPI.UISession.Open(data, &iid, machine); + if (NS_FAILED(rc)) + goto cleanup; + + rc = gVBoxAPI.UISession.GetMachine(data->vboxSession, &machine); + if (NS_SUCCEEDED(rc) && machine) { + + rc = gVBoxAPI.UIMachine.SetMemorySize(machine, + VIR_DIV_UP(memory, 1024)); + if (NS_SUCCEEDED(rc)) { + gVBoxAPI.UIMachine.SaveSettings(machine); + ret = 0; + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not set the memory size of the " + "domain to: %lu Kb, rc=%08x"), + memory, (unsigned)rc); + } + } + 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 58f921a..2cb564e 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -932,63 +932,6 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static int vboxDomainSetMemory(virDomainPtr dom, unsigned long memory) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IMachine *machine = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - PRUint32 state = MachineState_Null; - PRBool isAccessible = PR_FALSE; - 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_PoweredOff) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("memory size can't be changed unless domain is powered down")); - goto cleanup; - } - - rc = VBOX_SESSION_OPEN(iid.value, machine); - if (NS_SUCCEEDED(rc)) { - rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); - if (NS_SUCCEEDED(rc) && machine) { - - rc = machine->vtbl->SetMemorySize(machine, - VIR_DIV_UP(memory, 1024)); - if (NS_SUCCEEDED(rc)) { - machine->vtbl->SaveSettings(machine); - ret = 0; - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not set the memory size of the " - "domain to: %lu Kb, rc=%08x"), - memory, (unsigned)rc); - } - } - VBOX_SESSION_CLOSE(); - } - } - - cleanup: - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - static virDomainState vboxConvertState(enum MachineState state) { switch (state) { diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 31a0e45..bc76904 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -430,6 +430,7 @@ int vboxDomainReboot(virDomainPtr dom, unsigned int flags); int vboxDomainDestroyFlags(virDomainPtr dom, unsigned int flags); int vboxDomainDestroy(virDomainPtr dom); char *vboxDomainGetOSType(virDomainPtr dom); +int vboxDomainSetMemory(virDomainPtr dom, unsigned long memory); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 79 ++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 106 ++++++++++------------------------------- src/vbox/vbox_uniformed_api.h | 5 ++ 3 files changed, 108 insertions(+), 82 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index b457c00..d661110 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2669,3 +2669,82 @@ int vboxDomainSetMemory(virDomainPtr dom, unsigned long memory) vboxIIDUnalloc(&iid); return ret; } + +int vboxDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxArray machines = VBOX_ARRAY_INITIALIZER; + char *machineName = NULL; + PRUnichar *machineNameUtf16 = NULL; + nsresult rc; + size_t i = 0; + + 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; + } + + info->nrVirtCpu = 0; + 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, &machineName); + + if (STREQ(dom->name, machineName)) { + /* Get the Machine State (also match it with + * virDomainState). Get the Machine memory and + * for time being set max_balloon and cur_balloon to same + * Also since there is no direct way of checking + * the cputime required (one condition being the + * VM is remote), return zero for cputime. Get the + * number of CPU. + */ + PRUint32 CPUCount = 0; + PRUint32 memorySize = 0; + PRUint32 state; + PRUint32 maxMemorySize = 4 * 1024; + ISystemProperties *systemProperties = NULL; + + gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties); + if (systemProperties) { + gVBoxAPI.UISystemProperties.GetMaxGuestRAM(systemProperties, &maxMemorySize); + VBOX_RELEASE(systemProperties); + systemProperties = NULL; + } + + gVBoxAPI.UIMachine.GetCPUCount(machine, &CPUCount); + gVBoxAPI.UIMachine.GetMemorySize(machine, &memorySize); + gVBoxAPI.UIMachine.GetState(machine, &state); + + info->cpuTime = 0; + info->nrVirtCpu = CPUCount; + info->memory = memorySize * 1024; + info->maxMem = maxMemorySize * 1024; + info->state = gVBoxAPI.vboxConvertState(state); + + ret = 0; + } + + VBOX_UTF8_FREE(machineName); + VBOX_COM_UNALLOC_MEM(machineNameUtf16); + if (info->nrVirtCpu) + break; + + } + + gVBoxAPI.UArray.vboxArrayRelease(&machines); + + cleanup: + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 2cb564e..3ae1864 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -932,7 +932,7 @@ vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16, return result; } -static virDomainState vboxConvertState(enum MachineState state) +static virDomainState _vboxConvertState(PRUint32 state) { switch (state) { case MachineState_Running: @@ -954,86 +954,6 @@ static virDomainState vboxConvertState(enum MachineState state) } } -static int vboxDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxArray machines = VBOX_ARRAY_INITIALIZER; - char *machineName = NULL; - PRUnichar *machineNameUtf16 = NULL; - nsresult rc; - size_t i = 0; - - 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; - } - - info->nrVirtCpu = 0; - 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, &machineName); - - if (STREQ(dom->name, machineName)) { - /* Get the Machine State (also match it with - * virDomainState). Get the Machine memory and - * for time being set max_balloon and cur_balloon to same - * Also since there is no direct way of checking - * the cputime required (one condition being the - * VM is remote), return zero for cputime. Get the - * number of CPU. - */ - PRUint32 CPUCount = 0; - PRUint32 memorySize = 0; - PRUint32 state = MachineState_Null; - PRUint32 maxMemorySize = 4 * 1024; - ISystemProperties *systemProperties = NULL; - - data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties); - if (systemProperties) { - systemProperties->vtbl->GetMaxGuestRAM(systemProperties, &maxMemorySize); - VBOX_RELEASE(systemProperties); - systemProperties = NULL; - } - - - machine->vtbl->GetCPUCount(machine, &CPUCount); - machine->vtbl->GetMemorySize(machine, &memorySize); - machine->vtbl->GetState(machine, &state); - - info->cpuTime = 0; - info->nrVirtCpu = CPUCount; - info->memory = memorySize * 1024; - info->maxMem = maxMemorySize * 1024; - info->state = vboxConvertState(state); - - ret = 0; - } - - VBOX_UTF8_FREE(machineName); - VBOX_COM_UNALLOC_MEM(machineNameUtf16); - if (info->nrVirtCpu) - break; - } - - } - - vboxArrayRelease(&machines); - - cleanup: - return ret; -} - static int vboxDomainGetState(virDomainPtr dom, int *state, @@ -1058,7 +978,7 @@ vboxDomainGetState(virDomainPtr dom, machine->vtbl->GetState(machine, &mstate); - *state = vboxConvertState(mstate); + *state = _vboxConvertState(mstate); if (reason) *reason = 0; @@ -9556,12 +9476,24 @@ _machineGetUSBCommon(IMachine *machine, IUSBCommon **USBCommon) } static nsresult +_machineGetCPUCount(IMachine *machine, PRUint32 *CPUCount) +{ + return machine->vtbl->GetCPUCount(machine, CPUCount); +} + +static nsresult _machineSetCPUCount(IMachine *machine, PRUint32 CPUCount) { return machine->vtbl->SetCPUCount(machine, CPUCount); } static nsresult +_machineGetMemorySize(IMachine *machine, PRUint32 *memorySize) +{ + return machine->vtbl->GetMemorySize(machine, memorySize); +} + +static nsresult _machineSetMemorySize(IMachine *machine, PRUint32 memorySize) { return machine->vtbl->SetMemorySize(machine, memorySize); @@ -9829,6 +9761,12 @@ _systemPropertiesGetMaxDevicesPerPortForStorageBus(ISystemProperties *systemProp #endif static nsresult +_systemPropertiesGetMaxGuestRAM(ISystemProperties *systemProperties, PRUint32 *maxGuestRAM) +{ + return systemProperties->vtbl->GetMaxGuestRAM(systemProperties, maxGuestRAM); +} + +static nsresult _biosSettingsSetACPIEnabled(IBIOSSettings *bios, PRBool ACPIEnabled) { return bios->vtbl->SetACPIEnabled(bios, ACPIEnabled); @@ -10234,7 +10172,9 @@ static vboxUniformedIMachine _UIMachine = { .GetParallelPort = _machineGetParallelPort, .GetVRDxServer = _machineGetVRDxServer, .GetUSBCommon = _machineGetUSBCommon, + .GetCPUCount = _machineGetCPUCount, .SetCPUCount = _machineSetCPUCount, + .GetMemorySize = _machineGetMemorySize, .SetMemorySize = _machineSetMemorySize, .SetCPUProperty = _machineSetCPUProperty, .SetBootOrder = _machineSetBootOrder, @@ -10278,6 +10218,7 @@ static vboxUniformedISystemProperties _UISystemProperties = { .GetParallelPortCount = _systemPropertiesGetParallelPortCount, .GetMaxPortCountForStorageBus = _systemPropertiesGetMaxPortCountForStorageBus, .GetMaxDevicesPerPortForStorageBus = _systemPropertiesGetMaxDevicesPerPortForStorageBus, + .GetMaxGuestRAM = _systemPropertiesGetMaxGuestRAM, }; static vboxUniformedIBIOSSettings _UIBIOSSettings = { @@ -10362,6 +10303,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->unregisterMachine = _unregisterMachine; pVBoxAPI->deleteConfig = _deleteConfig; pVBoxAPI->vboxAttachDrivesOld = _vboxAttachDrivesOld; + pVBoxAPI->vboxConvertState = _vboxConvertState; pVBoxAPI->UPFN = _UPFN; pVBoxAPI->UIID = _UIID; pVBoxAPI->UArray = _UArray; diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index bc76904..897e10c 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -212,7 +212,9 @@ typedef struct { nsresult (*GetParallelPort)(IMachine *machine, PRUint32 slot, IParallelPort **port); nsresult (*GetVRDxServer)(IMachine *machine, IVRDxServer **VRDxServer); nsresult (*GetUSBCommon)(IMachine *machine, IUSBCommon **USBCommon); + nsresult (*GetCPUCount)(IMachine *machine, PRUint32 *CPUCount); nsresult (*SetCPUCount)(IMachine *machine, PRUint32 CPUCount); + nsresult (*GetMemorySize)(IMachine *machine, PRUint32 *memorySize); nsresult (*SetMemorySize)(IMachine *machine, PRUint32 memorySize); nsresult (*SetCPUProperty)(IMachine *machine, PRUint32 property, PRBool value); nsresult (*SetBootOrder)(IMachine *machine, PRUint32 position, PRUint32 device); @@ -263,6 +265,7 @@ typedef struct { PRUint32 *maxPortCount); nsresult (*GetMaxDevicesPerPortForStorageBus)(ISystemProperties *systemProperties, PRUint32 bus, PRUint32 *maxDevicesPerPort); + nsresult (*GetMaxGuestRAM)(ISystemProperties *systemProperties, PRUint32 *maxGuestRAM); } vboxUniformedISystemProperties; /* Functions for IBIOSSettings */ @@ -360,6 +363,7 @@ typedef struct { nsresult (*unregisterMachine)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine); void (*deleteConfig)(IMachine *machine); void (*vboxAttachDrivesOld)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine); + virDomainState (*vboxConvertState)(PRUint32 state); vboxUniformedPFN UPFN; vboxUniformedIID UIID; vboxUniformedArray UArray; @@ -431,6 +435,7 @@ int vboxDomainDestroyFlags(virDomainPtr dom, unsigned int flags); int vboxDomainDestroy(virDomainPtr dom); char *vboxDomainGetOSType(virDomainPtr dom); int vboxDomainSetMemory(virDomainPtr dom, unsigned long memory); +int vboxDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 27 +++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 36 ------------------------------------ src/vbox/vbox_uniformed_api.h | 2 ++ 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index d661110..1a4a4f5 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2748,3 +2748,30 @@ int vboxDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) cleanup: return ret; } + +int vboxDomainGetState(virDomainPtr dom, int *state, + int *reason, unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIIDUnion domiid; + IMachine *machine = NULL; + PRUint32 mstate; + + virCheckFlags(0, -1); + + if (openSessionForMachine(data, dom->uuid, &domiid, &machine, false) < 0) + goto cleanup; + + gVBoxAPI.UIMachine.GetState(machine, &mstate); + + *state = gVBoxAPI.vboxConvertState(mstate); + + if (reason) + *reason = 0; + + ret = 0; + + cleanup: + vboxIIDUnalloc(&domiid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 3ae1864..33aa66a 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -955,42 +955,6 @@ static virDomainState _vboxConvertState(PRUint32 state) } static int -vboxDomainGetState(virDomainPtr dom, - int *state, - int *reason, - unsigned int flags) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxIID domiid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - PRUint32 mstate = MachineState_Null; - nsresult rc; - - virCheckFlags(0, -1); - - vboxIIDFromUUID(&domiid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching UUID")); - goto cleanup; - } - - machine->vtbl->GetState(machine, &mstate); - - *state = _vboxConvertState(mstate); - - if (reason) - *reason = 0; - - ret = 0; - - cleanup: - vboxIIDUnalloc(&domiid); - return ret; -} - -static int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags) { diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 897e10c..0f6c8ea 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -436,6 +436,8 @@ int vboxDomainDestroy(virDomainPtr dom); char *vboxDomainGetOSType(virDomainPtr dom); int vboxDomainSetMemory(virDomainPtr dom, unsigned long memory); int vboxDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info); +int vboxDomainGetState(virDomainPtr dom, int *state, + int *reason, unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 46 ++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 55 ----------------------------------------- src/vbox/vbox_uniformed_api.h | 3 +++ 3 files changed, 49 insertions(+), 55 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 1a4a4f5..4aadd01 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2775,3 +2775,49 @@ int vboxDomainGetState(virDomainPtr dom, int *state, vboxIIDUnalloc(&domiid); return ret; } + +int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, + unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IMachine *machine = NULL; + vboxIIDUnion iid; + PRUint32 CPUCount = nvcpus; + nsresult rc; + + if (flags != VIR_DOMAIN_AFFECT_LIVE) { + virReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); + return -1; + } + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, true) < 0) + return -1; + + rc = gVBoxAPI.UISession.Open(data, &iid, machine); + if (NS_SUCCEEDED(rc)) { + gVBoxAPI.UISession.GetMachine(data->vboxSession, &machine); + if (machine) { + rc = gVBoxAPI.UIMachine.SetCPUCount(machine, CPUCount); + if (NS_SUCCEEDED(rc)) { + gVBoxAPI.UIMachine.SaveSettings(machine); + ret = 0; + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not set the number of cpus of the domain " + "to: %u, rc=%08x"), + CPUCount, (unsigned)rc); + } + VBOX_RELEASE(machine); + } else { + virReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching id %d"), dom->id); + } + } else { + virReportError(VIR_ERR_NO_DOMAIN, + _("can't open session to the domain with id %d"), dom->id); + } + gVBoxAPI.UISession.Close(data->vboxSession); + + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 33aa66a..c8cc951 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -955,61 +955,6 @@ static virDomainState _vboxConvertState(PRUint32 state) } static int -vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, - unsigned int flags) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IMachine *machine = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - PRUint32 CPUCount = nvcpus; - nsresult rc; - - if (flags != VIR_DOMAIN_AFFECT_LIVE) { - virReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); - return -1; - } - - vboxIIDFromUUID(&iid, dom->uuid); -#if VBOX_API_VERSION >= 4000000 - /* Get machine for the call to VBOX_SESSION_OPEN */ - 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(iid.value, machine); - if (NS_SUCCEEDED(rc)) { - data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); - if (machine) { - rc = machine->vtbl->SetCPUCount(machine, CPUCount); - if (NS_SUCCEEDED(rc)) { - machine->vtbl->SaveSettings(machine); - ret = 0; - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not set the number of cpus of the domain " - "to: %u, rc=%08x"), - CPUCount, (unsigned)rc); - } - VBOX_RELEASE(machine); - } else { - virReportError(VIR_ERR_NO_DOMAIN, - _("no domain with matching id %d"), dom->id); - } - } else { - virReportError(VIR_ERR_NO_DOMAIN, - _("can't open session to the domain with id %d"), dom->id); - } - VBOX_SESSION_CLOSE(); - - vboxIIDUnalloc(&iid); - return ret; -} - -static int vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) { return vboxDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_AFFECT_LIVE); diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 0f6c8ea..84a8a37 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -438,6 +438,9 @@ int vboxDomainSetMemory(virDomainPtr dom, unsigned long memory); int vboxDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info); int vboxDomainGetState(virDomainPtr dom, int *state, int *reason, unsigned int flags); +int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, + 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 | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 4aadd01..1df946d 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2821,3 +2821,8 @@ int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, vboxIIDUnalloc(&iid); return ret; } + +int vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) +{ + return vboxDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_AFFECT_LIVE); +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index c8cc951..db16092 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -955,12 +955,6 @@ static virDomainState _vboxConvertState(PRUint32 state) } static int -vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) -{ - return vboxDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_AFFECT_LIVE); -} - -static int vboxDomainGetVcpusFlags(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 84a8a37..cb04501 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -440,7 +440,7 @@ int vboxDomainGetState(virDomainPtr dom, int *state, int *reason, unsigned int flags); int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags); - +int vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus); /* 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 | 29 ----------------------------- src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 1df946d..120ad6c 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2826,3 +2826,31 @@ int vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) { return vboxDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_AFFECT_LIVE); } + +int vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + ISystemProperties *systemProperties = NULL; + PRUint32 maxCPUCount = 0; + + if (flags != (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) { + virReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); + return -1; + } + + /* Currently every domain supports the same number of max cpus + * as that supported by vbox and thus take it directly from + * the systemproperties. + */ + + gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties); + if (systemProperties) { + gVBoxAPI.UISystemProperties.GetMaxGuestCPUCount(systemProperties, &maxCPUCount); + VBOX_RELEASE(systemProperties); + } + + if (maxCPUCount > 0) + ret = maxCPUCount; + + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index db16092..50e4653 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -955,35 +955,6 @@ static virDomainState _vboxConvertState(PRUint32 state) } static int -vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - ISystemProperties *systemProperties = NULL; - PRUint32 maxCPUCount = 0; - - if (flags != (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) { - virReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); - return -1; - } - - /* Currently every domain supports the same number of max cpus - * as that supported by vbox and thus take it directly from - * the systemproperties. - */ - - 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 int vboxDomainGetMaxVcpus(virDomainPtr dom) { return vboxDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE | diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index cb04501..5bab8fa 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -441,6 +441,7 @@ int vboxDomainGetState(virDomainPtr dom, int *state, int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags); int vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus); +int vboxDomainGetVcpusFlags(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 | 6 ++++++ src/vbox/vbox_tmpl.c | 7 ------- src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 120ad6c..24d2ddb 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2854,3 +2854,9 @@ int vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) return ret; } + +int vboxDomainGetMaxVcpus(virDomainPtr dom) +{ + return vboxDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_VCPU_MAXIMUM)); +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 50e4653..8abb9a7 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -954,13 +954,6 @@ static virDomainState _vboxConvertState(PRUint32 state) } } -static int -vboxDomainGetMaxVcpus(virDomainPtr dom) -{ - return vboxDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE | - VIR_DOMAIN_VCPU_MAXIMUM)); -} - static void vboxHostDeviceGetXMLDesc(vboxGlobalData *data, virDomainDefPtr def, IMachine *machine) { #if VBOX_API_VERSION < 4003000 diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 5bab8fa..f67c109 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -442,6 +442,7 @@ int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags); int vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus); int vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags); +int vboxDomainGetMaxVcpus(virDomainPtr dom); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.h | 2 + src/vbox/vbox_tmpl.c | 718 +++++++++++++++++++++++++++++++++++++++++ src/vbox/vbox_uniformed_api.h | 73 +++++ 3 files changed, 793 insertions(+) diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h index eedd755..c4e7ae5 100644 --- a/src/vbox/vbox_common.h +++ b/src/vbox/vbox_common.h @@ -257,6 +257,8 @@ typedef nsISupports IVRDxServer; typedef nsISupports IUSBCommon; typedef nsISupports IUSBDeviceFilter; typedef nsISupports IMedium; +typedef nsISupports IMediumAttachment; typedef nsISupports IStorageController; +typedef nsISupports ISharedFolder; #endif /* VBOX_COMMON_H */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 8abb9a7..803b0cc 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -102,6 +102,10 @@ typedef IUSBController IUSBCommon; typedef IUSBDeviceFilters IUSBCommon; #endif /* VBOX_API_VERSION >= 4003000 */ +#if VBOX_API_VERSION < 3001000 +typedef IHardDiskAttachment IMediumAttachment; +#endif /* VBOX_API_VERSION < 3001000 */ + #include "vbox_uniformed_api.h" #define VIR_FROM_THIS VIR_FROM_VBOX @@ -8982,6 +8986,260 @@ _deleteConfig(IMachine *machine) #endif /* VBOX_API_VERSION >= 4000000 */ +#if VBOX_API_VERSION < 3001000 + +static void +_dumpIDEHDDsOld(virDomainDefPtr def, + vboxGlobalData *data, + IMachine *machine) +{ + PRInt32 hddNum = 0; + IHardDisk *hardDiskPM = NULL; + IHardDisk *hardDiskPS = NULL; + IHardDisk *hardDiskSS = NULL; + const char *hddBus = "IDE"; + PRUnichar *hddBusUtf16 = NULL; + + /* dump IDE hdds if present */ + VBOX_UTF8_TO_UTF16(hddBus, &hddBusUtf16); + + def->ndisks = 0; + machine->vtbl->GetHardDisk(machine, hddBusUtf16, 0, 0, &hardDiskPM); + if (hardDiskPM) + def->ndisks++; + + machine->vtbl->GetHardDisk(machine, hddBusUtf16, 0, 1, &hardDiskPS); + if (hardDiskPS) + def->ndisks++; + + machine->vtbl->GetHardDisk(machine, hddBusUtf16, 1, 1, &hardDiskSS); + if (hardDiskSS) + def->ndisks++; + + VBOX_UTF16_FREE(hddBusUtf16); + + if ((def->ndisks > 0) && (VIR_ALLOC_N(def->disks, def->ndisks) >= 0)) { + size_t i; + for (i = 0; i < def->ndisks; i++) { + if ((def->disks[i] = virDomainDiskDefNew())) { + def->disks[i]->device = VIR_DOMAIN_DISK_DEVICE_DISK; + def->disks[i]->bus = VIR_DOMAIN_DISK_BUS_IDE; + virDomainDiskSetType(def->disks[i], + VIR_STORAGE_TYPE_FILE); + } + } + } + + if (hardDiskPM) { + PRUnichar *hddlocationUtf16 = NULL; + char *hddlocation = NULL; + PRUint32 hddType = HardDiskType_Normal; + + hardDiskPM->vtbl->imedium.GetLocation((IMedium *)hardDiskPM, &hddlocationUtf16); + VBOX_UTF16_TO_UTF8(hddlocationUtf16, &hddlocation); + + hardDiskPM->vtbl->GetType(hardDiskPM, &hddType); + + if (hddType == HardDiskType_Immutable) + def->disks[hddNum]->src->readonly = true; + ignore_value(virDomainDiskSetSource(def->disks[hddNum], + hddlocation)); + ignore_value(VIR_STRDUP(def->disks[hddNum]->dst, "hda")); + hddNum++; + + VBOX_UTF8_FREE(hddlocation); + VBOX_UTF16_FREE(hddlocationUtf16); + VBOX_MEDIUM_RELEASE(hardDiskPM); + } + + if (hardDiskPS) { + PRUnichar *hddlocationUtf16 = NULL; + char *hddlocation = NULL; + PRUint32 hddType = HardDiskType_Normal; + + hardDiskPS->vtbl->imedium.GetLocation((IMedium *)hardDiskPS, &hddlocationUtf16); + VBOX_UTF16_TO_UTF8(hddlocationUtf16, &hddlocation); + + hardDiskPS->vtbl->GetType(hardDiskPS, &hddType); + + if (hddType == HardDiskType_Immutable) + def->disks[hddNum]->src->readonly = true; + ignore_value(virDomainDiskSetSource(def->disks[hddNum], + hddlocation)); + ignore_value(VIR_STRDUP(def->disks[hddNum]->dst, "hdb")); + hddNum++; + + VBOX_UTF8_FREE(hddlocation); + VBOX_UTF16_FREE(hddlocationUtf16); + VBOX_MEDIUM_RELEASE(hardDiskPS); + } + + if (hardDiskSS) { + PRUnichar *hddlocationUtf16 = NULL; + char *hddlocation = NULL; + PRUint32 hddType = HardDiskType_Normal; + + hardDiskSS->vtbl->imedium.GetLocation((IMedium *)hardDiskSS, &hddlocationUtf16); + VBOX_UTF16_TO_UTF8(hddlocationUtf16, &hddlocation); + + hardDiskSS->vtbl->GetType(hardDiskSS, &hddType); + + if (hddType == HardDiskType_Immutable) + def->disks[hddNum]->src->readonly = true; + ignore_value(virDomainDiskSetSource(def->disks[hddNum], + hddlocation)); + ignore_value(VIR_STRDUP(def->disks[hddNum]->dst, "hdd")); + hddNum++; + + VBOX_UTF8_FREE(hddlocation); + VBOX_UTF16_FREE(hddlocationUtf16); + VBOX_MEDIUM_RELEASE(hardDiskSS); + } +} + +static void +_dumpDVD(virDomainDefPtr def, + vboxGlobalData *data, + IMachine *machine) +{ + IDVDDrive *dvdDrive = NULL; + IDVDImage *dvdImage = NULL; + PRUnichar *locationUtf16 = NULL; + char *location = NULL; + + + /* dump CDROM/DVD if the drive is attached and has DVD/CD in it */ + machine->vtbl->GetDVDDrive(machine, &dvdDrive); + if (!dvdDrive) + return; + + PRUint32 state = DriveState_Null; + + dvdDrive->vtbl->GetState(dvdDrive, &state); + if (state != DriveState_ImageMounted) + goto cleanupDVDDrive; + + + dvdDrive->vtbl->GetImage(dvdDrive, &dvdImage); + if (!dvdImage) + goto cleanupDVDDrive; + + dvdImage->vtbl->imedium.GetLocation((IMedium *)dvdImage, &locationUtf16); + VBOX_UTF16_TO_UTF8(locationUtf16, &location); + + def->ndisks++; + if (VIR_REALLOC_N(def->disks, def->ndisks) >= 0) { + if ((def->disks[def->ndisks - 1] = virDomainDiskDefNew())) { + def->disks[def->ndisks - 1]->device = VIR_DOMAIN_DISK_DEVICE_CDROM; + def->disks[def->ndisks - 1]->bus = VIR_DOMAIN_DISK_BUS_IDE; + virDomainDiskSetType(def->disks[def->ndisks - 1], + VIR_STORAGE_TYPE_FILE); + def->disks[def->ndisks - 1]->src->readonly = true; + ignore_value(virDomainDiskSetSource(def->disks[def->ndisks - 1], location)); + ignore_value(VIR_STRDUP(def->disks[def->ndisks - 1]->dst, "hdc")); + def->ndisks--; + } else { + def->ndisks--; + } + } else { + def->ndisks--; + } + + VBOX_UTF8_FREE(location); + VBOX_UTF16_FREE(locationUtf16); + VBOX_MEDIUM_RELEASE(dvdImage); + + cleanupDVDDrive: + VBOX_RELEASE(dvdDrive); +} + +static void +_dumpFloppy(virDomainDefPtr def, + vboxGlobalData *data, + IMachine *machine) +{ + IFloppyDrive *floppyDrive = NULL; + IFloppyImage *floppyImage = NULL; + PRUnichar *locationUtf16 = NULL; + char *location = NULL; + PRBool enabled = PR_FALSE; + PRUint32 state = DriveState_Null; + + /* dump Floppy if the drive is attached and has floppy in it */ + machine->vtbl->GetFloppyDrive(machine, &floppyDrive); + if (!floppyDrive) + return; + + floppyDrive->vtbl->GetEnabled(floppyDrive, &enabled); + if (!enabled) + goto cleanupFloppyDrive; + + + floppyDrive->vtbl->GetState(floppyDrive, &state); + if (state != DriveState_ImageMounted) + goto cleanupFloppyDrive; + + floppyDrive->vtbl->GetImage(floppyDrive, &floppyImage); + if (!floppyImage) + goto cleanupFloppyDrive; + + floppyImage->vtbl->imedium.GetLocation((IMedium *)floppyImage, &locationUtf16); + VBOX_UTF16_TO_UTF8(locationUtf16, &location); + + def->ndisks++; + if (VIR_REALLOC_N(def->disks, def->ndisks) >= 0) { + if ((def->disks[def->ndisks - 1] = virDomainDiskDefNew())) { + def->disks[def->ndisks - 1]->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY; + def->disks[def->ndisks - 1]->bus = VIR_DOMAIN_DISK_BUS_FDC; + virDomainDiskSetType(def->disks[def->ndisks - 1], + VIR_STORAGE_TYPE_FILE); + def->disks[def->ndisks - 1]->src->readonly = false; + ignore_value(virDomainDiskSetSource(def->disks[def->ndisks - 1], location)); + ignore_value(VIR_STRDUP(def->disks[def->ndisks - 1]->dst, "fda")); + def->ndisks--; + } else { + def->ndisks--; + } + } else { + def->ndisks--; + } + + VBOX_UTF8_FREE(location); + VBOX_UTF16_FREE(locationUtf16); + VBOX_MEDIUM_RELEASE(floppyImage); + + cleanupFloppyDrive: + VBOX_RELEASE(floppyDrive); +} + +#else /* VBOX_API_VERSION >= 3001000 */ + +static void +_dumpIDEHDDsOld(virDomainDefPtr def ATTRIBUTE_UNUSED, + vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); +} + +static void +_dumpDVD(virDomainDefPtr def ATTRIBUTE_UNUSED, + vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); +} + +static void +_dumpFloppy(virDomainDefPtr def ATTRIBUTE_UNUSED, + vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); +} + +#endif /* VBOX_API_VERSION >= 3001000 */ + static void _pfnUninitialize(vboxGlobalData *data) { if (data->pFuncs) @@ -9049,6 +9307,25 @@ static void* _handleGetMachines(IVirtualBox *vboxObj) return vboxObj->vtbl->GetMachines; } +static void* _handleUSBGetDeviceFilters(IUSBCommon *USBCommon) +{ + return USBCommon->vtbl->GetDeviceFilters; +} + +static void* _handleMachineGetMediumAttachments(IMachine *machine) +{ +#if VBOX_API_VERSION < 3001000 + return machine->vtbl->GetHardDiskAttachments; +#else /* VBOX_API_VERSION >= 3001000 */ + return machine->vtbl->GetMediumAttachments; +#endif /* VBOX_API_VERSION >= 3001000 */ +} + +static void* _handleMachineGetSharedFolders(IMachine *machine) +{ + return machine->vtbl->GetSharedFolders; +} + static nsresult _nsisupportsRelease(nsISupports *nsi) { return nsi->vtbl->Release(nsi); @@ -9207,6 +9484,14 @@ _machineAddStorageController(IMachine *machine, PRUnichar *name, } static nsresult +_machineGetStorageControllerByName(IMachine *machine, PRUnichar *name, + IStorageController **storageController) +{ + return machine->vtbl->GetStorageControllerByName(machine, name, + storageController); +} + +static nsresult _machineAttachDevice(IMachine *machine ATTRIBUTE_UNUSED, PRUnichar *name ATTRIBUTE_UNUSED, PRInt32 controllerPort ATTRIBUTE_UNUSED, @@ -9367,6 +9652,18 @@ _machineSetMemorySize(IMachine *machine, PRUint32 memorySize) } static nsresult +_machineGetCPUProperty(IMachine *machine, PRUint32 property ATTRIBUTE_UNUSED, PRBool *value) +{ +#if VBOX_API_VERSION < 3001000 + return machine->vtbl->GetPAEEnabled(machine, value); +#elif VBOX_API_VERSION == 3001000 + return machine->vtbl->GetCpuProperty(machine, property, value); +#elif VBOX_API_VERSION >= 3002000 + return machine->vtbl->GetCPUProperty(machine, property, value); +#endif +} + +static nsresult _machineSetCPUProperty(IMachine *machine, PRUint32 property ATTRIBUTE_UNUSED, PRBool value) { #if VBOX_API_VERSION < 3001000 @@ -9379,30 +9676,66 @@ _machineSetCPUProperty(IMachine *machine, PRUint32 property ATTRIBUTE_UNUSED, PR } static nsresult +_machineGetBootOrder(IMachine *machine, PRUint32 position, PRUint32 *device) +{ + return machine->vtbl->GetBootOrder(machine, position, device); +} + +static nsresult _machineSetBootOrder(IMachine *machine, PRUint32 position, PRUint32 device) { return machine->vtbl->SetBootOrder(machine, position, device); } static nsresult +_machineGetVRAMSize(IMachine *machine, PRUint32 *VRAMSize) +{ + return machine->vtbl->GetVRAMSize(machine, VRAMSize); +} + +static nsresult _machineSetVRAMSize(IMachine *machine, PRUint32 VRAMSize) { return machine->vtbl->SetVRAMSize(machine, VRAMSize); } static nsresult +_machineGetMonitorCount(IMachine *machine, PRUint32 *monitorCount) +{ + return machine->vtbl->GetMonitorCount(machine, monitorCount); +} + +static nsresult _machineSetMonitorCount(IMachine *machine, PRUint32 monitorCount) { return machine->vtbl->SetMonitorCount(machine, monitorCount); } static nsresult +_machineGetAccelerate3DEnabled(IMachine *machine, PRBool *accelerate3DEnabled) +{ + return machine->vtbl->GetAccelerate3DEnabled(machine, accelerate3DEnabled); +} + +static nsresult _machineSetAccelerate3DEnabled(IMachine *machine, PRBool accelerate3DEnabled) { return machine->vtbl->SetAccelerate3DEnabled(machine, accelerate3DEnabled); } static nsresult +_machineGetAccelerate2DVideoEnabled(IMachine *machine ATTRIBUTE_UNUSED, + PRBool *accelerate2DVideoEnabled ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION >= 3001000 + return machine->vtbl->GetAccelerate2DVideoEnabled(machine, accelerate2DVideoEnabled); +#else /* VBOX_API_VERSION < 3001000 */ + vboxUnsupported(); + return 0; +#endif /* VBOX_API_VERSION < 3001000 */ +} + +static nsresult _machineSetAccelerate2DVideoEnabled(IMachine *machine ATTRIBUTE_UNUSED, PRBool accelerate2DVideoEnabled ATTRIBUTE_UNUSED) { @@ -9634,48 +9967,102 @@ _systemPropertiesGetMaxGuestRAM(ISystemProperties *systemProperties, PRUint32 *m } static nsresult +_biosSettingsGetACPIEnabled(IBIOSSettings *bios, PRBool *ACPIEnabled) +{ + return bios->vtbl->GetACPIEnabled(bios, ACPIEnabled); +} + +static nsresult _biosSettingsSetACPIEnabled(IBIOSSettings *bios, PRBool ACPIEnabled) { return bios->vtbl->SetACPIEnabled(bios, ACPIEnabled); } static nsresult +_biosSettingsGetIOAPICEnabled(IBIOSSettings *bios, PRBool *IOAPICEnabled) +{ + return bios->vtbl->GetIOAPICEnabled(bios, IOAPICEnabled); +} + +static nsresult _biosSettingsSetIOAPICEnabled(IBIOSSettings *bios, PRBool IOAPICEnabled) { return bios->vtbl->SetIOAPICEnabled(bios, IOAPICEnabled); } static nsresult +_audioAdapterGetEnabled(IAudioAdapter *audioAdapter, PRBool *enabled) +{ + return audioAdapter->vtbl->GetEnabled(audioAdapter, enabled); +} + +static nsresult _audioAdapterSetEnabled(IAudioAdapter *audioAdapter, PRBool enabled) { return audioAdapter->vtbl->SetEnabled(audioAdapter, enabled); } static nsresult +_audioAdapterGetAudioController(IAudioAdapter *audioAdapter, PRUint32 *audioController) +{ + return audioAdapter->vtbl->GetAudioController(audioAdapter, audioController); +} + +static nsresult _audioAdapterSetAudioController(IAudioAdapter *audioAdapter, PRUint32 audioController) { return audioAdapter->vtbl->SetAudioController(audioAdapter, audioController); } static nsresult +_networkAdapterGetAttachmentType(INetworkAdapter *adapter, PRUint32 *attachmentType) +{ + return adapter->vtbl->GetAttachmentType(adapter, attachmentType); +} + +static nsresult +_networkAdapterGetEnabled(INetworkAdapter *adapter, PRBool *enabled) +{ + return adapter->vtbl->GetEnabled(adapter, enabled); +} + +static nsresult _networkAdapterSetEnabled(INetworkAdapter *adapter, PRBool enabled) { return adapter->vtbl->SetEnabled(adapter, enabled); } static nsresult +_networkAdapterGetAdapterType(INetworkAdapter *adapter, PRUint32 *adapterType) +{ + return adapter->vtbl->GetAdapterType(adapter, adapterType); +} + +static nsresult _networkAdapterSetAdapterType(INetworkAdapter *adapter, PRUint32 adapterType) { return adapter->vtbl->SetAdapterType(adapter, adapterType); } static nsresult +_networkAdapterGetInternalNetwork(INetworkAdapter *adapter, PRUnichar **internalNetwork) +{ + return adapter->vtbl->GetInternalNetwork(adapter, internalNetwork); +} + +static nsresult _networkAdapterSetInternalNetwork(INetworkAdapter *adapter, PRUnichar *internalNetwork) { return adapter->vtbl->SetInternalNetwork(adapter, internalNetwork); } static nsresult +_networkAdapterGetMACAddress(INetworkAdapter *adapter, PRUnichar **MACAddress) +{ + return adapter->vtbl->GetMACAddress(adapter, MACAddress); +} + +static nsresult _networkAdapterSetMACAddress(INetworkAdapter *adapter, PRUnichar *MACAddress) { return adapter->vtbl->SetMACAddress(adapter, MACAddress); @@ -9684,12 +10071,24 @@ _networkAdapterSetMACAddress(INetworkAdapter *adapter, PRUnichar *MACAddress) #if VBOX_API_VERSION < 4001000 static nsresult +_networkAdapterGetBridgedInterface(INetworkAdapter *adapter, PRUnichar **hostInterface) +{ + return adapter->vtbl->GetHostInterface(adapter, hostInterface); +} + +static nsresult _networkAdapterSetBridgedInterface(INetworkAdapter *adapter, PRUnichar *hostInterface) { return adapter->vtbl->SetHostInterface(adapter, hostInterface); } static nsresult +_networkAdapterGetHostOnlyInterface(INetworkAdapter *adapter, PRUnichar **hostOnlyInterface) +{ + return adapter->vtbl->GetHostInterface(adapter, hostOnlyInterface); +} + +static nsresult _networkAdapterSetHostOnlyInterface(INetworkAdapter *adapter, PRUnichar *hostOnlyInterface) { return adapter->vtbl->SetHostInterface(adapter, hostOnlyInterface); @@ -9722,12 +10121,24 @@ _networkAdapterAttachToNAT(INetworkAdapter *adapter) #else /* VBOX_API_VERSION >= 4001000 */ static nsresult +_networkAdapterGetBridgedInterface(INetworkAdapter *adapter, PRUnichar **bridgedInterface) +{ + return adapter->vtbl->GetBridgedInterface(adapter, bridgedInterface); +} + +static nsresult _networkAdapterSetBridgedInterface(INetworkAdapter *adapter, PRUnichar *bridgedInterface) { return adapter->vtbl->SetBridgedInterface(adapter, bridgedInterface); } static nsresult +_networkAdapterGetHostOnlyInterface(INetworkAdapter *adapter, PRUnichar **hostOnlyInterface) +{ + return adapter->vtbl->GetHostOnlyInterface(adapter, hostOnlyInterface); +} + +static nsresult _networkAdapterSetHostOnlyInterface(INetworkAdapter *adapter, PRUnichar *hostOnlyInterface) { return adapter->vtbl->SetHostOnlyInterface(adapter, hostOnlyInterface); @@ -9760,66 +10171,166 @@ _networkAdapterAttachToNAT(INetworkAdapter *adapter) #endif /* VBOX_API_VERSION >= 4001000 */ static nsresult +_serialPortGetEnabled(ISerialPort *port, PRBool *enabled) +{ + return port->vtbl->GetEnabled(port, enabled); +} + +static nsresult _serialPortSetEnabled(ISerialPort *port, PRBool enabled) { return port->vtbl->SetEnabled(port, enabled); } static nsresult +_serialPortGetPath(ISerialPort *port, PRUnichar **path) +{ + return port->vtbl->GetPath(port, path); +} + +static nsresult _serialPortSetPath(ISerialPort *port, PRUnichar *path) { return port->vtbl->SetPath(port, path); } static nsresult +_serialPortGetIRQ(ISerialPort *port, PRUint32 *IRQ) +{ + return port->vtbl->GetIRQ(port, IRQ); +} + +static nsresult _serialPortSetIRQ(ISerialPort *port, PRUint32 IRQ) { return port->vtbl->SetIRQ(port, IRQ); } static nsresult +_serialPortGetIOBase(ISerialPort *port, PRUint32 *IOBase) +{ + return port->vtbl->GetIOBase(port, IOBase); +} + +static nsresult _serialPortSetIOBase(ISerialPort *port, PRUint32 IOBase) { return port->vtbl->SetIOBase(port, IOBase); } static nsresult +_serialPortGetHostMode(ISerialPort *port, PRUint32 *hostMode) +{ + return port->vtbl->GetHostMode(port, hostMode); +} + +static nsresult _serialPortSetHostMode(ISerialPort *port, PRUint32 hostMode) { return port->vtbl->SetHostMode(port, hostMode); } static nsresult +_parallelPortGetEnabled(IParallelPort *port, PRBool *enabled) +{ + return port->vtbl->GetEnabled(port, enabled); +} + +static nsresult _parallelPortSetEnabled(IParallelPort *port, PRBool enabled) { return port->vtbl->SetEnabled(port, enabled); } static nsresult +_parallelPortGetPath(IParallelPort *port, PRUnichar **path) +{ + return port->vtbl->GetPath(port, path); +} + +static nsresult _parallelPortSetPath(IParallelPort *port, PRUnichar *path) { return port->vtbl->SetPath(port, path); } static nsresult +_parallelPortGetIRQ(IParallelPort *port, PRUint32 *IRQ) +{ + return port->vtbl->GetIRQ(port, IRQ); +} + +static nsresult _parallelPortSetIRQ(IParallelPort *port, PRUint32 IRQ) { return port->vtbl->SetIRQ(port, IRQ); } static nsresult +_parallelPortGetIOBase(IParallelPort *port, PRUint32 *IOBase) +{ + return port->vtbl->GetIOBase(port, IOBase); +} + +static nsresult _parallelPortSetIOBase(IParallelPort *port, PRUint32 IOBase) { return port->vtbl->SetIOBase(port, IOBase); } static nsresult +_vrdxServerGetEnabled(IVRDxServer *VRDxServer, PRBool *enabled) +{ + return VRDxServer->vtbl->GetEnabled(VRDxServer, enabled); +} + +static nsresult _vrdxServerSetEnabled(IVRDxServer *VRDxServer, PRBool enabled) { return VRDxServer->vtbl->SetEnabled(VRDxServer, enabled); } static nsresult +_vrdxServerGetPorts(vboxGlobalData *data ATTRIBUTE_UNUSED, + IVRDxServer *VRDxServer, virDomainGraphicsDefPtr graphics) +{ + nsresult rc; +#if VBOX_API_VERSION < 3001000 + PRUint32 VRDPport = 0; + rc = VRDxServer->vtbl->GetPort(VRDxServer, &VRDPport); + if (VRDPport) { + graphics->data.rdp.port = VRDPport; + } else { + graphics->data.rdp.autoport = true; + } +#elif VBOX_API_VERSION < 4000000 /* 3001000 <= VBOX_API_VERSION < 4000000 */ + PRUnichar *VRDPport = NULL; + rc = VRDxServer->vtbl->GetPorts(VRDxServer, &VRDPport); + if (VRDPport) { + /* even if vbox supports mutilpe ports, single port for now here */ + graphics->data.rdp.port = PRUnicharToInt(VRDPport); + VBOX_UTF16_FREE(VRDPport); + } else { + graphics->data.rdp.autoport = true; + } +#else /* VBOX_API_VERSION >= 4000000 */ + PRUnichar *VRDEPortsKey = NULL; + PRUnichar *VRDEPortsValue = NULL; + VBOX_UTF8_TO_UTF16("TCP/Ports", &VRDEPortsKey); + rc = VRDxServer->vtbl->GetVRDEProperty(VRDxServer, VRDEPortsKey, &VRDEPortsValue); + VBOX_UTF16_FREE(VRDEPortsKey); + if (VRDEPortsValue) { + /* even if vbox supports mutilpe ports, single port for now here */ + graphics->data.rdp.port = PRUnicharToInt(VRDEPortsValue); + VBOX_UTF16_FREE(VRDEPortsValue); + } else { + graphics->data.rdp.autoport = true; + } +#endif /* VBOX_API_VERSION >= 4000000 */ + return rc; +} + +static nsresult _vrdxServerSetPorts(vboxGlobalData *data ATTRIBUTE_UNUSED, IVRDxServer *VRDxServer, virDomainGraphicsDefPtr graphics) { @@ -9856,18 +10367,46 @@ _vrdxServerSetPorts(vboxGlobalData *data ATTRIBUTE_UNUSED, } static nsresult +_vrdxServerGetReuseSingleConnection(IVRDxServer *VRDxServer, PRBool *enabled) +{ + return VRDxServer->vtbl->GetReuseSingleConnection(VRDxServer, enabled); +} + +static nsresult _vrdxServerSetReuseSingleConnection(IVRDxServer *VRDxServer, PRBool enabled) { return VRDxServer->vtbl->SetReuseSingleConnection(VRDxServer, enabled); } static nsresult +_vrdxServerGetAllowMultiConnection(IVRDxServer *VRDxServer, PRBool *enabled) +{ + return VRDxServer->vtbl->GetAllowMultiConnection(VRDxServer, enabled); +} + +static nsresult _vrdxServerSetAllowMultiConnection(IVRDxServer *VRDxServer, PRBool enabled) { return VRDxServer->vtbl->SetAllowMultiConnection(VRDxServer, enabled); } static nsresult +_vrdxServerGetNetAddress(vboxGlobalData *data ATTRIBUTE_UNUSED, + IVRDxServer *VRDxServer, PRUnichar **netAddress) +{ +#if VBOX_API_VERSION >= 4000000 + PRUnichar *VRDENetAddressKey = NULL; + nsresult rc; + VBOX_UTF8_TO_UTF16("TCP/Address", &VRDENetAddressKey); + rc = VRDxServer->vtbl->GetVRDEProperty(VRDxServer, VRDENetAddressKey, netAddress); + VBOX_UTF16_FREE(VRDENetAddressKey); + return rc; +#else /* VBOX_API_VERSION < 4000000 */ + return VRDxServer->vtbl->GetNetAddress(VRDxServer, netAddress); +#endif /* VBOX_API_VERSION < 4000000 */ +} + +static nsresult _vrdxServerSetNetAddress(vboxGlobalData *data ATTRIBUTE_UNUSED, IVRDxServer *VRDxServer, PRUnichar *netAddress) { @@ -9902,6 +10441,17 @@ _usbCommonEnable(IUSBCommon *USBCommon ATTRIBUTE_UNUSED) } static nsresult +_usbCommonGetEnabled(IUSBCommon *USBCommon ATTRIBUTE_UNUSED, PRBool *enabled) +{ +#if VBOX_API_VERSION < 4003000 + return USBCommon->vtbl->GetEnabled(USBCommon, enabled); +#else /* VBOX_API_VERSION >= 4003000 */ + *enabled = true; + return 0; +#endif /* VBOX_API_VERSION >= 4003000 */ +} + +static nsresult _usbCommonCreateDeviceFilter(IUSBCommon *USBCommon, PRUnichar *name, IUSBDeviceFilter **filter) { @@ -9916,18 +10466,36 @@ _usbCommonInsertDeviceFilter(IUSBCommon *USBCommon, PRUint32 position, } static nsresult +_usbDeviceFilterGetProductId(IUSBDeviceFilter *USBDeviceFilter, PRUnichar **productId) +{ + return USBDeviceFilter->vtbl->GetProductId(USBDeviceFilter, productId); +} + +static nsresult _usbDeviceFilterSetProductId(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *productId) { return USBDeviceFilter->vtbl->SetProductId(USBDeviceFilter, productId); } static nsresult +_usbDeviceFilterGetActive(IUSBDeviceFilter *USBDeviceFilter, PRBool *active) +{ + return USBDeviceFilter->vtbl->GetActive(USBDeviceFilter, active); +} + +static nsresult _usbDeviceFilterSetActive(IUSBDeviceFilter *USBDeviceFilter, PRBool active) { return USBDeviceFilter->vtbl->SetActive(USBDeviceFilter, active); } static nsresult +_usbDeviceFilterGetVendorId(IUSBDeviceFilter *USBDeviceFilter, PRUnichar **vendorId) +{ + return USBDeviceFilter->vtbl->GetVendorId(USBDeviceFilter, vendorId); +} + +static nsresult _usbDeviceFilterSetVendorId(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *vendorId) { return USBDeviceFilter->vtbl->SetVendorId(USBDeviceFilter, vendorId); @@ -9938,6 +10506,22 @@ static nsresult _mediumGetId(IMedium *medium, vboxIIDUnion *iidu) return medium->vtbl->GetId(medium, &IID_MEMBER(value)); } +static nsresult _mediumGetLocation(IMedium *medium, PRUnichar **location) +{ + return medium->vtbl->GetLocation(medium, location); +} + +static nsresult _mediumGetReadOnly(IMedium *medium ATTRIBUTE_UNUSED, + PRBool *readOnly ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION < 3001000 + vboxUnsupported(); + return 0; +#else /* VBOX_API_VERSION >= 3001000 */ + return medium->vtbl->GetReadOnly(medium, readOnly); +#endif /* VBOX_API_VERSION >= 3001000 */ +} + static nsresult _mediumRelease(IMedium *medium) { return medium->vtbl->nsisupports.Release((nsISupports *)medium); @@ -9954,6 +10538,73 @@ static nsresult _mediumSetType(IMedium *medium ATTRIBUTE_UNUSED, #endif } +static nsresult +_mediumAttachmentGetMedium(IMediumAttachment *mediumAttachment ATTRIBUTE_UNUSED, + IMedium **medium ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION < 3001000 + vboxUnsupported(); + return 0; +#else /* VBOX_API_VERSION >= 3001000 */ + return mediumAttachment->vtbl->GetMedium(mediumAttachment, medium); +#endif /* VBOX_API_VERSION >= 3001000 */ +} + +static nsresult +_mediumAttachmentGetController(IMediumAttachment *mediumAttachment, + PRUnichar **controller) +{ + return mediumAttachment->vtbl->GetController(mediumAttachment, controller); +} + +static nsresult +_mediumAttachmentGetType(IMediumAttachment *mediumAttachment ATTRIBUTE_UNUSED, + PRUint32 *type ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION < 3001000 + vboxUnsupported(); + return 0; +#else /* VBOX_API_VERSION >= 3001000 */ + return mediumAttachment->vtbl->GetType(mediumAttachment, type); +#endif /* VBOX_API_VERSION >= 3001000 */ +} + +static nsresult +_mediumAttachmentGetPort(IMediumAttachment *mediumAttachment, PRInt32 *port) +{ + return mediumAttachment->vtbl->GetPort(mediumAttachment, port); +} + +static nsresult +_mediumAttachmentGetDevice(IMediumAttachment *mediumAttachment, PRInt32 *device) +{ + return mediumAttachment->vtbl->GetDevice(mediumAttachment, device); +} + +static nsresult +_storageControllerGetBus(IStorageController *storageController, PRUint32 *bus) +{ + return storageController->vtbl->GetBus(storageController, bus); +} + +static nsresult +_sharedFolderGetHostPath(ISharedFolder *sharedFolder, PRUnichar **hostPath) +{ + return sharedFolder->vtbl->GetHostPath(sharedFolder, hostPath); +} + +static nsresult +_sharedFolderGetName(ISharedFolder *sharedFolder, PRUnichar **name) +{ + return sharedFolder->vtbl->GetName(sharedFolder, name); +} + +static nsresult +_sharedFolderGetWritable(ISharedFolder *sharedFolder, PRBool *writable) +{ + return sharedFolder->vtbl->GetWritable(sharedFolder, writable); +} + static bool _machineStateOnline(PRUint32 state) { return ((state >= MachineState_FirstOnline) && @@ -10006,6 +10657,9 @@ static vboxUniformedArray _UArray = { .vboxArrayGet = vboxArrayGet, .vboxArrayRelease = vboxArrayRelease, .handleGetMachines = _handleGetMachines, + .handleUSBGetDeviceFilters = _handleUSBGetDeviceFilters, + .handleMachineGetMediumAttachments = _handleMachineGetMediumAttachments, + .handleMachineGetSharedFolders = _handleMachineGetSharedFolders, }; static vboxUniformednsISupports _nsUISupports = { @@ -10024,6 +10678,7 @@ static vboxUniformedIVirtualBox _UIVirtualBox = { static vboxUniformedIMachine _UIMachine = { .AddStorageController = _machineAddStorageController, + .GetStorageControllerByName = _machineGetStorageControllerByName, .AttachDevice = _machineAttachDevice, .CreateSharedFolder = _machineCreateSharedFolder, .LaunchVMProcess = _machineLaunchVMProcess, @@ -10043,11 +10698,17 @@ static vboxUniformedIMachine _UIMachine = { .SetCPUCount = _machineSetCPUCount, .GetMemorySize = _machineGetMemorySize, .SetMemorySize = _machineSetMemorySize, + .GetCPUProperty = _machineGetCPUProperty, .SetCPUProperty = _machineSetCPUProperty, + .GetBootOrder = _machineGetBootOrder, .SetBootOrder = _machineSetBootOrder, + .GetVRAMSize = _machineGetVRAMSize, .SetVRAMSize = _machineSetVRAMSize, + .GetMonitorCount = _machineGetMonitorCount, .SetMonitorCount = _machineSetMonitorCount, + .GetAccelerate3DEnabled = _machineGetAccelerate3DEnabled, .SetAccelerate3DEnabled = _machineSetAccelerate3DEnabled, + .GetAccelerate2DVideoEnabled = _machineGetAccelerate2DVideoEnabled, .SetAccelerate2DVideoEnabled = _machineSetAccelerate2DVideoEnabled, .GetExtraData = _machineGetExtraData, .SetExtraData = _machineSetExtraData, @@ -10089,21 +10750,32 @@ static vboxUniformedISystemProperties _UISystemProperties = { }; static vboxUniformedIBIOSSettings _UIBIOSSettings = { + .GetACPIEnabled = _biosSettingsGetACPIEnabled, .SetACPIEnabled = _biosSettingsSetACPIEnabled, + .GetIOAPICEnabled = _biosSettingsGetIOAPICEnabled, .SetIOAPICEnabled = _biosSettingsSetIOAPICEnabled, }; static vboxUniformedIAudioAdapter _UIAudioAdapter = { + .GetEnabled = _audioAdapterGetEnabled, .SetEnabled = _audioAdapterSetEnabled, + .GetAudioController = _audioAdapterGetAudioController, .SetAudioController = _audioAdapterSetAudioController, }; static vboxUniformedINetworkAdapter _UINetworkAdapter = { + .GetAttachmentType = _networkAdapterGetAttachmentType, + .GetEnabled = _networkAdapterGetEnabled, .SetEnabled = _networkAdapterSetEnabled, + .GetAdapterType = _networkAdapterGetAdapterType, .SetAdapterType = _networkAdapterSetAdapterType, + .GetBridgedInterface = _networkAdapterGetBridgedInterface, .SetBridgedInterface = _networkAdapterSetBridgedInterface, + .GetInternalNetwork = _networkAdapterGetInternalNetwork, .SetInternalNetwork = _networkAdapterSetInternalNetwork, + .GetHostOnlyInterface = _networkAdapterGetHostOnlyInterface, .SetHostOnlyInterface = _networkAdapterSetHostOnlyInterface, + .GetMACAddress = _networkAdapterGetMACAddress, .SetMACAddress = _networkAdapterSetMACAddress, .AttachToBridgedInterface = _networkAdapterAttachToBridgedInterface, .AttachToInternalNetwork = _networkAdapterAttachToInternalNetwork, @@ -10112,46 +10784,84 @@ static vboxUniformedINetworkAdapter _UINetworkAdapter = { }; static vboxUniformedISerialPort _UISerialPort = { + .GetEnabled = _serialPortGetEnabled, .SetEnabled = _serialPortSetEnabled, + .GetPath = _serialPortGetPath, .SetPath = _serialPortSetPath, + .GetIRQ = _serialPortGetIRQ, .SetIRQ = _serialPortSetIRQ, + .GetIOBase = _serialPortGetIOBase, .SetIOBase = _serialPortSetIOBase, + .GetHostMode = _serialPortGetHostMode, .SetHostMode = _serialPortSetHostMode, }; static vboxUniformedIParallelPort _UIParallelPort = { + .GetEnabled = _parallelPortGetEnabled, .SetEnabled = _parallelPortSetEnabled, + .GetPath = _parallelPortGetPath, .SetPath = _parallelPortSetPath, + .GetIRQ = _parallelPortGetIRQ, .SetIRQ = _parallelPortSetIRQ, + .GetIOBase = _parallelPortGetIOBase, .SetIOBase = _parallelPortSetIOBase, }; static vboxUniformedIVRDxServer _UIVRDxServer = { + .GetEnabled = _vrdxServerGetEnabled, .SetEnabled = _vrdxServerSetEnabled, + .GetPorts = _vrdxServerGetPorts, .SetPorts = _vrdxServerSetPorts, + .GetReuseSingleConnection = _vrdxServerGetReuseSingleConnection, .SetReuseSingleConnection = _vrdxServerSetReuseSingleConnection, + .GetAllowMultiConnection = _vrdxServerGetAllowMultiConnection, .SetAllowMultiConnection = _vrdxServerSetAllowMultiConnection, + .GetNetAddress = _vrdxServerGetNetAddress, .SetNetAddress = _vrdxServerSetNetAddress, }; static vboxUniformedIUSBCommon _UIUSBCommon = { .Enable = _usbCommonEnable, + .GetEnabled = _usbCommonGetEnabled, .CreateDeviceFilter = _usbCommonCreateDeviceFilter, .InsertDeviceFilter = _usbCommonInsertDeviceFilter, }; static vboxUniformedIUSBDeviceFilter _UIUSBDeviceFilter = { + .GetProductId = _usbDeviceFilterGetProductId, .SetProductId = _usbDeviceFilterSetProductId, + .GetActive = _usbDeviceFilterGetActive, .SetActive = _usbDeviceFilterSetActive, + .GetVendorId = _usbDeviceFilterGetVendorId, .SetVendorId = _usbDeviceFilterSetVendorId, }; static vboxUniformedIMedium _UIMedium = { .GetId = _mediumGetId, + .GetLocation = _mediumGetLocation, + .GetReadOnly = _mediumGetReadOnly, .Release = _mediumRelease, .SetType = _mediumSetType, }; +static vboxUniformedIMediumAttachment _UIMediumAttachment = { + .GetMedium = _mediumAttachmentGetMedium, + .GetController = _mediumAttachmentGetController, + .GetType = _mediumAttachmentGetType, + .GetPort = _mediumAttachmentGetPort, + .GetDevice = _mediumAttachmentGetDevice, +}; + +static vboxUniformedIStorageController _UIStorageController = { + .GetBus = _storageControllerGetBus, +}; + +static vboxUniformedISharedFolder _UISharedFolder = { + .GetHostPath = _sharedFolderGetHostPath, + .GetName = _sharedFolderGetName, + .GetWritable = _sharedFolderGetWritable, +}; + static uniformedMachineStateChecker _machineStateChecker = { .Online = _machineStateOnline, .NotStart = _machineStateNotStart, @@ -10171,6 +10881,9 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->deleteConfig = _deleteConfig; pVBoxAPI->vboxAttachDrivesOld = _vboxAttachDrivesOld; pVBoxAPI->vboxConvertState = _vboxConvertState; + pVBoxAPI->dumpIDEHDDsOld = _dumpIDEHDDsOld; + pVBoxAPI->dumpDVD = _dumpDVD; + pVBoxAPI->dumpFloppy = _dumpFloppy; pVBoxAPI->UPFN = _UPFN; pVBoxAPI->UIID = _UIID; pVBoxAPI->UArray = _UArray; @@ -10190,6 +10903,9 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->UIUSBCommon = _UIUSBCommon; pVBoxAPI->UIUSBDeviceFilter = _UIUSBDeviceFilter; pVBoxAPI->UIMedium = _UIMedium; + pVBoxAPI->UIMediumAttachment = _UIMediumAttachment; + pVBoxAPI->UIStorageController = _UIStorageController; + pVBoxAPI->UISharedFolder = _UISharedFolder; pVBoxAPI->machineStateChecker = _machineStateChecker; #if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 @@ -10223,8 +10939,10 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) #if VBOX_API_VERSION >= 3001000 pVBoxAPI->accelerate2DVideo = 1; + pVBoxAPI->oldMediumInterface = 0; #else /* VBOX_API_VERSION < 3001000 */ pVBoxAPI->accelerate2DVideo = 0; + pVBoxAPI->oldMediumInterface = 1; #endif /* VBOX_API_VERSION < 3001000 */ } diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index f67c109..f72d03f 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -168,6 +168,9 @@ typedef struct { void (*vboxArrayRelease)(vboxArray *array); /* Generate function pointers for vboxArrayGet */ void* (*handleGetMachines)(IVirtualBox *vboxObj); + void* (*handleUSBGetDeviceFilters)(IUSBCommon *USBCommon); + void* (*handleMachineGetMediumAttachments)(IMachine *machine); + void* (*handleMachineGetSharedFolders)(IMachine *machine); } vboxUniformedArray; /* Functions for nsISupports */ @@ -190,6 +193,8 @@ typedef struct { typedef struct { nsresult (*AddStorageController)(IMachine *machine, PRUnichar *name, PRUint32 connectionType, IStorageController **controller); + nsresult (*GetStorageControllerByName)(IMachine *machine, PRUnichar *name, + IStorageController **storageController); nsresult (*AttachDevice)(IMachine *machine, PRUnichar *name, PRInt32 controllerPort, PRInt32 device, PRUint32 type, IMedium *medium); @@ -216,11 +221,17 @@ typedef struct { nsresult (*SetCPUCount)(IMachine *machine, PRUint32 CPUCount); nsresult (*GetMemorySize)(IMachine *machine, PRUint32 *memorySize); nsresult (*SetMemorySize)(IMachine *machine, PRUint32 memorySize); + nsresult (*GetCPUProperty)(IMachine *machine, PRUint32 property, PRBool *value); nsresult (*SetCPUProperty)(IMachine *machine, PRUint32 property, PRBool value); + nsresult (*GetBootOrder)(IMachine *machine, PRUint32 position, PRUint32 *device); nsresult (*SetBootOrder)(IMachine *machine, PRUint32 position, PRUint32 device); + nsresult (*GetVRAMSize)(IMachine *machine, PRUint32 *VRAMSize); nsresult (*SetVRAMSize)(IMachine *machine, PRUint32 VRAMSize); + nsresult (*GetMonitorCount)(IMachine *machine, PRUint32 *monitorCount); nsresult (*SetMonitorCount)(IMachine *machine, PRUint32 monitorCount); + nsresult (*GetAccelerate3DEnabled)(IMachine *machine, PRBool *accelerate3DEnabled); nsresult (*SetAccelerate3DEnabled)(IMachine *machine, PRBool accelerate3DEnabled); + nsresult (*GetAccelerate2DVideoEnabled)(IMachine *machine, PRBool *accelerate2DVideoEnabled); nsresult (*SetAccelerate2DVideoEnabled)(IMachine *machine, PRBool accelerate2DVideoEnabled); nsresult (*GetExtraData)(IMachine *machine, PRUnichar *key, PRUnichar **value); nsresult (*SetExtraData)(IMachine *machine, PRUnichar *key, PRUnichar *value); @@ -270,23 +281,34 @@ typedef struct { /* Functions for IBIOSSettings */ typedef struct { + nsresult (*GetACPIEnabled)(IBIOSSettings *bios, PRBool *ACPIEnabled); nsresult (*SetACPIEnabled)(IBIOSSettings *bios, PRBool ACPIEnabled); + nsresult (*GetIOAPICEnabled)(IBIOSSettings *bios, PRBool *IOAPICEnabled); nsresult (*SetIOAPICEnabled)(IBIOSSettings *bios, PRBool IOAPICEnabled); } vboxUniformedIBIOSSettings; /* Functions for IAudioAdapter */ typedef struct { + nsresult (*GetEnabled)(IAudioAdapter *audioAdapter, PRBool *enabled); nsresult (*SetEnabled)(IAudioAdapter *audioAdapter, PRBool enabled); + nsresult (*GetAudioController)(IAudioAdapter *audioAdapter, PRUint32 *audioController); nsresult (*SetAudioController)(IAudioAdapter *audioAdapter, PRUint32 audioController); } vboxUniformedIAudioAdapter; /* Functions for INetworkAdapter */ typedef struct { + nsresult (*GetAttachmentType)(INetworkAdapter *adapter, PRUint32 *attachmentType); + nsresult (*GetEnabled)(INetworkAdapter *adapter, PRBool *enabled); nsresult (*SetEnabled)(INetworkAdapter *adapter, PRBool enabled); + nsresult (*GetAdapterType)(INetworkAdapter *adapter, PRUint32 *adapterType); nsresult (*SetAdapterType)(INetworkAdapter *adapter, PRUint32 adapterType); + nsresult (*GetBridgedInterface)(INetworkAdapter *adapter, PRUnichar **bridgedInterface); nsresult (*SetBridgedInterface)(INetworkAdapter *adapter, PRUnichar *bridgedInterface); + nsresult (*GetInternalNetwork)(INetworkAdapter *adapter, PRUnichar **internalNetwork); nsresult (*SetInternalNetwork)(INetworkAdapter *adapter, PRUnichar *internalNetwork); + nsresult (*GetHostOnlyInterface)(INetworkAdapter *adapter, PRUnichar **hostOnlyInterface); nsresult (*SetHostOnlyInterface)(INetworkAdapter *adapter, PRUnichar *hostOnlyInterface); + nsresult (*GetMACAddress)(INetworkAdapter *adapter, PRUnichar **MACAddress); nsresult (*SetMACAddress)(INetworkAdapter *adapter, PRUnichar *MACAddress); nsresult (*AttachToBridgedInterface)(INetworkAdapter *adapter); nsresult (*AttachToInternalNetwork)(INetworkAdapter *adapter); @@ -296,28 +318,44 @@ typedef struct { /* Functions for ISerialPort */ typedef struct { + nsresult (*GetEnabled)(ISerialPort *port, PRBool *enabled); nsresult (*SetEnabled)(ISerialPort *port, PRBool enabled); + nsresult (*GetPath)(ISerialPort *port, PRUnichar **path); nsresult (*SetPath)(ISerialPort *port, PRUnichar *path); + nsresult (*GetIRQ)(ISerialPort *port, PRUint32 *IRQ); nsresult (*SetIRQ)(ISerialPort *port, PRUint32 IRQ); + nsresult (*GetIOBase)(ISerialPort *port, PRUint32 *IOBase); nsresult (*SetIOBase)(ISerialPort *port, PRUint32 IOBase); + nsresult (*GetHostMode)(ISerialPort *port, PRUint32 *hostMode); nsresult (*SetHostMode)(ISerialPort *port, PRUint32 hostMode); } vboxUniformedISerialPort; /* Functions for IParallelPort */ typedef struct { + nsresult (*GetEnabled)(IParallelPort *port, PRBool *enabled); nsresult (*SetEnabled)(IParallelPort *port, PRBool enabled); + nsresult (*GetPath)(IParallelPort *port, PRUnichar **path); nsresult (*SetPath)(IParallelPort *port, PRUnichar *path); + nsresult (*GetIRQ)(IParallelPort *port, PRUint32 *IRQ); nsresult (*SetIRQ)(IParallelPort *port, PRUint32 IRQ); + nsresult (*GetIOBase)(IParallelPort *port, PRUint32 *IOBase); nsresult (*SetIOBase)(IParallelPort *port, PRUint32 IOBase); } vboxUniformedIParallelPort; /* Functions for IVRDPServer and IVRDEServer */ typedef struct { + nsresult (*GetEnabled)(IVRDxServer *VRDxServer, PRBool *enabled); nsresult (*SetEnabled)(IVRDxServer *VRDxServer, PRBool enabled); + nsresult (*GetPorts)(vboxGlobalData *data, IVRDxServer *VRDxServer, + virDomainGraphicsDefPtr graphics); nsresult (*SetPorts)(vboxGlobalData *data, IVRDxServer *VRDxServer, virDomainGraphicsDefPtr graphics); + nsresult (*GetReuseSingleConnection)(IVRDxServer *VRDxServer, PRBool *enabled); nsresult (*SetReuseSingleConnection)(IVRDxServer *VRDxServer, PRBool enabled); + nsresult (*GetAllowMultiConnection)(IVRDxServer *VRDxServer, PRBool *enabled); nsresult (*SetAllowMultiConnection)(IVRDxServer *VRDxServer, PRBool enabled); + nsresult (*GetNetAddress)(vboxGlobalData *data, IVRDxServer *VRDxServer, + PRUnichar **netAddress); nsresult (*SetNetAddress)(vboxGlobalData *data, IVRDxServer *VRDxServer, PRUnichar *netAddress); } vboxUniformedIVRDxServer; @@ -325,6 +363,7 @@ typedef struct { /* Common Functions for IUSBController and IUSBDeviceFilters */ typedef struct { nsresult (*Enable)(IUSBCommon *USBCommon); + nsresult (*GetEnabled)(IUSBCommon *USBCommon, PRBool *enabled); nsresult (*CreateDeviceFilter)(IUSBCommon *USBCommon, PRUnichar *name, IUSBDeviceFilter **filter); nsresult (*InsertDeviceFilter)(IUSBCommon *USBCommon, PRUint32 position, @@ -332,18 +371,45 @@ typedef struct { } vboxUniformedIUSBCommon; typedef struct { + nsresult (*GetProductId)(IUSBDeviceFilter *USBDeviceFilter, PRUnichar **productId); nsresult (*SetProductId)(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *productId); + nsresult (*GetActive)(IUSBDeviceFilter *USBDeviceFilter, PRBool *active); nsresult (*SetActive)(IUSBDeviceFilter *USBDeviceFilter, PRBool active); + nsresult (*GetVendorId)(IUSBDeviceFilter *USBDeviceFilter, PRUnichar **vendorId); nsresult (*SetVendorId)(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *vendorId); } vboxUniformedIUSBDeviceFilter; /* Functions for IMedium */ typedef struct { nsresult (*GetId)(IMedium *medium, vboxIIDUnion *iidu); + nsresult (*GetLocation)(IMedium *medium, PRUnichar **location); + nsresult (*GetReadOnly)(IMedium *medium, PRBool *readOnly); nsresult (*Release)(IMedium *medium); nsresult (*SetType)(IMedium *medium, PRUint32 type); } vboxUniformedIMedium; +/* Functions for IMediumAttachment */ +typedef struct { + nsresult (*GetMedium)(IMediumAttachment *mediumAttachment, IMedium **medium); + nsresult (*GetController)(IMediumAttachment *mediumAttachment, PRUnichar **controller); + nsresult (*GetType)(IMediumAttachment *mediumAttachment, PRUint32 *type); + nsresult (*GetPort)(IMediumAttachment *mediumAttachment, PRInt32 *port); + nsresult (*GetDevice)(IMediumAttachment *mediumAttachment, PRInt32 *device); +} vboxUniformedIMediumAttachment; + + +/* Functions for IStorageController */ +typedef struct { + nsresult (*GetBus)(IStorageController *storageController, PRUint32 *bus); +} vboxUniformedIStorageController; + +/* Functions for ISharedFolder */ +typedef struct { + nsresult (*GetHostPath)(ISharedFolder *sharedFolder, PRUnichar **hostPath); + nsresult (*GetName)(ISharedFolder *sharedFolder, PRUnichar **name); + nsresult (*GetWritable)(ISharedFolder *sharedFolder, PRBool *writable); +} vboxUniformedISharedFolder; + typedef struct { bool (*Online)(PRUint32 state); bool (*NotStart)(PRUint32 state); @@ -364,6 +430,9 @@ typedef struct { void (*deleteConfig)(IMachine *machine); void (*vboxAttachDrivesOld)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine); virDomainState (*vboxConvertState)(PRUint32 state); + void (*dumpIDEHDDsOld)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine); + void (*dumpDVD)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine); + void (*dumpFloppy)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine); vboxUniformedPFN UPFN; vboxUniformedIID UIID; vboxUniformedArray UArray; @@ -383,6 +452,9 @@ typedef struct { vboxUniformedIUSBCommon UIUSBCommon; vboxUniformedIUSBDeviceFilter UIUSBDeviceFilter; vboxUniformedIMedium UIMedium; + vboxUniformedIMediumAttachment UIMediumAttachment; + vboxUniformedIStorageController UIStorageController; + vboxUniformedISharedFolder UISharedFolder; uniformedMachineStateChecker machineStateChecker; /* vbox API features */ bool domainEventCallbacks; @@ -392,6 +464,7 @@ typedef struct { bool chipsetType; bool accelerate2DVideo; bool vboxAttachDrivesUseOld; + bool oldMediumInterface; } vboxUniformedAPI; /* libvirt API -- 1.7.9.5

--- src/vbox/vbox_common.c | 1076 ++++++++++++++++++++++++++++++++++- src/vbox/vbox_common.h | 9 + src/vbox/vbox_tmpl.c | 1261 +---------------------------------------- src/vbox/vbox_uniformed_api.h | 1 + 4 files changed, 1094 insertions(+), 1253 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 24d2ddb..fa9c0b0 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -109,7 +109,6 @@ if (!data->vboxObj) {\ #define ARRAY_GET_MACHINES \ (gVBoxAPI.UArray.handleGetMachines(data->vboxObj)) - /* global vbox API, used for all common codes. */ static vboxUniformedAPI gVBoxAPI; @@ -277,6 +276,66 @@ static bool vboxGetDeviceDetails(const char *deviceName, return true; } +/** + * function to generate the name for medium, + * for e.g: hda, sda, etc + * + * @returns null terminated string with device name or NULL + * for failures + * @param conn Input Connection Pointer + * @param storageBus Input storage bus type + * @param deviceInst Input device instance number + * @param devicePort Input port number + * @param deviceSlot Input slot number + * @param aMaxPortPerInst Input array of max port per device instance + * @param aMaxSlotPerPort Input array of max slot per device port + * + */ +static char *vboxGenerateMediumName(PRUint32 storageBus, + PRInt32 deviceInst, + PRInt32 devicePort, + PRInt32 deviceSlot, + PRUint32 *aMaxPortPerInst, + PRUint32 *aMaxSlotPerPort) +{ + const char *prefix = NULL; + char *name = NULL; + int total = 0; + PRUint32 maxPortPerInst = 0; + PRUint32 maxSlotPerPort = 0; + + if (!aMaxPortPerInst || + !aMaxSlotPerPort) + return NULL; + + if ((storageBus < StorageBus_IDE) || + (storageBus > StorageBus_Floppy)) + return NULL; + + maxPortPerInst = aMaxPortPerInst[storageBus]; + maxSlotPerPort = aMaxSlotPerPort[storageBus]; + total = (deviceInst * maxPortPerInst * maxSlotPerPort) + + (devicePort * maxSlotPerPort) + + deviceSlot; + + if (storageBus == StorageBus_IDE) { + prefix = "hd"; + } else if ((storageBus == StorageBus_SATA) || + (storageBus == StorageBus_SCSI)) { + prefix = "sd"; + } else if (storageBus == StorageBus_Floppy) { + prefix = "fd"; + } + + name = virIndexToDiskName(total, prefix); + + VIR_DEBUG("name=%s, total=%d, storageBus=%u, deviceInst=%d, " + "devicePort=%d deviceSlot=%d, maxPortPerInst=%u maxSlotPerPort=%u", + NULLSTR(name), total, storageBus, deviceInst, devicePort, + deviceSlot, maxPortPerInst, maxSlotPerPort); + return name; +} + static virDomainDefParserConfig vboxDomainDefParserConfig = { .macPrefix = { 0x08, 0x00, 0x27 }, }; @@ -2860,3 +2919,1018 @@ int vboxDomainGetMaxVcpus(virDomainPtr dom) return vboxDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)); } + +static void +vboxHostDeviceGetXMLDesc(vboxGlobalData *data, virDomainDefPtr def, IMachine *machine) +{ + IUSBCommon *USBCommon = NULL; + PRBool enabled = PR_FALSE; + vboxArray deviceFilters = VBOX_ARRAY_INITIALIZER; + size_t i; + PRUint32 USBFilterCount = 0; + + def->nhostdevs = 0; + + gVBoxAPI.UIMachine.GetUSBCommon(machine, &USBCommon); + if (!USBCommon) + return; + + gVBoxAPI.UIUSBCommon.GetEnabled(USBCommon, &enabled); + if (!enabled) + goto release_controller; + + gVBoxAPI.UArray.vboxArrayGet(&deviceFilters, USBCommon, + gVBoxAPI.UArray.handleUSBGetDeviceFilters(USBCommon)); + + if (deviceFilters.count <= 0) + goto release_filters; + + /* check if the filters are active and then only + * alloc mem and set def->nhostdevs + */ + + for (i = 0; i < deviceFilters.count; i++) { + PRBool active = PR_FALSE; + IUSBDeviceFilter *deviceFilter = deviceFilters.items[i]; + + gVBoxAPI.UIUSBDeviceFilter.GetActive(deviceFilter, &active); + if (active) { + def->nhostdevs++; + } + } + + if (def->nhostdevs == 0) + goto release_filters; + + /* Alloc mem needed for the filters now */ + if (VIR_ALLOC_N(def->hostdevs, def->nhostdevs) < 0) + goto release_filters; + + for (i = 0; i < def->nhostdevs; i++) { + def->hostdevs[i] = virDomainHostdevDefAlloc(); + if (!def->hostdevs[i]) + goto release_hostdevs; + } + + for (i = 0; i < deviceFilters.count; i++) { + PRBool active = PR_FALSE; + IUSBDeviceFilter *deviceFilter = deviceFilters.items[i]; + PRUnichar *vendorIdUtf16 = NULL; + char *vendorIdUtf8 = NULL; + unsigned vendorId = 0; + PRUnichar *productIdUtf16 = NULL; + char *productIdUtf8 = NULL; + unsigned productId = 0; + char *endptr = NULL; + + gVBoxAPI.UIUSBDeviceFilter.GetActive(deviceFilter, &active); + if (!active) + continue; + + def->hostdevs[USBFilterCount]->mode = + VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; + def->hostdevs[USBFilterCount]->source.subsys.type = + VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB; + + gVBoxAPI.UIUSBDeviceFilter.GetVendorId(deviceFilter, &vendorIdUtf16); + gVBoxAPI.UIUSBDeviceFilter.GetProductId(deviceFilter, &productIdUtf16); + + VBOX_UTF16_TO_UTF8(vendorIdUtf16, &vendorIdUtf8); + VBOX_UTF16_TO_UTF8(productIdUtf16, &productIdUtf8); + + ignore_value(virStrToLong_ui(vendorIdUtf8, &endptr, 16, &vendorId)); + ignore_value(virStrToLong_ui(productIdUtf8, &endptr, 16, &productId)); + + def->hostdevs[USBFilterCount]->source.subsys.u.usb.vendor = vendorId; + def->hostdevs[USBFilterCount]->source.subsys.u.usb.product = productId; + + VBOX_UTF16_FREE(vendorIdUtf16); + VBOX_UTF8_FREE(vendorIdUtf8); + + VBOX_UTF16_FREE(productIdUtf16); + VBOX_UTF8_FREE(productIdUtf8); + + USBFilterCount++; + } + + release_filters: + gVBoxAPI.UArray.vboxArrayRelease(&deviceFilters); + release_controller: + VBOX_RELEASE(USBCommon); + return; + + release_hostdevs: + for (i = 0; i < def->nhostdevs; i++) + virDomainHostdevDefFree(def->hostdevs[i]); + VIR_FREE(def->hostdevs); + + goto release_filters; +} + +static void +vboxDumpIDEHDDsNew(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + /* dump IDE hdds if present */ + vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER; + bool error = false; + int diskCount = 0; + size_t i; + PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {}; + PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {}; + + if (gVBoxAPI.oldMediumInterface) + VIR_WARN("This function may not work in current vbox version"); + + def->ndisks = 0; + gVBoxAPI.UArray.vboxArrayGet(&mediumAttachments, machine, + gVBoxAPI.UArray.handleMachineGetMediumAttachments(machine)); + + /* get the number of attachments */ + for (i = 0; i < mediumAttachments.count; i++) { + IMediumAttachment *imediumattach = mediumAttachments.items[i]; + if (imediumattach) { + IMedium *medium = NULL; + + gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &medium); + if (medium) { + def->ndisks++; + VBOX_RELEASE(medium); + } + } + } + + /* Allocate mem, if fails return error */ + if (VIR_ALLOC_N(def->disks, def->ndisks) >= 0) { + for (i = 0; i < def->ndisks; i++) { + virDomainDiskDefPtr disk = virDomainDiskDefNew(); + if (!disk) { + error = true; + break; + } + def->disks[i] = disk; + } + } else { + error = true; + } + + if (!error) + error = !vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, maxSlotPerPort); + + /* get the attachment details here */ + for (i = 0; i < mediumAttachments.count && diskCount < def->ndisks && !error; i++) { + IMediumAttachment *imediumattach = mediumAttachments.items[i]; + IStorageController *storageController = NULL; + PRUnichar *storageControllerName = NULL; + PRUint32 deviceType = DeviceType_Null; + PRUint32 storageBus = StorageBus_Null; + PRBool readOnly = PR_FALSE; + IMedium *medium = NULL; + PRUnichar *mediumLocUtf16 = NULL; + char *mediumLocUtf8 = NULL; + PRUint32 deviceInst = 0; + PRInt32 devicePort = 0; + PRInt32 deviceSlot = 0; + + if (!imediumattach) + continue; + + gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &medium); + if (!medium) + continue; + + gVBoxAPI.UIMediumAttachment.GetController(imediumattach, &storageControllerName); + if (!storageControllerName) { + VBOX_RELEASE(medium); + continue; + } + + gVBoxAPI.UIMachine.GetStorageControllerByName(machine, + storageControllerName, + &storageController); + VBOX_UTF16_FREE(storageControllerName); + if (!storageController) { + VBOX_RELEASE(medium); + continue; + } + + gVBoxAPI.UIMedium.GetLocation(medium, &mediumLocUtf16); + VBOX_UTF16_TO_UTF8(mediumLocUtf16, &mediumLocUtf8); + VBOX_UTF16_FREE(mediumLocUtf16); + ignore_value(virDomainDiskSetSource(def->disks[diskCount], + mediumLocUtf8)); + VBOX_UTF8_FREE(mediumLocUtf8); + + if (!virDomainDiskGetSource(def->disks[diskCount])) { + VBOX_RELEASE(medium); + VBOX_RELEASE(storageController); + error = true; + break; + } + + gVBoxAPI.UIStorageController.GetBus(storageController, &storageBus); + if (storageBus == StorageBus_IDE) { + def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_IDE; + } else if (storageBus == StorageBus_SATA) { + def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SATA; + } else if (storageBus == StorageBus_SCSI) { + def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SCSI; + } else if (storageBus == StorageBus_Floppy) { + def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_FDC; + } + + gVBoxAPI.UIMediumAttachment.GetType(imediumattach, &deviceType); + if (deviceType == DeviceType_HardDisk) + def->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_DISK; + else if (deviceType == DeviceType_Floppy) + def->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY; + else if (deviceType == DeviceType_DVD) + def->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_CDROM; + + gVBoxAPI.UIMediumAttachment.GetPort(imediumattach, &devicePort); + gVBoxAPI.UIMediumAttachment.GetDevice(imediumattach, &deviceSlot); + def->disks[diskCount]->dst = vboxGenerateMediumName(storageBus, + deviceInst, + devicePort, + deviceSlot, + maxPortPerInst, + maxSlotPerPort); + if (!def->disks[diskCount]->dst) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not generate medium name for the disk " + "at: controller instance:%u, port:%d, slot:%d"), + deviceInst, devicePort, deviceSlot); + VBOX_RELEASE(medium); + VBOX_RELEASE(storageController); + error = true; + break; + } + + gVBoxAPI.UIMedium.GetReadOnly(medium, &readOnly); + if (readOnly == PR_TRUE) + def->disks[diskCount]->src->readonly = true; + + virDomainDiskSetType(def->disks[diskCount], + VIR_STORAGE_TYPE_FILE); + + VBOX_RELEASE(medium); + VBOX_RELEASE(storageController); + diskCount++; + } + + gVBoxAPI.UArray.vboxArrayRelease(&mediumAttachments); + + /* cleanup on error */ + if (error) { + for (i = 0; i < def->ndisks; i++) { + VIR_FREE(def->disks[i]); + } + VIR_FREE(def->disks); + def->ndisks = 0; + } +} + +static void +vboxDumpVideo(virDomainDefPtr def, vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine) +{ + /* dump video options vram/2d/3d/directx/etc. */ + /* Currently supports only one graphics card */ + def->nvideos = 1; + if (VIR_ALLOC_N(def->videos, def->nvideos) >= 0) { + if (VIR_ALLOC(def->videos[0]) >= 0) { + /* the default is: vram is 8MB, One monitor, 3dAccel Off */ + PRUint32 VRAMSize = 8; + PRUint32 monitorCount = 1; + PRBool accelerate3DEnabled = PR_FALSE; + PRBool accelerate2DEnabled = PR_FALSE; + + gVBoxAPI.UIMachine.GetVRAMSize(machine, &VRAMSize); + gVBoxAPI.UIMachine.GetMonitorCount(machine, &monitorCount); + gVBoxAPI.UIMachine.GetAccelerate3DEnabled(machine, &accelerate3DEnabled); + if (gVBoxAPI.accelerate2DVideo) + gVBoxAPI.UIMachine.GetAccelerate2DVideoEnabled(machine, &accelerate2DEnabled); + + def->videos[0]->type = VIR_DOMAIN_VIDEO_TYPE_VBOX; + def->videos[0]->vram = VRAMSize * 1024; + def->videos[0]->heads = monitorCount; + if (VIR_ALLOC(def->videos[0]->accel) >= 0) { + def->videos[0]->accel->support3d = accelerate3DEnabled; + def->videos[0]->accel->support2d = accelerate2DEnabled; + } + } + } +} + +static void +vboxDumpDisplay(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + /* dump display options vrdp/gui/sdl */ + int vrdpPresent = 0; + int sdlPresent = 0; + int guiPresent = 0; + int totalPresent = 0; + char *guiDisplay = NULL; + char *sdlDisplay = NULL; + PRUnichar *keyTypeUtf16 = NULL; + PRUnichar *valueTypeUtf16 = NULL; + char *valueTypeUtf8 = NULL; + IVRDxServer *VRDxServer = NULL; + PRBool VRDxEnabled = PR_FALSE; + + def->ngraphics = 0; + + 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")) { + PRUnichar *keyDislpayUtf16 = NULL; + PRUnichar *valueDisplayUtf16 = NULL; + char *valueDisplayUtf8 = NULL; + + 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 + */ + } + totalPresent++; + } + + 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 + */ + } + totalPresent++; + } + VBOX_UTF8_FREE(valueDisplayUtf8); + } + + if (STREQ(valueTypeUtf8, "vrdp")) + vrdpPresent = 1; + + VBOX_UTF8_FREE(valueTypeUtf8); + } + + if ((totalPresent > 0) && (VIR_ALLOC_N(def->graphics, totalPresent) >= 0)) { + if ((guiPresent) && (VIR_ALLOC(def->graphics[def->ngraphics]) >= 0)) { + def->graphics[def->ngraphics]->type = VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP; + if (guiDisplay) + def->graphics[def->ngraphics]->data.desktop.display = guiDisplay; + def->ngraphics++; + } + + if ((sdlPresent) && (VIR_ALLOC(def->graphics[def->ngraphics]) >= 0)) { + def->graphics[def->ngraphics]->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL; + if (sdlDisplay) + def->graphics[def->ngraphics]->data.sdl.display = sdlDisplay; + def->ngraphics++; + } + } else if ((vrdpPresent != 1) && (totalPresent == 0) && (VIR_ALLOC_N(def->graphics, 1) >= 0)) { + if (VIR_ALLOC(def->graphics[def->ngraphics]) >= 0) { + const char *tmp; + def->graphics[def->ngraphics]->type = VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP; + tmp = virGetEnvBlockSUID("DISPLAY"); + if (VIR_STRDUP(def->graphics[def->ngraphics]->data.desktop.display, tmp) < 0) { + /* just don't go to cleanup yet as it is ok to have + * display as NULL + */ + } + totalPresent++; + def->ngraphics++; + } + } + + gVBoxAPI.UIMachine.GetVRDxServer(machine, &VRDxServer); + if (VRDxServer) { + gVBoxAPI.UIVRDxServer.GetEnabled(VRDxServer, &VRDxEnabled); + if (VRDxEnabled) { + + totalPresent++; + + if ((VIR_REALLOC_N(def->graphics, totalPresent) >= 0) && + (VIR_ALLOC(def->graphics[def->ngraphics]) >= 0)) { + PRUnichar *netAddressUtf16 = NULL; + char *netAddressUtf8 = NULL; + PRBool allowMultiConnection = PR_FALSE; + PRBool reuseSingleConnection = PR_FALSE; + + gVBoxAPI.UIVRDxServer.GetPorts(data, VRDxServer, def->graphics[def->ngraphics]); + + def->graphics[def->ngraphics]->type = VIR_DOMAIN_GRAPHICS_TYPE_RDP; + + gVBoxAPI.UIVRDxServer.GetNetAddress(data, VRDxServer, &netAddressUtf16); + if (netAddressUtf16) { + VBOX_UTF16_TO_UTF8(netAddressUtf16, &netAddressUtf8); + if (STRNEQ(netAddressUtf8, "")) + virDomainGraphicsListenSetAddress(def->graphics[def->ngraphics], 0, + netAddressUtf8, -1, true); + VBOX_UTF16_FREE(netAddressUtf16); + VBOX_UTF8_FREE(netAddressUtf8); + } + + gVBoxAPI.UIVRDxServer.GetAllowMultiConnection(VRDxServer, &allowMultiConnection); + if (allowMultiConnection) { + def->graphics[def->ngraphics]->data.rdp.multiUser = true; + } + + gVBoxAPI.UIVRDxServer.GetReuseSingleConnection(VRDxServer, &reuseSingleConnection); + if (reuseSingleConnection) { + def->graphics[def->ngraphics]->data.rdp.replaceUser = true; + } + + def->ngraphics++; + } else + virReportOOMError(); + } + VBOX_RELEASE(VRDxServer); + } +} + +static void +vboxDumpSharedFolders(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + /* shared folders */ + vboxArray sharedFolders = VBOX_ARRAY_INITIALIZER; + size_t i = 0; + + def->nfss = 0; + + gVBoxAPI.UArray.vboxArrayGet(&sharedFolders, machine, + gVBoxAPI.UArray.handleMachineGetSharedFolders(machine)); + + if (sharedFolders.count <= 0) + goto sharedFoldersCleanup; + + if (VIR_ALLOC_N(def->fss, sharedFolders.count) < 0) + goto sharedFoldersCleanup; + + for (i = 0; i < sharedFolders.count; i++) { + ISharedFolder *sharedFolder = sharedFolders.items[i]; + PRUnichar *nameUtf16 = NULL; + char *name = NULL; + PRUnichar *hostPathUtf16 = NULL; + char *hostPath = NULL; + PRBool writable = PR_FALSE; + + if (VIR_ALLOC(def->fss[i]) < 0) + goto sharedFoldersCleanup; + + def->fss[i]->type = VIR_DOMAIN_FS_TYPE_MOUNT; + + gVBoxAPI.UISharedFolder.GetHostPath(sharedFolder, &hostPathUtf16); + VBOX_UTF16_TO_UTF8(hostPathUtf16, &hostPath); + if (VIR_STRDUP(def->fss[i]->src, hostPath) < 0) { + VBOX_UTF8_FREE(hostPath); + VBOX_UTF16_FREE(hostPathUtf16); + goto sharedFoldersCleanup; + } + VBOX_UTF8_FREE(hostPath); + VBOX_UTF16_FREE(hostPathUtf16); + + gVBoxAPI.UISharedFolder.GetName(sharedFolder, &nameUtf16); + VBOX_UTF16_TO_UTF8(nameUtf16, &name); + if (VIR_STRDUP(def->fss[i]->dst, name) < 0) { + VBOX_UTF8_FREE(name); + VBOX_UTF16_FREE(nameUtf16); + goto sharedFoldersCleanup; + } + VBOX_UTF8_FREE(name); + VBOX_UTF16_FREE(nameUtf16); + + gVBoxAPI.UISharedFolder.GetWritable(sharedFolder, &writable); + def->fss[i]->readonly = !writable; + + ++def->nfss; + } + + sharedFoldersCleanup: + gVBoxAPI.UArray.vboxArrayRelease(&sharedFolders); +} + +static void +vboxDumpNetwork(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine, PRUint32 networkAdapterCount) +{ + PRUint32 netAdpIncCnt = 0; + size_t i = 0; + /* dump network cards if present */ + def->nnets = 0; + /* Get which network cards are enabled */ + for (i = 0; i < networkAdapterCount; i++) { + INetworkAdapter *adapter = NULL; + + gVBoxAPI.UIMachine.GetNetworkAdapter(machine, i, &adapter); + if (adapter) { + PRBool enabled = PR_FALSE; + + gVBoxAPI.UINetworkAdapter.GetEnabled(adapter, &enabled); + if (enabled) { + def->nnets++; + } + + VBOX_RELEASE(adapter); + } + } + + /* Allocate memory for the networkcards which are enabled */ + if ((def->nnets > 0) && (VIR_ALLOC_N(def->nets, def->nnets) >= 0)) { + for (i = 0; i < def->nnets; i++) { + ignore_value(VIR_ALLOC(def->nets[i])); + } + } + + /* Now get the details about the network cards here */ + for (i = 0; netAdpIncCnt < def->nnets && i < networkAdapterCount; i++) { + INetworkAdapter *adapter = NULL; + + gVBoxAPI.UIMachine.GetNetworkAdapter(machine, i, &adapter); + if (adapter) { + PRBool enabled = PR_FALSE; + + gVBoxAPI.UINetworkAdapter.GetEnabled(adapter, &enabled); + if (enabled) { + PRUint32 attachmentType = NetworkAttachmentType_Null; + PRUint32 adapterType = NetworkAdapterType_Null; + PRUnichar *MACAddressUtf16 = NULL; + char *MACAddress = NULL; + char macaddr[VIR_MAC_STRING_BUFLEN] = {0}; + + gVBoxAPI.UINetworkAdapter.GetAttachmentType(adapter, &attachmentType); + if (attachmentType == NetworkAttachmentType_NAT) { + + def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_USER; + + } else if (attachmentType == NetworkAttachmentType_Bridged) { + PRUnichar *hostIntUtf16 = NULL; + char *hostInt = NULL; + + def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_BRIDGE; + + gVBoxAPI.UINetworkAdapter.GetBridgedInterface(adapter, &hostIntUtf16); + + VBOX_UTF16_TO_UTF8(hostIntUtf16, &hostInt); + ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->data.bridge.brname, hostInt)); + + VBOX_UTF8_FREE(hostInt); + VBOX_UTF16_FREE(hostIntUtf16); + + } else if (attachmentType == NetworkAttachmentType_Internal) { + PRUnichar *intNetUtf16 = NULL; + char *intNet = NULL; + + def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_INTERNAL; + + gVBoxAPI.UINetworkAdapter.GetInternalNetwork(adapter, &intNetUtf16); + + VBOX_UTF16_TO_UTF8(intNetUtf16, &intNet); + ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->data.internal.name, intNet)); + + VBOX_UTF8_FREE(intNet); + VBOX_UTF16_FREE(intNetUtf16); + + } else if (attachmentType == NetworkAttachmentType_HostOnly) { + PRUnichar *hostIntUtf16 = NULL; + char *hostInt = NULL; + + def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_NETWORK; + + gVBoxAPI.UINetworkAdapter.GetHostOnlyInterface(adapter, &hostIntUtf16); + + VBOX_UTF16_TO_UTF8(hostIntUtf16, &hostInt); + ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->data.network.name, hostInt)); + + VBOX_UTF8_FREE(hostInt); + VBOX_UTF16_FREE(hostIntUtf16); + + } else { + /* default to user type i.e. NAT in VirtualBox if this + * dump is ever used to create a machine. + */ + def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_USER; + } + + gVBoxAPI.UINetworkAdapter.GetAdapterType(adapter, &adapterType); + if (adapterType == NetworkAdapterType_Am79C970A) { + ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "Am79C970A")); + } else if (adapterType == NetworkAdapterType_Am79C973) { + ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "Am79C973")); + } else if (adapterType == NetworkAdapterType_I82540EM) { + ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "82540EM")); + } else if (adapterType == NetworkAdapterType_I82545EM) { + ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "82545EM")); + } else if (adapterType == NetworkAdapterType_I82543GC) { + ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "82543GC")); + } else if (gVBoxAPI.APIVersion >= 3000051 && + adapterType == NetworkAdapterType_Virtio) { + /* Only vbox 3.1 and later support NetworkAdapterType_Virto */ + ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "virtio")); + } + + gVBoxAPI.UINetworkAdapter.GetMACAddress(adapter, &MACAddressUtf16); + VBOX_UTF16_TO_UTF8(MACAddressUtf16, &MACAddress); + snprintf(macaddr, VIR_MAC_STRING_BUFLEN, + "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", + MACAddress[0], MACAddress[1], MACAddress[2], MACAddress[3], + MACAddress[4], MACAddress[5], MACAddress[6], MACAddress[7], + MACAddress[8], MACAddress[9], MACAddress[10], MACAddress[11]); + + /* XXX some real error handling here some day ... */ + if (virMacAddrParse(macaddr, &def->nets[netAdpIncCnt]->mac) < 0) + {} + + netAdpIncCnt++; + + VBOX_UTF16_FREE(MACAddressUtf16); + VBOX_UTF8_FREE(MACAddress); + } + + VBOX_RELEASE(adapter); + } + } +} + +static void +vboxDumpAudio(virDomainDefPtr def, vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine) +{ + /* dump sound card if active */ + + /* Set def->nsounds to one as VirtualBox currently supports + * only one sound card + */ + IAudioAdapter *audioAdapter = NULL; + + gVBoxAPI.UIMachine.GetAudioAdapter(machine, &audioAdapter); + if (audioAdapter) { + PRBool enabled = PR_FALSE; + + gVBoxAPI.UIAudioAdapter.GetEnabled(audioAdapter, &enabled); + if (enabled) { + PRUint32 audioController = AudioControllerType_AC97; + + def->nsounds = 1; + if (VIR_ALLOC_N(def->sounds, def->nsounds) >= 0) { + if (VIR_ALLOC(def->sounds[0]) >= 0) { + gVBoxAPI.UIAudioAdapter.GetAudioController(audioAdapter, &audioController); + if (audioController == AudioControllerType_SB16) { + def->sounds[0]->model = VIR_DOMAIN_SOUND_MODEL_SB16; + } else if (audioController == AudioControllerType_AC97) { + def->sounds[0]->model = VIR_DOMAIN_SOUND_MODEL_AC97; + } + } else { + VIR_FREE(def->sounds); + def->nsounds = 0; + } + } else { + def->nsounds = 0; + } + } + VBOX_RELEASE(audioAdapter); + } +} + +static void +vboxDumpSerial(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine, PRUint32 serialPortCount) +{ + PRUint32 serialPortIncCount = 0; + size_t i = 0; + /* dump serial port if active */ + def->nserials = 0; + /* Get which serial ports are enabled/active */ + for (i = 0; i < serialPortCount; i++) { + ISerialPort *serialPort = NULL; + + gVBoxAPI.UIMachine.GetSerialPort(machine, i, &serialPort); + if (serialPort) { + PRBool enabled = PR_FALSE; + + gVBoxAPI.UISerialPort.GetEnabled(serialPort, &enabled); + if (enabled) { + def->nserials++; + } + + VBOX_RELEASE(serialPort); + } + } + + /* Allocate memory for the serial ports which are enabled */ + if ((def->nserials > 0) && (VIR_ALLOC_N(def->serials, def->nserials) >= 0)) { + for (i = 0; i < def->nserials; i++) { + ignore_value(VIR_ALLOC(def->serials[i])); + } + } + + /* Now get the details about the serial ports here */ + for (i = 0; + serialPortIncCount < def->nserials && i < serialPortCount; + i++) { + ISerialPort *serialPort = NULL; + + gVBoxAPI.UIMachine.GetSerialPort(machine, i, &serialPort); + if (serialPort) { + PRBool enabled = PR_FALSE; + + gVBoxAPI.UISerialPort.GetEnabled(serialPort, &enabled); + if (enabled) { + PRUint32 hostMode = PortMode_Disconnected; + PRUint32 IOBase = 0; + PRUint32 IRQ = 0; + PRUnichar *pathUtf16 = NULL; + char *path = NULL; + + gVBoxAPI.UISerialPort.GetHostMode(serialPort, &hostMode); + if (hostMode == PortMode_HostPipe) { + def->serials[serialPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_PIPE; + } else if (hostMode == PortMode_HostDevice) { + def->serials[serialPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_DEV; + } else if (gVBoxAPI.APIVersion >= 2002051 && + hostMode == PortMode_RawFile) { + /* PortMode RawFile is used for vbox 3.0 or later */ + def->serials[serialPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_FILE; + } else { + def->serials[serialPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_NULL; + } + + def->serials[serialPortIncCount]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL; + + gVBoxAPI.UISerialPort.GetIRQ(serialPort, &IRQ); + gVBoxAPI.UISerialPort.GetIOBase(serialPort, &IOBase); + if ((IRQ == 4) && (IOBase == 1016)) { + def->serials[serialPortIncCount]->target.port = 0; + } else if ((IRQ == 3) && (IOBase == 760)) { + def->serials[serialPortIncCount]->target.port = 1; + } + + gVBoxAPI.UISerialPort.GetPath(serialPort, &pathUtf16); + + if (pathUtf16) { + VBOX_UTF16_TO_UTF8(pathUtf16, &path); + ignore_value(VIR_STRDUP(def->serials[serialPortIncCount]->source.data.file.path, path)); + } + + serialPortIncCount++; + + VBOX_UTF16_FREE(pathUtf16); + VBOX_UTF8_FREE(path); + } + + VBOX_RELEASE(serialPort); + } + } +} + +static void +vboxDumpParallel(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine, PRUint32 parallelPortCount) +{ + PRUint32 parallelPortIncCount = 0; + size_t i = 0; + /* dump parallel ports if active */ + def->nparallels = 0; + /* Get which parallel ports are enabled/active */ + for (i = 0; i < parallelPortCount; i++) { + IParallelPort *parallelPort = NULL; + + gVBoxAPI.UIMachine.GetParallelPort(machine, i, ¶llelPort); + if (parallelPort) { + PRBool enabled = PR_FALSE; + + gVBoxAPI.UIParallelPort.GetEnabled(parallelPort, &enabled); + if (enabled) { + def->nparallels++; + } + + VBOX_RELEASE(parallelPort); + } + } + + /* Allocate memory for the parallel ports which are enabled */ + if ((def->nparallels > 0) && (VIR_ALLOC_N(def->parallels, def->nparallels) >= 0)) { + for (i = 0; i < def->nparallels; i++) { + ignore_value(VIR_ALLOC(def->parallels[i])); + } + } + + /* Now get the details about the parallel ports here */ + for (i = 0; + parallelPortIncCount < def->nparallels && + i < parallelPortCount; + i++) { + IParallelPort *parallelPort = NULL; + + gVBoxAPI.UIMachine.GetParallelPort(machine, i, ¶llelPort); + if (parallelPort) { + PRBool enabled = PR_FALSE; + + gVBoxAPI.UIParallelPort.GetEnabled(parallelPort, &enabled); + if (enabled) { + PRUint32 IOBase = 0; + PRUint32 IRQ = 0; + PRUnichar *pathUtf16 = NULL; + char *path = NULL; + + gVBoxAPI.UIParallelPort.GetIRQ(parallelPort, &IRQ); + gVBoxAPI.UIParallelPort.GetIOBase(parallelPort, &IOBase); + if ((IRQ == 7) && (IOBase == 888)) { + def->parallels[parallelPortIncCount]->target.port = 0; + } else if ((IRQ == 5) && (IOBase == 632)) { + def->parallels[parallelPortIncCount]->target.port = 1; + } + + def->parallels[parallelPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_FILE; + def->parallels[parallelPortIncCount]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL; + + gVBoxAPI.UIParallelPort.GetPath(parallelPort, &pathUtf16); + + VBOX_UTF16_TO_UTF8(pathUtf16, &path); + ignore_value(VIR_STRDUP(def->parallels[parallelPortIncCount]->source.data.file.path, path)); + + parallelPortIncCount++; + + VBOX_UTF16_FREE(pathUtf16); + VBOX_UTF8_FREE(path); + } + + VBOX_RELEASE(parallelPort); + } + } +} + +char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, char *, NULL); + virDomainDefPtr def = NULL; + IMachine *machine = NULL; + vboxIIDUnion iid; + PRBool accessible = PR_FALSE; + size_t i = 0; + PRBool PAEEnabled = PR_FALSE; + PRBool ACPIEnabled = PR_FALSE; + PRBool IOAPICEnabled = PR_FALSE; + PRUint32 CPUCount = 0; + PRUint32 memorySize = 0; + PRUint32 networkAdapterCount = 0; + PRUint32 maxMemorySize = 4 * 1024; + PRUint32 maxBootPosition = 0; + PRUint32 serialPortCount = 0; + PRUint32 parallelPortCount = 0; + IBIOSSettings *bios = NULL; + PRUint32 chipsetType = ChipsetType_Null; + ISystemProperties *systemProperties = NULL; + + /* Flags checked by virDomainDefFormat */ + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + if (VIR_ALLOC(def) < 0) + goto cleanup; + + gVBoxAPI.UIMachine.GetAccessible(machine, &accessible); + if (!accessible) + goto cleanup; + + def->virtType = VIR_DOMAIN_VIRT_VBOX; + def->id = dom->id; + memcpy(def->uuid, dom->uuid, VIR_UUID_BUFLEN); + if (VIR_STRDUP(def->name, dom->name) < 0) + goto cleanup; + + gVBoxAPI.UIMachine.GetMemorySize(machine, &memorySize); + def->mem.cur_balloon = memorySize * 1024; + + if (gVBoxAPI.chipsetType) + gVBoxAPI.UIMachine.GetChipsetType(machine, &chipsetType); + + gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties); + if (systemProperties) { + gVBoxAPI.UISystemProperties.GetMaxGuestRAM(systemProperties, &maxMemorySize); + gVBoxAPI.UISystemProperties.GetMaxBootPosition(systemProperties, &maxBootPosition); + gVBoxAPI.UISystemProperties.GetMaxNetworkAdapters(systemProperties, chipsetType, &networkAdapterCount); + gVBoxAPI.UISystemProperties.GetSerialPortCount(systemProperties, &serialPortCount); + gVBoxAPI.UISystemProperties.GetParallelPortCount(systemProperties, ¶llelPortCount); + VBOX_RELEASE(systemProperties); + systemProperties = NULL; + } + /* Currently setting memory and maxMemory as same, cause + * the notation here seems to be inconsistent while + * reading and while dumping xml + */ + /* def->mem.max_balloon = maxMemorySize * 1024; */ + def->mem.max_balloon = memorySize * 1024; + + gVBoxAPI.UIMachine.GetCPUCount(machine, &CPUCount); + def->maxvcpus = def->vcpus = CPUCount; + + /* Skip cpumasklen, cpumask, onReboot, onPoweroff, onCrash */ + + if (VIR_STRDUP(def->os.type, "hvm") < 0) + goto cleanup; + + def->os.arch = virArchFromHost(); + + def->os.nBootDevs = 0; + for (i = 0; (i < VIR_DOMAIN_BOOT_LAST) && (i < maxBootPosition); i++) { + PRUint32 device = DeviceType_Null; + + gVBoxAPI.UIMachine.GetBootOrder(machine, i+1, &device); + + if (device == DeviceType_Floppy) { + def->os.bootDevs[i] = VIR_DOMAIN_BOOT_FLOPPY; + def->os.nBootDevs++; + } else if (device == DeviceType_DVD) { + def->os.bootDevs[i] = VIR_DOMAIN_BOOT_CDROM; + def->os.nBootDevs++; + } else if (device == DeviceType_HardDisk) { + def->os.bootDevs[i] = VIR_DOMAIN_BOOT_DISK; + def->os.nBootDevs++; + } else if (device == DeviceType_Network) { + def->os.bootDevs[i] = VIR_DOMAIN_BOOT_NET; + def->os.nBootDevs++; + } else if (device == DeviceType_USB) { + /* Not supported by libvirt yet */ + } else if (device == DeviceType_SharedFolder) { + /* Not supported by libvirt yet */ + /* Can VirtualBox really boot from a shared folder? */ + } + } + + gVBoxAPI.UIMachine.GetCPUProperty(machine, CPUPropertyType_PAE, &PAEEnabled); + if (PAEEnabled) + def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_TRISTATE_SWITCH_ON; + + gVBoxAPI.UIMachine.GetBIOSSettings(machine, &bios); + if (bios) { + gVBoxAPI.UIBIOSSettings.GetACPIEnabled(bios, &ACPIEnabled); + if (ACPIEnabled) + def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_TRISTATE_SWITCH_ON; + + gVBoxAPI.UIBIOSSettings.GetIOAPICEnabled(bios, &IOAPICEnabled); + if (IOAPICEnabled) + def->features[VIR_DOMAIN_FEATURE_APIC] = VIR_TRISTATE_SWITCH_ON; + + VBOX_RELEASE(bios); + } + + /* Currently VirtualBox always uses locatime + * so locatime is always true here */ + def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME; + + vboxDumpVideo(def, data, machine); + vboxDumpDisplay(def, data, machine); + + /* As the medium interface changed from 3.0 to 3.1. + * There are two totally different implementations. + * The old one would be version specified, while the + * new one is using the vboxUniformedAPI and be put + * into the common code. + */ + if (gVBoxAPI.oldMediumInterface) + gVBoxAPI.dumpIDEHDDsOld(def, data, machine); + else + vboxDumpIDEHDDsNew(def, data, machine); + + vboxDumpSharedFolders(def, data, machine); + vboxDumpNetwork(def, data, machine, networkAdapterCount); + vboxDumpAudio(def, data, machine); + + if (gVBoxAPI.oldMediumInterface) { + gVBoxAPI.dumpDVD(def, data, machine); + gVBoxAPI.dumpFloppy(def, data, machine); + } + + vboxDumpSerial(def, data, machine, serialPortCount); + vboxDumpParallel(def, data, machine, parallelPortCount); + + /* dump USB devices/filters if active */ + vboxHostDeviceGetXMLDesc(data, def, machine); + + ret = virDomainDefFormat(def, flags); + + cleanup: + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + virDomainDefFree(def); + return ret; +} diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h index c4e7ae5..434689b 100644 --- a/src/vbox/vbox_common.h +++ b/src/vbox/vbox_common.h @@ -196,6 +196,15 @@ enum NetworkAdapterType NetworkAdapterType_Virtio = 6 }; +enum NetworkAttachmentType +{ + NetworkAttachmentType_Null = 0, + NetworkAttachmentType_NAT = 1, + NetworkAttachmentType_Bridged = 2, + NetworkAttachmentType_Internal = 3, + NetworkAttachmentType_HostOnly = 4 +}; + enum PortMode { PortMode_Disconnected = 0, diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 803b0cc..f017840 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -676,7 +676,6 @@ _vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu, #endif /* !(VBOX_API_VERSION == 2002000) */ -#if VBOX_API_VERSION >= 3001000 /** * function to generate the name for medium, @@ -693,6 +692,9 @@ _vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu, * @param aMaxSlotPerPort Input array of max slot per device port * */ +/* This functions is used for 4.2 and later only since vboxDomainGetXMLDesc + * is rewritten. */ +#if VBOX_API_VERSION >= 4002000 static char *vboxGenerateMediumName(PRUint32 storageBus, PRInt32 deviceInst, PRInt32 devicePort, @@ -737,6 +739,7 @@ static char *vboxGenerateMediumName(PRUint32 storageBus, deviceSlot, maxPortPerInst, maxSlotPerPort); return name; } +#endif /* VBOX_API_VERSION >= 4002000 */ /** * function to get the StorageBus, Port number @@ -754,6 +757,7 @@ static char *vboxGenerateMediumName(PRUint32 storageBus, * @param deviceSlot Output slot number * */ +#if VBOX_API_VERSION >= 3001000 # if VBOX_API_VERSION < 4000000 /* Only 3.x will use this function. */ static bool vboxGetDeviceDetails(const char *deviceName, @@ -813,6 +817,9 @@ static bool vboxGetDeviceDetails(const char *deviceName, * */ +/* This function would not be used in 4.0 and 4.1 since + * vboxDomainGetXMLDesc is written*/ +# if VBOX_API_VERSION >= 4002000 || VBOX_API_VERSION < 4000000 static bool vboxGetMaxPortSlotValues(IVirtualBox *vbox, PRUint32 *maxPortPerInst, PRUint32 *maxSlotPerPort) @@ -857,6 +864,7 @@ static bool vboxGetMaxPortSlotValues(IVirtualBox *vbox, return true; } +# endif /* VBOX_API_VERSION >= 4002000 || VBOX_API_VERSION < 4000000 */ /** * Converts Utf-16 string to int @@ -958,1257 +966,6 @@ static virDomainState _vboxConvertState(PRUint32 state) } } -static void vboxHostDeviceGetXMLDesc(vboxGlobalData *data, virDomainDefPtr def, IMachine *machine) -{ -#if VBOX_API_VERSION < 4003000 - IUSBController *USBController = NULL; - PRBool enabled = PR_FALSE; -#else - IUSBDeviceFilters *USBDeviceFilters = NULL; -#endif - vboxArray deviceFilters = VBOX_ARRAY_INITIALIZER; - size_t i; - PRUint32 USBFilterCount = 0; - - def->nhostdevs = 0; - -#if VBOX_API_VERSION < 4003000 - machine->vtbl->GetUSBController(machine, &USBController); - - if (!USBController) - return; - - USBController->vtbl->GetEnabled(USBController, &enabled); - if (!enabled) - goto release_controller; - - vboxArrayGet(&deviceFilters, USBController, - USBController->vtbl->GetDeviceFilters); - -#else - machine->vtbl->GetUSBDeviceFilters(machine, &USBDeviceFilters); - - if (!USBDeviceFilters) - return; - - vboxArrayGet(&deviceFilters, USBDeviceFilters, - USBDeviceFilters->vtbl->GetDeviceFilters); -#endif - - if (deviceFilters.count <= 0) - goto release_filters; - - /* check if the filters are active and then only - * alloc mem and set def->nhostdevs - */ - - for (i = 0; i < deviceFilters.count; i++) { - PRBool active = PR_FALSE; - IUSBDeviceFilter *deviceFilter = deviceFilters.items[i]; - - deviceFilter->vtbl->GetActive(deviceFilter, &active); - if (active) { - def->nhostdevs++; - } - } - - if (def->nhostdevs == 0) - goto release_filters; - - /* Alloc mem needed for the filters now */ - if (VIR_ALLOC_N(def->hostdevs, def->nhostdevs) < 0) - goto release_filters; - - for (i = 0; i < def->nhostdevs; i++) { - def->hostdevs[i] = virDomainHostdevDefAlloc(); - if (!def->hostdevs[i]) - goto release_hostdevs; - } - - for (i = 0; i < deviceFilters.count; i++) { - PRBool active = PR_FALSE; - IUSBDeviceFilter *deviceFilter = deviceFilters.items[i]; - PRUnichar *vendorIdUtf16 = NULL; - char *vendorIdUtf8 = NULL; - unsigned vendorId = 0; - PRUnichar *productIdUtf16 = NULL; - char *productIdUtf8 = NULL; - unsigned productId = 0; - char *endptr = NULL; - - deviceFilter->vtbl->GetActive(deviceFilter, &active); - if (!active) - continue; - - def->hostdevs[USBFilterCount]->mode = - VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; - def->hostdevs[USBFilterCount]->source.subsys.type = - VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB; - - deviceFilter->vtbl->GetVendorId(deviceFilter, &vendorIdUtf16); - deviceFilter->vtbl->GetProductId(deviceFilter, &productIdUtf16); - - VBOX_UTF16_TO_UTF8(vendorIdUtf16, &vendorIdUtf8); - VBOX_UTF16_TO_UTF8(productIdUtf16, &productIdUtf8); - - ignore_value(virStrToLong_ui(vendorIdUtf8, &endptr, 16, &vendorId)); - ignore_value(virStrToLong_ui(productIdUtf8, &endptr, 16, &productId)); - - def->hostdevs[USBFilterCount]->source.subsys.u.usb.vendor = vendorId; - def->hostdevs[USBFilterCount]->source.subsys.u.usb.product = productId; - - VBOX_UTF16_FREE(vendorIdUtf16); - VBOX_UTF8_FREE(vendorIdUtf8); - - VBOX_UTF16_FREE(productIdUtf16); - VBOX_UTF8_FREE(productIdUtf8); - - USBFilterCount++; - } - - release_filters: - vboxArrayRelease(&deviceFilters); -#if VBOX_API_VERSION < 4003000 - release_controller: - VBOX_RELEASE(USBController); -#else - VBOX_RELEASE(USBDeviceFilters); -#endif - - return; - - release_hostdevs: - for (i = 0; i < def->nhostdevs; i++) - virDomainHostdevDefFree(def->hostdevs[i]); - VIR_FREE(def->hostdevs); - - goto release_filters; -} - -static char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) { - VBOX_OBJECT_CHECK(dom->conn, char *, NULL); - virDomainDefPtr def = NULL; - IMachine *machine = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - int gotAllABoutDef = -1; - nsresult rc; - - /* Flags checked by virDomainDefFormat */ - - if (VIR_ALLOC(def) < 0) - goto cleanup; - - vboxIIDFromUUID(&iid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); - if (NS_SUCCEEDED(rc)) { - PRBool accessible = PR_FALSE; - - machine->vtbl->GetAccessible(machine, &accessible); - if (accessible) { - size_t i = 0; - PRBool PAEEnabled = PR_FALSE; - PRBool ACPIEnabled = PR_FALSE; - PRBool IOAPICEnabled = PR_FALSE; - PRBool VRDxEnabled = PR_FALSE; - PRUint32 CPUCount = 0; - PRUint32 memorySize = 0; - PRUint32 netAdpCnt = 0; - PRUint32 netAdpIncCnt = 0; - PRUint32 maxMemorySize = 4 * 1024; - PRUint32 maxBootPosition = 0; - PRUint32 serialPortCount = 0; - PRUint32 serialPortIncCount = 0; - PRUint32 parallelPortCount = 0; - PRUint32 parallelPortIncCount = 0; - IBIOSSettings *bios = NULL; -#if VBOX_API_VERSION < 3001000 - PRInt32 hddNum = 0; - IDVDDrive *dvdDrive = NULL; - IHardDisk *hardDiskPM = NULL; - IHardDisk *hardDiskPS = NULL; - IHardDisk *hardDiskSS = NULL; - const char *hddBus = "IDE"; - PRUnichar *hddBusUtf16 = NULL; - IFloppyDrive *floppyDrive = NULL; -#else /* VBOX_API_VERSION >= 3001000 */ - vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER; -#endif /* VBOX_API_VERSION >= 3001000 */ -#if VBOX_API_VERSION < 4000000 - IVRDPServer *VRDxServer = NULL; -#else /* VBOX_API_VERSION >= 4000000 */ - IVRDEServer *VRDxServer = NULL; -#endif /* VBOX_API_VERSION >= 4000000 */ - IAudioAdapter *audioAdapter = NULL; -#if VBOX_API_VERSION >= 4001000 - PRUint32 chipsetType = ChipsetType_Null; -#endif /* VBOX_API_VERSION >= 4001000 */ - ISystemProperties *systemProperties = NULL; - - - def->virtType = VIR_DOMAIN_VIRT_VBOX; - def->id = dom->id; - memcpy(def->uuid, dom->uuid, VIR_UUID_BUFLEN); - if (VIR_STRDUP(def->name, dom->name) < 0) - goto cleanup; - - machine->vtbl->GetMemorySize(machine, &memorySize); - def->mem.cur_balloon = memorySize * 1024; - -#if VBOX_API_VERSION >= 4001000 - machine->vtbl->GetChipsetType(machine, &chipsetType); -#endif /* VBOX_API_VERSION >= 4001000 */ - - data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties); - if (systemProperties) { - systemProperties->vtbl->GetMaxGuestRAM(systemProperties, &maxMemorySize); - systemProperties->vtbl->GetMaxBootPosition(systemProperties, &maxBootPosition); -#if VBOX_API_VERSION < 4001000 - systemProperties->vtbl->GetNetworkAdapterCount(systemProperties, &netAdpCnt); -#else /* VBOX_API_VERSION >= 4000000 */ - systemProperties->vtbl->GetMaxNetworkAdapters(systemProperties, chipsetType, &netAdpCnt); -#endif /* VBOX_API_VERSION >= 4000000 */ - systemProperties->vtbl->GetSerialPortCount(systemProperties, &serialPortCount); - systemProperties->vtbl->GetParallelPortCount(systemProperties, ¶llelPortCount); - VBOX_RELEASE(systemProperties); - systemProperties = NULL; - } - /* Currently setting memory and maxMemory as same, cause - * the notation here seems to be inconsistent while - * reading and while dumping xml - */ - /* def->mem.max_balloon = maxMemorySize * 1024; */ - def->mem.max_balloon = memorySize * 1024; - - machine->vtbl->GetCPUCount(machine, &CPUCount); - def->maxvcpus = def->vcpus = CPUCount; - - /* Skip cpumasklen, cpumask, onReboot, onPoweroff, onCrash */ - - if (VIR_STRDUP(def->os.type, "hvm") < 0) - goto cleanup; - - def->os.arch = virArchFromHost(); - - def->os.nBootDevs = 0; - for (i = 0; (i < VIR_DOMAIN_BOOT_LAST) && (i < maxBootPosition); i++) { - PRUint32 device = DeviceType_Null; - - machine->vtbl->GetBootOrder(machine, i+1, &device); - - if (device == DeviceType_Floppy) { - def->os.bootDevs[i] = VIR_DOMAIN_BOOT_FLOPPY; - def->os.nBootDevs++; - } else if (device == DeviceType_DVD) { - def->os.bootDevs[i] = VIR_DOMAIN_BOOT_CDROM; - def->os.nBootDevs++; - } else if (device == DeviceType_HardDisk) { - def->os.bootDevs[i] = VIR_DOMAIN_BOOT_DISK; - def->os.nBootDevs++; - } else if (device == DeviceType_Network) { - def->os.bootDevs[i] = VIR_DOMAIN_BOOT_NET; - def->os.nBootDevs++; - } else if (device == DeviceType_USB) { - /* Not supported by libvirt yet */ - } else if (device == DeviceType_SharedFolder) { - /* Not supported by libvirt yet */ - /* Can VirtualBox really boot from a shared folder? */ - } - } - -#if VBOX_API_VERSION < 3001000 - machine->vtbl->GetPAEEnabled(machine, &PAEEnabled); -#elif VBOX_API_VERSION == 3001000 - machine->vtbl->GetCpuProperty(machine, CpuPropertyType_PAE, &PAEEnabled); -#elif VBOX_API_VERSION >= 3002000 - machine->vtbl->GetCPUProperty(machine, CPUPropertyType_PAE, &PAEEnabled); -#endif - if (PAEEnabled) - def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_TRISTATE_SWITCH_ON; - - machine->vtbl->GetBIOSSettings(machine, &bios); - if (bios) { - bios->vtbl->GetACPIEnabled(bios, &ACPIEnabled); - if (ACPIEnabled) - def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_TRISTATE_SWITCH_ON; - - bios->vtbl->GetIOAPICEnabled(bios, &IOAPICEnabled); - if (IOAPICEnabled) - def->features[VIR_DOMAIN_FEATURE_APIC] = VIR_TRISTATE_SWITCH_ON; - - VBOX_RELEASE(bios); - } - - /* Currently VirtualBox always uses locatime - * so locatime is always true here */ - def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME; - - /* dump video options vram/2d/3d/directx/etc. */ - { - /* Currently supports only one graphics card */ - def->nvideos = 1; - if (VIR_ALLOC_N(def->videos, def->nvideos) >= 0) { - if (VIR_ALLOC(def->videos[0]) >= 0) { - /* the default is: vram is 8MB, One monitor, 3dAccel Off */ - PRUint32 VRAMSize = 8; - PRUint32 monitorCount = 1; - PRBool accelerate3DEnabled = PR_FALSE; - PRBool accelerate2DEnabled = PR_FALSE; - - machine->vtbl->GetVRAMSize(machine, &VRAMSize); - machine->vtbl->GetMonitorCount(machine, &monitorCount); - machine->vtbl->GetAccelerate3DEnabled(machine, &accelerate3DEnabled); -#if VBOX_API_VERSION >= 3001000 - machine->vtbl->GetAccelerate2DVideoEnabled(machine, &accelerate2DEnabled); -#endif /* VBOX_API_VERSION >= 3001000 */ - - def->videos[0]->type = VIR_DOMAIN_VIDEO_TYPE_VBOX; - def->videos[0]->vram = VRAMSize * 1024; - def->videos[0]->heads = monitorCount; - if (VIR_ALLOC(def->videos[0]->accel) >= 0) { - def->videos[0]->accel->support3d = accelerate3DEnabled; - def->videos[0]->accel->support2d = accelerate2DEnabled; - } - } - } - } - - /* dump display options vrdp/gui/sdl */ - { - int vrdpPresent = 0; - int sdlPresent = 0; - int guiPresent = 0; - int totalPresent = 0; - char *guiDisplay = NULL; - char *sdlDisplay = NULL; - PRUnichar *keyTypeUtf16 = NULL; - PRUnichar *valueTypeUtf16 = NULL; - char *valueTypeUtf8 = NULL; - - def->ngraphics = 0; - - 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")) { - PRUnichar *keyDislpayUtf16 = NULL; - PRUnichar *valueDisplayUtf16 = NULL; - char *valueDisplayUtf8 = NULL; - - 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 - */ - } - totalPresent++; - } - - 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 - */ - } - totalPresent++; - } - VBOX_UTF8_FREE(valueDisplayUtf8); - } - - if (STREQ(valueTypeUtf8, "vrdp")) - vrdpPresent = 1; - - VBOX_UTF8_FREE(valueTypeUtf8); - } - - if ((totalPresent > 0) && (VIR_ALLOC_N(def->graphics, totalPresent) >= 0)) { - if ((guiPresent) && (VIR_ALLOC(def->graphics[def->ngraphics]) >= 0)) { - def->graphics[def->ngraphics]->type = VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP; - if (guiDisplay) - def->graphics[def->ngraphics]->data.desktop.display = guiDisplay; - def->ngraphics++; - } - - if ((sdlPresent) && (VIR_ALLOC(def->graphics[def->ngraphics]) >= 0)) { - def->graphics[def->ngraphics]->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL; - if (sdlDisplay) - def->graphics[def->ngraphics]->data.sdl.display = sdlDisplay; - def->ngraphics++; - } - } else if ((vrdpPresent != 1) && (totalPresent == 0) && (VIR_ALLOC_N(def->graphics, 1) >= 0)) { - if (VIR_ALLOC(def->graphics[def->ngraphics]) >= 0) { - const char *tmp; - def->graphics[def->ngraphics]->type = VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP; - tmp = virGetEnvBlockSUID("DISPLAY"); - if (VIR_STRDUP(def->graphics[def->ngraphics]->data.desktop.display, tmp) < 0) { - /* just don't go to cleanup yet as it is ok to have - * display as NULL - */ - } - totalPresent++; - def->ngraphics++; - } - } - -#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) { - VRDxServer->vtbl->GetEnabled(VRDxServer, &VRDxEnabled); - if (VRDxEnabled) { - - totalPresent++; - - if ((VIR_REALLOC_N(def->graphics, totalPresent) >= 0) && - (VIR_ALLOC(def->graphics[def->ngraphics]) >= 0)) { - PRUnichar *netAddressUtf16 = NULL; - char *netAddressUtf8 = NULL; - PRBool allowMultiConnection = PR_FALSE; - PRBool reuseSingleConnection = PR_FALSE; -#if VBOX_API_VERSION < 3001000 - PRUint32 VRDPport = 0; - VRDxServer->vtbl->GetPort(VRDxServer, &VRDPport); - if (VRDPport) { - def->graphics[def->ngraphics]->data.rdp.port = VRDPport; - } else { - def->graphics[def->ngraphics]->data.rdp.autoport = true; - } -#elif VBOX_API_VERSION < 4000000 /* 3001000 <= VBOX_API_VERSION < 4000000 */ - PRUnichar *VRDPport = NULL; - VRDxServer->vtbl->GetPorts(VRDxServer, &VRDPport); - if (VRDPport) { - /* even if vbox supports mutilpe ports, single port for now here */ - def->graphics[def->ngraphics]->data.rdp.port = PRUnicharToInt(VRDPport); - VBOX_UTF16_FREE(VRDPport); - } else { - def->graphics[def->ngraphics]->data.rdp.autoport = true; - } -#else /* VBOX_API_VERSION >= 4000000 */ - PRUnichar *VRDEPortsKey = NULL; - PRUnichar *VRDEPortsValue = NULL; - VBOX_UTF8_TO_UTF16("TCP/Ports", &VRDEPortsKey); - VRDxServer->vtbl->GetVRDEProperty(VRDxServer, VRDEPortsKey, &VRDEPortsValue); - VBOX_UTF16_FREE(VRDEPortsKey); - if (VRDEPortsValue) { - /* even if vbox supports mutilpe ports, single port for now here */ - def->graphics[def->ngraphics]->data.rdp.port = PRUnicharToInt(VRDEPortsValue); - VBOX_UTF16_FREE(VRDEPortsValue); - } else { - def->graphics[def->ngraphics]->data.rdp.autoport = true; - } -#endif /* VBOX_API_VERSION >= 4000000 */ - - def->graphics[def->ngraphics]->type = VIR_DOMAIN_GRAPHICS_TYPE_RDP; - -#if VBOX_API_VERSION >= 4000000 - PRUnichar *VRDENetAddressKey = NULL; - VBOX_UTF8_TO_UTF16("TCP/Address", &VRDENetAddressKey); - VRDxServer->vtbl->GetVRDEProperty(VRDxServer, VRDENetAddressKey, &netAddressUtf16); - VBOX_UTF16_FREE(VRDENetAddressKey); -#else /* VBOX_API_VERSION < 4000000 */ - VRDxServer->vtbl->GetNetAddress(VRDxServer, &netAddressUtf16); -#endif /* VBOX_API_VERSION < 4000000 */ - if (netAddressUtf16) { - VBOX_UTF16_TO_UTF8(netAddressUtf16, &netAddressUtf8); - if (STRNEQ(netAddressUtf8, "")) - virDomainGraphicsListenSetAddress(def->graphics[def->ngraphics], 0, - netAddressUtf8, -1, true); - VBOX_UTF16_FREE(netAddressUtf16); - VBOX_UTF8_FREE(netAddressUtf8); - } - - VRDxServer->vtbl->GetAllowMultiConnection(VRDxServer, &allowMultiConnection); - if (allowMultiConnection) { - def->graphics[def->ngraphics]->data.rdp.multiUser = true; - } - - VRDxServer->vtbl->GetReuseSingleConnection(VRDxServer, &reuseSingleConnection); - if (reuseSingleConnection) { - def->graphics[def->ngraphics]->data.rdp.replaceUser = true; - } - - def->ngraphics++; - } else - virReportOOMError(); - } - VBOX_RELEASE(VRDxServer); - } - } - -#if VBOX_API_VERSION < 3001000 - /* dump IDE hdds if present */ - VBOX_UTF8_TO_UTF16(hddBus, &hddBusUtf16); - - def->ndisks = 0; - machine->vtbl->GetHardDisk(machine, hddBusUtf16, 0, 0, &hardDiskPM); - if (hardDiskPM) - def->ndisks++; - - machine->vtbl->GetHardDisk(machine, hddBusUtf16, 0, 1, &hardDiskPS); - if (hardDiskPS) - def->ndisks++; - - machine->vtbl->GetHardDisk(machine, hddBusUtf16, 1, 1, &hardDiskSS); - if (hardDiskSS) - def->ndisks++; - - VBOX_UTF16_FREE(hddBusUtf16); - - if ((def->ndisks > 0) && (VIR_ALLOC_N(def->disks, def->ndisks) >= 0)) { - for (i = 0; i < def->ndisks; i++) { - if ((def->disks[i] = virDomainDiskDefNew())) { - def->disks[i]->device = VIR_DOMAIN_DISK_DEVICE_DISK; - def->disks[i]->bus = VIR_DOMAIN_DISK_BUS_IDE; - virDomainDiskSetType(def->disks[i], - VIR_STORAGE_TYPE_FILE); - } - } - } - - if (hardDiskPM) { - PRUnichar *hddlocationUtf16 = NULL; - char *hddlocation = NULL; - PRUint32 hddType = HardDiskType_Normal; - - hardDiskPM->vtbl->imedium.GetLocation((IMedium *)hardDiskPM, &hddlocationUtf16); - VBOX_UTF16_TO_UTF8(hddlocationUtf16, &hddlocation); - - hardDiskPM->vtbl->GetType(hardDiskPM, &hddType); - - if (hddType == HardDiskType_Immutable) - def->disks[hddNum]->src->readonly = true; - ignore_value(virDomainDiskSetSource(def->disks[hddNum], - hddlocation)); - ignore_value(VIR_STRDUP(def->disks[hddNum]->dst, "hda")); - hddNum++; - - VBOX_UTF8_FREE(hddlocation); - VBOX_UTF16_FREE(hddlocationUtf16); - VBOX_MEDIUM_RELEASE(hardDiskPM); - } - - if (hardDiskPS) { - PRUnichar *hddlocationUtf16 = NULL; - char *hddlocation = NULL; - PRUint32 hddType = HardDiskType_Normal; - - hardDiskPS->vtbl->imedium.GetLocation((IMedium *)hardDiskPS, &hddlocationUtf16); - VBOX_UTF16_TO_UTF8(hddlocationUtf16, &hddlocation); - - hardDiskPS->vtbl->GetType(hardDiskPS, &hddType); - - if (hddType == HardDiskType_Immutable) - def->disks[hddNum]->src->readonly = true; - ignore_value(virDomainDiskSetSource(def->disks[hddNum], - hddlocation)); - ignore_value(VIR_STRDUP(def->disks[hddNum]->dst, "hdb")); - hddNum++; - - VBOX_UTF8_FREE(hddlocation); - VBOX_UTF16_FREE(hddlocationUtf16); - VBOX_MEDIUM_RELEASE(hardDiskPS); - } - - if (hardDiskSS) { - PRUnichar *hddlocationUtf16 = NULL; - char *hddlocation = NULL; - PRUint32 hddType = HardDiskType_Normal; - - hardDiskSS->vtbl->imedium.GetLocation((IMedium *)hardDiskSS, &hddlocationUtf16); - VBOX_UTF16_TO_UTF8(hddlocationUtf16, &hddlocation); - - hardDiskSS->vtbl->GetType(hardDiskSS, &hddType); - - if (hddType == HardDiskType_Immutable) - def->disks[hddNum]->src->readonly = true; - ignore_value(virDomainDiskSetSource(def->disks[hddNum], - hddlocation)); - ignore_value(VIR_STRDUP(def->disks[hddNum]->dst, "hdd")); - hddNum++; - - VBOX_UTF8_FREE(hddlocation); - VBOX_UTF16_FREE(hddlocationUtf16); - VBOX_MEDIUM_RELEASE(hardDiskSS); - } -#else /* VBOX_API_VERSION >= 3001000 */ - /* dump IDE hdds if present */ - - bool error = false; - int diskCount = 0; - PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {}; - PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {}; - def->ndisks = 0; - vboxArrayGet(&mediumAttachments, machine, machine->vtbl->GetMediumAttachments); - - /* get the number of attachments */ - for (i = 0; i < mediumAttachments.count; i++) { - IMediumAttachment *imediumattach = mediumAttachments.items[i]; - if (imediumattach) { - IMedium *medium = NULL; - - imediumattach->vtbl->GetMedium(imediumattach, &medium); - if (medium) { - def->ndisks++; - VBOX_RELEASE(medium); - } - } - } - - /* Allocate mem, if fails return error */ - if (VIR_ALLOC_N(def->disks, def->ndisks) >= 0) { - for (i = 0; i < def->ndisks; i++) { - virDomainDiskDefPtr disk = virDomainDiskDefNew(); - if (!disk) { - error = true; - break; - } - def->disks[i] = disk; - } - } else { - error = true; - } - - if (!error) - error = !vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, maxSlotPerPort); - - /* get the attachment details here */ - for (i = 0; i < mediumAttachments.count && diskCount < def->ndisks && !error; i++) { - IMediumAttachment *imediumattach = mediumAttachments.items[i]; - IStorageController *storageController = NULL; - PRUnichar *storageControllerName = NULL; - PRUint32 deviceType = DeviceType_Null; - PRUint32 storageBus = StorageBus_Null; - PRBool readOnly = PR_FALSE; - IMedium *medium = NULL; - PRUnichar *mediumLocUtf16 = NULL; - char *mediumLocUtf8 = NULL; - PRUint32 deviceInst = 0; - PRInt32 devicePort = 0; - PRInt32 deviceSlot = 0; - - if (!imediumattach) - continue; - - imediumattach->vtbl->GetMedium(imediumattach, &medium); - if (!medium) - continue; - - imediumattach->vtbl->GetController(imediumattach, &storageControllerName); - if (!storageControllerName) { - VBOX_RELEASE(medium); - continue; - } - - machine->vtbl->GetStorageControllerByName(machine, - storageControllerName, - &storageController); - VBOX_UTF16_FREE(storageControllerName); - if (!storageController) { - VBOX_RELEASE(medium); - continue; - } - - medium->vtbl->GetLocation(medium, &mediumLocUtf16); - VBOX_UTF16_TO_UTF8(mediumLocUtf16, &mediumLocUtf8); - VBOX_UTF16_FREE(mediumLocUtf16); - ignore_value(virDomainDiskSetSource(def->disks[diskCount], - mediumLocUtf8)); - VBOX_UTF8_FREE(mediumLocUtf8); - - if (!virDomainDiskGetSource(def->disks[diskCount])) { - VBOX_RELEASE(medium); - VBOX_RELEASE(storageController); - error = true; - break; - } - - storageController->vtbl->GetBus(storageController, &storageBus); - if (storageBus == StorageBus_IDE) { - def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_IDE; - } else if (storageBus == StorageBus_SATA) { - def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SATA; - } else if (storageBus == StorageBus_SCSI) { - def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SCSI; - } else if (storageBus == StorageBus_Floppy) { - def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_FDC; - } - - imediumattach->vtbl->GetType(imediumattach, &deviceType); - if (deviceType == DeviceType_HardDisk) - def->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_DISK; - else if (deviceType == DeviceType_Floppy) - def->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY; - else if (deviceType == DeviceType_DVD) - def->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_CDROM; - - imediumattach->vtbl->GetPort(imediumattach, &devicePort); - imediumattach->vtbl->GetDevice(imediumattach, &deviceSlot); - def->disks[diskCount]->dst = vboxGenerateMediumName(storageBus, - deviceInst, - devicePort, - deviceSlot, - maxPortPerInst, - maxSlotPerPort); - if (!def->disks[diskCount]->dst) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not generate medium name for the disk " - "at: controller instance:%u, port:%d, slot:%d"), - deviceInst, devicePort, deviceSlot); - VBOX_RELEASE(medium); - VBOX_RELEASE(storageController); - error = true; - break; - } - - medium->vtbl->GetReadOnly(medium, &readOnly); - if (readOnly == PR_TRUE) - def->disks[diskCount]->src->readonly = true; - - virDomainDiskSetType(def->disks[diskCount], - VIR_STORAGE_TYPE_FILE); - - VBOX_RELEASE(medium); - VBOX_RELEASE(storageController); - diskCount++; - } - - vboxArrayRelease(&mediumAttachments); - - /* cleanup on error */ - if (error) { - for (i = 0; i < def->ndisks; i++) { - VIR_FREE(def->disks[i]); - } - VIR_FREE(def->disks); - def->ndisks = 0; - } - -#endif /* VBOX_API_VERSION >= 3001000 */ - - /* shared folders */ - vboxArray sharedFolders = VBOX_ARRAY_INITIALIZER; - - def->nfss = 0; - - vboxArrayGet(&sharedFolders, machine, - machine->vtbl->GetSharedFolders); - - if (sharedFolders.count > 0) { - if (VIR_ALLOC_N(def->fss, sharedFolders.count) < 0) - goto sharedFoldersCleanup; - - for (i = 0; i < sharedFolders.count; i++) { - ISharedFolder *sharedFolder = sharedFolders.items[i]; - PRUnichar *nameUtf16 = NULL; - char *name = NULL; - PRUnichar *hostPathUtf16 = NULL; - char *hostPath = NULL; - PRBool writable = PR_FALSE; - - if (VIR_ALLOC(def->fss[i]) < 0) - goto sharedFoldersCleanup; - - def->fss[i]->type = VIR_DOMAIN_FS_TYPE_MOUNT; - - sharedFolder->vtbl->GetHostPath(sharedFolder, &hostPathUtf16); - VBOX_UTF16_TO_UTF8(hostPathUtf16, &hostPath); - if (VIR_STRDUP(def->fss[i]->src, hostPath) < 0) { - VBOX_UTF8_FREE(hostPath); - VBOX_UTF16_FREE(hostPathUtf16); - goto sharedFoldersCleanup; - } - VBOX_UTF8_FREE(hostPath); - VBOX_UTF16_FREE(hostPathUtf16); - - sharedFolder->vtbl->GetName(sharedFolder, &nameUtf16); - VBOX_UTF16_TO_UTF8(nameUtf16, &name); - if (VIR_STRDUP(def->fss[i]->dst, name) < 0) { - VBOX_UTF8_FREE(name); - VBOX_UTF16_FREE(nameUtf16); - goto sharedFoldersCleanup; - } - VBOX_UTF8_FREE(name); - VBOX_UTF16_FREE(nameUtf16); - - sharedFolder->vtbl->GetWritable(sharedFolder, &writable); - def->fss[i]->readonly = !writable; - - ++def->nfss; - } - } - - sharedFoldersCleanup: - vboxArrayRelease(&sharedFolders); - - /* dump network cards if present */ - def->nnets = 0; - /* Get which network cards are enabled */ - for (i = 0; i < netAdpCnt; i++) { - INetworkAdapter *adapter = NULL; - - machine->vtbl->GetNetworkAdapter(machine, i, &adapter); - if (adapter) { - PRBool enabled = PR_FALSE; - - adapter->vtbl->GetEnabled(adapter, &enabled); - if (enabled) { - def->nnets++; - } - - VBOX_RELEASE(adapter); - } - } - - /* Allocate memory for the networkcards which are enabled */ - if ((def->nnets > 0) && (VIR_ALLOC_N(def->nets, def->nnets) >= 0)) { - for (i = 0; i < def->nnets; i++) { - ignore_value(VIR_ALLOC(def->nets[i])); - } - } - - /* Now get the details about the network cards here */ - for (i = 0; netAdpIncCnt < def->nnets && i < netAdpCnt; i++) { - INetworkAdapter *adapter = NULL; - - machine->vtbl->GetNetworkAdapter(machine, i, &adapter); - if (adapter) { - PRBool enabled = PR_FALSE; - - adapter->vtbl->GetEnabled(adapter, &enabled); - if (enabled) { - PRUint32 attachmentType = NetworkAttachmentType_Null; - PRUint32 adapterType = NetworkAdapterType_Null; - PRUnichar *MACAddressUtf16 = NULL; - char *MACAddress = NULL; - char macaddr[VIR_MAC_STRING_BUFLEN] = {0}; - - adapter->vtbl->GetAttachmentType(adapter, &attachmentType); - if (attachmentType == NetworkAttachmentType_NAT) { - - def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_USER; - - } else if (attachmentType == NetworkAttachmentType_Bridged) { - PRUnichar *hostIntUtf16 = NULL; - char *hostInt = NULL; - - def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_BRIDGE; - -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->GetHostInterface(adapter, &hostIntUtf16); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->GetBridgedInterface(adapter, &hostIntUtf16); -#endif /* VBOX_API_VERSION >= 4001000 */ - - VBOX_UTF16_TO_UTF8(hostIntUtf16, &hostInt); - ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->data.bridge.brname, hostInt)); - - VBOX_UTF8_FREE(hostInt); - VBOX_UTF16_FREE(hostIntUtf16); - - } else if (attachmentType == NetworkAttachmentType_Internal) { - PRUnichar *intNetUtf16 = NULL; - char *intNet = NULL; - - def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_INTERNAL; - - adapter->vtbl->GetInternalNetwork(adapter, &intNetUtf16); - - VBOX_UTF16_TO_UTF8(intNetUtf16, &intNet); - ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->data.internal.name, intNet)); - - VBOX_UTF8_FREE(intNet); - VBOX_UTF16_FREE(intNetUtf16); - - } else if (attachmentType == NetworkAttachmentType_HostOnly) { - PRUnichar *hostIntUtf16 = NULL; - char *hostInt = NULL; - - def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_NETWORK; - -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->GetHostInterface(adapter, &hostIntUtf16); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->GetHostOnlyInterface(adapter, &hostIntUtf16); -#endif /* VBOX_API_VERSION >= 4001000 */ - - VBOX_UTF16_TO_UTF8(hostIntUtf16, &hostInt); - ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->data.network.name, hostInt)); - - VBOX_UTF8_FREE(hostInt); - VBOX_UTF16_FREE(hostIntUtf16); - - } else { - /* default to user type i.e. NAT in VirtualBox if this - * dump is ever used to create a machine. - */ - def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_USER; - } - - adapter->vtbl->GetAdapterType(adapter, &adapterType); - if (adapterType == NetworkAdapterType_Am79C970A) { - ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "Am79C970A")); - } else if (adapterType == NetworkAdapterType_Am79C973) { - ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "Am79C973")); - } else if (adapterType == NetworkAdapterType_I82540EM) { - ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "82540EM")); - } else if (adapterType == NetworkAdapterType_I82545EM) { - ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "82545EM")); - } else if (adapterType == NetworkAdapterType_I82543GC) { - ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "82543GC")); -#if VBOX_API_VERSION >= 3001000 - } else if (adapterType == NetworkAdapterType_Virtio) { - ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "virtio")); -#endif /* VBOX_API_VERSION >= 3001000 */ - } - - adapter->vtbl->GetMACAddress(adapter, &MACAddressUtf16); - VBOX_UTF16_TO_UTF8(MACAddressUtf16, &MACAddress); - snprintf(macaddr, VIR_MAC_STRING_BUFLEN, - "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", - MACAddress[0], MACAddress[1], MACAddress[2], MACAddress[3], - MACAddress[4], MACAddress[5], MACAddress[6], MACAddress[7], - MACAddress[8], MACAddress[9], MACAddress[10], MACAddress[11]); - - /* XXX some real error handling here some day ... */ - if (virMacAddrParse(macaddr, &def->nets[netAdpIncCnt]->mac) < 0) - {} - - netAdpIncCnt++; - - VBOX_UTF16_FREE(MACAddressUtf16); - VBOX_UTF8_FREE(MACAddress); - } - - VBOX_RELEASE(adapter); - } - } - - /* dump sound card if active */ - - /* Set def->nsounds to one as VirtualBox currently supports - * only one sound card - */ - - machine->vtbl->GetAudioAdapter(machine, &audioAdapter); - if (audioAdapter) { - PRBool enabled = PR_FALSE; - - audioAdapter->vtbl->GetEnabled(audioAdapter, &enabled); - if (enabled) { - PRUint32 audioController = AudioControllerType_AC97; - - def->nsounds = 1; - if (VIR_ALLOC_N(def->sounds, def->nsounds) >= 0) { - if (VIR_ALLOC(def->sounds[0]) >= 0) { - audioAdapter->vtbl->GetAudioController(audioAdapter, &audioController); - if (audioController == AudioControllerType_SB16) { - def->sounds[0]->model = VIR_DOMAIN_SOUND_MODEL_SB16; - } else if (audioController == AudioControllerType_AC97) { - def->sounds[0]->model = VIR_DOMAIN_SOUND_MODEL_AC97; - } - } else { - VIR_FREE(def->sounds); - def->nsounds = 0; - } - } else { - def->nsounds = 0; - } - } - VBOX_RELEASE(audioAdapter); - } - -#if VBOX_API_VERSION < 3001000 - /* dump CDROM/DVD if the drive is attached and has DVD/CD in it */ - machine->vtbl->GetDVDDrive(machine, &dvdDrive); - if (dvdDrive) { - PRUint32 state = DriveState_Null; - - dvdDrive->vtbl->GetState(dvdDrive, &state); - if (state == DriveState_ImageMounted) { - IDVDImage *dvdImage = NULL; - - dvdDrive->vtbl->GetImage(dvdDrive, &dvdImage); - if (dvdImage) { - PRUnichar *locationUtf16 = NULL; - char *location = NULL; - - dvdImage->vtbl->imedium.GetLocation((IMedium *)dvdImage, &locationUtf16); - VBOX_UTF16_TO_UTF8(locationUtf16, &location); - - def->ndisks++; - if (VIR_REALLOC_N(def->disks, def->ndisks) >= 0) { - if ((def->disks[def->ndisks - 1] = virDomainDiskDefNew())) { - def->disks[def->ndisks - 1]->device = VIR_DOMAIN_DISK_DEVICE_CDROM; - def->disks[def->ndisks - 1]->bus = VIR_DOMAIN_DISK_BUS_IDE; - virDomainDiskSetType(def->disks[def->ndisks - 1], - VIR_STORAGE_TYPE_FILE); - def->disks[def->ndisks - 1]->src->readonly = true; - ignore_value(virDomainDiskSetSource(def->disks[def->ndisks - 1], location)); - ignore_value(VIR_STRDUP(def->disks[def->ndisks - 1]->dst, "hdc")); - def->ndisks--; - } else { - def->ndisks--; - } - } else { - def->ndisks--; - } - - VBOX_UTF8_FREE(location); - VBOX_UTF16_FREE(locationUtf16); - VBOX_MEDIUM_RELEASE(dvdImage); - } - } - VBOX_RELEASE(dvdDrive); - } - - /* dump Floppy if the drive is attached and has floppy in it */ - machine->vtbl->GetFloppyDrive(machine, &floppyDrive); - if (floppyDrive) { - PRBool enabled = PR_FALSE; - - floppyDrive->vtbl->GetEnabled(floppyDrive, &enabled); - if (enabled) { - PRUint32 state = DriveState_Null; - - floppyDrive->vtbl->GetState(floppyDrive, &state); - if (state == DriveState_ImageMounted) { - IFloppyImage *floppyImage = NULL; - - floppyDrive->vtbl->GetImage(floppyDrive, &floppyImage); - if (floppyImage) { - PRUnichar *locationUtf16 = NULL; - char *location = NULL; - - floppyImage->vtbl->imedium.GetLocation((IMedium *)floppyImage, &locationUtf16); - VBOX_UTF16_TO_UTF8(locationUtf16, &location); - - def->ndisks++; - if (VIR_REALLOC_N(def->disks, def->ndisks) >= 0) { - if ((def->disks[def->ndisks - 1] = virDomainDiskDefNew())) { - def->disks[def->ndisks - 1]->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY; - def->disks[def->ndisks - 1]->bus = VIR_DOMAIN_DISK_BUS_FDC; - virDomainDiskSetType(def->disks[def->ndisks - 1], - VIR_STORAGE_TYPE_FILE); - def->disks[def->ndisks - 1]->src->readonly = false; - ignore_value(virDomainDiskSetSource(def->disks[def->ndisks - 1], location)); - ignore_value(VIR_STRDUP(def->disks[def->ndisks - 1]->dst, "fda")); - def->ndisks--; - } else { - def->ndisks--; - } - } else { - def->ndisks--; - } - - VBOX_UTF8_FREE(location); - VBOX_UTF16_FREE(locationUtf16); - VBOX_MEDIUM_RELEASE(floppyImage); - } - } - } - - VBOX_RELEASE(floppyDrive); - } -#else /* VBOX_API_VERSION >= 3001000 */ -#endif /* VBOX_API_VERSION >= 3001000 */ - - /* dump serial port if active */ - def->nserials = 0; - /* Get which serial ports are enabled/active */ - for (i = 0; i < serialPortCount; i++) { - ISerialPort *serialPort = NULL; - - machine->vtbl->GetSerialPort(machine, i, &serialPort); - if (serialPort) { - PRBool enabled = PR_FALSE; - - serialPort->vtbl->GetEnabled(serialPort, &enabled); - if (enabled) { - def->nserials++; - } - - VBOX_RELEASE(serialPort); - } - } - - /* Allocate memory for the serial ports which are enabled */ - if ((def->nserials > 0) && (VIR_ALLOC_N(def->serials, def->nserials) >= 0)) { - for (i = 0; i < def->nserials; i++) { - ignore_value(VIR_ALLOC(def->serials[i])); - } - } - - /* Now get the details about the serial ports here */ - for (i = 0; - serialPortIncCount < def->nserials && i < serialPortCount; - i++) { - ISerialPort *serialPort = NULL; - - machine->vtbl->GetSerialPort(machine, i, &serialPort); - if (serialPort) { - PRBool enabled = PR_FALSE; - - serialPort->vtbl->GetEnabled(serialPort, &enabled); - if (enabled) { - PRUint32 hostMode = PortMode_Disconnected; - PRUint32 IOBase = 0; - PRUint32 IRQ = 0; - PRUnichar *pathUtf16 = NULL; - char *path = NULL; - - serialPort->vtbl->GetHostMode(serialPort, &hostMode); - if (hostMode == PortMode_HostPipe) { - def->serials[serialPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_PIPE; - } else if (hostMode == PortMode_HostDevice) { - def->serials[serialPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_DEV; -#if VBOX_API_VERSION >= 3000000 - } else if (hostMode == PortMode_RawFile) { - def->serials[serialPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_FILE; -#endif /* VBOX_API_VERSION >= 3000000 */ - } else { - def->serials[serialPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_NULL; - } - - def->serials[serialPortIncCount]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL; - - serialPort->vtbl->GetIRQ(serialPort, &IRQ); - serialPort->vtbl->GetIOBase(serialPort, &IOBase); - if ((IRQ == 4) && (IOBase == 1016)) { - def->serials[serialPortIncCount]->target.port = 0; - } else if ((IRQ == 3) && (IOBase == 760)) { - def->serials[serialPortIncCount]->target.port = 1; - } - - serialPort->vtbl->GetPath(serialPort, &pathUtf16); - - if (pathUtf16) { - VBOX_UTF16_TO_UTF8(pathUtf16, &path); - ignore_value(VIR_STRDUP(def->serials[serialPortIncCount]->source.data.file.path, path)); - } - - serialPortIncCount++; - - VBOX_UTF16_FREE(pathUtf16); - VBOX_UTF8_FREE(path); - } - - VBOX_RELEASE(serialPort); - } - } - - /* dump parallel ports if active */ - def->nparallels = 0; - /* Get which parallel ports are enabled/active */ - for (i = 0; i < parallelPortCount; i++) { - IParallelPort *parallelPort = NULL; - - machine->vtbl->GetParallelPort(machine, i, ¶llelPort); - if (parallelPort) { - PRBool enabled = PR_FALSE; - - parallelPort->vtbl->GetEnabled(parallelPort, &enabled); - if (enabled) { - def->nparallels++; - } - - VBOX_RELEASE(parallelPort); - } - } - - /* Allocate memory for the parallel ports which are enabled */ - if ((def->nparallels > 0) && (VIR_ALLOC_N(def->parallels, def->nparallels) >= 0)) { - for (i = 0; i < def->nparallels; i++) { - ignore_value(VIR_ALLOC(def->parallels[i])); - } - } - - /* Now get the details about the parallel ports here */ - for (i = 0; - parallelPortIncCount < def->nparallels && - i < parallelPortCount; - i++) { - IParallelPort *parallelPort = NULL; - - machine->vtbl->GetParallelPort(machine, i, ¶llelPort); - if (parallelPort) { - PRBool enabled = PR_FALSE; - - parallelPort->vtbl->GetEnabled(parallelPort, &enabled); - if (enabled) { - PRUint32 IOBase = 0; - PRUint32 IRQ = 0; - PRUnichar *pathUtf16 = NULL; - char *path = NULL; - - parallelPort->vtbl->GetIRQ(parallelPort, &IRQ); - parallelPort->vtbl->GetIOBase(parallelPort, &IOBase); - if ((IRQ == 7) && (IOBase == 888)) { - def->parallels[parallelPortIncCount]->target.port = 0; - } else if ((IRQ == 5) && (IOBase == 632)) { - def->parallels[parallelPortIncCount]->target.port = 1; - } - - def->parallels[parallelPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_FILE; - def->parallels[parallelPortIncCount]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL; - - parallelPort->vtbl->GetPath(parallelPort, &pathUtf16); - - VBOX_UTF16_TO_UTF8(pathUtf16, &path); - ignore_value(VIR_STRDUP(def->parallels[parallelPortIncCount]->source.data.file.path, path)); - - parallelPortIncCount++; - - VBOX_UTF16_FREE(pathUtf16); - VBOX_UTF8_FREE(path); - } - - VBOX_RELEASE(parallelPort); - } - } - - /* dump USB devices/filters if active */ - vboxHostDeviceGetXMLDesc(data, def, machine); - - /* all done so set gotAllABoutDef and pass def to virDomainDefFormat - * to generate XML for it - */ - gotAllABoutDef = 0; - } - VBOX_RELEASE(machine); - machine = NULL; - } - - if (gotAllABoutDef == 0) - ret = virDomainDefFormat(def, flags); - - cleanup: - vboxIIDUnalloc(&iid); - virDomainDefFree(def); - return ret; -} - static int vboxConnectListDefinedDomains(virConnectPtr conn, char ** const names, int maxnames) { VBOX_OBJECT_CHECK(conn, int, -1); vboxArray machines = VBOX_ARRAY_INITIALIZER; diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index f72d03f..518dd2a 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -516,6 +516,7 @@ int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, int vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus); int vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags); int vboxDomainGetMaxVcpus(virDomainPtr dom); +char *vboxDomainGetXMLDesc(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 | 59 +++++++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 61 +++++------------------------------------ src/vbox/vbox_uniformed_api.h | 3 ++ 3 files changed, 69 insertions(+), 54 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index fa9c0b0..fcde620 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -3934,3 +3934,62 @@ char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) virDomainDefFree(def); return ret; } + +int vboxConnectListDefinedDomains(virConnectPtr conn, + char ** const names, int maxnames) +{ + VBOX_OBJECT_CHECK(conn, int, -1); + vboxArray machines = VBOX_ARRAY_INITIALIZER; + char *machineName = NULL; + PRUnichar *machineNameUtf16 = NULL; + 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 Defined Domains, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + + memset(names, 0, sizeof(names[i]) * maxnames); + + ret = 0; + for (i = 0, j = 0; (i < machines.count) && (j < maxnames); i++) { + PRBool isAccessible = PR_FALSE; + IMachine *machine = machines.items[i]; + + if (!machine) + continue; + + gVBoxAPI.UIMachine.GetAccessible(machine, &isAccessible); + if (!isAccessible) + continue; + + gVBoxAPI.UIMachine.GetState(machine, &state); + if (!gVBoxAPI.machineStateChecker.Inactive(state)) + continue; + + gVBoxAPI.UIMachine.GetName(machine, &machineNameUtf16); + VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineName); + if (VIR_STRDUP(names[j], machineName) < 0) { + VBOX_UTF16_FREE(machineNameUtf16); + VBOX_UTF8_FREE(machineName); + for (j = 0; j < maxnames; j++) + VIR_FREE(names[j]); + ret = -1; + goto cleanup; + } + VBOX_UTF16_FREE(machineNameUtf16); + VBOX_UTF8_FREE(machineName); + j++; + ret++; + } + + cleanup: + gVBoxAPI.UArray.vboxArrayRelease(&machines); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index f017840..7479f23 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -966,60 +966,6 @@ static virDomainState _vboxConvertState(PRUint32 state) } } -static int vboxConnectListDefinedDomains(virConnectPtr conn, char ** const names, int maxnames) { - VBOX_OBJECT_CHECK(conn, int, -1); - vboxArray machines = VBOX_ARRAY_INITIALIZER; - char *machineName = NULL; - PRUnichar *machineNameUtf16 = NULL; - 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 Defined Domains, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - - memset(names, 0, sizeof(names[i]) * maxnames); - - ret = 0; - for (i = 0, j = 0; (i < machines.count) && (j < maxnames); 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)) { - machine->vtbl->GetName(machine, &machineNameUtf16); - VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineName); - if (VIR_STRDUP(names[j], machineName) < 0) { - VBOX_UTF16_FREE(machineNameUtf16); - VBOX_UTF8_FREE(machineName); - for (j = 0; j < maxnames; j++) - VIR_FREE(names[j]); - ret = -1; - goto cleanup; - } - VBOX_UTF16_FREE(machineNameUtf16); - VBOX_UTF8_FREE(machineName); - j++; - ret++; - } - } - } - } - - cleanup: - vboxArrayRelease(&machines); - return ret; -} - static int vboxConnectNumOfDefinedDomains(virConnectPtr conn) { VBOX_OBJECT_CHECK(conn, int, -1); @@ -9368,6 +9314,12 @@ static bool _machineStateOnline(PRUint32 state) (state <= MachineState_LastOnline)); } +static bool _machineStateInactive(PRUint32 state) +{ + return ((state > MachineState_FirstOnline) && + (state < MachineState_LastOnline)); +} + static bool _machineStateNotStart(PRUint32 state) { return ((state == MachineState_PoweredOff) || @@ -9621,6 +9573,7 @@ static vboxUniformedISharedFolder _UISharedFolder = { static uniformedMachineStateChecker _machineStateChecker = { .Online = _machineStateOnline, + .Inactive = _machineStateInactive, .NotStart = _machineStateNotStart, .Running = _machineStateRunning, .Paused = _machineStatePaused, diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 518dd2a..7ff6b57 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -412,6 +412,7 @@ typedef struct { typedef struct { bool (*Online)(PRUint32 state); + bool (*Inactive)(PRUint32 state); bool (*NotStart)(PRUint32 state); bool (*Running)(PRUint32 state); bool (*Paused)(PRUint32 state); @@ -517,6 +518,8 @@ int vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus); int vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags); int vboxDomainGetMaxVcpus(virDomainPtr dom); char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags); +int vboxConnectListDefinedDomains(virConnectPtr conn, + char ** const names, int maxnames); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 38 -------------------------------------- src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 41 insertions(+), 38 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index fcde620..cd9fede 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -3993,3 +3993,43 @@ int vboxConnectListDefinedDomains(virConnectPtr conn, gVBoxAPI.UArray.vboxArrayRelease(&machines); return ret; } + +int vboxConnectNumOfDefinedDomains(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 Defined Domains, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + + ret = 0; + for (i = 0; i < machines.count; ++i) { + PRBool isAccessible = PR_FALSE; + IMachine *machine = machines.items[i]; + + if (!machine) + continue; + + gVBoxAPI.UIMachine.GetAccessible(machine, &isAccessible); + if (!isAccessible) + continue; + + gVBoxAPI.UIMachine.GetState(machine, &state); + if (gVBoxAPI.machineStateChecker.Inactive(state)) { + ret++; + } + } + + cleanup: + gVBoxAPI.UArray.vboxArrayRelease(&machines); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 7479f23..239ee67 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -966,44 +966,6 @@ static virDomainState _vboxConvertState(PRUint32 state) } } -static int vboxConnectNumOfDefinedDomains(virConnectPtr conn) -{ - VBOX_OBJECT_CHECK(conn, int, -1); - vboxArray machines = VBOX_ARRAY_INITIALIZER; - PRUint32 state = MachineState_Null; - 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 Defined 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; -} - #if VBOX_API_VERSION < 3001000 static void diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 7ff6b57..f57eaa9 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -520,6 +520,7 @@ int vboxDomainGetMaxVcpus(virDomainPtr dom); char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags); int vboxConnectListDefinedDomains(virConnectPtr conn, char ** const names, int maxnames); +int vboxConnectNumOfDefinedDomains(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 | 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 cd9fede..5b0706f 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -2066,6 +2066,11 @@ int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags) return ret; } +int vboxDomainUndefine(virDomainPtr dom) +{ + return vboxDomainUndefineFlags(dom, 0); +} + static int vboxStartMachine(virDomainPtr dom, int maxDomID, IMachine *machine, vboxIIDUnion *iid) { diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 239ee67..3651498 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1450,12 +1450,6 @@ _vboxAttachDrivesOld(virDomainDefPtr def ATTRIBUTE_UNUSED, #endif /* VBOX_API_VERSION >= 4000000 */ -static int -vboxDomainUndefine(virDomainPtr dom) -{ - return vboxDomainUndefineFlags(dom, 0); -} - static int vboxDomainAttachDeviceImpl(virDomainPtr dom, const char *xml, int mediaChangeOnly ATTRIBUTE_UNUSED) diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index f57eaa9..9488999 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -493,6 +493,7 @@ virDomainPtr vboxDomainLookupByName(virConnectPtr conn, const char *name); virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml); int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags); +int vboxDomainUndefine(virDomainPtr dom); int vboxDomainCreateWithFlags(virDomainPtr dom, unsigned int flags); int vboxDomainCreate(virDomainPtr dom); virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml, -- 1.7.9.5

--- src/vbox/vbox_common.c | 117 ++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 141 +++++++++++++++++++++++++++++++++++++++-- src/vbox/vbox_uniformed_api.h | 3 + 3 files changed, 256 insertions(+), 5 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 5b0706f..84d82d7 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -4038,3 +4038,120 @@ int vboxConnectNumOfDefinedDomains(virConnectPtr conn) gVBoxAPI.UArray.vboxArrayRelease(&machines); return ret; } + +static int vboxDomainAttachDeviceImpl(virDomainPtr dom, + const char *xml, + int mediaChangeOnly ATTRIBUTE_UNUSED) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IMachine *machine = NULL; + vboxIIDUnion iid; + PRUint32 state; + virDomainDefPtr def = NULL; + virDomainDeviceDefPtr dev = NULL; + nsresult rc; + + VBOX_IID_INITIALIZE(&iid); + if (VIR_ALLOC(def) < 0) + return ret; + + if (VIR_STRDUP(def->os.type, "hvm") < 0) + goto cleanup; + + dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, + VIR_DOMAIN_XML_INACTIVE); + if (dev == NULL) + goto cleanup; + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + if (!machine) + goto cleanup; + + gVBoxAPI.UIMachine.GetState(machine, &state); + + if (gVBoxAPI.machineStateChecker.Running(state) || + gVBoxAPI.machineStateChecker.Paused(state)) { + rc = gVBoxAPI.UISession.OpenExisting(data, &iid, machine); + } else { + rc = gVBoxAPI.UISession.Open(data, &iid, machine); + } + + if (NS_FAILED(rc)) + goto cleanup; + + rc = gVBoxAPI.UISession.GetMachine(data->vboxSession, &machine); + + if (NS_SUCCEEDED(rc) && machine) { + /* ret = -VIR_ERR_ARGUMENT_UNSUPPORTED means the current device don't support hotplug. */ + ret = -VIR_ERR_ARGUMENT_UNSUPPORTED; + if (dev->type == VIR_DOMAIN_DEVICE_DISK) { + if (gVBoxAPI.oldMediumInterface) { + const char *src = virDomainDiskGetSource(dev->data.disk); + int type = virDomainDiskGetType(dev->data.disk); + + if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { + if (type == VIR_STORAGE_TYPE_FILE && src) { + ret = gVBoxAPI.attachDVD(data, machine, src); + } else if (type == VIR_STORAGE_TYPE_BLOCK) { + } + } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { + if (type == VIR_STORAGE_TYPE_FILE && src) { + ret = gVBoxAPI.attachFloppy(data, machine, src); + } else if (type == VIR_STORAGE_TYPE_BLOCK) { + } + } + } + } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { + } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { + if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { + if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { + } + } + } else if (dev->type == VIR_DOMAIN_DEVICE_FS && + dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) { + PRUnichar *nameUtf16; + PRUnichar *hostPathUtf16; + PRBool writable; + + VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16); + VBOX_UTF8_TO_UTF16(dev->data.fs->src, &hostPathUtf16); + writable = !dev->data.fs->readonly; + + rc = gVBoxAPI.UIMachine.CreateSharedFolder(machine, nameUtf16, hostPathUtf16, + writable, PR_FALSE); + + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not attach shared folder '%s', rc=%08x"), + dev->data.fs->dst, (unsigned)rc); + ret = -1; + } else { + ret = 0; + } + + VBOX_UTF16_FREE(nameUtf16); + VBOX_UTF16_FREE(hostPathUtf16); + } + gVBoxAPI.UIMachine.SaveSettings(machine); + VBOX_RELEASE(machine); + + if (ret == -VIR_ERR_ARGUMENT_UNSUPPORTED) { + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, _("Unsupported device type %d"), dev->type); + ret = -1; + } + } + gVBoxAPI.UISession.Close(data->vboxSession); + + cleanup: + vboxIIDUnalloc(&iid); + virDomainDefFree(def); + virDomainDeviceDefFree(dev); + return ret; +} + +int vboxDomainAttachDevice(virDomainPtr dom, const char *xml) +{ + return vboxDomainAttachDeviceImpl(dom, xml, 0); +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 3651498..b80810d 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1649,11 +1649,6 @@ static int vboxDomainAttachDeviceImpl(virDomainPtr dom, return ret; } -static int vboxDomainAttachDevice(virDomainPtr dom, const char *xml) -{ - return vboxDomainAttachDeviceImpl(dom, xml, 0); -} - static int vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags) @@ -7812,6 +7807,63 @@ _dumpDVD(virDomainDefPtr def, VBOX_RELEASE(dvdDrive); } +static int +_attachDVD(vboxGlobalData *data, IMachine *machine, const char *src) +{ + IDVDDrive *dvdDrive = NULL; + IDVDImage *dvdImage = NULL; + PRUnichar *dvdfileUtf16 = NULL; + vboxIID dvduuid = VBOX_IID_INITIALIZER; + vboxIID dvdemptyuuid = VBOX_IID_INITIALIZER; + nsresult rc; + int ret = -1; + + /* Currently CDROM/DVD Drive is always IDE + * Secondary Master so neglecting the following + * parameter dev->data.disk->bus + */ + machine->vtbl->GetDVDDrive(machine, &dvdDrive); + if (!dvdDrive) + return ret; + + VBOX_UTF8_TO_UTF16(src, &dvdfileUtf16); + + data->vboxObj->vtbl->FindDVDImage(data->vboxObj, dvdfileUtf16, &dvdImage); + if (!dvdImage) { + data->vboxObj->vtbl->OpenDVDImage(data->vboxObj, dvdfileUtf16, dvdemptyuuid.value, &dvdImage); + } + + if (!dvdImage) + goto cleanup; + + rc = dvdImage->vtbl->imedium.GetId((IMedium *)dvdImage, &dvduuid.value); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("can't get the uuid of the file to " + "be attached to cdrom: %s, rc=%08x"), + src, (unsigned)rc); + } else { + /* unmount the previous mounted image */ + dvdDrive->vtbl->Unmount(dvdDrive); + rc = dvdDrive->vtbl->MountImage(dvdDrive, dvduuid.value); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not attach the file to cdrom: %s, rc=%08x"), + src, (unsigned)rc); + } else { + ret = 0; + DEBUGIID("CD/DVD Image UUID:", dvduuid.value); + } + } + + VBOX_MEDIUM_RELEASE(dvdImage); + cleanup: + vboxIIDUnalloc(&dvduuid); + VBOX_UTF16_FREE(dvdfileUtf16); + VBOX_RELEASE(dvdDrive); + return ret; +} + static void _dumpFloppy(virDomainDefPtr def, vboxGlobalData *data, @@ -7871,6 +7923,65 @@ _dumpFloppy(virDomainDefPtr def, VBOX_RELEASE(floppyDrive); } +static int +_attachFloppy(vboxGlobalData *data, IMachine *machine, const char *src) +{ + IFloppyDrive *floppyDrive; + IFloppyImage *floppyImage = NULL; + PRUnichar *fdfileUtf16 = NULL; + vboxIID fduuid = VBOX_IID_INITIALIZER; + vboxIID fdemptyuuid = VBOX_IID_INITIALIZER; + nsresult rc; + int ret = -1; + + machine->vtbl->GetFloppyDrive(machine, &floppyDrive); + if (!floppyDrive) + return ret; + + rc = floppyDrive->vtbl->SetEnabled(floppyDrive, 1); + if (NS_FAILED(rc)) + goto cleanup; + + VBOX_UTF8_TO_UTF16(src, &fdfileUtf16); + rc = data->vboxObj->vtbl->FindFloppyImage(data->vboxObj, + fdfileUtf16, + &floppyImage); + + if (!floppyImage) { + data->vboxObj->vtbl->OpenFloppyImage(data->vboxObj, + fdfileUtf16, + fdemptyuuid.value, + &floppyImage); + } + + if (floppyImage) { + rc = floppyImage->vtbl->imedium.GetId((IMedium *)floppyImage, &fduuid.value); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("can't get the uuid of the file to be " + "attached to floppy drive: %s, rc=%08x"), + src, (unsigned)rc); + } else { + rc = floppyDrive->vtbl->MountImage(floppyDrive, fduuid.value); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not attach the file to floppy drive: %s, rc=%08x"), + src, (unsigned)rc); + } else { + ret = 0; + DEBUGIID("attached floppy, UUID:", fduuid.value); + } + } + VBOX_MEDIUM_RELEASE(floppyImage); + } + vboxIIDUnalloc(&fduuid); + VBOX_UTF16_FREE(fdfileUtf16); + + cleanup: + VBOX_RELEASE(floppyDrive); + return ret; +} + #else /* VBOX_API_VERSION >= 3001000 */ static void @@ -7889,6 +8000,15 @@ _dumpDVD(virDomainDefPtr def ATTRIBUTE_UNUSED, vboxUnsupported(); } +static int +_attachDVD(vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine ATTRIBUTE_UNUSED, + const char *src ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); + return 0; +} + static void _dumpFloppy(virDomainDefPtr def ATTRIBUTE_UNUSED, vboxGlobalData *data ATTRIBUTE_UNUSED, @@ -7897,6 +8017,15 @@ _dumpFloppy(virDomainDefPtr def ATTRIBUTE_UNUSED, vboxUnsupported(); } +static int +_attachFloppy(vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine ATTRIBUTE_UNUSED, + const char *src ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); + return 0; +} + #endif /* VBOX_API_VERSION >= 3001000 */ static void _pfnUninitialize(vboxGlobalData *data) @@ -9549,7 +9678,9 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->vboxConvertState = _vboxConvertState; pVBoxAPI->dumpIDEHDDsOld = _dumpIDEHDDsOld; pVBoxAPI->dumpDVD = _dumpDVD; + pVBoxAPI->attachDVD = _attachDVD; pVBoxAPI->dumpFloppy = _dumpFloppy; + pVBoxAPI->attachFloppy = _attachFloppy; pVBoxAPI->UPFN = _UPFN; pVBoxAPI->UIID = _UIID; pVBoxAPI->UArray = _UArray; diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 9488999..1f82616 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -433,7 +433,9 @@ typedef struct { virDomainState (*vboxConvertState)(PRUint32 state); void (*dumpIDEHDDsOld)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine); void (*dumpDVD)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine); + int (*attachDVD)(vboxGlobalData *data, IMachine *machine, const char *src); void (*dumpFloppy)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine); + int (*attachFloppy)(vboxGlobalData *data, IMachine *machine, const char *src); vboxUniformedPFN UPFN; vboxUniformedIID UIID; vboxUniformedArray UArray; @@ -522,6 +524,7 @@ char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags); int vboxConnectListDefinedDomains(virConnectPtr conn, char ** const names, int maxnames); int vboxConnectNumOfDefinedDomains(virConnectPtr conn); +int vboxDomainAttachDevice(virDomainPtr dom, const char *xml); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 14 ++++++++++++++ src/vbox/vbox_tmpl.c | 15 --------------- src/vbox/vbox_uniformed_api.h | 2 ++ 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 84d82d7..f22cb5b 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -4155,3 +4155,17 @@ int vboxDomainAttachDevice(virDomainPtr dom, const char *xml) { return vboxDomainAttachDeviceImpl(dom, xml, 0); } + +int vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) +{ + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify the persistent configuration of a domain")); + return -1; + } + + return vboxDomainAttachDeviceImpl(dom, xml, 0); +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index b80810d..5078f27 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1649,21 +1649,6 @@ static int vboxDomainAttachDeviceImpl(virDomainPtr dom, return ret; } -static int -vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) -{ - virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); - - if (flags & VIR_DOMAIN_AFFECT_CONFIG) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return vboxDomainAttachDeviceImpl(dom, xml, 0); -} - static int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags) { diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 1f82616..69090f3 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -525,6 +525,8 @@ int vboxConnectListDefinedDomains(virConnectPtr conn, char ** const names, int maxnames); int vboxConnectNumOfDefinedDomains(virConnectPtr conn); int vboxDomainAttachDevice(virDomainPtr dom, const char *xml); +int vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

On 11.08.2014 12:06, Taowei wrote:
--- src/vbox/vbox_common.c | 14 ++++++++++++++ src/vbox/vbox_tmpl.c | 15 --------------- src/vbox/vbox_uniformed_api.h | 2 ++ 3 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 84d82d7..f22cb5b 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -4155,3 +4155,17 @@ int vboxDomainAttachDevice(virDomainPtr dom, const char *xml) { return vboxDomainAttachDeviceImpl(dom, xml, 0); } + +int vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) +{ + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify the persistent configuration of a domain")); + return -1; + }
I know you're just copying pre-existing code, but this doesn't make much sense to me. I'd just drop VIR_DOMAIN_AFFECT_CONFIG flag from the virCheckFlags(). Michal

Since vboxDomainAttachDeviceImple not used in vbox_tmpl.c, it has been deleted. --- src/vbox/vbox_common.c | 16 +++ src/vbox/vbox_tmpl.c | 215 ----------------------------------------- src/vbox/vbox_uniformed_api.h | 2 + 3 files changed, 18 insertions(+), 215 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index f22cb5b..71c97a0 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -4169,3 +4169,19 @@ int vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, return vboxDomainAttachDeviceImpl(dom, xml, 0); } + +int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) +{ + virCheckFlags(VIR_DOMAIN_AFFECT_CURRENT | + VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify the persistent configuration of a domain")); + return -1; + } + + return vboxDomainAttachDeviceImpl(dom, xml, 1); +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 5078f27..dd93e2a 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1450,221 +1450,6 @@ _vboxAttachDrivesOld(virDomainDefPtr def ATTRIBUTE_UNUSED, #endif /* VBOX_API_VERSION >= 4000000 */ -static int vboxDomainAttachDeviceImpl(virDomainPtr dom, - const char *xml, - int mediaChangeOnly ATTRIBUTE_UNUSED) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IMachine *machine = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - PRUint32 state = MachineState_Null; - virDomainDefPtr def = NULL; - virDomainDeviceDefPtr dev = NULL; - nsresult rc; - - if (VIR_ALLOC(def) < 0) - return ret; - - if (VIR_STRDUP(def->os.type, "hvm") < 0) - goto cleanup; - - dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, - VIR_DOMAIN_XML_INACTIVE); - if (dev == NULL) - goto cleanup; - - 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; - } - - if (machine) { - machine->vtbl->GetState(machine, &state); - - if ((state == MachineState_Running) || - (state == MachineState_Paused)) { - rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); - } else { - 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 (dev->type == VIR_DOMAIN_DEVICE_DISK) { -#if VBOX_API_VERSION < 3001000 - const char *src = virDomainDiskGetSource(dev->data.disk); - int type = virDomainDiskGetType(dev->data.disk); - - if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { - if (type == VIR_STORAGE_TYPE_FILE && src) { - IDVDDrive *dvdDrive = NULL; - /* Currently CDROM/DVD Drive is always IDE - * Secondary Master so neglecting the following - * parameter dev->data.disk->bus - */ - machine->vtbl->GetDVDDrive(machine, &dvdDrive); - if (dvdDrive) { - IDVDImage *dvdImage = NULL; - PRUnichar *dvdfileUtf16 = NULL; - vboxIID dvduuid = VBOX_IID_INITIALIZER; - vboxIID dvdemptyuuid = VBOX_IID_INITIALIZER; - - VBOX_UTF8_TO_UTF16(src, &dvdfileUtf16); - - data->vboxObj->vtbl->FindDVDImage(data->vboxObj, dvdfileUtf16, &dvdImage); - if (!dvdImage) { - data->vboxObj->vtbl->OpenDVDImage(data->vboxObj, dvdfileUtf16, dvdemptyuuid.value, &dvdImage); - } - if (dvdImage) { - rc = dvdImage->vtbl->imedium.GetId((IMedium *)dvdImage, &dvduuid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("can't get the uuid of the file to " - "be attached to cdrom: %s, rc=%08x"), - src, (unsigned)rc); - } else { - /* unmount the previous mounted image */ - dvdDrive->vtbl->Unmount(dvdDrive); - rc = dvdDrive->vtbl->MountImage(dvdDrive, dvduuid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not attach the file to cdrom: %s, rc=%08x"), - src, (unsigned)rc); - } else { - ret = 0; - DEBUGIID("CD/DVD Image UUID:", dvduuid.value); - } - } - - VBOX_MEDIUM_RELEASE(dvdImage); - } - vboxIIDUnalloc(&dvduuid); - VBOX_UTF16_FREE(dvdfileUtf16); - VBOX_RELEASE(dvdDrive); - } - } else if (type == VIR_STORAGE_TYPE_BLOCK) { - } - } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { - if (type == VIR_STORAGE_TYPE_FILE && src) { - IFloppyDrive *floppyDrive; - machine->vtbl->GetFloppyDrive(machine, &floppyDrive); - if (floppyDrive) { - rc = floppyDrive->vtbl->SetEnabled(floppyDrive, 1); - if (NS_SUCCEEDED(rc)) { - IFloppyImage *floppyImage = NULL; - PRUnichar *fdfileUtf16 = NULL; - vboxIID fduuid = VBOX_IID_INITIALIZER; - vboxIID fdemptyuuid = VBOX_IID_INITIALIZER; - VBOX_UTF8_TO_UTF16(src, &fdfileUtf16); - rc = data->vboxObj->vtbl->FindFloppyImage(data->vboxObj, - fdfileUtf16, - &floppyImage); - - if (!floppyImage) { - data->vboxObj->vtbl->OpenFloppyImage(data->vboxObj, - fdfileUtf16, - fdemptyuuid.value, - &floppyImage); - } - - if (floppyImage) { - rc = floppyImage->vtbl->imedium.GetId((IMedium *)floppyImage, &fduuid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("can't get the uuid of the file to be " - "attached to floppy drive: %s, rc=%08x"), - src, (unsigned)rc); - } else { - rc = floppyDrive->vtbl->MountImage(floppyDrive, fduuid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not attach the file to floppy drive: %s, rc=%08x"), - src, (unsigned)rc); - } else { - ret = 0; - DEBUGIID("attached floppy, UUID:", fduuid.value); - } - } - VBOX_MEDIUM_RELEASE(floppyImage); - } - vboxIIDUnalloc(&fduuid); - VBOX_UTF16_FREE(fdfileUtf16); - } - VBOX_RELEASE(floppyDrive); - } - } else if (type == VIR_STORAGE_TYPE_BLOCK) { - } - } -#else /* VBOX_API_VERSION >= 3001000 */ -#endif /* VBOX_API_VERSION >= 3001000 */ - } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { - } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { - if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { - if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { - } - } - } else if (dev->type == VIR_DOMAIN_DEVICE_FS && - dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) { - PRUnichar *nameUtf16; - PRUnichar *hostPathUtf16; - PRBool writable; - - VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16); - VBOX_UTF8_TO_UTF16(dev->data.fs->src, &hostPathUtf16); - writable = !dev->data.fs->readonly; - -#if VBOX_API_VERSION < 4000000 - rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16, - writable); -#else /* VBOX_API_VERSION >= 4000000 */ - rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16, - writable, PR_FALSE); -#endif /* VBOX_API_VERSION >= 4000000 */ - - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not attach shared folder '%s', rc=%08x"), - dev->data.fs->dst, (unsigned)rc); - } else { - ret = 0; - } - - VBOX_UTF16_FREE(nameUtf16); - VBOX_UTF16_FREE(hostPathUtf16); - } - machine->vtbl->SaveSettings(machine); - VBOX_RELEASE(machine); - } - VBOX_SESSION_CLOSE(); - } - } - - cleanup: - vboxIIDUnalloc(&iid); - virDomainDefFree(def); - virDomainDeviceDefFree(dev); - return ret; -} - -static int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) -{ - virCheckFlags(VIR_DOMAIN_AFFECT_CURRENT | - VIR_DOMAIN_AFFECT_LIVE | - VIR_DOMAIN_AFFECT_CONFIG, -1); - - if (flags & VIR_DOMAIN_AFFECT_CONFIG) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return vboxDomainAttachDeviceImpl(dom, xml, 1); -} - static int vboxDomainDetachDevice(virDomainPtr dom, const char *xml) { VBOX_OBJECT_CHECK(dom->conn, int, -1); diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 69090f3..493d12c 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -527,6 +527,8 @@ int vboxConnectNumOfDefinedDomains(virConnectPtr conn); int vboxDomainAttachDevice(virDomainPtr dom, const char *xml); int vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags); +int vboxDomainUpdateDeviceFlags(virDomainPtr dom, 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 | 101 +++++++++++++++++++ src/vbox/vbox_tmpl.c | 221 ++++++++++++++++------------------------- src/vbox/vbox_uniformed_api.h | 4 + 3 files changed, 190 insertions(+), 136 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 71c97a0..f6ea357 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -4185,3 +4185,104 @@ int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, return vboxDomainAttachDeviceImpl(dom, xml, 1); } + +int vboxDomainDetachDevice(virDomainPtr dom, const char *xml) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IMachine *machine = NULL; + vboxIIDUnion iid; + PRUint32 state; + virDomainDefPtr def = NULL; + virDomainDeviceDefPtr dev = NULL; + nsresult rc; + + VBOX_IID_INITIALIZE(&iid); + if (VIR_ALLOC(def) < 0) + return ret; + + if (VIR_STRDUP(def->os.type, "hvm") < 0) + goto cleanup; + + dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, + VIR_DOMAIN_XML_INACTIVE); + if (dev == NULL) + goto cleanup; + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + if (!machine) + goto cleanup; + + gVBoxAPI.UIMachine.GetState(machine, &state); + + if (gVBoxAPI.machineStateChecker.Running(state) || + gVBoxAPI.machineStateChecker.Paused(state)) { + rc = gVBoxAPI.UISession.OpenExisting(data, &iid, machine); + } else { + rc = gVBoxAPI.UISession.Open(data, &iid, machine); + } + + if (NS_FAILED(rc)) + goto cleanup; + + rc = gVBoxAPI.UISession.GetMachine(data->vboxSession, &machine); + if (NS_SUCCEEDED(rc) && machine) { + /* ret = -VIR_ERR_ARGUMENT_UNSUPPORTED means the current device don't support hotplug. */ + ret = -VIR_ERR_ARGUMENT_UNSUPPORTED; + if (dev->type == VIR_DOMAIN_DEVICE_DISK) { + if (gVBoxAPI.oldMediumInterface) { + int type = virDomainDiskGetType(dev->data.disk); + + if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { + if (type == VIR_STORAGE_TYPE_FILE) { + ret = gVBoxAPI.detachDVD(machine); + } else if (type == VIR_STORAGE_TYPE_BLOCK) { + } + } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { + if (type == VIR_STORAGE_TYPE_FILE) { + ret = gVBoxAPI.detachFloppy(machine); + } else if (type == VIR_STORAGE_TYPE_BLOCK) { + } + } + } + } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { + } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { + if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { + if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { + } + } + } else if (dev->type == VIR_DOMAIN_DEVICE_FS && + dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) { + PRUnichar *nameUtf16; + + VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16); + + rc = gVBoxAPI.UIMachine.RemoveSharedFolder(machine, nameUtf16); + + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not detach shared folder '%s', rc=%08x"), + dev->data.fs->dst, (unsigned)rc); + } else { + ret = 0; + } + + VBOX_UTF16_FREE(nameUtf16); + } + gVBoxAPI.UIMachine.SaveSettings(machine); + VBOX_RELEASE(machine); + + if (ret == -VIR_ERR_ARGUMENT_UNSUPPORTED) { + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, _("Unsupported device type %d"), dev->type); + ret = -1; + } + } + gVBoxAPI.UISession.Close(data->vboxSession); + + cleanup: + vboxIIDUnalloc(&iid); + virDomainDefFree(def); + virDomainDeviceDefFree(dev); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index dd93e2a..65f2d34 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1450,142 +1450,6 @@ _vboxAttachDrivesOld(virDomainDefPtr def ATTRIBUTE_UNUSED, #endif /* VBOX_API_VERSION >= 4000000 */ -static int vboxDomainDetachDevice(virDomainPtr dom, const char *xml) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IMachine *machine = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - PRUint32 state = MachineState_Null; - virDomainDefPtr def = NULL; - virDomainDeviceDefPtr dev = NULL; - nsresult rc; - - if (VIR_ALLOC(def) < 0) - return ret; - - if (VIR_STRDUP(def->os.type, "hvm") < 0) - goto cleanup; - - dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, - VIR_DOMAIN_XML_INACTIVE); - if (dev == NULL) - goto cleanup; - - 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; - } - - if (machine) { - machine->vtbl->GetState(machine, &state); - - if ((state == MachineState_Running) || - (state == MachineState_Paused)) { - rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); - } else { - 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 (dev->type == VIR_DOMAIN_DEVICE_DISK) { -#if VBOX_API_VERSION < 3001000 - int type = virDomainDiskGetType(dev->data.disk); - - if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { - if (type == VIR_STORAGE_TYPE_FILE) { - IDVDDrive *dvdDrive = NULL; - /* Currently CDROM/DVD Drive is always IDE - * Secondary Master so neglecting the following - * parameter dev->data.disk->bus - */ - machine->vtbl->GetDVDDrive(machine, &dvdDrive); - if (dvdDrive) { - rc = dvdDrive->vtbl->Unmount(dvdDrive); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not de-attach the mounted ISO, rc=%08x"), - (unsigned)rc); - } else { - ret = 0; - } - VBOX_RELEASE(dvdDrive); - } - } else if (type == VIR_STORAGE_TYPE_BLOCK) { - } - } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { - if (type == VIR_STORAGE_TYPE_FILE) { - IFloppyDrive *floppyDrive; - machine->vtbl->GetFloppyDrive(machine, &floppyDrive); - if (floppyDrive) { - PRBool enabled = PR_FALSE; - - floppyDrive->vtbl->GetEnabled(floppyDrive, &enabled); - if (enabled) { - rc = floppyDrive->vtbl->Unmount(floppyDrive); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not attach the file " - "to floppy drive, rc=%08x"), - (unsigned)rc); - } else { - ret = 0; - } - } else { - /* If you are here means floppy drive is already unmounted - * so don't flag error, just say everything is fine and quit - */ - ret = 0; - } - VBOX_RELEASE(floppyDrive); - } - } else if (type == VIR_STORAGE_TYPE_BLOCK) { - } - } -#else /* VBOX_API_VERSION >= 3001000 */ -#endif /* VBOX_API_VERSION >= 3001000 */ - } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { - } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { - if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { - if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { - } - } - } else if (dev->type == VIR_DOMAIN_DEVICE_FS && - dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) { - PRUnichar *nameUtf16; - - VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16); - - rc = machine->vtbl->RemoveSharedFolder(machine, nameUtf16); - - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not detach shared folder '%s', rc=%08x"), - dev->data.fs->dst, (unsigned)rc); - } else { - ret = 0; - } - - VBOX_UTF16_FREE(nameUtf16); - } - machine->vtbl->SaveSettings(machine); - VBOX_RELEASE(machine); - } - VBOX_SESSION_CLOSE(); - } - } - - cleanup: - vboxIIDUnalloc(&iid); - virDomainDefFree(def); - virDomainDeviceDefFree(dev); - return ret; -} - static int vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags) @@ -7634,6 +7498,33 @@ _attachDVD(vboxGlobalData *data, IMachine *machine, const char *src) return ret; } +static int +_detachDVD(IMachine *machine) +{ + IDVDDrive *dvdDrive = NULL; + int ret = -1; + nsresult rc; + /* Currently CDROM/DVD Drive is always IDE + * Secondary Master so neglecting the following + * parameter dev->data.disk->bus + */ + machine->vtbl->GetDVDDrive(machine, &dvdDrive); + if (!dvdDrive) + return ret; + + rc = dvdDrive->vtbl->Unmount(dvdDrive); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not de-attach the mounted ISO, rc=%08x"), + (unsigned)rc); + } else { + ret = 0; + } + VBOX_RELEASE(dvdDrive); + + return ret; +} + static void _dumpFloppy(virDomainDefPtr def, vboxGlobalData *data, @@ -7752,6 +7643,41 @@ _attachFloppy(vboxGlobalData *data, IMachine *machine, const char *src) return ret; } +static int +_detachFloppy(IMachine *machine) +{ + IFloppyDrive *floppyDrive; + int ret = -1; + nsresult rc; + + machine->vtbl->GetFloppyDrive(machine, &floppyDrive); + if (!floppyDrive) + return ret; + + PRBool enabled = PR_FALSE; + + floppyDrive->vtbl->GetEnabled(floppyDrive, &enabled); + if (enabled) { + rc = floppyDrive->vtbl->Unmount(floppyDrive); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not attach the file " + "to floppy drive, rc=%08x"), + (unsigned)rc); + } else { + ret = 0; + } + } else { + /* If you are here means floppy drive is already unmounted + * so don't flag error, just say everything is fine and quit + */ + ret = 0; + } + VBOX_RELEASE(floppyDrive); + + return ret; +} + #else /* VBOX_API_VERSION >= 3001000 */ static void @@ -7779,6 +7705,13 @@ _attachDVD(vboxGlobalData *data ATTRIBUTE_UNUSED, return 0; } +static int +_detachDVD(IMachine *machine ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); + return 0; +} + static void _dumpFloppy(virDomainDefPtr def ATTRIBUTE_UNUSED, vboxGlobalData *data ATTRIBUTE_UNUSED, @@ -7796,6 +7729,13 @@ _attachFloppy(vboxGlobalData *data ATTRIBUTE_UNUSED, return 0; } +static int +_detachFloppy(IMachine *machine ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); + return 0; +} + #endif /* VBOX_API_VERSION >= 3001000 */ static void _pfnUninitialize(vboxGlobalData *data) @@ -8081,6 +8021,12 @@ _machineCreateSharedFolder(IMachine *machine, PRUnichar *name, } static nsresult +_machineRemoveSharedFolder(IMachine *machine, PRUnichar *name) +{ + return machine->vtbl->RemoveSharedFolder(machine, name); +} + +static nsresult _machineLaunchVMProcess(vboxGlobalData *data, IMachine *machine ATTRIBUTE_UNUSED, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, @@ -9245,6 +9191,7 @@ static vboxUniformedIMachine _UIMachine = { .GetStorageControllerByName = _machineGetStorageControllerByName, .AttachDevice = _machineAttachDevice, .CreateSharedFolder = _machineCreateSharedFolder, + .RemoveSharedFolder = _machineRemoveSharedFolder, .LaunchVMProcess = _machineLaunchVMProcess, .GetAccessible = _machineGetAccessible, .GetState = _machineGetState, @@ -9449,8 +9396,10 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->dumpIDEHDDsOld = _dumpIDEHDDsOld; pVBoxAPI->dumpDVD = _dumpDVD; pVBoxAPI->attachDVD = _attachDVD; + pVBoxAPI->detachDVD = _detachDVD; pVBoxAPI->dumpFloppy = _dumpFloppy; pVBoxAPI->attachFloppy = _attachFloppy; + pVBoxAPI->detachFloppy = _detachFloppy; pVBoxAPI->UPFN = _UPFN; pVBoxAPI->UIID = _UIID; pVBoxAPI->UArray = _UArray; diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 493d12c..357590c 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -201,6 +201,7 @@ typedef struct { nsresult (*CreateSharedFolder)(IMachine *machine, PRUnichar *name, PRUnichar *hostPath, PRBool writable, PRBool automount); + nsresult (*RemoveSharedFolder)(IMachine *machine, PRUnichar *name); nsresult (*LaunchVMProcess)(vboxGlobalData *data, IMachine *machine, vboxIIDUnion *iidu, PRUnichar *sessionType, PRUnichar *env, @@ -434,8 +435,10 @@ typedef struct { void (*dumpIDEHDDsOld)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine); void (*dumpDVD)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine); int (*attachDVD)(vboxGlobalData *data, IMachine *machine, const char *src); + int (*detachDVD)(IMachine *machine); void (*dumpFloppy)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine); int (*attachFloppy)(vboxGlobalData *data, IMachine *machine, const char *src); + int (*detachFloppy)(IMachine *machine); vboxUniformedPFN UPFN; vboxUniformedIID UIID; vboxUniformedArray UArray; @@ -529,6 +532,7 @@ int vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags); int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags); +int vboxDomainDetachDevice(virDomainPtr dom, const char *xml); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 14 ++++++++++++++ src/vbox/vbox_tmpl.c | 15 --------------- src/vbox/vbox_uniformed_api.h | 2 ++ 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index f6ea357..4e0b990 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -4286,3 +4286,17 @@ int vboxDomainDetachDevice(virDomainPtr dom, const char *xml) virDomainDeviceDefFree(dev); return ret; } + +int vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) +{ + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify the persistent configuration of a domain")); + return -1; + } + + return vboxDomainDetachDevice(dom, xml); +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 65f2d34..eeebd6f 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1451,21 +1451,6 @@ _vboxAttachDrivesOld(virDomainDefPtr def ATTRIBUTE_UNUSED, #endif /* VBOX_API_VERSION >= 4000000 */ static int -vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) -{ - virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); - - if (flags & VIR_DOMAIN_AFFECT_CONFIG) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return vboxDomainDetachDevice(dom, xml); -} - -static int vboxDomainSnapshotGetAll(virDomainPtr dom, IMachine *machine, ISnapshot ***snapshots) diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 357590c..48c2973 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -533,6 +533,8 @@ int vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags); int vboxDomainDetachDevice(virDomainPtr dom, const char *xml); +int vboxDomainDetachDeviceFlags(virDomainPtr dom, 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.h | 1 + src/vbox/vbox_tmpl.c | 171 ++++++++++++++++++++++++++++++++++++++++- src/vbox/vbox_uniformed_api.h | 17 ++++ 3 files changed, 187 insertions(+), 2 deletions(-) diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h index 434689b..a093481 100644 --- a/src/vbox/vbox_common.h +++ b/src/vbox/vbox_common.h @@ -269,5 +269,6 @@ typedef nsISupports IMedium; typedef nsISupports IMediumAttachment; typedef nsISupports IStorageController; typedef nsISupports ISharedFolder; +typedef nsISupports ISnapshot; #endif /* VBOX_COMMON_H */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index eeebd6f..2d5ea5c 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -665,7 +665,6 @@ _vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu, 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) # define vboxIIDFromUUID(iid, uuid) vboxIIDFromUUID_v3_x(data, iid, uuid) @@ -676,7 +675,6 @@ _vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu, #endif /* !(VBOX_API_VERSION == 2002000) */ - /** * function to generate the name for medium, * for e.g: hda, sda, etc @@ -7785,6 +7783,18 @@ static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu) #endif /* VBOX_API_VERSION != 2002000 */ +static void +_vboxIIDToUtf8(vboxGlobalData *data ATTRIBUTE_UNUSED, + vboxIIDUnion *iidu ATTRIBUTE_UNUSED, + char **utf8 ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION == 2002000 + vboxUnsupported(); +#else /* !(VBOX_API_VERSION == 2002000) */ + data->pFuncs->pfnUtf16ToUtf8(IID_MEMBER(value), utf8); +#endif /* !(VBOX_API_VERSION == 2002000) */ +} + static void* _handleGetMachines(IVirtualBox *vboxObj) { return vboxObj->vtbl->GetMachines; @@ -7839,6 +7849,12 @@ _virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machi #endif /* VBOX_API_VERSION >= 4000000 */ static nsresult +_virtualboxOpenMachine(IVirtualBox *vboxObj, PRUnichar *settingsFile, IMachine **machine) +{ + return vboxObj->vtbl->OpenMachine(vboxObj, settingsFile, machine); +} + +static nsresult _virtualboxGetSystemProperties(IVirtualBox *vboxObj, ISystemProperties **systemProperties) { return vboxObj->vtbl->GetSystemProperties(vboxObj, systemProperties); @@ -7909,6 +7925,20 @@ _virtualboxCreateMachine(vboxGlobalData *data, virDomainDefPtr def, IMachine **m } static nsresult +_virtualboxCreateHardDiskMedium(IVirtualBox *vboxObj ATTRIBUTE_UNUSED, + PRUnichar *format ATTRIBUTE_UNUSED, + PRUnichar *location ATTRIBUTE_UNUSED, + IMedium **medium ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION < 3001000 + vboxUnsupported(); + return 0; +#else /* VBOX_API_VERSION >= 3001000 */ + return vboxObj->vtbl->CreateHardDisk(vboxObj, format, location, medium); +#endif /* VBOX_API_VERSION >= 3001000 */ +} + +static nsresult _virtualboxRegisterMachine(IVirtualBox *vboxObj, IMachine *machine) { return vboxObj->vtbl->RegisterMachine(vboxObj, machine); @@ -8032,6 +8062,20 @@ _machineLaunchVMProcess(vboxGlobalData *data, } static nsresult +_machineUnregister(IMachine *machine ATTRIBUTE_UNUSED, + PRUint32 cleanupMode ATTRIBUTE_UNUSED, + PRUint32 *aMediaSize ATTRIBUTE_UNUSED, + IMedium ***aMedia ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION < 4000000 + vboxUnsupported(); + return 0; +#else /* VBOX_API_VERSION >= 4000000 */ + return machine->vtbl->Unregister(machine, cleanupMode, aMediaSize, aMedia); +#endif /* VBOX_API_VERSION >= 4000000 */ +} + +static nsresult _machineGetAccessible(IMachine *machine, PRBool *isAccessible) { return machine->vtbl->GetAccessible(machine, isAccessible); @@ -8117,6 +8161,18 @@ _machineGetUSBCommon(IMachine *machine, IUSBCommon **USBCommon) } static nsresult +_machineGetCurrentSnapshot(IMachine *machine, ISnapshot **currentSnapshot) +{ + return machine->vtbl->GetCurrentSnapshot(machine, currentSnapshot); +} + +static nsresult +_machineGetSettingsFilePath(IMachine *machine, PRUnichar **settingsFilePath) +{ + return machine->vtbl->GetSettingsFilePath(machine, settingsFilePath); +} + +static nsresult _machineGetCPUCount(IMachine *machine, PRUint32 *CPUCount) { return machine->vtbl->GetCPUCount(machine, CPUCount); @@ -8356,6 +8412,13 @@ _consoleReset(IConsole *console) } static nsresult +_consoleTakeSnapshot(IConsole *console, PRUnichar *name, + PRUnichar *description, IProgress **progress) +{ + return console->vtbl->TakeSnapshot(console, name, description, progress); +} + +static nsresult _progressWaitForCompletion(IProgress *progress, PRInt32 timeout) { return progress->vtbl->WaitForCompletion(progress, timeout); @@ -9011,10 +9074,74 @@ static nsresult _mediumGetReadOnly(IMedium *medium ATTRIBUTE_UNUSED, #endif /* VBOX_API_VERSION >= 3001000 */ } +#if VBOX_API_VERSION < 3001000 + +static nsresult _mediumGetParent(IMedium *medium ATTRIBUTE_UNUSED, + IMedium **parent ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); + return 0; +} + +static nsresult _mediumGetChildren(IMedium *medium ATTRIBUTE_UNUSED, + PRUint32 *childrenSize ATTRIBUTE_UNUSED, + IMedium ***children ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); + return 0; +} + +static nsresult _mediumGetFormat(IMedium *medium ATTRIBUTE_UNUSED, + PRUnichar **format ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); + return 0; +} + +static nsresult _mediumDeleteStorage(IMedium *medium ATTRIBUTE_UNUSED, + IProgress **progress ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); + return 0; +} + +#else /* VBOX_API_VERSION >= 3001000 */ + +static nsresult _mediumGetParent(IMedium *medium, + IMedium **parent) +{ + return medium->vtbl->GetParent(medium, parent); +} + +static nsresult _mediumGetChildren(IMedium *medium, + PRUint32 *childrenSize, + IMedium ***children) +{ + return medium->vtbl->GetChildren(medium, childrenSize, children); +} + +static nsresult _mediumGetFormat(IMedium *medium, + PRUnichar **format) +{ + return medium->vtbl->GetFormat(medium, format); +} + +static nsresult _mediumDeleteStorage(IMedium *medium, + IProgress **progress) +{ + return medium->vtbl->DeleteStorage(medium, progress); +} + +#endif /* VBOX_API_VERSION >= 3001000 */ + static nsresult _mediumRelease(IMedium *medium) { return medium->vtbl->nsisupports.Release((nsISupports *)medium); } +static nsresult _mediumClose(IMedium *medium) +{ + return medium->vtbl->Close(medium); +} static nsresult _mediumSetType(IMedium *medium ATTRIBUTE_UNUSED, PRUint32 type ATTRIBUTE_UNUSED) @@ -9028,6 +9155,27 @@ static nsresult _mediumSetType(IMedium *medium ATTRIBUTE_UNUSED, } static nsresult +_mediumCreateDiffStorage(IMedium *medium ATTRIBUTE_UNUSED, + IMedium *target ATTRIBUTE_UNUSED, + PRUint32 variantSize ATTRIBUTE_UNUSED, + PRUint32 *variant ATTRIBUTE_UNUSED, + IProgress **progress ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION < 3001000 + vboxUnsupported(); + return 0; +#elif VBOX_API_VERSION < 4003000 + if (variantSize == 0) + return 0; + if (variantSize > 1) + VIR_WARN("Only one variant is avaible in current version"); + return medium->vtbl->CreateDiffStorage(medium, target, variant[0], progress); +#else /* VBOX_API_VERSION >= 4003000 */ + return medium->vtbl->CreateDiffStorage(medium, target, variantSize, variant, progress); +#endif /* VBOX_API_VERSION >= 4003000 */ +} + +static nsresult _mediumAttachmentGetMedium(IMediumAttachment *mediumAttachment ATTRIBUTE_UNUSED, IMedium **medium ATTRIBUTE_UNUSED) { @@ -9145,6 +9293,7 @@ static vboxUniformedIID _UIID = { .vboxIIDFromUUID = _vboxIIDFromUUID, .vboxIIDIsEqual = _vboxIIDIsEqual, .vboxIIDFromArrayItem = _vboxIIDFromArrayItem, + .vboxIIDToUtf8 = _vboxIIDToUtf8, .DEBUGIID = _DEBUGIID, }; @@ -9164,8 +9313,10 @@ static vboxUniformednsISupports _nsUISupports = { static vboxUniformedIVirtualBox _UIVirtualBox = { .GetVersion = _virtualboxGetVersion, .GetMachine = _virtualboxGetMachine, + .OpenMachine = _virtualboxOpenMachine, .GetSystemProperties = _virtualboxGetSystemProperties, .CreateMachine = _virtualboxCreateMachine, + .CreateHardDiskMedium = _virtualboxCreateHardDiskMedium, .RegisterMachine = _virtualboxRegisterMachine, .FindMedium = _virtualboxFindMedium, .OpenMedium = _virtualboxOpenMedium, @@ -9178,6 +9329,7 @@ static vboxUniformedIMachine _UIMachine = { .CreateSharedFolder = _machineCreateSharedFolder, .RemoveSharedFolder = _machineRemoveSharedFolder, .LaunchVMProcess = _machineLaunchVMProcess, + .Unregister = _machineUnregister, .GetAccessible = _machineGetAccessible, .GetState = _machineGetState, .GetName = _machineGetName, @@ -9190,6 +9342,8 @@ static vboxUniformedIMachine _UIMachine = { .GetParallelPort = _machineGetParallelPort, .GetVRDxServer = _machineGetVRDxServer, .GetUSBCommon = _machineGetUSBCommon, + .GetCurrentSnapshot = _machineGetCurrentSnapshot, + .GetSettingsFilePath = _machineGetSettingsFilePath, .GetCPUCount = _machineGetCPUCount, .SetCPUCount = _machineSetCPUCount, .GetMemorySize = _machineGetMemorySize, @@ -9226,6 +9380,7 @@ static vboxUniformedIConsole _UIConsole = { .PowerButton = _consolePowerButton, .PowerDown = _consolePowerDown, .Reset = _consoleReset, + .TakeSnapshot = _consoleTakeSnapshot, }; static vboxUniformedIProgress _UIProgress = { @@ -9336,8 +9491,14 @@ static vboxUniformedIMedium _UIMedium = { .GetId = _mediumGetId, .GetLocation = _mediumGetLocation, .GetReadOnly = _mediumGetReadOnly, + .GetParent = _mediumGetParent, + .GetChildren = _mediumGetChildren, + .GetFormat = _mediumGetFormat, + .DeleteStorage = _mediumDeleteStorage, .Release = _mediumRelease, + .Close = _mediumClose, .SetType = _mediumSetType, + .CreateDiffStorage = _mediumCreateDiffStorage, }; static vboxUniformedIMediumAttachment _UIMediumAttachment = { @@ -9445,6 +9606,12 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->accelerate2DVideo = 0; pVBoxAPI->oldMediumInterface = 1; #endif /* VBOX_API_VERSION < 3001000 */ + +#if VBOX_API_VERSION >= 4002000 + pVBoxAPI->vboxSnapshotRedefine = 1; +#else /* VBOX_API_VERSION < 4002000 */ + pVBoxAPI->vboxSnapshotRedefine = 0; +#endif /* VBOX_API_VERSION < 4002000 */ } /** diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 48c2973..b36e154 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -159,6 +159,7 @@ typedef struct { 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 (*vboxIIDToUtf8)(vboxGlobalData *data, vboxIIDUnion *iidu, char **utf8); void (*DEBUGIID)(const char *msg, vboxIIDUnion *iidu); } vboxUniformedIID; @@ -182,8 +183,10 @@ typedef struct { typedef struct { nsresult (*GetVersion)(IVirtualBox *vboxObj, PRUnichar **versionUtf16); nsresult (*GetMachine)(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine); + nsresult (*OpenMachine)(IVirtualBox *vboxObj, PRUnichar *settingsFile, IMachine **machine); nsresult (*GetSystemProperties)(IVirtualBox *vboxObj, ISystemProperties **systemProperties); nsresult (*CreateMachine)(vboxGlobalData *data, virDomainDefPtr def, IMachine **machine, char *uuidstr); + nsresult (*CreateHardDiskMedium)(IVirtualBox *vboxObj, PRUnichar *format, PRUnichar *location, IMedium **medium); 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); @@ -206,6 +209,8 @@ typedef struct { vboxIIDUnion *iidu, PRUnichar *sessionType, PRUnichar *env, IProgress **progress); + nsresult (*Unregister)(IMachine *machine, PRUint32 cleanupMode, + PRUint32 *aMediaSize, IMedium ***aMedia); nsresult (*GetAccessible)(IMachine *machine, PRBool *isAccessible); nsresult (*GetState)(IMachine *machine, PRUint32 *state); nsresult (*GetName)(IMachine *machine, PRUnichar **name); @@ -218,6 +223,8 @@ typedef struct { nsresult (*GetParallelPort)(IMachine *machine, PRUint32 slot, IParallelPort **port); nsresult (*GetVRDxServer)(IMachine *machine, IVRDxServer **VRDxServer); nsresult (*GetUSBCommon)(IMachine *machine, IUSBCommon **USBCommon); + nsresult (*GetCurrentSnapshot)(IMachine *machine, ISnapshot **currentSnapshot); + nsresult (*GetSettingsFilePath)(IMachine *machine, PRUnichar **settingsFilePath); nsresult (*GetCPUCount)(IMachine *machine, PRUint32 *CPUCount); nsresult (*SetCPUCount)(IMachine *machine, PRUint32 CPUCount); nsresult (*GetMemorySize)(IMachine *machine, PRUint32 *memorySize); @@ -256,6 +263,8 @@ typedef struct { nsresult (*PowerButton)(IConsole *console); nsresult (*PowerDown)(IConsole *console); nsresult (*Reset)(IConsole *console); + nsresult (*TakeSnapshot)(IConsole *console, PRUnichar *name, + PRUnichar *description, IProgress **progress); } vboxUniformedIConsole; /* Functions for IProgress */ @@ -385,8 +394,15 @@ typedef struct { nsresult (*GetId)(IMedium *medium, vboxIIDUnion *iidu); nsresult (*GetLocation)(IMedium *medium, PRUnichar **location); nsresult (*GetReadOnly)(IMedium *medium, PRBool *readOnly); + nsresult (*GetParent)(IMedium *medium, IMedium **parent); + nsresult (*GetChildren)(IMedium *medium, PRUint32 *childrenSize, IMedium ***children); + nsresult (*GetFormat)(IMedium *medium, PRUnichar **format); + nsresult (*DeleteStorage)(IMedium *medium, IProgress **progress); nsresult (*Release)(IMedium *medium); + nsresult (*Close)(IMedium *medium); nsresult (*SetType)(IMedium *medium, PRUint32 type); + nsresult (*CreateDiffStorage)(IMedium *medium, IMedium *target, PRUint32 variantSize, + PRUint32 *variant, IProgress **progress); } vboxUniformedIMedium; /* Functions for IMediumAttachment */ @@ -471,6 +487,7 @@ typedef struct { bool accelerate2DVideo; bool vboxAttachDrivesUseOld; bool oldMediumInterface; + bool vboxSnapshotRedefine; } vboxUniformedAPI; /* libvirt API -- 1.7.9.5

The vboxDomainSnapshotCreateXML integrated the snapshot redefine with this patch: http://www.redhat.com/archives/libvir-list/2014-May/msg00589.html This patch introduced vboxSnapshotRedefine in vboxUniformedAPI to enable the features. This patch replace all version specified APIs to the uniformed api, then, moving the whole implementation to vbox_common.c. As there is only API level changes, the behavior of the function doesn't change. Some old version's defects has brought to the new one. The already known things are: *goto cleanup in a loop without releasing the pointers in the loop. *When function failed after machine unregister, no roll back to recovery it and the virtual machine would disappear. --- src/vbox/vbox_common.c | 1069 ++++++++++++++++++++++++++++++++++++++++ src/vbox/vbox_common.h | 18 + src/vbox/vbox_tmpl.c | 1087 ----------------------------------------- src/vbox/vbox_uniformed_api.h | 5 + 4 files changed, 1092 insertions(+), 1087 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 4e0b990..8f3fe03 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -28,6 +28,10 @@ #include "viralloc.h" #include "nodeinfo.h" #include "virstring.h" +#include "virfile.h" +#include "virtime.h" +#include "snapshot_conf.h" +#include "vbox_snapshot_conf.h" #include "vbox_common.h" #include "vbox_uniformed_api.h" @@ -4300,3 +4304,1068 @@ int vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, return vboxDomainDetachDevice(dom, xml); } + +static int vboxCloseDisksRecursively(virDomainPtr dom, char *location) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + nsresult rc; + size_t i = 0; + PRUnichar *locationUtf = NULL; + IMedium *medium = NULL; + IMedium **children = NULL; + PRUint32 childrenSize = 0; + + if (!gVBoxAPI.vboxSnapshotRedefine) + VIR_WARN("This function may not work in current version"); + + VBOX_UTF8_TO_UTF16(location, &locationUtf); + rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj, + locationUtf, + DeviceType_HardDisk, + AccessMode_ReadWrite, + &medium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to open HardDisk, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + rc = gVBoxAPI.UIMedium.GetChildren(medium, &childrenSize, &children); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s" + , _("Unable to get disk children")); + goto cleanup; + } + for (i = 0; i < childrenSize; i++) { + IMedium *childMedium = children[i]; + if (childMedium) { + PRUnichar *childLocationUtf = NULL; + char *childLocation = NULL; + rc = gVBoxAPI.UIMedium.GetLocation(childMedium, &childLocationUtf); + VBOX_UTF16_TO_UTF8(childLocationUtf, &childLocation); + VBOX_UTF16_FREE(childLocationUtf); + if (vboxCloseDisksRecursively(dom, childLocation) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s" + , _("Unable to close disk children")); + goto cleanup; + } + VIR_FREE(childLocation); + } + } + rc = gVBoxAPI.UIMedium.Close(medium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to close HardDisk, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + + ret = 0; + cleanup: + VBOX_UTF16_FREE(locationUtf); + return ret; +} + +static int +vboxSnapshotRedefine(virDomainPtr dom, + virDomainSnapshotDefPtr def, + bool isCurrent) +{ + /* + * If your snapshot has a parent, + * it will only be redefined if you have already + * redefined the parent. + * + * The general algorithm of this function is below : + * First of all, we are going to create our vboxSnapshotXmlMachinePtr struct from + * the machine settings path. + * Then, if the machine current snapshot xml file is saved in the machine location, + * it means that this snapshot was previously modified by us and has fake disks. + * Fake disks are added when the flag VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT was not set + * yet, in order to not corrupt read-only disks. The first thing to do is to remove those + * disks and restore the read-write disks, if any, in the vboxSnapshotXmlMachinePtr struct. + * We also delete the current snapshot xml file. + * + * After that, we are going to register the snapshot read-only disks that we want to redefine, + * if they are not in the media registry struct. + * + * The next step is to unregister the machine and close all disks. + * + * Then, we check if the flag VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE has already been set. + * If this flag was set, we just add read-write disks to the media registry + * struct. Otherwise, we save the snapshot xml file into the machine location in order + * to recover the read-write disks during the next redefine and we create differential disks + * from the snapshot read-only disks and add them to the media registry struct. + * + * Finally, we register the machine with the new virtualbox description file. + */ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIIDUnion domiid; + IMachine *machine = NULL; + nsresult rc; + PRUnichar *settingsFilePath = NULL; + char *settingsFilePath_Utf8 = NULL; + virVBoxSnapshotConfMachinePtr snapshotMachineDesc = NULL; + char *currentSnapshotXmlFilePath = NULL; + PRUnichar *machineNameUtf16 = NULL; + char *machineName = NULL; + char **realReadWriteDisksPath = NULL; + int realReadWriteDisksPathSize = 0; + char **realReadOnlyDisksPath = NULL; + int realReadOnlyDisksPathSize = 0; + virVBoxSnapshotConfSnapshotPtr newSnapshotPtr = NULL; + unsigned char snapshotUuid[VIR_UUID_BUFLEN]; + int it = 0; + int jt = 0; + PRUint32 aMediaSize = 0; + IMedium **aMedia = NULL; + char *machineLocationPath = NULL; + char *nameTmpUse = NULL; + bool snapshotFileExists = false; + bool needToChangeStorageController = false; + + if (!gVBoxAPI.vboxSnapshotRedefine) + VIR_WARN("This function may not work in current version"); + + if (openSessionForMachine(data, dom->uuid, &domiid, &machine, false) < 0) + goto cleanup; + + rc = gVBoxAPI.UIMachine.SaveSettings(machine); + /*It may failed when the machine is not mutable.*/ + rc = gVBoxAPI.UIMachine.GetSettingsFilePath(machine, &settingsFilePath); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get settings file path")); + goto cleanup; + } + VBOX_UTF16_TO_UTF8(settingsFilePath, &settingsFilePath_Utf8); + + /*Getting the machine name to retrieve the machine location path.*/ + rc = gVBoxAPI.UIMachine.GetName(machine, &machineNameUtf16); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get machine name")); + goto cleanup; + } + VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineName); + + if (virAsprintf(&nameTmpUse, "%s.vbox", machineName) < 0) + goto cleanup; + machineLocationPath = virStringReplace(settingsFilePath_Utf8, nameTmpUse, ""); + if (machineLocationPath == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get the machine location path")); + goto cleanup; + } + + /*We create the xml struct with the settings file path.*/ + snapshotMachineDesc = virVBoxSnapshotConfLoadVboxFile(settingsFilePath_Utf8, machineLocationPath); + if (snapshotMachineDesc == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot create a vboxSnapshotXmlPtr")); + goto cleanup; + } + if (snapshotMachineDesc->currentSnapshot != NULL) { + if (virAsprintf(¤tSnapshotXmlFilePath, "%s%s.xml", machineLocationPath, + snapshotMachineDesc->currentSnapshot) < 0) + goto cleanup; + snapshotFileExists = virFileExists(currentSnapshotXmlFilePath); + } + + if (snapshotFileExists) { + /* + * We have created fake disks, so we have to remove them and replace them with + * the read-write disks if there are any. The fake disks will be closed during + * the machine unregistration. + */ + if (virVBoxSnapshotConfRemoveFakeDisks(snapshotMachineDesc) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to remove Fake Disks")); + goto cleanup; + } + realReadWriteDisksPathSize = virVBoxSnapshotConfGetRWDisksPathsFromLibvirtXML(currentSnapshotXmlFilePath, + &realReadWriteDisksPath); + realReadOnlyDisksPathSize = virVBoxSnapshotConfGetRODisksPathsFromLibvirtXML(currentSnapshotXmlFilePath, + &realReadOnlyDisksPath); + /*The read-only disk number is necessarily greater or equal to the + *read-write disk number*/ + if (realReadOnlyDisksPathSize < realReadWriteDisksPathSize) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("The read only disk number must be greater or equal to the " + " read write disk number")); + goto cleanup; + } + for (it = 0; it < realReadWriteDisksPathSize; it++) { + virVBoxSnapshotConfHardDiskPtr readWriteDisk = NULL; + PRUnichar *locationUtf = NULL; + IMedium *readWriteMedium = NULL; + char *uuid = NULL; + PRUnichar *formatUtf = NULL; + char *format = NULL; + const char *parentUuid = NULL; + vboxIIDUnion iid; + + VBOX_IID_INITIALIZE(&iid); + VBOX_UTF8_TO_UTF16(realReadWriteDisksPath[it], &locationUtf); + rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj, + locationUtf, + DeviceType_HardDisk, + AccessMode_ReadWrite, + &readWriteMedium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to open HardDisk, rc=%08x"), + (unsigned)rc); + VBOX_UTF16_FREE(locationUtf); + goto cleanup; + } + VBOX_UTF16_FREE(locationUtf); + + rc = gVBoxAPI.UIMedium.GetId(readWriteMedium, &iid); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get the read write medium id")); + goto cleanup; + } + gVBoxAPI.UIID.vboxIIDToUtf8(data, &iid, &uuid); + vboxIIDUnalloc(&iid); + + rc = gVBoxAPI.UIMedium.GetFormat(readWriteMedium, &formatUtf); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get the read write medium format")); + goto cleanup; + } + VBOX_UTF16_TO_UTF8(formatUtf, &format); + VBOX_UTF16_FREE(formatUtf); + + if (VIR_ALLOC(readWriteDisk) < 0) { + VIR_FREE(formatUtf); + goto cleanup; + } + + readWriteDisk->format = format; + readWriteDisk->uuid = uuid; + readWriteDisk->location = realReadWriteDisksPath[it]; + /* + * We get the current snapshot's read-only disk uuid in order to add the + * read-write disk to the media registry as it's child. The read-only disk + * is already in the media registry because it is the fake disk's parent. + */ + parentUuid = virVBoxSnapshotConfHardDiskUuidByLocation(snapshotMachineDesc, + realReadOnlyDisksPath[it]); + if (parentUuid == NULL) { + VIR_FREE(readWriteDisk); + goto cleanup; + } + + if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(readWriteDisk, + snapshotMachineDesc->mediaRegistry, + parentUuid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to add hard disk to media Registry")); + VIR_FREE(readWriteDisk); + goto cleanup; + } + rc = gVBoxAPI.UIMedium.Close(readWriteMedium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to close HardDisk, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + } + /* + * Now we have done this swap, we remove the snapshot xml file from the + * current machine location. + */ + if (unlink(currentSnapshotXmlFilePath) < 0) { + virReportSystemError(errno, + _("Unable to delete file %s"), currentSnapshotXmlFilePath); + goto cleanup; + } + } + /* + * Before unregistering the machine, while all disks are still open, ensure that all + * read-only disks are in the redefined snapshot's media registry (the disks need to + * be open to query their uuid). + */ + for (it = 0; it < def->dom->ndisks; it++) { + int diskInMediaRegistry = 0; + IMedium *readOnlyMedium = NULL; + PRUnichar *locationUtf = NULL; + char *uuid = NULL; + PRUnichar *formatUtf = NULL; + char *format = NULL; + char *parentUuid = NULL; + virVBoxSnapshotConfHardDiskPtr readOnlyDisk = NULL; + vboxIIDUnion iid, parentiid; + + VBOX_IID_INITIALIZE(&iid); + VBOX_IID_INITIALIZE(&parentiid); + diskInMediaRegistry = virVBoxSnapshotConfDiskIsInMediaRegistry(snapshotMachineDesc, + def->dom->disks[it]->src->path); + if (diskInMediaRegistry == -1) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to know if disk is in media registry")); + goto cleanup; + } + if (diskInMediaRegistry == 1) /*Nothing to do.*/ + continue; + /*The read only disk is not in the media registry*/ + + VBOX_UTF8_TO_UTF16(def->dom->disks[it]->src->path, &locationUtf); + rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj, + locationUtf, + DeviceType_HardDisk, + AccessMode_ReadWrite, + &readOnlyMedium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to open HardDisk, rc=%08x"), + (unsigned)rc); + VBOX_UTF16_FREE(locationUtf); + goto cleanup; + } + VBOX_UTF16_FREE(locationUtf); + + rc = gVBoxAPI.UIMedium.GetId(readOnlyMedium, &iid); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get hard disk id")); + goto cleanup; + } + gVBoxAPI.UIID.vboxIIDToUtf8(data, &iid, &uuid); + vboxIIDUnalloc(&iid); + + rc = gVBoxAPI.UIMedium.GetFormat(readOnlyMedium, &formatUtf); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get hard disk format")); + VIR_FREE(uuid); + goto cleanup; + } + VBOX_UTF16_TO_UTF8(formatUtf, &format); + VBOX_UTF16_FREE(formatUtf); + + /*This disk is already in the media registry*/ + IMedium *parentReadOnlyMedium = NULL; + rc = gVBoxAPI.UIMedium.GetParent(readOnlyMedium, &parentReadOnlyMedium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get parent hard disk")); + VIR_FREE(uuid); + goto cleanup; + } + + rc = gVBoxAPI.UIMedium.GetId(parentReadOnlyMedium, &parentiid); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to get hard disk id, rc=%08x"), + (unsigned)rc); + VIR_FREE(uuid); + goto cleanup; + } + gVBoxAPI.UIID.vboxIIDToUtf8(data, &parentiid, &parentUuid); + vboxIIDUnalloc(&parentiid); + + rc = gVBoxAPI.UIMedium.Close(readOnlyMedium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to close HardDisk, rc=%08x"), + (unsigned)rc); + VIR_FREE(uuid); + VIR_FREE(parentUuid); + goto cleanup; + } + + if (VIR_ALLOC(readOnlyDisk) < 0) { + VIR_FREE(uuid); + VIR_FREE(parentUuid); + goto cleanup; + } + + readOnlyDisk->format = format; + readOnlyDisk->uuid = uuid; + if (VIR_STRDUP(readOnlyDisk->location, def->dom->disks[it]->src->path) < 0) { + VIR_FREE(readOnlyDisk); + goto cleanup; + } + + if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(readOnlyDisk, snapshotMachineDesc->mediaRegistry, + parentUuid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to add hard disk to media registry")); + VIR_FREE(readOnlyDisk); + goto cleanup; + } + } + + /*Now, we can unregister the machine*/ + rc = gVBoxAPI.UIMachine.Unregister(machine, + CleanupMode_DetachAllReturnHardDisksOnly, + &aMediaSize, + &aMedia); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to unregister machine, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + VBOX_RELEASE(machine); + + /* + * Unregister the machine, and then close all disks returned by the unregister method. + * Some close operations will fail because some disks that need to be closed will not + * be returned by virtualbox. We will close them just after. We have to use this + * solution because it is the only way to delete fake disks. + */ + for (it = 0; it < aMediaSize; it++) { + IMedium *medium = aMedia[it]; + if (medium) { + PRUnichar *locationUtf16 = NULL; + char *locationUtf8 = NULL; + rc = gVBoxAPI.UIMedium.GetLocation(medium, &locationUtf16); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get medium location")); + goto cleanup; + } + VBOX_UTF16_TO_UTF8(locationUtf16, &locationUtf8); + VBOX_UTF16_FREE(locationUtf16); + if (strstr(locationUtf8, "fake") != NULL) { + /*we delete the fake disk because we don't need it anymore*/ + IProgress *progress = NULL; + resultCodeUnion resultCode; + rc = gVBoxAPI.UIMedium.DeleteStorage(medium, &progress); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to delete medium, rc=%08x"), + (unsigned)rc); + VIR_FREE(locationUtf8); + goto cleanup; + } + gVBoxAPI.UIProgress.WaitForCompletion(progress, -1); + gVBoxAPI.UIProgress.GetResultCode(progress, &resultCode); + if (RC_FAILED(resultCode)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Error while closing medium, rc=%08x"), + resultCode.uResultCode); + VIR_FREE(locationUtf8); + goto cleanup; + } + VBOX_RELEASE(progress); + } else { + /* + * This a comment from vboxmanage code in the handleUnregisterVM + * function in VBoxManageMisc.cpp : + * Note that the IMachine::Unregister method will return the medium + * reference in a sane order, which means that closing will normally + * succeed, unless there is still another machine which uses the + * medium. No harm done if we ignore the error. + */ + rc = gVBoxAPI.UIMedium.Close(medium); + } + VBOX_UTF8_FREE(locationUtf8); + } + } + /*Close all disks that failed to close normally.*/ + for (it = 0; it < snapshotMachineDesc->mediaRegistry->ndisks; it++) { + if (vboxCloseDisksRecursively(dom, snapshotMachineDesc->mediaRegistry->disks[it]->location) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to close recursively all disks")); + goto cleanup; + } + } + /*Here, all disks are closed or deleted*/ + + /*We are now going to create and fill the Snapshot xml struct*/ + if (VIR_ALLOC(newSnapshotPtr) < 0) + goto cleanup; + + if (virUUIDGenerate(snapshotUuid) < 0) + goto cleanup; + + char uuidtmp[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(snapshotUuid, uuidtmp); + if (VIR_STRDUP(newSnapshotPtr->uuid, uuidtmp) < 0) + goto cleanup; + + VIR_DEBUG("New snapshot UUID: %s", newSnapshotPtr->uuid); + if (VIR_STRDUP(newSnapshotPtr->name, def->name) < 0) + goto cleanup; + + newSnapshotPtr->timeStamp = virTimeStringThen(def->creationTime * 1000); + + if (VIR_STRDUP(newSnapshotPtr->description, def->description) < 0) + goto cleanup; + + if (VIR_STRDUP(newSnapshotPtr->hardware, snapshotMachineDesc->hardware) < 0) + goto cleanup; + + if (VIR_STRDUP(newSnapshotPtr->storageController, snapshotMachineDesc->storageController) < 0) + goto cleanup; + + /*We get the parent disk uuid from the parent disk location to correctly fill the storage controller.*/ + for (it = 0; it < def->dom->ndisks; it++) { + char *location = NULL; + const char *uuidReplacing = NULL; + char **searchResultTab = NULL; + ssize_t resultSize = 0; + char *tmp = NULL; + + location = def->dom->disks[it]->src->path; + if (!location) + goto cleanup; + /*Replacing the uuid*/ + uuidReplacing = virVBoxSnapshotConfHardDiskUuidByLocation(snapshotMachineDesc, location); + if (uuidReplacing == NULL) + goto cleanup; + + resultSize = virStringSearch(newSnapshotPtr->storageController, + VBOX_UUID_REGEX, + it + 1, + &searchResultTab); + if (resultSize != it + 1) + goto cleanup; + + tmp = virStringReplace(newSnapshotPtr->storageController, + searchResultTab[it], + uuidReplacing); + virStringFreeList(searchResultTab); + VIR_FREE(newSnapshotPtr->storageController); + if (!tmp) + goto cleanup; + if (VIR_STRDUP(newSnapshotPtr->storageController, tmp) < 0) + goto cleanup; + + VIR_FREE(tmp); + } + if (virVBoxSnapshotConfAddSnapshotToXmlMachine(newSnapshotPtr, snapshotMachineDesc, def->parent) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to add the snapshot to the machine description")); + goto cleanup; + } + /* + * We change the current snapshot only if there is no current snapshot or if the + * snapshotFile exists, otherwise, it means that the correct current snapshot is + * already set. + */ + + if (snapshotMachineDesc->currentSnapshot == NULL || snapshotFileExists) { + snapshotMachineDesc->currentSnapshot = newSnapshotPtr->uuid; + needToChangeStorageController = true; + } + + /* + * Open the snapshot's read-write disk's full ancestry to allow opening the + * read-write disk itself. + */ + for (it = 0; it < def->dom->ndisks; it++) { + char *location = NULL; + virVBoxSnapshotConfHardDiskPtr *hardDiskToOpen = NULL; + size_t hardDiskToOpenSize = 0; + + location = def->dom->disks[it]->src->path; + if (!location) + goto cleanup; + + hardDiskToOpenSize = virVBoxSnapshotConfDiskListToOpen(snapshotMachineDesc, + &hardDiskToOpen, location); + for (jt = hardDiskToOpenSize -1; jt >= 0; jt--) { + IMedium *medium = NULL; + PRUnichar *locationUtf16 = NULL; + VBOX_UTF8_TO_UTF16(hardDiskToOpen[jt]->location, &locationUtf16); + + rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj, + locationUtf16, + DeviceType_HardDisk, + AccessMode_ReadWrite, + &medium); + VBOX_UTF16_FREE(locationUtf16); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to open HardDisk, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + } + } + if (isCurrent || !needToChangeStorageController) { + /* We don't create a differential hard disk because either the current snapshot + * has already been defined or the snapshot to redefine is the current snapshot. + * If the snapshot to redefine is the current snapshot, we add read-write disks in + * the machine storage controllers. + */ + for (it = 0; it < def->ndisks; it++) { + IMedium *medium = NULL; + PRUnichar *locationUtf16 = NULL; + virVBoxSnapshotConfHardDiskPtr disk = NULL; + PRUnichar *formatUtf16 = NULL; + char *format = NULL; + char *uuid = NULL; + IMedium *parentDisk = NULL; + char *parentUuid = NULL; + vboxIIDUnion iid, parentiid; + + VBOX_IID_INITIALIZE(&iid); + VBOX_IID_INITIALIZE(&parentiid); + VBOX_UTF8_TO_UTF16(def->disks[it].src->path, &locationUtf16); + rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj, + locationUtf16, + DeviceType_HardDisk, + AccessMode_ReadWrite, + &medium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to open HardDisk, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + VBOX_UTF16_FREE(locationUtf16); + + if (VIR_ALLOC(disk) < 0) + goto cleanup; + + rc = gVBoxAPI.UIMedium.GetFormat(medium, &formatUtf16); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get disk format")); + VIR_FREE(disk); + goto cleanup; + } + + VBOX_UTF16_TO_UTF8(formatUtf16, &format); + disk->format = format; + VBOX_UTF16_FREE(formatUtf16); + + if (VIR_STRDUP(disk->location, def->disks[it].src->path) < 0) { + VIR_FREE(disk); + goto cleanup; + } + + rc = gVBoxAPI.UIMedium.GetId(medium, &iid); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get disk uuid")); + VIR_FREE(disk); + goto cleanup; + } + gVBoxAPI.UIID.vboxIIDToUtf8(data, &iid, &uuid); + disk->uuid = uuid; + vboxIIDUnalloc(&iid); + + rc = gVBoxAPI.UIMedium.GetParent(medium, &parentDisk); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get disk parent")); + VIR_FREE(disk); + goto cleanup; + } + + gVBoxAPI.UIMedium.GetId(parentDisk, &parentiid); + gVBoxAPI.UIID.vboxIIDToUtf8(data, &parentiid, &parentUuid); + vboxIIDUnalloc(&parentiid); + if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(disk, + snapshotMachineDesc->mediaRegistry, + parentUuid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to add hard disk to the media registry")); + VIR_FREE(disk); + goto cleanup; + } + + if (needToChangeStorageController) { + /*We need to append this disk in the storage controller*/ + char **searchResultTab = NULL; + ssize_t resultSize = 0; + char *tmp = NULL; + resultSize = virStringSearch(snapshotMachineDesc->storageController, + VBOX_UUID_REGEX, + it + 1, + &searchResultTab); + if (resultSize != it + 1) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to find UUID %s"), searchResultTab[it]); + goto cleanup; + } + + tmp = virStringReplace(snapshotMachineDesc->storageController, + searchResultTab[it], + disk->uuid); + virStringFreeList(searchResultTab); + VIR_FREE(snapshotMachineDesc->storageController); + if (!tmp) + goto cleanup; + if (VIR_STRDUP(snapshotMachineDesc->storageController, tmp) < 0) + goto cleanup; + + VIR_FREE(tmp); + } + /*Close disk*/ + rc = gVBoxAPI.UIMedium.Close(medium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to close HardDisk, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + } + } else { + /*Create a "fake" disk to avoid corrupting children snapshot disks.*/ + for (it = 0; it < def->dom->ndisks; it++) { + IMedium *medium = NULL; + PRUnichar *locationUtf16 = NULL; + char *parentUuid = NULL; + IMedium *newMedium = NULL; + PRUnichar *formatUtf16 = NULL; + PRUnichar *newLocation = NULL; + char *newLocationUtf8 = NULL; + resultCodeUnion resultCode; + virVBoxSnapshotConfHardDiskPtr disk = NULL; + char *uuid = NULL; + char *format = NULL; + char **searchResultTab = NULL; + ssize_t resultSize = 0; + char *tmp = NULL; + vboxIIDUnion iid, parentiid; + + VBOX_IID_INITIALIZE(&iid); + VBOX_IID_INITIALIZE(&parentiid); + VBOX_UTF8_TO_UTF16(def->dom->disks[it]->src->path, &locationUtf16); + rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj, + locationUtf16, + DeviceType_HardDisk, + AccessMode_ReadWrite, + &medium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to open HardDisk, rc=%08x"), + (unsigned)rc); + VBOX_UTF16_FREE(locationUtf16); + goto cleanup; + } + VBOX_UTF16_FREE(locationUtf16); + + rc = gVBoxAPI.UIMedium.GetId(medium, &parentiid); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to get hardDisk Id, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + gVBoxAPI.UIID.vboxIIDToUtf8(data, &parentiid, &parentUuid); + vboxIIDUnalloc(&parentiid); + VBOX_UTF8_TO_UTF16("VDI", &formatUtf16); + + if (virAsprintf(&newLocationUtf8, "%sfakedisk-%d.vdi", machineLocationPath, it) < 0) + goto cleanup; + VBOX_UTF8_TO_UTF16(newLocationUtf8, &newLocation); + rc = gVBoxAPI.UIVirtualBox.CreateHardDiskMedium(data->vboxObj, + formatUtf16, + newLocation, + &newMedium); + VBOX_UTF16_FREE(newLocation); + VBOX_UTF16_FREE(formatUtf16); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to create HardDisk, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + + IProgress *progress = NULL; + PRUint32 tab[1]; + tab[0] = MediumVariant_Diff; + gVBoxAPI.UIMedium.CreateDiffStorage(medium, newMedium, 1, tab, &progress); + + gVBoxAPI.UIProgress.WaitForCompletion(progress, -1); + gVBoxAPI.UIProgress.GetResultCode(progress, &resultCode); + if (RC_FAILED(resultCode)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Error while creating diff storage, rc=%08x"), + resultCode.uResultCode); + goto cleanup; + } + VBOX_RELEASE(progress); + /* + * The differential disk is created, we add it to the media registry and the + * machine storage controllers. + */ + + if (VIR_ALLOC(disk) < 0) + goto cleanup; + + rc = gVBoxAPI.UIMedium.GetId(newMedium, &iid); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to get medium uuid, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + gVBoxAPI.UIID.vboxIIDToUtf8(data, &iid, &uuid); + disk->uuid = uuid; + vboxIIDUnalloc(&iid); + + if (VIR_STRDUP(disk->location, newLocationUtf8) < 0) + goto cleanup; + + rc = gVBoxAPI.UIMedium.GetFormat(newMedium, &formatUtf16); + VBOX_UTF16_TO_UTF8(formatUtf16, &format); + disk->format = format; + VBOX_UTF16_FREE(formatUtf16); + + if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(disk, + snapshotMachineDesc->mediaRegistry, + parentUuid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to add hard disk to the media registry")); + goto cleanup; + } + /*Adding the fake disk to the machine storage controllers*/ + + resultSize = virStringSearch(snapshotMachineDesc->storageController, + VBOX_UUID_REGEX, + it + 1, + &searchResultTab); + if (resultSize != it + 1) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to find UUID %s"), searchResultTab[it]); + goto cleanup; + } + + tmp = virStringReplace(snapshotMachineDesc->storageController, + searchResultTab[it], + disk->uuid); + virStringFreeList(searchResultTab); + VIR_FREE(snapshotMachineDesc->storageController); + if (!tmp) + goto cleanup; + if (VIR_STRDUP(snapshotMachineDesc->storageController, tmp) < 0) + goto cleanup; + + VIR_FREE(tmp); + /*Closing the "fake" disk*/ + rc = gVBoxAPI.UIMedium.Close(newMedium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to close the new medium, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + } + /* + * We save the snapshot xml file to retrieve the real read-write disk during the + * next define. This file is saved as "'machineLocation'/snapshot-'uuid'.xml" + */ + VIR_FREE(currentSnapshotXmlFilePath); + if (virAsprintf(¤tSnapshotXmlFilePath, "%s%s.xml", machineLocationPath, snapshotMachineDesc->currentSnapshot) < 0) + goto cleanup; + char *snapshotContent = virDomainSnapshotDefFormat(NULL, def, VIR_DOMAIN_XML_SECURE, 0); + if (snapshotContent == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get snapshot content")); + goto cleanup; + } + if (virFileWriteStr(currentSnapshotXmlFilePath, snapshotContent, 0644) < 0) { + virReportSystemError(errno, "%s", + _("Unable to save new snapshot xml file")); + goto cleanup; + } + VIR_FREE(snapshotContent); + } + /* + * All the snapshot structure manipulation is done, we close the disks we have + * previously opened. + */ + for (it = 0; it < def->dom->ndisks; it++) { + char *location = def->dom->disks[it]->src->path; + if (!location) + goto cleanup; + + virVBoxSnapshotConfHardDiskPtr *hardDiskToOpen = NULL; + size_t hardDiskToOpenSize = virVBoxSnapshotConfDiskListToOpen(snapshotMachineDesc, + &hardDiskToOpen, location); + for (jt = 0; jt < hardDiskToOpenSize; jt++) { + IMedium *medium = NULL; + PRUnichar *locationUtf16 = NULL; + VBOX_UTF8_TO_UTF16(hardDiskToOpen[jt]->location, &locationUtf16); + rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj, + locationUtf16, + DeviceType_HardDisk, + AccessMode_ReadWrite, + &medium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to open HardDisk, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + rc = gVBoxAPI.UIMedium.Close(medium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to close HardDisk, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + VBOX_UTF16_FREE(locationUtf16); + } + } + + /*Now, we rewrite the 'machineName'.vbox file to redefine the machine.*/ + if (virVBoxSnapshotConfSaveVboxFile(snapshotMachineDesc, settingsFilePath_Utf8) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to serialize the machine description")); + goto cleanup; + } + rc = gVBoxAPI.UIVirtualBox.OpenMachine(data->vboxObj, + settingsFilePath, + &machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to open Machine, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + + rc = gVBoxAPI.UIVirtualBox.RegisterMachine(data->vboxObj, machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to register Machine, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + + ret = 0; + cleanup: + VBOX_RELEASE(machine); + VBOX_UTF16_FREE(settingsFilePath); + VBOX_UTF8_FREE(settingsFilePath_Utf8); + VIR_FREE(snapshotMachineDesc); + VIR_FREE(currentSnapshotXmlFilePath); + VBOX_UTF16_FREE(machineNameUtf16); + VBOX_UTF8_FREE(machineName); + virStringFreeList(realReadOnlyDisksPath); + virStringFreeList(realReadWriteDisksPath); + VIR_FREE(newSnapshotPtr); + VIR_FREE(machineLocationPath); + VIR_FREE(nameTmpUse); + return ret; +} + +virDomainSnapshotPtr +vboxDomainSnapshotCreateXML(virDomainPtr dom, + const char *xmlDesc, + unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, virDomainSnapshotPtr, NULL); + virDomainSnapshotDefPtr def = NULL; + vboxIIDUnion domiid; + IMachine *machine = NULL; + IConsole *console = NULL; + IProgress *progress = NULL; + ISnapshot *snapshot = NULL; + PRUnichar *name = NULL; + PRUnichar *description = NULL; + PRUint32 state; + nsresult rc; + resultCodeUnion result; + + VBOX_IID_INITIALIZE(&domiid); + /* VBox has no snapshot metadata, so this flag is trivial. */ + virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA | + VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE | + VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT, NULL); + + if (!(def = virDomainSnapshotDefParseString(xmlDesc, data->caps, + data->xmlopt, -1, + VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | + VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE))) + goto cleanup; + + + if (openSessionForMachine(data, dom->uuid, &domiid, &machine, false) < 0) + goto cleanup; + + if (gVBoxAPI.vboxSnapshotRedefine) { + PRBool isCurrent = flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT; + if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) { + if (vboxSnapshotRedefine(dom, def, isCurrent) < 0) + goto cleanup; + ret = virGetDomainSnapshot(dom, def->name); + goto cleanup; + } + } + + rc = gVBoxAPI.UIMachine.GetState(machine, &state); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get domain state")); + goto cleanup; + } + + if (gVBoxAPI.machineStateChecker.Online(state)) { + rc = gVBoxAPI.UISession.OpenExisting(data, &domiid, machine); + } else { + rc = gVBoxAPI.UISession.Open(data, &domiid, machine); + } + + if (NS_SUCCEEDED(rc)) + rc = gVBoxAPI.UISession.GetConsole(data->vboxSession, &console); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not open VirtualBox session with domain %s"), + dom->name); + goto cleanup; + } + + VBOX_UTF8_TO_UTF16(def->name, &name); + if (!name) { + virReportOOMError(); + goto cleanup; + } + + if (def->description) { + VBOX_UTF8_TO_UTF16(def->description, &description); + if (!description) { + virReportOOMError(); + goto cleanup; + } + } + + rc = gVBoxAPI.UIConsole.TakeSnapshot(console, name, description, &progress); + if (NS_FAILED(rc) || !progress) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not take snapshot of domain %s"), dom->name); + goto cleanup; + } + + gVBoxAPI.UIProgress.WaitForCompletion(progress, -1); + gVBoxAPI.UIProgress.GetResultCode(progress, &result); + if (RC_FAILED(result)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not take snapshot of domain %s"), dom->name); + goto cleanup; + } + + rc = gVBoxAPI.UIMachine.GetCurrentSnapshot(machine, &snapshot); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get current snapshot of domain %s"), + dom->name); + goto cleanup; + } + + ret = virGetDomainSnapshot(dom, def->name); + + cleanup: + VBOX_RELEASE(progress); + VBOX_UTF16_FREE(description); + VBOX_UTF16_FREE(name); + VBOX_RELEASE(console); + gVBoxAPI.UISession.Close(data->vboxSession); + VBOX_RELEASE(machine); + vboxIIDUnalloc(&domiid); + virDomainSnapshotDefFree(def); + return ret; +} diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h index a093481..1c01fe8 100644 --- a/src/vbox/vbox_common.h +++ b/src/vbox/vbox_common.h @@ -247,6 +247,24 @@ enum MediumType MediumType_Writethrough = 2, }; +enum CleanupMode +{ + CleanupMode_UnregisterOnly = 1, + CleanupMode_DetachAllReturnNone = 2, + CleanupMode_DetachAllReturnHardDisksOnly = 3, + CleanupMode_Full = 4 +}; + +enum MediumVariant +{ + MediumVariant_Standard = 0, + MediumVariant_VmdkSplit2G = 0x01, + MediumVariant_VmdkStreamOptimized = 0x04, + MediumVariant_VmdkESX = 0x08, + MediumVariant_Fixed = 0x10000, + MediumVariant_Diff = 0x20000 +}; + /* Simplied definitions in vbox_CAPI_*.h */ typedef void const *PCVBOXXPCOM; diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 2d5ea5c..2218baf 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1588,1093 +1588,6 @@ vboxDomainSnapshotGet(vboxGlobalData *data, return snapshot; } -#if VBOX_API_VERSION >= 4002000 -static int vboxCloseDisksRecursively(virDomainPtr dom, char *location) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - nsresult rc; - size_t i = 0; - PRUnichar *locationUtf = NULL; - IMedium *medium = NULL; - IMedium **children = NULL; - PRUint32 childrenSize = 0; - VBOX_UTF8_TO_UTF16(location, &locationUtf); - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, - locationUtf, - DeviceType_HardDisk, - AccessMode_ReadWrite, - false, - &medium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to open HardDisk, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - rc = medium->vtbl->GetChildren(medium, &childrenSize, &children); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s" - , _("Unable to get disk children")); - goto cleanup; - } - for (i = 0; i < childrenSize; i++) { - IMedium *childMedium = children[i]; - if (childMedium) { - PRUnichar *childLocationUtf = NULL; - char *childLocation = NULL; - rc = childMedium->vtbl->GetLocation(childMedium, &childLocationUtf); - VBOX_UTF16_TO_UTF8(childLocationUtf, &childLocation); - VBOX_UTF16_FREE(childLocationUtf); - if (vboxCloseDisksRecursively(dom, childLocation) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s" - , _("Unable to close disk children")); - goto cleanup; - } - VIR_FREE(childLocation); - } - } - rc = medium->vtbl->Close(medium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to close HardDisk, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - - ret = 0; - cleanup: - VBOX_UTF16_FREE(locationUtf); - return ret; -} - -static int -vboxSnapshotRedefine(virDomainPtr dom, - virDomainSnapshotDefPtr def, - bool isCurrent) -{ - /* - * If your snapshot has a parent, - * it will only be redefined if you have already - * redefined the parent. - * - * The general algorithm of this function is below : - * First of all, we are going to create our vboxSnapshotXmlMachinePtr struct from - * the machine settings path. - * Then, if the machine current snapshot xml file is saved in the machine location, - * it means that this snapshot was previously modified by us and has fake disks. - * Fake disks are added when the flag VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT was not set - * yet, in order to not corrupt read-only disks. The first thing to do is to remove those - * disks and restore the read-write disks, if any, in the vboxSnapshotXmlMachinePtr struct. - * We also delete the current snapshot xml file. - * - * After that, we are going to register the snapshot read-only disks that we want to redefine, - * if they are not in the media registry struct. - * - * The next step is to unregister the machine and close all disks. - * - * Then, we check if the flag VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE has already been set. - * If this flag was set, we just add read-write disks to the media registry - * struct. Otherwise, we save the snapshot xml file into the machine location in order - * to recover the read-write disks during the next redefine and we create differential disks - * from the snapshot read-only disks and add them to the media registry struct. - * - * Finally, we register the machine with the new virtualbox description file. - */ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxIID domiid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - nsresult rc; - PRUnichar *settingsFilePath = NULL; - char *settingsFilePath_Utf8 = NULL; - virVBoxSnapshotConfMachinePtr snapshotMachineDesc = NULL; - char *currentSnapshotXmlFilePath = NULL; - PRUnichar *machineNameUtf16 = NULL; - char *machineName = NULL; - char **realReadWriteDisksPath = NULL; - int realReadWriteDisksPathSize = 0; - char **realReadOnlyDisksPath = NULL; - int realReadOnlyDisksPathSize = 0; - virVBoxSnapshotConfSnapshotPtr newSnapshotPtr = NULL; - unsigned char snapshotUuid[VIR_UUID_BUFLEN]; - int it = 0; - int jt = 0; - PRUint32 aMediaSize = 0; - IMedium **aMedia = NULL; - char *machineLocationPath = NULL; - char *nameTmpUse = NULL; - bool snapshotFileExists = false; - bool needToChangeStorageController = false; - - vboxIIDFromUUID(&domiid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching UUID")); - goto cleanup; - } - - rc = machine->vtbl->SaveSettings(machine); - /*It may failed when the machine is not mutable.*/ - rc = machine->vtbl->GetSettingsFilePath(machine, &settingsFilePath); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get settings file path")); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(settingsFilePath, &settingsFilePath_Utf8); - - /*Getting the machine name to retrieve the machine location path.*/ - rc = machine->vtbl->GetName(machine, &machineNameUtf16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get machine name")); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineName); - - if (virAsprintf(&nameTmpUse, "%s.vbox", machineName) < 0) - goto cleanup; - machineLocationPath = virStringReplace(settingsFilePath_Utf8, nameTmpUse, ""); - if (machineLocationPath == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get the machine location path")); - goto cleanup; - } - - /*We create the xml struct with the settings file path.*/ - snapshotMachineDesc = virVBoxSnapshotConfLoadVboxFile(settingsFilePath_Utf8, machineLocationPath); - if (snapshotMachineDesc == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot create a vboxSnapshotXmlPtr")); - goto cleanup; - } - if (snapshotMachineDesc->currentSnapshot != NULL) { - if (virAsprintf(¤tSnapshotXmlFilePath, "%s%s.xml", machineLocationPath, - snapshotMachineDesc->currentSnapshot) < 0) - goto cleanup; - snapshotFileExists = virFileExists(currentSnapshotXmlFilePath); - } - - if (snapshotFileExists) { - /* - * We have created fake disks, so we have to remove them and replace them with - * the read-write disks if there are any. The fake disks will be closed during - * the machine unregistration. - */ - if (virVBoxSnapshotConfRemoveFakeDisks(snapshotMachineDesc) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to remove Fake Disks")); - goto cleanup; - } - realReadWriteDisksPathSize = virVBoxSnapshotConfGetRWDisksPathsFromLibvirtXML(currentSnapshotXmlFilePath, - &realReadWriteDisksPath); - realReadOnlyDisksPathSize = virVBoxSnapshotConfGetRODisksPathsFromLibvirtXML(currentSnapshotXmlFilePath, - &realReadOnlyDisksPath); - /*The read-only disk number is necessarily greater or equal to the - *read-write disk number*/ - if (realReadOnlyDisksPathSize < realReadWriteDisksPathSize) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("The read only disk number must be greater or equal to the " - " read write disk number")); - goto cleanup; - } - for (it = 0; it < realReadWriteDisksPathSize; it++) { - virVBoxSnapshotConfHardDiskPtr readWriteDisk = NULL; - PRUnichar *locationUtf = NULL; - IMedium *readWriteMedium = NULL; - PRUnichar *uuidUtf = NULL; - char *uuid = NULL; - PRUnichar *formatUtf = NULL; - char *format = NULL; - const char *parentUuid = NULL; - - VBOX_UTF8_TO_UTF16(realReadWriteDisksPath[it], &locationUtf); - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, - locationUtf, - DeviceType_HardDisk, - AccessMode_ReadWrite, - false, - &readWriteMedium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to open HardDisk, rc=%08x"), - (unsigned)rc); - VBOX_UTF16_FREE(locationUtf); - goto cleanup; - } - VBOX_UTF16_FREE(locationUtf); - - rc = readWriteMedium->vtbl->GetId(readWriteMedium, &uuidUtf); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get the read write medium id")); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(uuidUtf, &uuid); - VBOX_UTF16_FREE(uuidUtf); - - rc = readWriteMedium->vtbl->GetFormat(readWriteMedium, &formatUtf); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get the read write medium format")); - VIR_FREE(uuid); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(formatUtf, &format); - VBOX_UTF16_FREE(formatUtf); - - if (VIR_ALLOC(readWriteDisk) < 0) { - VIR_FREE(uuid); - VIR_FREE(formatUtf); - goto cleanup; - } - - readWriteDisk->format = format; - readWriteDisk->uuid = uuid; - readWriteDisk->location = realReadWriteDisksPath[it]; - /* - * We get the current snapshot's read-only disk uuid in order to add the - * read-write disk to the media registry as it's child. The read-only disk - * is already in the media registry because it is the fake disk's parent. - */ - parentUuid = virVBoxSnapshotConfHardDiskUuidByLocation(snapshotMachineDesc, - realReadOnlyDisksPath[it]); - if (parentUuid == NULL) { - VIR_FREE(readWriteDisk); - goto cleanup; - } - - if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(readWriteDisk, - snapshotMachineDesc->mediaRegistry, - parentUuid) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to add hard disk to media Registry")); - VIR_FREE(readWriteDisk); - goto cleanup; - } - rc = readWriteMedium->vtbl->Close(readWriteMedium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to close HardDisk, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - } - /* - * Now we have done this swap, we remove the snapshot xml file from the - * current machine location. - */ - if (unlink(currentSnapshotXmlFilePath) < 0) { - virReportSystemError(errno, - _("Unable to delete file %s"), currentSnapshotXmlFilePath); - goto cleanup; - } - } - /* - * Before unregistering the machine, while all disks are still open, ensure that all - * read-only disks are in the redefined snapshot's media registry (the disks need to - * be open to query their uuid). - */ - for (it = 0; it < def->dom->ndisks; it++) { - int diskInMediaRegistry = 0; - IMedium *readOnlyMedium = NULL; - PRUnichar *locationUtf = NULL; - PRUnichar *uuidUtf = NULL; - char *uuid = NULL; - PRUnichar *formatUtf = NULL; - char *format = NULL; - PRUnichar *parentUuidUtf = NULL; - char *parentUuid = NULL; - virVBoxSnapshotConfHardDiskPtr readOnlyDisk = NULL; - - diskInMediaRegistry = virVBoxSnapshotConfDiskIsInMediaRegistry(snapshotMachineDesc, - def->dom->disks[it]->src->path); - if (diskInMediaRegistry == -1) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to know if disk is in media registry")); - goto cleanup; - } - if (diskInMediaRegistry == 1) /*Nothing to do.*/ - continue; - /*The read only disk is not in the media registry*/ - - VBOX_UTF8_TO_UTF16(def->dom->disks[it]->src->path, &locationUtf); - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, - locationUtf, - DeviceType_HardDisk, - AccessMode_ReadWrite, - false, - &readOnlyMedium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to open HardDisk, rc=%08x"), - (unsigned)rc); - VBOX_UTF16_FREE(locationUtf); - goto cleanup; - } - VBOX_UTF16_FREE(locationUtf); - - rc = readOnlyMedium->vtbl->GetId(readOnlyMedium, &uuidUtf); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get hard disk id")); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(uuidUtf, &uuid); - VBOX_UTF16_FREE(uuidUtf); - - rc = readOnlyMedium->vtbl->GetFormat(readOnlyMedium, &formatUtf); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get hard disk format")); - VIR_FREE(uuid); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(formatUtf, &format); - VBOX_UTF16_FREE(formatUtf); - - /*This disk is already in the media registry*/ - IMedium *parentReadOnlyMedium = NULL; - rc = readOnlyMedium->vtbl->GetParent(readOnlyMedium, &parentReadOnlyMedium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get parent hard disk")); - VIR_FREE(uuid); - goto cleanup; - } - - rc = parentReadOnlyMedium->vtbl->GetId(parentReadOnlyMedium, &parentUuidUtf); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to get hard disk id, rc=%08x"), - (unsigned)rc); - VIR_FREE(uuid); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(parentUuidUtf, &parentUuid); - VBOX_UTF16_FREE(parentUuidUtf); - - rc = readOnlyMedium->vtbl->Close(readOnlyMedium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to close HardDisk, rc=%08x"), - (unsigned)rc); - VIR_FREE(uuid); - VIR_FREE(parentUuid); - goto cleanup; - } - - if (VIR_ALLOC(readOnlyDisk) < 0) { - VIR_FREE(uuid); - VIR_FREE(parentUuid); - goto cleanup; - } - - readOnlyDisk->format = format; - readOnlyDisk->uuid = uuid; - if (VIR_STRDUP(readOnlyDisk->location, def->dom->disks[it]->src->path) < 0) { - VIR_FREE(readOnlyDisk); - goto cleanup; - } - - if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(readOnlyDisk, snapshotMachineDesc->mediaRegistry, - parentUuid) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to add hard disk to media registry")); - VIR_FREE(readOnlyDisk); - goto cleanup; - } - } - - /*Now, we can unregister the machine*/ - rc = machine->vtbl->Unregister(machine, - CleanupMode_DetachAllReturnHardDisksOnly, - &aMediaSize, - &aMedia); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to unregister machine, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - VBOX_RELEASE(machine); - - /* - * Unregister the machine, and then close all disks returned by the unregister method. - * Some close operations will fail because some disks that need to be closed will not - * be returned by virtualbox. We will close them just after. We have to use this - * solution because it is the only way to delete fake disks. - */ - for (it = 0; it < aMediaSize; it++) { - IMedium *medium = aMedia[it]; - if (medium) { - PRUnichar *locationUtf16 = NULL; - char *locationUtf8 = NULL; - rc = medium->vtbl->GetLocation(medium, &locationUtf16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get medium location")); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(locationUtf16, &locationUtf8); - VBOX_UTF16_FREE(locationUtf16); - if (strstr(locationUtf8, "fake") != NULL) { - /*we delete the fake disk because we don't need it anymore*/ - IProgress *progress = NULL; - PRInt32 resultCode = -1; - rc = medium->vtbl->DeleteStorage(medium, &progress); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to delete medium, rc=%08x"), - (unsigned)rc); - VIR_FREE(locationUtf8); - goto cleanup; - } - progress->vtbl->WaitForCompletion(progress, -1); - progress->vtbl->GetResultCode(progress, &resultCode); - if (NS_FAILED(resultCode)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Error while closing medium, rc=%08x"), - (unsigned)resultCode); - VIR_FREE(locationUtf8); - goto cleanup; - } - VBOX_RELEASE(progress); - } else { - /* - * This a comment from vboxmanage code in the handleUnregisterVM - * function in VBoxManageMisc.cpp : - * Note that the IMachine::Unregister method will return the medium - * reference in a sane order, which means that closing will normally - * succeed, unless there is still another machine which uses the - * medium. No harm done if we ignore the error. - */ - rc = medium->vtbl->Close(medium); - } - VBOX_UTF8_FREE(locationUtf8); - } - } - /*Close all disks that failed to close normally.*/ - for (it = 0; it < snapshotMachineDesc->mediaRegistry->ndisks; it++) { - if (vboxCloseDisksRecursively(dom, snapshotMachineDesc->mediaRegistry->disks[it]->location) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to close recursively all disks")); - goto cleanup; - } - } - /*Here, all disks are closed or deleted*/ - - /*We are now going to create and fill the Snapshot xml struct*/ - if (VIR_ALLOC(newSnapshotPtr) < 0) - goto cleanup; - - if (virUUIDGenerate(snapshotUuid) < 0) - goto cleanup; - - char uuidtmp[VIR_UUID_STRING_BUFLEN]; - virUUIDFormat(snapshotUuid, uuidtmp); - if (VIR_STRDUP(newSnapshotPtr->uuid, uuidtmp) < 0) - goto cleanup; - - VIR_DEBUG("New snapshot UUID: %s", newSnapshotPtr->uuid); - if (VIR_STRDUP(newSnapshotPtr->name, def->name) < 0) - goto cleanup; - - newSnapshotPtr->timeStamp = virTimeStringThen(def->creationTime * 1000); - - if (VIR_STRDUP(newSnapshotPtr->description, def->description) < 0) - goto cleanup; - - if (VIR_STRDUP(newSnapshotPtr->hardware, snapshotMachineDesc->hardware) < 0) - goto cleanup; - - if (VIR_STRDUP(newSnapshotPtr->storageController, snapshotMachineDesc->storageController) < 0) - goto cleanup; - - /*We get the parent disk uuid from the parent disk location to correctly fill the storage controller.*/ - for (it = 0; it < def->dom->ndisks; it++) { - char *location = NULL; - const char *uuidReplacing = NULL; - char **searchResultTab = NULL; - ssize_t resultSize = 0; - char *tmp = NULL; - - location = def->dom->disks[it]->src->path; - if (!location) - goto cleanup; - /*Replacing the uuid*/ - uuidReplacing = virVBoxSnapshotConfHardDiskUuidByLocation(snapshotMachineDesc, location); - if (uuidReplacing == NULL) - goto cleanup; - - resultSize = virStringSearch(newSnapshotPtr->storageController, - VBOX_UUID_REGEX, - it + 1, - &searchResultTab); - if (resultSize != it + 1) - goto cleanup; - - tmp = virStringReplace(newSnapshotPtr->storageController, - searchResultTab[it], - uuidReplacing); - virStringFreeList(searchResultTab); - VIR_FREE(newSnapshotPtr->storageController); - if (!tmp) - goto cleanup; - if (VIR_STRDUP(newSnapshotPtr->storageController, tmp) < 0) - goto cleanup; - - VIR_FREE(tmp); - } - if (virVBoxSnapshotConfAddSnapshotToXmlMachine(newSnapshotPtr, snapshotMachineDesc, def->parent) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to add the snapshot to the machine description")); - goto cleanup; - } - /* - * We change the current snapshot only if there is no current snapshot or if the - * snapshotFile exists, otherwise, it means that the correct current snapshot is - * already set. - */ - - if (snapshotMachineDesc->currentSnapshot == NULL || snapshotFileExists) { - snapshotMachineDesc->currentSnapshot = newSnapshotPtr->uuid; - needToChangeStorageController = true; - } - - /* - * Open the snapshot's read-write disk's full ancestry to allow opening the - * read-write disk itself. - */ - for (it = 0; it < def->dom->ndisks; it++) { - char *location = NULL; - virVBoxSnapshotConfHardDiskPtr *hardDiskToOpen = NULL; - size_t hardDiskToOpenSize = 0; - - location = def->dom->disks[it]->src->path; - if (!location) - goto cleanup; - - hardDiskToOpenSize = virVBoxSnapshotConfDiskListToOpen(snapshotMachineDesc, - &hardDiskToOpen, location); - for (jt = hardDiskToOpenSize -1; jt >= 0; jt--) { - IMedium *medium = NULL; - PRUnichar *locationUtf16 = NULL; - VBOX_UTF8_TO_UTF16(hardDiskToOpen[jt]->location, &locationUtf16); - - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, - locationUtf16, - DeviceType_HardDisk, - AccessMode_ReadWrite, - false, - &medium); - VBOX_UTF16_FREE(locationUtf16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to open HardDisk, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - } - } - if (isCurrent || !needToChangeStorageController) { - /* We don't create a differential hard disk because either the current snapshot - * has already been defined or the snapshot to redefine is the current snapshot. - * If the snapshot to redefine is the current snapshot, we add read-write disks in - * the machine storage controllers. - */ - for (it = 0; it < def->ndisks; it++) { - IMedium *medium = NULL; - PRUnichar *locationUtf16 = NULL; - virVBoxSnapshotConfHardDiskPtr disk = NULL; - PRUnichar *formatUtf16 = NULL; - char *format = NULL; - PRUnichar *uuidUtf16 = NULL; - char *uuid = NULL; - IMedium *parentDisk = NULL; - PRUnichar *parentUuidUtf16 = NULL; - char *parentUuid = NULL; - - VBOX_UTF8_TO_UTF16(def->disks[it].src->path, &locationUtf16); - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, - locationUtf16, - DeviceType_HardDisk, - AccessMode_ReadWrite, - false, - &medium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to open HardDisk, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - VBOX_UTF16_FREE(locationUtf16); - - if (VIR_ALLOC(disk) < 0) - goto cleanup; - - rc = medium->vtbl->GetFormat(medium, &formatUtf16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get disk format")); - VIR_FREE(disk); - goto cleanup; - } - - VBOX_UTF16_TO_UTF8(formatUtf16, &format); - disk->format = format; - VBOX_UTF16_FREE(formatUtf16); - - if (VIR_STRDUP(disk->location, def->disks[it].src->path) < 0) { - VIR_FREE(disk); - goto cleanup; - } - - rc = medium->vtbl->GetId(medium, &uuidUtf16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get disk uuid")); - VIR_FREE(disk); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(uuidUtf16, &uuid); - disk->uuid = uuid; - VBOX_UTF16_FREE(uuidUtf16); - - rc = medium->vtbl->GetParent(medium, &parentDisk); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get disk parent")); - VIR_FREE(disk); - goto cleanup; - } - - parentDisk->vtbl->GetId(parentDisk, &parentUuidUtf16); - VBOX_UTF16_TO_UTF8(parentUuidUtf16, &parentUuid); - VBOX_UTF16_FREE(parentUuidUtf16); - if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(disk, - snapshotMachineDesc->mediaRegistry, - parentUuid) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to add hard disk to the media registry")); - VIR_FREE(disk); - goto cleanup; - } - - if (needToChangeStorageController) { - /*We need to append this disk in the storage controller*/ - char **searchResultTab = NULL; - ssize_t resultSize = 0; - char *tmp = NULL; - resultSize = virStringSearch(snapshotMachineDesc->storageController, - VBOX_UUID_REGEX, - it + 1, - &searchResultTab); - if (resultSize != it + 1) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to find UUID %s"), searchResultTab[it]); - goto cleanup; - } - - tmp = virStringReplace(snapshotMachineDesc->storageController, - searchResultTab[it], - disk->uuid); - virStringFreeList(searchResultTab); - VIR_FREE(snapshotMachineDesc->storageController); - if (!tmp) - goto cleanup; - if (VIR_STRDUP(snapshotMachineDesc->storageController, tmp) < 0) - goto cleanup; - - VIR_FREE(tmp); - } - /*Close disk*/ - rc = medium->vtbl->Close(medium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to close HardDisk, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - } - } else { - /*Create a "fake" disk to avoid corrupting children snapshot disks.*/ - for (it = 0; it < def->dom->ndisks; it++) { - IMedium *medium = NULL; - PRUnichar *locationUtf16 = NULL; - PRUnichar *parentUuidUtf16 = NULL; - char *parentUuid = NULL; - IMedium *newMedium = NULL; - PRUnichar *formatUtf16 = NULL; - PRUnichar *newLocation = NULL; - char *newLocationUtf8 = NULL; - PRInt32 resultCode = -1; - virVBoxSnapshotConfHardDiskPtr disk = NULL; - PRUnichar *uuidUtf16 = NULL; - char *uuid = NULL; - char *format = NULL; - char **searchResultTab = NULL; - ssize_t resultSize = 0; - char *tmp = NULL; - - VBOX_UTF8_TO_UTF16(def->dom->disks[it]->src->path, &locationUtf16); - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, - locationUtf16, - DeviceType_HardDisk, - AccessMode_ReadWrite, - false, - &medium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to open HardDisk, rc=%08x"), - (unsigned)rc); - VBOX_UTF16_FREE(locationUtf16); - goto cleanup; - } - VBOX_UTF16_FREE(locationUtf16); - - rc = medium->vtbl->GetId(medium, &parentUuidUtf16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to get hardDisk Id, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(parentUuidUtf16, &parentUuid); - VBOX_UTF16_FREE(parentUuidUtf16); - VBOX_UTF8_TO_UTF16("VDI", &formatUtf16); - - if (virAsprintf(&newLocationUtf8, "%sfakedisk-%d.vdi", machineLocationPath, it) < 0) - goto cleanup; - VBOX_UTF8_TO_UTF16(newLocationUtf8, &newLocation); - rc = data->vboxObj->vtbl->CreateHardDisk(data->vboxObj, - formatUtf16, - newLocation, - &newMedium); - VBOX_UTF16_FREE(newLocation); - VBOX_UTF16_FREE(formatUtf16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to create HardDisk, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - - IProgress *progress = NULL; -# if VBOX_API_VERSION < 4003000 - medium->vtbl->CreateDiffStorage(medium, newMedium, MediumVariant_Diff, &progress); -# else - PRUint32 tab[1]; - tab[0] = MediumVariant_Diff; - medium->vtbl->CreateDiffStorage(medium, newMedium, 1, tab, &progress); -# endif - - progress->vtbl->WaitForCompletion(progress, -1); - progress->vtbl->GetResultCode(progress, &resultCode); - if (NS_FAILED(resultCode)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Error while creating diff storage, rc=%08x"), - (unsigned)resultCode); - goto cleanup; - } - VBOX_RELEASE(progress); - /* - * The differential disk is created, we add it to the media registry and the - * machine storage controllers. - */ - - if (VIR_ALLOC(disk) < 0) - goto cleanup; - - rc = newMedium->vtbl->GetId(newMedium, &uuidUtf16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to get medium uuid, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(uuidUtf16, &uuid); - disk->uuid = uuid; - VBOX_UTF16_FREE(uuidUtf16); - - if (VIR_STRDUP(disk->location, newLocationUtf8) < 0) - goto cleanup; - - rc = newMedium->vtbl->GetFormat(newMedium, &formatUtf16); - VBOX_UTF16_TO_UTF8(formatUtf16, &format); - disk->format = format; - VBOX_UTF16_FREE(formatUtf16); - - if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(disk, - snapshotMachineDesc->mediaRegistry, - parentUuid) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to add hard disk to the media registry")); - goto cleanup; - } - /*Adding the fake disk to the machine storage controllers*/ - - resultSize = virStringSearch(snapshotMachineDesc->storageController, - VBOX_UUID_REGEX, - it + 1, - &searchResultTab); - if (resultSize != it + 1) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to find UUID %s"), searchResultTab[it]); - goto cleanup; - } - - tmp = virStringReplace(snapshotMachineDesc->storageController, - searchResultTab[it], - disk->uuid); - virStringFreeList(searchResultTab); - VIR_FREE(snapshotMachineDesc->storageController); - if (!tmp) - goto cleanup; - if (VIR_STRDUP(snapshotMachineDesc->storageController, tmp) < 0) - goto cleanup; - - VIR_FREE(tmp); - /*Closing the "fake" disk*/ - rc = newMedium->vtbl->Close(newMedium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to close the new medium, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - } - /* - * We save the snapshot xml file to retrieve the real read-write disk during the - * next define. This file is saved as "'machineLocation'/snapshot-'uuid'.xml" - */ - VIR_FREE(currentSnapshotXmlFilePath); - if (virAsprintf(¤tSnapshotXmlFilePath, "%s%s.xml", machineLocationPath, snapshotMachineDesc->currentSnapshot) < 0) - goto cleanup; - char *snapshotContent = virDomainSnapshotDefFormat(NULL, def, VIR_DOMAIN_XML_SECURE, 0); - if (snapshotContent == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get snapshot content")); - goto cleanup; - } - if (virFileWriteStr(currentSnapshotXmlFilePath, snapshotContent, 0644) < 0) { - virReportSystemError(errno, "%s", - _("Unable to save new snapshot xml file")); - goto cleanup; - } - VIR_FREE(snapshotContent); - } - /* - * All the snapshot structure manipulation is done, we close the disks we have - * previously opened. - */ - for (it = 0; it < def->dom->ndisks; it++) { - char *location = def->dom->disks[it]->src->path; - if (!location) - goto cleanup; - - virVBoxSnapshotConfHardDiskPtr *hardDiskToOpen = NULL; - size_t hardDiskToOpenSize = virVBoxSnapshotConfDiskListToOpen(snapshotMachineDesc, - &hardDiskToOpen, location); - for (jt = 0; jt < hardDiskToOpenSize; jt++) { - IMedium *medium = NULL; - PRUnichar *locationUtf16 = NULL; - VBOX_UTF8_TO_UTF16(hardDiskToOpen[jt]->location, &locationUtf16); - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, - locationUtf16, - DeviceType_HardDisk, - AccessMode_ReadWrite, - false, - &medium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to open HardDisk, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - rc = medium->vtbl->Close(medium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to close HardDisk, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - VBOX_UTF16_FREE(locationUtf16); - } - } - - /*Now, we rewrite the 'machineName'.vbox file to redefine the machine.*/ - if (virVBoxSnapshotConfSaveVboxFile(snapshotMachineDesc, settingsFilePath_Utf8) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to serialize the machine description")); - goto cleanup; - } - rc = data->vboxObj->vtbl->OpenMachine(data->vboxObj, - settingsFilePath, - &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to open Machine, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - - rc = data->vboxObj->vtbl->RegisterMachine(data->vboxObj, machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to register Machine, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - - ret = 0; - cleanup: - VBOX_RELEASE(machine); - VBOX_UTF16_FREE(settingsFilePath); - VBOX_UTF8_FREE(settingsFilePath_Utf8); - VIR_FREE(snapshotMachineDesc); - VIR_FREE(currentSnapshotXmlFilePath); - VBOX_UTF16_FREE(machineNameUtf16); - VBOX_UTF8_FREE(machineName); - virStringFreeList(realReadOnlyDisksPath); - virStringFreeList(realReadWriteDisksPath); - VIR_FREE(newSnapshotPtr); - VIR_FREE(machineLocationPath); - VIR_FREE(nameTmpUse); - return ret; -} -#endif - -static virDomainSnapshotPtr -vboxDomainSnapshotCreateXML(virDomainPtr dom, - const char *xmlDesc, - unsigned int flags) -{ - VBOX_OBJECT_CHECK(dom->conn, virDomainSnapshotPtr, NULL); - virDomainSnapshotDefPtr def = NULL; - vboxIID domiid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - IConsole *console = NULL; - IProgress *progress = NULL; - ISnapshot *snapshot = NULL; - PRUnichar *name = NULL; - PRUnichar *description = NULL; - PRUint32 state; - nsresult rc; -#if VBOX_API_VERSION == 2002000 - nsresult result; -#else - PRInt32 result; -#endif -#if VBOX_API_VERSION >= 4002000 - bool isCurrent = false; -#endif - - - /* VBox has no snapshot metadata, so this flag is trivial. */ - virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA | - VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE | - VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT, NULL); - - if (!(def = virDomainSnapshotDefParseString(xmlDesc, data->caps, - data->xmlopt, -1, - VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | - VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE))) - goto cleanup; - - - vboxIIDFromUUID(&domiid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching UUID")); - goto cleanup; - } - -#if VBOX_API_VERSION >= 4002000 - isCurrent = flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT; - if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) { - if (vboxSnapshotRedefine(dom, def, isCurrent) < 0) - goto cleanup; - ret = virGetDomainSnapshot(dom, def->name); - goto cleanup; - } -#endif - - rc = machine->vtbl->GetState(machine, &state); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get domain state")); - goto cleanup; - } - - if ((state >= MachineState_FirstOnline) - && (state <= MachineState_LastOnline)) { - rc = VBOX_SESSION_OPEN_EXISTING(domiid.value, machine); - } else { - rc = VBOX_SESSION_OPEN(domiid.value, machine); - } - - if (NS_SUCCEEDED(rc)) - rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not open VirtualBox session with domain %s"), - dom->name); - goto cleanup; - } - - VBOX_UTF8_TO_UTF16(def->name, &name); - if (!name) { - virReportOOMError(); - goto cleanup; - } - - if (def->description) { - VBOX_UTF8_TO_UTF16(def->description, &description); - if (!description) { - virReportOOMError(); - goto cleanup; - } - } - - rc = console->vtbl->TakeSnapshot(console, name, description, &progress); - if (NS_FAILED(rc) || !progress) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not take snapshot of domain %s"), dom->name); - goto cleanup; - } - - progress->vtbl->WaitForCompletion(progress, -1); - progress->vtbl->GetResultCode(progress, &result); - if (NS_FAILED(result)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not take snapshot of domain %s"), dom->name); - goto cleanup; - } - - rc = machine->vtbl->GetCurrentSnapshot(machine, &snapshot); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get current snapshot of domain %s"), - dom->name); - goto cleanup; - } - - ret = virGetDomainSnapshot(dom, def->name); - - cleanup: - VBOX_RELEASE(progress); - VBOX_UTF16_FREE(description); - VBOX_UTF16_FREE(name); - VBOX_RELEASE(console); - VBOX_SESSION_CLOSE(); - VBOX_RELEASE(machine); - vboxIIDUnalloc(&domiid); - virDomainSnapshotDefFree(def); - return ret; -} - #if VBOX_API_VERSION >=4002000 static int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def, diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index b36e154..8357df5 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -552,6 +552,11 @@ int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, int vboxDomainDetachDevice(virDomainPtr dom, const char *xml); int vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags); +virDomainSnapshotPtr +vboxDomainSnapshotCreateXML(virDomainPtr dom, + const char *xmlDesc, + unsigned int flags); + /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 712 ++++++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 756 ++++++----------------------------------- src/vbox/vbox_uniformed_api.h | 22 +- 3 files changed, 843 insertions(+), 647 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 8f3fe03..36260de 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -77,6 +77,8 @@ 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_ADDREF(arg) gVBoxAPI.nsUISupports.AddRef((void *)(arg)) + #define VBOX_RELEASE(arg) \ do { \ if (arg) { \ @@ -5369,3 +5371,713 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom, virDomainSnapshotDefFree(def); return ret; } + +static int +vboxDomainSnapshotGetAll(virDomainPtr dom, + IMachine *machine, + ISnapshot ***snapshots) +{ + vboxIIDUnion empty; + ISnapshot **list = NULL; + PRUint32 count; + nsresult rc; + unsigned int next; + unsigned int top; + + VBOX_IID_INITIALIZE(&empty); + rc = gVBoxAPI.UIMachine.GetSnapshotCount(machine, &count); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get snapshot count for domain %s"), + dom->name); + goto error; + } + + if (count == 0) + goto out; + + if (VIR_ALLOC_N(list, count) < 0) + goto error; + + rc = gVBoxAPI.UIMachine.FindSnapshot(machine, &empty, list); + if (NS_FAILED(rc) || !list[0]) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get root snapshot for domain %s"), + dom->name); + goto error; + } + + /* BFS walk through snapshot tree */ + top = 1; + for (next = 0; next < count; next++) { + vboxArray children = VBOX_ARRAY_INITIALIZER; + size_t i; + + if (!list[next]) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected number of snapshots < %u"), count); + goto error; + } + + rc = gVBoxAPI.UArray.vboxArrayGet(&children, list[next], + gVBoxAPI.UArray.handleSnapshotGetChildren(list[next])); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("could not get children snapshots")); + goto error; + } + for (i = 0; i < children.count; i++) { + ISnapshot *child = children.items[i]; + if (!child) + continue; + if (top == count) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected number of snapshots > %u"), count); + gVBoxAPI.UArray.vboxArrayRelease(&children); + goto error; + } + VBOX_ADDREF(child); + list[top++] = child; + } + gVBoxAPI.UArray.vboxArrayRelease(&children); + } + + out: + *snapshots = list; + return count; + + error: + if (list) { + for (next = 0; next < count; next++) + VBOX_RELEASE(list[next]); + } + VIR_FREE(list); + + return -1; +} + +static ISnapshot * +vboxDomainSnapshotGet(vboxGlobalData *data, + virDomainPtr dom, + IMachine *machine, + const char *name) +{ + ISnapshot **snapshots = NULL; + ISnapshot *snapshot = NULL; + nsresult rc; + int count = 0; + size_t i; + + if ((count = vboxDomainSnapshotGetAll(dom, machine, &snapshots)) < 0) + goto cleanup; + + for (i = 0; i < count; i++) { + PRUnichar *nameUtf16; + char *nameUtf8; + + rc = gVBoxAPI.UISnapshot.GetName(snapshots[i], &nameUtf16); + if (NS_FAILED(rc) || !nameUtf16) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("could not get snapshot name")); + goto cleanup; + } + VBOX_UTF16_TO_UTF8(nameUtf16, &nameUtf8); + VBOX_UTF16_FREE(nameUtf16); + if (STREQ(name, nameUtf8)) + snapshot = snapshots[i]; + VBOX_UTF8_FREE(nameUtf8); + + if (snapshot) + break; + } + + if (!snapshot) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("domain %s has no snapshots with name %s"), + dom->name, name); + goto cleanup; + } + + cleanup: + if (count > 0) { + for (i = 0; i < count; i++) { + if (snapshots[i] != snapshot) + VBOX_RELEASE(snapshots[i]); + } + } + VIR_FREE(snapshots); + return snapshot; +} + +static +int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def, + virDomainSnapshotPtr snapshot) +{ + virDomainPtr dom = snapshot->domain; + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIIDUnion domiid; + IMachine *machine = NULL; + ISnapshot *snap = NULL; + IMachine *snapMachine = NULL; + vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER; + PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {}; + PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {}; + int diskCount = 0; + nsresult rc; + vboxIIDUnion snapIid; + char *snapshotUuidStr = NULL; + size_t i = 0; + + if (!gVBoxAPI.vboxSnapshotRedefine) + VIR_WARN("This function may not work in current version"); + + VBOX_IID_INITIALIZE(&snapIid); + if (openSessionForMachine(data, dom->uuid, &domiid, &machine, false) < 0) + goto cleanup; + + if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) + goto cleanup; + + rc = gVBoxAPI.UISnapshot.GetId(snap, &snapIid); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not get snapshot id")); + goto cleanup; + } + + gVBoxAPI.UIID.vboxIIDToUtf8(data, &snapIid, &snapshotUuidStr); + vboxIIDUnalloc(&snapIid); + rc = gVBoxAPI.UISnapshot.GetMachine(snap, &snapMachine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get machine")); + goto cleanup; + } + def->ndisks = 0; + rc = gVBoxAPI.UArray.vboxArrayGet(&mediumAttachments, snapMachine, + gVBoxAPI.UArray.handleMachineGetMediumAttachments(snapMachine)); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("no medium attachments")); + goto cleanup; + } + /* get the number of attachments */ + for (i = 0; i < mediumAttachments.count; i++) { + IMediumAttachment *imediumattach = mediumAttachments.items[i]; + if (imediumattach) { + IMedium *medium = NULL; + + rc = gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &medium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get medium")); + goto cleanup; + } + if (medium) { + def->ndisks++; + VBOX_RELEASE(medium); + } + } + } + /* Allocate mem, if fails return error */ + if (VIR_ALLOC_N(def->disks, def->ndisks) < 0) + goto cleanup; + for (i = 0; i < def->ndisks; i++) { + if (VIR_ALLOC(def->disks[i].src) < 0) + goto cleanup; + } + + if (!vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, maxSlotPerPort)) + goto cleanup; + + /* get the attachment details here */ + for (i = 0; i < mediumAttachments.count && diskCount < def->ndisks; i++) { + IStorageController *storageController = NULL; + PRUnichar *storageControllerName = NULL; + PRUint32 deviceType = DeviceType_Null; + PRUint32 storageBus = StorageBus_Null; + IMedium *disk = NULL; + PRUnichar *childLocUtf16 = NULL; + char *childLocUtf8 = NULL; + PRUint32 deviceInst = 0; + PRInt32 devicePort = 0; + PRInt32 deviceSlot = 0; + vboxArray children = VBOX_ARRAY_INITIALIZER; + vboxArray snapshotIids = VBOX_ARRAY_INITIALIZER; + IMediumAttachment *imediumattach = mediumAttachments.items[i]; + void *handle; + size_t j = 0; + size_t k = 0; + if (!imediumattach) + continue; + rc = gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &disk); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get medium")); + goto cleanup; + } + if (!disk) + continue; + rc = gVBoxAPI.UIMediumAttachment.GetController(imediumattach, &storageControllerName); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get controller")); + goto cleanup; + } + if (!storageControllerName) { + VBOX_RELEASE(disk); + continue; + } + handle = gVBoxAPI.UArray.handleMediumGetChildren(disk); + rc = gVBoxAPI.UArray.vboxArrayGet(&children, disk, handle); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get children disk")); + goto cleanup; + } + handle = gVBoxAPI.UArray.handleMediumGetSnapshotIds(disk); + rc = gVBoxAPI.UArray.vboxArrayGetWithIIDArg(&snapshotIids, disk, + handle, &domiid); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get snapshot ids")); + goto cleanup; + } + for (j = 0; j < children.count; ++j) { + IMedium *child = children.items[j]; + for (k = 0; k < snapshotIids.count; ++k) { + PRUnichar *diskSnapId = snapshotIids.items[k]; + char *diskSnapIdStr = NULL; + VBOX_UTF16_TO_UTF8(diskSnapId, &diskSnapIdStr); + if (STREQ(diskSnapIdStr, snapshotUuidStr)) { + rc = gVBoxAPI.UIMachine.GetStorageControllerByName(machine, + storageControllerName, + &storageController); + VBOX_UTF16_FREE(storageControllerName); + if (!storageController) { + VBOX_RELEASE(child); + break; + } + rc = gVBoxAPI.UIMedium.GetLocation(child, &childLocUtf16); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get disk location")); + goto cleanup; + } + VBOX_UTF16_TO_UTF8(childLocUtf16, &childLocUtf8); + VBOX_UTF16_FREE(childLocUtf16); + if (VIR_STRDUP(def->disks[diskCount].src->path, childLocUtf8) < 0) { + VBOX_RELEASE(child); + VBOX_RELEASE(storageController); + goto cleanup; + } + VBOX_UTF8_FREE(childLocUtf8); + + rc = gVBoxAPI.UIStorageController.GetBus(storageController, &storageBus); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get storage controller bus")); + goto cleanup; + } + rc = gVBoxAPI.UIMediumAttachment.GetType(imediumattach, &deviceType); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get medium attachment type")); + goto cleanup; + } + rc = gVBoxAPI.UIMediumAttachment.GetPort(imediumattach, &devicePort); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get medium attachment type")); + goto cleanup; + } + rc = gVBoxAPI.UIMediumAttachment.GetDevice(imediumattach, &deviceSlot); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get medium attachment device")); + goto cleanup; + } + def->disks[diskCount].src->type = VIR_STORAGE_TYPE_FILE; + def->disks[diskCount].name = vboxGenerateMediumName(storageBus, + deviceInst, + devicePort, + deviceSlot, + maxPortPerInst, + maxSlotPerPort); + } + VBOX_UTF8_FREE(diskSnapIdStr); + } + } + VBOX_RELEASE(storageController); + VBOX_RELEASE(disk); + diskCount++; + } + gVBoxAPI.UArray.vboxArrayRelease(&mediumAttachments); + + ret = 0; + cleanup: + if (ret < 0) { + for (i = 0; i < def->ndisks; i++) { + VIR_FREE(def->disks[i].src); + } + VIR_FREE(def->disks); + def->ndisks = 0; + } + VBOX_RELEASE(snap); + return ret; +} + +static +int vboxSnapshotGetReadOnlyDisks(virDomainSnapshotPtr snapshot, + virDomainSnapshotDefPtr def) +{ + virDomainPtr dom = snapshot->domain; + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIIDUnion domiid; + ISnapshot *snap = NULL; + IMachine *machine = NULL; + IMachine *snapMachine = NULL; + IStorageController *storageController = NULL; + IMedium *disk = NULL; + nsresult rc; + vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER; + size_t i = 0; + PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {}; + PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {}; + int diskCount = 0; + + if (!gVBoxAPI.vboxSnapshotRedefine) + VIR_WARN("This function may not work in current version"); + + if (openSessionForMachine(data, dom->uuid, &domiid, &machine, false) < 0) + goto cleanup; + + if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) + goto cleanup; + + rc = gVBoxAPI.UISnapshot.GetMachine(snap, &snapMachine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get machine")); + goto cleanup; + } + /* + * Get READ ONLY disks + * In the snapshot metadata, these are the disks written inside the <domain> node + */ + rc = gVBoxAPI.UArray.vboxArrayGet(&mediumAttachments, snapMachine, + gVBoxAPI.UArray.handleMachineGetMediumAttachments(snapMachine)); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get medium attachments")); + goto cleanup; + } + /* get the number of attachments */ + for (i = 0; i < mediumAttachments.count; i++) { + IMediumAttachment *imediumattach = mediumAttachments.items[i]; + if (imediumattach) { + IMedium *medium = NULL; + + rc = gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &medium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get medium")); + goto cleanup; + } + if (medium) { + def->dom->ndisks++; + VBOX_RELEASE(medium); + } + } + } + + /* Allocate mem, if fails return error */ + if (VIR_ALLOC_N(def->dom->disks, def->dom->ndisks) >= 0) { + for (i = 0; i < def->dom->ndisks; i++) { + virDomainDiskDefPtr diskDef = virDomainDiskDefNew(); + if (!diskDef) + goto cleanup; + def->dom->disks[i] = diskDef; + } + } else { + goto cleanup; + } + + if (!vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, maxSlotPerPort)) + goto cleanup; + + /* get the attachment details here */ + for (i = 0; i < mediumAttachments.count && diskCount < def->dom->ndisks; i++) { + PRUnichar *storageControllerName = NULL; + PRUint32 deviceType = DeviceType_Null; + PRUint32 storageBus = StorageBus_Null; + PRBool readOnly = PR_FALSE; + PRUnichar *mediumLocUtf16 = NULL; + char *mediumLocUtf8 = NULL; + PRUint32 deviceInst = 0; + PRInt32 devicePort = 0; + PRInt32 deviceSlot = 0; + IMediumAttachment *imediumattach = mediumAttachments.items[i]; + if (!imediumattach) + continue; + rc = gVBoxAPI.UIMediumAttachment.GetMedium(imediumattach, &disk); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get medium")); + goto cleanup; + } + if (!disk) + continue; + rc = gVBoxAPI.UIMediumAttachment.GetController(imediumattach, &storageControllerName); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get storage controller name")); + goto cleanup; + } + if (!storageControllerName) + continue; + rc = gVBoxAPI.UIMachine.GetStorageControllerByName(machine, + storageControllerName, + &storageController); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get storage controller")); + goto cleanup; + } + VBOX_UTF16_FREE(storageControllerName); + if (!storageController) + continue; + rc = gVBoxAPI.UIMedium.GetLocation(disk, &mediumLocUtf16); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get disk location")); + goto cleanup; + } + VBOX_UTF16_TO_UTF8(mediumLocUtf16, &mediumLocUtf8); + VBOX_UTF16_FREE(mediumLocUtf16); + if (VIR_STRDUP(def->dom->disks[diskCount]->src->path, mediumLocUtf8) < 0) + goto cleanup; + + VBOX_UTF8_FREE(mediumLocUtf8); + + rc = gVBoxAPI.UIStorageController.GetBus(storageController, &storageBus); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get storage controller bus")); + goto cleanup; + } + if (storageBus == StorageBus_IDE) { + def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_IDE; + } else if (storageBus == StorageBus_SATA) { + def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SATA; + } else if (storageBus == StorageBus_SCSI) { + def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SCSI; + } else if (storageBus == StorageBus_Floppy) { + def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_FDC; + } + + rc = gVBoxAPI.UIMediumAttachment.GetType(imediumattach, &deviceType); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get medium attachment type")); + goto cleanup; + } + if (deviceType == DeviceType_HardDisk) + def->dom->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_DISK; + else if (deviceType == DeviceType_Floppy) + def->dom->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY; + else if (deviceType == DeviceType_DVD) + def->dom->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_CDROM; + + rc = gVBoxAPI.UIMediumAttachment.GetPort(imediumattach, &devicePort); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get medium attachment port")); + goto cleanup; + } + rc = gVBoxAPI.UIMediumAttachment.GetDevice(imediumattach, &deviceSlot); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get device")); + goto cleanup; + } + rc = gVBoxAPI.UIMedium.GetReadOnly(disk, &readOnly); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get read only attribute")); + goto cleanup; + } + if (readOnly == PR_TRUE) + def->dom->disks[diskCount]->src->readonly = true; + def->dom->disks[diskCount]->src->type = VIR_STORAGE_TYPE_FILE; + def->dom->disks[diskCount]->dst = vboxGenerateMediumName(storageBus, + deviceInst, + devicePort, + deviceSlot, + maxPortPerInst, + maxSlotPerPort); + if (!def->dom->disks[diskCount]->dst) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not generate medium name for the disk " + "at: controller instance:%u, port:%d, slot:%d"), + deviceInst, devicePort, deviceSlot); + ret = -1; + goto cleanup; + } + diskCount ++; + } + /* cleanup on error */ + + ret = 0; + cleanup: + if (ret < 0) { + for (i = 0; i < def->dom->ndisks; i++) + virDomainDiskDefFree(def->dom->disks[i]); + VIR_FREE(def->dom->disks); + def->dom->ndisks = 0; + } + VBOX_RELEASE(disk); + VBOX_RELEASE(storageController); + gVBoxAPI.UArray.vboxArrayRelease(&mediumAttachments); + VBOX_RELEASE(snap); + return ret; +} + +char *vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, + unsigned int flags) +{ + virDomainPtr dom = snapshot->domain; + VBOX_OBJECT_CHECK(dom->conn, char *, NULL); + vboxIIDUnion domiid; + IMachine *machine = NULL; + ISnapshot *snap = NULL; + ISnapshot *parent = NULL; + nsresult rc; + virDomainSnapshotDefPtr def = NULL; + PRUnichar *str16; + char *str8; + PRInt64 timestamp; + PRBool online = PR_FALSE; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + + virCheckFlags(0, NULL); + + if (openSessionForMachine(data, dom->uuid, &domiid, &machine, false) < 0) + goto cleanup; + + if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) + goto cleanup; + + if (VIR_ALLOC(def) < 0 || VIR_ALLOC(def->dom) < 0) + goto cleanup; + if (VIR_STRDUP(def->name, snapshot->name) < 0) + goto cleanup; + + if (gVBoxAPI.vboxSnapshotRedefine) { + /* Register def->dom properties for them to be saved inside the snapshot XMl + * Otherwise, there is a problem while parsing the xml + */ + PRUint32 memorySize = 0; + PRUint32 CPUCount = 0; + + def->dom->virtType = VIR_DOMAIN_VIRT_VBOX; + def->dom->id = dom->id; + memcpy(def->dom->uuid, dom->uuid, VIR_UUID_BUFLEN); + if (VIR_STRDUP(def->dom->name, dom->name) < 0) + goto cleanup; + gVBoxAPI.UIMachine.GetMemorySize(machine, &memorySize); + def->dom->mem.cur_balloon = memorySize * 1024; + /* Currently setting memory and maxMemory as same, cause + * the notation here seems to be inconsistent while + * reading and while dumping xml + */ + def->dom->mem.max_balloon = memorySize * 1024; + if (VIR_STRDUP(def->dom->os.type, "hvm") < 0) + goto cleanup; + def->dom->os.arch = virArchFromHost(); + gVBoxAPI.UIMachine.GetCPUCount(machine, &CPUCount); + def->dom->maxvcpus = def->dom->vcpus = CPUCount; + if (vboxSnapshotGetReadWriteDisks(def, snapshot) < 0) { + VIR_DEBUG("Could not get read write disks for snapshot"); + } + + if (vboxSnapshotGetReadOnlyDisks(snapshot, def) < 0) { + VIR_DEBUG("Could not get Readonly disks for snapshot"); + } + } + + rc = gVBoxAPI.UISnapshot.GetDescription(snap, &str16); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get description of snapshot %s"), + snapshot->name); + goto cleanup; + } + if (str16) { + VBOX_UTF16_TO_UTF8(str16, &str8); + VBOX_UTF16_FREE(str16); + if (VIR_STRDUP(def->description, str8) < 0) { + VBOX_UTF8_FREE(str8); + goto cleanup; + } + VBOX_UTF8_FREE(str8); + } + + rc = gVBoxAPI.UISnapshot.GetTimeStamp(snap, ×tamp); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get creation time of snapshot %s"), + snapshot->name); + goto cleanup; + } + /* timestamp is in milliseconds while creationTime in seconds */ + def->creationTime = timestamp / 1000; + + rc = gVBoxAPI.UISnapshot.GetParent(snap, &parent); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get parent of snapshot %s"), + snapshot->name); + goto cleanup; + } + if (parent) { + rc = gVBoxAPI.UISnapshot.GetName(parent, &str16); + if (NS_FAILED(rc) || !str16) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get name of parent of snapshot %s"), + snapshot->name); + goto cleanup; + } + VBOX_UTF16_TO_UTF8(str16, &str8); + VBOX_UTF16_FREE(str16); + if (VIR_STRDUP(def->parent, str8) < 0) { + VBOX_UTF8_FREE(str8); + goto cleanup; + } + VBOX_UTF8_FREE(str8); + } + + rc = gVBoxAPI.UISnapshot.GetOnline(snap, &online); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get online state of snapshot %s"), + snapshot->name); + goto cleanup; + } + if (online) + def->state = VIR_DOMAIN_RUNNING; + else + def->state = VIR_DOMAIN_SHUTOFF; + + virUUIDFormat(dom->uuid, uuidstr); + memcpy(def->dom->uuid, dom->uuid, VIR_UUID_BUFLEN); + ret = virDomainSnapshotDefFormat(uuidstr, def, flags, 0); + + cleanup: + virDomainSnapshotDefFree(def); + VBOX_RELEASE(parent); + VBOX_RELEASE(snap); + VBOX_RELEASE(machine); + vboxIIDUnalloc(&domiid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 2218baf..4b5f993 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -676,70 +676,6 @@ _vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu, #endif /* !(VBOX_API_VERSION == 2002000) */ /** - * function to generate the name for medium, - * for e.g: hda, sda, etc - * - * @returns null terminated string with device name or NULL - * for failures - * @param conn Input Connection Pointer - * @param storageBus Input storage bus type - * @param deviceInst Input device instance number - * @param devicePort Input port number - * @param deviceSlot Input slot number - * @param aMaxPortPerInst Input array of max port per device instance - * @param aMaxSlotPerPort Input array of max slot per device port - * - */ -/* This functions is used for 4.2 and later only since vboxDomainGetXMLDesc - * is rewritten. */ -#if VBOX_API_VERSION >= 4002000 -static char *vboxGenerateMediumName(PRUint32 storageBus, - PRInt32 deviceInst, - PRInt32 devicePort, - PRInt32 deviceSlot, - PRUint32 *aMaxPortPerInst, - PRUint32 *aMaxSlotPerPort) -{ - const char *prefix = NULL; - char *name = NULL; - int total = 0; - PRUint32 maxPortPerInst = 0; - PRUint32 maxSlotPerPort = 0; - - if (!aMaxPortPerInst || - !aMaxSlotPerPort) - return NULL; - - if ((storageBus < StorageBus_IDE) || - (storageBus > StorageBus_Floppy)) - return NULL; - - maxPortPerInst = aMaxPortPerInst[storageBus]; - maxSlotPerPort = aMaxSlotPerPort[storageBus]; - total = (deviceInst * maxPortPerInst * maxSlotPerPort) - + (devicePort * maxSlotPerPort) - + deviceSlot; - - if (storageBus == StorageBus_IDE) { - prefix = "hd"; - } else if ((storageBus == StorageBus_SATA) || - (storageBus == StorageBus_SCSI)) { - prefix = "sd"; - } else if (storageBus == StorageBus_Floppy) { - prefix = "fd"; - } - - name = virIndexToDiskName(total, prefix); - - VIR_DEBUG("name=%s, total=%d, storageBus=%u, deviceInst=%d, " - "devicePort=%d deviceSlot=%d, maxPortPerInst=%u maxSlotPerPort=%u", - NULLSTR(name), total, storageBus, deviceInst, devicePort, - deviceSlot, maxPortPerInst, maxSlotPerPort); - return name; -} -#endif /* VBOX_API_VERSION >= 4002000 */ - -/** * function to get the StorageBus, Port number * and Device number for the given devicename * e.g: hda has StorageBus = IDE, port = 0, @@ -802,7 +738,6 @@ static bool vboxGetDeviceDetails(const char *deviceName, return true; } -# endif /* VBOX_API_VERSION < 4000000 */ /** * function to get the values for max port per @@ -815,9 +750,8 @@ static bool vboxGetDeviceDetails(const char *deviceName, * */ -/* This function would not be used in 4.0 and 4.1 since - * vboxDomainGetXMLDesc is written*/ -# if VBOX_API_VERSION >= 4002000 || VBOX_API_VERSION < 4000000 +/* This function would not be used in 4.1 and later since + * vboxDomainSnapshotGetXMLDesc is written*/ static bool vboxGetMaxPortSlotValues(IVirtualBox *vbox, PRUint32 *maxPortPerInst, PRUint32 *maxSlotPerPort) @@ -862,7 +796,7 @@ static bool vboxGetMaxPortSlotValues(IVirtualBox *vbox, return true; } -# endif /* VBOX_API_VERSION >= 4002000 || VBOX_API_VERSION < 4000000 */ +# endif /* VBOX_API_VERSION < 4000000 */ /** * Converts Utf-16 string to int @@ -1588,583 +1522,6 @@ vboxDomainSnapshotGet(vboxGlobalData *data, return snapshot; } -#if VBOX_API_VERSION >=4002000 -static -int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def, - virDomainSnapshotPtr snapshot) -{ - virDomainPtr dom = snapshot->domain; - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxIID domiid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - ISnapshot *snap = NULL; - IMachine *snapMachine = NULL; - vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER; - PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {}; - PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {}; - int diskCount = 0; - nsresult rc; - vboxIID snapIid = VBOX_IID_INITIALIZER; - char *snapshotUuidStr = NULL; - size_t i = 0; - - vboxIIDFromUUID(&domiid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("no domain with matching UUID")); - goto cleanup; - } - if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) - goto cleanup; - - rc = snap->vtbl->GetId(snap, &snapIid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Could not get snapshot id")); - goto cleanup; - } - - VBOX_UTF16_TO_UTF8(snapIid.value, &snapshotUuidStr); - rc = snap->vtbl->GetMachine(snap, &snapMachine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get machine")); - goto cleanup; - } - def->ndisks = 0; - rc = vboxArrayGet(&mediumAttachments, snapMachine, snapMachine->vtbl->GetMediumAttachments); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("no medium attachments")); - goto cleanup; - } - /* get the number of attachments */ - for (i = 0; i < mediumAttachments.count; i++) { - IMediumAttachment *imediumattach = mediumAttachments.items[i]; - if (imediumattach) { - IMedium *medium = NULL; - - rc = imediumattach->vtbl->GetMedium(imediumattach, &medium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get medium")); - goto cleanup; - } - if (medium) { - def->ndisks++; - VBOX_RELEASE(medium); - } - } - } - /* Allocate mem, if fails return error */ - if (VIR_ALLOC_N(def->disks, def->ndisks) < 0) - goto cleanup; - for (i = 0; i < def->ndisks; i++) { - if (VIR_ALLOC(def->disks[i].src) < 0) - goto cleanup; - } - - if (!vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, maxSlotPerPort)) - goto cleanup; - - /* get the attachment details here */ - for (i = 0; i < mediumAttachments.count && diskCount < def->ndisks; i++) { - IStorageController *storageController = NULL; - PRUnichar *storageControllerName = NULL; - PRUint32 deviceType = DeviceType_Null; - PRUint32 storageBus = StorageBus_Null; - IMedium *disk = NULL; - PRUnichar *childLocUtf16 = NULL; - char *childLocUtf8 = NULL; - PRUint32 deviceInst = 0; - PRInt32 devicePort = 0; - PRInt32 deviceSlot = 0; - vboxArray children = VBOX_ARRAY_INITIALIZER; - vboxArray snapshotIids = VBOX_ARRAY_INITIALIZER; - IMediumAttachment *imediumattach = mediumAttachments.items[i]; - size_t j = 0; - size_t k = 0; - if (!imediumattach) - continue; - rc = imediumattach->vtbl->GetMedium(imediumattach, &disk); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get medium")); - goto cleanup; - } - if (!disk) - continue; - rc = imediumattach->vtbl->GetController(imediumattach, &storageControllerName); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get controller")); - goto cleanup; - } - if (!storageControllerName) { - VBOX_RELEASE(disk); - continue; - } - rc = vboxArrayGet(&children, disk, disk->vtbl->GetChildren); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get children disk")); - goto cleanup; - } - rc = vboxArrayGetWithPtrArg(&snapshotIids, disk, disk->vtbl->GetSnapshotIds, domiid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get snapshot ids")); - goto cleanup; - } - for (j = 0; j < children.count; ++j) { - IMedium *child = children.items[j]; - for (k = 0; k < snapshotIids.count; ++k) { - PRUnichar *diskSnapId = snapshotIids.items[k]; - char *diskSnapIdStr = NULL; - VBOX_UTF16_TO_UTF8(diskSnapId, &diskSnapIdStr); - if (STREQ(diskSnapIdStr, snapshotUuidStr)) { - rc = machine->vtbl->GetStorageControllerByName(machine, - storageControllerName, - &storageController); - VBOX_UTF16_FREE(storageControllerName); - if (!storageController) { - VBOX_RELEASE(child); - break; - } - rc = child->vtbl->GetLocation(child, &childLocUtf16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get disk location")); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(childLocUtf16, &childLocUtf8); - VBOX_UTF16_FREE(childLocUtf16); - if (VIR_STRDUP(def->disks[diskCount].src->path, childLocUtf8) < 0) { - VBOX_RELEASE(child); - VBOX_RELEASE(storageController); - goto cleanup; - } - VBOX_UTF8_FREE(childLocUtf8); - - rc = storageController->vtbl->GetBus(storageController, &storageBus); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get storage controller bus")); - goto cleanup; - } - rc = imediumattach->vtbl->GetType(imediumattach, &deviceType); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get medium attachment type")); - goto cleanup; - } - rc = imediumattach->vtbl->GetPort(imediumattach, &devicePort); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get medium attachment type")); - goto cleanup; - } - rc = imediumattach->vtbl->GetDevice(imediumattach, &deviceSlot); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get medium attachment device")); - goto cleanup; - } - def->disks[diskCount].src->type = VIR_STORAGE_TYPE_FILE; - def->disks[diskCount].name = vboxGenerateMediumName(storageBus, - deviceInst, - devicePort, - deviceSlot, - maxPortPerInst, - maxSlotPerPort); - } - VBOX_UTF8_FREE(diskSnapIdStr); - } - } - VBOX_RELEASE(storageController); - VBOX_RELEASE(disk); - diskCount++; - } - vboxArrayRelease(&mediumAttachments); - - ret = 0; - cleanup: - if (ret < 0) { - for (i = 0; i < def->ndisks; i++) { - VIR_FREE(def->disks[i].src); - } - VIR_FREE(def->disks); - def->ndisks = 0; - } - VBOX_RELEASE(snap); - return ret; -} - -static -int vboxSnapshotGetReadOnlyDisks(virDomainSnapshotPtr snapshot, - virDomainSnapshotDefPtr def) -{ - virDomainPtr dom = snapshot->domain; - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxIID domiid = VBOX_IID_INITIALIZER; - ISnapshot *snap = NULL; - IMachine *machine = NULL; - IMachine *snapMachine = NULL; - IStorageController *storageController = NULL; - IMedium *disk = NULL; - nsresult rc; - vboxIIDFromUUID(&domiid, dom->uuid); - vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER; - size_t i = 0; - PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {}; - PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {}; - int diskCount = 0; - - rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching UUID")); - goto cleanup; - } - - if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) - goto cleanup; - - rc = snap->vtbl->GetMachine(snap, &snapMachine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get machine")); - goto cleanup; - } - /* - * Get READ ONLY disks - * In the snapshot metadata, these are the disks written inside the <domain> node - */ - rc = vboxArrayGet(&mediumAttachments, snapMachine, snapMachine->vtbl->GetMediumAttachments); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get medium attachments")); - goto cleanup; - } - /* get the number of attachments */ - for (i = 0; i < mediumAttachments.count; i++) { - IMediumAttachment *imediumattach = mediumAttachments.items[i]; - if (imediumattach) { - IMedium *medium = NULL; - - rc = imediumattach->vtbl->GetMedium(imediumattach, &medium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get medium")); - goto cleanup; - } - if (medium) { - def->dom->ndisks++; - VBOX_RELEASE(medium); - } - } - } - - /* Allocate mem, if fails return error */ - if (VIR_ALLOC_N(def->dom->disks, def->dom->ndisks) >= 0) { - for (i = 0; i < def->dom->ndisks; i++) { - virDomainDiskDefPtr diskDef = virDomainDiskDefNew(); - if (!diskDef) - goto cleanup; - def->dom->disks[i] = diskDef; - } - } else { - goto cleanup; - } - - if (!vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, maxSlotPerPort)) - goto cleanup; - - /* get the attachment details here */ - for (i = 0; i < mediumAttachments.count && diskCount < def->dom->ndisks; i++) { - PRUnichar *storageControllerName = NULL; - PRUint32 deviceType = DeviceType_Null; - PRUint32 storageBus = StorageBus_Null; - PRBool readOnly = PR_FALSE; - PRUnichar *mediumLocUtf16 = NULL; - char *mediumLocUtf8 = NULL; - PRUint32 deviceInst = 0; - PRInt32 devicePort = 0; - PRInt32 deviceSlot = 0; - IMediumAttachment *imediumattach = mediumAttachments.items[i]; - if (!imediumattach) - continue; - rc = imediumattach->vtbl->GetMedium(imediumattach, &disk); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get medium")); - goto cleanup; - } - if (!disk) - continue; - rc = imediumattach->vtbl->GetController(imediumattach, &storageControllerName); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get storage controller name")); - goto cleanup; - } - if (!storageControllerName) - continue; - rc = machine->vtbl->GetStorageControllerByName(machine, - storageControllerName, - &storageController); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get storage controller")); - goto cleanup; - } - VBOX_UTF16_FREE(storageControllerName); - if (!storageController) - continue; - rc = disk->vtbl->GetLocation(disk, &mediumLocUtf16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get disk location")); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(mediumLocUtf16, &mediumLocUtf8); - VBOX_UTF16_FREE(mediumLocUtf16); - if (VIR_STRDUP(def->dom->disks[diskCount]->src->path, mediumLocUtf8) < 0) - goto cleanup; - - VBOX_UTF8_FREE(mediumLocUtf8); - - rc = storageController->vtbl->GetBus(storageController, &storageBus); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get storage controller bus")); - goto cleanup; - } - if (storageBus == StorageBus_IDE) { - def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_IDE; - } else if (storageBus == StorageBus_SATA) { - def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SATA; - } else if (storageBus == StorageBus_SCSI) { - def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SCSI; - } else if (storageBus == StorageBus_Floppy) { - def->dom->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_FDC; - } - - rc = imediumattach->vtbl->GetType(imediumattach, &deviceType); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get medium attachment type")); - goto cleanup; - } - if (deviceType == DeviceType_HardDisk) - def->dom->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_DISK; - else if (deviceType == DeviceType_Floppy) - def->dom->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY; - else if (deviceType == DeviceType_DVD) - def->dom->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_CDROM; - - rc = imediumattach->vtbl->GetPort(imediumattach, &devicePort); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get medium attachment port")); - goto cleanup; - } - rc = imediumattach->vtbl->GetDevice(imediumattach, &deviceSlot); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get device")); - goto cleanup; - } - rc = disk->vtbl->GetReadOnly(disk, &readOnly); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get read only attribute")); - goto cleanup; - } - if (readOnly == PR_TRUE) - def->dom->disks[diskCount]->src->readonly = true; - def->dom->disks[diskCount]->src->type = VIR_STORAGE_TYPE_FILE; - def->dom->disks[diskCount]->dst = vboxGenerateMediumName(storageBus, - deviceInst, - devicePort, - deviceSlot, - maxPortPerInst, - maxSlotPerPort); - if (!def->dom->disks[diskCount]->dst) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not generate medium name for the disk " - "at: controller instance:%u, port:%d, slot:%d"), - deviceInst, devicePort, deviceSlot); - ret = -1; - goto cleanup; - } - diskCount ++; - } - /* cleanup on error */ - - ret = 0; - cleanup: - if (ret < 0) { - for (i = 0; i < def->dom->ndisks; i++) - virDomainDiskDefFree(def->dom->disks[i]); - VIR_FREE(def->dom->disks); - def->dom->ndisks = 0; - } - VBOX_RELEASE(disk); - VBOX_RELEASE(storageController); - vboxArrayRelease(&mediumAttachments); - VBOX_RELEASE(snap); - return ret; -} -#endif - -static char * -vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, - unsigned int flags) -{ - virDomainPtr dom = snapshot->domain; - VBOX_OBJECT_CHECK(dom->conn, char *, NULL); - vboxIID domiid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - ISnapshot *snap = NULL; - ISnapshot *parent = NULL; - nsresult rc; - virDomainSnapshotDefPtr def = NULL; - PRUnichar *str16; - char *str8; - PRInt64 timestamp; - PRBool online = PR_FALSE; - char uuidstr[VIR_UUID_STRING_BUFLEN]; -#if VBOX_API_VERSION >=4002000 - PRUint32 memorySize = 0; - PRUint32 CPUCount = 0; -#endif - - virCheckFlags(0, NULL); - - vboxIIDFromUUID(&domiid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching UUID")); - goto cleanup; - } - - if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) - goto cleanup; - - if (VIR_ALLOC(def) < 0 || VIR_ALLOC(def->dom) < 0) - goto cleanup; - if (VIR_STRDUP(def->name, snapshot->name) < 0) - goto cleanup; - -#if VBOX_API_VERSION >=4002000 - /* Register def->dom properties for them to be saved inside the snapshot XMl - * Otherwise, there is a problem while parsing the xml - */ - def->dom->virtType = VIR_DOMAIN_VIRT_VBOX; - def->dom->id = dom->id; - memcpy(def->dom->uuid, dom->uuid, VIR_UUID_BUFLEN); - if (VIR_STRDUP(def->dom->name, dom->name) < 0) - goto cleanup; - machine->vtbl->GetMemorySize(machine, &memorySize); - def->dom->mem.cur_balloon = memorySize * 1024; - /* Currently setting memory and maxMemory as same, cause - * the notation here seems to be inconsistent while - * reading and while dumping xml - */ - def->dom->mem.max_balloon = memorySize * 1024; - if (VIR_STRDUP(def->dom->os.type, "hvm") < 0) - goto cleanup; - def->dom->os.arch = virArchFromHost(); - machine->vtbl->GetCPUCount(machine, &CPUCount); - def->dom->maxvcpus = def->dom->vcpus = CPUCount; - if (vboxSnapshotGetReadWriteDisks(def, snapshot) < 0) { - VIR_DEBUG("Could not get read write disks for snapshot"); - } - - if (vboxSnapshotGetReadOnlyDisks(snapshot, def) < 0) { - VIR_DEBUG("Could not get Readonly disks for snapshot"); - } -#endif /* VBOX_API_VERSION >= 4002000 */ - - rc = snap->vtbl->GetDescription(snap, &str16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get description of snapshot %s"), - snapshot->name); - goto cleanup; - } - if (str16) { - VBOX_UTF16_TO_UTF8(str16, &str8); - VBOX_UTF16_FREE(str16); - if (VIR_STRDUP(def->description, str8) < 0) { - VBOX_UTF8_FREE(str8); - goto cleanup; - } - VBOX_UTF8_FREE(str8); - } - - rc = snap->vtbl->GetTimeStamp(snap, ×tamp); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get creation time of snapshot %s"), - snapshot->name); - goto cleanup; - } - /* timestamp is in milliseconds while creationTime in seconds */ - def->creationTime = timestamp / 1000; - - rc = snap->vtbl->GetParent(snap, &parent); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get parent of snapshot %s"), - snapshot->name); - goto cleanup; - } - if (parent) { - rc = parent->vtbl->GetName(parent, &str16); - if (NS_FAILED(rc) || !str16) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get name of parent of snapshot %s"), - snapshot->name); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(str16, &str8); - VBOX_UTF16_FREE(str16); - if (VIR_STRDUP(def->parent, str8) < 0) { - VBOX_UTF8_FREE(str8); - goto cleanup; - } - VBOX_UTF8_FREE(str8); - } - - rc = snap->vtbl->GetOnline(snap, &online); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get online state of snapshot %s"), - snapshot->name); - goto cleanup; - } - if (online) - def->state = VIR_DOMAIN_RUNNING; - else - def->state = VIR_DOMAIN_SHUTOFF; - - virUUIDFormat(dom->uuid, uuidstr); - memcpy(def->dom->uuid, dom->uuid, VIR_UUID_BUFLEN); - ret = virDomainSnapshotDefFormat(uuidstr, def, flags, 0); - - cleanup: - virDomainSnapshotDefFree(def); - VBOX_RELEASE(parent); - VBOX_RELEASE(snap); - VBOX_RELEASE(machine); - vboxIIDUnalloc(&domiid); - return ret; -} - static int vboxDomainSnapshotNum(virDomainPtr dom, unsigned int flags) @@ -6708,6 +6065,12 @@ _vboxIIDToUtf8(vboxGlobalData *data ATTRIBUTE_UNUSED, #endif /* !(VBOX_API_VERSION == 2002000) */ } +static nsresult +_vboxArrayGetWithIIDArg(vboxArray *array, void *self, void *getter, vboxIIDUnion *iidu) +{ + return vboxArrayGetWithPtrArg(array, self, getter, IID_MEMBER(value)); +} + static void* _handleGetMachines(IVirtualBox *vboxObj) { return vboxObj->vtbl->GetMachines; @@ -6732,11 +6095,36 @@ static void* _handleMachineGetSharedFolders(IMachine *machine) return machine->vtbl->GetSharedFolders; } +static void* _handleSnapshotGetChildren(ISnapshot *snapshot) +{ + return snapshot->vtbl->GetChildren; +} + +static void* _handleMediumGetChildren(IMedium *medium ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION < 3001000 + vboxUnsupported(); + return 0; +#else /* VBOX_API_VERSION >= 3001000 */ + return medium->vtbl->GetChildren; +#endif /* VBOX_API_VERSION >= 3001000 */ +} + +static void* _handleMediumGetSnapshotIds(IMedium *medium) +{ + return medium->vtbl->GetSnapshotIds; +} + static nsresult _nsisupportsRelease(nsISupports *nsi) { return nsi->vtbl->Release(nsi); } +static nsresult _nsisupportsAddRef(nsISupports *nsi) +{ + return nsi->vtbl->AddRef(nsi); +} + static nsresult _virtualboxGetVersion(IVirtualBox *vboxObj, PRUnichar **versionUtf16) { @@ -6989,6 +6377,16 @@ _machineUnregister(IMachine *machine ATTRIBUTE_UNUSED, } static nsresult +_machineFindSnapshot(IMachine *machine, vboxIIDUnion *iidu, ISnapshot **snapshot) +{ +#if VBOX_API_VERSION < 4000000 + return machine->vtbl->GetSnapshot(machine, IID_MEMBER(value), snapshot); +#else /* VBOX_API_VERSION >= 4000000 */ + return machine->vtbl->FindSnapshot(machine, IID_MEMBER(value), snapshot); +#endif /* VBOX_API_VERSION >= 4000000 */ +} + +static nsresult _machineGetAccessible(IMachine *machine, PRBool *isAccessible) { return machine->vtbl->GetAccessible(machine, isAccessible); @@ -7218,6 +6616,12 @@ _machineSetExtraData(IMachine *machine, PRUnichar *key, PRUnichar *value) } static nsresult +_machineGetSnapshotCount(IMachine *machine, PRUint32 *snapshotCount) +{ + return machine->vtbl->GetSnapshotCount(machine, snapshotCount); +} + +static nsresult _machineSaveSettings(IMachine *machine) { return machine->vtbl->SaveSettings(machine); @@ -8155,6 +7559,48 @@ _sharedFolderGetWritable(ISharedFolder *sharedFolder, PRBool *writable) return sharedFolder->vtbl->GetWritable(sharedFolder, writable); } +static nsresult +_snapshotGetName(ISnapshot *snapshot, PRUnichar **name) +{ + return snapshot->vtbl->GetName(snapshot, name); +} + +static nsresult +_snapshotGetId(ISnapshot *snapshot, vboxIIDUnion *iidu) +{ + return snapshot->vtbl->GetId(snapshot, &IID_MEMBER(value)); +} + +static nsresult +_snapshotGetMachine(ISnapshot *snapshot, IMachine **machine) +{ + return snapshot->vtbl->GetMachine(snapshot, machine); +} + +static nsresult +_snapshotGetDescription(ISnapshot *snapshot, PRUnichar **description) +{ + return snapshot->vtbl->GetDescription(snapshot, description); +} + +static nsresult +_snapshotGetTimeStamp(ISnapshot *snapshot, PRInt64 *timeStamp) +{ + return snapshot->vtbl->GetTimeStamp(snapshot, timeStamp); +} + +static nsresult +_snapshotGetParent(ISnapshot *snapshot, ISnapshot **parent) +{ + return snapshot->vtbl->GetParent(snapshot, parent); +} + +static nsresult +_snapshotGetOnline(ISnapshot *snapshot, PRBool *online) +{ + return snapshot->vtbl->GetOnline(snapshot, online); +} + static bool _machineStateOnline(PRUint32 state) { return ((state >= MachineState_FirstOnline) && @@ -8212,15 +7658,20 @@ static vboxUniformedIID _UIID = { static vboxUniformedArray _UArray = { .vboxArrayGet = vboxArrayGet, + .vboxArrayGetWithIIDArg = _vboxArrayGetWithIIDArg, .vboxArrayRelease = vboxArrayRelease, .handleGetMachines = _handleGetMachines, .handleUSBGetDeviceFilters = _handleUSBGetDeviceFilters, .handleMachineGetMediumAttachments = _handleMachineGetMediumAttachments, .handleMachineGetSharedFolders = _handleMachineGetSharedFolders, + .handleSnapshotGetChildren = _handleSnapshotGetChildren, + .handleMediumGetChildren = _handleMediumGetChildren, + .handleMediumGetSnapshotIds = _handleMediumGetSnapshotIds, }; static vboxUniformednsISupports _nsUISupports = { .Release = _nsisupportsRelease, + .AddRef = _nsisupportsAddRef, }; static vboxUniformedIVirtualBox _UIVirtualBox = { @@ -8243,6 +7694,7 @@ static vboxUniformedIMachine _UIMachine = { .RemoveSharedFolder = _machineRemoveSharedFolder, .LaunchVMProcess = _machineLaunchVMProcess, .Unregister = _machineUnregister, + .FindSnapshot = _machineFindSnapshot, .GetAccessible = _machineGetAccessible, .GetState = _machineGetState, .GetName = _machineGetName, @@ -8275,6 +7727,7 @@ static vboxUniformedIMachine _UIMachine = { .SetAccelerate2DVideoEnabled = _machineSetAccelerate2DVideoEnabled, .GetExtraData = _machineGetExtraData, .SetExtraData = _machineSetExtraData, + .GetSnapshotCount = _machineGetSnapshotCount, .SaveSettings = _machineSaveSettings, }; @@ -8432,6 +7885,16 @@ static vboxUniformedISharedFolder _UISharedFolder = { .GetWritable = _sharedFolderGetWritable, }; +static vboxUniformedISnapshot _UISnapshot = { + .GetName = _snapshotGetName, + .GetId = _snapshotGetId, + .GetMachine = _snapshotGetMachine, + .GetDescription = _snapshotGetDescription, + .GetTimeStamp = _snapshotGetTimeStamp, + .GetParent = _snapshotGetParent, + .GetOnline = _snapshotGetOnline, +}; + static uniformedMachineStateChecker _machineStateChecker = { .Online = _machineStateOnline, .Inactive = _machineStateInactive, @@ -8481,6 +7944,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->UIMediumAttachment = _UIMediumAttachment; pVBoxAPI->UIStorageController = _UIStorageController; pVBoxAPI->UISharedFolder = _UISharedFolder; + pVBoxAPI->UISnapshot = _UISnapshot; pVBoxAPI->machineStateChecker = _machineStateChecker; #if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 8357df5..6b04b57 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -166,17 +166,22 @@ typedef struct { /* Functions for vboxArray */ typedef struct { nsresult (*vboxArrayGet)(vboxArray *array, void *self, void *getter); + nsresult (*vboxArrayGetWithIIDArg)(vboxArray *array, void *self, void *getter, vboxIIDUnion *iidu); void (*vboxArrayRelease)(vboxArray *array); /* Generate function pointers for vboxArrayGet */ void* (*handleGetMachines)(IVirtualBox *vboxObj); void* (*handleUSBGetDeviceFilters)(IUSBCommon *USBCommon); void* (*handleMachineGetMediumAttachments)(IMachine *machine); void* (*handleMachineGetSharedFolders)(IMachine *machine); + void* (*handleSnapshotGetChildren)(ISnapshot *snapshot); + void* (*handleMediumGetChildren)(IMedium *medium); + void* (*handleMediumGetSnapshotIds)(IMedium *medium); } vboxUniformedArray; /* Functions for nsISupports */ typedef struct { nsresult (*Release)(nsISupports *nsi); + nsresult (*AddRef)(nsISupports *nsi); } vboxUniformednsISupports; /* Functions for IVirtualBox */ @@ -211,6 +216,7 @@ typedef struct { IProgress **progress); nsresult (*Unregister)(IMachine *machine, PRUint32 cleanupMode, PRUint32 *aMediaSize, IMedium ***aMedia); + nsresult (*FindSnapshot)(IMachine *machine, vboxIIDUnion *iidu, ISnapshot **snapshot); nsresult (*GetAccessible)(IMachine *machine, PRBool *isAccessible); nsresult (*GetState)(IMachine *machine, PRUint32 *state); nsresult (*GetName)(IMachine *machine, PRUnichar **name); @@ -243,6 +249,7 @@ typedef struct { nsresult (*SetAccelerate2DVideoEnabled)(IMachine *machine, PRBool accelerate2DVideoEnabled); nsresult (*GetExtraData)(IMachine *machine, PRUnichar *key, PRUnichar **value); nsresult (*SetExtraData)(IMachine *machine, PRUnichar *key, PRUnichar *value); + nsresult (*GetSnapshotCount)(IMachine *machine, PRUint32 *snapshotCount); nsresult (*SaveSettings)(IMachine *machine); } vboxUniformedIMachine; @@ -427,6 +434,17 @@ typedef struct { nsresult (*GetWritable)(ISharedFolder *sharedFolder, PRBool *writable); } vboxUniformedISharedFolder; +/* Functions for ISnapshot */ +typedef struct { + nsresult (*GetName)(ISnapshot *snapshot, PRUnichar **name); + nsresult (*GetId)(ISnapshot *snapshot, vboxIIDUnion *iidu); + nsresult (*GetMachine)(ISnapshot *snapshot, IMachine **machine); + nsresult (*GetDescription)(ISnapshot *snapshot, PRUnichar **description); + nsresult (*GetTimeStamp)(ISnapshot *snapshot, PRInt64 *timeStamp); + nsresult (*GetParent)(ISnapshot *snapshot, ISnapshot **parent); + nsresult (*GetOnline)(ISnapshot *snapshot, PRBool *online); +} vboxUniformedISnapshot; + typedef struct { bool (*Online)(PRUint32 state); bool (*Inactive)(PRUint32 state); @@ -477,6 +495,7 @@ typedef struct { vboxUniformedIMediumAttachment UIMediumAttachment; vboxUniformedIStorageController UIStorageController; vboxUniformedISharedFolder UISharedFolder; + vboxUniformedISnapshot UISnapshot; uniformedMachineStateChecker machineStateChecker; /* vbox API features */ bool domainEventCallbacks; @@ -556,7 +575,8 @@ virDomainSnapshotPtr vboxDomainSnapshotCreateXML(virDomainPtr dom, const char *xmlDesc, unsigned int flags); - +char *vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, + unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 40 +++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 47 ----------------------------------------- src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 41 insertions(+), 47 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 36260de..074eab0 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -6081,3 +6081,43 @@ char *vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, vboxIIDUnalloc(&domiid); return ret; } + +int vboxDomainSnapshotNum(virDomainPtr dom, unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIIDUnion iid; + IMachine *machine = NULL; + nsresult rc; + PRUint32 snapshotCount; + + virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS | + VIR_DOMAIN_SNAPSHOT_LIST_METADATA, -1); + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + /* VBox snapshots do not require libvirt to maintain any metadata. */ + if (flags & VIR_DOMAIN_SNAPSHOT_LIST_METADATA) { + ret = 0; + goto cleanup; + } + + rc = gVBoxAPI.UIMachine.GetSnapshotCount(machine, &snapshotCount); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get snapshot count for domain %s"), + dom->name); + goto cleanup; + } + + /* VBox has at most one root snapshot. */ + if (snapshotCount && (flags & VIR_DOMAIN_SNAPSHOT_LIST_ROOTS)) + ret = 1; + else + ret = snapshotCount; + + cleanup: + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 4b5f993..f384741 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1523,53 +1523,6 @@ vboxDomainSnapshotGet(vboxGlobalData *data, } static int -vboxDomainSnapshotNum(virDomainPtr dom, - unsigned int flags) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - nsresult rc; - PRUint32 snapshotCount; - - virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS | - VIR_DOMAIN_SNAPSHOT_LIST_METADATA, -1); - - 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; - } - - /* VBox snapshots do not require libvirt to maintain any metadata. */ - if (flags & VIR_DOMAIN_SNAPSHOT_LIST_METADATA) { - ret = 0; - goto cleanup; - } - - rc = machine->vtbl->GetSnapshotCount(machine, &snapshotCount); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get snapshot count for domain %s"), - dom->name); - goto cleanup; - } - - /* VBox has at most one root snapshot. */ - if (snapshotCount && (flags & VIR_DOMAIN_SNAPSHOT_LIST_ROOTS)) - ret = 1; - else - ret = snapshotCount; - - cleanup: - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - -static int vboxDomainSnapshotListNames(virDomainPtr dom, char **names, int nameslen, diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 6b04b57..ba75d00 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -577,6 +577,7 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom, unsigned int flags); char *vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, unsigned int flags); +int vboxDomainSnapshotNum(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 | 79 ++++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 90 ----------------------------------------- src/vbox/vbox_uniformed_api.h | 2 + 3 files changed, 81 insertions(+), 90 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 074eab0..dc9018f 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -6121,3 +6121,82 @@ int vboxDomainSnapshotNum(virDomainPtr dom, unsigned int flags) vboxIIDUnalloc(&iid); return ret; } + +int vboxDomainSnapshotListNames(virDomainPtr dom, char **names, + int nameslen, unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIIDUnion iid; + IMachine *machine = NULL; + nsresult rc; + ISnapshot **snapshots = NULL; + int count = 0; + size_t i; + + virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS | + VIR_DOMAIN_SNAPSHOT_LIST_METADATA, -1); + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + if (flags & VIR_DOMAIN_SNAPSHOT_LIST_METADATA) { + ret = 0; + goto cleanup; + } + + if (flags & VIR_DOMAIN_SNAPSHOT_LIST_ROOTS) { + vboxIIDUnion empty; + + VBOX_IID_INITIALIZE(&empty); + if (VIR_ALLOC_N(snapshots, 1) < 0) + goto cleanup; + rc = gVBoxAPI.UIMachine.FindSnapshot(machine, &empty, snapshots); + if (NS_FAILED(rc) || !snapshots[0]) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get root snapshot for domain %s"), + dom->name); + goto cleanup; + } + count = 1; + } else { + if ((count = vboxDomainSnapshotGetAll(dom, machine, &snapshots)) < 0) + goto cleanup; + } + + for (i = 0; i < nameslen; i++) { + PRUnichar *nameUtf16; + char *name; + + if (i >= count) + break; + + rc = gVBoxAPI.UISnapshot.GetName(snapshots[i], &nameUtf16); + if (NS_FAILED(rc) || !nameUtf16) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("could not get snapshot name")); + goto cleanup; + } + VBOX_UTF16_TO_UTF8(nameUtf16, &name); + VBOX_UTF16_FREE(nameUtf16); + if (VIR_STRDUP(names[i], name) < 0) { + VBOX_UTF8_FREE(name); + goto cleanup; + } + VBOX_UTF8_FREE(name); + } + + if (count <= nameslen) + ret = count; + else + ret = nameslen; + + cleanup: + if (count > 0) { + for (i = 0; i < count; i++) + VBOX_RELEASE(snapshots[i]); + } + VIR_FREE(snapshots); + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index f384741..7b6f847 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1522,96 +1522,6 @@ vboxDomainSnapshotGet(vboxGlobalData *data, return snapshot; } -static int -vboxDomainSnapshotListNames(virDomainPtr dom, - char **names, - int nameslen, - unsigned int flags) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - nsresult rc; - ISnapshot **snapshots = NULL; - int count = 0; - size_t i; - - virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS | - VIR_DOMAIN_SNAPSHOT_LIST_METADATA, -1); - - 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; - } - - if (flags & VIR_DOMAIN_SNAPSHOT_LIST_METADATA) { - ret = 0; - goto cleanup; - } - - if (flags & VIR_DOMAIN_SNAPSHOT_LIST_ROOTS) { - vboxIID empty = VBOX_IID_INITIALIZER; - - if (VIR_ALLOC_N(snapshots, 1) < 0) - goto cleanup; -#if VBOX_API_VERSION < 4000000 - rc = machine->vtbl->GetSnapshot(machine, empty.value, snapshots); -#else /* VBOX_API_VERSION >= 4000000 */ - rc = machine->vtbl->FindSnapshot(machine, empty.value, snapshots); -#endif /* VBOX_API_VERSION >= 4000000 */ - if (NS_FAILED(rc) || !snapshots[0]) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get root snapshot for domain %s"), - dom->name); - goto cleanup; - } - count = 1; - } else { - if ((count = vboxDomainSnapshotGetAll(dom, machine, &snapshots)) < 0) - goto cleanup; - } - - for (i = 0; i < nameslen; i++) { - PRUnichar *nameUtf16; - char *name; - - if (i >= count) - break; - - rc = snapshots[i]->vtbl->GetName(snapshots[i], &nameUtf16); - if (NS_FAILED(rc) || !nameUtf16) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("could not get snapshot name")); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(nameUtf16, &name); - VBOX_UTF16_FREE(nameUtf16); - if (VIR_STRDUP(names[i], name) < 0) { - VBOX_UTF8_FREE(name); - goto cleanup; - } - VBOX_UTF8_FREE(name); - } - - if (count <= nameslen) - ret = count; - else - ret = nameslen; - - cleanup: - if (count > 0) { - for (i = 0; i < count; i++) - VBOX_RELEASE(snapshots[i]); - } - VIR_FREE(snapshots); - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - static virDomainSnapshotPtr vboxDomainSnapshotLookupByName(virDomainPtr dom, const char *name, diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index ba75d00..f0cfb18 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -578,6 +578,8 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom, char *vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, unsigned int flags); int vboxDomainSnapshotNum(virDomainPtr dom, unsigned int flags); +int vboxDomainSnapshotListNames(virDomainPtr dom, char **names, + int nameslen, unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 26 ++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 33 --------------------------------- src/vbox/vbox_uniformed_api.h | 3 +++ 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index dc9018f..5178cda 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -6200,3 +6200,29 @@ int vboxDomainSnapshotListNames(virDomainPtr dom, char **names, vboxIIDUnalloc(&iid); return ret; } + +virDomainSnapshotPtr +vboxDomainSnapshotLookupByName(virDomainPtr dom, const char *name, + unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, virDomainSnapshotPtr, NULL); + vboxIIDUnion iid; + IMachine *machine = NULL; + ISnapshot *snapshot = NULL; + + virCheckFlags(0, NULL); + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + if (!(snapshot = vboxDomainSnapshotGet(data, dom, machine, name))) + goto cleanup; + + ret = virGetDomainSnapshot(dom, name); + + cleanup: + VBOX_RELEASE(snapshot); + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 7b6f847..5aef7dd 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1522,39 +1522,6 @@ vboxDomainSnapshotGet(vboxGlobalData *data, return snapshot; } -static virDomainSnapshotPtr -vboxDomainSnapshotLookupByName(virDomainPtr dom, - const char *name, - unsigned int flags) -{ - VBOX_OBJECT_CHECK(dom->conn, virDomainSnapshotPtr, NULL); - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - ISnapshot *snapshot = NULL; - nsresult rc; - - virCheckFlags(0, NULL); - - 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; - } - - if (!(snapshot = vboxDomainSnapshotGet(data, dom, machine, name))) - goto cleanup; - - ret = virGetDomainSnapshot(dom, name); - - cleanup: - VBOX_RELEASE(snapshot); - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - static int vboxDomainHasCurrentSnapshot(virDomainPtr dom, unsigned int flags) diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index f0cfb18..afbc351 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -580,6 +580,9 @@ char *vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, int vboxDomainSnapshotNum(virDomainPtr dom, unsigned int flags); int vboxDomainSnapshotListNames(virDomainPtr dom, char **names, int nameslen, unsigned int flags); +virDomainSnapshotPtr +vboxDomainSnapshotLookupByName(virDomainPtr dom, const char *name, + unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 32 ++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 38 -------------------------------------- src/vbox/vbox_uniformed_api.h | 1 + 3 files changed, 33 insertions(+), 38 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 5178cda..cb6ba78 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -6226,3 +6226,35 @@ vboxDomainSnapshotLookupByName(virDomainPtr dom, const char *name, vboxIIDUnalloc(&iid); return ret; } + +int vboxDomainHasCurrentSnapshot(virDomainPtr dom, + unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIIDUnion iid; + IMachine *machine = NULL; + ISnapshot *snapshot = NULL; + nsresult rc; + + virCheckFlags(0, -1); + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + rc = gVBoxAPI.UIMachine.GetCurrentSnapshot(machine, &snapshot); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get current snapshot")); + goto cleanup; + } + + if (snapshot) + ret = 1; + else + 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 5aef7dd..73b3fc3 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1522,44 +1522,6 @@ vboxDomainSnapshotGet(vboxGlobalData *data, return snapshot; } -static int -vboxDomainHasCurrentSnapshot(virDomainPtr dom, - unsigned int flags) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - ISnapshot *snapshot = NULL; - 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, "%s", - _("no domain with matching UUID")); - goto cleanup; - } - - rc = machine->vtbl->GetCurrentSnapshot(machine, &snapshot); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get current snapshot")); - goto cleanup; - } - - if (snapshot) - ret = 1; - else - ret = 0; - - cleanup: - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - static virDomainSnapshotPtr vboxDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, unsigned int flags) diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index afbc351..d91e970 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -583,6 +583,7 @@ int vboxDomainSnapshotListNames(virDomainPtr dom, char **names, virDomainSnapshotPtr vboxDomainSnapshotLookupByName(virDomainPtr dom, const char *name, unsigned int flags); +int vboxDomainHasCurrentSnapshot(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 | 61 +++++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 66 ----------------------------------------- src/vbox/vbox_uniformed_api.h | 3 ++ 3 files changed, 64 insertions(+), 66 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index cb6ba78..04e6c2c 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -6258,3 +6258,64 @@ int vboxDomainHasCurrentSnapshot(virDomainPtr dom, vboxIIDUnalloc(&iid); return ret; } + +virDomainSnapshotPtr +vboxDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, + unsigned int flags) +{ + virDomainPtr dom = snapshot->domain; + VBOX_OBJECT_CHECK(dom->conn, virDomainSnapshotPtr, NULL); + vboxIIDUnion iid; + IMachine *machine = NULL; + ISnapshot *snap = NULL; + ISnapshot *parent = NULL; + PRUnichar *nameUtf16 = NULL; + char *name = NULL; + nsresult rc; + + virCheckFlags(0, NULL); + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) + goto cleanup; + + rc = gVBoxAPI.UISnapshot.GetParent(snap, &parent); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get parent of snapshot %s"), + snapshot->name); + goto cleanup; + } + if (!parent) { + virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, + _("snapshot '%s' does not have a parent"), + snapshot->name); + goto cleanup; + } + + rc = gVBoxAPI.UISnapshot.GetName(parent, &nameUtf16); + if (NS_FAILED(rc) || !nameUtf16) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get name of parent of snapshot %s"), + snapshot->name); + goto cleanup; + } + VBOX_UTF16_TO_UTF8(nameUtf16, &name); + if (!name) { + virReportOOMError(); + goto cleanup; + } + + ret = virGetDomainSnapshot(dom, name); + + cleanup: + VBOX_UTF8_FREE(name); + VBOX_UTF16_FREE(nameUtf16); + VBOX_RELEASE(snap); + VBOX_RELEASE(parent); + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 73b3fc3..d5df286 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1523,72 +1523,6 @@ vboxDomainSnapshotGet(vboxGlobalData *data, } static virDomainSnapshotPtr -vboxDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, - unsigned int flags) -{ - virDomainPtr dom = snapshot->domain; - VBOX_OBJECT_CHECK(dom->conn, virDomainSnapshotPtr, NULL); - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - ISnapshot *snap = NULL; - ISnapshot *parent = NULL; - PRUnichar *nameUtf16 = NULL; - char *name = NULL; - nsresult rc; - - virCheckFlags(0, NULL); - - 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; - } - - if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) - goto cleanup; - - rc = snap->vtbl->GetParent(snap, &parent); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get parent of snapshot %s"), - snapshot->name); - goto cleanup; - } - if (!parent) { - virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, - _("snapshot '%s' does not have a parent"), - snapshot->name); - goto cleanup; - } - - rc = parent->vtbl->GetName(parent, &nameUtf16); - if (NS_FAILED(rc) || !nameUtf16) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get name of parent of snapshot %s"), - snapshot->name); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(nameUtf16, &name); - if (!name) { - virReportOOMError(); - goto cleanup; - } - - ret = virGetDomainSnapshot(dom, name); - - cleanup: - VBOX_UTF8_FREE(name); - VBOX_UTF16_FREE(nameUtf16); - VBOX_RELEASE(snap); - VBOX_RELEASE(parent); - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - -static virDomainSnapshotPtr vboxDomainSnapshotCurrent(virDomainPtr dom, unsigned int flags) { diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index d91e970..978da5e 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -584,6 +584,9 @@ virDomainSnapshotPtr vboxDomainSnapshotLookupByName(virDomainPtr dom, const char *name, unsigned int flags); int vboxDomainHasCurrentSnapshot(virDomainPtr dom, unsigned int flags); +virDomainSnapshotPtr +vboxDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, + unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 53 ++++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 59 ----------------------------------------- src/vbox/vbox_uniformed_api.h | 2 ++ 3 files changed, 55 insertions(+), 59 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 04e6c2c..32cbe60 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -6319,3 +6319,56 @@ vboxDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, vboxIIDUnalloc(&iid); return ret; } + +virDomainSnapshotPtr +vboxDomainSnapshotCurrent(virDomainPtr dom, unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, virDomainSnapshotPtr, NULL); + vboxIIDUnion iid; + IMachine *machine = NULL; + ISnapshot *snapshot = NULL; + PRUnichar *nameUtf16 = NULL; + char *name = NULL; + nsresult rc; + + virCheckFlags(0, NULL); + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + rc = gVBoxAPI.UIMachine.GetCurrentSnapshot(machine, &snapshot); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get current snapshot")); + goto cleanup; + } + + if (!snapshot) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("domain has no snapshots")); + goto cleanup; + } + + rc = gVBoxAPI.UISnapshot.GetName(snapshot, &nameUtf16); + if (NS_FAILED(rc) || !nameUtf16) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get current snapshot name")); + goto cleanup; + } + + VBOX_UTF16_TO_UTF8(nameUtf16, &name); + if (!name) { + virReportOOMError(); + goto cleanup; + } + + ret = virGetDomainSnapshot(dom, name); + + cleanup: + VBOX_UTF8_FREE(name); + VBOX_UTF16_FREE(nameUtf16); + VBOX_RELEASE(snapshot); + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index d5df286..87200f1 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1522,65 +1522,6 @@ vboxDomainSnapshotGet(vboxGlobalData *data, return snapshot; } -static virDomainSnapshotPtr -vboxDomainSnapshotCurrent(virDomainPtr dom, - unsigned int flags) -{ - VBOX_OBJECT_CHECK(dom->conn, virDomainSnapshotPtr, NULL); - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - ISnapshot *snapshot = NULL; - PRUnichar *nameUtf16 = NULL; - char *name = NULL; - nsresult rc; - - virCheckFlags(0, NULL); - - 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; - } - - rc = machine->vtbl->GetCurrentSnapshot(machine, &snapshot); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get current snapshot")); - goto cleanup; - } - - if (!snapshot) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("domain has no snapshots")); - goto cleanup; - } - - rc = snapshot->vtbl->GetName(snapshot, &nameUtf16); - if (NS_FAILED(rc) || !nameUtf16) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get current snapshot name")); - goto cleanup; - } - - VBOX_UTF16_TO_UTF8(nameUtf16, &name); - if (!name) { - virReportOOMError(); - goto cleanup; - } - - ret = virGetDomainSnapshot(dom, name); - - cleanup: - VBOX_UTF8_FREE(name); - VBOX_UTF16_FREE(nameUtf16); - VBOX_RELEASE(snapshot); - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - static int vboxDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, unsigned int flags) diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 978da5e..c320ac2 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -587,6 +587,8 @@ int vboxDomainHasCurrentSnapshot(virDomainPtr dom, unsigned int flags); virDomainSnapshotPtr vboxDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, unsigned int flags); +virDomainSnapshotPtr +vboxDomainSnapshotCurrent(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 | 57 +++++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 63 ----------------------------------------- src/vbox/vbox_uniformed_api.h | 2 ++ 3 files changed, 59 insertions(+), 63 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 32cbe60..f38305a 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -6372,3 +6372,60 @@ vboxDomainSnapshotCurrent(virDomainPtr dom, unsigned int flags) vboxIIDUnalloc(&iid); return ret; } + +int vboxDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, + unsigned int flags) +{ + virDomainPtr dom = snapshot->domain; + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIIDUnion iid; + IMachine *machine = NULL; + ISnapshot *snap = NULL; + ISnapshot *current = NULL; + PRUnichar *nameUtf16 = NULL; + char *name = NULL; + nsresult rc; + + virCheckFlags(0, -1); + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) + goto cleanup; + + rc = gVBoxAPI.UIMachine.GetCurrentSnapshot(machine, ¤t); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get current snapshot")); + goto cleanup; + } + if (!current) { + ret = 0; + goto cleanup; + } + + rc = gVBoxAPI.UISnapshot.GetName(current, &nameUtf16); + if (NS_FAILED(rc) || !nameUtf16) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get current snapshot name")); + goto cleanup; + } + + VBOX_UTF16_TO_UTF8(nameUtf16, &name); + if (!name) { + virReportOOMError(); + goto cleanup; + } + + ret = STREQ(snapshot->name, name); + + cleanup: + VBOX_UTF8_FREE(name); + VBOX_UTF16_FREE(nameUtf16); + VBOX_RELEASE(snap); + VBOX_RELEASE(current); + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 87200f1..fb3ed61 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1523,69 +1523,6 @@ vboxDomainSnapshotGet(vboxGlobalData *data, } static int -vboxDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, - unsigned int flags) -{ - virDomainPtr dom = snapshot->domain; - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - ISnapshot *snap = NULL; - ISnapshot *current = NULL; - PRUnichar *nameUtf16 = NULL; - char *name = NULL; - 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, "%s", - _("no domain with matching UUID")); - goto cleanup; - } - - if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) - goto cleanup; - - rc = machine->vtbl->GetCurrentSnapshot(machine, ¤t); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get current snapshot")); - goto cleanup; - } - if (!current) { - ret = 0; - goto cleanup; - } - - rc = current->vtbl->GetName(current, &nameUtf16); - if (NS_FAILED(rc) || !nameUtf16) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get current snapshot name")); - goto cleanup; - } - - VBOX_UTF16_TO_UTF8(nameUtf16, &name); - if (!name) { - virReportOOMError(); - goto cleanup; - } - - ret = STREQ(snapshot->name, name); - - cleanup: - VBOX_UTF8_FREE(name); - VBOX_UTF16_FREE(nameUtf16); - VBOX_RELEASE(snap); - VBOX_RELEASE(current); - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - -static int vboxDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot, unsigned int flags) { diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index c320ac2..c761bda 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -589,6 +589,8 @@ vboxDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, unsigned int flags); virDomainSnapshotPtr vboxDomainSnapshotCurrent(virDomainPtr dom, unsigned int flags); +int vboxDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, + unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 27 +++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 34 ---------------------------------- src/vbox/vbox_uniformed_api.h | 2 ++ 3 files changed, 29 insertions(+), 34 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index f38305a..dcd8ab8 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -6429,3 +6429,30 @@ int vboxDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, vboxIIDUnalloc(&iid); return ret; } + +int vboxDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot, + unsigned int flags) +{ + virDomainPtr dom = snapshot->domain; + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIIDUnion iid; + IMachine *machine = NULL; + ISnapshot *snap = NULL; + + virCheckFlags(0, -1); + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + goto cleanup; + + /* Check that snapshot exists. If so, there is no metadata. */ + if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) + goto cleanup; + + ret = 0; + + cleanup: + VBOX_RELEASE(snap); + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index fb3ed61..6d80a26 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1522,40 +1522,6 @@ vboxDomainSnapshotGet(vboxGlobalData *data, return snapshot; } -static int -vboxDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot, - unsigned int flags) -{ - virDomainPtr dom = snapshot->domain; - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - ISnapshot *snap = NULL; - 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, "%s", - _("no domain with matching UUID")); - goto cleanup; - } - - /* Check that snapshot exists. If so, there is no metadata. */ - if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) - goto cleanup; - - ret = 0; - - cleanup: - VBOX_RELEASE(snap); - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - #if VBOX_API_VERSION < 3001000 static int vboxDomainSnapshotRestore(virDomainPtr dom, diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index c761bda..ac8a6b7 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -591,6 +591,8 @@ virDomainSnapshotPtr vboxDomainSnapshotCurrent(virDomainPtr dom, unsigned int flags); int vboxDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, unsigned int flags); +int vboxDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot, + unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 68 +++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 80 ++--------------------------------------- src/vbox/vbox_uniformed_api.h | 3 ++ 3 files changed, 74 insertions(+), 77 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index dcd8ab8..f5b07cf 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -6456,3 +6456,71 @@ int vboxDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot, vboxIIDUnalloc(&iid); return ret; } + +int vboxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, + unsigned int flags) +{ + virDomainPtr dom = snapshot->domain; + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIIDUnion domiid; + IMachine *machine = NULL; + ISnapshot *newSnapshot = NULL; + ISnapshot *prevSnapshot = NULL; + PRBool online = PR_FALSE; + PRUint32 state; + nsresult rc; + + virCheckFlags(0, -1); + + if (openSessionForMachine(data, dom->uuid, &domiid, &machine, false) < 0) + goto cleanup; + + newSnapshot = vboxDomainSnapshotGet(data, dom, machine, snapshot->name); + if (!newSnapshot) + goto cleanup; + + rc = gVBoxAPI.UISnapshot.GetOnline(newSnapshot, &online); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get online state of snapshot %s"), + snapshot->name); + goto cleanup; + } + + rc = gVBoxAPI.UIMachine.GetCurrentSnapshot(machine, &prevSnapshot); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not get current snapshot of domain %s"), + dom->name); + goto cleanup; + } + + rc = gVBoxAPI.UIMachine.GetState(machine, &state); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get domain state")); + goto cleanup; + } + + if (gVBoxAPI.machineStateChecker.Online(state)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot revert snapshot of running domain")); + goto cleanup; + } + + if (gVBoxAPI.snapshotRestore(dom, machine, newSnapshot)) + goto cleanup; + + if (online) { + ret = vboxDomainCreate(dom); + if (!ret) + gVBoxAPI.snapshotRestore(dom, machine, prevSnapshot); + } else + ret = 0; + + cleanup: + VBOX_RELEASE(prevSnapshot); + VBOX_RELEASE(newSnapshot); + vboxIIDUnalloc(&domiid); + return ret; +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 6d80a26..adba028 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1524,7 +1524,7 @@ vboxDomainSnapshotGet(vboxGlobalData *data, #if VBOX_API_VERSION < 3001000 static int -vboxDomainSnapshotRestore(virDomainPtr dom, +_vboxDomainSnapshotRestore(virDomainPtr dom, IMachine *machine, ISnapshot *snapshot) { @@ -1554,7 +1554,7 @@ vboxDomainSnapshotRestore(virDomainPtr dom, } #else static int -vboxDomainSnapshotRestore(virDomainPtr dom, +_vboxDomainSnapshotRestore(virDomainPtr dom, IMachine *machine, ISnapshot *snapshot) { @@ -1630,81 +1630,6 @@ vboxDomainSnapshotRestore(virDomainPtr dom, #endif static int -vboxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, - unsigned int flags) -{ - virDomainPtr dom = snapshot->domain; - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxIID domiid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - ISnapshot *newSnapshot = NULL; - ISnapshot *prevSnapshot = NULL; - PRBool online = PR_FALSE; - PRUint32 state; - nsresult rc; - - virCheckFlags(0, -1); - - vboxIIDFromUUID(&domiid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching UUID")); - goto cleanup; - } - - newSnapshot = vboxDomainSnapshotGet(data, dom, machine, snapshot->name); - if (!newSnapshot) - goto cleanup; - - rc = newSnapshot->vtbl->GetOnline(newSnapshot, &online); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get online state of snapshot %s"), - snapshot->name); - goto cleanup; - } - - rc = machine->vtbl->GetCurrentSnapshot(machine, &prevSnapshot); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get current snapshot of domain %s"), - dom->name); - goto cleanup; - } - - rc = machine->vtbl->GetState(machine, &state); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get domain state")); - goto cleanup; - } - - if (state >= MachineState_FirstOnline - && state <= MachineState_LastOnline) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("cannot revert snapshot of running domain")); - goto cleanup; - } - - if (vboxDomainSnapshotRestore(dom, machine, newSnapshot)) - goto cleanup; - - if (online) { - ret = vboxDomainCreate(dom); - if (!ret) - vboxDomainSnapshotRestore(dom, machine, prevSnapshot); - } else - ret = 0; - - cleanup: - VBOX_RELEASE(prevSnapshot); - VBOX_RELEASE(newSnapshot); - vboxIIDUnalloc(&domiid); - return ret; -} - -static int vboxDomainSnapshotDeleteSingle(vboxGlobalData *data, IConsole *console, ISnapshot *snapshot) @@ -7492,6 +7417,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->dumpFloppy = _dumpFloppy; pVBoxAPI->attachFloppy = _attachFloppy; pVBoxAPI->detachFloppy = _detachFloppy; + pVBoxAPI->snapshotRestore = _vboxDomainSnapshotRestore; pVBoxAPI->UPFN = _UPFN; pVBoxAPI->UIID = _UIID; pVBoxAPI->UArray = _UArray; diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index ac8a6b7..005b21b 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -473,6 +473,7 @@ typedef struct { void (*dumpFloppy)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine); int (*attachFloppy)(vboxGlobalData *data, IMachine *machine, const char *src); int (*detachFloppy)(IMachine *machine); + int (*snapshotRestore)(virDomainPtr dom, IMachine *machine, ISnapshot *snapshot); vboxUniformedPFN UPFN; vboxUniformedIID UIID; vboxUniformedArray UArray; @@ -593,6 +594,8 @@ int vboxDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, unsigned int flags); int vboxDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot, unsigned int flags); +int vboxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, + unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 609 ++++++++++++++++++++++++++++++++ src/vbox/vbox_common.h | 13 + src/vbox/vbox_tmpl.c | 778 +---------------------------------------- src/vbox/vbox_uniformed_api.h | 4 + 4 files changed, 637 insertions(+), 767 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index f5b07cf..505f1cd 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -6524,3 +6524,612 @@ int vboxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, vboxIIDUnalloc(&domiid); return ret; } + +static int +vboxDomainSnapshotDeleteSingle(vboxGlobalData *data, + IConsole *console, + ISnapshot *snapshot) +{ + IProgress *progress = NULL; + vboxIIDUnion iid; + int ret = -1; + nsresult rc; + resultCodeUnion result; + + VBOX_IID_INITIALIZE(&iid); + rc = gVBoxAPI.UISnapshot.GetId(snapshot, &iid); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get snapshot UUID")); + goto cleanup; + } + + rc = gVBoxAPI.UIConsole.DeleteSnapshot(console, &iid, &progress); + if (NS_FAILED(rc) || !progress) { + if (rc == VBOX_E_INVALID_VM_STATE) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot delete domain snapshot for running domain")); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not delete snapshot")); + } + goto cleanup; + } + + gVBoxAPI.UIProgress.WaitForCompletion(progress, -1); + gVBoxAPI.UIProgress.GetResultCode(progress, &result); + if (RC_FAILED(result)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not delete snapshot")); + goto cleanup; + } + + ret = 0; + + cleanup: + VBOX_RELEASE(progress); + vboxIIDUnalloc(&iid); + return ret; +} + +static int +vboxDomainSnapshotDeleteTree(vboxGlobalData *data, + IConsole *console, + ISnapshot *snapshot) +{ + vboxArray children = VBOX_ARRAY_INITIALIZER; + int ret = -1; + nsresult rc; + size_t i; + + rc = gVBoxAPI.UArray.vboxArrayGet(&children, snapshot, + gVBoxAPI.UArray.handleSnapshotGetChildren(snapshot)); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get children snapshots")); + goto cleanup; + } + + for (i = 0; i < children.count; i++) { + if (vboxDomainSnapshotDeleteTree(data, console, children.items[i])) + goto cleanup; + } + + ret = vboxDomainSnapshotDeleteSingle(data, console, snapshot); + + cleanup: + gVBoxAPI.UArray.vboxArrayRelease(&children); + return ret; +} + +static int +vboxDomainSnapshotDeleteMetadataOnly(virDomainSnapshotPtr snapshot) +{ + /* + * This function will remove the node in the vbox xml corresponding to the snapshot. + * It is usually called by vboxDomainSnapshotDelete() with the flag + * VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY. + * If you want to use it anywhere else, be careful, if the snapshot you want to delete + * has children, the result is not granted, they will probably will be deleted in the + * xml, but you may have a problem with hard drives. + * + * If the snapshot which is being deleted is the current one, we will set the current + * snapshot of the machine to the parent of this snapshot. Before writing the modified + * xml file, we undefine the machine from vbox. After writing the file, we redefine + * the machine with the new file. + */ + + virDomainPtr dom = snapshot->domain; + VBOX_OBJECT_CHECK(dom->conn, int, -1); + virDomainSnapshotDefPtr def= NULL; + char *defXml = NULL; + vboxIIDUnion domiid; + nsresult rc; + IMachine *machine = NULL; + PRUnichar *settingsFilePathUtf16 = NULL; + char *settingsFilepath = NULL; + virVBoxSnapshotConfMachinePtr snapshotMachineDesc = NULL; + int isCurrent = -1; + int it = 0; + PRUnichar *machineNameUtf16 = NULL; + char *machineName = NULL; + char *nameTmpUse = NULL; + char *machineLocationPath = NULL; + PRUint32 aMediaSize = 0; + IMedium **aMedia = NULL; + + VBOX_IID_INITIALIZE(&domiid); + if (!gVBoxAPI.vboxSnapshotRedefine) + VIR_WARN("This function may not work in current version"); + + defXml = vboxDomainSnapshotGetXMLDesc(snapshot, 0); + if (!defXml) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get XML Desc of snapshot")); + goto cleanup; + } + def = virDomainSnapshotDefParseString(defXml, + data->caps, + data->xmlopt, + -1, + VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | + VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE); + if (!def) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get a virDomainSnapshotDefPtr")); + goto cleanup; + } + + if (openSessionForMachine(data, dom->uuid, &domiid, &machine, false) < 0) + goto cleanup; + rc = gVBoxAPI.UIMachine.GetSettingsFilePath(machine, &settingsFilePathUtf16); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get settings file path")); + goto cleanup; + } + VBOX_UTF16_TO_UTF8(settingsFilePathUtf16, &settingsFilepath); + + /*Getting the machine name to retrieve the machine location path.*/ + rc = gVBoxAPI.UIMachine.GetName(machine, &machineNameUtf16); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot get machine name")); + goto cleanup; + } + VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineName); + if (virAsprintf(&nameTmpUse, "%s.vbox", machineName) < 0) + goto cleanup; + machineLocationPath = virStringReplace(settingsFilepath, nameTmpUse, ""); + if (machineLocationPath == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get the machine location path")); + goto cleanup; + } + snapshotMachineDesc = virVBoxSnapshotConfLoadVboxFile(settingsFilepath, machineLocationPath); + if (!snapshotMachineDesc) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot create a vboxSnapshotXmlPtr")); + goto cleanup; + } + + isCurrent = virVBoxSnapshotConfIsCurrentSnapshot(snapshotMachineDesc, def->name); + if (isCurrent < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to know if the snapshot is the current snapshot")); + goto cleanup; + } + if (isCurrent) { + /* + * If the snapshot is the current snapshot, it means that the machine has read-write + * disks. The first thing to do is to manipulate VirtualBox API to create + * differential read-write disks if the parent snapshot is not null. + */ + if (def->parent != NULL) { + for (it = 0; it < def->dom->ndisks; it++) { + virVBoxSnapshotConfHardDiskPtr readOnly = NULL; + IMedium *medium = NULL; + PRUnichar *locationUtf16 = NULL; + char *parentUuid = NULL; + IMedium *newMedium = NULL; + PRUnichar *formatUtf16 = NULL; + PRUnichar *newLocation = NULL; + char *newLocationUtf8 = NULL; + IProgress *progress = NULL; + virVBoxSnapshotConfHardDiskPtr disk = NULL; + char *uuid = NULL; + char *format = NULL; + char **searchResultTab = NULL; + ssize_t resultSize = 0; + char *tmp = NULL; + vboxIIDUnion iid, parentiid; + resultCodeUnion resultCode; + + VBOX_IID_INITIALIZE(&iid); + VBOX_IID_INITIALIZE(&parentiid); + readOnly = virVBoxSnapshotConfHardDiskPtrByLocation(snapshotMachineDesc, + def->dom->disks[it]->src->path); + if (!readOnly) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot get hard disk by location")); + goto cleanup; + } + if (readOnly->parent == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("The read only disk has no parent")); + goto cleanup; + } + + VBOX_UTF8_TO_UTF16(readOnly->parent->location, &locationUtf16); + rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj, + locationUtf16, + DeviceType_HardDisk, + AccessMode_ReadWrite, + &medium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to open HardDisk, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + + rc = gVBoxAPI.UIMedium.GetId(medium, &parentiid); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to get hardDisk Id, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + gVBoxAPI.UIID.vboxIIDToUtf8(data, &parentiid, &parentUuid); + vboxIIDUnalloc(&parentiid); + VBOX_UTF16_FREE(locationUtf16); + VBOX_UTF8_TO_UTF16("VDI", &formatUtf16); + + if (virAsprintf(&newLocationUtf8, "%sfakedisk-%s-%d.vdi", + machineLocationPath, def->parent, it) < 0) + goto cleanup; + VBOX_UTF8_TO_UTF16(newLocationUtf8, &newLocation); + rc = gVBoxAPI.UIVirtualBox.CreateHardDiskMedium(data->vboxObj, + formatUtf16, + newLocation, + &newMedium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to create HardDisk, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + VBOX_UTF16_FREE(formatUtf16); + VBOX_UTF16_FREE(newLocation); + + PRUint32 tab[1]; + tab[0] = MediumVariant_Diff; + gVBoxAPI.UIMedium.CreateDiffStorage(medium, newMedium, 1, tab, &progress); + + gVBoxAPI.UIProgress.WaitForCompletion(progress, -1); + gVBoxAPI.UIProgress.GetResultCode(progress, &resultCode); + if (RC_FAILED(resultCode)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Error while creating diff storage, rc=%08x"), + resultCode.uResultCode); + goto cleanup; + } + VBOX_RELEASE(progress); + /* + * The differential disk is created, we add it to the media registry and + * the machine storage controller. + */ + + if (VIR_ALLOC(disk) < 0) + goto cleanup; + + rc = gVBoxAPI.UIMedium.GetId(newMedium, &iid); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to get medium uuid, rc=%08x"), + (unsigned)rc); + VIR_FREE(disk); + goto cleanup; + } + gVBoxAPI.UIID.vboxIIDToUtf8(data, &iid, &uuid); + disk->uuid = uuid; + vboxIIDUnalloc(&iid); + + if (VIR_STRDUP(disk->location, newLocationUtf8) < 0) { + VIR_FREE(disk); + goto cleanup; + } + + rc = gVBoxAPI.UIMedium.GetFormat(newMedium, &formatUtf16); + VBOX_UTF16_TO_UTF8(formatUtf16, &format); + disk->format = format; + VBOX_UTF16_FREE(formatUtf16); + + if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(disk, + snapshotMachineDesc->mediaRegistry, + parentUuid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to add hard disk to the media registry")); + goto cleanup; + } + /*Adding fake disks to the machine storage controllers*/ + + resultSize = virStringSearch(snapshotMachineDesc->storageController, + VBOX_UUID_REGEX, + it + 1, + &searchResultTab); + if (resultSize != it + 1) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to find UUID %s"), searchResultTab[it]); + goto cleanup; + } + + tmp = virStringReplace(snapshotMachineDesc->storageController, + searchResultTab[it], + disk->uuid); + virStringFreeList(searchResultTab); + VIR_FREE(snapshotMachineDesc->storageController); + if (!tmp) + goto cleanup; + if (VIR_STRDUP(snapshotMachineDesc->storageController, tmp) < 0) + goto cleanup; + + VIR_FREE(tmp); + /*Closing the "fake" disk*/ + rc = gVBoxAPI.UIMedium.Close(newMedium); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to close the new medium, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + } + } else { + for (it = 0; it < def->dom->ndisks; it++) { + const char *uuidRO = NULL; + char **searchResultTab = NULL; + ssize_t resultSize = 0; + char *tmp = NULL; + uuidRO = virVBoxSnapshotConfHardDiskUuidByLocation(snapshotMachineDesc, + def->dom->disks[it]->src->path); + if (!uuidRO) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("No such disk in media registry %s"), + def->dom->disks[it]->src->path); + goto cleanup; + } + + resultSize = virStringSearch(snapshotMachineDesc->storageController, + VBOX_UUID_REGEX, + it + 1, + &searchResultTab); + if (resultSize != it + 1) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to find UUID %s"), + searchResultTab[it]); + goto cleanup; + } + + tmp = virStringReplace(snapshotMachineDesc->storageController, + searchResultTab[it], + uuidRO); + virStringFreeList(searchResultTab); + VIR_FREE(snapshotMachineDesc->storageController); + if (!tmp) + goto cleanup; + if (VIR_STRDUP(snapshotMachineDesc->storageController, tmp) < 0) + goto cleanup; + + VIR_FREE(tmp); + } + } + } + /*We remove the read write disks from the media registry*/ + for (it = 0; it < def->ndisks; it++) { + const char *uuidRW = + virVBoxSnapshotConfHardDiskUuidByLocation(snapshotMachineDesc, + def->disks[it].src->path); + if (!uuidRW) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to find UUID for location %s"), def->disks[it].src->path); + goto cleanup; + } + if (virVBoxSnapshotConfRemoveHardDisk(snapshotMachineDesc->mediaRegistry, uuidRW) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to remove disk from media registry. uuid = %s"), uuidRW); + goto cleanup; + } + } + /*If the parent snapshot is not NULL, we remove the-read only disks from the media registry*/ + if (def->parent != NULL) { + for (it = 0; it < def->dom->ndisks; it++) { + const char *uuidRO = + virVBoxSnapshotConfHardDiskUuidByLocation(snapshotMachineDesc, + def->dom->disks[it]->src->path); + if (!uuidRO) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to find UUID for location %s"), def->dom->disks[it]->src->path); + goto cleanup; + } + if (virVBoxSnapshotConfRemoveHardDisk(snapshotMachineDesc->mediaRegistry, uuidRO) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to remove disk from media registry. uuid = %s"), uuidRO); + goto cleanup; + } + } + } + rc = gVBoxAPI.UIMachine.Unregister(machine, + CleanupMode_DetachAllReturnHardDisksOnly, + &aMediaSize, + &aMedia); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to unregister machine, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + VBOX_RELEASE(machine); + for (it = 0; it < aMediaSize; it++) { + IMedium *medium = aMedia[it]; + PRUnichar *locationUtf16 = NULL; + char *locationUtf8 = NULL; + + if (!medium) + continue; + + rc = gVBoxAPI.UIMedium.GetLocation(medium, &locationUtf16); + VBOX_UTF16_TO_UTF8(locationUtf16, &locationUtf8); + if (isCurrent && strstr(locationUtf8, "fake") != NULL) { + /*we delete the fake disk because we don't need it anymore*/ + IProgress *progress = NULL; + resultCodeUnion resultCode; + rc = gVBoxAPI.UIMedium.DeleteStorage(medium, &progress); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to delete medium, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + gVBoxAPI.UIProgress.WaitForCompletion(progress, -1); + gVBoxAPI.UIProgress.GetResultCode(progress, &resultCode); + if (RC_FAILED(resultCode)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Error while closing medium, rc=%08x"), + resultCode.uResultCode); + goto cleanup; + } + VBOX_RELEASE(progress); + } else { + /* This a comment from vboxmanage code in the handleUnregisterVM + * function in VBoxManageMisc.cpp : + * Note that the IMachine::Unregister method will return the medium + * reference in a sane order, which means that closing will normally + * succeed, unless there is still another machine which uses the + * medium. No harm done if we ignore the error. */ + rc = gVBoxAPI.UIMedium.Close(medium); + } + VBOX_UTF16_FREE(locationUtf16); + VBOX_UTF8_FREE(locationUtf8); + } + + /*removing the snapshot*/ + if (virVBoxSnapshotConfRemoveSnapshot(snapshotMachineDesc, def->name) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to remove snapshot %s"), def->name); + goto cleanup; + } + + if (isCurrent) { + VIR_FREE(snapshotMachineDesc->currentSnapshot); + if (def->parent != NULL) { + virVBoxSnapshotConfSnapshotPtr snap = virVBoxSnapshotConfSnapshotByName(snapshotMachineDesc->snapshot, def->parent); + if (!snap) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to get the snapshot to remove")); + goto cleanup; + } + if (VIR_STRDUP(snapshotMachineDesc->currentSnapshot, snap->uuid) < 0) + goto cleanup; + } + } + + /*Registering the machine*/ + if (virVBoxSnapshotConfSaveVboxFile(snapshotMachineDesc, settingsFilepath) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to serialize the machine description")); + goto cleanup; + } + rc = gVBoxAPI.UIVirtualBox.OpenMachine(data->vboxObj, + settingsFilePathUtf16, + &machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to open Machine, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + + rc = gVBoxAPI.UIVirtualBox.RegisterMachine(data->vboxObj, machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to register Machine, rc=%08x"), + (unsigned)rc); + goto cleanup; + } + + ret = 0; + cleanup: + VIR_FREE(def); + VIR_FREE(defXml); + VBOX_RELEASE(machine); + VBOX_UTF16_FREE(settingsFilePathUtf16); + VBOX_UTF8_FREE(settingsFilepath); + VIR_FREE(snapshotMachineDesc); + VBOX_UTF16_FREE(machineNameUtf16); + VBOX_UTF8_FREE(machineName); + VIR_FREE(machineLocationPath); + VIR_FREE(nameTmpUse); + + return ret; +} + +int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, + unsigned int flags) +{ + virDomainPtr dom = snapshot->domain; + VBOX_OBJECT_CHECK(dom->conn, int, -1); + vboxIIDUnion domiid; + IMachine *machine = NULL; + ISnapshot *snap = NULL; + IConsole *console = NULL; + PRUint32 state; + nsresult rc; + vboxArray snapChildren = VBOX_ARRAY_INITIALIZER; + + virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN | + VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, -1); + + if (openSessionForMachine(data, dom->uuid, &domiid, &machine, false) < 0) + goto cleanup; + + snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name); + if (!snap) + goto cleanup; + + rc = gVBoxAPI.UIMachine.GetState(machine, &state); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get domain state")); + goto cleanup; + } + + /* In case we just want to delete the metadata, we will edit the vbox file in order + *to remove the node concerning the snapshot + */ + if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY) { + rc = gVBoxAPI.UArray.vboxArrayGet(&snapChildren, snap, + gVBoxAPI.UArray.handleSnapshotGetChildren(snap)); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get snapshot children")); + goto cleanup; + } + if (snapChildren.count != 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot delete metadata of a snapshot with children")); + goto cleanup; + } else + if (gVBoxAPI.vboxSnapshotRedefine) { + ret = vboxDomainSnapshotDeleteMetadataOnly(snapshot); + } + goto cleanup; + } + + if (gVBoxAPI.machineStateChecker.Online(state)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot delete snapshots of running domain")); + goto cleanup; + } + + rc = gVBoxAPI.UISession.Open(data, &domiid, machine); + if (NS_SUCCEEDED(rc)) + rc = gVBoxAPI.UISession.GetConsole(data->vboxSession, &console); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not open VirtualBox session with domain %s"), + dom->name); + goto cleanup; + } + + if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN) + ret = vboxDomainSnapshotDeleteTree(data, console, snap); + else + ret = vboxDomainSnapshotDeleteSingle(data, console, snap); + + cleanup: + VBOX_RELEASE(console); + VBOX_RELEASE(snap); + vboxIIDUnalloc(&domiid); + gVBoxAPI.UISession.Close(data->vboxSession); + return ret; +} diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h index 1c01fe8..15bf8e2 100644 --- a/src/vbox/vbox_common.h +++ b/src/vbox/vbox_common.h @@ -265,6 +265,19 @@ enum MediumVariant MediumVariant_Diff = 0x20000 }; +# define VBOX_E_OBJECT_NOT_FOUND 0x80BB0001 +# define VBOX_E_INVALID_VM_STATE 0x80BB0002 +# define VBOX_E_VM_ERROR 0x80BB0003 +# define VBOX_E_FILE_ERROR 0x80BB0004 +# define VBOX_E_IPRT_ERROR 0x80BB0005 +# define VBOX_E_PDM_ERROR 0x80BB0006 +# define VBOX_E_INVALID_OBJECT_STATE 0x80BB0007 +# define VBOX_E_HOST_ERROR 0x80BB0008 +# define VBOX_E_NOT_SUPPORTED 0x80BB0009 +# define VBOX_E_XML_ERROR 0x80BB000A +# define VBOX_E_INVALID_SESSION_STATE 0x80BB000B +# define VBOX_E_OBJECT_IN_USE 0x80BB000C + /* Simplied definitions in vbox_CAPI_*.h */ typedef void const *PCVBOXXPCOM; diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index adba028..044e6d6 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1382,146 +1382,6 @@ _vboxAttachDrivesOld(virDomainDefPtr def ATTRIBUTE_UNUSED, #endif /* VBOX_API_VERSION >= 4000000 */ -static int -vboxDomainSnapshotGetAll(virDomainPtr dom, - IMachine *machine, - ISnapshot ***snapshots) -{ - vboxIID empty = VBOX_IID_INITIALIZER; - ISnapshot **list = NULL; - PRUint32 count; - nsresult rc; - unsigned int next; - unsigned int top; - - rc = machine->vtbl->GetSnapshotCount(machine, &count); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get snapshot count for domain %s"), - dom->name); - goto error; - } - - if (count == 0) - goto out; - - if (VIR_ALLOC_N(list, count) < 0) - goto error; - -#if VBOX_API_VERSION < 4000000 - rc = machine->vtbl->GetSnapshot(machine, empty.value, list); -#else /* VBOX_API_VERSION >= 4000000 */ - rc = machine->vtbl->FindSnapshot(machine, empty.value, list); -#endif /* VBOX_API_VERSION >= 4000000 */ - if (NS_FAILED(rc) || !list[0]) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get root snapshot for domain %s"), - dom->name); - goto error; - } - - /* BFS walk through snapshot tree */ - top = 1; - for (next = 0; next < count; next++) { - vboxArray children = VBOX_ARRAY_INITIALIZER; - size_t i; - - if (!list[next]) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unexpected number of snapshots < %u"), count); - goto error; - } - - rc = vboxArrayGet(&children, list[next], - list[next]->vtbl->GetChildren); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("could not get children snapshots")); - goto error; - } - for (i = 0; i < children.count; i++) { - ISnapshot *child = children.items[i]; - if (!child) - continue; - if (top == count) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unexpected number of snapshots > %u"), count); - vboxArrayRelease(&children); - goto error; - } - VBOX_ADDREF(child); - list[top++] = child; - } - vboxArrayRelease(&children); - } - - out: - *snapshots = list; - return count; - - error: - if (list) { - for (next = 0; next < count; next++) - VBOX_RELEASE(list[next]); - } - VIR_FREE(list); - - return -1; -} - -static ISnapshot * -vboxDomainSnapshotGet(vboxGlobalData *data, - virDomainPtr dom, - IMachine *machine, - const char *name) -{ - ISnapshot **snapshots = NULL; - ISnapshot *snapshot = NULL; - nsresult rc; - int count = 0; - size_t i; - - if ((count = vboxDomainSnapshotGetAll(dom, machine, &snapshots)) < 0) - goto cleanup; - - for (i = 0; i < count; i++) { - PRUnichar *nameUtf16; - char *nameUtf8; - - rc = snapshots[i]->vtbl->GetName(snapshots[i], &nameUtf16); - if (NS_FAILED(rc) || !nameUtf16) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("could not get snapshot name")); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(nameUtf16, &nameUtf8); - VBOX_UTF16_FREE(nameUtf16); - if (STREQ(name, nameUtf8)) - snapshot = snapshots[i]; - VBOX_UTF8_FREE(nameUtf8); - - if (snapshot) - break; - } - - if (!snapshot) { - virReportError(VIR_ERR_OPERATION_INVALID, - _("domain %s has no snapshots with name %s"), - dom->name, name); - goto cleanup; - } - - cleanup: - if (count > 0) { - for (i = 0; i < count; i++) { - if (snapshots[i] != snapshot) - VBOX_RELEASE(snapshots[i]); - } - } - VIR_FREE(snapshots); - return snapshot; -} - #if VBOX_API_VERSION < 3001000 static int _vboxDomainSnapshotRestore(virDomainPtr dom, @@ -1629,633 +1489,6 @@ _vboxDomainSnapshotRestore(virDomainPtr dom, } #endif -static int -vboxDomainSnapshotDeleteSingle(vboxGlobalData *data, - IConsole *console, - ISnapshot *snapshot) -{ - IProgress *progress = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - int ret = -1; - nsresult rc; -#if VBOX_API_VERSION == 2002000 - nsresult result; -#else - PRInt32 result; -#endif - - rc = snapshot->vtbl->GetId(snapshot, &iid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get snapshot UUID")); - goto cleanup; - } - -#if VBOX_API_VERSION < 3001000 - rc = console->vtbl->DiscardSnapshot(console, iid.value, &progress); -#else - rc = console->vtbl->DeleteSnapshot(console, iid.value, &progress); -#endif - if (NS_FAILED(rc) || !progress) { - if (rc == VBOX_E_INVALID_VM_STATE) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("cannot delete domain snapshot for running domain")); - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not delete snapshot")); - } - goto cleanup; - } - - progress->vtbl->WaitForCompletion(progress, -1); - progress->vtbl->GetResultCode(progress, &result); - if (NS_FAILED(result)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not delete snapshot")); - goto cleanup; - } - - ret = 0; - - cleanup: - VBOX_RELEASE(progress); - vboxIIDUnalloc(&iid); - return ret; -} - -static int -vboxDomainSnapshotDeleteTree(vboxGlobalData *data, - IConsole *console, - ISnapshot *snapshot) -{ - vboxArray children = VBOX_ARRAY_INITIALIZER; - int ret = -1; - nsresult rc; - size_t i; - - rc = vboxArrayGet(&children, snapshot, snapshot->vtbl->GetChildren); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get children snapshots")); - goto cleanup; - } - - for (i = 0; i < children.count; i++) { - if (vboxDomainSnapshotDeleteTree(data, console, children.items[i])) - goto cleanup; - } - - ret = vboxDomainSnapshotDeleteSingle(data, console, snapshot); - - cleanup: - vboxArrayRelease(&children); - return ret; -} - -#if VBOX_API_VERSION >= 4002000 -static int -vboxDomainSnapshotDeleteMetadataOnly(virDomainSnapshotPtr snapshot) -{ - /* - * This function will remove the node in the vbox xml corresponding to the snapshot. - * It is usually called by vboxDomainSnapshotDelete() with the flag - * VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY. - * If you want to use it anywhere else, be careful, if the snapshot you want to delete - * has children, the result is not granted, they will probably will be deleted in the - * xml, but you may have a problem with hard drives. - * - * If the snapshot which is being deleted is the current one, we will set the current - * snapshot of the machine to the parent of this snapshot. Before writing the modified - * xml file, we undefine the machine from vbox. After writing the file, we redefine - * the machine with the new file. - */ - - virDomainPtr dom = snapshot->domain; - VBOX_OBJECT_CHECK(dom->conn, int, -1); - virDomainSnapshotDefPtr def= NULL; - char *defXml = NULL; - vboxIID domiid = VBOX_IID_INITIALIZER; - nsresult rc; - IMachine *machine = NULL; - PRUnichar *settingsFilePathUtf16 = NULL; - char *settingsFilepath = NULL; - virVBoxSnapshotConfMachinePtr snapshotMachineDesc = NULL; - int isCurrent = -1; - int it = 0; - PRUnichar *machineNameUtf16 = NULL; - char *machineName = NULL; - char *nameTmpUse = NULL; - char *machineLocationPath = NULL; - PRUint32 aMediaSize = 0; - IMedium **aMedia = NULL; - - defXml = vboxDomainSnapshotGetXMLDesc(snapshot, 0); - if (!defXml) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get XML Desc of snapshot")); - goto cleanup; - } - def = virDomainSnapshotDefParseString(defXml, - data->caps, - data->xmlopt, - -1, - VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | - VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE); - if (!def) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get a virDomainSnapshotDefPtr")); - goto cleanup; - } - - vboxIIDFromUUID(&domiid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching UUID")); - goto cleanup; - } - rc = machine->vtbl->GetSettingsFilePath(machine, &settingsFilePathUtf16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get settings file path")); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(settingsFilePathUtf16, &settingsFilepath); - - /*Getting the machine name to retrieve the machine location path.*/ - rc = machine->vtbl->GetName(machine, &machineNameUtf16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot get machine name")); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineName); - if (virAsprintf(&nameTmpUse, "%s.vbox", machineName) < 0) - goto cleanup; - machineLocationPath = virStringReplace(settingsFilepath, nameTmpUse, ""); - if (machineLocationPath == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get the machine location path")); - goto cleanup; - } - snapshotMachineDesc = virVBoxSnapshotConfLoadVboxFile(settingsFilepath, machineLocationPath); - if (!snapshotMachineDesc) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot create a vboxSnapshotXmlPtr")); - goto cleanup; - } - - isCurrent = virVBoxSnapshotConfIsCurrentSnapshot(snapshotMachineDesc, def->name); - if (isCurrent < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to know if the snapshot is the current snapshot")); - goto cleanup; - } - if (isCurrent) { - /* - * If the snapshot is the current snapshot, it means that the machine has read-write - * disks. The first thing to do is to manipulate VirtualBox API to create - * differential read-write disks if the parent snapshot is not null. - */ - if (def->parent != NULL) { - for (it = 0; it < def->dom->ndisks; it++) { - virVBoxSnapshotConfHardDiskPtr readOnly = NULL; - IMedium *medium = NULL; - PRUnichar *locationUtf16 = NULL; - PRUnichar *parentUuidUtf16 = NULL; - char *parentUuid = NULL; - IMedium *newMedium = NULL; - PRUnichar *formatUtf16 = NULL; - PRUnichar *newLocation = NULL; - char *newLocationUtf8 = NULL; - IProgress *progress = NULL; - PRInt32 resultCode = -1; - virVBoxSnapshotConfHardDiskPtr disk = NULL; - PRUnichar *uuidUtf16 = NULL; - char *uuid = NULL; - char *format = NULL; - char **searchResultTab = NULL; - ssize_t resultSize = 0; - char *tmp = NULL; - - readOnly = virVBoxSnapshotConfHardDiskPtrByLocation(snapshotMachineDesc, - def->dom->disks[it]->src->path); - if (!readOnly) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot get hard disk by location")); - goto cleanup; - } - if (readOnly->parent == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("The read only disk has no parent")); - goto cleanup; - } - - VBOX_UTF8_TO_UTF16(readOnly->parent->location, &locationUtf16); - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, - locationUtf16, - DeviceType_HardDisk, - AccessMode_ReadWrite, - false, - &medium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to open HardDisk, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - - rc = medium->vtbl->GetId(medium, &parentUuidUtf16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to get hardDisk Id, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(parentUuidUtf16, &parentUuid); - VBOX_UTF16_FREE(parentUuidUtf16); - VBOX_UTF16_FREE(locationUtf16); - VBOX_UTF8_TO_UTF16("VDI", &formatUtf16); - - if (virAsprintf(&newLocationUtf8, "%sfakedisk-%s-%d.vdi", - machineLocationPath, def->parent, it) < 0) - goto cleanup; - VBOX_UTF8_TO_UTF16(newLocationUtf8, &newLocation); - rc = data->vboxObj->vtbl->CreateHardDisk(data->vboxObj, - formatUtf16, - newLocation, - &newMedium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to create HardDisk, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - VBOX_UTF16_FREE(formatUtf16); - VBOX_UTF16_FREE(newLocation); - -# if VBOX_API_VERSION < 4003000 - medium->vtbl->CreateDiffStorage(medium, newMedium, MediumVariant_Diff, &progress); -# else - PRUint32 tab[1]; - tab[0] = MediumVariant_Diff; - medium->vtbl->CreateDiffStorage(medium, newMedium, 1, tab, &progress); -# endif - - progress->vtbl->WaitForCompletion(progress, -1); - progress->vtbl->GetResultCode(progress, &resultCode); - if (NS_FAILED(resultCode)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Error while creating diff storage, rc=%08x"), - (unsigned)resultCode); - goto cleanup; - } - VBOX_RELEASE(progress); - /* - * The differential disk is created, we add it to the media registry and - * the machine storage controller. - */ - - if (VIR_ALLOC(disk) < 0) - goto cleanup; - - rc = newMedium->vtbl->GetId(newMedium, &uuidUtf16); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to get medium uuid, rc=%08x"), - (unsigned)rc); - VIR_FREE(disk); - goto cleanup; - } - VBOX_UTF16_TO_UTF8(uuidUtf16, &uuid); - disk->uuid = uuid; - VBOX_UTF16_FREE(uuidUtf16); - - if (VIR_STRDUP(disk->location, newLocationUtf8) < 0) { - VIR_FREE(disk); - goto cleanup; - } - - rc = newMedium->vtbl->GetFormat(newMedium, &formatUtf16); - VBOX_UTF16_TO_UTF8(formatUtf16, &format); - disk->format = format; - VBOX_UTF16_FREE(formatUtf16); - - if (virVBoxSnapshotConfAddHardDiskToMediaRegistry(disk, - snapshotMachineDesc->mediaRegistry, - parentUuid) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to add hard disk to the media registry")); - goto cleanup; - } - /*Adding fake disks to the machine storage controllers*/ - - resultSize = virStringSearch(snapshotMachineDesc->storageController, - VBOX_UUID_REGEX, - it + 1, - &searchResultTab); - if (resultSize != it + 1) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to find UUID %s"), searchResultTab[it]); - goto cleanup; - } - - tmp = virStringReplace(snapshotMachineDesc->storageController, - searchResultTab[it], - disk->uuid); - virStringFreeList(searchResultTab); - VIR_FREE(snapshotMachineDesc->storageController); - if (!tmp) - goto cleanup; - if (VIR_STRDUP(snapshotMachineDesc->storageController, tmp) < 0) - goto cleanup; - - VIR_FREE(tmp); - /*Closing the "fake" disk*/ - rc = newMedium->vtbl->Close(newMedium); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to close the new medium, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - } - } else { - for (it = 0; it < def->dom->ndisks; it++) { - const char *uuidRO = NULL; - char **searchResultTab = NULL; - ssize_t resultSize = 0; - char *tmp = NULL; - uuidRO = virVBoxSnapshotConfHardDiskUuidByLocation(snapshotMachineDesc, - def->dom->disks[it]->src->path); - if (!uuidRO) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("No such disk in media registry %s"), - def->dom->disks[it]->src->path); - goto cleanup; - } - - resultSize = virStringSearch(snapshotMachineDesc->storageController, - VBOX_UUID_REGEX, - it + 1, - &searchResultTab); - if (resultSize != it + 1) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to find UUID %s"), - searchResultTab[it]); - goto cleanup; - } - - tmp = virStringReplace(snapshotMachineDesc->storageController, - searchResultTab[it], - uuidRO); - virStringFreeList(searchResultTab); - VIR_FREE(snapshotMachineDesc->storageController); - if (!tmp) - goto cleanup; - if (VIR_STRDUP(snapshotMachineDesc->storageController, tmp) < 0) - goto cleanup; - - VIR_FREE(tmp); - } - } - } - /*We remove the read write disks from the media registry*/ - for (it = 0; it < def->ndisks; it++) { - const char *uuidRW = - virVBoxSnapshotConfHardDiskUuidByLocation(snapshotMachineDesc, - def->disks[it].src->path); - if (!uuidRW) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to find UUID for location %s"), def->disks[it].src->path); - goto cleanup; - } - if (virVBoxSnapshotConfRemoveHardDisk(snapshotMachineDesc->mediaRegistry, uuidRW) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to remove disk from media registry. uuid = %s"), uuidRW); - goto cleanup; - } - } - /*If the parent snapshot is not NULL, we remove the-read only disks from the media registry*/ - if (def->parent != NULL) { - for (it = 0; it < def->dom->ndisks; it++) { - const char *uuidRO = - virVBoxSnapshotConfHardDiskUuidByLocation(snapshotMachineDesc, - def->dom->disks[it]->src->path); - if (!uuidRO) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to find UUID for location %s"), def->dom->disks[it]->src->path); - goto cleanup; - } - if (virVBoxSnapshotConfRemoveHardDisk(snapshotMachineDesc->mediaRegistry, uuidRO) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to remove disk from media registry. uuid = %s"), uuidRO); - goto cleanup; - } - } - } - rc = machine->vtbl->Unregister(machine, - CleanupMode_DetachAllReturnHardDisksOnly, - &aMediaSize, - &aMedia); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to unregister machine, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - VBOX_RELEASE(machine); - for (it = 0; it < aMediaSize; it++) { - IMedium *medium = aMedia[it]; - if (medium) { - PRUnichar *locationUtf16 = NULL; - char *locationUtf8 = NULL; - rc = medium->vtbl->GetLocation(medium, &locationUtf16); - VBOX_UTF16_TO_UTF8(locationUtf16, &locationUtf8); - if (isCurrent && strstr(locationUtf8, "fake") != NULL) { - /*we delete the fake disk because we don't need it anymore*/ - IProgress *progress = NULL; - PRInt32 resultCode = -1; - rc = medium->vtbl->DeleteStorage(medium, &progress); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to delete medium, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - progress->vtbl->WaitForCompletion(progress, -1); - progress->vtbl->GetResultCode(progress, &resultCode); - if (NS_FAILED(resultCode)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Error while closing medium, rc=%08x"), - (unsigned)resultCode); - goto cleanup; - } - VBOX_RELEASE(progress); - } else { - /* This a comment from vboxmanage code in the handleUnregisterVM - * function in VBoxManageMisc.cpp : - * Note that the IMachine::Unregister method will return the medium - * reference in a sane order, which means that closing will normally - * succeed, unless there is still another machine which uses the - * medium. No harm done if we ignore the error. */ - rc = medium->vtbl->Close(medium); - } - VBOX_UTF16_FREE(locationUtf16); - VBOX_UTF8_FREE(locationUtf8); - } - } - - /*removing the snapshot*/ - if (virVBoxSnapshotConfRemoveSnapshot(snapshotMachineDesc, def->name) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to remove snapshot %s"), def->name); - goto cleanup; - } - - if (isCurrent) { - VIR_FREE(snapshotMachineDesc->currentSnapshot); - if (def->parent != NULL) { - virVBoxSnapshotConfSnapshotPtr snap = virVBoxSnapshotConfSnapshotByName(snapshotMachineDesc->snapshot, def->parent); - if (!snap) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to get the snapshot to remove")); - goto cleanup; - } - if (VIR_STRDUP(snapshotMachineDesc->currentSnapshot, snap->uuid) < 0) - goto cleanup; - } - } - - /*Registering the machine*/ - if (virVBoxSnapshotConfSaveVboxFile(snapshotMachineDesc, settingsFilepath) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to serialize the machine description")); - goto cleanup; - } - rc = data->vboxObj->vtbl->OpenMachine(data->vboxObj, - settingsFilePathUtf16, - &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to open Machine, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - - rc = data->vboxObj->vtbl->RegisterMachine(data->vboxObj, machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to register Machine, rc=%08x"), - (unsigned)rc); - goto cleanup; - } - - ret = 0; - cleanup: - VIR_FREE(def); - VIR_FREE(defXml); - VBOX_RELEASE(machine); - VBOX_UTF16_FREE(settingsFilePathUtf16); - VBOX_UTF8_FREE(settingsFilepath); - VIR_FREE(snapshotMachineDesc); - VBOX_UTF16_FREE(machineNameUtf16); - VBOX_UTF8_FREE(machineName); - VIR_FREE(machineLocationPath); - VIR_FREE(nameTmpUse); - - return ret; -} -#endif - -static int -vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, - unsigned int flags) -{ - virDomainPtr dom = snapshot->domain; - VBOX_OBJECT_CHECK(dom->conn, int, -1); - vboxIID domiid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - ISnapshot *snap = NULL; - IConsole *console = NULL; - PRUint32 state; - nsresult rc; - vboxArray snapChildren = VBOX_ARRAY_INITIALIZER; - - virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN | - VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, -1); - - vboxIIDFromUUID(&domiid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching UUID")); - goto cleanup; - } - - snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name); - if (!snap) - goto cleanup; - - rc = machine->vtbl->GetState(machine, &state); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get domain state")); - goto cleanup; - } - - /* In case we just want to delete the metadata, we will edit the vbox file in order - *to remove the node concerning the snapshot - */ - if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY) { - rc = vboxArrayGet(&snapChildren, snap, snap->vtbl->GetChildren); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get snapshot children")); - goto cleanup; - } - if (snapChildren.count != 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot delete metadata of a snapshot with children")); - goto cleanup; - } else { -#if VBOX_API_VERSION >= 4002000 - ret = vboxDomainSnapshotDeleteMetadataOnly(snapshot); -#endif - } - goto cleanup; - } - - if (state >= MachineState_FirstOnline - && state <= MachineState_LastOnline) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("cannot delete snapshots of running domain")); - goto cleanup; - } - - rc = VBOX_SESSION_OPEN(domiid.value, machine); - if (NS_SUCCEEDED(rc)) - rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not open VirtualBox session with domain %s"), - dom->name); - goto cleanup; - } - - if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN) - ret = vboxDomainSnapshotDeleteTree(data, console, snap); - else - ret = vboxDomainSnapshotDeleteSingle(data, console, snap); - - cleanup: - VBOX_RELEASE(console); - VBOX_RELEASE(snap); - vboxIIDUnalloc(&domiid); - VBOX_SESSION_CLOSE(); - return ret; -} - #if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 /* No Callback support for VirtualBox 2.2.* series */ /* No Callback support for VirtualBox 4.* series */ @@ -6231,6 +5464,16 @@ _consoleTakeSnapshot(IConsole *console, PRUnichar *name, } static nsresult +_consoleDeleteSnapshot(IConsole *console, vboxIIDUnion *iidu, IProgress **progress) +{ +#if VBOX_API_VERSION < 3001000 + return console->vtbl->DiscardSnapshot(console, IID_MEMBER(value), progress); +#else /* VBOX_API_VERSION >= 3001000 */ + return console->vtbl->DeleteSnapshot(console, IID_MEMBER(value), progress); +#endif /* VBOX_API_VERSION >= 3001000 */ +} + +static nsresult _progressWaitForCompletion(IProgress *progress, PRInt32 timeout) { return progress->vtbl->WaitForCompletion(progress, timeout); @@ -7242,6 +6485,7 @@ static vboxUniformedIConsole _UIConsole = { .PowerDown = _consolePowerDown, .Reset = _consoleReset, .TakeSnapshot = _consoleTakeSnapshot, + .DeleteSnapshot = _consoleDeleteSnapshot, }; static vboxUniformedIProgress _UIProgress = { diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 005b21b..2800b60 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -272,6 +272,7 @@ typedef struct { nsresult (*Reset)(IConsole *console); nsresult (*TakeSnapshot)(IConsole *console, PRUnichar *name, PRUnichar *description, IProgress **progress); + nsresult (*DeleteSnapshot)(IConsole *console, vboxIIDUnion *iidu, IProgress **progress); } vboxUniformedIConsole; /* Functions for IProgress */ @@ -596,6 +597,9 @@ int vboxDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot, unsigned int flags); int vboxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, unsigned int flags); +int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, + unsigned int flags); + /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 130 ++++++++++++++++++++++++++++ src/vbox/vbox_common.h | 1 + src/vbox/vbox_tmpl.c | 190 ++++++++++++----------------------------- src/vbox/vbox_uniformed_api.h | 23 ++++- 4 files changed, 208 insertions(+), 136 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 505f1cd..d3735ac 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -19,6 +19,7 @@ #include <config.h> #include <unistd.h> +#include <fcntl.h> #include "internal.h" #include "datatypes.h" @@ -32,6 +33,8 @@ #include "virtime.h" #include "snapshot_conf.h" #include "vbox_snapshot_conf.h" +#include "fdstream.h" +#include "configmake.h" #include "vbox_common.h" #include "vbox_uniformed_api.h" @@ -7133,3 +7136,130 @@ int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, gVBoxAPI.UISession.Close(data->vboxSession); return ret; } + +char * +vboxDomainScreenshot(virDomainPtr dom, + virStreamPtr st, + unsigned int screen, + unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, char *, NULL); + IConsole *console = NULL; + vboxIIDUnion iid; + IMachine *machine = NULL; + nsresult rc; + char *tmp; + int tmp_fd = -1; + unsigned int max_screen; + + if (!gVBoxAPI.supportScreenshot) { + virReportError(VIR_ERR_NO_SUPPORT, "%s", + _("virDomainScreenshot don't support for current vbox version")); + return NULL; + } + + virCheckFlags(0, NULL); + + if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0) + return NULL; + + rc = gVBoxAPI.UIMachine.GetMonitorCount(machine, &max_screen); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("unable to get monitor count")); + VBOX_RELEASE(machine); + return NULL; + } + + if (screen >= max_screen) { + virReportError(VIR_ERR_INVALID_ARG, + _("screen ID higher than monitor " + "count (%d)"), max_screen); + VBOX_RELEASE(machine); + return NULL; + } + + if (virAsprintf(&tmp, "%s/cache/libvirt/vbox.screendump.XXXXXX", LOCALSTATEDIR) < 0) { + VBOX_RELEASE(machine); + return NULL; + } + + if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) { + virReportSystemError(errno, _("mkostemp(\"%s\") failed"), tmp); + VIR_FREE(tmp); + VBOX_RELEASE(machine); + return NULL; + } + + + rc = gVBoxAPI.UISession.OpenExisting(data, &iid, machine); + if (NS_SUCCEEDED(rc)) { + rc = gVBoxAPI.UISession.GetConsole(data->vboxSession, &console); + if (NS_SUCCEEDED(rc) && console) { + IDisplay *display = NULL; + + gVBoxAPI.UIConsole.GetDisplay(console, &display); + + if (display) { + PRUint32 width, height, bitsPerPixel; + PRUint32 screenDataSize; + PRUint8 *screenData; + PRInt32 xOrigin, yOrigin; + + rc = gVBoxAPI.UIDisplay.GetScreenResolution(display, screen, + &width, &height, + &bitsPerPixel, + &xOrigin, &yOrigin); + + if (NS_FAILED(rc) || !width || !height) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("unable to get screen resolution")); + goto endjob; + } + + rc = gVBoxAPI.UIDisplay.TakeScreenShotPNGToArray(display, screen, + width, height, + &screenDataSize, + &screenData); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("failed to take screenshot")); + goto endjob; + } + + if (safewrite(tmp_fd, (char *) screenData, + screenDataSize) < 0) { + virReportSystemError(errno, _("unable to write data " + "to '%s'"), tmp); + goto endjob; + } + + if (VIR_CLOSE(tmp_fd) < 0) { + virReportSystemError(errno, _("unable to close %s"), tmp); + goto endjob; + } + + if (VIR_STRDUP(ret, "image/png") < 0) + goto endjob; + + if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("unable to open stream")); + VIR_FREE(ret); + } + endjob: + VIR_FREE(screenData); + VBOX_RELEASE(display); + } + VBOX_RELEASE(console); + } + gVBoxAPI.UISession.Close(data->vboxSession); + } + + VIR_FORCE_CLOSE(tmp_fd); + unlink(tmp); + VIR_FREE(tmp); + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h index 15bf8e2..b5a0353 100644 --- a/src/vbox/vbox_common.h +++ b/src/vbox/vbox_common.h @@ -301,5 +301,6 @@ typedef nsISupports IMediumAttachment; typedef nsISupports IStorageController; typedef nsISupports ISharedFolder; typedef nsISupports ISnapshot; +typedef nsISupports IDisplay; #endif /* VBOX_COMMON_H */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 044e6d6..82c45ad 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -3732,141 +3732,6 @@ static char *vboxStorageVolGetPath(virStorageVolPtr vol) { return ret; } -#if VBOX_API_VERSION >= 4000000 -static char * -vboxDomainScreenshot(virDomainPtr dom, - virStreamPtr st, - unsigned int screen, - unsigned int flags) -{ - VBOX_OBJECT_CHECK(dom->conn, char *, NULL); - IConsole *console = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - nsresult rc; - char *tmp; - int tmp_fd = -1; - unsigned int max_screen; - - virCheckFlags(0, NULL); - - 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")); - return NULL; - } - - rc = machine->vtbl->GetMonitorCount(machine, &max_screen); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("unable to get monitor count")); - VBOX_RELEASE(machine); - return NULL; - } - - if (screen >= max_screen) { - virReportError(VIR_ERR_INVALID_ARG, - _("screen ID higher than monitor " - "count (%d)"), max_screen); - VBOX_RELEASE(machine); - return NULL; - } - - if (virAsprintf(&tmp, "%s/cache/libvirt/vbox.screendump.XXXXXX", LOCALSTATEDIR) < 0) { - VBOX_RELEASE(machine); - return NULL; - } - - if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) { - virReportSystemError(errno, _("mkostemp(\"%s\") failed"), tmp); - VIR_FREE(tmp); - VBOX_RELEASE(machine); - return NULL; - } - - - 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) { - IDisplay *display = NULL; - - console->vtbl->GetDisplay(console, &display); - - if (display) { - PRUint32 width, height, bitsPerPixel; - PRUint32 screenDataSize; - PRUint8 *screenData; -# if VBOX_API_VERSION >= 4003000 - PRInt32 xOrigin, yOrigin; -# endif - - rc = display->vtbl->GetScreenResolution(display, screen, - &width, &height, -# if VBOX_API_VERSION < 4003000 - &bitsPerPixel); -# else - &bitsPerPixel, - &xOrigin, &yOrigin); -# endif - - if (NS_FAILED(rc) || !width || !height) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("unable to get screen resolution")); - goto endjob; - } - - rc = display->vtbl->TakeScreenShotPNGToArray(display, screen, - width, height, - &screenDataSize, - &screenData); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("failed to take screenshot")); - goto endjob; - } - - if (safewrite(tmp_fd, (char *) screenData, - screenDataSize) < 0) { - virReportSystemError(errno, _("unable to write data " - "to '%s'"), tmp); - goto endjob; - } - - if (VIR_CLOSE(tmp_fd) < 0) { - virReportSystemError(errno, _("unable to close %s"), tmp); - goto endjob; - } - - if (VIR_STRDUP(ret, "image/png") < 0) - goto endjob; - - if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("unable to open stream")); - VIR_FREE(ret); - } - endjob: - VIR_FREE(screenData); - VBOX_RELEASE(display); - } - VBOX_RELEASE(console); - } - VBOX_SESSION_CLOSE(); - } - - VIR_FORCE_CLOSE(tmp_fd); - unlink(tmp); - VIR_FREE(tmp); - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} -#endif /* VBOX_API_VERSION >= 4000000 */ - - #define MATCH(FLAG) (flags & (FLAG)) static int vboxConnectListAllDomains(virConnectPtr conn, @@ -5474,6 +5339,12 @@ _consoleDeleteSnapshot(IConsole *console, vboxIIDUnion *iidu, IProgress **progre } static nsresult +_consoleGetDisplay(IConsole *console, IDisplay **display) +{ + return console->vtbl->GetDisplay(console, display); +} + +static nsresult _progressWaitForCompletion(IProgress *progress, PRInt32 timeout) { return progress->vtbl->WaitForCompletion(progress, timeout); @@ -6339,6 +6210,46 @@ _snapshotGetOnline(ISnapshot *snapshot, PRBool *online) return snapshot->vtbl->GetOnline(snapshot, online); } +static nsresult +_displayGetScreenResolution(IDisplay *display ATTRIBUTE_UNUSED, + PRUint32 screenId ATTRIBUTE_UNUSED, + PRUint32 *width ATTRIBUTE_UNUSED, + PRUint32 *height ATTRIBUTE_UNUSED, + PRUint32 *bitsPerPixel ATTRIBUTE_UNUSED, + PRInt32 *xOrigin ATTRIBUTE_UNUSED, + PRInt32 *yOrigin ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION < 3002000 + vboxUnsupported(); + return 0; +#elif VBOX_API_VERSION < 4003000 + return display->vtbl->GetScreenResolution(display, screenId, width, + height, bitsPerPixel); +#else /* VBOX_API_VERSION >= 4003000 */ + return display->vtbl->GetScreenResolution(display, screenId, width, + height, bitsPerPixel, + xOrigin, yOrigin); +#endif /* VBOX_API_VERSION >= 4003000 */ +} + +static nsresult +_displayTakeScreenShotPNGToArray(IDisplay *display ATTRIBUTE_UNUSED, + PRUint32 screenId ATTRIBUTE_UNUSED, + PRUint32 width ATTRIBUTE_UNUSED, + PRUint32 height ATTRIBUTE_UNUSED, + PRUint32 *screenDataSize ATTRIBUTE_UNUSED, + PRUint8** screenData ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION < 4000000 + vboxUnsupported(); + return 0; +#else /* VBOX_API_VERSION >= 4000000 */ + return display->vtbl->TakeScreenShotPNGToArray(display, screenId, width, + height, screenDataSize, + screenData); +#endif /* VBOX_API_VERSION >= 4000000 */ +} + static bool _machineStateOnline(PRUint32 state) { return ((state >= MachineState_FirstOnline) && @@ -6486,6 +6397,7 @@ static vboxUniformedIConsole _UIConsole = { .Reset = _consoleReset, .TakeSnapshot = _consoleTakeSnapshot, .DeleteSnapshot = _consoleDeleteSnapshot, + .GetDisplay = _consoleGetDisplay, }; static vboxUniformedIProgress _UIProgress = { @@ -6634,6 +6546,11 @@ static vboxUniformedISnapshot _UISnapshot = { .GetOnline = _snapshotGetOnline, }; +static vboxUniformedIDisplay _UIDisplay = { + .GetScreenResolution = _displayGetScreenResolution, + .TakeScreenShotPNGToArray = _displayTakeScreenShotPNGToArray, +}; + static uniformedMachineStateChecker _machineStateChecker = { .Online = _machineStateOnline, .Inactive = _machineStateInactive, @@ -6685,6 +6602,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->UIStorageController = _UIStorageController; pVBoxAPI->UISharedFolder = _UISharedFolder; pVBoxAPI->UISnapshot = _UISnapshot; + pVBoxAPI->UIDisplay = _UIDisplay; pVBoxAPI->machineStateChecker = _machineStateChecker; #if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 @@ -6704,10 +6622,12 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->getMachineForSession = 1; pVBoxAPI->detachDevicesExplicitly = 0; pVBoxAPI->vboxAttachDrivesUseOld = 0; + pVBoxAPI->supportScreenshot = 1; #else /* VBOX_API_VERSION < 4000000 */ pVBoxAPI->getMachineForSession = 0; pVBoxAPI->detachDevicesExplicitly = 1; pVBoxAPI->vboxAttachDrivesUseOld = 1; + pVBoxAPI->supportScreenshot = 0; #endif /* VBOX_API_VERSION < 4000000 */ #if VBOX_API_VERSION >= 4001000 diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 2800b60..7e8f677 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -273,6 +273,7 @@ typedef struct { nsresult (*TakeSnapshot)(IConsole *console, PRUnichar *name, PRUnichar *description, IProgress **progress); nsresult (*DeleteSnapshot)(IConsole *console, vboxIIDUnion *iidu, IProgress **progress); + nsresult (*GetDisplay)(IConsole *console, IDisplay **display); } vboxUniformedIConsole; /* Functions for IProgress */ @@ -446,6 +447,23 @@ typedef struct { nsresult (*GetOnline)(ISnapshot *snapshot, PRBool *online); } vboxUniformedISnapshot; +/* Functions for IDisplay */ +typedef struct { + nsresult (*GetScreenResolution)(IDisplay *display, + PRUint32 screenId, + PRUint32 *width, + PRUint32 *height, + PRUint32 *bitsPerPixel, + PRInt32 *xOrigin, + PRInt32 *yOrigin); + nsresult (*TakeScreenShotPNGToArray)(IDisplay *display, + PRUint32 screenId, + PRUint32 width, + PRUint32 height, + PRUint32 *screenDataSize, + PRUint8** screenData); +} vboxUniformedIDisplay; + typedef struct { bool (*Online)(PRUint32 state); bool (*Inactive)(PRUint32 state); @@ -498,6 +516,7 @@ typedef struct { vboxUniformedIStorageController UIStorageController; vboxUniformedISharedFolder UISharedFolder; vboxUniformedISnapshot UISnapshot; + vboxUniformedIDisplay UIDisplay; uniformedMachineStateChecker machineStateChecker; /* vbox API features */ bool domainEventCallbacks; @@ -509,6 +528,7 @@ typedef struct { bool vboxAttachDrivesUseOld; bool oldMediumInterface; bool vboxSnapshotRedefine; + bool supportScreenshot; } vboxUniformedAPI; /* libvirt API @@ -599,7 +619,8 @@ int vboxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, unsigned int flags); int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, unsigned int flags); - +char *vboxDomainScreenshot(virDomainPtr dom, virStreamPtr st, + unsigned int screen, unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_common.c | 157 +++++++++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 156 ---------------------------------------- src/vbox/vbox_uniformed_api.h | 2 + 3 files changed, 159 insertions(+), 156 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index d3735ac..14f627f 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -7263,3 +7263,160 @@ vboxDomainScreenshot(virDomainPtr dom, vboxIIDUnalloc(&iid); return ret; } + +#define MATCH(FLAG) (flags & (FLAG)) +int +vboxConnectListAllDomains(virConnectPtr conn, + virDomainPtr **domains, + unsigned int flags) +{ + VBOX_OBJECT_CHECK(conn, int, -1); + vboxArray machines = VBOX_ARRAY_INITIALIZER; + char *machineNameUtf8 = NULL; + PRUnichar *machineNameUtf16 = NULL; + unsigned char uuid[VIR_UUID_BUFLEN]; + vboxIIDUnion iid; + PRUint32 state; + nsresult rc; + size_t i; + virDomainPtr dom; + virDomainPtr *doms = NULL; + int count = 0; + bool active; + PRUint32 snapshotCount; + + virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); + + /* filter out flag options that will produce 0 results in vbox driver: + * - managed save: vbox guests don't have managed save images + * - autostart: vbox doesn't support autostarting guests + * - persistance: vbox doesn't support transient guests + */ + if ((MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) && + !MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT)) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) && + !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART)) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && + !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE))) { + if (domains && + VIR_ALLOC_N(*domains, 1) < 0) + goto cleanup; + + ret = 0; + 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 domains, rc=%08x"), (unsigned)rc); + goto cleanup; + } + + if (domains && + VIR_ALLOC_N(doms, machines.count + 1) < 0) + goto cleanup; + + for (i = 0; i < machines.count; i++) { + IMachine *machine = machines.items[i]; + + if (!machine) + continue; + + PRBool isAccessible = PR_FALSE; + gVBoxAPI.UIMachine.GetAccessible(machine, &isAccessible); + + if (!isAccessible) + continue; + + gVBoxAPI.UIMachine.GetState(machine, &state); + + if (gVBoxAPI.machineStateChecker.Online(state)) + active = true; + else + active = false; + + /* filter by active state */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) && + !((MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE) && active) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE) && !active))) + continue; + + /* filter by snapshot existence */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_SNAPSHOT)) { + rc = gVBoxAPI.UIMachine.GetSnapshotCount(machine, &snapshotCount); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get snapshot count for listed domains")); + goto cleanup; + } + if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) && + snapshotCount > 0) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) && + snapshotCount == 0))) + continue; + } + + /* filter by machine state */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE) && + !((MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) && + gVBoxAPI.machineStateChecker.Running(state)) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) && + gVBoxAPI.machineStateChecker.Paused(state)) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) && + gVBoxAPI.machineStateChecker.PoweredOff(state)) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) && + (!gVBoxAPI.machineStateChecker.Running(state) && + !gVBoxAPI.machineStateChecker.Paused(state) && + !gVBoxAPI.machineStateChecker.PoweredOff(state))))) + continue; + + /* just count the machines */ + if (!doms) { + count++; + continue; + } + + gVBoxAPI.UIMachine.GetName(machine, &machineNameUtf16); + VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8); + gVBoxAPI.UIMachine.GetId(machine, &iid); + vboxIIDToUUID(&iid, uuid); + vboxIIDUnalloc(&iid); + + dom = virGetDomain(conn, machineNameUtf8, uuid); + + VBOX_UTF8_FREE(machineNameUtf8); + VBOX_UTF16_FREE(machineNameUtf16); + + if (!dom) + goto cleanup; + + if (active) + dom->id = i + 1; + + doms[count++] = dom; + } + + if (doms) { + /* safe to ignore, new size will be equal or less than + * previous allocation*/ + ignore_value(VIR_REALLOC_N(doms, count + 1)); + *domains = doms; + doms = NULL; + } + + ret = count; + + cleanup: + if (doms) { + for (i = 0; i < count; i++) { + if (doms[i]) + virDomainFree(doms[i]); + } + } + VIR_FREE(doms); + + gVBoxAPI.UArray.vboxArrayRelease(&machines); + return ret; +} +#undef MATCH diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 82c45ad..55ccbc7 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -3732,162 +3732,6 @@ static char *vboxStorageVolGetPath(virStorageVolPtr vol) { return ret; } -#define MATCH(FLAG) (flags & (FLAG)) -static int -vboxConnectListAllDomains(virConnectPtr conn, - virDomainPtr **domains, - unsigned int flags) -{ - VBOX_OBJECT_CHECK(conn, int, -1); - vboxArray machines = VBOX_ARRAY_INITIALIZER; - char *machineNameUtf8 = NULL; - PRUnichar *machineNameUtf16 = NULL; - unsigned char uuid[VIR_UUID_BUFLEN]; - vboxIID iid = VBOX_IID_INITIALIZER; - PRUint32 state; - nsresult rc; - size_t i; - virDomainPtr dom; - virDomainPtr *doms = NULL; - int count = 0; - bool active; - PRUint32 snapshotCount; - - virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); - - /* filter out flag options that will produce 0 results in vbox driver: - * - managed save: vbox guests don't have managed save images - * - autostart: vbox doesn't support autostarting guests - * - persistance: vbox doesn't support transient guests - */ - if ((MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) && - !MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT)) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) && - !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART)) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && - !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE))) { - if (domains && - VIR_ALLOC_N(*domains, 1) < 0) - goto cleanup; - - ret = 0; - 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 domains, rc=%08x"), (unsigned)rc); - goto cleanup; - } - - if (domains && - VIR_ALLOC_N(doms, machines.count + 1) < 0) - goto cleanup; - - 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) - active = true; - else - active = false; - - /* filter by active state */ - if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) && - !((MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE) && active) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE) && !active))) - continue; - - /* filter by snapshot existence */ - if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_SNAPSHOT)) { - rc = machine->vtbl->GetSnapshotCount(machine, &snapshotCount); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get snapshot count for listed domains")); - goto cleanup; - } - if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) && - snapshotCount > 0) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) && - snapshotCount == 0))) - continue; - } - - /* filter by machine state */ - if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE) && - !((MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) && - state == MachineState_Running) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) && - state == MachineState_Paused) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) && - state == MachineState_PoweredOff) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) && - (state != MachineState_Running && - state != MachineState_Paused && - state != MachineState_PoweredOff)))) - continue; - - /* just count the machines */ - if (!doms) { - count++; - continue; - } - - machine->vtbl->GetName(machine, &machineNameUtf16); - VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8); - machine->vtbl->GetId(machine, &iid.value); - vboxIIDToUUID(&iid, uuid); - vboxIIDUnalloc(&iid); - - dom = virGetDomain(conn, machineNameUtf8, uuid); - - VBOX_UTF8_FREE(machineNameUtf8); - VBOX_UTF16_FREE(machineNameUtf16); - - if (!dom) - goto cleanup; - - if (active) - dom->id = i + 1; - - doms[count++] = dom; - } - } - } - - if (doms) { - /* safe to ignore, new size will be equal or less than - * previous allocation*/ - ignore_value(VIR_REALLOC_N(doms, count + 1)); - *domains = doms; - doms = NULL; - } - - ret = count; - - cleanup: - if (doms) { - for (i = 0; i < count; i++) { - if (doms[i]) - virDomainFree(doms[i]); - } - } - VIR_FREE(doms); - - vboxArrayRelease(&machines); - return ret; -} -#undef MATCH - - static int vboxNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 7e8f677..c105a07 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -621,6 +621,8 @@ int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, unsigned int flags); char *vboxDomainScreenshot(virDomainPtr dom, virStreamPtr st, unsigned int screen, unsigned int flags); +int vboxConnectListAllDomains(virConnectPtr conn, virDomainPtr **domains, + unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

Four functions are rewrite in this patch, that is: vboxNodeGetInfo vboxNodeGetCellsFreeMemory vboxNodeGetFreeMemory vboxNodeGetFreePages Since these functions has nothing to do with vbox, it can be directly moved to vbox_common.c. So, I merged these things into one patch. --- src/vbox/vbox_common.c | 39 ++++++++++++++++++++++++++++++++++++++ src/vbox/vbox_tmpl.c | 42 ----------------------------------------- src/vbox/vbox_uniformed_api.h | 13 +++++++++++++ 3 files changed, 52 insertions(+), 42 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 14f627f..c05fd6a 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -7420,3 +7420,42 @@ vboxConnectListAllDomains(virConnectPtr conn, return ret; } #undef MATCH + +int +vboxNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, + virNodeInfoPtr nodeinfo) +{ + return nodeGetInfo(nodeinfo); +} + +int +vboxNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, + unsigned long long *freeMems, + int startCell, + int maxCells) +{ + return nodeGetCellsFreeMemory(freeMems, startCell, maxCells); +} + +unsigned long long +vboxNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) +{ + unsigned long long freeMem; + if (nodeGetMemory(NULL, &freeMem) < 0) + return 0; + return freeMem; +} + +int +vboxNodeGetFreePages(virConnectPtr conn ATTRIBUTE_UNUSED, + unsigned int npages, + unsigned int *pages, + int startCell, + unsigned int cellCount, + unsigned long long *counts, + unsigned int flags) +{ + virCheckFlags(0, -1); + + return nodeGetFreePages(npages, pages, startCell, cellCount, counts); +} diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 55ccbc7..72d4c4d 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -3732,48 +3732,6 @@ static char *vboxStorageVolGetPath(virStorageVolPtr vol) { return ret; } -static int -vboxNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, - virNodeInfoPtr nodeinfo) -{ - return nodeGetInfo(nodeinfo); -} - - -static int -vboxNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, - unsigned long long *freeMems, - int startCell, - int maxCells) -{ - return nodeGetCellsFreeMemory(freeMems, startCell, maxCells); -} - - -static unsigned long long -vboxNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) -{ - unsigned long long freeMem; - if (nodeGetMemory(NULL, &freeMem) < 0) - return 0; - return freeMem; -} - - -static int -vboxNodeGetFreePages(virConnectPtr conn ATTRIBUTE_UNUSED, - unsigned int npages, - unsigned int *pages, - int startCell, - unsigned int cellCount, - unsigned long long *counts, - unsigned int flags) -{ - virCheckFlags(0, -1); - - return nodeGetFreePages(npages, pages, startCell, cellCount, counts); -} - static int _pfnInitialize(vboxGlobalData *data) { data->pFuncs = g_pfnGetFunctions(VBOX_XPCOMC_VERSION); diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index c105a07..a868ac0 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -623,6 +623,19 @@ char *vboxDomainScreenshot(virDomainPtr dom, virStreamPtr st, unsigned int screen, unsigned int flags); int vboxConnectListAllDomains(virConnectPtr conn, virDomainPtr **domains, unsigned int flags); +int vboxNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo); +int vboxNodeGetCellsFreeMemory(virConnectPtr conn, + unsigned long long *freeMems, + int startCell, + int maxCells); +unsigned long long vboxNodeGetFreeMemory(virConnectPtr); +int vboxNodeGetFreePages(virConnectPtr conn, + unsigned int npages, + unsigned int *pages, + int startCell, + unsigned int cellCount, + unsigned long long *counts, + unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

--- src/vbox/vbox_tmpl.c | 20 ++++++++++++++++++++ src/vbox/vbox_uniformed_api.h | 1 + 2 files changed, 21 insertions(+) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 72d4c4d..fbd0d08 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -1492,6 +1492,16 @@ _vboxDomainSnapshotRestore(virDomainPtr dom, #if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 /* No Callback support for VirtualBox 2.2.* series */ /* No Callback support for VirtualBox 4.* series */ + +static void +_registerDomainEvent(virDriverPtr driver) +{ + driver->connectDomainEventRegister = NULL; + driver->connectDomainEventDeregister = NULL; + driver->connectDomainEventRegisterAny = NULL; + driver->connectDomainEventDeregisterAny = NULL; +} + #else /* !(VBOX_API_VERSION == 2002000 || VBOX_API_VERSION >= 4000000) */ /* Functions needed for Callbacks */ @@ -2034,6 +2044,15 @@ vboxConnectDomainEventDeregisterAny(virConnectPtr conn, return ret; } +static void +_registerDomainEvent(virDriverPtr driver) +{ + driver->connectDomainEventRegister = vboxConnectDomainEventRegister; /* 0.7.0 */ + driver->connectDomainEventDeregister = vboxConnectDomainEventDeregister; /* 0.7.0 */ + driver->connectDomainEventRegisterAny = vboxConnectDomainEventRegisterAny; /* 0.8.0 */ + driver->connectDomainEventDeregisterAny = vboxConnectDomainEventDeregisterAny; /* 0.8.0 */ +} + #endif /* !(VBOX_API_VERSION == 2002000 || VBOX_API_VERSION >= 4000000) */ /** @@ -6381,6 +6400,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->attachFloppy = _attachFloppy; pVBoxAPI->detachFloppy = _detachFloppy; pVBoxAPI->snapshotRestore = _vboxDomainSnapshotRestore; + pVBoxAPI->registerDomainEvent = _registerDomainEvent; pVBoxAPI->UPFN = _UPFN; pVBoxAPI->UIID = _UIID; pVBoxAPI->UArray = _UArray; diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index a868ac0..c0586c0 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -493,6 +493,7 @@ typedef struct { int (*attachFloppy)(vboxGlobalData *data, IMachine *machine, const char *src); int (*detachFloppy)(IMachine *machine); int (*snapshotRestore)(virDomainPtr dom, IMachine *machine, ISnapshot *snapshot); + void (*registerDomainEvent)(virDriverPtr driver); vboxUniformedPFN UPFN; vboxUniformedIID UIID; vboxUniformedArray UArray; -- 1.7.9.5

After this patch, we will have only one common domain driver. So, the rewritten on domain driver is finished in this patch. --- src/vbox/README | 7 +- src/vbox/vbox_common.c | 257 +++++++++++++++++++++++++++-------------- src/vbox/vbox_driver.c | 28 ++--- src/vbox/vbox_tmpl.c | 80 ------------- src/vbox/vbox_uniformed_api.h | 103 ----------------- 5 files changed, 186 insertions(+), 289 deletions(-) diff --git a/src/vbox/README b/src/vbox/README index 6e88ae6..0551db9 100644 --- a/src/vbox/README +++ b/src/vbox/README @@ -37,7 +37,12 @@ The file which has version dependent changes and includes the template file for given below for all of its functionality. vbox_tmpl.c -The file where all the real driver implementation code exists. +The file contains all version specified codes. It implements the +vboxUniformedAPI for each vbox version. + +vbox_common.c +The file implement the common driver, with the uniformed api which +defined in vbox_uniformed_api.h and implemented in vbox_tmpl.c Now there would be a vbox_V*.c file (for eg: vbox_V2_2.c for V2.2) for each major virtualbox version which would do some preprocessor magic diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index c05fd6a..edd3eef 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -121,6 +121,9 @@ if (!data->vboxObj) {\ /* global vbox API, used for all common codes. */ static vboxUniformedAPI gVBoxAPI; +/* update the virDriver according to the vboxUniformedAPI */ +static void updateDriver(void); + int vboxRegisterUniformedAPI(uint32_t uVersion) { /* Install gVBoxAPI according to the vbox API version. @@ -149,6 +152,7 @@ int vboxRegisterUniformedAPI(uint32_t uVersion) } else { return -1; } + updateDriver(); return 0; } @@ -461,9 +465,10 @@ static void vboxUninitialize(vboxGlobalData *data) VIR_FREE(data); } -virDrvOpenStatus vboxConnectOpen(virConnectPtr conn, - virConnectAuthPtr auth ATTRIBUTE_UNUSED, - unsigned int flags) +static virDrvOpenStatus +vboxConnectOpen(virConnectPtr conn, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + unsigned int flags) { vboxGlobalData *data = NULL; uid_t uid = geteuid(); @@ -532,7 +537,7 @@ virDrvOpenStatus vboxConnectOpen(virConnectPtr conn, return VIR_DRV_OPEN_SUCCESS; } -int vboxConnectClose(virConnectPtr conn) +static int vboxConnectClose(virConnectPtr conn) { vboxGlobalData *data = conn->privateData; VIR_DEBUG("%s: in vboxClose", conn->driver->name); @@ -543,7 +548,7 @@ int vboxConnectClose(virConnectPtr conn) return 0; } -int +static int vboxDomainSave(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED) { VBOX_OBJECT_CHECK(dom->conn, int, -1); @@ -604,7 +609,7 @@ static void vboxDriverUnlock(vboxGlobalData *data) virMutexUnlock(&data->lock); } -int vboxConnectGetVersion(virConnectPtr conn, unsigned long *version) +static int vboxConnectGetVersion(virConnectPtr conn, unsigned long *version) { vboxGlobalData *data = conn->privateData; VIR_DEBUG("%s: in vboxGetVersion", conn->driver->name); @@ -616,29 +621,29 @@ int vboxConnectGetVersion(virConnectPtr conn, unsigned long *version) return 0; } -char *vboxConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED) +static char *vboxConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED) { return virGetHostname(); } -int vboxConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED) +static int vboxConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED) { /* Driver is using local, non-network based transport */ return 1; } -int vboxConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED) +static int vboxConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED) { /* No encryption is needed, or used on the local transport*/ return 0; } -int vboxConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED) +static int vboxConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED) { return 1; } -int +static int vboxConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED) { VBOX_OBJECT_CHECK(conn, int, -1); @@ -662,7 +667,7 @@ vboxConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED) return ret; } -char *vboxConnectGetCapabilities(virConnectPtr conn) +static char *vboxConnectGetCapabilities(virConnectPtr conn) { VBOX_OBJECT_CHECK(conn, char *, NULL); @@ -673,7 +678,7 @@ char *vboxConnectGetCapabilities(virConnectPtr conn) return ret; } -int vboxConnectListDomains(virConnectPtr conn, int *ids, int nids) +static int vboxConnectListDomains(virConnectPtr conn, int *ids, int nids) { VBOX_OBJECT_CHECK(conn, int, -1); vboxArray machines = VBOX_ARRAY_INITIALIZER; @@ -711,7 +716,7 @@ int vboxConnectListDomains(virConnectPtr conn, int *ids, int nids) return ret; } -int vboxConnectNumOfDomains(virConnectPtr conn) +static int vboxConnectNumOfDomains(virConnectPtr conn) { VBOX_OBJECT_CHECK(conn, int, -1); vboxArray machines = VBOX_ARRAY_INITIALIZER; @@ -746,7 +751,7 @@ int vboxConnectNumOfDomains(virConnectPtr conn) return ret; } -virDomainPtr vboxDomainLookupByID(virConnectPtr conn, int id) +static virDomainPtr vboxDomainLookupByID(virConnectPtr conn, int id) { VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL); vboxArray machines = VBOX_ARRAY_INITIALIZER; @@ -892,7 +897,7 @@ virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn, return ret; } -virDomainPtr +static virDomainPtr vboxDomainLookupByName(virConnectPtr conn, const char *name) { VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL); @@ -1873,7 +1878,7 @@ vboxAttachSharedFolder(virDomainDefPtr def, vboxGlobalData *data, IMachine *mach } } -virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml) +static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml) { VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL); IMachine *machine = NULL; @@ -2042,7 +2047,7 @@ detachDevices_common(vboxGlobalData *data, vboxIIDUnion *iidu) VBOX_UTF16_FREE(hddcnameUtf16); } -int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags) +static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags) { VBOX_OBJECT_CHECK(dom->conn, int, -1); IMachine *machine = NULL; @@ -2075,7 +2080,7 @@ int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags) return ret; } -int vboxDomainUndefine(virDomainPtr dom) +static int vboxDomainUndefine(virDomainPtr dom) { return vboxDomainUndefineFlags(dom, 0); } @@ -2231,7 +2236,7 @@ vboxStartMachine(virDomainPtr dom, int maxDomID, IMachine *machine, vboxIIDUnion return ret; } -int vboxDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) +static int vboxDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) { VBOX_OBJECT_CHECK(dom->conn, int, -1); vboxArray machines = VBOX_ARRAY_INITIALIZER; @@ -2299,13 +2304,13 @@ int vboxDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) return ret; } -int vboxDomainCreate(virDomainPtr dom) +static int vboxDomainCreate(virDomainPtr dom) { return vboxDomainCreateWithFlags(dom, 0); } -virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml, - unsigned int flags) +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 @@ -2332,7 +2337,7 @@ virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml, return dom; } -int vboxDomainIsActive(virDomainPtr dom) +static int vboxDomainIsActive(virDomainPtr dom) { VBOX_OBJECT_CHECK(dom->conn, int, -1); vboxArray machines = VBOX_ARRAY_INITIALIZER; @@ -2398,7 +2403,7 @@ int vboxDomainIsActive(virDomainPtr dom) return ret; } -int vboxDomainIsPersistent(virDomainPtr dom) +static int vboxDomainIsPersistent(virDomainPtr dom) { /* All domains are persistent. However, we do want to check for * existence. */ @@ -2417,7 +2422,7 @@ int vboxDomainIsPersistent(virDomainPtr dom) return ret; } -int vboxDomainIsUpdated(virDomainPtr dom) +static int vboxDomainIsUpdated(virDomainPtr dom) { /* VBox domains never have a persistent state that differs from * current state. However, we do want to check for existence. */ @@ -2436,7 +2441,7 @@ int vboxDomainIsUpdated(virDomainPtr dom) return ret; } -int vboxDomainSuspend(virDomainPtr dom) +static int vboxDomainSuspend(virDomainPtr dom) { VBOX_OBJECT_CHECK(dom->conn, int, -1); IMachine *machine = NULL; @@ -2483,7 +2488,7 @@ int vboxDomainSuspend(virDomainPtr dom) return ret; } -int vboxDomainResume(virDomainPtr dom) +static int vboxDomainResume(virDomainPtr dom) { VBOX_OBJECT_CHECK(dom->conn, int, -1); IMachine *machine = NULL; @@ -2530,7 +2535,7 @@ int vboxDomainResume(virDomainPtr dom) return ret; } -int vboxDomainShutdownFlags(virDomainPtr dom, unsigned int flags) +static int vboxDomainShutdownFlags(virDomainPtr dom, unsigned int flags) { VBOX_OBJECT_CHECK(dom->conn, int, -1); IMachine *machine = NULL; @@ -2578,12 +2583,12 @@ int vboxDomainShutdownFlags(virDomainPtr dom, unsigned int flags) return ret; } -int vboxDomainShutdown(virDomainPtr dom) +static int vboxDomainShutdown(virDomainPtr dom) { return vboxDomainShutdownFlags(dom, 0); } -int vboxDomainReboot(virDomainPtr dom, unsigned int flags) +static int vboxDomainReboot(virDomainPtr dom, unsigned int flags) { VBOX_OBJECT_CHECK(dom->conn, int, -1); IMachine *machine = NULL; @@ -2627,7 +2632,7 @@ int vboxDomainReboot(virDomainPtr dom, unsigned int flags) return ret; } -int vboxDomainDestroyFlags(virDomainPtr dom, unsigned int flags) +static int vboxDomainDestroyFlags(virDomainPtr dom, unsigned int flags) { VBOX_OBJECT_CHECK(dom->conn, int, -1); IMachine *machine = NULL; @@ -2672,12 +2677,12 @@ int vboxDomainDestroyFlags(virDomainPtr dom, unsigned int flags) return ret; } -int vboxDomainDestroy(virDomainPtr dom) +static int vboxDomainDestroy(virDomainPtr dom) { return vboxDomainDestroyFlags(dom, 0); } -char *vboxDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) { +static char *vboxDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) { /* Returning "hvm" always as suggested on list, cause * this functions seems to be badly named and it * is supposed to pass the ABI name and not the domain @@ -2689,7 +2694,7 @@ char *vboxDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) { return osType; } -int vboxDomainSetMemory(virDomainPtr dom, unsigned long memory) +static int vboxDomainSetMemory(virDomainPtr dom, unsigned long memory) { VBOX_OBJECT_CHECK(dom->conn, int, -1); IMachine *machine = NULL; @@ -2743,7 +2748,7 @@ int vboxDomainSetMemory(virDomainPtr dom, unsigned long memory) return ret; } -int vboxDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) +static int vboxDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { VBOX_OBJECT_CHECK(dom->conn, int, -1); vboxArray machines = VBOX_ARRAY_INITIALIZER; @@ -2822,8 +2827,8 @@ int vboxDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) return ret; } -int vboxDomainGetState(virDomainPtr dom, int *state, - int *reason, unsigned int flags) +static int vboxDomainGetState(virDomainPtr dom, int *state, + int *reason, unsigned int flags) { VBOX_OBJECT_CHECK(dom->conn, int, -1); vboxIIDUnion domiid; @@ -2849,8 +2854,8 @@ int vboxDomainGetState(virDomainPtr dom, int *state, return ret; } -int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, - unsigned int flags) +static int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, + unsigned int flags) { VBOX_OBJECT_CHECK(dom->conn, int, -1); IMachine *machine = NULL; @@ -2895,12 +2900,12 @@ int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, return ret; } -int vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) +static int vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) { return vboxDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_AFFECT_LIVE); } -int vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) +static int vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) { VBOX_OBJECT_CHECK(dom->conn, int, -1); ISystemProperties *systemProperties = NULL; @@ -2928,7 +2933,7 @@ int vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) return ret; } -int vboxDomainGetMaxVcpus(virDomainPtr dom) +static int vboxDomainGetMaxVcpus(virDomainPtr dom) { return vboxDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)); @@ -3791,7 +3796,7 @@ vboxDumpParallel(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine, P } } -char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) +static char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) { VBOX_OBJECT_CHECK(dom->conn, char *, NULL); virDomainDefPtr def = NULL; @@ -3949,8 +3954,8 @@ char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) return ret; } -int vboxConnectListDefinedDomains(virConnectPtr conn, - char ** const names, int maxnames) +static int vboxConnectListDefinedDomains(virConnectPtr conn, + char ** const names, int maxnames) { VBOX_OBJECT_CHECK(conn, int, -1); vboxArray machines = VBOX_ARRAY_INITIALIZER; @@ -4008,7 +4013,7 @@ int vboxConnectListDefinedDomains(virConnectPtr conn, return ret; } -int vboxConnectNumOfDefinedDomains(virConnectPtr conn) +static int vboxConnectNumOfDefinedDomains(virConnectPtr conn) { VBOX_OBJECT_CHECK(conn, int, -1); vboxArray machines = VBOX_ARRAY_INITIALIZER; @@ -4160,13 +4165,13 @@ static int vboxDomainAttachDeviceImpl(virDomainPtr dom, return ret; } -int vboxDomainAttachDevice(virDomainPtr dom, const char *xml) +static int vboxDomainAttachDevice(virDomainPtr dom, const char *xml) { return vboxDomainAttachDeviceImpl(dom, xml, 0); } -int vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) +static int vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) { virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); @@ -4179,8 +4184,8 @@ int vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, return vboxDomainAttachDeviceImpl(dom, xml, 0); } -int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) +static int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) { virCheckFlags(VIR_DOMAIN_AFFECT_CURRENT | VIR_DOMAIN_AFFECT_LIVE | @@ -4195,7 +4200,7 @@ int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, return vboxDomainAttachDeviceImpl(dom, xml, 1); } -int vboxDomainDetachDevice(virDomainPtr dom, const char *xml) +static int vboxDomainDetachDevice(virDomainPtr dom, const char *xml) { VBOX_OBJECT_CHECK(dom->conn, int, -1); IMachine *machine = NULL; @@ -4296,8 +4301,8 @@ int vboxDomainDetachDevice(virDomainPtr dom, const char *xml) return ret; } -int vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) +static int vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) { virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); @@ -5258,7 +5263,7 @@ vboxSnapshotRedefine(virDomainPtr dom, return ret; } -virDomainSnapshotPtr +static virDomainSnapshotPtr vboxDomainSnapshotCreateXML(virDomainPtr dom, const char *xmlDesc, unsigned int flags) @@ -5512,9 +5517,8 @@ vboxDomainSnapshotGet(vboxGlobalData *data, return snapshot; } -static -int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def, - virDomainSnapshotPtr snapshot) +static int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def, + virDomainSnapshotPtr snapshot) { virDomainPtr dom = snapshot->domain; VBOX_OBJECT_CHECK(dom->conn, int, -1); @@ -5732,7 +5736,7 @@ int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def, static int vboxSnapshotGetReadOnlyDisks(virDomainSnapshotPtr snapshot, - virDomainSnapshotDefPtr def) + virDomainSnapshotDefPtr def) { virDomainPtr dom = snapshot->domain; VBOX_OBJECT_CHECK(dom->conn, int, -1); @@ -5946,8 +5950,8 @@ int vboxSnapshotGetReadOnlyDisks(virDomainSnapshotPtr snapshot, return ret; } -char *vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, - unsigned int flags) +static char *vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, + unsigned int flags) { virDomainPtr dom = snapshot->domain; VBOX_OBJECT_CHECK(dom->conn, char *, NULL); @@ -6085,7 +6089,7 @@ char *vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, return ret; } -int vboxDomainSnapshotNum(virDomainPtr dom, unsigned int flags) +static int vboxDomainSnapshotNum(virDomainPtr dom, unsigned int flags) { VBOX_OBJECT_CHECK(dom->conn, int, -1); vboxIIDUnion iid; @@ -6125,8 +6129,8 @@ int vboxDomainSnapshotNum(virDomainPtr dom, unsigned int flags) return ret; } -int vboxDomainSnapshotListNames(virDomainPtr dom, char **names, - int nameslen, unsigned int flags) +static int vboxDomainSnapshotListNames(virDomainPtr dom, char **names, + int nameslen, unsigned int flags) { VBOX_OBJECT_CHECK(dom->conn, int, -1); vboxIIDUnion iid; @@ -6204,7 +6208,7 @@ int vboxDomainSnapshotListNames(virDomainPtr dom, char **names, return ret; } -virDomainSnapshotPtr +static virDomainSnapshotPtr vboxDomainSnapshotLookupByName(virDomainPtr dom, const char *name, unsigned int flags) { @@ -6230,8 +6234,8 @@ vboxDomainSnapshotLookupByName(virDomainPtr dom, const char *name, return ret; } -int vboxDomainHasCurrentSnapshot(virDomainPtr dom, - unsigned int flags) +static int vboxDomainHasCurrentSnapshot(virDomainPtr dom, + unsigned int flags) { VBOX_OBJECT_CHECK(dom->conn, int, -1); vboxIIDUnion iid; @@ -6262,7 +6266,7 @@ int vboxDomainHasCurrentSnapshot(virDomainPtr dom, return ret; } -virDomainSnapshotPtr +static virDomainSnapshotPtr vboxDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, unsigned int flags) { @@ -6323,7 +6327,7 @@ vboxDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, return ret; } -virDomainSnapshotPtr +static virDomainSnapshotPtr vboxDomainSnapshotCurrent(virDomainPtr dom, unsigned int flags) { VBOX_OBJECT_CHECK(dom->conn, virDomainSnapshotPtr, NULL); @@ -6376,8 +6380,8 @@ vboxDomainSnapshotCurrent(virDomainPtr dom, unsigned int flags) return ret; } -int vboxDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, - unsigned int flags) +static int vboxDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, + unsigned int flags) { virDomainPtr dom = snapshot->domain; VBOX_OBJECT_CHECK(dom->conn, int, -1); @@ -6433,8 +6437,8 @@ int vboxDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, return ret; } -int vboxDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot, - unsigned int flags) +static int vboxDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot, + unsigned int flags) { virDomainPtr dom = snapshot->domain; VBOX_OBJECT_CHECK(dom->conn, int, -1); @@ -6460,8 +6464,8 @@ int vboxDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot, return ret; } -int vboxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, - unsigned int flags) +static int vboxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, + unsigned int flags) { virDomainPtr dom = snapshot->domain; VBOX_OBJECT_CHECK(dom->conn, int, -1); @@ -7056,8 +7060,8 @@ vboxDomainSnapshotDeleteMetadataOnly(virDomainSnapshotPtr snapshot) return ret; } -int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, - unsigned int flags) +static int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, + unsigned int flags) { virDomainPtr dom = snapshot->domain; VBOX_OBJECT_CHECK(dom->conn, int, -1); @@ -7137,7 +7141,7 @@ int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, return ret; } -char * +static char * vboxDomainScreenshot(virDomainPtr dom, virStreamPtr st, unsigned int screen, @@ -7265,7 +7269,7 @@ vboxDomainScreenshot(virDomainPtr dom, } #define MATCH(FLAG) (flags & (FLAG)) -int +static int vboxConnectListAllDomains(virConnectPtr conn, virDomainPtr **domains, unsigned int flags) @@ -7421,14 +7425,14 @@ vboxConnectListAllDomains(virConnectPtr conn, } #undef MATCH -int +static int vboxNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) { return nodeGetInfo(nodeinfo); } -int +static int vboxNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long long *freeMems, int startCell, @@ -7437,7 +7441,7 @@ vboxNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, return nodeGetCellsFreeMemory(freeMems, startCell, maxCells); } -unsigned long long +static unsigned long long vboxNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) { unsigned long long freeMem; @@ -7446,7 +7450,7 @@ vboxNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) return freeMem; } -int +static int vboxNodeGetFreePages(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned int npages, unsigned int *pages, @@ -7459,3 +7463,88 @@ vboxNodeGetFreePages(virConnectPtr conn ATTRIBUTE_UNUSED, return nodeGetFreePages(npages, pages, startCell, cellCount, counts); } + +/** + * Function Tables + */ + +virDriver vboxCommonDriver = { + .no = VIR_DRV_VBOX, + .name = "VBOX", + .connectOpen = vboxConnectOpen, /* 0.6.3 */ + .connectClose = vboxConnectClose, /* 0.6.3 */ + .connectGetVersion = vboxConnectGetVersion, /* 0.6.3 */ + .connectGetHostname = vboxConnectGetHostname, /* 0.6.3 */ + .connectGetMaxVcpus = vboxConnectGetMaxVcpus, /* 0.6.3 */ + .nodeGetInfo = vboxNodeGetInfo, /* 0.6.3 */ + .connectGetCapabilities = vboxConnectGetCapabilities, /* 0.6.3 */ + .connectListDomains = vboxConnectListDomains, /* 0.6.3 */ + .connectNumOfDomains = vboxConnectNumOfDomains, /* 0.6.3 */ + .connectListAllDomains = vboxConnectListAllDomains, /* 0.9.13 */ + .domainCreateXML = vboxDomainCreateXML, /* 0.6.3 */ + .domainLookupByID = vboxDomainLookupByID, /* 0.6.3 */ + .domainLookupByUUID = vboxDomainLookupByUUID, /* 0.6.3 */ + .domainLookupByName = vboxDomainLookupByName, /* 0.6.3 */ + .domainSuspend = vboxDomainSuspend, /* 0.6.3 */ + .domainResume = vboxDomainResume, /* 0.6.3 */ + .domainShutdown = vboxDomainShutdown, /* 0.6.3 */ + .domainShutdownFlags = vboxDomainShutdownFlags, /* 0.9.10 */ + .domainReboot = vboxDomainReboot, /* 0.6.3 */ + .domainDestroy = vboxDomainDestroy, /* 0.6.3 */ + .domainDestroyFlags = vboxDomainDestroyFlags, /* 0.9.4 */ + .domainGetOSType = vboxDomainGetOSType, /* 0.6.3 */ + .domainSetMemory = vboxDomainSetMemory, /* 0.6.3 */ + .domainGetInfo = vboxDomainGetInfo, /* 0.6.3 */ + .domainGetState = vboxDomainGetState, /* 0.9.2 */ + .domainSave = vboxDomainSave, /* 0.6.3 */ + .domainSetVcpus = vboxDomainSetVcpus, /* 0.7.1 */ + .domainSetVcpusFlags = vboxDomainSetVcpusFlags, /* 0.8.5 */ + .domainGetVcpusFlags = vboxDomainGetVcpusFlags, /* 0.8.5 */ + .domainGetMaxVcpus = vboxDomainGetMaxVcpus, /* 0.7.1 */ + .domainGetXMLDesc = vboxDomainGetXMLDesc, /* 0.6.3 */ + .connectListDefinedDomains = vboxConnectListDefinedDomains, /* 0.6.3 */ + .connectNumOfDefinedDomains = vboxConnectNumOfDefinedDomains, /* 0.6.3 */ + .domainCreate = vboxDomainCreate, /* 0.6.3 */ + .domainCreateWithFlags = vboxDomainCreateWithFlags, /* 0.8.2 */ + .domainDefineXML = vboxDomainDefineXML, /* 0.6.3 */ + .domainUndefine = vboxDomainUndefine, /* 0.6.3 */ + .domainUndefineFlags = vboxDomainUndefineFlags, /* 0.9.5 */ + .domainAttachDevice = vboxDomainAttachDevice, /* 0.6.3 */ + .domainAttachDeviceFlags = vboxDomainAttachDeviceFlags, /* 0.7.7 */ + .domainDetachDevice = vboxDomainDetachDevice, /* 0.6.3 */ + .domainDetachDeviceFlags = vboxDomainDetachDeviceFlags, /* 0.7.7 */ + .domainUpdateDeviceFlags = vboxDomainUpdateDeviceFlags, /* 0.8.0 */ + .nodeGetCellsFreeMemory = vboxNodeGetCellsFreeMemory, /* 0.6.5 */ + .nodeGetFreeMemory = vboxNodeGetFreeMemory, /* 0.6.5 */ + .connectIsEncrypted = vboxConnectIsEncrypted, /* 0.7.3 */ + .connectIsSecure = vboxConnectIsSecure, /* 0.7.3 */ + .domainIsActive = vboxDomainIsActive, /* 0.7.3 */ + .domainIsPersistent = vboxDomainIsPersistent, /* 0.7.3 */ + .domainIsUpdated = vboxDomainIsUpdated, /* 0.8.6 */ + .domainSnapshotCreateXML = vboxDomainSnapshotCreateXML, /* 0.8.0 */ + .domainSnapshotGetXMLDesc = vboxDomainSnapshotGetXMLDesc, /* 0.8.0 */ + .domainSnapshotNum = vboxDomainSnapshotNum, /* 0.8.0 */ + .domainSnapshotListNames = vboxDomainSnapshotListNames, /* 0.8.0 */ + .domainSnapshotLookupByName = vboxDomainSnapshotLookupByName, /* 0.8.0 */ + .domainHasCurrentSnapshot = vboxDomainHasCurrentSnapshot, /* 0.8.0 */ + .domainSnapshotGetParent = vboxDomainSnapshotGetParent, /* 0.9.7 */ + .domainSnapshotCurrent = vboxDomainSnapshotCurrent, /* 0.8.0 */ + .domainSnapshotIsCurrent = vboxDomainSnapshotIsCurrent, /* 0.9.13 */ + .domainSnapshotHasMetadata = vboxDomainSnapshotHasMetadata, /* 0.9.13 */ + .domainRevertToSnapshot = vboxDomainRevertToSnapshot, /* 0.8.0 */ + .domainSnapshotDelete = vboxDomainSnapshotDelete, /* 0.8.0 */ + .connectIsAlive = vboxConnectIsAlive, /* 0.9.8 */ + .nodeGetFreePages = vboxNodeGetFreePages, /* 1.2.6 */ +}; + +static void updateDriver(void) +{ + /* Update the vboxDriver according to the vboxUniformedAPI. + * We need to make sure the vboxUniformedAPI is initialized + * before calling this function. */ + gVBoxAPI.registerDomainEvent(&vboxCommonDriver); + if (gVBoxAPI.supportScreenshot) + vboxCommonDriver.domainScreenshot = vboxDomainScreenshot; + else + vboxCommonDriver.domainScreenshot = NULL; +} diff --git a/src/vbox/vbox_driver.c b/src/vbox/vbox_driver.c index 37b772c..f0c05fe 100644 --- a/src/vbox/vbox_driver.c +++ b/src/vbox/vbox_driver.c @@ -48,37 +48,29 @@ VIR_LOG_INIT("vbox.vbox_driver"); -extern virDriver vbox22Driver; extern virNetworkDriver vbox22NetworkDriver; extern virStorageDriver vbox22StorageDriver; -extern virDriver vbox30Driver; extern virNetworkDriver vbox30NetworkDriver; extern virStorageDriver vbox30StorageDriver; -extern virDriver vbox31Driver; extern virNetworkDriver vbox31NetworkDriver; extern virStorageDriver vbox31StorageDriver; -extern virDriver vbox32Driver; extern virNetworkDriver vbox32NetworkDriver; extern virStorageDriver vbox32StorageDriver; -extern virDriver vbox40Driver; extern virNetworkDriver vbox40NetworkDriver; extern virStorageDriver vbox40StorageDriver; -extern virDriver vbox41Driver; extern virNetworkDriver vbox41NetworkDriver; extern virStorageDriver vbox41StorageDriver; -extern virDriver vbox42Driver; extern virNetworkDriver vbox42NetworkDriver; extern virStorageDriver vbox42StorageDriver; -extern virDriver vbox42_20Driver; extern virNetworkDriver vbox42_20NetworkDriver; extern virStorageDriver vbox42_20StorageDriver; -extern virDriver vbox43Driver; extern virNetworkDriver vbox43NetworkDriver; extern virStorageDriver vbox43StorageDriver; -extern virDriver vbox43_4Driver; extern virNetworkDriver vbox43_4NetworkDriver; extern virStorageDriver vbox43_4StorageDriver; +extern virDriver vboxCommonDriver; + static virDriver vboxDriverDummy; #define VIR_FROM_THIS VIR_FROM_VBOX @@ -114,59 +106,53 @@ int vboxRegister(void) */ if (uVersion >= 2001052 && uVersion < 2002051) { VIR_DEBUG("VirtualBox API version: 2.2"); - driver = &vbox22Driver; networkDriver = &vbox22NetworkDriver; storageDriver = &vbox22StorageDriver; } else if (uVersion >= 2002051 && uVersion < 3000051) { VIR_DEBUG("VirtualBox API version: 3.0"); - driver = &vbox30Driver; networkDriver = &vbox30NetworkDriver; storageDriver = &vbox30StorageDriver; } else if (uVersion >= 3000051 && uVersion < 3001051) { VIR_DEBUG("VirtualBox API version: 3.1"); - driver = &vbox31Driver; networkDriver = &vbox31NetworkDriver; storageDriver = &vbox31StorageDriver; } else if (uVersion >= 3001051 && uVersion < 3002051) { VIR_DEBUG("VirtualBox API version: 3.2"); - driver = &vbox32Driver; networkDriver = &vbox32NetworkDriver; storageDriver = &vbox32StorageDriver; } else if (uVersion >= 3002051 && uVersion < 4000051) { VIR_DEBUG("VirtualBox API version: 4.0"); - driver = &vbox40Driver; networkDriver = &vbox40NetworkDriver; storageDriver = &vbox40StorageDriver; } else if (uVersion >= 4000051 && uVersion < 4001051) { VIR_DEBUG("VirtualBox API version: 4.1"); - driver = &vbox41Driver; networkDriver = &vbox41NetworkDriver; storageDriver = &vbox41StorageDriver; } else if (uVersion >= 4001051 && uVersion < 4002020) { VIR_DEBUG("VirtualBox API version: 4.2"); - driver = &vbox42Driver; networkDriver = &vbox42NetworkDriver; storageDriver = &vbox42StorageDriver; } else if (uVersion >= 4002020 && uVersion < 4002051) { VIR_DEBUG("VirtualBox API version: 4.2.20 or higher"); - driver = &vbox42_20Driver; networkDriver = &vbox42_20NetworkDriver; storageDriver = &vbox42_20StorageDriver; } else if (uVersion >= 4002051 && uVersion < 4003004) { VIR_DEBUG("VirtualBox API version: 4.3"); - driver = &vbox43Driver; networkDriver = &vbox43NetworkDriver; storageDriver = &vbox43StorageDriver; } else if (uVersion >= 4003004 && uVersion < 4003051) { VIR_DEBUG("VirtualBox API version: 4.3.4 or higher"); - driver = &vbox43_4Driver; networkDriver = &vbox43_4NetworkDriver; storageDriver = &vbox43_4StorageDriver; } else { VIR_DEBUG("Unsupported VirtualBox API version: %u", uVersion); } /* Register vboxUniformedAPI. */ - vboxRegisterUniformedAPI(uVersion); + if (vboxRegisterUniformedAPI(uVersion) == 0) + /* Only if successfully register the uniformed api, + * can we use the vboxCommonDriver. Or use the + * vboxDriverDummy in case of failure. */ + driver = &vboxCommonDriver; } else { VIR_DEBUG("VBoxCGlueInit failed, using dummy driver"); } diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index fbd0d08..de833dc 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -6477,86 +6477,6 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) * Function Tables */ -virDriver NAME(Driver) = { - .no = VIR_DRV_VBOX, - .name = "VBOX", - .connectOpen = vboxConnectOpen, /* 0.6.3 */ - .connectClose = vboxConnectClose, /* 0.6.3 */ - .connectGetVersion = vboxConnectGetVersion, /* 0.6.3 */ - .connectGetHostname = vboxConnectGetHostname, /* 0.6.3 */ - .connectGetMaxVcpus = vboxConnectGetMaxVcpus, /* 0.6.3 */ - .nodeGetInfo = vboxNodeGetInfo, /* 0.6.3 */ - .connectGetCapabilities = vboxConnectGetCapabilities, /* 0.6.3 */ - .connectListDomains = vboxConnectListDomains, /* 0.6.3 */ - .connectNumOfDomains = vboxConnectNumOfDomains, /* 0.6.3 */ - .connectListAllDomains = vboxConnectListAllDomains, /* 0.9.13 */ - .domainCreateXML = vboxDomainCreateXML, /* 0.6.3 */ - .domainLookupByID = vboxDomainLookupByID, /* 0.6.3 */ - .domainLookupByUUID = vboxDomainLookupByUUID, /* 0.6.3 */ - .domainLookupByName = vboxDomainLookupByName, /* 0.6.3 */ - .domainSuspend = vboxDomainSuspend, /* 0.6.3 */ - .domainResume = vboxDomainResume, /* 0.6.3 */ - .domainShutdown = vboxDomainShutdown, /* 0.6.3 */ - .domainShutdownFlags = vboxDomainShutdownFlags, /* 0.9.10 */ - .domainReboot = vboxDomainReboot, /* 0.6.3 */ - .domainDestroy = vboxDomainDestroy, /* 0.6.3 */ - .domainDestroyFlags = vboxDomainDestroyFlags, /* 0.9.4 */ - .domainGetOSType = vboxDomainGetOSType, /* 0.6.3 */ - .domainSetMemory = vboxDomainSetMemory, /* 0.6.3 */ - .domainGetInfo = vboxDomainGetInfo, /* 0.6.3 */ - .domainGetState = vboxDomainGetState, /* 0.9.2 */ - .domainSave = vboxDomainSave, /* 0.6.3 */ - .domainSetVcpus = vboxDomainSetVcpus, /* 0.7.1 */ - .domainSetVcpusFlags = vboxDomainSetVcpusFlags, /* 0.8.5 */ - .domainGetVcpusFlags = vboxDomainGetVcpusFlags, /* 0.8.5 */ - .domainGetMaxVcpus = vboxDomainGetMaxVcpus, /* 0.7.1 */ - .domainGetXMLDesc = vboxDomainGetXMLDesc, /* 0.6.3 */ - .connectListDefinedDomains = vboxConnectListDefinedDomains, /* 0.6.3 */ - .connectNumOfDefinedDomains = vboxConnectNumOfDefinedDomains, /* 0.6.3 */ - .domainCreate = vboxDomainCreate, /* 0.6.3 */ - .domainCreateWithFlags = vboxDomainCreateWithFlags, /* 0.8.2 */ - .domainDefineXML = vboxDomainDefineXML, /* 0.6.3 */ - .domainUndefine = vboxDomainUndefine, /* 0.6.3 */ - .domainUndefineFlags = vboxDomainUndefineFlags, /* 0.9.5 */ - .domainAttachDevice = vboxDomainAttachDevice, /* 0.6.3 */ - .domainAttachDeviceFlags = vboxDomainAttachDeviceFlags, /* 0.7.7 */ - .domainDetachDevice = vboxDomainDetachDevice, /* 0.6.3 */ - .domainDetachDeviceFlags = vboxDomainDetachDeviceFlags, /* 0.7.7 */ - .domainUpdateDeviceFlags = vboxDomainUpdateDeviceFlags, /* 0.8.0 */ - .nodeGetCellsFreeMemory = vboxNodeGetCellsFreeMemory, /* 0.6.5 */ - .nodeGetFreeMemory = vboxNodeGetFreeMemory, /* 0.6.5 */ -#if VBOX_API_VERSION >= 4000000 - .domainScreenshot = vboxDomainScreenshot, /* 0.9.2 */ -#endif -#if VBOX_API_VERSION > 2002000 && VBOX_API_VERSION < 4000000 - .connectDomainEventRegister = vboxConnectDomainEventRegister, /* 0.7.0 */ - .connectDomainEventDeregister = vboxConnectDomainEventDeregister, /* 0.7.0 */ -#endif - .connectIsEncrypted = vboxConnectIsEncrypted, /* 0.7.3 */ - .connectIsSecure = vboxConnectIsSecure, /* 0.7.3 */ - .domainIsActive = vboxDomainIsActive, /* 0.7.3 */ - .domainIsPersistent = vboxDomainIsPersistent, /* 0.7.3 */ - .domainIsUpdated = vboxDomainIsUpdated, /* 0.8.6 */ -#if VBOX_API_VERSION > 2002000 && VBOX_API_VERSION < 4000000 - .connectDomainEventRegisterAny = vboxConnectDomainEventRegisterAny, /* 0.8.0 */ - .connectDomainEventDeregisterAny = vboxConnectDomainEventDeregisterAny, /* 0.8.0 */ -#endif - .domainSnapshotCreateXML = vboxDomainSnapshotCreateXML, /* 0.8.0 */ - .domainSnapshotGetXMLDesc = vboxDomainSnapshotGetXMLDesc, /* 0.8.0 */ - .domainSnapshotNum = vboxDomainSnapshotNum, /* 0.8.0 */ - .domainSnapshotListNames = vboxDomainSnapshotListNames, /* 0.8.0 */ - .domainSnapshotLookupByName = vboxDomainSnapshotLookupByName, /* 0.8.0 */ - .domainHasCurrentSnapshot = vboxDomainHasCurrentSnapshot, /* 0.8.0 */ - .domainSnapshotGetParent = vboxDomainSnapshotGetParent, /* 0.9.7 */ - .domainSnapshotCurrent = vboxDomainSnapshotCurrent, /* 0.8.0 */ - .domainSnapshotIsCurrent = vboxDomainSnapshotIsCurrent, /* 0.9.13 */ - .domainSnapshotHasMetadata = vboxDomainSnapshotHasMetadata, /* 0.9.13 */ - .domainRevertToSnapshot = vboxDomainRevertToSnapshot, /* 0.8.0 */ - .domainSnapshotDelete = vboxDomainSnapshotDelete, /* 0.8.0 */ - .connectIsAlive = vboxConnectIsAlive, /* 0.9.8 */ - .nodeGetFreePages = vboxNodeGetFreePages, /* 1.2.6 */ -}; - virNetworkDriver NAME(NetworkDriver) = { "VBOX", .networkOpen = vboxNetworkOpen, /* 0.6.4 */ diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index c0586c0..41ce40f 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -532,111 +532,8 @@ typedef struct { bool supportScreenshot; } 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); -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); -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); -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 vboxDomainUndefine(virDomainPtr dom); -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); -int vboxDomainIsPersistent(virDomainPtr dom); -int vboxDomainIsUpdated(virDomainPtr dom); -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); -int vboxDomainDestroyFlags(virDomainPtr dom, unsigned int flags); -int vboxDomainDestroy(virDomainPtr dom); -char *vboxDomainGetOSType(virDomainPtr dom); -int vboxDomainSetMemory(virDomainPtr dom, unsigned long memory); -int vboxDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info); -int vboxDomainGetState(virDomainPtr dom, int *state, - int *reason, unsigned int flags); -int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, - unsigned int flags); -int vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus); -int vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags); -int vboxDomainGetMaxVcpus(virDomainPtr dom); -char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags); -int vboxConnectListDefinedDomains(virConnectPtr conn, - char ** const names, int maxnames); -int vboxConnectNumOfDefinedDomains(virConnectPtr conn); -int vboxDomainAttachDevice(virDomainPtr dom, const char *xml); -int vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags); -int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags); -int vboxDomainDetachDevice(virDomainPtr dom, const char *xml); -int vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags); -virDomainSnapshotPtr -vboxDomainSnapshotCreateXML(virDomainPtr dom, - const char *xmlDesc, - unsigned int flags); -char *vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, - unsigned int flags); -int vboxDomainSnapshotNum(virDomainPtr dom, unsigned int flags); -int vboxDomainSnapshotListNames(virDomainPtr dom, char **names, - int nameslen, unsigned int flags); -virDomainSnapshotPtr -vboxDomainSnapshotLookupByName(virDomainPtr dom, const char *name, - unsigned int flags); -int vboxDomainHasCurrentSnapshot(virDomainPtr dom, unsigned int flags); -virDomainSnapshotPtr -vboxDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, - unsigned int flags); -virDomainSnapshotPtr -vboxDomainSnapshotCurrent(virDomainPtr dom, unsigned int flags); -int vboxDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, - unsigned int flags); -int vboxDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot, - unsigned int flags); -int vboxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, - unsigned int flags); -int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, - unsigned int flags); -char *vboxDomainScreenshot(virDomainPtr dom, virStreamPtr st, - unsigned int screen, unsigned int flags); -int vboxConnectListAllDomains(virConnectPtr conn, virDomainPtr **domains, - unsigned int flags); -int vboxNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo); -int vboxNodeGetCellsFreeMemory(virConnectPtr conn, - unsigned long long *freeMems, - int startCell, - int maxCells); -unsigned long long vboxNodeGetFreeMemory(virConnectPtr); -int vboxNodeGetFreePages(virConnectPtr conn, - unsigned int npages, - unsigned int *pages, - int startCell, - unsigned int cellCount, - unsigned long long *counts, - unsigned int flags); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5

On 11.08.2014 12:06, Taowei wrote:
This series of patches rewrite the vbox's domain driver. The driver is separated into two parts: the version specified and the common part. The common driver use vboxUniformedAPI to build a general driver for all vbox versions. The vboxUniformedAPI take the responsiblity to communicate with virtualbox. Since there are some incompatible changes in virtualbox, vboxUniformedAPI should be aware of these changes and provide a uniformed api for the upper layer.
The significant result of this patch is that we replace all vir${vbox_version}Driver into one virCommonDriver. So, we will have only one vbox driver implementation for all vbox versions in libvirt.
PS: I have send part of my patches before: https://www.redhat.com/archives/libvir-list/2014-July/msg00937.html But I have to resend it beacuse I did some improvement on previous patches: *Remove the test case for vboxUniformedAPI, because it would raise "break strict-aliasing rules" warning in some distibutions *Merged the flag fdWatchNeedInitialize into domainEventCallbacks, So, we use one flag to indicate whether vbox support callbacks as well as we need to initialize variables for it.
Taowei (66): vbox: Begin to rewrite, vboxConnectOpen 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 vbox: Rewrite vboxDomainDestroyFlags vbox: Rewrite vboxDomainDestroy vbox: Rewrite vboxDomainGetOSType vbox: Rewrite vboxDomainSetMemory vbox: Rewrite vboxDomainGetInfo vbox: Rewrite vboxDomainGetState vbox: Rewrite vboxDomainSetVcpusFlags vbox: Rewrite vboxDomainSetVcpus vbox: Rewrite vboxDomainGetVcpusFlags vbox: Rewrite vboxDomainGetMaxVcpus vbox: Add API for vboxDomainGetXMLDesc vbox: Rewrite vboxDomainGetXMLDesc vbox: Rewrite vboxConnectListDefinedDomains vbox: Rewrite vboxConnectNumOfDefinedDomains vbox: Rewrite vboxDomainUndefine vbox: Rewrite vboxDomainAttachDevice vbox: Rewrite vboxDomainAttachDeviceFlags vbox: Rewrite vboxDomainUpdateDeviceFlags vbox: Rewrite vboxDomainDetachDevice vbox: Rewrite vboxDomainDetachDeviceFlags vbox: Add API for vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotGetXMLDesc vbox: Rewrite vboxDomainSnapshotNum vbox: Rewrite vboxDomainSnapshotListNames vbox: Rewrite vboxSnapshotLookupByName vbox: Rewrite vboxDomainHasCurrentSnapshot vbox: Rewrite vboxDomainSnapshotGetParent vbox: Rewrite vboxDomainSnapshotCurrent vbox: Rewrite vboxDomainSnapshotIsCurrent vbox: Rewrite vboxDomainSnapshotHasMetadata vbox: Rewrite vboxDomainRevertToSnapshot vbox: Rewrite vboxDomainSnapshotDelete vbox: Rewrite vboxDomainScreenshot vbox: Rewrite vboxConnectListAllDomains vbox: Rewrite vboxNode functions vbox: Add registerDomainEvent vbox: Introducing vboxCommonDriver
po/POTFILES.in | 1 + src/Makefile.am | 5 +- src/vbox/README | 7 +- src/vbox/vbox_common.c | 7550 +++++++++++++++++++++ src/vbox/vbox_common.h | 306 + src/vbox/vbox_driver.c | 40 +- src/vbox/vbox_install_api.h | 26 + src/vbox/vbox_tmpl.c |14557 +++++++++++++---------------------------- src/vbox/vbox_uniformed_api.h | 551 ++ 9 files changed, 13186 insertions(+), 9857 deletions(-) create mode 100644 src/vbox/vbox_common.c create mode 100644 src/vbox/vbox_common.h create mode 100644 src/vbox/vbox_install_api.h create mode 100644 src/vbox/vbox_uniformed_api.h
ACK to all the patches. I've fixed all the small nits I found. I'm keeping the patches on my private branch for some time to give others time to share their opinions. Nevertheless, incredible work in making the vbox driver look more sane what you've done! Michal

Thank you, Michal. This could never been done without your help! Taowei
在 2014年8月12日,23:31,Michal Privoznik <mprivozn@redhat.com> 写道:
On 11.08.2014 12:06, Taowei wrote: This series of patches rewrite the vbox's domain driver. The driver is separated into two parts: the version specified and the common part. The common driver use vboxUniformedAPI to build a general driver for all vbox versions. The vboxUniformedAPI take the responsiblity to communicate with virtualbox. Since there are some incompatible changes in virtualbox, vboxUniformedAPI should be aware of these changes and provide a uniformed api for the upper layer.
The significant result of this patch is that we replace all vir${vbox_version}Driver into one virCommonDriver. So, we will have only one vbox driver implementation for all vbox versions in libvirt.
PS: I have send part of my patches before: https://www.redhat.com/archives/libvir-list/2014-July/msg00937.html But I have to resend it beacuse I did some improvement on previous patches: *Remove the test case for vboxUniformedAPI, because it would raise "break strict-aliasing rules" warning in some distibutions *Merged the flag fdWatchNeedInitialize into domainEventCallbacks, So, we use one flag to indicate whether vbox support callbacks as well as we need to initialize variables for it.
Taowei (66): vbox: Begin to rewrite, vboxConnectOpen 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 vbox: Rewrite vboxDomainDestroyFlags vbox: Rewrite vboxDomainDestroy vbox: Rewrite vboxDomainGetOSType vbox: Rewrite vboxDomainSetMemory vbox: Rewrite vboxDomainGetInfo vbox: Rewrite vboxDomainGetState vbox: Rewrite vboxDomainSetVcpusFlags vbox: Rewrite vboxDomainSetVcpus vbox: Rewrite vboxDomainGetVcpusFlags vbox: Rewrite vboxDomainGetMaxVcpus vbox: Add API for vboxDomainGetXMLDesc vbox: Rewrite vboxDomainGetXMLDesc vbox: Rewrite vboxConnectListDefinedDomains vbox: Rewrite vboxConnectNumOfDefinedDomains vbox: Rewrite vboxDomainUndefine vbox: Rewrite vboxDomainAttachDevice vbox: Rewrite vboxDomainAttachDeviceFlags vbox: Rewrite vboxDomainUpdateDeviceFlags vbox: Rewrite vboxDomainDetachDevice vbox: Rewrite vboxDomainDetachDeviceFlags vbox: Add API for vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotGetXMLDesc vbox: Rewrite vboxDomainSnapshotNum vbox: Rewrite vboxDomainSnapshotListNames vbox: Rewrite vboxSnapshotLookupByName vbox: Rewrite vboxDomainHasCurrentSnapshot vbox: Rewrite vboxDomainSnapshotGetParent vbox: Rewrite vboxDomainSnapshotCurrent vbox: Rewrite vboxDomainSnapshotIsCurrent vbox: Rewrite vboxDomainSnapshotHasMetadata vbox: Rewrite vboxDomainRevertToSnapshot vbox: Rewrite vboxDomainSnapshotDelete vbox: Rewrite vboxDomainScreenshot vbox: Rewrite vboxConnectListAllDomains vbox: Rewrite vboxNode functions vbox: Add registerDomainEvent vbox: Introducing vboxCommonDriver
po/POTFILES.in | 1 + src/Makefile.am | 5 +- src/vbox/README | 7 +- src/vbox/vbox_common.c | 7550 +++++++++++++++++++++ src/vbox/vbox_common.h | 306 + src/vbox/vbox_driver.c | 40 +- src/vbox/vbox_install_api.h | 26 + src/vbox/vbox_tmpl.c |14557 +++++++++++++---------------------------- src/vbox/vbox_uniformed_api.h | 551 ++ 9 files changed, 13186 insertions(+), 9857 deletions(-) create mode 100644 src/vbox/vbox_common.c create mode 100644 src/vbox/vbox_common.h create mode 100644 src/vbox/vbox_install_api.h create mode 100644 src/vbox/vbox_uniformed_api.h
ACK to all the patches. I've fixed all the small nits I found. I'm keeping the patches on my private branch for some time to give others time to share their opinions. Nevertheless, incredible work in making the vbox driver look more sane what you've done!
Michal

[CC-ing Yohan BELLEGUIC and Manuel VIVES] On 12.08.2014 17:31, Michal Privoznik wrote:
On 11.08.2014 12:06, Taowei wrote:
This series of patches rewrite the vbox's domain driver. The driver is separated into two parts: the version specified and the common part. The common driver use vboxUniformedAPI to build a general driver for all vbox versions. The vboxUniformedAPI take the responsiblity to communicate with virtualbox. Since there are some incompatible changes in virtualbox, vboxUniformedAPI should be aware of these changes and provide a uniformed api for the upper layer.
The significant result of this patch is that we replace all vir${vbox_version}Driver into one virCommonDriver. So, we will have only one vbox driver implementation for all vbox versions in libvirt.
PS: I have send part of my patches before: https://www.redhat.com/archives/libvir-list/2014-July/msg00937.html But I have to resend it beacuse I did some improvement on previous patches: *Remove the test case for vboxUniformedAPI, because it would raise "break strict-aliasing rules" warning in some distibutions *Merged the flag fdWatchNeedInitialize into domainEventCallbacks, So, we use one flag to indicate whether vbox support callbacks as well as we need to initialize variables for it.
Taowei (66): vbox: Begin to rewrite, vboxConnectOpen 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 vbox: Rewrite vboxDomainDestroyFlags vbox: Rewrite vboxDomainDestroy vbox: Rewrite vboxDomainGetOSType vbox: Rewrite vboxDomainSetMemory vbox: Rewrite vboxDomainGetInfo vbox: Rewrite vboxDomainGetState vbox: Rewrite vboxDomainSetVcpusFlags vbox: Rewrite vboxDomainSetVcpus vbox: Rewrite vboxDomainGetVcpusFlags vbox: Rewrite vboxDomainGetMaxVcpus vbox: Add API for vboxDomainGetXMLDesc vbox: Rewrite vboxDomainGetXMLDesc vbox: Rewrite vboxConnectListDefinedDomains vbox: Rewrite vboxConnectNumOfDefinedDomains vbox: Rewrite vboxDomainUndefine vbox: Rewrite vboxDomainAttachDevice vbox: Rewrite vboxDomainAttachDeviceFlags vbox: Rewrite vboxDomainUpdateDeviceFlags vbox: Rewrite vboxDomainDetachDevice vbox: Rewrite vboxDomainDetachDeviceFlags vbox: Add API for vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotGetXMLDesc vbox: Rewrite vboxDomainSnapshotNum vbox: Rewrite vboxDomainSnapshotListNames vbox: Rewrite vboxSnapshotLookupByName vbox: Rewrite vboxDomainHasCurrentSnapshot vbox: Rewrite vboxDomainSnapshotGetParent vbox: Rewrite vboxDomainSnapshotCurrent vbox: Rewrite vboxDomainSnapshotIsCurrent vbox: Rewrite vboxDomainSnapshotHasMetadata vbox: Rewrite vboxDomainRevertToSnapshot vbox: Rewrite vboxDomainSnapshotDelete vbox: Rewrite vboxDomainScreenshot vbox: Rewrite vboxConnectListAllDomains vbox: Rewrite vboxNode functions vbox: Add registerDomainEvent vbox: Introducing vboxCommonDriver
po/POTFILES.in | 1 + src/Makefile.am | 5 +- src/vbox/README | 7 +- src/vbox/vbox_common.c | 7550 +++++++++++++++++++++ src/vbox/vbox_common.h | 306 + src/vbox/vbox_driver.c | 40 +- src/vbox/vbox_install_api.h | 26 + src/vbox/vbox_tmpl.c |14557 +++++++++++++---------------------------- src/vbox/vbox_uniformed_api.h | 551 ++ 9 files changed, 13186 insertions(+), 9857 deletions(-) create mode 100644 src/vbox/vbox_common.c create mode 100644 src/vbox/vbox_common.h create mode 100644 src/vbox/vbox_install_api.h create mode 100644 src/vbox/vbox_uniformed_api.h
ACK to all the patches. I've fixed all the small nits I found. I'm keeping the patches on my private branch for some time to give others time to share their opinions. Nevertheless, incredible work in making the vbox driver look more sane what you've done!
Yohan and Manuel, can you guys please give this patchset a test? You seem to be interested in our virtual box driver (esp. snapshots) and we won't be happy if we break something by merging the patches. I haven't spotted anything wrong in the patches, so I gave my ACK but I'll postpone the push for a while to give you chance to try them out. Michal

Le Wednesday 13 August 2014 17:18:44, Michal Privoznik a écrit :
[CC-ing Yohan BELLEGUIC and Manuel VIVES]
On 12.08.2014 17:31, Michal Privoznik wrote:
On 11.08.2014 12:06, Taowei wrote:
This series of patches rewrite the vbox's domain driver. The driver is separated into two parts: the version specified and the common part. The common driver use vboxUniformedAPI to build a general driver for all vbox versions. The vboxUniformedAPI take the responsiblity to communicate with virtualbox. Since there are some incompatible changes in virtualbox, vboxUniformedAPI should be aware of these changes and provide a uniformed api for the upper layer.
The significant result of this patch is that we replace all vir${vbox_version}Driver into one virCommonDriver. So, we will have only one vbox driver implementation for all vbox versions in libvirt.
PS: I have send part of my patches before: https://www.redhat.com/archives/libvir-list/2014-July/msg00937.html But I have to resend it beacuse I did some improvement on previous patches: *Remove the test case for vboxUniformedAPI, because it would raise
"break strict-aliasing rules" warning in some distibutions
*Merged the flag fdWatchNeedInitialize into domainEventCallbacks,
So, we use one flag to indicate whether vbox support callbacks as well as we need to initialize variables for it.
Taowei (66): vbox: Begin to rewrite, vboxConnectOpen 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 vbox: Rewrite vboxDomainDestroyFlags vbox: Rewrite vboxDomainDestroy vbox: Rewrite vboxDomainGetOSType vbox: Rewrite vboxDomainSetMemory vbox: Rewrite vboxDomainGetInfo vbox: Rewrite vboxDomainGetState vbox: Rewrite vboxDomainSetVcpusFlags vbox: Rewrite vboxDomainSetVcpus vbox: Rewrite vboxDomainGetVcpusFlags vbox: Rewrite vboxDomainGetMaxVcpus vbox: Add API for vboxDomainGetXMLDesc vbox: Rewrite vboxDomainGetXMLDesc vbox: Rewrite vboxConnectListDefinedDomains vbox: Rewrite vboxConnectNumOfDefinedDomains vbox: Rewrite vboxDomainUndefine vbox: Rewrite vboxDomainAttachDevice vbox: Rewrite vboxDomainAttachDeviceFlags vbox: Rewrite vboxDomainUpdateDeviceFlags vbox: Rewrite vboxDomainDetachDevice vbox: Rewrite vboxDomainDetachDeviceFlags vbox: Add API for vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotGetXMLDesc vbox: Rewrite vboxDomainSnapshotNum vbox: Rewrite vboxDomainSnapshotListNames vbox: Rewrite vboxSnapshotLookupByName vbox: Rewrite vboxDomainHasCurrentSnapshot vbox: Rewrite vboxDomainSnapshotGetParent vbox: Rewrite vboxDomainSnapshotCurrent vbox: Rewrite vboxDomainSnapshotIsCurrent vbox: Rewrite vboxDomainSnapshotHasMetadata vbox: Rewrite vboxDomainRevertToSnapshot vbox: Rewrite vboxDomainSnapshotDelete vbox: Rewrite vboxDomainScreenshot vbox: Rewrite vboxConnectListAllDomains vbox: Rewrite vboxNode functions vbox: Add registerDomainEvent vbox: Introducing vboxCommonDriver
po/POTFILES.in | 1 + src/Makefile.am | 5 +- src/vbox/README | 7 +- src/vbox/vbox_common.c | 7550 +++++++++++++++++++++ src/vbox/vbox_common.h | 306 + src/vbox/vbox_driver.c | 40 +- src/vbox/vbox_install_api.h | 26 + src/vbox/vbox_tmpl.c |14557
+++++++++++++----------------------------
src/vbox/vbox_uniformed_api.h | 551 ++ 9 files changed, 13186 insertions(+), 9857 deletions(-) create mode 100644 src/vbox/vbox_common.c create mode 100644 src/vbox/vbox_common.h create mode 100644 src/vbox/vbox_install_api.h create mode 100644 src/vbox/vbox_uniformed_api.h
ACK to all the patches. I've fixed all the small nits I found. I'm keeping the patches on my private branch for some time to give others time to share their opinions. Nevertheless, incredible work in making the vbox driver look more sane what you've done!
Yohan and Manuel,
can you guys please give this patchset a test? You seem to be interested in our virtual box driver (esp. snapshots) and we won't be happy if we break something by merging the patches. I haven't spotted anything wrong in the patches, so I gave my ACK but I'll postpone the push for a while to give you chance to try them out.
Michal
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Hello, Everything seems good to me, I didn't see any apparent problem. We will not update immediately libvirt, so we won't be able to thoroughly test the vbox driver. Regards -- Yohan BELLEGUIC Software Engineer - diateam : Architectes de l'information Phone : +33 (0)2 98 050 050 Fax : +33 (0)2 98 050 05

On Thu, Aug 14, 2014 at 05:50:18PM +0200, Yohan Belleguic wrote:
Le Wednesday 13 August 2014 17:18:44, Michal Privoznik a écrit :
[CC-ing Yohan BELLEGUIC and Manuel VIVES]
On 12.08.2014 17:31, Michal Privoznik wrote:
On 11.08.2014 12:06, Taowei wrote:
This series of patches rewrite the vbox's domain driver. The driver is separated into two parts: the version specified and the common part. The common driver use vboxUniformedAPI to build a general driver for all vbox versions. The vboxUniformedAPI take the responsiblity to communicate with virtualbox. Since there are some incompatible changes in virtualbox, vboxUniformedAPI should be aware of these changes and provide a uniformed api for the upper layer.
The significant result of this patch is that we replace all vir${vbox_version}Driver into one virCommonDriver. So, we will have only one vbox driver implementation for all vbox versions in libvirt.
PS: I have send part of my patches before: https://www.redhat.com/archives/libvir-list/2014-July/msg00937.html But I have to resend it beacuse I did some improvement on previous patches: *Remove the test case for vboxUniformedAPI, because it would raise
"break strict-aliasing rules" warning in some distibutions
*Merged the flag fdWatchNeedInitialize into domainEventCallbacks,
So, we use one flag to indicate whether vbox support callbacks as well as we need to initialize variables for it.
Taowei (66): vbox: Begin to rewrite, vboxConnectOpen 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 vbox: Rewrite vboxDomainDestroyFlags vbox: Rewrite vboxDomainDestroy vbox: Rewrite vboxDomainGetOSType vbox: Rewrite vboxDomainSetMemory vbox: Rewrite vboxDomainGetInfo vbox: Rewrite vboxDomainGetState vbox: Rewrite vboxDomainSetVcpusFlags vbox: Rewrite vboxDomainSetVcpus vbox: Rewrite vboxDomainGetVcpusFlags vbox: Rewrite vboxDomainGetMaxVcpus vbox: Add API for vboxDomainGetXMLDesc vbox: Rewrite vboxDomainGetXMLDesc vbox: Rewrite vboxConnectListDefinedDomains vbox: Rewrite vboxConnectNumOfDefinedDomains vbox: Rewrite vboxDomainUndefine vbox: Rewrite vboxDomainAttachDevice vbox: Rewrite vboxDomainAttachDeviceFlags vbox: Rewrite vboxDomainUpdateDeviceFlags vbox: Rewrite vboxDomainDetachDevice vbox: Rewrite vboxDomainDetachDeviceFlags vbox: Add API for vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotGetXMLDesc vbox: Rewrite vboxDomainSnapshotNum vbox: Rewrite vboxDomainSnapshotListNames vbox: Rewrite vboxSnapshotLookupByName vbox: Rewrite vboxDomainHasCurrentSnapshot vbox: Rewrite vboxDomainSnapshotGetParent vbox: Rewrite vboxDomainSnapshotCurrent vbox: Rewrite vboxDomainSnapshotIsCurrent vbox: Rewrite vboxDomainSnapshotHasMetadata vbox: Rewrite vboxDomainRevertToSnapshot vbox: Rewrite vboxDomainSnapshotDelete vbox: Rewrite vboxDomainScreenshot vbox: Rewrite vboxConnectListAllDomains vbox: Rewrite vboxNode functions vbox: Add registerDomainEvent vbox: Introducing vboxCommonDriver
po/POTFILES.in | 1 + src/Makefile.am | 5 +- src/vbox/README | 7 +- src/vbox/vbox_common.c | 7550 +++++++++++++++++++++ src/vbox/vbox_common.h | 306 + src/vbox/vbox_driver.c | 40 +- src/vbox/vbox_install_api.h | 26 + src/vbox/vbox_tmpl.c |14557
+++++++++++++----------------------------
src/vbox/vbox_uniformed_api.h | 551 ++ 9 files changed, 13186 insertions(+), 9857 deletions(-) create mode 100644 src/vbox/vbox_common.c create mode 100644 src/vbox/vbox_common.h create mode 100644 src/vbox/vbox_install_api.h create mode 100644 src/vbox/vbox_uniformed_api.h
ACK to all the patches. I've fixed all the small nits I found. I'm keeping the patches on my private branch for some time to give others time to share their opinions. Nevertheless, incredible work in making the vbox driver look more sane what you've done!
Yohan and Manuel,
can you guys please give this patchset a test? You seem to be interested in our virtual box driver (esp. snapshots) and we won't be happy if we break something by merging the patches. I haven't spotted anything wrong in the patches, so I gave my ACK but I'll postpone the push for a while to give you chance to try them out.
Everything seems good to me, I didn't see any apparent problem. We will not update immediately libvirt, so we won't be able to thoroughly test the vbox driver.
Ok, thanks for the feedback. We just wanted to make sure your team don't have any significant objections to this patch series before we went ahead and merged it :-) Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 14.08.2014 17:50, Yohan Belleguic wrote:
Le Wednesday 13 August 2014 17:18:44, Michal Privoznik a écrit :
[CC-ing Yohan BELLEGUIC and Manuel VIVES]
On 12.08.2014 17:31, Michal Privoznik wrote:
On 11.08.2014 12:06, Taowei wrote:
This series of patches rewrite the vbox's domain driver. The driver is separated into two parts: the version specified and the common part. The common driver use vboxUniformedAPI to build a general driver for all vbox versions. The vboxUniformedAPI take the responsiblity to communicate with virtualbox. Since there are some incompatible changes in virtualbox, vboxUniformedAPI should be aware of these changes and provide a uniformed api for the upper layer.
The significant result of this patch is that we replace all vir${vbox_version}Driver into one virCommonDriver. So, we will have only one vbox driver implementation for all vbox versions in libvirt.
PS: I have send part of my patches before: https://www.redhat.com/archives/libvir-list/2014-July/msg00937.html But I have to resend it beacuse I did some improvement on previous patches: *Remove the test case for vboxUniformedAPI, because it would raise
"break strict-aliasing rules" warning in some distibutions
*Merged the flag fdWatchNeedInitialize into domainEventCallbacks,
So, we use one flag to indicate whether vbox support callbacks as well as we need to initialize variables for it.
Taowei (66): vbox: Begin to rewrite, vboxConnectOpen 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 vbox: Rewrite vboxDomainDestroyFlags vbox: Rewrite vboxDomainDestroy vbox: Rewrite vboxDomainGetOSType vbox: Rewrite vboxDomainSetMemory vbox: Rewrite vboxDomainGetInfo vbox: Rewrite vboxDomainGetState vbox: Rewrite vboxDomainSetVcpusFlags vbox: Rewrite vboxDomainSetVcpus vbox: Rewrite vboxDomainGetVcpusFlags vbox: Rewrite vboxDomainGetMaxVcpus vbox: Add API for vboxDomainGetXMLDesc vbox: Rewrite vboxDomainGetXMLDesc vbox: Rewrite vboxConnectListDefinedDomains vbox: Rewrite vboxConnectNumOfDefinedDomains vbox: Rewrite vboxDomainUndefine vbox: Rewrite vboxDomainAttachDevice vbox: Rewrite vboxDomainAttachDeviceFlags vbox: Rewrite vboxDomainUpdateDeviceFlags vbox: Rewrite vboxDomainDetachDevice vbox: Rewrite vboxDomainDetachDeviceFlags vbox: Add API for vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotGetXMLDesc vbox: Rewrite vboxDomainSnapshotNum vbox: Rewrite vboxDomainSnapshotListNames vbox: Rewrite vboxSnapshotLookupByName vbox: Rewrite vboxDomainHasCurrentSnapshot vbox: Rewrite vboxDomainSnapshotGetParent vbox: Rewrite vboxDomainSnapshotCurrent vbox: Rewrite vboxDomainSnapshotIsCurrent vbox: Rewrite vboxDomainSnapshotHasMetadata vbox: Rewrite vboxDomainRevertToSnapshot vbox: Rewrite vboxDomainSnapshotDelete vbox: Rewrite vboxDomainScreenshot vbox: Rewrite vboxConnectListAllDomains vbox: Rewrite vboxNode functions vbox: Add registerDomainEvent vbox: Introducing vboxCommonDriver
po/POTFILES.in | 1 + src/Makefile.am | 5 +- src/vbox/README | 7 +- src/vbox/vbox_common.c | 7550 +++++++++++++++++++++ src/vbox/vbox_common.h | 306 + src/vbox/vbox_driver.c | 40 +- src/vbox/vbox_install_api.h | 26 + src/vbox/vbox_tmpl.c |14557
+++++++++++++----------------------------
src/vbox/vbox_uniformed_api.h | 551 ++ 9 files changed, 13186 insertions(+), 9857 deletions(-) create mode 100644 src/vbox/vbox_common.c create mode 100644 src/vbox/vbox_common.h create mode 100644 src/vbox/vbox_install_api.h create mode 100644 src/vbox/vbox_uniformed_api.h
ACK to all the patches. I've fixed all the small nits I found. I'm keeping the patches on my private branch for some time to give others time to share their opinions. Nevertheless, incredible work in making the vbox driver look more sane what you've done!
Yohan and Manuel,
can you guys please give this patchset a test? You seem to be interested in our virtual box driver (esp. snapshots) and we won't be happy if we break something by merging the patches. I haven't spotted anything wrong in the patches, so I gave my ACK but I'll postpone the push for a while to give you chance to try them out.
Michal
Hello,
Everything seems good to me, I didn't see any apparent problem. We will not update immediately libvirt, so we won't be able to thoroughly test the vbox driver.
Regards
Perfect! So I've merged this. Thanks to Taowei for taking the effort and turning spaghetti code into something more readable. Michal
participants (5)
-
Daniel P. Berrange
-
Michal Privoznik
-
taowei
-
Taowei
-
Yohan Belleguic