VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/tests/api/tdSnapshots1.py@ 107044

Last change on this file since 107044 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 11.6 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdSnapshots1.py 106061 2024-09-16 14:03:52Z vboxsync $
4
5"""
6VirtualBox Validation Kit - Nested Snapshot Restoration Test #1
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2023-2024 Oracle and/or its affiliates.
12
13This file is part of VirtualBox base platform packages, as
14available from https://www.virtualbox.org.
15
16This program is free software; you can redistribute it and/or
17modify it under the terms of the GNU General Public License
18as published by the Free Software Foundation, in version 3 of the
19License.
20
21This program is distributed in the hope that it will be useful, but
22WITHOUT ANY WARRANTY; without even the implied warranty of
23MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24General Public License for more details.
25
26You should have received a copy of the GNU General Public License
27along with this program; if not, see <https://www.gnu.org/licenses>.
28
29The contents of this file may alternatively be used under the terms
30of the Common Development and Distribution License Version 1.0
31(CDDL), a copy of it is provided in the "COPYING.CDDL" file included
32in the VirtualBox distribution, in which case the provisions of the
33CDDL are applicable instead of those of the GPL.
34
35You may elect to license modified versions of this file under the
36terms and conditions of either the GPL or the CDDL or both.
37
38SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
39"""
40__version__ = "$Revision: 106061 $"
41
42
43# Standard Python imports.
44import os
45import sys
46
47# Only the main script needs to modify the path.
48try: __file__ # pylint: disable=used-before-assignment
49except: __file__ = sys.argv[0]
50g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
51sys.path.append(g_ksValidationKitDir)
52
53# Validation Kit imports.
54from testdriver import base
55from testdriver import reporter
56from testdriver import vboxcon
57
58
59class SubTstDrvNestedSnapshots1(base.SubTestDriverBase):
60 """
61 Sub-test driver for nested snapshot testing.
62 """
63 def __init__(self, oTstDrv):
64 base.SubTestDriverBase.__init__(self, oTstDrv, 'nested-snapshots', 'Nested Snapshot Testing');
65 self.sVmName = 'tst-nested-snapshots';
66 # Note that any VM can be used here as these tests simply involve taking
67 # online snapshots and restoring them. This OL6 image was chosen based purely
68 # on its location being in the 7.1 directory.
69 self.asRsrcs = ['7.1/ol-6u10-x86.vdi'];
70
71 #
72 # Overridden methods specified in the TestDriverBase class (testdriver/base.py).
73 #
74
75 # Handle the action to execute the test itself.
76 def testIt(self):
77 """
78 Execute the sub-testcases.
79 """
80 return self.testRestoreNestedSnapshot() \
81 and self.testDeleteSnapshots();
82
83 #
84 # Test execution helpers.
85 #
86 def testRestoreNestedSnapshot(self):
87 """
88 The scenario being exercised here is referenced in xTracker 10252 Comment #9
89 where the sequence of restoring a nested snapshot and then booting that restored
90 VM would accidentally delete that snapshot's saved state file during boot. So
91 here we perform the following steps to exercise this functionality:
92 + Take two online snapshots of the VM: 'alpha', and 'beta' (IMachine::takeSnapshot())
93 + Restore snapshot 'beta' (IMachine::restoreSnapshot())
94 + Boot and then poweroff the VM
95 + Verify snapshot 'beta' still exists (IMachine::findSnapshot())
96 """
97 reporter.testStart('testRestoreNestedSnapshot');
98 reporter.log('Verify saved state file exists after nested snapshot restore');
99
100 # Restoring an online snapshot requires an updated TXS (r157880 or later) for the
101 # TCP keep alive support added in r157875 thus it is essential that the
102 # ValidationKit ISO be mounted in the VM so that TXS can auto-update if needed.
103 reporter.log('Creating test VM: \'%s\'' % self.sVmName);
104 oVM = self.oTstDrv.createTestVM(self.sVmName, 1, sHd = '7.1/ol-6u10-x86.vdi',
105 sKind = 'Oracle', fIoApic = True,
106 sDvdImage = self.oTstDrv.sVBoxValidationKitIso);
107 if oVM is None:
108 reporter.error('Error creating test VM: \'%s\'' % self.sVmName);
109
110 reporter.log('Starting test VM \'%s\' for the first time' % self.sVmName);
111 oSession, oTxsSession = self.oTstDrv.startVmAndConnectToTxsViaTcp(self.sVmName, fCdWait=True,
112 fNatForwardingForTxs = False);
113 if oSession is None or oTxsSession is None:
114 return reporter.error('Failed to start test VM: \'%s\'' % self.sVmName);
115
116 reporter.log('Guest VM \'%s\' successfully started. Connection to TXS service established.' % self.sVmName);
117 self.oTstDrv.addTask(oTxsSession);
118
119 # Take two online snapshots.
120 reporter.log('Taking two online snapshots of test VM: \'%s\'' % self.sVmName);
121 fRc = oSession.takeSnapshot('alpha');
122 fRc = fRc and oSession.takeSnapshot('beta');
123
124 # Shutdown the VM and cleanup.
125 self.oTstDrv.txsDisconnect(oSession, oTxsSession)
126 reporter.log('Shutting down test VM: \'%s\'' % self.sVmName);
127 self.oTstDrv.removeTask(oTxsSession);
128 self.oTstDrv.terminateVmBySession(oSession);
129 fRc = oSession.close() and fRc and True; # pychecker hack.
130 oSession = None;
131 oTxsSession = None;
132 if not fRc:
133 return reporter.error('Failed to take snapshot of test VM: \'%s\'' % self.sVmName);
134
135 oVM = self.oTstDrv.getVmByName(self.sVmName);
136 oSession = self.oTstDrv.openSession(oVM);
137 if oSession is None:
138 return reporter.error('Failed to create session for test VM: \'%s\'' % self.sVmName);
139
140 oSnapshot = oSession.findSnapshot('beta');
141 if oSnapshot is None:
142 return reporter.testFailure('Failed to find snapshot \'beta\' of test VM: \'%s\'' % self.sVmName);
143
144 reporter.log('Restoring nested snapshot \'%s\' ({%s}) of test VM: \'%s\'' %
145 (oSnapshot.name, oSnapshot.id, self.sVmName));
146 fRc = oSession.restoreSnapshot(oSnapshot);
147 if not fRc:
148 return reporter.error('Failed to restore snapshot \'%s\' of test VM: \'%s\'' % (oSnapshot.name, self.sVmName));
149
150 fRc = oSession.close() and fRc and True; # pychecker hack.
151 oSession = None;
152 if not fRc:
153 return reporter.error('Failed to close session of test VM: \'%s\'' % self.sVmName);
154
155 reporter.log('Starting test VM after snapshot restore: \'%s\'' % self.sVmName);
156
157 oSession, oTxsSession = self.oTstDrv.startVmAndConnectToTxsViaTcp(self.sVmName, fCdWait=True,
158 fNatForwardingForTxs = False);
159 if oSession is None or oTxsSession is None:
160 return reporter.error('Failed to start test VM: \'%s\'' % self.sVmName);
161
162 # Display the version of TXS running in the guest VM to confirm that it is r157880 or later.
163 sTxsVer = self.oTstDrv.txsVer(oSession, oTxsSession, cMsTimeout=1000*30*60, fIgnoreErrors = True);
164 if sTxsVer is not False:
165 reporter.log('startVmAndConnectToTxsViaTcp: TestExecService version %s' % (sTxsVer));
166 else:
167 reporter.log('startVmAndConnectToTxsViaTcp: Unable to retrieve TestExecService version');
168
169 reporter.log('Guest VM \'%s\' successfully started after restoring nested snapshot.' % self.sVmName);
170 self.oTstDrv.addTask(oTxsSession);
171
172 # Shutdown the VM and cleanup.
173 reporter.log('Shutting down test VM: \'%s\'' % self.sVmName);
174 self.oTstDrv.removeTask(oTxsSession);
175 self.oTstDrv.terminateVmBySession(oSession);
176 fRc = oSession.close() and fRc and True; # pychecker hack.
177 oSession = None;
178 oTxsSession = None;
179 if not fRc:
180 return reporter.testFailure('Failed to close session of test VM: \'%s\'' % self.sVmName);
181
182 reporter.log('Verifying nested snapshot \'beta\' still exists.');
183 oVM = self.oTstDrv.getVmByName(self.sVmName);
184 oSession = self.oTstDrv.openSession(oVM);
185 if oSession is None:
186 return reporter.error('Failed to create session for test VM: \'%s\'' % self.sVmName);
187
188 oSnapshot = oSession.findSnapshot('beta');
189 if oSnapshot is None:
190 return reporter.testFailure('Failed to find snapshot \'beta\' of test VM: \'%s\'' % self.sVmName);
191
192 return reporter.testDone()[1] == 0;
193
194
195 def testDeleteSnapshots(self):
196 """
197 The scenario being exercised here is also referenced in xTracker 10252 Comment #9
198 where unregistering and deleting a VM which contained one or more snapshots would
199 neglect to delete the snapshot(s). So here we perform the following steps to
200 exercise this functionality which conveniently also tidies up our test setup:
201 + Unregister our test VM (IMachine::unregister())
202 + Delete the VM and the attached media including snapshots (IMachine::deleteConfig())
203 + Check that the snapshots are truly gone.
204 """
205
206 reporter.testStart('testDeleteSnapshots');
207 reporter.log('Verify IMachine::unregister()+IMachine::deleteConfig() deletes snapshots');
208 oVM = self.oTstDrv.getVmByName(self.sVmName);
209 # IMachine::stateFilePath() isn't implemented in the testdriver so we manually
210 # retrieve the paths to the snapshots.
211 asStateFilesList = [];
212 sSnapshotFolder = oVM.snapshotFolder;
213 for sFile in os.listdir(sSnapshotFolder):
214 if sFile.endswith(".sav"):
215 sSnapshotFullPath = os.path.normcase(os.path.join(sSnapshotFolder, sFile));
216 asStateFilesList.append(sSnapshotFullPath)
217 reporter.log("Snapshot path = %s" % (sSnapshotFullPath))
218
219 reporter.log('Calling IMachine::unregister() and IMachine::deleteConfig()');
220 # Call IMachine::unregister() and IMachine::deleteConfig() (or their historic
221 # equivalents) to remove all vestiges of the VM from the system.
222 if self.oTstDrv.fpApiVer >= 4.0:
223 try:
224 oVM.unregister(vboxcon.CleanupMode_Full);
225 except:
226 return reporter.error('Failed to unregister VM \'%s\'' % self.sVmName);
227 try:
228 if self.oTstDrv.fpApiVer >= 4.3:
229 oProgress = oVM.deleteConfig([]);
230 else:
231 oProgress = oVM.delete([]);
232 except:
233 return reporter.error('Failed to delete configuration of VM \'%s\'' % self.sVmName);
234 self.oTstDrv.waitOnProgress(oProgress);
235 else:
236 try:
237 self.oTstDrv.oVBox.unregisterMachine(oVM.id);
238 except:
239 return reporter.error('Failed to unregister VM \'%s\'' % self.sVmName);
240 try:
241 oVM.deleteSettings();
242 except:
243 return reporter.error('Failed to delete configuration of VM \'%s\'' % self.sVmName);
244
245 # Verify that all of the snapshots were removed as part of the
246 # IMachine::deleteConfig() call.
247 reporter.log('Verifying no snapshots remain after IMachine::deleteConfig()');
248 for sFile in os.listdir(sSnapshotFolder):
249 if os.path.exists(sFile):
250 return reporter.error('Snapshot \'%s\' was not deleted' % sFile);
251
252 return reporter.testDone()[1] == 0;
253
254if __name__ == '__main__':
255 sys.path.append(os.path.dirname(os.path.abspath(__file__)));
256 from tdApi1 import tdApi1; # pylint: disable=relative-import
257 sys.exit(tdApi1([SubTstDrvNestedSnapshots1]).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