VirtualBox

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

Last change on this file since 88254 was 88254, checked in by vboxsync, 4 years ago

ValidationKit/tdStorageSnapshotMerging1: pylint-2.x points out that the
expression 'uOrigCrc = 0xa8f5daa3' redefines 'uOrigCrc' to a long since
the value 0xa8f5daa3 exceeds MAX_INT. Thus specify 'uOrigCrc' and
'uResCrc32' (which is promoted to 'long' in the comparison 'if uResCrc32

uOrigCrc') as long data types and then include the Python3

compatibility hack of 'long = int' since Python3 dropped support for the
'long' data type.

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 15.4 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdStorageSnapshotMerging1.py 88254 2021-03-22 20:59:46Z vboxsync $
4
5"""
6VirtualBox Validation Kit - Storage snapshotting and merging testcase.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2013-2020 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: 88254 $"
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# Python 3 hacks:
52if sys.version_info[0] >= 3:
53 long = int; # pylint: disable=redefined-builtin,invalid-name
54
55
56def crc32_of_file(filepath):
57 fileobj = open(filepath,'rb');
58 current = 0;
59
60 while True:
61 buf = fileobj.read(1024 * 1024);
62 if not buf:
63 break
64 current = zlib.crc32(buf, current);
65
66 fileobj.close();
67 return current % 2**32;
68
69
70class tdStorageSnapshot(vbox.TestDriver): # pylint: disable=too-many-instance-attributes
71 """
72 Storage benchmark.
73 """
74 def __init__(self):
75 vbox.TestDriver.__init__(self);
76 self.asRsrcs = None;
77 self.oGuestToGuestVM = None;
78 self.oGuestToGuestSess = None;
79 self.oGuestToGuestTxs = None;
80 self.asStorageCtrlsDef = ['AHCI'];
81 self.asStorageCtrls = self.asStorageCtrlsDef;
82 #self.asDiskFormatsDef = ['VDI', 'VMDK', 'VHD', 'QED', 'Parallels', 'QCOW', 'iSCSI'];
83 self.asDiskFormatsDef = ['VDI', 'VMDK', 'VHD'];
84 self.asDiskFormats = self.asDiskFormatsDef;
85 self.sRndData = os.urandom(100*1024*1024);
86
87 #
88 # Overridden methods.
89 #
90 def showUsage(self):
91 rc = vbox.TestDriver.showUsage(self);
92 reporter.log('');
93 reporter.log('tdStorageSnapshot1 Options:');
94 reporter.log(' --storage-ctrls <type1[:type2[:...]]>');
95 reporter.log(' Default: %s' % (':'.join(self.asStorageCtrls)));
96 reporter.log(' --disk-formats <type1[:type2[:...]]>');
97 reporter.log(' Default: %s' % (':'.join(self.asDiskFormats)));
98 return rc;
99
100 def parseOption(self, asArgs, iArg): # pylint: disable=too-many-branches,too-many-statements
101 if asArgs[iArg] == '--storage-ctrls':
102 iArg += 1;
103 if iArg >= len(asArgs):
104 raise base.InvalidOption('The "--storage-ctrls" takes a colon separated list of Storage controller types');
105 self.asStorageCtrls = asArgs[iArg].split(':');
106 elif asArgs[iArg] == '--disk-formats':
107 iArg += 1;
108 if iArg >= len(asArgs): raise base.InvalidOption('The "--disk-formats" takes a colon separated list of disk formats');
109 self.asDiskFormats = asArgs[iArg].split(':');
110 else:
111 return vbox.TestDriver.parseOption(self, asArgs, iArg);
112 return iArg + 1;
113
114 def getResourceSet(self):
115 # Construct the resource list the first time it's queried.
116 if self.asRsrcs is None:
117 self.asRsrcs = ['5.3/storage/mergeMedium/t-orig.vdi',
118 '5.3/storage/mergeMedium/t-fixed.vdi',
119 '5.3/storage/mergeMedium/t-resized.vdi'];
120 return self.asRsrcs;
121
122 def actionExecute(self):
123 """
124 Execute the testcase.
125 """
126 fRc = self.test1();
127 return fRc;
128
129 def resizeMedium(self, oMedium, cbNewSize):
130 if oMedium.deviceType is not vboxcon.DeviceType_HardDisk:
131 return False;
132
133 if oMedium.type is not vboxcon.MediumType_Normal:
134 return False;
135
136 #currently only VDI can be resizable. Medium variant is not checked, because testcase creates disks itself
137 oMediumFormat = oMedium.mediumFormat;
138 if oMediumFormat.id != 'VDI':
139 return False;
140
141 cbCurrSize = oMedium.logicalSize;
142 # currently reduce is not supported
143 if cbNewSize < cbCurrSize:
144 return False;
145
146 try:
147 oProgressCom = oMedium.resize(cbNewSize);
148 except:
149 reporter.logXcpt('IMedium::resize failed on %s' % (oMedium.name));
150 return False;
151 oProgress = vboxwrappers.ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oVBox.oTstDrv,
152 'Resize medium %s' % (oMedium.name));
153 oProgress.wait(cMsTimeout = 15*60*1000); # 15 min
154 oProgress.logResult();
155 return True;
156
157 def getMedium(self, oVM, sController):
158 oMediumAttachments = oVM.getMediumAttachmentsOfController(sController);
159
160 for oAttachment in oMediumAttachments:
161 oMedium = oAttachment.medium;
162 if oMedium.deviceType is not vboxcon.DeviceType_HardDisk:
163 continue;
164 if oMedium.type is not vboxcon.MediumType_Normal:
165 continue;
166 return oMedium;
167
168 return None;
169
170 def getSnapshotMedium(self, oSnapshot, sController):
171 oVM = oSnapshot.machine;
172 oMedium = self.getMedium(oVM, sController);
173
174 aoMediumChildren = self.oVBoxMgr.getArray(oMedium, 'children')
175 if aoMediumChildren is None or not aoMediumChildren:
176 return None;
177
178 for oChildMedium in aoMediumChildren:
179 for uSnapshotId in oChildMedium.getSnapshotIds(oVM.id):
180 if uSnapshotId == oVM.id:
181 return oChildMedium;
182
183 return None;
184
185 def openMedium(self, sHd, fImmutable = False):
186 """
187 Opens medium in readonly mode.
188 Returns Medium object on success and None on failure. Error information is logged.
189 """
190 sFullName = self.oVBox.oTstDrv.getFullResourceName(sHd);
191 try:
192 oHd = self.oVBox.findHardDisk(sFullName);
193 except:
194 try:
195 if self.fpApiVer >= 4.1:
196 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly, False);
197 elif self.fpApiVer >= 4.0:
198 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly);
199 else:
200 oHd = self.oVBox.openHardDisk(sFullName, vboxcon.AccessMode_ReadOnly, False, "", False, "");
201
202 except:
203 reporter.errorXcpt('failed to open hd "%s"' % (sFullName));
204 return None;
205
206 try:
207 if fImmutable:
208 oHd.type = vboxcon.MediumType_Immutable;
209 else:
210 oHd.type = vboxcon.MediumType_Normal;
211
212 except:
213 if fImmutable:
214 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
215 else:
216 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
217
218 return None;
219
220 return oHd;
221
222 def cloneMedium(self, oSrcHd, oTgtHd):
223 """
224 Clones medium into target medium.
225 """
226 try:
227 oProgressCom = oSrcHd.cloneTo(oTgtHd, (vboxcon.MediumVariant_Standard, ), None);
228 except:
229 reporter.errorXcpt('failed to clone medium %s to %s' % (oSrcHd.name, oTgtHd.name));
230 return False;
231 oProgress = vboxwrappers.ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oVBox.oTstDrv,
232 'clone base disk %s to %s' % (oSrcHd.name, oTgtHd.name));
233 oProgress.wait(cMsTimeout = 15*60*1000); # 15 min
234 oProgress.logResult();
235 return True;
236
237 def deleteVM(self, oVM):
238 try:
239 oVM.unregister(vboxcon.CleanupMode_DetachAllReturnNone);
240 except:
241 reporter.logXcpt();
242
243 if self.fpApiVer >= 4.0:
244 try:
245 if self.fpApiVer >= 4.3:
246 oProgressCom = oVM.deleteConfig([]);
247 else:
248 oProgressCom = oVM.delete(None);
249 except:
250 reporter.logXcpt();
251 else:
252 oProgress = vboxwrappers.ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oVBox.oTstDrv,
253 'Delete VM %s' % (oVM.name));
254 oProgress.wait(cMsTimeout = 15*60*1000); # 15 min
255 oProgress.logResult();
256 else:
257 try: oVM.deleteSettings();
258 except: reporter.logXcpt();
259
260 return None;
261
262 #
263 # Test execution helpers.
264 #
265
266 def test1OneCfg(self, eStorageController, oDskFmt):
267 """
268 Runs the specified VM thru test #1.
269
270 Returns a success indicator on the general test execution. This is not
271 the actual test result.
272 """
273
274 (asExts, aTypes) = oDskFmt.describeFileExtensions()
275 for i in range(0, len(asExts)): #pylint: disable=consider-using-enumerate
276 if aTypes[i] is vboxcon.DeviceType_HardDisk:
277 sExt = '.' + asExts[i]
278 break
279
280 if sExt is None:
281 return False;
282
283 oOrigBaseHd = self.openMedium('5.3/storage/mergeMedium/t-orig.vdi');
284 if oOrigBaseHd is None:
285 return False;
286
287 #currently only VDI can be resizable. Medium variant is not checked, because testcase creates disks itself
288 fFmtDynamic = oDskFmt.id == 'VDI';
289 sOrigWithDiffHd = '5.3/storage/mergeMedium/t-fixed.vdi'
290 uOrigCrc = long(0x7a417cbb);
291
292 if fFmtDynamic:
293 sOrigWithDiffHd = '5.3/storage/mergeMedium/t-resized.vdi';
294 uOrigCrc = long(0xa8f5daa3);
295
296 oOrigWithDiffHd = self.openMedium(sOrigWithDiffHd);
297 if oOrigWithDiffHd is None:
298 return False;
299
300 oVM = self.createTestVM('testvm', 1, None);
301 if oVM is None:
302 return False;
303
304 sController = self.controllerTypeToName(eStorageController);
305
306 # Reconfigure the VM
307 oSession = self.openSession(oVM);
308 if oSession is None:
309 return False;
310 # Attach HD
311
312 fRc = True;
313 sFile = 't-base' + sExt;
314 sHddPath = os.path.join(self.oVBox.oTstDrv.sScratchPath, sFile);
315 oHd = oSession.createBaseHd(sHddPath, sFmt=oDskFmt.id, cb=oOrigBaseHd.logicalSize,
316 cMsTimeout = 15 * 60 * 1000); # 15 min
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,
344 tMediumVariant = (vboxcon.MediumVariant_Fixed, ),
345 cMsTimeout = 15 * 60 * 1000); # 15 min
346 fRc = oResHd is not None;
347 fRc = fRc and self.cloneMedium(oHd, oResHd);
348
349 uResCrc32 = long(0);
350 if fRc:
351 uResCrc32 = long(crc32_of_file(sResFilePathRaw));
352 if uResCrc32 == uOrigCrc:
353 reporter.log('Snapshot merged successfully. Crc32 is correct');
354 fRc = True;
355 else:
356 reporter.error('Snapshot merging failed. Crc32 is invalid');
357 fRc = False;
358
359 self.oVBox.deleteHdByMedium(oResHd);
360
361 if oSession is not None:
362 if oHd is not None:
363 oSession.detachHd(sController, iPort = 0, iDevice = 0);
364
365 oSession.saveSettings(fClose = True);
366 if oHd is not None:
367 self.oVBox.deleteHdByMedium(oHd);
368
369 self.deleteVM(oVM);
370 return fRc;
371
372 def test1(self):
373 """
374 Executes test #1 thru the various configurations.
375 """
376 if not self.importVBoxApi():
377 return False;
378
379 sVmName = 'testvm';
380 reporter.testStart(sVmName);
381
382 aoDskFmts = self.oVBoxMgr.getArray(self.oVBox.systemProperties, 'mediumFormats')
383 if aoDskFmts is None or not aoDskFmts:
384 return False;
385
386 fRc = True;
387 for sStorageCtrl in self.asStorageCtrls:
388 reporter.testStart(sStorageCtrl);
389 if sStorageCtrl == 'AHCI':
390 eStorageCtrl = vboxcon.StorageControllerType_IntelAhci;
391 elif sStorageCtrl == 'IDE':
392 eStorageCtrl = vboxcon.StorageControllerType_PIIX4;
393 elif sStorageCtrl == 'LsiLogicSAS':
394 eStorageCtrl = vboxcon.StorageControllerType_LsiLogicSas;
395 elif sStorageCtrl == 'LsiLogic':
396 eStorageCtrl = vboxcon.StorageControllerType_LsiLogic;
397 elif sStorageCtrl == 'BusLogic':
398 eStorageCtrl = vboxcon.StorageControllerType_BusLogic;
399 else:
400 eStorageCtrl = None;
401
402 for oDskFmt in aoDskFmts:
403 if oDskFmt.id in self.asDiskFormats:
404 reporter.testStart('%s' % (oDskFmt.id));
405 fRc = self.test1OneCfg(eStorageCtrl, oDskFmt);
406 reporter.testDone();
407 if not fRc:
408 break;
409
410 reporter.testDone();
411 if not fRc:
412 break;
413
414 reporter.testDone();
415 return fRc;
416
417if __name__ == '__main__':
418 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