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