def actionConfig(self): if not self.importVBoxApi(): # So we can use the constant below. return False eNic0AttachType = vboxcon.NetworkAttachmentType_NAT sGaIso = self.getGuestAdditionsIso() # On 6.0 we merge the GAs with the ValidationKit so we can get at FsPerf. # Note! Not possible to do a dboule import as both images an '/OS2' dir. # So, using same dir as with unattended VISOs for the valkit. if self.fpApiVer >= 6.0 and 'sharedfolders' in self.asTests: sGaViso = os.path.join(self.sScratchPath, 'AdditionsAndValKit.viso') ## @todo encode as bash cmd line: sVisoContent = '--iprt-iso-maker-file-marker-bourne-sh %s ' \ '--import-iso \'%s\' ' \ '--push-iso \'%s\' ' \ '/vboxvalidationkit=/ ' \ '--pop ' \ % (uuid.uuid4(), sGaIso, self.sVBoxValidationKitIso) reporter.log2('Using VISO combining GAs and ValKit "%s": %s' % (sGaViso, sVisoContent)) oGaViso = open(sGaViso, 'w') oGaViso.write(sVisoContent) oGaViso.close() sGaIso = sGaViso return self.oTestVmSet.actionConfig(self, eNic0AttachType=eNic0AttachType, sDvdImage=sGaIso)
def processCheckPidAndName(uPid, sName): """ The Windows version of base.processCheckPidAndName """ fRc = processExists(uPid) if fRc is True: try: from win32com.client import GetObject # pylint: disable=F0401 oWmi = GetObject('winmgmts:') aoProcesses = oWmi.InstancesOf('Win32_Process') for oProcess in aoProcesses: if long(oProcess.Properties_("ProcessId").Value) == uPid: sCurName = oProcess.Properties_("Name").Value reporter.log2('uPid=%s sName=%s sCurName=%s' % (uPid, sName, sCurName)) sName = sName.lower() sCurName = sCurName.lower() if os.path.basename(sName) == sName: sCurName = os.path.basename(sCurName) if sCurName == sName \ or sCurName + '.exe' == sName \ or sCurName == sName + '.exe': fRc = True break except: reporter.logXcpt('uPid=%s sName=%s' % (uPid, sName)) return fRc
def _getVBoxInstallPath(self, fFailIfNotFound): """ Returns the default VBox installation path. """ sHost = utils.getHostOs() if sHost == 'win': sProgFiles = os.environ.get('ProgramFiles', 'C:\\Program Files') asLocs = [ os.path.join(sProgFiles, 'Oracle', 'VirtualBox'), os.path.join(sProgFiles, 'OracleVM', 'VirtualBox'), os.path.join(sProgFiles, 'Sun', 'VirtualBox'), ] elif sHost == 'linux' or sHost == 'solaris': asLocs = [ '/opt/VirtualBox', '/opt/VirtualBox-3.2', '/opt/VirtualBox-3.1', '/opt/VirtualBox-3.0' ] elif sHost == 'darwin': asLocs = ['/Applications/VirtualBox.app/Contents/MacOS'] else: asLocs = ['/opt/VirtualBox'] if 'VBOX_INSTALL_PATH' in os.environ: asLocs.insert(0, os.environ.get('VBOX_INSTALL_PATH', None)) for sLoc in asLocs: if os.path.isdir(sLoc): return sLoc if fFailIfNotFound: reporter.error('Failed to locate VirtualBox installation: %s' % (asLocs, )) else: reporter.log2('Failed to locate VirtualBox installation: %s' % (asLocs, )) return None
def processCheckPidAndName(uPid, sName): """ The Windows version of base.processCheckPidAndName """ fRc = processExists(uPid); if fRc is True: try: from win32com.client import GetObject; # pylint: disable=F0401 oWmi = GetObject('winmgmts:'); aoProcesses = oWmi.InstancesOf('Win32_Process'); for oProcess in aoProcesses: if long(oProcess.Properties_("ProcessId").Value) == uPid: sCurName = oProcess.Properties_("Name").Value; reporter.log2('uPid=%s sName=%s sCurName=%s' % (uPid, sName, sCurName)); sName = sName.lower(); sCurName = sCurName.lower(); if os.path.basename(sName) == sName: sCurName = os.path.basename(sCurName); if sCurName == sName \ or sCurName + '.exe' == sName \ or sCurName == sName + '.exe': fRc = True; break; except: reporter.logXcpt('uPid=%s sName=%s' % (uPid, sName)); return fRc;
def processCreate(sName, asArgs): """ Returns a (pid, handle, tid) tuple on success. (-1, None) on failure (logged). """ # Construct a command line. sCmdLine = '' for sArg in asArgs: if sCmdLine == '': sCmdLine += '"' else: sCmdLine += ' "' sCmdLine += sArg sCmdLine += '"' # Try start the process. dwCreationFlags = win32con.CREATE_NEW_PROCESS_GROUP oStartupInfo = win32process.STARTUPINFO() try: (hProcess, hThread, uPid, uTid) = win32process.CreateProcess( sName, sCmdLine, # CommandLine None, # ProcessAttributes None, # ThreadAttibutes 1, # fInheritHandles dwCreationFlags, None, # Environment None, # CurrentDirectory. oStartupInfo) except: reporter.logXcpt('sName="%s" sCmdLine="%s"' % (sName, sCmdLine)) return (-1, None, -1) # Dispense with the thread handle. try: win32api.CloseHandle(hThread) except: reporter.logXcpt() # Try get full access to the process. try: hProcessFullAccess = win32api.DuplicateHandle( \ win32api.GetCurrentProcess(), \ hProcess, \ win32api.GetCurrentProcess(), \ win32con.PROCESS_TERMINATE \ | win32con.PROCESS_QUERY_INFORMATION \ | win32con.SYNCHRONIZE \ | win32con.DELETE, \ False, \ 0) win32api.CloseHandle(hProcess) hProcess = hProcessFullAccess except: reporter.logXcpt() reporter.log2('processCreate -> %#x, hProcess=%#x' % ( uPid, hProcess, )) return (uPid, hProcess, uTid)
def processCheckPidAndName(uPid, sName): """ The Windows version of base.processCheckPidAndName """ fRc = processExists(uPid) if fRc is True: try: from win32com.client import GetObject # pylint: disable=F0401 oWmi = GetObject("winmgmts:") aoProcesses = oWmi.InstancesOf("Win32_Process") for oProcess in aoProcesses: if long(oProcess.Properties_("ProcessId").Value) == uPid: sCurName = oProcess.Properties_("Name").Value reporter.log2("uPid=%s sName=%s sCurName=%s" % (uPid, sName, sCurName)) sName = sName.lower() sCurName = sCurName.lower() if os.path.basename(sName) == sName: sCurName = os.path.basename(sCurName) if sCurName == sName or sCurName + ".exe" == sName or sCurName == sName + ".exe": fRc = True break except: reporter.logXcpt("uPid=%s sName=%s" % (uPid, sName)) return fRc
def _getVBoxInstallPath(self, fFailIfNotFound): """ Returns the default VBox installation path. """ sHost = utils.getHostOs(); if sHost == 'win': sProgFiles = os.environ.get('ProgramFiles', 'C:\\Program Files'); asLocs = [ os.path.join(sProgFiles, 'Oracle', 'VirtualBox'), os.path.join(sProgFiles, 'OracleVM', 'VirtualBox'), os.path.join(sProgFiles, 'Sun', 'VirtualBox'), ]; elif sHost == 'linux' or sHost == 'solaris': asLocs = [ '/opt/VirtualBox', '/opt/VirtualBox-3.2', '/opt/VirtualBox-3.1', '/opt/VirtualBox-3.0']; elif sHost == 'darwin': asLocs = [ '/Applications/VirtualBox.app/Contents/MacOS' ]; else: asLocs = [ '/opt/VirtualBox' ]; if 'VBOX_INSTALL_PATH' in os.environ: asLocs.insert(0, os.environ.get('VBOX_INSTALL_PATH', None)); for sLoc in asLocs: if os.path.isdir(sLoc): return sLoc; if fFailIfNotFound: reporter.error('Failed to locate VirtualBox installation: %s' % (asLocs,)); else: reporter.log2('Failed to locate VirtualBox installation: %s' % (asLocs,)); return None;
def _isExcluded(self, sTest, dExclList): """ Checks if the testcase is excluded or not. """ if sTest in dExclList: sFullExpr = dExclList[sTest].replace(' ', '').strip() if sFullExpr == '': return True # Consider each exclusion expression. These are generally ranges, # either open ended or closed: "<4.3.51r12345", ">=4.3.0 && <=4.3.4". asExprs = sFullExpr.split(';') for sExpr in asExprs: # Split it on the and operator and process each sub expression. fResult = True for sSubExpr in sExpr.split('&&'): # Split out the comparison operator and the version value. if sSubExpr.startswith('<=') or sSubExpr.startswith('>='): sOp = sSubExpr[:2] sValue = sSubExpr[2:] elif sSubExpr.startswith('<') or sSubExpr.startswith( '>') or sSubExpr.startswith('='): sOp = sSubExpr[:1] sValue = sSubExpr[1:] else: sOp = sValue = '' # Convert the version value, making sure we've got a valid one. try: aiValue = [ int(sComp) for sComp in sValue.replace('r', '.').split('.') ] except: aiValue = () if not aiValue or len(aiValue) > 4: reporter.error( 'Invalid exclusion expression for %s: "%s" [%s]' % (sTest, sSubExpr, dExclList[sTest])) return True # Do the compare. iCmp = self._compareVersion(aiValue) if sOp == '>=' and iCmp < 0: fResult = False elif sOp == '>' and iCmp <= 0: fResult = False elif sOp == '<' and iCmp >= 0: fResult = False elif sOp == '>=' and iCmp < 0: fResult = False reporter.log2( 'iCmp=%s; %s %s %s -> %s' % (iCmp, self.aiVBoxVer, sOp, aiValue, fResult)) # Did the expression match? if fResult: return True return False
def processCreate(sName, asArgs): """ Returns a (pid, handle, tid) tuple on success. (-1, None) on failure (logged). """ # Construct a command line. sCmdLine = ''; for sArg in asArgs: if sCmdLine == '': sCmdLine += '"'; else: sCmdLine += ' "'; sCmdLine += sArg; sCmdLine += '"'; # Try start the process. # pylint: disable=no-member dwCreationFlags = win32con.CREATE_NEW_PROCESS_GROUP; oStartupInfo = win32process.STARTUPINFO(); try: (hProcess, hThread, uPid, uTid) = win32process.CreateProcess(sName, sCmdLine, # CommandLine None, # ProcessAttributes None, # ThreadAttibutes 1, # fInheritHandles dwCreationFlags, None, # Environment None, # CurrentDirectory. oStartupInfo); except: reporter.logXcpt('sName="%s" sCmdLine="%s"' % (sName, sCmdLine)); return (-1, None, -1); # Dispense with the thread handle. try: win32api.CloseHandle(hThread); except: reporter.logXcpt(); # Try get full access to the process. try: hProcessFullAccess = win32api.DuplicateHandle( win32api.GetCurrentProcess(), hProcess, win32api.GetCurrentProcess(), win32con.PROCESS_TERMINATE | win32con.PROCESS_QUERY_INFORMATION | win32con.SYNCHRONIZE | win32con.DELETE, False, 0); win32api.CloseHandle(hProcess); hProcess = hProcessFullAccess; except: reporter.logXcpt(); reporter.log2('processCreate -> %#x, hProcess=%#x' % (uPid, hProcess,)); return (uPid, hProcess, uTid);
def _isExcluded(self, sTest, dExclList): """ Checks if the testcase is excluded or not. """ if sTest in dExclList: sFullExpr = dExclList[sTest].replace(" ", "").strip() if sFullExpr == "": return True # Consider each exclusion expression. These are generally ranges, # either open ended or closed: "<4.3.51r12345", ">=4.3.0 && <=4.3.4". asExprs = sFullExpr.split(";") for sExpr in asExprs: # Split it on the and operator and process each sub expression. fResult = True for sSubExpr in sExpr.split("&&"): # Split out the comparison operator and the version value. if sSubExpr.startswith("<=") or sSubExpr.startswith(">="): sOp = sSubExpr[:2] sValue = sSubExpr[2:] elif sSubExpr.startswith("<") or sSubExpr.startswith(">") or sSubExpr.startswith("="): sOp = sSubExpr[:1] sValue = sSubExpr[1:] else: sOp = sValue = "" # Convert the version value, making sure we've got a valid one. try: aiValue = [int(sComp) for sComp in sValue.replace("r", ".").split(".")] except: aiValue = () if len(aiValue) == 0 or len(aiValue) > 4: reporter.error( 'Invalid exclusion expression for %s: "%s" [%s]' % (sTest, sSubExpr, dExclList[sTest]) ) return True # Do the compare. iCmp = self._compareVersion(aiValue) if sOp == ">=" and iCmp < 0: fResult = False elif sOp == ">" and iCmp <= 0: fResult = False elif sOp == "<" and iCmp >= 0: fResult = False elif sOp == ">=" and iCmp < 0: fResult = False reporter.log2("iCmp=%s; %s %s %s -> %s" % (iCmp, self.aiVBoxVer, sOp, aiValue, fResult)) # Did the expression match? if fResult: return True return False
def _isExcluded(self, sTest, dExclList): """ Checks if the testcase is excluded or not. """ if sTest in dExclList: sFullExpr = dExclList[sTest].replace(' ', '').strip(); if sFullExpr == '': return True; # Consider each exclusion expression. These are generally ranges, # either open ended or closed: "<4.3.51r12345", ">=4.3.0 && <=4.3.4". asExprs = sFullExpr.split(';'); for sExpr in asExprs: # Split it on the and operator and process each sub expression. fResult = True; for sSubExpr in sExpr.split('&&'): # Split out the comparison operator and the version value. if sSubExpr.startswith('<=') or sSubExpr.startswith('>='): sOp = sSubExpr[:2]; sValue = sSubExpr[2:]; elif sSubExpr.startswith('<') or sSubExpr.startswith('>') or sSubExpr.startswith('='): sOp = sSubExpr[:1]; sValue = sSubExpr[1:]; else: sOp = sValue = ''; # Convert the version value, making sure we've got a valid one. try: aiValue = [int(sComp) for sComp in sValue.replace('r', '.').split('.')]; except: aiValue = (); if len(aiValue) == 0 or len(aiValue) > 4: reporter.error('Invalid exclusion expression for %s: "%s" [%s]' % (sTest, sSubExpr, dExclList[sTest])); return True; # Do the compare. iCmp = self._compareVersion(aiValue); if sOp == '>=' and iCmp < 0: fResult = False; elif sOp == '>' and iCmp <= 0: fResult = False; elif sOp == '<' and iCmp >= 0: fResult = False; elif sOp == '>=' and iCmp < 0: fResult = False; reporter.log2('iCmp=%s; %s %s %s -> %s' % (iCmp, self.aiVBoxVer, sOp, aiValue, fResult)); # Did the expression match? if fResult: return True; return False;
def locateGstBinary(self, oSession, oTxsSession, asPaths): """ Locates a guest binary on the guest by checking the paths in \a asPaths. """ for sCurPath in asPaths: reporter.log2('Checking for \"%s\" ...' % (sCurPath)) if self.txsIsFile(oSession, oTxsSession, sCurPath, fIgnoreErrors=True): return (True, sCurPath) reporter.error( 'Unable to find guest binary in any of these places:\n%s' % ('\n'.join(asPaths), )) return (False, "")
def mountShareEx(self, oSession, oTxsSession, sShareName, sHostPath, sGuestMountPoint, fMustSucceed): """ Automount a shared folder in the guest, extended version. Returns success status, based on fMustSucceed. """ reporter.testStart('Automounting "%s"' % (sShareName, )) reporter.log2('Creating shared folder "%s" at "%s" ...' % (sShareName, sGuestMountPoint)) try: oConsole = oSession.o.console oConsole.createSharedFolder(sShareName, sHostPath, True, True, sGuestMountPoint) except: if fMustSucceed: reporter.errorXcpt('createSharedFolder(%s,%s,True,True,%s)' % (sShareName, sHostPath, sGuestMountPoint)) else: reporter.log( 'createSharedFolder(%s,%s,True,True,%s) failed, good' % (sShareName, sHostPath, sGuestMountPoint)) reporter.testDone() return False is fMustSucceed # Check whether we can see the shared folder now. Retry for 30 seconds. msStart = base.timestampMilli() while True: fRc = oTxsSession.syncIsDir(sGuestMountPoint + self.sGuestSlash + 'candle.dir') reporter.log2('candle.dir check -> %s' % (fRc, )) if fRc is fMustSucceed: break if base.timestampMilli() - msStart > 30000: reporter.error('Shared folder mounting timed out!') break self.oTstDrv.sleep(1) reporter.testDone() return fRc == fMustSucceed
def actionConfig(self): if not self.importVBoxApi(): # So we can use the constant below. return False; eNic0AttachType = vboxcon.NetworkAttachmentType_NAT; sGaIso = self.getGuestAdditionsIso(); # On 6.0 we merge the GAs with the ValidationKit so we can get at FsPerf. # # Note1: Not possible to do a double import as both images an '/OS2' dir. # So, using same dir as with unattended VISOs for the valkit. # # Note2: We need to make sure that we don't change the location of the # ValidationKit bits of the combined VISO, as this will break TXS' (TestExecService) # automatic updating mechanism (uses hardcoded paths, e.g. "{CDROM}/linux/amd64/TestExecService"). # ## @todo Find a solution for testing the automatic Guest Additions updates, which also looks at {CDROM}s root. if self.fpApiVer >= 6.0: sGaViso = os.path.join(self.sScratchPath, 'AdditionsAndValKit.viso'); ## @todo encode as bash cmd line: sVisoContent = '--iprt-iso-maker-file-marker-bourne-sh %s ' \ '--import-iso \'%s\' ' \ '--push-iso \'%s\' ' \ '/vboxadditions=/ ' \ '--pop ' \ % (uuid.uuid4(), self.sVBoxValidationKitIso, sGaIso); reporter.log2('Using VISO combining ValKit and GAs "%s": %s' % (sVisoContent, sGaViso)); oGaViso = open(sGaViso, 'w'); oGaViso.write(sVisoContent); oGaViso.close(); sGaIso = sGaViso; self.sGstPathGaPrefix = 'vboxadditions'; else: self.sGstPathGaPrefix = ''; reporter.log2('Path to Guest Additions on ISO is "%s"' % self.sGstPathGaPrefix); return self.oTestVmSet.actionConfig(self, eNic0AttachType = eNic0AttachType, sDvdImage = sGaIso);
def executeHstLoop(self, sWhat, asArgs, asEnv=None, fAsAdmin=False): """ Inner loop which handles the execution of a host binary. """ fRc = False asEnvTmp = os.environ.copy() if asEnv: for sEnv in asEnv: sKey, sValue = sEnv.split('=') reporter.log2('Setting env var \"%s\" -> \"%s\"' % (sKey, sValue)) os.environ[sKey] = sValue # Also apply it to the current environment. asEnvTmp[sKey] = sValue if fAsAdmin \ and utils.getHostOs() != 'win': oProcess = utils.sudoProcessPopen(asArgs, env=asEnvTmp, stdout=sys.stdout, stderr=sys.stdout, close_fds=False) else: oProcess = utils.processPopenSafe(asArgs, env=asEnvTmp, stdout=sys.stdout, stderr=sys.stdout) if oProcess: self.pidFileAdd(oProcess.pid, sWhat, fSudo=fAsAdmin) iRc = oProcess.wait() self.pidFileRemove(oProcess.pid) if iRc == 0: reporter.log('*** %s: exit code %d' % (sWhat, iRc)) fRc = True else: reporter.log('!*! %s: exit code %d' % (sWhat, iRc)) return fRc
def executeHst(self, sWhat, asArgs, asEnv=None, fAsAdmin=False): """ Runs a binary (image) with optional admin (root) rights on the host and waits until it terminates. Windows currently is not supported yet running stuff as Administrator. Returns success status (exit code is 0). """ reporter.log('Executing \"%s\" on host (as admin = %s)' % (sWhat, fAsAdmin)) try: sys.stdout.flush() except: pass try: sys.stderr.flush() except: pass # Initialize thread rc. self.iThreadHstProcRc = -42 try: oThread = threading.Thread(target=self.executeHstThread, args=[sWhat, asArgs, asEnv, fAsAdmin]) oThread.start() while oThread.join(0.1): if not oThread.is_alive(): break self.processEvents(0) reporter.log2('Thread returned exit code for "%s": %d' % (sWhat, self.iThreadHstProcRc)) except: reporter.logXcpt('Starting thread for "%s" failed' % (sWhat, )) return self.iThreadHstProcRc == 0
def unmountShareEx(self, oSession, oTxsSession, sShareName, sGuestMountPoint, fMustSucceed): """ Unmounts a shared folder in the guest. Returns success status, based on fMustSucceed. """ reporter.log2('Autounmount') try: oConsole = oSession.o.console oConsole.removeSharedFolder(sShareName) except: if fMustSucceed: reporter.errorXcpt('removeSharedFolder(%s)' % (sShareName, )) else: reporter.log('removeSharedFolder(%s)' % (sShareName, )) reporter.testDone() return False is fMustSucceed # Check whether the shared folder is gone on the guest now. Retry for 30 seconds. msStart = base.timestampMilli() while True: fRc = oTxsSession.syncIsDir(sGuestMountPoint + self.sGuestSlash + 'candle.dir') reporter.log2('candle.dir check -> %s' % (fRc, )) if fRc is not fMustSucceed: break if base.timestampMilli() - msStart > 30000: reporter.error('Shared folder unmounting timed out!') fRc = False break self.oTstDrv.sleep(1) reporter.testDone() return fRc is not fMustSucceed
def testIt(self, oTestVm, oSession, oTxsSession): """ Executes the test. Returns fRc, oTxsSession. The latter may have changed. """ reporter.log("Active tests: %s" % (self.asTests, )) # # Skip the test if before 6.0 # if self.oTstDrv.fpApiVer < 6.0: reporter.log('Requires 6.0 or later (for now)') return (None, oTxsSession) # # Create the host directory to share. Empty except for a 'candle.dir' subdir # that we use to check that it mounted correctly. # sSharedFolder1 = os.path.join(self.oTstDrv.sScratchPath, 'shfl1') reporter.log2('Creating shared host folder "%s"...' % (sSharedFolder1, )) if os.path.exists(sSharedFolder1): try: shutil.rmtree(sSharedFolder1) except: return (reporter.errorXcpt('shutil.rmtree(%s)' % (sSharedFolder1, )), oTxsSession) try: os.mkdir(sSharedFolder1) except: return (reporter.errorXcpt('os.mkdir(%s)' % (sSharedFolder1, )), oTxsSession) try: os.mkdir(os.path.join(sSharedFolder1, 'candle.dir')) except: return (reporter.errorXcpt('os.mkdir(%s)' % (sSharedFolder1, )), oTxsSession) # Guess a free mount point inside the guest. if oTestVm.isWindows() or oTestVm.isOS2(): sMountPoint1 = 'V:' sGuestSlash = '\\' else: sMountPoint1 = '/mnt/shfl1' sGuestSlash = '/' # # Automount a shared folder in the guest. # reporter.testStart('Automount') reporter.log2('Creating shared folder shfl1...') try: oConsole = oSession.o.console oConsole.createSharedFolder('shfl1', sSharedFolder1, True, True, sMountPoint1) except: reporter.errorXcpt('createSharedFolder(shfl1,%s,True,True,%s)' % (sSharedFolder1, sMountPoint1)) reporter.testDone() return (False, oTxsSession) # Check whether we can see the shared folder now. Retry for 30 seconds. msStart = base.timestampMilli() while True: fRc = oTxsSession.syncIsDir(sMountPoint1 + sGuestSlash + 'candle.dir') reporter.log2('candle.dir check -> %s' % (fRc, )) if fRc is not False: break if base.timestampMilli() - msStart > 30000: reporter.error('Shared folder mounting timed out!') break self.oTstDrv.sleep(1) reporter.testDone() if fRc is not True: return (False, oTxsSession) # skip the remainder if we cannot auto mount the folder. # # Run FsPerf inside the guest. # fSkip = 'fsperf' not in self.asTests if fSkip is False: cMbFree = utils.getDiskUsage(sSharedFolder1) if cMbFree >= 16: reporter.log2('Free space: %u MBs' % (cMbFree, )) else: reporter.log('Skipping FsPerf because only %u MB free on %s' % ( cMbFree, sSharedFolder1, )) fSkip = True if fSkip is False: # Common arguments: asArgs = [ 'FsPerf', '-d', sMountPoint1 + sGuestSlash + 'fstestdir-1', '-s8' ] # Skip part of mmap on older windows systems without CcCoherencyFlushAndPurgeCache (>= w7). reporter.log2('oTestVm.sGuestOsType=%s' % (oTestVm.sGuestOsType, )) if oTestVm.getNonCanonicalGuestOsType() \ in [ 'WindowsNT3x', 'WindowsNT4', 'Windows2000', 'WindowsXP', 'WindowsXP_64', 'Windows2003', 'Windows2003_64', 'WindowsVista', 'WindowsVista_64', 'Windows2008', 'Windows2008_64']: asArgs.append('--no-mmap-coherency') # Configure I/O block sizes according to guest memory size: cbMbRam = 128 try: cbMbRam = oSession.o.machine.memorySize except: reporter.errorXcpt() reporter.log2('cbMbRam=%s' % (cbMbRam, )) asArgs.append('--set-block-size=1') asArgs.append('--add-block-size=512') asArgs.append('--add-block-size=4096') asArgs.append('--add-block-size=16384') asArgs.append('--add-block-size=65536') asArgs.append('--add-block-size=1048576') # 1 MiB if cbMbRam >= 512: asArgs.append('--add-block-size=33554432') # 32 MiB if cbMbRam >= 768: asArgs.append('--add-block-size=134217728') # 128 MiB # Putting lots (10000) of files in a single directory causes issues on OS X # (HFS+ presumably, though could be slow disks) and some linuxes (slow disks, # maybe ext2/3?). So, generally reduce the file count to 4096 everywhere # since we're not here to test the host file systems, and 3072 on macs. if utils.getHostOs() in [ 'darwin', ]: asArgs.append('--many-files=3072') elif utils.getHostOs() in [ 'linux', ]: asArgs.append('--many-files=4096') # Add the extra arguments from the command line and kick it off: asArgs.extend(self.asExtraArgs) # Run FsPerf: reporter.log2('Starting guest FsPerf (%s)...' % (asArgs, )) sFsPerfPath = self._locateGstFsPerf(oTxsSession) fRc = self.oTstDrv.txsRunTest(oTxsSession, 'FsPerf', 30 * 60 * 1000, sFsPerfPath, asArgs) reporter.log2('FsPerf -> %s' % (fRc, )) sTestDir = os.path.join(sSharedFolder1, 'fstestdir-1') if os.path.exists(sTestDir): fRc = reporter.errorXcpt('test directory lingers: %s' % (sTestDir, )) try: shutil.rmtree(sTestDir) except: fRc = reporter.errorXcpt('shutil.rmtree(%s)' % (sTestDir, )) else: reporter.testStart('FsPerf') reporter.testDone(fSkip or fRc is None) return (fRc, oTxsSession)
def executeHstLoop(self, sWhat, asArgs, asEnv=None, fAsAdmin=False): """ Inner loop which handles the execution of a host binary. Might be called synchronously in main thread or via the thread exeuction helper (asynchronous). """ fRc = False asEnvTmp = os.environ.copy() if asEnv: for sEnv in asEnv: sKey, sValue = sEnv.split('=') reporter.log2('Setting env var \"%s\" -> \"%s\"' % (sKey, sValue)) os.environ[sKey] = sValue # Also apply it to the current environment. asEnvTmp[sKey] = sValue try: # Spawn process. if fAsAdmin \ and utils.getHostOs() != 'win': oProcess = utils.sudoProcessStart(asArgs, env=asEnvTmp, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) else: oProcess = utils.processStart(asArgs, env=asEnvTmp, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if not oProcess: reporter.error('Starting process for "%s" failed!' % (sWhat)) return False iPid = oProcess.pid self.pidFileAdd(iPid, sWhat) iRc = 0 # For Python 3.x we provide "real-time" output. if sys.version_info[0] >= 3: while oProcess.stdout.readable(): # pylint: disable=no-member sStdOut = oProcess.stdout.readline() if sStdOut: sStdOut = sStdOut.strip() reporter.log('%s: %s' % (sWhat, sStdOut)) iRc = oProcess.poll() if iRc is not None: break else: # For Python 2.x it's too much hassle to set the file descriptor options (O_NONBLOCK) and stuff, # so just use communicate() here and dump everythiong all at once when finished. sStdOut = oProcess.communicate() if sStdOut: reporter.log('%s: %s' % (sWhat, sStdOut)) iRc = oProcess.poll() if iRc == 0: reporter.log('*** %s: exit code %d' % (sWhat, iRc)) fRc = True else: reporter.log('!*! %s: exit code %d' % (sWhat, iRc)) self.pidFileRemove(iPid) # Save thread result code. self.iThreadHstProcRc = iRc except: reporter.logXcpt('Executing "%s" failed!' % (sWhat)) return fRc
def testIt(self, oTestVm, oSession, oTxsSession): """ Executes the test. Returns fRc, oTxsSession. The latter may have changed. """ reporter.log("Active tests: %s" % (self.asTests, )) # # Skip the test if before 6.0 # if self.oTstDrv.fpApiVer < 6.0: reporter.log('Requires 6.0 or later (for now)') return (None, oTxsSession) # Guess a free mount point inside the guest. if oTestVm.isWindows() or oTestVm.isOS2(): self.sGuestSlash = '\\' else: self.sGuestSlash = '/' # # Create the host directory to share. Empty except for a 'candle.dir' subdir # that we use to check that it mounted correctly. # sShareName1 = 'shfl1' sShareHostPath1 = os.path.join(self.oTstDrv.sScratchPath, sShareName1) reporter.log2('Creating shared host folder "%s"...' % (sShareHostPath1, )) if os.path.exists(sShareHostPath1): try: shutil.rmtree(sShareHostPath1) except: return (reporter.errorXcpt('shutil.rmtree(%s)' % (sShareHostPath1, )), oTxsSession) try: os.mkdir(sShareHostPath1) except: return (reporter.errorXcpt('os.mkdir(%s)' % (sShareHostPath1, )), oTxsSession) try: os.mkdir(os.path.join(sShareHostPath1, 'candle.dir')) except: return (reporter.errorXcpt('os.mkdir(%s)' % (sShareHostPath1, )), oTxsSession) # Guess a free mount point inside the guest. if oTestVm.isWindows() or oTestVm.isOS2(): sMountPoint1 = 'V:' else: sMountPoint1 = '/mnt/' + sShareName1 fRc = self.mountShare(oSession, oTxsSession, sShareName1, sShareHostPath1, sMountPoint1) if fRc is not True: return (False, oTxsSession) # skip the remainder if we cannot auto mount the folder. # # Run FsPerf inside the guest. # fSkip = 'fsperf' not in self.asTests if fSkip is False: cMbFree = utils.getDiskUsage(sShareHostPath1) if cMbFree >= 16: reporter.log2('Free space: %u MBs' % (cMbFree, )) else: reporter.log('Skipping FsPerf because only %u MB free on %s' % ( cMbFree, sShareHostPath1, )) fSkip = True if fSkip is False: # Common arguments: asArgs = [ 'FsPerf', '-d', sMountPoint1 + self.sGuestSlash + 'fstestdir-1', '-s8' ] # Skip part of mmap on older windows systems without CcCoherencyFlushAndPurgeCache (>= w7). reporter.log2('oTestVm.sGuestOsType=%s' % (oTestVm.sGuestOsType, )) if oTestVm.getNonCanonicalGuestOsType() \ in [ 'WindowsNT3x', 'WindowsNT4', 'Windows2000', 'WindowsXP', 'WindowsXP_64', 'Windows2003', 'Windows2003_64', 'WindowsVista', 'WindowsVista_64', 'Windows2008', 'Windows2008_64']: asArgs.append('--no-mmap-coherency') # Configure I/O block sizes according to guest memory size: cbMbRam = 128 try: cbMbRam = oSession.o.machine.memorySize except: reporter.errorXcpt() reporter.log2('cbMbRam=%s' % (cbMbRam, )) asArgs.append('--set-block-size=1') asArgs.append('--add-block-size=512') asArgs.append('--add-block-size=4096') asArgs.append('--add-block-size=16384') asArgs.append('--add-block-size=65536') asArgs.append('--add-block-size=1048576') # 1 MiB if cbMbRam >= 512: asArgs.append('--add-block-size=33554432') # 32 MiB if cbMbRam >= 768: asArgs.append('--add-block-size=134217728') # 128 MiB # Putting lots (10000) of files in a single directory causes issues on OS X # (HFS+ presumably, though could be slow disks) and some linuxes (slow disks, # maybe ext2/3?). So, generally reduce the file count to 4096 everywhere # since we're not here to test the host file systems, and 3072 on macs. if utils.getHostOs() in [ 'darwin', ]: asArgs.append('--many-files=3072') elif utils.getHostOs() in [ 'linux', ]: asArgs.append('--many-files=4096') # Add the extra arguments from the command line and kick it off: asArgs.extend(self.asExtraArgs) # Run FsPerf: reporter.log2('Starting guest FsPerf (%s)...' % (asArgs, )) sFsPerfPath = self._locateGstFsPerf(oTxsSession) ## @todo For some odd reason the combined GA/VaKit .ISO (by IPRT/fs/isomakercmd) # sometimes (?) contains FsPerf as non-executable (-r--r--r-- 1 root root) on Linux. # # So work around this for now by copying the desired FsPerf binary to the temp directory, # make it executable and execute it from there. fISOMakerCmdIsBuggy = oTestVm.isLinux() if fISOMakerCmdIsBuggy: sFsPerfPathTemp = oTestVm.pathJoin( self.oTstDrv.getGuestTempDir(oTestVm), 'FsPerf${EXESUFF}') if oTestVm.isWindows() \ or oTestVm.isOS2(): sCopy = self.oTstDrv.getGuestSystemShell() sCopyArgs = (sCopy, "/C", "copy", "/Y", sFsPerfPath, sFsPerfPathTemp) else: sCopy = oTestVm.pathJoin( self.oTstDrv.getGuestSystemDir(oTestVm), 'cp') sCopyArgs = (sCopy, "-a", "-v", sFsPerfPath, sFsPerfPathTemp) fRc = self.oTstDrv.txsRunTest(oTxsSession, 'Copying FsPerf', 60 * 1000, sCopy, sCopyArgs, fCheckSessionStatus=True) fRc = fRc and oTxsSession.syncChMod(sFsPerfPathTemp, 0o755) if fRc: sFsPerfPath = sFsPerfPathTemp fRc = self.oTstDrv.txsRunTest(oTxsSession, 'Running FsPerf', 90 * 60 * 1000, sFsPerfPath, asArgs, fCheckSessionStatus=True) reporter.log2('FsPerf -> %s' % (fRc, )) if fRc: # Do a bit of diagnosis to find out why this failed. if not oTestVm.isWindows() \ and not oTestVm.isOS2(): sCmdLs = oTestVm.pathJoin( self.oTstDrv.getGuestSystemDir(oTestVm), 'ls') oTxsSession.syncExec(sCmdLs, (sCmdLs, "-al", sFsPerfPath), fIgnoreErrors=True) oTxsSession.syncExec(sCmdLs, (sCmdLs, "-al", "-R", "/opt"), fIgnoreErrors=True) oTxsSession.syncExec(sCmdLs, (sCmdLs, "-al", "-R", "/media/cdrom"), fIgnoreErrors=True) sTestDir = os.path.join(sShareHostPath1, 'fstestdir-1') if os.path.exists(sTestDir): fRc = reporter.errorXcpt('test directory lingers: %s' % (sTestDir, )) try: shutil.rmtree(sTestDir) except: fRc = reporter.errorXcpt('shutil.rmtree(%s)' % (sTestDir, )) else: reporter.testStart('FsPerf') reporter.testDone(fSkip or fRc is None) # # Check if auto-unmounting works. # if fRc is True: fRc = self.unmountShare(oSession, oTxsSession, sShareName1, sMountPoint1) ## @todo Add tests for multiple automount shares, random unmounting, reboot test. return (fRc, oTxsSession)
def actionExecute(self, oTestDrv, fnCallback): # pylint: disable=R0914 """ For base.TestDriver.actionExecute. Calls the callback function for each of the VMs and basic configuration variations (virt-mode and cpu count). Returns True if all fnCallback calls returned True, otherwise False. The callback can return True, False or None. The latter is for when the test is skipped. (True is for success, False is for failure.) """ self._removeUnsupportedVirtModes(oTestDrv); cMaxCpus = oTestDrv.getHostCpuCount(); # # The test loop. # fRc = True; for oTestVm in self.aoTestVms: if oTestVm.fSkip and self.fIgnoreSkippedVm: reporter.log2('Ignoring VM %s (fSkip = True).' % (oTestVm.sVmName,)); continue; reporter.testStart(oTestVm.sVmName); if oTestVm.fSkip: reporter.testDone(fSkipped = True); continue; # Intersect the supported modes and the ones being testing. asVirtModesSup = [sMode for sMode in oTestVm.asVirtModesSup if sMode in self.asVirtModes]; # Ditto for CPUs. acCpusSup = [cCpus for cCpus in oTestVm.acCpusSup if cCpus in self.acCpus]; # Ditto for paravirtualization modes, except if not specified we got a less obvious default. if self.asParavirtModes is not None and oTestDrv.fpApiVer >= 5.0: asParavirtModes = [sPvMode for sPvMode in oTestVm.asParavirtModesSup if sPvMode in self.asParavirtModes]; assert None not in asParavirtModes; elif oTestDrv.fpApiVer >= 5.0: asParavirtModes = (oTestVm.asParavirtModesSup[0],); assert asParavirtModes[0] is not None; else: asParavirtModes = (None,); for cCpus in acCpusSup: if cCpus == 1: reporter.testStart('1 cpu'); else: reporter.testStart('%u cpus' % (cCpus)); if cCpus > cMaxCpus: reporter.testDone(fSkipped = True); continue; cTests = 0; for sVirtMode in asVirtModesSup: if sVirtMode == 'raw' and cCpus > 1: continue; reporter.testStart('%s' % ( g_dsVirtModeDescs[sVirtMode], ) ); cStartTests = cTests; for sParavirtMode in asParavirtModes: if sParavirtMode is not None: assert oTestDrv.fpApiVer >= 5.0; reporter.testStart('%s' % ( sParavirtMode, ) ); # Reconfigure the VM. try: (rc2, oVM) = oTestVm.getReconfiguredVm(oTestDrv, cCpus, sVirtMode, sParavirtMode = sParavirtMode); except KeyboardInterrupt: raise; except: reporter.errorXcpt(cFrames = 9); rc2 = False; if rc2 is True: # Do the testing. try: rc2 = fnCallback(oVM, oTestVm); except KeyboardInterrupt: raise; except: reporter.errorXcpt(cFrames = 9); rc2 = False; if rc2 is False: reporter.maybeErr(reporter.testErrorCount() == 0, 'fnCallback failed'); elif rc2 is False: reporter.log('getReconfiguredVm failed'); if rc2 is False: fRc = False; cTests = cTests + (rc2 is not None); if sParavirtMode is not None: reporter.testDone(fSkipped = (rc2 is None)); reporter.testDone(fSkipped = cTests == cStartTests); reporter.testDone(fSkipped = cTests == 0); _, cErrors = reporter.testDone(); if cErrors > 0: fRc = False; return fRc;
def startVkatOnGuest(self, oTestVm, oSession, oTxsSession, sTag): """ Starts VKAT on the guest (running in background). """ sPathTemp = self.getGuestTempDir(oTestVm) sPathAudioOut = oTestVm.pathJoin(sPathTemp, 'vkat-guest-out') sPathAudioTemp = oTestVm.pathJoin(sPathTemp, 'vkat-guest-temp') reporter.log('Guest audio test temp path is \"%s\"' % (sPathAudioOut)) reporter.log('Guest audio test output path is \"%s\"' % (sPathAudioTemp)) reporter.log('Guest audio test tag is \"%s\"' % (sTag)) fRc, sVkatExe = self.locateGstBinary(oSession, oTxsSession, self.asGstVkatPaths) if fRc: reporter.log('Using VKAT on guest at \"%s\"' % (sVkatExe)) sCmd = '' asArgs = [] asArgsVkat = [ sVkatExe, 'test', '--mode', 'guest', '--probe-backends', \ '--tempdir', sPathAudioTemp, '--outdir', sPathAudioOut, \ '--tag', sTag ] asArgs.extend(asArgsVkat) for _ in range(1, reporter.getVerbosity() ): # Verbosity always is initialized at 1. asArgs.extend(['-v']) # Needed for NATed VMs. asArgs.extend(['--tcp-connect-addr', '10.0.2.2']) if oTestVm.sKind in 'Oracle_64': # # Some Linux distros have a bug / are configured (?) so that processes started by init system # cannot access the PulseAudio server ("Connection refused"), for example OL 8.1. # # To work around this, we use the (hopefully) configured user "vbox" and run it under its behalf, # as the Test Execution Service (TxS) currently does not implement impersonation yet. # asSU = ['/bin/su', '/usr/bin/su', '/usr/local/bin/su'] fRc, sCmd = self.locateGstBinary(oSession, oTxsSession, asSU) if fRc: sCmdArgs = '' for sArg in asArgs: sCmdArgs += sArg + " " asArgs = [sCmd, oTestVm.getTestUser(), '-c', sCmdArgs] else: reporter.log( 'Unable to find SU on guest, falling back to regular starting ...' ) if not sCmd: # Just start it with the same privileges as TxS. sCmd = sVkatExe reporter.log2('startVkatOnGuest: sCmd=%s' % (sCmd, )) reporter.log2('startVkatOnGuest: asArgs=%s' % (asArgs, )) # # Add own environment stuff. # asEnv = [] # Write the log file to some deterministic place so TxS can retrieve it later. sVkatLogFile = 'VKAT_RELEASE_LOG_DEST=file=' + self.getGstVkatLogFilePath( oTestVm) asEnv.extend([sVkatLogFile]) # # Execute asynchronously on the guest. # fRc = oTxsSession.asyncExec(sCmd, asArgs, asEnv, cMsTimeout=15 * 60 * 1000, sPrefix='[VKAT Guest] ') if fRc: self.addTask(oTxsSession) if not fRc: reporter.error('VKAT on guest returned exit code error %d' % (self.getLastRcFromTxs(oTxsSession))) else: reporter.error('VKAT on guest not found') return fRc
def actionExecute(self, oTestDrv, fnCallback): # pylint: disable=R0914 """ For base.TestDriver.actionExecute. Calls the callback function for each of the VMs and basic configuration variations (virt-mode and cpu count). Returns True if all fnCallback calls returned True, otherwise False. The callback can return True, False or None. The latter is for when the test is skipped. (True is for success, False is for failure.) """ self._removeUnsupportedVirtModes(oTestDrv) cMaxCpus = oTestDrv.getHostCpuCount() # # The test loop. # fRc = True for oTestVm in self.aoTestVms: if oTestVm.fSkip and self.fIgnoreSkippedVm: reporter.log2('Ignoring VM %s (fSkip = True).' % (oTestVm.sVmName, )) continue reporter.testStart(oTestVm.sVmName) if oTestVm.fSkip: reporter.testDone(fSkipped=True) continue # Intersect the supported modes and the ones being testing. asVirtModesSup = [ sMode for sMode in oTestVm.asVirtModesSup if sMode in self.asVirtModes ] # Ditto for CPUs. acCpusSup = [ cCpus for cCpus in oTestVm.acCpusSup if cCpus in self.acCpus ] # Ditto for paravirtualization modes, except if not specified we got a less obvious default. if self.asParavirtModes is not None and oTestDrv.fpApiVer >= 5.0: asParavirtModes = [ sPvMode for sPvMode in oTestVm.asParavirtModesSup if sPvMode in self.asParavirtModes ] assert None not in asParavirtModes elif oTestDrv.fpApiVer >= 5.0: asParavirtModes = (oTestVm.asParavirtModesSup[0], ) assert asParavirtModes[0] is not None else: asParavirtModes = (None, ) for cCpus in acCpusSup: if cCpus == 1: reporter.testStart('1 cpu') else: reporter.testStart('%u cpus' % (cCpus)) if cCpus > cMaxCpus: reporter.testDone(fSkipped=True) continue cTests = 0 for sVirtMode in asVirtModesSup: if sVirtMode == 'raw' and cCpus > 1: continue reporter.testStart('%s' % (g_dsVirtModeDescs[sVirtMode], )) cStartTests = cTests for sParavirtMode in asParavirtModes: if sParavirtMode is not None: assert oTestDrv.fpApiVer >= 5.0 reporter.testStart('%s' % (sParavirtMode, )) # Reconfigure the VM. try: (rc2, oVM) = oTestVm.getReconfiguredVm( oTestDrv, cCpus, sVirtMode, sParavirtMode=sParavirtMode) except KeyboardInterrupt: raise except: reporter.errorXcpt(cFrames=9) rc2 = False if rc2 is True: # Do the testing. try: rc2 = fnCallback(oVM, oTestVm) except KeyboardInterrupt: raise except: reporter.errorXcpt(cFrames=9) rc2 = False if rc2 is False: reporter.maybeErr( reporter.testErrorCount() == 0, 'fnCallback failed') elif rc2 is False: reporter.log('getReconfiguredVm failed') if rc2 is False: fRc = False cTests = cTests + (rc2 is not None) if sParavirtMode is not None: reporter.testDone(fSkipped=(rc2 is None)) reporter.testDone(fSkipped=cTests == cStartTests) reporter.testDone(fSkipped=cTests == 0) _, cErrors = reporter.testDone() if cErrors > 0: fRc = False return fRc
def actionExecute(self, oTestDrv, fnCallback): # pylint: disable=R0914 """ For base.TestDriver.actionExecute. Calls the callback function for each of the VMs and basic configuration variations (virt-mode and cpu count). Returns True if all fnCallback calls returned True, otherwise False. The callback can return True, False or None. The latter is for when the test is skipped. (True is for success, False is for failure.) """ self._removeUnsupportedVirtModes(oTestDrv); cMaxCpus = oTestDrv.getHostCpuCount(); # # The test loop. # fRc = True; for oTestVm in self.aoTestVms: if oTestVm.fSkip and self.fIgnoreSkippedVm: reporter.log2('Ignoring VM %s (fSkip = True).' % (oTestVm.sVmName,)); continue; reporter.testStart(oTestVm.sVmName); if oTestVm.fSkip: reporter.testDone(fSkipped = True); continue; # Intersect the supported modes and the ones being testing. asVirtModesSup = [sMode for sMode in oTestVm.asVirtModesSup if sMode in self.asVirtModes]; # Ditto for CPUs. acCpusSup = [cCpus for cCpus in oTestVm.acCpusSup if cCpus in self.acCpus]; for cCpus in acCpusSup: if cCpus == 1: reporter.testStart('1 cpu'); else: reporter.testStart('%u cpus' % (cCpus)); if cCpus > cMaxCpus: reporter.testDone(fSkipped = True); continue; cTests = 0; for sVirtMode in asVirtModesSup: if sVirtMode == 'raw' and cCpus > 1: continue; for sParavirtMode in oTestVm.asParavirtModes: reporter.testStart("%s/%s" % (g_dsVirtModeDescs[sVirtMode], sParavirtMode if sParavirtMode is not None else "[paravirtualisation provider not set]")); # pylint: disable=C0301 # Reconfigure the VM. try: (rc2, oVM) = oTestVm.getReconfiguredVm(oTestDrv, cCpus, sVirtMode, sParavirtMode=sParavirtMode); except KeyboardInterrupt: raise; except: reporter.errorXcpt(cFrames = 9); rc2 = False; if rc2 is True: try: rc2 = fnCallback(oVM, oTestVm); except KeyboardInterrupt: raise; except: reporter.errorXcpt(cFrames = 9); rc2 = False; if rc2 is False: reporter.maybeErr(reporter.testErrorCount() == 0, 'fnCallback failed'); elif rc2 is False: reporter.log('getReconfiguredVm failed'); if rc2 is False: fRc = False; cTests = cTests + (rc2 is not None); reporter.testDone(fSkipped = (rc2 is None)); reporter.testDone(fSkipped = cTests == 0); _, cErrors = reporter.testDone(); if cErrors > 0: fRc = False; return fRc;