示例#1
0
    def _installVBoxOnWindows(self):
        """ Installs VBox on Windows."""
        sExe = self._findFile('^VirtualBox-.*-(MultiArch|Win).exe$')
        if sExe is None:
            return False

        # TEMPORARY HACK - START
        # It seems that running the NDIS cleanup script upon uninstallation is not
        # a good idea, so let's run it before installing VirtualBox.
        sHostName = socket.getfqdn()
        if    not sHostName.startswith('testboxwin3') \
          and not sHostName.startswith('testboxharp2') \
          and utils.getHostOsVersion() in ['8', '8.1', '9', '2008Server', '2008ServerR2', '2012Server']:
            reporter.log('Peforming extra NDIS cleanup...')
            sMagicScript = os.path.abspath(
                os.path.join(g_ksValidationKitDir, 'testdriver',
                             'win-vbox-net-uninstall.ps1'))
            fRc2, _ = self._sudoExecuteSync([
                'powershell.exe', '-Command',
                'set-executionpolicy unrestricted'
            ])
            if not fRc2:
                reporter.log('set-executionpolicy failed.')
            self._sudoExecuteSync(
                ['powershell.exe', '-Command', 'get-executionpolicy'])
            fRc2, _ = self._sudoExecuteSync(
                ['powershell.exe', '-File', sMagicScript])
            if not fRc2:
                reporter.log('NDIS cleanup failed.')
        # TEMPORARY HACK - END

        # Uninstall any previous vbox version first.
        fRc = self._uninstallVBoxOnWindows()
        if fRc is not True:
            return None
            # There shouldn't be anything to uninstall, and if there is, it's not our fault.

        # Install the new one.
        asArgs = [sExe, '-vvvv', '--silent', '--logging']
        asArgs.extend(['--msiparams', 'REBOOT=ReallySuppress'])
        sVBoxInstallPath = os.environ.get('VBOX_INSTALL_PATH', None)
        if sVBoxInstallPath is not None:
            asArgs.extend(['INSTALLDIR="%s"' % (sVBoxInstallPath, )])
        fRc2, iRc = self._sudoExecuteSync(asArgs)
        if fRc2 is False:
            if iRc == 3010:  # ERROR_SUCCESS_REBOOT_REQUIRED
                reporter.log(
                    'Note: Installer required a reboot to complete installation'
                )
                # Optional, don't fail.
            else:
                fRc = False
        sLogFile = os.path.join(tempfile.gettempdir(), 'VirtualBox',
                                'VBoxInstallLog.txt')
        if      sLogFile is not None \
            and os.path.isfile(sLogFile):
            reporter.addLogFile(sLogFile, 'log/installer',
                                "Verbose MSI installation log file")
        self._waitForTestManagerConnectivity(30)
        return fRc
示例#2
0
    def _installVBoxOnWindows(self):
        """ Installs VBox on Windows."""
        sExe = self._findFile('^VirtualBox-.*-(MultiArch|Win).exe$');
        if sExe is None:
            return False;

        # TEMPORARY HACK - START
        # It seems that running the NDIS cleanup script upon uninstallation is not
        # a good idea, so let's run it before installing VirtualBox.
        sHostName = socket.getfqdn();
        if    not sHostName.startswith('testboxwin3') \
          and not sHostName.startswith('testboxharp2') \
          and utils.getHostOsVersion() in ['8', '8.1', '9', '2008Server', '2008ServerR2', '2012Server']:
            reporter.log('Peforming extra NDIS cleanup...');
            sMagicScript = os.path.abspath(os.path.join(g_ksValidationKitDir, 'testdriver', 'win-vbox-net-uninstall.ps1'));
            fRc2, _ = self._sudoExecuteSync(['powershell.exe', '-Command', 'set-executionpolicy unrestricted']);
            if not fRc2:
                reporter.log('set-executionpolicy failed.');
            self._sudoExecuteSync(['powershell.exe', '-Command', 'get-executionpolicy']);
            fRc2, _ = self._sudoExecuteSync(['powershell.exe', '-File', sMagicScript]);
            if not fRc2:
                reporter.log('NDIS cleanup failed.');
        # TEMPORARY HACK - END

        # Uninstall any previous vbox version first.
        fRc = self._uninstallVBoxOnWindows();
        if fRc is not True:
            return None; # There shouldn't be anything to uninstall, and if there is, it's not our fault.

        # Install the new one.
        asArgs = [sExe, '-vvvv', '--silent', '--logging'];
        asArgs.extend(['--msiparams', 'REBOOT=ReallySuppress']);
        sVBoxInstallPath = os.environ.get('VBOX_INSTALL_PATH', None);
        if sVBoxInstallPath is not None:
            asArgs.extend(['INSTALLDIR="%s"' % (sVBoxInstallPath,)]);
        fRc2, iRc = self._sudoExecuteSync(asArgs);
        if fRc2 is False:
            if iRc == 3010: # ERROR_SUCCESS_REBOOT_REQUIRED
                reporter.log('Note: Installer required a reboot to complete installation');
                # Optional, don't fail.
            else:
                fRc = False;
        sLogFile = os.path.join(tempfile.gettempdir(), 'VirtualBox', 'VBoxInstallLog.txt');
        if      sLogFile is not None \
            and os.path.isfile(sLogFile):
            reporter.addLogFile(sLogFile, 'log/installer', "Verbose MSI installation log file");
        self._waitForTestManagerConnectivity(30);
        return fRc;
    def __init__(self, oOptions):
        """
        Initialize internals
        """
        self._oOptions        = oOptions;
        self._sTestBoxHelper  = None;

        # Signed-on state
        self._cSignOnAttempts = 0;
        self._fSignedOn       = False;
        self._fNeedReSignOn   = False;
        self._fFirstSignOn    = True;
        self._idTestBox       = None;
        self._sTestBoxName    = '';
        self._sTestBoxUuid    = self.ksNullUuid; # convenience, assigned below.

        # Command processor.
        self._oCommand = TestBoxCommand(self);

        #
        # Scratch dir setup.  Use /var/tmp instead of /tmp because we may need
        # many many GBs for some test scenarios and /tmp can be backed by swap
        # or be a fast+small disk of some kind, while /var/tmp is normally
        # larger, if slower.  /var/tmp is generally not cleaned up on reboot,
        # /tmp often is, this would break host panic / triple-fault detection.
        #
        if self._oOptions.sScratchRoot is None:
            if utils.getHostOs() in ('win', 'os2', 'haiku', 'dos'):
                # We need *lots* of space, so avoid /tmp as it may be a memory
                # file system backed by the swap file, or worse.
                self._oOptions.sScratchRoot = tempfile.gettempdir();
            else:
                self._oOptions.sScratchRoot = '/var/tmp';
            sSubDir = 'testbox';
            try:
                sSubDir = '%s-%u' % (sSubDir, os.getuid()); # pylint: disable=E1101
            except:
                pass;
            self._oOptions.sScratchRoot = os.path.join(self._oOptions.sScratchRoot, sSubDir);

        self._sScratchSpill   = os.path.join(self._oOptions.sScratchRoot, 'scratch');
        self._sScratchScripts = os.path.join(self._oOptions.sScratchRoot, 'scripts');
        self._sScratchState   = os.path.join(self._oOptions.sScratchRoot, 'state');   # persistant storage.

        for sDir in [self._oOptions.sScratchRoot, self._sScratchSpill, self._sScratchScripts, self._sScratchState]:
            if not os.path.isdir(sDir):
                os.makedirs(sDir, 0700);

        # We count consecutive reinitScratch failures and will reboot the
        # testbox after a while in the hope that it will correct the issue.
        self._cReinitScratchErrors = 0;

        #
        # Mount builds and test resources if requested.
        #
        self.mountShares();

        #
        # Sign-on parameters: Packed into list of records of format:
        # { <Parameter ID>: { <Current value>, <Check function> } }
        #
        self._ddSignOnParams = \
        {
            constants.tbreq.ALL_PARAM_TESTBOX_UUID:        { self.VALUE: self._getHostSystemUuid(),    self.FN: None },
            constants.tbreq.SIGNON_PARAM_OS:               { self.VALUE: utils.getHostOs(),            self.FN: None },
            constants.tbreq.SIGNON_PARAM_OS_VERSION:       { self.VALUE: utils.getHostOsVersion(),     self.FN: None },
            constants.tbreq.SIGNON_PARAM_CPU_ARCH:         { self.VALUE: utils.getHostArch(),          self.FN: None },
            constants.tbreq.SIGNON_PARAM_CPU_VENDOR:       { self.VALUE: self._getHostCpuVendor(),     self.FN: None },
            constants.tbreq.SIGNON_PARAM_CPU_NAME:         { self.VALUE: self._getHostCpuName(),       self.FN: None },
            constants.tbreq.SIGNON_PARAM_CPU_REVISION:     { self.VALUE: self._getHostCpuRevision(),   self.FN: None },
            constants.tbreq.SIGNON_PARAM_HAS_HW_VIRT:      { self.VALUE: self._hasHostHwVirt(),        self.FN: None },
            constants.tbreq.SIGNON_PARAM_HAS_NESTED_PAGING:{ self.VALUE: self._hasHostNestedPaging(),  self.FN: None },
            constants.tbreq.SIGNON_PARAM_HAS_64_BIT_GUEST: { self.VALUE: self._can64BitGuest(),        self.FN: None },
            constants.tbreq.SIGNON_PARAM_HAS_IOMMU:        { self.VALUE: self._hasHostIoMmu(),         self.FN: None },
            #constants.tbreq.SIGNON_PARAM_WITH_RAW_MODE:    { self.VALUE: self._withRawModeSupport(),   self.FN: None },
            constants.tbreq.SIGNON_PARAM_SCRIPT_REV:       { self.VALUE: self._getScriptRev(),         self.FN: None },
            constants.tbreq.SIGNON_PARAM_REPORT:           { self.VALUE: self._getHostReport(),        self.FN: None },
            constants.tbreq.SIGNON_PARAM_PYTHON_VERSION:   { self.VALUE: self._getPythonHexVersion(),  self.FN: None },
            constants.tbreq.SIGNON_PARAM_CPU_COUNT:        { self.VALUE: None,     self.FN: multiprocessing.cpu_count },
            constants.tbreq.SIGNON_PARAM_MEM_SIZE:         { self.VALUE: None,     self.FN: self._getHostMemSize },
            constants.tbreq.SIGNON_PARAM_SCRATCH_SIZE:     { self.VALUE: None,     self.FN: self._getFreeScratchSpace },
        }
        for sItem in self._ddSignOnParams:
            if self._ddSignOnParams[sItem][self.FN] is not None:
                self._ddSignOnParams[sItem][self.VALUE] = self._ddSignOnParams[sItem][self.FN]()

        testboxcommons.log('Starting Test Box script (%s)' % __version__)
        testboxcommons.log('Test Manager URL: %s' % self._oOptions.sTestManagerUrl,)
        testboxcommons.log('Scratch root path: %s' % self._oOptions.sScratchRoot,)
        for sItem in self._ddSignOnParams:
            testboxcommons.log('Sign-On value %18s: %s' % (sItem, self._ddSignOnParams[sItem][self.VALUE]));

        #
        # The System UUID is the primary identification of the machine, so
        # refuse to cooperate if it's NULL.
        #
        self._sTestBoxUuid = self.getSignOnParam(constants.tbreq.ALL_PARAM_TESTBOX_UUID);
        if self._sTestBoxUuid == self.ksNullUuid:
            raise TestBoxScriptException('Couldn\'t determine the System UUID, please use --system-uuid to specify it.');

        #
        # Export environment variables, clearing any we don't know yet.
        #
        for sEnvVar in self._oOptions.asEnvVars:
            iEqual = sEnvVar.find('=');
            if iEqual == -1:    # No '=', remove it.
                if sEnvVar in os.environ:
                    del os.environ[sEnvVar];
            elif iEqual > 0:    # Set it.
                os.environ[sEnvVar[:iEqual]] = sEnvVar[iEqual+1:];
            else:               # Starts with '=', bad user.
                raise TestBoxScriptException('Invalid -E argument: "%s"' % (sEnvVar,));

        os.environ['TESTBOX_PATH_BUILDS']       = self._oOptions.sBuildsPath;
        os.environ['TESTBOX_PATH_RESOURCES']    = self._oOptions.sTestRsrcPath;
        os.environ['TESTBOX_PATH_SCRATCH']      = self._sScratchSpill;
        os.environ['TESTBOX_PATH_SCRIPTS']      = self._sScratchScripts;
        os.environ['TESTBOX_PATH_UPLOAD']       = self._sScratchSpill; ## @todo drop the UPLOAD dir?
        os.environ['TESTBOX_HAS_HW_VIRT']       = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_HAS_HW_VIRT);
        os.environ['TESTBOX_HAS_NESTED_PAGING'] = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_HAS_NESTED_PAGING);
        os.environ['TESTBOX_HAS_IOMMU']         = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_HAS_IOMMU);
        os.environ['TESTBOX_SCRIPT_REV']        = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_SCRIPT_REV);
        os.environ['TESTBOX_CPU_COUNT']         = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_CPU_COUNT);
        os.environ['TESTBOX_MEM_SIZE']          = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_MEM_SIZE);
        os.environ['TESTBOX_SCRATCH_SIZE']      = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_SCRATCH_SIZE);
        #TODO: os.environ['TESTBOX_WITH_RAW_MODE']     = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_WITH_RAW_MODE);
        os.environ['TESTBOX_WITH_RAW_MODE']     = self._withRawModeSupport();
        os.environ['TESTBOX_MANAGER_URL']       = self._oOptions.sTestManagerUrl;
        os.environ['TESTBOX_UUID']              = self._sTestBoxUuid;
        os.environ['TESTBOX_REPORTER']          = 'remote';
        os.environ['TESTBOX_NAME']              = '';
        os.environ['TESTBOX_ID']                = '';
        os.environ['TESTBOX_TEST_SET_ID']       = '';
        os.environ['TESTBOX_TIMEOUT']           = '0';
        os.environ['TESTBOX_TIMEOUT_ABS']       = '0';

        if utils.getHostOs() is 'win':
            os.environ['COMSPEC']            = os.path.join(os.environ['SystemRoot'], 'System32', 'cmd.exe');
    def __init__(self, oOptions):
        """
        Initialize internals
        """
        self._oOptions        = oOptions;
        self._sTestBoxHelper  = None;

        # Signed-on state
        self._cSignOnAttempts = 0;
        self._fSignedOn       = False;
        self._fNeedReSignOn   = False;
        self._fFirstSignOn    = True;
        self._idTestBox       = None;
        self._sTestBoxName    = '';
        self._sTestBoxUuid    = self.ksNullUuid; # convenience, assigned below.

        # Command processor.
        self._oCommand = TestBoxCommand(self);

        #
        # Scratch dir setup.  Use /var/tmp instead of /tmp because we may need
        # many many GBs for some test scenarios and /tmp can be backed by swap
        # or be a fast+small disk of some kind, while /var/tmp is normally
        # larger, if slower.  /var/tmp is generally not cleaned up on reboot,
        # /tmp often is, this would break host panic / triple-fault detection.
        #
        if self._oOptions.sScratchRoot is None:
            if utils.getHostOs() in ('win', 'os2', 'haiku', 'dos'):
                # We need *lots* of space, so avoid /tmp as it may be a memory
                # file system backed by the swap file, or worse.
                self._oOptions.sScratchRoot = tempfile.gettempdir();
            else:
                self._oOptions.sScratchRoot = '/var/tmp';
            sSubDir = 'testbox';
            try:
                sSubDir = '%s-%u' % (sSubDir, os.getuid()); # pylint: disable=E1101
            except:
                pass;
            self._oOptions.sScratchRoot = os.path.join(self._oOptions.sScratchRoot, sSubDir);

        self._sScratchSpill   = os.path.join(self._oOptions.sScratchRoot, 'scratch');
        self._sScratchScripts = os.path.join(self._oOptions.sScratchRoot, 'scripts');
        self._sScratchState   = os.path.join(self._oOptions.sScratchRoot, 'state');   # persistant storage.

        for sDir in [self._oOptions.sScratchRoot, self._sScratchSpill, self._sScratchScripts, self._sScratchState]:
            if not os.path.isdir(sDir):
                os.makedirs(sDir, 0700);

        # We count consecutive reinitScratch failures and will reboot the
        # testbox after a while in the hope that it will correct the issue.
        self._cReinitScratchErrors = 0;

        #
        # Mount builds and test resources if requested.
        #
        self.mountShares();

        #
        # Sign-on parameters: Packed into list of records of format:
        # { <Parameter ID>: { <Current value>, <Check function> } }
        #
        self._ddSignOnParams = \
        {
            constants.tbreq.ALL_PARAM_TESTBOX_UUID:        { self.VALUE: self._getHostSystemUuid(),    self.FN: None },
            constants.tbreq.SIGNON_PARAM_OS:               { self.VALUE: utils.getHostOs(),            self.FN: None },
            constants.tbreq.SIGNON_PARAM_OS_VERSION:       { self.VALUE: utils.getHostOsVersion(),     self.FN: None },
            constants.tbreq.SIGNON_PARAM_CPU_ARCH:         { self.VALUE: utils.getHostArch(),          self.FN: None },
            constants.tbreq.SIGNON_PARAM_CPU_VENDOR:       { self.VALUE: self._getHostCpuVendor(),     self.FN: None },
            constants.tbreq.SIGNON_PARAM_CPU_NAME:         { self.VALUE: self._getHostCpuName(),       self.FN: None },
            constants.tbreq.SIGNON_PARAM_CPU_REVISION:     { self.VALUE: self._getHostCpuRevision(),   self.FN: None },
            constants.tbreq.SIGNON_PARAM_HAS_HW_VIRT:      { self.VALUE: self._hasHostHwVirt(),        self.FN: None },
            constants.tbreq.SIGNON_PARAM_HAS_NESTED_PAGING:{ self.VALUE: self._hasHostNestedPaging(),  self.FN: None },
            constants.tbreq.SIGNON_PARAM_HAS_64_BIT_GUEST: { self.VALUE: self._can64BitGuest(),        self.FN: None },
            constants.tbreq.SIGNON_PARAM_HAS_IOMMU:        { self.VALUE: self._hasHostIoMmu(),         self.FN: None },
            #constants.tbreq.SIGNON_PARAM_WITH_RAW_MODE:    { self.VALUE: self._withRawModeSupport(),   self.FN: None },
            constants.tbreq.SIGNON_PARAM_SCRIPT_REV:       { self.VALUE: self._getScriptRev(),         self.FN: None },
            constants.tbreq.SIGNON_PARAM_REPORT:           { self.VALUE: self._getHostReport(),        self.FN: None },
            constants.tbreq.SIGNON_PARAM_PYTHON_VERSION:   { self.VALUE: self._getPythonHexVersion(),  self.FN: None },
            constants.tbreq.SIGNON_PARAM_CPU_COUNT:        { self.VALUE: None,     self.FN: multiprocessing.cpu_count },
            constants.tbreq.SIGNON_PARAM_MEM_SIZE:         { self.VALUE: None,     self.FN: self._getHostMemSize },
            constants.tbreq.SIGNON_PARAM_SCRATCH_SIZE:     { self.VALUE: None,     self.FN: self._getFreeScratchSpace },
        }
        for sItem in self._ddSignOnParams:
            if self._ddSignOnParams[sItem][self.FN] is not None:
                self._ddSignOnParams[sItem][self.VALUE] = self._ddSignOnParams[sItem][self.FN]()

        testboxcommons.log('Starting Test Box script (%s)' % (self._getScriptRev(),));
        testboxcommons.log('Test Manager URL: %s' % self._oOptions.sTestManagerUrl,)
        testboxcommons.log('Scratch root path: %s' % self._oOptions.sScratchRoot,)
        for sItem in self._ddSignOnParams:
            testboxcommons.log('Sign-On value %18s: %s' % (sItem, self._ddSignOnParams[sItem][self.VALUE]));

        #
        # The System UUID is the primary identification of the machine, so
        # refuse to cooperate if it's NULL.
        #
        self._sTestBoxUuid = self.getSignOnParam(constants.tbreq.ALL_PARAM_TESTBOX_UUID);
        if self._sTestBoxUuid == self.ksNullUuid:
            raise TestBoxScriptException('Couldn\'t determine the System UUID, please use --system-uuid to specify it.');

        #
        # Export environment variables, clearing any we don't know yet.
        #
        for sEnvVar in self._oOptions.asEnvVars:
            iEqual = sEnvVar.find('=');
            if iEqual == -1:    # No '=', remove it.
                if sEnvVar in os.environ:
                    del os.environ[sEnvVar];
            elif iEqual > 0:    # Set it.
                os.environ[sEnvVar[:iEqual]] = sEnvVar[iEqual+1:];
            else:               # Starts with '=', bad user.
                raise TestBoxScriptException('Invalid -E argument: "%s"' % (sEnvVar,));

        os.environ['TESTBOX_PATH_BUILDS']       = self._oOptions.sBuildsPath;
        os.environ['TESTBOX_PATH_RESOURCES']    = self._oOptions.sTestRsrcPath;
        os.environ['TESTBOX_PATH_SCRATCH']      = self._sScratchSpill;
        os.environ['TESTBOX_PATH_SCRIPTS']      = self._sScratchScripts;
        os.environ['TESTBOX_PATH_UPLOAD']       = self._sScratchSpill; ## @todo drop the UPLOAD dir?
        os.environ['TESTBOX_HAS_HW_VIRT']       = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_HAS_HW_VIRT);
        os.environ['TESTBOX_HAS_NESTED_PAGING'] = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_HAS_NESTED_PAGING);
        os.environ['TESTBOX_HAS_IOMMU']         = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_HAS_IOMMU);
        os.environ['TESTBOX_SCRIPT_REV']        = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_SCRIPT_REV);
        os.environ['TESTBOX_CPU_COUNT']         = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_CPU_COUNT);
        os.environ['TESTBOX_MEM_SIZE']          = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_MEM_SIZE);
        os.environ['TESTBOX_SCRATCH_SIZE']      = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_SCRATCH_SIZE);
        #TODO: os.environ['TESTBOX_WITH_RAW_MODE']     = self.getSignOnParam(constants.tbreq.SIGNON_PARAM_WITH_RAW_MODE);
        os.environ['TESTBOX_WITH_RAW_MODE']     = str(self._withRawModeSupport());
        os.environ['TESTBOX_MANAGER_URL']       = self._oOptions.sTestManagerUrl;
        os.environ['TESTBOX_UUID']              = self._sTestBoxUuid;
        os.environ['TESTBOX_REPORTER']          = 'remote';
        os.environ['TESTBOX_NAME']              = '';
        os.environ['TESTBOX_ID']                = '';
        os.environ['TESTBOX_TEST_SET_ID']       = '';
        os.environ['TESTBOX_TIMEOUT']           = '0';
        os.environ['TESTBOX_TIMEOUT_ABS']       = '0';

        if utils.getHostOs() == 'win':
            os.environ['COMSPEC']            = os.path.join(os.environ['SystemRoot'], 'System32', 'cmd.exe');
示例#5
0
    def _uninstallVBoxOnWindows(self):
        """
        Uninstalls VBox on Windows, all installations we find to be on the safe side...
        """

        import win32com.client
        # pylint: disable=F0401
        win32com.client.gencache.EnsureModule(
            '{000C1092-0000-0000-C000-000000000046}', 1033, 1, 0)
        oInstaller = win32com.client.Dispatch(
            'WindowsInstaller.Installer',
            resultCLSID='{000C1090-0000-0000-C000-000000000046}')

        # Search installed products for VirtualBox.
        asProdCodes = []
        for sProdCode in oInstaller.Products:
            try:
                sProdName = oInstaller.ProductInfo(sProdCode, "ProductName")
            except:
                reporter.logXcpt()
                continue
            #reporter.log('Info: %s=%s' % (sProdCode, sProdName));
            if  sProdName.startswith('Oracle VM VirtualBox') \
             or sProdName.startswith('Sun VirtualBox'):
                asProdCodes.append([sProdCode, sProdName])

        # Before we start uninstalling anything, just ruthlessly kill any
        # msiexec process we might find hanging around.
        cKilled = 0
        for oProcess in utils.processListAll():
            sBase = oProcess.getBaseImageNameNoExeSuff()
            if sBase is not None and sBase.lower() in [
                    'msiexec',
            ]:
                reporter.log('Killing MSI process: %s (%s)' %
                             (oProcess.iPid, sBase))
                utils.processKill(oProcess.iPid)
                cKilled += 1
        if cKilled > 0:
            time.sleep(16)
            # fudge.

        # Do the uninstalling.
        fRc = True
        sLogFile = os.path.join(self.sScratchPath, 'VBoxUninstallLog.txt')
        for sProdCode, sProdName in asProdCodes:
            reporter.log('Uninstalling %s (%s)...' % (sProdName, sProdCode))
            fRc2, iRc = self._sudoExecuteSync([
                'msiexec',
                '/uninstall',
                sProdCode,
                '/quiet',
                '/passive',
                '/norestart',
                '/L*v',
                '%s' % (sLogFile),
            ])
            if fRc2 is False:
                if iRc == 3010:  # ERROR_SUCCESS_REBOOT_REQUIRED
                    reporter.log(
                        'Note: Uninstaller required a reboot to complete uninstallation'
                    )
                    # Optional, don't fail.
                else:
                    fRc = False
            reporter.addLogFile(sLogFile, 'log/uninstaller',
                                "Verbose MSI uninstallation log file")

        # TEMPORARY HACK - START
        if fRc and utils.getHostOsVersion() in [
                '8', '8.1', '9', '2008Server', '2008ServerR2', '2012Server'
        ]:
            reporter.log('Peforming extra NDIS cleanup...')
            sMagicScript = os.path.abspath(
                os.path.join(g_ksValidationKitDir, 'testdriver',
                             'win-vbox-net-uninstall.ps1'))
            fRc2, _ = self._sudoExecuteSync([
                'powershell.exe', '-Command',
                'set-executionpolicy unrestricted'
            ])
            if not fRc2:
                reporter.log('set-executionpolicy failed.')
            self._sudoExecuteSync(
                ['powershell.exe', '-Command', 'get-executionpolicy'])
            fRc2, _ = self._sudoExecuteSync(
                ['powershell.exe', '-File', sMagicScript])
            if not fRc2:
                reporter.log('NDIS cleanup failed.')
        # TEMPORARY HACK - END

        self._waitForTestManagerConnectivity(30)
        if fRc is False and os.path.isfile(sLogFile):
            reporter.addLogFile(sLogFile, 'log/uninstaller')
        return fRc