VirtualBox

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

Last change on this file since 84180 was 84180, checked in by vboxsync, 5 years ago

Validation Kit/tdAddBasic1.py: More code for GA runlevel testing.

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 21.3 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdAddBasic1.py 84180 2020-05-07 06:59:00Z vboxsync $
4
5"""
6VirtualBox Validation Kit - Additions Basics #1.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2010-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: 84180 $"
31
32# Standard Python imports.
33import os;
34import sys;
35import uuid;
36
37# Only the main script needs to modify the path.
38try: __file__
39except: __file__ = sys.argv[0];
40g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))));
41sys.path.append(g_ksValidationKitDir);
42
43# Validation Kit imports.
44from testdriver import reporter;
45from testdriver import base;
46from testdriver import vbox;
47from testdriver import vboxcon;
48
49# Sub-test driver imports.
50sys.path.append(os.path.dirname(os.path.abspath(__file__))); # For sub-test drivers.
51from tdAddGuestCtrl import SubTstDrvAddGuestCtrl;
52from tdAddSharedFolders1 import SubTstDrvAddSharedFolders1;
53
54
55
56class tdAddBasicConsoleCallbacks(vbox.ConsoleEventHandlerBase):
57 """
58 For catching the Guest Additions change state events.
59 """
60 def __init__(self, dArgs):
61 oTstDrv = dArgs['oTstDrv'];
62 oVBoxMgr = dArgs['oVBoxMgr']; _ = oVBoxMgr;
63 oGuest = dArgs['oGuest'];
64
65 vbox.ConsoleEventHandlerBase.__init__(self, dArgs, 'tdAddBasic1');
66 self.oTstDrv = oTstDrv;
67 self.oGuest = oGuest;
68
69 def handleEvent(self, oEvt):
70 try:
71 oEvtBase = self.oVBoxMgr.queryInterface(oEvt, 'IEvent');
72 eType = oEvtBase.type;
73 except:
74 reporter.logXcpt();
75 return None;
76 if eType == vboxcon.VBoxEventType_OnAdditionsStateChanged:
77 return self.onAdditionsStateChanged();
78 return None;
79
80 def onAdditionsStateChanged(self):
81 reporter.log('onAdditionsStateChange');
82 self.oTstDrv.fGAStatusCallbackFired = True;
83 self.oTstDrv.iGAStatusCallbackRunlevel = self.oGuest.additionsRunLevel;
84 self.oVBoxMgr.interruptWaitEvents();
85 return None;
86
87class tdAddBasic1(vbox.TestDriver): # pylint: disable=too-many-instance-attributes
88 """
89 Additions Basics #1.
90 """
91 ## @todo
92 # - More of the settings stuff can be and need to be generalized!
93 #
94
95 def __init__(self):
96 vbox.TestDriver.__init__(self);
97 self.oTestVmSet = self.oTestVmManager.getSmokeVmSet('nat');
98 self.asTestsDef = ['install', 'guestprops', 'stdguestprops', 'guestcontrol', 'sharedfolders'];
99 self.asTests = self.asTestsDef;
100 self.asRsrcs = None
101 # The file we're going to use as a beacon to wait if the Guest Additions CD-ROM is ready.
102 self.sFileCdWait = '';
103
104 self.addSubTestDriver(SubTstDrvAddGuestCtrl(self));
105 self.addSubTestDriver(SubTstDrvAddSharedFolders1(self));
106
107 self.fGAStatusCallbackFired = False;
108 self.iGAStatusCallbackRunlevel = 0;
109
110 #
111 # Overridden methods.
112 #
113 def showUsage(self):
114 rc = vbox.TestDriver.showUsage(self);
115 reporter.log('');
116 reporter.log('tdAddBasic1 Options:');
117 reporter.log(' --tests <s1[:s2[:]]>');
118 reporter.log(' Default: %s (all)' % (':'.join(self.asTestsDef)));
119 reporter.log(' --quick');
120 reporter.log(' Same as --virt-modes hwvirt --cpu-counts 1.');
121 return rc;
122
123 def parseOption(self, asArgs, iArg): # pylint: disable=too-many-branches,too-many-statements
124 if asArgs[iArg] == '--tests':
125 iArg += 1;
126 if iArg >= len(asArgs): raise base.InvalidOption('The "--tests" takes a colon separated list of tests');
127 self.asTests = asArgs[iArg].split(':');
128 for s in self.asTests:
129 if s not in self.asTestsDef:
130 raise base.InvalidOption('The "--tests" value "%s" is not valid; valid values are: %s'
131 % (s, ' '.join(self.asTestsDef),));
132
133 elif asArgs[iArg] == '--quick':
134 self.parseOption(['--virt-modes', 'hwvirt'], 0);
135 self.parseOption(['--cpu-counts', '1'], 0);
136
137 else:
138 return vbox.TestDriver.parseOption(self, asArgs, iArg);
139 return iArg + 1;
140
141 def getResourceSet(self):
142 if self.asRsrcs is None:
143 self.asRsrcs = []
144 for oSubTstDrv in self.aoSubTstDrvs:
145 self.asRsrcs.extend(oSubTstDrv.asRsrcs)
146 self.asRsrcs.extend(self.oTestVmSet.getResourceSet())
147 return self.asRsrcs
148
149 def actionConfig(self):
150 if not self.importVBoxApi(): # So we can use the constant below.
151 return False;
152
153 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
154 sGaIso = self.getGuestAdditionsIso();
155
156 # On 6.0 we merge the GAs with the ValidationKit so we can get at FsPerf.
157 # Note! Not possible to do a dboule import as both images an '/OS2' dir.
158 # So, using same dir as with unattended VISOs for the valkit.
159 if self.fpApiVer >= 6.0 and 'sharedfolders' in self.asTests:
160 sGaViso = os.path.join(self.sScratchPath, 'AdditionsAndValKit.viso');
161 ## @todo encode as bash cmd line:
162 sVisoContent = '--iprt-iso-maker-file-marker-bourne-sh %s ' \
163 '--import-iso \'%s\' ' \
164 '--push-iso \'%s\' ' \
165 '/vboxvalidationkit=/ ' \
166 '--pop ' \
167 % (uuid.uuid4(), sGaIso, self.sVBoxValidationKitIso);
168 reporter.log2('Using VISO combining GAs and ValKit "%s": %s' % (sGaViso, sVisoContent));
169 oGaViso = open(sGaViso, 'w');
170 oGaViso.write(sVisoContent);
171 oGaViso.close();
172 sGaIso = sGaViso;
173
174 return self.oTestVmSet.actionConfig(self, eNic0AttachType = eNic0AttachType, sDvdImage = sGaIso);
175
176 def actionExecute(self):
177 return self.oTestVmSet.actionExecute(self, self.testOneCfg);
178
179
180 #
181 # Test execution helpers.
182 #
183
184 def testOneCfg(self, oVM, oTestVm):
185 """
186 Runs the specified VM thru the tests.
187
188 Returns a success indicator on the general test execution. This is not
189 the actual test result.
190 """
191 fRc = False;
192
193 if oTestVm.isWindows():
194 self.sFileCdWait = 'VBoxWindowsAdditions.exe';
195 elif oTestVm.isLinux():
196 self.sFileCdWait = 'VBoxLinuxAdditions.run';
197
198 self.logVmInfo(oVM);
199 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = True,
200 cMsCdWait = 5 * 60 * 1000,
201 sFileCdWait = self.sFileCdWait);
202 if oSession is not None:
203 self.addTask(oTxsSession);
204 # Do the testing.
205 fSkip = 'install' not in self.asTests;
206 reporter.testStart('Install');
207 if not fSkip:
208 fRc, oTxsSession = self.testInstallAdditions(oSession, oTxsSession, oTestVm);
209 reporter.testDone(fSkip);
210
211 if not fSkip \
212 and not fRc:
213 reporter.log('Skipping following tests as Guest Additions were not installed successfully');
214 else:
215 fSkip = 'guestprops' not in self.asTests;
216 reporter.testStart('Guest Properties');
217 if not fSkip:
218 fRc = self.testGuestProperties(oSession, oTxsSession, oTestVm) and fRc;
219 reporter.testDone(fSkip);
220
221 fSkip = 'guestcontrol' not in self.asTests;
222 reporter.testStart('Guest Control');
223 if not fSkip:
224 fRc, oTxsSession = self.aoSubTstDrvs[0].testIt(oTestVm, oSession, oTxsSession);
225 reporter.testDone(fSkip);
226
227 fSkip = 'sharedfolders' not in self.asTests and self.fpApiVer >= 6.0;
228 reporter.testStart('Shared Folders');
229 if not fSkip:
230 fRc, oTxsSession = self.aoSubTstDrvs[1].testIt(oTestVm, oSession, oTxsSession);
231 reporter.testDone(fSkip or fRc is None);
232
233 ## @todo Save and restore test.
234
235 ## @todo Reset tests.
236
237 ## @todo Final test: Uninstallation.
238
239 # Cleanup.
240 self.removeTask(oTxsSession);
241 self.terminateVmBySession(oSession)
242 return fRc;
243
244 def waitForGuestAdditionsRunLevel(self, oSession, oGuest, cMsTimeout, eRunLevel):
245 """
246 Waits for the Guest Additions to reach a specific run level.
247
248 Returns success status.
249 """
250 # No need to wait as we already reached the run level?
251 if eRunLevel == oGuest.additionsRunLevel:
252 reporter.log('Already reached run level %s' % eRunLevel);
253 return True;
254
255 reporter.log('Waiting for Guest Additions to reach run level %s ...' % eRunLevel);
256
257 oConsoleCallbacks = oSession.registerDerivedEventHandler(tdAddBasicConsoleCallbacks, \
258 {'oTstDrv':self, 'oGuest':oGuest, });
259 fRc = False;
260 if oConsoleCallbacks is not None:
261 # Wait for 5 minutes max.
262 tsStart = base.timestampMilli();
263 while base.timestampMilli() - tsStart < cMsTimeout:
264 oTask = self.waitForTasks(1000);
265 if oTask is not None:
266 break;
267 if self.fGAStatusCallbackFired:
268 reporter.log('Reached new run level %s' % eRunLevel);
269 if eRunLevel == self.iGAStatusCallbackRunlevel:
270 fRc = True;
271 break;
272 self.fGAStatusCallbackFired = False;
273 if fRc:
274 reporter.log('Guest Additions run level reached after %dms' % (base.timestampMilli() - tsStart));
275 else:
276 reporter.error('Guest Additions run level not reached');
277
278 # cleanup.
279 oConsoleCallbacks.unregister();
280
281 if not fRc:
282 reporter.log('Waiting for Guest Additions to reach run level %s failed' % (eRunLevel));
283 return fRc;
284
285 def testInstallAdditions(self, oSession, oTxsSession, oTestVm):
286 """
287 Tests installing the guest additions
288 """
289 if oTestVm.isWindows():
290 (fRc, oTxsSession) = self.testWindowsInstallAdditions(oSession, oTxsSession, oTestVm);
291 elif oTestVm.isLinux():
292 (fRc, oTxsSession) = self.testLinuxInstallAdditions(oSession, oTxsSession, oTestVm);
293 else:
294 reporter.error('Guest Additions installation not implemented for %s yet! (%s)' %
295 (oTestVm.sKind, oTestVm.sVmName,));
296 fRc = False;
297
298 #
299 # Verify installation of Guest Additions using commmon bits.
300 #
301 if fRc:
302 #
303 # Check if the additions are operational.
304 #
305 try: oGuest = oSession.o.console.guest;
306 except:
307 reporter.errorXcpt('Getting IGuest failed.');
308 return (False, oTxsSession);
309
310 # Check the additionsVersion attribute. It must not be empty.
311 reporter.testStart('IGuest::additionsVersion');
312 fRc = self.testIGuest_additionsVersion(oGuest);
313 reporter.testDone();
314 if not fRc:
315 return (False, oTxsSession);
316
317 # Wait for the GAs to come up.
318 reporter.testStart('IGuest::additionsRunLevel');
319 fRc = self.testIGuest_additionsRunLevel(oSession, oTestVm, oGuest);
320 reporter.testDone();
321 if not fRc:
322 return (False, oTxsSession);
323
324 ## @todo test IAdditionsFacilities.
325
326 return (fRc, oTxsSession);
327
328 def testWindowsInstallAdditions(self, oSession, oTxsSession, oTestVm):
329 """
330 Installs the Windows guest additions using the test execution service.
331 Since this involves rebooting the guest, we will have to create a new TXS session.
332 """
333
334 #
335 # Install the public signing key.
336 #
337 if oTestVm.sKind not in ('WindowsNT4', 'Windows2000', 'WindowsXP', 'Windows2003'):
338 fRc = self.txsRunTest(oTxsSession, 'VBoxCertUtil.exe', 1 * 60 * 1000, '${CDROM}/cert/VBoxCertUtil.exe',
339 ('${CDROM}/cert/VBoxCertUtil.exe', 'add-trusted-publisher', '${CDROM}/cert/vbox-sha1.cer'),
340 fCheckSessionStatus = True);
341 if not fRc:
342 reporter.error('Error installing SHA1 certificate');
343 else:
344 fRc = self.txsRunTest(oTxsSession, 'VBoxCertUtil.exe', 1 * 60 * 1000, '${CDROM}/cert/VBoxCertUtil.exe',
345 ('${CDROM}/cert/VBoxCertUtil.exe', 'add-trusted-publisher',
346 '${CDROM}/cert/vbox-sha256.cer'), fCheckSessionStatus = True);
347 if not fRc:
348 reporter.error('Error installing SHA256 certificate');
349
350 #
351 # Delete relevant log files.
352 #
353 # Note! On some guests the files in question still can be locked by the OS, so ignore
354 # deletion errors from the guest side (e.g. sharing violations) and just continue.
355 #
356 asLogFiles = [];
357 fHaveSetupApiDevLog = False;
358 if oTestVm.sKind in ('WindowsNT4',):
359 sWinDir = 'C:/WinNT/';
360 else:
361 sWinDir = 'C:/Windows/';
362 asLogFiles = [sWinDir + 'setupapi.log', sWinDir + 'setupact.log', sWinDir + 'setuperr.log'];
363
364 # Apply The SetupAPI logging level so that we also get the (most verbose) setupapi.dev.log file.
365 ## @todo !!! HACK ALERT !!! Add the value directly into the testing source image. Later.
366 fHaveSetupApiDevLog = self.txsRunTest(oTxsSession, 'Enabling setupapi.dev.log', 30 * 1000,
367 'c:\\Windows\\System32\\reg.exe',
368 ('c:\\Windows\\System32\\reg.exe', 'add',
369 '"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Setup"',
370 '/v', 'LogLevel', '/t', 'REG_DWORD', '/d', '0xFF'),
371 fCheckSessionStatus = True);
372
373 for sFile in asLogFiles:
374 self.txsRmFile(oSession, oTxsSession, sFile, 10 * 1000, fIgnoreErrors = True);
375
376 #
377 # The actual install.
378 # Enable installing the optional auto-logon modules (VBoxGINA/VBoxCredProv).
379 # Also tell the installer to produce the appropriate log files.
380 #
381 fRc = self.txsRunTest(oTxsSession, 'VBoxWindowsAdditions.exe', 5 * 60 * 1000, '${CDROM}/VBoxWindowsAdditions.exe',
382 ('${CDROM}/VBoxWindowsAdditions.exe', '/S', '/l', '/with_autologon'), fCheckSessionStatus = True);
383
384 #
385 # Reboot the VM and reconnect the TXS session.
386 #
387 if not fRc \
388 or oTxsSession.getResult() is False:
389 reporter.error('Error installing Windows Guest Additions (installer returned with exit code)')
390 else:
391 (fRc, oTxsSession) = self.txsRebootAndReconnectViaTcp(oSession, oTxsSession, cMsTimeout = 15 * 60 * 1000,
392 cMsCdWait = 15 * 60 * 1000);
393 if fRc is True:
394 # Add the Windows Guest Additions installer files to the files we want to download
395 # from the guest.
396 sGuestAddsDir = 'C:/Program Files/Oracle/VirtualBox Guest Additions/';
397 asLogFiles.append(sGuestAddsDir + 'install.log');
398 # Note: There won't be a install_ui.log because of the silent installation.
399 asLogFiles.append(sGuestAddsDir + 'install_drivers.log');
400 asLogFiles.append('C:/Windows/setupapi.log');
401
402 # Note: setupapi.dev.log only is available since Windows 2000.
403 if fHaveSetupApiDevLog:
404 asLogFiles.append('C:/Windows/setupapi.dev.log');
405
406 #
407 # Download log files.
408 # Ignore errors as all files above might not be present (or in different locations)
409 # on different Windows guests.
410 #
411 self.txsDownloadFiles(oSession, oTxsSession, asLogFiles, fIgnoreErrors = True);
412
413 return (fRc, oTxsSession);
414
415 def getAdditionsInstallerResult(self, oTxsSession):
416 """
417 Extracts the Guest Additions installer exit code from a run before.
418 Assumes that nothing else has been run on the same TXS session in the meantime.
419 """
420 iRc = 0;
421 (_, sOpcode, abPayload) = oTxsSession.getLastReply();
422 if sOpcode.startswith('PROC NOK '): # Extract process rc
423 iRc = abPayload[0]; # ASSUMES 8-bit rc for now.
424 ## @todo Parse more statuses here.
425 return iRc;
426
427 def testLinuxInstallAdditions(self, oSession, oTxsSession, oTestVm):
428 _ = oSession;
429 _ = oTestVm;
430
431 fRc = False;
432
433 #
434 # The actual install.
435 # Also tell the installer to produce the appropriate log files.
436 #
437 # Make sure to add "--nox11" to the makeself wrapper in order to not getting any blocking
438 # xterm window spawned.
439 fRc = self.txsRunTest(oTxsSession, 'VBoxLinuxAdditions.run', 30 * 60 * 1000,
440 '/bin/sh', ('/bin/sh', '${CDROM}/VBoxLinuxAdditions.run', '--nox11'));
441 if not fRc:
442 iRc = self.getAdditionsInstallerResult(oTxsSession);
443 # Check for rc == 0 just for completeness.
444 if iRc in (0, 2): # Can happen if the GA installer has detected older VBox kernel modules running and needs a reboot.
445 reporter.log('Guest has old(er) VBox kernel modules still running; requires a reboot');
446 fRc = True;
447
448 if not fRc:
449 reporter.error('Installing Linux Additions failed (isSuccess=%s, lastReply=%s, see log file for details)'
450 % (oTxsSession.isSuccess(), oTxsSession.getLastReply()));
451
452 #
453 # Download log files.
454 # Ignore errors as all files above might not be present for whatever reason.
455 #
456 asLogFile = [];
457 asLogFile.append('/var/log/vboxadd-install.log');
458 self.txsDownloadFiles(oSession, oTxsSession, asLogFile, fIgnoreErrors = True);
459
460 # Do the final reboot to get the just installed Guest Additions up and running.
461 if fRc:
462 reporter.testStart('Rebooting guest w/ updated Guest Additions active');
463 (fRc, oTxsSession) = self.txsRebootAndReconnectViaTcp(oSession, oTxsSession, cMsTimeout = 15 * 60 * 1000,
464 cMsCdWait = 15 * 60 * 1000);
465 if fRc:
466 pass
467 else:
468 reporter.testFailure('Rebooting and reconnecting to TXS service failed');
469 reporter.testDone();
470
471 return (fRc, oTxsSession);
472
473 def testIGuest_additionsVersion(self, oGuest):
474 """
475 Returns False if no version string could be obtained, otherwise True
476 even though errors are logged.
477 """
478 try:
479 sVer = oGuest.additionsVersion;
480 except:
481 reporter.errorXcpt('Getting the additions version failed.');
482 return False;
483 reporter.log('IGuest::additionsVersion="%s"' % (sVer,));
484
485 if sVer.strip() == '':
486 reporter.error('IGuest::additionsVersion is empty.');
487 return False;
488
489 if sVer != sVer.strip():
490 reporter.error('IGuest::additionsVersion is contains spaces: "%s".' % (sVer,));
491
492 asBits = sVer.split('.');
493 if len(asBits) < 3:
494 reporter.error('IGuest::additionsVersion does not contain at least tree dot separated fields: "%s" (%d).'
495 % (sVer, len(asBits)));
496
497 ## @todo verify the format.
498 return True;
499
500 def testIGuest_additionsRunLevel(self, oSession, oTestVm, oGuest):
501 """
502 Do run level tests.
503 """
504 if oTestVm.isLoggedOntoDesktop():
505 eExpectedRunLevel = vboxcon.AdditionsRunLevelType_Desktop;
506 else:
507 eExpectedRunLevel = vboxcon.AdditionsRunLevelType_Userland;
508
509 return self.waitForGuestAdditionsRunLevel(oSession, oGuest, 5 * 60 * 1000, eExpectedRunLevel);
510
511 def testGuestProperties(self, oSession, oTxsSession, oTestVm):
512 """
513 Test guest properties.
514 """
515 _ = oSession; _ = oTxsSession; _ = oTestVm;
516 return True;
517
518if __name__ == '__main__':
519 sys.exit(tdAddBasic1().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