Changeset 37074 in vbox
- Timestamp:
- May 13, 2011 2:32:50 PM (14 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
r35741 r37074 232 232 #endif /* !VBOX_ONLY_DOCS */ 233 233 234 #ifdef RT_OS_WINDOWS 234 #ifdef RT_OS_WINDOWS 235 235 // Required for ATL 236 236 static CComModule _Module; … … 399 399 { "registervm", USAGE_REGISTERVM, handleRegisterVM }, 400 400 { "unregistervm", USAGE_UNREGISTERVM, handleUnregisterVM }, 401 { "clonevm", USAGE_CLONEVM, handleCloneVM }, 401 402 { "createhd", USAGE_CREATEHD, handleCreateHardDisk }, 402 403 { "createvdi", USAGE_CREATEHD, handleCreateHardDisk }, /* backward compatibility */ -
trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h
r36067 r37074 45 45 #define USAGE_CREATEVM RT_BIT_64(4) 46 46 #define USAGE_MODIFYVM RT_BIT_64(5) 47 #define USAGE_STARTVM RT_BIT_64(6) 48 #define USAGE_CONTROLVM RT_BIT_64(7) 49 #define USAGE_DISCARDSTATE RT_BIT_64(8) 50 #define USAGE_SNAPSHOT RT_BIT_64(9) 47 #define USAGE_CLONEVM RT_BIT_64(6) 48 #define USAGE_STARTVM RT_BIT_64(7) 49 #define USAGE_CONTROLVM RT_BIT_64(8) 50 #define USAGE_DISCARDSTATE RT_BIT_64(9) 51 #define USAGE_SNAPSHOT RT_BIT_64(10) 51 52 #define USAGE_CLOSEMEDIUM RT_BIT_64(11) 52 53 #define USAGE_SHOWHDINFO RT_BIT_64(12) … … 210 211 int handleUnregisterVM(HandlerArg *a); 211 212 int handleCreateVM(HandlerArg *a); 213 int handleCloneVM(HandlerArg *a); 212 214 int handleStartVM(HandlerArg *a); 213 215 int handleDiscardState(HandlerArg *a); -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
r36720 r37074 333 333 } 334 334 335 if (u64Cmd & USAGE_CLONEVM) 336 RTStrmPrintf(pStrm, 337 "VBoxManage clonevm <uuid>|<name>\n" 338 " [--name <name>]\n" 339 " [--basefolder <basefolder>]\n" 340 " [--uuid <uuid>]\n" 341 " [--register]\n" 342 "\n"); 343 335 344 if (u64Cmd & USAGE_IMPORTAPPLIANCE) 336 345 RTStrmPrintf(pStrm, -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp
r36673 r37074 266 266 267 267 return SUCCEEDED(rc) ? 0 : 1; 268 } 269 270 static const RTGETOPTDEF g_aCloneVMOptions[] = 271 { 272 { "--name", 'n', RTGETOPT_REQ_STRING }, 273 { "--register", 'r', RTGETOPT_REQ_NOTHING }, 274 { "--basefolder", 'p', RTGETOPT_REQ_STRING }, 275 { "--uuid", 'u', RTGETOPT_REQ_STRING }, 276 }; 277 278 int handleCloneVM(HandlerArg *a) 279 { 280 HRESULT rc; 281 const char *pszSrcName = NULL; 282 const char *pszTrgName = NULL; 283 const char *pszTrgBaseFolder = NULL; 284 bool fRegister = false; 285 RTUUID trgUuid; 286 287 int c; 288 RTGETOPTUNION ValueUnion; 289 RTGETOPTSTATE GetState; 290 // start at 0 because main() has hacked both the argc and argv given to us 291 RTGetOptInit(&GetState, a->argc, a->argv, g_aCloneVMOptions, RT_ELEMENTS(g_aCloneVMOptions), 292 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); 293 while ((c = RTGetOpt(&GetState, &ValueUnion))) 294 { 295 switch (c) 296 { 297 case 'n': // --name 298 pszTrgName = ValueUnion.psz; 299 break; 300 301 case 'p': // --basefolder 302 pszTrgBaseFolder = ValueUnion.psz; 303 break; 304 305 case 'u': // --uuid 306 if (RT_FAILURE(RTUuidFromStr(&trgUuid, ValueUnion.psz))) 307 return errorArgument("Invalid UUID format %s\n", ValueUnion.psz); 308 break; 309 310 case 'r': // --register 311 fRegister = true; 312 break; 313 314 case VINF_GETOPT_NOT_OPTION: 315 if (!pszSrcName) 316 pszSrcName = ValueUnion.psz; 317 else 318 return errorSyntax(USAGE_CLONEVM, "Invalid parameter '%s'", ValueUnion.psz); 319 break; 320 321 default: 322 return errorGetOpt(USAGE_CLONEVM, c, &ValueUnion); 323 } 324 } 325 326 /* ~heck for required options */ 327 if (!pszSrcName) 328 return errorSyntax(USAGE_CLONEVM, "VM name required"); 329 330 ComPtr<IMachine> srcMachine; 331 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(pszSrcName).raw(), 332 srcMachine.asOutParam()), 333 RTEXITCODE_FAILURE); 334 335 /* Default name necessary? */ 336 if (!pszTrgName) 337 pszTrgName = RTStrAPrintf2("%s Copy", pszSrcName); 338 339 Bstr bstrSettingsFile; 340 CHECK_ERROR_RET(a->virtualBox, 341 ComposeMachineFilename(Bstr(pszTrgName).raw(), 342 Bstr(pszTrgBaseFolder).raw(), 343 bstrSettingsFile.asOutParam()), 344 RTEXITCODE_FAILURE); 345 346 ComPtr<IMachine> trgMachine; 347 CHECK_ERROR_RET(a->virtualBox, CreateMachine(bstrSettingsFile.raw(), 348 Bstr(pszTrgName).raw(), 349 NULL, 350 Guid(trgUuid).toUtf16().raw(), 351 FALSE, 352 trgMachine.asOutParam()), 353 RTEXITCODE_FAILURE); 354 ComPtr<IProgress> progress; 355 CHECK_ERROR_RET(srcMachine, CloneTo(trgMachine, 356 FALSE, 357 progress.asOutParam()), 358 RTEXITCODE_FAILURE); 359 rc = showProgress(progress); 360 if (FAILED(rc)) 361 { 362 com::ProgressErrorInfo ErrInfo(progress); 363 com::GluePrintErrorInfo(ErrInfo); 364 return RTEXITCODE_FAILURE; 365 } 366 367 if (fRegister) 368 CHECK_ERROR_RET(a->virtualBox, RegisterMachine(trgMachine), RTEXITCODE_FAILURE); 369 370 Bstr bstrNewName; 371 CHECK_ERROR_RET(trgMachine, COMGETTER(Name)(bstrNewName.asOutParam()), RTEXITCODE_FAILURE); 372 RTPrintf("Machine has been successfully cloned as \"%lS\"\n", bstrNewName.raw()); 373 374 return RTEXITCODE_SUCCESS; 268 375 } 269 376 -
trunk/src/VBox/Main/include/MachineImpl.h
r36991 r37074 840 840 HRESULT deleteTaskWorker(DeleteTask &task); 841 841 842 struct CloneVMTask; 843 static DECLCALLBACK(int) cloneVMThread(RTTHREAD Thread, void *pvUser); 844 HRESULT cloneVMTaskWorker(CloneVMTask *pTask); 845 842 846 #ifdef VBOX_WITH_GUEST_PROPS 843 847 HRESULT getGuestPropertyFromService(IN_BSTR aName, BSTR *aValue, -
trunk/src/VBox/Main/src-server/MachineImpl.cpp
r36991 r37074 72 72 73 73 #include <VBox/com/array.h> 74 #include <VBox/com/list.h> 74 75 75 76 #include <VBox/err.h> … … 6072 6073 } 6073 6074 6074 STDMETHODIMP Machine::CloneTo(IMachine *aTarget, BOOL aFullClone, IProgress **aProgress) 6075 { 6076 NOREF(aTarget); NOREF(aFullClone); NOREF(aProgress); 6077 ReturnComNotImplemented(); 6075 struct Machine::CloneVMTask 6076 { 6077 ComObjPtr<Machine> pSrcMachine; 6078 ComObjPtr<Machine> pTrgMachine; 6079 ComObjPtr<Progress> pProgress; 6080 bool fLink; 6081 typedef struct 6082 { 6083 ComPtr<IMedium> pMedium; 6084 uint64_t uSize; 6085 }MediumTask; 6086 typedef RTCList<MediumTask> MediumTaskChain; 6087 RTCList<MediumTaskChain> llMedias; 6088 }; 6089 6090 STDMETHODIMP Machine::CloneTo(IMachine *pTarget, BOOL fFullClone, IProgress **pProgress) 6091 { 6092 LogFlowFuncEnter(); 6093 6094 CheckComArgNotNull(pTarget); 6095 CheckComArgOutPointerValid(pProgress); 6096 6097 AutoCaller autoCaller(this); 6098 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 6099 6100 AutoReadLock srcLock(this COMMA_LOCKVAL_SRC_POS); 6101 6102 CloneVMTask *pTask = NULL; 6103 6104 HRESULT rc; 6105 try 6106 { 6107 pTask = new CloneVMTask; 6108 pTask->pSrcMachine = this; 6109 pTask->pTrgMachine = static_cast<Machine*>(pTarget); 6110 pTask->fLink = !fFullClone; 6111 6112 AutoWriteLock trgLock(pTask->pTrgMachine COMMA_LOCKVAL_SRC_POS); 6113 6114 ULONG uCount = 2; /* One init task and the machine creation. */ 6115 ULONG uTotalWeight = 2; /* The init task and the machine creation is worth one. */ 6116 for (MediaData::AttachmentList::iterator it = mMediaData->mAttachments.begin(); 6117 it != mMediaData->mAttachments.end(); 6118 ++it) 6119 { 6120 /* Query some info of the source image. */ 6121 const ComObjPtr<MediumAttachment> &pAtt = *it; 6122 DeviceType_T type; 6123 rc = pAtt->COMGETTER(Type)(&type); 6124 if (FAILED(rc)) throw rc; 6125 6126 /* Only harddisk's are of interest. */ 6127 if (type != DeviceType_HardDisk) 6128 continue; 6129 6130 /* Valid medium attached? */ 6131 ComPtr<IMedium> pSrcMedium; 6132 rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam()); 6133 if (FAILED(rc)) throw rc; 6134 if (pSrcMedium.isNull()) 6135 continue; 6136 6137 /* Build up a child->parent list of this attachment. (Note: we are 6138 * not interested of any child's not attached to this VM. So this 6139 * will not create a full copy of the base/child relationship.) */ 6140 Machine::CloneVMTask::MediumTaskChain mtc; 6141 while(!pSrcMedium.isNull()) 6142 { 6143 /* Refresh the state so that the file size get read. */ 6144 MediumState_T e; 6145 rc = pSrcMedium->RefreshState(&e); 6146 if (FAILED(rc)) throw rc; 6147 LONG64 lSize; 6148 rc = pSrcMedium->COMGETTER(Size)(&lSize); 6149 if (FAILED(rc)) throw rc; 6150 6151 /* Save the current medium, for later cloning. */ 6152 Machine::CloneVMTask::MediumTask mt; 6153 mt.pMedium = pSrcMedium; 6154 mt.uSize = lSize; 6155 mtc.append(mt); 6156 6157 /* Calculate progress data */ 6158 ++uCount; 6159 uTotalWeight += lSize; 6160 6161 /* Query next parent. */ 6162 rc = pSrcMedium->COMGETTER(Parent)(pSrcMedium.asOutParam()); 6163 if (FAILED(rc)) throw rc; 6164 }; 6165 pTask->llMedias.append(mtc); 6166 } 6167 6168 rc = pTask->pProgress.createObject(); 6169 if (FAILED(rc)) throw rc; 6170 rc = pTask->pProgress->init(getVirtualBox(), 6171 static_cast<IMachine*>(this) /* aInitiator */, 6172 Bstr(tr("Cloning Machine")).raw(), 6173 true /* fCancellable */, 6174 uCount, 6175 uTotalWeight, 6176 Bstr(tr("Initialize Cloning")).raw(), 6177 1); 6178 if (FAILED(rc)) throw rc; 6179 6180 int vrc = RTThreadCreate(NULL, 6181 Machine::cloneVMThread, 6182 static_cast<void*>(pTask), 6183 0, 6184 RTTHREADTYPE_MAIN_WORKER, 6185 0, 6186 "MachineClone"); 6187 if (RT_FAILURE(vrc)) 6188 throw setError(E_FAIL, "Could not create Machine clone thread (%Rrc)", vrc); 6189 } 6190 catch (HRESULT rc2) 6191 { 6192 if (pTask) 6193 delete pTask; 6194 rc = rc2; 6195 } 6196 6197 if (SUCCEEDED(rc)) 6198 pTask->pProgress.queryInterfaceTo(pProgress); 6199 6200 LogFlowFuncLeave(); 6201 6202 return rc; 6203 } 6204 6205 /** 6206 * Static task wrapper passed to RTThreadCreate() in Machine::CloneTo() which then 6207 * calls Machine::cloneVMTaskWorker() on the actual machine object. 6208 * @param Thread 6209 * @param pvUser 6210 * @return 6211 */ 6212 /* static */ 6213 DECLCALLBACK(int) Machine::cloneVMThread(RTTHREAD /* Thread */, void *pvUser) 6214 { 6215 LogFlowFuncEnter(); 6216 6217 CloneVMTask *pTask = static_cast<CloneVMTask*>(pvUser); 6218 AssertReturn(pTask, VERR_INVALID_POINTER); 6219 AssertReturn(pTask->pSrcMachine, VERR_INVALID_POINTER); 6220 AssertReturn(pTask->pTrgMachine, VERR_INVALID_POINTER); 6221 AssertReturn(pTask->pProgress, VERR_INVALID_POINTER); 6222 6223 HRESULT rc = pTask->pSrcMachine->cloneVMTaskWorker(pTask); 6224 pTask->pProgress->notifyComplete(rc); 6225 6226 delete pTask; 6227 6228 LogFlowFuncLeave(); 6229 6230 return VINF_SUCCESS; 6231 } 6232 6233 /** 6234 * Task thread implementation for Machine::CloneTo(), called from Machine::cloneVMThread(). 6235 * @param task 6236 * @return 6237 */ 6238 HRESULT Machine::cloneVMTaskWorker(CloneVMTask *pTask) 6239 { 6240 AutoCaller autoCaller(this); 6241 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 6242 6243 AutoReadLock srcLock(this COMMA_LOCKVAL_SRC_POS); 6244 AutoWriteLock trgLock(pTask->pTrgMachine COMMA_LOCKVAL_SRC_POS); 6245 6246 HRESULT rc = S_OK; 6247 6248 /* 6249 * Todo: 6250 * - Regardless where the old media comes from (e.g. snapshots folder) it 6251 * goes to the new main VM folder. Maybe we like to be a little bit 6252 * smarter here. 6253 * - Snapshot diffs (can) have the uuid as name. After cloning this isn't 6254 * right anymore. Is it worth to change to the new uuid? Or should the 6255 * cloned disks called exactly as the original one or should all new disks 6256 * get a new name with the new VM name in it. 6257 */ 6258 6259 /* Where should all the media go? */ 6260 Utf8Str strTrgMachineFolder = pTask->pTrgMachine->getSettingsFileFull(); 6261 strTrgMachineFolder.stripFilename(); 6262 6263 RTCList< ComObjPtr<Medium> > newMedias; /* All created images */ 6264 try 6265 { 6266 /* Copy all the configuration from this machine to an empty 6267 * configuration dataset. */ 6268 settings::MachineConfigFile *pTrgMCF = new settings::MachineConfigFile(0); 6269 *pTrgMCF = *mData->pMachineConfigFile; 6270 6271 /* Reset media registry. */ 6272 pTrgMCF->mediaRegistry.llHardDisks.clear(); 6273 /* Reset all snapshots. */ 6274 pTrgMCF->llFirstSnapshot.clear(); 6275 pTrgMCF->uuidCurrentSnapshot.clear(); 6276 pTrgMCF->strStateFile = ""; 6277 /* Force writing of setting file. */ 6278 pTrgMCF->fCurrentStateModified = true; 6279 /* Set the new name. */ 6280 pTrgMCF->machineUserData.strName = pTask->pTrgMachine->mUserData->s.strName; 6281 pTrgMCF->uuid = pTask->pTrgMachine->mData->mUuid; 6282 6283 for (size_t i = 0; i < pTask->llMedias.size(); ++i) 6284 { 6285 const Machine::CloneVMTask::MediumTaskChain &mtc = pTask->llMedias.at(i); 6286 ComObjPtr<Medium> pNewParent; 6287 for (size_t a = mtc.size(); a > 0; --a) 6288 { 6289 const Machine::CloneVMTask::MediumTask &mt = mtc.at(a - 1); 6290 ComPtr<IMedium> pMedium = mt.pMedium; 6291 6292 Bstr bstrSrcName; 6293 rc = pMedium->COMGETTER(Name)(bstrSrcName.asOutParam()); 6294 if (FAILED(rc)) throw rc; 6295 6296 rc = pTask->pProgress->SetNextOperation(BstrFmt(tr("Cloning Disk '%ls' ..."), bstrSrcName.raw()).raw(), mt.uSize); 6297 if (FAILED(rc)) throw rc; 6298 6299 ComPtr<IMediumFormat> pSrcFormat; 6300 rc = pMedium->COMGETTER(MediumFormat)(pSrcFormat.asOutParam()); 6301 ULONG uSrcCaps = 0; 6302 rc = pSrcFormat->COMGETTER(Capabilities)(&uSrcCaps); 6303 if (FAILED(rc)) throw rc; 6304 6305 Bstr bstrSrcFormat = "VDI"; 6306 MediumVariant_T srcVar = MediumVariant_Standard; 6307 /* Is the source file based? */ 6308 if ((uSrcCaps & MediumFormatCapabilities_File) == MediumFormatCapabilities_File) 6309 { 6310 /* Yes, just use the source format. Otherwise the defaults 6311 * will be used. */ 6312 rc = pMedium->COMGETTER(Format)(bstrSrcFormat.asOutParam()); 6313 if (FAILED(rc)) throw rc; 6314 rc = pMedium->COMGETTER(Variant)(&srcVar); 6315 if (FAILED(rc)) throw rc; 6316 } 6317 6318 /* Start creating the clone. */ 6319 ComObjPtr<Medium> pTarget; 6320 rc = pTarget.createObject(); 6321 if (FAILED(rc)) throw rc; 6322 6323 Utf8Str strFile = Utf8StrFmt("%s%c%lS", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, bstrSrcName.raw()); 6324 rc = pTarget->init(mParent, 6325 Utf8Str(bstrSrcFormat), 6326 strFile, 6327 pTask->pTrgMachine->mData->mUuid, /* media registry */ 6328 NULL /* llRegistriesThatNeedSaving */); 6329 if (FAILED(rc)) throw rc; 6330 6331 /* Do the disk cloning. */ 6332 ComPtr<IProgress> progress2; 6333 rc = pMedium->CloneTo(pTarget, 6334 srcVar, 6335 pNewParent, 6336 progress2.asOutParam()); 6337 if (FAILED(rc)) throw rc; 6338 6339 /* Wait until the asynchrony process has finished. */ 6340 srcLock.release(); 6341 rc = pTask->pProgress->WaitForAsyncProgressCompletion(progress2); 6342 srcLock.acquire(); 6343 if (FAILED(rc)) throw rc; 6344 6345 /* Check the result of the asynchrony process. */ 6346 LONG iRc; 6347 rc = progress2->COMGETTER(ResultCode)(&iRc); 6348 if (FAILED(rc)) throw rc; 6349 if (FAILED(iRc)) 6350 { 6351 /* If the thread of the progress object has an error, then 6352 * retrieve the error info from there, or it'll be lost. */ 6353 ProgressErrorInfo info(progress2); 6354 throw setError(iRc, Utf8Str(info.getText()).c_str()); 6355 } 6356 /* Remember created medias. */ 6357 newMedias.append(pTarget); 6358 /* This medium becomes the parent of the next medium in the 6359 * chain. */ 6360 pNewParent = pTarget; 6361 } 6362 6363 Bstr bstrSrcId; 6364 rc = mtc.first().pMedium->COMGETTER(Id)(bstrSrcId.asOutParam()); 6365 if (FAILED(rc)) throw rc; 6366 Bstr bstrTrgId; 6367 rc = pNewParent->COMGETTER(Id)(bstrTrgId.asOutParam()); 6368 if (FAILED(rc)) throw rc; 6369 /* We have to patch the configuration, so it contains the new 6370 * medium uuid instead of the old one. */ 6371 settings::StorageControllersList::iterator it3; 6372 for (it3 = pTrgMCF->storageMachine.llStorageControllers.begin(); 6373 it3 != pTrgMCF->storageMachine.llStorageControllers.end(); 6374 ++it3) 6375 { 6376 settings::AttachedDevicesList &llAttachments = it3->llAttachedDevices; 6377 settings::AttachedDevicesList::iterator it4; 6378 for (it4 = llAttachments.begin(); 6379 it4 != llAttachments.end(); 6380 ++it4) 6381 { 6382 if ( it4->deviceType == DeviceType_HardDisk 6383 && it4->uuid == bstrSrcId) 6384 it4->uuid = bstrTrgId; 6385 } 6386 } 6387 } 6388 6389 { 6390 rc = pTask->pProgress->SetNextOperation(BstrFmt(tr("Create Machine Clone '%s' ..."), pTrgMCF->machineUserData.strName.c_str()).raw(), 1); 6391 if (FAILED(rc)) throw rc; 6392 /* After modifying the new machine config, we can copy the stuff 6393 * over to the new machine. The machine have to be mutable for 6394 * this. */ 6395 rc = pTask->pTrgMachine->checkStateDependency(MutableStateDep); 6396 if (FAILED(rc)) throw rc; 6397 rc = pTask->pTrgMachine->loadMachineDataFromSettings(*pTrgMCF, 6398 &pTask->pTrgMachine->mData->mUuid); 6399 if (FAILED(rc)) throw rc; 6400 } 6401 6402 /* The medias are created before the machine was there. We have to make 6403 * sure the new medias know of there new parent or we get in trouble 6404 * when the media registry is saved for this VM, especially in case of 6405 * difference image chain's. See VirtualBox::saveMediaRegistry.*/ 6406 // for (size_t i = 0; i < newBaseMedias.size(); ++i) 6407 // { 6408 // rc = newBaseMedias.at(i)->addRegistry(pTask->pTrgMachine->mData->mUuid, true /* fRecursive */); 6409 // if (FAILED(rc)) throw rc; 6410 // } 6411 6412 /* Now save the new configuration to disk. */ 6413 rc = pTask->pTrgMachine->SaveSettings(); 6414 if (FAILED(rc)) throw rc; 6415 } 6416 catch(HRESULT rc2) 6417 { 6418 rc = rc2; 6419 } 6420 catch (...) 6421 { 6422 rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS); 6423 } 6424 6425 /* Cleanup on failure (CANCEL also) */ 6426 if (FAILED(rc)) 6427 { 6428 /* Delete all already created medias. (Reverse, cause there could be 6429 * parent->child relations.) */ 6430 for (size_t i = newMedias.size(); i > 0; --i) 6431 { 6432 ComObjPtr<Medium> &pMedium = newMedias.at(i - 1); 6433 AutoCaller mac(pMedium); 6434 if (FAILED(mac.rc())) return mac.rc(); 6435 AutoReadLock mlock(pMedium COMMA_LOCKVAL_SRC_POS); 6436 bool fFile = pMedium->isMediumFormatFile(); 6437 Utf8Str strLoc = pMedium->getLocationFull(); 6438 mlock.release(); 6439 /* Close the medium. If this succeed, delete it finally from the 6440 * disk. */ 6441 HRESULT rc1 = pMedium->close(NULL, mac); 6442 if ( SUCCEEDED(rc1) 6443 && fFile) 6444 RTFileDelete(strLoc.c_str()); 6445 } 6446 /* Delete the machine folder when not empty. */ 6447 RTDirRemove(strTrgMachineFolder.c_str()); 6448 } 6449 6450 return rc; 6078 6451 } 6079 6452 … … 7272 7645 * ensure that the media listed as attachments in the config (which have 7273 7646 * been imported from the OVF) receive the correct registry ID. 7647 * 7648 * -- During VM cloning. 7274 7649 * 7275 7650 * @param config Machine settings from XML.
Note:
See TracChangeset
for help on using the changeset viewer.