Changeset 75373 in vbox
- Timestamp:
- Nov 9, 2018 6:12:30 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 126508
- Location:
- trunk/src/VBox
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/MediumImpl.h
r74353 r75373 202 202 void i_cancelMergeTo(MediumLockList *aChildrenToReparent, 203 203 MediumLockList *aMediumLockList); 204 205 HRESULT i_resize(LONG64 aLogicalSize, 206 MediumLockList *aMediumLockList, 207 ComObjPtr<Progress> *aProgress, 208 bool aWait); 204 209 205 210 HRESULT i_fixParentUuidOfChildren(MediumLockList *pChildrenToReparent); -
trunk/src/VBox/Main/src-server/MediumImpl.cpp
r74822 r75373 3379 3379 HRESULT rc = S_OK; 3380 3380 ComObjPtr<Progress> pProgress; 3381 Medium::Task *pTask = NULL; 3381 3382 /* Build the medium lock list. */ 3383 MediumLockList *pMediumLockList(new MediumLockList()); 3382 3384 3383 3385 try 3384 3386 { 3385 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 3386 3387 /* Build the medium lock list. */ 3388 MediumLockList *pMediumLockList(new MediumLockList()); 3389 alock.release(); 3387 const char *pszError = NULL; 3388 3390 3389 rc = i_createMediumLockList(true /* fFailIfInaccessible */ , 3391 3390 this /* pToLockWrite */, … … 3393 3392 NULL, 3394 3393 *pMediumLockList); 3395 alock.acquire();3396 3394 if (FAILED(rc)) 3397 3395 { 3396 pszError = tr("Failed to create medium lock list when resize '%s'"); 3397 } 3398 else 3399 { 3400 rc = pMediumLockList->Lock(); 3401 if (FAILED(rc)) 3402 pszError = tr("Failed to lock media when compacting '%s'"); 3403 } 3404 3405 3406 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 3407 3408 if (FAILED(rc)) 3409 { 3398 3410 delete pMediumLockList; 3399 throw rc; 3400 } 3401 3402 alock.release(); 3403 rc = pMediumLockList->Lock(); 3404 alock.acquire(); 3405 if (FAILED(rc)) 3406 { 3407 delete pMediumLockList; 3408 throw setError(rc, 3409 tr("Failed to lock media when compacting '%s'"), 3410 i_getLocationFull().c_str()); 3411 throw setError(rc, pszError, i_getLocationFull().c_str()); 3411 3412 } 3412 3413 … … 3414 3415 rc = pProgress->init(m->pVirtualBox, 3415 3416 static_cast <IMedium *>(this), 3416 BstrFmt(tr(" Compacting medium '%s'"), m->strLocationFull.c_str()).raw(),3417 BstrFmt(tr("Resizing medium '%s'"), m->strLocationFull.c_str()).raw(), 3417 3418 TRUE /* aCancelable */); 3418 3419 if (FAILED(rc)) … … 3421 3422 throw rc; 3422 3423 } 3423 3424 /* setup task object to carry out the operation asynchronously */3425 pTask = new Medium::ResizeTask(this, aLogicalSize, pProgress, pMediumLockList);3426 rc = pTask->rc();3427 AssertComRC(rc);3428 if (FAILED(rc))3429 throw rc;3430 3424 } 3431 3425 catch (HRESULT aRC) { rc = aRC; } 3432 3426 3433 3427 if (SUCCEEDED(rc)) 3434 { 3435 rc = pTask->createThread(); 3436 3437 if (SUCCEEDED(rc)) 3438 pProgress.queryInterfaceTo(aProgress.asOutParam()); 3439 } 3440 else if (pTask != NULL) 3441 delete pTask; 3428 rc = i_resize(aLogicalSize, pMediumLockList, &pProgress, false /* aWait */); 3429 3430 if (SUCCEEDED(rc)) 3431 pProgress.queryInterfaceTo(aProgress.asOutParam()); 3432 else 3433 delete pMediumLockList; 3442 3434 3443 3435 return rc; … … 5530 5522 * media are used by a running VM. 5531 5523 */ 5532 bool fMergeIntoThis = cbMediumThis > cbMediumOther; 5524 5525 uint32_t mediumVariants = MediumVariant_Fixed | MediumVariant_VmdkStreamOptimized; 5526 uint32_t mediumCaps = MediumFormatCapabilities_CreateDynamic | MediumFormatCapabilities_File; 5527 5528 bool fDynamicOther = pOther->i_getMediumFormat()->i_getCapabilities() & mediumCaps 5529 && pOther->i_getVariant() & ~mediumVariants; 5530 bool fDynamicThis = i_getMediumFormat()->i_getCapabilities() & mediumCaps 5531 && i_getVariant() & ~mediumVariants; 5532 bool fMergeIntoThis = (fDynamicThis && !fDynamicOther) 5533 || (fDynamicThis == fDynamicOther && cbMediumThis > cbMediumOther); 5533 5534 fMergeForward = fMergeIntoThis != fThisParent; 5534 5535 } … … 6004 6005 i_getName().c_str(), 6005 6006 tgtName.c_str()).raw(), 6006 TRUE /* aCancelable */); 6007 TRUE, /* aCancelable */ 6008 2, /* Number of opearations */ 6009 BstrFmt(tr("Resizing medium '%s' before merge"), 6010 tgtName.c_str()).raw() 6011 ); 6007 6012 if (FAILED(rc)) 6008 6013 throw rc; … … 6051 6056 * @param aMediumLockList Medium locking information. 6052 6057 * 6053 * @note Locks the media from the chain for writing. 6058 * @note Locks the tree lock for writing. Locks the media from the chain 6059 * for writing. 6054 6060 */ 6055 6061 void Medium::i_cancelMergeTo(MediumLockList *aChildrenToReparent, … … 6096 6102 if (aChildrenToReparent) 6097 6103 delete aChildrenToReparent; 6104 } 6105 6106 /** 6107 * Resizes the media. 6108 * 6109 * If @a aWait is @c true then this method will perform the operation on the 6110 * calling thread and will not return to the caller until the operation is 6111 * completed. When this method succeeds, the state of the target medium (and all 6112 * involved extra media) will be restored. @a aMediumLockList will not be 6113 * deleted, whether the operation is successful or not. The caller has to do 6114 * this if appropriate. 6115 * 6116 * If @a aWait is @c false then this method will create a thread to perform the 6117 * operation asynchronously and will return immediately. The thread will reset 6118 * the state of the target medium (and all involved extra media) and delete 6119 * @a aMediumLockList. 6120 * 6121 * When this method fails (regardless of the @a aWait mode), it is a caller's 6122 * responsibility to undo state changes and delete @a aMediumLockList. 6123 * 6124 * If @a aProgress is not NULL but the object it points to is @c null then a new 6125 * progress object will be created and assigned to @a *aProgress on success, 6126 * otherwise the existing progress object is used. If Progress is NULL, then no 6127 * progress object is created/used at all. Note that @a aProgress cannot be 6128 * NULL when @a aWait is @c false (this method will assert in this case). 6129 * 6130 * @param aLogicalSize New nominal capacity of the medium in bytes. 6131 * @param aMediumLockList Medium locking information. 6132 * @param aProgress Where to find/store a Progress object to track operation 6133 * completion. 6134 * @param aWait @c true if this method should block instead of creating 6135 * an asynchronous thread. 6136 * 6137 * @note Locks the media from the chain for writing. 6138 */ 6139 6140 HRESULT Medium::i_resize(LONG64 aLogicalSize, 6141 MediumLockList *aMediumLockList, 6142 ComObjPtr<Progress> *aProgress, 6143 bool aWait) 6144 { 6145 AssertReturn(aMediumLockList != NULL, E_FAIL); 6146 AssertReturn(aProgress != NULL || aWait == true, E_FAIL); 6147 6148 AutoCaller autoCaller(this); 6149 AssertComRCReturnRC(autoCaller.rc()); 6150 6151 HRESULT rc = S_OK; 6152 ComObjPtr<Progress> pProgress; 6153 Medium::Task *pTask = NULL; 6154 6155 try 6156 { 6157 if (aProgress != NULL) 6158 { 6159 /* use the existing progress object... */ 6160 pProgress = *aProgress; 6161 6162 /* ...but create a new one if it is null */ 6163 if (pProgress.isNull()) 6164 { 6165 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 6166 6167 pProgress.createObject(); 6168 rc = pProgress->init(m->pVirtualBox, 6169 static_cast <IMedium *>(this), 6170 BstrFmt(tr("Resizing medium '%s'"), m->strLocationFull.c_str()).raw(), 6171 TRUE /* aCancelable */); 6172 if (FAILED(rc)) 6173 throw rc; 6174 } 6175 } 6176 6177 /* setup task object to carry out the operation asynchronously */ 6178 pTask = new Medium::ResizeTask(this, 6179 aLogicalSize, 6180 pProgress, 6181 aMediumLockList, 6182 aWait /* fKeepMediumLockList */); 6183 rc = pTask->rc(); 6184 AssertComRC(rc); 6185 if (FAILED(rc)) 6186 throw rc; 6187 } 6188 catch (HRESULT aRC) { rc = aRC; } 6189 6190 if (SUCCEEDED(rc)) 6191 { 6192 if (aWait) 6193 { 6194 rc = pTask->runNow(); 6195 delete pTask; 6196 } 6197 else 6198 rc = pTask->createThread(); 6199 6200 if (SUCCEEDED(rc) && aProgress != NULL) 6201 *aProgress = pProgress; 6202 } 6203 else if (pTask != NULL) 6204 delete pTask; 6205 6206 return rc; 6098 6207 } 6099 6208 … … 8653 8762 task.mParentForTarget->m->strLocationFull.c_str()); 8654 8763 } 8764 8765 // Resize target to source size, if possible. Otherwise throw an error. 8766 // It's offline resizing. Online resizing will be called in the 8767 // SessionMachine::onlineMergeMedium. 8768 8769 uint64_t sourceSize = 0; 8770 Utf8Str sourceName; 8771 { 8772 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 8773 sourceSize = i_getLogicalSize(); 8774 sourceName = i_getName(); 8775 } 8776 uint64_t targetSize = 0; 8777 Utf8Str targetName; 8778 { 8779 AutoReadLock alock(pTarget COMMA_LOCKVAL_SRC_POS); 8780 targetSize = pTarget->i_getLogicalSize(); 8781 targetName = pTarget->i_getName(); 8782 } 8783 8784 //reducing vm disks are not implemented yet 8785 if (sourceSize > targetSize) 8786 { 8787 if (i_isMediumFormatFile()) 8788 { 8789 // Have to make own lock list, because "resize" method resizes only last image 8790 // in the lock chain. The lock chain already in the task.mpMediumLockList, so 8791 // just make new lock list based on it. In fact the own lock list neither makes 8792 // double locking of mediums nor unlocks them during delete, because medium 8793 // already locked by task.mpMediumLockList and own list is used just to specify 8794 // what "resize" method should resize. 8795 8796 MediumLockList* pMediumLockListForResize = new MediumLockList(); 8797 8798 for (MediumLockList::Base::iterator it = task.mpMediumLockList->GetBegin(); 8799 it != task.mpMediumLockList->GetEnd(); 8800 ++it) 8801 { 8802 ComObjPtr<Medium> pMedium = it->GetMedium(); 8803 pMediumLockListForResize->Append(pMedium, pMedium->m->state == MediumState_LockedWrite); 8804 if (pMedium == pTarget) 8805 break; 8806 } 8807 8808 // just to switch internal state of the lock list to avoid errors during list deletion, 8809 // because all meduims in the list already locked by task.mpMediumLockList 8810 HRESULT rc = pMediumLockListForResize->Lock(true /* fSkipOverLockedMedia */); 8811 if (FAILED(rc)) 8812 { 8813 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 8814 rc = setError(rc, 8815 tr("Failed to lock the medium '%s' to resize before merge"), 8816 targetName.c_str()); 8817 delete pMediumLockListForResize; 8818 throw rc; 8819 } 8820 8821 ComObjPtr<Progress> pProgress(task.GetProgressObject()); 8822 rc = pTarget->i_resize(sourceSize, pMediumLockListForResize, &pProgress, true); 8823 if (FAILED(rc)) 8824 { 8825 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 8826 rc = setError(rc, 8827 tr("Failed to set size of '%s' to size of '%s'"), 8828 targetName.c_str(), sourceName.c_str()); 8829 delete pMediumLockListForResize; 8830 throw rc; 8831 } 8832 delete pMediumLockListForResize; 8833 } 8834 else 8835 { 8836 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 8837 HRESULT rc = setError(VBOX_E_NOT_SUPPORTED, 8838 tr("Sizes of '%s' and '%s' are different and medium format does not support resing"), 8839 sourceName.c_str(), targetName.c_str()); 8840 throw rc; 8841 } 8842 } 8843 8844 task.GetProgressObject()->SetNextOperation(BstrFmt(tr("Merging medium '%s' to '%s'"), 8845 i_getName().c_str(), 8846 targetName.c_str()).raw(), 8847 1); 8655 8848 8656 8849 PVDISK hdd; … … 9786 9979 Assert(pMedium->m->state == MediumState_LockedWrite); 9787 9980 else 9788 Assert(pMedium->m->state == MediumState_LockedRead); 9981 Assert(pMedium->m->state == MediumState_LockedRead || 9982 // Allow resize the target image during mergeTo in case 9983 // of direction from parent to child because all intermediate 9984 // images are marked to MediumState_Deleting and will be 9985 // destroyed after successful merge 9986 pMedium->m->state == MediumState_Deleting); 9789 9987 9790 9988 /* Open all media but last in read-only mode. Do not handle -
trunk/src/VBox/Main/src-server/SnapshotImpl.cpp
r75361 r75373 2504 2504 } 2505 2505 2506 bool fDeleteOnline = mData->mMachineState == MachineState_Running || mData->mMachineState == MachineState_Paused; 2507 2506 2508 // count normal hard disks and add their sizes to the weight 2507 2509 for (MediumAttachmentList::iterator … … 2527 2529 // normal or immutable media need attention 2528 2530 ++ulOpCount; 2531 // offline merge includes medium resizing 2532 if (!fDeleteOnline) 2533 ++ulOpCount; 2529 2534 ulTotalWeight += (ULONG)(pHD->i_getSize() / _1M); 2530 2535 } … … 2542 2547 Bstr(tr("Setting up")).raw(), 2543 2548 1); 2544 2545 bool fDeleteOnline = ( (mData->mMachineState == MachineState_Running)2546 || (mData->mMachineState == MachineState_Paused));2547 2549 2548 2550 /* create and start the task on a separate thread */ … … 2814 2816 // a file representation such as iSCSI. 2815 2817 2816 // not going to merge a big source into a small target 2817 if ( pSource->i_getLogicalSize() > pTarget->i_getLogicalSize())2818 // not going to merge a big source into a small target on online merge. Otherwise it will be resized 2819 if (fNeedsOnlineMerge && pSource->i_getLogicalSize() > pTarget->i_getLogicalSize()) 2818 2820 { 2819 2821 rc = setError(E_FAIL, … … 3039 3041 } 3040 3042 3041 task.m_pProgress->SetNextOperation(BstrFmt(tr("Merging differencing image '%s'"), 3043 const char *pszOperationText = it->mfNeedsOnlineMerge ? 3044 tr("Merging differencing image '%s'") 3045 : tr("Resizing before merge differencing image '%s'"); 3046 3047 task.m_pProgress->SetNextOperation(BstrFmt(pszOperationText, 3042 3048 pMedium->i_getName().c_str()).raw(), 3043 3049 ulWeight); -
trunk/src/VBox/Storage/VD.cpp
r75351 r75373 36 36 #include <iprt/sg.h> 37 37 #include <iprt/semaphore.h> 38 #include <iprt/vector.h> 38 39 39 40 #include "VDInternal.h" … … 362 363 uint8_t abData[1]; 363 364 } VDMETAXFER; 365 366 /* vector for temporary storing image sizes */ 367 RTVEC_DECL(VDImgSzVec, uint64_t) 364 368 365 369 /** … … 7046 7050 uint64_t uOffset = 0; 7047 7051 uint64_t cbRemaining = cbSize; 7052 7048 7053 do 7049 7054 { -
trunk/src/VBox/ValidationKit/tests/storage/tdStorageSnapshotMerging1.py
r69111 r75373 28 28 terms and conditions of either the GPL or the CDDL or both. 29 29 """ 30 __version__ = "$Id$" 31 30 __version__ = "$Revision$" 32 31 33 32 # Standard Python imports. … … 35 34 import sys; 36 35 import uuid; 36 import zlib; 37 37 38 38 # Only the main script needs to modify the path. … … 47 47 from testdriver import vbox; 48 48 from testdriver import vboxcon; 49 from testdriver import vboxwrappers; 49 50 50 51 def _ControllerTypeToName(eControllerType): … … 62 63 return sType; 63 64 65 def crc32_of_file(filepath): 66 fileobj = open(filepath,'rb'); 67 current = 0; 68 69 while True: 70 buf = fileobj.read(1024 * 1024); 71 if not buf: 72 break 73 current = zlib.crc32(buf, current); 74 75 fileobj.close(); 76 return current % 2**32; 77 64 78 class tdStorageSnapshot(vbox.TestDriver): # pylint: disable=R0902 65 79 """ 66 80 Storage benchmark. 67 81 """ 68 69 82 def __init__(self): 70 83 vbox.TestDriver.__init__(self); … … 73 86 self.oGuestToGuestSess = None; 74 87 self.oGuestToGuestTxs = None; 75 self.asTestVMsDef = ['tst-win7-vhd', 'tst-debian-vhd', 'tst-debian-vdi'];76 self.asTestVMs = self.asTestVMsDef;77 self.asSkipVMs = [];78 88 self.asStorageCtrlsDef = ['AHCI', 'IDE', 'LsiLogicSAS', 'LsiLogic', 'BusLogic']; 79 89 self.asStorageCtrls = self.asStorageCtrlsDef; 80 self.asDiskFormatsDef = ['VDI', 'VMDK', 'VHD', 'QED', 'Parallels', 'QCOW', 'iSCSI']; 90 #self.asDiskFormatsDef = ['VDI', 'VMDK', 'VHD', 'QED', 'Parallels', 'QCOW', 'iSCSI']; 91 self.asDiskFormatsDef = ['VDI', 'VMDK', 'VHD']; 81 92 self.asDiskFormats = self.asDiskFormatsDef; 82 93 self.sRndData = os.urandom(100*1024*1024); … … 93 104 reporter.log(' --disk-formats <type1[:type2[:...]]>'); 94 105 reporter.log(' Default: %s' % (':'.join(self.asDiskFormats))); 95 reporter.log(' --test-vms <vm1[:vm2[:...]]>');96 reporter.log(' Test the specified VMs in the given order. Use this to change');97 reporter.log(' the execution order or limit the choice of VMs');98 reporter.log(' Default: %s (all)' % (':'.join(self.asTestVMsDef)));99 reporter.log(' --skip-vms <vm1[:vm2[:...]]>');100 reporter.log(' Skip the specified VMs when testing.');101 106 return rc; 102 107 … … 111 116 if iArg >= len(asArgs): raise base.InvalidOption('The "--disk-formats" takes a colon separated list of disk formats'); 112 117 self.asDiskFormats = asArgs[iArg].split(':'); 113 elif asArgs[iArg] == '--test-vms':114 iArg += 1;115 if iArg >= len(asArgs): raise base.InvalidOption('The "--test-vms" takes colon separated list');116 self.asTestVMs = asArgs[iArg].split(':');117 for s in self.asTestVMs:118 if s not in self.asTestVMsDef:119 raise base.InvalidOption('The "--test-vms" value "%s" is not valid; valid values are: %s' \120 % (s, ' '.join(self.asTestVMsDef)));121 elif asArgs[iArg] == '--skip-vms':122 iArg += 1;123 if iArg >= len(asArgs): raise base.InvalidOption('The "--skip-vms" takes colon separated list');124 self.asSkipVMs = asArgs[iArg].split(':');125 for s in self.asSkipVMs:126 if s not in self.asTestVMsDef:127 reporter.log('warning: The "--test-vms" value "%s" does not specify any of our test VMs.' % (s));128 118 else: 129 119 return vbox.TestDriver.parseOption(self, asArgs, iArg); 130 120 return iArg + 1; 131 121 132 def completeOptions(self):133 # Remove skipped VMs from the test list.134 for sVM in self.asSkipVMs:135 try: self.asTestVMs.remove(sVM);136 except: pass;137 138 return vbox.TestDriver.completeOptions(self);139 140 122 def getResourceSet(self): 141 123 # Construct the resource list the first time it's queried. 142 124 if self.asRsrcs is None: 143 self.asRsrcs = []; 144 if 'tst-win7-vhd' in self.asTestVMs: 145 self.asRsrcs.append('4.2/storage/win7.vhd'); 146 147 if 'tst-debian-vhd' in self.asTestVMs: 148 self.asRsrcs.append('4.2/storage/debian.vhd'); 149 150 if 'tst-debian-vdi' in self.asTestVMs: 151 self.asRsrcs.append('4.2/storage/debian.vdi'); 152 125 self.asRsrcs = ['5.3/storage/mergeMedium/t-orig.vdi', '5.3/storage/mergeMedium/t-fixed.vdi', '5.3/storage/mergeMedium/t-resized.vdi']; 153 126 return self.asRsrcs; 154 155 def actionConfig(self):156 157 # Make sure vboxapi has been imported so we can use the constants.158 if not self.importVBoxApi():159 return False;160 161 #162 # Configure the VMs we're going to use.163 #164 165 # Windows VMs166 if 'tst-win7-vhd' in self.asTestVMs:167 oVM = self.createTestVM('tst-win7-vhd', 1, '4.2/storage/win7.vhd', sKind = 'Windows7', fIoApic = True, \168 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT, \169 eNic0Type = vboxcon.NetworkAdapterType_Am79C973);170 if oVM is None:171 return False;172 173 # Linux VMs174 if 'tst-debian-vhd' in self.asTestVMs:175 oVM = self.createTestVM('tst-debian-vhd', 1, '4.2/storage/debian.vhd', sKind = 'Debian_64', fIoApic = True, \176 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT, \177 eNic0Type = vboxcon.NetworkAdapterType_Am79C973);178 if oVM is None:179 return False;180 181 if 'tst-debian-vdi' in self.asTestVMs:182 oVM = self.createTestVM('tst-debian-vdi', 1, '4.2/storage/debian.vdi', sKind = 'Debian_64', fIoApic = True, \183 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT, \184 eNic0Type = vboxcon.NetworkAdapterType_Am79C973);185 if oVM is None:186 return False;187 188 return True;189 127 190 128 def actionExecute(self): … … 194 132 fRc = self.test1(); 195 133 return fRc; 196 197 134 135 def resizeMedium(self, oMedium, cbNewSize): 136 if oMedium.deviceType is not vboxcon.DeviceType_HardDisk: 137 return False; 138 139 if oMedium.type is not vboxcon.MediumType_Normal: 140 return False; 141 142 #currently only VDI can be resizable. Medium variant is not checked, because testcase creates disks itself 143 oMediumFormat = oMedium.mediumFormat; 144 if oMediumFormat.id != 'VDI': 145 return False; 146 147 cbCurrSize = oMedium.logicalSize; 148 # currently reduce is not supported 149 if cbNewSize < cbCurrSize: 150 return False; 151 152 try: 153 oProgressCom = oMedium.resize(cbNewSize); 154 oProgress = vboxwrappers.ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oVBox.oTstDrv, 'Resize medium %s' % (oMedium.name)); 155 oProgress.wait(cMsTimeout = 60 * 1000); 156 oProgress.logResult(); 157 except: 158 reporter.logXcpt('IMedium::resize failed on %s' % (oMedium.name)); 159 return False; 160 161 return True; 162 163 def getMedium(self, oVM, sController): 164 oMediumAttachments = oVM.getMediumAttachmentsOfController(sController); 165 166 for oAttachment in oMediumAttachments: 167 oMedium = oAttachment.medium; 168 if oMedium.deviceType is not vboxcon.DeviceType_HardDisk: 169 continue; 170 if oMedium.type is not vboxcon.MediumType_Normal: 171 continue; 172 return oMedium; 173 174 return None; 175 176 def getSnapshotMedium(self, oSnapshot, sController): 177 oVM = oSnapshot.machine; 178 oMedium = self.getMedium(oVM, sController); 179 180 for oChildMedium in oMedium.children: 181 for uSnapshotId in oChildMedium.getSnapshotIds(oVM.id): 182 if uSnapshotId == oVM.id: 183 return oChildMedium; 184 185 return None; 186 187 def openMedium(self, sHd, fImmutable = False): 188 """ 189 Opens medium in readonly mode. 190 Returns Medium object on success and None on failure. Error information is logged. 191 """ 192 sFullName = self.oVBox.oTstDrv.getFullResourceName(sHd); 193 try: 194 oHd = self.oVBox.findHardDisk(sFullName); 195 except: 196 try: 197 if self.fpApiVer >= 4.1: 198 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly, False); 199 elif self.fpApiVer >= 4.0: 200 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly); 201 else: 202 oHd = self.oVBox.openHardDisk(sFullName, vboxcon.AccessMode_ReadOnly, False, "", False, ""); 203 204 except: 205 reporter.errorXcpt('failed to open hd "%s"' % (sFullName)); 206 return False; 207 208 try: 209 if fImmutable: 210 oHd.type = vboxcon.MediumType_Immutable; 211 else: 212 oHd.type = vboxcon.MediumType_Normal; 213 214 except: 215 if fImmutable: 216 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd)); 217 else: 218 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd)); 219 220 return None; 221 222 return oHd; 223 224 def cloneMedium(self, oSrcHd, oTgtHd): 225 """ 226 Clones medium into target medium. 227 """ 228 try: 229 oProgressCom = oSrcHd.cloneTo(oTgtHd, (vboxcon.MediumVariant_Standard, ), None); 230 oProgress = vboxwrappers.ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oVBox.oTstDrv, 'clone base disk %s to %s' % (oSrcHd.name, oTgtHd.name)); 231 oProgress.wait(cMsTimeout = 60 * 1000); 232 oProgress.logResult(); 233 except: 234 reporter.errorXcpt('failed to clone medium %s to %s' % (oSrcHd.name, oTgtHd.name)); 235 return False; 236 237 return True; 238 239 def deleteVM(self, oVM): 240 try: 241 oVM.unregister(vboxcon.CleanupMode_DetachAllReturnNone); 242 except: 243 reporter.logXcpt(); 244 pass; 245 246 if self.fpApiVer >= 4.0: 247 try: 248 if self.fpApiVer >= 4.3: 249 oProgress = oVM.deleteConfig([]); 250 else: 251 oProgress = oVM.delete(None); 252 self.waitOnProgress(oProgress); 253 254 except: 255 reporter.logXcpt(); 256 257 else: 258 try: oVM.deleteSettings(); 259 except: reporter.logXcpt(); 260 261 return None; 262 198 263 # 199 264 # Test execution helpers. 200 265 # 201 266 202 def test1UploadFile(self, oSession, oTxsSession): 203 """ 204 Uploads a test file to the test machine. 205 """ 206 reporter.testStart('Upload file'); 207 208 fRc = self.txsUploadString(oSession, oTxsSession, self.sRndData, '${SCRATCH}/' + str(uuid.uuid4()), \ 209 cMsTimeout = 3600 * 1000); 210 211 reporter.testDone(not fRc); 212 return fRc; 213 214 def test1OneCfg(self, sVmName, eStorageController, sDiskFormat): 267 def test1OneCfg(self, eStorageController, oDskFmt): 215 268 """ 216 269 Runs the specified VM thru test #1. … … 219 272 the actual test result. 220 273 """ 221 oVM = self.getVmByName(sVmName); 222 223 # @ŧodo: Implement support for different formats. 224 _ = sDiskFormat; 225 274 275 (asExts, aTypes) = oDskFmt.describeFileExtensions() 276 for i in range(0, len(asExts)): #pylint: disable=consider-using-enumerate 277 if aTypes[i] is vboxcon.DeviceType_HardDisk: 278 sExt = '.' + asExts[i] 279 break 280 281 if sExt is None: 282 return False; 283 284 oOrigBaseHd = self.openMedium('5.3/storage/mergeMedium/t-orig.vdi'); 285 if oOrigBaseHd is None: 286 return False; 287 288 #currently only VDI can be resizable. Medium variant is not checked, because testcase creates disks itself 289 fFmtDynamic = oDskFmt.id == 'VDI'; 290 sOrigWithDiffHd = '5.3/storage/mergeMedium/t-fixed.vdi' 291 uOrigCrc = 0x7a417cbb; 292 293 if fFmtDynamic: 294 sOrigWithDiffHd = '5.3/storage/mergeMedium/t-resized.vdi'; 295 uOrigCrc = 0xa8f5daa3; 296 297 oOrigWithDiffHd = self.openMedium(sOrigWithDiffHd); 298 if oOrigWithDiffHd is None: 299 return False; 300 301 oVM = self.createTestVM('testvm', 1, None); 302 if oVM is None: 303 return False; 304 305 sController = _ControllerTypeToName(eStorageController); 306 226 307 # Reconfigure the VM 308 oSession = self.openSession(oVM); 309 if oSession is None: 310 return False; 311 # Attach HD 312 227 313 fRc = True; 228 oSession = self.openSession(oVM); 314 sFile = 't-base' + sExt; 315 sHddPath = os.path.join(self.oVBox.oTstDrv.sScratchPath, sFile); 316 oHd = oSession.createBaseHd(sHddPath, sFmt=oDskFmt.id, cb=oOrigBaseHd.logicalSize); 317 #if oSession.createBaseHd can't create disk because it exists, oHd will point to some stub object anyway 318 fRc = fRc and oHd is not None and oHd.logicalSize == oOrigBaseHd.logicalSize; 319 fRc = fRc and self.cloneMedium(oOrigBaseHd, oHd); 320 321 fRc = fRc and oSession.ensureControllerAttached(sController); 322 fRc = fRc and oSession.setStorageControllerType(eStorageController, sController); 323 fRc = fRc and oSession.saveSettings(); 324 fRc = fRc and oSession.attachHd(sHddPath, sController, iPort = 0, fImmutable=False, fForceResource=False) 325 326 if fRc: 327 oSession.takeSnapshot('Base snapshot'); 328 oSnapshot = oSession.findSnapshot('Base snapshot'); 329 330 if oSnapshot is not None: 331 oSnapshotMedium = self.getSnapshotMedium(oSnapshot, sController); 332 fRc = oSnapshotMedium is not None; 333 334 if fFmtDynamic: 335 fRc = fRc and self.resizeMedium(oSnapshotMedium, oOrigWithDiffHd.logicalSize); 336 fRc = fRc and self.cloneMedium(oOrigWithDiffHd, oSnapshotMedium); 337 fRc = fRc and oSession.deleteSnapshot(oSnapshot.id, cMsTimeout = 120 * 1000); 338 339 if fRc: 340 # disk for result test by checksum 341 sResFilePath = os.path.join(self.oVBox.oTstDrv.sScratchPath, 't_res.vmdk'); 342 sResFilePathRaw = os.path.join(self.oVBox.oTstDrv.sScratchPath, 't_res-flat.vmdk'); 343 oResHd = oSession.createBaseHd(sResFilePath, sFmt='VMDK', cb=oOrigWithDiffHd.logicalSize, tMediumVariant = (vboxcon.MediumVariant_Fixed, )); 344 fRc = oResHd is not None; 345 fRc = fRc and self.cloneMedium(oHd, oResHd); 346 347 uResCrc32 = 0; 348 if fRc: 349 uResCrc32 = crc32_of_file(sResFilePathRaw); 350 if uResCrc32 == uOrigCrc: 351 reporter.log('Snapshot merged successfully. Data of the result medium are correspond to data of the original medium'); 352 fRc = True; 353 else: 354 reporter.error('Snapshot merging failed. Data of the result medium not correspond to data of the original medium'); 355 fRc = False; 356 357 self.oVBox.deleteHdByMedium(oResHd); 358 229 359 if oSession is not None: 230 # Attach HD 231 fRc = oSession.ensureControllerAttached(_ControllerTypeToName(eStorageController)); 232 fRc = fRc and oSession.setStorageControllerType(eStorageController, _ControllerTypeToName(eStorageController)); 233 fRc = fRc and oSession.saveSettings(); 234 fRc = oSession.close() and fRc and True; # pychecker hack. 235 oSession = None; 236 else: 237 fRc = False; 238 239 # Start up. 240 if fRc is True: 241 self.logVmInfo(oVM); 242 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(sVmName, fCdWait = False, fNatForwardingForTxs = True); 243 if oSession is not None: 244 self.addTask(oTxsSession); 245 246 # Fudge factor - Allow the guest to finish starting up. 247 self.sleep(5); 248 249 # Do a snapshot first. 250 oSession.takeSnapshot('Base snapshot'); 251 252 for i in range(0, 10): 253 oSession.takeSnapshot('Snapshot ' + str(i)); 254 self.test1UploadFile(oSession, oTxsSession); 255 msNow = base.timestampMilli(); 256 oSnapshot = oSession.findSnapshot('Snapshot ' + str(i)); 257 oSession.deleteSnapshot(oSnapshot.id, cMsTimeout = 60 * 1000); 258 msElapsed = base.timestampMilli() - msNow; 259 reporter.log('Deleting snapshot %d took %d ms' % (i, msElapsed)); 260 261 # cleanup. 262 self.removeTask(oTxsSession); 263 self.terminateVmBySession(oSession) 264 else: 265 fRc = False; 360 if oHd is not None: 361 oSession.detachHd(sController, iPort = 0, iDevice = 0); 362 363 oSession.saveSettings(fClose = True); 364 if oHd is not None: 365 self.oVBox.deleteHdByMedium(oHd); 366 367 self.deleteVM(oVM); 266 368 return fRc; 267 369 268 def test1OneVM(self, sVmName): 269 """ 270 Runs one VM thru the various configurations. 271 """ 370 def test1(self): 371 """ 372 Executes test #1 thru the various configurations. 373 """ 374 if not self.importVBoxApi(): 375 return False; 376 377 sVmName = 'testvm'; 272 378 reporter.testStart(sVmName); 379 380 aoDskFmts = self.oVBoxMgr.getArray(self.oVBox.systemProperties, 'mediumFormats') 381 if aoDskFmts is None or len(aoDskFmts) < 1: 382 return False; 383 273 384 fRc = True; 274 385 for sStorageCtrl in self.asStorageCtrls: 275 386 reporter.testStart(sStorageCtrl); 276 277 387 if sStorageCtrl == 'AHCI': 278 388 eStorageCtrl = vboxcon.StorageControllerType_IntelAhci; … … 287 397 else: 288 398 eStorageCtrl = None; 289 290 for sDiskFormat in self.asDiskFormats: 291 reporter.testStart('%s' % (sDiskFormat)); 292 self.test1OneCfg(sVmName, eStorageCtrl, sDiskFormat); 293 reporter.testDone(); 399 400 for oDskFmt in aoDskFmts: 401 if (oDskFmt.id in self.asDiskFormats): 402 reporter.testStart('%s' % (oDskFmt.id)); 403 fRc = self.test1OneCfg(eStorageCtrl, oDskFmt); 404 reporter.testDone(); 405 if not fRc: 406 break; 407 294 408 reporter.testDone(); 409 if not fRc: 410 break; 411 295 412 reporter.testDone(); 296 413 return fRc; 297 414 298 def test1(self):299 """300 Executes test #1.301 """302 303 # Loop thru the test VMs.304 for sVM in self.asTestVMs:305 # run test on the VM.306 if not self.test1OneVM(sVM):307 fRc = False;308 else:309 fRc = True;310 311 return fRc;312 313 314 315 415 if __name__ == '__main__': 316 416 sys.exit(tdStorageSnapshot().main(sys.argv));
Note:
See TracChangeset
for help on using the changeset viewer.