VirtualBox

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

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

Main:bugref:6598:Fixed pylint issue

  • 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 78125 2019-04-15 14:35:53Z 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: 78125 $"
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 oProgress = vboxwrappers.ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oVBox.oTstDrv,
160 'Resize medium %s' % (oMedium.name));
161 oProgress.wait(cMsTimeout = 60 * 1000);
162 oProgress.logResult();
163 except:
164 reporter.logXcpt('IMedium::resize failed on %s' % (oMedium.name));
165 return False;
166
167 return True;
168
169 def getMedium(self, oVM, sController):
170 oMediumAttachments = oVM.getMediumAttachmentsOfController(sController);
171
172 for oAttachment in oMediumAttachments:
173 oMedium = oAttachment.medium;
174 if oMedium.deviceType is not vboxcon.DeviceType_HardDisk:
175 continue;
176 if oMedium.type is not vboxcon.MediumType_Normal:
177 continue;
178 return oMedium;
179
180 return None;
181
182 def getSnapshotMedium(self, oSnapshot, sController):
183 oVM = oSnapshot.machine;
184 oMedium = self.getMedium(oVM, sController);
185
186 aoMediumChildren = self.oVBoxMgr.getArray(oMedium, 'children')
187 if aoMediumChildren is None or len(aoMediumChildren) < 1:
188 return None;
189
190 for oChildMedium in aoMediumChildren:
191 for uSnapshotId in oChildMedium.getSnapshotIds(oVM.id):
192 if uSnapshotId == oVM.id:
193 return oChildMedium;
194
195 return None;
196
197 def openMedium(self, sHd, fImmutable = False):
198 """
199 Opens medium in readonly mode.
200 Returns Medium object on success and None on failure. Error information is logged.
201 """
202 sFullName = self.oVBox.oTstDrv.getFullResourceName(sHd);
203 try:
204 oHd = self.oVBox.findHardDisk(sFullName);
205 except:
206 try:
207 if self.fpApiVer >= 4.1:
208 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly, False);
209 elif self.fpApiVer >= 4.0:
210 oHd = self.oVBox.openMedium(sFullName, vboxcon.DeviceType_HardDisk, vboxcon.AccessMode_ReadOnly);
211 else:
212 oHd = self.oVBox.openHardDisk(sFullName, vboxcon.AccessMode_ReadOnly, False, "", False, "");
213
214 except:
215 reporter.errorXcpt('failed to open hd "%s"' % (sFullName));
216 return None;
217
218 try:
219 if fImmutable:
220 oHd.type = vboxcon.MediumType_Immutable;
221 else:
222 oHd.type = vboxcon.MediumType_Normal;
223
224 except:
225 if fImmutable:
226 reporter.errorXcpt('failed to set hd "%s" immutable' % (sHd));
227 else:
228 reporter.errorXcpt('failed to set hd "%s" normal' % (sHd));
229
230 return None;
231
232 return oHd;
233
234 def cloneMedium(self, oSrcHd, oTgtHd):
235 """
236 Clones medium into target medium.
237 """
238 try:
239 oProgressCom = oSrcHd.cloneTo(oTgtHd, (vboxcon.MediumVariant_Standard, ), None);
240 oProgress = vboxwrappers.ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oVBox.oTstDrv,
241 'clone base disk %s to %s' % (oSrcHd.name, oTgtHd.name));
242 oProgress.wait(cMsTimeout = 60 * 1000);
243 oProgress.logResult();
244 except:
245 reporter.errorXcpt('failed to clone medium %s to %s' % (oSrcHd.name, oTgtHd.name));
246 return False;
247
248 return True;
249
250 def deleteVM(self, oVM):
251 try:
252 oVM.unregister(vboxcon.CleanupMode_DetachAllReturnNone);
253 except:
254 reporter.logXcpt();
255
256 if self.fpApiVer >= 4.0:
257 try:
258 if self.fpApiVer >= 4.3:
259 oProgress = oVM.deleteConfig([]);
260 else:
261 oProgress = oVM.delete(None);
262 self.waitOnProgress(oProgress);
263
264 except:
265 reporter.logXcpt();
266
267 else:
268 try: oVM.deleteSettings();
269 except: reporter.logXcpt();
270
271 return None;
272
273 #
274 # Test execution helpers.
275 #
276
277 def test1OneCfg(self, eStorageController, oDskFmt):
278 """
279 Runs the specified VM thru test #1.
280
281 Returns a success indicator on the general test execution. This is not
282 the actual test result.
283 """
284
285 (asExts, aTypes) = oDskFmt.describeFileExtensions()
286 for i in range(0, len(asExts)): #pylint: disable=consider-using-enumerate
287 if aTypes[i] is vboxcon.DeviceType_HardDisk:
288 sExt = '.' + asExts[i]
289 break
290
291 if sExt is None:
292 return False;
293
294 oOrigBaseHd = self.openMedium('5.3/storage/mergeMedium/t-orig.vdi');
295 if oOrigBaseHd is None:
296 return False;
297
298 #currently only VDI can be resizable. Medium variant is not checked, because testcase creates disks itself
299 fFmtDynamic = oDskFmt.id == 'VDI';
300 sOrigWithDiffHd = '5.3/storage/mergeMedium/t-fixed.vdi'
301 uOrigCrc = 0x7a417cbb;
302
303 if fFmtDynamic:
304 sOrigWithDiffHd = '5.3/storage/mergeMedium/t-resized.vdi';
305 uOrigCrc = 0xa8f5daa3;
306
307 oOrigWithDiffHd = self.openMedium(sOrigWithDiffHd);
308 if oOrigWithDiffHd is None:
309 return False;
310
311 oVM = self.createTestVM('testvm', 1, None);
312 if oVM is None:
313 return False;
314
315 sController = _ControllerTypeToName(eStorageController);
316
317 # Reconfigure the VM
318 oSession = self.openSession(oVM);
319 if oSession is None:
320 return False;
321 # Attach HD
322
323 fRc = True;
324 sFile = 't-base' + sExt;
325 sHddPath = os.path.join(self.oVBox.oTstDrv.sScratchPath, sFile);
326 oHd = oSession.createBaseHd(sHddPath, sFmt=oDskFmt.id, cb=oOrigBaseHd.logicalSize);
327 #if oSession.createBaseHd can't create disk because it exists, oHd will point to some stub object anyway
328 fRc = fRc and oHd is not None and (oHd.logicalSize == oOrigBaseHd.logicalSize);
329 fRc = fRc and self.cloneMedium(oOrigBaseHd, oHd);
330
331 fRc = fRc and oSession.ensureControllerAttached(sController);
332 fRc = fRc and oSession.setStorageControllerType(eStorageController, sController);
333 fRc = fRc and oSession.saveSettings();
334 fRc = fRc and oSession.attachHd(sHddPath, sController, iPort = 0, fImmutable=False, fForceResource=False)
335
336 if fRc:
337 oSession.takeSnapshot('Base snapshot');
338 oSnapshot = oSession.findSnapshot('Base snapshot');
339
340 if oSnapshot is not None:
341 oSnapshotMedium = self.getSnapshotMedium(oSnapshot, sController);
342 fRc = oSnapshotMedium is not None;
343
344 if fFmtDynamic:
345 fRc = fRc and self.resizeMedium(oSnapshotMedium, oOrigWithDiffHd.logicalSize);
346 fRc = fRc and self.cloneMedium(oOrigWithDiffHd, oSnapshotMedium);
347 fRc = fRc and oSession.deleteSnapshot(oSnapshot.id, cMsTimeout = 120 * 1000);
348
349 if fRc:
350 # disk for result test by checksum
351 sResFilePath = os.path.join(self.oVBox.oTstDrv.sScratchPath, 't_res.vmdk');
352 sResFilePathRaw = os.path.join(self.oVBox.oTstDrv.sScratchPath, 't_res-flat.vmdk');
353 oResHd = oSession.createBaseHd(sResFilePath, sFmt='VMDK', cb=oOrigWithDiffHd.logicalSize,
354 tMediumVariant = (vboxcon.MediumVariant_Fixed, ));
355 fRc = oResHd is not None;
356 fRc = fRc and self.cloneMedium(oHd, oResHd);
357
358 uResCrc32 = 0;
359 if fRc:
360 uResCrc32 = crc32_of_file(sResFilePathRaw);
361 if uResCrc32 == uOrigCrc:
362 reporter.log('Snapshot merged successfully. Crc32 is correct');
363 fRc = True;
364 else:
365 reporter.error('Snapshot merging failed. Crc32 is invalid');
366 fRc = False;
367
368 self.oVBox.deleteHdByMedium(oResHd);
369
370 if oSession is not None:
371 if oHd is not None:
372 oSession.detachHd(sController, iPort = 0, iDevice = 0);
373
374 oSession.saveSettings(fClose = True);
375 if oHd is not None:
376 self.oVBox.deleteHdByMedium(oHd);
377
378 self.deleteVM(oVM);
379 return fRc;
380
381 def test1(self):
382 """
383 Executes test #1 thru the various configurations.
384 """
385 if not self.importVBoxApi():
386 return False;
387
388 sVmName = 'testvm';
389 reporter.testStart(sVmName);
390
391 aoDskFmts = self.oVBoxMgr.getArray(self.oVBox.systemProperties, 'mediumFormats')
392 if aoDskFmts is None or len(aoDskFmts) < 1:
393 return False;
394
395 fRc = True;
396 for sStorageCtrl in self.asStorageCtrls:
397 reporter.testStart(sStorageCtrl);
398 if sStorageCtrl == 'AHCI':
399 eStorageCtrl = vboxcon.StorageControllerType_IntelAhci;
400 elif sStorageCtrl == 'IDE':
401 eStorageCtrl = vboxcon.StorageControllerType_PIIX4;
402 elif sStorageCtrl == 'LsiLogicSAS':
403 eStorageCtrl = vboxcon.StorageControllerType_LsiLogicSas;
404 elif sStorageCtrl == 'LsiLogic':
405 eStorageCtrl = vboxcon.StorageControllerType_LsiLogic;
406 elif sStorageCtrl == 'BusLogic':
407 eStorageCtrl = vboxcon.StorageControllerType_BusLogic;
408 else:
409 eStorageCtrl = None;
410
411 for oDskFmt in aoDskFmts:
412 if oDskFmt.id in self.asDiskFormats:
413 reporter.testStart('%s' % (oDskFmt.id));
414 fRc = self.test1OneCfg(eStorageCtrl, oDskFmt);
415 reporter.testDone();
416 if not fRc:
417 break;
418
419 reporter.testDone();
420 if not fRc:
421 break;
422
423 reporter.testDone();
424 return fRc;
425
426if __name__ == '__main__':
427 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