Ken Mixter | 92a44ab | 2010-04-12 22:10:18 | [diff] [blame] | 1 | # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
| 5 | """Upload crash client ID to Issue Tracker by using Issue Tracker API. |
| 6 | |
| 7 | Crash client ID and release notes update to the Chromium Issue Tracker system. |
| 8 | |
| 9 | """ |
| 10 | |
| 11 | import getpass |
| 12 | import httplib |
| 13 | import os |
| 14 | import re |
| 15 | import sys |
| 16 | import urllib |
| 17 | |
| 18 | |
| 19 | # Create crash client ID and sent to "Consent To Send Stats". |
| 20 | def _get_client_id(): |
| 21 | if not os.path.isfile('/home/chronos/Consent To Send Stats'): |
| 22 | sys.exit('Please consent to ending stats in Chromium and rerun.') |
| 23 | else: |
| 24 | id = open('/home/chronos/Consent To Send Stats', 'r') |
| 25 | client_id = id.read() |
| 26 | return client_id |
| 27 | |
| 28 | # Get sender's login credentials. |
| 29 | def _get_credential(): |
| 30 | valid_email = False |
| 31 | while not valid_email: |
| 32 | email = raw_input('Enter your email : ') |
| 33 | # Allowing user to use these email domains |
| 34 | email_domain = re.compile(r'(@chromium.org|@google.com|@gmail.com)$') |
| 35 | valid_email = (email_domain.search(email)) |
| 36 | if not valid_email: |
| 37 | print 'Please check email address, and try again' |
| 38 | pwd = getpass.getpass('Enter your password : ') |
| 39 | return email, pwd |
| 40 | |
| 41 | # Get bug ID corresponding to the crashing report. |
| 42 | def _get_bug_id(): |
| 43 | valid_number = False |
| 44 | while not valid_number: |
| 45 | print ('You are about to publish crashing client ID and lsb-release ' |
| 46 | 'info to this bug') |
| 47 | bug_id = raw_input('Enter bug id that you would like to update : ') |
| 48 | valid_number = re.match(r'^\d+$', bug_id) is not None |
| 49 | # TODO(tturchetto): Verify bug number is in the chrome OS database. |
| 50 | return int(bug_id) |
| 51 | |
| 52 | # Get lsb_release information from the crashed system. |
| 53 | def _get_lsb_release(): |
| 54 | lsb_info = open('/etc/lsb-release', 'r') |
| 55 | lsb_release = lsb_info.read() |
| 56 | return lsb_release |
| 57 | |
| 58 | # Get authetication token to access code.google.com |
| 59 | def _get_auth_token(email, pwd): |
| 60 | google_login_host = 'google.com:443' |
| 61 | client_login_url = '/accounts/ClientLogin' |
| 62 | login_values = { |
| 63 | 'Email': email, |
| 64 | 'Passwd': pwd, |
| 65 | 'accountType': 'GOOGLE', |
| 66 | 'service': 'code', |
| 67 | 'source': 'google-crash_uploader-1.0' |
| 68 | } |
| 69 | |
| 70 | params = urllib.urlencode(login_values) |
| 71 | headers = { |
| 72 | 'Content-type': 'application/x-www-form-urlencoded', |
| 73 | 'Accept': 'text/plain' |
| 74 | } |
| 75 | |
| 76 | conn = httplib.HTTPSConnection(google_login_host) |
| 77 | # Send the request |
| 78 | conn.request('POST', client_login_url, params, headers) |
| 79 | response = conn.getresponse() |
| 80 | response_data = response.read() |
| 81 | error_code = response.status |
| 82 | # 200 is expected response status |
| 83 | if 200 == response.status: |
| 84 | body = response_data.split('\n') |
| 85 | for line in body: |
| 86 | if re.match('Auth=', line): |
| 87 | token = line.split('=')[1] |
| 88 | return token |
| 89 | if 403 == response.status: |
| 90 | sys.exit('Error: unsupported standard parameter, or authentication' |
| 91 | 'or authorization failed.') |
| 92 | |
| 93 | # Create the XML string to be sent as data. |
| 94 | def _create_xml(client_id, lsb_release, email): |
| 95 | # Create the XML string to be sent as data. |
| 96 | issue_tracker_xml = ( |
| 97 | '<?xml version="1.0" encoding="UTF-8"?>\n' |
| 98 | ' <entry xmlns="http://www.w3.org/2005/Atom" ' |
| 99 | 'xmlns:issues="http://schemas.google.com/projecthosting/issues/2009">\n' |
| 100 | ' <content type="html">crashing report client ID: "%(client_id)s "\n' |
| 101 | 'lsb_release is\n" %(lsb_release)s"\n' |
| 102 | ' </content>\n' |
| 103 | ' <author>\n' |
| 104 | ' <name>"%(author)s"</name>\n' |
| 105 | ' </author>\n' |
| 106 | ' <issues:updates>\n' |
| 107 | ' </issues:updates>\n' |
| 108 | '</entry>\n' |
| 109 | ) |
| 110 | |
| 111 | issue_tracker_xml = issue_tracker_xml % { |
| 112 | 'author' : email, |
| 113 | 'client_id' : client_id, |
| 114 | 'lsb_release' : lsb_release |
| 115 | } |
| 116 | return issue_tracker_xml |
| 117 | |
| 118 | # Comment information to the bug. |
| 119 | def _update_bug(email, bug_id, token, issue_tracker_xml): |
| 120 | """Updates the bug. |
| 121 | Args: |
| 122 | email: An user email to access the Issue Tracker. |
| 123 | bug_id: Bug ID that user want to update. |
| 124 | token: Authenticated ClientLogin token to access issue tracker |
| 125 | issue_tracker_xml: Project hosting on Google Code uses xml entry to updates |
| 126 | bug |
| 127 | """ |
| 128 | |
| 129 | # Get headers. |
| 130 | headers = {'Content-type': 'application/atom+xml', |
| 131 | 'Accept': 'text/plain', |
| 132 | 'Authorization': 'GoogleLogin auth=' + token} |
| 133 | conn = httplib.HTTPConnection('code.google.com:80') |
| 134 | google_login_host = 'google.com:443' |
| 135 | issue_update_url = \ |
| 136 | '/feeds/issues/p/chromium-os/issues/%s/comments/full' % ( bug_id ) |
| 137 | # Send the request |
| 138 | conn.request("POST", issue_update_url, issue_tracker_xml, headers) |
| 139 | response = conn.getresponse() |
| 140 | conn.set_debuglevel(1) |
| 141 | data = response.read() |
| 142 | conn.close() |
| 143 | # 201 is expected response status |
| 144 | if 201 == response.status: |
| 145 | print ('%s updated bug # %s successfully.' % ( email, bug_id )) |
| 146 | else: |
| 147 | print ('Your update is not successful posted on the bug # %s' % ( bug_id )) |
| 148 | |
| 149 | def main(): |
| 150 | os.system('clear') |
| 151 | client_id = _get_client_id() |
| 152 | (email, password) = _get_credential() |
| 153 | lsb_release = _get_lsb_release() |
| 154 | token = _get_auth_token(email, password) |
| 155 | bug_id = _get_bug_id() |
| 156 | xml = _create_xml(client_id, lsb_release, email) |
| 157 | _update_bug(email, bug_id, token, xml) |
| 158 | |
| 159 | if __name__ == '__main__': |
| 160 | main() |