summaryrefslogtreecommitdiff
path: root/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp')
-rw-r--r--src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp251
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);