diff options
Diffstat (limited to 'src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp')
-rw-r--r-- | src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp | 251 |
1 files changed, 222 insertions, 29 deletions
diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp index f999db8ec..3713bd318 100644 --- a/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp +++ b/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp @@ -1,4 +1,4 @@ -/* $Id: VBoxManageMisc.cpp $ */ +/* $Id: VBoxManageMisc.cpp 38055 2011-07-19 08:55:42Z vboxsync $ */ /** @file * VBoxManage - VirtualBox's command-line interface. */ @@ -149,36 +149,27 @@ int handleUnregisterVM(HandlerArg *a) return errorSyntax(USAGE_UNREGISTERVM, "VM name required"); ComPtr<IMachine> machine; - CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMName).raw(), - machine.asOutParam())); - if (machine) + CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(VMName).raw(), + machine.asOutParam()), + RTEXITCODE_FAILURE); + SafeIfaceArray<IMedium> aMedia; + CHECK_ERROR_RET(machine, Unregister(fDelete ? (CleanupMode_T)CleanupMode_DetachAllReturnHardDisksOnly : (CleanupMode_T)CleanupMode_DetachAllReturnNone, + ComSafeArrayAsOutParam(aMedia)), + RTEXITCODE_FAILURE); + if (fDelete) { - SafeIfaceArray<IMedium> aMedia; - CleanupMode_T cleanupMode = CleanupMode_DetachAllReturnNone; -#if !defined(RT_OS_WINDOWS) || !defined(RT_ARCH_AMD64) - /* XXX currently disabled due to a bug in ComSafeArrayIn on 64-bit Windows hosts! */ - if (fDelete) - cleanupMode = CleanupMode_DetachAllReturnHardDisksOnly; -#endif - CHECK_ERROR(machine, Unregister(cleanupMode, - ComSafeArrayAsOutParam(aMedia))); - if (SUCCEEDED(rc)) - { -#if defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64) - /* XXX currently disabled due to a bug in ComSafeArrayIn on 64-bit Windows hosts! */ - RTPrintf("The ''--delete'' parameter is ignored on Windows/x64 to prevent a crash.\n" - "This will be fixed in the next release."); -#else - if (fDelete) - { - ComPtr<IProgress> pProgress; - CHECK_ERROR(machine, Delete(ComSafeArrayAsInParam(aMedia), pProgress.asOutParam())); - CHECK_ERROR(pProgress, WaitForCompletion(-1)); - } -#endif + ComPtr<IProgress> pProgress; + CHECK_ERROR_RET(machine, Delete(ComSafeArrayAsInParam(aMedia), pProgress.asOutParam()), + RTEXITCODE_FAILURE); + rc = showProgress(pProgress); + if (FAILED(rc)) + { + com::ProgressErrorInfo ErrInfo(pProgress); + com::GluePrintErrorInfo(ErrInfo); + return RTEXITCODE_FAILURE; } } - return SUCCEEDED(rc) ? 0 : 1; + return RTEXITCODE_SUCCESS; } int handleCreateVM(HandlerArg *a) @@ -275,6 +266,200 @@ int handleCreateVM(HandlerArg *a) return SUCCEEDED(rc) ? 0 : 1; } +static const RTGETOPTDEF g_aCloneVMOptions[] = +{ + { "--snapshot", 's', RTGETOPT_REQ_STRING }, + { "--name", 'n', RTGETOPT_REQ_STRING }, + { "--mode", 'm', RTGETOPT_REQ_STRING }, + { "--options", 'o', RTGETOPT_REQ_STRING }, + { "--register", 'r', RTGETOPT_REQ_NOTHING }, + { "--basefolder", 'p', RTGETOPT_REQ_STRING }, + { "--uuid", 'u', RTGETOPT_REQ_STRING }, +}; + +static int parseCloneMode(const char *psz, CloneMode_T *pMode) +{ + if (!RTStrICmp(psz, "machine")) + *pMode = CloneMode_MachineState; +// else if (!RTStrICmp(psz, "machineandchildren")) +// *pMode = CloneMode_MachineAndChildStates; + else if (!RTStrICmp(psz, "all")) + *pMode = CloneMode_AllStates; + else + return VERR_PARSE_ERROR; + + return VINF_SUCCESS; +} + +static int parseCloneOptions(const char *psz, com::SafeArray<CloneOptions_T> *options) +{ + int rc = VINF_SUCCESS; + while (psz && *psz && RT_SUCCESS(rc)) + { + size_t len; + const char *pszComma = strchr(psz, ','); + if (pszComma) + len = pszComma - psz; + else + len = strlen(psz); + if (len > 0) + { + if (!RTStrNICmp(psz, "KeepAllMACs", len)) + options->push_back(CloneOptions_KeepAllMACs); + else if (!RTStrNICmp(psz, "KeepNATMACs", len)) + options->push_back(CloneOptions_KeepNATMACs); + else if (!RTStrNICmp(psz, "KeepDiskNames", len)) + options->push_back(CloneOptions_KeepDiskNames); + else if ( !RTStrNICmp(psz, "Link", len) + || !RTStrNICmp(psz, "Linked", len)) + options->push_back(CloneOptions_Link); + else + rc = VERR_PARSE_ERROR; + } + if (pszComma) + psz += len + 1; + else + psz += len; + } + + return rc; +} + +int handleCloneVM(HandlerArg *a) +{ + HRESULT rc; + const char *pszSrcName = NULL; + const char *pszSnapshotName = NULL; + CloneMode_T mode = CloneMode_MachineState; + com::SafeArray<CloneOptions_T> options; + const char *pszTrgName = NULL; + const char *pszTrgBaseFolder = NULL; + bool fRegister = false; + Bstr bstrUuid; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aCloneVMOptions, RT_ELEMENTS(g_aCloneVMOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 's': // --snapshot + pszSnapshotName = ValueUnion.psz; + break; + + case 'm': // --mode + if (RT_FAILURE(parseCloneMode(ValueUnion.psz, &mode))) + return errorArgument("Invalid clone mode '%s'\n", ValueUnion.psz); + break; + + case 'o': // --options + if (RT_FAILURE(parseCloneOptions(ValueUnion.psz, &options))) + return errorArgument("Invalid clone options '%s'\n", ValueUnion.psz); + break; + + case 'n': // --name + pszTrgName = ValueUnion.psz; + break; + + case 'p': // --basefolder + pszTrgBaseFolder = ValueUnion.psz; + break; + + case 'u': // --uuid + RTUUID trgUuid; + if (RT_FAILURE(RTUuidFromStr(&trgUuid, ValueUnion.psz))) + return errorArgument("Invalid UUID format %s\n", ValueUnion.psz); + else + bstrUuid = Guid(trgUuid).toUtf16().raw(); + break; + + case 'r': // --register + fRegister = true; + break; + + case VINF_GETOPT_NOT_OPTION: + if (!pszSrcName) + pszSrcName = ValueUnion.psz; + else + return errorSyntax(USAGE_CLONEVM, "Invalid parameter '%s'", ValueUnion.psz); + break; + + default: + return errorGetOpt(USAGE_CLONEVM, c, &ValueUnion); + } + } + + /* Check for required options */ + if (!pszSrcName) + return errorSyntax(USAGE_CLONEVM, "VM name required"); + + /* Get the machine object */ + ComPtr<IMachine> srcMachine; + CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(pszSrcName).raw(), + srcMachine.asOutParam()), + RTEXITCODE_FAILURE); + + /* If a snapshot name/uuid was given, get the particular machine of this + * snapshot. */ + if (pszSnapshotName) + { + ComPtr<ISnapshot> srcSnapshot; + CHECK_ERROR_RET(srcMachine, FindSnapshot(Bstr(pszSnapshotName).raw(), + srcSnapshot.asOutParam()), + RTEXITCODE_FAILURE); + CHECK_ERROR_RET(srcSnapshot, COMGETTER(Machine)(srcMachine.asOutParam()), + RTEXITCODE_FAILURE); + } + + /* Default name necessary? */ + if (!pszTrgName) + pszTrgName = RTStrAPrintf2("%s Clone", pszSrcName); + + Bstr bstrSettingsFile; + CHECK_ERROR_RET(a->virtualBox, + ComposeMachineFilename(Bstr(pszTrgName).raw(), + Bstr(pszTrgBaseFolder).raw(), + bstrSettingsFile.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<IMachine> trgMachine; + CHECK_ERROR_RET(a->virtualBox, CreateMachine(bstrSettingsFile.raw(), + Bstr(pszTrgName).raw(), + NULL, + bstrUuid.raw(), + FALSE, + trgMachine.asOutParam()), + RTEXITCODE_FAILURE); + + /* Start the cloning */ + ComPtr<IProgress> progress; + CHECK_ERROR_RET(srcMachine, CloneTo(trgMachine, + mode, + ComSafeArrayAsInParam(options), + progress.asOutParam()), + RTEXITCODE_FAILURE); + rc = showProgress(progress); + if (FAILED(rc)) + { + com::ProgressErrorInfo ErrInfo(progress); + com::GluePrintErrorInfo(ErrInfo); + return RTEXITCODE_FAILURE; + } + + if (fRegister) + CHECK_ERROR_RET(a->virtualBox, RegisterMachine(trgMachine), RTEXITCODE_FAILURE); + + Bstr bstrNewName; + CHECK_ERROR_RET(trgMachine, COMGETTER(Name)(bstrNewName.asOutParam()), RTEXITCODE_FAILURE); + RTPrintf("Machine has been successfully cloned as \"%lS\"\n", bstrNewName.raw()); + + return RTEXITCODE_SUCCESS; +} + int handleStartVM(HandlerArg *a) { HRESULT rc; @@ -439,6 +624,14 @@ int handleAdoptState(HandlerArg *a) machine.asOutParam())); if (machine) { + char szStateFileAbs[RTPATH_MAX] = ""; + int vrc = RTPathAbs(a->argv[1], szStateFileAbs, sizeof(szStateFileAbs)); + if (RT_FAILURE(vrc)) + { + RTMsgError("Cannot convert filename \"%s\" to absolute path", a->argv[0]); + return 1; + } + do { /* we have to open a session for this task */ @@ -447,7 +640,7 @@ int handleAdoptState(HandlerArg *a) { ComPtr<IConsole> console; CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam())); - CHECK_ERROR_BREAK(console, AdoptSavedState(Bstr(a->argv[1]).raw())); + CHECK_ERROR_BREAK(console, AdoptSavedState(Bstr(szStateFileAbs).raw())); } while (0); CHECK_ERROR_BREAK(a->session, UnlockMachine()); } while (0); |