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