def get_bitlocker_drive_status(drive: str) -> Union[str, None]: """ Returns a string that describes the current bitlocker status for a drive """ exit_code, result = command_runner('where manage-bde', valid_exit_codes=[0, 1, 4294967295]) if exit_code != 0: logger.debug('Bitlocker management tool not installed.') return None exit_code, result = command_runner('manage-bde {} -status'.format(drive), encoding='cp437') if exit_code == 0: return result # -2147217405 (cmd) or 2147749891 (Python) == (0x80041003) = Permission denied if exit_code in [-2147217405, 2147749891]: logger.warning( 'Don\'t have permission to get bitlocker drive status for {}.'. format(drive)) # -1 is returned in cmd on drives without bitlocker suppprt (or as unsigned 2^32-1 = 4294967295 in Python)# elif exit_code in [-1, 4294967295]: logger.debug( 'Drive {} does not seem to have bitlocker protectors yet.'.format( drive)) else: logger.warning( 'Cannot get bitlocker drive status for {}.'.format(drive)) logger.warning('{}'.format(result)) return None
def get_bitlocker_drive_status(drive: str) -> Union[str, None]: """ Returns a string that describes the current bitlocker status for a drive """ if not check_bitlocker_management_tools(): return None exit_code, result = command_runner("manage-bde {} -status".format(drive), encoding="cp437") if exit_code == 0: return result # -2147217405 (cmd) or 2147749891 (Python) == (0x80041003) = Permission denied if exit_code in [-2147217405, 2147749891]: logger.warning( "Don't have permission to get bitlocker drive status for {}.". format(drive)) # -1 is returned in cmd on drives without bitlocker suppprt (or as unsigned 2^32-1 = 4294967295 in Python) elif exit_code in [-1, 4294967295]: logger.debug( "Drive {} does not seem to have bitlocker protectors yet.".format( drive)) else: logger.warning( "Cannot get bitlocker drive status for {}.".format(drive)) logger.warning("{}".format(result)) return None
def get_bitlocker_protection_key(drive: str) -> Union[str, None]: """ Returns a string containing the protection key of a bitlocked drive """ if not check_bitlocker_management_tools(): return None # utf-8 produces less good results on latin alphabets, but better results on logographic / syllabic alphabets exit_code, result = command_runner( "manage-bde -protectors {} -get".format(drive), encoding="cp437") if exit_code == 0: return result # -2147217405 (cmd) or 2147749891 (Python) == (0x80041003) = Permission denied if exit_code in [-2147217405, 2147749891]: logger.warning( "Don't have permission to get bitlocker drive protectors for {}.". format(drive)) # -2147024809 (cmd) or 2147942487 (Python) == (0x80070057) = Incorrect parameter # This will happen on drives that aren't supposed to have bitlocker (FAT32, network drives, subst drives...) elif exit_code in [-2147024809, 2147942487]: logger.info( "Drive {} is not supposed to have a bitlocker protecter.".format( drive)) # -1 is returned in cmd on valid drive without protectors (or as unsigned 2^32-1 = 4294967295 in Python) elif exit_code in [-1, 4294967295]: logger.debug( "Drive {} does not seem to have bitlocker protectors yet.".format( drive)) # -2147024809 is returned on invalid drives (eg network drives, inexisting drives) else: logger.warning( "Could not get bitlocker protector for drive {}: {}".format( drive, result)) return None
def os_traceroute(address): """ Launches actuel traceroute binary :param address: (str) address :return: (str) raw traceroute output """ if address: if os.name == 'nt': executable = 'tracert' # Ugly hack se we get actual characters encoding right from cmd.exe # Also encodes "well" cp850 using cp437 parameter encoding = 'cp437' else: executable = 'traceroute' encoding = 'utf-8' command = '{0} {1}'.format(executable, address) exit_code, output = command_runner(command, shell=True, encoding=encoding) if exit_code != 0: logger.error( 'Traceroute to address: "{0}" failed with exit code {1}. Command output:' .format(address, exit_code)) logger.error(output) return exit_code, output return 1, 'Bogus address given.'
def run_script(self, script, *args, **kwargs): """ Accepts subprocess.check_output arguments """ if self.powershell_interpreter is None: return False timeout = kwargs.pop("timeout", 300) valid_exit_codes = kwargs.pop("valid_exit_codes", [0]) # Welcome in Powershell hell where running a script with -Command argument returns exit # codes 0 or 1 whereas as running with -File argument returns your script exit code command = ( self.powershell_interpreter + " -executionPolicy Bypass -NonInteractive -NoLogo -NoProfile -File " + script + (" " if len(args) > 0 else " ") + " ".join('"' + arg + '"' for arg in args)) exit_code, output = command_runner(command, timeout=timeout, valid_exit_codes=valid_exit_codes, encoding="unicode_escape", **kwargs) return exit_code, output
def sign(self, executable, bitness: int): if bitness == 32: signtool = os.environ.get("SIGNTOOL_X32", self.detect_signtool("x86")) elif bitness == 64: signtool = os.environ.get("SIGNTOOL_X64", self.detect_signtool("x64")) else: raise ValueError("Bogus bitness.") if not os.path.exists(signtool): raise EnvironmentError("Could not find valid signtool.exe") result, output = command_runner( '"%s" sign /tr %s /td sha256 /fd sha256 /f "%s" /p %s "%s"' % ( signtool, self.authority_timestamp_url, self.certificate, self.pkcs12_password, executable, ) ) if result == 0: return True else: raise AttributeError( "Cannot sign executable file [%s] with signtool.exe. Command output\n%s" % (executable, output) )
def get_disks(): """ Lists all disks found by smartctl and tries to identify disk_type: - ssd, spinning, nvme or unknwown where unknown are disks smartctl cannot handle :return: (list) list of dictionaries with keys: name, info_name, type, protocol, disk_type """ disk_list = [] result, output = command_runner('"smartctl" --scan-open --json') if result != 0: return None disks = json.loads(output) for disk in disks['devices']: # Before adding disks to disk list, we need to check whether the SMART attributes can be read # This is specially usefull to filter raid member drives result, output = command_runner( f'"smartctl" --info --json {disk["name"]}', valid_exit_codes=[0, 1], timeout=60) if result != 0: # Don't add drives that can't be opened continue # disk['type'] is already correct for nvme disks disk_detail = json.loads(output) try: # set disk_type for nvme disks if disk['type'] == 'nvme': disk['disk_type'] = 'nvme' # Determnie if disk is spinning elif disk_detail['rotation_rate'] == 'Solid State Device': disk['disk_type'] = 'ssd' elif int(disk_detail['rotation_rate']) != 0: disk['disk_type'] = 'spinning' else: disk['disk_type'] = 'unknown' except (TypeError, KeyError): disk['disk_type'] = 'unknown' logger.debug('Trace', exc_info=True) disk_list.append(disk) return disk_list
def stdPrecond(devName): logging.info('Starting preconditioning') exit_code, output = command_runner('fio --name=precondition \ --filename=' + devName + ' --iodepth=32 \ --numjobs=1 --bs=128k --ioengine=libaio \ --rw=write --group_reporting --direct=1 \ --thread --refill_buffers --loops=2', timeout=14400)
def unix_service_status(service): # type: (str) -> bool """ Handle unix service using standard lsb commands Valid exit code are 0 and 3 (because of systemctl using a service redirect) """ service_status, _ = command_runner('service "{}" status'.format(service), timeout=15) if service_status in [0, 3]: return True return False
def hide_windows_file( file, # type: str hidden=True, # type: bool ): # type: (...) -> bool """ Hides / unhides a file under windows by using attrib command """ result, _ = command_runner('attrib %sh "%s"' % ("+" if hidden else "-", file)) if result == 0: return True return False
def check_bitlocker_management_tools() -> bool: """ Checks whether bitlocker management tools are insqtalled """ exit_code, result = command_runner("where manage-bde", valid_exit_codes=[0, 1, 4294967295]) if exit_code != 0: logger.debug( "Bitlocker management tools not installed. This might also happen when 32 bit Python " "is run on 64 bit Windows.") logger.debug(result) return False return True
def get_smart_state(disk_index): """ Bit 0: Command line did not parse. Bit 1: Device open failed, device did not return an IDENTIFY DEVICE structure, or device is in a low-power mode (see '-n' option above). Bit 2: Some SMART or other ATA command to the disk failed, or there was a checksum error in a SMART data structure (see '-b' option above). Bit 3: SMART status check returned "DISK FAILING". Bit 4: We found prefail Attributes <= threshold. Bit 5: SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past. Bit 6: The device error log contains records of errors. Bit 7: The device self-test log contains records of errors. [ATA only] Failed self-tests outdated by a newer successful extended self-test are ignored. return: (bool): True if state is OK, False if state is BAD, None if undefined """ exitcode, _ = command_runner('smartctl -q silent /dev/pd%s' % str(disk_index), encoding='unicode_escape') if exitcode is not None: if exitcode >> 0 & 1: smartstate = None # Command line dit not parse elif exitcode >> 1 & 1: smartstate = None # Device open failed elif exitcode >> 2 & 1: smartstate = True # Some smart commands failed (typically happens on RAID members) elif exitcode >> 3 & 1: smartstate = False # DISK FAILING elif exitcode >> 4 & 1: smartstate = False # PREFAIL ATTRIBUTES FAILING elif exitcode >> 5 & 1: smartstate = False # PREVIOUS PREFAIL ATTRIBUTES FAILING elif exitcode >> 6 & 1: smartstate = False # DEVICE ERROR LOG CONTAINS RECORDS elif exitcode >> 7 & 1: smartstate = False # DEVICE SELF-TEST LOG CONTAINS ERRORS else: smartstate = True return smartstate return None
def get_smart_info(disk_name, json_output=False): """ Get smart disk info :param disk_name: (str) disk name that smartctl can handle (ie /dev/sda, /dev/pd0, /dev/csmi1,0 ... :param json_output: (bool) return as json or string :return: (str) smartctl standard output """ result, output = command_runner('"smartctl" --all {0} {1}'.format( '--json' if json_output else '', disk_name)) # If commandline didn't parse or device cannot be opened if result >> 0 & 1 and result >> 1 & 1: return None return output
def devicePurge(devType, devName): logging.info('Purging device ' + devName) if devType == 'sata': if (not isProg('hdparm')): sys.exit('hdparm not found!') exit_code, output = command_runner( 'hdparm --user-master u --security-set-pass PasSWorD ' + devName, shell=True, live_output=True) exit_code, output = command_runner( 'hdparm --user-master u --security-erase PasSWorD ' + devName, shell=True, live_output=True) elif devType == 'sas': if (not isProg('sg_format')): sys.exit('sg_format not found! Install sg3_utils package') exit_code, output = command_runner('sg_format --format ' + devName, shell=True, live_output=True) elif devType == 'nvme': if (not isProg('nvme')): sys.exit('nvme not found! Install nvme-cli package') exit_code, output = command_runner('nvme format ' + devName, shell=True, live_output=True) else: exit_code, output = command_runner('dd bs=128k if=/dev/zero of=' + devName, shell=True, live_output=True) logging.info('Purging done (zeroing with dd)')
def unix_service_action(service, action): # type: (str, str) -> bool """ Using lsb service X command on Unix variants, hopefully the most portable """ if action in ["start", "stop"]: result, output = command_runner('service "{}" {}'.format( service, action)) # exit codes are (for systemd) # 0 = runs # 3 = dead # 4 = does not exist if result == 0: return True logger.error("Could not {} service, code [{}].".format(action, result)) logger.error("Output:\n{}".format(output)) return False
def _ping_host(target, retries): if os.name == "nt": # -4/-6: IPType # -n ...: number of packets to send # -f: do not fragment # -l ...: packet size to send # -w ...: timeout (ms) command = "ping -n 1 -l {} -w {}".format(mtu_encapsulated, windows_timeout) # IPv6 does not allow to set fragmentation if do_not_fragment and ip_type != 6: command += " -f" encoding = "cp437" else: # -4/-6: IPType # -c ...: number of packets to send # -M do: do not fragment # -s ...: packet size to send # -i ...: interval (s), only root can set less than .2 seconds # -W ...: timeous (s) command = "ping -c 1 -s {} -W {} -i {}".format( mtu_encapsulated, timeout, interval) # IPv6 does not allow to set fragmentation if do_not_fragment and ip_type != 6: command += " -M do" encoding = "utf-8" # Add ip_type if specified if ip_type: command += " -{}".format(ip_type) command += " {}".format(target) result = False while retries > 0 and not result: exit_code, output = command_runner(command, timeout=command_timeout, encoding=encoding) if exit_code == 0: return True retries -= 1 return False
def run_command(self, command, **kwargs): """ Accepts subprocess.check_output arguments Accepts command_runner arguments like timeout, encoding and valid_exit_codes """ if self.powershell_interpreter is None: return False timeout = kwargs.pop("timeout", 300) valid_exit_codes = kwargs.pop("valid_exit_codes", [0]) # Do not add -NoProfile so we don't end up in a path we're not supposed to command = self.powershell_interpreter + " -NonInteractive -NoLogo %s" % command exit_code, output = command_runner(command, timeout=timeout, valid_exit_codes=valid_exit_codes, encoding="unicode_escape", **kwargs) return exit_code, output
def elevate(callable_function, *args, **kwargs): """ UAC elevation / sudo code working for CPython, Nuitka >= 0.6.2, PyInstaller, PyExe, CxFreeze """ if is_admin(): # Don't bother if we already got mighty admin privileges callable_function(*args, **kwargs) else: runner, arguments = _check_environment() # Windows runner if os.name == "nt": # Re-run the script with admin rights # Join arguments and double quote each argument in order to prevent space separation arguments = " ".join('"' + arg + '"' for arg in arguments) try: exit_code = _windows_runner(runner, arguments) logger.debug('Child exited with code "{}"'.format(exit_code)) sys.exit(exit_code) except Exception as exc: logger.info(exc) logger.debug("Trace:", exc_info=True) sys.exit(255) # Linux runner and hopefully Unixes else: # Re-run the script but with sudo sudo_path = get_absolute_path("sudo") if sudo_path is None: logger.error( "Cannot find sudo executable. Trying to run without privileges elevation." ) callable_function(*args, **kwargs) else: command = ["sudo", runner] + arguments # Optionnaly might also pass a stdout PIPE to command_runner so we get live output exit_code, output = command_runner(command, shell=False, timeout=None) logger.info("Child output: {}".format(output)) sys.exit(exit_code)
def get_absolute_path(executable): # type: (str) -> str """ Search for full executable path in preferred shell paths This allows avoiding usage of shell=True with subprocess """ executable_path = None exit_code, output = command_runner(["type", "-p", "sudo"]) if exit_code == 0: # Remove ending '\n'' character output = output.strip() if os.path.isfile(output): return output if os.name == "nt": split_char = ";" else: split_char = ":" for path in os.environ.get("PATH", "").split(split_char): if os.path.isfile(os.path.join(path, executable)): executable_path = os.path.join(path, executable) return executable_path
def elevate(fn, *args, **kwargs): if is_admin(): fn(*args, **kwargs) else: # UAC elevation / sudo code working for CPython, Nuitka >= 0.6.2, PyInstaller, PyExe, CxFreeze # Regardless of the runner (CPython, Nuitka or frozen CPython), sys.argv[0] is the relative path to script, # sys.argv[1] are the arguments # The only exception being CPython on Windows where sys.argv[0] contains absolute path to script # Regarless of OS, sys.executable will contain full path to python binary for CPython and Nuitka, # and full path to frozen executable on frozen CPython # Recapitulative table create with # (CentOS 7x64 / Python 3.4 / Nuitka 0.6.1 / PyInstaller 3.4) and # (Windows 10 x64 / Python 3.7x32 / Nuitka 0.6.2.10 / PyInstaller 3.4) # -------------------------------------------------------------------------------------------------------------- # | OS | Variable | CPython | Nuitka | PyInstaller | # |------------------------------------------------------------------------------------------------------------| # | Lin | argv | ['./script.py', '-h'] | ['./test', '-h'] | ['./test.py', -h'] | # | Lin | sys.executable | /usr/bin/python3.4 | /usr/bin/python3.4 | /absolute/path/to/test | # | Win | argv | ['C:\\Python\\test.py', '-h'] | ['test', '-h'] | ['test', '-h'] | # | Win | sys.executable | C:\Python\python.exe | C:\Python\Python.exe | C:\absolute\path\to\test.exe | # -------------------------------------------------------------------------------------------------------------- # Nuitka 0.6.2 and newer define builtin __nuitka_binary_dir # Nuitka does not set the frozen attribute on sys # Nuitka < 0.6.2 can be detected in sloppy ways, ie if not sys.argv[0].endswith('.py') or len(sys.path) < 3 # Let's assume this will only be compiled with newer nuitka, and remove sloppy detections try: # Actual if statement not needed, but keeps code inspectors more happy if __nuitka_binary_dir or '__compiled__' in globals() is not None: is_nuitka_compiled = True except NameError: is_nuitka_compiled = False if is_nuitka_compiled: # On nuitka, sys.executable is the python binary, even if it does not exist in standalone, # so we need to fill runner with sys.argv[0] absolute path runner = os.path.abspath(sys.argv[0]) arguments = sys.argv[1:] # current_dir = os.path.dirname(runner) logger.debug('Running elevator as Nuitka with runner [%s]' % runner) logger.debug('Arguments are %s' % arguments) # If a freezer is used (PyInstaller, cx_freeze, py2exe) elif getattr(sys, "frozen", False): runner = os.path.abspath(sys.executable) arguments = sys.argv[1:] # current_dir = os.path.dirname(runner) logger.debug('Running elevator as Frozen with runner [%s]' % runner) logger.debug('Arguments are %s' % arguments) # If standard interpreter CPython is used else: runner = os.path.abspath(sys.executable) arguments = [os.path.abspath(sys.argv[0])] + sys.argv[1:] # current_dir = os.path.abspath(sys.argv[0]) logger.debug('Running elevator as CPython with runner [%s]' % runner) logger.debug('Arguments are %s' % arguments) if os.name == 'nt': # Re-run the function with admin rights # Join arguments and double quote each argument in order to prevent space separation arguments = ' '.join('"' + arg + '"' for arg in arguments) try: # Old method using ctypes which does not wait for executable to exit nor deos get exit code # See https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutew # int 0 means SH_HIDE window, 1 is SW_SHOWNORMAL # needs the following imports # import ctypes # ctypes.windll.shell32.ShellExecuteW(None, 'runas', runner, arguments, None, 0) # Method with exit code that waits for executable to exit, needs the following imports # import win32event # monitor process # import win32process # monitor process # from win32com.shell.shell import ShellExecuteEx # from win32com.shell import shellcon childProcess = ShellExecuteEx( nShow=0, fMask=shellcon.SEE_MASK_NOCLOSEPROCESS, lpVerb='runas', lpFile=runner, lpParameters=arguments) procHandle = childProcess['hProcess'] win32event.WaitForSingleObject(procHandle, win32event.INFINITE) exit_code = win32process.GetExitCodeProcess(procHandle) logger.debug('Child exited with code: %s' % exit_code) sys.exit(exit_code) except Exception as e: logger.info(e) logger.debug('Trace:', exc_info=True) sys.exit(255) # Linux runner and hopefully Unixes else: # Search for sudo executable in order to avoid using shell=True with subprocess sudo_path = None for path in os.environ.get('PATH', ''): if os.path.isfile(os.path.join(path, 'sudo')): sudo_path = os.path.join(path, 'sudo') if sudo_path is None: logger.error( 'Cannot find sudo executable. Cannot elevate privileges. Trying to run wihtout.' ) fn(*args, **kwargs) else: command = 'sudo "%s"%s%s' % (runner, (' ' if len(arguments) > 0 else ''), ' '.join( '"%s"' % argument for argument in arguments)) exit_code, output = command_runner(command, shell=False, timeout=None) logger.info('Child output: %s' % output) sys.exit(exit_code)
if not args.SkipErase: ptsu.devicePurge(str(args.DevType), str(args.Device)) logging.info('Purge done') # There is no preconditioning logging.info('Starting test: ' + TestName) logging.info('Starting AG1') for TestPass in tqdm(range(1, SeqRounds+1)): JSONFileName = ('fio_ag1_pass='******'.json') exit_code, output = command_runner('fio --runtime=' + str(RoundTime) + ' --filename=' + str(args.Device) + ' --ioengine=' + str(args.IOEngine) + ' --numjobs=' + str(TC) + ' --iodepth=' + str(OIO) + ' --rw=write --bs=1m' ' --output=' + TestName + '/results/' + JSONFileName + ' ' + ' '.join(FioArgs), timeout=RoundTime + 5) logging.info('AG1: round ' + str(TestPass) + ' of ' + str(SeqRounds) + ' complete') logging.info('Starting AG2') for TestPass in tqdm(range(1, RndRounds+1)): JSONFileName = ('fio_ag2_pass='******'.json') exit_code, output = command_runner('fio --runtime=' + str(RoundTime) + ' --filename=' + str(args.Device) + ' --ioengine=' + str(args.IOEngine) + ' --numjobs=' + str(TC) + ' --iodepth=' + str(OIO) + ' --rw=randwrite --bs=8k'
ptsu.prepResultsDir(TestName) if not args.SkipErase: ptsu.devicePurge(str(args.DevType), str(args.Device)) logging.info('Purge done') # There is no preconditioning # 10.2.2 logging.info('Starting test: ' + TestName) for TestPass in tqdm(range(1, WSATRounds+1)): JSONFileName = ('fio_pass='******'.json') exit_code, output = command_runner('fio --runtime=' + str(RoundTime) + ' --filename=' + str(args.Device) + ' --ioengine=' + str(args.IOEngine) + ' --numjobs=' + str(TC) + ' --iodepth=' + str(OIO) + ' --output=' + TestName + '/results/' + JSONFileName + ' ' + ' '.join(FioArgs), timeout=RoundTime + 5) logging.info('Round ' + str(TestPass) + ' of ' + str(WSATRounds) + ' complete') # 10.2.4 logging.info('Starting RTH test') JSONFileName = ('fio_rth.json') exit_code, output = command_runner('fio --runtime=' + str(RTHTime) + ' --filename=' + str(args.Device) + ' --ioengine=' + str(args.IOEngine) + ' --numjobs=' + str(TC) + ' --iodepth=' + str(OIO) + ' --write_lat_log=' + TestName + '/results/test04' +
logging.info('Purge done') if not args.SkipPrecond: ptsu.stdPrecond(str(args.Device)) logging.info('Preconditioning done') logging.info('Starting test: ' + TestName) for TestPass in tqdm(range(1, int(args.MaxRounds) + 1)): for RWMix in RWMixes: for BS in BlockSizes: JSONFileName = ('fio_pass='******'_rw=' + str(RWMix) + '_bs=' + str(BS) + '.json') exit_code, output = command_runner( 'fio --runtime=' + str(RoundTime) + ' --filename=' + str(args.Device) + ' --bs=' + str(BS) + ' --ioengine=' + str(args.IOEngine) + ' --rwmixread=' + str(RWMix) + ' --output=' + TestName + '/results/' + JSONFileName + ' ' + ' '.join(FioArgs), timeout=RoundTime + 5) logging.info('Round ' + str(TestPass) + ' of ' + str(args.MaxRounds) + ' complete') # 3.3 with added 100%-read test logging.info('Starting 20 min test') for RWMix in [100, 0]: JSONFileName = ('fio_20min_rw=' + str(RWMix) + '.json') exit_code, output = command_runner( 'fio --runtime=1200 --filename=' + str(args.Device) + ' --bs=4k --ioengine=' + str(args.IOEngine) + ' --rwmixread=' + str(RWMix) + ' --write_lat_log=' + TestName + '/results/test03_' + str(RWMix) + ' --log_avg_msec=0.2 --disable_slat=1 \
ptsu.prepResultsDir(TestName) if not args.SkipErase: ptsu.devicePurge(str(args.DevType), str(args.Device)) logging.info('Purge done') if not args.SkipPrecond: # Special preconditioning print('Starting preconditioning') for TestPass in tqdm(range(1, PrecondRounds + 1)): JSONFileName = ('fio_pc_pass='******'.json') exit_code, output = command_runner( 'fio --runtime=' + str(RoundTime) + ' --filename=' + str(args.Device) + ' --ioengine=' + str(args.IOEngine) + ' --numjobs=32 --iodepth=32 \ --rw=randwrite' + ' --output=' + TestName + '/results/' + JSONFileName + ' ' + ' '.join(FioArgs), timeout=RoundTime + 5) logging.info('Preconditioning round ' + str(TestPass) + ' of ' + str(PrecondRounds) + ' complete') for HistName, TC, QD in zip(HistNames, TCSet, QDSet): print('Starting test: ' + HistName) JSONFileName = ('fio_' + HistName + '.json') exit_code, output = command_runner( 'fio --runtime=600 \ --filename=' + str(args.Device) + ' --ioengine=' + str(args.IOEngine) + ' --numjobs=' + str(TC) + ' --iodepth=' + str(QD) + ' --rw=randrw --rwmixread=60' + ' --write_lat_log=' + TestName + '/results/test07_' + HistName + '_RTH \
ptsu.prepResultsDir(TestName) if not args.SkipErase: ptsu.devicePurge(str(args.DevType), str(args.Device)) logging.info('Purge done') if not args.SkipPrecond: # Special preconditioning print('Starting preconditioning') for TestPass in tqdm(range(1, PrecondRounds + 1)): JSONFileName = ('fio_pc_pass='******'.json') exit_code, output = command_runner( 'fio --runtime=' + str(RoundTime) + ' --filename=' + str(args.Device) + ' --ioengine=' + str(args.IOEngine) + ' --numjobs=32 --iodepth=32 \ --rw=randwrite' + ' --output=' + TestName + '/results/' + JSONFileName + ' ' + ' '.join(FioArgs), timeout=RoundTime + 5) logging.info('Preconditioning round ' + str(TestPass) + ' of ' + str(PrecondRounds) + ' complete') print('Starting main test') logging.info('Starting test: ' + TestName) for TestPass in tqdm(range(1, args.MaxRounds + 1)): for IRPWPass in range(1, IRPWRounds + 1): JSONFileNamePW = ('fio_pw_pass='******'_test_pass='******'.json') exit_code, output = command_runner( 'fio --runtime=' + str(RoundTime) + ' --filename=' + str(args.Device) + ' --ioengine=' + str(args.IOEngine) +
BS = '128k' # 2.2 128K WIPC for 128K test, 1M WIPC for 1M test if not args.SkipPrecond: ptsu.stdPrecond(str(args.Device)) logging.info(BS + ' preconditioning done') logging.info('Starting test: ' + TestName + ' (' + BS + ')') for TestPass in tqdm(range(1, int(args.MaxRounds)+1)): for RWMix in RWMixes: JSONFileName = ('fio_pass='******'_rw=' + str(RWMix) + '_bs=' + str(BS) + '.json') exit_code, output = command_runner('fio --runtime=' + str(RoundTime) + ' --filename=' + str(args.Device) + ' --iodepth=' + str(OIO) + ' --bs=' + BS + ' --ioengine=' + str(args.IOEngine) + ' --rwmixread=' + str(RWMix) + ' --output=' + TestName + '/results/' + JSONFileName + ' ' + ' '.join(FioArgs), timeout=RoundTime + 5) logging.info(BS + ' test, round ' + str(TestPass) + ' of ' + str(args.MaxRounds) + ' complete') BS = '1m' logging.info('Starting preconditioning' + ' (' + BS + ')') exit_code, output = command_runner('fio --name=precondition1M \ --filename=' + str(args.Device) + ' --iodepth=32 \ --numjobs=1 --bs=' + BS + ' --ioengine=libaio \ --rw=write --group_reporting --direct=1 \ --thread --refill_buffers --loops=2', timeout=14400) logging.info(BS + ' preconditioning done')