def send_message(self): """ Sends consolidated message to the Slack Teams. Global variable message contains conosolidated messages. This consolidated message will be sent to Slack Teams - **parameters**, **types**, **return** and **return types**:: :return: Success string or error message :rtype: String """ global flag message = os.environ.get("sutasmessages") if message: if flag: suitename = os.path.basename(os.environ['logpath']).split( str(datetime.datetime.now().year))[0] #Customizing slack notifications using hash hash = "######################################" message = "\n" + 2 * hash + "\n\t\t" + suitename + "\n" + 2 * hash + "\n" + message + "\n" flag = False else: flag = True if self.glob_data['SlackNotifications'].lower() == 'yes': req = self.slk.api_call("chat.postMessage", channel="%s" % self.channelid, text="%s" % message, username="******" % self.username) if req["ok"]: return "success" else: return req["error"] else: logger.warn("No messages to send.")
def slackobj(self): """ Returns slackobj if user provides correct data otherwise raises Exception """ try: if self.glob_data['SlackNotifications'].lower() == 'yes': if "Slack" in self.glob_data: username = self.data['Slack']['username'] channelname = self.glob_data['Slack']['channelname'] token = self.data['Slack']['token'] if not channelname or channelname == 'None': logger.warn("ChannelName is not provided \ hence not sending mail notifications") else: return Message() except KeyError: logger.warn("SlackNotifications are disabled") try: slkobj = Slacklib(username, channelname, slack_token=token) return slkobj except SlackChannelException as e: logger.warn(e.message) return Message() except SlackTokenException as e: logger.warn(e.message, console=False) raise SlackTokenException(e.message) except Exception as e: logger.warn(e.message) return Message()
def update_hitcount(self, obj, issue, att, namemap, log_msg): """ Increments value of Hit count field and updates - **parameters**, **types**, **return** and **return types**:: :param obj: Jiralib object :param issue: issue where HitCount field needs to be updated :param att: attachment to be added in the issue :param namemap: dictionary of customfields and its values in jira project :param log_msg: Message to be updated in the log :type obj: object :type issue: string :type att: string :type namemap: dictionary :type log_msg: string """ logger.warn(log_msg) try: value = \ issue.raw['fields'][namemap['HitCount']] + 1 issue.update(fields={namemap['HitCount']: value}) text = '\n\nHitCount increased to {}'.format(int(value)) + '\n' notify.message(text) except (KeyError, TypeError): logger.warn("\nHitCount field not found.") comment = "updated Hitcount and attached latest log" if not att is None: self.add_attachment_and_comment(obj, issue, att, comment)
def update_data_bulk(self, table, db_id, data): """ it updates the test case data in bulk in corresponding table - **parameters**, **types**, **return** and **return types**:: :param table: data base table obj. :type table: data base class :param db_id: db_id. :type db_id: integer :param data: to be modified test case date. :type data: dictionary :return: True : """ try: self.db.query(table).filter_by(id=db_id).update(data) except sqlalchemy.exc.StatementError as err: logger.error(data) raise Exception(err) except Exception as err: logger.warn(err) try: self.db = db() self.db.query(table).filter_by(id=db_id).update(data) except Exception as err: logger.warn('DB connection failed') logger.error(err) raise Exception(err) self.db.commit() self.db.close() return True
def push_content(self): logger.debug('call: ubuntupaste.push_content') conf = config.getConfig() post_target = 'http://paste.ubuntu.com/' logger.debug('post target: ' + post_target) poster = conf.get('ubuntu.user', getpass.getuser()) logger.debug('poster: ' + poster) # Get Filename for highlight. filename = conf.require('src').name if filename == '-': print 'Type your content here, end with EOF' print 'Use Ctrl-C to interrupt, if you have mistyped something.' try: content = conf.require('src').read() except KeyboardInterrupt: logger.warn('Ctrl-C received, interrpted...') sys.exit(1) lines = content.count('\n') bytes = len(content) logger.info('content: %d lines, %d bytes' % (lines, bytes)) lang = conf.get('ubuntu.lang', _get_language(filename)) logger.debug('highlight: ' + lang) post_data = { 'poster' : poster, 'syntax' : lang, 'content' : content, } try: resp = self.req.post(post_target, data=post_data, allow_redirects=False) except exceptions.RequestException as e: logger.info('Exception: ' + e.__class__.__name__) logger.error('Something went wrong when communicating with paste.ubuntu.com!') raise exception.ServerException(e) logger.debug('HTTP OK') logger.info('HTTP Status: %d %s' % (resp.status_code, resp.reason)) if resp.status_code == 302: pastepad = resp.headers['location'] logger.debug('location: ' + pastepad) pattern = re.compile(r'^http:\/\/paste.ubuntu.com/(?P<paste_id>\d+)/$') res = pattern.match(pastepad) if not res: raise exception.ServerException('Unknown location: ' + pastepad) paste_id = res.group('paste_id') logger.info('paste_id: ' + paste_id) # return paste_id print 'Paste ID: ' + str(paste_id) print 'HTTP Link: ' + pastepad return if resp.status_code == 200: data = resp.content err_start_flag = '<ul class="errorlist"><li>' err_stop_flag = '</li></ul>' msg = self.html2text(self.fetch_between(resp.content, err_start_flag, err_stop_flag)) raise exception.ServerException('Server refused our paste: ' + msg) raise exception.ServerException('Server responsed with unknown status %d %s' % (resp.status_code, resp.reason))
def addwatchersforduplicateissue(obj, watcher): if watcher: users = self.watcher.split(",") for user in users: try: obj.conn.add_watcher(issue, user) except Exception as err: msg = '{} cannot be added as watcher'.format(user) logger.warn(msg)
def __get_media_file(self): try: self.current_processing_file = self.mfq.peek( MediaFileState.WAITING) self.mfq[self.current_processing_file.id, self.current_processing_file. file_path] = MediaFileState.PROCESSING except Exception: logger.warn("Can't obtain media file to process")
def __setitem__(self, key, status): now = datetime.datetime.now() if self.__contains__(key): update_fields = {'status': status, 'last_modified': now} if status == MediaFileState.PROCESSING: update_fields['date_started'] = now elif status == MediaFileState.PROCESSED: transcoded_file_path = self.__getitem__( key).transcoded_file_path try: update_fields['transcoded_file_size'] = os.path.getsize( transcoded_file_path) except OSError: logger.warn( "Unable to obtain transcoded file size [{}]".format( transcoded_file_path)) update_fields['date_finished'] = now elif status == MediaFileState.FAILED: update_fields['date_finished'] = now elif status == MediaFileState.WAITING: update_fields['date_started'] = None update_fields['date_finished'] = None update_fields['transcoded_file_size'] = None if isinstance(key, tuple): MediaFile.update(update_fields).where( (MediaFile.id == key[0]) & (MediaFile.file_path == key[1])).execute() else: MediaFile.update(update_fields).where( MediaFile.id == key).execute() else: if isinstance(key, tuple): file_directory = os.path.dirname(key[1]) file_name = os.path.splitext(os.path.basename(key[1]))[0] transcoded_file = os.path.join( file_directory, "{}_transcoded.{}".format(file_name, self.output_file_extension)) log_file = os.path.join(file_directory, "{}_transcoding.log".format(file_name)) MediaFile.create(id=key[0], file_path=key[1], transcoded_file_path=transcoded_file, log_file_path=log_file, status=status, file_size=os.path.getsize(key[1]), date_added=now, last_modified=now) else: raise Exception( 'media file doesn\'t exist, you must provide both id and file_path' )
def validate_error(self, msg, tc_name): """ Validates error for not raising a defect incase of invalid user inputs" - **parameters**, **types**, **return** and **return types**:: :param msg: error msg of failed test case from output xml file. :param tc_name: name of the failed testcase :type msg: string :type tc_name: string """ msg1 = "hardware requirement failed" msg2 = "software requirement failed" msg3 = "dependency tests failed" msg4 = "hence skipping the test case" msg_lower = msg.lower() if "No keyword with name".lower() in msg_lower: log_msg = "Not raising defect for tc '%s' since it is an import error.\n" % tc_name logger.warn(log_msg) notify.message(log_msg) return False elif msg_lower in [ 'connectionerror:', 'max retries exceeded with url' ]: log_msg = "Not raising defect for tc %s since it is a connection error.\n" % tc_name logger.warn(log_msg) notify.message(log_msg) return False elif re.search(r"expected\s\d\sarguments, \sgot\s\d", msg): key_word = re.search(r"\'(.*)\'", msg).group(1) log_msg = "Not raising defect for tc '%s' since user did not \ provide required arguments for keyword %s.\n" % (tc_name, key_word) logger.warn(log_msg) notify.message(log_msg) return False elif "Already_Exist" in msg: log_msg = "Not raising defect for tc '%s' since user tried to \ create already existing configurarion.\n" % tc_name logger.warn(log_msg) notify.message(log_msg) return False elif "Invalid_Argument" in msg: log_msg = "Not raising defect for tc '%s' since user provided \ invalid arguments.\n" % tc_name logger.warn(log_msg) notify.message(log_msg) return False elif (msg1 in msg_lower) or (msg2 in msg_lower) or \ (msg3 in msg_lower) or (msg4 in msg_lower): return False return True
def send_message(self): """ Sends consolidated message to the MS Teams. Global variable message contains conosolidated messages. This consolidated message will be sent to MS Teams - **parameters**, **types**, **return** and **return types**:: :return: Success string or error message :rtype: String """ global flag message = os.environ.get("sutasmessages") if message: if flag: hash = "######################################" message = "\n" + 2 * hash + message + 2 * hash + "\n" flag = False else: flag = True if self.glob_data['TeamsNotifications'].lower() == 'yes': data = {"text": message} try: req = requests.post(self.url, json=data) if req.status_code != 200: logger.warn("Failed to send messages to Teams.") logger.warn(str(req.text)) return str(req.text) else: return "success" except ConnectionError: msg = "Failed to establish connection with MS Teams" logger.warn(msg) return msg else: logger.warn("No messages to send.")
def get_password(self, strng, prevpass): while True: pwd = getpass.getpass(strng) if pwd: password = AESCipher().encrypt(pwd) break else: if prevpass: password = prevpass break else: logger.warn("No password in global conf to use." "Please enter password.") return password
def emailobj(self): """ Returns mailobj if user provides correct data otherwise raises Exception """ try: if self.glob_data['EmailNotifications'].lower() == 'yes': if "Email" in self.glob_data: recipients = self.glob_data['Email']['recipients'] if not recipients or recipients == 'None': logger.warn("Recipients list is not provided hence \ not sending email notifications") else: return Message() except KeyError: logger.warn('MailNotifications are disabled') try: emailobj = Maillib(recipients) return emailobj except MailConnectionException as err: logger.warn(err.message) return Message() except MailRecipientsException as err: logger.warn(err.message) return Message()
def add_slackconf(self): """ Add slack details into YAML. - **parameters**, **types**, **return** and **return types**:: :return: Returns slack dictionary :rtype: dictionary """ slacknotifications = ( "\nDo you want notifications to " "Slack Channel [" + self.prevdata('SlackNotifications', self.globalprevdata) + "]:(Yes/No)") slacknotifications = self.get_input(slacknotifications, choices=["yes", "no"]) usrname = self.prevdata('Slack.username', self.userprevdata) channelname = self.prevdata('Slack.channelname', self.globalprevdata) token = self.prevdata('Slack.token', self.userprevdata) prevtoken = token if token: token = AESCipher().decrypt(token) prevtoken = token if slacknotifications.lower() == 'yes': if token: token = AESCipher().decrypt(token) prevtoken = token usrname = "Enter username[" + usrname + "]:" usrname = self.get_input(usrname) channelname = "Enter slack channelname [" + channelname + "]: " channelname = self.get_input(channelname) while True: token = "enter Slack token[" + prevtoken + "]: " token = self.get_input(token) if token: token = AESCipher().encrypt(token) break else: logger.warn("token cannot be empty. Please re-enter.") else: token = token slack_dict = {'Slack': {'username': usrname, 'token': token}} globalslack_dict = { 'SlackNotifications': slacknotifications, 'Slack': { 'channelname': channelname } } return slack_dict, globalslack_dict
def _update_status_jira(tc_ids, resultslist, j_conn, new_issue, error=None): """ Update the status of test case in JIRA - **parameters**, **types**, **return** and **return types**:: :param tc_id: Test case id to update the status :param result(str): status of a test case in this case it is Pass or Fail :param j_conn: JIRA connection object. :param new_issue: raised bug id in case of test failed to link the bug id to test case :type: tc_id: string :type: result: string :type: j_conn: object :type: new_issue: string """ for count, tc_id in enumerate(tc_ids): try: result = resultslist[count] #issue object issue = j_conn.issue(tc_id) if new_issue: try: j_conn.create_issue_link('blocked by', issue, new_issue) except Exception as err: logger.warn(err) logger.warn( "Not able to link the bug {} to testcase {}". format(new_issue, tc_id)) except Exception as err: raise Exception(err) #raise Exception('No issues found with this test case id', tc_id) status = issue.fields().status transitions = j_conn.transitions(tc_id) if status.name.lower() in ['test in progress', 'running']: for transition in transitions: if not transition['name'].lower().find(result.lower()): #making transitions to what ever result comes in j_conn.transition_issue(issue.key, str(transition['id'])) if result.lower() == "skip" and error: #adding eeror message to the issue as a comment j_conn.add_comment(issue, str(error)) return
def lock(self): '''locks the database by creating a file on db server.''' if self.servertype.lower() == 'linux': self.ssh = paramiko.SSHClient() self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: self.ssh.connect(self.dbserver, username=self.username, password=self.password) self.sftp = self.ssh.open_sftp() self.sftp.chdir('/tmp/') try: self.sftp.stat('/tmp/prune.lock') logger.warn( 'pruning is already in progress.. hence skipping the pruning for now.' ) return False except IOError: with open('prune.lock', 'w') as psql: psql.write('pruning is starting...') self.sftp.put('prune.lock', '/tmp/prune.lock') except paramiko.SSHException: logger.error("Connection Error") except Exception: return False return True else: self.winrmclient = WINRM(self.dbserver, self.username, self.password) try: self.winrmclient.connect() except: logger.error('connection failed') raise Exceptioneption('connection failed') std_out, std_err, status_code = self.winrmclient.run_cmd( 'type C:\\prune.lock') if status_code == 0: logger.warn( 'pruning is already in progress.. hence skipping the pruning for now.' ) return False else: std_out, std_err, status_code = self.winrmclient.run_cmd( 'echo datapruning > C:\\prune.lock') return True
def reopen_issue(self, obj, issue, issue_key, att): """ Reopens an issue :param obj: Jiralib object :param issue: issue to be reopened :param issue_key: issue key value :param att: attachment to be added in the issue """ for transition in obj.conn.transitions(issue): if 'open' or 'reopen' or 'reopened' in transition['name'].lower(): obj.conn.transition_issue(issue.key, str(transition['id'])) #issue.fields.labels.append(u'reopen') #issue.update(fields={"labels": issue.fields.labels}) comment = 'Reopened Bug and attached latest log' self.add_attachment_and_comment(obj, issue, att, comment) return issue break logger.warn("\nReopened {} issue \n".format(issue_key))
def __init__(self, server, username, pwd): """ Constructor - **parameters**, **types**, **return** and **return types**:: param server: ipaddress of Jira server type: string param username: Username to login into jira type: string param pwd: Password to login into jira type: string """ try: pwd = aes().decrypt(pwd) except ValueError: logger.warn("Invalid Password is provided".format(pwd)) raise Exception(pwd) self.conn = self.connect_jira(server, username, pwd)
def teamsobj(self): """ Returns slackobj if user provides correct data otherwise raises Exception """ try: if self.glob_data['TeamsNotifications'].lower() == 'yes': if "Teams" in self.glob_data: url = self.glob_data['Teams']['url'] else: return Message() except KeyError: logger.warn("TeamsNotifications are disabled") try: tmsobj = Teamslib(url) return tmsobj except Exception as e: logger.warn(e.message) return Message()
def _perform_auth(self, otp_token=None): if otp_token is None: try: self.user = raw_input('Username: '******'user: '******'Password: '******'password ok.') except KeyboardInterrupt: logger.warn('Ctrl-C detected.') sys.exit(1) user = self.user pwd = self.pwd logger.info('auth: fetch new token') post_json = { 'scopes' : ['gist'], 'note' : 'paste.py @ ' + str(datetime.datetime.now()), 'note_url' : 'https://github.com/jackyyf/paste.py', } post_headers = { 'Content-Type' : 'application/json', } if otp_token is not None: post_headers['X-GitHub-OTP'] = otp_token post_str = json.dumps(post_json) post_url = _api_base + '/authorizations' logger.debug('post_url: ' + post_url) try: resp = self.req.post(post_url, data=post_str, headers=post_headers, auth=(user, pwd)) except exceptions.RequestException as e: raise exception.ServerException(e) logger.info('http ok. response: %d %s' % (resp.status_code, resp.reason)) if resp.status_code == 201: logger.info('auth ok.') token = resp.json()[u'token'] logger.debug(resp.content) self.req.headers['Authorization'] = 'token ' + token return token elif resp.status_code == 401: # Two factor auth? logger.warn('auth failed') if 'X-GitHub-OTP' in resp.headers: logger.warn('auth: two-factor required') try: token = raw_input('Two factor token from ' + resp.headers['X-Github-OTP'].replace('required; ', '') + ':') except KeyboardInterrupt: logger.warn('Ctrl-C detected') sys.exit(1) return self._perform_auth(otp_token=token) else: logger.error('username or password error.') return self._perform_auth() else: raise exception.ServerException('Server responsed with unknown status: %d %s' % (resp.status_code, resp.reason))
def find_project_by_key(conn, project_key): """ Returns Project's Name if project exists - **parameters**, **types**, **return** and **return types**:: :param project_name: Project Key :return: project's Name """ project = None for i in conn.projects(): if i.key == project_key: project = i break if project: return project.name else: logger.warn("no project with name %s" % project_key) raise Exception( "No Project with Key {} found in jira".format(project_key))
def find_project_by_name(self, project_name): """ Retuns project_id if project exists - **parameters**, **types**, **return** and **return types**:: param project_name: Project Name type: string """ project = None for i in self.conn.projects(): if i.name == project_name: project = i break if project: return project.id else: logger.warn("no project with name %s" % project_name) raise Exception( "No Project with Name {} found in jira".format(project_name))
def _do_auth(self, token=None): # Authenticate to github, save some login info (user/pass, or oauth token) conf = config.getConfig() auth = conf.getboolean('gist.auth', False) or token is not None if auth: # User/Pass Pair logger.info('auth: oauth token') if token is None: token = conf.require('gist.token') logger.debug('auth: test token usability') # Try authenticate self.req.headers['Authorization'] = 'token ' + token # Get a time in future (1 year) fmt_time = (datetime.datetime.now() + datetime.timedelta(days=365)).strftime('%Y-%m-%dT%H:%M:%SZ') test_url = _api_base + '/gists?since=' + fmt_time logger.debug('test url: ' + test_url) try: resp = self.req.get(test_url) except exceptions.RequestException as e: logger.warn('http error, assume token is good.') logger.info('[%s] %s' % (e.__class__.__name__, e.message)) return logger.debug('http ok, response: %d %s' % (resp.status_code, resp.reason)) if resp.status_code == 401: # Invalid token logger.warn('invalid token') return False elif resp.status_code == 200: logger.info('token ok.') return True else: logger.warn('unknown response status: %d %s' % (resp.status_code, resp.reason)) raise exception.ServerException('Server responsed with unknown status: %d %s' % (resp.status_code, resp.reason)) logger.info('auth: none') return None
def check_diskusage(conn): '''checks the disk space on a server - **parameters**, **types**, **return** and **return types**:: :param conn: ssh connection obj. :type kwargs: ssh object ''' rtcode, stdout, stderr = conn.exec_command('df -h /') if stderr.read() == '': out = stdout.read().strip().split('\n') used = int(out[-1].split()[-2][:-1]) if used > 75: msg = 'used disk space is ' + str( used ) + '%. Available disk space is less than 75%. please free up the disk space' logger.warn(msg) return True else: msg = str(used) + '% of disk space is utilized.' logger.warn(msg)
def check_diskspace(self): '''Checks the disks space on database server''' ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: ssh.connect(self.dbserver, username=self.username, password=self.password) except Exception as err: if 'Authentication failed' in err: msg = 'Check username and password of Webserver' logger.error(msg) raise Exception(msg) else: msg = "" logger.error(str(err)) logger.warn('Checking disk space on database server..') if check_diskusage(ssh): logger.warn("please check the below url to prune the database " "https://sungardas.sharepoint.com/teams/ProdTeam/" "_layouts/15/WopiFrame.aspx?sourcedoc=%7B0F36181D-55F3" "-4757-BFEE-259F967D76CA%7D&file=High%20Level%20" "Design%20Document%20-%20SUTAS.docx&action=default")
def check_diskspace(self): '''Checks the diskspace available on artifactory server''' if self.glob_data['EnableTestArtifacts'].lower() == "yes": ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: #Establishes a connection to Linux machine ssh.connect(self.serverip, username=self.username, password=self.password) except Exception as err: if 'Authentication failed' in err: msg = 'Check username and password of Webserver' logger.error(msg) #raise Exception(msg) else: msg = "" logger.error(str(err)) else: logger.info('Checking disk space on test artifacts server.. ') if check_diskusage(ssh): logger.warn('Please remove some files from ' 'artifactory server..')
def get_input(self, strng, choices=None): if re.search(r'\[(.*?)\]', strng): old_value = re.search(r'\[(.*?)\]', strng).group(1) else: old_value = "" while True: inpt = input(strng) if inpt == "": inpt = old_value if choices: if inpt.lower() not in choices: raise Exception( "input must be given from the choices {}".format( choices)) return inpt if choices: if inpt.lower() in choices: break else: logger.warn("values must be '%s' please re-enter " "the value." % ("/".join(choices))) else: break return inpt
def __init__(self, username, channelname, slack_token): """ Initialize the Slacklib class - **parameters**, **types**, **return** and **return types**:: param username : username of the slack member who runs the test suite param channelname : Channel to which notifications will be sent param slack_token : Slack_token of user type username: String type channelname: String type slack_token: String """ self.channelname = channelname self.username = username try: #slack token of user in that channel for sending notifications. slack_token = aes().decrypt(slack_token) except Exception as e: logger.warn("Invalid slack token") #self.slk = SlackClient(slack_token) self.slk = WebClient(token=slack_token) self.channelid = self.get_channelid() self.message = "" self.globalfilepath = os.path.join(expanduser('~'), "global_conf.yaml") self.glob_data = get_data_from_yaml(self.globalfilepath)
def get_individual_log(tcname): """ This function creates individual TC logs from testsuite log. Sutas generates whole testsuite log. From this testsuite log individual test case logs will be created. - **parameters**, **types**, **return** and **return types**:: :param tcname: Testcase name with which testsuite log will be parsed and created individual log. :type tcname: String :return: Path of created test case log :rtype: String """ str = tcname + " execution started by sutas" logfile = os.environ["logpath"] logpath = os.path.dirname(logfile) startline = None startline = _get_line_number(logfile, str) if startline is None: logger.warn("Cannot find individual TC log for %s" % tcname) return logfile with open(logfile, 'r') as suitelog: log_data = suitelog.readlines() line = startline - 1 log_data = log_data[line:] tclog = os.path.join(logpath, tcname + ".log") fp = open(tclog, "w") fp.write(log_data[0]) for line in log_data[1:]: if "execution started by sutas" in line: break fp.write(line) fp.close return tclog
def connect(self): """ Method to connect to a Windows machine. """ try: self.host_win_ip = "http://" + self.host_ip + ":5985/wsman" self.conn = Protocol(endpoint=self.host_win_ip, transport="ntlm", username=self.usr, password=self.pwd, server_cert_validation="ignore") logger.warn("Connecting Windows ...") self.shell_id = self.conn.open_shell() logger.warn(self.shell_id) logger.warn('Connected to Windows.') except Exception as error: msg_exception_error = "Exception raised: %s " % error raise (msg_exception_error)
def make_transitions(conn, test_case): """ Transitions """ status = test_case.fields().status.name.lower() msg = 'Current status of testcase %s is %s' % (test_case, status) logger.warn(msg) if status == 'failed' or status == 'skipped' or status in [ 'todo', 'to do' ]: if status == 'failed' or status == 'skipped': _changetransistion(conn, test_case.key, 'back to todo') _changetransistion(conn, test_case.key, 'ready to run') _changetransistion(conn, test_case.key, 'running') _changetransistion(conn, test_case.key, 'test in progress') elif status == 'ready to run': _changetransistion(conn, test_case.key, 'running') elif status in ['running', 'test in progress']: msg = test_case.fields().issuetype.name + ' is in ' + status + ' State' logger.warn(msg) else: logger.warn("Unknown Status...")
def send_mail_when_failed(self, body): try: if self.recipients: msg = MIMEMultipart() msg['From'] = self.sender msg['To'] = self.recipients self.recipients = self.recipients.split(',') msg['Subject'] = "SUTAS Execution Terminated" msg['X-Priority'] = '2' hashh = "######################################" line = "=" * len(hashh) space = " " * len(hashh) body = line + '\n' + os.environ[ 'cmd'] + '\n' + line + '\n' + space + '\n' + body msg.attach(MIMEText(body, 'plain')) text = msg.as_string() self.mailconn.sendmail(self.sender, self.recipients, text) except MailRecipientsException as err: logger.warn(err.message) except SMTPRecipientsRefused as err: logger.warn(err) logger.warn("No connectivity to smtp.")
def push(self): # TODO: Implements push. conf = config.getConfig() res = self._do_auth() if res is not None: if not res: if conf.getboolean('check', True): print 'Token is invalid, please use paste.py gist auth to get a new token.' sys.exit(1) else: del self.req.headers['Authorization'] files = conf.require('files') if files.count(sys.stdin) > 1: raise exception.InvalidValue('stdin was listed more than once!') logger.debug('private: ' + ('yes' if conf.require('private') else 'no')) logger.debug('description: ' + conf.require('description')) logger.debug('files: ' + str(len(files))) post_data = { 'public' : not conf.require('private'), 'description' : conf.require('description'), } file_data = dict() try: for file in files: logger.info('reading file ' + file.name) if file is sys.stdin: print 'Type your content here, end with EOF' print 'Use Ctrl-C to interrupt, if you have mistyped something.' content = file.read() logger.debug('file ' + file.name + ': %d lines, %d bytes' % (content.count('\n'), len(content))) fname = os.path.basename(file.name) now = 2 if fname in file_data: if '.' in fname: name, ext = fname.rsplit('.', 1) else: name, ext = fname, '' while (name + '-' + str(now) + '.' + ext) in file_data: now += 1 fname = (name + '-' + str(now) + '.' + ext) logger.debug('final filename: ' + fname) file_data[fname] = { 'content' : content, } except KeyboardInterrupt: logger.warn('Ctrl-C received, exiting.') sys.exit(1) post_data['files'] = file_data post_str = json.dumps(post_data) post_url = _api_base + '/gists' logger.debug('post url: ' + post_url) try: resp = self.req.post(post_url, data=post_str, headers={ 'Content-Type' : 'application/json', }) except exceptions.RequestException as e: logger.error('Post error: ' + e.message) raise exception.ServerException(e) logger.debug('http ok.') logger.info('server response: %d %s' % (resp.status_code, resp.reason)) if resp.status_code == 201: logger.info('gist created') url = resp.json()[u'html_url'] gistid = url.rsplit('/', 1)[1] print 'HTTP Link: ' + url print 'Paste.py uri: gist://' + gistid else: raise exception.ServerException('Server responsed with unknown status: %d %s ' % (resp.status_code, resp.reason))
def pull_content(self): logger.debug('call: ubuntupaste.pull_content') conf = config.getConfig() fn = conf.require('dest') if fn == '-': fo = sys.stdout else: if os.path.exists(fn): if not conf.get('overwrite', False): raise exception.FileExists('File %s already exists.' % fn) fo = open(fn, 'w') _uri = conf.require('src') res = uri.parse(_uri) if res is None: raise exception.InvalidURI('Invalid URI: ' + _uri) logger.debug('uri format ok.') logger.debug('scheme: ' + res.scheme) if res.scheme == 'ubuntu': logger.info('using ubuntu:// style uri') pid = res.path logger.debug('path: ' + pid) for ch in pid: if not ch.isdigit(): raise exception.InvalidURI('UbuntuPaste should only contains digits!') if pid != str(int(pid)): raise exception.InvalidURI('No leading zero allowed.') url = 'http://paste.ubuntu.com/{pid}/'.format(pid=pid) logger.info('to http url: ' + url) elif res.scheme == 'http': logger.info('using http:// style uri') if '/' not in res.path: raise exception.InvalidURI('Invalid http url: ' + _uri) host, path = map(lambda x : x.lower(), res.path.split('/', 1)) # NOTE: Leading / in path is removed when using split. logger.debug('http host: ' + host) logger.debug('http path: ' + path) if host != 'paste.ubuntu.com': raise exception.InvalidURI('HTTP Host should be paste.ubuntu.com!') pattern = re.compile(r'^[1-9](?:\d+)(?:/?)') if not pattern.match(path): raise exception.InvalidURI('Invalid path for ubuntu paste!') # url validated. url = _uri else: raise exception.InvalidURI('Unknown scheme: ' + res.scheme) # Check if pad exists try: res = self.req.get(url) except exceptions.RequestException as e: logger.info('Exception: ' + e.__class__.__name__) logger.warn('Something wrong when communicating with paste.ubuntu.com, assume paste pad exists.') return url logger.debug('HTTP OK.') logger.info('Server response: %d %s' % (res.status_code, res.reason)) if res.status_code == 200: # OK # Q = pyquery.PyQuery(res.content) # content = pyquery.PyQuery(Q('.code').html().replace('\n', '<br />')).text()# start_flag = '<td class="code"><div class="paste"><pre>' end_flag = '</pre></div>' content = self.html2text(self.fetch_between(res.content, start_flag, end_flag)) logger.debug('content: %d lines, %d bytes' % (content.count('\n') + 1, len(content))) # return content fo.write(content) return if res.status_code >= 400 and res.status_code < 500: raise exception.NoSuchPad('No such pad: %s. Server responsed with status code %d' % (_uri, res.status_code)) raise exception.ServerException('Server responsed with status code %d' % res.status_code)