Changeset 15556 in vbox for trunk/src/VBox
- Timestamp:
- Dec 15, 2008 10:31:49 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 41058
- Location:
- trunk/src/VBox
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
r15492 r15556 530 530 { 531 531 RTPrintf("VBoxManage clonehd <uuid>|<filename> <outputfile>\n" 532 " [-format VDI|VMDK|VHD|RAW|<other>]\n" 533 " [-remember]\n" 532 534 "\n"); 533 535 } -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp
r15529 r15556 314 314 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session) 315 315 { 316 #if 1 317 RTPrintf("Error: Clone hard disk operation is temporarily unavailable!\n"); 318 return 1; 319 #else 320 /// @todo NEWMEDIA use IHardDisk2::cloneTo/flattenTo (not yet implemented) 316 Bstr src, dst; 317 Bstr format; 318 bool remember = false; 319 321 320 HRESULT rc; 322 321 323 /* source hard disk and target path */ 324 if (argc != 2) 325 return errorSyntax(USAGE_CLONEHD, "Incorrect number of parameters"); 322 /* Parse the arguments. */ 323 for (int i = 0; i < argc; i++) 324 { 325 if (strcmp(argv[i], "-format") == 0) 326 { 327 if (argc <= i + 1) 328 { 329 return errorArgument("Missing argument to '%s'", argv[i]); 330 } 331 i++; 332 format = argv[i]; 333 } 334 else if (strcmp(argv[i], "-remember") == 0 || 335 strcmp(argv[i], "-register") == 0 /* backward compatiblity */) 336 { 337 remember = true; 338 } 339 else if (src.isEmpty()) 340 { 341 src = argv[i]; 342 } 343 else if (dst.isEmpty()) 344 { 345 dst = argv[i]; 346 } 347 else 348 { 349 return errorSyntax(USAGE_CLONEHD, "Invalid parameter '%s'", Utf8Str(argv[i]).raw()); 350 } 351 } 352 353 if (src.isEmpty()) 354 return errorSyntax(USAGE_CLONEHD, "Mandatory UUID or input file parameter missing"); 355 if (dst.isEmpty()) 356 return errorSyntax(USAGE_CLONEHD, "Mandatory output file parameter missing"); 357 358 ComPtr<IHardDisk2> srcDisk; 359 ComPtr<IHardDisk2> dstDisk; 360 bool unknown = false; 326 361 327 362 /* first guess is that it's a UUID */ 328 363 Guid uuid(argv[0]); 329 ComPtr<IHardDisk2> hardDisk; 330 rc = virtualBox->GetHardDisk2(uuid, hardDisk.asOutParam()); 331 if (!hardDisk) 332 { 333 /* not successful? Then it must be a filename */ 334 CHECK_ERROR(virtualBox, OpenHardDisk2(Bstr(argv[0]), hardDisk.asOutParam())); 335 } 336 if (hardDisk) 337 { 364 rc = virtualBox->GetHardDisk2(uuid, srcDisk.asOutParam()); 365 /* no? then it must be a filename */ 366 if (FAILED (rc)) 367 { 368 rc = virtualBox->FindHardDisk2(src, srcDisk.asOutParam()); 369 /* no? well, then it's an unkwnown image */ 370 if (FAILED (rc)) 371 { 372 CHECK_ERROR(virtualBox, OpenHardDisk2(src, srcDisk.asOutParam())); 373 if (SUCCEEDED (rc)) 374 { 375 unknown = true; 376 } 377 } 378 } 379 380 do 381 { 382 if (!SUCCEEDED(rc)) 383 break; 384 385 if (format.isEmpty()) 386 { 387 /* get the format of the source hard disk */ 388 CHECK_ERROR_BREAK(srcDisk, COMGETTER(Format) (format.asOutParam())); 389 } 390 391 CHECK_ERROR_BREAK(virtualBox, CreateHardDisk2(format, dst, dstDisk.asOutParam())); 392 338 393 ComPtr<IProgress> progress; 339 CHECK_ERROR(hardDisk, CloneToImage(Bstr(argv[1]), hardDisk.asOutParam(), progress.asOutParam())); 340 if (SUCCEEDED(rc)) 341 { 342 showProgress(progress); 343 progress->COMGETTER(ResultCode)(&rc); 344 if (FAILED(rc)) 345 { 346 com::ProgressErrorInfo info(progress); 347 if (info.isBasicAvailable()) 348 { 349 RTPrintf("Error: failed to clone disk image. Error message: %lS\n", info.getText().raw()); 350 } 351 else 352 { 353 RTPrintf("Error: failed to clone disk image. No error message available!\n"); 354 } 355 } 356 } 357 } 394 CHECK_ERROR_BREAK(srcDisk, CloneTo(dstDisk, progress.asOutParam())); 395 396 showProgress(progress); 397 progress->COMGETTER(ResultCode)(&rc); 398 if (FAILED(rc)) 399 { 400 com::ProgressErrorInfo info(progress); 401 if (info.isBasicAvailable()) 402 RTPrintf("Error: failed to clone hard disk. Error message: %lS\n", info.getText().raw()); 403 else 404 RTPrintf("Error: failed to clone hard disk. No error message available!\n"); 405 break; 406 } 407 408 CHECK_ERROR_BREAK(dstDisk, COMGETTER(Id)(uuid.asOutParam())); 409 410 RTPrintf("Clone hard disk created in format '%ls'. UUID: %s\n", 411 format.raw(), uuid.toString().raw()); 412 } 413 while (0); 414 415 if (!remember && !dstDisk.isNull()) 416 { 417 /* forget the created clone */ 418 dstDisk->Close(); 419 } 420 421 if (unknown) 422 { 423 /* close the unknown hard disk to forget it again */ 424 srcDisk->Close(); 425 } 426 358 427 return SUCCEEDED(rc) ? 0 : 1; 359 #endif360 428 } 361 429 -
trunk/src/VBox/Main/HardDisk2Impl.cpp
r15486 r15556 57 57 struct HardDisk2::Task : public com::SupportErrorInfoBase 58 58 { 59 enum Operation { CreateDynamic, CreateFixed, CreateDiff, Merge, Delete }; 59 enum Operation { CreateDynamic, CreateFixed, CreateDiff, 60 Merge, Clone, Delete }; 60 61 61 62 HardDisk2 *that; … … 1128 1129 IProgress **aProgress) 1129 1130 { 1130 if (aProgress == NULL) 1131 return E_POINTER; 1131 CheckComArgOutPointerValid (aProgress); 1132 1132 1133 1133 AutoCaller autoCaller (this); … … 1184 1184 IProgress **aProgress) 1185 1185 { 1186 if (aProgress == NULL) 1187 return E_POINTER; 1186 CheckComArgOutPointerValid (aProgress); 1188 1187 1189 1188 AutoCaller autoCaller (this); … … 1239 1238 STDMETHODIMP HardDisk2::DeleteStorage (IProgress **aProgress) 1240 1239 { 1241 if (aProgress == NULL) 1242 return E_POINTER; 1240 CheckComArgOutPointerValid (aProgress); 1241 1242 AutoCaller autoCaller (this); 1243 CheckComRCReturnRC (autoCaller.rc()); 1243 1244 1244 1245 ComObjPtr <Progress> progress; … … 1256 1257 STDMETHODIMP HardDisk2::CreateDiffStorage (IHardDisk2 *aTarget, IProgress **aProgress) 1257 1258 { 1258 if (aTarget == NULL) 1259 return E_INVALIDARG; 1260 if (aProgress == NULL) 1261 return E_POINTER; 1259 CheckComArgNotNull (aTarget); 1260 CheckComArgOutPointerValid (aProgress); 1262 1261 1263 1262 AutoCaller autoCaller (this); … … 1306 1305 STDMETHODIMP HardDisk2::CloneTo (IHardDisk2 *aTarget, IProgress **aProgress) 1307 1306 { 1307 CheckComArgNotNull (aTarget); 1308 CheckComArgOutPointerValid (aProgress); 1309 1308 1310 AutoCaller autoCaller (this); 1309 1311 CheckComRCReturnRC (autoCaller.rc()); 1310 1312 1311 ReturnComNotImplemented(); 1313 ComObjPtr <HardDisk2> target; 1314 HRESULT rc = mVirtualBox->cast (aTarget, target); 1315 CheckComRCReturnRC (rc); 1316 1317 AutoMultiWriteLock2 alock (this, target); 1318 1319 /* We want to be locked for reading as long as the clone hard disk is being 1320 * created*/ 1321 rc = LockRead (NULL); 1322 CheckComRCReturnRC (rc); 1323 1324 ComObjPtr <Progress> progress; 1325 1326 try 1327 { 1328 if (target->m.state != MediaState_NotCreated) 1329 throw target->setStateError(); 1330 1331 progress.createObject(); 1332 rc = progress->init (mVirtualBox, static_cast <IHardDisk2 *> (this), 1333 BstrFmt (tr ("Creating a clone hard disk '%s'"), 1334 target->name().raw()), 1335 FALSE /* aCancelable */); 1336 CheckComRCThrowRC (rc); 1337 1338 /* setup task object and thread to carry out the operation 1339 * asynchronously */ 1340 1341 std::auto_ptr <Task> task (new Task (this, progress, Task::Clone)); 1342 AssertComRCThrowRC (task->autoCaller.rc()); 1343 1344 task->setData (target); 1345 1346 rc = task->startThread(); 1347 CheckComRCThrowRC (rc); 1348 1349 /* go to Creating state before leaving the lock */ 1350 target->m.state = MediaState_Creating; 1351 1352 /* task is now owned (or already deleted) by taskThread() so release it */ 1353 task.release(); 1354 } 1355 catch (HRESULT aRC) 1356 { 1357 rc = aRC; 1358 } 1359 1360 if (FAILED (rc)) 1361 { 1362 HRESULT rc2 = UnlockRead (NULL); 1363 AssertComRC (rc2); 1364 /* Note: on success, taskThread() will unlock this */ 1365 } 1366 else 1367 { 1368 /* return progress to the caller */ 1369 progress.queryInterfaceTo (aProgress); 1370 } 1371 1372 return rc; 1312 1373 } 1313 1374 … … 3203 3264 uint64_t size = 0, logicalSize = 0; 3204 3265 3205 /* the object may request a specific UUID (through a special3206 * form of the setLocation() argumet)*/3266 /* The object may request a specific UUID (through a special form of 3267 * the setLocation() argumet). Otherwise we have to generate it */ 3207 3268 Guid id = that->m.id; 3269 bool generateUuid = id.isEmpty(); 3270 if (generateUuid) 3271 { 3272 id.create(); 3273 /* VirtualBox::registerHardDisk2() will need UUID */ 3274 unconst (that->m.id) = id; 3275 } 3208 3276 3209 3277 try … … 3238 3306 task->d.size * _1M, 3239 3307 VD_IMAGE_FLAGS_NONE, 3240 NULL, &geo, &geo, 3241 id.isEmpty() ? NULL : id.raw(), 3308 NULL, &geo, &geo, id.raw(), 3242 3309 VD_OPEN_FLAGS_NORMAL, 3243 3310 NULL, that->mm.vdDiskIfaces); … … 3251 3318 } 3252 3319 3253 if (capabilities & HardDiskFormatCapabilities_Uuid)3254 {3255 RTUUID uuid;3256 vrc = VDGetUuid (hdd, 0, &uuid);3257 ComAssertRCThrow (vrc, E_FAIL);3258 3259 if (!id.isEmpty())3260 Assert (id == uuid);3261 else3262 id = uuid;3263 }3264 else3265 {3266 /* we have to generate an UUID ourselves */3267 id.create();3268 }3269 3270 3320 size = VDGetFileSize (hdd, 0); 3271 3321 logicalSize = VDGetSize (hdd, 0) / _1M; … … 3279 3329 if (SUCCEEDED (rc)) 3280 3330 { 3281 /* mVirtualBox->registerHardDisk2() needs a write lock */3282 AutoWriteLock vboxLock (that->mVirtualBox);3283 thatLock.enter();3284 3285 unconst (that->m.id) = id;3286 3287 that->m.size = size;3288 that->mm.logicalSize = logicalSize;3289 3290 3331 /* register with mVirtualBox as the last step and move to 3291 3332 * Created state only on success (leaving an orphan file is 3292 3333 * better than breaking media registry consistency) */ 3293 3334 rc = that->mVirtualBox->registerHardDisk2 (that); 3294 3295 if (SUCCEEDED (rc))3296 that->m.state = MediaState_Created;3297 3335 } 3298 3336 3299 if (FAILED (rc)) 3337 thatLock.maybeEnter(); 3338 3339 if (SUCCEEDED (rc)) 3300 3340 { 3301 thatLock.maybeEnter(); 3302 3341 that->m.state = MediaState_Created; 3342 3343 that->m.size = size; 3344 that->mm.logicalSize = logicalSize; 3345 } 3346 else 3347 { 3303 3348 /* back to NotCreated on failiure */ 3304 3349 that->m.state = MediaState_NotCreated; 3350 3351 /* reset UUID to prevent it from being reused next time */ 3352 if (generateUuid) 3353 unconst (that->m.id).clear(); 3305 3354 } 3306 3355 … … 3320 3369 3321 3370 uint64_t size = 0, logicalSize = 0; 3371 3372 /* The object may request a specific UUID (through a special form of 3373 * the setLocation() argumet). Otherwise we have to generate it */ 3374 Guid targetId = target->m.id; 3375 bool generateUuid = targetId.isEmpty(); 3376 if (generateUuid) 3377 { 3378 targetId.create(); 3379 /* VirtualBox::registerHardDisk2() will need UUID */ 3380 unconst (target->m.id) = targetId; 3381 } 3322 3382 3323 3383 try … … 3332 3392 Utf8Str targetFormat (target->mm.format); 3333 3393 Utf8Str targetLocation (target->m.locationFull); 3334 Guid targetId = target->m.id;3335 3336 /* UUID must have been set by setLocation() */3337 Assert (!targetId.isEmpty());3338 3394 3339 3395 Assert (target->m.state == MediaState_Creating); … … 3434 3490 /* back to NotCreated on failiure */ 3435 3491 target->m.state = MediaState_NotCreated; 3492 3493 /* reset UUID to prevent it from being reused next time */ 3494 if (generateUuid) 3495 unconst (target->m.id).clear(); 3436 3496 } 3437 3497 … … 3759 3819 //////////////////////////////////////////////////////////////////////// 3760 3820 3821 case Task::Clone: 3822 { 3823 ComObjPtr <HardDisk2> &target = task->d.target; 3824 3825 /* Lock both in {parent,child} order. The lock is also used as a 3826 * signal from the task initiator (which releases it only after 3827 * RTThreadCreate()) that we can start the job*/ 3828 AutoMultiWriteLock2 thatLock (that, target); 3829 3830 uint64_t size = 0, logicalSize = 0; 3831 3832 /* The object may request a specific UUID (through a special form of 3833 * the setLocation() argumet). Otherwise we have to generate it */ 3834 Guid targetId = target->m.id; 3835 bool generateUuid = targetId.isEmpty(); 3836 if (generateUuid) 3837 { 3838 targetId.create(); 3839 /* VirtualBox::registerHardDisk2() will need UUID */ 3840 unconst (target->m.id) = targetId; 3841 } 3842 3843 try 3844 { 3845 PVBOXHDD hdd; 3846 int vrc = VDCreate (that->mm.vdDiskIfaces, &hdd); 3847 ComAssertRCThrow (vrc, E_FAIL); 3848 3849 Utf8Str format (that->mm.format); 3850 Utf8Str location (that->m.locationFull); 3851 3852 Utf8Str targetFormat (target->mm.format); 3853 Utf8Str targetLocation (target->m.locationFull); 3854 3855 Assert (target->m.state == MediaState_Creating); 3856 3857 Assert (that->m.state == MediaState_LockedRead); 3858 3859 /* unlock before the potentially lengthy operation */ 3860 thatLock.leave(); 3861 3862 try 3863 { 3864 vrc = VDOpen (hdd, format, location, 3865 VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO, 3866 NULL); 3867 if (RT_FAILURE (vrc)) 3868 { 3869 throw setError (E_FAIL, 3870 tr ("Could not open the hard disk storage " 3871 "unit '%s'%s"), 3872 location.raw(), that->vdError (vrc).raw()); 3873 } 3874 3875 /* ensure the target directory exists */ 3876 rc = VirtualBox::ensureFilePathExists (targetLocation); 3877 CheckComRCThrowRC (rc); 3878 3879 /* needed for vdProgressCallback */ 3880 that->mm.vdProgress = task->progress; 3881 3882 PVBOXHDD targetHdd; 3883 int vrc = VDCreate (that->mm.vdDiskIfaces, &targetHdd); 3884 ComAssertRCThrow (vrc, E_FAIL); 3885 3886 vrc = VDCopy (hdd, 0, targetHdd, targetFormat, 3887 targetLocation, false, 0, targetId.raw(), 3888 NULL, NULL, that->mm.vdDiskIfaces); 3889 3890 that->mm.vdProgress = NULL; 3891 3892 if (RT_FAILURE (vrc)) 3893 { 3894 VDDestroy (targetHdd); 3895 3896 throw setError (E_FAIL, 3897 tr ("Could not create the clone hard disk " 3898 "'%s'%s"), 3899 targetLocation.raw(), that->vdError (vrc).raw()); 3900 } 3901 3902 size = VDGetFileSize (hdd, 0); 3903 logicalSize = VDGetSize (hdd, 0) / _1M; 3904 3905 VDDestroy (targetHdd); 3906 } 3907 catch (HRESULT aRC) { rc = aRC; } 3908 3909 VDDestroy (hdd); 3910 } 3911 catch (HRESULT aRC) { rc = aRC; } 3912 3913 if (SUCCEEDED (rc)) 3914 { 3915 /* we set mParent & children() (note that thatLock is released 3916 * here), but lock VirtualBox first to follow the rule */ 3917 AutoMultiWriteLock2 alock (that->mVirtualBox->lockHandle(), 3918 that->treeLock()); 3919 3920 Assert (target->mParent.isNull()); 3921 3922 if (!that->mParent.isNull()) 3923 { 3924 /* associate the clone with the original's parent and 3925 * deassociate from VirtualBox */ 3926 target->mParent = that->mParent; 3927 that->mParent->addDependentChild (target); 3928 target->mVirtualBox->removeDependentChild (target); 3929 3930 /* register with mVirtualBox as the last step and move to 3931 * Created state only on success (leaving an orphan file is 3932 * better than breaking media registry consistency) */ 3933 rc = that->mVirtualBox->registerHardDisk2 (target); 3934 3935 if (FAILED (rc)) 3936 { 3937 /* break the parent association on failure to register */ 3938 target->mVirtualBox->addDependentChild (target); 3939 that->mParent->removeDependentChild (target); 3940 target->mParent.setNull(); 3941 } 3942 } 3943 else 3944 { 3945 /* just register */ 3946 rc = that->mVirtualBox->registerHardDisk2 (target); 3947 } 3948 } 3949 3950 thatLock.maybeEnter(); 3951 3952 if (SUCCEEDED (rc)) 3953 { 3954 target->m.state = MediaState_Created; 3955 3956 target->m.size = size; 3957 target->mm.logicalSize = logicalSize; 3958 } 3959 else 3960 { 3961 /* back to NotCreated on failiure */ 3962 target->m.state = MediaState_NotCreated; 3963 3964 /* reset UUID to prevent it from being reused next time */ 3965 if (generateUuid) 3966 unconst (target->m.id).clear(); 3967 } 3968 3969 if (isAsync) 3970 { 3971 /* unlock ourselves when done (unless in MediaState_LockedWrite 3972 * state because of taking the online snapshot*/ 3973 if (that->m.state != MediaState_LockedWrite) 3974 { 3975 HRESULT rc2 = that->UnlockRead (NULL); 3976 AssertComRC (rc2); 3977 } 3978 } 3979 3980 /* Note that in sync mode, it's the caller's responsibility to 3981 * unlock the hard disk */ 3982 3983 break; 3984 } 3985 3986 //////////////////////////////////////////////////////////////////////// 3987 3761 3988 case Task::Delete: 3762 3989 {
Note:
See TracChangeset
for help on using the changeset viewer.