2 * Template File to support multiple versions of VirtualBox
6 * Please dont include this file in the src/Makefile.am, it
7 * is automatically include by other files.
11 * Copyright (C) 2010-2014 Red Hat, Inc.
12 * Copyright (C) 2008-2009 Sun Microsystems, Inc.
14 * This file is part of a free software library; you can redistribute
15 * it and/or modify it under the terms of the GNU Lesser General
16 * Public License version 2.1 as published by the Free Software
17 * Foundation and shipped in the "COPYING.LESSER" file with this library.
18 * The library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY of any kind.
21 * Sun LGPL Disclaimer: For the avoidance of doubt, except that if
22 * any license choice other than GPL or LGPL is available it will
23 * apply instead, Sun elects to use only the Lesser General Public
24 * License version 2.1 (LGPLv2) at this time for any software where
25 * a choice of LGPL license versions is made available with the
26 * language indicating that LGPLv2 or any later version may be used,
27 * or where a choice of which version of the LGPL is applied is
28 * otherwise unspecified.
30 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
31 * Clara, CA 95054 USA or visit http://www.sun.com if you need
32 * additional information or have any questions.
38 #include <sys/types.h>
43 #include "datatypes.h"
44 #include "domain_conf.h"
45 #include "snapshot_conf.h"
46 #include "network_conf.h"
48 #include "domain_event.h"
49 #include "storage_conf.h"
50 #include "virstoragefile.h"
55 #include "vbox_driver.h"
56 #include "configmake.h"
60 #include "virstring.h"
62 /* This one changes from version to version. */
63 #if VBOX_API_VERSION == 2002000
64 # include "vbox_CAPI_v2_2.h"
65 #elif VBOX_API_VERSION == 3000000
66 # include "vbox_CAPI_v3_0.h"
67 #elif VBOX_API_VERSION == 3001000
68 # include "vbox_CAPI_v3_1.h"
69 #elif VBOX_API_VERSION == 3002000
70 # include "vbox_CAPI_v3_2.h"
71 #elif VBOX_API_VERSION == 4000000
72 # include "vbox_CAPI_v4_0.h"
73 #elif VBOX_API_VERSION == 4001000
74 # include "vbox_CAPI_v4_1.h"
75 #elif VBOX_API_VERSION == 4002000
76 # include "vbox_CAPI_v4_2.h"
77 #elif VBOX_API_VERSION == 4002020
78 # include "vbox_CAPI_v4_2_20.h"
79 #elif VBOX_API_VERSION == 4003000
80 # include "vbox_CAPI_v4_3.h"
81 #elif VBOX_API_VERSION == 4003004
82 # include "vbox_CAPI_v4_3_4.h"
84 # error "Unsupport VBOX_API_VERSION"
87 /* Include this *last* or we'll get the wrong vbox_CAPI_*.h. */
88 #include "vbox_glue.h"
91 #define VIR_FROM_THIS VIR_FROM_VBOX
93 VIR_LOG_INIT("vbox.vbox_tmpl");
95 #define VBOX_UTF16_FREE(arg) \
98 data->pFuncs->pfnUtf16Free(arg); \
103 #define VBOX_UTF8_FREE(arg) \
106 data->pFuncs->pfnUtf8Free(arg); \
111 #define VBOX_COM_UNALLOC_MEM(arg) \
114 data->pFuncs->pfnComUnallocMem(arg); \
119 #define VBOX_UTF16_TO_UTF8(arg1, arg2) data->pFuncs->pfnUtf16ToUtf8(arg1, arg2)
120 #define VBOX_UTF8_TO_UTF16(arg1, arg2) data->pFuncs->pfnUtf8ToUtf16(arg1, arg2)
122 #define VBOX_ADDREF(arg) (arg)->vtbl->nsisupports.AddRef((nsISupports *)(arg))
124 #define VBOX_RELEASE(arg) \
127 (arg)->vtbl->nsisupports.Release((nsISupports *)(arg)); \
132 #define VBOX_OBJECT_CHECK(conn, type, value) \
133 vboxGlobalData *data = conn->privateData;\
135 if (!data->vboxObj) {\
139 #define VBOX_OBJECT_HOST_CHECK(conn, type, value) \
140 vboxGlobalData *data = conn->privateData;\
143 if (!data->vboxObj) {\
146 data->vboxObj->vtbl->GetHost(data->vboxObj, &host);\
151 #if VBOX_API_VERSION < 3001000
153 # define VBOX_MEDIUM_RELEASE(arg) \
155 (arg)->vtbl->imedium.nsisupports.Release((nsISupports *)(arg))
156 # define VBOX_MEDIUM_FUNC_ARG1(object, func, arg1) \
157 (object)->vtbl->imedium.func((IMedium *)(object), arg1)
158 # define VBOX_MEDIUM_FUNC_ARG2(object, func, arg1, arg2) \
159 (object)->vtbl->imedium.func((IMedium *)(object), arg1, arg2)
161 #else /* VBOX_API_VERSION >= 3001000 */
163 typedef IMedium IHardDisk;
164 typedef IMediumAttachment IHardDiskAttachment;
165 # define MediaState_Inaccessible MediumState_Inaccessible
166 # define HardDiskVariant_Standard MediumVariant_Standard
167 # define HardDiskVariant_Fixed MediumVariant_Fixed
168 # define VBOX_MEDIUM_RELEASE(arg) VBOX_RELEASE(arg)
169 # define VBOX_MEDIUM_FUNC_ARG1(object, func, arg1) \
170 (object)->vtbl->func(object, arg1)
171 # define VBOX_MEDIUM_FUNC_ARG2(object, func, arg1, arg2) \
172 (object)->vtbl->func(object, arg1, arg2)
174 #endif /* VBOX_API_VERSION >= 3001000 */
176 #define DEBUGPRUnichar(msg, strUtf16) \
178 char *strUtf8 = NULL;\
180 g_pVBoxGlobalData->pFuncs->pfnUtf16ToUtf8(strUtf16, &strUtf8);\
182 VIR_DEBUG("%s: %s", msg, strUtf8);\
183 g_pVBoxGlobalData->pFuncs->pfnUtf8Free(strUtf8);\
187 #define DEBUGUUID(msg, iid) \
189 VIR_DEBUG(msg ": {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",\
190 (unsigned)(iid)->m0,\
191 (unsigned)(iid)->m1,\
192 (unsigned)(iid)->m2,\
193 (unsigned)(iid)->m3[0],\
194 (unsigned)(iid)->m3[1],\
195 (unsigned)(iid)->m3[2],\
196 (unsigned)(iid)->m3[3],\
197 (unsigned)(iid)->m3[4],\
198 (unsigned)(iid)->m3[5],\
199 (unsigned)(iid)->m3[6],\
200 (unsigned)(iid)->m3[7]);\
205 unsigned long version;
208 virDomainXMLOptionPtr xmlopt;
210 IVirtualBox *vboxObj;
211 ISession *vboxSession;
213 /** Our version specific API table pointer. */
216 #if VBOX_API_VERSION == 2002000
220 #else /* !(VBOX_API_VERSION == 2002000) */
222 /* Async event handling */
223 virObjectEventStatePtr domainEvents;
226 # if VBOX_API_VERSION <= 3002000
227 /* IVirtualBoxCallback is used in VirtualBox 3.x only */
228 IVirtualBoxCallback *vboxCallback;
229 # endif /* VBOX_API_VERSION <= 3002000 */
231 nsIEventQueue *vboxQueue;
232 int volatile vboxCallBackRefCount;
234 /* pointer back to the connection */
239 /* g_pVBoxGlobalData has to be global variable,
240 * there is no other way to make the callbacks
241 * work other then having g_pVBoxGlobalData as
242 * global, because the functions namely AddRef,
243 * Release, etc consider it as global and you
244 * can't change the function definition as it
245 * is XPCOM nsISupport::* function and it expects
249 static vboxGlobalData *g_pVBoxGlobalData = NULL;
251 #endif /* !(VBOX_API_VERSION == 2002000) */
253 #if VBOX_API_VERSION < 4000000
255 # define VBOX_OBJECT_GET_MACHINE(/* in */ iid_value, /* out */ machine) \
256 data->vboxObj->vtbl->GetMachine(data->vboxObj, iid_value, machine)
258 # define VBOX_SESSION_OPEN(/* in */ iid_value, /* unused */ machine) \
259 data->vboxObj->vtbl->OpenSession(data->vboxObj, data->vboxSession, iid_value)
261 # define VBOX_SESSION_OPEN_EXISTING(/* in */ iid_value, /* unused */ machine) \
262 data->vboxObj->vtbl->OpenExistingSession(data->vboxObj, data->vboxSession, iid_value)
264 # define VBOX_SESSION_CLOSE() \
265 data->vboxSession->vtbl->Close(data->vboxSession)
267 #else /* VBOX_API_VERSION >= 4000000 */
269 # define VBOX_OBJECT_GET_MACHINE(/* in */ iid_value, /* out */ machine) \
270 data->vboxObj->vtbl->FindMachine(data->vboxObj, iid_value, machine)
272 # define VBOX_SESSION_OPEN(/* unused */ iid_value, /* in */ machine) \
273 machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Write)
275 # define VBOX_SESSION_OPEN_EXISTING(/* unused */ iid_value, /* in */ machine) \
276 machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Shared)
278 # define VBOX_SESSION_CLOSE() \
279 data->vboxSession->vtbl->UnlockMachine(data->vboxSession)
281 #endif /* VBOX_API_VERSION >= 4000000 */
283 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
284 static int vboxDomainCreate(virDomainPtr dom);
285 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
287 static void vboxDriverLock(vboxGlobalData *data)
289 virMutexLock(&data->lock);
292 static void vboxDriverUnlock(vboxGlobalData *data)
294 virMutexUnlock(&data->lock);
297 #if VBOX_API_VERSION == 2002000
299 static void nsIDtoChar(unsigned char *uuid, const nsID *iid)
301 char uuidstrsrc[VIR_UUID_STRING_BUFLEN];
302 char uuidstrdst[VIR_UUID_STRING_BUFLEN];
303 unsigned char uuidinterim[VIR_UUID_BUFLEN];
306 memcpy(uuidinterim, iid, VIR_UUID_BUFLEN);
307 virUUIDFormat(uuidinterim, uuidstrsrc);
309 uuidstrdst[0] = uuidstrsrc[6];
310 uuidstrdst[1] = uuidstrsrc[7];
311 uuidstrdst[2] = uuidstrsrc[4];
312 uuidstrdst[3] = uuidstrsrc[5];
313 uuidstrdst[4] = uuidstrsrc[2];
314 uuidstrdst[5] = uuidstrsrc[3];
315 uuidstrdst[6] = uuidstrsrc[0];
316 uuidstrdst[7] = uuidstrsrc[1];
318 uuidstrdst[8] = uuidstrsrc[8];
320 uuidstrdst[9] = uuidstrsrc[11];
321 uuidstrdst[10] = uuidstrsrc[12];
322 uuidstrdst[11] = uuidstrsrc[9];
323 uuidstrdst[12] = uuidstrsrc[10];
325 uuidstrdst[13] = uuidstrsrc[13];
327 uuidstrdst[14] = uuidstrsrc[16];
328 uuidstrdst[15] = uuidstrsrc[17];
329 uuidstrdst[16] = uuidstrsrc[14];
330 uuidstrdst[17] = uuidstrsrc[15];
332 for (i = 18; i < VIR_UUID_STRING_BUFLEN; i++) {
333 uuidstrdst[i] = uuidstrsrc[i];
336 uuidstrdst[VIR_UUID_STRING_BUFLEN-1] = '\0';
337 ignore_value(virUUIDParse(uuidstrdst, uuid));
340 static void nsIDFromChar(nsID *iid, const unsigned char *uuid)
342 char uuidstrsrc[VIR_UUID_STRING_BUFLEN];
343 char uuidstrdst[VIR_UUID_STRING_BUFLEN];
344 unsigned char uuidinterim[VIR_UUID_BUFLEN];
347 virUUIDFormat(uuid, uuidstrsrc);
349 uuidstrdst[0] = uuidstrsrc[6];
350 uuidstrdst[1] = uuidstrsrc[7];
351 uuidstrdst[2] = uuidstrsrc[4];
352 uuidstrdst[3] = uuidstrsrc[5];
353 uuidstrdst[4] = uuidstrsrc[2];
354 uuidstrdst[5] = uuidstrsrc[3];
355 uuidstrdst[6] = uuidstrsrc[0];
356 uuidstrdst[7] = uuidstrsrc[1];
358 uuidstrdst[8] = uuidstrsrc[8];
360 uuidstrdst[9] = uuidstrsrc[11];
361 uuidstrdst[10] = uuidstrsrc[12];
362 uuidstrdst[11] = uuidstrsrc[9];
363 uuidstrdst[12] = uuidstrsrc[10];
365 uuidstrdst[13] = uuidstrsrc[13];
367 uuidstrdst[14] = uuidstrsrc[16];
368 uuidstrdst[15] = uuidstrsrc[17];
369 uuidstrdst[16] = uuidstrsrc[14];
370 uuidstrdst[17] = uuidstrsrc[15];
372 for (i = 18; i < VIR_UUID_STRING_BUFLEN; i++) {
373 uuidstrdst[i] = uuidstrsrc[i];
376 uuidstrdst[VIR_UUID_STRING_BUFLEN-1] = '\0';
377 ignore_value(virUUIDParse(uuidstrdst, uuidinterim));
378 memcpy(iid, uuidinterim, VIR_UUID_BUFLEN);
383 typedef struct _vboxIID_v2_x_WIN32 vboxIID;
384 typedef struct _vboxIID_v2_x_WIN32 vboxIID_v2_x_WIN32;
386 struct _vboxIID_v2_x_WIN32 {
387 /* IID is represented by a GUID value. */
391 # define VBOX_IID_INITIALIZER { { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } }
394 vboxIIDUnalloc_v2_x_WIN32(vboxGlobalData *data ATTRIBUTE_UNUSED,
395 vboxIID_v2_x_WIN32 *iid ATTRIBUTE_UNUSED)
397 /* Nothing to free */
401 vboxIIDToUUID_v2_x_WIN32(vboxIID_v2_x_WIN32 *iid, unsigned char *uuid)
403 nsIDtoChar(uuid, (nsID *)&iid->value);
407 vboxIIDFromUUID_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid,
408 const unsigned char *uuid)
410 vboxIIDUnalloc_v2_x_WIN32(data, iid);
412 nsIDFromChar((nsID *)&iid->value, uuid);
416 vboxIIDIsEqual_v2_x_WIN32(vboxIID_v2_x_WIN32 *iid1, vboxIID_v2_x_WIN32 *iid2)
418 return memcmp(&iid1->value, &iid2->value, sizeof(GUID)) == 0;
422 vboxIIDFromArrayItem_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid,
423 vboxArray *array, int idx)
425 GUID *items = (GUID *)array->items;
427 vboxIIDUnalloc_v2_x_WIN32(data, iid);
429 memcpy(&iid->value, &items[idx], sizeof(GUID));
432 # define vboxIIDUnalloc(iid) vboxIIDUnalloc_v2_x_WIN32(data, iid)
433 # define vboxIIDToUUID(iid, uuid) vboxIIDToUUID_v2_x_WIN32(iid, uuid)
434 # define vboxIIDFromUUID(iid, uuid) vboxIIDFromUUID_v2_x_WIN32(data, iid, uuid)
435 # define vboxIIDIsEqual(iid1, iid2) vboxIIDIsEqual_v2_x_WIN32(iid1, iid2)
436 # define vboxIIDFromArrayItem(iid, array, idx) \
437 vboxIIDFromArrayItem_v2_x_WIN32(data, iid, array, idx)
438 # define DEBUGIID(msg, iid) DEBUGUUID(msg, (nsID *)&(iid))
442 typedef struct _vboxIID_v2_x vboxIID;
443 typedef struct _vboxIID_v2_x vboxIID_v2_x;
445 struct _vboxIID_v2_x {
446 /* IID is represented by a pointer to a nsID. */
449 /* backing is used in cases where we need to create or copy an IID.
450 * We cannot allocate memory that can be freed by ComUnallocMem.
451 * Therefore, we use this stack allocated nsID instead. */
455 # define VBOX_IID_INITIALIZER { NULL, { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } }
458 vboxIIDUnalloc_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid)
460 if (iid->value == NULL) {
464 if (iid->value != &iid->backing) {
465 data->pFuncs->pfnComUnallocMem(iid->value);
472 vboxIIDToUUID_v2_x(vboxIID_v2_x *iid, unsigned char *uuid)
474 nsIDtoChar(uuid, iid->value);
478 vboxIIDFromUUID_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid,
479 const unsigned char *uuid)
481 vboxIIDUnalloc_v2_x(data, iid);
483 iid->value = &iid->backing;
485 sa_assert(iid->value);
486 nsIDFromChar(iid->value, uuid);
490 vboxIIDIsEqual_v2_x(vboxIID_v2_x *iid1, vboxIID_v2_x *iid2)
492 return memcmp(iid1->value, iid2->value, sizeof(nsID)) == 0;
496 vboxIIDFromArrayItem_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid,
497 vboxArray *array, int idx)
499 vboxIIDUnalloc_v2_x(data, iid);
501 iid->value = &iid->backing;
503 memcpy(iid->value, array->items[idx], sizeof(nsID));
506 # define vboxIIDUnalloc(iid) vboxIIDUnalloc_v2_x(data, iid)
507 # define vboxIIDToUUID(iid, uuid) vboxIIDToUUID_v2_x(iid, uuid)
508 # define vboxIIDFromUUID(iid, uuid) vboxIIDFromUUID_v2_x(data, iid, uuid)
509 # define vboxIIDIsEqual(iid1, iid2) vboxIIDIsEqual_v2_x(iid1, iid2)
510 # define vboxIIDFromArrayItem(iid, array, idx) \
511 vboxIIDFromArrayItem_v2_x(data, iid, array, idx)
512 # define DEBUGIID(msg, iid) DEBUGUUID(msg, iid)
516 #else /* VBOX_API_VERSION != 2002000 */
518 typedef struct _vboxIID_v3_x vboxIID;
519 typedef struct _vboxIID_v3_x vboxIID_v3_x;
521 struct _vboxIID_v3_x {
522 /* IID is represented by a UTF-16 encoded UUID in string form. */
525 /* owner indicates if we own the value and need to free it. */
529 # define VBOX_IID_INITIALIZER { NULL, true }
532 vboxIIDUnalloc_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid)
534 if (iid->value != NULL && iid->owner) {
535 data->pFuncs->pfnUtf16Free(iid->value);
543 vboxIIDToUUID_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid,
548 data->pFuncs->pfnUtf16ToUtf8(iid->value, &utf8);
550 ignore_value(virUUIDParse(utf8, uuid));
552 data->pFuncs->pfnUtf8Free(utf8);
556 vboxIIDFromUUID_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid,
557 const unsigned char *uuid)
559 char utf8[VIR_UUID_STRING_BUFLEN];
561 vboxIIDUnalloc_v3_x(data, iid);
563 virUUIDFormat(uuid, utf8);
565 data->pFuncs->pfnUtf8ToUtf16(utf8, &iid->value);
569 vboxIIDIsEqual_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid1,
572 unsigned char uuid1[VIR_UUID_BUFLEN];
573 unsigned char uuid2[VIR_UUID_BUFLEN];
575 /* Note: we can't directly compare the utf8 strings here
576 * cause the two UUID's may have separators as space or '-'
577 * or mixture of both and we don't want to fail here by
578 * using direct string comparison. Here virUUIDParse() takes
579 * care of these cases. */
580 vboxIIDToUUID_v3_x(data, iid1, uuid1);
581 vboxIIDToUUID_v3_x(data, iid2, uuid2);
583 return memcmp(uuid1, uuid2, VIR_UUID_BUFLEN) == 0;
588 vboxIIDFromArrayItem_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid,
589 vboxArray *array, int idx)
591 vboxIIDUnalloc_v3_x(data, iid);
593 iid->value = array->items[idx];
598 # define vboxIIDUnalloc(iid) vboxIIDUnalloc_v3_x(data, iid)
599 # define vboxIIDToUUID(iid, uuid) vboxIIDToUUID_v3_x(data, iid, uuid)
600 # define vboxIIDFromUUID(iid, uuid) vboxIIDFromUUID_v3_x(data, iid, uuid)
601 # define vboxIIDIsEqual(iid1, iid2) vboxIIDIsEqual_v3_x(data, iid1, iid2)
602 # define vboxIIDFromArrayItem(iid, array, idx) \
603 vboxIIDFromArrayItem_v3_x(data, iid, array, idx)
604 # define DEBUGIID(msg, strUtf16) DEBUGPRUnichar(msg, strUtf16)
606 # if VBOX_API_VERSION >= 3001000
609 * function to generate the name for medium,
610 * for e.g: hda, sda, etc
612 * @returns null terminated string with device name or NULL
614 * @param conn Input Connection Pointer
615 * @param storageBus Input storage bus type
616 * @param deviceInst Input device instance number
617 * @param devicePort Input port number
618 * @param deviceSlot Input slot number
619 * @param aMaxPortPerInst Input array of max port per device instance
620 * @param aMaxSlotPerPort Input array of max slot per device port
623 static char *vboxGenerateMediumName(PRUint32 storageBus,
627 PRUint32 *aMaxPortPerInst,
628 PRUint32 *aMaxSlotPerPort)
630 const char *prefix = NULL;
633 PRUint32 maxPortPerInst = 0;
634 PRUint32 maxSlotPerPort = 0;
636 if (!aMaxPortPerInst ||
640 if ((storageBus < StorageBus_IDE) ||
641 (storageBus > StorageBus_Floppy))
644 maxPortPerInst = aMaxPortPerInst[storageBus];
645 maxSlotPerPort = aMaxSlotPerPort[storageBus];
646 total = (deviceInst * maxPortPerInst * maxSlotPerPort)
647 + (devicePort * maxSlotPerPort)
650 if (storageBus == StorageBus_IDE) {
652 } else if ((storageBus == StorageBus_SATA) ||
653 (storageBus == StorageBus_SCSI)) {
655 } else if (storageBus == StorageBus_Floppy) {
659 name = virIndexToDiskName(total, prefix);
661 VIR_DEBUG("name=%s, total=%d, storageBus=%u, deviceInst=%d, "
662 "devicePort=%d deviceSlot=%d, maxPortPerInst=%u maxSlotPerPort=%u",
663 NULLSTR(name), total, storageBus, deviceInst, devicePort,
664 deviceSlot, maxPortPerInst, maxSlotPerPort);
669 * function to get the StorageBus, Port number
670 * and Device number for the given devicename
671 * e.g: hda has StorageBus = IDE, port = 0,
674 * @returns true on Success, false on failure.
675 * @param deviceName Input device name
676 * @param aMaxPortPerInst Input array of max port per device instance
677 * @param aMaxSlotPerPort Input array of max slot per device port
678 * @param storageBus Input storage bus type
679 * @param deviceInst Output device instance number
680 * @param devicePort Output port number
681 * @param deviceSlot Output slot number
684 static bool vboxGetDeviceDetails(const char *deviceName,
685 PRUint32 *aMaxPortPerInst,
686 PRUint32 *aMaxSlotPerPort,
690 PRInt32 *deviceSlot) {
692 PRUint32 maxPortPerInst = 0;
693 PRUint32 maxSlotPerPort = 0;
703 if ((storageBus < StorageBus_IDE) ||
704 (storageBus > StorageBus_Floppy))
707 total = virDiskNameToIndex(deviceName);
709 maxPortPerInst = aMaxPortPerInst[storageBus];
710 maxSlotPerPort = aMaxSlotPerPort[storageBus];
712 if (!maxPortPerInst ||
717 *deviceInst = total / (maxPortPerInst * maxSlotPerPort);
718 *devicePort = (total % (maxPortPerInst * maxSlotPerPort)) / maxSlotPerPort;
719 *deviceSlot = (total % (maxPortPerInst * maxSlotPerPort)) % maxSlotPerPort;
721 VIR_DEBUG("name=%s, total=%d, storageBus=%u, deviceInst=%d, "
722 "devicePort=%d deviceSlot=%d, maxPortPerInst=%u maxSlotPerPort=%u",
723 deviceName, total, storageBus, *deviceInst, *devicePort,
724 *deviceSlot, maxPortPerInst, maxSlotPerPort);
730 * function to get the values for max port per
731 * instance and max slots per port for the devices
733 * @returns true on Success, false on failure.
734 * @param vbox Input IVirtualBox pointer
735 * @param maxPortPerInst Output array of max port per instance
736 * @param maxSlotPerPort Output array of max slot per port
740 static bool vboxGetMaxPortSlotValues(IVirtualBox *vbox,
741 PRUint32 *maxPortPerInst,
742 PRUint32 *maxSlotPerPort)
744 ISystemProperties *sysProps = NULL;
749 vbox->vtbl->GetSystemProperties(vbox, &sysProps);
754 sysProps->vtbl->GetMaxPortCountForStorageBus(sysProps,
756 &maxPortPerInst[StorageBus_IDE]);
757 sysProps->vtbl->GetMaxPortCountForStorageBus(sysProps,
759 &maxPortPerInst[StorageBus_SATA]);
760 sysProps->vtbl->GetMaxPortCountForStorageBus(sysProps,
762 &maxPortPerInst[StorageBus_SCSI]);
763 sysProps->vtbl->GetMaxPortCountForStorageBus(sysProps,
765 &maxPortPerInst[StorageBus_Floppy]);
767 sysProps->vtbl->GetMaxDevicesPerPortForStorageBus(sysProps,
769 &maxSlotPerPort[StorageBus_IDE]);
770 sysProps->vtbl->GetMaxDevicesPerPortForStorageBus(sysProps,
772 &maxSlotPerPort[StorageBus_SATA]);
773 sysProps->vtbl->GetMaxDevicesPerPortForStorageBus(sysProps,
775 &maxSlotPerPort[StorageBus_SCSI]);
776 sysProps->vtbl->GetMaxDevicesPerPortForStorageBus(sysProps,
778 &maxSlotPerPort[StorageBus_Floppy]);
780 VBOX_RELEASE(sysProps);
786 * Converts Utf-16 string to int
788 static int PRUnicharToInt(PRUnichar *strUtf16)
790 char *strUtf8 = NULL;
796 g_pVBoxGlobalData->pFuncs->pfnUtf16ToUtf8(strUtf16, &strUtf8);
800 if (virStrToLong_i(strUtf8, NULL, 10, &ret) < 0)
803 g_pVBoxGlobalData->pFuncs->pfnUtf8Free(strUtf8);
809 * Converts int to Utf-16 string
811 static PRUnichar *PRUnicharFromInt(int n) {
812 PRUnichar *strUtf16 = NULL;
815 snprintf(s, sizeof(s), "%d", n);
817 g_pVBoxGlobalData->pFuncs->pfnUtf8ToUtf16(s, &strUtf16);
822 # endif /* VBOX_API_VERSION >= 3001000 */
824 #endif /* !(VBOX_API_VERSION == 2002000) */
827 vboxSocketFormatAddrUtf16(vboxGlobalData *data, virSocketAddrPtr addr)
830 PRUnichar *utf16 = NULL;
832 utf8 = virSocketAddrFormat(addr);
838 VBOX_UTF8_TO_UTF16(utf8, &utf16);
845 vboxSocketParseAddrUtf16(vboxGlobalData *data, const PRUnichar *utf16,
846 virSocketAddrPtr addr)
851 VBOX_UTF16_TO_UTF8(utf16, &utf8);
853 if (virSocketAddrParse(addr, utf8, AF_UNSPEC) < 0) {
860 VBOX_UTF8_FREE(utf8);
866 static virDomainDefParserConfig vboxDomainDefParserConfig = {
867 .macPrefix = { 0x08, 0x00, 0x27 },
871 static virDomainXMLOptionPtr
872 vboxXMLConfInit(void)
874 return virDomainXMLOptionNew(&vboxDomainDefParserConfig,
879 static virCapsPtr vboxCapsInit(void)
882 virCapsGuestPtr guest;
884 if ((caps = virCapabilitiesNew(virArchFromHost(),
888 if (nodeCapsInitNUMA(caps) < 0)
891 if ((guest = virCapabilitiesAddGuest(caps,
900 if (virCapabilitiesAddGuestDomain(guest,
911 virObjectUnref(caps);
916 vboxInitialize(vboxGlobalData *data)
918 data->pFuncs = g_pfnGetFunctions(VBOX_XPCOMC_VERSION);
920 if (data->pFuncs == NULL)
923 #if VBOX_XPCOMC_VERSION == 0x00010000U
924 data->pFuncs->pfnComInitialize(&data->vboxObj, &data->vboxSession);
925 #else /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */
926 data->pFuncs->pfnComInitialize(IVIRTUALBOX_IID_STR, &data->vboxObj,
927 ISESSION_IID_STR, &data->vboxSession);
929 # if VBOX_API_VERSION == 2002000
931 /* No event queue functionality in 2.2.* as of now */
933 # else /* !(VBOX_API_VERSION == 2002000) */
935 /* Initial the fWatch needed for Event Callbacks */
938 data->pFuncs->pfnGetEventQueue(&data->vboxQueue);
940 if (data->vboxQueue == NULL) {
941 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
942 _("nsIEventQueue object is null"));
946 # endif /* !(VBOX_API_VERSION == 2002000) */
947 #endif /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */
949 if (data->vboxObj == NULL) {
950 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
951 _("IVirtualBox object is null"));
955 if (data->vboxSession == NULL) {
956 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
957 _("ISession object is null"));
967 static int vboxExtractVersion(vboxGlobalData *data)
970 PRUnichar *versionUtf16 = NULL;
973 if (data->version > 0)
976 rc = data->vboxObj->vtbl->GetVersion(data->vboxObj, &versionUtf16);
977 if (NS_SUCCEEDED(rc)) {
978 char *vboxVersion = NULL;
980 VBOX_UTF16_TO_UTF8(versionUtf16, &vboxVersion);
982 if (virParseVersionString(vboxVersion, &data->version, false) >= 0)
985 VBOX_UTF8_FREE(vboxVersion);
986 VBOX_COM_UNALLOC_MEM(versionUtf16);
990 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
991 _("Could not extract VirtualBox version"));
996 static void vboxUninitialize(vboxGlobalData *data)
1002 data->pFuncs->pfnComUninitialize();
1004 virObjectUnref(data->caps);
1005 virObjectUnref(data->xmlopt);
1006 #if VBOX_API_VERSION == 2002000
1007 /* No domainEventCallbacks in 2.2.* version */
1008 #else /* !(VBOX_API_VERSION == 2002000) */
1009 virObjectEventStateFree(data->domainEvents);
1010 #endif /* !(VBOX_API_VERSION == 2002000) */
1015 static virDrvOpenStatus vboxConnectOpen(virConnectPtr conn,
1016 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
1019 vboxGlobalData *data = NULL;
1020 uid_t uid = geteuid();
1022 virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
1024 if (conn->uri == NULL &&
1025 !(conn->uri = virURIParse(uid ? "vbox:///session" : "vbox:///system")))
1026 return VIR_DRV_OPEN_ERROR;
1028 if (conn->uri->scheme == NULL ||
1029 STRNEQ(conn->uri->scheme, "vbox"))
1030 return VIR_DRV_OPEN_DECLINED;
1032 /* Leave for remote driver */
1033 if (conn->uri->server != NULL)
1034 return VIR_DRV_OPEN_DECLINED;
1036 if (conn->uri->path == NULL || STREQ(conn->uri->path, "")) {
1037 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1038 _("no VirtualBox driver path specified (try vbox:///session)"));
1039 return VIR_DRV_OPEN_ERROR;
1043 if (STRNEQ(conn->uri->path, "/session")) {
1044 virReportError(VIR_ERR_INTERNAL_ERROR,
1045 _("unknown driver path '%s' specified (try vbox:///session)"), conn->uri->path);
1046 return VIR_DRV_OPEN_ERROR;
1049 if (STRNEQ(conn->uri->path, "/system") &&
1050 STRNEQ(conn->uri->path, "/session")) {
1051 virReportError(VIR_ERR_INTERNAL_ERROR,
1052 _("unknown driver path '%s' specified (try vbox:///system)"), conn->uri->path);
1053 return VIR_DRV_OPEN_ERROR;
1057 if (VIR_ALLOC(data) < 0)
1058 return VIR_DRV_OPEN_ERROR;
1060 if (!(data->caps = vboxCapsInit()) ||
1061 vboxInitialize(data) < 0 ||
1062 vboxExtractVersion(data) < 0 ||
1063 !(data->xmlopt = vboxXMLConfInit())) {
1064 vboxUninitialize(data);
1065 return VIR_DRV_OPEN_ERROR;
1068 #if VBOX_API_VERSION == 2002000
1070 /* No domainEventCallbacks in 2.2.* version */
1072 #else /* !(VBOX_API_VERSION == 2002000) */
1074 if (!(data->domainEvents = virObjectEventStateNew())) {
1075 vboxUninitialize(data);
1076 return VIR_DRV_OPEN_ERROR;
1080 g_pVBoxGlobalData = data;
1082 #endif /* !(VBOX_API_VERSION == 2002000) */
1084 conn->privateData = data;
1085 VIR_DEBUG("in vboxOpen");
1087 return VIR_DRV_OPEN_SUCCESS;
1090 static int vboxConnectClose(virConnectPtr conn)
1092 vboxGlobalData *data = conn->privateData;
1093 VIR_DEBUG("%s: in vboxClose", conn->driver->name);
1095 vboxUninitialize(data);
1096 conn->privateData = NULL;
1101 static int vboxConnectGetVersion(virConnectPtr conn, unsigned long *version)
1103 vboxGlobalData *data = conn->privateData;
1104 VIR_DEBUG("%s: in vboxGetVersion", conn->driver->name);
1106 vboxDriverLock(data);
1107 *version = data->version;
1108 vboxDriverUnlock(data);
1114 static char *vboxConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
1116 return virGetHostname();
1120 static int vboxConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
1122 /* Driver is using local, non-network based transport */
1126 static int vboxConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1128 /* No encryption is needed, or used on the local transport*/
1132 static int vboxConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
1138 vboxConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED)
1140 VBOX_OBJECT_CHECK(conn, int, -1);
1141 PRUint32 maxCPUCount = 0;
1143 /* VirtualBox Supports only hvm and thus the type passed to it
1144 * has no meaning, setting it to ATTRIBUTE_UNUSED
1146 ISystemProperties *systemProperties = NULL;
1148 data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties);
1149 if (systemProperties) {
1150 systemProperties->vtbl->GetMaxGuestCPUCount(systemProperties, &maxCPUCount);
1151 VBOX_RELEASE(systemProperties);
1154 if (maxCPUCount > 0)
1161 static char *vboxConnectGetCapabilities(virConnectPtr conn) {
1162 VBOX_OBJECT_CHECK(conn, char *, NULL);
1164 vboxDriverLock(data);
1165 ret = virCapabilitiesFormatXML(data->caps);
1166 vboxDriverUnlock(data);
1171 static int vboxConnectListDomains(virConnectPtr conn, int *ids, int nids)
1173 VBOX_OBJECT_CHECK(conn, int, -1);
1174 vboxArray machines = VBOX_ARRAY_INITIALIZER;
1179 rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines);
1180 if (NS_FAILED(rc)) {
1181 virReportError(VIR_ERR_INTERNAL_ERROR,
1182 _("Could not get list of Domains, rc=%08x"),
1188 for (i = 0, j = 0; (i < machines.count) && (j < nids); ++i) {
1189 IMachine *machine = machines.items[i];
1192 PRBool isAccessible = PR_FALSE;
1193 machine->vtbl->GetAccessible(machine, &isAccessible);
1195 machine->vtbl->GetState(machine, &state);
1196 if ((state >= MachineState_FirstOnline) &&
1197 (state <= MachineState_LastOnline)) {
1206 vboxArrayRelease(&machines);
1210 static int vboxConnectNumOfDomains(virConnectPtr conn)
1212 VBOX_OBJECT_CHECK(conn, int, -1);
1213 vboxArray machines = VBOX_ARRAY_INITIALIZER;
1218 rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines);
1219 if (NS_FAILED(rc)) {
1220 virReportError(VIR_ERR_INTERNAL_ERROR,
1221 _("Could not get number of Domains, rc=%08x"), (unsigned)rc);
1226 for (i = 0; i < machines.count; ++i) {
1227 IMachine *machine = machines.items[i];
1230 PRBool isAccessible = PR_FALSE;
1231 machine->vtbl->GetAccessible(machine, &isAccessible);
1233 machine->vtbl->GetState(machine, &state);
1234 if ((state >= MachineState_FirstOnline) &&
1235 (state <= MachineState_LastOnline))
1242 vboxArrayRelease(&machines);
1246 static virDomainPtr vboxDomainCreateXML(virConnectPtr conn, const char *xml,
1249 /* VirtualBox currently doesn't have support for running
1250 * virtual machines without actually defining them and thus
1251 * for time being just define new machine and start it.
1253 * TODO: After the appropriate API's are added in VirtualBox
1254 * change this behaviour to the expected one.
1259 virCheckFlags(0, NULL);
1261 dom = vboxDomainDefineXML(conn, xml);
1265 if (vboxDomainCreate(dom) < 0) {
1266 vboxDomainUndefineFlags(dom, 0);
1267 virObjectUnref(dom);
1274 static virDomainPtr vboxDomainLookupByID(virConnectPtr conn, int id)
1276 VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL);
1277 vboxArray machines = VBOX_ARRAY_INITIALIZER;
1278 vboxIID iid = VBOX_IID_INITIALIZER;
1279 unsigned char uuid[VIR_UUID_BUFLEN];
1283 /* Internal vbox IDs start from 0, the public libvirt ID
1284 * starts from 1, so refuse id == 0, and adjust the rest*/
1286 virReportError(VIR_ERR_NO_DOMAIN,
1287 _("no domain with matching id %d"), id);
1292 rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines);
1293 if (NS_FAILED(rc)) {
1294 virReportError(VIR_ERR_INTERNAL_ERROR,
1295 _("Could not get list of machines, rc=%08x"), (unsigned)rc);
1299 if (id < machines.count) {
1300 IMachine *machine = machines.items[id];
1303 PRBool isAccessible = PR_FALSE;
1304 machine->vtbl->GetAccessible(machine, &isAccessible);
1306 machine->vtbl->GetState(machine, &state);
1307 if ((state >= MachineState_FirstOnline) &&
1308 (state <= MachineState_LastOnline)) {
1309 PRUnichar *machineNameUtf16 = NULL;
1310 char *machineNameUtf8 = NULL;
1312 machine->vtbl->GetName(machine, &machineNameUtf16);
1313 VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8);
1315 machine->vtbl->GetId(machine, &iid.value);
1316 vboxIIDToUUID(&iid, uuid);
1317 vboxIIDUnalloc(&iid);
1319 /* get a new domain pointer from virGetDomain, if it fails
1320 * then no need to assign the id, else assign the id, cause
1321 * it is -1 by default. rest is taken care by virGetDomain
1322 * itself, so need not worry.
1325 ret = virGetDomain(conn, machineNameUtf8, uuid);
1329 /* Cleanup all the XPCOM allocated stuff here */
1330 VBOX_UTF8_FREE(machineNameUtf8);
1331 VBOX_UTF16_FREE(machineNameUtf16);
1337 vboxArrayRelease(&machines);
1343 vboxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
1345 VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL);
1346 vboxArray machines = VBOX_ARRAY_INITIALIZER;
1347 vboxIID iid = VBOX_IID_INITIALIZER;
1348 char *machineNameUtf8 = NULL;
1349 PRUnichar *machineNameUtf16 = NULL;
1350 unsigned char iid_as_uuid[VIR_UUID_BUFLEN];
1355 rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines);
1356 if (NS_FAILED(rc)) {
1357 virReportError(VIR_ERR_INTERNAL_ERROR,
1358 _("Could not get list of machines, rc=%08x"), (unsigned)rc);
1362 for (i = 0; i < machines.count; ++i) {
1363 IMachine *machine = machines.items[i];
1364 PRBool isAccessible = PR_FALSE;
1369 machine->vtbl->GetAccessible(machine, &isAccessible);
1372 rc = machine->vtbl->GetId(machine, &iid.value);
1375 vboxIIDToUUID(&iid, iid_as_uuid);
1376 vboxIIDUnalloc(&iid);
1378 if (memcmp(uuid, iid_as_uuid, VIR_UUID_BUFLEN) == 0) {
1384 machine->vtbl->GetName(machine, &machineNameUtf16);
1385 VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8);
1387 machine->vtbl->GetState(machine, &state);
1389 /* get a new domain pointer from virGetDomain, if it fails
1390 * then no need to assign the id, else assign the id, cause
1391 * it is -1 by default. rest is taken care by virGetDomain
1392 * itself, so need not worry.
1395 ret = virGetDomain(conn, machineNameUtf8, iid_as_uuid);
1397 (state >= MachineState_FirstOnline) &&
1398 (state <= MachineState_LastOnline))
1407 /* Do the cleanup and take care you dont leak any memory */
1408 VBOX_UTF8_FREE(machineNameUtf8);
1409 VBOX_COM_UNALLOC_MEM(machineNameUtf16);
1410 vboxArrayRelease(&machines);
1416 vboxDomainLookupByName(virConnectPtr conn, const char *name)
1418 VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL);
1419 vboxArray machines = VBOX_ARRAY_INITIALIZER;
1420 vboxIID iid = VBOX_IID_INITIALIZER;
1421 char *machineNameUtf8 = NULL;
1422 PRUnichar *machineNameUtf16 = NULL;
1423 unsigned char uuid[VIR_UUID_BUFLEN];
1428 rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines);
1429 if (NS_FAILED(rc)) {
1430 virReportError(VIR_ERR_INTERNAL_ERROR,
1431 _("Could not get list of machines, rc=%08x"), (unsigned)rc);
1435 for (i = 0; i < machines.count; ++i) {
1436 IMachine *machine = machines.items[i];
1437 PRBool isAccessible = PR_FALSE;
1442 machine->vtbl->GetAccessible(machine, &isAccessible);
1445 machine->vtbl->GetName(machine, &machineNameUtf16);
1446 VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8);
1448 if (STREQ(name, machineNameUtf8)) {
1454 machine->vtbl->GetId(machine, &iid.value);
1455 vboxIIDToUUID(&iid, uuid);
1456 vboxIIDUnalloc(&iid);
1458 machine->vtbl->GetState(machine, &state);
1460 /* get a new domain pointer from virGetDomain, if it fails
1461 * then no need to assign the id, else assign the id, cause
1462 * it is -1 by default. rest is taken care by virGetDomain
1463 * itself, so need not worry.
1466 ret = virGetDomain(conn, machineNameUtf8, uuid);
1468 (state >= MachineState_FirstOnline) &&
1469 (state <= MachineState_LastOnline))
1473 VBOX_UTF8_FREE(machineNameUtf8);
1474 VBOX_COM_UNALLOC_MEM(machineNameUtf16);
1480 vboxArrayRelease(&machines);
1486 static int vboxDomainIsActive(virDomainPtr dom)
1488 VBOX_OBJECT_CHECK(dom->conn, int, -1);
1489 vboxArray machines = VBOX_ARRAY_INITIALIZER;
1490 vboxIID iid = VBOX_IID_INITIALIZER;
1491 char *machineNameUtf8 = NULL;
1492 PRUnichar *machineNameUtf16 = NULL;
1493 unsigned char uuid[VIR_UUID_BUFLEN];
1498 rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines);
1499 if (NS_FAILED(rc)) {
1500 virReportError(VIR_ERR_INTERNAL_ERROR,
1501 _("Could not get list of machines, rc=%08x"), (unsigned)rc);
1505 for (i = 0; i < machines.count; ++i) {
1506 IMachine *machine = machines.items[i];
1507 PRBool isAccessible = PR_FALSE;
1512 machine->vtbl->GetAccessible(machine, &isAccessible);
1515 rc = machine->vtbl->GetId(machine, &iid.value);
1518 vboxIIDToUUID(&iid, uuid);
1519 vboxIIDUnalloc(&iid);
1521 if (memcmp(dom->uuid, uuid, VIR_UUID_BUFLEN) == 0) {
1527 machine->vtbl->GetName(machine, &machineNameUtf16);
1528 VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8);
1530 machine->vtbl->GetState(machine, &state);
1532 if ((state >= MachineState_FirstOnline) &&
1533 (state <= MachineState_LastOnline))
1544 /* Do the cleanup and take care you dont leak any memory */
1545 VBOX_UTF8_FREE(machineNameUtf8);
1546 VBOX_COM_UNALLOC_MEM(machineNameUtf16);
1547 vboxArrayRelease(&machines);
1553 static int vboxDomainIsPersistent(virDomainPtr dom ATTRIBUTE_UNUSED)
1555 /* All domains are persistent. However, we do want to check for
1557 VBOX_OBJECT_CHECK(dom->conn, int, -1);
1558 vboxIID iid = VBOX_IID_INITIALIZER;
1559 IMachine *machine = NULL;
1562 vboxIIDFromUUID(&iid, dom->uuid);
1563 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
1564 if (NS_FAILED(rc)) {
1565 virReportError(VIR_ERR_NO_DOMAIN, "%s",
1566 _("no domain with matching UUID"));
1573 VBOX_RELEASE(machine);
1574 vboxIIDUnalloc(&iid);
1579 static int vboxDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
1581 /* VBox domains never have a persistent state that differs from
1582 * current state. However, we do want to check for existence. */
1583 VBOX_OBJECT_CHECK(dom->conn, int, -1);
1584 vboxIID iid = VBOX_IID_INITIALIZER;
1585 IMachine *machine = NULL;
1588 vboxIIDFromUUID(&iid, dom->uuid);
1589 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
1590 if (NS_FAILED(rc)) {
1591 virReportError(VIR_ERR_NO_DOMAIN, "%s",
1592 _("no domain with matching UUID"));
1599 VBOX_RELEASE(machine);
1600 vboxIIDUnalloc(&iid);
1604 static int vboxDomainSuspend(virDomainPtr dom)
1606 VBOX_OBJECT_CHECK(dom->conn, int, -1);
1607 IMachine *machine = NULL;
1608 vboxIID iid = VBOX_IID_INITIALIZER;
1609 IConsole *console = NULL;
1610 PRBool isAccessible = PR_FALSE;
1614 vboxIIDFromUUID(&iid, dom->uuid);
1615 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
1616 if (NS_FAILED(rc)) {
1617 virReportError(VIR_ERR_NO_DOMAIN,
1618 _("no domain with matching id %d"), dom->id);
1625 machine->vtbl->GetAccessible(machine, &isAccessible);
1627 machine->vtbl->GetState(machine, &state);
1629 if (state == MachineState_Running) {
1630 /* set state pause */
1631 VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
1632 data->vboxSession->vtbl->GetConsole(data->vboxSession, &console);
1634 console->vtbl->Pause(console);
1635 VBOX_RELEASE(console);
1638 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
1639 _("error while suspending the domain"));
1642 VBOX_SESSION_CLOSE();
1644 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
1645 _("machine not in running state to suspend it"));
1651 VBOX_RELEASE(machine);
1652 vboxIIDUnalloc(&iid);
1656 static int vboxDomainResume(virDomainPtr dom)
1658 VBOX_OBJECT_CHECK(dom->conn, int, -1);
1659 IMachine *machine = NULL;
1660 vboxIID iid = VBOX_IID_INITIALIZER;
1661 IConsole *console = NULL;
1662 PRUint32 state = MachineState_Null;
1665 PRBool isAccessible = PR_FALSE;
1667 vboxIIDFromUUID(&iid, dom->uuid);
1668 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
1669 if (NS_FAILED(rc)) {
1670 virReportError(VIR_ERR_NO_DOMAIN,
1671 _("no domain with matching id %d"), dom->id);
1678 machine->vtbl->GetAccessible(machine, &isAccessible);
1680 machine->vtbl->GetState(machine, &state);
1682 if (state == MachineState_Paused) {
1683 /* resume the machine here */
1684 VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
1685 data->vboxSession->vtbl->GetConsole(data->vboxSession, &console);
1687 console->vtbl->Resume(console);
1688 VBOX_RELEASE(console);
1691 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
1692 _("error while resuming the domain"));
1695 VBOX_SESSION_CLOSE();
1697 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
1698 _("machine not paused, so can't resume it"));
1704 VBOX_RELEASE(machine);
1705 vboxIIDUnalloc(&iid);
1709 static int vboxDomainShutdownFlags(virDomainPtr dom,
1712 VBOX_OBJECT_CHECK(dom->conn, int, -1);
1713 IMachine *machine = NULL;
1714 vboxIID iid = VBOX_IID_INITIALIZER;
1715 IConsole *console = NULL;
1716 PRUint32 state = MachineState_Null;
1717 PRBool isAccessible = PR_FALSE;
1720 virCheckFlags(0, -1);
1722 vboxIIDFromUUID(&iid, dom->uuid);
1723 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
1724 if (NS_FAILED(rc)) {
1725 virReportError(VIR_ERR_NO_DOMAIN,
1726 _("no domain with matching id %d"), dom->id);
1733 machine->vtbl->GetAccessible(machine, &isAccessible);
1735 machine->vtbl->GetState(machine, &state);
1737 if (state == MachineState_Paused) {
1738 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
1739 _("machine paused, so can't power it down"));
1741 } else if (state == MachineState_PoweredOff) {
1742 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
1743 _("machine already powered down"));
1747 VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
1748 data->vboxSession->vtbl->GetConsole(data->vboxSession, &console);
1750 console->vtbl->PowerButton(console);
1751 VBOX_RELEASE(console);
1754 VBOX_SESSION_CLOSE();
1758 VBOX_RELEASE(machine);
1759 vboxIIDUnalloc(&iid);
1763 static int vboxDomainShutdown(virDomainPtr dom)
1765 return vboxDomainShutdownFlags(dom, 0);
1769 static int vboxDomainReboot(virDomainPtr dom, unsigned int flags)
1771 VBOX_OBJECT_CHECK(dom->conn, int, -1);
1772 IMachine *machine = NULL;
1773 vboxIID iid = VBOX_IID_INITIALIZER;
1774 IConsole *console = NULL;
1775 PRUint32 state = MachineState_Null;
1776 PRBool isAccessible = PR_FALSE;
1779 virCheckFlags(0, -1);
1781 vboxIIDFromUUID(&iid, dom->uuid);
1782 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
1783 if (NS_FAILED(rc)) {
1784 virReportError(VIR_ERR_NO_DOMAIN,
1785 _("no domain with matching id %d"), dom->id);
1792 machine->vtbl->GetAccessible(machine, &isAccessible);
1794 machine->vtbl->GetState(machine, &state);
1796 if (state == MachineState_Running) {
1797 VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
1798 data->vboxSession->vtbl->GetConsole(data->vboxSession, &console);
1800 console->vtbl->Reset(console);
1801 VBOX_RELEASE(console);
1804 VBOX_SESSION_CLOSE();
1806 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
1807 _("machine not running, so can't reboot it"));
1813 VBOX_RELEASE(machine);
1814 vboxIIDUnalloc(&iid);
1819 vboxDomainDestroyFlags(virDomainPtr dom,
1822 VBOX_OBJECT_CHECK(dom->conn, int, -1);
1823 IMachine *machine = NULL;
1824 vboxIID iid = VBOX_IID_INITIALIZER;
1825 IConsole *console = NULL;
1826 PRUint32 state = MachineState_Null;
1827 PRBool isAccessible = PR_FALSE;
1830 virCheckFlags(0, -1);
1832 vboxIIDFromUUID(&iid, dom->uuid);
1833 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
1834 if (NS_FAILED(rc)) {
1835 virReportError(VIR_ERR_NO_DOMAIN,
1836 _("no domain with matching id %d"), dom->id);
1843 machine->vtbl->GetAccessible(machine, &isAccessible);
1845 machine->vtbl->GetState(machine, &state);
1847 if (state == MachineState_PoweredOff) {
1848 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
1849 _("machine already powered down"));
1853 VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
1854 data->vboxSession->vtbl->GetConsole(data->vboxSession, &console);
1857 #if VBOX_API_VERSION == 2002000
1858 console->vtbl->PowerDown(console);
1860 IProgress *progress = NULL;
1861 console->vtbl->PowerDown(console, &progress);
1863 progress->vtbl->WaitForCompletion(progress, -1);
1864 VBOX_RELEASE(progress);
1867 VBOX_RELEASE(console);
1871 VBOX_SESSION_CLOSE();
1875 VBOX_RELEASE(machine);
1876 vboxIIDUnalloc(&iid);
1881 vboxDomainDestroy(virDomainPtr dom)
1883 return vboxDomainDestroyFlags(dom, 0);
1886 static char *vboxDomainGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) {
1887 /* Returning "hvm" always as suggested on list, cause
1888 * this functions seems to be badly named and it
1889 * is supposed to pass the ABI name and not the domain
1890 * operating system driver as I had imagined ;)
1894 ignore_value(VIR_STRDUP(osType, "hvm"));
1898 static int vboxDomainSetMemory(virDomainPtr dom, unsigned long memory)
1900 VBOX_OBJECT_CHECK(dom->conn, int, -1);
1901 IMachine *machine = NULL;
1902 vboxIID iid = VBOX_IID_INITIALIZER;
1903 PRUint32 state = MachineState_Null;
1904 PRBool isAccessible = PR_FALSE;
1907 vboxIIDFromUUID(&iid, dom->uuid);
1908 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
1909 if (NS_FAILED(rc)) {
1910 virReportError(VIR_ERR_NO_DOMAIN,
1911 _("no domain with matching id %d"), dom->id);
1918 machine->vtbl->GetAccessible(machine, &isAccessible);
1920 machine->vtbl->GetState(machine, &state);
1922 if (state != MachineState_PoweredOff) {
1923 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
1924 _("memory size can't be changed unless domain is powered down"));
1928 rc = VBOX_SESSION_OPEN(iid.value, machine);
1929 if (NS_SUCCEEDED(rc)) {
1930 rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
1931 if (NS_SUCCEEDED(rc) && machine) {
1933 rc = machine->vtbl->SetMemorySize(machine,
1934 VIR_DIV_UP(memory, 1024));
1935 if (NS_SUCCEEDED(rc)) {
1936 machine->vtbl->SaveSettings(machine);
1939 virReportError(VIR_ERR_INTERNAL_ERROR,
1940 _("could not set the memory size of the "
1941 "domain to: %lu Kb, rc=%08x"),
1942 memory, (unsigned)rc);
1945 VBOX_SESSION_CLOSE();
1950 VBOX_RELEASE(machine);
1951 vboxIIDUnalloc(&iid);
1955 static virDomainState vboxConvertState(enum MachineState state)
1958 case MachineState_Running:
1959 return VIR_DOMAIN_RUNNING;
1960 case MachineState_Stuck:
1961 return VIR_DOMAIN_BLOCKED;
1962 case MachineState_Paused:
1963 return VIR_DOMAIN_PAUSED;
1964 case MachineState_Stopping:
1965 return VIR_DOMAIN_SHUTDOWN;
1966 case MachineState_PoweredOff:
1967 case MachineState_Saved:
1968 return VIR_DOMAIN_SHUTOFF;
1969 case MachineState_Aborted:
1970 return VIR_DOMAIN_CRASHED;
1971 case MachineState_Null:
1973 return VIR_DOMAIN_NOSTATE;
1977 static int vboxDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
1979 VBOX_OBJECT_CHECK(dom->conn, int, -1);
1980 vboxArray machines = VBOX_ARRAY_INITIALIZER;
1981 char *machineName = NULL;
1982 PRUnichar *machineNameUtf16 = NULL;
1986 rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines);
1987 if (NS_FAILED(rc)) {
1988 virReportError(VIR_ERR_INTERNAL_ERROR,
1989 _("Could not get list of machines, rc=%08x"), (unsigned)rc);
1993 info->nrVirtCpu = 0;
1994 for (i = 0; i < machines.count; ++i) {
1995 IMachine *machine = machines.items[i];
1996 PRBool isAccessible = PR_FALSE;
2001 machine->vtbl->GetAccessible(machine, &isAccessible);
2004 machine->vtbl->GetName(machine, &machineNameUtf16);
2005 VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineName);
2007 if (STREQ(dom->name, machineName)) {
2008 /* Get the Machine State (also match it with
2009 * virDomainState). Get the Machine memory and
2010 * for time being set max_balloon and cur_balloon to same
2011 * Also since there is no direct way of checking
2012 * the cputime required (one condition being the
2013 * VM is remote), return zero for cputime. Get the
2016 PRUint32 CPUCount = 0;
2017 PRUint32 memorySize = 0;
2018 PRUint32 state = MachineState_Null;
2019 PRUint32 maxMemorySize = 4 * 1024;
2020 ISystemProperties *systemProperties = NULL;
2022 data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties);
2023 if (systemProperties) {
2024 systemProperties->vtbl->GetMaxGuestRAM(systemProperties, &maxMemorySize);
2025 VBOX_RELEASE(systemProperties);
2026 systemProperties = NULL;
2030 machine->vtbl->GetCPUCount(machine, &CPUCount);
2031 machine->vtbl->GetMemorySize(machine, &memorySize);
2032 machine->vtbl->GetState(machine, &state);
2035 info->nrVirtCpu = CPUCount;
2036 info->memory = memorySize * 1024;
2037 info->maxMem = maxMemorySize * 1024;
2038 info->state = vboxConvertState(state);
2043 VBOX_UTF8_FREE(machineName);
2044 VBOX_COM_UNALLOC_MEM(machineNameUtf16);
2045 if (info->nrVirtCpu)
2051 vboxArrayRelease(&machines);
2058 vboxDomainGetState(virDomainPtr dom,
2063 VBOX_OBJECT_CHECK(dom->conn, int, -1);
2064 vboxIID domiid = VBOX_IID_INITIALIZER;
2065 IMachine *machine = NULL;
2066 PRUint32 mstate = MachineState_Null;
2069 virCheckFlags(0, -1);
2071 vboxIIDFromUUID(&domiid, dom->uuid);
2072 rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
2073 if (NS_FAILED(rc)) {
2074 virReportError(VIR_ERR_NO_DOMAIN, "%s",
2075 _("no domain with matching UUID"));
2079 machine->vtbl->GetState(machine, &mstate);
2081 *state = vboxConvertState(mstate);
2089 vboxIIDUnalloc(&domiid);
2093 static int vboxDomainSave(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED)
2095 VBOX_OBJECT_CHECK(dom->conn, int, -1);
2096 IConsole *console = NULL;
2097 vboxIID iid = VBOX_IID_INITIALIZER;
2098 IMachine *machine = NULL;
2101 /* VirtualBox currently doesn't support saving to a file
2102 * at a location other then the machine folder and thus
2103 * setting path to ATTRIBUTE_UNUSED for now, will change
2104 * this behaviour once get the VirtualBox API in right
2108 /* Open a Session for the machine */
2109 vboxIIDFromUUID(&iid, dom->uuid);
2110 #if VBOX_API_VERSION >= 4000000
2111 /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */
2112 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
2113 if (NS_FAILED(rc)) {
2114 virReportError(VIR_ERR_NO_DOMAIN, "%s",
2115 _("no domain with matching uuid"));
2120 rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
2121 if (NS_SUCCEEDED(rc)) {
2122 rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console);
2123 if (NS_SUCCEEDED(rc) && console) {
2124 IProgress *progress = NULL;
2126 console->vtbl->SaveState(console, &progress);
2129 #if VBOX_API_VERSION == 2002000
2130 nsresult resultCode;
2135 progress->vtbl->WaitForCompletion(progress, -1);
2136 progress->vtbl->GetResultCode(progress, &resultCode);
2137 if (NS_SUCCEEDED(resultCode)) {
2140 VBOX_RELEASE(progress);
2142 VBOX_RELEASE(console);
2144 VBOX_SESSION_CLOSE();
2147 DEBUGIID("UUID of machine being saved:", iid.value);
2149 VBOX_RELEASE(machine);
2150 vboxIIDUnalloc(&iid);
2155 vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
2158 VBOX_OBJECT_CHECK(dom->conn, int, -1);
2159 IMachine *machine = NULL;
2160 vboxIID iid = VBOX_IID_INITIALIZER;
2161 PRUint32 CPUCount = nvcpus;
2164 if (flags != VIR_DOMAIN_AFFECT_LIVE) {
2165 virReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
2169 vboxIIDFromUUID(&iid, dom->uuid);
2170 #if VBOX_API_VERSION >= 4000000
2171 /* Get machine for the call to VBOX_SESSION_OPEN */
2172 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
2173 if (NS_FAILED(rc)) {
2174 virReportError(VIR_ERR_NO_DOMAIN, "%s",
2175 _("no domain with matching uuid"));
2180 rc = VBOX_SESSION_OPEN(iid.value, machine);
2181 if (NS_SUCCEEDED(rc)) {
2182 data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
2184 rc = machine->vtbl->SetCPUCount(machine, CPUCount);
2185 if (NS_SUCCEEDED(rc)) {
2186 machine->vtbl->SaveSettings(machine);
2189 virReportError(VIR_ERR_INTERNAL_ERROR,
2190 _("could not set the number of cpus of the domain "
2192 CPUCount, (unsigned)rc);
2194 VBOX_RELEASE(machine);
2196 virReportError(VIR_ERR_NO_DOMAIN,
2197 _("no domain with matching id %d"), dom->id);
2200 virReportError(VIR_ERR_NO_DOMAIN,
2201 _("can't open session to the domain with id %d"), dom->id);
2203 VBOX_SESSION_CLOSE();
2205 vboxIIDUnalloc(&iid);
2210 vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
2212 return vboxDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_AFFECT_LIVE);
2216 vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
2218 VBOX_OBJECT_CHECK(dom->conn, int, -1);
2219 ISystemProperties *systemProperties = NULL;
2220 PRUint32 maxCPUCount = 0;
2222 if (flags != (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
2223 virReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
2227 /* Currently every domain supports the same number of max cpus
2228 * as that supported by vbox and thus take it directly from
2229 * the systemproperties.
2232 data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties);
2233 if (systemProperties) {
2234 systemProperties->vtbl->GetMaxGuestCPUCount(systemProperties, &maxCPUCount);
2235 VBOX_RELEASE(systemProperties);
2238 if (maxCPUCount > 0)
2245 vboxDomainGetMaxVcpus(virDomainPtr dom)
2247 return vboxDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE |
2248 VIR_DOMAIN_VCPU_MAXIMUM));
2251 static void vboxHostDeviceGetXMLDesc(vboxGlobalData *data, virDomainDefPtr def, IMachine *machine)
2253 #if VBOX_API_VERSION < 4003000
2254 IUSBController *USBController = NULL;
2255 PRBool enabled = PR_FALSE;
2257 IUSBDeviceFilters *USBDeviceFilters = NULL;
2259 vboxArray deviceFilters = VBOX_ARRAY_INITIALIZER;
2261 PRUint32 USBFilterCount = 0;
2265 #if VBOX_API_VERSION < 4003000
2266 machine->vtbl->GetUSBController(machine, &USBController);
2271 USBController->vtbl->GetEnabled(USBController, &enabled);
2273 goto release_controller;
2275 vboxArrayGet(&deviceFilters, USBController,
2276 USBController->vtbl->GetDeviceFilters);
2279 machine->vtbl->GetUSBDeviceFilters(machine, &USBDeviceFilters);
2281 if (!USBDeviceFilters)
2284 vboxArrayGet(&deviceFilters, USBDeviceFilters,
2285 USBDeviceFilters->vtbl->GetDeviceFilters);
2288 if (deviceFilters.count <= 0)
2289 goto release_filters;
2291 /* check if the filters are active and then only
2292 * alloc mem and set def->nhostdevs
2295 for (i = 0; i < deviceFilters.count; i++) {
2296 PRBool active = PR_FALSE;
2297 IUSBDeviceFilter *deviceFilter = deviceFilters.items[i];
2299 deviceFilter->vtbl->GetActive(deviceFilter, &active);
2305 if (def->nhostdevs == 0)
2306 goto release_filters;
2308 /* Alloc mem needed for the filters now */
2309 if (VIR_ALLOC_N(def->hostdevs, def->nhostdevs) < 0)
2310 goto release_filters;
2312 for (i = 0; i < def->nhostdevs; i++) {
2313 def->hostdevs[i] = virDomainHostdevDefAlloc();
2314 if (!def->hostdevs[i])
2315 goto release_hostdevs;
2318 for (i = 0; i < deviceFilters.count; i++) {
2319 PRBool active = PR_FALSE;
2320 IUSBDeviceFilter *deviceFilter = deviceFilters.items[i];
2321 PRUnichar *vendorIdUtf16 = NULL;
2322 char *vendorIdUtf8 = NULL;
2323 unsigned vendorId = 0;
2324 PRUnichar *productIdUtf16 = NULL;
2325 char *productIdUtf8 = NULL;
2326 unsigned productId = 0;
2327 char *endptr = NULL;
2329 deviceFilter->vtbl->GetActive(deviceFilter, &active);
2333 def->hostdevs[USBFilterCount]->mode =
2334 VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
2335 def->hostdevs[USBFilterCount]->source.subsys.type =
2336 VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB;
2338 deviceFilter->vtbl->GetVendorId(deviceFilter, &vendorIdUtf16);
2339 deviceFilter->vtbl->GetProductId(deviceFilter, &productIdUtf16);
2341 VBOX_UTF16_TO_UTF8(vendorIdUtf16, &vendorIdUtf8);
2342 VBOX_UTF16_TO_UTF8(productIdUtf16, &productIdUtf8);
2344 vendorId = strtol(vendorIdUtf8, &endptr, 16);
2345 productId = strtol(productIdUtf8, &endptr, 16);
2347 def->hostdevs[USBFilterCount]->source.subsys.u.usb.vendor = vendorId;
2348 def->hostdevs[USBFilterCount]->source.subsys.u.usb.product = productId;
2350 VBOX_UTF16_FREE(vendorIdUtf16);
2351 VBOX_UTF8_FREE(vendorIdUtf8);
2353 VBOX_UTF16_FREE(productIdUtf16);
2354 VBOX_UTF8_FREE(productIdUtf8);
2360 vboxArrayRelease(&deviceFilters);
2361 #if VBOX_API_VERSION < 4003000
2363 VBOX_RELEASE(USBController);
2365 VBOX_RELEASE(USBDeviceFilters);
2371 for (i = 0; i < def->nhostdevs; i++)
2372 virDomainHostdevDefFree(def->hostdevs[i]);
2373 VIR_FREE(def->hostdevs);
2375 goto release_filters;
2378 static char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) {
2379 VBOX_OBJECT_CHECK(dom->conn, char *, NULL);
2380 virDomainDefPtr def = NULL;
2381 IMachine *machine = NULL;
2382 vboxIID iid = VBOX_IID_INITIALIZER;
2383 int gotAllABoutDef = -1;
2386 /* Flags checked by virDomainDefFormat */
2388 if (VIR_ALLOC(def) < 0)
2391 vboxIIDFromUUID(&iid, dom->uuid);
2392 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
2393 if (NS_SUCCEEDED(rc)) {
2394 PRBool accessible = PR_FALSE;
2396 machine->vtbl->GetAccessible(machine, &accessible);
2399 PRBool PAEEnabled = PR_FALSE;
2400 PRBool ACPIEnabled = PR_FALSE;
2401 PRBool IOAPICEnabled = PR_FALSE;
2402 PRBool VRDxEnabled = PR_FALSE;
2403 PRUint32 CPUCount = 0;
2404 PRUint32 memorySize = 0;
2405 PRUint32 netAdpCnt = 0;
2406 PRUint32 netAdpIncCnt = 0;
2407 PRUint32 maxMemorySize = 4 * 1024;
2408 PRUint32 maxBootPosition = 0;
2409 PRUint32 serialPortCount = 0;
2410 PRUint32 serialPortIncCount = 0;
2411 PRUint32 parallelPortCount = 0;
2412 PRUint32 parallelPortIncCount = 0;
2413 IBIOSSettings *bios = NULL;
2414 #if VBOX_API_VERSION < 3001000
2416 IDVDDrive *dvdDrive = NULL;
2417 IHardDisk *hardDiskPM = NULL;
2418 IHardDisk *hardDiskPS = NULL;
2419 IHardDisk *hardDiskSS = NULL;
2420 const char *hddBus = "IDE";
2421 PRUnichar *hddBusUtf16 = NULL;
2422 IFloppyDrive *floppyDrive = NULL;
2423 #else /* VBOX_API_VERSION >= 3001000 */
2424 vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER;
2425 #endif /* VBOX_API_VERSION >= 3001000 */
2426 #if VBOX_API_VERSION < 4000000
2427 IVRDPServer *VRDxServer = NULL;
2428 #else /* VBOX_API_VERSION >= 4000000 */
2429 IVRDEServer *VRDxServer = NULL;
2430 #endif /* VBOX_API_VERSION >= 4000000 */
2431 IAudioAdapter *audioAdapter = NULL;
2432 #if VBOX_API_VERSION >= 4001000
2433 PRUint32 chipsetType = ChipsetType_Null;
2434 #endif /* VBOX_API_VERSION >= 4001000 */
2435 ISystemProperties *systemProperties = NULL;
2438 def->virtType = VIR_DOMAIN_VIRT_VBOX;
2440 memcpy(def->uuid, dom->uuid, VIR_UUID_BUFLEN);
2441 if (VIR_STRDUP(def->name, dom->name) < 0)
2444 machine->vtbl->GetMemorySize(machine, &memorySize);
2445 def->mem.cur_balloon = memorySize * 1024;
2447 #if VBOX_API_VERSION >= 4001000
2448 machine->vtbl->GetChipsetType(machine, &chipsetType);
2449 #endif /* VBOX_API_VERSION >= 4001000 */
2451 data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties);
2452 if (systemProperties) {
2453 systemProperties->vtbl->GetMaxGuestRAM(systemProperties, &maxMemorySize);
2454 systemProperties->vtbl->GetMaxBootPosition(systemProperties, &maxBootPosition);
2455 #if VBOX_API_VERSION < 4001000
2456 systemProperties->vtbl->GetNetworkAdapterCount(systemProperties, &netAdpCnt);
2457 #else /* VBOX_API_VERSION >= 4000000 */
2458 systemProperties->vtbl->GetMaxNetworkAdapters(systemProperties, chipsetType, &netAdpCnt);
2459 #endif /* VBOX_API_VERSION >= 4000000 */
2460 systemProperties->vtbl->GetSerialPortCount(systemProperties, &serialPortCount);
2461 systemProperties->vtbl->GetParallelPortCount(systemProperties, ¶llelPortCount);
2462 VBOX_RELEASE(systemProperties);
2463 systemProperties = NULL;
2465 /* Currently setting memory and maxMemory as same, cause
2466 * the notation here seems to be inconsistent while
2467 * reading and while dumping xml
2469 /* def->mem.max_balloon = maxMemorySize * 1024; */
2470 def->mem.max_balloon = memorySize * 1024;
2472 machine->vtbl->GetCPUCount(machine, &CPUCount);
2473 def->maxvcpus = def->vcpus = CPUCount;
2475 /* Skip cpumasklen, cpumask, onReboot, onPoweroff, onCrash */
2477 if (VIR_STRDUP(def->os.type, "hvm") < 0)
2480 def->os.arch = virArchFromHost();
2482 def->os.nBootDevs = 0;
2483 for (i = 0; (i < VIR_DOMAIN_BOOT_LAST) && (i < maxBootPosition); i++) {
2484 PRUint32 device = DeviceType_Null;
2486 machine->vtbl->GetBootOrder(machine, i+1, &device);
2488 if (device == DeviceType_Floppy) {
2489 def->os.bootDevs[i] = VIR_DOMAIN_BOOT_FLOPPY;
2490 def->os.nBootDevs++;
2491 } else if (device == DeviceType_DVD) {
2492 def->os.bootDevs[i] = VIR_DOMAIN_BOOT_CDROM;
2493 def->os.nBootDevs++;
2494 } else if (device == DeviceType_HardDisk) {
2495 def->os.bootDevs[i] = VIR_DOMAIN_BOOT_DISK;
2496 def->os.nBootDevs++;
2497 } else if (device == DeviceType_Network) {
2498 def->os.bootDevs[i] = VIR_DOMAIN_BOOT_NET;
2499 def->os.nBootDevs++;
2500 } else if (device == DeviceType_USB) {
2501 /* Not supported by libvirt yet */
2502 } else if (device == DeviceType_SharedFolder) {
2503 /* Not supported by libvirt yet */
2504 /* Can VirtualBox really boot from a shared folder? */
2508 #if VBOX_API_VERSION < 3001000
2509 machine->vtbl->GetPAEEnabled(machine, &PAEEnabled);
2510 #elif VBOX_API_VERSION == 3001000
2511 machine->vtbl->GetCpuProperty(machine, CpuPropertyType_PAE, &PAEEnabled);
2512 #elif VBOX_API_VERSION >= 3002000
2513 machine->vtbl->GetCPUProperty(machine, CPUPropertyType_PAE, &PAEEnabled);
2516 def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_DOMAIN_FEATURE_STATE_ON;
2518 machine->vtbl->GetBIOSSettings(machine, &bios);
2520 bios->vtbl->GetACPIEnabled(bios, &ACPIEnabled);
2522 def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_DOMAIN_FEATURE_STATE_ON;
2524 bios->vtbl->GetIOAPICEnabled(bios, &IOAPICEnabled);
2526 def->features[VIR_DOMAIN_FEATURE_APIC] = VIR_DOMAIN_FEATURE_STATE_ON;
2531 /* Currently VirtualBox always uses locatime
2532 * so locatime is always true here */
2533 def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
2535 /* dump video options vram/2d/3d/directx/etc. */
2537 /* Currently supports only one graphics card */
2539 if (VIR_ALLOC_N(def->videos, def->nvideos) >= 0) {
2540 if (VIR_ALLOC(def->videos[0]) >= 0) {
2541 /* the default is: vram is 8MB, One monitor, 3dAccel Off */
2542 PRUint32 VRAMSize = 8;
2543 PRUint32 monitorCount = 1;
2544 PRBool accelerate3DEnabled = PR_FALSE;
2545 PRBool accelerate2DEnabled = PR_FALSE;
2547 machine->vtbl->GetVRAMSize(machine, &VRAMSize);
2548 machine->vtbl->GetMonitorCount(machine, &monitorCount);
2549 machine->vtbl->GetAccelerate3DEnabled(machine, &accelerate3DEnabled);
2550 #if VBOX_API_VERSION >= 3001000
2551 machine->vtbl->GetAccelerate2DVideoEnabled(machine, &accelerate2DEnabled);
2552 #endif /* VBOX_API_VERSION >= 3001000 */
2554 def->videos[0]->type = VIR_DOMAIN_VIDEO_TYPE_VBOX;
2555 def->videos[0]->vram = VRAMSize * 1024;
2556 def->videos[0]->heads = monitorCount;
2557 if (VIR_ALLOC(def->videos[0]->accel) >= 0) {
2558 def->videos[0]->accel->support3d = accelerate3DEnabled;
2559 def->videos[0]->accel->support2d = accelerate2DEnabled;
2565 /* dump display options vrdp/gui/sdl */
2567 int vrdpPresent = 0;
2570 int totalPresent = 0;
2571 char *guiDisplay = NULL;
2572 char *sdlDisplay = NULL;
2573 PRUnichar *keyTypeUtf16 = NULL;
2574 PRUnichar *valueTypeUtf16 = NULL;
2575 char *valueTypeUtf8 = NULL;
2579 VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16);
2580 machine->vtbl->GetExtraData(machine, keyTypeUtf16, &valueTypeUtf16);
2581 VBOX_UTF16_FREE(keyTypeUtf16);
2583 if (valueTypeUtf16) {
2584 VBOX_UTF16_TO_UTF8(valueTypeUtf16, &valueTypeUtf8);
2585 VBOX_UTF16_FREE(valueTypeUtf16);
2587 if (STREQ(valueTypeUtf8, "sdl") || STREQ(valueTypeUtf8, "gui")) {
2588 PRUnichar *keyDislpayUtf16 = NULL;
2589 PRUnichar *valueDisplayUtf16 = NULL;
2590 char *valueDisplayUtf8 = NULL;
2592 VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16);
2593 machine->vtbl->GetExtraData(machine, keyDislpayUtf16, &valueDisplayUtf16);
2594 VBOX_UTF16_FREE(keyDislpayUtf16);
2596 if (valueDisplayUtf16) {
2597 VBOX_UTF16_TO_UTF8(valueDisplayUtf16, &valueDisplayUtf8);
2598 VBOX_UTF16_FREE(valueDisplayUtf16);
2600 if (strlen(valueDisplayUtf8) <= 0)
2601 VBOX_UTF8_FREE(valueDisplayUtf8);
2604 if (STREQ(valueTypeUtf8, "sdl")) {
2606 if (VIR_STRDUP(sdlDisplay, valueDisplayUtf8) < 0) {
2607 /* just don't go to cleanup yet as it is ok to have
2608 * sdlDisplay as NULL and we check it below if it
2609 * exist and then only use it there
2615 if (STREQ(valueTypeUtf8, "gui")) {
2617 if (VIR_STRDUP(guiDisplay, valueDisplayUtf8) < 0) {
2618 /* just don't go to cleanup yet as it is ok to have
2619 * guiDisplay as NULL and we check it below if it
2620 * exist and then only use it there
2625 VBOX_UTF8_FREE(valueDisplayUtf8);
2628 if (STREQ(valueTypeUtf8, "vrdp"))
2631 VBOX_UTF8_FREE(valueTypeUtf8);
2634 if ((totalPresent > 0) && (VIR_ALLOC_N(def->graphics, totalPresent) >= 0)) {
2635 if ((guiPresent) && (VIR_ALLOC(def->graphics[def->ngraphics]) >= 0)) {
2636 def->graphics[def->ngraphics]->type = VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP;
2638 def->graphics[def->ngraphics]->data.desktop.display = guiDisplay;
2642 if ((sdlPresent) && (VIR_ALLOC(def->graphics[def->ngraphics]) >= 0)) {
2643 def->graphics[def->ngraphics]->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
2645 def->graphics[def->ngraphics]->data.sdl.display = sdlDisplay;
2648 } else if ((vrdpPresent != 1) && (totalPresent == 0) && (VIR_ALLOC_N(def->graphics, 1) >= 0)) {
2649 if (VIR_ALLOC(def->graphics[def->ngraphics]) >= 0) {
2651 def->graphics[def->ngraphics]->type = VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP;
2652 tmp = virGetEnvBlockSUID("DISPLAY");
2653 if (VIR_STRDUP(def->graphics[def->ngraphics]->data.desktop.display, tmp) < 0) {
2654 /* just don't go to cleanup yet as it is ok to have
2663 #if VBOX_API_VERSION < 4000000
2664 machine->vtbl->GetVRDPServer(machine, &VRDxServer);
2665 #else /* VBOX_API_VERSION >= 4000000 */
2666 machine->vtbl->GetVRDEServer(machine, &VRDxServer);
2667 #endif /* VBOX_API_VERSION >= 4000000 */
2669 VRDxServer->vtbl->GetEnabled(VRDxServer, &VRDxEnabled);
2674 if ((VIR_REALLOC_N(def->graphics, totalPresent) >= 0) &&
2675 (VIR_ALLOC(def->graphics[def->ngraphics]) >= 0)) {
2676 PRUnichar *netAddressUtf16 = NULL;
2677 char *netAddressUtf8 = NULL;
2678 PRBool allowMultiConnection = PR_FALSE;
2679 PRBool reuseSingleConnection = PR_FALSE;
2680 #if VBOX_API_VERSION < 3001000
2681 PRUint32 VRDPport = 0;
2682 VRDxServer->vtbl->GetPort(VRDxServer, &VRDPport);
2684 def->graphics[def->ngraphics]->data.rdp.port = VRDPport;
2686 def->graphics[def->ngraphics]->data.rdp.autoport = true;
2688 #elif VBOX_API_VERSION < 4000000 /* 3001000 <= VBOX_API_VERSION < 4000000 */
2689 PRUnichar *VRDPport = NULL;
2690 VRDxServer->vtbl->GetPorts(VRDxServer, &VRDPport);
2692 /* even if vbox supports mutilpe ports, single port for now here */
2693 def->graphics[def->ngraphics]->data.rdp.port = PRUnicharToInt(VRDPport);
2694 VBOX_UTF16_FREE(VRDPport);
2696 def->graphics[def->ngraphics]->data.rdp.autoport = true;
2698 #else /* VBOX_API_VERSION >= 4000000 */
2699 PRUnichar *VRDEPortsKey = NULL;
2700 PRUnichar *VRDEPortsValue = NULL;
2701 VBOX_UTF8_TO_UTF16("TCP/Ports", &VRDEPortsKey);
2702 VRDxServer->vtbl->GetVRDEProperty(VRDxServer, VRDEPortsKey, &VRDEPortsValue);
2703 VBOX_UTF16_FREE(VRDEPortsKey);
2704 if (VRDEPortsValue) {
2705 /* even if vbox supports mutilpe ports, single port for now here */
2706 def->graphics[def->ngraphics]->data.rdp.port = PRUnicharToInt(VRDEPortsValue);
2707 VBOX_UTF16_FREE(VRDEPortsValue);
2709 def->graphics[def->ngraphics]->data.rdp.autoport = true;
2711 #endif /* VBOX_API_VERSION >= 4000000 */
2713 def->graphics[def->ngraphics]->type = VIR_DOMAIN_GRAPHICS_TYPE_RDP;
2715 #if VBOX_API_VERSION >= 4000000
2716 PRUnichar *VRDENetAddressKey = NULL;
2717 VBOX_UTF8_TO_UTF16("TCP/Address", &VRDENetAddressKey);
2718 VRDxServer->vtbl->GetVRDEProperty(VRDxServer, VRDENetAddressKey, &netAddressUtf16);
2719 VBOX_UTF16_FREE(VRDENetAddressKey);
2720 #else /* VBOX_API_VERSION < 4000000 */
2721 VRDxServer->vtbl->GetNetAddress(VRDxServer, &netAddressUtf16);
2722 #endif /* VBOX_API_VERSION < 4000000 */
2723 if (netAddressUtf16) {
2724 VBOX_UTF16_TO_UTF8(netAddressUtf16, &netAddressUtf8);
2725 if (STRNEQ(netAddressUtf8, ""))
2726 virDomainGraphicsListenSetAddress(def->graphics[def->ngraphics], 0,
2727 netAddressUtf8, -1, true);
2728 VBOX_UTF16_FREE(netAddressUtf16);
2729 VBOX_UTF8_FREE(netAddressUtf8);
2732 VRDxServer->vtbl->GetAllowMultiConnection(VRDxServer, &allowMultiConnection);
2733 if (allowMultiConnection) {
2734 def->graphics[def->ngraphics]->data.rdp.multiUser = true;
2737 VRDxServer->vtbl->GetReuseSingleConnection(VRDxServer, &reuseSingleConnection);
2738 if (reuseSingleConnection) {
2739 def->graphics[def->ngraphics]->data.rdp.replaceUser = true;
2744 virReportOOMError();
2746 VBOX_RELEASE(VRDxServer);
2750 #if VBOX_API_VERSION < 3001000
2751 /* dump IDE hdds if present */
2752 VBOX_UTF8_TO_UTF16(hddBus, &hddBusUtf16);
2755 machine->vtbl->GetHardDisk(machine, hddBusUtf16, 0, 0, &hardDiskPM);
2759 machine->vtbl->GetHardDisk(machine, hddBusUtf16, 0, 1, &hardDiskPS);
2763 machine->vtbl->GetHardDisk(machine, hddBusUtf16, 1, 1, &hardDiskSS);
2767 VBOX_UTF16_FREE(hddBusUtf16);
2769 if ((def->ndisks > 0) && (VIR_ALLOC_N(def->disks, def->ndisks) >= 0)) {
2770 for (i = 0; i < def->ndisks; i++) {
2771 if (VIR_ALLOC(def->disks[i]) >= 0) {
2772 def->disks[i]->device = VIR_DOMAIN_DISK_DEVICE_DISK;
2773 def->disks[i]->bus = VIR_DOMAIN_DISK_BUS_IDE;
2774 virDomainDiskSetType(def->disks[i],
2775 VIR_STORAGE_TYPE_FILE);
2781 PRUnichar *hddlocationUtf16 = NULL;
2782 char *hddlocation = NULL;
2783 PRUint32 hddType = HardDiskType_Normal;
2785 hardDiskPM->vtbl->imedium.GetLocation((IMedium *)hardDiskPM, &hddlocationUtf16);
2786 VBOX_UTF16_TO_UTF8(hddlocationUtf16, &hddlocation);
2788 hardDiskPM->vtbl->GetType(hardDiskPM, &hddType);
2790 if (hddType == HardDiskType_Immutable)
2791 def->disks[hddNum]->readonly = true;
2792 ignore_value(virDomainDiskSetSource(def->disks[hddNum],
2794 ignore_value(VIR_STRDUP(def->disks[hddNum]->dst, "hda"));
2797 VBOX_UTF8_FREE(hddlocation);
2798 VBOX_UTF16_FREE(hddlocationUtf16);
2799 VBOX_MEDIUM_RELEASE(hardDiskPM);
2803 PRUnichar *hddlocationUtf16 = NULL;
2804 char *hddlocation = NULL;
2805 PRUint32 hddType = HardDiskType_Normal;
2807 hardDiskPS->vtbl->imedium.GetLocation((IMedium *)hardDiskPS, &hddlocationUtf16);
2808 VBOX_UTF16_TO_UTF8(hddlocationUtf16, &hddlocation);
2810 hardDiskPS->vtbl->GetType(hardDiskPS, &hddType);
2812 if (hddType == HardDiskType_Immutable)
2813 def->disks[hddNum]->readonly = true;
2814 ignore_value(virDomainDiskSetSource(def->disks[hddNum],
2816 ignore_value(VIR_STRDUP(def->disks[hddNum]->dst, "hdb"));
2819 VBOX_UTF8_FREE(hddlocation);
2820 VBOX_UTF16_FREE(hddlocationUtf16);
2821 VBOX_MEDIUM_RELEASE(hardDiskPS);
2825 PRUnichar *hddlocationUtf16 = NULL;
2826 char *hddlocation = NULL;
2827 PRUint32 hddType = HardDiskType_Normal;
2829 hardDiskSS->vtbl->imedium.GetLocation((IMedium *)hardDiskSS, &hddlocationUtf16);
2830 VBOX_UTF16_TO_UTF8(hddlocationUtf16, &hddlocation);
2832 hardDiskSS->vtbl->GetType(hardDiskSS, &hddType);
2834 if (hddType == HardDiskType_Immutable)
2835 def->disks[hddNum]->readonly = true;
2836 ignore_value(virDomainDiskSetSource(def->disks[hddNum],
2838 ignore_value(VIR_STRDUP(def->disks[hddNum]->dst, "hdd"));
2841 VBOX_UTF8_FREE(hddlocation);
2842 VBOX_UTF16_FREE(hddlocationUtf16);
2843 VBOX_MEDIUM_RELEASE(hardDiskSS);
2845 #else /* VBOX_API_VERSION >= 3001000 */
2846 /* dump IDE hdds if present */
2850 PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {};
2851 PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {};
2853 vboxArrayGet(&mediumAttachments, machine, machine->vtbl->GetMediumAttachments);
2855 /* get the number of attachments */
2856 for (i = 0; i < mediumAttachments.count; i++) {
2857 IMediumAttachment *imediumattach = mediumAttachments.items[i];
2858 if (imediumattach) {
2859 IMedium *medium = NULL;
2861 imediumattach->vtbl->GetMedium(imediumattach, &medium);
2864 VBOX_RELEASE(medium);
2869 /* Allocate mem, if fails return error */
2870 if (VIR_ALLOC_N(def->disks, def->ndisks) >= 0) {
2871 for (i = 0; i < def->ndisks; i++) {
2872 if (VIR_ALLOC(def->disks[i]) < 0) {
2882 error = !vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, maxSlotPerPort);
2884 /* get the attachment details here */
2885 for (i = 0; i < mediumAttachments.count && diskCount < def->ndisks && !error; i++) {
2886 IMediumAttachment *imediumattach = mediumAttachments.items[i];
2887 IStorageController *storageController = NULL;
2888 PRUnichar *storageControllerName = NULL;
2889 PRUint32 deviceType = DeviceType_Null;
2890 PRUint32 storageBus = StorageBus_Null;
2891 PRBool readOnly = PR_FALSE;
2892 IMedium *medium = NULL;
2893 PRUnichar *mediumLocUtf16 = NULL;
2894 char *mediumLocUtf8 = NULL;
2895 PRUint32 deviceInst = 0;
2896 PRInt32 devicePort = 0;
2897 PRInt32 deviceSlot = 0;
2902 imediumattach->vtbl->GetMedium(imediumattach, &medium);
2906 imediumattach->vtbl->GetController(imediumattach, &storageControllerName);
2907 if (!storageControllerName) {
2908 VBOX_RELEASE(medium);
2912 machine->vtbl->GetStorageControllerByName(machine,
2913 storageControllerName,
2914 &storageController);
2915 VBOX_UTF16_FREE(storageControllerName);
2916 if (!storageController) {
2917 VBOX_RELEASE(medium);
2921 medium->vtbl->GetLocation(medium, &mediumLocUtf16);
2922 VBOX_UTF16_TO_UTF8(mediumLocUtf16, &mediumLocUtf8);
2923 VBOX_UTF16_FREE(mediumLocUtf16);
2924 ignore_value(virDomainDiskSetSource(def->disks[diskCount],
2926 VBOX_UTF8_FREE(mediumLocUtf8);
2928 if (!virDomainDiskGetSource(def->disks[diskCount])) {
2929 VBOX_RELEASE(medium);
2930 VBOX_RELEASE(storageController);
2935 storageController->vtbl->GetBus(storageController, &storageBus);
2936 if (storageBus == StorageBus_IDE) {
2937 def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_IDE;
2938 } else if (storageBus == StorageBus_SATA) {
2939 def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SATA;
2940 } else if (storageBus == StorageBus_SCSI) {
2941 def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_SCSI;
2942 } else if (storageBus == StorageBus_Floppy) {
2943 def->disks[diskCount]->bus = VIR_DOMAIN_DISK_BUS_FDC;
2946 imediumattach->vtbl->GetType(imediumattach, &deviceType);
2947 if (deviceType == DeviceType_HardDisk)
2948 def->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_DISK;
2949 else if (deviceType == DeviceType_Floppy)
2950 def->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
2951 else if (deviceType == DeviceType_DVD)
2952 def->disks[diskCount]->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
2954 imediumattach->vtbl->GetPort(imediumattach, &devicePort);
2955 imediumattach->vtbl->GetDevice(imediumattach, &deviceSlot);
2956 def->disks[diskCount]->dst = vboxGenerateMediumName(storageBus,
2962 if (!def->disks[diskCount]->dst) {
2963 virReportError(VIR_ERR_INTERNAL_ERROR,
2964 _("Could not generate medium name for the disk "
2965 "at: controller instance:%u, port:%d, slot:%d"),
2966 deviceInst, devicePort, deviceSlot);
2967 VBOX_RELEASE(medium);
2968 VBOX_RELEASE(storageController);
2973 medium->vtbl->GetReadOnly(medium, &readOnly);
2974 if (readOnly == PR_TRUE)
2975 def->disks[diskCount]->readonly = true;
2977 virDomainDiskSetType(def->disks[diskCount],
2978 VIR_STORAGE_TYPE_FILE);
2980 VBOX_RELEASE(medium);
2981 VBOX_RELEASE(storageController);
2985 vboxArrayRelease(&mediumAttachments);
2987 /* cleanup on error */
2989 for (i = 0; i < def->ndisks; i++) {
2990 VIR_FREE(def->disks[i]);
2992 VIR_FREE(def->disks);
2996 #endif /* VBOX_API_VERSION >= 3001000 */
2998 /* shared folders */
2999 vboxArray sharedFolders = VBOX_ARRAY_INITIALIZER;
3003 vboxArrayGet(&sharedFolders, machine,
3004 machine->vtbl->GetSharedFolders);
3006 if (sharedFolders.count > 0) {
3007 if (VIR_ALLOC_N(def->fss, sharedFolders.count) < 0)
3008 goto sharedFoldersCleanup;
3010 for (i = 0; i < sharedFolders.count; i++) {
3011 ISharedFolder *sharedFolder = sharedFolders.items[i];
3012 PRUnichar *nameUtf16 = NULL;
3014 PRUnichar *hostPathUtf16 = NULL;
3015 char *hostPath = NULL;
3016 PRBool writable = PR_FALSE;
3018 if (VIR_ALLOC(def->fss[i]) < 0)
3019 goto sharedFoldersCleanup;
3021 def->fss[i]->type = VIR_DOMAIN_FS_TYPE_MOUNT;
3023 sharedFolder->vtbl->GetHostPath(sharedFolder, &hostPathUtf16);
3024 VBOX_UTF16_TO_UTF8(hostPathUtf16, &hostPath);
3025 if (VIR_STRDUP(def->fss[i]->src, hostPath) < 0) {
3026 VBOX_UTF8_FREE(hostPath);
3027 VBOX_UTF16_FREE(hostPathUtf16);
3028 goto sharedFoldersCleanup;
3030 VBOX_UTF8_FREE(hostPath);
3031 VBOX_UTF16_FREE(hostPathUtf16);
3033 sharedFolder->vtbl->GetName(sharedFolder, &nameUtf16);
3034 VBOX_UTF16_TO_UTF8(nameUtf16, &name);
3035 if (VIR_STRDUP(def->fss[i]->dst, name) < 0) {
3036 VBOX_UTF8_FREE(name);
3037 VBOX_UTF16_FREE(nameUtf16);
3038 goto sharedFoldersCleanup;
3040 VBOX_UTF8_FREE(name);
3041 VBOX_UTF16_FREE(nameUtf16);
3043 sharedFolder->vtbl->GetWritable(sharedFolder, &writable);
3044 def->fss[i]->readonly = !writable;
3050 sharedFoldersCleanup:
3051 vboxArrayRelease(&sharedFolders);
3053 /* dump network cards if present */
3055 /* Get which network cards are enabled */
3056 for (i = 0; i < netAdpCnt; i++) {
3057 INetworkAdapter *adapter = NULL;
3059 machine->vtbl->GetNetworkAdapter(machine, i, &adapter);
3061 PRBool enabled = PR_FALSE;
3063 adapter->vtbl->GetEnabled(adapter, &enabled);
3068 VBOX_RELEASE(adapter);
3072 /* Allocate memory for the networkcards which are enabled */
3073 if ((def->nnets > 0) && (VIR_ALLOC_N(def->nets, def->nnets) >= 0)) {
3074 for (i = 0; i < def->nnets; i++) {
3075 ignore_value(VIR_ALLOC(def->nets[i]));
3079 /* Now get the details about the network cards here */
3080 for (i = 0; netAdpIncCnt < def->nnets && i < netAdpCnt; i++) {
3081 INetworkAdapter *adapter = NULL;
3083 machine->vtbl->GetNetworkAdapter(machine, i, &adapter);
3085 PRBool enabled = PR_FALSE;
3087 adapter->vtbl->GetEnabled(adapter, &enabled);
3089 PRUint32 attachmentType = NetworkAttachmentType_Null;
3090 PRUint32 adapterType = NetworkAdapterType_Null;
3091 PRUnichar *MACAddressUtf16 = NULL;
3092 char *MACAddress = NULL;
3093 char macaddr[VIR_MAC_STRING_BUFLEN] = {0};
3095 adapter->vtbl->GetAttachmentType(adapter, &attachmentType);
3096 if (attachmentType == NetworkAttachmentType_NAT) {
3098 def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_USER;
3100 } else if (attachmentType == NetworkAttachmentType_Bridged) {
3101 PRUnichar *hostIntUtf16 = NULL;
3102 char *hostInt = NULL;
3104 def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
3106 #if VBOX_API_VERSION < 4001000
3107 adapter->vtbl->GetHostInterface(adapter, &hostIntUtf16);
3108 #else /* VBOX_API_VERSION >= 4001000 */
3109 adapter->vtbl->GetBridgedInterface(adapter, &hostIntUtf16);
3110 #endif /* VBOX_API_VERSION >= 4001000 */
3112 VBOX_UTF16_TO_UTF8(hostIntUtf16, &hostInt);
3113 ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->data.bridge.brname, hostInt));
3115 VBOX_UTF8_FREE(hostInt);
3116 VBOX_UTF16_FREE(hostIntUtf16);
3118 } else if (attachmentType == NetworkAttachmentType_Internal) {
3119 PRUnichar *intNetUtf16 = NULL;
3120 char *intNet = NULL;
3122 def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_INTERNAL;
3124 adapter->vtbl->GetInternalNetwork(adapter, &intNetUtf16);
3126 VBOX_UTF16_TO_UTF8(intNetUtf16, &intNet);
3127 ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->data.internal.name, intNet));
3129 VBOX_UTF8_FREE(intNet);
3130 VBOX_UTF16_FREE(intNetUtf16);
3132 } else if (attachmentType == NetworkAttachmentType_HostOnly) {
3133 PRUnichar *hostIntUtf16 = NULL;
3134 char *hostInt = NULL;
3136 def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_NETWORK;
3138 #if VBOX_API_VERSION < 4001000
3139 adapter->vtbl->GetHostInterface(adapter, &hostIntUtf16);
3140 #else /* VBOX_API_VERSION >= 4001000 */
3141 adapter->vtbl->GetHostOnlyInterface(adapter, &hostIntUtf16);
3142 #endif /* VBOX_API_VERSION >= 4001000 */
3144 VBOX_UTF16_TO_UTF8(hostIntUtf16, &hostInt);
3145 ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->data.network.name, hostInt));
3147 VBOX_UTF8_FREE(hostInt);
3148 VBOX_UTF16_FREE(hostIntUtf16);
3151 /* default to user type i.e. NAT in VirtualBox if this
3152 * dump is ever used to create a machine.
3154 def->nets[netAdpIncCnt]->type = VIR_DOMAIN_NET_TYPE_USER;
3157 adapter->vtbl->GetAdapterType(adapter, &adapterType);
3158 if (adapterType == NetworkAdapterType_Am79C970A) {
3159 ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "Am79C970A"));
3160 } else if (adapterType == NetworkAdapterType_Am79C973) {
3161 ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "Am79C973"));
3162 } else if (adapterType == NetworkAdapterType_I82540EM) {
3163 ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "82540EM"));
3164 } else if (adapterType == NetworkAdapterType_I82545EM) {
3165 ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "82545EM"));
3166 } else if (adapterType == NetworkAdapterType_I82543GC) {
3167 ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "82543GC"));
3168 #if VBOX_API_VERSION >= 3001000
3169 } else if (adapterType == NetworkAdapterType_Virtio) {
3170 ignore_value(VIR_STRDUP(def->nets[netAdpIncCnt]->model, "virtio"));
3171 #endif /* VBOX_API_VERSION >= 3001000 */
3174 adapter->vtbl->GetMACAddress(adapter, &MACAddressUtf16);
3175 VBOX_UTF16_TO_UTF8(MACAddressUtf16, &MACAddress);
3176 snprintf(macaddr, VIR_MAC_STRING_BUFLEN,
3177 "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c",
3178 MACAddress[0], MACAddress[1], MACAddress[2], MACAddress[3],
3179 MACAddress[4], MACAddress[5], MACAddress[6], MACAddress[7],
3180 MACAddress[8], MACAddress[9], MACAddress[10], MACAddress[11]);
3182 /* XXX some real error handling here some day ... */
3183 if (virMacAddrParse(macaddr, &def->nets[netAdpIncCnt]->mac) < 0)
3188 VBOX_UTF16_FREE(MACAddressUtf16);
3189 VBOX_UTF8_FREE(MACAddress);
3192 VBOX_RELEASE(adapter);
3196 /* dump sound card if active */
3198 /* Set def->nsounds to one as VirtualBox currently supports
3199 * only one sound card
3202 machine->vtbl->GetAudioAdapter(machine, &audioAdapter);
3204 PRBool enabled = PR_FALSE;
3206 audioAdapter->vtbl->GetEnabled(audioAdapter, &enabled);
3208 PRUint32 audioController = AudioControllerType_AC97;
3211 if (VIR_ALLOC_N(def->sounds, def->nsounds) >= 0) {
3212 if (VIR_ALLOC(def->sounds[0]) >= 0) {
3213 audioAdapter->vtbl->GetAudioController(audioAdapter, &audioController);
3214 if (audioController == AudioControllerType_SB16) {
3215 def->sounds[0]->model = VIR_DOMAIN_SOUND_MODEL_SB16;
3216 } else if (audioController == AudioControllerType_AC97) {
3217 def->sounds[0]->model = VIR_DOMAIN_SOUND_MODEL_AC97;
3220 VIR_FREE(def->sounds);
3227 VBOX_RELEASE(audioAdapter);
3230 #if VBOX_API_VERSION < 3001000
3231 /* dump CDROM/DVD if the drive is attached and has DVD/CD in it */
3232 machine->vtbl->GetDVDDrive(machine, &dvdDrive);
3234 PRUint32 state = DriveState_Null;
3236 dvdDrive->vtbl->GetState(dvdDrive, &state);
3237 if (state == DriveState_ImageMounted) {
3238 IDVDImage *dvdImage = NULL;
3240 dvdDrive->vtbl->GetImage(dvdDrive, &dvdImage);
3242 PRUnichar *locationUtf16 = NULL;
3243 char *location = NULL;
3245 dvdImage->vtbl->imedium.GetLocation((IMedium *)dvdImage, &locationUtf16);
3246 VBOX_UTF16_TO_UTF8(locationUtf16, &location);
3249 if (VIR_REALLOC_N(def->disks, def->ndisks) >= 0) {
3250 if (VIR_ALLOC(def->disks[def->ndisks - 1]) >= 0) {
3251 def->disks[def->ndisks - 1]->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
3252 def->disks[def->ndisks - 1]->bus = VIR_DOMAIN_DISK_BUS_IDE;
3253 virDomainDiskSetType(def->disks[def->ndisks - 1],
3254 VIR_STORAGE_TYPE_FILE);
3255 def->disks[def->ndisks - 1]->readonly = true;
3256 ignore_value(virDomainDiskSetSource(def->disks[def->ndisks - 1], location));
3257 ignore_value(VIR_STRDUP(def->disks[def->ndisks - 1]->dst, "hdc"));
3266 VBOX_UTF8_FREE(location);
3267 VBOX_UTF16_FREE(locationUtf16);
3268 VBOX_MEDIUM_RELEASE(dvdImage);
3271 VBOX_RELEASE(dvdDrive);
3274 /* dump Floppy if the drive is attached and has floppy in it */
3275 machine->vtbl->GetFloppyDrive(machine, &floppyDrive);
3277 PRBool enabled = PR_FALSE;
3279 floppyDrive->vtbl->GetEnabled(floppyDrive, &enabled);
3281 PRUint32 state = DriveState_Null;
3283 floppyDrive->vtbl->GetState(floppyDrive, &state);
3284 if (state == DriveState_ImageMounted) {
3285 IFloppyImage *floppyImage = NULL;
3287 floppyDrive->vtbl->GetImage(floppyDrive, &floppyImage);
3289 PRUnichar *locationUtf16 = NULL;
3290 char *location = NULL;
3292 floppyImage->vtbl->imedium.GetLocation((IMedium *)floppyImage, &locationUtf16);
3293 VBOX_UTF16_TO_UTF8(locationUtf16, &location);
3296 if (VIR_REALLOC_N(def->disks, def->ndisks) >= 0) {
3297 if (VIR_ALLOC(def->disks[def->ndisks - 1]) >= 0) {
3298 def->disks[def->ndisks - 1]->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
3299 def->disks[def->ndisks - 1]->bus = VIR_DOMAIN_DISK_BUS_FDC;
3300 virDomainDiskSetType(def->disks[def->ndisks - 1],
3301 VIR_STORAGE_TYPE_FILE);
3302 def->disks[def->ndisks - 1]->readonly = false;
3303 ignore_value(virDomainDiskSetSource(def->disks[def->ndisks - 1], location));
3304 ignore_value(VIR_STRDUP(def->disks[def->ndisks - 1]->dst, "fda"));
3313 VBOX_UTF8_FREE(location);
3314 VBOX_UTF16_FREE(locationUtf16);
3315 VBOX_MEDIUM_RELEASE(floppyImage);
3320 VBOX_RELEASE(floppyDrive);
3322 #else /* VBOX_API_VERSION >= 3001000 */
3323 #endif /* VBOX_API_VERSION >= 3001000 */
3325 /* dump serial port if active */
3327 /* Get which serial ports are enabled/active */
3328 for (i = 0; i < serialPortCount; i++) {
3329 ISerialPort *serialPort = NULL;
3331 machine->vtbl->GetSerialPort(machine, i, &serialPort);
3333 PRBool enabled = PR_FALSE;
3335 serialPort->vtbl->GetEnabled(serialPort, &enabled);
3340 VBOX_RELEASE(serialPort);
3344 /* Allocate memory for the serial ports which are enabled */
3345 if ((def->nserials > 0) && (VIR_ALLOC_N(def->serials, def->nserials) >= 0)) {
3346 for (i = 0; i < def->nserials; i++) {
3347 ignore_value(VIR_ALLOC(def->serials[i]));
3351 /* Now get the details about the serial ports here */
3353 serialPortIncCount < def->nserials && i < serialPortCount;
3355 ISerialPort *serialPort = NULL;
3357 machine->vtbl->GetSerialPort(machine, i, &serialPort);
3359 PRBool enabled = PR_FALSE;
3361 serialPort->vtbl->GetEnabled(serialPort, &enabled);
3363 PRUint32 hostMode = PortMode_Disconnected;
3364 PRUint32 IOBase = 0;
3366 PRUnichar *pathUtf16 = NULL;
3369 serialPort->vtbl->GetHostMode(serialPort, &hostMode);
3370 if (hostMode == PortMode_HostPipe) {
3371 def->serials[serialPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_PIPE;
3372 } else if (hostMode == PortMode_HostDevice) {
3373 def->serials[serialPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_DEV;
3374 #if VBOX_API_VERSION >= 3000000
3375 } else if (hostMode == PortMode_RawFile) {
3376 def->serials[serialPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_FILE;
3377 #endif /* VBOX_API_VERSION >= 3000000 */
3379 def->serials[serialPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_NULL;
3382 def->serials[serialPortIncCount]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
3384 serialPort->vtbl->GetIRQ(serialPort, &IRQ);
3385 serialPort->vtbl->GetIOBase(serialPort, &IOBase);
3386 if ((IRQ == 4) && (IOBase == 1016)) {
3387 def->serials[serialPortIncCount]->target.port = 0;
3388 } else if ((IRQ == 3) && (IOBase == 760)) {
3389 def->serials[serialPortIncCount]->target.port = 1;
3392 serialPort->vtbl->GetPath(serialPort, &pathUtf16);
3395 VBOX_UTF16_TO_UTF8(pathUtf16, &path);
3396 ignore_value(VIR_STRDUP(def->serials[serialPortIncCount]->source.data.file.path, path));
3399 serialPortIncCount++;
3401 VBOX_UTF16_FREE(pathUtf16);
3402 VBOX_UTF8_FREE(path);
3405 VBOX_RELEASE(serialPort);
3409 /* dump parallel ports if active */
3410 def->nparallels = 0;
3411 /* Get which parallel ports are enabled/active */
3412 for (i = 0; i < parallelPortCount; i++) {
3413 IParallelPort *parallelPort = NULL;
3415 machine->vtbl->GetParallelPort(machine, i, ¶llelPort);
3417 PRBool enabled = PR_FALSE;
3419 parallelPort->vtbl->GetEnabled(parallelPort, &enabled);
3424 VBOX_RELEASE(parallelPort);
3428 /* Allocate memory for the parallel ports which are enabled */
3429 if ((def->nparallels > 0) && (VIR_ALLOC_N(def->parallels, def->nparallels) >= 0)) {
3430 for (i = 0; i < def->nparallels; i++) {
3431 ignore_value(VIR_ALLOC(def->parallels[i]));
3435 /* Now get the details about the parallel ports here */
3437 parallelPortIncCount < def->nparallels &&
3438 i < parallelPortCount;
3440 IParallelPort *parallelPort = NULL;
3442 machine->vtbl->GetParallelPort(machine, i, ¶llelPort);
3444 PRBool enabled = PR_FALSE;
3446 parallelPort->vtbl->GetEnabled(parallelPort, &enabled);
3448 PRUint32 IOBase = 0;
3450 PRUnichar *pathUtf16 = NULL;
3453 parallelPort->vtbl->GetIRQ(parallelPort, &IRQ);
3454 parallelPort->vtbl->GetIOBase(parallelPort, &IOBase);
3455 if ((IRQ == 7) && (IOBase == 888)) {
3456 def->parallels[parallelPortIncCount]->target.port = 0;
3457 } else if ((IRQ == 5) && (IOBase == 632)) {
3458 def->parallels[parallelPortIncCount]->target.port = 1;
3461 def->parallels[parallelPortIncCount]->source.type = VIR_DOMAIN_CHR_TYPE_FILE;
3462 def->parallels[parallelPortIncCount]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL;
3464 parallelPort->vtbl->GetPath(parallelPort, &pathUtf16);
3466 VBOX_UTF16_TO_UTF8(pathUtf16, &path);
3467 ignore_value(VIR_STRDUP(def->parallels[parallelPortIncCount]->source.data.file.path, path));
3469 parallelPortIncCount++;
3471 VBOX_UTF16_FREE(pathUtf16);
3472 VBOX_UTF8_FREE(path);
3475 VBOX_RELEASE(parallelPort);
3479 /* dump USB devices/filters if active */
3480 vboxHostDeviceGetXMLDesc(data, def, machine);
3482 /* all done so set gotAllABoutDef and pass def to virDomainDefFormat
3483 * to generate XML for it
3487 VBOX_RELEASE(machine);
3491 if (gotAllABoutDef == 0)
3492 ret = virDomainDefFormat(def, flags);
3495 vboxIIDUnalloc(&iid);
3496 virDomainDefFree(def);
3500 static int vboxConnectListDefinedDomains(virConnectPtr conn, char ** const names, int maxnames) {
3501 VBOX_OBJECT_CHECK(conn, int, -1);
3502 vboxArray machines = VBOX_ARRAY_INITIALIZER;
3503 char *machineName = NULL;
3504 PRUnichar *machineNameUtf16 = NULL;
3509 rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines);
3510 if (NS_FAILED(rc)) {
3511 virReportError(VIR_ERR_INTERNAL_ERROR,
3512 _("Could not get list of Defined Domains, rc=%08x"),
3517 memset(names, 0, sizeof(names[i]) * maxnames);
3520 for (i = 0, j = 0; (i < machines.count) && (j < maxnames); i++) {
3521 IMachine *machine = machines.items[i];
3524 PRBool isAccessible = PR_FALSE;
3525 machine->vtbl->GetAccessible(machine, &isAccessible);
3527 machine->vtbl->GetState(machine, &state);
3528 if ((state < MachineState_FirstOnline) ||
3529 (state > MachineState_LastOnline)) {
3530 machine->vtbl->GetName(machine, &machineNameUtf16);
3531 VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineName);
3532 if (VIR_STRDUP(names[j], machineName) < 0) {
3533 VBOX_UTF16_FREE(machineNameUtf16);
3534 VBOX_UTF8_FREE(machineName);
3535 for (j = 0; j < maxnames; j++)
3540 VBOX_UTF16_FREE(machineNameUtf16);
3541 VBOX_UTF8_FREE(machineName);
3550 vboxArrayRelease(&machines);
3554 static int vboxConnectNumOfDefinedDomains(virConnectPtr conn)
3556 VBOX_OBJECT_CHECK(conn, int, -1);
3557 vboxArray machines = VBOX_ARRAY_INITIALIZER;
3558 PRUint32 state = MachineState_Null;
3562 rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines);
3563 if (NS_FAILED(rc)) {
3564 virReportError(VIR_ERR_INTERNAL_ERROR,
3565 _("Could not get number of Defined Domains, rc=%08x"),
3571 for (i = 0; i < machines.count; ++i) {
3572 IMachine *machine = machines.items[i];
3575 PRBool isAccessible = PR_FALSE;
3576 machine->vtbl->GetAccessible(machine, &isAccessible);
3578 machine->vtbl->GetState(machine, &state);
3579 if ((state < MachineState_FirstOnline) ||
3580 (state > MachineState_LastOnline)) {
3588 vboxArrayRelease(&machines);
3594 vboxStartMachine(virDomainPtr dom, int maxDomID, IMachine *machine,
3595 vboxIID *iid ATTRIBUTE_UNUSED /* >= 4.0 */)
3597 VBOX_OBJECT_CHECK(dom->conn, int, -1);
3598 int vrdpPresent = 0;
3601 char *guiDisplay = NULL;
3602 char *sdlDisplay = NULL;
3603 PRUnichar *keyTypeUtf16 = NULL;
3604 PRUnichar *valueTypeUtf16 = NULL;
3605 char *valueTypeUtf8 = NULL;
3606 PRUnichar *keyDislpayUtf16 = NULL;
3607 PRUnichar *valueDisplayUtf16 = NULL;
3608 char *valueDisplayUtf8 = NULL;
3609 IProgress *progress = NULL;
3610 PRUnichar *env = NULL;
3611 PRUnichar *sessionType = NULL;
3614 VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16);
3615 machine->vtbl->GetExtraData(machine, keyTypeUtf16, &valueTypeUtf16);
3616 VBOX_UTF16_FREE(keyTypeUtf16);
3618 if (valueTypeUtf16) {
3619 VBOX_UTF16_TO_UTF8(valueTypeUtf16, &valueTypeUtf8);
3620 VBOX_UTF16_FREE(valueTypeUtf16);
3622 if (STREQ(valueTypeUtf8, "sdl") || STREQ(valueTypeUtf8, "gui")) {
3624 VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16);
3625 machine->vtbl->GetExtraData(machine, keyDislpayUtf16,
3626 &valueDisplayUtf16);
3627 VBOX_UTF16_FREE(keyDislpayUtf16);
3629 if (valueDisplayUtf16) {
3630 VBOX_UTF16_TO_UTF8(valueDisplayUtf16, &valueDisplayUtf8);
3631 VBOX_UTF16_FREE(valueDisplayUtf16);
3633 if (strlen(valueDisplayUtf8) <= 0)
3634 VBOX_UTF8_FREE(valueDisplayUtf8);
3637 if (STREQ(valueTypeUtf8, "sdl")) {
3639 if (VIR_STRDUP(sdlDisplay, valueDisplayUtf8) < 0) {
3640 /* just don't go to cleanup yet as it is ok to have
3641 * sdlDisplay as NULL and we check it below if it
3642 * exist and then only use it there
3647 if (STREQ(valueTypeUtf8, "gui")) {
3649 if (VIR_STRDUP(guiDisplay, valueDisplayUtf8) < 0) {
3650 /* just don't go to cleanup yet as it is ok to have
3651 * guiDisplay as NULL and we check it below if it
3652 * exist and then only use it there
3658 if (STREQ(valueTypeUtf8, "vrdp")) {
3662 if (!vrdpPresent && !sdlPresent && !guiPresent) {
3663 /* if nothing is selected it means either the machine xml
3664 * file is really old or some values are missing so fallback
3669 VBOX_UTF8_FREE(valueTypeUtf8);
3674 VBOX_UTF8_FREE(valueDisplayUtf8);
3679 if (virAsprintf(&displayutf8, "DISPLAY=%s", guiDisplay) >= 0) {
3680 VBOX_UTF8_TO_UTF16(displayutf8, &env);
3681 VIR_FREE(displayutf8);
3683 VIR_FREE(guiDisplay);
3686 VBOX_UTF8_TO_UTF16("gui", &sessionType);
3692 if (virAsprintf(&displayutf8, "DISPLAY=%s", sdlDisplay) >= 0) {
3693 VBOX_UTF8_TO_UTF16(displayutf8, &env);
3694 VIR_FREE(displayutf8);
3696 VIR_FREE(sdlDisplay);
3699 VBOX_UTF8_TO_UTF16("sdl", &sessionType);
3703 VBOX_UTF8_TO_UTF16("vrdp", &sessionType);
3706 #if VBOX_API_VERSION < 4000000
3707 rc = data->vboxObj->vtbl->OpenRemoteSession(data->vboxObj,
3713 #else /* VBOX_API_VERSION >= 4000000 */
3714 rc = machine->vtbl->LaunchVMProcess(machine, data->vboxSession,
3715 sessionType, env, &progress);
3716 #endif /* VBOX_API_VERSION >= 4000000 */
3718 if (NS_FAILED(rc)) {
3719 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3720 _("OpenRemoteSession/LaunchVMProcess failed, domain can't be started"));
3723 PRBool completed = 0;
3724 #if VBOX_API_VERSION == 2002000
3725 nsresult resultCode;
3729 progress->vtbl->WaitForCompletion(progress, -1);
3730 rc = progress->vtbl->GetCompleted(progress, &completed);
3731 if (NS_FAILED(rc)) {
3735 progress->vtbl->GetResultCode(progress, &resultCode);
3736 if (NS_FAILED(resultCode)) {
3740 /* all ok set the domid */
3741 dom->id = maxDomID + 1;
3746 VBOX_RELEASE(progress);
3748 VBOX_SESSION_CLOSE();
3750 VBOX_UTF16_FREE(env);
3751 VBOX_UTF16_FREE(sessionType);
3756 static int vboxDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
3758 VBOX_OBJECT_CHECK(dom->conn, int, -1);
3759 vboxArray machines = VBOX_ARRAY_INITIALIZER;
3760 unsigned char uuid[VIR_UUID_BUFLEN] = {0};
3764 virCheckFlags(0, -1);
3767 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3768 _("Error while reading the domain name"));
3772 rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines);
3773 if (NS_FAILED(rc)) {
3774 virReportError(VIR_ERR_INTERNAL_ERROR,
3775 _("Could not get list of machines, rc=%08x"), (unsigned)rc);
3779 for (i = 0; i < machines.count; ++i) {
3780 IMachine *machine = machines.items[i];
3781 PRBool isAccessible = PR_FALSE;
3786 machine->vtbl->GetAccessible(machine, &isAccessible);
3788 vboxIID iid = VBOX_IID_INITIALIZER;
3790 rc = machine->vtbl->GetId(machine, &iid.value);
3793 vboxIIDToUUID(&iid, uuid);
3795 if (memcmp(dom->uuid, uuid, VIR_UUID_BUFLEN) == 0) {
3796 PRUint32 state = MachineState_Null;
3797 machine->vtbl->GetState(machine, &state);
3799 if ((state == MachineState_PoweredOff) ||
3800 (state == MachineState_Saved) ||
3801 (state == MachineState_Aborted)) {
3802 ret = vboxStartMachine(dom, i, machine, &iid);
3804 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3805 _("machine is not in "
3806 "poweroff|saved|aborted state, so "
3807 "couldn't start it"));
3811 vboxIIDUnalloc(&iid);
3817 /* Do the cleanup and take care you dont leak any memory */
3818 vboxArrayRelease(&machines);
3824 static int vboxDomainCreate(virDomainPtr dom)
3826 return vboxDomainCreateWithFlags(dom, 0);
3830 vboxSetBootDeviceOrder(virDomainDefPtr def, vboxGlobalData *data,
3833 ISystemProperties *systemProperties = NULL;
3834 PRUint32 maxBootPosition = 0;
3837 VIR_DEBUG("def->os.type %s", def->os.type);
3838 VIR_DEBUG("def->os.arch %s", virArchToString(def->os.arch));
3839 VIR_DEBUG("def->os.machine %s", def->os.machine);
3840 VIR_DEBUG("def->os.nBootDevs %zu", def->os.nBootDevs);
3841 VIR_DEBUG("def->os.bootDevs[0] %d", def->os.bootDevs[0]);
3842 VIR_DEBUG("def->os.bootDevs[1] %d", def->os.bootDevs[1]);
3843 VIR_DEBUG("def->os.bootDevs[2] %d", def->os.bootDevs[2]);
3844 VIR_DEBUG("def->os.bootDevs[3] %d", def->os.bootDevs[3]);
3845 VIR_DEBUG("def->os.init %s", def->os.init);
3846 VIR_DEBUG("def->os.kernel %s", def->os.kernel);
3847 VIR_DEBUG("def->os.initrd %s", def->os.initrd);
3848 VIR_DEBUG("def->os.cmdline %s", def->os.cmdline);
3849 VIR_DEBUG("def->os.root %s", def->os.root);
3850 VIR_DEBUG("def->os.loader %s", def->os.loader);
3851 VIR_DEBUG("def->os.bootloader %s", def->os.bootloader);
3852 VIR_DEBUG("def->os.bootloaderArgs %s", def->os.bootloaderArgs);
3854 data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties);
3855 if (systemProperties) {
3856 systemProperties->vtbl->GetMaxBootPosition(systemProperties,
3858 VBOX_RELEASE(systemProperties);
3859 systemProperties = NULL;
3862 /* Clear the defaults first */
3863 for (i = 0; i < maxBootPosition; i++) {
3864 machine->vtbl->SetBootOrder(machine, i+1, DeviceType_Null);
3867 for (i = 0; (i < def->os.nBootDevs) && (i < maxBootPosition); i++) {
3868 PRUint32 device = DeviceType_Null;
3870 if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_FLOPPY) {
3871 device = DeviceType_Floppy;
3872 } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_CDROM) {
3873 device = DeviceType_DVD;
3874 } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_DISK) {
3875 device = DeviceType_HardDisk;
3876 } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_NET) {
3877 device = DeviceType_Network;
3879 machine->vtbl->SetBootOrder(machine, i+1, device);
3884 vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
3889 #if VBOX_API_VERSION < 3001000
3890 if (def->ndisks == 0)
3893 for (i = 0; i < def->ndisks; i++) {
3894 const char *src = virDomainDiskGetSource(def->disks[i]);
3895 int type = virDomainDiskGetType(def->disks[i]);
3896 int format = virDomainDiskGetFormat(def->disks[i]);
3898 VIR_DEBUG("disk(%zu) type: %d", i, type);
3899 VIR_DEBUG("disk(%zu) device: %d", i, def->disks[i]->device);
3900 VIR_DEBUG("disk(%zu) bus: %d", i, def->disks[i]->bus);
3901 VIR_DEBUG("disk(%zu) src: %s", i, src);
3902 VIR_DEBUG("disk(%zu) dst: %s", i, def->disks[i]->dst);
3903 VIR_DEBUG("disk(%zu) driverName: %s", i,
3904 virDomainDiskGetDriver(def->disks[i]));
3905 VIR_DEBUG("disk(%zu) driverType: %s", i,
3906 virStorageFileFormatTypeToString(format));
3907 VIR_DEBUG("disk(%zu) cachemode: %d", i, def->disks[i]->cachemode);
3908 VIR_DEBUG("disk(%zu) readonly: %s", i, (def->disks[i]->readonly
3909 ? "True" : "False"));
3910 VIR_DEBUG("disk(%zu) shared: %s", i, (def->disks[i]->shared
3911 ? "True" : "False"));
3913 if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
3914 if (type == VIR_STORAGE_TYPE_FILE && src) {
3915 IDVDDrive *dvdDrive = NULL;
3916 /* Currently CDROM/DVD Drive is always IDE
3917 * Secondary Master so neglecting the following
3919 * def->disks[i]->bus
3920 * def->disks[i]->dst
3923 machine->vtbl->GetDVDDrive(machine, &dvdDrive);
3925 IDVDImage *dvdImage = NULL;
3926 PRUnichar *dvdfileUtf16 = NULL;
3927 vboxIID dvduuid = VBOX_IID_INITIALIZER;
3928 vboxIID dvdemptyuuid = VBOX_IID_INITIALIZER;
3930 VBOX_UTF8_TO_UTF16(src, &dvdfileUtf16);
3932 data->vboxObj->vtbl->FindDVDImage(data->vboxObj,
3933 dvdfileUtf16, &dvdImage);
3935 data->vboxObj->vtbl->OpenDVDImage(data->vboxObj,
3941 rc = dvdImage->vtbl->imedium.GetId((IMedium *)dvdImage,
3943 if (NS_FAILED(rc)) {
3944 virReportError(VIR_ERR_INTERNAL_ERROR,
3945 _("can't get the uuid of the file to "
3946 "be attached to cdrom: %s, rc=%08x"),
3949 rc = dvdDrive->vtbl->MountImage(dvdDrive, dvduuid.value);
3950 if (NS_FAILED(rc)) {
3951 virReportError(VIR_ERR_INTERNAL_ERROR,
3952 _("could not attach the file to cdrom: %s, rc=%08x"),
3955 DEBUGIID("CD/DVDImage UUID:", dvduuid.value);
3959 VBOX_MEDIUM_RELEASE(dvdImage);
3961 vboxIIDUnalloc(&dvduuid);
3962 VBOX_UTF16_FREE(dvdfileUtf16);
3963 VBOX_RELEASE(dvdDrive);
3965 } else if (type == VIR_STORAGE_TYPE_BLOCK) {
3967 } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
3968 if (type == VIR_STORAGE_TYPE_FILE && src) {
3969 IHardDisk *hardDisk = NULL;
3970 PRUnichar *hddfileUtf16 = NULL;
3971 vboxIID hdduuid = VBOX_IID_INITIALIZER;
3972 PRUnichar *hddEmpty = NULL;
3973 /* Current Limitation: Harddisk can't be connected to
3974 * Secondary Master as Secondary Master is always used
3975 * for CD/DVD Drive, so don't connect the harddisk if it
3976 * is requested to be connected to Secondary master
3979 VBOX_UTF8_TO_UTF16(src, &hddfileUtf16);
3980 VBOX_UTF8_TO_UTF16("", &hddEmpty);
3982 data->vboxObj->vtbl->FindHardDisk(data->vboxObj, hddfileUtf16,
3986 # if VBOX_API_VERSION == 2002000
3987 data->vboxObj->vtbl->OpenHardDisk(data->vboxObj,
3989 AccessMode_ReadWrite,
3992 data->vboxObj->vtbl->OpenHardDisk(data->vboxObj,
3994 AccessMode_ReadWrite,
4004 rc = hardDisk->vtbl->imedium.GetId((IMedium *)hardDisk,
4006 if (NS_FAILED(rc)) {
4007 virReportError(VIR_ERR_INTERNAL_ERROR,
4008 _("can't get the uuid of the file to be "
4009 "attached as harddisk: %s, rc=%08x"),
4012 if (def->disks[i]->readonly) {
4013 hardDisk->vtbl->SetType(hardDisk,
4014 HardDiskType_Immutable);
4015 VIR_DEBUG("setting harddisk to readonly");
4016 } else if (!def->disks[i]->readonly) {
4017 hardDisk->vtbl->SetType(hardDisk,
4018 HardDiskType_Normal);
4019 VIR_DEBUG("setting harddisk type to normal");
4021 if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_IDE) {
4022 if (STREQ(def->disks[i]->dst, "hdc")) {
4023 VIR_DEBUG("Not connecting harddisk to hdc as hdc"
4024 " is taken by CD/DVD Drive");
4026 PRInt32 channel = 0;
4028 PRUnichar *hddcnameUtf16 = NULL;
4031 ignore_value(VIR_STRDUP(hddcname, "IDE"));
4032 VBOX_UTF8_TO_UTF16(hddcname, &hddcnameUtf16);
4035 if (STREQ(def->disks[i]->dst, "hda")) {
4038 } else if (STREQ(def->disks[i]->dst, "hdb")) {
4041 } else if (STREQ(def->disks[i]->dst, "hdd")) {
4046 rc = machine->vtbl->AttachHardDisk(machine,
4051 VBOX_UTF16_FREE(hddcnameUtf16);
4053 if (NS_FAILED(rc)) {
4054 virReportError(VIR_ERR_INTERNAL_ERROR,
4055 _("could not attach the file as "
4056 "harddisk: %s, rc=%08x"),
4059 DEBUGIID("Attached HDD with UUID", hdduuid.value);
4064 VBOX_MEDIUM_RELEASE(hardDisk);
4066 vboxIIDUnalloc(&hdduuid);
4067 VBOX_UTF16_FREE(hddEmpty);
4068 VBOX_UTF16_FREE(hddfileUtf16);
4069 } else if (type == VIR_STORAGE_TYPE_BLOCK) {
4071 } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
4072 if (type == VIR_STORAGE_TYPE_FILE && src) {
4073 IFloppyDrive *floppyDrive;
4074 machine->vtbl->GetFloppyDrive(machine, &floppyDrive);
4076 rc = floppyDrive->vtbl->SetEnabled(floppyDrive, 1);
4077 if (NS_SUCCEEDED(rc)) {
4078 IFloppyImage *floppyImage = NULL;
4079 PRUnichar *fdfileUtf16 = NULL;
4080 vboxIID fduuid = VBOX_IID_INITIALIZER;
4081 vboxIID fdemptyuuid = VBOX_IID_INITIALIZER;
4083 VBOX_UTF8_TO_UTF16(src, &fdfileUtf16);
4084 rc = data->vboxObj->vtbl->FindFloppyImage(data->vboxObj,
4089 data->vboxObj->vtbl->OpenFloppyImage(data->vboxObj,
4096 rc = floppyImage->vtbl->imedium.GetId((IMedium *)floppyImage,
4098 if (NS_FAILED(rc)) {
4099 virReportError(VIR_ERR_INTERNAL_ERROR,
4100 _("can't get the uuid of the file to "
4101 "be attached to floppy drive: %s, rc=%08x"),
4104 rc = floppyDrive->vtbl->MountImage(floppyDrive,
4106 if (NS_FAILED(rc)) {
4107 virReportError(VIR_ERR_INTERNAL_ERROR,
4108 _("could not attach the file to "
4109 "floppy drive: %s, rc=%08x"),
4112 DEBUGIID("floppyImage UUID", fduuid.value);
4115 VBOX_MEDIUM_RELEASE(floppyImage);
4117 vboxIIDUnalloc(&fduuid);
4118 VBOX_UTF16_FREE(fdfileUtf16);
4120 VBOX_RELEASE(floppyDrive);
4122 } else if (type == VIR_STORAGE_TYPE_BLOCK) {
4126 #else /* VBOX_API_VERSION >= 3001000 */
4127 PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {};
4128 PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {};
4129 PRUnichar *storageCtlName = NULL;
4132 /* get the max port/slots/etc for the given storage bus */
4133 error = !vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst,
4136 /* add a storage controller for the mediums to be attached */
4137 /* this needs to change when multiple controller are supported for
4140 IStorageController *storageCtl = NULL;
4141 PRUnichar *sName = NULL;
4143 VBOX_UTF8_TO_UTF16("IDE Controller", &sName);
4144 machine->vtbl->AddStorageController(machine,
4148 VBOX_UTF16_FREE(sName);
4149 VBOX_RELEASE(storageCtl);
4151 VBOX_UTF8_TO_UTF16("SATA Controller", &sName);
4152 machine->vtbl->AddStorageController(machine,
4156 VBOX_UTF16_FREE(sName);
4157 VBOX_RELEASE(storageCtl);
4159 VBOX_UTF8_TO_UTF16("SCSI Controller", &sName);
4160 machine->vtbl->AddStorageController(machine,
4164 VBOX_UTF16_FREE(sName);
4165 VBOX_RELEASE(storageCtl);
4167 VBOX_UTF8_TO_UTF16("Floppy Controller", &sName);
4168 machine->vtbl->AddStorageController(machine,
4172 VBOX_UTF16_FREE(sName);
4173 VBOX_RELEASE(storageCtl);
4176 for (i = 0; i < def->ndisks && !error; i++) {
4177 const char *src = virDomainDiskGetSource(def->disks[i]);
4178 int type = virDomainDiskGetType(def->disks[i]);
4179 int format = virDomainDiskGetFormat(def->disks[i]);
4181 VIR_DEBUG("disk(%zu) type: %d", i, type);
4182 VIR_DEBUG("disk(%zu) device: %d", i, def->disks[i]->device);
4183 VIR_DEBUG("disk(%zu) bus: %d", i, def->disks[i]->bus);
4184 VIR_DEBUG("disk(%zu) src: %s", i, src);
4185 VIR_DEBUG("disk(%zu) dst: %s", i, def->disks[i]->dst);
4186 VIR_DEBUG("disk(%zu) driverName: %s", i,
4187 virDomainDiskGetDriver(def->disks[i]));
4188 VIR_DEBUG("disk(%zu) driverType: %s", i,
4189 virStorageFileFormatTypeToString(format));
4190 VIR_DEBUG("disk(%zu) cachemode: %d", i, def->disks[i]->cachemode);
4191 VIR_DEBUG("disk(%zu) readonly: %s", i, (def->disks[i]->readonly
4192 ? "True" : "False"));
4193 VIR_DEBUG("disk(%zu) shared: %s", i, (def->disks[i]->shared
4194 ? "True" : "False"));
4196 if (type == VIR_STORAGE_TYPE_FILE && src) {
4197 IMedium *medium = NULL;
4198 PRUnichar *mediumUUID = NULL;
4199 PRUnichar *mediumFileUtf16 = NULL;
4200 PRUint32 storageBus = StorageBus_Null;
4201 PRUint32 deviceType = DeviceType_Null;
4202 # if VBOX_API_VERSION >= 4000000
4203 PRUint32 accessMode = AccessMode_ReadOnly;
4205 PRInt32 deviceInst = 0;
4206 PRInt32 devicePort = 0;
4207 PRInt32 deviceSlot = 0;
4209 VBOX_UTF8_TO_UTF16(src, &mediumFileUtf16);
4211 if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
4212 deviceType = DeviceType_HardDisk;
4213 # if VBOX_API_VERSION < 4000000
4214 data->vboxObj->vtbl->FindHardDisk(data->vboxObj,
4215 mediumFileUtf16, &medium);
4217 accessMode = AccessMode_ReadWrite;
4219 } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
4220 deviceType = DeviceType_DVD;
4221 # if VBOX_API_VERSION < 4000000
4222 data->vboxObj->vtbl->FindDVDImage(data->vboxObj,
4223 mediumFileUtf16, &medium);
4225 accessMode = AccessMode_ReadOnly;
4227 } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
4228 deviceType = DeviceType_Floppy;
4229 # if VBOX_API_VERSION < 4000000
4230 data->vboxObj->vtbl->FindFloppyImage(data->vboxObj,
4231 mediumFileUtf16, &medium);
4233 accessMode = AccessMode_ReadWrite;
4236 VBOX_UTF16_FREE(mediumFileUtf16);
4240 # if VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
4241 data->vboxObj->vtbl->FindMedium(data->vboxObj, mediumFileUtf16,
4242 deviceType, &medium);
4243 # elif VBOX_API_VERSION >= 4002000
4244 data->vboxObj->vtbl->OpenMedium(data->vboxObj, mediumFileUtf16,
4245 deviceType, accessMode, PR_FALSE, &medium);
4249 PRUnichar *mediumEmpty = NULL;
4251 VBOX_UTF8_TO_UTF16("", &mediumEmpty);
4253 # if VBOX_API_VERSION < 4000000
4254 if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
4255 rc = data->vboxObj->vtbl->OpenHardDisk(data->vboxObj,
4257 AccessMode_ReadWrite,
4263 } else if (def->disks[i]->device ==
4264 VIR_DOMAIN_DISK_DEVICE_CDROM) {
4265 rc = data->vboxObj->vtbl->OpenDVDImage(data->vboxObj,
4269 } else if (def->disks[i]->device ==
4270 VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
4271 rc = data->vboxObj->vtbl->OpenFloppyImage(data->vboxObj,
4278 # elif VBOX_API_VERSION == 4000000
4279 rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj,
4281 deviceType, accessMode,
4283 # elif VBOX_API_VERSION >= 4001000
4284 rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj,
4286 deviceType, accessMode,
4289 # endif /* VBOX_API_VERSION >= 4001000 */
4291 VBOX_UTF16_FREE(mediumEmpty);
4295 virReportError(VIR_ERR_INTERNAL_ERROR,
4296 _("Failed to attach the following disk/dvd/floppy "
4297 "to the machine: %s, rc=%08x"),
4299 VBOX_UTF16_FREE(mediumFileUtf16);
4303 rc = medium->vtbl->GetId(medium, &mediumUUID);
4304 if (NS_FAILED(rc)) {
4305 virReportError(VIR_ERR_INTERNAL_ERROR,
4306 _("can't get the uuid of the file to be attached "
4307 "as harddisk/dvd/floppy: %s, rc=%08x"),
4309 VBOX_RELEASE(medium);
4310 VBOX_UTF16_FREE(mediumFileUtf16);
4314 if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
4315 if (def->disks[i]->readonly) {
4316 medium->vtbl->SetType(medium, MediumType_Immutable);
4317 VIR_DEBUG("setting harddisk to immutable");
4318 } else if (!def->disks[i]->readonly) {
4319 medium->vtbl->SetType(medium, MediumType_Normal);
4320 VIR_DEBUG("setting harddisk type to normal");
4324 if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_IDE) {
4325 VBOX_UTF8_TO_UTF16("IDE Controller", &storageCtlName);
4326 storageBus = StorageBus_IDE;
4327 } else if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_SATA) {
4328 VBOX_UTF8_TO_UTF16("SATA Controller", &storageCtlName);
4329 storageBus = StorageBus_SATA;
4330 } else if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
4331 VBOX_UTF8_TO_UTF16("SCSI Controller", &storageCtlName);
4332 storageBus = StorageBus_SCSI;
4333 } else if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_FDC) {
4334 VBOX_UTF8_TO_UTF16("Floppy Controller", &storageCtlName);
4335 storageBus = StorageBus_Floppy;
4338 /* get the device details i.e instance, port and slot */
4339 if (!vboxGetDeviceDetails(def->disks[i]->dst,
4346 virReportError(VIR_ERR_INTERNAL_ERROR,
4347 _("can't get the port/slot number of "
4348 "harddisk/dvd/floppy to be attached: "
4351 VBOX_RELEASE(medium);
4352 VBOX_UTF16_FREE(mediumUUID);
4353 VBOX_UTF16_FREE(mediumFileUtf16);
4357 /* attach the harddisk/dvd/Floppy to the storage controller */
4358 rc = machine->vtbl->AttachDevice(machine,
4363 # if VBOX_API_VERSION < 4000000
4365 # else /* VBOX_API_VERSION >= 4000000 */
4367 # endif /* VBOX_API_VERSION >= 4000000 */
4369 if (NS_FAILED(rc)) {
4370 virReportError(VIR_ERR_INTERNAL_ERROR,
4371 _("could not attach the file as "
4372 "harddisk/dvd/floppy: %s, rc=%08x"),
4375 DEBUGIID("Attached HDD/DVD/Floppy with UUID", mediumUUID);
4378 VBOX_RELEASE(medium);
4379 VBOX_UTF16_FREE(mediumUUID);
4380 VBOX_UTF16_FREE(mediumFileUtf16);
4381 VBOX_UTF16_FREE(storageCtlName);
4384 #endif /* VBOX_API_VERSION >= 3001000 */
4388 vboxAttachSound(virDomainDefPtr def, IMachine *machine)
4392 /* Check if def->nsounds is one as VirtualBox currently supports
4393 * only one sound card
4395 if (def->nsounds == 1) {
4396 IAudioAdapter *audioAdapter = NULL;
4398 machine->vtbl->GetAudioAdapter(machine, &audioAdapter);
4400 rc = audioAdapter->vtbl->SetEnabled(audioAdapter, 1);
4401 if (NS_SUCCEEDED(rc)) {
4402 if (def->sounds[0]->model == VIR_DOMAIN_SOUND_MODEL_SB16) {
4403 audioAdapter->vtbl->SetAudioController(audioAdapter,
4404 AudioControllerType_SB16);
4405 } else if (def->sounds[0]->model == VIR_DOMAIN_SOUND_MODEL_AC97) {
4406 audioAdapter->vtbl->SetAudioController(audioAdapter,
4407 AudioControllerType_AC97);
4410 VBOX_RELEASE(audioAdapter);
4416 vboxAttachNetwork(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
4418 ISystemProperties *systemProperties = NULL;
4419 #if VBOX_API_VERSION >= 4001000
4420 PRUint32 chipsetType = ChipsetType_Null;
4421 #endif /* VBOX_API_VERSION >= 4001000 */
4422 PRUint32 networkAdapterCount = 0;
4425 #if VBOX_API_VERSION >= 4001000
4426 machine->vtbl->GetChipsetType(machine, &chipsetType);
4427 #endif /* VBOX_API_VERSION >= 4001000 */
4429 data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties);
4430 if (systemProperties) {
4431 #if VBOX_API_VERSION < 4001000
4432 systemProperties->vtbl->GetNetworkAdapterCount(systemProperties,
4433 &networkAdapterCount);
4434 #else /* VBOX_API_VERSION >= 4000000 */
4435 systemProperties->vtbl->GetMaxNetworkAdapters(systemProperties, chipsetType,
4436 &networkAdapterCount);
4437 #endif /* VBOX_API_VERSION >= 4000000 */
4438 VBOX_RELEASE(systemProperties);
4439 systemProperties = NULL;
4442 VIR_DEBUG("Number of Network Cards to be connected: %zu", def->nnets);
4443 VIR_DEBUG("Number of Network Cards available: %d", networkAdapterCount);
4445 for (i = 0; (i < def->nnets) && (i < networkAdapterCount); i++) {
4446 INetworkAdapter *adapter = NULL;
4447 PRUint32 adapterType = NetworkAdapterType_Null;
4448 char macaddr[VIR_MAC_STRING_BUFLEN] = {0};
4449 char macaddrvbox[VIR_MAC_STRING_BUFLEN - 5] = {0};
4451 virMacAddrFormat(&def->nets[i]->mac, macaddr);
4452 snprintf(macaddrvbox, VIR_MAC_STRING_BUFLEN - 5,
4453 "%02X%02X%02X%02X%02X%02X",
4454 def->nets[i]->mac.addr[0],
4455 def->nets[i]->mac.addr[1],
4456 def->nets[i]->mac.addr[2],
4457 def->nets[i]->mac.addr[3],
4458 def->nets[i]->mac.addr[4],
4459 def->nets[i]->mac.addr[5]);
4460 macaddrvbox[VIR_MAC_STRING_BUFLEN - 6] = '\0';
4462 VIR_DEBUG("NIC(%zu): Type: %d", i, def->nets[i]->type);
4463 VIR_DEBUG("NIC(%zu): Model: %s", i, def->nets[i]->model);
4464 VIR_DEBUG("NIC(%zu): Mac: %s", i, macaddr);
4465 VIR_DEBUG("NIC(%zu): ifname: %s", i, def->nets[i]->ifname);
4466 if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
4467 VIR_DEBUG("NIC(%zu): name: %s", i, def->nets[i]->data.network.name);
4468 } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_INTERNAL) {
4469 VIR_DEBUG("NIC(%zu): name: %s", i, def->nets[i]->data.internal.name);
4470 } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_USER) {
4471 VIR_DEBUG("NIC(%zu): NAT.", i);
4472 } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
4473 VIR_DEBUG("NIC(%zu): brname: %s", i, def->nets[i]->data.bridge.brname);
4474 VIR_DEBUG("NIC(%zu): script: %s", i, def->nets[i]->script);
4475 VIR_DEBUG("NIC(%zu): ipaddr: %s", i, def->nets[i]->data.bridge.ipaddr);
4478 machine->vtbl->GetNetworkAdapter(machine, i, &adapter);
4480 PRUnichar *MACAddress = NULL;
4482 adapter->vtbl->SetEnabled(adapter, 1);
4484 if (def->nets[i]->model) {
4485 if (STRCASEEQ(def->nets[i]->model, "Am79C970A")) {
4486 adapterType = NetworkAdapterType_Am79C970A;
4487 } else if (STRCASEEQ(def->nets[i]->model, "Am79C973")) {
4488 adapterType = NetworkAdapterType_Am79C973;
4489 } else if (STRCASEEQ(def->nets[i]->model, "82540EM")) {
4490 adapterType = NetworkAdapterType_I82540EM;
4491 } else if (STRCASEEQ(def->nets[i]->model, "82545EM")) {
4492 adapterType = NetworkAdapterType_I82545EM;
4493 } else if (STRCASEEQ(def->nets[i]->model, "82543GC")) {
4494 adapterType = NetworkAdapterType_I82543GC;
4495 #if VBOX_API_VERSION >= 3001000
4496 } else if (STRCASEEQ(def->nets[i]->model, "virtio")) {
4497 adapterType = NetworkAdapterType_Virtio;
4498 #endif /* VBOX_API_VERSION >= 3001000 */
4501 adapterType = NetworkAdapterType_Am79C973;
4504 adapter->vtbl->SetAdapterType(adapter, adapterType);
4506 if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
4507 PRUnichar *hostInterface = NULL;
4508 /* Bridged Network */
4510 #if VBOX_API_VERSION < 4001000
4511 adapter->vtbl->AttachToBridgedInterface(adapter);
4512 #else /* VBOX_API_VERSION >= 4001000 */
4513 adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Bridged);
4514 #endif /* VBOX_API_VERSION >= 4001000 */
4516 if (def->nets[i]->data.bridge.brname) {
4517 VBOX_UTF8_TO_UTF16(def->nets[i]->data.bridge.brname,
4519 #if VBOX_API_VERSION < 4001000
4520 adapter->vtbl->SetHostInterface(adapter, hostInterface);
4521 #else /* VBOX_API_VERSION >= 4001000 */
4522 adapter->vtbl->SetBridgedInterface(adapter, hostInterface);
4523 #endif /* VBOX_API_VERSION >= 4001000 */
4524 VBOX_UTF16_FREE(hostInterface);
4526 } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_INTERNAL) {
4527 PRUnichar *internalNetwork = NULL;
4528 /* Internal Network */
4530 #if VBOX_API_VERSION < 4001000
4531 adapter->vtbl->AttachToInternalNetwork(adapter);
4532 #else /* VBOX_API_VERSION >= 4001000 */
4533 adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Internal);
4534 #endif /* VBOX_API_VERSION >= 4001000 */
4536 if (def->nets[i]->data.internal.name) {
4537 VBOX_UTF8_TO_UTF16(def->nets[i]->data.internal.name,
4539 adapter->vtbl->SetInternalNetwork(adapter, internalNetwork);
4540 VBOX_UTF16_FREE(internalNetwork);
4542 } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
4543 PRUnichar *hostInterface = NULL;
4544 /* Host Only Networking (currently only vboxnet0 available
4545 * on *nix and mac, on windows you can create and configure
4546 * as many as you want)
4548 #if VBOX_API_VERSION < 4001000
4549 adapter->vtbl->AttachToHostOnlyInterface(adapter);
4550 #else /* VBOX_API_VERSION >= 4001000 */
4551 adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_HostOnly);
4552 #endif /* VBOX_API_VERSION >= 4001000 */
4554 if (def->nets[i]->data.network.name) {
4555 VBOX_UTF8_TO_UTF16(def->nets[i]->data.network.name,
4557 #if VBOX_API_VERSION < 4001000
4558 adapter->vtbl->SetHostInterface(adapter, hostInterface);
4559 #else /* VBOX_API_VERSION >= 4001000 */
4560 adapter->vtbl->SetHostOnlyInterface(adapter, hostInterface);
4561 #endif /* VBOX_API_VERSION >= 4001000 */
4562 VBOX_UTF16_FREE(hostInterface);
4564 } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_USER) {
4566 #if VBOX_API_VERSION < 4001000
4567 adapter->vtbl->AttachToNAT(adapter);
4568 #else /* VBOX_API_VERSION >= 4001000 */
4569 adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_NAT);
4570 #endif /* VBOX_API_VERSION >= 4001000 */
4572 /* else always default to NAT if we don't understand
4573 * what option is been passed to us
4575 #if VBOX_API_VERSION < 4001000
4576 adapter->vtbl->AttachToNAT(adapter);
4577 #else /* VBOX_API_VERSION >= 4001000 */
4578 adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_NAT);
4579 #endif /* VBOX_API_VERSION >= 4001000 */
4582 VBOX_UTF8_TO_UTF16(macaddrvbox, &MACAddress);
4583 adapter->vtbl->SetMACAddress(adapter, MACAddress);
4584 VBOX_UTF16_FREE(MACAddress);
4590 vboxAttachSerial(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
4592 ISystemProperties *systemProperties = NULL;
4593 PRUint32 serialPortCount = 0;
4596 data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties);
4597 if (systemProperties) {
4598 systemProperties->vtbl->GetSerialPortCount(systemProperties,
4600 VBOX_RELEASE(systemProperties);
4601 systemProperties = NULL;
4604 VIR_DEBUG("Number of Serial Ports to be connected: %zu", def->nserials);
4605 VIR_DEBUG("Number of Serial Ports available: %d", serialPortCount);
4606 for (i = 0; (i < def->nserials) && (i < serialPortCount); i++) {
4607 ISerialPort *serialPort = NULL;
4609 VIR_DEBUG("SerialPort(%zu): Type: %d", i, def->serials[i]->source.type);
4610 VIR_DEBUG("SerialPort(%zu): target.port: %d", i,
4611 def->serials[i]->target.port);
4613 machine->vtbl->GetSerialPort(machine, i, &serialPort);
4615 PRUnichar *pathUtf16 = NULL;
4617 serialPort->vtbl->SetEnabled(serialPort, 1);
4619 if (def->serials[i]->source.data.file.path) {
4620 VBOX_UTF8_TO_UTF16(def->serials[i]->source.data.file.path,
4622 serialPort->vtbl->SetPath(serialPort, pathUtf16);
4625 /* For now hard code the serial ports to COM1 and COM2,
4626 * COM1 (Base Addr: 0x3F8 (decimal: 1016), IRQ: 4)
4627 * COM2 (Base Addr: 0x2F8 (decimal: 760), IRQ: 3)
4628 * TODO: make this more flexible
4630 /* TODO: to improve the libvirt XMl handling so
4631 * that def->serials[i]->target.port shows real port
4632 * and not always start at 0
4634 if (def->serials[i]->target.port == 0) {
4635 serialPort->vtbl->SetIRQ(serialPort, 4);
4636 serialPort->vtbl->SetIOBase(serialPort, 1016);
4637 VIR_DEBUG(" serialPort-%zu irq: %d, iobase 0x%x, path: %s",
4638 i, 4, 1016, def->serials[i]->source.data.file.path);
4639 } else if (def->serials[i]->target.port == 1) {
4640 serialPort->vtbl->SetIRQ(serialPort, 3);
4641 serialPort->vtbl->SetIOBase(serialPort, 760);
4642 VIR_DEBUG(" serialPort-%zu irq: %d, iobase 0x%x, path: %s",
4643 i, 3, 760, def->serials[i]->source.data.file.path);
4646 if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV) {
4647 serialPort->vtbl->SetHostMode(serialPort, PortMode_HostDevice);
4648 } else if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE) {
4649 serialPort->vtbl->SetHostMode(serialPort, PortMode_HostPipe);
4650 #if VBOX_API_VERSION >= 3000000
4651 } else if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE) {
4652 serialPort->vtbl->SetHostMode(serialPort, PortMode_RawFile);
4653 #endif /* VBOX_API_VERSION >= 3000000 */
4655 serialPort->vtbl->SetHostMode(serialPort,
4656 PortMode_Disconnected);
4659 VBOX_RELEASE(serialPort);
4660 VBOX_UTF16_FREE(pathUtf16);
4666 vboxAttachParallel(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
4668 ISystemProperties *systemProperties = NULL;
4669 PRUint32 parallelPortCount = 0;
4672 data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties);
4673 if (systemProperties) {
4674 systemProperties->vtbl->GetParallelPortCount(systemProperties,
4675 ¶llelPortCount);
4676 VBOX_RELEASE(systemProperties);
4677 systemProperties = NULL;
4680 VIR_DEBUG("Number of Parallel Ports to be connected: %zu", def->nparallels);
4681 VIR_DEBUG("Number of Parallel Ports available: %d", parallelPortCount);
4682 for (i = 0; (i < def->nparallels) && (i < parallelPortCount); i++) {
4683 IParallelPort *parallelPort = NULL;
4685 VIR_DEBUG("ParallelPort(%zu): Type: %d", i, def->parallels[i]->source.type);
4686 VIR_DEBUG("ParallelPort(%zu): target.port: %d", i,
4687 def->parallels[i]->target.port);
4689 machine->vtbl->GetParallelPort(machine, i, ¶llelPort);
4691 PRUnichar *pathUtf16 = NULL;
4693 VBOX_UTF8_TO_UTF16(def->parallels[i]->source.data.file.path, &pathUtf16);
4695 /* For now hard code the parallel ports to
4696 * LPT1 (Base Addr: 0x378 (decimal: 888), IRQ: 7)
4697 * LPT2 (Base Addr: 0x278 (decimal: 632), IRQ: 5)
4698 * TODO: make this more flexible
4700 if ((def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV) ||
4701 (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_PTY) ||
4702 (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE) ||
4703 (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE)) {
4704 parallelPort->vtbl->SetPath(parallelPort, pathUtf16);
4706 parallelPort->vtbl->SetIRQ(parallelPort, 7);
4707 parallelPort->vtbl->SetIOBase(parallelPort, 888);
4708 VIR_DEBUG(" parallePort-%zu irq: %d, iobase 0x%x, path: %s",
4709 i, 7, 888, def->parallels[i]->source.data.file.path);
4710 } else if (i == 1) {
4711 parallelPort->vtbl->SetIRQ(parallelPort, 5);
4712 parallelPort->vtbl->SetIOBase(parallelPort, 632);
4713 VIR_DEBUG(" parallePort-%zu irq: %d, iobase 0x%x, path: %s",
4714 i, 5, 632, def->parallels[i]->source.data.file.path);
4718 /* like serial port, parallel port can't be enabled unless
4719 * correct IRQ and IOBase values are specified.
4721 parallelPort->vtbl->SetEnabled(parallelPort, 1);
4723 VBOX_RELEASE(parallelPort);
4724 VBOX_UTF16_FREE(pathUtf16);
4730 vboxAttachVideo(virDomainDefPtr def, IMachine *machine)
4732 if ((def->nvideos == 1) &&
4733 (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_VBOX)) {
4734 machine->vtbl->SetVRAMSize(machine,
4735 VIR_DIV_UP(def->videos[0]->vram, 1024));
4736 machine->vtbl->SetMonitorCount(machine, def->videos[0]->heads);
4737 if (def->videos[0]->accel) {
4738 machine->vtbl->SetAccelerate3DEnabled(machine,
4739 def->videos[0]->accel->support3d);
4740 #if VBOX_API_VERSION >= 3001000
4741 machine->vtbl->SetAccelerate2DVideoEnabled(machine,
4742 def->videos[0]->accel->support2d);
4743 #endif /* VBOX_API_VERSION >= 3001000 */
4745 machine->vtbl->SetAccelerate3DEnabled(machine, 0);
4746 #if VBOX_API_VERSION >= 3001000
4747 machine->vtbl->SetAccelerate2DVideoEnabled(machine, 0);
4748 #endif /* VBOX_API_VERSION >= 3001000 */
4754 vboxAttachDisplay(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
4756 int vrdpPresent = 0;
4759 char *guiDisplay = NULL;
4760 char *sdlDisplay = NULL;
4763 for (i = 0; i < def->ngraphics; i++) {
4764 #if VBOX_API_VERSION < 4000000
4765 IVRDPServer *VRDxServer = NULL;
4766 #else /* VBOX_API_VERSION >= 4000000 */
4767 IVRDEServer *VRDxServer = NULL;
4768 #endif /* VBOX_API_VERSION >= 4000000 */
4770 if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_RDP) &&
4771 (vrdpPresent == 0)) {
4774 #if VBOX_API_VERSION < 4000000
4775 machine->vtbl->GetVRDPServer(machine, &VRDxServer);
4776 #else /* VBOX_API_VERSION >= 4000000 */
4777 machine->vtbl->GetVRDEServer(machine, &VRDxServer);
4778 #endif /* VBOX_API_VERSION >= 4000000 */
4780 const char *listenAddr
4781 = virDomainGraphicsListenGetAddress(def->graphics[i], 0);
4783 VRDxServer->vtbl->SetEnabled(VRDxServer, PR_TRUE);
4784 VIR_DEBUG("VRDP Support turned ON.");
4786 #if VBOX_API_VERSION < 3001000
4787 if (def->graphics[i]->data.rdp.port) {
4788 VRDxServer->vtbl->SetPort(VRDxServer,
4789 def->graphics[i]->data.rdp.port);
4790 VIR_DEBUG("VRDP Port changed to: %d",
4791 def->graphics[i]->data.rdp.port);
4792 } else if (def->graphics[i]->data.rdp.autoport) {
4793 /* Setting the port to 0 will reset its value to
4794 * the default one which is 3389 currently
4796 VRDxServer->vtbl->SetPort(VRDxServer, 0);
4797 VIR_DEBUG("VRDP Port changed to default, which is 3389 currently");
4799 #elif VBOX_API_VERSION < 4000000 /* 3001000 <= VBOX_API_VERSION < 4000000 */
4800 PRUnichar *portUtf16 = NULL;
4801 portUtf16 = PRUnicharFromInt(def->graphics[i]->data.rdp.port);
4802 VRDxServer->vtbl->SetPorts(VRDxServer, portUtf16);
4803 VBOX_UTF16_FREE(portUtf16);
4804 #else /* VBOX_API_VERSION >= 4000000 */
4805 PRUnichar *VRDEPortsKey = NULL;
4806 PRUnichar *VRDEPortsValue = NULL;
4807 VBOX_UTF8_TO_UTF16("TCP/Ports", &VRDEPortsKey);
4808 VRDEPortsValue = PRUnicharFromInt(def->graphics[i]->data.rdp.port);
4809 VRDxServer->vtbl->SetVRDEProperty(VRDxServer, VRDEPortsKey,
4811 VBOX_UTF16_FREE(VRDEPortsKey);
4812 VBOX_UTF16_FREE(VRDEPortsValue);
4813 #endif /* VBOX_API_VERSION >= 4000000 */
4815 if (def->graphics[i]->data.rdp.replaceUser) {
4816 VRDxServer->vtbl->SetReuseSingleConnection(VRDxServer,
4818 VIR_DEBUG("VRDP set to reuse single connection");
4821 if (def->graphics[i]->data.rdp.multiUser) {
4822 VRDxServer->vtbl->SetAllowMultiConnection(VRDxServer,
4824 VIR_DEBUG("VRDP set to allow multiple connection");
4828 #if VBOX_API_VERSION >= 4000000
4829 PRUnichar *netAddressKey = NULL;
4831 PRUnichar *netAddressUtf16 = NULL;
4833 VBOX_UTF8_TO_UTF16(listenAddr, &netAddressUtf16);
4834 #if VBOX_API_VERSION < 4000000
4835 VRDxServer->vtbl->SetNetAddress(VRDxServer,
4837 #else /* VBOX_API_VERSION >= 4000000 */
4838 VBOX_UTF8_TO_UTF16("TCP/Address", &netAddressKey);
4839 VRDxServer->vtbl->SetVRDEProperty(VRDxServer, netAddressKey,
4841 VBOX_UTF16_FREE(netAddressKey);
4842 #endif /* VBOX_API_VERSION >= 4000000 */
4843 VIR_DEBUG("VRDP listen address is set to: %s",
4846 VBOX_UTF16_FREE(netAddressUtf16);
4849 VBOX_RELEASE(VRDxServer);
4853 if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP) &&
4854 (guiPresent == 0)) {
4856 if (VIR_STRDUP(guiDisplay, def->graphics[i]->data.desktop.display) < 0) {
4857 /* just don't go to cleanup yet as it is ok to have
4858 * guiDisplay as NULL and we check it below if it
4859 * exist and then only use it there
4864 if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) &&
4865 (sdlPresent == 0)) {
4867 if (VIR_STRDUP(sdlDisplay, def->graphics[i]->data.sdl.display) < 0) {
4868 /* just don't go to cleanup yet as it is ok to have
4869 * sdlDisplay as NULL and we check it below if it
4870 * exist and then only use it there
4876 if ((vrdpPresent == 1) && (guiPresent == 0) && (sdlPresent == 0)) {
4877 /* store extradata key that frontend is set to vrdp */
4878 PRUnichar *keyTypeUtf16 = NULL;
4879 PRUnichar *valueTypeUtf16 = NULL;
4881 VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16);
4882 VBOX_UTF8_TO_UTF16("vrdp", &valueTypeUtf16);
4884 machine->vtbl->SetExtraData(machine, keyTypeUtf16, valueTypeUtf16);
4886 VBOX_UTF16_FREE(keyTypeUtf16);
4887 VBOX_UTF16_FREE(valueTypeUtf16);
4889 } else if ((guiPresent == 0) && (sdlPresent == 1)) {
4890 /* store extradata key that frontend is set to sdl */
4891 PRUnichar *keyTypeUtf16 = NULL;
4892 PRUnichar *valueTypeUtf16 = NULL;
4893 PRUnichar *keyDislpayUtf16 = NULL;
4894 PRUnichar *valueDisplayUtf16 = NULL;
4896 VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16);
4897 VBOX_UTF8_TO_UTF16("sdl", &valueTypeUtf16);
4899 machine->vtbl->SetExtraData(machine, keyTypeUtf16, valueTypeUtf16);
4901 VBOX_UTF16_FREE(keyTypeUtf16);
4902 VBOX_UTF16_FREE(valueTypeUtf16);
4905 VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16);
4906 VBOX_UTF8_TO_UTF16(sdlDisplay, &valueDisplayUtf16);
4908 machine->vtbl->SetExtraData(machine, keyDislpayUtf16,
4911 VBOX_UTF16_FREE(keyDislpayUtf16);
4912 VBOX_UTF16_FREE(valueDisplayUtf16);
4916 /* if all are set then default is gui, with vrdp turned on */
4917 PRUnichar *keyTypeUtf16 = NULL;
4918 PRUnichar *valueTypeUtf16 = NULL;
4919 PRUnichar *keyDislpayUtf16 = NULL;
4920 PRUnichar *valueDisplayUtf16 = NULL;
4922 VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16);
4923 VBOX_UTF8_TO_UTF16("gui", &valueTypeUtf16);
4925 machine->vtbl->SetExtraData(machine, keyTypeUtf16, valueTypeUtf16);
4927 VBOX_UTF16_FREE(keyTypeUtf16);
4928 VBOX_UTF16_FREE(valueTypeUtf16);
4931 VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16);
4932 VBOX_UTF8_TO_UTF16(guiDisplay, &valueDisplayUtf16);
4934 machine->vtbl->SetExtraData(machine, keyDislpayUtf16,
4937 VBOX_UTF16_FREE(keyDislpayUtf16);
4938 VBOX_UTF16_FREE(valueDisplayUtf16);
4942 VIR_FREE(guiDisplay);
4943 VIR_FREE(sdlDisplay);
4947 vboxAttachUSB(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
4949 #if VBOX_API_VERSION < 4003000
4950 IUSBController *USBController = NULL;
4952 IUSBDeviceFilters *USBDeviceFilters = NULL;
4957 if (def->nhostdevs == 0)
4960 /* Loop through the devices first and see if you
4961 * have a USB Device, only if you have one then
4962 * start the USB controller else just proceed as
4965 for (i = 0; i < def->nhostdevs; i++) {
4966 if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
4969 if (def->hostdevs[i]->source.subsys.type !=
4970 VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
4973 if (!def->hostdevs[i]->source.subsys.u.usb.vendor &&
4974 !def->hostdevs[i]->source.subsys.u.usb.product)
4977 VIR_DEBUG("USB Device detected, VendorId:0x%x, ProductId:0x%x",
4978 def->hostdevs[i]->source.subsys.u.usb.vendor,
4979 def->hostdevs[i]->source.subsys.u.usb.product);
4987 #if VBOX_API_VERSION < 4003000
4988 /* First Start the USB Controller and then loop
4989 * to attach USB Devices to it
4991 machine->vtbl->GetUSBController(machine, &USBController);
4996 USBController->vtbl->SetEnabled(USBController, 1);
4997 # if VBOX_API_VERSION < 4002000
4998 USBController->vtbl->SetEnabledEhci(USBController, 1);
5000 USBController->vtbl->SetEnabledEHCI(USBController, 1);
5003 machine->vtbl->GetUSBDeviceFilters(machine, &USBDeviceFilters);
5005 if (!USBDeviceFilters)
5009 for (i = 0; i < def->nhostdevs; i++) {
5010 char *filtername = NULL;
5011 PRUnichar *filternameUtf16 = NULL;
5012 IUSBDeviceFilter *filter = NULL;
5013 PRUnichar *vendorIdUtf16 = NULL;
5014 char vendorId[40] = {0};
5015 PRUnichar *productIdUtf16 = NULL;
5016 char productId[40] = {0};
5018 if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
5021 if (def->hostdevs[i]->source.subsys.type !=
5022 VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
5025 /* Zero pad for nice alignment when fewer than 9999
5028 if (virAsprintf(&filtername, "filter%04zu", i) >= 0) {
5029 VBOX_UTF8_TO_UTF16(filtername, &filternameUtf16);
5030 VIR_FREE(filtername);
5031 #if VBOX_API_VERSION < 4003000
5032 USBController->vtbl->CreateDeviceFilter(USBController,
5036 USBDeviceFilters->vtbl->CreateDeviceFilter(USBDeviceFilters,
5041 VBOX_UTF16_FREE(filternameUtf16);
5046 if (!def->hostdevs[i]->source.subsys.u.usb.vendor &&
5047 !def->hostdevs[i]->source.subsys.u.usb.product)
5050 if (def->hostdevs[i]->source.subsys.u.usb.vendor) {
5051 snprintf(vendorId, sizeof(vendorId), "%x",
5052 def->hostdevs[i]->source.subsys.u.usb.vendor);
5053 VBOX_UTF8_TO_UTF16(vendorId, &vendorIdUtf16);
5054 filter->vtbl->SetVendorId(filter, vendorIdUtf16);
5055 VBOX_UTF16_FREE(vendorIdUtf16);
5057 if (def->hostdevs[i]->source.subsys.u.usb.product) {
5058 snprintf(productId, sizeof(productId), "%x",
5059 def->hostdevs[i]->source.subsys.u.usb.product);
5060 VBOX_UTF8_TO_UTF16(productId, &productIdUtf16);
5061 filter->vtbl->SetProductId(filter,
5063 VBOX_UTF16_FREE(productIdUtf16);
5065 filter->vtbl->SetActive(filter, 1);
5066 #if VBOX_API_VERSION < 4003000
5067 USBController->vtbl->InsertDeviceFilter(USBController,
5071 USBDeviceFilters->vtbl->InsertDeviceFilter(USBDeviceFilters,
5075 VBOX_RELEASE(filter);
5078 #if VBOX_API_VERSION < 4003000
5079 VBOX_RELEASE(USBController);
5081 VBOX_RELEASE(USBDeviceFilters);
5086 vboxAttachSharedFolder(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
5089 PRUnichar *nameUtf16;
5090 PRUnichar *hostPathUtf16;
5096 for (i = 0; i < def->nfss; i++) {
5097 if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT)
5100 VBOX_UTF8_TO_UTF16(def->fss[i]->dst, &nameUtf16);
5101 VBOX_UTF8_TO_UTF16(def->fss[i]->src, &hostPathUtf16);
5102 writable = !def->fss[i]->readonly;
5104 #if VBOX_API_VERSION < 4000000
5105 machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16,
5107 #else /* VBOX_API_VERSION >= 4000000 */
5108 machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16,
5109 writable, PR_FALSE);
5110 #endif /* VBOX_API_VERSION >= 4000000 */
5112 VBOX_UTF16_FREE(nameUtf16);
5113 VBOX_UTF16_FREE(hostPathUtf16);
5117 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml)
5119 VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL);
5120 IMachine *machine = NULL;
5121 IBIOSSettings *bios = NULL;
5122 vboxIID iid = VBOX_IID_INITIALIZER;
5123 vboxIID mchiid = VBOX_IID_INITIALIZER;
5124 virDomainDefPtr def = NULL;
5125 PRUnichar *machineNameUtf16 = NULL;
5126 #if VBOX_API_VERSION >= 3002000 && VBOX_API_VERSION < 4002000
5127 PRBool override = PR_FALSE;
5130 char uuidstr[VIR_UUID_STRING_BUFLEN];
5131 #if VBOX_API_VERSION >= 4002000
5132 const char *flagsUUIDPrefix = "UUID=";
5133 const char *flagsForceOverwrite = "forceOverwrite=0";
5134 const char *flagsSeparator = ",";
5135 char createFlags[strlen(flagsUUIDPrefix) + VIR_UUID_STRING_BUFLEN + strlen(flagsSeparator) + strlen(flagsForceOverwrite) + 1];
5136 PRUnichar *createFlagsUtf16 = NULL;
5139 if (!(def = virDomainDefParseString(xml, data->caps, data->xmlopt,
5140 1 << VIR_DOMAIN_VIRT_VBOX,
5141 VIR_DOMAIN_XML_INACTIVE))) {
5145 VBOX_UTF8_TO_UTF16(def->name, &machineNameUtf16);
5146 vboxIIDFromUUID(&iid, def->uuid);
5147 virUUIDFormat(def->uuid, uuidstr);
5149 #if VBOX_API_VERSION < 3002000
5150 rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
5156 #elif VBOX_API_VERSION < 4000000 /* 3002000 <= VBOX_API_VERSION < 4000000 */
5157 rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
5164 #elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
5165 rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
5172 #else /* VBOX_API_VERSION >= 4002000 */
5173 snprintf(createFlags, sizeof(createFlags), "%s%s%s%s",
5179 VBOX_UTF8_TO_UTF16(createFlags, &createFlagsUtf16);
5180 rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
5188 #endif /* VBOX_API_VERSION >= 4002000 */
5189 VBOX_UTF16_FREE(machineNameUtf16);
5191 if (NS_FAILED(rc)) {
5192 virReportError(VIR_ERR_INTERNAL_ERROR,
5193 _("could not define a domain, rc=%08x"), (unsigned)rc);
5197 rc = machine->vtbl->SetMemorySize(machine,
5198 VIR_DIV_UP(def->mem.cur_balloon, 1024));
5199 if (NS_FAILED(rc)) {
5200 virReportError(VIR_ERR_INTERNAL_ERROR,
5201 _("could not set the memory size of the domain to: %llu Kb, "
5203 def->mem.cur_balloon, (unsigned)rc);
5206 if (def->vcpus != def->maxvcpus) {
5207 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5208 _("current vcpu count must equal maximum"));
5210 rc = machine->vtbl->SetCPUCount(machine, def->maxvcpus);
5211 if (NS_FAILED(rc)) {
5212 virReportError(VIR_ERR_INTERNAL_ERROR,
5213 _("could not set the number of virtual CPUs to: %u, rc=%08x"),
5214 def->maxvcpus, (unsigned)rc);
5217 #if VBOX_API_VERSION < 3001000
5218 rc = machine->vtbl->SetPAEEnabled(machine,
5219 def->features[VIR_DOMAIN_FEATURE_PAE] ==
5220 VIR_DOMAIN_FEATURE_STATE_ON);
5221 #elif VBOX_API_VERSION == 3001000
5222 rc = machine->vtbl->SetCpuProperty(machine, CpuPropertyType_PAE,
5223 def->features[VIR_DOMAIN_FEATURE_PAE] ==
5224 VIR_DOMAIN_FEATURE_STATE_ON);
5225 #elif VBOX_API_VERSION >= 3002000
5226 rc = machine->vtbl->SetCPUProperty(machine, CPUPropertyType_PAE,
5227 def->features[VIR_DOMAIN_FEATURE_PAE] ==
5228 VIR_DOMAIN_FEATURE_STATE_ON);
5230 if (NS_FAILED(rc)) {
5231 virReportError(VIR_ERR_INTERNAL_ERROR,
5232 _("could not change PAE status to: %s, rc=%08x"),
5233 (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_DOMAIN_FEATURE_STATE_ON)
5234 ? _("Enabled") : _("Disabled"), (unsigned)rc);
5237 machine->vtbl->GetBIOSSettings(machine, &bios);
5239 rc = bios->vtbl->SetACPIEnabled(bios,
5240 def->features[VIR_DOMAIN_FEATURE_ACPI] ==
5241 VIR_DOMAIN_FEATURE_STATE_ON);
5242 if (NS_FAILED(rc)) {
5243 virReportError(VIR_ERR_INTERNAL_ERROR,
5244 _("could not change ACPI status to: %s, rc=%08x"),
5245 (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_DOMAIN_FEATURE_STATE_ON)
5246 ? _("Enabled") : _("Disabled"), (unsigned)rc);
5248 rc = bios->vtbl->SetIOAPICEnabled(bios,
5249 def->features[VIR_DOMAIN_FEATURE_APIC] ==
5250 VIR_DOMAIN_FEATURE_STATE_ON);
5251 if (NS_FAILED(rc)) {
5252 virReportError(VIR_ERR_INTERNAL_ERROR,
5253 _("could not change APIC status to: %s, rc=%08x"),
5254 (def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_DOMAIN_FEATURE_STATE_ON)
5255 ? _("Enabled") : _("Disabled"), (unsigned)rc);
5260 /* Register the machine before attaching other devices to it */
5261 rc = data->vboxObj->vtbl->RegisterMachine(data->vboxObj, machine);
5262 if (NS_FAILED(rc)) {
5263 virReportError(VIR_ERR_INTERNAL_ERROR,
5264 _("could not define a domain, rc=%08x"), (unsigned)rc);
5268 /* Get the uuid of the machine, currently it is immutable
5269 * object so open a session to it and get it back, so that
5270 * you can make changes to the machine setting
5272 machine->vtbl->GetId(machine, &mchiid.value);
5273 VBOX_SESSION_OPEN(mchiid.value, machine);
5274 data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
5276 vboxSetBootDeviceOrder(def, data, machine);
5277 vboxAttachDrives(def, data, machine);
5278 vboxAttachSound(def, machine);
5279 vboxAttachNetwork(def, data, machine);
5280 vboxAttachSerial(def, data, machine);
5281 vboxAttachParallel(def, data, machine);
5282 vboxAttachVideo(def, machine);
5283 vboxAttachDisplay(def, data, machine);
5284 vboxAttachUSB(def, data, machine);
5285 vboxAttachSharedFolder(def, data, machine);
5287 /* Save the machine settings made till now and close the
5288 * session. also free up the mchiid variable used.
5290 rc = machine->vtbl->SaveSettings(machine);
5291 VBOX_SESSION_CLOSE();
5292 vboxIIDUnalloc(&mchiid);
5294 ret = virGetDomain(conn, def->name, def->uuid);
5295 VBOX_RELEASE(machine);
5297 vboxIIDUnalloc(&iid);
5298 virDomainDefFree(def);
5303 VBOX_RELEASE(machine);
5304 vboxIIDUnalloc(&iid);
5305 virDomainDefFree(def);
5310 vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags)
5312 VBOX_OBJECT_CHECK(dom->conn, int, -1);
5313 IMachine *machine = NULL;
5314 vboxIID iid = VBOX_IID_INITIALIZER;
5316 #if VBOX_API_VERSION >= 4000000
5317 vboxArray media = VBOX_ARRAY_INITIALIZER;
5319 /* No managed save, so we explicitly reject
5320 * VIR_DOMAIN_UNDEFINE_MANAGED_SAVE. No snapshot metadata for
5321 * VBox, so we can trivially ignore that flag. */
5322 virCheckFlags(VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);
5324 vboxIIDFromUUID(&iid, dom->uuid);
5326 #if VBOX_API_VERSION < 4000000
5327 /* Block for checking if HDD's are attched to VM.
5328 * considering just IDE bus for now. Also skipped
5329 * chanel=1 and device=0 (Secondary Master) as currenlty
5330 * it is allocated to CD/DVD Drive by default.
5332 * Only do this for VirtualBox 3.x and before. Since
5333 * VirtualBox 4.0 the Unregister method can do this for use.
5336 PRUnichar *hddcnameUtf16 = NULL;
5339 ignore_value(VIR_STRDUP(hddcname, "IDE"));
5340 VBOX_UTF8_TO_UTF16(hddcname, &hddcnameUtf16);
5343 /* Open a Session for the machine */
5344 rc = VBOX_SESSION_OPEN(iid.value, machine);
5345 if (NS_SUCCEEDED(rc)) {
5346 rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
5347 if (NS_SUCCEEDED(rc) && machine) {
5349 # if VBOX_API_VERSION < 3001000
5350 /* Disconnect all the drives if present */
5351 machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 0, 0);
5352 machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 0, 1);
5353 machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 1, 1);
5354 # else /* VBOX_API_VERSION >= 3001000 */
5355 /* get all the controller first, then the attachments and
5356 * remove them all so that the machine can be undefined
5358 vboxArray storageControllers = VBOX_ARRAY_INITIALIZER;
5359 size_t i = 0, j = 0;
5361 vboxArrayGet(&storageControllers, machine,
5362 machine->vtbl->GetStorageControllers);
5364 for (i = 0; i < storageControllers.count; i++) {
5365 IStorageController *strCtl = storageControllers.items[i];
5366 PRUnichar *strCtlName = NULL;
5367 vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER;
5372 strCtl->vtbl->GetName(strCtl, &strCtlName);
5373 vboxArrayGetWithPtrArg(&mediumAttachments, machine,
5374 machine->vtbl->GetMediumAttachmentsOfController,
5377 for (j = 0; j < mediumAttachments.count; j++) {
5378 IMediumAttachment *medAtt = mediumAttachments.items[j];
5380 PRInt32 device = ~0U;
5385 medAtt->vtbl->GetPort(medAtt, &port);
5386 medAtt->vtbl->GetDevice(medAtt, &device);
5388 if ((port != ~0U) && (device != ~0U)) {
5389 machine->vtbl->DetachDevice(machine,
5396 vboxArrayRelease(&storageControllers);
5398 machine->vtbl->RemoveStorageController(machine, strCtlName);
5399 VBOX_UTF16_FREE(strCtlName);
5402 vboxArrayRelease(&storageControllers);
5403 # endif /* VBOX_API_VERSION >= 3001000 */
5405 machine->vtbl->SaveSettings(machine);
5407 VBOX_SESSION_CLOSE();
5409 VBOX_UTF16_FREE(hddcnameUtf16);
5413 #if VBOX_API_VERSION < 4000000
5414 rc = data->vboxObj->vtbl->UnregisterMachine(data->vboxObj, iid.value, &machine);
5415 #else /* VBOX_API_VERSION >= 4000000 */
5416 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
5417 if (NS_FAILED(rc)) {
5418 virReportError(VIR_ERR_NO_DOMAIN, "%s",
5419 _("no domain with matching uuid"));
5423 /* We're not interested in the array returned by the Unregister method,
5424 * but in the side effect of unregistering the virtual machine. In order
5425 * to call the Unregister method correctly we need to use the vboxArray
5427 rc = vboxArrayGetWithUintArg(&media, machine, machine->vtbl->Unregister,
5428 CleanupMode_DetachAllReturnNone);
5429 #endif /* VBOX_API_VERSION >= 4000000 */
5430 DEBUGIID("UUID of machine being undefined", iid.value);
5432 if (NS_SUCCEEDED(rc)) {
5433 #if VBOX_API_VERSION < 4000000
5434 machine->vtbl->DeleteSettings(machine);
5435 #else /* VBOX_API_VERSION >= 4000000 */
5436 IProgress *progress = NULL;
5438 /* The IMachine Delete method takes an array of IMedium items to be
5439 * deleted along with the virtual machine. We just want to pass an
5440 * empty array. But instead of adding a full vboxArraySetWithReturn to
5441 * the glue layer (in order to handle the required signature of the
5442 * Delete method) we use a local solution here. */
5444 SAFEARRAY *safeArray = NULL;
5445 typedef HRESULT __stdcall (*IMachine_Delete)(IMachine *self,
5447 IProgress **progress);
5449 # if VBOX_API_VERSION < 4003000
5450 ((IMachine_Delete)machine->vtbl->Delete)(machine, &safeArray, &progress);
5452 ((IMachine_Delete)machine->vtbl->DeleteConfig)(machine, &safeArray, &progress);
5455 /* XPCOM doesn't like NULL as an array, even when the array size is 0.
5456 * Instead pass it a dummy array to avoid passing NULL. */
5457 IMedium *array[] = { NULL };
5458 # if VBOX_API_VERSION < 4003000
5459 machine->vtbl->Delete(machine, 0, array, &progress);
5461 machine->vtbl->DeleteConfig(machine, 0, array, &progress);
5464 if (progress != NULL) {
5465 progress->vtbl->WaitForCompletion(progress, -1);
5466 VBOX_RELEASE(progress);
5468 #endif /* VBOX_API_VERSION >= 4000000 */
5471 virReportError(VIR_ERR_INTERNAL_ERROR,
5472 _("could not delete the domain, rc=%08x"), (unsigned)rc);
5475 #if VBOX_API_VERSION >= 4000000
5476 vboxArrayUnalloc(&media);
5478 vboxIIDUnalloc(&iid);
5479 VBOX_RELEASE(machine);
5485 vboxDomainUndefine(virDomainPtr dom)
5487 return vboxDomainUndefineFlags(dom, 0);
5490 static int vboxDomainAttachDeviceImpl(virDomainPtr dom,
5492 int mediaChangeOnly ATTRIBUTE_UNUSED)
5494 VBOX_OBJECT_CHECK(dom->conn, int, -1);
5495 IMachine *machine = NULL;
5496 vboxIID iid = VBOX_IID_INITIALIZER;
5497 PRUint32 state = MachineState_Null;
5498 virDomainDefPtr def = NULL;
5499 virDomainDeviceDefPtr dev = NULL;
5502 if (VIR_ALLOC(def) < 0)
5505 if (VIR_STRDUP(def->os.type, "hvm") < 0)
5508 dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt,
5509 VIR_DOMAIN_XML_INACTIVE);
5513 vboxIIDFromUUID(&iid, dom->uuid);
5514 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
5515 if (NS_FAILED(rc)) {
5516 virReportError(VIR_ERR_NO_DOMAIN, "%s",
5517 _("no domain with matching uuid"));
5522 machine->vtbl->GetState(machine, &state);
5524 if ((state == MachineState_Running) ||
5525 (state == MachineState_Paused)) {
5526 rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
5528 rc = VBOX_SESSION_OPEN(iid.value, machine);
5530 if (NS_SUCCEEDED(rc)) {
5531 rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
5532 if (NS_SUCCEEDED(rc) && machine) {
5533 if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
5534 #if VBOX_API_VERSION < 3001000
5535 const char *src = virDomainDiskGetSource(dev->data.disk);
5536 int type = virDomainDiskGetType(dev->data.disk);
5538 if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
5539 if (type == VIR_STORAGE_TYPE_FILE && src) {
5540 IDVDDrive *dvdDrive = NULL;
5541 /* Currently CDROM/DVD Drive is always IDE
5542 * Secondary Master so neglecting the following
5543 * parameter dev->data.disk->bus
5545 machine->vtbl->GetDVDDrive(machine, &dvdDrive);
5547 IDVDImage *dvdImage = NULL;
5548 PRUnichar *dvdfileUtf16 = NULL;
5549 vboxIID dvduuid = VBOX_IID_INITIALIZER;
5550 vboxIID dvdemptyuuid = VBOX_IID_INITIALIZER;
5552 VBOX_UTF8_TO_UTF16(src, &dvdfileUtf16);
5554 data->vboxObj->vtbl->FindDVDImage(data->vboxObj, dvdfileUtf16, &dvdImage);
5556 data->vboxObj->vtbl->OpenDVDImage(data->vboxObj, dvdfileUtf16, dvdemptyuuid.value, &dvdImage);
5559 rc = dvdImage->vtbl->imedium.GetId((IMedium *)dvdImage, &dvduuid.value);
5560 if (NS_FAILED(rc)) {
5561 virReportError(VIR_ERR_INTERNAL_ERROR,
5562 _("can't get the uuid of the file to "
5563 "be attached to cdrom: %s, rc=%08x"),
5566 /* unmount the previous mounted image */
5567 dvdDrive->vtbl->Unmount(dvdDrive);
5568 rc = dvdDrive->vtbl->MountImage(dvdDrive, dvduuid.value);
5569 if (NS_FAILED(rc)) {
5570 virReportError(VIR_ERR_INTERNAL_ERROR,
5571 _("could not attach the file to cdrom: %s, rc=%08x"),
5575 DEBUGIID("CD/DVD Image UUID:", dvduuid.value);
5579 VBOX_MEDIUM_RELEASE(dvdImage);
5581 vboxIIDUnalloc(&dvduuid);
5582 VBOX_UTF16_FREE(dvdfileUtf16);
5583 VBOX_RELEASE(dvdDrive);
5585 } else if (type == VIR_STORAGE_TYPE_BLOCK) {
5587 } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
5588 if (type == VIR_STORAGE_TYPE_FILE && src) {
5589 IFloppyDrive *floppyDrive;
5590 machine->vtbl->GetFloppyDrive(machine, &floppyDrive);
5592 rc = floppyDrive->vtbl->SetEnabled(floppyDrive, 1);
5593 if (NS_SUCCEEDED(rc)) {
5594 IFloppyImage *floppyImage = NULL;
5595 PRUnichar *fdfileUtf16 = NULL;
5596 vboxIID fduuid = VBOX_IID_INITIALIZER;
5597 vboxIID fdemptyuuid = VBOX_IID_INITIALIZER;
5598 VBOX_UTF8_TO_UTF16(src, &fdfileUtf16);
5599 rc = data->vboxObj->vtbl->FindFloppyImage(data->vboxObj,
5604 data->vboxObj->vtbl->OpenFloppyImage(data->vboxObj,
5611 rc = floppyImage->vtbl->imedium.GetId((IMedium *)floppyImage, &fduuid.value);
5612 if (NS_FAILED(rc)) {
5613 virReportError(VIR_ERR_INTERNAL_ERROR,
5614 _("can't get the uuid of the file to be "
5615 "attached to floppy drive: %s, rc=%08x"),
5618 rc = floppyDrive->vtbl->MountImage(floppyDrive, fduuid.value);
5619 if (NS_FAILED(rc)) {
5620 virReportError(VIR_ERR_INTERNAL_ERROR,
5621 _("could not attach the file to floppy drive: %s, rc=%08x"),
5625 DEBUGIID("attached floppy, UUID:", fduuid.value);
5628 VBOX_MEDIUM_RELEASE(floppyImage);
5630 vboxIIDUnalloc(&fduuid);
5631 VBOX_UTF16_FREE(fdfileUtf16);
5633 VBOX_RELEASE(floppyDrive);
5635 } else if (type == VIR_STORAGE_TYPE_BLOCK) {
5638 #else /* VBOX_API_VERSION >= 3001000 */
5639 #endif /* VBOX_API_VERSION >= 3001000 */
5640 } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
5641 } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
5642 if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
5643 if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
5646 } else if (dev->type == VIR_DOMAIN_DEVICE_FS &&
5647 dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) {
5648 PRUnichar *nameUtf16;
5649 PRUnichar *hostPathUtf16;
5652 VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16);
5653 VBOX_UTF8_TO_UTF16(dev->data.fs->src, &hostPathUtf16);
5654 writable = !dev->data.fs->readonly;
5656 #if VBOX_API_VERSION < 4000000
5657 rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16,
5659 #else /* VBOX_API_VERSION >= 4000000 */
5660 rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16,
5661 writable, PR_FALSE);
5662 #endif /* VBOX_API_VERSION >= 4000000 */
5664 if (NS_FAILED(rc)) {
5665 virReportError(VIR_ERR_INTERNAL_ERROR,
5666 _("could not attach shared folder '%s', rc=%08x"),
5667 dev->data.fs->dst, (unsigned)rc);
5672 VBOX_UTF16_FREE(nameUtf16);
5673 VBOX_UTF16_FREE(hostPathUtf16);
5675 machine->vtbl->SaveSettings(machine);
5676 VBOX_RELEASE(machine);
5678 VBOX_SESSION_CLOSE();
5683 vboxIIDUnalloc(&iid);
5684 virDomainDefFree(def);
5685 virDomainDeviceDefFree(dev);
5689 static int vboxDomainAttachDevice(virDomainPtr dom, const char *xml)
5691 return vboxDomainAttachDeviceImpl(dom, xml, 0);
5695 vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
5698 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1);
5700 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
5701 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
5702 _("cannot modify the persistent configuration of a domain"));
5706 return vboxDomainAttachDeviceImpl(dom, xml, 0);
5709 static int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
5712 virCheckFlags(VIR_DOMAIN_AFFECT_CURRENT |
5713 VIR_DOMAIN_AFFECT_LIVE |
5714 VIR_DOMAIN_AFFECT_CONFIG, -1);
5716 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
5717 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
5718 _("cannot modify the persistent configuration of a domain"));
5722 return vboxDomainAttachDeviceImpl(dom, xml, 1);
5725 static int vboxDomainDetachDevice(virDomainPtr dom, const char *xml)
5727 VBOX_OBJECT_CHECK(dom->conn, int, -1);
5728 IMachine *machine = NULL;
5729 vboxIID iid = VBOX_IID_INITIALIZER;
5730 PRUint32 state = MachineState_Null;
5731 virDomainDefPtr def = NULL;
5732 virDomainDeviceDefPtr dev = NULL;
5735 if (VIR_ALLOC(def) < 0)
5738 if (VIR_STRDUP(def->os.type, "hvm") < 0)
5741 dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt,
5742 VIR_DOMAIN_XML_INACTIVE);
5746 vboxIIDFromUUID(&iid, dom->uuid);
5747 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
5748 if (NS_FAILED(rc)) {
5749 virReportError(VIR_ERR_NO_DOMAIN, "%s",
5750 _("no domain with matching uuid"));
5755 machine->vtbl->GetState(machine, &state);
5757 if ((state == MachineState_Running) ||
5758 (state == MachineState_Paused)) {
5759 rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
5761 rc = VBOX_SESSION_OPEN(iid.value, machine);
5764 if (NS_SUCCEEDED(rc)) {
5765 rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
5766 if (NS_SUCCEEDED(rc) && machine) {
5767 if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
5768 #if VBOX_API_VERSION < 3001000
5769 int type = virDomainDiskGetType(dev->data.disk);
5771 if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
5772 if (type == VIR_STORAGE_TYPE_FILE) {
5773 IDVDDrive *dvdDrive = NULL;
5774 /* Currently CDROM/DVD Drive is always IDE
5775 * Secondary Master so neglecting the following
5776 * parameter dev->data.disk->bus
5778 machine->vtbl->GetDVDDrive(machine, &dvdDrive);
5780 rc = dvdDrive->vtbl->Unmount(dvdDrive);
5781 if (NS_FAILED(rc)) {
5782 virReportError(VIR_ERR_INTERNAL_ERROR,
5783 _("could not de-attach the mounted ISO, rc=%08x"),
5788 VBOX_RELEASE(dvdDrive);
5790 } else if (type == VIR_STORAGE_TYPE_BLOCK) {
5792 } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
5793 if (type == VIR_STORAGE_TYPE_FILE) {
5794 IFloppyDrive *floppyDrive;
5795 machine->vtbl->GetFloppyDrive(machine, &floppyDrive);
5797 PRBool enabled = PR_FALSE;
5799 floppyDrive->vtbl->GetEnabled(floppyDrive, &enabled);
5801 rc = floppyDrive->vtbl->Unmount(floppyDrive);
5802 if (NS_FAILED(rc)) {
5803 virReportError(VIR_ERR_INTERNAL_ERROR,
5804 _("could not attach the file "
5805 "to floppy drive, rc=%08x"),
5811 /* If you are here means floppy drive is already unmounted
5812 * so don't flag error, just say everything is fine and quit
5816 VBOX_RELEASE(floppyDrive);
5818 } else if (type == VIR_STORAGE_TYPE_BLOCK) {
5821 #else /* VBOX_API_VERSION >= 3001000 */
5822 #endif /* VBOX_API_VERSION >= 3001000 */
5823 } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
5824 } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
5825 if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
5826 if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
5829 } else if (dev->type == VIR_DOMAIN_DEVICE_FS &&
5830 dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) {
5831 PRUnichar *nameUtf16;
5833 VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16);
5835 rc = machine->vtbl->RemoveSharedFolder(machine, nameUtf16);
5837 if (NS_FAILED(rc)) {
5838 virReportError(VIR_ERR_INTERNAL_ERROR,
5839 _("could not detach shared folder '%s', rc=%08x"),
5840 dev->data.fs->dst, (unsigned)rc);
5845 VBOX_UTF16_FREE(nameUtf16);
5847 machine->vtbl->SaveSettings(machine);
5848 VBOX_RELEASE(machine);
5850 VBOX_SESSION_CLOSE();
5855 vboxIIDUnalloc(&iid);
5856 virDomainDefFree(def);
5857 virDomainDeviceDefFree(dev);
5862 vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
5865 virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1);
5867 if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
5868 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
5869 _("cannot modify the persistent configuration of a domain"));
5873 return vboxDomainDetachDevice(dom, xml);
5877 vboxDomainSnapshotGetAll(virDomainPtr dom,
5879 ISnapshot ***snapshots)
5881 vboxIID empty = VBOX_IID_INITIALIZER;
5882 ISnapshot **list = NULL;
5888 rc = machine->vtbl->GetSnapshotCount(machine, &count);
5889 if (NS_FAILED(rc)) {
5890 virReportError(VIR_ERR_INTERNAL_ERROR,
5891 _("could not get snapshot count for domain %s"),
5899 if (VIR_ALLOC_N(list, count) < 0)
5902 #if VBOX_API_VERSION < 4000000
5903 rc = machine->vtbl->GetSnapshot(machine, empty.value, list);
5904 #else /* VBOX_API_VERSION >= 4000000 */
5905 rc = machine->vtbl->FindSnapshot(machine, empty.value, list);
5906 #endif /* VBOX_API_VERSION >= 4000000 */
5907 if (NS_FAILED(rc) || !list[0]) {
5908 virReportError(VIR_ERR_INTERNAL_ERROR,
5909 _("could not get root snapshot for domain %s"),
5914 /* BFS walk through snapshot tree */
5916 for (next = 0; next < count; next++) {
5917 vboxArray children = VBOX_ARRAY_INITIALIZER;
5921 virReportError(VIR_ERR_INTERNAL_ERROR,
5922 _("unexpected number of snapshots < %u"), count);
5926 rc = vboxArrayGet(&children, list[next],
5927 list[next]->vtbl->GetChildren);
5928 if (NS_FAILED(rc)) {
5929 virReportError(VIR_ERR_INTERNAL_ERROR,
5930 "%s", _("could not get children snapshots"));
5933 for (i = 0; i < children.count; i++) {
5934 ISnapshot *child = children.items[i];
5938 virReportError(VIR_ERR_INTERNAL_ERROR,
5939 _("unexpected number of snapshots > %u"), count);
5940 vboxArrayRelease(&children);
5944 list[top++] = child;
5946 vboxArrayRelease(&children);
5955 for (next = 0; next < count; next++)
5956 VBOX_RELEASE(list[next]);
5964 vboxDomainSnapshotGet(vboxGlobalData *data,
5969 ISnapshot **snapshots = NULL;
5970 ISnapshot *snapshot = NULL;
5975 if ((count = vboxDomainSnapshotGetAll(dom, machine, &snapshots)) < 0)
5978 for (i = 0; i < count; i++) {
5979 PRUnichar *nameUtf16;
5982 rc = snapshots[i]->vtbl->GetName(snapshots[i], &nameUtf16);
5983 if (NS_FAILED(rc) || !nameUtf16) {
5984 virReportError(VIR_ERR_INTERNAL_ERROR,
5985 "%s", _("could not get snapshot name"));
5988 VBOX_UTF16_TO_UTF8(nameUtf16, &nameUtf8);
5989 VBOX_UTF16_FREE(nameUtf16);
5990 if (STREQ(name, nameUtf8))
5991 snapshot = snapshots[i];
5992 VBOX_UTF8_FREE(nameUtf8);
5999 virReportError(VIR_ERR_OPERATION_INVALID,
6000 _("domain %s has no snapshots with name %s"),
6007 for (i = 0; i < count; i++) {
6008 if (snapshots[i] != snapshot)
6009 VBOX_RELEASE(snapshots[i]);
6012 VIR_FREE(snapshots);
6016 static virDomainSnapshotPtr
6017 vboxDomainSnapshotCreateXML(virDomainPtr dom,
6018 const char *xmlDesc,
6021 VBOX_OBJECT_CHECK(dom->conn, virDomainSnapshotPtr, NULL);
6022 virDomainSnapshotDefPtr def = NULL;
6023 vboxIID domiid = VBOX_IID_INITIALIZER;
6024 IMachine *machine = NULL;
6025 IConsole *console = NULL;
6026 IProgress *progress = NULL;
6027 ISnapshot *snapshot = NULL;
6028 PRUnichar *name = NULL;
6029 PRUnichar *description = NULL;
6032 #if VBOX_API_VERSION == 2002000
6038 /* VBox has no snapshot metadata, so this flag is trivial. */
6039 virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA, NULL);
6041 if (!(def = virDomainSnapshotDefParseString(xmlDesc, data->caps,
6042 data->xmlopt, 0, 0)))
6046 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6047 _("disk snapshots not supported yet"));
6051 vboxIIDFromUUID(&domiid, dom->uuid);
6052 rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
6053 if (NS_FAILED(rc)) {
6054 virReportError(VIR_ERR_NO_DOMAIN, "%s",
6055 _("no domain with matching UUID"));
6059 rc = machine->vtbl->GetState(machine, &state);
6060 if (NS_FAILED(rc)) {
6061 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6062 _("could not get domain state"));
6066 if ((state >= MachineState_FirstOnline)
6067 && (state <= MachineState_LastOnline)) {
6068 rc = VBOX_SESSION_OPEN_EXISTING(domiid.value, machine);
6070 rc = VBOX_SESSION_OPEN(domiid.value, machine);
6073 if (NS_SUCCEEDED(rc))
6074 rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console);
6075 if (NS_FAILED(rc)) {
6076 virReportError(VIR_ERR_INTERNAL_ERROR,
6077 _("could not open VirtualBox session with domain %s"),
6082 VBOX_UTF8_TO_UTF16(def->name, &name);
6084 virReportOOMError();
6088 if (def->description) {
6089 VBOX_UTF8_TO_UTF16(def->description, &description);
6091 virReportOOMError();
6096 rc = console->vtbl->TakeSnapshot(console, name, description, &progress);
6097 if (NS_FAILED(rc) || !progress) {
6098 virReportError(VIR_ERR_INTERNAL_ERROR,
6099 _("could not take snapshot of domain %s"), dom->name);
6103 progress->vtbl->WaitForCompletion(progress, -1);
6104 progress->vtbl->GetResultCode(progress, &result);
6105 if (NS_FAILED(result)) {
6106 virReportError(VIR_ERR_INTERNAL_ERROR,
6107 _("could not take snapshot of domain %s"), dom->name);
6111 rc = machine->vtbl->GetCurrentSnapshot(machine, &snapshot);
6112 if (NS_FAILED(rc)) {
6113 virReportError(VIR_ERR_INTERNAL_ERROR,
6114 _("could not get current snapshot of domain %s"),
6119 ret = virGetDomainSnapshot(dom, def->name);
6122 VBOX_RELEASE(progress);
6123 VBOX_UTF16_FREE(description);
6124 VBOX_UTF16_FREE(name);
6125 VBOX_RELEASE(console);
6126 VBOX_SESSION_CLOSE();
6127 VBOX_RELEASE(machine);
6128 vboxIIDUnalloc(&domiid);
6129 virDomainSnapshotDefFree(def);
6134 vboxDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
6137 virDomainPtr dom = snapshot->domain;
6138 VBOX_OBJECT_CHECK(dom->conn, char *, NULL);
6139 vboxIID domiid = VBOX_IID_INITIALIZER;
6140 IMachine *machine = NULL;
6141 ISnapshot *snap = NULL;
6142 ISnapshot *parent = NULL;
6144 virDomainSnapshotDefPtr def = NULL;
6148 PRBool online = PR_FALSE;
6149 char uuidstr[VIR_UUID_STRING_BUFLEN];
6151 virCheckFlags(0, NULL);
6153 vboxIIDFromUUID(&domiid, dom->uuid);
6154 rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
6155 if (NS_FAILED(rc)) {
6156 virReportError(VIR_ERR_NO_DOMAIN, "%s",
6157 _("no domain with matching UUID"));
6161 if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name)))
6164 if (VIR_ALLOC(def) < 0)
6166 if (VIR_STRDUP(def->name, snapshot->name) < 0)
6169 rc = snap->vtbl->GetDescription(snap, &str16);
6170 if (NS_FAILED(rc)) {
6171 virReportError(VIR_ERR_INTERNAL_ERROR,
6172 _("could not get description of snapshot %s"),
6177 VBOX_UTF16_TO_UTF8(str16, &str8);
6178 VBOX_UTF16_FREE(str16);
6179 if (VIR_STRDUP(def->description, str8) < 0) {
6180 VBOX_UTF8_FREE(str8);
6183 VBOX_UTF8_FREE(str8);
6186 rc = snap->vtbl->GetTimeStamp(snap, ×tamp);
6187 if (NS_FAILED(rc)) {
6188 virReportError(VIR_ERR_INTERNAL_ERROR,
6189 _("could not get creation time of snapshot %s"),
6193 /* timestamp is in milliseconds while creationTime in seconds */
6194 def->creationTime = timestamp / 1000;
6196 rc = snap->vtbl->GetParent(snap, &parent);
6197 if (NS_FAILED(rc)) {
6198 virReportError(VIR_ERR_INTERNAL_ERROR,
6199 _("could not get parent of snapshot %s"),
6204 rc = parent->vtbl->GetName(parent, &str16);
6205 if (NS_FAILED(rc) || !str16) {
6206 virReportError(VIR_ERR_INTERNAL_ERROR,
6207 _("could not get name of parent of snapshot %s"),
6211 VBOX_UTF16_TO_UTF8(str16, &str8);
6212 VBOX_UTF16_FREE(str16);
6213 if (VIR_STRDUP(def->parent, str8) < 0) {
6214 VBOX_UTF8_FREE(str8);
6217 VBOX_UTF8_FREE(str8);
6220 rc = snap->vtbl->GetOnline(snap, &online);
6221 if (NS_FAILED(rc)) {
6222 virReportError(VIR_ERR_INTERNAL_ERROR,
6223 _("could not get online state of snapshot %s"),
6228 def->state = VIR_DOMAIN_RUNNING;
6230 def->state = VIR_DOMAIN_SHUTOFF;
6232 virUUIDFormat(dom->uuid, uuidstr);
6233 ret = virDomainSnapshotDefFormat(uuidstr, def, flags, 0);
6236 virDomainSnapshotDefFree(def);
6237 VBOX_RELEASE(parent);
6239 VBOX_RELEASE(machine);
6240 vboxIIDUnalloc(&domiid);
6245 vboxDomainSnapshotNum(virDomainPtr dom,
6248 VBOX_OBJECT_CHECK(dom->conn, int, -1);
6249 vboxIID iid = VBOX_IID_INITIALIZER;
6250 IMachine *machine = NULL;
6252 PRUint32 snapshotCount;
6254 virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
6255 VIR_DOMAIN_SNAPSHOT_LIST_METADATA, -1);
6257 vboxIIDFromUUID(&iid, dom->uuid);
6258 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
6259 if (NS_FAILED(rc)) {
6260 virReportError(VIR_ERR_NO_DOMAIN, "%s",
6261 _("no domain with matching UUID"));
6265 /* VBox snapshots do not require libvirt to maintain any metadata. */
6266 if (flags & VIR_DOMAIN_SNAPSHOT_LIST_METADATA) {
6271 rc = machine->vtbl->GetSnapshotCount(machine, &snapshotCount);
6272 if (NS_FAILED(rc)) {
6273 virReportError(VIR_ERR_INTERNAL_ERROR,
6274 _("could not get snapshot count for domain %s"),
6279 /* VBox has at most one root snapshot. */
6280 if (snapshotCount && (flags & VIR_DOMAIN_SNAPSHOT_LIST_ROOTS))
6283 ret = snapshotCount;
6286 VBOX_RELEASE(machine);
6287 vboxIIDUnalloc(&iid);
6292 vboxDomainSnapshotListNames(virDomainPtr dom,
6297 VBOX_OBJECT_CHECK(dom->conn, int, -1);
6298 vboxIID iid = VBOX_IID_INITIALIZER;
6299 IMachine *machine = NULL;
6301 ISnapshot **snapshots = NULL;
6305 virCheckFlags(VIR_DOMAIN_SNAPSHOT_LIST_ROOTS |
6306 VIR_DOMAIN_SNAPSHOT_LIST_METADATA, -1);
6308 vboxIIDFromUUID(&iid, dom->uuid);
6309 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
6310 if (NS_FAILED(rc)) {
6311 virReportError(VIR_ERR_NO_DOMAIN, "%s",
6312 _("no domain with matching UUID"));
6316 if (flags & VIR_DOMAIN_SNAPSHOT_LIST_METADATA) {
6321 if (flags & VIR_DOMAIN_SNAPSHOT_LIST_ROOTS) {
6322 vboxIID empty = VBOX_IID_INITIALIZER;
6324 if (VIR_ALLOC_N(snapshots, 1) < 0)
6326 #if VBOX_API_VERSION < 4000000
6327 rc = machine->vtbl->GetSnapshot(machine, empty.value, snapshots);
6328 #else /* VBOX_API_VERSION >= 4000000 */
6329 rc = machine->vtbl->FindSnapshot(machine, empty.value, snapshots);
6330 #endif /* VBOX_API_VERSION >= 4000000 */
6331 if (NS_FAILED(rc) || !snapshots[0]) {
6332 virReportError(VIR_ERR_INTERNAL_ERROR,
6333 _("could not get root snapshot for domain %s"),
6339 if ((count = vboxDomainSnapshotGetAll(dom, machine, &snapshots)) < 0)
6343 for (i = 0; i < nameslen; i++) {
6344 PRUnichar *nameUtf16;
6350 rc = snapshots[i]->vtbl->GetName(snapshots[i], &nameUtf16);
6351 if (NS_FAILED(rc) || !nameUtf16) {
6352 virReportError(VIR_ERR_INTERNAL_ERROR,
6353 "%s", _("could not get snapshot name"));
6356 VBOX_UTF16_TO_UTF8(nameUtf16, &name);
6357 VBOX_UTF16_FREE(nameUtf16);
6358 if (VIR_STRDUP(names[i], name) < 0) {
6359 VBOX_UTF8_FREE(name);
6362 VBOX_UTF8_FREE(name);
6365 if (count <= nameslen)
6372 for (i = 0; i < count; i++)
6373 VBOX_RELEASE(snapshots[i]);
6375 VIR_FREE(snapshots);
6376 VBOX_RELEASE(machine);
6377 vboxIIDUnalloc(&iid);
6381 static virDomainSnapshotPtr
6382 vboxDomainSnapshotLookupByName(virDomainPtr dom,
6386 VBOX_OBJECT_CHECK(dom->conn, virDomainSnapshotPtr, NULL);
6387 vboxIID iid = VBOX_IID_INITIALIZER;
6388 IMachine *machine = NULL;
6389 ISnapshot *snapshot = NULL;
6392 virCheckFlags(0, NULL);
6394 vboxIIDFromUUID(&iid, dom->uuid);
6395 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
6396 if (NS_FAILED(rc)) {
6397 virReportError(VIR_ERR_NO_DOMAIN, "%s",
6398 _("no domain with matching UUID"));
6402 if (!(snapshot = vboxDomainSnapshotGet(data, dom, machine, name)))
6405 ret = virGetDomainSnapshot(dom, name);
6408 VBOX_RELEASE(snapshot);
6409 VBOX_RELEASE(machine);
6410 vboxIIDUnalloc(&iid);
6415 vboxDomainHasCurrentSnapshot(virDomainPtr dom,
6418 VBOX_OBJECT_CHECK(dom->conn, int, -1);
6419 vboxIID iid = VBOX_IID_INITIALIZER;
6420 IMachine *machine = NULL;
6421 ISnapshot *snapshot = NULL;
6424 virCheckFlags(0, -1);
6426 vboxIIDFromUUID(&iid, dom->uuid);
6427 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
6428 if (NS_FAILED(rc)) {
6429 virReportError(VIR_ERR_NO_DOMAIN, "%s",
6430 _("no domain with matching UUID"));
6434 rc = machine->vtbl->GetCurrentSnapshot(machine, &snapshot);
6435 if (NS_FAILED(rc)) {
6436 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6437 _("could not get current snapshot"));
6447 VBOX_RELEASE(machine);
6448 vboxIIDUnalloc(&iid);
6452 static virDomainSnapshotPtr
6453 vboxDomainSnapshotGetParent(virDomainSnapshotPtr snapshot,
6456 virDomainPtr dom = snapshot->domain;
6457 VBOX_OBJECT_CHECK(dom->conn, virDomainSnapshotPtr, NULL);
6458 vboxIID iid = VBOX_IID_INITIALIZER;
6459 IMachine *machine = NULL;
6460 ISnapshot *snap = NULL;
6461 ISnapshot *parent = NULL;
6462 PRUnichar *nameUtf16 = NULL;
6466 virCheckFlags(0, NULL);
6468 vboxIIDFromUUID(&iid, dom->uuid);
6469 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
6470 if (NS_FAILED(rc)) {
6471 virReportError(VIR_ERR_NO_DOMAIN, "%s",
6472 _("no domain with matching UUID"));
6476 if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name)))
6479 rc = snap->vtbl->GetParent(snap, &parent);
6480 if (NS_FAILED(rc)) {
6481 virReportError(VIR_ERR_INTERNAL_ERROR,
6482 _("could not get parent of snapshot %s"),
6487 virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT,
6488 _("snapshot '%s' does not have a parent"),
6493 rc = parent->vtbl->GetName(parent, &nameUtf16);
6494 if (NS_FAILED(rc) || !nameUtf16) {
6495 virReportError(VIR_ERR_INTERNAL_ERROR,
6496 _("could not get name of parent of snapshot %s"),
6500 VBOX_UTF16_TO_UTF8(nameUtf16, &name);
6502 virReportOOMError();
6506 ret = virGetDomainSnapshot(dom, name);
6509 VBOX_UTF8_FREE(name);
6510 VBOX_UTF16_FREE(nameUtf16);
6512 VBOX_RELEASE(parent);
6513 VBOX_RELEASE(machine);
6514 vboxIIDUnalloc(&iid);
6518 static virDomainSnapshotPtr
6519 vboxDomainSnapshotCurrent(virDomainPtr dom,
6522 VBOX_OBJECT_CHECK(dom->conn, virDomainSnapshotPtr, NULL);
6523 vboxIID iid = VBOX_IID_INITIALIZER;
6524 IMachine *machine = NULL;
6525 ISnapshot *snapshot = NULL;
6526 PRUnichar *nameUtf16 = NULL;
6530 virCheckFlags(0, NULL);
6532 vboxIIDFromUUID(&iid, dom->uuid);
6533 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
6534 if (NS_FAILED(rc)) {
6535 virReportError(VIR_ERR_NO_DOMAIN, "%s",
6536 _("no domain with matching UUID"));
6540 rc = machine->vtbl->GetCurrentSnapshot(machine, &snapshot);
6541 if (NS_FAILED(rc)) {
6542 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6543 _("could not get current snapshot"));
6548 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6549 _("domain has no snapshots"));
6553 rc = snapshot->vtbl->GetName(snapshot, &nameUtf16);
6554 if (NS_FAILED(rc) || !nameUtf16) {
6555 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6556 _("could not get current snapshot name"));
6560 VBOX_UTF16_TO_UTF8(nameUtf16, &name);
6562 virReportOOMError();
6566 ret = virGetDomainSnapshot(dom, name);
6569 VBOX_UTF8_FREE(name);
6570 VBOX_UTF16_FREE(nameUtf16);
6571 VBOX_RELEASE(snapshot);
6572 VBOX_RELEASE(machine);
6573 vboxIIDUnalloc(&iid);
6578 vboxDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot,
6581 virDomainPtr dom = snapshot->domain;
6582 VBOX_OBJECT_CHECK(dom->conn, int, -1);
6583 vboxIID iid = VBOX_IID_INITIALIZER;
6584 IMachine *machine = NULL;
6585 ISnapshot *snap = NULL;
6586 ISnapshot *current = NULL;
6587 PRUnichar *nameUtf16 = NULL;
6591 virCheckFlags(0, -1);
6593 vboxIIDFromUUID(&iid, dom->uuid);
6594 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
6595 if (NS_FAILED(rc)) {
6596 virReportError(VIR_ERR_NO_DOMAIN, "%s",
6597 _("no domain with matching UUID"));
6601 if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name)))
6604 rc = machine->vtbl->GetCurrentSnapshot(machine, ¤t);
6605 if (NS_FAILED(rc)) {
6606 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6607 _("could not get current snapshot"));
6615 rc = current->vtbl->GetName(current, &nameUtf16);
6616 if (NS_FAILED(rc) || !nameUtf16) {
6617 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6618 _("could not get current snapshot name"));
6622 VBOX_UTF16_TO_UTF8(nameUtf16, &name);
6624 virReportOOMError();
6628 ret = STREQ(snapshot->name, name);
6631 VBOX_UTF8_FREE(name);
6632 VBOX_UTF16_FREE(nameUtf16);
6634 VBOX_RELEASE(current);
6635 VBOX_RELEASE(machine);
6636 vboxIIDUnalloc(&iid);
6641 vboxDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot,
6644 virDomainPtr dom = snapshot->domain;
6645 VBOX_OBJECT_CHECK(dom->conn, int, -1);
6646 vboxIID iid = VBOX_IID_INITIALIZER;
6647 IMachine *machine = NULL;
6648 ISnapshot *snap = NULL;
6651 virCheckFlags(0, -1);
6653 vboxIIDFromUUID(&iid, dom->uuid);
6654 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
6655 if (NS_FAILED(rc)) {
6656 virReportError(VIR_ERR_NO_DOMAIN, "%s",
6657 _("no domain with matching UUID"));
6661 /* Check that snapshot exists. If so, there is no metadata. */
6662 if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name)))
6669 VBOX_RELEASE(machine);
6670 vboxIIDUnalloc(&iid);
6674 #if VBOX_API_VERSION < 3001000
6676 vboxDomainSnapshotRestore(virDomainPtr dom,
6678 ISnapshot *snapshot)
6680 VBOX_OBJECT_CHECK(dom->conn, int, -1);
6681 vboxIID iid = VBOX_IID_INITIALIZER;
6684 rc = snapshot->vtbl->GetId(snapshot, &iid.value);
6685 if (NS_FAILED(rc)) {
6686 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6687 _("could not get snapshot UUID"));
6691 rc = machine->vtbl->SetCurrentSnapshot(machine, iid.value);
6692 if (NS_FAILED(rc)) {
6693 virReportError(VIR_ERR_INTERNAL_ERROR,
6694 _("could not restore snapshot for domain %s"), dom->name);
6701 vboxIIDUnalloc(&iid);
6706 vboxDomainSnapshotRestore(virDomainPtr dom,
6708 ISnapshot *snapshot)
6710 VBOX_OBJECT_CHECK(dom->conn, int, -1);
6711 IConsole *console = NULL;
6712 IProgress *progress = NULL;
6716 vboxIID domiid = VBOX_IID_INITIALIZER;
6718 rc = machine->vtbl->GetId(machine, &domiid.value);
6719 if (NS_FAILED(rc)) {
6720 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6721 _("could not get domain UUID"));
6725 rc = machine->vtbl->GetState(machine, &state);
6726 if (NS_FAILED(rc)) {
6727 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6728 _("could not get domain state"));
6732 if (state >= MachineState_FirstOnline
6733 && state <= MachineState_LastOnline) {
6734 virReportError(VIR_ERR_OPERATION_INVALID,
6735 _("domain %s is already running"), dom->name);
6739 rc = VBOX_SESSION_OPEN(domiid.value, machine);
6740 if (NS_SUCCEEDED(rc))
6741 rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console);
6742 if (NS_FAILED(rc)) {
6743 virReportError(VIR_ERR_INTERNAL_ERROR,
6744 _("could not open VirtualBox session with domain %s"),
6749 rc = console->vtbl->RestoreSnapshot(console, snapshot, &progress);
6750 if (NS_FAILED(rc) || !progress) {
6751 if (rc == VBOX_E_INVALID_VM_STATE) {
6752 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6753 _("cannot restore domain snapshot for running domain"));
6755 virReportError(VIR_ERR_INTERNAL_ERROR,
6756 _("could not restore snapshot for domain %s"),
6762 progress->vtbl->WaitForCompletion(progress, -1);
6763 progress->vtbl->GetResultCode(progress, &result);
6764 if (NS_FAILED(result)) {
6765 virReportError(VIR_ERR_INTERNAL_ERROR,
6766 _("could not restore snapshot for domain %s"), dom->name);
6773 VBOX_RELEASE(progress);
6774 VBOX_RELEASE(console);
6775 VBOX_SESSION_CLOSE();
6776 vboxIIDUnalloc(&domiid);
6782 vboxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
6785 virDomainPtr dom = snapshot->domain;
6786 VBOX_OBJECT_CHECK(dom->conn, int, -1);
6787 vboxIID domiid = VBOX_IID_INITIALIZER;
6788 IMachine *machine = NULL;
6789 ISnapshot *newSnapshot = NULL;
6790 ISnapshot *prevSnapshot = NULL;
6791 PRBool online = PR_FALSE;
6795 virCheckFlags(0, -1);
6797 vboxIIDFromUUID(&domiid, dom->uuid);
6798 rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
6799 if (NS_FAILED(rc)) {
6800 virReportError(VIR_ERR_NO_DOMAIN, "%s",
6801 _("no domain with matching UUID"));
6805 newSnapshot = vboxDomainSnapshotGet(data, dom, machine, snapshot->name);
6809 rc = newSnapshot->vtbl->GetOnline(newSnapshot, &online);
6810 if (NS_FAILED(rc)) {
6811 virReportError(VIR_ERR_INTERNAL_ERROR,
6812 _("could not get online state of snapshot %s"),
6817 rc = machine->vtbl->GetCurrentSnapshot(machine, &prevSnapshot);
6818 if (NS_FAILED(rc)) {
6819 virReportError(VIR_ERR_INTERNAL_ERROR,
6820 _("could not get current snapshot of domain %s"),
6825 rc = machine->vtbl->GetState(machine, &state);
6826 if (NS_FAILED(rc)) {
6827 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6828 _("could not get domain state"));
6832 if (state >= MachineState_FirstOnline
6833 && state <= MachineState_LastOnline) {
6834 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6835 _("cannot revert snapshot of running domain"));
6839 if (vboxDomainSnapshotRestore(dom, machine, newSnapshot))
6843 ret = vboxDomainCreate(dom);
6845 vboxDomainSnapshotRestore(dom, machine, prevSnapshot);
6850 VBOX_RELEASE(prevSnapshot);
6851 VBOX_RELEASE(newSnapshot);
6852 vboxIIDUnalloc(&domiid);
6857 vboxDomainSnapshotDeleteSingle(vboxGlobalData *data,
6859 ISnapshot *snapshot)
6861 IProgress *progress = NULL;
6862 vboxIID iid = VBOX_IID_INITIALIZER;
6865 #if VBOX_API_VERSION == 2002000
6871 rc = snapshot->vtbl->GetId(snapshot, &iid.value);
6872 if (NS_FAILED(rc)) {
6873 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6874 _("could not get snapshot UUID"));
6878 #if VBOX_API_VERSION < 3001000
6879 rc = console->vtbl->DiscardSnapshot(console, iid.value, &progress);
6881 rc = console->vtbl->DeleteSnapshot(console, iid.value, &progress);
6883 if (NS_FAILED(rc) || !progress) {
6884 if (rc == VBOX_E_INVALID_VM_STATE) {
6885 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6886 _("cannot delete domain snapshot for running domain"));
6888 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6889 _("could not delete snapshot"));
6894 progress->vtbl->WaitForCompletion(progress, -1);
6895 progress->vtbl->GetResultCode(progress, &result);
6896 if (NS_FAILED(result)) {
6897 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6898 _("could not delete snapshot"));
6905 VBOX_RELEASE(progress);
6906 vboxIIDUnalloc(&iid);
6911 vboxDomainSnapshotDeleteTree(vboxGlobalData *data,
6913 ISnapshot *snapshot)
6915 vboxArray children = VBOX_ARRAY_INITIALIZER;
6920 rc = vboxArrayGet(&children, snapshot, snapshot->vtbl->GetChildren);
6921 if (NS_FAILED(rc)) {
6922 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6923 _("could not get children snapshots"));
6927 for (i = 0; i < children.count; i++) {
6928 if (vboxDomainSnapshotDeleteTree(data, console, children.items[i]))
6932 ret = vboxDomainSnapshotDeleteSingle(data, console, snapshot);
6935 vboxArrayRelease(&children);
6940 vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
6943 virDomainPtr dom = snapshot->domain;
6944 VBOX_OBJECT_CHECK(dom->conn, int, -1);
6945 vboxIID domiid = VBOX_IID_INITIALIZER;
6946 IMachine *machine = NULL;
6947 ISnapshot *snap = NULL;
6948 IConsole *console = NULL;
6952 virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN |
6953 VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, -1);
6955 vboxIIDFromUUID(&domiid, dom->uuid);
6956 rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
6957 if (NS_FAILED(rc)) {
6958 virReportError(VIR_ERR_NO_DOMAIN, "%s",
6959 _("no domain with matching UUID"));
6963 snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name);
6967 rc = machine->vtbl->GetState(machine, &state);
6968 if (NS_FAILED(rc)) {
6969 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6970 _("could not get domain state"));
6974 /* VBOX snapshots do not require any libvirt metadata, making this
6975 * flag trivial once we know we have a valid snapshot. */
6976 if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY) {
6981 if (state >= MachineState_FirstOnline
6982 && state <= MachineState_LastOnline) {
6983 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
6984 _("cannot delete snapshots of running domain"));
6988 rc = VBOX_SESSION_OPEN(domiid.value, machine);
6989 if (NS_SUCCEEDED(rc))
6990 rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console);
6991 if (NS_FAILED(rc)) {
6992 virReportError(VIR_ERR_INTERNAL_ERROR,
6993 _("could not open VirtualBox session with domain %s"),
6998 if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN)
6999 ret = vboxDomainSnapshotDeleteTree(data, console, snap);
7001 ret = vboxDomainSnapshotDeleteSingle(data, console, snap);
7004 VBOX_RELEASE(console);
7006 vboxIIDUnalloc(&domiid);
7007 VBOX_SESSION_CLOSE();
7011 #if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000
7012 /* No Callback support for VirtualBox 2.2.* series */
7013 /* No Callback support for VirtualBox 4.* series */
7014 #else /* !(VBOX_API_VERSION == 2002000 || VBOX_API_VERSION >= 4000000) */
7016 /* Functions needed for Callbacks */
7017 static nsresult PR_COM_METHOD
7018 vboxCallbackOnMachineStateChange(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED,
7019 PRUnichar *machineId, PRUint32 state)
7021 virDomainPtr dom = NULL;
7025 vboxDriverLock(g_pVBoxGlobalData);
7027 VIR_DEBUG("IVirtualBoxCallback: %p, State: %d", pThis, state);
7028 DEBUGPRUnichar("machineId", machineId);
7031 char *machineIdUtf8 = NULL;
7032 unsigned char uuid[VIR_UUID_BUFLEN];
7034 g_pVBoxGlobalData->pFuncs->pfnUtf16ToUtf8(machineId, &machineIdUtf8);
7035 ignore_value(virUUIDParse(machineIdUtf8, uuid));
7037 dom = vboxDomainLookupByUUID(g_pVBoxGlobalData->conn, uuid);
7039 virObjectEventPtr ev;
7041 if (state == MachineState_Starting) {
7042 event = VIR_DOMAIN_EVENT_STARTED;
7043 detail = VIR_DOMAIN_EVENT_STARTED_BOOTED;
7044 } else if (state == MachineState_Restoring) {
7045 event = VIR_DOMAIN_EVENT_STARTED;
7046 detail = VIR_DOMAIN_EVENT_STARTED_RESTORED;
7047 } else if (state == MachineState_Paused) {
7048 event = VIR_DOMAIN_EVENT_SUSPENDED;
7049 detail = VIR_DOMAIN_EVENT_SUSPENDED_PAUSED;
7050 } else if (state == MachineState_Running) {
7051 event = VIR_DOMAIN_EVENT_RESUMED;
7052 detail = VIR_DOMAIN_EVENT_RESUMED_UNPAUSED;
7053 } else if (state == MachineState_PoweredOff) {
7054 event = VIR_DOMAIN_EVENT_STOPPED;
7055 detail = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN;
7056 } else if (state == MachineState_Stopping) {
7057 event = VIR_DOMAIN_EVENT_STOPPED;
7058 detail = VIR_DOMAIN_EVENT_STOPPED_DESTROYED;
7059 } else if (state == MachineState_Aborted) {
7060 event = VIR_DOMAIN_EVENT_STOPPED;
7061 detail = VIR_DOMAIN_EVENT_STOPPED_CRASHED;
7062 } else if (state == MachineState_Saving) {
7063 event = VIR_DOMAIN_EVENT_STOPPED;
7064 detail = VIR_DOMAIN_EVENT_STOPPED_SAVED;
7066 event = VIR_DOMAIN_EVENT_STOPPED;
7067 detail = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN;
7070 ev = virDomainEventLifecycleNewFromDom(dom, event, detail);
7073 virObjectEventStateQueue(g_pVBoxGlobalData->domainEvents, ev);
7077 vboxDriverUnlock(g_pVBoxGlobalData);
7082 static nsresult PR_COM_METHOD
7083 vboxCallbackOnMachineDataChange(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED,
7084 PRUnichar *machineId)
7086 VIR_DEBUG("IVirtualBoxCallback: %p", pThis);
7087 DEBUGPRUnichar("machineId", machineId);
7092 static nsresult PR_COM_METHOD
7093 vboxCallbackOnExtraDataCanChange(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED,
7094 PRUnichar *machineId, PRUnichar *key,
7096 PRUnichar **error ATTRIBUTE_UNUSED,
7097 PRBool *allowChange ATTRIBUTE_UNUSED)
7099 VIR_DEBUG("IVirtualBoxCallback: %p, allowChange: %s", pThis, *allowChange ? "true" : "false");
7100 DEBUGPRUnichar("machineId", machineId);
7101 DEBUGPRUnichar("key", key);
7102 DEBUGPRUnichar("value", value);
7107 static nsresult PR_COM_METHOD
7108 vboxCallbackOnExtraDataChange(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED,
7109 PRUnichar *machineId,
7110 PRUnichar *key, PRUnichar *value)
7112 VIR_DEBUG("IVirtualBoxCallback: %p", pThis);
7113 DEBUGPRUnichar("machineId", machineId);
7114 DEBUGPRUnichar("key", key);
7115 DEBUGPRUnichar("value", value);
7120 # if VBOX_API_VERSION < 3001000
7121 static nsresult PR_COM_METHOD
7122 vboxCallbackOnMediaRegistered(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED,
7124 PRUint32 mediaType ATTRIBUTE_UNUSED,
7125 PRBool registered ATTRIBUTE_UNUSED)
7127 VIR_DEBUG("IVirtualBoxCallback: %p, registered: %s", pThis, registered ? "true" : "false");
7128 VIR_DEBUG("mediaType: %d", mediaType);
7129 DEBUGPRUnichar("mediaId", mediaId);
7133 # else /* VBOX_API_VERSION >= 3001000 */
7134 # endif /* VBOX_API_VERSION >= 3001000 */
7136 static nsresult PR_COM_METHOD
7137 vboxCallbackOnMachineRegistered(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED,
7138 PRUnichar *machineId, PRBool registered)
7140 virDomainPtr dom = NULL;
7144 vboxDriverLock(g_pVBoxGlobalData);
7146 VIR_DEBUG("IVirtualBoxCallback: %p, registered: %s", pThis, registered ? "true" : "false");
7147 DEBUGPRUnichar("machineId", machineId);
7150 char *machineIdUtf8 = NULL;
7151 unsigned char uuid[VIR_UUID_BUFLEN];
7153 g_pVBoxGlobalData->pFuncs->pfnUtf16ToUtf8(machineId, &machineIdUtf8);
7154 ignore_value(virUUIDParse(machineIdUtf8, uuid));
7156 dom = vboxDomainLookupByUUID(g_pVBoxGlobalData->conn, uuid);
7158 virObjectEventPtr ev;
7160 /* CURRENT LIMITATION: we never get the VIR_DOMAIN_EVENT_UNDEFINED
7161 * event because the when the machine is de-registered the call
7162 * to vboxDomainLookupByUUID fails and thus we don't get any
7163 * dom pointer which is necessary (null dom pointer doesn't work)
7164 * to show the VIR_DOMAIN_EVENT_UNDEFINED event
7167 event = VIR_DOMAIN_EVENT_DEFINED;
7168 detail = VIR_DOMAIN_EVENT_DEFINED_ADDED;
7170 event = VIR_DOMAIN_EVENT_UNDEFINED;
7171 detail = VIR_DOMAIN_EVENT_UNDEFINED_REMOVED;
7174 ev = virDomainEventLifecycleNewFromDom(dom, event, detail);
7177 virObjectEventStateQueue(g_pVBoxGlobalData->domainEvents, ev);
7181 vboxDriverUnlock(g_pVBoxGlobalData);
7186 static nsresult PR_COM_METHOD
7187 vboxCallbackOnSessionStateChange(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED,
7188 PRUnichar *machineId,
7189 PRUint32 state ATTRIBUTE_UNUSED)
7191 VIR_DEBUG("IVirtualBoxCallback: %p, state: %d", pThis, state);
7192 DEBUGPRUnichar("machineId", machineId);
7197 static nsresult PR_COM_METHOD
7198 vboxCallbackOnSnapshotTaken(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED,
7199 PRUnichar *machineId,
7200 PRUnichar *snapshotId)
7202 VIR_DEBUG("IVirtualBoxCallback: %p", pThis);
7203 DEBUGPRUnichar("machineId", machineId);
7204 DEBUGPRUnichar("snapshotId", snapshotId);
7209 static nsresult PR_COM_METHOD
7210 vboxCallbackOnSnapshotDiscarded(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED,
7211 PRUnichar *machineId,
7212 PRUnichar *snapshotId)
7214 VIR_DEBUG("IVirtualBoxCallback: %p", pThis);
7215 DEBUGPRUnichar("machineId", machineId);
7216 DEBUGPRUnichar("snapshotId", snapshotId);
7221 static nsresult PR_COM_METHOD
7222 vboxCallbackOnSnapshotChange(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED,
7223 PRUnichar *machineId,
7224 PRUnichar *snapshotId)
7226 VIR_DEBUG("IVirtualBoxCallback: %p", pThis);
7227 DEBUGPRUnichar("machineId", machineId);
7228 DEBUGPRUnichar("snapshotId", snapshotId);
7233 static nsresult PR_COM_METHOD
7234 vboxCallbackOnGuestPropertyChange(IVirtualBoxCallback *pThis ATTRIBUTE_UNUSED,
7235 PRUnichar *machineId, PRUnichar *name,
7236 PRUnichar *value, PRUnichar *flags)
7238 VIR_DEBUG("IVirtualBoxCallback: %p", pThis);
7239 DEBUGPRUnichar("machineId", machineId);
7240 DEBUGPRUnichar("name", name);
7241 DEBUGPRUnichar("value", value);
7242 DEBUGPRUnichar("flags", flags);
7247 static nsresult PR_COM_METHOD
7248 vboxCallbackAddRef(nsISupports *pThis ATTRIBUTE_UNUSED)
7252 c = ++g_pVBoxGlobalData->vboxCallBackRefCount;
7254 VIR_DEBUG("pThis: %p, vboxCallback AddRef: %d", pThis, c);
7259 static nsresult PR_COM_METHOD
7260 vboxCallbackRelease(nsISupports *pThis)
7264 c = --g_pVBoxGlobalData->vboxCallBackRefCount;
7267 VIR_FREE(pThis->vtbl);
7271 VIR_DEBUG("pThis: %p, vboxCallback Release: %d", pThis, c);
7276 static nsresult PR_COM_METHOD
7277 vboxCallbackQueryInterface(nsISupports *pThis, const nsID *iid, void **resultp)
7279 IVirtualBoxCallback *that = (IVirtualBoxCallback *)pThis;
7280 static const nsID ivirtualboxCallbackUUID = IVIRTUALBOXCALLBACK_IID;
7281 static const nsID isupportIID = NS_ISUPPORTS_IID;
7283 /* Match UUID for IVirtualBoxCallback class */
7284 if (memcmp(iid, &ivirtualboxCallbackUUID, sizeof(nsID)) == 0 ||
7285 memcmp(iid, &isupportIID, sizeof(nsID)) == 0) {
7286 g_pVBoxGlobalData->vboxCallBackRefCount++;
7289 VIR_DEBUG("pThis: %p, vboxCallback QueryInterface: %d", pThis, g_pVBoxGlobalData->vboxCallBackRefCount);
7295 VIR_DEBUG("pThis: %p, vboxCallback QueryInterface didn't find a matching interface", pThis);
7296 DEBUGUUID("The UUID Callback Interface expects", iid);
7297 DEBUGUUID("The UUID Callback Interface got", &ivirtualboxCallbackUUID);
7298 return NS_NOINTERFACE;
7302 static IVirtualBoxCallback *vboxAllocCallbackObj(void) {
7303 IVirtualBoxCallback *vboxCallback = NULL;
7305 /* Allocate, Initialize and return a valid
7306 * IVirtualBoxCallback object here
7308 if ((VIR_ALLOC(vboxCallback) < 0) || (VIR_ALLOC(vboxCallback->vtbl) < 0)) {
7309 VIR_FREE(vboxCallback);
7314 vboxCallback->vtbl->nsisupports.AddRef = &vboxCallbackAddRef;
7315 vboxCallback->vtbl->nsisupports.Release = &vboxCallbackRelease;
7316 vboxCallback->vtbl->nsisupports.QueryInterface = &vboxCallbackQueryInterface;
7317 vboxCallback->vtbl->OnMachineStateChange = &vboxCallbackOnMachineStateChange;
7318 vboxCallback->vtbl->OnMachineDataChange = &vboxCallbackOnMachineDataChange;
7319 vboxCallback->vtbl->OnExtraDataCanChange = &vboxCallbackOnExtraDataCanChange;
7320 vboxCallback->vtbl->OnExtraDataChange = &vboxCallbackOnExtraDataChange;
7321 # if VBOX_API_VERSION < 3001000
7322 vboxCallback->vtbl->OnMediaRegistered = &vboxCallbackOnMediaRegistered;
7323 # else /* VBOX_API_VERSION >= 3001000 */
7324 # endif /* VBOX_API_VERSION >= 3001000 */
7325 vboxCallback->vtbl->OnMachineRegistered = &vboxCallbackOnMachineRegistered;
7326 vboxCallback->vtbl->OnSessionStateChange = &vboxCallbackOnSessionStateChange;
7327 vboxCallback->vtbl->OnSnapshotTaken = &vboxCallbackOnSnapshotTaken;
7328 # if VBOX_API_VERSION < 3002000
7329 vboxCallback->vtbl->OnSnapshotDiscarded = &vboxCallbackOnSnapshotDiscarded;
7330 # else /* VBOX_API_VERSION >= 3002000 */
7331 vboxCallback->vtbl->OnSnapshotDeleted = &vboxCallbackOnSnapshotDiscarded;
7332 # endif /* VBOX_API_VERSION >= 3002000 */
7333 vboxCallback->vtbl->OnSnapshotChange = &vboxCallbackOnSnapshotChange;
7334 vboxCallback->vtbl->OnGuestPropertyChange = &vboxCallbackOnGuestPropertyChange;
7335 g_pVBoxGlobalData->vboxCallBackRefCount = 1;
7339 return vboxCallback;
7342 static void vboxReadCallback(int watch ATTRIBUTE_UNUSED,
7344 int events ATTRIBUTE_UNUSED,
7345 void *opaque ATTRIBUTE_UNUSED)
7348 g_pVBoxGlobalData->vboxQueue->vtbl->ProcessPendingEvents(g_pVBoxGlobalData->vboxQueue);
7351 PLEvent *pEvent = NULL;
7353 rc = g_pVBoxGlobalData->vboxQueue->vtbl->WaitForEvent(g_pVBoxGlobalData->vboxQueue, &pEvent);
7354 if (NS_SUCCEEDED(rc))
7355 g_pVBoxGlobalData->vboxQueue->vtbl->HandleEvent(g_pVBoxGlobalData->vboxQueue, pEvent);
7360 vboxConnectDomainEventRegister(virConnectPtr conn,
7361 virConnectDomainEventCallback callback,
7363 virFreeCallback freecb)
7365 VBOX_OBJECT_CHECK(conn, int, -1);
7369 /* Locking has to be there as callbacks are not
7370 * really fully thread safe
7372 vboxDriverLock(data);
7374 if (data->vboxCallback == NULL) {
7375 data->vboxCallback = vboxAllocCallbackObj();
7376 if (data->vboxCallback != NULL) {
7377 rc = data->vboxObj->vtbl->RegisterCallback(data->vboxObj, data->vboxCallback);
7378 if (NS_SUCCEEDED(rc)) {
7386 /* Get the vbox file handle and add a event handle to it
7387 * so that the events can be passed down to the user
7390 if (data->fdWatch < 0) {
7391 PRInt32 vboxFileHandle;
7392 vboxFileHandle = data->vboxQueue->vtbl->GetEventQueueSelectFD(data->vboxQueue);
7394 data->fdWatch = virEventAddHandle(vboxFileHandle, VIR_EVENT_HANDLE_READABLE, vboxReadCallback, NULL, NULL);
7397 if (data->fdWatch >= 0) {
7398 /* Once a callback is registered with virtualbox, use a list
7399 * to store the callbacks registered with libvirt so that
7400 * later you can iterate over them
7403 ret = virDomainEventStateRegister(conn, data->domainEvents,
7404 callback, opaque, freecb);
7405 VIR_DEBUG("virObjectEventStateRegister (ret = %d) (conn: %p, "
7406 "callback: %p, opaque: %p, "
7407 "freecb: %p)", ret, conn, callback,
7412 vboxDriverUnlock(data);
7417 if (data->vboxObj && data->vboxCallback) {
7418 data->vboxObj->vtbl->UnregisterCallback(data->vboxObj, data->vboxCallback);
7425 vboxConnectDomainEventDeregister(virConnectPtr conn,
7426 virConnectDomainEventCallback callback)
7428 VBOX_OBJECT_CHECK(conn, int, -1);
7431 /* Locking has to be there as callbacks are not
7432 * really fully thread safe
7434 vboxDriverLock(data);
7436 cnt = virDomainEventStateDeregister(conn, data->domainEvents,
7439 if (data->vboxCallback && cnt == 0) {
7440 data->vboxObj->vtbl->UnregisterCallback(data->vboxObj, data->vboxCallback);
7441 VBOX_RELEASE(data->vboxCallback);
7443 /* Remove the Event file handle on which we are listening as well */
7444 virEventRemoveHandle(data->fdWatch);
7448 vboxDriverUnlock(data);
7456 static int vboxConnectDomainEventRegisterAny(virConnectPtr conn,
7459 virConnectDomainEventGenericCallback callback,
7461 virFreeCallback freecb)
7463 VBOX_OBJECT_CHECK(conn, int, -1);
7467 /* Locking has to be there as callbacks are not
7468 * really fully thread safe
7470 vboxDriverLock(data);
7472 if (data->vboxCallback == NULL) {
7473 data->vboxCallback = vboxAllocCallbackObj();
7474 if (data->vboxCallback != NULL) {
7475 rc = data->vboxObj->vtbl->RegisterCallback(data->vboxObj, data->vboxCallback);
7476 if (NS_SUCCEEDED(rc)) {
7484 /* Get the vbox file handle and add a event handle to it
7485 * so that the events can be passed down to the user
7488 if (data->fdWatch < 0) {
7489 PRInt32 vboxFileHandle;
7490 vboxFileHandle = data->vboxQueue->vtbl->GetEventQueueSelectFD(data->vboxQueue);
7492 data->fdWatch = virEventAddHandle(vboxFileHandle, VIR_EVENT_HANDLE_READABLE, vboxReadCallback, NULL, NULL);
7495 if (data->fdWatch >= 0) {
7496 /* Once a callback is registered with virtualbox, use a list
7497 * to store the callbacks registered with libvirt so that
7498 * later you can iterate over them
7501 if (virDomainEventStateRegisterID(conn, data->domainEvents,
7503 callback, opaque, freecb, &ret) < 0)
7505 VIR_DEBUG("virDomainEventStateRegisterID (ret = %d) (conn: %p, "
7506 "callback: %p, opaque: %p, "
7507 "freecb: %p)", ret, conn, callback,
7512 vboxDriverUnlock(data);
7517 if (data->vboxObj && data->vboxCallback) {
7518 data->vboxObj->vtbl->UnregisterCallback(data->vboxObj, data->vboxCallback);
7525 vboxConnectDomainEventDeregisterAny(virConnectPtr conn,
7528 VBOX_OBJECT_CHECK(conn, int, -1);
7531 /* Locking has to be there as callbacks are not
7532 * really fully thread safe
7534 vboxDriverLock(data);
7536 cnt = virObjectEventStateDeregisterID(conn, data->domainEvents,
7539 if (data->vboxCallback && cnt == 0) {
7540 data->vboxObj->vtbl->UnregisterCallback(data->vboxObj, data->vboxCallback);
7541 VBOX_RELEASE(data->vboxCallback);
7543 /* Remove the Event file handle on which we are listening as well */
7544 virEventRemoveHandle(data->fdWatch);
7548 vboxDriverUnlock(data);
7556 #endif /* !(VBOX_API_VERSION == 2002000 || VBOX_API_VERSION >= 4000000) */
7559 * The Network Functions here on
7561 static virDrvOpenStatus vboxNetworkOpen(virConnectPtr conn,
7562 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
7565 vboxGlobalData *data = conn->privateData;
7567 virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
7569 if (STRNEQ(conn->driver->name, "VBOX"))
7572 if ((data->pFuncs == NULL) ||
7573 (data->vboxObj == NULL) ||
7574 (data->vboxSession == NULL))
7577 VIR_DEBUG("network initialized");
7578 /* conn->networkPrivateData = some network specific data */
7579 return VIR_DRV_OPEN_SUCCESS;
7582 return VIR_DRV_OPEN_DECLINED;
7585 static int vboxNetworkClose(virConnectPtr conn)
7587 VIR_DEBUG("network uninitialized");
7588 conn->networkPrivateData = NULL;
7592 static int vboxConnectNumOfNetworks(virConnectPtr conn)
7594 VBOX_OBJECT_HOST_CHECK(conn, int, 0);
7595 vboxArray networkInterfaces = VBOX_ARRAY_INITIALIZER;
7598 vboxArrayGet(&networkInterfaces, host, host->vtbl->GetNetworkInterfaces);
7600 for (i = 0; i < networkInterfaces.count; i++) {
7601 IHostNetworkInterface *networkInterface = networkInterfaces.items[i];
7603 if (networkInterface) {
7604 PRUint32 interfaceType = 0;
7606 networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType);
7607 if (interfaceType == HostNetworkInterfaceType_HostOnly) {
7608 PRUint32 status = HostNetworkInterfaceStatus_Unknown;
7610 networkInterface->vtbl->GetStatus(networkInterface, &status);
7612 if (status == HostNetworkInterfaceStatus_Up)
7618 vboxArrayRelease(&networkInterfaces);
7622 VIR_DEBUG("numActive: %d", ret);
7626 static int vboxConnectListNetworks(virConnectPtr conn, char **const names, int nnames) {
7627 VBOX_OBJECT_HOST_CHECK(conn, int, 0);
7628 vboxArray networkInterfaces = VBOX_ARRAY_INITIALIZER;
7631 vboxArrayGet(&networkInterfaces, host, host->vtbl->GetNetworkInterfaces);
7633 for (i = 0; (ret < nnames) && (i < networkInterfaces.count); i++) {
7634 IHostNetworkInterface *networkInterface = networkInterfaces.items[i];
7636 if (networkInterface) {
7637 PRUint32 interfaceType = 0;
7639 networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType);
7641 if (interfaceType == HostNetworkInterfaceType_HostOnly) {
7642 PRUint32 status = HostNetworkInterfaceStatus_Unknown;
7644 networkInterface->vtbl->GetStatus(networkInterface, &status);
7646 if (status == HostNetworkInterfaceStatus_Up) {
7647 char *nameUtf8 = NULL;
7648 PRUnichar *nameUtf16 = NULL;
7650 networkInterface->vtbl->GetName(networkInterface, &nameUtf16);
7651 VBOX_UTF16_TO_UTF8(nameUtf16, &nameUtf8);
7653 VIR_DEBUG("nnames[%d]: %s", ret, nameUtf8);
7654 if (VIR_STRDUP(names[ret], nameUtf8) >= 0)
7657 VBOX_UTF8_FREE(nameUtf8);
7658 VBOX_UTF16_FREE(nameUtf16);
7664 vboxArrayRelease(&networkInterfaces);
7671 static int vboxConnectNumOfDefinedNetworks(virConnectPtr conn)
7673 VBOX_OBJECT_HOST_CHECK(conn, int, 0);
7674 vboxArray networkInterfaces = VBOX_ARRAY_INITIALIZER;
7677 vboxArrayGet(&networkInterfaces, host, host->vtbl->GetNetworkInterfaces);
7679 for (i = 0; i < networkInterfaces.count; i++) {
7680 IHostNetworkInterface *networkInterface = networkInterfaces.items[i];
7682 if (networkInterface) {
7683 PRUint32 interfaceType = 0;
7685 networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType);
7686 if (interfaceType == HostNetworkInterfaceType_HostOnly) {
7687 PRUint32 status = HostNetworkInterfaceStatus_Unknown;
7689 networkInterface->vtbl->GetStatus(networkInterface, &status);
7691 if (status == HostNetworkInterfaceStatus_Down)
7697 vboxArrayRelease(&networkInterfaces);
7701 VIR_DEBUG("numActive: %d", ret);
7705 static int vboxConnectListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
7706 VBOX_OBJECT_HOST_CHECK(conn, int, 0);
7707 vboxArray networkInterfaces = VBOX_ARRAY_INITIALIZER;
7710 vboxArrayGet(&networkInterfaces, host, host->vtbl->GetNetworkInterfaces);
7712 for (i = 0; (ret < nnames) && (i < networkInterfaces.count); i++) {
7713 IHostNetworkInterface *networkInterface = networkInterfaces.items[i];
7715 if (networkInterface) {
7716 PRUint32 interfaceType = 0;
7718 networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType);
7720 if (interfaceType == HostNetworkInterfaceType_HostOnly) {
7721 PRUint32 status = HostNetworkInterfaceStatus_Unknown;
7723 networkInterface->vtbl->GetStatus(networkInterface, &status);
7725 if (status == HostNetworkInterfaceStatus_Down) {
7726 char *nameUtf8 = NULL;
7727 PRUnichar *nameUtf16 = NULL;
7729 networkInterface->vtbl->GetName(networkInterface, &nameUtf16);
7730 VBOX_UTF16_TO_UTF8(nameUtf16, &nameUtf8);
7732 VIR_DEBUG("nnames[%d]: %s", ret, nameUtf8);
7733 if (VIR_STRDUP(names[ret], nameUtf8) >= 0)
7736 VBOX_UTF8_FREE(nameUtf8);
7737 VBOX_UTF16_FREE(nameUtf16);
7743 vboxArrayRelease(&networkInterfaces);
7750 static virNetworkPtr
7751 vboxNetworkLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
7753 VBOX_OBJECT_HOST_CHECK(conn, virNetworkPtr, NULL);
7754 vboxIID iid = VBOX_IID_INITIALIZER;
7756 vboxIIDFromUUID(&iid, uuid);
7758 /* TODO: "internal" networks are just strings and
7759 * thus can't do much with them
7761 IHostNetworkInterface *networkInterface = NULL;
7763 host->vtbl->FindHostNetworkInterfaceById(host, iid.value, &networkInterface);
7764 if (networkInterface) {
7765 PRUint32 interfaceType = 0;
7767 networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType);
7769 if (interfaceType == HostNetworkInterfaceType_HostOnly) {
7770 char *nameUtf8 = NULL;
7771 PRUnichar *nameUtf16 = NULL;
7773 networkInterface->vtbl->GetName(networkInterface, &nameUtf16);
7774 VBOX_UTF16_TO_UTF8(nameUtf16, &nameUtf8);
7776 ret = virGetNetwork(conn, nameUtf8, uuid);
7778 VIR_DEBUG("Network Name: %s", nameUtf8);
7779 DEBUGIID("Network UUID", iid.value);
7781 VBOX_UTF8_FREE(nameUtf8);
7782 VBOX_UTF16_FREE(nameUtf16);
7785 VBOX_RELEASE(networkInterface);
7790 vboxIIDUnalloc(&iid);
7794 static virNetworkPtr
7795 vboxNetworkLookupByName(virConnectPtr conn, const char *name)
7797 VBOX_OBJECT_HOST_CHECK(conn, virNetworkPtr, NULL);
7798 PRUnichar *nameUtf16 = NULL;
7799 IHostNetworkInterface *networkInterface = NULL;
7801 VBOX_UTF8_TO_UTF16(name, &nameUtf16);
7803 host->vtbl->FindHostNetworkInterfaceByName(host, nameUtf16, &networkInterface);
7805 if (networkInterface) {
7806 PRUint32 interfaceType = 0;
7808 networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType);
7810 if (interfaceType == HostNetworkInterfaceType_HostOnly) {
7811 unsigned char uuid[VIR_UUID_BUFLEN];
7812 vboxIID iid = VBOX_IID_INITIALIZER;
7814 networkInterface->vtbl->GetId(networkInterface, &iid.value);
7815 vboxIIDToUUID(&iid, uuid);
7816 ret = virGetNetwork(conn, name, uuid);
7817 VIR_DEBUG("Network Name: %s", name);
7819 DEBUGIID("Network UUID", iid.value);
7820 vboxIIDUnalloc(&iid);
7823 VBOX_RELEASE(networkInterface);
7826 VBOX_UTF16_FREE(nameUtf16);
7832 static virNetworkPtr
7833 vboxNetworkDefineCreateXML(virConnectPtr conn, const char *xml, bool start)
7835 VBOX_OBJECT_HOST_CHECK(conn, virNetworkPtr, NULL);
7836 PRUnichar *networkInterfaceNameUtf16 = NULL;
7837 char *networkInterfaceNameUtf8 = NULL;
7838 IHostNetworkInterface *networkInterface = NULL;
7841 virNetworkDefPtr def = virNetworkDefParseString(xml);
7842 virNetworkIpDefPtr ipdef;
7843 virSocketAddr netmask;
7846 (def->forward.type != VIR_NETWORK_FORWARD_NONE) ||
7847 (def->nips == 0 || !def->ips))
7850 /* Look for the first IPv4 IP address definition and use that.
7851 * If there weren't any IPv4 addresses, ignore the network (since it's
7852 * required below to have an IPv4 address)
7854 ipdef = virNetworkDefGetIpByIndex(def, AF_INET, 0);
7858 if (virNetworkIpDefNetmask(ipdef, &netmask) < 0)
7861 /* the current limitation of hostonly network is that you can't
7862 * assign a name to it and it defaults to vboxnet*, for e.g:
7863 * vboxnet0, vboxnet1, etc. Also the UUID is assigned to it
7864 * automatically depending on the mac address and thus both
7865 * these paramters are ignored here for now.
7868 #if VBOX_API_VERSION == 2002000
7869 if (STREQ(def->name, "vboxnet0")) {
7870 PRUint32 interfaceType = 0;
7872 VBOX_UTF8_TO_UTF16(def->name, &networkInterfaceNameUtf16);
7873 host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface);
7875 networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType);
7876 if (interfaceType != HostNetworkInterfaceType_HostOnly) {
7877 VBOX_RELEASE(networkInterface);
7878 networkInterface = NULL;
7881 #else /* VBOX_API_VERSION != 2002000 */
7883 IProgress *progress = NULL;
7884 host->vtbl->CreateHostOnlyNetworkInterface(host, &networkInterface,
7888 progress->vtbl->WaitForCompletion(progress, -1);
7889 VBOX_RELEASE(progress);
7892 #endif /* VBOX_API_VERSION != 2002000 */
7894 if (networkInterface) {
7895 unsigned char uuid[VIR_UUID_BUFLEN];
7896 char *networkNameUtf8 = NULL;
7897 PRUnichar *networkNameUtf16 = NULL;
7898 vboxIID vboxnetiid = VBOX_IID_INITIALIZER;
7900 networkInterface->vtbl->GetName(networkInterface, &networkInterfaceNameUtf16);
7901 if (networkInterfaceNameUtf16) {
7902 VBOX_UTF16_TO_UTF8(networkInterfaceNameUtf16, &networkInterfaceNameUtf8);
7904 if (virAsprintf(&networkNameUtf8, "HostInterfaceNetworking-%s", networkInterfaceNameUtf8) < 0) {
7906 VBOX_RELEASE(networkInterface);
7911 VBOX_UTF8_TO_UTF16(networkNameUtf8, &networkNameUtf16);
7913 /* Currently support only one dhcp server per network
7914 * with contigious address space from start to end
7916 if ((ipdef->nranges >= 1) &&
7917 VIR_SOCKET_ADDR_VALID(&ipdef->ranges[0].start) &&
7918 VIR_SOCKET_ADDR_VALID(&ipdef->ranges[0].end)) {
7919 IDHCPServer *dhcpServer = NULL;
7921 data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj,
7925 /* create a dhcp server */
7926 data->vboxObj->vtbl->CreateDHCPServer(data->vboxObj,
7929 VIR_DEBUG("couldn't find dhcp server so creating one");
7932 PRUnichar *ipAddressUtf16 = NULL;
7933 PRUnichar *networkMaskUtf16 = NULL;
7934 PRUnichar *fromIPAddressUtf16 = NULL;
7935 PRUnichar *toIPAddressUtf16 = NULL;
7936 PRUnichar *trunkTypeUtf16 = NULL;
7938 ipAddressUtf16 = vboxSocketFormatAddrUtf16(data, &ipdef->address);
7939 networkMaskUtf16 = vboxSocketFormatAddrUtf16(data, &netmask);
7940 fromIPAddressUtf16 = vboxSocketFormatAddrUtf16(data, &ipdef->ranges[0].start);
7941 toIPAddressUtf16 = vboxSocketFormatAddrUtf16(data, &ipdef->ranges[0].end);
7943 if (ipAddressUtf16 == NULL || networkMaskUtf16 == NULL ||
7944 fromIPAddressUtf16 == NULL || toIPAddressUtf16 == NULL) {
7945 VBOX_UTF16_FREE(ipAddressUtf16);
7946 VBOX_UTF16_FREE(networkMaskUtf16);
7947 VBOX_UTF16_FREE(fromIPAddressUtf16);
7948 VBOX_UTF16_FREE(toIPAddressUtf16);
7949 VBOX_RELEASE(dhcpServer);
7953 VBOX_UTF8_TO_UTF16("netflt", &trunkTypeUtf16);
7955 dhcpServer->vtbl->SetEnabled(dhcpServer, PR_TRUE);
7957 dhcpServer->vtbl->SetConfiguration(dhcpServer,
7964 dhcpServer->vtbl->Start(dhcpServer,
7966 networkInterfaceNameUtf16,
7969 VBOX_UTF16_FREE(ipAddressUtf16);
7970 VBOX_UTF16_FREE(networkMaskUtf16);
7971 VBOX_UTF16_FREE(fromIPAddressUtf16);
7972 VBOX_UTF16_FREE(toIPAddressUtf16);
7973 VBOX_UTF16_FREE(trunkTypeUtf16);
7974 VBOX_RELEASE(dhcpServer);
7978 if ((ipdef->nhosts >= 1) &&
7979 VIR_SOCKET_ADDR_VALID(&ipdef->hosts[0].ip)) {
7980 PRUnichar *ipAddressUtf16 = NULL;
7981 PRUnichar *networkMaskUtf16 = NULL;
7983 ipAddressUtf16 = vboxSocketFormatAddrUtf16(data, &ipdef->hosts[0].ip);
7984 networkMaskUtf16 = vboxSocketFormatAddrUtf16(data, &netmask);
7986 if (ipAddressUtf16 == NULL || networkMaskUtf16 == NULL) {
7987 VBOX_UTF16_FREE(ipAddressUtf16);
7988 VBOX_UTF16_FREE(networkMaskUtf16);
7992 /* Current drawback is that since EnableStaticIpConfig() sets
7993 * IP and enables the interface so even if the dhcpserver is not
7994 * started the interface is still up and running
7996 #if VBOX_API_VERSION < 4002000
7997 networkInterface->vtbl->EnableStaticIpConfig(networkInterface,
8001 networkInterface->vtbl->EnableStaticIPConfig(networkInterface,
8006 VBOX_UTF16_FREE(ipAddressUtf16);
8007 VBOX_UTF16_FREE(networkMaskUtf16);
8009 #if VBOX_API_VERSION < 4002000
8010 networkInterface->vtbl->EnableDynamicIpConfig(networkInterface);
8011 networkInterface->vtbl->DhcpRediscover(networkInterface);
8013 networkInterface->vtbl->EnableDynamicIPConfig(networkInterface);
8014 networkInterface->vtbl->DHCPRediscover(networkInterface);
8018 rc = networkInterface->vtbl->GetId(networkInterface, &vboxnetiid.value);
8019 if (NS_SUCCEEDED(rc)) {
8020 vboxIIDToUUID(&vboxnetiid, uuid);
8021 DEBUGIID("Real Network UUID", vboxnetiid.value);
8022 vboxIIDUnalloc(&vboxnetiid);
8023 ret = virGetNetwork(conn, networkInterfaceNameUtf8, uuid);
8026 VIR_FREE(networkNameUtf8);
8027 VBOX_UTF16_FREE(networkNameUtf16);
8028 VBOX_RELEASE(networkInterface);
8031 VBOX_UTF8_FREE(networkInterfaceNameUtf8);
8032 VBOX_UTF16_FREE(networkInterfaceNameUtf16);
8036 virNetworkDefFree(def);
8040 static virNetworkPtr vboxNetworkCreateXML(virConnectPtr conn, const char *xml)
8042 return vboxNetworkDefineCreateXML(conn, xml, true);
8045 static virNetworkPtr vboxNetworkDefineXML(virConnectPtr conn, const char *xml)
8047 return vboxNetworkDefineCreateXML(conn, xml, false);
8051 vboxNetworkUndefineDestroy(virNetworkPtr network, bool removeinterface)
8053 VBOX_OBJECT_HOST_CHECK(network->conn, int, -1);
8054 char *networkNameUtf8 = NULL;
8055 PRUnichar *networkInterfaceNameUtf16 = NULL;
8056 IHostNetworkInterface *networkInterface = NULL;
8058 /* Current limitation of the function for VirtualBox 2.2.* is
8059 * that you can't delete the default hostonly adaptor namely:
8060 * vboxnet0 and thus all this functions does is remove the
8061 * dhcp server configuration, but the network can still be used
8062 * by giving the machine static IP and also it will still
8063 * show up in the net-list in virsh
8066 if (virAsprintf(&networkNameUtf8, "HostInterfaceNetworking-%s", network->name) < 0)
8069 VBOX_UTF8_TO_UTF16(network->name, &networkInterfaceNameUtf16);
8071 host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface);
8073 if (networkInterface) {
8074 PRUint32 interfaceType = 0;
8076 networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType);
8078 if (interfaceType == HostNetworkInterfaceType_HostOnly) {
8079 PRUnichar *networkNameUtf16 = NULL;
8080 IDHCPServer *dhcpServer = NULL;
8082 #if VBOX_API_VERSION != 2002000
8083 if (removeinterface) {
8084 PRUnichar *iidUtf16 = NULL;
8085 IProgress *progress = NULL;
8087 networkInterface->vtbl->GetId(networkInterface, &iidUtf16);
8090 # if VBOX_API_VERSION == 3000000
8091 IHostNetworkInterface *netInt = NULL;
8092 host->vtbl->RemoveHostOnlyNetworkInterface(host, iidUtf16, &netInt, &progress);
8093 VBOX_RELEASE(netInt);
8094 # else /* VBOX_API_VERSION > 3000000 */
8095 host->vtbl->RemoveHostOnlyNetworkInterface(host, iidUtf16, &progress);
8096 # endif /* VBOX_API_VERSION > 3000000 */
8097 VBOX_UTF16_FREE(iidUtf16);
8101 progress->vtbl->WaitForCompletion(progress, -1);
8102 VBOX_RELEASE(progress);
8105 #endif /* VBOX_API_VERSION != 2002000 */
8107 VBOX_UTF8_TO_UTF16(networkNameUtf8, &networkNameUtf16);
8109 data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj,
8113 dhcpServer->vtbl->SetEnabled(dhcpServer, PR_FALSE);
8114 dhcpServer->vtbl->Stop(dhcpServer);
8115 if (removeinterface)
8116 data->vboxObj->vtbl->RemoveDHCPServer(data->vboxObj, dhcpServer);
8117 VBOX_RELEASE(dhcpServer);
8120 VBOX_UTF16_FREE(networkNameUtf16);
8123 VBOX_RELEASE(networkInterface);
8126 VBOX_UTF16_FREE(networkInterfaceNameUtf16);
8132 VIR_FREE(networkNameUtf8);
8136 static int vboxNetworkUndefine(virNetworkPtr network)
8138 return vboxNetworkUndefineDestroy(network, true);
8141 static int vboxNetworkCreate(virNetworkPtr network)
8143 VBOX_OBJECT_HOST_CHECK(network->conn, int, -1);
8144 char *networkNameUtf8 = NULL;
8145 PRUnichar *networkInterfaceNameUtf16 = NULL;
8146 IHostNetworkInterface *networkInterface = NULL;
8148 /* Current limitation of the function for VirtualBox 2.2.* is
8149 * that the default hostonly network "vboxnet0" is always active
8150 * and thus all this functions does is start the dhcp server,
8151 * but the network can still be used without starting the dhcp
8152 * server by giving the machine static IP
8155 if (virAsprintf(&networkNameUtf8, "HostInterfaceNetworking-%s", network->name) < 0)
8158 VBOX_UTF8_TO_UTF16(network->name, &networkInterfaceNameUtf16);
8160 host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface);
8162 if (networkInterface) {
8163 PRUint32 interfaceType = 0;
8165 networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType);
8167 if (interfaceType == HostNetworkInterfaceType_HostOnly) {
8168 PRUnichar *networkNameUtf16 = NULL;
8169 IDHCPServer *dhcpServer = NULL;
8172 VBOX_UTF8_TO_UTF16(networkNameUtf8, &networkNameUtf16);
8174 data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj,
8178 PRUnichar *trunkTypeUtf16 = NULL;
8180 dhcpServer->vtbl->SetEnabled(dhcpServer, PR_TRUE);
8182 VBOX_UTF8_TO_UTF16("netflt", &trunkTypeUtf16);
8184 dhcpServer->vtbl->Start(dhcpServer,
8186 networkInterfaceNameUtf16,
8189 VBOX_UTF16_FREE(trunkTypeUtf16);
8190 VBOX_RELEASE(dhcpServer);
8193 VBOX_UTF16_FREE(networkNameUtf16);
8196 VBOX_RELEASE(networkInterface);
8199 VBOX_UTF16_FREE(networkInterfaceNameUtf16);
8205 VIR_FREE(networkNameUtf8);
8209 static int vboxNetworkDestroy(virNetworkPtr network)
8211 return vboxNetworkUndefineDestroy(network, false);
8214 static char *vboxNetworkGetXMLDesc(virNetworkPtr network,
8217 VBOX_OBJECT_HOST_CHECK(network->conn, char *, NULL);
8218 virNetworkDefPtr def = NULL;
8219 virNetworkIpDefPtr ipdef = NULL;
8220 char *networkNameUtf8 = NULL;
8221 PRUnichar *networkInterfaceNameUtf16 = NULL;
8222 IHostNetworkInterface *networkInterface = NULL;
8224 virCheckFlags(0, NULL);
8226 if (VIR_ALLOC(def) < 0)
8228 if (VIR_ALLOC(ipdef) < 0)
8233 if (virAsprintf(&networkNameUtf8, "HostInterfaceNetworking-%s", network->name) < 0)
8236 VBOX_UTF8_TO_UTF16(network->name, &networkInterfaceNameUtf16);
8238 host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface);
8240 if (networkInterface) {
8241 PRUint32 interfaceType = 0;
8243 networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType);
8245 if (interfaceType == HostNetworkInterfaceType_HostOnly) {
8246 if (VIR_STRDUP(def->name, network->name) >= 0) {
8247 PRUnichar *networkNameUtf16 = NULL;
8248 IDHCPServer *dhcpServer = NULL;
8249 vboxIID vboxnet0IID = VBOX_IID_INITIALIZER;
8251 networkInterface->vtbl->GetId(networkInterface, &vboxnet0IID.value);
8252 vboxIIDToUUID(&vboxnet0IID, def->uuid);
8254 VBOX_UTF8_TO_UTF16(networkNameUtf8, &networkNameUtf16);
8256 def->forward.type = VIR_NETWORK_FORWARD_NONE;
8258 data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj,
8263 if (VIR_ALLOC_N(ipdef->ranges, ipdef->nranges) >=0) {
8264 PRUnichar *ipAddressUtf16 = NULL;
8265 PRUnichar *networkMaskUtf16 = NULL;
8266 PRUnichar *fromIPAddressUtf16 = NULL;
8267 PRUnichar *toIPAddressUtf16 = NULL;
8268 bool errorOccurred = false;
8270 dhcpServer->vtbl->GetIPAddress(dhcpServer, &ipAddressUtf16);
8271 dhcpServer->vtbl->GetNetworkMask(dhcpServer, &networkMaskUtf16);
8272 dhcpServer->vtbl->GetLowerIP(dhcpServer, &fromIPAddressUtf16);
8273 dhcpServer->vtbl->GetUpperIP(dhcpServer, &toIPAddressUtf16);
8274 /* Currently virtualbox supports only one dhcp server per network
8275 * with contigious address space from start to end
8277 if (vboxSocketParseAddrUtf16(data, ipAddressUtf16,
8278 &ipdef->address) < 0 ||
8279 vboxSocketParseAddrUtf16(data, networkMaskUtf16,
8280 &ipdef->netmask) < 0 ||
8281 vboxSocketParseAddrUtf16(data, fromIPAddressUtf16,
8282 &ipdef->ranges[0].start) < 0 ||
8283 vboxSocketParseAddrUtf16(data, toIPAddressUtf16,
8284 &ipdef->ranges[0].end) < 0) {
8285 errorOccurred = true;
8288 VBOX_UTF16_FREE(ipAddressUtf16);
8289 VBOX_UTF16_FREE(networkMaskUtf16);
8290 VBOX_UTF16_FREE(fromIPAddressUtf16);
8291 VBOX_UTF16_FREE(toIPAddressUtf16);
8293 if (errorOccurred) {
8301 if (VIR_ALLOC_N(ipdef->hosts, ipdef->nhosts) >=0) {
8302 if (VIR_STRDUP(ipdef->hosts[0].name, network->name) < 0) {
8303 VIR_FREE(ipdef->hosts);
8306 PRUnichar *macAddressUtf16 = NULL;
8307 PRUnichar *ipAddressUtf16 = NULL;
8308 bool errorOccurred = false;
8310 networkInterface->vtbl->GetHardwareAddress(networkInterface, &macAddressUtf16);
8311 networkInterface->vtbl->GetIPAddress(networkInterface, &ipAddressUtf16);
8313 VBOX_UTF16_TO_UTF8(macAddressUtf16, &ipdef->hosts[0].mac);
8315 if (vboxSocketParseAddrUtf16(data, ipAddressUtf16,
8316 &ipdef->hosts[0].ip) < 0) {
8317 errorOccurred = true;
8320 VBOX_UTF16_FREE(macAddressUtf16);
8321 VBOX_UTF16_FREE(ipAddressUtf16);
8323 if (errorOccurred) {
8331 VBOX_RELEASE(dhcpServer);
8333 PRUnichar *networkMaskUtf16 = NULL;
8334 PRUnichar *ipAddressUtf16 = NULL;
8335 bool errorOccurred = false;
8337 networkInterface->vtbl->GetNetworkMask(networkInterface, &networkMaskUtf16);
8338 networkInterface->vtbl->GetIPAddress(networkInterface, &ipAddressUtf16);
8340 if (vboxSocketParseAddrUtf16(data, networkMaskUtf16,
8341 &ipdef->netmask) < 0 ||
8342 vboxSocketParseAddrUtf16(data, ipAddressUtf16,
8343 &ipdef->address) < 0) {
8344 errorOccurred = true;
8347 VBOX_UTF16_FREE(networkMaskUtf16);
8348 VBOX_UTF16_FREE(ipAddressUtf16);
8350 if (errorOccurred) {
8355 DEBUGIID("Network UUID", vboxnet0IID.value);
8356 vboxIIDUnalloc(&vboxnet0IID);
8357 VBOX_UTF16_FREE(networkNameUtf16);
8361 VBOX_RELEASE(networkInterface);
8364 VBOX_UTF16_FREE(networkInterfaceNameUtf16);
8367 ret = virNetworkDefFormat(def, 0);
8370 virNetworkDefFree(def);
8371 VIR_FREE(networkNameUtf8);
8376 * The Storage Functions here on
8379 static virDrvOpenStatus vboxStorageOpen(virConnectPtr conn,
8380 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
8383 vboxGlobalData *data = conn->privateData;
8385 virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
8387 if (STRNEQ(conn->driver->name, "VBOX"))
8388 return VIR_DRV_OPEN_DECLINED;
8390 if ((data->pFuncs == NULL) ||
8391 (data->vboxObj == NULL) ||
8392 (data->vboxSession == NULL))
8393 return VIR_DRV_OPEN_ERROR;
8395 VIR_DEBUG("vbox storage initialized");
8396 /* conn->storagePrivateData = some storage specific data */
8397 return VIR_DRV_OPEN_SUCCESS;
8400 static int vboxStorageClose(virConnectPtr conn)
8402 VIR_DEBUG("vbox storage uninitialized");
8403 conn->storagePrivateData = NULL;
8407 static int vboxConnectNumOfStoragePools(virConnectPtr conn ATTRIBUTE_UNUSED)
8410 /** Currently only one pool supported, the default one
8411 * given by ISystemProperties::defaultHardDiskFolder()
8417 static int vboxConnectListStoragePools(virConnectPtr conn ATTRIBUTE_UNUSED,
8418 char **const names, int nnames) {
8422 VIR_STRDUP(names[numActive], "default-pool") > 0)
8427 static virStoragePoolPtr
8428 vboxStoragePoolLookupByName(virConnectPtr conn, const char *name)
8430 virStoragePoolPtr ret = NULL;
8432 /** Current limitation of the function: since
8433 * the default pool doesn't have UUID just assign
8434 * one till vbox can handle pools
8436 if (STREQ("default-pool", name)) {
8437 unsigned char uuid[VIR_UUID_BUFLEN];
8438 const char *uuidstr = "1deff1ff-1481-464f-967f-a50fe8936cc4";
8440 ignore_value(virUUIDParse(uuidstr, uuid));
8442 ret = virGetStoragePool(conn, name, uuid, NULL, NULL);
8448 static int vboxStoragePoolNumOfVolumes(virStoragePoolPtr pool)
8450 VBOX_OBJECT_CHECK(pool->conn, int, -1);
8451 vboxArray hardDisks = VBOX_ARRAY_INITIALIZER;
8452 PRUint32 hardDiskAccessible = 0;
8456 rc = vboxArrayGet(&hardDisks, data->vboxObj, data->vboxObj->vtbl->GetHardDisks);
8457 if (NS_SUCCEEDED(rc)) {
8458 for (i = 0; i < hardDisks.count; ++i) {
8459 IHardDisk *hardDisk = hardDisks.items[i];
8463 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
8464 if (hddstate != MediaState_Inaccessible)
8465 hardDiskAccessible++;
8469 vboxArrayRelease(&hardDisks);
8471 ret = hardDiskAccessible;
8474 virReportError(VIR_ERR_INTERNAL_ERROR,
8475 _("could not get number of volumes in the pool: %s, rc=%08x"),
8476 pool->name, (unsigned)rc);
8482 static int vboxStoragePoolListVolumes(virStoragePoolPtr pool, char **const names, int nnames) {
8483 VBOX_OBJECT_CHECK(pool->conn, int, -1);
8484 vboxArray hardDisks = VBOX_ARRAY_INITIALIZER;
8485 PRUint32 numActive = 0;
8489 rc = vboxArrayGet(&hardDisks, data->vboxObj, data->vboxObj->vtbl->GetHardDisks);
8490 if (NS_SUCCEEDED(rc)) {
8491 for (i = 0; i < hardDisks.count && numActive < nnames; ++i) {
8492 IHardDisk *hardDisk = hardDisks.items[i];
8496 char *nameUtf8 = NULL;
8497 PRUnichar *nameUtf16 = NULL;
8499 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
8500 if (hddstate != MediaState_Inaccessible) {
8501 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &nameUtf16);
8503 VBOX_UTF16_TO_UTF8(nameUtf16, &nameUtf8);
8504 VBOX_UTF16_FREE(nameUtf16);
8507 VIR_DEBUG("nnames[%d]: %s", numActive, nameUtf8);
8508 if (VIR_STRDUP(names[numActive], nameUtf8) > 0)
8511 VBOX_UTF8_FREE(nameUtf8);
8517 vboxArrayRelease(&hardDisks);
8522 virReportError(VIR_ERR_INTERNAL_ERROR,
8523 _("could not get the volume list in the pool: %s, rc=%08x"),
8524 pool->name, (unsigned)rc);
8530 static virStorageVolPtr
8531 vboxStorageVolLookupByName(virStoragePoolPtr pool, const char *name)
8533 VBOX_OBJECT_CHECK(pool->conn, virStorageVolPtr, NULL);
8534 vboxArray hardDisks = VBOX_ARRAY_INITIALIZER;
8541 rc = vboxArrayGet(&hardDisks, data->vboxObj, data->vboxObj->vtbl->GetHardDisks);
8542 if (NS_SUCCEEDED(rc)) {
8543 for (i = 0; i < hardDisks.count; ++i) {
8544 IHardDisk *hardDisk = hardDisks.items[i];
8548 char *nameUtf8 = NULL;
8549 PRUnichar *nameUtf16 = NULL;
8551 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
8552 if (hddstate != MediaState_Inaccessible) {
8553 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &nameUtf16);
8556 VBOX_UTF16_TO_UTF8(nameUtf16, &nameUtf8);
8557 VBOX_UTF16_FREE(nameUtf16);
8560 if (nameUtf8 && STREQ(nameUtf8, name)) {
8561 vboxIID hddIID = VBOX_IID_INITIALIZER;
8562 unsigned char uuid[VIR_UUID_BUFLEN];
8563 char key[VIR_UUID_STRING_BUFLEN] = "";
8565 rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value);
8566 if (NS_SUCCEEDED(rc)) {
8567 vboxIIDToUUID(&hddIID, uuid);
8568 virUUIDFormat(uuid, key);
8570 ret = virGetStorageVol(pool->conn, pool->name, name, key,
8573 VIR_DEBUG("virStorageVolPtr: %p", ret);
8574 VIR_DEBUG("Storage Volume Name: %s", name);
8575 VIR_DEBUG("Storage Volume key : %s", key);
8576 VIR_DEBUG("Storage Volume Pool: %s", pool->name);
8579 vboxIIDUnalloc(&hddIID);
8580 VBOX_UTF8_FREE(nameUtf8);
8584 VBOX_UTF8_FREE(nameUtf8);
8589 vboxArrayRelease(&hardDisks);
8595 static virStorageVolPtr
8596 vboxStorageVolLookupByKey(virConnectPtr conn, const char *key)
8598 VBOX_OBJECT_CHECK(conn, virStorageVolPtr, NULL);
8599 vboxIID hddIID = VBOX_IID_INITIALIZER;
8600 unsigned char uuid[VIR_UUID_BUFLEN];
8601 IHardDisk *hardDisk = NULL;
8607 if (virUUIDParse(key, uuid) < 0) {
8608 virReportError(VIR_ERR_INVALID_ARG,
8609 _("Could not parse UUID from '%s'"), key);
8613 vboxIIDFromUUID(&hddIID, uuid);
8614 #if VBOX_API_VERSION < 4000000
8615 rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk);
8616 #elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
8617 rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value,
8618 DeviceType_HardDisk, &hardDisk);
8620 rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value,
8621 DeviceType_HardDisk, AccessMode_ReadWrite,
8622 PR_FALSE, &hardDisk);
8623 #endif /* VBOX_API_VERSION >= 4000000 */
8624 if (NS_SUCCEEDED(rc)) {
8627 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
8628 if (hddstate != MediaState_Inaccessible) {
8629 PRUnichar *hddNameUtf16 = NULL;
8630 char *hddNameUtf8 = NULL;
8632 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &hddNameUtf16);
8633 VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8);
8636 if (vboxConnectNumOfStoragePools(conn) == 1) {
8637 ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key,
8639 VIR_DEBUG("Storage Volume Pool: %s", "default-pool");
8641 /* TODO: currently only one default pool and thus
8642 * nothing here, change it when pools are supported
8646 VIR_DEBUG("Storage Volume Name: %s", key);
8647 VIR_DEBUG("Storage Volume key : %s", hddNameUtf8);
8649 VBOX_UTF8_FREE(hddNameUtf8);
8650 VBOX_UTF16_FREE(hddNameUtf16);
8654 VBOX_MEDIUM_RELEASE(hardDisk);
8657 vboxIIDUnalloc(&hddIID);
8661 static virStorageVolPtr
8662 vboxStorageVolLookupByPath(virConnectPtr conn, const char *path)
8664 VBOX_OBJECT_CHECK(conn, virStorageVolPtr, NULL);
8665 PRUnichar *hddPathUtf16 = NULL;
8666 IHardDisk *hardDisk = NULL;
8672 VBOX_UTF8_TO_UTF16(path, &hddPathUtf16);
8677 #if VBOX_API_VERSION < 4000000
8678 rc = data->vboxObj->vtbl->FindHardDisk(data->vboxObj, hddPathUtf16, &hardDisk);
8679 #elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
8680 rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddPathUtf16,
8681 DeviceType_HardDisk, &hardDisk);
8683 rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddPathUtf16,
8684 DeviceType_HardDisk, AccessMode_ReadWrite,
8685 PR_FALSE, &hardDisk);
8686 #endif /* VBOX_API_VERSION >= 4000000 */
8687 if (NS_SUCCEEDED(rc)) {
8690 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
8691 if (hddstate != MediaState_Inaccessible) {
8692 PRUnichar *hddNameUtf16 = NULL;
8693 char *hddNameUtf8 = NULL;
8695 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &hddNameUtf16);
8698 VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8);
8699 VBOX_UTF16_FREE(hddNameUtf16);
8703 vboxIID hddIID = VBOX_IID_INITIALIZER;
8704 unsigned char uuid[VIR_UUID_BUFLEN];
8705 char key[VIR_UUID_STRING_BUFLEN] = "";
8707 rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value);
8708 if (NS_SUCCEEDED(rc)) {
8709 vboxIIDToUUID(&hddIID, uuid);
8710 virUUIDFormat(uuid, key);
8712 /* TODO: currently only one default pool and thus
8713 * the check below, change it when pools are supported
8715 if (vboxConnectNumOfStoragePools(conn) == 1)
8716 ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key,
8719 VIR_DEBUG("Storage Volume Pool: %s", "default-pool");
8720 VIR_DEBUG("Storage Volume Name: %s", hddNameUtf8);
8721 VIR_DEBUG("Storage Volume key : %s", key);
8724 vboxIIDUnalloc(&hddIID);
8727 VBOX_UTF8_FREE(hddNameUtf8);
8730 VBOX_MEDIUM_RELEASE(hardDisk);
8733 VBOX_UTF16_FREE(hddPathUtf16);
8738 static virStorageVolPtr vboxStorageVolCreateXML(virStoragePoolPtr pool,
8742 VBOX_OBJECT_CHECK(pool->conn, virStorageVolPtr, NULL);
8743 virStorageVolDefPtr def = NULL;
8744 PRUnichar *hddFormatUtf16 = NULL;
8745 PRUnichar *hddNameUtf16 = NULL;
8746 virStoragePoolDef poolDef;
8749 virCheckFlags(0, NULL);
8751 /* since there is currently one default pool now
8752 * and virStorageVolDefFormat() just checks it type
8753 * so just assign it for now, change the behaviour
8754 * when vbox supports pools.
8756 memset(&poolDef, 0, sizeof(poolDef));
8757 poolDef.type = VIR_STORAGE_POOL_DIR;
8759 if ((def = virStorageVolDefParseString(&poolDef, xml)) == NULL)
8763 (def->type != VIR_STORAGE_VOL_FILE))
8766 /* For now only the vmdk, vpc and vdi type harddisk
8767 * variants can be created. For historical reason, we default to vdi */
8768 if (def->target.format == VIR_STORAGE_FILE_VMDK) {
8769 VBOX_UTF8_TO_UTF16("VMDK", &hddFormatUtf16);
8770 } else if (def->target.format == VIR_STORAGE_FILE_VPC) {
8771 VBOX_UTF8_TO_UTF16("VHD", &hddFormatUtf16);
8773 VBOX_UTF8_TO_UTF16("VDI", &hddFormatUtf16);
8776 VBOX_UTF8_TO_UTF16(def->name, &hddNameUtf16);
8778 if (hddFormatUtf16 && hddNameUtf16) {
8779 IHardDisk *hardDisk = NULL;
8781 rc = data->vboxObj->vtbl->CreateHardDisk(data->vboxObj, hddFormatUtf16, hddNameUtf16, &hardDisk);
8782 if (NS_SUCCEEDED(rc)) {
8783 IProgress *progress = NULL;
8784 PRUint64 logicalSize = VIR_DIV_UP(def->target.capacity,
8786 PRUint32 variant = HardDiskVariant_Standard;
8788 if (def->target.capacity == def->target.allocation)
8789 variant = HardDiskVariant_Fixed;
8791 #if VBOX_API_VERSION < 4003000
8792 rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, variant, &progress);
8794 rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, 1, &variant, &progress);
8796 if (NS_SUCCEEDED(rc) && progress) {
8797 #if VBOX_API_VERSION == 2002000
8798 nsresult resultCode;
8803 progress->vtbl->WaitForCompletion(progress, -1);
8804 progress->vtbl->GetResultCode(progress, &resultCode);
8806 if (NS_SUCCEEDED(resultCode)) {
8807 vboxIID hddIID = VBOX_IID_INITIALIZER;
8808 unsigned char uuid[VIR_UUID_BUFLEN];
8809 char key[VIR_UUID_STRING_BUFLEN] = "";
8811 rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value);
8812 if (NS_SUCCEEDED(rc)) {
8813 vboxIIDToUUID(&hddIID, uuid);
8814 virUUIDFormat(uuid, key);
8816 ret = virGetStorageVol(pool->conn, pool->name, def->name, key,
8820 vboxIIDUnalloc(&hddIID);
8823 VBOX_RELEASE(progress);
8828 VBOX_UTF16_FREE(hddFormatUtf16);
8829 VBOX_UTF16_FREE(hddNameUtf16);
8832 virStorageVolDefFree(def);
8836 static int vboxStorageVolDelete(virStorageVolPtr vol,
8839 VBOX_OBJECT_CHECK(vol->conn, int, -1);
8840 vboxIID hddIID = VBOX_IID_INITIALIZER;
8841 unsigned char uuid[VIR_UUID_BUFLEN];
8842 IHardDisk *hardDisk = NULL;
8848 virCheckFlags(0, -1);
8850 if (virUUIDParse(vol->key, uuid) < 0) {
8851 virReportError(VIR_ERR_INVALID_ARG,
8852 _("Could not parse UUID from '%s'"), vol->key);
8856 vboxIIDFromUUID(&hddIID, uuid);
8857 #if VBOX_API_VERSION < 4000000
8858 rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk);
8859 #elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
8860 rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value,
8861 DeviceType_HardDisk, &hardDisk);
8863 rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value,
8864 DeviceType_HardDisk, AccessMode_ReadWrite,
8865 PR_FALSE, &hardDisk);
8866 #endif /* VBOX_API_VERSION >= 4000000 */
8867 if (NS_SUCCEEDED(rc)) {
8870 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
8871 if (hddstate != MediaState_Inaccessible) {
8872 PRUint32 machineIdsSize = 0;
8873 vboxArray machineIds = VBOX_ARRAY_INITIALIZER;
8875 #if VBOX_API_VERSION < 3001000
8876 vboxArrayGet(&machineIds, hardDisk, hardDisk->vtbl->imedium.GetMachineIds);
8877 #else /* VBOX_API_VERSION >= 3001000 */
8878 vboxArrayGet(&machineIds, hardDisk, hardDisk->vtbl->GetMachineIds);
8879 #endif /* VBOX_API_VERSION >= 3001000 */
8881 #if VBOX_API_VERSION == 2002000 && defined WIN32
8882 /* VirtualBox 2.2 on Windows represents IIDs as GUIDs and the
8883 * machineIds array contains direct instances of the GUID struct
8884 * instead of pointers to the actual struct instances. But there
8885 * is no 128bit width simple item type for a SafeArray to fit a
8886 * GUID in. The largest simple type it 64bit width and VirtualBox
8887 * uses two of this 64bit items to represents one GUID. Therefore,
8888 * we divide the size of the SafeArray by two, to compensate for
8889 * this workaround in VirtualBox */
8890 machineIds.count /= 2;
8891 #endif /* VBOX_API_VERSION >= 2002000 */
8893 machineIdsSize = machineIds.count;
8895 for (i = 0; i < machineIds.count; i++) {
8896 IMachine *machine = NULL;
8897 vboxIID machineId = VBOX_IID_INITIALIZER;
8899 vboxIIDFromArrayItem(&machineId, &machineIds, i);
8901 #if VBOX_API_VERSION >= 4000000
8902 rc = VBOX_OBJECT_GET_MACHINE(machineId.value, &machine);
8903 if (NS_FAILED(rc)) {
8904 virReportError(VIR_ERR_NO_DOMAIN, "%s",
8905 _("no domain with matching uuid"));
8910 rc = VBOX_SESSION_OPEN(machineId.value, machine);
8912 if (NS_SUCCEEDED(rc)) {
8914 rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
8915 if (NS_SUCCEEDED(rc)) {
8916 vboxArray hddAttachments = VBOX_ARRAY_INITIALIZER;
8918 #if VBOX_API_VERSION < 3001000
8919 vboxArrayGet(&hddAttachments, machine,
8920 machine->vtbl->GetHardDiskAttachments);
8921 #else /* VBOX_API_VERSION >= 3001000 */
8922 vboxArrayGet(&hddAttachments, machine,
8923 machine->vtbl->GetMediumAttachments);
8924 #endif /* VBOX_API_VERSION >= 3001000 */
8925 for (j = 0; j < hddAttachments.count; j++) {
8926 IHardDiskAttachment *hddAttachment = hddAttachments.items[j];
8928 if (hddAttachment) {
8929 IHardDisk *hdd = NULL;
8931 #if VBOX_API_VERSION < 3001000
8932 rc = hddAttachment->vtbl->GetHardDisk(hddAttachment, &hdd);
8933 #else /* VBOX_API_VERSION >= 3001000 */
8934 rc = hddAttachment->vtbl->GetMedium(hddAttachment, &hdd);
8935 #endif /* VBOX_API_VERSION >= 3001000 */
8936 if (NS_SUCCEEDED(rc) && hdd) {
8937 vboxIID iid = VBOX_IID_INITIALIZER;
8939 rc = VBOX_MEDIUM_FUNC_ARG1(hdd, GetId, &iid.value);
8940 if (NS_SUCCEEDED(rc)) {
8942 DEBUGIID("HardDisk (to delete) UUID", hddIID.value);
8943 DEBUGIID("HardDisk (currently processing) UUID", iid.value);
8945 if (vboxIIDIsEqual(&hddIID, &iid)) {
8946 PRUnichar *controller = NULL;
8950 DEBUGIID("Found HardDisk to delete, UUID", hddIID.value);
8952 hddAttachment->vtbl->GetController(hddAttachment, &controller);
8953 hddAttachment->vtbl->GetPort(hddAttachment, &port);
8954 hddAttachment->vtbl->GetDevice(hddAttachment, &device);
8956 #if VBOX_API_VERSION < 3001000
8957 rc = machine->vtbl->DetachHardDisk(machine, controller, port, device);
8958 #else /* VBOX_API_VERSION >= 3001000 */
8959 rc = machine->vtbl->DetachDevice(machine, controller, port, device);
8960 #endif /* VBOX_API_VERSION >= 3001000 */
8961 if (NS_SUCCEEDED(rc)) {
8962 rc = machine->vtbl->SaveSettings(machine);
8963 VIR_DEBUG("saving machine settings");
8966 if (NS_SUCCEEDED(rc)) {
8968 VIR_DEBUG("deregistering hdd:%d", deregister);
8971 VBOX_UTF16_FREE(controller);
8973 vboxIIDUnalloc(&iid);
8975 VBOX_MEDIUM_RELEASE(hdd);
8979 vboxArrayRelease(&hddAttachments);
8980 VBOX_RELEASE(machine);
8982 VBOX_SESSION_CLOSE();
8985 vboxIIDUnalloc(&machineId);
8988 vboxArrayUnalloc(&machineIds);
8990 if (machineIdsSize == 0 || machineIdsSize == deregister) {
8991 IProgress *progress = NULL;
8993 rc = hardDisk->vtbl->DeleteStorage(hardDisk, &progress);
8995 if (NS_SUCCEEDED(rc) && progress) {
8996 progress->vtbl->WaitForCompletion(progress, -1);
8997 VBOX_RELEASE(progress);
8998 DEBUGIID("HardDisk deleted, UUID", hddIID.value);
9004 VBOX_MEDIUM_RELEASE(hardDisk);
9007 vboxIIDUnalloc(&hddIID);
9013 vboxStorageVolGetInfo(virStorageVolPtr vol, virStorageVolInfoPtr info)
9015 VBOX_OBJECT_CHECK(vol->conn, int, -1);
9016 IHardDisk *hardDisk = NULL;
9017 unsigned char uuid[VIR_UUID_BUFLEN];
9018 vboxIID hddIID = VBOX_IID_INITIALIZER;
9024 if (virUUIDParse(vol->key, uuid) < 0) {
9025 virReportError(VIR_ERR_INVALID_ARG,
9026 _("Could not parse UUID from '%s'"), vol->key);
9030 vboxIIDFromUUID(&hddIID, uuid);
9031 #if VBOX_API_VERSION < 4000000
9032 rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk);
9033 #elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
9034 rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value,
9035 DeviceType_HardDisk, &hardDisk);
9037 rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value,
9038 DeviceType_HardDisk, AccessMode_ReadWrite,
9039 PR_FALSE, &hardDisk);
9040 #endif /* VBOX_API_VERSION >= 4000000 */
9041 if (NS_SUCCEEDED(rc)) {
9044 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
9045 if (hddstate != MediaState_Inaccessible) {
9046 #if VBOX_API_VERSION < 4000000
9047 PRUint64 hddLogicalSize;
9048 PRUint64 hddActualSize;
9049 #else /* VBOX_API_VERSION >= 4000000 */
9050 PRInt64 hddLogicalSize;
9051 PRInt64 hddActualSize;
9052 #endif /* VBOX_API_VERSION >= 4000000 */
9054 info->type = VIR_STORAGE_VOL_FILE;
9056 hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize);
9057 #if VBOX_API_VERSION < 4000000
9058 info->capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */
9059 #else /* VBOX_API_VERSION >= 4000000 */
9060 info->capacity = hddLogicalSize;
9061 #endif /* VBOX_API_VERSION >= 4000000 */
9063 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetSize, &hddActualSize);
9064 info->allocation = hddActualSize;
9068 VIR_DEBUG("Storage Volume Name: %s", vol->name);
9069 VIR_DEBUG("Storage Volume Type: %s", info->type == VIR_STORAGE_VOL_BLOCK ? "Block" : "File");
9070 VIR_DEBUG("Storage Volume Capacity: %llu", info->capacity);
9071 VIR_DEBUG("Storage Volume Allocation: %llu", info->allocation);
9074 VBOX_MEDIUM_RELEASE(hardDisk);
9077 vboxIIDUnalloc(&hddIID);
9082 static char *vboxStorageVolGetXMLDesc(virStorageVolPtr vol, unsigned int flags)
9084 VBOX_OBJECT_CHECK(vol->conn, char *, NULL);
9085 IHardDisk *hardDisk = NULL;
9086 unsigned char uuid[VIR_UUID_BUFLEN];
9087 vboxIID hddIID = VBOX_IID_INITIALIZER;
9088 virStoragePoolDef pool;
9089 virStorageVolDef def;
9093 virCheckFlags(0, NULL);
9095 memset(&pool, 0, sizeof(pool));
9096 memset(&def, 0, sizeof(def));
9098 if (virUUIDParse(vol->key, uuid) < 0) {
9099 virReportError(VIR_ERR_INVALID_ARG,
9100 _("Could not parse UUID from '%s'"), vol->key);
9104 vboxIIDFromUUID(&hddIID, uuid);
9105 #if VBOX_API_VERSION < 4000000
9106 rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk);
9107 #elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
9108 rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value,
9109 DeviceType_HardDisk, &hardDisk);
9111 rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value,
9112 DeviceType_HardDisk, AccessMode_ReadWrite,
9113 PR_FALSE, &hardDisk);
9114 #endif /* VBOX_API_VERSION >= 4000000 */
9115 if (NS_SUCCEEDED(rc)) {
9118 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
9119 if (NS_SUCCEEDED(rc) && hddstate != MediaState_Inaccessible) {
9120 PRUnichar *hddFormatUtf16 = NULL;
9121 #if VBOX_API_VERSION < 4000000
9122 PRUint64 hddLogicalSize;
9123 PRUint64 hddActualSize;
9124 #else /* VBOX_API_VERSION >= 4000000 */
9125 PRInt64 hddLogicalSize;
9126 PRInt64 hddActualSize;
9127 #endif /* VBOX_API_VERSION >= 4000000 */
9129 /* since there is currently one default pool now
9130 * and virStorageVolDefFormat() just checks it type
9131 * so just assign it for now, change the behaviour
9132 * when vbox supports pools.
9134 pool.type = VIR_STORAGE_POOL_DIR;
9135 def.type = VIR_STORAGE_VOL_FILE;
9138 rc = hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize);
9139 if (NS_SUCCEEDED(rc) && defOk) {
9140 #if VBOX_API_VERSION < 4000000
9141 def.target.capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */
9142 #else /* VBOX_API_VERSION >= 4000000 */
9143 def.target.capacity = hddLogicalSize;
9144 #endif /* VBOX_API_VERSION >= 4000000 */
9148 rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetSize, &hddActualSize);
9149 if (NS_SUCCEEDED(rc) && defOk)
9150 def.target.allocation = hddActualSize;
9154 if (VIR_STRDUP(def.name, vol->name) < 0)
9157 if (VIR_STRDUP(def.key, vol->key) < 0)
9160 rc = hardDisk->vtbl->GetFormat(hardDisk, &hddFormatUtf16);
9161 if (NS_SUCCEEDED(rc) && defOk) {
9162 char *hddFormatUtf8 = NULL;
9164 VBOX_UTF16_TO_UTF8(hddFormatUtf16, &hddFormatUtf8);
9165 if (hddFormatUtf8) {
9167 VIR_DEBUG("Storage Volume Format: %s", hddFormatUtf8);
9169 if (STRCASEEQ("vmdk", hddFormatUtf8))
9170 def.target.format = VIR_STORAGE_FILE_VMDK;
9171 else if (STRCASEEQ("vhd", hddFormatUtf8))
9172 def.target.format = VIR_STORAGE_FILE_VPC;
9173 else if (STRCASEEQ("vdi", hddFormatUtf8))
9174 def.target.format = VIR_STORAGE_FILE_VDI;
9176 def.target.format = VIR_STORAGE_FILE_RAW;
9178 VBOX_UTF8_FREE(hddFormatUtf8);
9181 VBOX_UTF16_FREE(hddFormatUtf16);
9187 VBOX_MEDIUM_RELEASE(hardDisk);
9190 vboxIIDUnalloc(&hddIID);
9193 ret = virStorageVolDefFormat(&pool, &def);
9198 static char *vboxStorageVolGetPath(virStorageVolPtr vol) {
9199 VBOX_OBJECT_CHECK(vol->conn, char *, NULL);
9200 IHardDisk *hardDisk = NULL;
9201 unsigned char uuid[VIR_UUID_BUFLEN];
9202 vboxIID hddIID = VBOX_IID_INITIALIZER;
9205 if (virUUIDParse(vol->key, uuid) < 0) {
9206 virReportError(VIR_ERR_INVALID_ARG,
9207 _("Could not parse UUID from '%s'"), vol->key);
9211 vboxIIDFromUUID(&hddIID, uuid);
9212 #if VBOX_API_VERSION < 4000000
9213 rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk);
9214 #elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
9215 rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value,
9216 DeviceType_HardDisk, &hardDisk);
9218 rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value,
9219 DeviceType_HardDisk, AccessMode_ReadWrite,
9220 PR_FALSE, &hardDisk);
9221 #endif /* VBOX_API_VERSION >= 4000000 */
9222 if (NS_SUCCEEDED(rc)) {
9225 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
9226 if (hddstate != MediaState_Inaccessible) {
9227 PRUnichar *hddLocationUtf16 = NULL;
9228 char *hddLocationUtf8 = NULL;
9230 VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetLocation, &hddLocationUtf16);
9232 VBOX_UTF16_TO_UTF8(hddLocationUtf16, &hddLocationUtf8);
9233 if (hddLocationUtf8) {
9235 ignore_value(VIR_STRDUP(ret, hddLocationUtf8));
9237 VIR_DEBUG("Storage Volume Name: %s", vol->name);
9238 VIR_DEBUG("Storage Volume Path: %s", hddLocationUtf8);
9239 VIR_DEBUG("Storage Volume Pool: %s", vol->pool);
9241 VBOX_UTF8_FREE(hddLocationUtf8);
9244 VBOX_UTF16_FREE(hddLocationUtf16);
9247 VBOX_MEDIUM_RELEASE(hardDisk);
9250 vboxIIDUnalloc(&hddIID);
9255 #if VBOX_API_VERSION >= 4000000
9257 vboxDomainScreenshot(virDomainPtr dom,
9259 unsigned int screen,
9262 VBOX_OBJECT_CHECK(dom->conn, char *, NULL);
9263 IConsole *console = NULL;
9264 vboxIID iid = VBOX_IID_INITIALIZER;
9265 IMachine *machine = NULL;
9269 unsigned int max_screen;
9271 virCheckFlags(0, NULL);
9273 vboxIIDFromUUID(&iid, dom->uuid);
9274 rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
9275 if (NS_FAILED(rc)) {
9276 virReportError(VIR_ERR_NO_DOMAIN, "%s",
9277 _("no domain with matching uuid"));
9281 rc = machine->vtbl->GetMonitorCount(machine, &max_screen);
9282 if (NS_FAILED(rc)) {
9283 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
9284 _("unable to get monitor count"));
9285 VBOX_RELEASE(machine);
9289 if (screen >= max_screen) {
9290 virReportError(VIR_ERR_INVALID_ARG,
9291 _("screen ID higher than monitor "
9292 "count (%d)"), max_screen);
9293 VBOX_RELEASE(machine);
9297 if (virAsprintf(&tmp, "%s/cache/libvirt/vbox.screendump.XXXXXX", LOCALSTATEDIR) < 0) {
9298 VBOX_RELEASE(machine);
9302 if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
9303 virReportSystemError(errno, _("mkostemp(\"%s\") failed"), tmp);
9305 VBOX_RELEASE(machine);
9310 rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
9311 if (NS_SUCCEEDED(rc)) {
9312 rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console);
9313 if (NS_SUCCEEDED(rc) && console) {
9314 IDisplay *display = NULL;
9316 console->vtbl->GetDisplay(console, &display);
9319 PRUint32 width, height, bitsPerPixel;
9320 PRUint32 screenDataSize;
9321 PRUint8 *screenData;
9322 # if VBOX_API_VERSION >= 4003000
9323 PRInt32 xOrigin, yOrigin;
9326 rc = display->vtbl->GetScreenResolution(display, screen,
9328 # if VBOX_API_VERSION < 4003000
9332 &xOrigin, &yOrigin);
9335 if (NS_FAILED(rc) || !width || !height) {
9336 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
9337 _("unable to get screen resolution"));
9341 rc = display->vtbl->TakeScreenShotPNGToArray(display, screen,
9345 if (NS_FAILED(rc)) {
9346 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
9347 _("failed to take screenshot"));
9351 if (safewrite(tmp_fd, (char *) screenData,
9352 screenDataSize) < 0) {
9353 virReportSystemError(errno, _("unable to write data "
9358 if (VIR_CLOSE(tmp_fd) < 0) {
9359 virReportSystemError(errno, _("unable to close %s"), tmp);
9363 if (VIR_STRDUP(ret, "image/png") < 0)
9366 if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) {
9367 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
9368 _("unable to open stream"));
9372 VIR_FREE(screenData);
9373 VBOX_RELEASE(display);
9375 VBOX_RELEASE(console);
9377 VBOX_SESSION_CLOSE();
9380 VIR_FORCE_CLOSE(tmp_fd);
9383 VBOX_RELEASE(machine);
9384 vboxIIDUnalloc(&iid);
9387 #endif /* VBOX_API_VERSION >= 4000000 */
9390 #define MATCH(FLAG) (flags & (FLAG))
9392 vboxConnectListAllDomains(virConnectPtr conn,
9393 virDomainPtr **domains,
9396 VBOX_OBJECT_CHECK(conn, int, -1);
9397 vboxArray machines = VBOX_ARRAY_INITIALIZER;
9398 char *machineNameUtf8 = NULL;
9399 PRUnichar *machineNameUtf16 = NULL;
9400 unsigned char uuid[VIR_UUID_BUFLEN];
9401 vboxIID iid = VBOX_IID_INITIALIZER;
9406 virDomainPtr *doms = NULL;
9409 PRUint32 snapshotCount;
9411 virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
9413 /* filter out flag options that will produce 0 results in vbox driver:
9414 * - managed save: vbox guests don't have managed save images
9415 * - autostart: vbox doesn't support autostarting guests
9416 * - persistance: vbox doesn't support transient guests
9418 if ((MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) &&
9419 !MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT)) ||
9420 (MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) &&
9421 !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART)) ||
9422 (MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) &&
9423 !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE))) {
9425 VIR_ALLOC_N(*domains, 1) < 0)
9432 rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines);
9433 if (NS_FAILED(rc)) {
9434 virReportError(VIR_ERR_INTERNAL_ERROR,
9435 _("Could not get list of domains, rc=%08x"), (unsigned)rc);
9440 VIR_ALLOC_N(doms, machines.count + 1) < 0)
9443 for (i = 0; i < machines.count; i++) {
9444 IMachine *machine = machines.items[i];
9447 PRBool isAccessible = PR_FALSE;
9448 machine->vtbl->GetAccessible(machine, &isAccessible);
9450 machine->vtbl->GetState(machine, &state);
9452 if (state >= MachineState_FirstOnline &&
9453 state <= MachineState_LastOnline)
9458 /* filter by active state */
9459 if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) &&
9460 !((MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE) && active) ||
9461 (MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE) && !active)))
9464 /* filter by snapshot existence */
9465 if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_SNAPSHOT)) {
9466 rc = machine->vtbl->GetSnapshotCount(machine, &snapshotCount);
9467 if (NS_FAILED(rc)) {
9468 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9469 _("could not get snapshot count for listed domains"));
9472 if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) &&
9473 snapshotCount > 0) ||
9474 (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) &&
9475 snapshotCount == 0)))
9479 /* filter by machine state */
9480 if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE) &&
9481 !((MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) &&
9482 state == MachineState_Running) ||
9483 (MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) &&
9484 state == MachineState_Paused) ||
9485 (MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) &&
9486 state == MachineState_PoweredOff) ||
9487 (MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) &&
9488 (state != MachineState_Running &&
9489 state != MachineState_Paused &&
9490 state != MachineState_PoweredOff))))
9493 /* just count the machines */
9499 machine->vtbl->GetName(machine, &machineNameUtf16);
9500 VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8);
9501 machine->vtbl->GetId(machine, &iid.value);
9502 vboxIIDToUUID(&iid, uuid);
9503 vboxIIDUnalloc(&iid);
9505 dom = virGetDomain(conn, machineNameUtf8, uuid);
9507 VBOX_UTF8_FREE(machineNameUtf8);
9508 VBOX_UTF16_FREE(machineNameUtf16);
9516 doms[count++] = dom;
9522 /* safe to ignore, new size will be equal or less than
9523 * previous allocation*/
9524 ignore_value(VIR_REALLOC_N(doms, count + 1));
9533 for (i = 0; i < count; i++) {
9535 virDomainFree(doms[i]);
9540 vboxArrayRelease(&machines);
9547 vboxNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED,
9548 virNodeInfoPtr nodeinfo)
9550 return nodeGetInfo(nodeinfo);
9555 vboxNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED,
9556 unsigned long long *freeMems,
9560 return nodeGetCellsFreeMemory(freeMems, startCell, maxCells);
9564 static unsigned long long
9565 vboxNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED)
9567 return nodeGetFreeMemory();
9575 virDriver NAME(Driver) = {
9578 .connectOpen = vboxConnectOpen, /* 0.6.3 */
9579 .connectClose = vboxConnectClose, /* 0.6.3 */
9580 .connectGetVersion = vboxConnectGetVersion, /* 0.6.3 */
9581 .connectGetHostname = vboxConnectGetHostname, /* 0.6.3 */
9582 .connectGetMaxVcpus = vboxConnectGetMaxVcpus, /* 0.6.3 */
9583 .nodeGetInfo = vboxNodeGetInfo, /* 0.6.3 */
9584 .connectGetCapabilities = vboxConnectGetCapabilities, /* 0.6.3 */
9585 .connectListDomains = vboxConnectListDomains, /* 0.6.3 */
9586 .connectNumOfDomains = vboxConnectNumOfDomains, /* 0.6.3 */
9587 .connectListAllDomains = vboxConnectListAllDomains, /* 0.9.13 */
9588 .domainCreateXML = vboxDomainCreateXML, /* 0.6.3 */
9589 .domainLookupByID = vboxDomainLookupByID, /* 0.6.3 */
9590 .domainLookupByUUID = vboxDomainLookupByUUID, /* 0.6.3 */
9591 .domainLookupByName = vboxDomainLookupByName, /* 0.6.3 */
9592 .domainSuspend = vboxDomainSuspend, /* 0.6.3 */
9593 .domainResume = vboxDomainResume, /* 0.6.3 */
9594 .domainShutdown = vboxDomainShutdown, /* 0.6.3 */
9595 .domainShutdownFlags = vboxDomainShutdownFlags, /* 0.9.10 */
9596 .domainReboot = vboxDomainReboot, /* 0.6.3 */
9597 .domainDestroy = vboxDomainDestroy, /* 0.6.3 */
9598 .domainDestroyFlags = vboxDomainDestroyFlags, /* 0.9.4 */
9599 .domainGetOSType = vboxDomainGetOSType, /* 0.6.3 */
9600 .domainSetMemory = vboxDomainSetMemory, /* 0.6.3 */
9601 .domainGetInfo = vboxDomainGetInfo, /* 0.6.3 */
9602 .domainGetState = vboxDomainGetState, /* 0.9.2 */
9603 .domainSave = vboxDomainSave, /* 0.6.3 */
9604 .domainSetVcpus = vboxDomainSetVcpus, /* 0.7.1 */
9605 .domainSetVcpusFlags = vboxDomainSetVcpusFlags, /* 0.8.5 */
9606 .domainGetVcpusFlags = vboxDomainGetVcpusFlags, /* 0.8.5 */
9607 .domainGetMaxVcpus = vboxDomainGetMaxVcpus, /* 0.7.1 */
9608 .domainGetXMLDesc = vboxDomainGetXMLDesc, /* 0.6.3 */
9609 .connectListDefinedDomains = vboxConnectListDefinedDomains, /* 0.6.3 */
9610 .connectNumOfDefinedDomains = vboxConnectNumOfDefinedDomains, /* 0.6.3 */
9611 .domainCreate = vboxDomainCreate, /* 0.6.3 */
9612 .domainCreateWithFlags = vboxDomainCreateWithFlags, /* 0.8.2 */
9613 .domainDefineXML = vboxDomainDefineXML, /* 0.6.3 */
9614 .domainUndefine = vboxDomainUndefine, /* 0.6.3 */
9615 .domainUndefineFlags = vboxDomainUndefineFlags, /* 0.9.5 */
9616 .domainAttachDevice = vboxDomainAttachDevice, /* 0.6.3 */
9617 .domainAttachDeviceFlags = vboxDomainAttachDeviceFlags, /* 0.7.7 */
9618 .domainDetachDevice = vboxDomainDetachDevice, /* 0.6.3 */
9619 .domainDetachDeviceFlags = vboxDomainDetachDeviceFlags, /* 0.7.7 */
9620 .domainUpdateDeviceFlags = vboxDomainUpdateDeviceFlags, /* 0.8.0 */
9621 .nodeGetCellsFreeMemory = vboxNodeGetCellsFreeMemory, /* 0.6.5 */
9622 .nodeGetFreeMemory = vboxNodeGetFreeMemory, /* 0.6.5 */
9623 #if VBOX_API_VERSION >= 4000000
9624 .domainScreenshot = vboxDomainScreenshot, /* 0.9.2 */
9626 #if VBOX_API_VERSION > 2002000 && VBOX_API_VERSION < 4000000
9627 .connectDomainEventRegister = vboxConnectDomainEventRegister, /* 0.7.0 */
9628 .connectDomainEventDeregister = vboxConnectDomainEventDeregister, /* 0.7.0 */
9630 .connectIsEncrypted = vboxConnectIsEncrypted, /* 0.7.3 */
9631 .connectIsSecure = vboxConnectIsSecure, /* 0.7.3 */
9632 .domainIsActive = vboxDomainIsActive, /* 0.7.3 */
9633 .domainIsPersistent = vboxDomainIsPersistent, /* 0.7.3 */
9634 .domainIsUpdated = vboxDomainIsUpdated, /* 0.8.6 */
9635 #if VBOX_API_VERSION > 2002000 && VBOX_API_VERSION < 4000000
9636 .connectDomainEventRegisterAny = vboxConnectDomainEventRegisterAny, /* 0.8.0 */
9637 .connectDomainEventDeregisterAny = vboxConnectDomainEventDeregisterAny, /* 0.8.0 */
9639 .domainSnapshotCreateXML = vboxDomainSnapshotCreateXML, /* 0.8.0 */
9640 .domainSnapshotGetXMLDesc = vboxDomainSnapshotGetXMLDesc, /* 0.8.0 */
9641 .domainSnapshotNum = vboxDomainSnapshotNum, /* 0.8.0 */
9642 .domainSnapshotListNames = vboxDomainSnapshotListNames, /* 0.8.0 */
9643 .domainSnapshotLookupByName = vboxDomainSnapshotLookupByName, /* 0.8.0 */
9644 .domainHasCurrentSnapshot = vboxDomainHasCurrentSnapshot, /* 0.8.0 */
9645 .domainSnapshotGetParent = vboxDomainSnapshotGetParent, /* 0.9.7 */
9646 .domainSnapshotCurrent = vboxDomainSnapshotCurrent, /* 0.8.0 */
9647 .domainSnapshotIsCurrent = vboxDomainSnapshotIsCurrent, /* 0.9.13 */
9648 .domainSnapshotHasMetadata = vboxDomainSnapshotHasMetadata, /* 0.9.13 */
9649 .domainRevertToSnapshot = vboxDomainRevertToSnapshot, /* 0.8.0 */
9650 .domainSnapshotDelete = vboxDomainSnapshotDelete, /* 0.8.0 */
9651 .connectIsAlive = vboxConnectIsAlive, /* 0.9.8 */
9654 virNetworkDriver NAME(NetworkDriver) = {
9656 .networkOpen = vboxNetworkOpen, /* 0.6.4 */
9657 .networkClose = vboxNetworkClose, /* 0.6.4 */
9658 .connectNumOfNetworks = vboxConnectNumOfNetworks, /* 0.6.4 */
9659 .connectListNetworks = vboxConnectListNetworks, /* 0.6.4 */
9660 .connectNumOfDefinedNetworks = vboxConnectNumOfDefinedNetworks, /* 0.6.4 */
9661 .connectListDefinedNetworks = vboxConnectListDefinedNetworks, /* 0.6.4 */
9662 .networkLookupByUUID = vboxNetworkLookupByUUID, /* 0.6.4 */
9663 .networkLookupByName = vboxNetworkLookupByName, /* 0.6.4 */
9664 .networkCreateXML = vboxNetworkCreateXML, /* 0.6.4 */
9665 .networkDefineXML = vboxNetworkDefineXML, /* 0.6.4 */
9666 .networkUndefine = vboxNetworkUndefine, /* 0.6.4 */
9667 .networkCreate = vboxNetworkCreate, /* 0.6.4 */
9668 .networkDestroy = vboxNetworkDestroy, /* 0.6.4 */
9669 .networkGetXMLDesc = vboxNetworkGetXMLDesc, /* 0.6.4 */
9672 virStorageDriver NAME(StorageDriver) = {
9674 .storageOpen = vboxStorageOpen, /* 0.7.1 */
9675 .storageClose = vboxStorageClose, /* 0.7.1 */
9676 .connectNumOfStoragePools = vboxConnectNumOfStoragePools, /* 0.7.1 */
9677 .connectListStoragePools = vboxConnectListStoragePools, /* 0.7.1 */
9678 .storagePoolLookupByName = vboxStoragePoolLookupByName, /* 0.7.1 */
9679 .storagePoolNumOfVolumes = vboxStoragePoolNumOfVolumes, /* 0.7.1 */
9680 .storagePoolListVolumes = vboxStoragePoolListVolumes, /* 0.7.1 */
9682 .storageVolLookupByName = vboxStorageVolLookupByName, /* 0.7.1 */
9683 .storageVolLookupByKey = vboxStorageVolLookupByKey, /* 0.7.1 */
9684 .storageVolLookupByPath = vboxStorageVolLookupByPath, /* 0.7.1 */
9685 .storageVolCreateXML = vboxStorageVolCreateXML, /* 0.7.1 */
9686 .storageVolDelete = vboxStorageVolDelete, /* 0.7.1 */
9687 .storageVolGetInfo = vboxStorageVolGetInfo, /* 0.7.1 */
9688 .storageVolGetXMLDesc = vboxStorageVolGetXMLDesc, /* 0.7.1 */
9689 .storageVolGetPath = vboxStorageVolGetPath /* 0.7.1 */