VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testdriver/vboxinstaller.py@ 56295

Last change on this file since 56295 was 56295, checked in by vboxsync, 10 years ago

ValidationKit: Updated (C) year.

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 33.3 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4"""
5VirtualBox Installer Wrapper Driver.
6
7This installs VirtualBox, starts a sub driver which does the real testing,
8and then uninstall VirtualBox afterwards. This reduces the complexity of the
9other VBox test drivers.
10"""
11
12__copyright__ = \
13"""
14Copyright (C) 2010-2015 Oracle Corporation
15
16This file is part of VirtualBox Open Source Edition (OSE), as
17available from http://www.virtualbox.org. This file is free software;
18you can redistribute it and/or modify it under the terms of the GNU
19General Public License (GPL) as published by the Free Software
20Foundation, in version 2 as it comes in the "COPYING" file of the
21VirtualBox OSE distribution. VirtualBox OSE is distributed in the
22hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
23
24The contents of this file may alternatively be used under the terms
25of the Common Development and Distribution License Version 1.0
26(CDDL) only, as it comes in the "COPYING.CDDL" file of the
27VirtualBox OSE distribution, in which case the provisions of the
28CDDL are applicable instead of those of the GPL.
29
30You may elect to license modified versions of this file under the
31terms and conditions of either the GPL or the CDDL or both.
32"""
33__version__ = "$Revision: 56295 $"
34
35
36# Standard Python imports.
37import os
38import sys
39import re
40#import socket
41import tempfile
42import time
43
44# Only the main script needs to modify the path.
45try: __file__
46except: __file__ = sys.argv[0];
47g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)));
48sys.path.append(g_ksValidationKitDir);
49
50# Validation Kit imports.
51from common import utils, webutils;
52from testdriver import reporter;
53from testdriver.base import TestDriverBase;
54
55
56
57class VBoxInstallerTestDriver(TestDriverBase):
58 """
59 Implementation of a top level test driver.
60 """
61
62
63 ## State file indicating that we've skipped installation.
64 ksVar_Skipped = 'vboxinstaller-skipped';
65
66
67 def __init__(self):
68 TestDriverBase.__init__(self);
69 self._asSubDriver = []; # The sub driver and it's arguments.
70 self._asBuildUrls = []; # The URLs passed us on the command line.
71 self._asBuildFiles = []; # The downloaded file names.
72 self._fAutoInstallPuelExtPack = True;
73
74 #
75 # Base method we override
76 #
77
78 def showUsage(self):
79 rc = TestDriverBase.showUsage(self);
80 # 0 1 2 3 4 5 6 7 8
81 # 012345678901234567890123456789012345678901234567890123456789012345678901234567890
82 reporter.log('');
83 reporter.log('vboxinstaller Options:');
84 reporter.log(' --vbox-build <url[,url2[,..]]>');
85 reporter.log(' Comma separated list of URL to file to download and install or/and');
86 reporter.log(' unpack. URLs without a schema are assumed to be files on the');
87 reporter.log(' build share and will be copied off it.');
88 reporter.log(' --no-puel-extpack');
89 reporter.log(' Indicates that the PUEL extension pack should not be installed if found.');
90 reporter.log(' The default is to install it if found in the vbox-build.');
91 reporter.log(' --');
92 reporter.log(' Indicates the end of our parameters and the start of the sub');
93 reporter.log(' testdriver and its arguments.');
94 return rc;
95
96 def parseOption(self, asArgs, iArg):
97 """
98 Parse our arguments.
99 """
100 if asArgs[iArg] == '--':
101 # End of our parameters and start of the sub driver invocation.
102 iArg = self.requireMoreArgs(1, asArgs, iArg);
103 assert len(self._asSubDriver) == 0;
104 self._asSubDriver = asArgs[iArg:];
105 self._asSubDriver[0] = self._asSubDriver[0].replace('/', os.path.sep);
106 iArg = len(asArgs) - 1;
107 elif asArgs[iArg] == '--vbox-build':
108 # List of files to copy/download and install.
109 iArg = self.requireMoreArgs(1, asArgs, iArg);
110 self._asBuildUrls = asArgs[iArg].split(',');
111 elif asArgs[iArg] == '--no-puel-extpack':
112 self._fAutoInstallPuelExtPack = False;
113 elif asArgs[iArg] == '--puel-extpack':
114 self._fAutoInstallPuelExtPack = True;
115 else:
116 return TestDriverBase.parseOption(self, asArgs, iArg);
117 return iArg + 1;
118
119 def completeOptions(self):
120 #
121 # Check that we've got what we need.
122 #
123 if len(self._asBuildUrls) == 0:
124 reporter.error('No build files specfiied ("--vbox-build file1[,file2[...]]")');
125 return False;
126 if len(self._asSubDriver) == 0:
127 reporter.error('No sub testdriver specified. (" -- test/stuff/tdStuff1.py args")');
128 return False;
129
130 #
131 # Construct _asBuildFiles as an array parallel to _asBuildUrls.
132 #
133 for sUrl in self._asBuildUrls:
134 sDstFile = os.path.join(self.sScratchPath, webutils.getFilename(sUrl));
135 self._asBuildFiles.append(sDstFile);
136
137 return TestDriverBase.completeOptions(self);
138
139 def actionExtract(self):
140 reporter.error('vboxinstall does not support extracting resources, you have to do that using the sub testdriver.');
141 return False;
142
143 def actionCleanupBefore(self):
144 """
145 Kills all VBox process we see.
146
147 This is only supposed to execute on a testbox so we don't need to go
148 all complicated wrt other users.
149 """
150 return self._killAllVBoxProcesses();
151
152 def actionConfig(self):
153 """
154 Install VBox and pass on the configure request to the sub testdriver.
155 """
156 fRc = self._installVBox();
157 if fRc is None: self._persistentVarSet(self.ksVar_Skipped, 'true');
158 else: self._persistentVarUnset(self.ksVar_Skipped);
159
160 ## @todo vbox.py still has bugs preventing us from invoking it seperately with each action.
161 if fRc is True and 'execute' not in self.asActions and 'all' not in self.asActions:
162 fRc = self._executeSubDriver([ 'verify', ]);
163 if fRc is True and 'execute' not in self.asActions and 'all' not in self.asActions:
164 fRc = self._executeSubDriver([ 'config', ]);
165 return fRc;
166
167 def actionExecute(self):
168 """
169 Execute the sub testdriver.
170 """
171 return self._executeSubDriver(self.asActions);
172
173 def actionCleanupAfter(self):
174 """
175 Forward this to the sub testdriver, then uninstall VBox.
176 """
177 fRc = True;
178 if 'execute' not in self.asActions and 'all' not in self.asActions:
179 fRc = self._executeSubDriver([ 'cleanup-after', ]);
180
181 if not self._killAllVBoxProcesses():
182 fRc = False;
183
184 if not self._uninstallVBox(self._persistentVarExists(self.ksVar_Skipped)):
185 fRc = False;
186
187 if utils.getHostOs() == 'darwin':
188 self._darwinUnmountDmg(fIgnoreError = True); # paranoia
189
190 if not TestDriverBase.actionCleanupAfter(self):
191 fRc = False;
192
193 return fRc;
194
195
196 def actionAbort(self):
197 """
198 Forward this to the sub testdriver first, then do the default pid file
199 based cleanup and finally swipe the scene with the heavy artillery.
200 """
201 fRc1 = self._executeSubDriver([ 'abort', ]);
202 fRc2 = TestDriverBase.actionAbort(self);
203 fRc3 = self._killAllVBoxProcesses();
204 return fRc1 and fRc2 and fRc3;
205
206
207 #
208 # Persistent variables.
209 #
210 ## @todo integrate into the base driver. Persisten accross scratch wipes?
211
212 def __persistentVarCalcName(self, sVar):
213 """Returns the (full) filename for the given persistent variable."""
214 assert re.match(r'^[a-zA-Z0-9_-]*$', sVar) is not None;
215 return os.path.join(self.sScratchPath, 'persistent-%s.var' % (sVar,));
216
217 def _persistentVarSet(self, sVar, sValue = ''):
218 """
219 Sets a persistent variable.
220
221 Returns True on success, False + reporter.error on failure.
222
223 May raise exception if the variable name is invalid or something
224 unexpected happens.
225 """
226 sFull = self.__persistentVarCalcName(sVar);
227 try:
228 oFile = open(sFull, 'w');
229 if len(sValue) > 0:
230 oFile.write(sValue.encode('utf-8'));
231 oFile.close();
232 except:
233 reporter.errorXcpt('Error creating "%s"' % (sFull,));
234 return False;
235 return True;
236
237 def _persistentVarUnset(self, sVar):
238 """
239 Unsets a persistent variable.
240
241 Returns True on success, False + reporter.error on failure.
242
243 May raise exception if the variable name is invalid or something
244 unexpected happens.
245 """
246 sFull = self.__persistentVarCalcName(sVar);
247 if os.path.exists(sFull):
248 try:
249 os.unlink(sFull);
250 except:
251 reporter.errorXcpt('Error unlinking "%s"' % (sFull,));
252 return False;
253 return True;
254
255 def _persistentVarExists(self, sVar):
256 """
257 Checks if a persistent variable exists.
258
259 Returns true/false.
260
261 May raise exception if the variable name is invalid or something
262 unexpected happens.
263 """
264 return os.path.exists(self.__persistentVarCalcName(sVar));
265
266 def _persistentVarGet(self, sVar):
267 """
268 Gets the value of a persistent variable.
269
270 Returns variable value on success.
271 Returns None if the variable doesn't exist or if an
272 error (reported) occured.
273
274 May raise exception if the variable name is invalid or something
275 unexpected happens.
276 """
277 sFull = self.__persistentVarCalcName(sVar);
278 if not os.path.exists(sFull):
279 return None;
280 try:
281 oFile = open(sFull, 'r');
282 sValue = oFile.read().decode('utf-8');
283 oFile.close();
284 except:
285 reporter.errorXcpt('Error creating "%s"' % (sFull,));
286 return None;
287 return sValue;
288
289
290 #
291 # Helpers.
292 #
293
294 def _killAllVBoxProcesses(self):
295 """
296 Kills all virtual box related processes we find in the system.
297 """
298
299 for iIteration in range(22):
300 # Gather processes to kill.
301 aoTodo = [];
302 for oProcess in utils.processListAll():
303 sBase = oProcess.getBaseImageNameNoExeSuff();
304 if sBase is None:
305 continue;
306 sBase = sBase.lower();
307 if sBase in [ 'vboxsvc', 'virtualbox', 'virtualboxvm', 'vboxheadless', 'vboxmanage', 'vboxsdl', 'vboxwebsrv',
308 'vboxautostart', 'vboxballoonctrl', 'vboxbfe', 'vboxextpackhelperapp', 'vboxnetdhcp',
309 'vboxnetadpctl', 'vboxtestogl', 'vboxtunctl', 'vboxvmmpreload', 'vboxxpcomipcd', 'vmCreator', ]:
310 aoTodo.append(oProcess);
311 if iIteration in [0, 21] and sBase in [ 'windbg', 'gdb', 'gdb-i386-apple-darwin', ]:
312 reporter.log('Warning: debugger running: %s (%s)' % (oProcess.iPid, sBase,));
313 if len(aoTodo) == 0:
314 return True;
315
316 # Kill.
317 for oProcess in aoTodo:
318 reporter.log('Loop #%d - Killing %s (%s)'
319 % (iIteration, oProcess.iPid, oProcess.sImage if oProcess.sName is None else oProcess.sName,));
320 utils.processKill(oProcess.iPid); # No mercy.
321
322 # Check if they're all dead like they should be.
323 time.sleep(0.1);
324 for oProcess in aoTodo:
325 if utils.processExists(oProcess.iPid):
326 time.sleep(2);
327 break;
328
329 return False;
330
331 def _executeSync(self, asArgs):
332 """
333 Executes a child process synchronously.
334 Returns True if the process executed successfully and returned 0,
335 otherwise False is returned.
336 """
337 reporter.log('Executing: %s' % (asArgs, ));
338 reporter.flushall();
339 try:
340 iRc = utils.processCall(asArgs, shell = False, close_fds = False);
341 except:
342 reporter.errorXcpt();
343 return False;
344 reporter.log('Exit code: %s (%s)' % (iRc, asArgs));
345 return iRc is 0;
346
347 def _sudoExecuteSync(self, asArgs):
348 """
349 Executes a sudo child process synchronously.
350 Returns a tuple [True, 0] if the process executed successfully
351 and returned 0, otherwise [False, rc] is returned.
352 """
353 reporter.log('Executing [sudo]: %s' % (asArgs, ));
354 reporter.flushall();
355 iRc = 0;
356 try:
357 iRc = utils.sudoProcessCall(asArgs, shell = False, close_fds = False);
358 except:
359 reporter.errorXcpt();
360 return (False, 0);
361 reporter.log('Exit code [sudo]: %s (%s)' % (iRc, asArgs));
362 return (iRc is 0, iRc);
363
364 def _executeSubDriver(self, asActions):
365 """
366 Execute the sub testdriver with the specified action.
367 """
368 asArgs = list(self._asSubDriver)
369 asArgs.append('--no-wipe-clean');
370 asArgs.extend(asActions);
371 return self._executeSync(asArgs);
372
373 def _maybeUnpackArchive(self, sMaybeArchive, fNonFatal = False):
374 """
375 Attempts to unpack the given build file.
376 Updates _asBuildFiles.
377 Returns True/False. No exceptions.
378 """
379 asMembers = utils.unpackFile(sMaybeArchive, self.sScratchPath, reporter.log,
380 reporter.log if fNonFatal else reporter.error);
381 if asMembers is None:
382 return False;
383 self._asBuildFiles.extend(asMembers);
384 return True;
385
386
387 def _installVBox(self):
388 """
389 Download / copy the build files into the scratch area and install them.
390 """
391 reporter.testStart('Installing VirtualBox');
392 reporter.log('CWD=%s' % (os.getcwd(),)); # curious
393
394 #
395 # Download the build files.
396 #
397 for i in range(len(self._asBuildUrls)):
398 if webutils.downloadFile(self._asBuildUrls[i], self._asBuildFiles[i],
399 self.sBuildPath, reporter.log, reporter.log) is not True:
400 reporter.testDone(fSkipped = True);
401 return None; # Failed to get binaries, probably deleted. Skip the test run.
402
403 #
404 # Unpack anything we know what is and append it to the build files
405 # list. This allows us to use VBoxAll*.tar.gz files.
406 #
407 for sFile in list(self._asBuildFiles):
408 if self._maybeUnpackArchive(sFile, fNonFatal = True) is not True:
409 reporter.testDone(fSkipped = True);
410 return None; # Failed to unpack. Probably local error, like busy
411 # DLLs on windows, no reason for failing the build.
412
413 #
414 # Go to system specific installation code.
415 #
416 sHost = utils.getHostOs()
417 if sHost == 'darwin': fRc = self._installVBoxOnDarwin();
418 elif sHost == 'linux': fRc = self._installVBoxOnLinux();
419 elif sHost == 'solaris': fRc = self._installVBoxOnSolaris();
420 elif sHost == 'win': fRc = self._installVBoxOnWindows();
421 else:
422 reporter.error('Unsupported host "%s".' % (sHost,));
423 if fRc is False:
424 reporter.testFailure('Installation error.');
425
426 #
427 # Install the extension pack.
428 #
429 if fRc is True and self._fAutoInstallPuelExtPack:
430 fRc = self._installExtPack();
431 if fRc is False:
432 reporter.testFailure('Extension pack installation error.');
433
434 # Some debugging...
435 try:
436 cMbFreeSpace = utils.getDiskUsage(self.sScratchPath);
437 reporter.log('Disk usage after VBox install: %d MB available at %s' % (cMbFreeSpace, self.sScratchPath,));
438 except:
439 reporter.logXcpt('Unable to get disk free space. Ignored. Continuing.');
440
441 reporter.testDone();
442 return fRc;
443
444 def _uninstallVBox(self, fIgnoreError = False):
445 """
446 Uninstall VirtualBox.
447 """
448 reporter.testStart('Uninstalling VirtualBox');
449
450 sHost = utils.getHostOs()
451 if sHost == 'darwin': fRc = self._uninstallVBoxOnDarwin();
452 elif sHost == 'linux': fRc = self._uninstallVBoxOnLinux();
453 elif sHost == 'solaris': fRc = self._uninstallVBoxOnSolaris();
454 elif sHost == 'win': fRc = self._uninstallVBoxOnWindows();
455 else:
456 reporter.error('Unsupported host "%s".' % (sHost,));
457 if fRc is False and not fIgnoreError:
458 reporter.testFailure('Uninstallation failed.');
459
460 fRc2 = self._uninstallAllExtPacks();
461 if not fRc2 and fRc:
462 fRc = fRc2;
463
464 reporter.testDone(fSkipped = (fRc is None));
465 return fRc;
466
467 def _findFile(self, sRegExp, fMandatory = False):
468 """
469 Returns the first build file that matches the given regular expression
470 (basename only).
471
472 Returns None if no match was found, logging it as an error if
473 fMandatory is set.
474 """
475 oRegExp = re.compile(sRegExp);
476
477 for sFile in self._asBuildFiles:
478 if oRegExp.match(os.path.basename(sFile)) and os.path.exists(sFile):
479 return sFile;
480
481 if fMandatory:
482 reporter.error('Failed to find a file matching "%s" in %s.' % (sRegExp, self._asBuildFiles,));
483 return None;
484
485 def _waitForTestManagerConnectivity(self, cSecTimeout):
486 """
487 Check and wait for network connectivity to the test manager.
488
489 This is used with the windows installation and uninstallation since
490 these usually disrupts network connectivity when installing the filter
491 driver. If we proceed to quickly, we might finish the test at a time
492 when we cannot report to the test manager and thus end up with an
493 abandonded test error.
494 """
495 cSecElapsed = 0;
496 secStart = utils.timestampSecond();
497 while reporter.checkTestManagerConnection() is False:
498 cSecElapsed = utils.timestampSecond() - secStart;
499 if cSecElapsed >= cSecTimeout:
500 reporter.log('_waitForTestManagerConnectivity: Giving up after %u secs.' % (cSecTimeout,));
501 return False;
502 time.sleep(2);
503
504 if cSecElapsed > 0:
505 reporter.log('_waitForTestManagerConnectivity: Waited %s secs.' % (cSecTimeout,));
506 return True;
507
508
509 #
510 # Darwin (Mac OS X).
511 #
512
513 def _darwinDmgPath(self):
514 """ Returns the path to the DMG mount."""
515 return os.path.join(self.sScratchPath, 'DmgMountPoint');
516
517 def _darwinUnmountDmg(self, fIgnoreError):
518 """
519 Umount any DMG on at the default mount point.
520 """
521 sMountPath = self._darwinDmgPath();
522 if not os.path.exists(sMountPath):
523 return True;
524
525 # Unmount.
526 fRc = self._executeSync(['hdiutil', 'detach', sMountPath ]);
527 if not fRc and not fIgnoreError:
528 reporter.error('Failed to unmount DMG at %s' % sMountPath);
529
530 # Remove dir.
531 try:
532 os.rmdir(sMountPath);
533 except:
534 if not fIgnoreError:
535 reporter.errorXcpt('Failed to remove directory %s' % sMountPath);
536 return fRc;
537
538 def _darwinMountDmg(self, sDmg):
539 """
540 Mount the DMG at the default mount point.
541 """
542 self._darwinUnmountDmg(fIgnoreError = True)
543
544 sMountPath = self._darwinDmgPath();
545 if not os.path.exists(sMountPath):
546 try:
547 os.mkdir(sMountPath, 0755);
548 except:
549 reporter.logXcpt();
550 return False;
551
552 return self._executeSync(['hdiutil', 'attach', '-readonly', '-mount', 'required', '-mountpoint', sMountPath, sDmg, ]);
553
554 def _installVBoxOnDarwin(self):
555 """ Installs VBox on Mac OS X."""
556 sDmg = self._findFile('^VirtualBox-.*\\.dmg$');
557 if sDmg is None:
558 return False;
559
560 # Mount the DMG.
561 fRc = self._darwinMountDmg(sDmg);
562 if fRc is not True:
563 return False;
564
565 # Uninstall any previous vbox version first.
566 sUninstaller = os.path.join(self._darwinDmgPath(), 'VirtualBox_Uninstall.tool');
567 fRc, _ = self._sudoExecuteSync([sUninstaller, '--unattended',]);
568 if fRc is True:
569
570 # Install the package.
571 sPkg = os.path.join(self._darwinDmgPath(), 'VirtualBox.pkg');
572 fRc, _ = self._sudoExecuteSync(['installer', '-verbose', '-dumplog', '-pkg', sPkg, '-target', '/']);
573
574 # Unmount the DMG and we're done.
575 if not self._darwinUnmountDmg(fIgnoreError = False):
576 fRc = False;
577 return fRc;
578
579 def _uninstallVBoxOnDarwin(self):
580 """ Uninstalls VBox on Mac OS X."""
581
582 # Is VirtualBox installed? If not, don't try uninstall it.
583 sVBox = self._getVBoxInstallPath(fFailIfNotFound = False);
584 if sVBox is None:
585 return True;
586
587 # Find the dmg.
588 sDmg = self._findFile('^VirtualBox-.*\\.dmg$');
589 if sDmg is None:
590 return False;
591 if not os.path.exists(sDmg):
592 return True;
593
594 # Mount the DMG.
595 fRc = self._darwinMountDmg(sDmg);
596 if fRc is not True:
597 return False;
598
599 # Execute the uninstaller.
600 sUninstaller = os.path.join(self._darwinDmgPath(), 'VirtualBox_Uninstall.tool');
601 fRc, _ = self._sudoExecuteSync([sUninstaller, '--unattended',]);
602
603 # Unmount the DMG and we're done.
604 if not self._darwinUnmountDmg(fIgnoreError = False):
605 fRc = False;
606 return fRc;
607
608 #
609 # GNU/Linux
610 #
611
612 def _installVBoxOnLinux(self):
613 """ Installs VBox on Linux."""
614 sRun = self._findFile('^VirtualBox-.*\\.run$');
615 if sRun is None:
616 return False;
617 utils.chmodPlusX(sRun);
618
619 # Install the new one.
620 fRc, _ = self._sudoExecuteSync([sRun,]);
621 return fRc;
622
623 def _uninstallVBoxOnLinux(self):
624 """ Uninstalls VBox on Linux."""
625
626 # Is VirtualBox installed? If not, don't try uninstall it.
627 sVBox = self._getVBoxInstallPath(fFailIfNotFound = False);
628 if sVBox is None:
629 return True;
630
631 # Find the .run file and use it.
632 sRun = self._findFile('^VirtualBox-.*\\.run$', fMandatory = False);
633 if sRun is not None:
634 utils.chmodPlusX(sRun);
635 fRc, _ = self._sudoExecuteSync([sRun, 'uninstall']);
636 return fRc;
637
638 # Try the installed uninstaller.
639 for sUninstaller in [os.path.join(sVBox, 'uninstall.sh'), '/opt/VirtualBox/uninstall.sh', ]:
640 if os.path.isfile(sUninstaller):
641 reporter.log('Invoking "%s"...' % (sUninstaller,));
642 fRc, _ = self._sudoExecuteSync([sUninstaller, 'uninstall']);
643 return fRc;
644
645 reporter.log('Did not find any VirtualBox install to uninstall.');
646 return True;
647
648
649 #
650 # Solaris
651 #
652
653 def _generateAutoResponseOnSolaris(self):
654 """
655 Generates an autoresponse file on solaris, returning the name.
656 None is return on failure.
657 """
658 sPath = os.path.join(self.sScratchPath, 'SolarisAutoResponse');
659 oFile = utils.openNoInherit(sPath, 'wt');
660 oFile.write('basedir=default\n'
661 'runlevel=nocheck\n'
662 'conflict=quit\n'
663 'setuid=nocheck\n'
664 'action=nocheck\n'
665 'partial=quit\n'
666 'instance=unique\n'
667 'idepend=quit\n'
668 'rdepend=quit\n'
669 'space=quit\n'
670 'mail=\n');
671 oFile.close();
672 return sPath;
673
674 def _installVBoxOnSolaris(self):
675 """ Installs VBox on Solaris."""
676 sPkg = self._findFile('^VirtualBox-.*\\.pkg$', fMandatory = False);
677 if sPkg is None:
678 sTar = self._findFile('^VirtualBox-.*-SunOS-.*\\.tar.gz$', fMandatory = False);
679 if sTar is not None:
680 if self._maybeUnpackArchive(sTar) is not True:
681 return False;
682 sPkg = self._findFile('^VirtualBox-.*\\.pkg$', fMandatory = True);
683 sRsp = self._findFile('^autoresponse$', fMandatory = True);
684 if sPkg is None or sRsp is None:
685 return False;
686
687 # Uninstall first (ignore result).
688 self._uninstallVBoxOnSolaris();
689
690 # Install the new one.
691 fRc, _ = self._sudoExecuteSync(['pkgadd', '-d', sPkg, '-n', '-a', sRsp, 'SUNWvbox']);
692 return fRc;
693
694 def _uninstallVBoxOnSolaris(self):
695 """ Uninstalls VBox on Solaris."""
696 reporter.flushall();
697 if utils.processCall(['pkginfo', '-q', 'SUNWvbox']) != 0:
698 return True;
699 sRsp = self._generateAutoResponseOnSolaris();
700 fRc, _ = self._sudoExecuteSync(['pkgrm', '-n', '-a', sRsp, 'SUNWvbox']);
701 return fRc;
702
703 #
704 # Windows
705 #
706
707 def _installVBoxOnWindows(self):
708 """ Installs VBox on Windows."""
709 sExe = self._findFile('^VirtualBox-.*-(MultiArch|Win).exe$');
710 if sExe is None:
711 return False;
712
713 # TEMPORARY HACK - START
714 # It seems that running the NDIS cleanup script upon uninstallation is not
715 # a good idea, so let's run it before installing VirtualBox.
716 #sHostName = socket.getfqdn();
717 #if not sHostName.startswith('testboxwin3') \
718 # and not sHostName.startswith('testboxharp2') \
719 # and not sHostName.startswith('wei01-b6ka-3') \
720 # and utils.getHostOsVersion() in ['8', '8.1', '9', '2008Server', '2008ServerR2', '2012Server']:
721 # reporter.log('Peforming extra NDIS cleanup...');
722 # sMagicScript = os.path.abspath(os.path.join(g_ksValidationKitDir, 'testdriver', 'win-vbox-net-uninstall.ps1'));
723 # fRc2, _ = self._sudoExecuteSync(['powershell.exe', '-Command', 'set-executionpolicy unrestricted']);
724 # if not fRc2:
725 # reporter.log('set-executionpolicy failed.');
726 # self._sudoExecuteSync(['powershell.exe', '-Command', 'get-executionpolicy']);
727 # fRc2, _ = self._sudoExecuteSync(['powershell.exe', '-File', sMagicScript]);
728 # if not fRc2:
729 # reporter.log('NDIS cleanup failed.');
730 # TEMPORARY HACK - END
731
732 # Uninstall any previous vbox version first.
733 fRc = self._uninstallVBoxOnWindows();
734 if fRc is not True:
735 return None; # There shouldn't be anything to uninstall, and if there is, it's not our fault.
736
737 # Install the new one.
738 asArgs = [sExe, '-vvvv', '--silent', '--logging'];
739 asArgs.extend(['--msiparams', 'REBOOT=ReallySuppress']);
740 sVBoxInstallPath = os.environ.get('VBOX_INSTALL_PATH', None);
741 if sVBoxInstallPath is not None:
742 asArgs.extend(['INSTALLDIR="%s"' % (sVBoxInstallPath,)]);
743 fRc2, iRc = self._sudoExecuteSync(asArgs);
744 if fRc2 is False:
745 if iRc == 3010: # ERROR_SUCCESS_REBOOT_REQUIRED
746 reporter.log('Note: Installer required a reboot to complete installation');
747 # Optional, don't fail.
748 else:
749 fRc = False;
750 sLogFile = os.path.join(tempfile.gettempdir(), 'VirtualBox', 'VBoxInstallLog.txt');
751 if sLogFile is not None \
752 and os.path.isfile(sLogFile):
753 reporter.addLogFile(sLogFile, 'log/installer', "Verbose MSI installation log file");
754 self._waitForTestManagerConnectivity(30);
755 return fRc;
756
757 def _uninstallVBoxOnWindows(self):
758 """
759 Uninstalls VBox on Windows, all installations we find to be on the safe side...
760 """
761
762 import win32com.client; # pylint: disable=F0401
763 win32com.client.gencache.EnsureModule('{000C1092-0000-0000-C000-000000000046}', 1033, 1, 0);
764 oInstaller = win32com.client.Dispatch('WindowsInstaller.Installer',
765 resultCLSID = '{000C1090-0000-0000-C000-000000000046}')
766
767 # Search installed products for VirtualBox.
768 asProdCodes = [];
769 for sProdCode in oInstaller.Products:
770 try:
771 sProdName = oInstaller.ProductInfo(sProdCode, "ProductName");
772 except:
773 reporter.logXcpt();
774 continue;
775 #reporter.log('Info: %s=%s' % (sProdCode, sProdName));
776 if sProdName.startswith('Oracle VM VirtualBox') \
777 or sProdName.startswith('Sun VirtualBox'):
778 asProdCodes.append([sProdCode, sProdName]);
779
780 # Before we start uninstalling anything, just ruthlessly kill any
781 # msiexec process we might find hanging around.
782 cKilled = 0;
783 for oProcess in utils.processListAll():
784 sBase = oProcess.getBaseImageNameNoExeSuff();
785 if sBase is not None and sBase.lower() in [ 'msiexec', ]:
786 reporter.log('Killing MSI process: %s (%s)' % (oProcess.iPid, sBase));
787 utils.processKill(oProcess.iPid);
788 cKilled += 1;
789 if cKilled > 0:
790 time.sleep(16); # fudge.
791
792 # Do the uninstalling.
793 fRc = True;
794 sLogFile = os.path.join(self.sScratchPath, 'VBoxUninstallLog.txt');
795 for sProdCode, sProdName in asProdCodes:
796 reporter.log('Uninstalling %s (%s)...' % (sProdName, sProdCode));
797 fRc2, iRc = self._sudoExecuteSync(['msiexec', '/uninstall', sProdCode, '/quiet', '/passive', '/norestart',
798 '/L*v', '%s' % (sLogFile), ]);
799 if fRc2 is False:
800 if iRc == 3010: # ERROR_SUCCESS_REBOOT_REQUIRED
801 reporter.log('Note: Uninstaller required a reboot to complete uninstallation');
802 # Optional, don't fail.
803 else:
804 fRc = False;
805 reporter.addLogFile(sLogFile, 'log/uninstaller', "Verbose MSI uninstallation log file");
806
807 self._waitForTestManagerConnectivity(30);
808 if fRc is False and os.path.isfile(sLogFile):
809 reporter.addLogFile(sLogFile, 'log/uninstaller');
810 return fRc;
811
812
813 #
814 # Extension pack.
815 #
816
817 def _getVBoxInstallPath(self, fFailIfNotFound):
818 """ Returns the default VBox installation path. """
819 sHost = utils.getHostOs();
820 if sHost == 'win':
821 sProgFiles = os.environ.get('ProgramFiles', 'C:\\Program Files');
822 asLocs = [
823 os.path.join(sProgFiles, 'Oracle', 'VirtualBox'),
824 os.path.join(sProgFiles, 'OracleVM', 'VirtualBox'),
825 os.path.join(sProgFiles, 'Sun', 'VirtualBox'),
826 ];
827 elif sHost == 'linux' or sHost == 'solaris':
828 asLocs = [ '/opt/VirtualBox', '/opt/VirtualBox-3.2', '/opt/VirtualBox-3.1', '/opt/VirtualBox-3.0'];
829 elif sHost == 'darwin':
830 asLocs = [ '/Applications/VirtualBox.app/Contents/MacOS' ];
831 else:
832 asLocs = [ '/opt/VirtualBox' ];
833 if 'VBOX_INSTALL_PATH' in os.environ:
834 asLocs.insert(0, os.environ.get('VBOX_INSTALL_PATH', None));
835
836 for sLoc in asLocs:
837 if os.path.isdir(sLoc):
838 return sLoc;
839 if fFailIfNotFound:
840 reporter.error('Failed to locate VirtualBox installation: %s' % (asLocs,));
841 else:
842 reporter.log2('Failed to locate VirtualBox installation: %s' % (asLocs,));
843 return None;
844
845 def _installExtPack(self):
846 """ Installs the extension pack. """
847 sVBox = self._getVBoxInstallPath(fFailIfNotFound = True);
848 if sVBox is None:
849 return False;
850 sExtPackDir = os.path.join(sVBox, 'ExtensionPacks');
851
852 if self._uninstallAllExtPacks() is not True:
853 return False;
854
855 sExtPack = self._findFile('Oracle_VM_VirtualBox_Extension_Pack.vbox-extpack');
856 if sExtPack is None:
857 sExtPack = self._findFile('Oracle_VM_VirtualBox_Extension_Pack.*.vbox-extpack');
858 if sExtPack is None:
859 return True;
860
861 sDstDir = os.path.join(sExtPackDir, 'Oracle_VM_VirtualBox_Extension_Pack');
862 reporter.log('Installing extension pack "%s" to "%s"...' % (sExtPack, sExtPackDir));
863 fRc, _ = self._sudoExecuteSync([ self.getBinTool('vts_tar'),
864 '--extract',
865 '--verbose',
866 '--gzip',
867 '--file', sExtPack,
868 '--directory', sDstDir,
869 '--file-mode-and-mask', '0644',
870 '--file-mode-or-mask', '0644',
871 '--dir-mode-and-mask', '0755',
872 '--dir-mode-or-mask', '0755',
873 '--owner', '0',
874 '--group', '0',
875 ]);
876 return fRc;
877
878 def _uninstallAllExtPacks(self):
879 """ Uninstalls all extension packs. """
880 sVBox = self._getVBoxInstallPath(fFailIfNotFound = False);
881 if sVBox is None:
882 return True;
883
884 sExtPackDir = os.path.join(sVBox, 'ExtensionPacks');
885 if not os.path.exists(sExtPackDir):
886 return True;
887
888 fRc, _ = self._sudoExecuteSync([self.getBinTool('vts_rm'), '-Rfv', '--', sExtPackDir]);
889 return fRc;
890
891
892
893if __name__ == '__main__':
894 sys.exit(VBoxInstallerTestDriver().main(sys.argv));
895
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