1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2024-12-27 07:22:07 +03:00

vbox: Rewrite vboxDomainCreateWithFlags

This commit is contained in:
Taowei 2014-08-11 18:06:20 +08:00 committed by Michal Privoznik
parent 34364df3c6
commit 815d17398c
3 changed files with 269 additions and 232 deletions

View File

@ -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;
}

View File

@ -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)

View File

@ -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);