VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/tests/additions/tdAddBasic1.py@ 77643

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

Validation Kit/tdAddBasic1.py: Added initial Linux Additions installation testing support.

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 16.0 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdAddBasic1.py 77469 2019-02-26 12:25:43Z vboxsync $
4
5"""
6VirtualBox Validation Kit - Additions Basics #1.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2010-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: 77469 $"
31
32# pylint: disable=unnecessary-semicolon
33
34# Standard Python imports.
35import os;
36import sys;
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;
49
50# Sub test driver imports.
51sys.path.append(os.path.dirname(os.path.abspath(__file__))); # For sub-test drivers.
52from tdAddGuestCtrl import SubTstDrvAddGuestCtrl;
53
54
55class tdAddBasic1(vbox.TestDriver): # pylint: disable=R0902
56 """
57 Additions Basics #1.
58 """
59 ## @todo
60 # - More of the settings stuff can be and need to be generalized!
61 #
62
63 def __init__(self):
64 vbox.TestDriver.__init__(self);
65 self.oTestVmSet = self.oTestVmManager.getSmokeVmSet('nat');
66 self.asTestsDef = ['install', 'guestprops', 'stdguestprops', 'guestcontrol'];
67 self.asTests = self.asTestsDef;
68 self.asRsrcs = None
69
70 self.addSubTestDriver(SubTstDrvAddGuestCtrl(self));
71
72 #
73 # Overridden methods.
74 #
75 def showUsage(self):
76 rc = vbox.TestDriver.showUsage(self);
77 reporter.log('');
78 reporter.log('tdAddBasic1 Options:');
79 reporter.log(' --tests <s1[:s2[:]]>');
80 reporter.log(' Default: %s (all)' % (':'.join(self.asTestsDef)));
81 reporter.log(' --quick');
82 reporter.log(' Same as --virt-modes hwvirt --cpu-counts 1.');
83 return rc;
84
85 def parseOption(self, asArgs, iArg): # pylint: disable=R0912,R0915
86 if asArgs[iArg] == '--tests':
87 iArg += 1;
88 if iArg >= len(asArgs): raise base.InvalidOption('The "--tests" takes a colon separated list of tests');
89 self.asTests = asArgs[iArg].split(':');
90 for s in self.asTests:
91 if s not in self.asTestsDef:
92 raise base.InvalidOption('The "--tests" value "%s" is not valid; valid values are: %s' \
93 % (s, ' '.join(self.asTestsDef)));
94
95 elif asArgs[iArg] == '--quick':
96 self.parseOption(['--virt-modes', 'hwvirt'], 0);
97 self.parseOption(['--cpu-counts', '1'], 0);
98
99 else:
100 return vbox.TestDriver.parseOption(self, asArgs, iArg);
101 return iArg + 1;
102
103 def getResourceSet(self):
104 if self.asRsrcs is None:
105 self.asRsrcs = []
106 for oSubTstDrv in self.aoSubTstDrvs:
107 self.asRsrcs.extend(oSubTstDrv.asRsrcs)
108 self.asRsrcs.extend(self.oTestVmSet.getResourceSet())
109 return self.asRsrcs
110
111 def actionConfig(self):
112 if not self.importVBoxApi(): # So we can use the constant below.
113 return False;
114
115 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
116 sGaIso = self.getGuestAdditionsIso();
117 return self.oTestVmSet.actionConfig(self, eNic0AttachType = eNic0AttachType, sDvdImage = sGaIso);
118
119 def actionExecute(self):
120 return self.oTestVmSet.actionExecute(self, self.testOneCfg);
121
122
123 #
124 # Test execution helpers.
125 #
126
127 def testOneCfg(self, oVM, oTestVm):
128 """
129 Runs the specified VM thru the tests.
130
131 Returns a success indicator on the general test execution. This is not
132 the actual test result.
133 """
134 fRc = False;
135
136 if oTestVm.isWindows():
137 sFileCdWait = 'VBoxWindowsAdditions.exe';
138 elif oTestVm.isLinux():
139 sFileCdWait = 'VBoxLinuxAdditions.run';
140
141 self.logVmInfo(oVM);
142 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = True, sFileCdWait = sFileCdWait);
143 if oSession is not None:
144 self.addTask(oTxsSession);
145 # Do the testing.
146 fSkip = 'install' not in self.asTests;
147 reporter.testStart('Install');
148 if not fSkip:
149 fRc, oTxsSession = self.testInstallAdditions(oSession, oTxsSession, oTestVm);
150 reporter.testDone(fSkip);
151
152 fSkip = 'guestprops' not in self.asTests;
153 reporter.testStart('Guest Properties');
154 if not fSkip:
155 fRc = self.testGuestProperties(oSession, oTxsSession, oTestVm) and fRc;
156 reporter.testDone(fSkip);
157
158 fSkip = 'guestcontrol' not in self.asTests;
159 reporter.testStart('Guest Control');
160 if not fSkip:
161 fRc, oTxsSession = self.aoSubTstDrvs[0].testIt(oTestVm, oSession, oTxsSession);
162 reporter.testDone(fSkip);
163
164 ## @todo Save and restore test.
165
166 ## @todo Reset tests.
167
168 ## @todo Final test: Uninstallation.
169
170 # Cleanup.
171 self.removeTask(oTxsSession);
172 self.terminateVmBySession(oSession)
173 return fRc;
174
175 def testInstallAdditions(self, oSession, oTxsSession, oTestVm):
176 """
177 Tests installing the guest additions
178 """
179 if oTestVm.isWindows():
180 (fRc, oTxsSession) = self.testWindowsInstallAdditions(oSession, oTxsSession, oTestVm);
181 elif oTestVm.isLinux():
182 (fRc, oTxsSession) = self.testLinuxInstallAdditions(oSession, oTxsSession, oTestVm);
183 else:
184 reporter.error('Guest Additions installation not implemented for %s yet! (%s)' % \
185 (oTestVm.sKind, oTestVm.sVmName));
186 fRc = False;
187
188 #
189 # Verify installation of Guest Additions using commmon bits.
190 #
191 if fRc is True:
192 #
193 # Wait for the GAs to come up.
194 #
195
196 ## @todo need to signed up for a OnAdditionsStateChanged and wait runlevel to
197 # at least reach Userland.
198
199 #
200 # Check if the additions are operational.
201 #
202 try: oGuest = oSession.o.console.guest;
203 except:
204 reporter.errorXcpt('Getting IGuest failed.');
205 return (False, oTxsSession);
206
207 # Check the additionsVersion attribute. It must not be empty.
208 reporter.testStart('IGuest::additionsVersion');
209 fRc = self.testIGuest_additionsVersion(oGuest);
210 reporter.testDone();
211
212 reporter.testStart('IGuest::additionsRunLevel');
213 self.testIGuest_additionsRunLevel(oGuest, oTestVm);
214 reporter.testDone();
215
216 ## @todo test IAdditionsFacilities.
217
218 return (fRc, oTxsSession);
219
220 def testWindowsInstallAdditions(self, oSession, oTxsSession, oTestVm):
221 """
222 Installs the Windows guest additions using the test execution service.
223 Since this involves rebooting the guest, we will have to create a new TXS session.
224 """
225 asLogFile = [];
226
227 fHaveSetupApiDevLog = False;
228
229 # Delete relevant log files.
230 if oTestVm.sKind in ('WindowsNT4',):
231 sWinDir = 'C:/WinNT/';
232 else:
233 sWinDir = 'C:/Windows/';
234 asLogFile = [sWinDir+'setupapi.log', sWinDir+'setupact.log', sWinDir+'setuperr.log'];
235
236 # Apply The SetupAPI logging level so that we also get the (most verbose) setupapi.dev.log file.
237 ## @todo !!! HACK ALERT !!! Add the value directly into the testing source image. Later.
238 fHaveSetupApiDevLog = self.txsRunTest(oTxsSession, 'Enabling setupapi.dev.log', 30 * 1000, \
239 'c:\\Windows\\System32\\reg.exe', ('c:\\Windows\\System32\\reg.exe', \
240 'add', '"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Setup"', '/v', 'LogLevel', '/t', 'REG_DWORD', \
241 '/d', '0xFF'));
242
243 # On some guests the files in question still can be locked by the OS, so ignore deletion
244 # errors from the guest side (e.g. sharing violations) and just continue.
245 for sFile in asLogFile:
246 self.txsRmFile(oSession, oTxsSession, sFile, 10 * 1000, fIgnoreErrors = True);
247
248 # Install the public signing key.
249 if oTestVm.sKind not in ('WindowsNT4', 'Windows2000', 'WindowsXP', 'Windows2003'):
250 ## TODO
251 pass;
252
253 #
254 # The actual install.
255 # Enable installing the optional auto-logon modules (VBoxGINA/VBoxCredProv) + (Direct)3D support.
256 # Also tell the installer to produce the appropriate log files.
257 #
258 fRc = self.txsRunTest(oTxsSession, 'VBoxWindowsAdditions.exe', 5 * 60 * 1000, \
259 '${CDROM}/VBoxWindowsAdditions.exe', ('${CDROM}/VBoxWindowsAdditions.exe', '/S', '/l', '/with_autologon'));
260 ## @todo For testing the installation (D)3D stuff ('/with_d3d') we need to boot up in safe mode.
261
262 #
263 # Reboot the VM and reconnect the TXS session.
264 #
265 if fRc is True:
266 (fRc, oTxsSession) = self.txsRebootAndReconnectViaTcp(oSession, oTxsSession, cMsTimeout = 3 * 60000);
267
268 if fRc is True:
269 # Add the Windows Guest Additions installer files to the files we want to download
270 # from the guest.
271 sGuestAddsDir = 'C:/Program Files/Oracle/VirtualBox Guest Additions/';
272 asLogFile.append(sGuestAddsDir + 'install.log');
273 # Note: There won't be a install_ui.log because of the silent installation.
274 asLogFile.append(sGuestAddsDir + 'install_drivers.log');
275 asLogFile.append('C:/Windows/setupapi.log');
276
277 # Note: setupapi.dev.log only is available since Windows 2000.
278 if fHaveSetupApiDevLog:
279 asLogFile.append('C:/Windows/setupapi.dev.log');
280
281 #
282 # Download log files.
283 # Ignore errors as all files above might not be present (or in different locations)
284 # on different Windows guests.
285 #
286 self.txsDownloadFiles(oSession, oTxsSession, asLogFile, fIgnoreErrors = True);
287
288 return (fRc, oTxsSession);
289
290 def testLinuxInstallAdditions(self, oSession, oTxsSession, oTestVm):
291 oSession = oSession;
292 oTestVm = oTestVm;
293
294 fRc = False;
295
296 # Install Kernel headers, which are required for actually installing the Linux Additions.
297 if oTestVm.sKind.startswith('Debian') \
298 or oTestVm.sKind.startswith('Ubuntu'):
299 fRc = self.txsRunTest(oTxsSession, 'Installing Kernel headers', 5 * 60 *1000,
300 '/usr/bin/apt-get', ('/usr/bin/apt-get', 'install', '-y', 'linux-headers-generic'));
301 if not fRc:
302 reporter.error('Error installing Kernel headers');
303 fRc = self.txsRunTest(oTxsSession, 'Installing Guest Additions depdendencies', 5 * 60 *1000, \
304 '/usr/bin/apt-get', ('/usr/bin/apt-get', 'install', '-y', 'build-essential', 'perl'));
305 if not fRc:
306 reporter.error('Error installing additional installer dependencies');
307 elif oTestVm.sKind.startswith('OL') \
308 or oTestVm.sKind.startswith('Oracle') \
309 or oTestVm.sKind.startswith('RHEL') \
310 or oTestVm.sKind.startswith('Redhat') \
311 or oTestVm.sKind.startswith('Cent'):
312 fRc = self.txsRunTest(oTxsSession, 'Installing Kernel headers', 5 * 60 *1000,
313 '/usr/bin/yum', ('/usr/bin/yum', '-y', 'install', 'kernel-headers'));
314 if not fRc:
315 reporter.error('Error installing Kernel headers');
316 fRc = self.txsRunTest(oTxsSession, 'Installing Guest Additions depdendencies', 5 * 60 *1000, \
317 '/usr/bin/yum', ('/usr/bin/yum', '-y', 'install', \
318 'make', 'automake', 'gcc', 'kernel-devel', 'dkms', 'bzip2', 'perl'));
319 if not fRc:
320 reporter.error('Error installing additional installer dependencies');
321 else:
322 reporter.error('Installing Linux Additions for kind "%s" is not supported yet' % oTestVm.sKind);
323 return (False, oTxsSession);
324
325 if fRc:
326 #
327 # The actual install.
328 # Also tell the installer to produce the appropriate log files.
329 #
330 fRc = self.txsRunTest(oTxsSession, 'VBoxLinuxAdditions.run', 5 * 60 * 1000,
331 '/bin/sh', ('/bin/sh', '${CDROM}/VBoxLinuxAdditions.run'));
332 if not fRc:
333 reporter.error('Installing Linux Additions failed (see log file for details)');
334
335 #
336 # Download log files.
337 # Ignore errors as all files above might not be present for whatever reason.
338 #
339 asLogFile = [];
340 asLogFile.append('/var/log/vboxadd-install.log');
341 self.txsDownloadFiles(oSession, oTxsSession, asLogFile, fIgnoreErrors = True);
342
343 if fRc:
344 (fRc, oTxsSession) = self.txsRebootAndReconnectViaTcp(oSession, oTxsSession, cMsTimeout = 3 * 60000);
345
346 return (fRc, oTxsSession);
347
348 def testIGuest_additionsVersion(self, oGuest):
349 """
350 Returns False if no version string could be obtained, otherwise True
351 even though errors are logged.
352 """
353 try:
354 sVer = oGuest.additionsVersion;
355 except:
356 reporter.errorXcpt('Getting the additions version failed.');
357 return False;
358 reporter.log('IGuest::additionsVersion="%s"' % (sVer,));
359
360 if sVer.strip() == '':
361 reporter.error('IGuest::additionsVersion is empty.');
362 return False;
363
364 if sVer != sVer.strip():
365 reporter.error('IGuest::additionsVersion is contains spaces: "%s".' % (sVer,));
366
367 asBits = sVer.split('.');
368 if len(asBits) < 3:
369 reporter.error('IGuest::additionsVersion does not contain at least tree dot separated fields: "%s" (%d).'
370 % (sVer, len(asBits)));
371
372 ## @todo verify the format.
373 return True;
374
375 def testIGuest_additionsRunLevel(self, oGuest, oTestVm):
376 """
377 Do run level tests.
378 """
379 if oTestVm.isLoggedOntoDesktop():
380 eExpectedRunLevel = vboxcon.AdditionsRunLevelType_Desktop;
381 else:
382 eExpectedRunLevel = vboxcon.AdditionsRunLevelType_Userland;
383
384 ## @todo Insert wait for the desired run level.
385 try:
386 iLevel = oGuest.additionsRunLevel;
387 except:
388 reporter.errorXcpt('Getting the additions run level failed.');
389 return False;
390 reporter.log('IGuest::additionsRunLevel=%s' % (iLevel,));
391
392 if iLevel != eExpectedRunLevel:
393 pass; ## @todo We really need that wait!!
394 #reporter.error('Expected runlevel %d, found %d instead' % (eExpectedRunLevel, iLevel));
395 return True;
396
397
398 def testGuestProperties(self, oSession, oTxsSession, oTestVm):
399 """
400 Test guest properties.
401 """
402 _ = oSession; _ = oTxsSession; _ = oTestVm;
403 return True;
404
405if __name__ == '__main__':
406 sys.exit(tdAddBasic1().main(sys.argv));
Note: See TracBrowser for help on using the repository browser.

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