Index: /trunk/src/VBox/ValidationKit/testmanager/batch/virtual_test_sheriff.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/batch/virtual_test_sheriff.py	(revision 65305)
+++ /trunk/src/VBox/ValidationKit/testmanager/batch/virtual_test_sheriff.py	(revision 65306)
@@ -444,4 +444,5 @@
     ktReason_Host_HostMemoryLow                        = ( 'Host',              'HostMemoryLow' );
     ktReason_Host_DriverNotLoaded                      = ( 'Host',              'Driver not loaded' );
+    ktReason_Host_DriverNotUnloading                   = ( 'Host',              'Driver not unloading' );
     ktReason_Host_NotSignedWithBuildCert               = ( 'Host',              'Not signed with build cert' );
     ktReason_Host_Reboot_OSX_Watchdog_Timeout          = ( 'Host Reboot',       'OSX Watchdog Timeout' );
@@ -619,4 +620,39 @@
     # The investigative units.
     #
+
+    katSimpleInstallUninstallMainLogReasons = [
+        # ( Whether to stop on hit, reason tuple, needle text. )
+    ];
+
+    kdatSimpleInstallUninstallMainLogReasonsPerOs = {
+        'darwin': [
+            # ( Whether to stop on hit, reason tuple, needle text. )
+            ( True, ktReason_Host_DriverNotUnloading,
+              'Can\'t remove kext org.virtualbox.kext.VBoxDrv; services failed to terminate - 0xe00002c7' ),
+        ],
+    };
+
+
+    def investigateInstallUninstallFailure(self, oCaseFile, oFailedResult, sResultLog, fInstall):
+        """
+        Investigates an install or uninstall failure.
+
+        We lump the two together since the installation typically also performs
+        an uninstall first and will be seeing similar issues to the uninstall.
+        """
+        atSimple = self.katSimpleInstallUninstallMainLogReasons;
+        if oCaseFile.oTestBox.sOs in self.kdatSimpleInstallUninstallMainLogReasonsPerOs:
+            atSimple = self.kdatSimpleInstallUninstallMainLogReasonsPerOs[oCaseFile.oTestBox.sOs] + atSimple;
+
+        fFoundSomething = False;
+        for fStopOnHit, tReason, sNeedle in atSimple:
+            if sResultLog.find(sNeedle) > 0:
+                oCaseFile.noteReasonForId(tReason, oFailedResult.idTestResult);
+                if fStopOnHit:
+                    return True;
+                fFoundSomething = True;
+
+        return fFoundSomething if fFoundSomething else None;
+
 
     def investigateBadTestBox(self, oCaseFile):
@@ -900,5 +936,4 @@
         return False;
 
-
     def investigateVBoxVMTest(self, oCaseFile, fSingleVM):
         """
@@ -970,8 +1005,8 @@
             sResultLog = TestSetData.extractLogSectionElapsed(sMainLog, oFailedResult.tsCreated, oFailedResult.tsElapsed);
             if oFailedResult.sName == 'Installing VirtualBox':
-                self.vprint('TODO: Installation failure');
+                self.investigateInstallUninstallFailure(oCaseFile, oFailedResult, sResultLog, fInstall = True)
 
             elif oFailedResult.sName == 'Uninstalling VirtualBox':
-                self.vprint('TODO: Uninstallation failure');
+                self.investigateInstallUninstallFailure(oCaseFile, oFailedResult, sResultLog, fInstall = False)
 
             elif self.isResultFromVMRun(oFailedResult, sResultLog):
