send-error-report 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #!/usr/bin/env python
  2. # Sends an error report (if the report-error class was enabled) to a
  3. # remote server.
  4. #
  5. # Copyright (C) 2013 Intel Corporation
  6. # Author: Andreea Proca <andreea.b.proca@intel.com>
  7. # Author: Michael Wood <michael.g.wood@intel.com>
  8. import urllib2
  9. import sys
  10. import json
  11. import os
  12. import subprocess
  13. import argparse
  14. import logging
  15. scripts_lib_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'lib')
  16. sys.path.insert(0, scripts_lib_path)
  17. import argparse_oe
  18. version = "0.3"
  19. log = logging.getLogger("send-error-report")
  20. logging.basicConfig(format='%(levelname)s: %(message)s')
  21. def getPayloadLimit(url):
  22. req = urllib2.Request(url, None)
  23. try:
  24. response = urllib2.urlopen(req)
  25. except urllib2.URLError as e:
  26. # Use this opportunity to bail out if we can't even contact the server
  27. log.error("Could not contact server: " + url)
  28. log.error(e.reason)
  29. sys.exit(1)
  30. try:
  31. ret = json.loads(response.read())
  32. max_log_size = ret.get('max_log_size', 0)
  33. return int(max_log_size)
  34. except:
  35. pass
  36. return 0
  37. def ask_for_contactdetails():
  38. print("Please enter your name and your email (optionally), they'll be saved in the file you send.")
  39. username = raw_input("Name (required): ")
  40. email = raw_input("E-mail (not required): ")
  41. return username, email
  42. def edit_content(json_file_path):
  43. edit = raw_input("Review information before sending? (y/n): ")
  44. if 'y' in edit or 'Y' in edit:
  45. editor = os.environ.get('EDITOR', None)
  46. if editor:
  47. subprocess.check_call([editor, json_file_path])
  48. else:
  49. log.error("Please set your EDITOR value")
  50. sys.exit(1)
  51. return True
  52. return False
  53. def prepare_data(args):
  54. # attempt to get the max_log_size from the server's settings
  55. max_log_size = getPayloadLimit("http://"+args.server+"/ClientPost/JSON")
  56. if not os.path.isfile(args.error_file):
  57. log.error("No data file found.")
  58. sys.exit(1)
  59. home = os.path.expanduser("~")
  60. userfile = os.path.join(home, ".oe-send-error")
  61. try:
  62. with open(userfile, 'r') as userfile_fp:
  63. if len(args.name) == 0:
  64. args.name = userfile_fp.readline()
  65. else:
  66. #use empty readline to increment the fp
  67. userfile_fp.readline()
  68. if len(args.email) == 0:
  69. args.email = userfile_fp.readline()
  70. except:
  71. pass
  72. if args.assume_yes == True and len(args.name) == 0:
  73. log.error("Name needs to be provided either via "+userfile+" or as an argument (-n).")
  74. sys.exit(1)
  75. while len(args.name) <= 0 and len(args.name) < 50:
  76. print("\nName needs to be given and must not more than 50 characters.")
  77. args.name, args.email = ask_for_contactdetails()
  78. with open(userfile, 'w') as userfile_fp:
  79. userfile_fp.write(args.name.strip() + "\n")
  80. userfile_fp.write(args.email.strip() + "\n")
  81. with open(args.error_file, 'r') as json_fp:
  82. data = json_fp.read()
  83. jsondata = json.loads(data)
  84. jsondata['username'] = args.name.strip()
  85. jsondata['email'] = args.email.strip()
  86. jsondata['link_back'] = args.link_back.strip()
  87. # If we got a max_log_size then use this to truncate to get the last
  88. # max_log_size bytes from the end
  89. if max_log_size != 0:
  90. for fail in jsondata['failures']:
  91. if len(fail['log']) > max_log_size:
  92. print "Truncating log to allow for upload"
  93. fail['log'] = fail['log'][-max_log_size:]
  94. data = json.dumps(jsondata, indent=4, sort_keys=True)
  95. # Write back the result which will contain all fields filled in and
  96. # any post processing done on the log data
  97. with open(args.error_file, "w") as json_fp:
  98. if data:
  99. json_fp.write(data)
  100. if args.assume_yes == False and edit_content(args.error_file):
  101. #We'll need to re-read the content if we edited it
  102. with open(args.error_file, 'r') as json_fp:
  103. data = json_fp.read()
  104. return data
  105. def send_data(data, args):
  106. headers={'Content-type': 'application/json', 'User-Agent': "send-error-report/"+version}
  107. if args.json:
  108. url = "http://"+args.server+"/ClientPost/JSON/"
  109. else:
  110. url = "http://"+args.server+"/ClientPost/"
  111. req = urllib2.Request(url, data=data, headers=headers)
  112. try:
  113. response = urllib2.urlopen(req)
  114. except urllib2.HTTPError, e:
  115. logging.error(e.reason)
  116. sys.exit(1)
  117. print response.read()
  118. if __name__ == '__main__':
  119. arg_parse = argparse_oe.ArgumentParser(description="This scripts will send an error report to your specified error-report-web server.")
  120. arg_parse.add_argument("error_file",
  121. help="Generated error report file location",
  122. type=str)
  123. arg_parse.add_argument("-y",
  124. "--assume-yes",
  125. help="Assume yes to all queries and do not prompt",
  126. action="store_true")
  127. arg_parse.add_argument("-s",
  128. "--server",
  129. help="Server to send error report to",
  130. type=str,
  131. default="errors.yoctoproject.org")
  132. arg_parse.add_argument("-e",
  133. "--email",
  134. help="Email address to be used for contact",
  135. type=str,
  136. default="")
  137. arg_parse.add_argument("-n",
  138. "--name",
  139. help="Submitter name used to identify your error report",
  140. type=str,
  141. default="")
  142. arg_parse.add_argument("-l",
  143. "--link-back",
  144. help="A url to link back to this build from the error report server",
  145. type=str,
  146. default="")
  147. arg_parse.add_argument("-j",
  148. "--json",
  149. help="Return the result in json format, silences all other output",
  150. action="store_true")
  151. args = arg_parse.parse_args()
  152. if (args.json == False):
  153. print "Preparing to send errors to: "+args.server
  154. data = prepare_data(args)
  155. send_data(data, args)
  156. sys.exit(0)