def sendmail(self, msg): if self.mailto is None or self.mailto == '': return me = "*****@*****.**" you = re.split(r'[;,\s]\s*', self.mailto) # Create message container - the correct MIME type is multipart/alternative. mime = MIMEMultipart('alternative') mime['Subject'] = self.mail_subject mime['From'] = me mime['To'] = self.mailto htmlMsg = "<html> <pre> " + msg + "</pre> </html>" part1 = MIMEText(msg, 'plain') part2 = MIMEText(htmlMsg, 'html') mime.attach(part1) mime.attach(part2) try: autopsy_logger.info("Sending mail to: " + self.mailto) server = smtplib.SMTP('localhost') server.set_debuglevel(0) server.sendmail(me, you, mime.as_string()) server.quit() except socket.error as e: autopsy_logger.error( "Couldn't send mail, check your local SMTP client: " + str(e))
def kill_process(self, procSubString, force=False, signal="9", ignore=None): """ Kills a process matching given substring. Kills only if the match returns one process (To limit not to kill wrong process by mistake). Use force to kill all matching processes. Use this with caution Returns True if successful, False otherwise :param ignore: :param signal: :param force: :param procSubString: """ if ignore is None: ignore = [] proc_id = self.get_pid(procSubString, ignore=ignore) if (not force) and len(proc_id) > 1: autopsy_logger.error("Multiple processes detected for string: '" + procSubString + "', can't kill, Use force=True to kill multiple process") return False if len(proc_id) == 0: autopsy_logger.warning("No processes found with string: '" + procSubString + "', just ignoring") return False self.execute("sudo kill -{0} {1} ".format(signal, str(' '.join(proc_id)))) if self.ssh_client.exit_status_last_command != 0: autopsy_logger.error("Error killing the process") return False return True
def simulate_nw_down(self, interface=None): """ Node should have iptables to use this :return: """ self.clear_ip_tables() local_ip = self.ssh_client.handle.get_transport().sock.getsockname()[0] self.ssh_client.execute("iptables --insert INPUT --source {0}/32 --jump ACCEPT".format(local_ip), sudo=True) if self.ssh_client.exit_status_last_command != 0: autopsy_logger.error("Couldn't simulate nw down, probably 'iptables' cmd not present in this node") return False self.ssh_client.execute("iptables --append INPUT --protocol tcp --dport 22 --jump ACCEPT", sudo=True) self.ssh_client.execute("iptables --append INPUT --protocol tcp --sport 1515 --jump ACCEPT", sudo=True) self.ssh_client.execute("iptables --insert OUTPUT --destination {0}/32 --jump ACCEPT".format(local_ip), sudo=True) self.ssh_client.execute("iptables --append OUTPUT --protocol tcp --sport 22 --jump ACCEPT", sudo=True) self.ssh_client.execute("iptables --append OUTPUT --protocol tcp --dport 1515 --jump ACCEPT", sudo=True) if interface: int_ip = self.getIpAddress(interface) self.ssh_client.execute("iptables --append INPUT --destination {0}/32 --jump DROP".format(int_ip), sudo=True) self.ssh_client.execute("iptables --append OUTPUT --source {0}/32 --jump DROP".format(int_ip), sudo=True) else: self.ssh_client.execute("iptables --append INPUT --jump DROP", sudo=True) self.ssh_client.execute("iptables --append OUTPUT --jump DROP", sudo=True) return True
def clear_ip_tables(self): self.ssh_client.execute("iptables --flush", sudo=True) if self.ssh_client.exit_status_last_command != 0: autopsy_logger.error("Couldn't clear iptable entries, probably 'iptables' cmd not present in this node") return False return True
def sendmail(subject, from_mail, to_mail, msg, html_msg=None): me = from_mail you = re.split(r'[;,\s]\s*', to_mail) # Create message container - the correct MIME type is multipart/alternative. mime = MIMEMultipart('alternative') mime['Subject'] = subject mime['From'] = me mime['To'] = to_mail if not html_msg: html_msg = "<html> <pre> " + msg + "</pre> </html>" part1 = MIMEText(msg, 'plain') part2 = MIMEText(html_msg, 'html') mime.attach(part1) mime.attach(part2) try: autopsy_logger.info("Sending mail to: " + to_mail) server = smtplib.SMTP('localhost') server.set_debuglevel(0) server.sendmail(me, you, mime.as_string()) server.quit() except socket.error as e: autopsy_logger.error("Couldn't send mail, check your local SMTP client: " + str(e))
def setBwInterface(self, interface, downSpeed, upSpeed, unit="kbit"): """ :param interface: :param downSpeed: :param upSpeed: :param unit: Valid units are "kbps" - Kilo Bytes/s, "mbps" - Mega Bytes/s , "kbit" - Kilo Bits/s , "mbit" - Mega Bits/s , "bps" - Bytes/s :return: """ if not interface: autopsy_logger.error("Interface can't be None/Empty") return False autopsy_logger.info("Setting (up/down) speed on interface : ({0}/{1}), {2}".format(upSpeed, downSpeed, interface)) # self.execute("sudo wondershaper {0} {1} {2}".format(interface, downSpeed, upSpeed)) self.execute("sudo tc qdisc del dev {2} root;" "sudo tc qdisc add dev {2} root handle 1: htb default 99;" "sudo tc class add dev {2} classid 1:99 htb rate {0}{1} ceil {0}{1} burst 1000k;" "sudo tc class add dev {2} classid 1:1 htb rate 10mbit ceil 10mbit burst 1000k;" "sudo tc filter add dev {2} protocol ip parent 1:0 prio 0 u32 match ip sport 22 0xffff flowid 1:1" .format(upSpeed, unit, interface), quiet=True) if self.ssh_client.exit_status_last_command != 0: autopsy_logger.error("Error setting bw limits, exiting...") return False return True
def interface_up(self, interface): if not interface: autopsy_logger.error("Interface can't be None/Empty") return False self.execute("sudo ifconfig {0} up".format(interface), quiet=True) if self.ssh_client.exit_status_last_command != 0: return False else: return True
def is_interface_up(self, interface): if not interface: autopsy_logger.error("Interface can't be None/Empty") return False output = self.execute("sudo ifconfig {0}".format(interface), quiet=True) if not output or "Device not found" in output: return False return True
def restart_service(self, serviceName): if not serviceName: return False autopsy_logger.debug(self.hostname + ":" + "Restarting service: " + serviceName) output = self.execute("sudo service {0} restart".format(serviceName), quiet=True) if self.ssh_client.exit_status_last_command != 0: if "already running" not in output: autopsy_logger.error("Error restarting the service") return False return True
def flap_interface(self, interface, downtime=10, repeat=1, repeat_gap=20): if not interface: autopsy_logger.error("Interface can't be None/Empty") return False for i in range(1, repeat + 1): self.execute("sudo ifdown {0};sleep {1}; ifup {0}".format(interface, downtime)) if i != repeat: time.sleep(repeat_gap) return True
def clearBwInterface(self, interface): if not interface: autopsy_logger.error("Interface can't be None/Empty") return False autopsy_logger.info("Clear BW params on interface " + interface) self.execute("sudo tc qdisc del dev {0} root".format(interface), quiet=True) if self.ssh_client.exit_status_last_command != 0: autopsy_logger.error("Error clearing bw limits, exiting...") return False return True
def injectErrorsinfile(self, f): fileLocation = f.rsplit('/', 2)[0] fileName = f.rsplit('/', 1)[-1] mountPoint = self.execute("df -k {0}".format(f)) mountPoint = mountPoint.rsplit('\n')[1].rsplit(' ')[0] if not f: autopsy_logger.error("Please Provide a file to inject errors into...") return False # self.ssh_client.connect() if not self.isFileExists(f): autopsy_logger.info("Creating file as it doesn't exist on source...") self.createFile(filePath=fileLocation, fileName=fileName, size="1G", randomData=True) diskSize = self.execute("blockdev --getsz {0}".format(mountPoint), sudo=True) autopsy_logger.info("Creating linear device...") self.execute("umount {0}".format(fileLocation)) self.execute("dmsetup create img 0 {0} linear {1} 0".format(diskSize, mountPoint)) self.execute("dmsetup table img") self.execute("mount /dev/mapper/img {0} && cd {0}".format(fileLocation), sudo=True) fileDetails = self.execute("hdparm {0}".format(f)) columns = fileDetails.split(' ') autopsy_logger.info("Introducing errors in last 64K of the file") self.execute("umount {0}".format(fileLocation), sudo=True) beginErrorAt = columns[1].split('\n')[-1] beginErrorRange = columns[3].split('\n')[-1] endErrorStart = int(columns[2].split('\n')[-1]) + 1 endErrorRange = int(diskSize) - endErrorStart cmd = "echo -e 0 {0} linear {1} 0\n" \ "{0} {2} error\n{3} {4} linear /dev/sdb1 {3}" \ " | dmsetup load img".format(beginErrorAt, mountPoint, beginErrorRange, endErrorStart, endErrorRange) self.execute(cmd, sudo=True) self.execute("dmsetup resume img", sudo=True) self.execute("dmsetup load img", sudo=True) self.execute("mount /dev/mapper/img {0}".format(fileLocation))
def addFailure(self, test, err, capt=None, tb_info=None): id = test.id() tb = format_exception(err, self.encoding) self.stats['fail'] += 1 try: (modulename, classname, testname) = id.split('.') except Exception as e: autopsy_logger.error("ID: " + str(id)) autopsy_logger.error(e.message) return # autopsy_logger.error("REASON: " + format_exception(err, self.encoding)) autopsy_logger.error("===========================================") autopsy_logger.error("| Test Failed : " + classname + "." + testname) autopsy_logger.error("===========================================") timetaken = self._timeTaken() # autopsy_logger.info(timetaken) self.total_run_time += timetaken if autopsy_globals.test_fail_reason.find("\n") != -1: autopsy_globals.test_fail_reason = autopsy_globals.test_fail_reason[0:autopsy_globals.test_fail_reason.find("\n")]\ .strip() self.report_string += "\n|{:<40}|{:^10}|{:^20}|{:<86}|"\ .format(" " + classname + ("" if testname.strip() == "test" else "." + testname), "FAIL", self.nice_to_see_time(timetaken), " " + autopsy_globals.test_fail_reason.strip()) self.fail_report_string += '\n' + "#" * 50 + '\n' self.fail_report_string += '\nTest Case : ' + classname + "." + testname self.fail_report_string += '\nDescription : \n' + self.reindent( self.currTestDescription, 5) self.fail_report_string += '\nSteps : \n' + self.reindent( self.dumpTestSteps(), 5) self.fail_report_string += '\nFail Reason : \n' + self.reindent( format_exception(err, self.encoding), 5) if "test" == testname: testcase = self.getTestByName(classname) testcase.result = "Failed" autopsy_globals.dumpTestCaseJsonFile() else: testcase = self.getTestByName(classname + "." + testname) testcase.result = "Failed" autopsy_globals.dumpTestCaseJsonFile() if is_pause_on_fail(): autopsy_logger.info( "Pausing the test run as pause on fail file found") pdb.set_trace()
def grep_file(self, filePath, pattern): if not filePath.strip(): autopsy_logger.error("File can't be None/empty") return if not pattern.strip(): autopsy_logger.error("Pattern can't be None/empty") return output = self.execute("grep -P '{0}' {1}".format(pattern, filePath), sudo=True) if "No such file or directory" in output: autopsy_logger.warning("File {0} doesn't exist".format(filePath)) return "" return output
def createDir(self, dirPath, dirName, createNonExistingParents=False): if not dirName: autopsy_logger.error("DirName can't be empty or None") return False if not dirPath: dirPath = "~" if createNonExistingParents: self.execute("mkdir -p {0}/{1}".format(dirPath, dirName)) else: self.execute("mkdir {0}/{1}".format(dirPath, dirName)) if self.ssh_client.exit_status_last_command == 0: return True return False
def get_rx_tx_bytes(self, iface): """ will return the received and transferred bytes on the particular interface """ if not iface: autopsy_logger.error("Interface name can not be empty") return False ifcfg = self.execute("sudo ifconfig {0}".format(iface), quiet=True) rx = re.search(r'RX bytes:(\S+)', ifcfg) tx = re.search(r'TX bytes:(\S+)', ifcfg) if rx and tx: rx = rx.group(1) tx = tx.group(1) return [True, int(rx), int(tx)] else: autopsy_logger.error("Interface: {0} ".format(iface) + "does not exist on this machine") return False
def stop_service(self, serviceName): """ Stops a service :param serviceName: """ if not serviceName: return False autopsy_logger.debug(self.hostname + ":" + "Stopping service: " + serviceName) output = self.execute("sudo service {0} stop".format(serviceName), quiet=True) if self.ssh_client.exit_status_last_command != 0: if "Unknown instance" not in output and "Job has already been stopped" not in output: autopsy_logger.error("Error stopping the service") return False return True
def downloadFile(self, remoteFile, localFile): if not remoteFile: autopsy_logger.error("RemoteFile can't be empty/None.") return False if not os.path.basename(remoteFile): autopsy_logger.error("Directory download is not supported.") return False if not localFile: localFile = os.path.basename(remoteFile) with self.ssh_client.get_sftp_connection() as sftp: try: sftp.get(remoteFile, localFile) return True except IOError as e: autopsy_logger.exception("Couldn't Download file: Local - {0}, " "Remote - {1}".format(localFile, remoteFile))
def probability(probs, eventlist=None): if not probs: autopsy_logger.error("List of probabilities cannot be empty") return -1 if eventlist and len(eventlist) != len(probs): autopsy_logger.error("No if items in eventlist and probabilities must match") return -1 sample_distribution = 100 sample_space = sum(probs) * sample_distribution randNo = random.randint(1, sample_space) sumI = 0 for i in range(len(probs)): sumI += probs[i] if randNo <= sumI * sample_distribution: if eventlist: return eventlist[i] return i
def getIpAddress(self, iface): if not iface: autopsy_logger.error("Interface name cannot be empty") return False autopsy_logger.info("Checking ip for interface: " + iface) ifcfg = self.execute("sudo ifconfig {0}".format(iface), quiet=True) # TODO - We need to make this condition more robust if iface in ifcfg: ip = re.search(r'inet addr:(\S+)', ifcfg) if ip: ip_address = ip.group(1) return ip_address elif iface not in ifcfg: autopsy_logger.error("Interface:".format(iface) + " does not exist on this machine") return False return False
def adjust_qos_param(self, interface, operation, packet_limit=None, delay_time=None, delay_jitter=None, delay_correlation=None, corrupt_percent=None, corrupt_correlation=None, duplicate_percent=None, duplicate_correlation=None, loss_percent=None, loss_correlation=None, delay_distribution=None, reorder_percent=None, reorder_correlation=None, reorder_gap=None ): cmd = generate_tc_cmd(interface, operation, packet_limit=packet_limit, delay_time=delay_time, delay_jitter=delay_jitter, delay_correlation=delay_correlation, corrupt_percent=corrupt_percent, corrupt_correlation=corrupt_correlation, duplicate_percent=duplicate_percent, duplicate_correlation=duplicate_correlation, loss_percent=loss_percent, loss_correlation=loss_correlation, delay_distribution=delay_distribution, reorder_percent=reorder_percent, reorder_correlation=reorder_correlation, reorder_gap=reorder_gap) out = self.execute(cmd, sudo=True) if self.ssh_client.exit_status_last_command != 0: if "File exists" in out and operation.lower() == "add": operation = "change" cmd = generate_tc_cmd(interface, operation, packet_limit=packet_limit, delay_time=delay_time, delay_jitter=delay_jitter, delay_correlation=delay_correlation, corrupt_percent=corrupt_percent, corrupt_correlation=corrupt_correlation, duplicate_percent=duplicate_percent, duplicate_correlation=duplicate_correlation, loss_percent=loss_percent, loss_correlation=loss_correlation, delay_distribution=delay_distribution, reorder_percent=reorder_percent, reorder_correlation=reorder_correlation, reorder_gap=reorder_gap) out = self.execute(cmd, sudo=True) if self.ssh_client.exit_status_last_command != 0: autopsy_logger.error("Error applying qos parameters on {0}".format(self.hostname)) elif "No such file" in out and operation.lower() == "change": operation = "add" cmd = generate_tc_cmd(interface, operation, packet_limit=packet_limit, delay_time=delay_time, delay_jitter=delay_jitter, delay_correlation=delay_correlation, corrupt_percent=corrupt_percent, corrupt_correlation=corrupt_correlation, duplicate_percent=duplicate_percent, duplicate_correlation=duplicate_correlation, loss_percent=loss_percent, loss_correlation=loss_correlation, delay_distribution=delay_distribution, reorder_percent=reorder_percent, reorder_correlation=reorder_correlation, reorder_gap=reorder_gap) out = self.execute(cmd, sudo=True) if self.ssh_client.exit_status_last_command != 0: autopsy_logger.error("Error applying qos parameters on {0}".format(self.hostname)) elif "Invalid argument" in out and operation.lower() == "del": pass else: autopsy_logger.error("Error applying qos parameters on {0}".format(self.hostname))
def execute(self, command, inputValues=None, timeout=EXEC_TIMEOUT, quiet=False, sudo=False): """ :param sudo: :param inputValues: List if you need to answer some interactive questions in the command. Pass in the same order they may occur in command output :param quiet: :param timeout: Timeout if the command is taking long time to return :param command: Command to execute in the SSH terminal Connects to SSH if not already connected If you are looking for polling a command output or the command has interactiveness, you can use 'run' proc instead of this. Pass 'inputValues' list if you need to answer some interactive questions in the command. Pass in the same order they may occur in command output :return: Returns the output of the command """ with self.max_session_lock: if not self.isConnected(): # Retrying 10 times, when this host was connected some time back and # now reconnecting because of some problem. # Otherwise, if it is first time being connected retry only 2 times as # it doesn't make much sense to waste time. # Same is the case with timeout self.connect(retries=10 if self.connected else 1, timeout=min(timeout, (60 if self.connected else 10))) if not inputValues: inputValues = [] if type(inputValues) is not list: inputValues = [inputValues] if command.startswith("sudo"): command = command.replace("sudo ", "") sudo = True feed_password = False if sudo and self.user != "root": if "bash " in command: autopsy_logger.critical( "Executing sudo commands with bash is not supported") return "Executing sudo commands with bash is not supported" # Escape double-quotes if the command is having double quotes in itself command = command.replace('"', '\\"') command = "sudo -k -S -p '' bash -c \"{0}\"".format(command) feed_password = self.root_password is not None and len( self.root_password) > 0 self.last_executed_command = command self.last_executed_command_inp_values = inputValues retries = 3 stdin, stdout, stderr = None, None, None while retries > 0: try: if not quiet: autopsy_logger.info( "Exec Cmd" + ((" (" + self.hostname + "): ") if self.hostname else ": ") + command, bold=True) else: autopsy_logger.debug( "Executing command " + ((" (" + self.hostname + "): ") if self.hostname else ": ") + command, bold=True) stdin, stdout, stderr = self.handle.exec_command( command=command, timeout=timeout if timeout is not None else self.EXEC_TIMEOUT, get_pty=True) if stdin and stdout and stderr: break except (SSHException, socket.timeout, socket.error, EOFError) as e: if retries == 0: autopsy_logger.error( "Error executing command even after retries") self.connected = False raise e autopsy_logger.debug( "Exception executing command, retrying") retries -= 1 time.sleep(0.1) if retries <= 0: autopsy_logger.critical( "Couldn't execute the command. Probably n/w issue or timeout: " + command) self.connected = False raise SSHError("Error executing command") # Give a bit of time for the prompt to show up. # It works even without this sleep. But if we send the password before prompt, it # gets reflected back on to stdout and password is visible # Same is the case with any interactive inputs too. time.sleep(0.1) try: if feed_password and stdin: stdin.write(self.root_password + "\n") except socket.error: pass try: if inputValues is not None and len(inputValues) > 0 and stdin: for inp in inputValues: # Same as above sleep for root password time.sleep(0.1) if len(inp) == 1 and ord(inp) < 32: # This IF condition means the input is a special character like, Ctrl + '[' # But we need to wait a little more time otherwise this command gets executed so fast that # even the required prompt will be taken off for the previous command to get executed. # # e.g., dlpause 1, dlclose 1, Ctrl + '[', quit # In the above commands, dlclose 1 may be skipped as the next command executed fast and # left the prompt. time.sleep(1) stdin.write(inp) else: autopsy_logger.debug("Inputting ----> : " + inp) stdin.write(inp + "\n") stdin.flush() except socket.error: autopsy_logger.warning( "Command finished before taking all the input values") output = stdout.read() if stdout else "" error = stderr.read() if stderr else "" output = output.strip() if output is not None else "" error = error.strip() if error is not None else "" self.exit_status_last_command = stdout.channel.recv_exit_status() self.stderr_last_command = error self.stdout_last_command = output if not quiet: autopsy_logger.info(output) else: autopsy_logger.debug(output) if self.exit_status_last_command != 0: if error: autopsy_logger.info(error) return output
def createFile(self, filePath, fileName, size=0, randomData=True, umask="777", append=False): """ Create a file :param append: If True, the content will be appended to the existing file. If False, file will be overwritten or created :param filePath: :param fileName: :param size: Can be in Bytes or in the format of "1M", "5G" ...etc :param randomData: Boolean. To have random data or not in the file created. Random data takes a while to create. :param umask: :return: True/False """ if not fileName: autopsy_logger.error("FileName can't be empty or None") return False if not filePath: filePath = "~" if size == 0: self.execute("touch {0}/{1}".format(filePath, fileName)) return self.ssh_client.exit_status_last_command == 0 if randomData: inFile = "/dev/urandom" else: if self.getFileSystemType(filePath + "/") == 'ext4': self.execute("fallocate -l {0} {1}".format(size, filePath + "/" + fileName), sudo=True) if self.ssh_client.exit_status_last_command != 0: autopsy_logger.error("Error creating file {0}".format(filePath + "/" + fileName)) return False self.execute("chmod {0} {1}".format(umask, filePath + "/" + fileName), sudo=True, quiet=True) return True else: inFile = "/dev/zero" remainder = Utilities.convertToBytes(size) value = 2 bsValues = ["1M", "1K", "1"] isFirst = not append while remainder > 0 and value >= 0: quotient = remainder // (pow(1024, value)) remainder %= (pow(1024, value)) if quotient > 0: if isFirst: self.execute("dd if={0} bs={3} count={2} > {1}".format(inFile, filePath + "/" + fileName, quotient, bsValues[len(bsValues) - value - 1]), sudo=True, quiet=True, timeout=3600) if self.ssh_client.exit_status_last_command != 0: autopsy_logger.error( "Error doing dd command for file {0}: Exiting...".format(filePath + "/" + fileName)) return False isFirst = False else: self.execute("dd if={0} bs={3} count={2} >> {1}".format(inFile, filePath + "/" + fileName, quotient, bsValues[len(bsValues) - value - 1]), sudo=True, quiet=True, timeout=3600) if self.ssh_client.exit_status_last_command != 0: autopsy_logger.error( "Error doing dd command for file {0}: Exiting...".format(filePath + "/" + fileName)) return False value -= 1 return True
def addError(self, test, err, capt=None): id = test.id() self.stats['error'] += 1 try: (modulename, classname, testname) = id.split('.') except Exception as e: autopsy_logger.error("ID: " + str(id)) autopsy_logger.error(e.message) return autopsy_logger.error("REASON: " + format_exception(err, self.encoding)) autopsy_logger.error("===========================================") autopsy_logger.error("| Test Errored : " + classname + "." + testname) autopsy_logger.error("===========================================") timetaken = self._timeTaken() self.total_run_time += timetaken if autopsy_globals.test_fail_reason.find("\n") != -1: autopsy_globals.test_fail_reason = autopsy_globals.test_fail_reason[0:autopsy_globals.test_fail_reason.find("\n")]\ .strip() self.report_string += "\n|{:<40}|{:^10}|{:^20}|{:<86}|"\ .format(" " + classname + ("" if testname.strip() == "test" else "." + testname), "ERROR", self.nice_to_see_time(timetaken), " " + autopsy_globals.test_fail_reason.strip()) self.err_report_string += '\n' + "#" * 50 + '\n' self.err_report_string += '\nTest Case : ' + classname + "." + testname self.err_report_string += '\nDescription : \n' + self.reindent( self.currTestDescription, 5) self.err_report_string += '\nSteps : \n' + self.reindent( self.dumpTestSteps(), 5) self.err_report_string += '\nErr Reason : \n' + self.reindent( format_exception(err, self.encoding), 5) if "test" == testname: testcase = self.getTestByName(classname) testcase.result = "Errored" autopsy_globals.dumpTestCaseJsonFile() else: testcase = self.getTestByName(classname + "." + testname) testcase.result = "Errored" autopsy_globals.dumpTestCaseJsonFile()
def report(self, stream): self.log_file = codecs.open(self.log_file_name, 'w', self.encoding, 'replace') ipaddr = '' try: ipaddr = socket.gethostbyname(socket.gethostname()) except Exception as e: autopsy_logger.error(e.message) self.report_string1 = "\n AUTOMATION SUMMARY REPORT\n" self.report_string1 += " -------------------------\n\n" self.report_string1 += "\nLog Loc : {0}".format( self.archive_loc) + "/" self.report_string1 += "\nTestbed : {0}".format( autopsy_globals.autopsy_testbed.tbname) self.report_string1 += "\nRun Time : {0}".format( self.nice_to_see_time(self.total_run_time)) self.report_string1 += "\nCmd Line : {0}".format( str(' '.join(sys.argv))) self.report_string1 += "\nExec Host : {0}".format(ipaddr) self.report_string1 += "\n" self.report_string1 += "\nTotal : {0}".format(self.stats['total']) self.report_string1 += "\nPass : {0}".format(self.stats['pass']) self.report_string1 += "\nFail : {0}".format(self.stats['fail']) self.report_string1 += "\nError : {0}".format(self.stats['error']) self.report_string1 += "\n" self.report_string += '\n ' + '-' * 159 self.mail_subject = 'Automation Report - ({4}) - Total: {0}, Pass: {1}, Fail: {2}, Err: {3}'\ .format(self.stats['total'], self.stats['pass'], self.stats['fail'], self.stats['error'], ", ".join(autopsy_globals.autopsy_test_suites)) self.report_string = self.report_string1 + self.report_string if self.fail_report_string != '': self.fail_report_string = '\n\n Diagnostics of Failed Tests' \ + '\n ---------------------------\n' \ + self.fail_report_string self.fail_report_string += '\n------------------------------------------------------------------------------------------------------\n\n' if self.err_report_string != '': self.err_report_string = '\n Diagnostics of Errored Tests' \ + '\n ----------------------------\n' \ + self.err_report_string self.err_report_string += '\n------------------------------------------------------------------------------------------------------\n\n' if self.pass_report_string != '': self.pass_report_string = '\n Diagnostics of Passed Tests' \ + '\n ---------------------------\n' \ + self.pass_report_string # self.pass_report_string += '\n------------------------------------------------------------------------------------------------------\n\n' self.report_string += self.fail_report_string self.report_string += self.err_report_string self.report_string += self.pass_report_string autopsy_logger.info(self.report_string) self.log_file.write(self.report_string) self.log_file.close() self.sendmail(self.report_string)
def check(condition, fail_msg=None, pass_msg=None, descr='', cont=False, run_on_fail=None): """ :param run_on_fail: :param condition: Some condition to evaluate to TRUE or FALSE :param fail_msg: :param pass_msg: :param descr: :param cont: Not to assert and continue with remaining even on failure, run_on_fail will not be called :return: """ step = Step() # step.stepnum = len(autopsy_globals.test_steps) + 1 step.stepdescr = descr if condition: step.setStatus('PASSED') if pass_msg is not None: # autopsy_logger.info("PASSED: " + pass_msg) if str.strip(str(descr)) == '': step.stepdescr = pass_msg else: step.stepdescr += " ({0})".format(pass_msg) if str.strip(str(step.stepdescr)) != '': autopsy_globals.test_steps.append(step) autopsy_logger.info(colored("STEP {0}: {1} - " .format(step.stepnum, step.stepdescr), color="magenta", attrs=["bold"]) + colored(step.stepstatus, color="green", on_color=None, attrs=["bold", "dark"])) else: step.setStatus('FAILED') if fail_msg is not None: autopsy_logger.error(colored("FAILED: " + fail_msg)) if str.strip(str(descr)) == '': step.stepdescr = fail_msg else: if str.strip(str(descr)) != '': fail_msg = descr + " is FAILED" else: fail_msg = "Test Step Failed" if str.strip(str(step.stepdescr)) != '': autopsy_globals.test_steps.append(step) autopsy_logger.info(colored("STEP {0}: {1} - " .format(step.stepnum, step.stepdescr), color="magenta", attrs=["bold"]) + colored(step.stepstatus, color="red", on_color=None, attrs=["bold", "dark"])) if len(autopsy_globals.test_fail_reason) > 0: autopsy_globals.test_fail_reason += '\n' autopsy_globals.test_fail_reason += fail_msg if len(fail_msg) < 80 else fail_msg[:70] + '...' if not cont: if run_on_fail is not None: if type(run_on_fail) is list: for func in run_on_fail: func() else: run_on_fail() assert False, fail_msg else: # if run_on_fail is not None: # autopsy_logger.warning("Run-On-Fail will not be called when cont is True") pass