VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/tests/storage/tdStorageSnapshotMerging1.py@ 79022

Last change on this file since 79022 was 79022, checked in by vboxsync, 6 years ago

tdStorageSnapshotMerging1.py: Readable time out values, please! Don't put anything unnecessary inside the try/except block!

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 15.6 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdStorageSnapshotMerging1.py 79022 2019-06-06 12:39:01Z vboxsync $
4
5"""
6VirtualBox Validation Kit - Storage snapshotting and merging testcase.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2013-2019 Oracle Corporation
12
13This file is part of VirtualBox Open Source Edition (OSE), as
14available from http://www.virtualbox.org. This file is free software;
15you can redistribute it and/or modify it under the terms of the GNU
16General Public License (GPL) as published by the Free Software
17Foundation, in version 2 as it comes in the "COPYING" file of the
18VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20
21The contents of this file may alternatively be used under the terms
22of the Common Development and Distribution License Version 1.0
23(CDDL) only, as it comes in the "COPYING.CDDL" file of the
24VirtualBox OSE distribution, in which case the provisions of the
25CDDL are applicable instead of those of the GPL.
26
27You may elect to license modified versions of this file under the
28terms and conditions of either the GPL or the CDDL or both.
29"""
30__version__ = "$Revision: 79022 $"
31
32
33# Standard Python imports.
34import os;
35import sys;
36import zlib;
37
38# Only the main script needs to modify the path.
39try: __file__
40except: __file__ = sys.argv[0];
41g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))));
42sys.path.append(g_ksValidationKitDir);
43
44# Validation Kit imports.
45from testdriver import reporter;
46from testdriver import base;
47from testdriver import vbox;
48from testdriver import vboxcon;
49from testdriver import vboxwrappers;
50
51
52def _ControllerTypeToName(eControllerType):
53 """ Translate a controller type to a name. """
54 if eControllerType == vboxcon.StorageControllerType_PIIX3 or eControllerType == vboxcon.StorageControllerType_PIIX4:
55 sType = "IDE Controller";
56 elif eControllerType == vboxcon.StorageControllerType_IntelAhci:
57 sType = "SATA Controller";
58 elif eControllerType == vboxcon.StorageControllerType_LsiLogicSas:
59 sType = "SAS Controller";
60 elif eControllerType == vboxcon.StorageControllerType_LsiLogic or eControllerType == vboxcon.StorageControllerType_BusLogic:
61 sType = "SCSI Controller";
62 else:
63 sType = "Storage Controller";
64 return sType;
65
66
67def crc32_of_file(filepath):
68 fileobj = open(filepath,'rb');
69 current = 0;
70
71 while True:
72 buf = fileobj.read(1024 * 1024);
73 if not buf:
74 break
75 current = zlib.crc32(buf, current);
76
77 fileobj.close();
78 return current % 2**32;
79
80
81class tdStorageSnapshot(vbox.TestDriver): # pylint: disable=R0902
82 """
83 Storage benchmark.
84 """
85 def __init__(self):
86 vbox.TestDriver.__init__(self);
87 self.asRsrcs = None;
88 self.oGuestToGuestVM = None;
89 self.oGuestToGuestSess = None;
90 self.oGuestToGuestTxs = None;
91 self.asStorageCtrlsDef = ['AHCI', 'IDE', 'LsiLogicSAS', 'LsiLogic', 'BusLogic'];
92 self.asStorageCtrls = self.asStorageCtrlsDef;
93 #self.asDiskFormatsDef = ['VDI', 'VMDK', 'VHD', 'QED', 'Parallels', 'QCOW', 'iSCSI'];
94 self.asDiskFormatsDef = ['VDI', 'VMDK', 'VHD'];
95 self.asDiskFormats = self.asDiskFormatsDef;
96 self.sRndData = os.urandom(100*1024*1024);
97
98 #
99 # Overridden methods.
100 #
101 def showUsage(self):
102 rc = vbox.TestDriver.showUsage(self);
103 reporter.log('');
104 reporter.log('tdStorageSnapshot1 Options:');
105 reporter.log(' --storage-ctrls <type1[:type2[:...]]>');
106 reporter.log(' Default: %s' % (':'.join(self.asStorageCtrls)));
107 reporter.log(' --disk-formats <type1[:type2[:...]]>');
108 reporter.log(' Default: %s' % (':'.join(self.asDiskFormats)));
109 return rc;
110
111 def parseOption(self, asArgs, iArg): # pylint: disable=R0912,R0915
112 if asArgs[iArg] == '--storage-ctrls':
113 iArg += 1;
114 if iArg >= len(asArgs):
115 raise base.InvalidOption('The "--storage-ctrls" takes a colon separated list of Storage controller types');
116 self.asStorageCtrls = asArgs[iArg].split(':');
117 elif asArgs[iArg] == '--disk-formats':
118 iArg += 1;
119 if iArg >= len(asArgs): raise base.InvalidOption('The "--disk-formats" takes a colon separated list of disk formats');
120 self.asDiskFormats = asArgs[iArg].split(':');
121 else:
122 return vbox.TestDriver.parseOption(self, asArgs, iArg);
123 return iArg + 1;
124
125 def getResourceSet(self):
126 # Construct the resource list the first time it's queried.
127 if self.asRsrcs is None:
128 self.asRsrcs = ['5.3/storage/mergeMedium/t-orig.vdi',
129 '5.3/storage/mergeMedium/t-fixed.vdi',
130 '5.3/storage/mergeMedium/t-resized.vdi'];
131 return self.asRsrcs;
132
133 def actionExecute(self):
134 """
135 Execute the testcase.
136 """
137 fRc = self.test1();
138 return fRc;
139
140 def resizeMedium(self, oMedium, cbNewSize):
141 if oMedium.deviceType is not vboxcon.DeviceType_HardDisk:
142 return False;
143
144 if oMedium.type is not vboxcon.MediumType_Normal:
145 return False;
146
147 #currently only VDI can be resizable. Medium variant is not checked, because testcase creates disks itself
148 oMediumFormat = oMedium.mediumFormat;
149 if oMediumFormat.id != 'VDI':
150 return False;
151
152 cbCurrSize = oMedium.logicalSize;
153 # currently reduce is not supported
154 if cbNewSize < cbCurrSize:
155 return False;
156
157 try:
158 oProgressCom = oMedium.resize(cbNewSize);
159 except:
160 reporter.logXcpt('IMedium::resize failed on %s' % (oMedium.name));
161 return False;
162 oProgress = vboxwrappers.ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oVBox.oTstDrv,
163 'Resize medium %s' % (oMedium.name));
164 oProgress.wait(cMsTimeout = 15*60*1000); # 15 min
165 oProgress.logResult();
166 return True;
167
168 def getMedium(self, oVM, sController):
169 oMediumAttachments = oVM.getMediumAttachmentsOfController(sController);
170
171 for oAttachment in oMediumAttachments:
172 oMedium = oAttachment.medium;
173 if oMedium.deviceType is not vboxcon.DeviceType_HardDisk:
174 continue;
175 if oMedium.type is not vboxcon.MediumType_Normal:
176 continue;
177 return oMedium;
178
179 return None;
180
181 def getSnapshotMedium(self, oSnapshot, sController):
182 oVM = oSnapshot.machine;
183 oMedium = self.getMedium(oVM, sController);
184
185 aoMediumChildren = self.oVBoxMgr.getArray(oMedium, 'children')
186 if aoMediumChildren is None or len(aoMediumChildren) < 1:
187 return None;
188
189 for oChildMedium in aoMediumChildren:
190 for uSnapshotId in oChildMedium.getSnapshotIds(oVM.id):
191 if uSnapshotId == oVM.id:
192 return oChildMedium;
193
194 return None;
195
196 def openMedium(self, sHd, fImmutable = False):
197 """
198 Opens medium in readonly mode.
199 Returns Medium object on success and None on failure. Error information is logged.
200 """
201 sFullName = self.oVBox.oTstDrv.getFullResourceName(sHd);
202 try:
203 oHd = self.oVBox.findHardDisk(sFullName);
204 except:
205 try:
206 if self.fpApiVer >= 4.1:
207 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly, False);
208 elif self.fpApiVer >= 4.0:
209 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly);
210 else:
211 oHd = self.oVBox.openHardDisk(sFullName, vboxcon.AccessMode_ReadOnly, False, "", False, "");
212
213 except:
214 reporter.errorXcpt('failed to open hd "%s"' % (sFullName));
215 return None;
216
217 try:
218 if fImmutable:
219 oHd.type = vboxcon.MediumType_Immutable;
220 else:
221 oHd.type = vboxcon.MediumType_Normal;
222
223 except:
224 if fImmutable:
225 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
226 else:
227 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
228
229 return None;
230
231 return oHd;
232
233 def cloneMedium(self, oSrcHd, oTgtHd):
234 """
235 Clones medium into target medium.
236 """
237 try:
238 oProgressCom = oSrcHd.cloneTo(oTgtHd, (vboxcon.MediumVariant_Standard, ), None);
239 except:
240 reporter.errorXcpt('failed to clone medium %s to %s' % (oSrcHd.name, oTgtHd.name));
241 return False;
242 oProgress = vboxwrappers.ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oVBox.oTstDrv,
243 'clone base disk %s to %s' % (oSrcHd.name, oTgtHd.name));
244 oProgress.wait(cMsTimeout = 15*60*1000); # 15 min
245 oProgress.logResult();
246 return True;
247
248 def deleteVM(self, oVM):
249 try:
250 oVM.unregister(vboxcon.CleanupMode_DetachAllReturnNone);
251 except:
252 reporter.logXcpt();
253
254 if self.fpApiVer >= 4.0:
255 try:
256 if self.fpApiVer >= 4.3:
257 oProgress = oVM.deleteConfig([]);
258 else:
259 oProgress = oVM.delete(None);
260 except:
261 reporter.logXcpt();
262 else:
263 oProgress.wait(cMsTimeout = 15*60*1000); # 15 min
264 else:
265 try: oVM.deleteSettings();
266 except: reporter.logXcpt();
267
268 return None;
269
270 #
271 # Test execution helpers.
272 #
273
274 def test1OneCfg(self, eStorageController, oDskFmt):
275 """
276 Runs the specified VM thru test #1.
277
278 Returns a success indicator on the general test execution. This is not
279 the actual test result.
280 """
281
282 (asExts, aTypes) = oDskFmt.describeFileExtensions()
283 for i in range(0, len(asExts)): #pylint: disable=consider-using-enumerate
284 if aTypes[i] is vboxcon.DeviceType_HardDisk:
285 sExt = '.' + asExts[i]
286 break
287
288 if sExt is None:
289 return False;
290
291 oOrigBaseHd = self.openMedium('5.3/storage/mergeMedium/t-orig.vdi');
292 if oOrigBaseHd is None:
293 return False;
294
295 #currently only VDI can be resizable. Medium variant is not checked, because testcase creates disks itself
296 fFmtDynamic = oDskFmt.id == 'VDI';
297 sOrigWithDiffHd = '5.3/storage/mergeMedium/t-fixed.vdi'
298 uOrigCrc = 0x7a417cbb;
299
300 if fFmtDynamic:
301 sOrigWithDiffHd = '5.3/storage/mergeMedium/t-resized.vdi';
302 uOrigCrc = 0xa8f5daa3;
303
304 oOrigWithDiffHd = self.openMedium(sOrigWithDiffHd);
305 if oOrigWithDiffHd is None:
306 return False;
307
308 oVM = self.createTestVM('testvm', 1, None);
309 if oVM is None:
310 return False;
311
312 sController = _ControllerTypeToName(eStorageController);
313
314 # Reconfigure the VM
315 oSession = self.openSession(oVM);
316 if oSession is None:
317 return False;
318 # Attach HD
319
320 fRc = True;
321 sFile = 't-base' + sExt;
322 sHddPath = os.path.join(self.oVBox.oTstDrv.sScratchPath, sFile);
323 oHd = oSession.createBaseHd(sHddPath, sFmt=oDskFmt.id, cb=oOrigBaseHd.logicalSize);
324 #if oSession.createBaseHd can't create disk because it exists, oHd will point to some stub object anyway
325 fRc = fRc and oHd is not None and (oHd.logicalSize == oOrigBaseHd.logicalSize);
326 fRc = fRc and self.cloneMedium(oOrigBaseHd, oHd);
327
328 fRc = fRc and oSession.ensureControllerAttached(sController);
329 fRc = fRc and oSession.setStorageControllerType(eStorageController, sController);
330 fRc = fRc and oSession.saveSettings();
331 fRc = fRc and oSession.attachHd(sHddPath, sController, iPort = 0, fImmutable=False, fForceResource=False)
332
333 if fRc:
334 oSession.takeSnapshot('Base snapshot');
335 oSnapshot = oSession.findSnapshot('Base snapshot');
336
337 if oSnapshot is not None:
338 oSnapshotMedium = self.getSnapshotMedium(oSnapshot, sController);
339 fRc = oSnapshotMedium is not None;
340
341 if fFmtDynamic:
342 fRc = fRc and self.resizeMedium(oSnapshotMedium, oOrigWithDiffHd.logicalSize);
343 fRc = fRc and self.cloneMedium(oOrigWithDiffHd, oSnapshotMedium);
344 fRc = fRc and oSession.deleteSnapshot(oSnapshot.id, cMsTimeout = 120 * 1000);
345
346 if fRc:
347 # disk for result test by checksum
348 sResFilePath = os.path.join(self.oVBox.oTstDrv.sScratchPath, 't_res.vmdk');
349 sResFilePathRaw = os.path.join(self.oVBox.oTstDrv.sScratchPath, 't_res-flat.vmdk');
350 oResHd = oSession.createBaseHd(sResFilePath, sFmt='VMDK', cb=oOrigWithDiffHd.logicalSize,
351 tMediumVariant = (vboxcon.MediumVariant_Fixed, ));
352 fRc = oResHd is not None;
353 fRc = fRc and self.cloneMedium(oHd, oResHd);
354
355 uResCrc32 = 0;
356 if fRc:
357 uResCrc32 = crc32_of_file(sResFilePathRaw);
358 if uResCrc32 == uOrigCrc:
359 reporter.log('Snapshot merged successfully. Crc32 is correct');
360 fRc = True;
361 else:
362 reporter.error('Snapshot merging failed. Crc32 is invalid');
363 fRc = False;
364
365 self.oVBox.deleteHdByMedium(oResHd);
366
367 if oSession is not None:
368 if oHd is not None:
369 oSession.detachHd(sController, iPort = 0, iDevice = 0);
370
371 oSession.saveSettings(fClose = True);
372 if oHd is not None:
373 self.oVBox.deleteHdByMedium(oHd);
374
375 self.deleteVM(oVM);
376 return fRc;
377
378 def test1(self):
379 """
380 Executes test #1 thru the various configurations.
381 """
382 if not self.importVBoxApi():
383 return False;
384
385 sVmName = 'testvm';
386 reporter.testStart(sVmName);
387
388 aoDskFmts = self.oVBoxMgr.getArray(self.oVBox.systemProperties, 'mediumFormats')
389 if aoDskFmts is None or len(aoDskFmts) < 1:
390 return False;
391
392 fRc = True;
393 for sStorageCtrl in self.asStorageCtrls:
394 reporter.testStart(sStorageCtrl);
395 if sStorageCtrl == 'AHCI':
396 eStorageCtrl = vboxcon.StorageControllerType_IntelAhci;
397 elif sStorageCtrl == 'IDE':
398 eStorageCtrl = vboxcon.StorageControllerType_PIIX4;
399 elif sStorageCtrl == 'LsiLogicSAS':
400 eStorageCtrl = vboxcon.StorageControllerType_LsiLogicSas;
401 elif sStorageCtrl == 'LsiLogic':
402 eStorageCtrl = vboxcon.StorageControllerType_LsiLogic;
403 elif sStorageCtrl == 'BusLogic':
404 eStorageCtrl = vboxcon.StorageControllerType_BusLogic;
405 else:
406 eStorageCtrl = None;
407
408 for oDskFmt in aoDskFmts:
409 if oDskFmt.id in self.asDiskFormats:
410 reporter.testStart('%s' % (oDskFmt.id));
411 fRc = self.test1OneCfg(eStorageCtrl, oDskFmt);
412 reporter.testDone();
413 if not fRc:
414 break;
415
416 reporter.testDone();
417 if not fRc:
418 break;
419
420 reporter.testDone();
421 return fRc;
422
423if __name__ == '__main__':
424 sys.exit(tdStorageSnapshot().main(sys.argv));
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette