VirtualBox

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

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

Reverted r137769 (Validation Kit/tdAddBasic1.py: Try running Windows GA installation stuff as Administrator), as TXS does not support running with different users yet.

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 21.7 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdAddBasic1.py 84174 2020-05-06 19:41:19Z 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: 84174 $"
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, iRunLevel):
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 iRunLevel == oGuest.additionsRunLevel:
252 reporter.log('Already reached run level %s' % iRunLevel);
253 return True;
254
255 reporter.log('Waiting for Guest Additions to reach run level %s ...' % iRunLevel);
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' % iRunLevel);
269 if iRunLevel == self.iGAStatusCallbackRunlevel:
270 fRc = True;
271 break;
272 self.fGAStatusCallbackFired = False;
273 if not fRc:
274 reporter.testFailure('Guest Additions status did not change to required level');
275
276 # cleanup.
277 oConsoleCallbacks.unregister();
278
279 reporter.log('Waiting for Guest Additions to reach run level %s ended with %s' % (iRunLevel, fRc));
280 return fRc;
281
282 def testInstallAdditions(self, oSession, oTxsSession, oTestVm):
283 """
284 Tests installing the guest additions
285 """
286 if oTestVm.isWindows():
287 (fRc, oTxsSession) = self.testWindowsInstallAdditions(oSession, oTxsSession, oTestVm);
288 elif oTestVm.isLinux():
289 (fRc, oTxsSession) = self.testLinuxInstallAdditions(oSession, oTxsSession, oTestVm);
290 else:
291 reporter.error('Guest Additions installation not implemented for %s yet! (%s)' %
292 (oTestVm.sKind, oTestVm.sVmName,));
293 fRc = False;
294
295 #
296 # Verify installation of Guest Additions using commmon bits.
297 #
298 if fRc:
299 #
300 # Check if the additions are operational.
301 #
302 try: oGuest = oSession.o.console.guest;
303 except:
304 reporter.errorXcpt('Getting IGuest failed.');
305 return (False, oTxsSession);
306
307 #
308 # Wait for the GAs to come up.
309 #
310 fRc = self.waitForGuestAdditionsRunLevel(oSession, oGuest, 5 * 60 * 1000, vboxcon.AdditionsRunLevelType_Userland);
311 if not fRc:
312 return (False, oTxsSession);
313
314 # Check the additionsVersion attribute. It must not be empty.
315 reporter.testStart('IGuest::additionsVersion');
316 fRc = self.testIGuest_additionsVersion(oGuest);
317 reporter.testDone();
318
319 reporter.testStart('IGuest::additionsRunLevel');
320 self.testIGuest_additionsRunLevel(oGuest, oTestVm);
321 reporter.testDone();
322
323 ## @todo test IAdditionsFacilities.
324
325 return (fRc, oTxsSession);
326
327 def testWindowsInstallAdditions(self, oSession, oTxsSession, oTestVm):
328 """
329 Installs the Windows guest additions using the test execution service.
330 Since this involves rebooting the guest, we will have to create a new TXS session.
331 """
332
333 #
334 # Install the public signing key.
335 #
336 if oTestVm.sKind not in ('WindowsNT4', 'Windows2000', 'WindowsXP', 'Windows2003'):
337 fRc = self.txsRunTest(oTxsSession, 'VBoxCertUtil.exe', 1 * 60 * 1000, '${CDROM}/cert/VBoxCertUtil.exe',
338 ('${CDROM}/cert/VBoxCertUtil.exe', 'add-trusted-publisher', '${CDROM}/cert/vbox-sha1.cer'),
339 fCheckSessionStatus = True);
340 if not fRc:
341 reporter.error('Error installing SHA1 certificate');
342 else:
343 fRc = self.txsRunTest(oTxsSession, 'VBoxCertUtil.exe', 1 * 60 * 1000, '${CDROM}/cert/VBoxCertUtil.exe',
344 ('${CDROM}/cert/VBoxCertUtil.exe', 'add-trusted-publisher',
345 '${CDROM}/cert/vbox-sha256.cer'), fCheckSessionStatus = True);
346 if not fRc:
347 reporter.error('Error installing SHA256 certificate');
348
349 #
350 # Delete relevant log files.
351 #
352 # Note! On some guests the files in question still can be locked by the OS, so ignore
353 # deletion errors from the guest side (e.g. sharing violations) and just continue.
354 #
355 asLogFiles = [];
356 fHaveSetupApiDevLog = False;
357 if oTestVm.sKind in ('WindowsNT4',):
358 sWinDir = 'C:/WinNT/';
359 else:
360 sWinDir = 'C:/Windows/';
361 asLogFiles = [sWinDir + 'setupapi.log', sWinDir + 'setupact.log', sWinDir + 'setuperr.log'];
362
363 # Apply The SetupAPI logging level so that we also get the (most verbose) setupapi.dev.log file.
364 ## @todo !!! HACK ALERT !!! Add the value directly into the testing source image. Later.
365 fHaveSetupApiDevLog = self.txsRunTest(oTxsSession, 'Enabling setupapi.dev.log', 30 * 1000,
366 'c:\\Windows\\System32\\reg.exe',
367 ('c:\\Windows\\System32\\reg.exe', 'add',
368 '"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Setup"',
369 '/v', 'LogLevel', '/t', 'REG_DWORD', '/d', '0xFF'),
370 fCheckSessionStatus = True);
371
372 for sFile in asLogFiles:
373 self.txsRmFile(oSession, oTxsSession, sFile, 10 * 1000, fIgnoreErrors = True);
374
375 #
376 # The actual install.
377 # Enable installing the optional auto-logon modules (VBoxGINA/VBoxCredProv).
378 # Also tell the installer to produce the appropriate log files.
379 #
380 fRc = self.txsRunTest(oTxsSession, 'VBoxWindowsAdditions.exe', 5 * 60 * 1000, '${CDROM}/VBoxWindowsAdditions.exe',
381 ('${CDROM}/VBoxWindowsAdditions.exe', '/S', '/l', '/with_autologon'), fCheckSessionStatus = True);
382
383 #
384 # Reboot the VM and reconnect the TXS session.
385 #
386 if not fRc \
387 or oTxsSession.getResult() is False:
388 reporter.error('Error installing Windows Guest Additions (installer returned with exit code)')
389 else:
390 (fRc, oTxsSession) = self.txsRebootAndReconnectViaTcp(oSession, oTxsSession, cMsTimeout = 15 * 60 * 1000,
391 cMsCdWait = 15 * 60 * 1000);
392 if fRc is True:
393 # Add the Windows Guest Additions installer files to the files we want to download
394 # from the guest.
395 sGuestAddsDir = 'C:/Program Files/Oracle/VirtualBox Guest Additions/';
396 asLogFiles.append(sGuestAddsDir + 'install.log');
397 # Note: There won't be a install_ui.log because of the silent installation.
398 asLogFiles.append(sGuestAddsDir + 'install_drivers.log');
399 asLogFiles.append('C:/Windows/setupapi.log');
400
401 # Note: setupapi.dev.log only is available since Windows 2000.
402 if fHaveSetupApiDevLog:
403 asLogFiles.append('C:/Windows/setupapi.dev.log');
404
405 #
406 # Download log files.
407 # Ignore errors as all files above might not be present (or in different locations)
408 # on different Windows guests.
409 #
410 self.txsDownloadFiles(oSession, oTxsSession, asLogFiles, fIgnoreErrors = True);
411
412 return (fRc, oTxsSession);
413
414 def getAdditionsInstallerResult(self, oTxsSession):
415 """
416 Extracts the Guest Additions installer exit code from a run before.
417 Assumes that nothing else has been run on the same TXS session in the meantime.
418 """
419 iRc = 0;
420 (_, sOpcode, abPayload) = oTxsSession.getLastReply();
421 if sOpcode.startswith('PROC NOK '): # Extract process rc
422 iRc = abPayload[0]; # ASSUMES 8-bit rc for now.
423 ## @todo Parse more statuses here.
424 return iRc;
425
426 def testLinuxInstallAdditions(self, oSession, oTxsSession, oTestVm):
427 _ = oSession;
428 _ = oTestVm;
429
430 fRc = False;
431
432 #
433 # The actual install.
434 # Also tell the installer to produce the appropriate log files.
435 #
436 # Make sure to add "--nox11" to the makeself wrapper in order to not getting any blocking
437 # xterm window spawned.
438 fRc = self.txsRunTest(oTxsSession, 'VBoxLinuxAdditions.run', 30 * 60 * 1000,
439 '/bin/sh', ('/bin/sh', '${CDROM}/VBoxLinuxAdditions.run', '--nox11'));
440 if not fRc:
441 iRc = self.getAdditionsInstallerResult(oTxsSession);
442 # Check for rc == 0 just for completeness.
443 if iRc in (0, 2): # Can happen if the GA installer has detected older VBox kernel modules running and needs a reboot.
444 reporter.log('Guest has old(er) VBox kernel modules still running; requires a reboot');
445 fRc = True;
446
447 if not fRc:
448 reporter.error('Installing Linux Additions failed (isSuccess=%s, lastReply=%s, see log file for details)'
449 % (oTxsSession.isSuccess(), oTxsSession.getLastReply()));
450
451 #
452 # Download log files.
453 # Ignore errors as all files above might not be present for whatever reason.
454 #
455 asLogFile = [];
456 asLogFile.append('/var/log/vboxadd-install.log');
457 self.txsDownloadFiles(oSession, oTxsSession, asLogFile, fIgnoreErrors = True);
458
459 # Do the final reboot to get the just installed Guest Additions up and running.
460 if fRc:
461 reporter.testStart('Rebooting guest w/ updated Guest Additions active');
462 (fRc, oTxsSession) = self.txsRebootAndReconnectViaTcp(oSession, oTxsSession, cMsTimeout = 15 * 60 * 1000,
463 cMsCdWait = 15 * 60 * 1000);
464 if fRc:
465 pass
466 else:
467 reporter.testFailure('Rebooting and reconnecting to TXS service failed');
468 reporter.testDone();
469
470 return (fRc, oTxsSession);
471
472 def testIGuest_additionsVersion(self, oGuest):
473 """
474 Returns False if no version string could be obtained, otherwise True
475 even though errors are logged.
476 """
477 try:
478 sVer = oGuest.additionsVersion;
479 except:
480 reporter.errorXcpt('Getting the additions version failed.');
481 return False;
482 reporter.log('IGuest::additionsVersion="%s"' % (sVer,));
483
484 if sVer.strip() == '':
485 reporter.error('IGuest::additionsVersion is empty.');
486 return False;
487
488 if sVer != sVer.strip():
489 reporter.error('IGuest::additionsVersion is contains spaces: "%s".' % (sVer,));
490
491 asBits = sVer.split('.');
492 if len(asBits) < 3:
493 reporter.error('IGuest::additionsVersion does not contain at least tree dot separated fields: "%s" (%d).'
494 % (sVer, len(asBits)));
495
496 ## @todo verify the format.
497 return True;
498
499 def testIGuest_additionsRunLevel(self, oGuest, oTestVm):
500 """
501 Do run level tests.
502 """
503 if oTestVm.isLoggedOntoDesktop():
504 eExpectedRunLevel = vboxcon.AdditionsRunLevelType_Desktop;
505 else:
506 eExpectedRunLevel = vboxcon.AdditionsRunLevelType_Userland;
507
508 ## @todo Insert wait for the desired run level.
509 try:
510 iLevel = oGuest.additionsRunLevel;
511 except:
512 reporter.errorXcpt('Getting the additions run level failed.');
513 return False;
514 reporter.log('IGuest::additionsRunLevel=%s' % (iLevel,));
515
516 if iLevel != eExpectedRunLevel:
517 pass; ## @todo We really need that wait!!
518 #reporter.error('Expected runlevel %d, found %d instead' % (eExpectedRunLevel, iLevel));
519 return True;
520
521
522 def testGuestProperties(self, oSession, oTxsSession, oTestVm):
523 """
524 Test guest properties.
525 """
526 _ = oSession; _ = oTxsSession; _ = oTestVm;
527 return True;
528
529if __name__ == '__main__':
530 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