1 | #!/usr/bin/env python
|
---|
2 | # -*- coding: utf-8 -*-
|
---|
3 | # $Id: tdStorageSnapshotMerging1.py 69111 2017-10-17 14:26:02Z vboxsync $
|
---|
4 |
|
---|
5 | """
|
---|
6 | VirtualBox Validation Kit - Storage snapshotting and merging testcase.
|
---|
7 | """
|
---|
8 |
|
---|
9 | __copyright__ = \
|
---|
10 | """
|
---|
11 | Copyright (C) 2013-2017 Oracle Corporation
|
---|
12 |
|
---|
13 | This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
14 | available from http://www.virtualbox.org. This file is free software;
|
---|
15 | you can redistribute it and/or modify it under the terms of the GNU
|
---|
16 | General Public License (GPL) as published by the Free Software
|
---|
17 | Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
18 | VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
19 | hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
20 |
|
---|
21 | The contents of this file may alternatively be used under the terms
|
---|
22 | of the Common Development and Distribution License Version 1.0
|
---|
23 | (CDDL) only, as it comes in the "COPYING.CDDL" file of the
|
---|
24 | VirtualBox OSE distribution, in which case the provisions of the
|
---|
25 | CDDL are applicable instead of those of the GPL.
|
---|
26 |
|
---|
27 | You may elect to license modified versions of this file under the
|
---|
28 | terms and conditions of either the GPL or the CDDL or both.
|
---|
29 | """
|
---|
30 | __version__ = "$Id: tdStorageSnapshotMerging1.py 69111 2017-10-17 14:26:02Z vboxsync $"
|
---|
31 |
|
---|
32 |
|
---|
33 | # Standard Python imports.
|
---|
34 | import os;
|
---|
35 | import sys;
|
---|
36 | import uuid;
|
---|
37 |
|
---|
38 | # Only the main script needs to modify the path.
|
---|
39 | try: __file__
|
---|
40 | except: __file__ = sys.argv[0];
|
---|
41 | g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))));
|
---|
42 | sys.path.append(g_ksValidationKitDir);
|
---|
43 |
|
---|
44 | # Validation Kit imports.
|
---|
45 | from testdriver import reporter;
|
---|
46 | from testdriver import base;
|
---|
47 | from testdriver import vbox;
|
---|
48 | from testdriver import vboxcon;
|
---|
49 |
|
---|
50 | def _ControllerTypeToName(eControllerType):
|
---|
51 | """ Translate a controller type to a name. """
|
---|
52 | if eControllerType == vboxcon.StorageControllerType_PIIX3 or eControllerType == vboxcon.StorageControllerType_PIIX4:
|
---|
53 | sType = "IDE Controller";
|
---|
54 | elif eControllerType == vboxcon.StorageControllerType_IntelAhci:
|
---|
55 | sType = "SATA Controller";
|
---|
56 | elif eControllerType == vboxcon.StorageControllerType_LsiLogicSas:
|
---|
57 | sType = "SAS Controller";
|
---|
58 | elif eControllerType == vboxcon.StorageControllerType_LsiLogic or eControllerType == vboxcon.StorageControllerType_BusLogic:
|
---|
59 | sType = "SCSI Controller";
|
---|
60 | else:
|
---|
61 | sType = "Storage Controller";
|
---|
62 | return sType;
|
---|
63 |
|
---|
64 | class tdStorageSnapshot(vbox.TestDriver): # pylint: disable=R0902
|
---|
65 | """
|
---|
66 | Storage benchmark.
|
---|
67 | """
|
---|
68 |
|
---|
69 | def __init__(self):
|
---|
70 | vbox.TestDriver.__init__(self);
|
---|
71 | self.asRsrcs = None;
|
---|
72 | self.oGuestToGuestVM = None;
|
---|
73 | self.oGuestToGuestSess = None;
|
---|
74 | self.oGuestToGuestTxs = None;
|
---|
75 | self.asTestVMsDef = ['tst-win7-vhd', 'tst-debian-vhd', 'tst-debian-vdi'];
|
---|
76 | self.asTestVMs = self.asTestVMsDef;
|
---|
77 | self.asSkipVMs = [];
|
---|
78 | self.asStorageCtrlsDef = ['AHCI', 'IDE', 'LsiLogicSAS', 'LsiLogic', 'BusLogic'];
|
---|
79 | self.asStorageCtrls = self.asStorageCtrlsDef;
|
---|
80 | self.asDiskFormatsDef = ['VDI', 'VMDK', 'VHD', 'QED', 'Parallels', 'QCOW', 'iSCSI'];
|
---|
81 | self.asDiskFormats = self.asDiskFormatsDef;
|
---|
82 | self.sRndData = os.urandom(100*1024*1024);
|
---|
83 |
|
---|
84 | #
|
---|
85 | # Overridden methods.
|
---|
86 | #
|
---|
87 | def showUsage(self):
|
---|
88 | rc = vbox.TestDriver.showUsage(self);
|
---|
89 | reporter.log('');
|
---|
90 | reporter.log('tdStorageSnapshot1 Options:');
|
---|
91 | reporter.log(' --storage-ctrls <type1[:type2[:...]]>');
|
---|
92 | reporter.log(' Default: %s' % (':'.join(self.asStorageCtrls)));
|
---|
93 | reporter.log(' --disk-formats <type1[:type2[:...]]>');
|
---|
94 | 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 | return rc;
|
---|
102 |
|
---|
103 | def parseOption(self, asArgs, iArg): # pylint: disable=R0912,R0915
|
---|
104 | if asArgs[iArg] == '--storage-ctrls':
|
---|
105 | iArg += 1;
|
---|
106 | if iArg >= len(asArgs):
|
---|
107 | raise base.InvalidOption('The "--storage-ctrls" takes a colon separated list of Storage controller types');
|
---|
108 | self.asStorageCtrls = asArgs[iArg].split(':');
|
---|
109 | elif asArgs[iArg] == '--disk-formats':
|
---|
110 | iArg += 1;
|
---|
111 | if iArg >= len(asArgs): raise base.InvalidOption('The "--disk-formats" takes a colon separated list of disk formats');
|
---|
112 | 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 | else:
|
---|
129 | return vbox.TestDriver.parseOption(self, asArgs, iArg);
|
---|
130 | return iArg + 1;
|
---|
131 |
|
---|
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 | def getResourceSet(self):
|
---|
141 | # Construct the resource list the first time it's queried.
|
---|
142 | 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 |
|
---|
153 | 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 VMs
|
---|
166 | 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 VMs
|
---|
174 | 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 |
|
---|
190 | def actionExecute(self):
|
---|
191 | """
|
---|
192 | Execute the testcase.
|
---|
193 | """
|
---|
194 | fRc = self.test1();
|
---|
195 | return fRc;
|
---|
196 |
|
---|
197 |
|
---|
198 | #
|
---|
199 | # Test execution helpers.
|
---|
200 | #
|
---|
201 |
|
---|
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):
|
---|
215 | """
|
---|
216 | Runs the specified VM thru test #1.
|
---|
217 |
|
---|
218 | Returns a success indicator on the general test execution. This is not
|
---|
219 | the actual test result.
|
---|
220 | """
|
---|
221 | oVM = self.getVmByName(sVmName);
|
---|
222 |
|
---|
223 | # @ŧodo: Implement support for different formats.
|
---|
224 | _ = sDiskFormat;
|
---|
225 |
|
---|
226 | # Reconfigure the VM
|
---|
227 | fRc = True;
|
---|
228 | oSession = self.openSession(oVM);
|
---|
229 | 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;
|
---|
266 | return fRc;
|
---|
267 |
|
---|
268 | def test1OneVM(self, sVmName):
|
---|
269 | """
|
---|
270 | Runs one VM thru the various configurations.
|
---|
271 | """
|
---|
272 | reporter.testStart(sVmName);
|
---|
273 | fRc = True;
|
---|
274 | for sStorageCtrl in self.asStorageCtrls:
|
---|
275 | reporter.testStart(sStorageCtrl);
|
---|
276 |
|
---|
277 | if sStorageCtrl == 'AHCI':
|
---|
278 | eStorageCtrl = vboxcon.StorageControllerType_IntelAhci;
|
---|
279 | elif sStorageCtrl == 'IDE':
|
---|
280 | eStorageCtrl = vboxcon.StorageControllerType_PIIX4;
|
---|
281 | elif sStorageCtrl == 'LsiLogicSAS':
|
---|
282 | eStorageCtrl = vboxcon.StorageControllerType_LsiLogicSas;
|
---|
283 | elif sStorageCtrl == 'LsiLogic':
|
---|
284 | eStorageCtrl = vboxcon.StorageControllerType_LsiLogic;
|
---|
285 | elif sStorageCtrl == 'BusLogic':
|
---|
286 | eStorageCtrl = vboxcon.StorageControllerType_BusLogic;
|
---|
287 | else:
|
---|
288 | eStorageCtrl = None;
|
---|
289 |
|
---|
290 | for sDiskFormat in self.asDiskFormats:
|
---|
291 | reporter.testStart('%s' % (sDiskFormat));
|
---|
292 | self.test1OneCfg(sVmName, eStorageCtrl, sDiskFormat);
|
---|
293 | reporter.testDone();
|
---|
294 | reporter.testDone();
|
---|
295 | reporter.testDone();
|
---|
296 | return fRc;
|
---|
297 |
|
---|
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 | if __name__ == '__main__':
|
---|
316 | sys.exit(tdStorageSnapshot().main(sys.argv));
|
---|
317 |
|
---|