--- src/vbox/vbox_common.c | 1169 +++++++++++ src/vbox/vbox_common.h | 90 + src/vbox/vbox_tmpl.c | 4535 ++++++++++++++++++++--------------------- src/vbox/vbox_uniformed_api.h | 128 ++ 4 files changed, 3557 insertions(+), 2365 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index efcda7a..f4e992d 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -81,6 +81,14 @@ VIR_LOG_INIT("vbox.vbox_common"); } \ } while (0) +#define VBOX_MEDIUM_RELEASE(arg) \ + do { \ + if (arg) { \ + gVBoxAPI.UIMedium.Release(arg); \ + (arg) = NULL; \ + } \ + } while (0) + #define VBOX_OBJECT_CHECK(conn, type, value) \ vboxGlobalData *data = conn->privateData;\ type ret = value;\ @@ -152,6 +160,123 @@ static int openSessionForMachine(vboxGlobalData *data, const unsigned char *dom_ return 0; } +/** + * function to get the values for max port per + * instance and max slots per port for the devices + * + * @returns true on Success, false on failure. + * @param vbox Input IVirtualBox pointer + * @param maxPortPerInst Output array of max port per instance + * @param maxSlotPerPort Output array of max slot per port + * + */ + +static bool vboxGetMaxPortSlotValues(IVirtualBox *vbox, + PRUint32 *maxPortPerInst, + PRUint32 *maxSlotPerPort) +{ + ISystemProperties *sysProps = NULL; + + if (!vbox) + return false; + + gVBoxAPI.UIVirtualBox.GetSystemProperties(vbox, &sysProps); + + if (!sysProps) + return false; + + gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps, + StorageBus_IDE, + &maxPortPerInst[StorageBus_IDE]); + gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps, + StorageBus_SATA, + &maxPortPerInst[StorageBus_SATA]); + gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps, + StorageBus_SCSI, + &maxPortPerInst[StorageBus_SCSI]); + gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps, + StorageBus_Floppy, + &maxPortPerInst[StorageBus_Floppy]); + + gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps, + StorageBus_IDE, + &maxSlotPerPort[StorageBus_IDE]); + gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps, + StorageBus_SATA, + &maxSlotPerPort[StorageBus_SATA]); + gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps, + StorageBus_SCSI, + &maxSlotPerPort[StorageBus_SCSI]); + gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps, + StorageBus_Floppy, + &maxSlotPerPort[StorageBus_Floppy]); + + VBOX_RELEASE(sysProps); + + return true; +} + +/** + * function to get the StorageBus, Port number + * and Device number for the given devicename + * e.g: hda has StorageBus = IDE, port = 0, + * device = 0 + * + * @returns true on Success, false on failure. + * @param deviceName Input device name + * @param aMaxPortPerInst Input array of max port per device instance + * @param aMaxSlotPerPort Input array of max slot per device port + * @param storageBus Input storage bus type + * @param deviceInst Output device instance number + * @param devicePort Output port number + * @param deviceSlot Output slot number + * + */ +static bool vboxGetDeviceDetails(const char *deviceName, + PRUint32 *aMaxPortPerInst, + PRUint32 *aMaxSlotPerPort, + PRUint32 storageBus, + PRInt32 *deviceInst, + PRInt32 *devicePort, + PRInt32 *deviceSlot) { + int total = 0; + PRUint32 maxPortPerInst = 0; + PRUint32 maxSlotPerPort = 0; + + if (!deviceName || + !deviceInst || + !devicePort || + !deviceSlot || + !aMaxPortPerInst || + !aMaxSlotPerPort) + return false; + + if ((storageBus < StorageBus_IDE) || + (storageBus > StorageBus_Floppy)) + return false; + + total = virDiskNameToIndex(deviceName); + + maxPortPerInst = aMaxPortPerInst[storageBus]; + maxSlotPerPort = aMaxSlotPerPort[storageBus]; + + if (!maxPortPerInst || + !maxSlotPerPort || + (total < 0)) + return false; + + *deviceInst = total / (maxPortPerInst * maxSlotPerPort); + *devicePort = (total % (maxPortPerInst * maxSlotPerPort)) / maxSlotPerPort; + *deviceSlot = (total % (maxPortPerInst * maxSlotPerPort)) % maxSlotPerPort; + + VIR_DEBUG("name=%s, total=%d, storageBus=%u, deviceInst=%d, " + "devicePort=%d deviceSlot=%d, maxPortPerInst=%u maxSlotPerPort=%u", + deviceName, total, storageBus, *deviceInst, *devicePort, + *deviceSlot, maxPortPerInst, maxSlotPerPort); + + return true; +} + static virDomainDefParserConfig vboxDomainDefParserConfig = { .macPrefix = { 0x08, 0x00, 0x27 }, }; @@ -700,6 +825,1050 @@ virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn, } static void +vboxSetBootDeviceOrder(virDomainDefPtr def, vboxGlobalData *data, + IMachine *machine) +{ + ISystemProperties *systemProperties = NULL; + PRUint32 maxBootPosition = 0; + size_t i = 0; + + VIR_DEBUG("def->os.type %s", def->os.type); + VIR_DEBUG("def->os.arch %s", virArchToString(def->os.arch)); + VIR_DEBUG("def->os.machine %s", def->os.machine); + VIR_DEBUG("def->os.nBootDevs %zu", def->os.nBootDevs); + VIR_DEBUG("def->os.bootDevs[0] %d", def->os.bootDevs[0]); + VIR_DEBUG("def->os.bootDevs[1] %d", def->os.bootDevs[1]); + VIR_DEBUG("def->os.bootDevs[2] %d", def->os.bootDevs[2]); + VIR_DEBUG("def->os.bootDevs[3] %d", def->os.bootDevs[3]); + VIR_DEBUG("def->os.init %s", def->os.init); + VIR_DEBUG("def->os.kernel %s", def->os.kernel); + VIR_DEBUG("def->os.initrd %s", def->os.initrd); + VIR_DEBUG("def->os.cmdline %s", def->os.cmdline); + VIR_DEBUG("def->os.root %s", def->os.root); + VIR_DEBUG("def->os.loader %s", def->os.loader); + VIR_DEBUG("def->os.bootloader %s", def->os.bootloader); + VIR_DEBUG("def->os.bootloaderArgs %s", def->os.bootloaderArgs); + + gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties); + if (systemProperties) { + gVBoxAPI.UISystemProperties.GetMaxBootPosition(systemProperties, + &maxBootPosition); + VBOX_RELEASE(systemProperties); + } + + /* Clear the defaults first */ + for (i = 0; i < maxBootPosition; i++) { + gVBoxAPI.UIMachine.SetBootOrder(machine, i+1, DeviceType_Null); + } + + for (i = 0; (i < def->os.nBootDevs) && (i < maxBootPosition); i++) { + PRUint32 device = DeviceType_Null; + + if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_FLOPPY) { + device = DeviceType_Floppy; + } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_CDROM) { + device = DeviceType_DVD; + } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_DISK) { + device = DeviceType_HardDisk; + } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_NET) { + device = DeviceType_Network; + } + gVBoxAPI.UIMachine.SetBootOrder(machine, i+1, device); + } +} + +static void +vboxAttachDrivesNew(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + /* AttachDrives for 3.0 and later */ + size_t i; + nsresult rc; + PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {}; + PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {}; + PRUnichar *storageCtlName = NULL; + bool error = false; + + if (gVBoxAPI.vboxAttachDrivesUseOld) + VIR_WARN("This function may not work in current vbox version"); + + /* get the max port/slots/etc for the given storage bus */ + error = !vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst, + maxSlotPerPort); + + /* add a storage controller for the mediums to be attached */ + /* this needs to change when multiple controller are supported for + * ver > 3.1 */ + { + IStorageController *storageCtl = NULL; + PRUnichar *sName = NULL; + + VBOX_UTF8_TO_UTF16("IDE Controller", &sName); + gVBoxAPI.UIMachine.AddStorageController(machine, + sName, + StorageBus_IDE, + &storageCtl); + VBOX_UTF16_FREE(sName); + VBOX_RELEASE(storageCtl); + + VBOX_UTF8_TO_UTF16("SATA Controller", &sName); + gVBoxAPI.UIMachine.AddStorageController(machine, + sName, + StorageBus_SATA, + &storageCtl); + VBOX_UTF16_FREE(sName); + VBOX_RELEASE(storageCtl); + + VBOX_UTF8_TO_UTF16("SCSI Controller", &sName); + gVBoxAPI.UIMachine.AddStorageController(machine, + sName, + StorageBus_SCSI, + &storageCtl); + VBOX_UTF16_FREE(sName); + VBOX_RELEASE(storageCtl); + + VBOX_UTF8_TO_UTF16("Floppy Controller", &sName); + gVBoxAPI.UIMachine.AddStorageController(machine, + sName, + StorageBus_Floppy, + &storageCtl); + VBOX_UTF16_FREE(sName); + VBOX_RELEASE(storageCtl); + } + + for (i = 0; i < def->ndisks && !error; i++) { + const char *src = virDomainDiskGetSource(def->disks[i]); + int type = virDomainDiskGetType(def->disks[i]); + int format = virDomainDiskGetFormat(def->disks[i]); + + VIR_DEBUG("disk(%zu) type: %d", i, type); + VIR_DEBUG("disk(%zu) device: %d", i, def->disks[i]->device); + VIR_DEBUG("disk(%zu) bus: %d", i, def->disks[i]->bus); + VIR_DEBUG("disk(%zu) src: %s", i, src); + VIR_DEBUG("disk(%zu) dst: %s", i, def->disks[i]->dst); + VIR_DEBUG("disk(%zu) driverName: %s", i, + virDomainDiskGetDriver(def->disks[i])); + VIR_DEBUG("disk(%zu) driverType: %s", i, + virStorageFileFormatTypeToString(format)); + VIR_DEBUG("disk(%zu) cachemode: %d", i, def->disks[i]->cachemode); + VIR_DEBUG("disk(%zu) readonly: %s", i, (def->disks[i]->src->readonly + ? "True" : "False")); + VIR_DEBUG("disk(%zu) shared: %s", i, (def->disks[i]->src->shared + ? "True" : "False")); + + if (type == VIR_STORAGE_TYPE_FILE && src) { + IMedium *medium = NULL; + vboxIIDUnion mediumUUID; + PRUnichar *mediumFileUtf16 = NULL; + PRUint32 storageBus = StorageBus_Null; + PRUint32 deviceType = DeviceType_Null; + PRUint32 accessMode = AccessMode_ReadOnly; + PRInt32 deviceInst = 0; + PRInt32 devicePort = 0; + PRInt32 deviceSlot = 0; + + VBOX_IID_INITIALIZE(&mediumUUID); + VBOX_UTF8_TO_UTF16(src, &mediumFileUtf16); + + if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) { + deviceType = DeviceType_HardDisk; + accessMode = AccessMode_ReadWrite; + } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { + deviceType = DeviceType_DVD; + accessMode = AccessMode_ReadOnly; + } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { + deviceType = DeviceType_Floppy; + accessMode = AccessMode_ReadWrite; + } else { + VBOX_UTF16_FREE(mediumFileUtf16); + continue; + } + + gVBoxAPI.UIVirtualBox.FindMedium(data->vboxObj, mediumFileUtf16, + deviceType, accessMode, &medium); + + if (!medium) { + PRUnichar *mediumEmpty = NULL; + + VBOX_UTF8_TO_UTF16("", &mediumEmpty); + + rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj, + mediumFileUtf16, + deviceType, accessMode, + &medium); + VBOX_UTF16_FREE(mediumEmpty); + } + + if (!medium) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to attach the following disk/dvd/floppy " + "to the machine: %s, rc=%08x"), + src, (unsigned)rc); + VBOX_UTF16_FREE(mediumFileUtf16); + continue; + } + + rc = gVBoxAPI.UIMedium.GetId(medium, &mediumUUID); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("can't get the uuid of the file to be attached " + "as harddisk/dvd/floppy: %s, rc=%08x"), + src, (unsigned)rc); + VBOX_MEDIUM_RELEASE(medium); + VBOX_UTF16_FREE(mediumFileUtf16); + continue; + } + + if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) { + if (def->disks[i]->src->readonly) { + gVBoxAPI.UIMedium.SetType(medium, MediumType_Immutable); + VIR_DEBUG("setting harddisk to immutable"); + } else if (!def->disks[i]->src->readonly) { + gVBoxAPI.UIMedium.SetType(medium, MediumType_Normal); + VIR_DEBUG("setting harddisk type to normal"); + } + } + + if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_IDE) { + VBOX_UTF8_TO_UTF16("IDE Controller", &storageCtlName); + storageBus = StorageBus_IDE; + } else if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_SATA) { + VBOX_UTF8_TO_UTF16("SATA Controller", &storageCtlName); + storageBus = StorageBus_SATA; + } else if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_SCSI) { + VBOX_UTF8_TO_UTF16("SCSI Controller", &storageCtlName); + storageBus = StorageBus_SCSI; + } else if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_FDC) { + VBOX_UTF8_TO_UTF16("Floppy Controller", &storageCtlName); + storageBus = StorageBus_Floppy; + } + + /* get the device details i.e instance, port and slot */ + if (!vboxGetDeviceDetails(def->disks[i]->dst, + maxPortPerInst, + maxSlotPerPort, + storageBus, + &deviceInst, + &devicePort, + &deviceSlot)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("can't get the port/slot number of " + "harddisk/dvd/floppy to be attached: " + "%s, rc=%08x"), + src, (unsigned)rc); + VBOX_MEDIUM_RELEASE(medium); + vboxIIDUnalloc(&mediumUUID); + VBOX_UTF16_FREE(mediumFileUtf16); + continue; + } + + /* attach the harddisk/dvd/Floppy to the storage controller */ + rc = gVBoxAPI.UIMachine.AttachDevice(machine, + storageCtlName, + devicePort, + deviceSlot, + deviceType, + medium); + + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not attach the file as " + "harddisk/dvd/floppy: %s, rc=%08x"), + src, (unsigned)rc); + } else { + DEBUGIID("Attached HDD/DVD/Floppy with UUID", &mediumUUID); + } + + VBOX_MEDIUM_RELEASE(medium); + vboxIIDUnalloc(&mediumUUID); + VBOX_UTF16_FREE(mediumFileUtf16); + VBOX_UTF16_FREE(storageCtlName); + } + } +} + +static void +vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + /* Here, About the vboxAttachDrives. In fact,there is + * three different implementations. We name it as + * v1, v2 and v3. + * + * The first version(v1) is only used in vbox 2.2 and 3.0, + * v2 is used by 3.1 and 3.2, and v3 is used for later + * vbox versions. In sight of implementation, the v1 is + * totally different with v2 and v3. The v2 shares the same + * outline with v3, meanwhile the API they used has much + * difference. + * + * It seems we have no thing to do with old versions such as + * v1 and v2 when developing new vbox drivers. What's more, + * most of the vbox APIs used in v1 and v2 is incompatible with + * new vbox versions. It is a burden to put these APIs into + * vboxUniformedAPI, I prefer not to do that. + * + * After balancing the code size and the complied code size, + * I put my solution here. The v1 and v2 is a version specified + * code, which only be generated for first four version. The v3 + * will be put in vbox_common.c, it be complied only once, then + * be used by all next vbox drivers. + * + * Check the flag vboxAttachDrivesUseOld can tell you which + * implementation to use. When the flag is set, we need use + * the old version though gVBoxAPI.vboxAttachDrivesOld. It + * will automatically point to v1 or v2 deponds on you version. + * If the flag is clear, just call vboxAttachDrivesNew, which + * is the v3 implementation. + */ + if (gVBoxAPI.vboxAttachDrivesUseOld) + gVBoxAPI.vboxAttachDrivesOld(def, data, machine); + else + vboxAttachDrivesNew(def, data, machine); +} + +static void +vboxAttachSound(virDomainDefPtr def, IMachine *machine) +{ + nsresult rc; + IAudioAdapter *audioAdapter = NULL; + + /* Check if def->nsounds is one as VirtualBox currently supports + * only one sound card + */ + if (def->nsounds != 1) + return; + + gVBoxAPI.UIMachine.GetAudioAdapter(machine, &audioAdapter); + if (!audioAdapter) + return; + + rc = gVBoxAPI.UIAudioAdapter.SetEnabled(audioAdapter, 1); + if (NS_FAILED(rc)) + goto cleanup; + + if (def->sounds[0]->model == VIR_DOMAIN_SOUND_MODEL_SB16) { + gVBoxAPI.UIAudioAdapter.SetAudioController(audioAdapter, + AudioControllerType_SB16); + } else + if (def->sounds[0]->model == VIR_DOMAIN_SOUND_MODEL_AC97) { + gVBoxAPI.UIAudioAdapter.SetAudioController(audioAdapter, + AudioControllerType_AC97); + } + + cleanup: + VBOX_RELEASE(audioAdapter); +} + +static void +vboxAttachNetwork(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + ISystemProperties *systemProperties = NULL; + PRUint32 chipsetType = ChipsetType_Null; + PRUint32 networkAdapterCount = 0; + size_t i = 0; + + if (gVBoxAPI.chipsetType) + gVBoxAPI.UIMachine.GetChipsetType(machine, &chipsetType); + + gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties); + if (systemProperties) { + gVBoxAPI.UISystemProperties.GetMaxNetworkAdapters(systemProperties, chipsetType, + &networkAdapterCount); + VBOX_RELEASE(systemProperties); + } + + VIR_DEBUG("Number of Network Cards to be connected: %zu", def->nnets); + VIR_DEBUG("Number of Network Cards available: %d", networkAdapterCount); + + for (i = 0; (i < def->nnets) && (i < networkAdapterCount); i++) { + INetworkAdapter *adapter = NULL; + PRUint32 adapterType = NetworkAdapterType_Null; + char macaddr[VIR_MAC_STRING_BUFLEN] = {0}; + char macaddrvbox[VIR_MAC_STRING_BUFLEN - 5] = {0}; + PRUnichar *MACAddress = NULL; + + virMacAddrFormat(&def->nets[i]->mac, macaddr); + snprintf(macaddrvbox, VIR_MAC_STRING_BUFLEN - 5, + "%02X%02X%02X%02X%02X%02X", + def->nets[i]->mac.addr[0], + def->nets[i]->mac.addr[1], + def->nets[i]->mac.addr[2], + def->nets[i]->mac.addr[3], + def->nets[i]->mac.addr[4], + def->nets[i]->mac.addr[5]); + macaddrvbox[VIR_MAC_STRING_BUFLEN - 6] = '\0'; + + VIR_DEBUG("NIC(%zu): Type: %d", i, def->nets[i]->type); + VIR_DEBUG("NIC(%zu): Model: %s", i, def->nets[i]->model); + VIR_DEBUG("NIC(%zu): Mac: %s", i, macaddr); + VIR_DEBUG("NIC(%zu): ifname: %s", i, def->nets[i]->ifname); + if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + VIR_DEBUG("NIC(%zu): name: %s", i, def->nets[i]->data.network.name); + } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_INTERNAL) { + VIR_DEBUG("NIC(%zu): name: %s", i, def->nets[i]->data.internal.name); + } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_USER) { + VIR_DEBUG("NIC(%zu): NAT.", i); + } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { + VIR_DEBUG("NIC(%zu): brname: %s", i, def->nets[i]->data.bridge.brname); + VIR_DEBUG("NIC(%zu): script: %s", i, def->nets[i]->script); + VIR_DEBUG("NIC(%zu): ipaddr: %s", i, def->nets[i]->data.bridge.ipaddr); + } + + gVBoxAPI.UIMachine.GetNetworkAdapter(machine, i, &adapter); + if (!adapter) + continue; + + gVBoxAPI.UINetworkAdapter.SetEnabled(adapter, 1); + + if (def->nets[i]->model) { + if (STRCASEEQ(def->nets[i]->model, "Am79C970A")) { + adapterType = NetworkAdapterType_Am79C970A; + } else if (STRCASEEQ(def->nets[i]->model, "Am79C973")) { + adapterType = NetworkAdapterType_Am79C973; + } else if (STRCASEEQ(def->nets[i]->model, "82540EM")) { + adapterType = NetworkAdapterType_I82540EM; + } else if (STRCASEEQ(def->nets[i]->model, "82545EM")) { + adapterType = NetworkAdapterType_I82545EM; + } else if (STRCASEEQ(def->nets[i]->model, "82543GC")) { + adapterType = NetworkAdapterType_I82543GC; + } else if (gVBoxAPI.APIVersion >= 3000051 && + STRCASEEQ(def->nets[i]->model, "virtio")) { + /* Only vbox 3.1 and later support NetworkAdapterType_Virto */ + adapterType = NetworkAdapterType_Virtio; + } + } else { + adapterType = NetworkAdapterType_Am79C973; + } + + gVBoxAPI.UINetworkAdapter.SetAdapterType(adapter, adapterType); + + if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { + PRUnichar *hostInterface = NULL; + /* Bridged Network */ + + gVBoxAPI.UINetworkAdapter.AttachToBridgedInterface(adapter); + + if (def->nets[i]->data.bridge.brname) { + VBOX_UTF8_TO_UTF16(def->nets[i]->data.bridge.brname, + &hostInterface); + gVBoxAPI.UINetworkAdapter.SetBridgedInterface(adapter, hostInterface); + VBOX_UTF16_FREE(hostInterface); + } + } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_INTERNAL) { + PRUnichar *internalNetwork = NULL; + /* Internal Network */ + + gVBoxAPI.UINetworkAdapter.AttachToInternalNetwork(adapter); + + if (def->nets[i]->data.internal.name) { + VBOX_UTF8_TO_UTF16(def->nets[i]->data.internal.name, + &internalNetwork); + gVBoxAPI.UINetworkAdapter.SetInternalNetwork(adapter, internalNetwork); + VBOX_UTF16_FREE(internalNetwork); + } + } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + PRUnichar *hostInterface = NULL; + /* Host Only Networking (currently only vboxnet0 available + * on *nix and mac, on windows you can create and configure + * as many as you want) + */ + gVBoxAPI.UINetworkAdapter.AttachToHostOnlyInterface(adapter); + + if (def->nets[i]->data.network.name) { + VBOX_UTF8_TO_UTF16(def->nets[i]->data.network.name, + &hostInterface); + gVBoxAPI.UINetworkAdapter.SetHostOnlyInterface(adapter, hostInterface); + VBOX_UTF16_FREE(hostInterface); + } + } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_USER) { + /* NAT */ + gVBoxAPI.UINetworkAdapter.AttachToNAT(adapter); + } else { + /* else always default to NAT if we don't understand + * what option is been passed to us + */ + gVBoxAPI.UINetworkAdapter.AttachToNAT(adapter); + } + + VBOX_UTF8_TO_UTF16(macaddrvbox, &MACAddress); + gVBoxAPI.UINetworkAdapter.SetMACAddress(adapter, MACAddress); + VBOX_UTF16_FREE(MACAddress); + } +} + +static void +vboxAttachSerial(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + ISystemProperties *systemProperties = NULL; + PRUint32 serialPortCount = 0; + size_t i = 0; + + gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties); + if (systemProperties) { + gVBoxAPI.UISystemProperties.GetSerialPortCount(systemProperties, + &serialPortCount); + VBOX_RELEASE(systemProperties); + } + + VIR_DEBUG("Number of Serial Ports to be connected: %zu", def->nserials); + VIR_DEBUG("Number of Serial Ports available: %d", serialPortCount); + + for (i = 0; (i < def->nserials) && (i < serialPortCount); i++) { + ISerialPort *serialPort = NULL; + PRUnichar *pathUtf16 = NULL; + + VIR_DEBUG("SerialPort(%zu): Type: %d", i, def->serials[i]->source.type); + VIR_DEBUG("SerialPort(%zu): target.port: %d", i, + def->serials[i]->target.port); + + gVBoxAPI.UIMachine.GetSerialPort(machine, i, &serialPort); + if (!serialPort) + continue; + + gVBoxAPI.UISerialPort.SetEnabled(serialPort, 1); + + if (def->serials[i]->source.data.file.path) { + VBOX_UTF8_TO_UTF16(def->serials[i]->source.data.file.path, + &pathUtf16); + gVBoxAPI.UISerialPort.SetPath(serialPort, pathUtf16); + } + + /* For now hard code the serial ports to COM1 and COM2, + * COM1 (Base Addr: 0x3F8 (decimal: 1016), IRQ: 4) + * COM2 (Base Addr: 0x2F8 (decimal: 760), IRQ: 3) + * TODO: make this more flexible + */ + /* TODO: to improve the libvirt XMl handling so + * that def->serials[i]->target.port shows real port + * and not always start at 0 + */ + if (def->serials[i]->target.port == 0) { + gVBoxAPI.UISerialPort.SetIRQ(serialPort, 4); + gVBoxAPI.UISerialPort.SetIOBase(serialPort, 1016); + VIR_DEBUG(" serialPort-%zu irq: %d, iobase 0x%x, path: %s", + i, 4, 1016, def->serials[i]->source.data.file.path); + } else if (def->serials[i]->target.port == 1) { + gVBoxAPI.UISerialPort.SetIRQ(serialPort, 3); + gVBoxAPI.UISerialPort.SetIOBase(serialPort, 760); + VIR_DEBUG(" serialPort-%zu irq: %d, iobase 0x%x, path: %s", + i, 3, 760, def->serials[i]->source.data.file.path); + } + + if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV) { + gVBoxAPI.UISerialPort.SetHostMode(serialPort, PortMode_HostDevice); + } else if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE) { + gVBoxAPI.UISerialPort.SetHostMode(serialPort, PortMode_HostPipe); + } else if (gVBoxAPI.APIVersion >= 2002051 && + def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE) { + /* PortMode RawFile is used for vbox 3.0 or later */ + gVBoxAPI.UISerialPort.SetHostMode(serialPort, PortMode_RawFile); + } else { + gVBoxAPI.UISerialPort.SetHostMode(serialPort, + PortMode_Disconnected); + } + + VBOX_RELEASE(serialPort); + VBOX_UTF16_FREE(pathUtf16); + } +} + +static void +vboxAttachParallel(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + ISystemProperties *systemProperties = NULL; + PRUint32 parallelPortCount = 0; + size_t i = 0; + + gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties); + if (systemProperties) { + gVBoxAPI.UISystemProperties.GetParallelPortCount(systemProperties, + ¶llelPortCount); + VBOX_RELEASE(systemProperties); + } + + VIR_DEBUG("Number of Parallel Ports to be connected: %zu", def->nparallels); + VIR_DEBUG("Number of Parallel Ports available: %d", parallelPortCount); + for (i = 0; (i < def->nparallels) && (i < parallelPortCount); i++) { + IParallelPort *parallelPort = NULL; + PRUnichar *pathUtf16 = NULL; + + VIR_DEBUG("ParallelPort(%zu): Type: %d", i, def->parallels[i]->source.type); + VIR_DEBUG("ParallelPort(%zu): target.port: %d", i, + def->parallels[i]->target.port); + + gVBoxAPI.UIMachine.GetParallelPort(machine, i, ¶llelPort); + if (!parallelPort) + continue; + + VBOX_UTF8_TO_UTF16(def->parallels[i]->source.data.file.path, &pathUtf16); + + /* For now hard code the parallel ports to + * LPT1 (Base Addr: 0x378 (decimal: 888), IRQ: 7) + * LPT2 (Base Addr: 0x278 (decimal: 632), IRQ: 5) + * TODO: make this more flexible + */ + if ((def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV) || + (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_PTY) || + (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE) || + (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE)) { + gVBoxAPI.UIParallelPort.SetPath(parallelPort, pathUtf16); + if (i == 0) { + gVBoxAPI.UIParallelPort.SetIRQ(parallelPort, 7); + gVBoxAPI.UIParallelPort.SetIOBase(parallelPort, 888); + VIR_DEBUG(" parallePort-%zu irq: %d, iobase 0x%x, path: %s", + i, 7, 888, def->parallels[i]->source.data.file.path); + } else if (i == 1) { + gVBoxAPI.UIParallelPort.SetIRQ(parallelPort, 5); + gVBoxAPI.UIParallelPort.SetIOBase(parallelPort, 632); + VIR_DEBUG(" parallePort-%zu irq: %d, iobase 0x%x, path: %s", + i, 5, 632, def->parallels[i]->source.data.file.path); + } + } + + /* like serial port, parallel port can't be enabled unless + * correct IRQ and IOBase values are specified. + */ + gVBoxAPI.UIParallelPort.SetEnabled(parallelPort, 1); + + VBOX_RELEASE(parallelPort); + VBOX_UTF16_FREE(pathUtf16); + } +} + +static void +vboxAttachVideo(virDomainDefPtr def, IMachine *machine) +{ + if ((def->nvideos == 1) && + (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_VBOX)) { + gVBoxAPI.UIMachine.SetVRAMSize(machine, + VIR_DIV_UP(def->videos[0]->vram, 1024)); + gVBoxAPI.UIMachine.SetMonitorCount(machine, def->videos[0]->heads); + if (def->videos[0]->accel) { + gVBoxAPI.UIMachine.SetAccelerate3DEnabled(machine, + def->videos[0]->accel->support3d); + if (gVBoxAPI.accelerate2DVideo) + gVBoxAPI.UIMachine.SetAccelerate2DVideoEnabled(machine, + def->videos[0]->accel->support2d); + } else { + gVBoxAPI.UIMachine.SetAccelerate3DEnabled(machine, 0); + if (gVBoxAPI.accelerate2DVideo) + gVBoxAPI.UIMachine.SetAccelerate2DVideoEnabled(machine, 0); + } + } +} + +static void +vboxAttachDisplay(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + int vrdpPresent = 0; + int sdlPresent = 0; + int guiPresent = 0; + char *guiDisplay = NULL; + char *sdlDisplay = NULL; + size_t i = 0; + + for (i = 0; i < def->ngraphics; i++) { + IVRDxServer *VRDxServer = NULL; + + if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_RDP) && + (vrdpPresent == 0)) { + + vrdpPresent = 1; + gVBoxAPI.UIMachine.GetVRDxServer(machine, &VRDxServer); + if (VRDxServer) { + const char *listenAddr + = virDomainGraphicsListenGetAddress(def->graphics[i], 0); + + gVBoxAPI.UIVRDxServer.SetEnabled(VRDxServer, PR_TRUE); + VIR_DEBUG("VRDP Support turned ON."); + + gVBoxAPI.UIVRDxServer.SetPorts(data, VRDxServer, def->graphics[i]); + + if (def->graphics[i]->data.rdp.replaceUser) { + gVBoxAPI.UIVRDxServer.SetReuseSingleConnection(VRDxServer, + PR_TRUE); + VIR_DEBUG("VRDP set to reuse single connection"); + } + + if (def->graphics[i]->data.rdp.multiUser) { + gVBoxAPI.UIVRDxServer.SetAllowMultiConnection(VRDxServer, + PR_TRUE); + VIR_DEBUG("VRDP set to allow multiple connection"); + } + + if (listenAddr) { + PRUnichar *netAddressUtf16 = NULL; + + VBOX_UTF8_TO_UTF16(listenAddr, &netAddressUtf16); + gVBoxAPI.UIVRDxServer.SetNetAddress(data, VRDxServer, + netAddressUtf16); + VIR_DEBUG("VRDP listen address is set to: %s", + listenAddr); + + VBOX_UTF16_FREE(netAddressUtf16); + } + + VBOX_RELEASE(VRDxServer); + } + } + + if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP) && + (guiPresent == 0)) { + guiPresent = 1; + if (VIR_STRDUP(guiDisplay, def->graphics[i]->data.desktop.display) < 0) { + /* just don't go to cleanup yet as it is ok to have + * guiDisplay as NULL and we check it below if it + * exist and then only use it there + */ + } + } + + if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) && + (sdlPresent == 0)) { + sdlPresent = 1; + if (VIR_STRDUP(sdlDisplay, def->graphics[i]->data.sdl.display) < 0) { + /* just don't go to cleanup yet as it is ok to have + * sdlDisplay as NULL and we check it below if it + * exist and then only use it there + */ + } + } + } + + if ((vrdpPresent == 1) && (guiPresent == 0) && (sdlPresent == 0)) { + /* store extradata key that frontend is set to vrdp */ + PRUnichar *keyTypeUtf16 = NULL; + PRUnichar *valueTypeUtf16 = NULL; + + VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); + VBOX_UTF8_TO_UTF16("vrdp", &valueTypeUtf16); + + gVBoxAPI.UIMachine.SetExtraData(machine, keyTypeUtf16, valueTypeUtf16); + + VBOX_UTF16_FREE(keyTypeUtf16); + VBOX_UTF16_FREE(valueTypeUtf16); + + } else if ((guiPresent == 0) && (sdlPresent == 1)) { + /* store extradata key that frontend is set to sdl */ + PRUnichar *keyTypeUtf16 = NULL; + PRUnichar *valueTypeUtf16 = NULL; + PRUnichar *keyDislpayUtf16 = NULL; + PRUnichar *valueDisplayUtf16 = NULL; + + VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); + VBOX_UTF8_TO_UTF16("sdl", &valueTypeUtf16); + + gVBoxAPI.UIMachine.SetExtraData(machine, keyTypeUtf16, valueTypeUtf16); + + VBOX_UTF16_FREE(keyTypeUtf16); + VBOX_UTF16_FREE(valueTypeUtf16); + + if (sdlDisplay) { + VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16); + VBOX_UTF8_TO_UTF16(sdlDisplay, &valueDisplayUtf16); + + gVBoxAPI.UIMachine.SetExtraData(machine, keyDislpayUtf16, + valueDisplayUtf16); + + VBOX_UTF16_FREE(keyDislpayUtf16); + VBOX_UTF16_FREE(valueDisplayUtf16); + } + + } else { + /* if all are set then default is gui, with vrdp turned on */ + PRUnichar *keyTypeUtf16 = NULL; + PRUnichar *valueTypeUtf16 = NULL; + PRUnichar *keyDislpayUtf16 = NULL; + PRUnichar *valueDisplayUtf16 = NULL; + + VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); + VBOX_UTF8_TO_UTF16("gui", &valueTypeUtf16); + + gVBoxAPI.UIMachine.SetExtraData(machine, keyTypeUtf16, valueTypeUtf16); + + VBOX_UTF16_FREE(keyTypeUtf16); + VBOX_UTF16_FREE(valueTypeUtf16); + + if (guiDisplay) { + VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16); + VBOX_UTF8_TO_UTF16(guiDisplay, &valueDisplayUtf16); + + gVBoxAPI.UIMachine.SetExtraData(machine, keyDislpayUtf16, + valueDisplayUtf16); + + VBOX_UTF16_FREE(keyDislpayUtf16); + VBOX_UTF16_FREE(valueDisplayUtf16); + } + } + + VIR_FREE(guiDisplay); + VIR_FREE(sdlDisplay); +} + +static void +vboxAttachUSB(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + IUSBCommon *USBCommon = NULL; + size_t i = 0; + bool isUSB = false; + nsresult rc; + + if (def->nhostdevs == 0) + return; + + /* Loop through the devices first and see if you + * have a USB Device, only if you have one then + * start the USB controller else just proceed as + * usual + */ + for (i = 0; i < def->nhostdevs; i++) { + if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + + if (def->hostdevs[i]->source.subsys.type != + VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) + continue; + + if (!def->hostdevs[i]->source.subsys.u.usb.vendor && + !def->hostdevs[i]->source.subsys.u.usb.product) + continue; + + VIR_DEBUG("USB Device detected, VendorId:0x%x, ProductId:0x%x", + def->hostdevs[i]->source.subsys.u.usb.vendor, + def->hostdevs[i]->source.subsys.u.usb.product); + isUSB = true; + break; + } + + if (!isUSB) + return; + + /* First Start the USB Controller and then loop + * to attach USB Devices to it + */ + rc = gVBoxAPI.UIMachine.GetUSBCommon(machine, &USBCommon); + if (NS_FAILED(rc) || !USBCommon) + return; + gVBoxAPI.UIUSBCommon.Enable(USBCommon); + + for (i = 0; i < def->nhostdevs; i++) { + char *filtername = NULL; + PRUnichar *filternameUtf16 = NULL; + IUSBDeviceFilter *filter = NULL; + PRUnichar *vendorIdUtf16 = NULL; + char vendorId[40] = {0}; + PRUnichar *productIdUtf16 = NULL; + char productId[40] = {0}; + + if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + + if (def->hostdevs[i]->source.subsys.type != + VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) + continue; + + /* Zero pad for nice alignment when fewer than 9999 + * devices. + */ + if (virAsprintf(&filtername, "filter%04zu", i) >= 0) { + VBOX_UTF8_TO_UTF16(filtername, &filternameUtf16); + VIR_FREE(filtername); + gVBoxAPI.UIUSBCommon.CreateDeviceFilter(USBCommon, + filternameUtf16, + &filter); + } + VBOX_UTF16_FREE(filternameUtf16); + + if (!filter) + continue; + + if (!def->hostdevs[i]->source.subsys.u.usb.vendor && + !def->hostdevs[i]->source.subsys.u.usb.product) + continue; + + if (def->hostdevs[i]->source.subsys.u.usb.vendor) { + snprintf(vendorId, sizeof(vendorId), "%x", + def->hostdevs[i]->source.subsys.u.usb.vendor); + VBOX_UTF8_TO_UTF16(vendorId, &vendorIdUtf16); + gVBoxAPI.UIUSBDeviceFilter.SetVendorId(filter, vendorIdUtf16); + VBOX_UTF16_FREE(vendorIdUtf16); + } + if (def->hostdevs[i]->source.subsys.u.usb.product) { + snprintf(productId, sizeof(productId), "%x", + def->hostdevs[i]->source.subsys.u.usb.product); + VBOX_UTF8_TO_UTF16(productId, &productIdUtf16); + gVBoxAPI.UIUSBDeviceFilter.SetProductId(filter, + productIdUtf16); + VBOX_UTF16_FREE(productIdUtf16); + } + gVBoxAPI.UIUSBDeviceFilter.SetActive(filter, 1); + gVBoxAPI.UIUSBCommon.InsertDeviceFilter(USBCommon, i, filter); + VBOX_RELEASE(filter); + } + + VBOX_RELEASE(USBCommon); +} + +static void +vboxAttachSharedFolder(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + size_t i; + PRUnichar *nameUtf16; + PRUnichar *hostPathUtf16; + PRBool writable; + + if (def->nfss == 0) + return; + + for (i = 0; i < def->nfss; i++) { + if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT) + continue; + + VBOX_UTF8_TO_UTF16(def->fss[i]->dst, &nameUtf16); + VBOX_UTF8_TO_UTF16(def->fss[i]->src, &hostPathUtf16); + writable = !def->fss[i]->readonly; + + gVBoxAPI.UIMachine.CreateSharedFolder(machine, nameUtf16, hostPathUtf16, + writable, PR_FALSE); + + VBOX_UTF16_FREE(nameUtf16); + VBOX_UTF16_FREE(hostPathUtf16); + } +} + +virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml) +{ + VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL); + IMachine *machine = NULL; + IBIOSSettings *bios = NULL; + vboxIIDUnion mchiid; + virDomainDefPtr def = NULL; + nsresult rc; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + + VBOX_IID_INITIALIZE(&mchiid); + if (!(def = virDomainDefParseString(xml, data->caps, data->xmlopt, + 1 << VIR_DOMAIN_VIRT_VBOX, + VIR_DOMAIN_XML_INACTIVE))) { + goto cleanup; + } + + virUUIDFormat(def->uuid, uuidstr); + + rc = gVBoxAPI.UIVirtualBox.CreateMachine(data, def, &machine, uuidstr); + + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not define a domain, rc=%08x"), (unsigned)rc); + goto cleanup; + } + + rc = gVBoxAPI.UIMachine.SetMemorySize(machine, + VIR_DIV_UP(def->mem.cur_balloon, 1024)); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not set the memory size of the domain to: %llu Kb, " + "rc=%08x"), + def->mem.cur_balloon, (unsigned)rc); + } + + if (def->vcpus != def->maxvcpus) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("current vcpu count must equal maximum")); + } + rc = gVBoxAPI.UIMachine.SetCPUCount(machine, def->maxvcpus); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not set the number of virtual CPUs to: %u, rc=%08x"), + def->maxvcpus, (unsigned)rc); + } + + rc = gVBoxAPI.UIMachine.SetCPUProperty(machine, CPUPropertyType_PAE, + def->features[VIR_DOMAIN_FEATURE_PAE] == + VIR_TRISTATE_SWITCH_ON); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not change PAE status to: %s, rc=%08x"), + (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_TRISTATE_SWITCH_ON) + ? _("Enabled") : _("Disabled"), (unsigned)rc); + } + + gVBoxAPI.UIMachine.GetBIOSSettings(machine, &bios); + if (bios) { + rc = gVBoxAPI.UIBIOSSettings.SetACPIEnabled(bios, + def->features[VIR_DOMAIN_FEATURE_ACPI] == + VIR_TRISTATE_SWITCH_ON); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not change ACPI status to: %s, rc=%08x"), + (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_TRISTATE_SWITCH_ON) + ? _("Enabled") : _("Disabled"), (unsigned)rc); + } + rc = gVBoxAPI.UIBIOSSettings.SetIOAPICEnabled(bios, + def->features[VIR_DOMAIN_FEATURE_APIC] == + VIR_TRISTATE_SWITCH_ON); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not change APIC status to: %s, rc=%08x"), + (def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_TRISTATE_SWITCH_ON) + ? _("Enabled") : _("Disabled"), (unsigned)rc); + } + VBOX_RELEASE(bios); + } + + /* Register the machine before attaching other devices to it */ + rc = gVBoxAPI.UIVirtualBox.RegisterMachine(data->vboxObj, machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not define a domain, rc=%08x"), (unsigned)rc); + goto cleanup; + } + + /* Get the uuid of the machine, currently it is immutable + * object so open a session to it and get it back, so that + * you can make changes to the machine setting + */ + gVBoxAPI.UIMachine.GetId(machine, &mchiid); + gVBoxAPI.UISession.Open(data, &mchiid, machine); + gVBoxAPI.UISession.GetMachine(data->vboxSession, &machine); + + vboxSetBootDeviceOrder(def, data, machine); + vboxAttachDrives(def, data, machine); + vboxAttachSound(def, machine); + vboxAttachNetwork(def, data, machine); + vboxAttachSerial(def, data, machine); + vboxAttachParallel(def, data, machine); + vboxAttachVideo(def, machine); + vboxAttachDisplay(def, data, machine); + vboxAttachUSB(def, data, machine); + vboxAttachSharedFolder(def, data, machine); + + /* Save the machine settings made till now and close the + * session. also free up the mchiid variable used. + */ + rc = gVBoxAPI.UIMachine.SaveSettings(machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed no saving settings, rc=%08x"), (unsigned)rc); + goto cleanup; + } + + gVBoxAPI.UISession.Close(data->vboxSession); + vboxIIDUnalloc(&mchiid); + + ret = virGetDomain(conn, def->name, def->uuid); + VBOX_RELEASE(machine); + + virDomainDefFree(def); + + return ret; + + cleanup: + VBOX_RELEASE(machine); + virDomainDefFree(def); + return NULL; +} + +static void detachDevices_common(vboxGlobalData *data, vboxIIDUnion *iidu) { /* Block for checking if HDD's are attched to VM. diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h index c4147a1..eedd755 100644 --- a/src/vbox/vbox_common.h +++ b/src/vbox/vbox_common.h @@ -158,6 +158,86 @@ struct _vboxArray { # endif /* !WIN32 */ +/* We make the assumption that these enum flags + * are compatible in all vbox API version. + * + * Yes it is, as it has been checked from vbox 2.2 to + * vbox 4.3.3. And this rule MAY NOT stands for new + * vbox versions. + * */ +enum CPUPropertyType +{ + CPUPropertyType_Null = 0, + CPUPropertyType_PAE = 1, + CPUPropertyType_Synthetic = 2, +}; + +enum AudioControllerType +{ + AudioControllerType_AC97 = 0, + AudioControllerType_SB16 = 1 +}; + +enum ChipsetType +{ + ChipsetType_Null = 0, + ChipsetType_PIIX3 = 1, + ChipsetType_ICH9 = 2 +}; + +enum NetworkAdapterType +{ + NetworkAdapterType_Null = 0, + NetworkAdapterType_Am79C970A = 1, + NetworkAdapterType_Am79C973 = 2, + NetworkAdapterType_I82540EM = 3, + NetworkAdapterType_I82543GC = 4, + NetworkAdapterType_I82545EM = 5, + NetworkAdapterType_Virtio = 6 +}; + +enum PortMode +{ + PortMode_Disconnected = 0, + PortMode_HostPipe = 1, + PortMode_HostDevice = 2, + PortMode_RawFile = 3 +}; + +enum DeviceType +{ + DeviceType_Null = 0, + DeviceType_Floppy = 1, + DeviceType_DVD = 2, + DeviceType_HardDisk = 3, + DeviceType_Network = 4, + DeviceType_USB = 5, + DeviceType_SharedFolder = 6 +}; + +enum StorageBus +{ + StorageBus_Null = 0, + StorageBus_IDE = 1, + StorageBus_SATA = 2, + StorageBus_SCSI = 3, + StorageBus_Floppy = 4, + StorageBus_SAS = 5 +}; + +enum AccessMode +{ + AccessMode_ReadOnly = 1, + AccessMode_ReadWrite = 2 +}; + +enum MediumType +{ + MediumType_Normal = 0, + MediumType_Immutable = 1, + MediumType_Writethrough = 2, +}; + /* Simplied definitions in vbox_CAPI_*.h */ typedef void const *PCVBOXXPCOM; @@ -168,5 +248,15 @@ typedef nsISupports IConsole; typedef nsISupports IProgress; typedef nsISupports IMachine; typedef nsISupports ISystemProperties; +typedef nsISupports IBIOSSettings; +typedef nsISupports IAudioAdapter; +typedef nsISupports INetworkAdapter; +typedef nsISupports ISerialPort; +typedef nsISupports IParallelPort; +typedef nsISupports IVRDxServer; +typedef nsISupports IUSBCommon; +typedef nsISupports IUSBDeviceFilter; +typedef nsISupports IMedium; +typedef nsISupports IStorageController; #endif /* VBOX_COMMON_H */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 86c02f1..537616d 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -89,6 +89,19 @@ /* Include this *last* or we'll get the wrong vbox_CAPI_*.h. */ #include "vbox_glue.h" + +#if VBOX_API_VERSION < 4000000 +typedef IVRDPServer IVRDxServer; +#else /* VBOX_API_VERSION >= 4000000 */ +typedef IVRDEServer IVRDxServer; +#endif /* VBOX_API_VERSION >= 4000000 */ + +#if VBOX_API_VERSION < 4003000 +typedef IUSBController IUSBCommon; +#else /* VBOX_API_VERSION >= 4003000 */ +typedef IUSBDeviceFilters IUSBCommon; +#endif /* VBOX_API_VERSION >= 4003000 */ + #include "vbox_uniformed_api.h" #define VIR_FROM_THIS VIR_FROM_VBOX @@ -252,7 +265,6 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL; #endif /* VBOX_API_VERSION >= 4000000 */ -static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml); static int vboxDomainCreate(virDomainPtr dom); #if VBOX_API_VERSION > 2002000 && VBOX_API_VERSION < 4000000 @@ -660,7 +672,9 @@ _vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu, vboxIIDFromArrayItem_v3_x(data, iid, array, idx) # define DEBUGIID(msg, strUtf16) DEBUGPRUnichar(msg, strUtf16) -# if VBOX_API_VERSION >= 3001000 +#endif /* !(VBOX_API_VERSION == 2002000) */ + +#if VBOX_API_VERSION >= 3001000 /** * function to generate the name for medium, @@ -738,6 +752,8 @@ static char *vboxGenerateMediumName(PRUint32 storageBus, * @param deviceSlot Output slot number * */ +# if VBOX_API_VERSION < 4000000 +/* Only 3.x will use this function. */ static bool vboxGetDeviceDetails(const char *deviceName, PRUint32 *aMaxPortPerInst, PRUint32 *aMaxSlotPerPort, @@ -782,6 +798,7 @@ static bool vboxGetDeviceDetails(const char *deviceName, return true; } +# endif /* VBOX_API_VERSION < 4000000 */ /** * function to get the values for max port per @@ -876,9 +893,7 @@ static PRUnichar *PRUnicharFromInt(int n) { return strUtf16; } -# endif /* VBOX_API_VERSION >= 3001000 */ - -#endif /* !(VBOX_API_VERSION == 2002000) */ +#endif /* VBOX_API_VERSION >= 3001000 */ static PRUnichar * vboxSocketFormatAddrUtf16(vboxGlobalData *data, virSocketAddrPtr addr) @@ -3302,67 +3317,14 @@ static int vboxDomainCreate(virDomainPtr dom) return vboxDomainCreateWithFlags(dom, 0); } -static void -vboxSetBootDeviceOrder(virDomainDefPtr def, vboxGlobalData *data, - IMachine *machine) -{ - ISystemProperties *systemProperties = NULL; - PRUint32 maxBootPosition = 0; - size_t i = 0; - - VIR_DEBUG("def->os.type %s", def->os.type); - VIR_DEBUG("def->os.arch %s", virArchToString(def->os.arch)); - VIR_DEBUG("def->os.machine %s", def->os.machine); - VIR_DEBUG("def->os.nBootDevs %zu", def->os.nBootDevs); - VIR_DEBUG("def->os.bootDevs[0] %d", def->os.bootDevs[0]); - VIR_DEBUG("def->os.bootDevs[1] %d", def->os.bootDevs[1]); - VIR_DEBUG("def->os.bootDevs[2] %d", def->os.bootDevs[2]); - VIR_DEBUG("def->os.bootDevs[3] %d", def->os.bootDevs[3]); - VIR_DEBUG("def->os.init %s", def->os.init); - VIR_DEBUG("def->os.kernel %s", def->os.kernel); - VIR_DEBUG("def->os.initrd %s", def->os.initrd); - VIR_DEBUG("def->os.cmdline %s", def->os.cmdline); - VIR_DEBUG("def->os.root %s", def->os.root); - VIR_DEBUG("def->os.loader %s", def->os.loader); - VIR_DEBUG("def->os.bootloader %s", def->os.bootloader); - VIR_DEBUG("def->os.bootloaderArgs %s", def->os.bootloaderArgs); - - data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties); - if (systemProperties) { - systemProperties->vtbl->GetMaxBootPosition(systemProperties, - &maxBootPosition); - VBOX_RELEASE(systemProperties); - systemProperties = NULL; - } - - /* Clear the defaults first */ - for (i = 0; i < maxBootPosition; i++) { - machine->vtbl->SetBootOrder(machine, i+1, DeviceType_Null); - } - - for (i = 0; (i < def->os.nBootDevs) && (i < maxBootPosition); i++) { - PRUint32 device = DeviceType_Null; - - if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_FLOPPY) { - device = DeviceType_Floppy; - } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_CDROM) { - device = DeviceType_DVD; - } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_DISK) { - device = DeviceType_HardDisk; - } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_NET) { - device = DeviceType_Network; - } - machine->vtbl->SetBootOrder(machine, i+1, device); - } -} +#if VBOX_API_VERSION < 3001000 static void -vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +_vboxAttachDrivesOld(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) { size_t i; nsresult rc; -#if VBOX_API_VERSION < 3001000 if (def->ndisks == 0) return; @@ -3599,7 +3561,16 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) } } } -#else /* VBOX_API_VERSION >= 3001000 */ +} + +#elif VBOX_API_VERSION < 4000000 + +static void +_vboxAttachDrivesOld(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +{ + size_t i; + nsresult rc; + PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {}; PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {}; PRUnichar *storageCtlName = NULL; @@ -3675,9 +3646,6 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) PRUnichar *mediumFileUtf16 = NULL; PRUint32 storageBus = StorageBus_Null; PRUint32 deviceType = DeviceType_Null; -# if VBOX_API_VERSION >= 4000000 - PRUint32 accessMode = AccessMode_ReadOnly; -# endif PRInt32 deviceInst = 0; PRInt32 devicePort = 0; PRInt32 deviceSlot = 0; @@ -3686,47 +3654,26 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) { deviceType = DeviceType_HardDisk; -# if VBOX_API_VERSION < 4000000 data->vboxObj->vtbl->FindHardDisk(data->vboxObj, mediumFileUtf16, &medium); -# else - accessMode = AccessMode_ReadWrite; -# endif } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { deviceType = DeviceType_DVD; -# if VBOX_API_VERSION < 4000000 data->vboxObj->vtbl->FindDVDImage(data->vboxObj, mediumFileUtf16, &medium); -# else - accessMode = AccessMode_ReadOnly; -# endif } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { deviceType = DeviceType_Floppy; -# if VBOX_API_VERSION < 4000000 data->vboxObj->vtbl->FindFloppyImage(data->vboxObj, mediumFileUtf16, &medium); -# else - accessMode = AccessMode_ReadWrite; -# endif } else { VBOX_UTF16_FREE(mediumFileUtf16); continue; } -# if VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 - data->vboxObj->vtbl->FindMedium(data->vboxObj, mediumFileUtf16, - deviceType, &medium); -# elif VBOX_API_VERSION >= 4002000 - data->vboxObj->vtbl->OpenMedium(data->vboxObj, mediumFileUtf16, - deviceType, accessMode, PR_FALSE, &medium); -# endif - if (!medium) { PRUnichar *mediumEmpty = NULL; VBOX_UTF8_TO_UTF16("", &mediumEmpty); -# if VBOX_API_VERSION < 4000000 if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) { rc = data->vboxObj->vtbl->OpenHardDisk(data->vboxObj, mediumFileUtf16, @@ -3751,19 +3698,6 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) } else { rc = 0; } -# elif VBOX_API_VERSION == 4000000 - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, - mediumFileUtf16, - deviceType, accessMode, - &medium); -# elif VBOX_API_VERSION >= 4001000 - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, - mediumFileUtf16, - deviceType, accessMode, - false, - &medium); -# endif /* VBOX_API_VERSION >= 4001000 */ - VBOX_UTF16_FREE(mediumEmpty); } @@ -3836,11 +3770,7 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) devicePort, deviceSlot, deviceType, -# if VBOX_API_VERSION < 4000000 mediumUUID); -# else /* VBOX_API_VERSION >= 4000000 */ - medium); -# endif /* VBOX_API_VERSION >= 4000000 */ if (NS_FAILED(rc)) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -3857,1421 +3787,510 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) VBOX_UTF16_FREE(storageCtlName); } } -#endif /* VBOX_API_VERSION >= 3001000 */ } -static void -vboxAttachSound(virDomainDefPtr def, IMachine *machine) -{ - nsresult rc; - - /* Check if def->nsounds is one as VirtualBox currently supports - * only one sound card - */ - if (def->nsounds == 1) { - IAudioAdapter *audioAdapter = NULL; - - machine->vtbl->GetAudioAdapter(machine, &audioAdapter); - if (audioAdapter) { - rc = audioAdapter->vtbl->SetEnabled(audioAdapter, 1); - if (NS_SUCCEEDED(rc)) { - if (def->sounds[0]->model == VIR_DOMAIN_SOUND_MODEL_SB16) { - audioAdapter->vtbl->SetAudioController(audioAdapter, - AudioControllerType_SB16); - } else if (def->sounds[0]->model == VIR_DOMAIN_SOUND_MODEL_AC97) { - audioAdapter->vtbl->SetAudioController(audioAdapter, - AudioControllerType_AC97); - } - } - VBOX_RELEASE(audioAdapter); - } - } -} +#else /* VBOX_API_VERSION >= 4000000 */ static void -vboxAttachNetwork(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +_vboxAttachDrivesOld(virDomainDefPtr def ATTRIBUTE_UNUSED, + vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine ATTRIBUTE_UNUSED) { - ISystemProperties *systemProperties = NULL; -#if VBOX_API_VERSION >= 4001000 - PRUint32 chipsetType = ChipsetType_Null; -#endif /* VBOX_API_VERSION >= 4001000 */ - PRUint32 networkAdapterCount = 0; - size_t i = 0; - -#if VBOX_API_VERSION >= 4001000 - machine->vtbl->GetChipsetType(machine, &chipsetType); -#endif /* VBOX_API_VERSION >= 4001000 */ + vboxUnsupported(); +} - data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties); - if (systemProperties) { -#if VBOX_API_VERSION < 4001000 - systemProperties->vtbl->GetNetworkAdapterCount(systemProperties, - &networkAdapterCount); -#else /* VBOX_API_VERSION >= 4000000 */ - systemProperties->vtbl->GetMaxNetworkAdapters(systemProperties, chipsetType, - &networkAdapterCount); #endif /* VBOX_API_VERSION >= 4000000 */ - VBOX_RELEASE(systemProperties); - systemProperties = NULL; - } - - VIR_DEBUG("Number of Network Cards to be connected: %zu", def->nnets); - VIR_DEBUG("Number of Network Cards available: %d", networkAdapterCount); - - for (i = 0; (i < def->nnets) && (i < networkAdapterCount); i++) { - INetworkAdapter *adapter = NULL; - PRUint32 adapterType = NetworkAdapterType_Null; - char macaddr[VIR_MAC_STRING_BUFLEN] = {0}; - char macaddrvbox[VIR_MAC_STRING_BUFLEN - 5] = {0}; - - virMacAddrFormat(&def->nets[i]->mac, macaddr); - snprintf(macaddrvbox, VIR_MAC_STRING_BUFLEN - 5, - "%02X%02X%02X%02X%02X%02X", - def->nets[i]->mac.addr[0], - def->nets[i]->mac.addr[1], - def->nets[i]->mac.addr[2], - def->nets[i]->mac.addr[3], - def->nets[i]->mac.addr[4], - def->nets[i]->mac.addr[5]); - macaddrvbox[VIR_MAC_STRING_BUFLEN - 6] = '\0'; - - VIR_DEBUG("NIC(%zu): Type: %d", i, def->nets[i]->type); - VIR_DEBUG("NIC(%zu): Model: %s", i, def->nets[i]->model); - VIR_DEBUG("NIC(%zu): Mac: %s", i, macaddr); - VIR_DEBUG("NIC(%zu): ifname: %s", i, def->nets[i]->ifname); - if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) { - VIR_DEBUG("NIC(%zu): name: %s", i, def->nets[i]->data.network.name); - } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_INTERNAL) { - VIR_DEBUG("NIC(%zu): name: %s", i, def->nets[i]->data.internal.name); - } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_USER) { - VIR_DEBUG("NIC(%zu): NAT.", i); - } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { - VIR_DEBUG("NIC(%zu): brname: %s", i, def->nets[i]->data.bridge.brname); - VIR_DEBUG("NIC(%zu): script: %s", i, def->nets[i]->script); - VIR_DEBUG("NIC(%zu): ipaddr: %s", i, def->nets[i]->data.bridge.ipaddr); - } - - machine->vtbl->GetNetworkAdapter(machine, i, &adapter); - if (adapter) { - PRUnichar *MACAddress = NULL; - - adapter->vtbl->SetEnabled(adapter, 1); - - if (def->nets[i]->model) { - if (STRCASEEQ(def->nets[i]->model, "Am79C970A")) { - adapterType = NetworkAdapterType_Am79C970A; - } else if (STRCASEEQ(def->nets[i]->model, "Am79C973")) { - adapterType = NetworkAdapterType_Am79C973; - } else if (STRCASEEQ(def->nets[i]->model, "82540EM")) { - adapterType = NetworkAdapterType_I82540EM; - } else if (STRCASEEQ(def->nets[i]->model, "82545EM")) { - adapterType = NetworkAdapterType_I82545EM; - } else if (STRCASEEQ(def->nets[i]->model, "82543GC")) { - adapterType = NetworkAdapterType_I82543GC; -#if VBOX_API_VERSION >= 3001000 - } else if (STRCASEEQ(def->nets[i]->model, "virtio")) { - adapterType = NetworkAdapterType_Virtio; -#endif /* VBOX_API_VERSION >= 3001000 */ - } - } else { - adapterType = NetworkAdapterType_Am79C973; - } - - adapter->vtbl->SetAdapterType(adapter, adapterType); - - if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { - PRUnichar *hostInterface = NULL; - /* Bridged Network */ - -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->AttachToBridgedInterface(adapter); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Bridged); -#endif /* VBOX_API_VERSION >= 4001000 */ - - if (def->nets[i]->data.bridge.brname) { - VBOX_UTF8_TO_UTF16(def->nets[i]->data.bridge.brname, - &hostInterface); -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->SetHostInterface(adapter, hostInterface); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->SetBridgedInterface(adapter, hostInterface); -#endif /* VBOX_API_VERSION >= 4001000 */ - VBOX_UTF16_FREE(hostInterface); - } - } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_INTERNAL) { - PRUnichar *internalNetwork = NULL; - /* Internal Network */ - -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->AttachToInternalNetwork(adapter); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Internal); -#endif /* VBOX_API_VERSION >= 4001000 */ - - if (def->nets[i]->data.internal.name) { - VBOX_UTF8_TO_UTF16(def->nets[i]->data.internal.name, - &internalNetwork); - adapter->vtbl->SetInternalNetwork(adapter, internalNetwork); - VBOX_UTF16_FREE(internalNetwork); - } - } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) { - PRUnichar *hostInterface = NULL; - /* Host Only Networking (currently only vboxnet0 available - * on *nix and mac, on windows you can create and configure - * as many as you want) - */ -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->AttachToHostOnlyInterface(adapter); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_HostOnly); -#endif /* VBOX_API_VERSION >= 4001000 */ - - if (def->nets[i]->data.network.name) { - VBOX_UTF8_TO_UTF16(def->nets[i]->data.network.name, - &hostInterface); -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->SetHostInterface(adapter, hostInterface); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->SetHostOnlyInterface(adapter, hostInterface); -#endif /* VBOX_API_VERSION >= 4001000 */ - VBOX_UTF16_FREE(hostInterface); - } - } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_USER) { - /* NAT */ -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->AttachToNAT(adapter); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_NAT); -#endif /* VBOX_API_VERSION >= 4001000 */ - } else { - /* else always default to NAT if we don't understand - * what option is been passed to us - */ -#if VBOX_API_VERSION < 4001000 - adapter->vtbl->AttachToNAT(adapter); -#else /* VBOX_API_VERSION >= 4001000 */ - adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_NAT); -#endif /* VBOX_API_VERSION >= 4001000 */ - } - - VBOX_UTF8_TO_UTF16(macaddrvbox, &MACAddress); - adapter->vtbl->SetMACAddress(adapter, MACAddress); - VBOX_UTF16_FREE(MACAddress); - } - } -} -static void -vboxAttachSerial(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +static int +vboxDomainUndefine(virDomainPtr dom) { - ISystemProperties *systemProperties = NULL; - PRUint32 serialPortCount = 0; - size_t i = 0; - - data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties); - if (systemProperties) { - systemProperties->vtbl->GetSerialPortCount(systemProperties, - &serialPortCount); - VBOX_RELEASE(systemProperties); - systemProperties = NULL; - } - - VIR_DEBUG("Number of Serial Ports to be connected: %zu", def->nserials); - VIR_DEBUG("Number of Serial Ports available: %d", serialPortCount); - for (i = 0; (i < def->nserials) && (i < serialPortCount); i++) { - ISerialPort *serialPort = NULL; - - VIR_DEBUG("SerialPort(%zu): Type: %d", i, def->serials[i]->source.type); - VIR_DEBUG("SerialPort(%zu): target.port: %d", i, - def->serials[i]->target.port); - - machine->vtbl->GetSerialPort(machine, i, &serialPort); - if (serialPort) { - PRUnichar *pathUtf16 = NULL; - - serialPort->vtbl->SetEnabled(serialPort, 1); - - if (def->serials[i]->source.data.file.path) { - VBOX_UTF8_TO_UTF16(def->serials[i]->source.data.file.path, - &pathUtf16); - serialPort->vtbl->SetPath(serialPort, pathUtf16); - } - - /* For now hard code the serial ports to COM1 and COM2, - * COM1 (Base Addr: 0x3F8 (decimal: 1016), IRQ: 4) - * COM2 (Base Addr: 0x2F8 (decimal: 760), IRQ: 3) - * TODO: make this more flexible - */ - /* TODO: to improve the libvirt XMl handling so - * that def->serials[i]->target.port shows real port - * and not always start at 0 - */ - if (def->serials[i]->target.port == 0) { - serialPort->vtbl->SetIRQ(serialPort, 4); - serialPort->vtbl->SetIOBase(serialPort, 1016); - VIR_DEBUG(" serialPort-%zu irq: %d, iobase 0x%x, path: %s", - i, 4, 1016, def->serials[i]->source.data.file.path); - } else if (def->serials[i]->target.port == 1) { - serialPort->vtbl->SetIRQ(serialPort, 3); - serialPort->vtbl->SetIOBase(serialPort, 760); - VIR_DEBUG(" serialPort-%zu irq: %d, iobase 0x%x, path: %s", - i, 3, 760, def->serials[i]->source.data.file.path); - } - - if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV) { - serialPort->vtbl->SetHostMode(serialPort, PortMode_HostDevice); - } else if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE) { - serialPort->vtbl->SetHostMode(serialPort, PortMode_HostPipe); -#if VBOX_API_VERSION >= 3000000 - } else if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE) { - serialPort->vtbl->SetHostMode(serialPort, PortMode_RawFile); -#endif /* VBOX_API_VERSION >= 3000000 */ - } else { - serialPort->vtbl->SetHostMode(serialPort, - PortMode_Disconnected); - } - - VBOX_RELEASE(serialPort); - VBOX_UTF16_FREE(pathUtf16); - } - } + return vboxDomainUndefineFlags(dom, 0); } -static void -vboxAttachParallel(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +static int vboxDomainAttachDeviceImpl(virDomainPtr dom, + const char *xml, + int mediaChangeOnly ATTRIBUTE_UNUSED) { - ISystemProperties *systemProperties = NULL; - PRUint32 parallelPortCount = 0; - size_t i = 0; - - data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties); - if (systemProperties) { - systemProperties->vtbl->GetParallelPortCount(systemProperties, - ¶llelPortCount); - VBOX_RELEASE(systemProperties); - systemProperties = NULL; - } - - VIR_DEBUG("Number of Parallel Ports to be connected: %zu", def->nparallels); - VIR_DEBUG("Number of Parallel Ports available: %d", parallelPortCount); - for (i = 0; (i < def->nparallels) && (i < parallelPortCount); i++) { - IParallelPort *parallelPort = NULL; - - VIR_DEBUG("ParallelPort(%zu): Type: %d", i, def->parallels[i]->source.type); - VIR_DEBUG("ParallelPort(%zu): target.port: %d", i, - def->parallels[i]->target.port); - - machine->vtbl->GetParallelPort(machine, i, ¶llelPort); - if (parallelPort) { - PRUnichar *pathUtf16 = NULL; + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IMachine *machine = NULL; + vboxIID iid = VBOX_IID_INITIALIZER; + PRUint32 state = MachineState_Null; + virDomainDefPtr def = NULL; + virDomainDeviceDefPtr dev = NULL; + nsresult rc; - VBOX_UTF8_TO_UTF16(def->parallels[i]->source.data.file.path, &pathUtf16); + if (VIR_ALLOC(def) < 0) + return ret; - /* For now hard code the parallel ports to - * LPT1 (Base Addr: 0x378 (decimal: 888), IRQ: 7) - * LPT2 (Base Addr: 0x278 (decimal: 632), IRQ: 5) - * TODO: make this more flexible - */ - if ((def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV) || - (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_PTY) || - (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE) || - (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE)) { - parallelPort->vtbl->SetPath(parallelPort, pathUtf16); - if (i == 0) { - parallelPort->vtbl->SetIRQ(parallelPort, 7); - parallelPort->vtbl->SetIOBase(parallelPort, 888); - VIR_DEBUG(" parallePort-%zu irq: %d, iobase 0x%x, path: %s", - i, 7, 888, def->parallels[i]->source.data.file.path); - } else if (i == 1) { - parallelPort->vtbl->SetIRQ(parallelPort, 5); - parallelPort->vtbl->SetIOBase(parallelPort, 632); - VIR_DEBUG(" parallePort-%zu irq: %d, iobase 0x%x, path: %s", - i, 5, 632, def->parallels[i]->source.data.file.path); - } - } + if (VIR_STRDUP(def->os.type, "hvm") < 0) + goto cleanup; - /* like serial port, parallel port can't be enabled unless - * correct IRQ and IOBase values are specified. - */ - parallelPort->vtbl->SetEnabled(parallelPort, 1); + dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, + VIR_DOMAIN_XML_INACTIVE); + if (dev == NULL) + goto cleanup; - VBOX_RELEASE(parallelPort); - VBOX_UTF16_FREE(pathUtf16); - } + vboxIIDFromUUID(&iid, dom->uuid); + rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + goto cleanup; } -} -static void -vboxAttachVideo(virDomainDefPtr def, IMachine *machine) -{ - if ((def->nvideos == 1) && - (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_VBOX)) { - machine->vtbl->SetVRAMSize(machine, - VIR_DIV_UP(def->videos[0]->vram, 1024)); - machine->vtbl->SetMonitorCount(machine, def->videos[0]->heads); - if (def->videos[0]->accel) { - machine->vtbl->SetAccelerate3DEnabled(machine, - def->videos[0]->accel->support3d); -#if VBOX_API_VERSION >= 3001000 - machine->vtbl->SetAccelerate2DVideoEnabled(machine, - def->videos[0]->accel->support2d); -#endif /* VBOX_API_VERSION >= 3001000 */ + if (machine) { + machine->vtbl->GetState(machine, &state); + + if ((state == MachineState_Running) || + (state == MachineState_Paused)) { + rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); } else { - machine->vtbl->SetAccelerate3DEnabled(machine, 0); -#if VBOX_API_VERSION >= 3001000 - machine->vtbl->SetAccelerate2DVideoEnabled(machine, 0); -#endif /* VBOX_API_VERSION >= 3001000 */ + rc = VBOX_SESSION_OPEN(iid.value, machine); } - } -} - -static void -vboxAttachDisplay(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) -{ - int vrdpPresent = 0; - int sdlPresent = 0; - int guiPresent = 0; - char *guiDisplay = NULL; - char *sdlDisplay = NULL; - size_t i = 0; - - for (i = 0; i < def->ngraphics; i++) { -#if VBOX_API_VERSION < 4000000 - IVRDPServer *VRDxServer = NULL; -#else /* VBOX_API_VERSION >= 4000000 */ - IVRDEServer *VRDxServer = NULL; -#endif /* VBOX_API_VERSION >= 4000000 */ - - if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_RDP) && - (vrdpPresent == 0)) { + if (NS_SUCCEEDED(rc)) { + rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); + if (NS_SUCCEEDED(rc) && machine) { + if (dev->type == VIR_DOMAIN_DEVICE_DISK) { +#if VBOX_API_VERSION < 3001000 + const char *src = virDomainDiskGetSource(dev->data.disk); + int type = virDomainDiskGetType(dev->data.disk); - vrdpPresent = 1; -#if VBOX_API_VERSION < 4000000 - machine->vtbl->GetVRDPServer(machine, &VRDxServer); -#else /* VBOX_API_VERSION >= 4000000 */ - machine->vtbl->GetVRDEServer(machine, &VRDxServer); -#endif /* VBOX_API_VERSION >= 4000000 */ - if (VRDxServer) { - const char *listenAddr - = virDomainGraphicsListenGetAddress(def->graphics[i], 0); + if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { + if (type == VIR_STORAGE_TYPE_FILE && src) { + IDVDDrive *dvdDrive = NULL; + /* Currently CDROM/DVD Drive is always IDE + * Secondary Master so neglecting the following + * parameter dev->data.disk->bus + */ + machine->vtbl->GetDVDDrive(machine, &dvdDrive); + if (dvdDrive) { + IDVDImage *dvdImage = NULL; + PRUnichar *dvdfileUtf16 = NULL; + vboxIID dvduuid = VBOX_IID_INITIALIZER; + vboxIID dvdemptyuuid = VBOX_IID_INITIALIZER; - VRDxServer->vtbl->SetEnabled(VRDxServer, PR_TRUE); - VIR_DEBUG("VRDP Support turned ON."); + VBOX_UTF8_TO_UTF16(src, &dvdfileUtf16); -#if VBOX_API_VERSION < 3001000 - if (def->graphics[i]->data.rdp.port) { - VRDxServer->vtbl->SetPort(VRDxServer, - def->graphics[i]->data.rdp.port); - VIR_DEBUG("VRDP Port changed to: %d", - def->graphics[i]->data.rdp.port); - } else if (def->graphics[i]->data.rdp.autoport) { - /* Setting the port to 0 will reset its value to - * the default one which is 3389 currently - */ - VRDxServer->vtbl->SetPort(VRDxServer, 0); - VIR_DEBUG("VRDP Port changed to default, which is 3389 currently"); - } -#elif VBOX_API_VERSION < 4000000 /* 3001000 <= VBOX_API_VERSION < 4000000 */ - PRUnichar *portUtf16 = NULL; - portUtf16 = PRUnicharFromInt(def->graphics[i]->data.rdp.port); - VRDxServer->vtbl->SetPorts(VRDxServer, portUtf16); - VBOX_UTF16_FREE(portUtf16); -#else /* VBOX_API_VERSION >= 4000000 */ - PRUnichar *VRDEPortsKey = NULL; - PRUnichar *VRDEPortsValue = NULL; - VBOX_UTF8_TO_UTF16("TCP/Ports", &VRDEPortsKey); - VRDEPortsValue = PRUnicharFromInt(def->graphics[i]->data.rdp.port); - VRDxServer->vtbl->SetVRDEProperty(VRDxServer, VRDEPortsKey, - VRDEPortsValue); - VBOX_UTF16_FREE(VRDEPortsKey); - VBOX_UTF16_FREE(VRDEPortsValue); -#endif /* VBOX_API_VERSION >= 4000000 */ + data->vboxObj->vtbl->FindDVDImage(data->vboxObj, dvdfileUtf16, &dvdImage); + if (!dvdImage) { + data->vboxObj->vtbl->OpenDVDImage(data->vboxObj, dvdfileUtf16, dvdemptyuuid.value, &dvdImage); + } + if (dvdImage) { + rc = dvdImage->vtbl->imedium.GetId((IMedium *)dvdImage, &dvduuid.value); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("can't get the uuid of the file to " + "be attached to cdrom: %s, rc=%08x"), + src, (unsigned)rc); + } else { + /* unmount the previous mounted image */ + dvdDrive->vtbl->Unmount(dvdDrive); + rc = dvdDrive->vtbl->MountImage(dvdDrive, dvduuid.value); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not attach the file to cdrom: %s, rc=%08x"), + src, (unsigned)rc); + } else { + ret = 0; + DEBUGIID("CD/DVD Image UUID:", dvduuid.value); + } + } - if (def->graphics[i]->data.rdp.replaceUser) { - VRDxServer->vtbl->SetReuseSingleConnection(VRDxServer, - PR_TRUE); - VIR_DEBUG("VRDP set to reuse single connection"); - } + VBOX_MEDIUM_RELEASE(dvdImage); + } + vboxIIDUnalloc(&dvduuid); + VBOX_UTF16_FREE(dvdfileUtf16); + VBOX_RELEASE(dvdDrive); + } + } else if (type == VIR_STORAGE_TYPE_BLOCK) { + } + } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { + if (type == VIR_STORAGE_TYPE_FILE && src) { + IFloppyDrive *floppyDrive; + machine->vtbl->GetFloppyDrive(machine, &floppyDrive); + if (floppyDrive) { + rc = floppyDrive->vtbl->SetEnabled(floppyDrive, 1); + if (NS_SUCCEEDED(rc)) { + IFloppyImage *floppyImage = NULL; + PRUnichar *fdfileUtf16 = NULL; + vboxIID fduuid = VBOX_IID_INITIALIZER; + vboxIID fdemptyuuid = VBOX_IID_INITIALIZER; + VBOX_UTF8_TO_UTF16(src, &fdfileUtf16); + rc = data->vboxObj->vtbl->FindFloppyImage(data->vboxObj, + fdfileUtf16, + &floppyImage); - if (def->graphics[i]->data.rdp.multiUser) { - VRDxServer->vtbl->SetAllowMultiConnection(VRDxServer, - PR_TRUE); - VIR_DEBUG("VRDP set to allow multiple connection"); - } + if (!floppyImage) { + data->vboxObj->vtbl->OpenFloppyImage(data->vboxObj, + fdfileUtf16, + fdemptyuuid.value, + &floppyImage); + } - if (listenAddr) { -#if VBOX_API_VERSION >= 4000000 - PRUnichar *netAddressKey = NULL; -#endif - PRUnichar *netAddressUtf16 = NULL; + if (floppyImage) { + rc = floppyImage->vtbl->imedium.GetId((IMedium *)floppyImage, &fduuid.value); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("can't get the uuid of the file to be " + "attached to floppy drive: %s, rc=%08x"), + src, (unsigned)rc); + } else { + rc = floppyDrive->vtbl->MountImage(floppyDrive, fduuid.value); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not attach the file to floppy drive: %s, rc=%08x"), + src, (unsigned)rc); + } else { + ret = 0; + DEBUGIID("attached floppy, UUID:", fduuid.value); + } + } + VBOX_MEDIUM_RELEASE(floppyImage); + } + vboxIIDUnalloc(&fduuid); + VBOX_UTF16_FREE(fdfileUtf16); + } + VBOX_RELEASE(floppyDrive); + } + } else if (type == VIR_STORAGE_TYPE_BLOCK) { + } + } +#else /* VBOX_API_VERSION >= 3001000 */ +#endif /* VBOX_API_VERSION >= 3001000 */ + } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { + } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { + if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { + if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { + } + } + } else if (dev->type == VIR_DOMAIN_DEVICE_FS && + dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) { + PRUnichar *nameUtf16; + PRUnichar *hostPathUtf16; + PRBool writable; + + VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16); + VBOX_UTF8_TO_UTF16(dev->data.fs->src, &hostPathUtf16); + writable = !dev->data.fs->readonly; - VBOX_UTF8_TO_UTF16(listenAddr, &netAddressUtf16); #if VBOX_API_VERSION < 4000000 - VRDxServer->vtbl->SetNetAddress(VRDxServer, - netAddressUtf16); + rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16, + writable); #else /* VBOX_API_VERSION >= 4000000 */ - VBOX_UTF8_TO_UTF16("TCP/Address", &netAddressKey); - VRDxServer->vtbl->SetVRDEProperty(VRDxServer, netAddressKey, - netAddressUtf16); - VBOX_UTF16_FREE(netAddressKey); + rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16, + writable, PR_FALSE); #endif /* VBOX_API_VERSION >= 4000000 */ - VIR_DEBUG("VRDP listen address is set to: %s", - listenAddr); - - VBOX_UTF16_FREE(netAddressUtf16); - } - - VBOX_RELEASE(VRDxServer); - } - } - if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP) && - (guiPresent == 0)) { - guiPresent = 1; - if (VIR_STRDUP(guiDisplay, def->graphics[i]->data.desktop.display) < 0) { - /* just don't go to cleanup yet as it is ok to have - * guiDisplay as NULL and we check it below if it - * exist and then only use it there - */ - } - } + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not attach shared folder '%s', rc=%08x"), + dev->data.fs->dst, (unsigned)rc); + } else { + ret = 0; + } - if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) && - (sdlPresent == 0)) { - sdlPresent = 1; - if (VIR_STRDUP(sdlDisplay, def->graphics[i]->data.sdl.display) < 0) { - /* just don't go to cleanup yet as it is ok to have - * sdlDisplay as NULL and we check it below if it - * exist and then only use it there - */ + VBOX_UTF16_FREE(nameUtf16); + VBOX_UTF16_FREE(hostPathUtf16); + } + machine->vtbl->SaveSettings(machine); + VBOX_RELEASE(machine); } + VBOX_SESSION_CLOSE(); } } - if ((vrdpPresent == 1) && (guiPresent == 0) && (sdlPresent == 0)) { - /* store extradata key that frontend is set to vrdp */ - PRUnichar *keyTypeUtf16 = NULL; - PRUnichar *valueTypeUtf16 = NULL; - - VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); - VBOX_UTF8_TO_UTF16("vrdp", &valueTypeUtf16); - - machine->vtbl->SetExtraData(machine, keyTypeUtf16, valueTypeUtf16); - - VBOX_UTF16_FREE(keyTypeUtf16); - VBOX_UTF16_FREE(valueTypeUtf16); - - } else if ((guiPresent == 0) && (sdlPresent == 1)) { - /* store extradata key that frontend is set to sdl */ - PRUnichar *keyTypeUtf16 = NULL; - PRUnichar *valueTypeUtf16 = NULL; - PRUnichar *keyDislpayUtf16 = NULL; - PRUnichar *valueDisplayUtf16 = NULL; - - VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); - VBOX_UTF8_TO_UTF16("sdl", &valueTypeUtf16); - - machine->vtbl->SetExtraData(machine, keyTypeUtf16, valueTypeUtf16); - - VBOX_UTF16_FREE(keyTypeUtf16); - VBOX_UTF16_FREE(valueTypeUtf16); - - if (sdlDisplay) { - VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16); - VBOX_UTF8_TO_UTF16(sdlDisplay, &valueDisplayUtf16); - - machine->vtbl->SetExtraData(machine, keyDislpayUtf16, - valueDisplayUtf16); - - VBOX_UTF16_FREE(keyDislpayUtf16); - VBOX_UTF16_FREE(valueDisplayUtf16); - } - - } else { - /* if all are set then default is gui, with vrdp turned on */ - PRUnichar *keyTypeUtf16 = NULL; - PRUnichar *valueTypeUtf16 = NULL; - PRUnichar *keyDislpayUtf16 = NULL; - PRUnichar *valueDisplayUtf16 = NULL; + cleanup: + vboxIIDUnalloc(&iid); + virDomainDefFree(def); + virDomainDeviceDefFree(dev); + return ret; +} - VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16); - VBOX_UTF8_TO_UTF16("gui", &valueTypeUtf16); +static int vboxDomainAttachDevice(virDomainPtr dom, const char *xml) +{ + return vboxDomainAttachDeviceImpl(dom, xml, 0); +} - machine->vtbl->SetExtraData(machine, keyTypeUtf16, valueTypeUtf16); +static int +vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) +{ + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); - VBOX_UTF16_FREE(keyTypeUtf16); - VBOX_UTF16_FREE(valueTypeUtf16); + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify the persistent configuration of a domain")); + return -1; + } - if (guiDisplay) { - VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16); - VBOX_UTF8_TO_UTF16(guiDisplay, &valueDisplayUtf16); + return vboxDomainAttachDeviceImpl(dom, xml, 0); +} - machine->vtbl->SetExtraData(machine, keyDislpayUtf16, - valueDisplayUtf16); +static int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) +{ + virCheckFlags(VIR_DOMAIN_AFFECT_CURRENT | + VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); - VBOX_UTF16_FREE(keyDislpayUtf16); - VBOX_UTF16_FREE(valueDisplayUtf16); - } + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify the persistent configuration of a domain")); + return -1; } - VIR_FREE(guiDisplay); - VIR_FREE(sdlDisplay); + return vboxDomainAttachDeviceImpl(dom, xml, 1); } -static void -vboxAttachUSB(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +static int vboxDomainDetachDevice(virDomainPtr dom, const char *xml) { -#if VBOX_API_VERSION < 4003000 - IUSBController *USBController = NULL; -#else - IUSBDeviceFilters *USBDeviceFilters = NULL; -#endif - size_t i = 0; - bool isUSB = false; - - if (def->nhostdevs == 0) - return; + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IMachine *machine = NULL; + vboxIID iid = VBOX_IID_INITIALIZER; + PRUint32 state = MachineState_Null; + virDomainDefPtr def = NULL; + virDomainDeviceDefPtr dev = NULL; + nsresult rc; - /* Loop through the devices first and see if you - * have a USB Device, only if you have one then - * start the USB controller else just proceed as - * usual - */ - for (i = 0; i < def->nhostdevs; i++) { - if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; + if (VIR_ALLOC(def) < 0) + return ret; - if (def->hostdevs[i]->source.subsys.type != - VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) - continue; + if (VIR_STRDUP(def->os.type, "hvm") < 0) + goto cleanup; - if (!def->hostdevs[i]->source.subsys.u.usb.vendor && - !def->hostdevs[i]->source.subsys.u.usb.product) - continue; + dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, + VIR_DOMAIN_XML_INACTIVE); + if (dev == NULL) + goto cleanup; - VIR_DEBUG("USB Device detected, VendorId:0x%x, ProductId:0x%x", - def->hostdevs[i]->source.subsys.u.usb.vendor, - def->hostdevs[i]->source.subsys.u.usb.product); - isUSB = true; - break; + vboxIIDFromUUID(&iid, dom->uuid); + rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + goto cleanup; } - if (!isUSB) - return; - -#if VBOX_API_VERSION < 4003000 - /* First Start the USB Controller and then loop - * to attach USB Devices to it - */ - machine->vtbl->GetUSBController(machine, &USBController); - - if (!USBController) - return; + if (machine) { + machine->vtbl->GetState(machine, &state); - USBController->vtbl->SetEnabled(USBController, 1); -# if VBOX_API_VERSION < 4002000 - USBController->vtbl->SetEnabledEhci(USBController, 1); -# else - USBController->vtbl->SetEnabledEHCI(USBController, 1); -# endif -#else - machine->vtbl->GetUSBDeviceFilters(machine, &USBDeviceFilters); + if ((state == MachineState_Running) || + (state == MachineState_Paused)) { + rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); + } else { + rc = VBOX_SESSION_OPEN(iid.value, machine); + } - if (!USBDeviceFilters) - return; -#endif + if (NS_SUCCEEDED(rc)) { + rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); + if (NS_SUCCEEDED(rc) && machine) { + if (dev->type == VIR_DOMAIN_DEVICE_DISK) { +#if VBOX_API_VERSION < 3001000 + int type = virDomainDiskGetType(dev->data.disk); - for (i = 0; i < def->nhostdevs; i++) { - char *filtername = NULL; - PRUnichar *filternameUtf16 = NULL; - IUSBDeviceFilter *filter = NULL; - PRUnichar *vendorIdUtf16 = NULL; - char vendorId[40] = {0}; - PRUnichar *productIdUtf16 = NULL; - char productId[40] = {0}; - - if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; + if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { + if (type == VIR_STORAGE_TYPE_FILE) { + IDVDDrive *dvdDrive = NULL; + /* Currently CDROM/DVD Drive is always IDE + * Secondary Master so neglecting the following + * parameter dev->data.disk->bus + */ + machine->vtbl->GetDVDDrive(machine, &dvdDrive); + if (dvdDrive) { + rc = dvdDrive->vtbl->Unmount(dvdDrive); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not de-attach the mounted ISO, rc=%08x"), + (unsigned)rc); + } else { + ret = 0; + } + VBOX_RELEASE(dvdDrive); + } + } else if (type == VIR_STORAGE_TYPE_BLOCK) { + } + } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { + if (type == VIR_STORAGE_TYPE_FILE) { + IFloppyDrive *floppyDrive; + machine->vtbl->GetFloppyDrive(machine, &floppyDrive); + if (floppyDrive) { + PRBool enabled = PR_FALSE; - if (def->hostdevs[i]->source.subsys.type != - VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) - continue; + floppyDrive->vtbl->GetEnabled(floppyDrive, &enabled); + if (enabled) { + rc = floppyDrive->vtbl->Unmount(floppyDrive); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not attach the file " + "to floppy drive, rc=%08x"), + (unsigned)rc); + } else { + ret = 0; + } + } else { + /* If you are here means floppy drive is already unmounted + * so don't flag error, just say everything is fine and quit + */ + ret = 0; + } + VBOX_RELEASE(floppyDrive); + } + } else if (type == VIR_STORAGE_TYPE_BLOCK) { + } + } +#else /* VBOX_API_VERSION >= 3001000 */ +#endif /* VBOX_API_VERSION >= 3001000 */ + } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { + } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { + if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { + if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { + } + } + } else if (dev->type == VIR_DOMAIN_DEVICE_FS && + dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) { + PRUnichar *nameUtf16; - /* Zero pad for nice alignment when fewer than 9999 - * devices. - */ - if (virAsprintf(&filtername, "filter%04zu", i) >= 0) { - VBOX_UTF8_TO_UTF16(filtername, &filternameUtf16); - VIR_FREE(filtername); -#if VBOX_API_VERSION < 4003000 - USBController->vtbl->CreateDeviceFilter(USBController, - filternameUtf16, - &filter); -#else - USBDeviceFilters->vtbl->CreateDeviceFilter(USBDeviceFilters, - filternameUtf16, - &filter); -#endif - } - VBOX_UTF16_FREE(filternameUtf16); + VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16); - if (!filter) - continue; + rc = machine->vtbl->RemoveSharedFolder(machine, nameUtf16); - if (!def->hostdevs[i]->source.subsys.u.usb.vendor && - !def->hostdevs[i]->source.subsys.u.usb.product) - continue; + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("could not detach shared folder '%s', rc=%08x"), + dev->data.fs->dst, (unsigned)rc); + } else { + ret = 0; + } - if (def->hostdevs[i]->source.subsys.u.usb.vendor) { - snprintf(vendorId, sizeof(vendorId), "%x", - def->hostdevs[i]->source.subsys.u.usb.vendor); - VBOX_UTF8_TO_UTF16(vendorId, &vendorIdUtf16); - filter->vtbl->SetVendorId(filter, vendorIdUtf16); - VBOX_UTF16_FREE(vendorIdUtf16); - } - if (def->hostdevs[i]->source.subsys.u.usb.product) { - snprintf(productId, sizeof(productId), "%x", - def->hostdevs[i]->source.subsys.u.usb.product); - VBOX_UTF8_TO_UTF16(productId, &productIdUtf16); - filter->vtbl->SetProductId(filter, - productIdUtf16); - VBOX_UTF16_FREE(productIdUtf16); - } - filter->vtbl->SetActive(filter, 1); -#if VBOX_API_VERSION < 4003000 - USBController->vtbl->InsertDeviceFilter(USBController, - i, - filter); -#else - USBDeviceFilters->vtbl->InsertDeviceFilter(USBDeviceFilters, - i, - filter); -#endif - VBOX_RELEASE(filter); + VBOX_UTF16_FREE(nameUtf16); + } + machine->vtbl->SaveSettings(machine); + VBOX_RELEASE(machine); + } + VBOX_SESSION_CLOSE(); + } } -#if VBOX_API_VERSION < 4003000 - VBOX_RELEASE(USBController); -#else - VBOX_RELEASE(USBDeviceFilters); -#endif + cleanup: + vboxIIDUnalloc(&iid); + virDomainDefFree(def); + virDomainDeviceDefFree(dev); + return ret; } -static void -vboxAttachSharedFolder(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine) +static int +vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags) { - size_t i; - PRUnichar *nameUtf16; - PRUnichar *hostPathUtf16; - PRBool writable; - - if (def->nfss == 0) - return; - - for (i = 0; i < def->nfss; i++) { - if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT) - continue; - - VBOX_UTF8_TO_UTF16(def->fss[i]->dst, &nameUtf16); - VBOX_UTF8_TO_UTF16(def->fss[i]->src, &hostPathUtf16); - writable = !def->fss[i]->readonly; - -#if VBOX_API_VERSION < 4000000 - machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16, - writable); -#else /* VBOX_API_VERSION >= 4000000 */ - machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16, - writable, PR_FALSE); -#endif /* VBOX_API_VERSION >= 4000000 */ + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); - VBOX_UTF16_FREE(nameUtf16); - VBOX_UTF16_FREE(hostPathUtf16); + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot modify the persistent configuration of a domain")); + return -1; } + + return vboxDomainDetachDevice(dom, xml); } -static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml) +static int +vboxDomainSnapshotGetAll(virDomainPtr dom, + IMachine *machine, + ISnapshot ***snapshots) { - VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL); - IMachine *machine = NULL; - IBIOSSettings *bios = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - vboxIID mchiid = VBOX_IID_INITIALIZER; - virDomainDefPtr def = NULL; - PRUnichar *machineNameUtf16 = NULL; -#if VBOX_API_VERSION >= 3002000 && VBOX_API_VERSION < 4002000 - PRBool override = PR_FALSE; -#endif + vboxIID empty = VBOX_IID_INITIALIZER; + ISnapshot **list = NULL; + PRUint32 count; nsresult rc; - char uuidstr[VIR_UUID_STRING_BUFLEN]; -#if VBOX_API_VERSION >= 4002000 - const char *flagsUUIDPrefix = "UUID="; - const char *flagsForceOverwrite = "forceOverwrite=0"; - const char *flagsSeparator = ","; - char createFlags[strlen(flagsUUIDPrefix) + VIR_UUID_STRING_BUFLEN + strlen(flagsSeparator) + strlen(flagsForceOverwrite) + 1]; - PRUnichar *createFlagsUtf16 = NULL; -#endif - - if (!(def = virDomainDefParseString(xml, data->caps, data->xmlopt, - 1 << VIR_DOMAIN_VIRT_VBOX, - VIR_DOMAIN_XML_INACTIVE))) { - goto cleanup; - } - - VBOX_UTF8_TO_UTF16(def->name, &machineNameUtf16); - vboxIIDFromUUID(&iid, def->uuid); - virUUIDFormat(def->uuid, uuidstr); - -#if VBOX_API_VERSION < 3002000 - rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, - machineNameUtf16, - NULL, - NULL, - iid.value, - &machine); -#elif VBOX_API_VERSION < 4000000 /* 3002000 <= VBOX_API_VERSION < 4000000 */ - rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, - machineNameUtf16, - NULL, - NULL, - iid.value, - override, - &machine); -#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 - rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, - NULL, - machineNameUtf16, - NULL, - iid.value, - override, - &machine); -#else /* VBOX_API_VERSION >= 4002000 */ - snprintf(createFlags, sizeof(createFlags), "%s%s%s%s", - flagsUUIDPrefix, - uuidstr, - flagsSeparator, - flagsForceOverwrite - ); - VBOX_UTF8_TO_UTF16(createFlags, &createFlagsUtf16); - rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, - NULL, - machineNameUtf16, - 0, - nsnull, - nsnull, - createFlagsUtf16, - &machine); -#endif /* VBOX_API_VERSION >= 4002000 */ - VBOX_UTF16_FREE(machineNameUtf16); + unsigned int next; + unsigned int top; + rc = machine->vtbl->GetSnapshotCount(machine, &count); if (NS_FAILED(rc)) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not define a domain, rc=%08x"), (unsigned)rc); - goto cleanup; + _("could not get snapshot count for domain %s"), + dom->name); + goto error; } - rc = machine->vtbl->SetMemorySize(machine, - VIR_DIV_UP(def->mem.cur_balloon, 1024)); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not set the memory size of the domain to: %llu Kb, " - "rc=%08x"), - def->mem.cur_balloon, (unsigned)rc); - } + if (count == 0) + goto out; - if (def->vcpus != def->maxvcpus) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("current vcpu count must equal maximum")); - } - rc = machine->vtbl->SetCPUCount(machine, def->maxvcpus); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not set the number of virtual CPUs to: %u, rc=%08x"), - def->maxvcpus, (unsigned)rc); - } + if (VIR_ALLOC_N(list, count) < 0) + goto error; -#if VBOX_API_VERSION < 3001000 - rc = machine->vtbl->SetPAEEnabled(machine, - def->features[VIR_DOMAIN_FEATURE_PAE] == - VIR_TRISTATE_SWITCH_ON); -#elif VBOX_API_VERSION == 3001000 - rc = machine->vtbl->SetCpuProperty(machine, CpuPropertyType_PAE, - def->features[VIR_DOMAIN_FEATURE_PAE] == - VIR_TRISTATE_SWITCH_ON); -#elif VBOX_API_VERSION >= 3002000 - rc = machine->vtbl->SetCPUProperty(machine, CPUPropertyType_PAE, - def->features[VIR_DOMAIN_FEATURE_PAE] == - VIR_TRISTATE_SWITCH_ON); -#endif - if (NS_FAILED(rc)) { +#if VBOX_API_VERSION < 4000000 + rc = machine->vtbl->GetSnapshot(machine, empty.value, list); +#else /* VBOX_API_VERSION >= 4000000 */ + rc = machine->vtbl->FindSnapshot(machine, empty.value, list); +#endif /* VBOX_API_VERSION >= 4000000 */ + if (NS_FAILED(rc) || !list[0]) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not change PAE status to: %s, rc=%08x"), - (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_TRISTATE_SWITCH_ON) - ? _("Enabled") : _("Disabled"), (unsigned)rc); + _("could not get root snapshot for domain %s"), + dom->name); + goto error; } - machine->vtbl->GetBIOSSettings(machine, &bios); - if (bios) { - rc = bios->vtbl->SetACPIEnabled(bios, - def->features[VIR_DOMAIN_FEATURE_ACPI] == - VIR_TRISTATE_SWITCH_ON); - if (NS_FAILED(rc)) { + /* BFS walk through snapshot tree */ + top = 1; + for (next = 0; next < count; next++) { + vboxArray children = VBOX_ARRAY_INITIALIZER; + size_t i; + + if (!list[next]) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not change ACPI status to: %s, rc=%08x"), - (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_TRISTATE_SWITCH_ON) - ? _("Enabled") : _("Disabled"), (unsigned)rc); + _("unexpected number of snapshots < %u"), count); + goto error; } - rc = bios->vtbl->SetIOAPICEnabled(bios, - def->features[VIR_DOMAIN_FEATURE_APIC] == - VIR_TRISTATE_SWITCH_ON); + + rc = vboxArrayGet(&children, list[next], + list[next]->vtbl->GetChildren); if (NS_FAILED(rc)) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not change APIC status to: %s, rc=%08x"), - (def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_TRISTATE_SWITCH_ON) - ? _("Enabled") : _("Disabled"), (unsigned)rc); + "%s", _("could not get children snapshots")); + goto error; } - VBOX_RELEASE(bios); - } - - /* Register the machine before attaching other devices to it */ - rc = data->vboxObj->vtbl->RegisterMachine(data->vboxObj, machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not define a domain, rc=%08x"), (unsigned)rc); - goto cleanup; + for (i = 0; i < children.count; i++) { + ISnapshot *child = children.items[i]; + if (!child) + continue; + if (top == count) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected number of snapshots > %u"), count); + vboxArrayRelease(&children); + goto error; + } + VBOX_ADDREF(child); + list[top++] = child; + } + vboxArrayRelease(&children); } - /* Get the uuid of the machine, currently it is immutable - * object so open a session to it and get it back, so that - * you can make changes to the machine setting - */ - machine->vtbl->GetId(machine, &mchiid.value); - VBOX_SESSION_OPEN(mchiid.value, machine); - data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); - - vboxSetBootDeviceOrder(def, data, machine); - vboxAttachDrives(def, data, machine); - vboxAttachSound(def, machine); - vboxAttachNetwork(def, data, machine); - vboxAttachSerial(def, data, machine); - vboxAttachParallel(def, data, machine); - vboxAttachVideo(def, machine); - vboxAttachDisplay(def, data, machine); - vboxAttachUSB(def, data, machine); - vboxAttachSharedFolder(def, data, machine); - - /* Save the machine settings made till now and close the - * session. also free up the mchiid variable used. - */ - rc = machine->vtbl->SaveSettings(machine); - VBOX_SESSION_CLOSE(); - vboxIIDUnalloc(&mchiid); - - ret = virGetDomain(conn, def->name, def->uuid); - VBOX_RELEASE(machine); - - vboxIIDUnalloc(&iid); - virDomainDefFree(def); + out: + *snapshots = list; + return count; - return ret; + error: + if (list) { + for (next = 0; next < count; next++) + VBOX_RELEASE(list[next]); + } + VIR_FREE(list); - cleanup: - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - virDomainDefFree(def); - return NULL; + return -1; } -static int -vboxDomainUndefine(virDomainPtr dom) +static ISnapshot * +vboxDomainSnapshotGet(vboxGlobalData *data, + virDomainPtr dom, + IMachine *machine, + const char *name) { - return vboxDomainUndefineFlags(dom, 0); -} - -static int vboxDomainAttachDeviceImpl(virDomainPtr dom, - const char *xml, - int mediaChangeOnly ATTRIBUTE_UNUSED) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IMachine *machine = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - PRUint32 state = MachineState_Null; - virDomainDefPtr def = NULL; - virDomainDeviceDefPtr dev = NULL; - nsresult rc; - - if (VIR_ALLOC(def) < 0) - return ret; - - if (VIR_STRDUP(def->os.type, "hvm") < 0) - goto cleanup; - - dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, - VIR_DOMAIN_XML_INACTIVE); - if (dev == NULL) - goto cleanup; - - vboxIIDFromUUID(&iid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching uuid")); - goto cleanup; - } - - if (machine) { - machine->vtbl->GetState(machine, &state); - - if ((state == MachineState_Running) || - (state == MachineState_Paused)) { - rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); - } else { - rc = VBOX_SESSION_OPEN(iid.value, machine); - } - if (NS_SUCCEEDED(rc)) { - rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); - if (NS_SUCCEEDED(rc) && machine) { - if (dev->type == VIR_DOMAIN_DEVICE_DISK) { -#if VBOX_API_VERSION < 3001000 - const char *src = virDomainDiskGetSource(dev->data.disk); - int type = virDomainDiskGetType(dev->data.disk); - - if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { - if (type == VIR_STORAGE_TYPE_FILE && src) { - IDVDDrive *dvdDrive = NULL; - /* Currently CDROM/DVD Drive is always IDE - * Secondary Master so neglecting the following - * parameter dev->data.disk->bus - */ - machine->vtbl->GetDVDDrive(machine, &dvdDrive); - if (dvdDrive) { - IDVDImage *dvdImage = NULL; - PRUnichar *dvdfileUtf16 = NULL; - vboxIID dvduuid = VBOX_IID_INITIALIZER; - vboxIID dvdemptyuuid = VBOX_IID_INITIALIZER; - - VBOX_UTF8_TO_UTF16(src, &dvdfileUtf16); - - data->vboxObj->vtbl->FindDVDImage(data->vboxObj, dvdfileUtf16, &dvdImage); - if (!dvdImage) { - data->vboxObj->vtbl->OpenDVDImage(data->vboxObj, dvdfileUtf16, dvdemptyuuid.value, &dvdImage); - } - if (dvdImage) { - rc = dvdImage->vtbl->imedium.GetId((IMedium *)dvdImage, &dvduuid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("can't get the uuid of the file to " - "be attached to cdrom: %s, rc=%08x"), - src, (unsigned)rc); - } else { - /* unmount the previous mounted image */ - dvdDrive->vtbl->Unmount(dvdDrive); - rc = dvdDrive->vtbl->MountImage(dvdDrive, dvduuid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not attach the file to cdrom: %s, rc=%08x"), - src, (unsigned)rc); - } else { - ret = 0; - DEBUGIID("CD/DVD Image UUID:", dvduuid.value); - } - } - - VBOX_MEDIUM_RELEASE(dvdImage); - } - vboxIIDUnalloc(&dvduuid); - VBOX_UTF16_FREE(dvdfileUtf16); - VBOX_RELEASE(dvdDrive); - } - } else if (type == VIR_STORAGE_TYPE_BLOCK) { - } - } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { - if (type == VIR_STORAGE_TYPE_FILE && src) { - IFloppyDrive *floppyDrive; - machine->vtbl->GetFloppyDrive(machine, &floppyDrive); - if (floppyDrive) { - rc = floppyDrive->vtbl->SetEnabled(floppyDrive, 1); - if (NS_SUCCEEDED(rc)) { - IFloppyImage *floppyImage = NULL; - PRUnichar *fdfileUtf16 = NULL; - vboxIID fduuid = VBOX_IID_INITIALIZER; - vboxIID fdemptyuuid = VBOX_IID_INITIALIZER; - VBOX_UTF8_TO_UTF16(src, &fdfileUtf16); - rc = data->vboxObj->vtbl->FindFloppyImage(data->vboxObj, - fdfileUtf16, - &floppyImage); - - if (!floppyImage) { - data->vboxObj->vtbl->OpenFloppyImage(data->vboxObj, - fdfileUtf16, - fdemptyuuid.value, - &floppyImage); - } - - if (floppyImage) { - rc = floppyImage->vtbl->imedium.GetId((IMedium *)floppyImage, &fduuid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("can't get the uuid of the file to be " - "attached to floppy drive: %s, rc=%08x"), - src, (unsigned)rc); - } else { - rc = floppyDrive->vtbl->MountImage(floppyDrive, fduuid.value); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not attach the file to floppy drive: %s, rc=%08x"), - src, (unsigned)rc); - } else { - ret = 0; - DEBUGIID("attached floppy, UUID:", fduuid.value); - } - } - VBOX_MEDIUM_RELEASE(floppyImage); - } - vboxIIDUnalloc(&fduuid); - VBOX_UTF16_FREE(fdfileUtf16); - } - VBOX_RELEASE(floppyDrive); - } - } else if (type == VIR_STORAGE_TYPE_BLOCK) { - } - } -#else /* VBOX_API_VERSION >= 3001000 */ -#endif /* VBOX_API_VERSION >= 3001000 */ - } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { - } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { - if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { - if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { - } - } - } else if (dev->type == VIR_DOMAIN_DEVICE_FS && - dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) { - PRUnichar *nameUtf16; - PRUnichar *hostPathUtf16; - PRBool writable; - - VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16); - VBOX_UTF8_TO_UTF16(dev->data.fs->src, &hostPathUtf16); - writable = !dev->data.fs->readonly; - -#if VBOX_API_VERSION < 4000000 - rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16, - writable); -#else /* VBOX_API_VERSION >= 4000000 */ - rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16, - writable, PR_FALSE); -#endif /* VBOX_API_VERSION >= 4000000 */ - - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not attach shared folder '%s', rc=%08x"), - dev->data.fs->dst, (unsigned)rc); - } else { - ret = 0; - } - - VBOX_UTF16_FREE(nameUtf16); - VBOX_UTF16_FREE(hostPathUtf16); - } - machine->vtbl->SaveSettings(machine); - VBOX_RELEASE(machine); - } - VBOX_SESSION_CLOSE(); - } - } - - cleanup: - vboxIIDUnalloc(&iid); - virDomainDefFree(def); - virDomainDeviceDefFree(dev); - return ret; -} - -static int vboxDomainAttachDevice(virDomainPtr dom, const char *xml) -{ - return vboxDomainAttachDeviceImpl(dom, xml, 0); -} - -static int -vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) -{ - virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); - - if (flags & VIR_DOMAIN_AFFECT_CONFIG) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return vboxDomainAttachDeviceImpl(dom, xml, 0); -} - -static int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) -{ - virCheckFlags(VIR_DOMAIN_AFFECT_CURRENT | - VIR_DOMAIN_AFFECT_LIVE | - VIR_DOMAIN_AFFECT_CONFIG, -1); - - if (flags & VIR_DOMAIN_AFFECT_CONFIG) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return vboxDomainAttachDeviceImpl(dom, xml, 1); -} - -static int vboxDomainDetachDevice(virDomainPtr dom, const char *xml) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IMachine *machine = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - PRUint32 state = MachineState_Null; - virDomainDefPtr def = NULL; - virDomainDeviceDefPtr dev = NULL; - nsresult rc; - - if (VIR_ALLOC(def) < 0) - return ret; - - if (VIR_STRDUP(def->os.type, "hvm") < 0) - goto cleanup; - - dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt, - VIR_DOMAIN_XML_INACTIVE); - if (dev == NULL) - goto cleanup; - - vboxIIDFromUUID(&iid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching uuid")); - goto cleanup; - } - - if (machine) { - machine->vtbl->GetState(machine, &state); - - if ((state == MachineState_Running) || - (state == MachineState_Paused)) { - rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); - } else { - rc = VBOX_SESSION_OPEN(iid.value, machine); - } - - if (NS_SUCCEEDED(rc)) { - rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); - if (NS_SUCCEEDED(rc) && machine) { - if (dev->type == VIR_DOMAIN_DEVICE_DISK) { -#if VBOX_API_VERSION < 3001000 - int type = virDomainDiskGetType(dev->data.disk); - - if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { - if (type == VIR_STORAGE_TYPE_FILE) { - IDVDDrive *dvdDrive = NULL; - /* Currently CDROM/DVD Drive is always IDE - * Secondary Master so neglecting the following - * parameter dev->data.disk->bus - */ - machine->vtbl->GetDVDDrive(machine, &dvdDrive); - if (dvdDrive) { - rc = dvdDrive->vtbl->Unmount(dvdDrive); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not de-attach the mounted ISO, rc=%08x"), - (unsigned)rc); - } else { - ret = 0; - } - VBOX_RELEASE(dvdDrive); - } - } else if (type == VIR_STORAGE_TYPE_BLOCK) { - } - } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { - if (type == VIR_STORAGE_TYPE_FILE) { - IFloppyDrive *floppyDrive; - machine->vtbl->GetFloppyDrive(machine, &floppyDrive); - if (floppyDrive) { - PRBool enabled = PR_FALSE; - - floppyDrive->vtbl->GetEnabled(floppyDrive, &enabled); - if (enabled) { - rc = floppyDrive->vtbl->Unmount(floppyDrive); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not attach the file " - "to floppy drive, rc=%08x"), - (unsigned)rc); - } else { - ret = 0; - } - } else { - /* If you are here means floppy drive is already unmounted - * so don't flag error, just say everything is fine and quit - */ - ret = 0; - } - VBOX_RELEASE(floppyDrive); - } - } else if (type == VIR_STORAGE_TYPE_BLOCK) { - } - } -#else /* VBOX_API_VERSION >= 3001000 */ -#endif /* VBOX_API_VERSION >= 3001000 */ - } else if (dev->type == VIR_DOMAIN_DEVICE_NET) { - } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { - if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { - if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { - } - } - } else if (dev->type == VIR_DOMAIN_DEVICE_FS && - dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) { - PRUnichar *nameUtf16; - - VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16); - - rc = machine->vtbl->RemoveSharedFolder(machine, nameUtf16); - - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not detach shared folder '%s', rc=%08x"), - dev->data.fs->dst, (unsigned)rc); - } else { - ret = 0; - } - - VBOX_UTF16_FREE(nameUtf16); - } - machine->vtbl->SaveSettings(machine); - VBOX_RELEASE(machine); - } - VBOX_SESSION_CLOSE(); - } - } - - cleanup: - vboxIIDUnalloc(&iid); - virDomainDefFree(def); - virDomainDeviceDefFree(dev); - return ret; -} - -static int -vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, - unsigned int flags) -{ - virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); - - if (flags & VIR_DOMAIN_AFFECT_CONFIG) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("cannot modify the persistent configuration of a domain")); - return -1; - } - - return vboxDomainDetachDevice(dom, xml); -} - -static int -vboxDomainSnapshotGetAll(virDomainPtr dom, - IMachine *machine, - ISnapshot ***snapshots) -{ - vboxIID empty = VBOX_IID_INITIALIZER; - ISnapshot **list = NULL; - PRUint32 count; - nsresult rc; - unsigned int next; - unsigned int top; - - rc = machine->vtbl->GetSnapshotCount(machine, &count); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get snapshot count for domain %s"), - dom->name); - goto error; - } - - if (count == 0) - goto out; - - if (VIR_ALLOC_N(list, count) < 0) - goto error; - -#if VBOX_API_VERSION < 4000000 - rc = machine->vtbl->GetSnapshot(machine, empty.value, list); -#else /* VBOX_API_VERSION >= 4000000 */ - rc = machine->vtbl->FindSnapshot(machine, empty.value, list); -#endif /* VBOX_API_VERSION >= 4000000 */ - if (NS_FAILED(rc) || !list[0]) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not get root snapshot for domain %s"), - dom->name); - goto error; - } - - /* BFS walk through snapshot tree */ - top = 1; - for (next = 0; next < count; next++) { - vboxArray children = VBOX_ARRAY_INITIALIZER; - size_t i; - - if (!list[next]) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unexpected number of snapshots < %u"), count); - goto error; - } - - rc = vboxArrayGet(&children, list[next], - list[next]->vtbl->GetChildren); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("could not get children snapshots")); - goto error; - } - for (i = 0; i < children.count; i++) { - ISnapshot *child = children.items[i]; - if (!child) - continue; - if (top == count) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unexpected number of snapshots > %u"), count); - vboxArrayRelease(&children); - goto error; - } - VBOX_ADDREF(child); - list[top++] = child; - } - vboxArrayRelease(&children); - } - - out: - *snapshots = list; - return count; - - error: - if (list) { - for (next = 0; next < count; next++) - VBOX_RELEASE(list[next]); - } - VIR_FREE(list); - - return -1; -} - -static ISnapshot * -vboxDomainSnapshotGet(vboxGlobalData *data, - virDomainPtr dom, - IMachine *machine, - const char *name) -{ - ISnapshot **snapshots = NULL; - ISnapshot *snapshot = NULL; - nsresult rc; - int count = 0; - size_t i; + ISnapshot **snapshots = NULL; + ISnapshot *snapshot = NULL; + nsresult rc; + int count = 0; + size_t i; if ((count = vboxDomainSnapshotGetAll(dom, machine, &snapshots)) < 0) goto cleanup; @@ -9801,22 +8820,265 @@ vboxStorageVolLookupByName(virStoragePoolPtr pool, const char *name) return ret; } -static virStorageVolPtr -vboxStorageVolLookupByKey(virConnectPtr conn, const char *key) +static virStorageVolPtr +vboxStorageVolLookupByKey(virConnectPtr conn, const char *key) +{ + VBOX_OBJECT_CHECK(conn, virStorageVolPtr, NULL); + vboxIID hddIID = VBOX_IID_INITIALIZER; + unsigned char uuid[VIR_UUID_BUFLEN]; + IHardDisk *hardDisk = NULL; + nsresult rc; + + if (!key) + return ret; + + if (virUUIDParse(key, uuid) < 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("Could not parse UUID from '%s'"), key); + return NULL; + } + + vboxIIDFromUUID(&hddIID, uuid); +#if VBOX_API_VERSION < 4000000 + rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk); +#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 + rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value, + DeviceType_HardDisk, &hardDisk); +#else + rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value, + DeviceType_HardDisk, AccessMode_ReadWrite, + PR_FALSE, &hardDisk); +#endif /* VBOX_API_VERSION >= 4000000 */ + if (NS_SUCCEEDED(rc)) { + PRUint32 hddstate; + + VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); + if (hddstate != MediaState_Inaccessible) { + PRUnichar *hddNameUtf16 = NULL; + char *hddNameUtf8 = NULL; + + VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &hddNameUtf16); + VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8); + + if (hddNameUtf8) { + if (vboxConnectNumOfStoragePools(conn) == 1) { + ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key, + NULL, NULL); + VIR_DEBUG("Storage Volume Pool: %s", "default-pool"); + } else { + /* TODO: currently only one default pool and thus + * nothing here, change it when pools are supported + */ + } + + VIR_DEBUG("Storage Volume Name: %s", key); + VIR_DEBUG("Storage Volume key : %s", hddNameUtf8); + + VBOX_UTF8_FREE(hddNameUtf8); + VBOX_UTF16_FREE(hddNameUtf16); + } + } + + VBOX_MEDIUM_RELEASE(hardDisk); + } + + vboxIIDUnalloc(&hddIID); + return ret; +} + +static virStorageVolPtr +vboxStorageVolLookupByPath(virConnectPtr conn, const char *path) +{ + VBOX_OBJECT_CHECK(conn, virStorageVolPtr, NULL); + PRUnichar *hddPathUtf16 = NULL; + IHardDisk *hardDisk = NULL; + nsresult rc; + + if (!path) + return ret; + + VBOX_UTF8_TO_UTF16(path, &hddPathUtf16); + + if (!hddPathUtf16) + return ret; + +#if VBOX_API_VERSION < 4000000 + rc = data->vboxObj->vtbl->FindHardDisk(data->vboxObj, hddPathUtf16, &hardDisk); +#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 + rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddPathUtf16, + DeviceType_HardDisk, &hardDisk); +#else + rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddPathUtf16, + DeviceType_HardDisk, AccessMode_ReadWrite, + PR_FALSE, &hardDisk); +#endif /* VBOX_API_VERSION >= 4000000 */ + if (NS_SUCCEEDED(rc)) { + PRUint32 hddstate; + + VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); + if (hddstate != MediaState_Inaccessible) { + PRUnichar *hddNameUtf16 = NULL; + char *hddNameUtf8 = NULL; + + VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &hddNameUtf16); + + if (hddNameUtf16) { + VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8); + VBOX_UTF16_FREE(hddNameUtf16); + } + + if (hddNameUtf8) { + vboxIID hddIID = VBOX_IID_INITIALIZER; + unsigned char uuid[VIR_UUID_BUFLEN]; + char key[VIR_UUID_STRING_BUFLEN] = ""; + + rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value); + if (NS_SUCCEEDED(rc)) { + vboxIIDToUUID(&hddIID, uuid); + virUUIDFormat(uuid, key); + + /* TODO: currently only one default pool and thus + * the check below, change it when pools are supported + */ + if (vboxConnectNumOfStoragePools(conn) == 1) + ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key, + NULL, NULL); + + VIR_DEBUG("Storage Volume Pool: %s", "default-pool"); + VIR_DEBUG("Storage Volume Name: %s", hddNameUtf8); + VIR_DEBUG("Storage Volume key : %s", key); + } + + vboxIIDUnalloc(&hddIID); + } + + VBOX_UTF8_FREE(hddNameUtf8); + } + + VBOX_MEDIUM_RELEASE(hardDisk); + } + + VBOX_UTF16_FREE(hddPathUtf16); + + return ret; +} + +static virStorageVolPtr vboxStorageVolCreateXML(virStoragePoolPtr pool, + const char *xml, + unsigned int flags) +{ + VBOX_OBJECT_CHECK(pool->conn, virStorageVolPtr, NULL); + virStorageVolDefPtr def = NULL; + PRUnichar *hddFormatUtf16 = NULL; + PRUnichar *hddNameUtf16 = NULL; + virStoragePoolDef poolDef; + nsresult rc; + + virCheckFlags(0, NULL); + + /* since there is currently one default pool now + * and virStorageVolDefFormat() just checks it type + * so just assign it for now, change the behaviour + * when vbox supports pools. + */ + memset(&poolDef, 0, sizeof(poolDef)); + poolDef.type = VIR_STORAGE_POOL_DIR; + + if ((def = virStorageVolDefParseString(&poolDef, xml)) == NULL) + goto cleanup; + + if (!def->name || + (def->type != VIR_STORAGE_VOL_FILE)) + goto cleanup; + + /* For now only the vmdk, vpc and vdi type harddisk + * variants can be created. For historical reason, we default to vdi */ + if (def->target.format == VIR_STORAGE_FILE_VMDK) { + VBOX_UTF8_TO_UTF16("VMDK", &hddFormatUtf16); + } else if (def->target.format == VIR_STORAGE_FILE_VPC) { + VBOX_UTF8_TO_UTF16("VHD", &hddFormatUtf16); + } else { + VBOX_UTF8_TO_UTF16("VDI", &hddFormatUtf16); + } + + VBOX_UTF8_TO_UTF16(def->name, &hddNameUtf16); + + if (hddFormatUtf16 && hddNameUtf16) { + IHardDisk *hardDisk = NULL; + + rc = data->vboxObj->vtbl->CreateHardDisk(data->vboxObj, hddFormatUtf16, hddNameUtf16, &hardDisk); + if (NS_SUCCEEDED(rc)) { + IProgress *progress = NULL; + PRUint64 logicalSize = VIR_DIV_UP(def->target.capacity, + 1024 * 1024); + PRUint32 variant = HardDiskVariant_Standard; + + if (def->target.capacity == def->target.allocation) + variant = HardDiskVariant_Fixed; + +#if VBOX_API_VERSION < 4003000 + rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, variant, &progress); +#else + rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, 1, &variant, &progress); +#endif + if (NS_SUCCEEDED(rc) && progress) { +#if VBOX_API_VERSION == 2002000 + nsresult resultCode; +#else + PRInt32 resultCode; +#endif + + progress->vtbl->WaitForCompletion(progress, -1); + progress->vtbl->GetResultCode(progress, &resultCode); + + if (NS_SUCCEEDED(resultCode)) { + vboxIID hddIID = VBOX_IID_INITIALIZER; + unsigned char uuid[VIR_UUID_BUFLEN]; + char key[VIR_UUID_STRING_BUFLEN] = ""; + + rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value); + if (NS_SUCCEEDED(rc)) { + vboxIIDToUUID(&hddIID, uuid); + virUUIDFormat(uuid, key); + + ret = virGetStorageVol(pool->conn, pool->name, def->name, key, + NULL, NULL); + } + + vboxIIDUnalloc(&hddIID); + } + + VBOX_RELEASE(progress); + } + } + } + + VBOX_UTF16_FREE(hddFormatUtf16); + VBOX_UTF16_FREE(hddNameUtf16); + + cleanup: + virStorageVolDefFree(def); + return ret; +} + +static int vboxStorageVolDelete(virStorageVolPtr vol, + unsigned int flags) { - VBOX_OBJECT_CHECK(conn, virStorageVolPtr, NULL); + VBOX_OBJECT_CHECK(vol->conn, int, -1); vboxIID hddIID = VBOX_IID_INITIALIZER; unsigned char uuid[VIR_UUID_BUFLEN]; IHardDisk *hardDisk = NULL; + int deregister = 0; nsresult rc; + size_t i = 0; + size_t j = 0; - if (!key) - return ret; + virCheckFlags(0, -1); - if (virUUIDParse(key, uuid) < 0) { + if (virUUIDParse(vol->key, uuid) < 0) { virReportError(VIR_ERR_INVALID_ARG, - _("Could not parse UUID from '%s'"), key); - return NULL; + _("Could not parse UUID from '%s'"), vol->key); + return -1; } vboxIIDFromUUID(&hddIID, uuid); @@ -9835,28 +9097,134 @@ vboxStorageVolLookupByKey(virConnectPtr conn, const char *key) VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); if (hddstate != MediaState_Inaccessible) { - PRUnichar *hddNameUtf16 = NULL; - char *hddNameUtf8 = NULL; + PRUint32 machineIdsSize = 0; + vboxArray machineIds = VBOX_ARRAY_INITIALIZER; - VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &hddNameUtf16); - VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8); +#if VBOX_API_VERSION < 3001000 + vboxArrayGet(&machineIds, hardDisk, hardDisk->vtbl->imedium.GetMachineIds); +#else /* VBOX_API_VERSION >= 3001000 */ + vboxArrayGet(&machineIds, hardDisk, hardDisk->vtbl->GetMachineIds); +#endif /* VBOX_API_VERSION >= 3001000 */ - if (hddNameUtf8) { - if (vboxConnectNumOfStoragePools(conn) == 1) { - ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key, - NULL, NULL); - VIR_DEBUG("Storage Volume Pool: %s", "default-pool"); - } else { - /* TODO: currently only one default pool and thus - * nothing here, change it when pools are supported - */ +#if VBOX_API_VERSION == 2002000 && defined WIN32 + /* VirtualBox 2.2 on Windows represents IIDs as GUIDs and the + * machineIds array contains direct instances of the GUID struct + * instead of pointers to the actual struct instances. But there + * is no 128bit width simple item type for a SafeArray to fit a + * GUID in. The largest simple type it 64bit width and VirtualBox + * uses two of this 64bit items to represents one GUID. Therefore, + * we divide the size of the SafeArray by two, to compensate for + * this workaround in VirtualBox */ + machineIds.count /= 2; +#endif /* VBOX_API_VERSION >= 2002000 */ + + machineIdsSize = machineIds.count; + + for (i = 0; i < machineIds.count; i++) { + IMachine *machine = NULL; + vboxIID machineId = VBOX_IID_INITIALIZER; + + vboxIIDFromArrayItem(&machineId, &machineIds, i); + +#if VBOX_API_VERSION >= 4000000 + rc = VBOX_OBJECT_GET_MACHINE(machineId.value, &machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + break; } +#endif - VIR_DEBUG("Storage Volume Name: %s", key); - VIR_DEBUG("Storage Volume key : %s", hddNameUtf8); + rc = VBOX_SESSION_OPEN(machineId.value, machine); - VBOX_UTF8_FREE(hddNameUtf8); - VBOX_UTF16_FREE(hddNameUtf16); + if (NS_SUCCEEDED(rc)) { + + rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); + if (NS_SUCCEEDED(rc)) { + vboxArray hddAttachments = VBOX_ARRAY_INITIALIZER; + +#if VBOX_API_VERSION < 3001000 + vboxArrayGet(&hddAttachments, machine, + machine->vtbl->GetHardDiskAttachments); +#else /* VBOX_API_VERSION >= 3001000 */ + vboxArrayGet(&hddAttachments, machine, + machine->vtbl->GetMediumAttachments); +#endif /* VBOX_API_VERSION >= 3001000 */ + for (j = 0; j < hddAttachments.count; j++) { + IHardDiskAttachment *hddAttachment = hddAttachments.items[j]; + + if (hddAttachment) { + IHardDisk *hdd = NULL; + +#if VBOX_API_VERSION < 3001000 + rc = hddAttachment->vtbl->GetHardDisk(hddAttachment, &hdd); +#else /* VBOX_API_VERSION >= 3001000 */ + rc = hddAttachment->vtbl->GetMedium(hddAttachment, &hdd); +#endif /* VBOX_API_VERSION >= 3001000 */ + if (NS_SUCCEEDED(rc) && hdd) { + vboxIID iid = VBOX_IID_INITIALIZER; + + rc = VBOX_MEDIUM_FUNC_ARG1(hdd, GetId, &iid.value); + if (NS_SUCCEEDED(rc)) { + + DEBUGIID("HardDisk (to delete) UUID", hddIID.value); + DEBUGIID("HardDisk (currently processing) UUID", iid.value); + + if (vboxIIDIsEqual(&hddIID, &iid)) { + PRUnichar *controller = NULL; + PRInt32 port = 0; + PRInt32 device = 0; + + DEBUGIID("Found HardDisk to delete, UUID", hddIID.value); + + hddAttachment->vtbl->GetController(hddAttachment, &controller); + hddAttachment->vtbl->GetPort(hddAttachment, &port); + hddAttachment->vtbl->GetDevice(hddAttachment, &device); + +#if VBOX_API_VERSION < 3001000 + rc = machine->vtbl->DetachHardDisk(machine, controller, port, device); +#else /* VBOX_API_VERSION >= 3001000 */ + rc = machine->vtbl->DetachDevice(machine, controller, port, device); +#endif /* VBOX_API_VERSION >= 3001000 */ + if (NS_SUCCEEDED(rc)) { + rc = machine->vtbl->SaveSettings(machine); + VIR_DEBUG("saving machine settings"); + } + + if (NS_SUCCEEDED(rc)) { + deregister++; + VIR_DEBUG("deregistering hdd:%d", deregister); + } + + VBOX_UTF16_FREE(controller); + } + vboxIIDUnalloc(&iid); + } + VBOX_MEDIUM_RELEASE(hdd); + } + } + } + vboxArrayRelease(&hddAttachments); + VBOX_RELEASE(machine); + } + VBOX_SESSION_CLOSE(); + } + + vboxIIDUnalloc(&machineId); + } + + vboxArrayUnalloc(&machineIds); + + if (machineIdsSize == 0 || machineIdsSize == deregister) { + IProgress *progress = NULL; + rc = hardDisk->vtbl->DeleteStorage(hardDisk, &progress); + + if (NS_SUCCEEDED(rc) && progress) { + progress->vtbl->WaitForCompletion(progress, -1); + VBOX_RELEASE(progress); + DEBUGIID("HardDisk deleted, UUID", hddIID.value); + ret = 0; + } } } @@ -9864,32 +9232,36 @@ vboxStorageVolLookupByKey(virConnectPtr conn, const char *key) } vboxIIDUnalloc(&hddIID); + return ret; } -static virStorageVolPtr -vboxStorageVolLookupByPath(virConnectPtr conn, const char *path) +static int +vboxStorageVolGetInfo(virStorageVolPtr vol, virStorageVolInfoPtr info) { - VBOX_OBJECT_CHECK(conn, virStorageVolPtr, NULL); - PRUnichar *hddPathUtf16 = NULL; - IHardDisk *hardDisk = NULL; + VBOX_OBJECT_CHECK(vol->conn, int, -1); + IHardDisk *hardDisk = NULL; + unsigned char uuid[VIR_UUID_BUFLEN]; + vboxIID hddIID = VBOX_IID_INITIALIZER; nsresult rc; - if (!path) + if (!info) return ret; - VBOX_UTF8_TO_UTF16(path, &hddPathUtf16); - - if (!hddPathUtf16) + if (virUUIDParse(vol->key, uuid) < 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("Could not parse UUID from '%s'"), vol->key); return ret; + } + vboxIIDFromUUID(&hddIID, uuid); #if VBOX_API_VERSION < 4000000 - rc = data->vboxObj->vtbl->FindHardDisk(data->vboxObj, hddPathUtf16, &hardDisk); + rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk); #elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 - rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddPathUtf16, + rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value, DeviceType_HardDisk, &hardDisk); #else - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddPathUtf16, + rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value, DeviceType_HardDisk, AccessMode_ReadWrite, PR_FALSE, &hardDisk); #endif /* VBOX_API_VERSION >= 4000000 */ @@ -9898,168 +9270,169 @@ vboxStorageVolLookupByPath(virConnectPtr conn, const char *path) VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); if (hddstate != MediaState_Inaccessible) { - PRUnichar *hddNameUtf16 = NULL; - char *hddNameUtf8 = NULL; - - VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &hddNameUtf16); - - if (hddNameUtf16) { - VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8); - VBOX_UTF16_FREE(hddNameUtf16); - } - - if (hddNameUtf8) { - vboxIID hddIID = VBOX_IID_INITIALIZER; - unsigned char uuid[VIR_UUID_BUFLEN]; - char key[VIR_UUID_STRING_BUFLEN] = ""; +#if VBOX_API_VERSION < 4000000 + PRUint64 hddLogicalSize; + PRUint64 hddActualSize; +#else /* VBOX_API_VERSION >= 4000000 */ + PRInt64 hddLogicalSize; + PRInt64 hddActualSize; +#endif /* VBOX_API_VERSION >= 4000000 */ - rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value); - if (NS_SUCCEEDED(rc)) { - vboxIIDToUUID(&hddIID, uuid); - virUUIDFormat(uuid, key); + info->type = VIR_STORAGE_VOL_FILE; - /* TODO: currently only one default pool and thus - * the check below, change it when pools are supported - */ - if (vboxConnectNumOfStoragePools(conn) == 1) - ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key, - NULL, NULL); + hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize); +#if VBOX_API_VERSION < 4000000 + info->capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */ +#else /* VBOX_API_VERSION >= 4000000 */ + info->capacity = hddLogicalSize; +#endif /* VBOX_API_VERSION >= 4000000 */ - VIR_DEBUG("Storage Volume Pool: %s", "default-pool"); - VIR_DEBUG("Storage Volume Name: %s", hddNameUtf8); - VIR_DEBUG("Storage Volume key : %s", key); - } + VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetSize, &hddActualSize); + info->allocation = hddActualSize; - vboxIIDUnalloc(&hddIID); - } + ret = 0; - VBOX_UTF8_FREE(hddNameUtf8); + VIR_DEBUG("Storage Volume Name: %s", vol->name); + VIR_DEBUG("Storage Volume Type: %s", info->type == VIR_STORAGE_VOL_BLOCK ? "Block" : "File"); + VIR_DEBUG("Storage Volume Capacity: %llu", info->capacity); + VIR_DEBUG("Storage Volume Allocation: %llu", info->allocation); } VBOX_MEDIUM_RELEASE(hardDisk); } - VBOX_UTF16_FREE(hddPathUtf16); + vboxIIDUnalloc(&hddIID); return ret; } -static virStorageVolPtr vboxStorageVolCreateXML(virStoragePoolPtr pool, - const char *xml, - unsigned int flags) +static char *vboxStorageVolGetXMLDesc(virStorageVolPtr vol, unsigned int flags) { - VBOX_OBJECT_CHECK(pool->conn, virStorageVolPtr, NULL); - virStorageVolDefPtr def = NULL; - PRUnichar *hddFormatUtf16 = NULL; - PRUnichar *hddNameUtf16 = NULL; - virStoragePoolDef poolDef; + VBOX_OBJECT_CHECK(vol->conn, char *, NULL); + IHardDisk *hardDisk = NULL; + unsigned char uuid[VIR_UUID_BUFLEN]; + vboxIID hddIID = VBOX_IID_INITIALIZER; + virStoragePoolDef pool; + virStorageVolDef def; + int defOk = 0; nsresult rc; virCheckFlags(0, NULL); - /* since there is currently one default pool now - * and virStorageVolDefFormat() just checks it type - * so just assign it for now, change the behaviour - * when vbox supports pools. - */ - memset(&poolDef, 0, sizeof(poolDef)); - poolDef.type = VIR_STORAGE_POOL_DIR; + memset(&pool, 0, sizeof(pool)); + memset(&def, 0, sizeof(def)); - if ((def = virStorageVolDefParseString(&poolDef, xml)) == NULL) - goto cleanup; + if (virUUIDParse(vol->key, uuid) < 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("Could not parse UUID from '%s'"), vol->key); + return ret; + } - if (!def->name || - (def->type != VIR_STORAGE_VOL_FILE)) - goto cleanup; + vboxIIDFromUUID(&hddIID, uuid); +#if VBOX_API_VERSION < 4000000 + rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk); +#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 + rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value, + DeviceType_HardDisk, &hardDisk); +#else + rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value, + DeviceType_HardDisk, AccessMode_ReadWrite, + PR_FALSE, &hardDisk); +#endif /* VBOX_API_VERSION >= 4000000 */ + if (NS_SUCCEEDED(rc)) { + PRUint32 hddstate; - /* For now only the vmdk, vpc and vdi type harddisk - * variants can be created. For historical reason, we default to vdi */ - if (def->target.format == VIR_STORAGE_FILE_VMDK) { - VBOX_UTF8_TO_UTF16("VMDK", &hddFormatUtf16); - } else if (def->target.format == VIR_STORAGE_FILE_VPC) { - VBOX_UTF8_TO_UTF16("VHD", &hddFormatUtf16); - } else { - VBOX_UTF8_TO_UTF16("VDI", &hddFormatUtf16); - } + VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); + if (NS_SUCCEEDED(rc) && hddstate != MediaState_Inaccessible) { + PRUnichar *hddFormatUtf16 = NULL; +#if VBOX_API_VERSION < 4000000 + PRUint64 hddLogicalSize; + PRUint64 hddActualSize; +#else /* VBOX_API_VERSION >= 4000000 */ + PRInt64 hddLogicalSize; + PRInt64 hddActualSize; +#endif /* VBOX_API_VERSION >= 4000000 */ - VBOX_UTF8_TO_UTF16(def->name, &hddNameUtf16); + /* since there is currently one default pool now + * and virStorageVolDefFormat() just checks it type + * so just assign it for now, change the behaviour + * when vbox supports pools. + */ + pool.type = VIR_STORAGE_POOL_DIR; + def.type = VIR_STORAGE_VOL_FILE; + defOk = 1; - if (hddFormatUtf16 && hddNameUtf16) { - IHardDisk *hardDisk = NULL; + rc = hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize); + if (NS_SUCCEEDED(rc) && defOk) { +#if VBOX_API_VERSION < 4000000 + def.target.capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */ +#else /* VBOX_API_VERSION >= 4000000 */ + def.target.capacity = hddLogicalSize; +#endif /* VBOX_API_VERSION >= 4000000 */ + } else + defOk = 0; - rc = data->vboxObj->vtbl->CreateHardDisk(data->vboxObj, hddFormatUtf16, hddNameUtf16, &hardDisk); - if (NS_SUCCEEDED(rc)) { - IProgress *progress = NULL; - PRUint64 logicalSize = VIR_DIV_UP(def->target.capacity, - 1024 * 1024); - PRUint32 variant = HardDiskVariant_Standard; + rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetSize, &hddActualSize); + if (NS_SUCCEEDED(rc) && defOk) + def.target.allocation = hddActualSize; + else + defOk = 0; - if (def->target.capacity == def->target.allocation) - variant = HardDiskVariant_Fixed; + if (VIR_STRDUP(def.name, vol->name) < 0) + defOk = 0; -#if VBOX_API_VERSION < 4003000 - rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, variant, &progress); -#else - rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, 1, &variant, &progress); -#endif - if (NS_SUCCEEDED(rc) && progress) { -#if VBOX_API_VERSION == 2002000 - nsresult resultCode; -#else - PRInt32 resultCode; -#endif + if (VIR_STRDUP(def.key, vol->key) < 0) + defOk = 0; - progress->vtbl->WaitForCompletion(progress, -1); - progress->vtbl->GetResultCode(progress, &resultCode); + rc = hardDisk->vtbl->GetFormat(hardDisk, &hddFormatUtf16); + if (NS_SUCCEEDED(rc) && defOk) { + char *hddFormatUtf8 = NULL; - if (NS_SUCCEEDED(resultCode)) { - vboxIID hddIID = VBOX_IID_INITIALIZER; - unsigned char uuid[VIR_UUID_BUFLEN]; - char key[VIR_UUID_STRING_BUFLEN] = ""; + VBOX_UTF16_TO_UTF8(hddFormatUtf16, &hddFormatUtf8); + if (hddFormatUtf8) { - rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value); - if (NS_SUCCEEDED(rc)) { - vboxIIDToUUID(&hddIID, uuid); - virUUIDFormat(uuid, key); + VIR_DEBUG("Storage Volume Format: %s", hddFormatUtf8); - ret = virGetStorageVol(pool->conn, pool->name, def->name, key, - NULL, NULL); - } + if (STRCASEEQ("vmdk", hddFormatUtf8)) + def.target.format = VIR_STORAGE_FILE_VMDK; + else if (STRCASEEQ("vhd", hddFormatUtf8)) + def.target.format = VIR_STORAGE_FILE_VPC; + else if (STRCASEEQ("vdi", hddFormatUtf8)) + def.target.format = VIR_STORAGE_FILE_VDI; + else + def.target.format = VIR_STORAGE_FILE_RAW; - vboxIIDUnalloc(&hddIID); + VBOX_UTF8_FREE(hddFormatUtf8); } - VBOX_RELEASE(progress); + VBOX_UTF16_FREE(hddFormatUtf16); + } else { + defOk = 0; } } + + VBOX_MEDIUM_RELEASE(hardDisk); } - VBOX_UTF16_FREE(hddFormatUtf16); - VBOX_UTF16_FREE(hddNameUtf16); + vboxIIDUnalloc(&hddIID); + + if (defOk) + ret = virStorageVolDefFormat(&pool, &def); - cleanup: - virStorageVolDefFree(def); return ret; } -static int vboxStorageVolDelete(virStorageVolPtr vol, - unsigned int flags) -{ - VBOX_OBJECT_CHECK(vol->conn, int, -1); - vboxIID hddIID = VBOX_IID_INITIALIZER; - unsigned char uuid[VIR_UUID_BUFLEN]; +static char *vboxStorageVolGetPath(virStorageVolPtr vol) { + VBOX_OBJECT_CHECK(vol->conn, char *, NULL); IHardDisk *hardDisk = NULL; - int deregister = 0; + unsigned char uuid[VIR_UUID_BUFLEN]; + vboxIID hddIID = VBOX_IID_INITIALIZER; nsresult rc; - size_t i = 0; - size_t j = 0; - - virCheckFlags(0, -1); if (virUUIDParse(vol->key, uuid) < 0) { virReportError(VIR_ERR_INVALID_ARG, _("Could not parse UUID from '%s'"), vol->key); - return -1; + return ret; } vboxIIDFromUUID(&hddIID, uuid); @@ -10078,1123 +9451,1437 @@ static int vboxStorageVolDelete(virStorageVolPtr vol, VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); if (hddstate != MediaState_Inaccessible) { - PRUint32 machineIdsSize = 0; - vboxArray machineIds = VBOX_ARRAY_INITIALIZER; + PRUnichar *hddLocationUtf16 = NULL; + char *hddLocationUtf8 = NULL; -#if VBOX_API_VERSION < 3001000 - vboxArrayGet(&machineIds, hardDisk, hardDisk->vtbl->imedium.GetMachineIds); -#else /* VBOX_API_VERSION >= 3001000 */ - vboxArrayGet(&machineIds, hardDisk, hardDisk->vtbl->GetMachineIds); -#endif /* VBOX_API_VERSION >= 3001000 */ + VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetLocation, &hddLocationUtf16); -#if VBOX_API_VERSION == 2002000 && defined WIN32 - /* VirtualBox 2.2 on Windows represents IIDs as GUIDs and the - * machineIds array contains direct instances of the GUID struct - * instead of pointers to the actual struct instances. But there - * is no 128bit width simple item type for a SafeArray to fit a - * GUID in. The largest simple type it 64bit width and VirtualBox - * uses two of this 64bit items to represents one GUID. Therefore, - * we divide the size of the SafeArray by two, to compensate for - * this workaround in VirtualBox */ - machineIds.count /= 2; -#endif /* VBOX_API_VERSION >= 2002000 */ + VBOX_UTF16_TO_UTF8(hddLocationUtf16, &hddLocationUtf8); + if (hddLocationUtf8) { - machineIdsSize = machineIds.count; + ignore_value(VIR_STRDUP(ret, hddLocationUtf8)); - for (i = 0; i < machineIds.count; i++) { - IMachine *machine = NULL; - vboxIID machineId = VBOX_IID_INITIALIZER; + VIR_DEBUG("Storage Volume Name: %s", vol->name); + VIR_DEBUG("Storage Volume Path: %s", hddLocationUtf8); + VIR_DEBUG("Storage Volume Pool: %s", vol->pool); - vboxIIDFromArrayItem(&machineId, &machineIds, i); + VBOX_UTF8_FREE(hddLocationUtf8); + } -#if VBOX_API_VERSION >= 4000000 - rc = VBOX_OBJECT_GET_MACHINE(machineId.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching uuid")); - break; - } -#endif + VBOX_UTF16_FREE(hddLocationUtf16); + } - rc = VBOX_SESSION_OPEN(machineId.value, machine); + VBOX_MEDIUM_RELEASE(hardDisk); + } - if (NS_SUCCEEDED(rc)) { + vboxIIDUnalloc(&hddIID); - rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine); - if (NS_SUCCEEDED(rc)) { - vboxArray hddAttachments = VBOX_ARRAY_INITIALIZER; + return ret; +} -#if VBOX_API_VERSION < 3001000 - vboxArrayGet(&hddAttachments, machine, - machine->vtbl->GetHardDiskAttachments); -#else /* VBOX_API_VERSION >= 3001000 */ - vboxArrayGet(&hddAttachments, machine, - machine->vtbl->GetMediumAttachments); -#endif /* VBOX_API_VERSION >= 3001000 */ - for (j = 0; j < hddAttachments.count; j++) { - IHardDiskAttachment *hddAttachment = hddAttachments.items[j]; +#if VBOX_API_VERSION >= 4000000 +static char * +vboxDomainScreenshot(virDomainPtr dom, + virStreamPtr st, + unsigned int screen, + unsigned int flags) +{ + VBOX_OBJECT_CHECK(dom->conn, char *, NULL); + IConsole *console = NULL; + vboxIID iid = VBOX_IID_INITIALIZER; + IMachine *machine = NULL; + nsresult rc; + char *tmp; + int tmp_fd = -1; + unsigned int max_screen; + + virCheckFlags(0, NULL); + + vboxIIDFromUUID(&iid, dom->uuid); + rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + return NULL; + } + + rc = machine->vtbl->GetMonitorCount(machine, &max_screen); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("unable to get monitor count")); + VBOX_RELEASE(machine); + return NULL; + } - if (hddAttachment) { - IHardDisk *hdd = NULL; + if (screen >= max_screen) { + virReportError(VIR_ERR_INVALID_ARG, + _("screen ID higher than monitor " + "count (%d)"), max_screen); + VBOX_RELEASE(machine); + return NULL; + } -#if VBOX_API_VERSION < 3001000 - rc = hddAttachment->vtbl->GetHardDisk(hddAttachment, &hdd); -#else /* VBOX_API_VERSION >= 3001000 */ - rc = hddAttachment->vtbl->GetMedium(hddAttachment, &hdd); -#endif /* VBOX_API_VERSION >= 3001000 */ - if (NS_SUCCEEDED(rc) && hdd) { - vboxIID iid = VBOX_IID_INITIALIZER; + if (virAsprintf(&tmp, "%s/cache/libvirt/vbox.screendump.XXXXXX", LOCALSTATEDIR) < 0) { + VBOX_RELEASE(machine); + return NULL; + } - rc = VBOX_MEDIUM_FUNC_ARG1(hdd, GetId, &iid.value); - if (NS_SUCCEEDED(rc)) { + if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) { + virReportSystemError(errno, _("mkostemp(\"%s\") failed"), tmp); + VIR_FREE(tmp); + VBOX_RELEASE(machine); + return NULL; + } - DEBUGIID("HardDisk (to delete) UUID", hddIID.value); - DEBUGIID("HardDisk (currently processing) UUID", iid.value); - if (vboxIIDIsEqual(&hddIID, &iid)) { - PRUnichar *controller = NULL; - PRInt32 port = 0; - PRInt32 device = 0; + rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); + if (NS_SUCCEEDED(rc)) { + rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console); + if (NS_SUCCEEDED(rc) && console) { + IDisplay *display = NULL; - DEBUGIID("Found HardDisk to delete, UUID", hddIID.value); + console->vtbl->GetDisplay(console, &display); - hddAttachment->vtbl->GetController(hddAttachment, &controller); - hddAttachment->vtbl->GetPort(hddAttachment, &port); - hddAttachment->vtbl->GetDevice(hddAttachment, &device); + if (display) { + PRUint32 width, height, bitsPerPixel; + PRUint32 screenDataSize; + PRUint8 *screenData; +# if VBOX_API_VERSION >= 4003000 + PRInt32 xOrigin, yOrigin; +# endif -#if VBOX_API_VERSION < 3001000 - rc = machine->vtbl->DetachHardDisk(machine, controller, port, device); -#else /* VBOX_API_VERSION >= 3001000 */ - rc = machine->vtbl->DetachDevice(machine, controller, port, device); -#endif /* VBOX_API_VERSION >= 3001000 */ - if (NS_SUCCEEDED(rc)) { - rc = machine->vtbl->SaveSettings(machine); - VIR_DEBUG("saving machine settings"); - } + rc = display->vtbl->GetScreenResolution(display, screen, + &width, &height, +# if VBOX_API_VERSION < 4003000 + &bitsPerPixel); +# else + &bitsPerPixel, + &xOrigin, &yOrigin); +# endif - if (NS_SUCCEEDED(rc)) { - deregister++; - VIR_DEBUG("deregistering hdd:%d", deregister); - } + if (NS_FAILED(rc) || !width || !height) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("unable to get screen resolution")); + goto endjob; + } - VBOX_UTF16_FREE(controller); - } - vboxIIDUnalloc(&iid); - } - VBOX_MEDIUM_RELEASE(hdd); - } - } - } - vboxArrayRelease(&hddAttachments); - VBOX_RELEASE(machine); - } - VBOX_SESSION_CLOSE(); + rc = display->vtbl->TakeScreenShotPNGToArray(display, screen, + width, height, + &screenDataSize, + &screenData); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("failed to take screenshot")); + goto endjob; } - vboxIIDUnalloc(&machineId); - } + if (safewrite(tmp_fd, (char *) screenData, + screenDataSize) < 0) { + virReportSystemError(errno, _("unable to write data " + "to '%s'"), tmp); + goto endjob; + } - vboxArrayUnalloc(&machineIds); + if (VIR_CLOSE(tmp_fd) < 0) { + virReportSystemError(errno, _("unable to close %s"), tmp); + goto endjob; + } - if (machineIdsSize == 0 || machineIdsSize == deregister) { - IProgress *progress = NULL; - rc = hardDisk->vtbl->DeleteStorage(hardDisk, &progress); + if (VIR_STRDUP(ret, "image/png") < 0) + goto endjob; - if (NS_SUCCEEDED(rc) && progress) { - progress->vtbl->WaitForCompletion(progress, -1); - VBOX_RELEASE(progress); - DEBUGIID("HardDisk deleted, UUID", hddIID.value); - ret = 0; + if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("unable to open stream")); + VIR_FREE(ret); } + endjob: + VIR_FREE(screenData); + VBOX_RELEASE(display); } + VBOX_RELEASE(console); } - - VBOX_MEDIUM_RELEASE(hardDisk); + VBOX_SESSION_CLOSE(); } - vboxIIDUnalloc(&hddIID); - + VIR_FORCE_CLOSE(tmp_fd); + unlink(tmp); + VIR_FREE(tmp); + VBOX_RELEASE(machine); + vboxIIDUnalloc(&iid); return ret; } +#endif /* VBOX_API_VERSION >= 4000000 */ + +#define MATCH(FLAG) (flags & (FLAG)) static int -vboxStorageVolGetInfo(virStorageVolPtr vol, virStorageVolInfoPtr info) +vboxConnectListAllDomains(virConnectPtr conn, + virDomainPtr **domains, + unsigned int flags) { - VBOX_OBJECT_CHECK(vol->conn, int, -1); - IHardDisk *hardDisk = NULL; + VBOX_OBJECT_CHECK(conn, int, -1); + vboxArray machines = VBOX_ARRAY_INITIALIZER; + char *machineNameUtf8 = NULL; + PRUnichar *machineNameUtf16 = NULL; unsigned char uuid[VIR_UUID_BUFLEN]; - vboxIID hddIID = VBOX_IID_INITIALIZER; + vboxIID iid = VBOX_IID_INITIALIZER; + PRUint32 state; nsresult rc; + size_t i; + virDomainPtr dom; + virDomainPtr *doms = NULL; + int count = 0; + bool active; + PRUint32 snapshotCount; - if (!info) - return ret; + virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); - if (virUUIDParse(vol->key, uuid) < 0) { - virReportError(VIR_ERR_INVALID_ARG, - _("Could not parse UUID from '%s'"), vol->key); - return ret; + /* filter out flag options that will produce 0 results in vbox driver: + * - managed save: vbox guests don't have managed save images + * - autostart: vbox doesn't support autostarting guests + * - persistance: vbox doesn't support transient guests + */ + if ((MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) && + !MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT)) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) && + !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART)) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && + !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE))) { + if (domains && + VIR_ALLOC_N(*domains, 1) < 0) + goto cleanup; + + ret = 0; + goto cleanup; } - vboxIIDFromUUID(&hddIID, uuid); -#if VBOX_API_VERSION < 4000000 - rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk); -#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 - rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value, - DeviceType_HardDisk, &hardDisk); -#else - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value, - DeviceType_HardDisk, AccessMode_ReadWrite, - PR_FALSE, &hardDisk); -#endif /* VBOX_API_VERSION >= 4000000 */ - if (NS_SUCCEEDED(rc)) { - PRUint32 hddstate; + rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get list of domains, rc=%08x"), (unsigned)rc); + goto cleanup; + } + + if (domains && + VIR_ALLOC_N(doms, machines.count + 1) < 0) + goto cleanup; + + for (i = 0; i < machines.count; i++) { + IMachine *machine = machines.items[i]; + + if (machine) { + PRBool isAccessible = PR_FALSE; + machine->vtbl->GetAccessible(machine, &isAccessible); + if (isAccessible) { + machine->vtbl->GetState(machine, &state); + + if (state >= MachineState_FirstOnline && + state <= MachineState_LastOnline) + active = true; + else + active = false; + + /* filter by active state */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) && + !((MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE) && active) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE) && !active))) + continue; + + /* filter by snapshot existence */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_SNAPSHOT)) { + rc = machine->vtbl->GetSnapshotCount(machine, &snapshotCount); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("could not get snapshot count for listed domains")); + goto cleanup; + } + if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) && + snapshotCount > 0) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) && + snapshotCount == 0))) + continue; + } + + /* filter by machine state */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE) && + !((MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) && + state == MachineState_Running) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) && + state == MachineState_Paused) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) && + state == MachineState_PoweredOff) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) && + (state != MachineState_Running && + state != MachineState_Paused && + state != MachineState_PoweredOff)))) + continue; - VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); - if (hddstate != MediaState_Inaccessible) { -#if VBOX_API_VERSION < 4000000 - PRUint64 hddLogicalSize; - PRUint64 hddActualSize; -#else /* VBOX_API_VERSION >= 4000000 */ - PRInt64 hddLogicalSize; - PRInt64 hddActualSize; -#endif /* VBOX_API_VERSION >= 4000000 */ + /* just count the machines */ + if (!doms) { + count++; + continue; + } - info->type = VIR_STORAGE_VOL_FILE; + machine->vtbl->GetName(machine, &machineNameUtf16); + VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8); + machine->vtbl->GetId(machine, &iid.value); + vboxIIDToUUID(&iid, uuid); + vboxIIDUnalloc(&iid); - hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize); -#if VBOX_API_VERSION < 4000000 - info->capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */ -#else /* VBOX_API_VERSION >= 4000000 */ - info->capacity = hddLogicalSize; -#endif /* VBOX_API_VERSION >= 4000000 */ + dom = virGetDomain(conn, machineNameUtf8, uuid); - VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetSize, &hddActualSize); - info->allocation = hddActualSize; + VBOX_UTF8_FREE(machineNameUtf8); + VBOX_UTF16_FREE(machineNameUtf16); - ret = 0; + if (!dom) + goto cleanup; - VIR_DEBUG("Storage Volume Name: %s", vol->name); - VIR_DEBUG("Storage Volume Type: %s", info->type == VIR_STORAGE_VOL_BLOCK ? "Block" : "File"); - VIR_DEBUG("Storage Volume Capacity: %llu", info->capacity); - VIR_DEBUG("Storage Volume Allocation: %llu", info->allocation); + if (active) + dom->id = i + 1; + + doms[count++] = dom; + } } + } - VBOX_MEDIUM_RELEASE(hardDisk); + if (doms) { + /* safe to ignore, new size will be equal or less than + * previous allocation*/ + ignore_value(VIR_REALLOC_N(doms, count + 1)); + *domains = doms; + doms = NULL; } - vboxIIDUnalloc(&hddIID); + ret = count; + + cleanup: + if (doms) { + for (i = 0; i < count; i++) { + if (doms[i]) + virDomainFree(doms[i]); + } + } + VIR_FREE(doms); + vboxArrayRelease(&machines); return ret; } +#undef MATCH -static char *vboxStorageVolGetXMLDesc(virStorageVolPtr vol, unsigned int flags) -{ - VBOX_OBJECT_CHECK(vol->conn, char *, NULL); - IHardDisk *hardDisk = NULL; - unsigned char uuid[VIR_UUID_BUFLEN]; - vboxIID hddIID = VBOX_IID_INITIALIZER; - virStoragePoolDef pool; - virStorageVolDef def; - int defOk = 0; - nsresult rc; - - virCheckFlags(0, NULL); - memset(&pool, 0, sizeof(pool)); - memset(&def, 0, sizeof(def)); +static int +vboxNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, + virNodeInfoPtr nodeinfo) +{ + return nodeGetInfo(nodeinfo); +} - if (virUUIDParse(vol->key, uuid) < 0) { - virReportError(VIR_ERR_INVALID_ARG, - _("Could not parse UUID from '%s'"), vol->key); - return ret; - } - vboxIIDFromUUID(&hddIID, uuid); -#if VBOX_API_VERSION < 4000000 - rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk); -#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 - rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value, - DeviceType_HardDisk, &hardDisk); -#else - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value, - DeviceType_HardDisk, AccessMode_ReadWrite, - PR_FALSE, &hardDisk); -#endif /* VBOX_API_VERSION >= 4000000 */ - if (NS_SUCCEEDED(rc)) { - PRUint32 hddstate; +static int +vboxNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, + unsigned long long *freeMems, + int startCell, + int maxCells) +{ + return nodeGetCellsFreeMemory(freeMems, startCell, maxCells); +} - VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); - if (NS_SUCCEEDED(rc) && hddstate != MediaState_Inaccessible) { - PRUnichar *hddFormatUtf16 = NULL; -#if VBOX_API_VERSION < 4000000 - PRUint64 hddLogicalSize; - PRUint64 hddActualSize; -#else /* VBOX_API_VERSION >= 4000000 */ - PRInt64 hddLogicalSize; - PRInt64 hddActualSize; -#endif /* VBOX_API_VERSION >= 4000000 */ - /* since there is currently one default pool now - * and virStorageVolDefFormat() just checks it type - * so just assign it for now, change the behaviour - * when vbox supports pools. - */ - pool.type = VIR_STORAGE_POOL_DIR; - def.type = VIR_STORAGE_VOL_FILE; - defOk = 1; +static unsigned long long +vboxNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) +{ + unsigned long long freeMem; + if (nodeGetMemory(NULL, &freeMem) < 0) + return 0; + return freeMem; +} - rc = hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize); - if (NS_SUCCEEDED(rc) && defOk) { -#if VBOX_API_VERSION < 4000000 - def.target.capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */ -#else /* VBOX_API_VERSION >= 4000000 */ - def.target.capacity = hddLogicalSize; -#endif /* VBOX_API_VERSION >= 4000000 */ - } else - defOk = 0; - rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetSize, &hddActualSize); - if (NS_SUCCEEDED(rc) && defOk) - def.target.allocation = hddActualSize; - else - defOk = 0; +static int +vboxNodeGetFreePages(virConnectPtr conn ATTRIBUTE_UNUSED, + unsigned int npages, + unsigned int *pages, + int startCell, + unsigned int cellCount, + unsigned long long *counts, + unsigned int flags) +{ + virCheckFlags(0, -1); - if (VIR_STRDUP(def.name, vol->name) < 0) - defOk = 0; + return nodeGetFreePages(npages, pages, startCell, cellCount, counts); +} - if (VIR_STRDUP(def.key, vol->key) < 0) - defOk = 0; +static int _pfnInitialize(vboxGlobalData *data) +{ + data->pFuncs = g_pfnGetFunctions(VBOX_XPCOMC_VERSION); + if (data->pFuncs == NULL) + return -1; +#if VBOX_XPCOMC_VERSION == 0x00010000U + data->pFuncs->pfnComInitialize(&data->vboxObj, &data->vboxSession); +#else /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */ + data->pFuncs->pfnComInitialize(IVIRTUALBOX_IID_STR, &data->vboxObj, ISESSION_IID_STR, &data->vboxSession); +#endif /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */ + return 0; +} - rc = hardDisk->vtbl->GetFormat(hardDisk, &hddFormatUtf16); - if (NS_SUCCEEDED(rc) && defOk) { - char *hddFormatUtf8 = NULL; +static int +_initializeDomainEvent(vboxGlobalData *data ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 + /* No event queue functionality in 2.2.* and 4.* as of now */ + vboxUnsupported(); +#else /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */ + /* Initialize the fWatch needed for Event Callbacks */ + data->fdWatch = -1; + data->pFuncs->pfnGetEventQueue(&data->vboxQueue); + if (data->vboxQueue == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("nsIEventQueue object is null")); + return -1; + } +#endif /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */ + return 0; +} - VBOX_UTF16_TO_UTF8(hddFormatUtf16, &hddFormatUtf8); - if (hddFormatUtf8) { +static +void _registerGlobalData(vboxGlobalData *data ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION == 2002000 + vboxUnsupported(); +#else /* VBOX_API_VERSION != 2002000 */ + g_pVBoxGlobalData = data; +#endif /* VBOX_API_VERSION != 2002000 */ +} - VIR_DEBUG("Storage Volume Format: %s", hddFormatUtf8); +#if VBOX_API_VERSION < 4000000 - if (STRCASEEQ("vmdk", hddFormatUtf8)) - def.target.format = VIR_STORAGE_FILE_VMDK; - else if (STRCASEEQ("vhd", hddFormatUtf8)) - def.target.format = VIR_STORAGE_FILE_VPC; - else if (STRCASEEQ("vdi", hddFormatUtf8)) - def.target.format = VIR_STORAGE_FILE_VDI; - else - def.target.format = VIR_STORAGE_FILE_RAW; +# if VBOX_API_VERSION < 3001000 +static void +_detachDevices(vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine, PRUnichar *hddcnameUtf16) +{ + /* Disconnect all the drives if present */ + machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 0, 0); + machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 0, 1); + machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 1, 1); +} +# else /* VBOX_API_VERSION >= 3001000 */ +static void +_detachDevices(vboxGlobalData *data, IMachine *machine, + PRUnichar *hddcnameUtf16 ATTRIBUTE_UNUSED) +{ + /* get all the controller first, then the attachments and + * remove them all so that the machine can be undefined + */ + vboxArray storageControllers = VBOX_ARRAY_INITIALIZER; + size_t i = 0, j = 0; - VBOX_UTF8_FREE(hddFormatUtf8); - } + vboxArrayGet(&storageControllers, machine, + machine->vtbl->GetStorageControllers); - VBOX_UTF16_FREE(hddFormatUtf16); - } else { - defOk = 0; - } - } + for (i = 0; i < storageControllers.count; i++) { + IStorageController *strCtl = storageControllers.items[i]; + PRUnichar *strCtlName = NULL; + vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER; - VBOX_MEDIUM_RELEASE(hardDisk); - } + if (!strCtl) + continue; - vboxIIDUnalloc(&hddIID); + strCtl->vtbl->GetName(strCtl, &strCtlName); + vboxArrayGetWithPtrArg(&mediumAttachments, machine, + machine->vtbl->GetMediumAttachmentsOfController, + strCtlName); - if (defOk) - ret = virStorageVolDefFormat(&pool, &def); + for (j = 0; j < mediumAttachments.count; j++) { + IMediumAttachment *medAtt = mediumAttachments.items[j]; + PRInt32 port = ~0U; + PRInt32 device = ~0U; - return ret; -} + if (!medAtt) + continue; -static char *vboxStorageVolGetPath(virStorageVolPtr vol) { - VBOX_OBJECT_CHECK(vol->conn, char *, NULL); - IHardDisk *hardDisk = NULL; - unsigned char uuid[VIR_UUID_BUFLEN]; - vboxIID hddIID = VBOX_IID_INITIALIZER; - nsresult rc; + medAtt->vtbl->GetPort(medAtt, &port); + medAtt->vtbl->GetDevice(medAtt, &device); - if (virUUIDParse(vol->key, uuid) < 0) { - virReportError(VIR_ERR_INVALID_ARG, - _("Could not parse UUID from '%s'"), vol->key); - return ret; - } + if ((port != ~0U) && (device != ~0U)) { + machine->vtbl->DetachDevice(machine, + strCtlName, + port, + device); + } + } + vboxArrayRelease(&storageControllers); + machine->vtbl->RemoveStorageController(machine, strCtlName); + VBOX_UTF16_FREE(strCtlName); + } + vboxArrayRelease(&storageControllers); +} +# endif /* VBOX_API_VERSION >= 3001000 */ - vboxIIDFromUUID(&hddIID, uuid); -#if VBOX_API_VERSION < 4000000 - rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk); -#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 - rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value, - DeviceType_HardDisk, &hardDisk); -#else - rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value, - DeviceType_HardDisk, AccessMode_ReadWrite, - PR_FALSE, &hardDisk); -#endif /* VBOX_API_VERSION >= 4000000 */ - if (NS_SUCCEEDED(rc)) { - PRUint32 hddstate; +static nsresult +_unregisterMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine) +{ + return data->vboxObj->vtbl->UnregisterMachine(data->vboxObj, IID_MEMBER(value), machine); +} - VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate); - if (hddstate != MediaState_Inaccessible) { - PRUnichar *hddLocationUtf16 = NULL; - char *hddLocationUtf8 = NULL; +static void +_deleteConfig(IMachine *machine) +{ + machine->vtbl->DeleteSettings(machine); +} - VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetLocation, &hddLocationUtf16); +#else /* VBOX_API_VERSION >= 4000000 */ - VBOX_UTF16_TO_UTF8(hddLocationUtf16, &hddLocationUtf8); - if (hddLocationUtf8) { +static void +_detachDevices(vboxGlobalData *data ATTRIBUTE_UNUSED, + IMachine *machine ATTRIBUTE_UNUSED, + PRUnichar *hddcnameUtf16 ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); +} - ignore_value(VIR_STRDUP(ret, hddLocationUtf8)); +static nsresult +_unregisterMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine) +{ + nsresult rc; + vboxArray media = VBOX_ARRAY_INITIALIZER; + rc = VBOX_OBJECT_GET_MACHINE(IID_MEMBER(value), machine); + if (NS_FAILED(rc)) { + virReportError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + return rc; + } - VIR_DEBUG("Storage Volume Name: %s", vol->name); - VIR_DEBUG("Storage Volume Path: %s", hddLocationUtf8); - VIR_DEBUG("Storage Volume Pool: %s", vol->pool); + /* We're not interested in the array returned by the Unregister method, + * but in the side effect of unregistering the virtual machine. In order + * to call the Unregister method correctly we need to use the vboxArray + * wrapper here. */ + rc = vboxArrayGetWithUintArg(&media, *machine, (*machine)->vtbl->Unregister, + CleanupMode_DetachAllReturnNone); + vboxArrayUnalloc(&media); + return rc; +} - VBOX_UTF8_FREE(hddLocationUtf8); - } +static void +_deleteConfig(IMachine *machine) +{ + IProgress *progress = NULL; - VBOX_UTF16_FREE(hddLocationUtf16); - } + /* The IMachine Delete method takes an array of IMedium items to be + * deleted along with the virtual machine. We just want to pass an + * empty array. But instead of adding a full vboxArraySetWithReturn to + * the glue layer (in order to handle the required signature of the + * Delete method) we use a local solution here. */ +# ifdef WIN32 + SAFEARRAY *safeArray = NULL; + typedef HRESULT __stdcall (*IMachine_Delete)(IMachine *self, + SAFEARRAY **media, + IProgress **progress); - VBOX_MEDIUM_RELEASE(hardDisk); +# if VBOX_API_VERSION < 4003000 + ((IMachine_Delete)machine->vtbl->Delete)(machine, &safeArray, &progress); +# else + ((IMachine_Delete)machine->vtbl->DeleteConfig)(machine, &safeArray, &progress); +# endif +# else + /* XPCOM doesn't like NULL as an array, even when the array size is 0. + * Instead pass it a dummy array to avoid passing NULL. */ + IMedium *array[] = { NULL }; +# if VBOX_API_VERSION < 4003000 + machine->vtbl->Delete(machine, 0, array, &progress); +# else + machine->vtbl->DeleteConfig(machine, 0, array, &progress); +# endif +# endif + if (progress != NULL) { + progress->vtbl->WaitForCompletion(progress, -1); + VBOX_RELEASE(progress); } +} - vboxIIDUnalloc(&hddIID); +#endif /* VBOX_API_VERSION >= 4000000 */ - return ret; +static void _pfnUninitialize(vboxGlobalData *data) +{ + if (data->pFuncs) + data->pFuncs->pfnComUninitialize(); } -#if VBOX_API_VERSION >= 4000000 -static char * -vboxDomainScreenshot(virDomainPtr dom, - virStreamPtr st, - unsigned int screen, - unsigned int flags) +static void _pfnComUnallocMem(PCVBOXXPCOM pFuncs, void *pv) { - VBOX_OBJECT_CHECK(dom->conn, char *, NULL); - IConsole *console = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - nsresult rc; - char *tmp; - int tmp_fd = -1; - unsigned int max_screen; + pFuncs->pfnComUnallocMem(pv); +} - virCheckFlags(0, NULL); +static void _pfnUtf16Free(PCVBOXXPCOM pFuncs, PRUnichar *pwszString) +{ + pFuncs->pfnUtf16Free(pwszString); +} - vboxIIDFromUUID(&iid, dom->uuid); - rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching uuid")); - return NULL; - } +static void _pfnUtf8Free(PCVBOXXPCOM pFuncs, char *pszString) +{ + pFuncs->pfnUtf8Free(pszString); +} - rc = machine->vtbl->GetMonitorCount(machine, &max_screen); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("unable to get monitor count")); - VBOX_RELEASE(machine); - return NULL; - } +static int _pfnUtf16ToUtf8(PCVBOXXPCOM pFuncs, const PRUnichar *pwszString, char **ppszString) +{ + return pFuncs->pfnUtf16ToUtf8(pwszString, ppszString); +} - if (screen >= max_screen) { - virReportError(VIR_ERR_INVALID_ARG, - _("screen ID higher than monitor " - "count (%d)"), max_screen); - VBOX_RELEASE(machine); - return NULL; - } +static int _pfnUtf8ToUtf16(PCVBOXXPCOM pFuncs, const char *pszString, PRUnichar **ppwszString) +{ + return pFuncs->pfnUtf8ToUtf16(pszString, ppwszString); +} - if (virAsprintf(&tmp, "%s/cache/libvirt/vbox.screendump.XXXXXX", LOCALSTATEDIR) < 0) { - VBOX_RELEASE(machine); - return NULL; - } +#if VBOX_API_VERSION == 2002000 - if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) { - virReportSystemError(errno, _("mkostemp(\"%s\") failed"), tmp); - VIR_FREE(tmp); - VBOX_RELEASE(machine); - return NULL; - } +static void _vboxIIDInitialize(vboxIIDUnion *iidu) +{ + memset(iidu, 0, sizeof(vboxIIDUnion)); +} +static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu) +{ +# ifdef WIN32 + DEBUGUUID(msg, (nsID *)&IID_MEMBER(value)); +# else /* !WIN32 */ + DEBUGUUID(msg, IID_MEMBER(value)); +# endif /* !WIN32 */ +} - rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine); - if (NS_SUCCEEDED(rc)) { - rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console); - if (NS_SUCCEEDED(rc) && console) { - IDisplay *display = NULL; +#else /* VBOX_API_VERSION != 2002000 */ - console->vtbl->GetDisplay(console, &display); +static void _vboxIIDInitialize(vboxIIDUnion *iidu) +{ + memset(iidu, 0, sizeof(vboxIIDUnion)); + IID_MEMBER(owner) = true; +} - if (display) { - PRUint32 width, height, bitsPerPixel; - PRUint32 screenDataSize; - PRUint8 *screenData; -# if VBOX_API_VERSION >= 4003000 - PRInt32 xOrigin, yOrigin; -# endif +static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu) +{ + DEBUGPRUnichar(msg, IID_MEMBER(value)); +} - rc = display->vtbl->GetScreenResolution(display, screen, - &width, &height, -# if VBOX_API_VERSION < 4003000 - &bitsPerPixel); -# else - &bitsPerPixel, - &xOrigin, &yOrigin); -# endif +#endif /* VBOX_API_VERSION != 2002000 */ - if (NS_FAILED(rc) || !width || !height) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("unable to get screen resolution")); - goto endjob; - } +static void* _handleGetMachines(IVirtualBox *vboxObj) +{ + return vboxObj->vtbl->GetMachines; +} - rc = display->vtbl->TakeScreenShotPNGToArray(display, screen, - width, height, - &screenDataSize, - &screenData); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("failed to take screenshot")); - goto endjob; - } +static nsresult _nsisupportsRelease(nsISupports *nsi) +{ + return nsi->vtbl->Release(nsi); +} - if (safewrite(tmp_fd, (char *) screenData, - screenDataSize) < 0) { - virReportSystemError(errno, _("unable to write data " - "to '%s'"), tmp); - goto endjob; - } +static nsresult +_virtualboxGetVersion(IVirtualBox *vboxObj, PRUnichar **versionUtf16) +{ + return vboxObj->vtbl->GetVersion(vboxObj, versionUtf16); +} - if (VIR_CLOSE(tmp_fd) < 0) { - virReportSystemError(errno, _("unable to close %s"), tmp); - goto endjob; - } +#if VBOX_API_VERSION < 4000000 - if (VIR_STRDUP(ret, "image/png") < 0) - goto endjob; +static nsresult +_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine) +{ + return vboxObj->vtbl->GetMachine(vboxObj, IID_MEMBER(value), machine); +} - if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("unable to open stream")); - VIR_FREE(ret); - } - endjob: - VIR_FREE(screenData); - VBOX_RELEASE(display); - } - VBOX_RELEASE(console); - } - VBOX_SESSION_CLOSE(); - } +#else /* VBOX_API_VERSION >= 4000000 */ - VIR_FORCE_CLOSE(tmp_fd); - unlink(tmp); - VIR_FREE(tmp); - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; +static nsresult +_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine) +{ + return vboxObj->vtbl->FindMachine(vboxObj, IID_MEMBER(value), machine); } + #endif /* VBOX_API_VERSION >= 4000000 */ +static nsresult +_virtualboxGetSystemProperties(IVirtualBox *vboxObj, ISystemProperties **systemProperties) +{ + return vboxObj->vtbl->GetSystemProperties(vboxObj, systemProperties); +} -#define MATCH(FLAG) (flags & (FLAG)) -static int -vboxConnectListAllDomains(virConnectPtr conn, - virDomainPtr **domains, - unsigned int flags) +static nsresult +_virtualboxCreateMachine(vboxGlobalData *data, virDomainDefPtr def, IMachine **machine, char *uuidstr ATTRIBUTE_UNUSED) { - VBOX_OBJECT_CHECK(conn, int, -1); - vboxArray machines = VBOX_ARRAY_INITIALIZER; - char *machineNameUtf8 = NULL; - PRUnichar *machineNameUtf16 = NULL; - unsigned char uuid[VIR_UUID_BUFLEN]; vboxIID iid = VBOX_IID_INITIALIZER; - PRUint32 state; + PRUnichar *machineNameUtf16 = NULL; nsresult rc; - size_t i; - virDomainPtr dom; - virDomainPtr *doms = NULL; - int count = 0; - bool active; - PRUint32 snapshotCount; - - virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); - - /* filter out flag options that will produce 0 results in vbox driver: - * - managed save: vbox guests don't have managed save images - * - autostart: vbox doesn't support autostarting guests - * - persistance: vbox doesn't support transient guests - */ - if ((MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) && - !MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT)) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) && - !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART)) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) && - !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE))) { - if (domains && - VIR_ALLOC_N(*domains, 1) < 0) - goto cleanup; - - ret = 0; - goto cleanup; - } - rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not get list of domains, rc=%08x"), (unsigned)rc); - goto cleanup; + VBOX_UTF8_TO_UTF16(def->name, &machineNameUtf16); + vboxIIDFromUUID(&iid, def->uuid); + { +#if VBOX_API_VERSION < 3002000 + rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, + machineNameUtf16, + NULL, + NULL, + iid.value, + machine); +#elif VBOX_API_VERSION < 4000000 /* 3002000 <= VBOX_API_VERSION < 4000000 */ + PRBool override = PR_FALSE; + rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, + machineNameUtf16, + NULL, + NULL, + iid.value, + override, + machine); +#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 + PRBool override = PR_FALSE; + rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, + NULL, + machineNameUtf16, + NULL, + iid.value, + override, + machine); +#else /* VBOX_API_VERSION >= 4002000 */ + const char *flagsUUIDPrefix = "UUID="; + const char *flagsForceOverwrite = "forceOverwrite=0"; + const char *flagsSeparator = ","; + char createFlags[strlen(flagsUUIDPrefix) + VIR_UUID_STRING_BUFLEN + strlen(flagsSeparator) + strlen(flagsForceOverwrite) + 1]; + PRUnichar *createFlagsUtf16 = NULL; + + snprintf(createFlags, sizeof(createFlags), "%s%s%s%s", + flagsUUIDPrefix, + uuidstr, + flagsSeparator, + flagsForceOverwrite + ); + VBOX_UTF8_TO_UTF16(createFlags, &createFlagsUtf16); + rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj, + NULL, + machineNameUtf16, + 0, + nsnull, + nsnull, + createFlagsUtf16, + machine); +#endif /* VBOX_API_VERSION >= 4002000 */ } + VBOX_UTF16_FREE(machineNameUtf16); + vboxIIDUnalloc(&iid); + return rc; +} - if (domains && - VIR_ALLOC_N(doms, machines.count + 1) < 0) - goto cleanup; - - for (i = 0; i < machines.count; i++) { - IMachine *machine = machines.items[i]; - - if (machine) { - PRBool isAccessible = PR_FALSE; - machine->vtbl->GetAccessible(machine, &isAccessible); - if (isAccessible) { - machine->vtbl->GetState(machine, &state); +static nsresult +_virtualboxRegisterMachine(IVirtualBox *vboxObj, IMachine *machine) +{ + return vboxObj->vtbl->RegisterMachine(vboxObj, machine); +} - if (state >= MachineState_FirstOnline && - state <= MachineState_LastOnline) - active = true; - else - active = false; +static nsresult +_virtualboxFindMedium(IVirtualBox *vboxObj ATTRIBUTE_UNUSED, + PRUnichar *location ATTRIBUTE_UNUSED, + PRUint32 deviceType ATTRIBUTE_UNUSED, + PRUint32 accessMode ATTRIBUTE_UNUSED, + IMedium **medium ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000 + return vboxObj->vtbl->FindMedium(vboxObj, location, + deviceType, medium); +#elif VBOX_API_VERSION >= 4002000 + return vboxObj->vtbl->OpenMedium(vboxObj, location, + deviceType, accessMode, PR_FALSE, medium); +#else + vboxUnsupported(); + return 0; +#endif +} - /* filter by active state */ - if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) && - !((MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE) && active) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE) && !active))) - continue; +static nsresult +_virtualboxOpenMedium(IVirtualBox *vboxObj ATTRIBUTE_UNUSED, + PRUnichar *location ATTRIBUTE_UNUSED, + PRUint32 deviceType ATTRIBUTE_UNUSED, + PRUint32 accessMode ATTRIBUTE_UNUSED, + IMedium **medium ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION == 4000000 + return vboxObj->vtbl->OpenMedium(vboxObj, + location, + deviceType, accessMode, + medium); +#elif VBOX_API_VERSION >= 4001000 + return vboxObj->vtbl->OpenMedium(vboxObj, + location, + deviceType, accessMode, + false, + medium); +#else + vboxUnsupported(); + return 0; +#endif +} - /* filter by snapshot existence */ - if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_SNAPSHOT)) { - rc = machine->vtbl->GetSnapshotCount(machine, &snapshotCount); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("could not get snapshot count for listed domains")); - goto cleanup; - } - if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) && - snapshotCount > 0) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) && - snapshotCount == 0))) - continue; - } +static nsresult +_machineAddStorageController(IMachine *machine, PRUnichar *name, + PRUint32 connectionType, + IStorageController **controller) +{ + return machine->vtbl->AddStorageController(machine, name, connectionType, + controller); +} - /* filter by machine state */ - if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE) && - !((MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) && - state == MachineState_Running) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) && - state == MachineState_Paused) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) && - state == MachineState_PoweredOff) || - (MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) && - (state != MachineState_Running && - state != MachineState_Paused && - state != MachineState_PoweredOff)))) - continue; +static nsresult +_machineAttachDevice(IMachine *machine ATTRIBUTE_UNUSED, + PRUnichar *name ATTRIBUTE_UNUSED, + PRInt32 controllerPort ATTRIBUTE_UNUSED, + PRInt32 device ATTRIBUTE_UNUSED, + PRUint32 type ATTRIBUTE_UNUSED, + IMedium * medium ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION >= 4000000 + return machine->vtbl->AttachDevice(machine, name, controllerPort, + device, type, medium); +#else /* VBOX_API_VERSION < 4000000 */ + vboxUnsupported(); + return 0; +#endif /* VBOX_API_VERSION < 4000000 */ +} - /* just count the machines */ - if (!doms) { - count++; - continue; - } +static nsresult +_machineCreateSharedFolder(IMachine *machine, PRUnichar *name, + PRUnichar *hostPath, PRBool writable, + PRBool automount ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION < 4000000 + return machine->vtbl->CreateSharedFolder(machine, name, hostPath, + writable); +#else /* VBOX_API_VERSION >= 4000000 */ + return machine->vtbl->CreateSharedFolder(machine, name, hostPath, + writable, automount); +#endif /* VBOX_API_VERSION >= 4000000 */ +} - machine->vtbl->GetName(machine, &machineNameUtf16); - VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8); - machine->vtbl->GetId(machine, &iid.value); - vboxIIDToUUID(&iid, uuid); - vboxIIDUnalloc(&iid); - dom = virGetDomain(conn, machineNameUtf8, uuid); +static nsresult +_machineGetAccessible(IMachine *machine, PRBool *isAccessible) +{ + return machine->vtbl->GetAccessible(machine, isAccessible); +} - VBOX_UTF8_FREE(machineNameUtf8); - VBOX_UTF16_FREE(machineNameUtf16); +static nsresult +_machineGetState(IMachine *machine, PRUint32 *state) +{ + return machine->vtbl->GetState(machine, state); +} - if (!dom) - goto cleanup; +static nsresult +_machineGetName(IMachine *machine, PRUnichar **name) +{ + return machine->vtbl->GetName(machine, name); +} - if (active) - dom->id = i + 1; +static nsresult +_machineGetId(IMachine *machine, vboxIIDUnion *iidu) +{ + return machine->vtbl->GetId(machine, &IID_MEMBER(value)); +} - doms[count++] = dom; - } - } - } +static nsresult +_machineGetBIOSSettings(IMachine *machine, IBIOSSettings **bios) +{ + return machine->vtbl->GetBIOSSettings(machine, bios); +} - if (doms) { - /* safe to ignore, new size will be equal or less than - * previous allocation*/ - ignore_value(VIR_REALLOC_N(doms, count + 1)); - *domains = doms; - doms = NULL; - } +static nsresult +_machineGetAudioAdapter(IMachine *machine, IAudioAdapter **audioadapter) +{ + return machine->vtbl->GetAudioAdapter(machine, audioadapter); +} - ret = count; +static nsresult +_machineGetNetworkAdapter(IMachine *machine, PRUint32 slot, INetworkAdapter **adapter) +{ + return machine->vtbl->GetNetworkAdapter(machine, slot, adapter); +} - cleanup: - if (doms) { - for (i = 0; i < count; i++) { - if (doms[i]) - virDomainFree(doms[i]); - } - } - VIR_FREE(doms); +static nsresult +_machineGetChipsetType(IMachine *machine ATTRIBUTE_UNUSED, PRUint32 *chipsetType ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION >= 4001000 + return machine->vtbl->GetChipsetType(machine, chipsetType); +#else /* VBOX_API_VERSION < 4001000 */ + vboxUnsupported(); + return 0; +#endif /* VBOX_API_VERSION < 4001000 */ +} - vboxArrayRelease(&machines); - return ret; +static nsresult +_machineGetSerialPort(IMachine *machine, PRUint32 slot, ISerialPort **port) +{ + return machine->vtbl->GetSerialPort(machine, slot, port); } -#undef MATCH +static nsresult +_machineGetParallelPort(IMachine *machine, PRUint32 slot, IParallelPort **port) +{ + return machine->vtbl->GetParallelPort(machine, slot, port); +} -static int -vboxNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, - virNodeInfoPtr nodeinfo) +static nsresult +_machineGetVRDxServer(IMachine *machine, IVRDxServer **VRDxServer) { - return nodeGetInfo(nodeinfo); +#if VBOX_API_VERSION < 4000000 + return machine->vtbl->GetVRDPServer(machine, VRDxServer); +#else /* VBOX_API_VERSION >= 4000000 */ + return machine->vtbl->GetVRDEServer(machine, VRDxServer); +#endif /* VBOX_API_VERSION >= 4000000 */ } +static nsresult +_machineGetUSBCommon(IMachine *machine, IUSBCommon **USBCommon) +{ +#if VBOX_API_VERSION < 4003000 + return machine->vtbl->GetUSBController(machine, USBCommon); +#else + return machine->vtbl->GetUSBDeviceFilters(machine, USBCommon); +#endif +} -static int -vboxNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, - unsigned long long *freeMems, - int startCell, - int maxCells) +static nsresult +_machineSetCPUCount(IMachine *machine, PRUint32 CPUCount) { - return nodeGetCellsFreeMemory(freeMems, startCell, maxCells); + return machine->vtbl->SetCPUCount(machine, CPUCount); } +static nsresult +_machineSetMemorySize(IMachine *machine, PRUint32 memorySize) +{ + return machine->vtbl->SetMemorySize(machine, memorySize); +} -static unsigned long long -vboxNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) +static nsresult +_machineSetCPUProperty(IMachine *machine, PRUint32 property ATTRIBUTE_UNUSED, PRBool value) { - unsigned long long freeMem; - if (nodeGetMemory(NULL, &freeMem) < 0) - return 0; - return freeMem; +#if VBOX_API_VERSION < 3001000 + return machine->vtbl->SetPAEEnabled(machine, value); +#elif VBOX_API_VERSION == 3001000 + return machine->vtbl->SetCpuProperty(machine, property, value); +#elif VBOX_API_VERSION >= 3002000 + return machine->vtbl->SetCPUProperty(machine, property, value); +#endif } +static nsresult +_machineSetBootOrder(IMachine *machine, PRUint32 position, PRUint32 device) +{ + return machine->vtbl->SetBootOrder(machine, position, device); +} -static int -vboxNodeGetFreePages(virConnectPtr conn ATTRIBUTE_UNUSED, - unsigned int npages, - unsigned int *pages, - int startCell, - unsigned int cellCount, - unsigned long long *counts, - unsigned int flags) +static nsresult +_machineSetVRAMSize(IMachine *machine, PRUint32 VRAMSize) { - virCheckFlags(0, -1); + return machine->vtbl->SetVRAMSize(machine, VRAMSize); +} - return nodeGetFreePages(npages, pages, startCell, cellCount, counts); +static nsresult +_machineSetMonitorCount(IMachine *machine, PRUint32 monitorCount) +{ + return machine->vtbl->SetMonitorCount(machine, monitorCount); } -static int _pfnInitialize(vboxGlobalData *data) +static nsresult +_machineSetAccelerate3DEnabled(IMachine *machine, PRBool accelerate3DEnabled) { - data->pFuncs = g_pfnGetFunctions(VBOX_XPCOMC_VERSION); - if (data->pFuncs == NULL) - return -1; -#if VBOX_XPCOMC_VERSION == 0x00010000U - data->pFuncs->pfnComInitialize(&data->vboxObj, &data->vboxSession); -#else /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */ - data->pFuncs->pfnComInitialize(IVIRTUALBOX_IID_STR, &data->vboxObj, ISESSION_IID_STR, &data->vboxSession); -#endif /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */ - return 0; + return machine->vtbl->SetAccelerate3DEnabled(machine, accelerate3DEnabled); } -static int -_initializeDomainEvent(vboxGlobalData *data ATTRIBUTE_UNUSED) +static nsresult +_machineSetAccelerate2DVideoEnabled(IMachine *machine ATTRIBUTE_UNUSED, + PRBool accelerate2DVideoEnabled ATTRIBUTE_UNUSED) { -#if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 - /* No event queue functionality in 2.2.* and 4.* as of now */ +#if VBOX_API_VERSION >= 3001000 + return machine->vtbl->SetAccelerate2DVideoEnabled(machine, accelerate2DVideoEnabled); +#else /* VBOX_API_VERSION < 3001000 */ vboxUnsupported(); -#else /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */ - /* Initialize the fWatch needed for Event Callbacks */ - data->fdWatch = -1; - data->pFuncs->pfnGetEventQueue(&data->vboxQueue); - if (data->vboxQueue == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("nsIEventQueue object is null")); - return -1; - } -#endif /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */ return 0; +#endif /* VBOX_API_VERSION < 3001000 */ } -static -void _registerGlobalData(vboxGlobalData *data ATTRIBUTE_UNUSED) +static nsresult +_machineSetExtraData(IMachine *machine, PRUnichar *key, PRUnichar *value) { -#if VBOX_API_VERSION == 2002000 - vboxUnsupported(); -#else /* VBOX_API_VERSION != 2002000 */ - g_pVBoxGlobalData = data; -#endif /* VBOX_API_VERSION != 2002000 */ + return machine->vtbl->SetExtraData(machine, key, value); +} + +static nsresult +_machineSaveSettings(IMachine *machine) +{ + return machine->vtbl->SaveSettings(machine); } #if VBOX_API_VERSION < 4000000 -# if VBOX_API_VERSION < 3001000 -static void -_detachDevices(vboxGlobalData *data ATTRIBUTE_UNUSED, - IMachine *machine, PRUnichar *hddcnameUtf16) +static nsresult +_sessionOpen(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED) { - /* Disconnect all the drives if present */ - machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 0, 0); - machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 0, 1); - machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 1, 1); + return data->vboxObj->vtbl->OpenSession(data->vboxObj, data->vboxSession, IID_MEMBER(value)); } -# else /* VBOX_API_VERSION >= 3001000 */ -static void -_detachDevices(vboxGlobalData *data, IMachine *machine, - PRUnichar *hddcnameUtf16 ATTRIBUTE_UNUSED) + +static nsresult +_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED) { - /* get all the controller first, then the attachments and - * remove them all so that the machine can be undefined - */ - vboxArray storageControllers = VBOX_ARRAY_INITIALIZER; - size_t i = 0, j = 0; + return data->vboxObj->vtbl->OpenExistingSession(data->vboxObj, data->vboxSession, IID_MEMBER(value)); +} - vboxArrayGet(&storageControllers, machine, - machine->vtbl->GetStorageControllers); +static nsresult +_sessionClose(ISession *session) +{ + return session->vtbl->Close(session); +} - for (i = 0; i < storageControllers.count; i++) { - IStorageController *strCtl = storageControllers.items[i]; - PRUnichar *strCtlName = NULL; - vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER; +#else /* VBOX_API_VERSION >= 4000000 */ - if (!strCtl) - continue; +static nsresult +_sessionOpen(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine) +{ + return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Write); +} - strCtl->vtbl->GetName(strCtl, &strCtlName); - vboxArrayGetWithPtrArg(&mediumAttachments, machine, - machine->vtbl->GetMediumAttachmentsOfController, - strCtlName); +static nsresult +_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine) +{ + return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Shared); +} - for (j = 0; j < mediumAttachments.count; j++) { - IMediumAttachment *medAtt = mediumAttachments.items[j]; - PRInt32 port = ~0U; - PRInt32 device = ~0U; +static nsresult +_sessionClose(ISession *session) +{ + return session->vtbl->UnlockMachine(session); +} - if (!medAtt) - continue; +#endif /* VBOX_API_VERSION >= 4000000 */ - medAtt->vtbl->GetPort(medAtt, &port); - medAtt->vtbl->GetDevice(medAtt, &device); +static nsresult +_sessionGetConsole(ISession *session, IConsole **console) +{ + return session->vtbl->GetConsole(session, console); +} - if ((port != ~0U) && (device != ~0U)) { - machine->vtbl->DetachDevice(machine, - strCtlName, - port, - device); - } - } - vboxArrayRelease(&storageControllers); - machine->vtbl->RemoveStorageController(machine, strCtlName); - VBOX_UTF16_FREE(strCtlName); - } - vboxArrayRelease(&storageControllers); +static nsresult +_sessionGetMachine(ISession *session, IMachine **machine) +{ + return session->vtbl->GetMachine(session, machine); +} + +static nsresult +_consoleSaveState(IConsole *console, IProgress **progress) +{ + return console->vtbl->SaveState(console, progress); +} + +static nsresult +_progressWaitForCompletion(IProgress *progress, PRInt32 timeout) +{ + return progress->vtbl->WaitForCompletion(progress, timeout); +} + +static nsresult +_progressGetResultCode(IProgress *progress, resultCodeUnion *resultCode) +{ +#if VBOX_API_VERSION == 2002000 + return progress->vtbl->GetResultCode(progress, &resultCode->uResultCode); +#else /* VBOX_API_VERSION != 2002000 */ + return progress->vtbl->GetResultCode(progress, &resultCode->resultCode); +#endif /* VBOX_API_VERSION != 2002000 */ +} + +static nsresult +_systemPropertiesGetMaxGuestCPUCount(ISystemProperties *systemProperties, PRUint32 *maxCPUCount) +{ + return systemProperties->vtbl->GetMaxGuestCPUCount(systemProperties, maxCPUCount); } -# endif /* VBOX_API_VERSION >= 3001000 */ static nsresult -_unregisterMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine) +_systemPropertiesGetMaxBootPosition(ISystemProperties *systemProperties, PRUint32 *maxBootPosition) { - return data->vboxObj->vtbl->UnregisterMachine(data->vboxObj, IID_MEMBER(value), machine); + return systemProperties->vtbl->GetMaxBootPosition(systemProperties, maxBootPosition); } -static void -_deleteConfig(IMachine *machine) +static nsresult +_systemPropertiesGetMaxNetworkAdapters(ISystemProperties *systemProperties, PRUint32 chipset ATTRIBUTE_UNUSED, + PRUint32 *maxNetworkAdapters) { - machine->vtbl->DeleteSettings(machine); +#if VBOX_API_VERSION < 4001000 + return systemProperties->vtbl->GetNetworkAdapterCount(systemProperties, + maxNetworkAdapters); +#else /* VBOX_API_VERSION >= 4000000 */ + return systemProperties->vtbl->GetMaxNetworkAdapters(systemProperties, chipset, + maxNetworkAdapters); +#endif /* VBOX_API_VERSION >= 4000000 */ } -#else /* VBOX_API_VERSION >= 4000000 */ - -static void -_detachDevices(vboxGlobalData *data ATTRIBUTE_UNUSED, - IMachine *machine ATTRIBUTE_UNUSED, - PRUnichar *hddcnameUtf16 ATTRIBUTE_UNUSED) +static nsresult +_systemPropertiesGetSerialPortCount(ISystemProperties *systemProperties, PRUint32 *SerialPortCount) { - vboxUnsupported(); + return systemProperties->vtbl->GetSerialPortCount(systemProperties, SerialPortCount); } static nsresult -_unregisterMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine) +_systemPropertiesGetParallelPortCount(ISystemProperties *systemProperties, PRUint32 *ParallelPortCount) { - nsresult rc; - vboxArray media = VBOX_ARRAY_INITIALIZER; - rc = VBOX_OBJECT_GET_MACHINE(IID_MEMBER(value), machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching uuid")); - return rc; - } + return systemProperties->vtbl->GetParallelPortCount(systemProperties, ParallelPortCount); +} - /* We're not interested in the array returned by the Unregister method, - * but in the side effect of unregistering the virtual machine. In order - * to call the Unregister method correctly we need to use the vboxArray - * wrapper here. */ - rc = vboxArrayGetWithUintArg(&media, *machine, (*machine)->vtbl->Unregister, - CleanupMode_DetachAllReturnNone); - vboxArrayUnalloc(&media); - return rc; +#if VBOX_API_VERSION >= 3001000 +static nsresult +_systemPropertiesGetMaxPortCountForStorageBus(ISystemProperties *systemProperties, PRUint32 bus, + PRUint32 *maxPortCount) +{ + return systemProperties->vtbl->GetMaxPortCountForStorageBus(systemProperties, bus, maxPortCount); } -static void -_deleteConfig(IMachine *machine) +static nsresult +_systemPropertiesGetMaxDevicesPerPortForStorageBus(ISystemProperties *systemProperties, + PRUint32 bus, PRUint32 *maxDevicesPerPort) { - IProgress *progress = NULL; + return systemProperties->vtbl->GetMaxDevicesPerPortForStorageBus(systemProperties, + bus, maxDevicesPerPort); +} +#else /* VBOX_API_VERSION < 3001000 */ +static nsresult +_systemPropertiesGetMaxPortCountForStorageBus(ISystemProperties *systemProperties ATTRIBUTE_UNUSED, + PRUint32 bus ATTRIBUTE_UNUSED, + PRUint32 *maxPortCount ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); + return 0; +} - /* The IMachine Delete method takes an array of IMedium items to be - * deleted along with the virtual machine. We just want to pass an - * empty array. But instead of adding a full vboxArraySetWithReturn to - * the glue layer (in order to handle the required signature of the - * Delete method) we use a local solution here. */ -# ifdef WIN32 - SAFEARRAY *safeArray = NULL; - typedef HRESULT __stdcall (*IMachine_Delete)(IMachine *self, - SAFEARRAY **media, - IProgress **progress); +static nsresult +_systemPropertiesGetMaxDevicesPerPortForStorageBus(ISystemProperties *systemProperties ATTRIBUTE_UNUSED, + PRUint32 bus ATTRIBUTE_UNUSED, + PRUint32 *maxDevicesPerPort ATTRIBUTE_UNUSED) +{ + vboxUnsupported(); + return 0; +} +#endif -# if VBOX_API_VERSION < 4003000 - ((IMachine_Delete)machine->vtbl->Delete)(machine, &safeArray, &progress); -# else - ((IMachine_Delete)machine->vtbl->DeleteConfig)(machine, &safeArray, &progress); -# endif -# else - /* XPCOM doesn't like NULL as an array, even when the array size is 0. - * Instead pass it a dummy array to avoid passing NULL. */ - IMedium *array[] = { NULL }; -# if VBOX_API_VERSION < 4003000 - machine->vtbl->Delete(machine, 0, array, &progress); -# else - machine->vtbl->DeleteConfig(machine, 0, array, &progress); -# endif -# endif - if (progress != NULL) { - progress->vtbl->WaitForCompletion(progress, -1); - VBOX_RELEASE(progress); - } +static nsresult +_biosSettingsSetACPIEnabled(IBIOSSettings *bios, PRBool ACPIEnabled) +{ + return bios->vtbl->SetACPIEnabled(bios, ACPIEnabled); } -#endif /* VBOX_API_VERSION >= 4000000 */ +static nsresult +_biosSettingsSetIOAPICEnabled(IBIOSSettings *bios, PRBool IOAPICEnabled) +{ + return bios->vtbl->SetIOAPICEnabled(bios, IOAPICEnabled); +} -static void _pfnUninitialize(vboxGlobalData *data) +static nsresult +_audioAdapterSetEnabled(IAudioAdapter *audioAdapter, PRBool enabled) { - if (data->pFuncs) - data->pFuncs->pfnComUninitialize(); + return audioAdapter->vtbl->SetEnabled(audioAdapter, enabled); } -static void _pfnComUnallocMem(PCVBOXXPCOM pFuncs, void *pv) +static nsresult +_audioAdapterSetAudioController(IAudioAdapter *audioAdapter, PRUint32 audioController) { - pFuncs->pfnComUnallocMem(pv); + return audioAdapter->vtbl->SetAudioController(audioAdapter, audioController); } -static void _pfnUtf16Free(PCVBOXXPCOM pFuncs, PRUnichar *pwszString) +static nsresult +_networkAdapterSetEnabled(INetworkAdapter *adapter, PRBool enabled) { - pFuncs->pfnUtf16Free(pwszString); + return adapter->vtbl->SetEnabled(adapter, enabled); } -static void _pfnUtf8Free(PCVBOXXPCOM pFuncs, char *pszString) +static nsresult +_networkAdapterSetAdapterType(INetworkAdapter *adapter, PRUint32 adapterType) { - pFuncs->pfnUtf8Free(pszString); + return adapter->vtbl->SetAdapterType(adapter, adapterType); } -static int _pfnUtf16ToUtf8(PCVBOXXPCOM pFuncs, const PRUnichar *pwszString, char **ppszString) +static nsresult +_networkAdapterSetInternalNetwork(INetworkAdapter *adapter, PRUnichar *internalNetwork) { - return pFuncs->pfnUtf16ToUtf8(pwszString, ppszString); + return adapter->vtbl->SetInternalNetwork(adapter, internalNetwork); } -static int _pfnUtf8ToUtf16(PCVBOXXPCOM pFuncs, const char *pszString, PRUnichar **ppwszString) +static nsresult +_networkAdapterSetMACAddress(INetworkAdapter *adapter, PRUnichar *MACAddress) { - return pFuncs->pfnUtf8ToUtf16(pszString, ppwszString); + return adapter->vtbl->SetMACAddress(adapter, MACAddress); } -#if VBOX_API_VERSION == 2002000 +#if VBOX_API_VERSION < 4001000 -static void _vboxIIDInitialize(vboxIIDUnion *iidu) +static nsresult +_networkAdapterSetBridgedInterface(INetworkAdapter *adapter, PRUnichar *hostInterface) { - memset(iidu, 0, sizeof(vboxIIDUnion)); + return adapter->vtbl->SetHostInterface(adapter, hostInterface); } -static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu) +static nsresult +_networkAdapterSetHostOnlyInterface(INetworkAdapter *adapter, PRUnichar *hostOnlyInterface) { -# ifdef WIN32 - DEBUGUUID(msg, (nsID *)&IID_MEMBER(value)); -# else /* !WIN32 */ - DEBUGUUID(msg, IID_MEMBER(value)); -# endif /* !WIN32 */ + return adapter->vtbl->SetHostInterface(adapter, hostOnlyInterface); } -#else /* VBOX_API_VERSION != 2002000 */ - -static void _vboxIIDInitialize(vboxIIDUnion *iidu) +static nsresult +_networkAdapterAttachToBridgedInterface(INetworkAdapter *adapter) { - memset(iidu, 0, sizeof(vboxIIDUnion)); - IID_MEMBER(owner) = true; + return adapter->vtbl->AttachToBridgedInterface(adapter); } -static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu) +static nsresult +_networkAdapterAttachToInternalNetwork(INetworkAdapter *adapter) { - DEBUGPRUnichar(msg, IID_MEMBER(value)); + return adapter->vtbl->AttachToInternalNetwork(adapter); } -#endif /* VBOX_API_VERSION != 2002000 */ +static nsresult +_networkAdapterAttachToHostOnlyInterface(INetworkAdapter *adapter) +{ + return adapter->vtbl->AttachToHostOnlyInterface(adapter); +} -static void* _handleGetMachines(IVirtualBox *vboxObj) +static nsresult +_networkAdapterAttachToNAT(INetworkAdapter *adapter) { - return vboxObj->vtbl->GetMachines; + return adapter->vtbl->AttachToNAT(adapter); } -static nsresult _nsisupportsRelease(nsISupports *nsi) +#else /* VBOX_API_VERSION >= 4001000 */ + +static nsresult +_networkAdapterSetBridgedInterface(INetworkAdapter *adapter, PRUnichar *bridgedInterface) { - return nsi->vtbl->Release(nsi); + return adapter->vtbl->SetBridgedInterface(adapter, bridgedInterface); } static nsresult -_virtualboxGetVersion(IVirtualBox *vboxObj, PRUnichar **versionUtf16) +_networkAdapterSetHostOnlyInterface(INetworkAdapter *adapter, PRUnichar *hostOnlyInterface) { - return vboxObj->vtbl->GetVersion(vboxObj, versionUtf16); + return adapter->vtbl->SetHostOnlyInterface(adapter, hostOnlyInterface); } -#if VBOX_API_VERSION < 4000000 +static nsresult +_networkAdapterAttachToBridgedInterface(INetworkAdapter *adapter) +{ + return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Bridged); +} static nsresult -_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine) +_networkAdapterAttachToInternalNetwork(INetworkAdapter *adapter) { - return vboxObj->vtbl->GetMachine(vboxObj, IID_MEMBER(value), machine); + return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Internal); } -#else /* VBOX_API_VERSION >= 4000000 */ +static nsresult +_networkAdapterAttachToHostOnlyInterface(INetworkAdapter *adapter) +{ + return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_HostOnly); +} static nsresult -_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine) +_networkAdapterAttachToNAT(INetworkAdapter *adapter) { - return vboxObj->vtbl->FindMachine(vboxObj, IID_MEMBER(value), machine); + return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_NAT); } -#endif /* VBOX_API_VERSION >= 4000000 */ +#endif /* VBOX_API_VERSION >= 4001000 */ static nsresult -_virtualboxGetSystemProperties(IVirtualBox *vboxObj, ISystemProperties **systemProperties) +_serialPortSetEnabled(ISerialPort *port, PRBool enabled) { - return vboxObj->vtbl->GetSystemProperties(vboxObj, systemProperties); + return port->vtbl->SetEnabled(port, enabled); } static nsresult -_machineGetAccessible(IMachine *machine, PRBool *isAccessible) +_serialPortSetPath(ISerialPort *port, PRUnichar *path) { - return machine->vtbl->GetAccessible(machine, isAccessible); + return port->vtbl->SetPath(port, path); } static nsresult -_machineGetState(IMachine *machine, PRUint32 *state) +_serialPortSetIRQ(ISerialPort *port, PRUint32 IRQ) { - return machine->vtbl->GetState(machine, state); + return port->vtbl->SetIRQ(port, IRQ); } static nsresult -_machineGetName(IMachine *machine, PRUnichar **name) +_serialPortSetIOBase(ISerialPort *port, PRUint32 IOBase) { - return machine->vtbl->GetName(machine, name); + return port->vtbl->SetIOBase(port, IOBase); } static nsresult -_machineGetId(IMachine *machine, vboxIIDUnion *iidu) +_serialPortSetHostMode(ISerialPort *port, PRUint32 hostMode) { - return machine->vtbl->GetId(machine, &IID_MEMBER(value)); + return port->vtbl->SetHostMode(port, hostMode); } static nsresult -_machineSaveSettings(IMachine *machine) +_parallelPortSetEnabled(IParallelPort *port, PRBool enabled) { - return machine->vtbl->SaveSettings(machine); + return port->vtbl->SetEnabled(port, enabled); } -#if VBOX_API_VERSION < 4000000 - static nsresult -_sessionOpen(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED) +_parallelPortSetPath(IParallelPort *port, PRUnichar *path) { - return data->vboxObj->vtbl->OpenSession(data->vboxObj, data->vboxSession, IID_MEMBER(value)); + return port->vtbl->SetPath(port, path); } static nsresult -_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED) +_parallelPortSetIRQ(IParallelPort *port, PRUint32 IRQ) { - return data->vboxObj->vtbl->OpenExistingSession(data->vboxObj, data->vboxSession, IID_MEMBER(value)); + return port->vtbl->SetIRQ(port, IRQ); } static nsresult -_sessionClose(ISession *session) +_parallelPortSetIOBase(IParallelPort *port, PRUint32 IOBase) { - return session->vtbl->Close(session); + return port->vtbl->SetIOBase(port, IOBase); } -#else /* VBOX_API_VERSION >= 4000000 */ +static nsresult +_vrdxServerSetEnabled(IVRDxServer *VRDxServer, PRBool enabled) +{ + return VRDxServer->vtbl->SetEnabled(VRDxServer, enabled); +} static nsresult -_sessionOpen(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine) +_vrdxServerSetPorts(vboxGlobalData *data ATTRIBUTE_UNUSED, + IVRDxServer *VRDxServer, virDomainGraphicsDefPtr graphics) { - return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Write); + nsresult rc = 0; +#if VBOX_API_VERSION < 3001000 + if (graphics->data.rdp.port) { + rc = VRDxServer->vtbl->SetPort(VRDxServer, + graphics->data.rdp.port); + VIR_DEBUG("VRDP Port changed to: %d", + graphics->data.rdp.port); + } else if (graphics->data.rdp.autoport) { + /* Setting the port to 0 will reset its value to + * the default one which is 3389 currently + */ + rc = VRDxServer->vtbl->SetPort(VRDxServer, 0); + VIR_DEBUG("VRDP Port changed to default, which is 3389 currently"); + } +#elif VBOX_API_VERSION < 4000000 /* 3001000 <= VBOX_API_VERSION < 4000000 */ + PRUnichar *portUtf16 = NULL; + portUtf16 = PRUnicharFromInt(graphics->data.rdp.port); + rc = VRDxServer->vtbl->SetPorts(VRDxServer, portUtf16); + VBOX_UTF16_FREE(portUtf16); +#else /* VBOX_API_VERSION >= 4000000 */ + PRUnichar *VRDEPortsKey = NULL; + PRUnichar *VRDEPortsValue = NULL; + VBOX_UTF8_TO_UTF16("TCP/Ports", &VRDEPortsKey); + VRDEPortsValue = PRUnicharFromInt(graphics->data.rdp.port); + rc = VRDxServer->vtbl->SetVRDEProperty(VRDxServer, VRDEPortsKey, + VRDEPortsValue); + VBOX_UTF16_FREE(VRDEPortsKey); + VBOX_UTF16_FREE(VRDEPortsValue); +#endif /* VBOX_API_VERSION >= 4000000 */ + return rc; } static nsresult -_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine) +_vrdxServerSetReuseSingleConnection(IVRDxServer *VRDxServer, PRBool enabled) { - return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Shared); + return VRDxServer->vtbl->SetReuseSingleConnection(VRDxServer, enabled); } static nsresult -_sessionClose(ISession *session) +_vrdxServerSetAllowMultiConnection(IVRDxServer *VRDxServer, PRBool enabled) { - return session->vtbl->UnlockMachine(session); + return VRDxServer->vtbl->SetAllowMultiConnection(VRDxServer, enabled); } +static nsresult +_vrdxServerSetNetAddress(vboxGlobalData *data ATTRIBUTE_UNUSED, + IVRDxServer *VRDxServer, PRUnichar *netAddress) +{ +#if VBOX_API_VERSION < 4000000 + return VRDxServer->vtbl->SetNetAddress(VRDxServer, + netAddress); +#else /* VBOX_API_VERSION >= 4000000 */ + PRUnichar *netAddressKey = NULL; + nsresult rc; + VBOX_UTF8_TO_UTF16("TCP/Address", &netAddressKey); + rc = VRDxServer->vtbl->SetVRDEProperty(VRDxServer, netAddressKey, + netAddress); + VBOX_UTF16_FREE(netAddressKey); + return rc; #endif /* VBOX_API_VERSION >= 4000000 */ +} static nsresult -_sessionGetConsole(ISession *session, IConsole **console) +_usbCommonEnable(IUSBCommon *USBCommon ATTRIBUTE_UNUSED) { - return session->vtbl->GetConsole(session, console); + nsresult rc = 0; +#if VBOX_API_VERSION < 4003000 + USBCommon->vtbl->SetEnabled(USBCommon, 1); +# if VBOX_API_VERSION < 4002000 + rc = USBCommon->vtbl->SetEnabledEhci(USBCommon, 1); +# else /* VBOX_API_VERSION >= 4002000 */ + rc = USBCommon->vtbl->SetEnabledEHCI(USBCommon, 1); +# endif /* VBOX_API_VERSION >= 4002000 */ +#endif /* VBOX_API_VERSION >= 4003000 */ + /* We don't need to set usb enabled for vbox 4.3 and later */ + return rc; } static nsresult -_sessionGetMachine(ISession *session, IMachine **machine) +_usbCommonCreateDeviceFilter(IUSBCommon *USBCommon, PRUnichar *name, + IUSBDeviceFilter **filter) { - return session->vtbl->GetMachine(session, machine); + return USBCommon->vtbl->CreateDeviceFilter(USBCommon, name, filter); } static nsresult -_consoleSaveState(IConsole *console, IProgress **progress) +_usbCommonInsertDeviceFilter(IUSBCommon *USBCommon, PRUint32 position, + IUSBDeviceFilter *filter) { - return console->vtbl->SaveState(console, progress); + return USBCommon->vtbl->InsertDeviceFilter(USBCommon, position, filter); } static nsresult -_progressWaitForCompletion(IProgress *progress, PRInt32 timeout) +_usbDeviceFilterSetProductId(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *productId) { - return progress->vtbl->WaitForCompletion(progress, timeout); + return USBDeviceFilter->vtbl->SetProductId(USBDeviceFilter, productId); } static nsresult -_progressGetResultCode(IProgress *progress, resultCodeUnion *resultCode) +_usbDeviceFilterSetActive(IUSBDeviceFilter *USBDeviceFilter, PRBool active) { -#if VBOX_API_VERSION == 2002000 - return progress->vtbl->GetResultCode(progress, &resultCode->uResultCode); -#else /* VBOX_API_VERSION != 2002000 */ - return progress->vtbl->GetResultCode(progress, &resultCode->resultCode); -#endif /* VBOX_API_VERSION != 2002000 */ + return USBDeviceFilter->vtbl->SetActive(USBDeviceFilter, active); } static nsresult -_systemPropertiesGetMaxGuestCPUCount(ISystemProperties *systemProperties, PRUint32 *maxCPUCount) +_usbDeviceFilterSetVendorId(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *vendorId) { - return systemProperties->vtbl->GetMaxGuestCPUCount(systemProperties, maxCPUCount); + return USBDeviceFilter->vtbl->SetVendorId(USBDeviceFilter, vendorId); +} + +static nsresult _mediumGetId(IMedium *medium, vboxIIDUnion *iidu) +{ + return medium->vtbl->GetId(medium, &IID_MEMBER(value)); +} + +static nsresult _mediumRelease(IMedium *medium) +{ + return medium->vtbl->nsisupports.Release((nsISupports *)medium); +} + +static nsresult _mediumSetType(IMedium *medium ATTRIBUTE_UNUSED, + PRUint32 type ATTRIBUTE_UNUSED) +{ +#if VBOX_API_VERSION > 3000000 + return medium->vtbl->SetType(medium, type); +#else + vboxUnsupported(); + return 0; +#endif } static bool _machineStateOnline(PRUint32 state) @@ -11237,13 +10924,37 @@ static vboxUniformedIVirtualBox _UIVirtualBox = { .GetVersion = _virtualboxGetVersion, .GetMachine = _virtualboxGetMachine, .GetSystemProperties = _virtualboxGetSystemProperties, + .CreateMachine = _virtualboxCreateMachine, + .RegisterMachine = _virtualboxRegisterMachine, + .FindMedium = _virtualboxFindMedium, + .OpenMedium = _virtualboxOpenMedium, }; static vboxUniformedIMachine _UIMachine = { + .AddStorageController = _machineAddStorageController, + .AttachDevice = _machineAttachDevice, + .CreateSharedFolder = _machineCreateSharedFolder, .GetAccessible = _machineGetAccessible, .GetState = _machineGetState, .GetName = _machineGetName, .GetId = _machineGetId, + .GetBIOSSettings = _machineGetBIOSSettings, + .GetAudioAdapter = _machineGetAudioAdapter, + .GetNetworkAdapter = _machineGetNetworkAdapter, + .GetChipsetType = _machineGetChipsetType, + .GetSerialPort = _machineGetSerialPort, + .GetParallelPort = _machineGetParallelPort, + .GetVRDxServer = _machineGetVRDxServer, + .GetUSBCommon = _machineGetUSBCommon, + .SetCPUCount = _machineSetCPUCount, + .SetMemorySize = _machineSetMemorySize, + .SetCPUProperty = _machineSetCPUProperty, + .SetBootOrder = _machineSetBootOrder, + .SetVRAMSize = _machineSetVRAMSize, + .SetMonitorCount = _machineSetMonitorCount, + .SetAccelerate3DEnabled = _machineSetAccelerate3DEnabled, + .SetAccelerate2DVideoEnabled = _machineSetAccelerate2DVideoEnabled, + .SetExtraData = _machineSetExtraData, .SaveSettings = _machineSaveSettings, }; @@ -11266,6 +10977,76 @@ static vboxUniformedIProgress _UIProgress = { static vboxUniformedISystemProperties _UISystemProperties = { .GetMaxGuestCPUCount = _systemPropertiesGetMaxGuestCPUCount, + .GetMaxBootPosition = _systemPropertiesGetMaxBootPosition, + .GetMaxNetworkAdapters = _systemPropertiesGetMaxNetworkAdapters, + .GetSerialPortCount = _systemPropertiesGetSerialPortCount, + .GetParallelPortCount = _systemPropertiesGetParallelPortCount, + .GetMaxPortCountForStorageBus = _systemPropertiesGetMaxPortCountForStorageBus, + .GetMaxDevicesPerPortForStorageBus = _systemPropertiesGetMaxDevicesPerPortForStorageBus, +}; + +static vboxUniformedIBIOSSettings _UIBIOSSettings = { + .SetACPIEnabled = _biosSettingsSetACPIEnabled, + .SetIOAPICEnabled = _biosSettingsSetIOAPICEnabled, +}; + +static vboxUniformedIAudioAdapter _UIAudioAdapter = { + .SetEnabled = _audioAdapterSetEnabled, + .SetAudioController = _audioAdapterSetAudioController, +}; + +static vboxUniformedINetworkAdapter _UINetworkAdapter = { + .SetEnabled = _networkAdapterSetEnabled, + .SetAdapterType = _networkAdapterSetAdapterType, + .SetBridgedInterface = _networkAdapterSetBridgedInterface, + .SetInternalNetwork = _networkAdapterSetInternalNetwork, + .SetHostOnlyInterface = _networkAdapterSetHostOnlyInterface, + .SetMACAddress = _networkAdapterSetMACAddress, + .AttachToBridgedInterface = _networkAdapterAttachToBridgedInterface, + .AttachToInternalNetwork = _networkAdapterAttachToInternalNetwork, + .AttachToHostOnlyInterface = _networkAdapterAttachToHostOnlyInterface, + .AttachToNAT = _networkAdapterAttachToNAT, +}; + +static vboxUniformedISerialPort _UISerialPort = { + .SetEnabled = _serialPortSetEnabled, + .SetPath = _serialPortSetPath, + .SetIRQ = _serialPortSetIRQ, + .SetIOBase = _serialPortSetIOBase, + .SetHostMode = _serialPortSetHostMode, +}; + +static vboxUniformedIParallelPort _UIParallelPort = { + .SetEnabled = _parallelPortSetEnabled, + .SetPath = _parallelPortSetPath, + .SetIRQ = _parallelPortSetIRQ, + .SetIOBase = _parallelPortSetIOBase, +}; + +static vboxUniformedIVRDxServer _UIVRDxServer = { + .SetEnabled = _vrdxServerSetEnabled, + .SetPorts = _vrdxServerSetPorts, + .SetReuseSingleConnection = _vrdxServerSetReuseSingleConnection, + .SetAllowMultiConnection = _vrdxServerSetAllowMultiConnection, + .SetNetAddress = _vrdxServerSetNetAddress, +}; + +static vboxUniformedIUSBCommon _UIUSBCommon = { + .Enable = _usbCommonEnable, + .CreateDeviceFilter = _usbCommonCreateDeviceFilter, + .InsertDeviceFilter = _usbCommonInsertDeviceFilter, +}; + +static vboxUniformedIUSBDeviceFilter _UIUSBDeviceFilter = { + .SetProductId = _usbDeviceFilterSetProductId, + .SetActive = _usbDeviceFilterSetActive, + .SetVendorId = _usbDeviceFilterSetVendorId, +}; + +static vboxUniformedIMedium _UIMedium = { + .GetId = _mediumGetId, + .Release = _mediumRelease, + .SetType = _mediumSetType, }; static uniformedMachineStateChecker _machineStateChecker = { @@ -11281,6 +11062,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->detachDevices = _detachDevices; pVBoxAPI->unregisterMachine = _unregisterMachine; pVBoxAPI->deleteConfig = _deleteConfig; + pVBoxAPI->vboxAttachDrivesOld = _vboxAttachDrivesOld; pVBoxAPI->UPFN = _UPFN; pVBoxAPI->UIID = _UIID; pVBoxAPI->UArray = _UArray; @@ -11291,6 +11073,15 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->UIConsole = _UIConsole; pVBoxAPI->UIProgress = _UIProgress; pVBoxAPI->UISystemProperties = _UISystemProperties; + pVBoxAPI->UIBIOSSettings = _UIBIOSSettings; + pVBoxAPI->UIAudioAdapter = _UIAudioAdapter; + pVBoxAPI->UINetworkAdapter = _UINetworkAdapter; + pVBoxAPI->UISerialPort = _UISerialPort; + pVBoxAPI->UIParallelPort = _UIParallelPort; + pVBoxAPI->UIVRDxServer = _UIVRDxServer; + pVBoxAPI->UIUSBCommon = _UIUSBCommon; + pVBoxAPI->UIUSBDeviceFilter = _UIUSBDeviceFilter; + pVBoxAPI->UIMedium = _UIMedium; pVBoxAPI->machineStateChecker = _machineStateChecker; #if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 @@ -11309,10 +11100,24 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */ pVBoxAPI->getMachineForSession = 1; pVBoxAPI->detachDevicesExplicitly = 0; + pVBoxAPI->vboxAttachDrivesUseOld = 0; #else /* VBOX_API_VERSION < 4000000 */ pVBoxAPI->getMachineForSession = 0; pVBoxAPI->detachDevicesExplicitly = 1; + pVBoxAPI->vboxAttachDrivesUseOld = 1; #endif /* VBOX_API_VERSION < 4000000 */ + +#if VBOX_API_VERSION >= 4001000 + pVBoxAPI->chipsetType = 1; +#else /* VBOX_API_VERSION < 4001000 */ + pVBoxAPI->chipsetType = 0; +#endif /* VBOX_API_VERSION < 4001000 */ + +#if VBOX_API_VERSION >= 3001000 + pVBoxAPI->accelerate2DVideo = 1; +#else /* VBOX_API_VERSION < 3001000 */ + pVBoxAPI->accelerate2DVideo = 0; +#endif /* VBOX_API_VERSION < 3001000 */ } /** diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index 01b91fc..439b1ed 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -180,14 +180,43 @@ typedef struct { nsresult (*GetVersion)(IVirtualBox *vboxObj, PRUnichar **versionUtf16); nsresult (*GetMachine)(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine); nsresult (*GetSystemProperties)(IVirtualBox *vboxObj, ISystemProperties **systemProperties); + nsresult (*CreateMachine)(vboxGlobalData *data, virDomainDefPtr def, IMachine **machine, char *uuidstr); + nsresult (*RegisterMachine)(IVirtualBox *vboxObj, IMachine *machine); + nsresult (*FindMedium)(IVirtualBox *vboxObj, PRUnichar *location, PRUint32 deviceType, PRUint32 accessMode, IMedium **medium); + nsresult (*OpenMedium)(IVirtualBox *vboxObj, PRUnichar *location, PRUint32 deviceType, PRUint32 accessMode, IMedium **medium); } vboxUniformedIVirtualBox; /* Functions for IMachine */ typedef struct { + nsresult (*AddStorageController)(IMachine *machine, PRUnichar *name, + PRUint32 connectionType, IStorageController **controller); + nsresult (*AttachDevice)(IMachine *machine, PRUnichar *name, + PRInt32 controllerPort, PRInt32 device, + PRUint32 type, IMedium *medium); + nsresult (*CreateSharedFolder)(IMachine *machine, PRUnichar *name, + PRUnichar *hostPath, PRBool writable, + PRBool automount); nsresult (*GetAccessible)(IMachine *machine, PRBool *isAccessible); nsresult (*GetState)(IMachine *machine, PRUint32 *state); nsresult (*GetName)(IMachine *machine, PRUnichar **name); nsresult (*GetId)(IMachine *machine, vboxIIDUnion *iidu); + nsresult (*GetBIOSSettings)(IMachine *machine, IBIOSSettings **bios); + nsresult (*GetAudioAdapter)(IMachine *machine, IAudioAdapter **audioAdapter); + nsresult (*GetNetworkAdapter)(IMachine *machine, PRUint32 slot, INetworkAdapter **adapter); + nsresult (*GetChipsetType)(IMachine *machine, PRUint32 *chipsetType); + nsresult (*GetSerialPort)(IMachine *machine, PRUint32 slot, ISerialPort **port); + nsresult (*GetParallelPort)(IMachine *machine, PRUint32 slot, IParallelPort **port); + nsresult (*GetVRDxServer)(IMachine *machine, IVRDxServer **VRDxServer); + nsresult (*GetUSBCommon)(IMachine *machine, IUSBCommon **USBCommon); + nsresult (*SetCPUCount)(IMachine *machine, PRUint32 CPUCount); + nsresult (*SetMemorySize)(IMachine *machine, PRUint32 memorySize); + nsresult (*SetCPUProperty)(IMachine *machine, PRUint32 property, PRBool value); + nsresult (*SetBootOrder)(IMachine *machine, PRUint32 position, PRUint32 device); + nsresult (*SetVRAMSize)(IMachine *machine, PRUint32 VRAMSize); + nsresult (*SetMonitorCount)(IMachine *machine, PRUint32 monitorCount); + nsresult (*SetAccelerate3DEnabled)(IMachine *machine, PRBool accelerate3DEnabled); + nsresult (*SetAccelerate2DVideoEnabled)(IMachine *machine, PRBool accelerate2DVideoEnabled); + nsresult (*SetExtraData)(IMachine *machine, PRUnichar *key, PRUnichar *value); nsresult (*SaveSettings)(IMachine *machine); } vboxUniformedIMachine; @@ -214,8 +243,93 @@ typedef struct { /* Functions for ISystemProperties */ typedef struct { nsresult (*GetMaxGuestCPUCount)(ISystemProperties *systemProperties, PRUint32 *maxCPUCount); + nsresult (*GetMaxBootPosition)(ISystemProperties *systemProperties, PRUint32 *maxBootPosition); + nsresult (*GetMaxNetworkAdapters)(ISystemProperties *systemProperties, PRUint32 chipset, + PRUint32 *maxNetworkAdapters); + nsresult (*GetSerialPortCount)(ISystemProperties *systemProperties, PRUint32 *SerialPortCount); + nsresult (*GetParallelPortCount)(ISystemProperties *systemProperties, PRUint32 *ParallelPortCount); + nsresult (*GetMaxPortCountForStorageBus)(ISystemProperties *systemProperties, PRUint32 bus, + PRUint32 *maxPortCount); + nsresult (*GetMaxDevicesPerPortForStorageBus)(ISystemProperties *systemProperties, + PRUint32 bus, PRUint32 *maxDevicesPerPort); } vboxUniformedISystemProperties; +/* Functions for IBIOSSettings */ +typedef struct { + nsresult (*SetACPIEnabled)(IBIOSSettings *bios, PRBool ACPIEnabled); + nsresult (*SetIOAPICEnabled)(IBIOSSettings *bios, PRBool IOAPICEnabled); +} vboxUniformedIBIOSSettings; + +/* Functions for IAudioAdapter */ +typedef struct { + nsresult (*SetEnabled)(IAudioAdapter *audioAdapter, PRBool enabled); + nsresult (*SetAudioController)(IAudioAdapter *audioAdapter, PRUint32 audioController); +} vboxUniformedIAudioAdapter; + +/* Functions for INetworkAdapter */ +typedef struct { + nsresult (*SetEnabled)(INetworkAdapter *adapter, PRBool enabled); + nsresult (*SetAdapterType)(INetworkAdapter *adapter, PRUint32 adapterType); + nsresult (*SetBridgedInterface)(INetworkAdapter *adapter, PRUnichar *bridgedInterface); + nsresult (*SetInternalNetwork)(INetworkAdapter *adapter, PRUnichar *internalNetwork); + nsresult (*SetHostOnlyInterface)(INetworkAdapter *adapter, PRUnichar *hostOnlyInterface); + nsresult (*SetMACAddress)(INetworkAdapter *adapter, PRUnichar *MACAddress); + nsresult (*AttachToBridgedInterface)(INetworkAdapter *adapter); + nsresult (*AttachToInternalNetwork)(INetworkAdapter *adapter); + nsresult (*AttachToHostOnlyInterface)(INetworkAdapter *adapter); + nsresult (*AttachToNAT)(INetworkAdapter *adapter); +} vboxUniformedINetworkAdapter; + +/* Functions for ISerialPort */ +typedef struct { + nsresult (*SetEnabled)(ISerialPort *port, PRBool enabled); + nsresult (*SetPath)(ISerialPort *port, PRUnichar *path); + nsresult (*SetIRQ)(ISerialPort *port, PRUint32 IRQ); + nsresult (*SetIOBase)(ISerialPort *port, PRUint32 IOBase); + nsresult (*SetHostMode)(ISerialPort *port, PRUint32 hostMode); +} vboxUniformedISerialPort; + +/* Functions for IParallelPort */ +typedef struct { + nsresult (*SetEnabled)(IParallelPort *port, PRBool enabled); + nsresult (*SetPath)(IParallelPort *port, PRUnichar *path); + nsresult (*SetIRQ)(IParallelPort *port, PRUint32 IRQ); + nsresult (*SetIOBase)(IParallelPort *port, PRUint32 IOBase); +} vboxUniformedIParallelPort; + +/* Functions for IVRDPServer and IVRDEServer */ +typedef struct { + nsresult (*SetEnabled)(IVRDxServer *VRDxServer, PRBool enabled); + nsresult (*SetPorts)(vboxGlobalData *data, IVRDxServer *VRDxServer, + virDomainGraphicsDefPtr graphics); + nsresult (*SetReuseSingleConnection)(IVRDxServer *VRDxServer, PRBool enabled); + nsresult (*SetAllowMultiConnection)(IVRDxServer *VRDxServer, PRBool enabled); + nsresult (*SetNetAddress)(vboxGlobalData *data, IVRDxServer *VRDxServer, + PRUnichar *netAddress); +} vboxUniformedIVRDxServer; + +/* Common Functions for IUSBController and IUSBDeviceFilters */ +typedef struct { + nsresult (*Enable)(IUSBCommon *USBCommon); + nsresult (*CreateDeviceFilter)(IUSBCommon *USBCommon, PRUnichar *name, + IUSBDeviceFilter **filter); + nsresult (*InsertDeviceFilter)(IUSBCommon *USBCommon, PRUint32 position, + IUSBDeviceFilter *filter); +} vboxUniformedIUSBCommon; + +typedef struct { + nsresult (*SetProductId)(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *productId); + nsresult (*SetActive)(IUSBDeviceFilter *USBDeviceFilter, PRBool active); + nsresult (*SetVendorId)(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *vendorId); +} vboxUniformedIUSBDeviceFilter; + +/* Functions for IMedium */ +typedef struct { + nsresult (*GetId)(IMedium *medium, vboxIIDUnion *iidu); + nsresult (*Release)(IMedium *medium); + nsresult (*SetType)(IMedium *medium, PRUint32 type); +} vboxUniformedIMedium; + typedef struct { bool (*Online)(PRUint32 state); } uniformedMachineStateChecker; @@ -230,6 +344,7 @@ typedef struct { void (*detachDevices)(vboxGlobalData *data, IMachine *machine, PRUnichar *hddcnameUtf16); nsresult (*unregisterMachine)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine); void (*deleteConfig)(IMachine *machine); + void (*vboxAttachDrivesOld)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine); vboxUniformedPFN UPFN; vboxUniformedIID UIID; vboxUniformedArray UArray; @@ -240,12 +355,24 @@ typedef struct { vboxUniformedIConsole UIConsole; vboxUniformedIProgress UIProgress; vboxUniformedISystemProperties UISystemProperties; + vboxUniformedIBIOSSettings UIBIOSSettings; + vboxUniformedIAudioAdapter UIAudioAdapter; + vboxUniformedINetworkAdapter UINetworkAdapter; + vboxUniformedISerialPort UISerialPort; + vboxUniformedIParallelPort UIParallelPort; + vboxUniformedIVRDxServer UIVRDxServer; + vboxUniformedIUSBCommon UIUSBCommon; + vboxUniformedIUSBDeviceFilter UIUSBDeviceFilter; + vboxUniformedIMedium UIMedium; uniformedMachineStateChecker machineStateChecker; /* vbox API features */ bool domainEventCallbacks; bool hasStaticGlobalData; bool getMachineForSession; bool detachDevicesExplicitly; + bool chipsetType; + bool accelerate2DVideo; + bool vboxAttachDrivesUseOld; } vboxUniformedAPI; /* libvirt API @@ -269,6 +396,7 @@ int vboxConnectNumOfDomains(virConnectPtr conn); virDomainPtr vboxDomainLookupByID(virConnectPtr conn, int id); virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid); +virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml); int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags); /* Version specified functions for installing uniformed API */ -- 1.7.9.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list