Package backend :: Package common :: Module rhnTB
[hide private]
[frames] | no frames]

Source Code for Module backend.common.rhnTB

  1  # 
  2  # Copyright (c) 2008--2016 Red Hat, Inc. 
  3  # 
  4  # This software is licensed to you under the GNU General Public License, 
  5  # version 2 (GPLv2). There is NO WARRANTY for this software, express or 
  6  # implied, including the implied warranties of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 
  8  # along with this software; if not, see 
  9  # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 
 10  # 
 11  # Red Hat trademarks are not licensed under GPLv2. No permission is 
 12  # granted to use or replicate Red Hat trademarks that are incorporated 
 13  # in this software or its documentation. 
 14  # 
 15  # 
 16   
 17  import os 
 18  import sys 
 19  import time 
 20  import traceback 
 21  import socket 
 22  try: 
 23      #  python 2 
 24      from StringIO import StringIO 
 25  except ImportError: 
 26      #  python3 
 27      from io import StringIO 
 28  from rhn.connections import idn_puny_to_unicode 
 29   
 30  from spacewalk.common.rhnConfig import CFG, PRODUCT_NAME 
 31  from spacewalk.common.rhnLog import log_error 
 32  from spacewalk.common.rhnTranslate import _ 
 33  from spacewalk.common.stringutils import to_string 
 34  from spacewalk.common import rhnMail 
 35  from spacewalk.common import rhnFlags 
 36   
 37  # Get the hostname for traceback use 
 38  hostname = socket.gethostname() 
 39   
 40  # Keep QUIET_MAIL in a global variable that is initialized from CFG 
 41  # when it is first needed. It controls the maximum number of 
 42  # tracebacks we're willing to send out of this process in order to 
 43  # avoid a huge flood of mail requests. 
 44  QUIET_MAIL = None 
 45   
 46   
 55   
 56   
 93   
 94   
110   
111   
112 -def Traceback(method=None, req=None, mail=1, ostream=sys.stderr, 113 extra=None, severity="notification", with_locals=0):
114 """ Reports an traceback error and optionally sends mail about it. 115 NOTE: extra = extra text information. 116 """ 117 # pylint: disable=C0103 118 119 global QUIET_MAIL 120 121 if mail: 122 # safeguard 123 if QUIET_MAIL is None: 124 QUIET_MAIL = CFG.QUIET_MAIL 125 126 if QUIET_MAIL < 0: 127 QUIET_MAIL = 0 128 if QUIET_MAIL == 0: # make sure we don't mail 129 mail = 0 130 131 e_type = sys.exc_info()[:2][0] 132 t = time.ctime(time.time()) 133 exc = StringIO() 134 135 unicode_hostname = idn_puny_to_unicode(hostname) 136 exc.write("Exception reported from %s\nTime: %s\n" % (to_string(unicode_hostname), t)) 137 exc.write("Exception type %s\n" % to_string(e_type)) 138 if method: 139 exc.write("Exception while handling function %s\n" % to_string(method)) 140 141 # print information about the request being served 142 if req: 143 print_req(req, exc) 144 if extra: 145 exc.write("Extra information about this error:\n%s\n" % to_string(extra)) 146 147 # Print the traceback 148 exc.write("\nException Handler Information\n") 149 traceback.print_exc(None, exc) 150 151 if with_locals and not mail: 152 # The mail case will call print_locals by itself 153 print_locals(exc) 154 155 # we always log it somewhere 156 if ostream: 157 ostream.write(to_string(exc.getvalue())) 158 ostream.write("\n") 159 160 if mail: 161 # print the stack frames for the mail we send out 162 print_locals(exc) 163 # dump the environment 164 print_env(exc) 165 # and send the mail 166 # build the headers 167 to = CFG.TRACEBACK_MAIL 168 fr = to 169 if isinstance(to, type([])): 170 fr = to[0].strip() 171 to = ', '.join([x.strip() for x in to]) 172 headers = { 173 "Subject": "%s TRACEBACK from %s" % (PRODUCT_NAME, unicode_hostname), 174 "From": "%s <%s>" % (hostname, fr), 175 "To": to, 176 "X-RHN-Traceback-Severity": severity, 177 "Content-Type": 'text/plain; charset="utf-8"', 178 179 } 180 QUIET_MAIL = QUIET_MAIL - 1 # count it no matter what 181 182 outstring = to_string(exc.getvalue()) 183 184 # 5/18/05 wregglej - 151158 Go through every string in the security list 185 # and censor it out of the debug information. 186 outstring = censor_string(outstring) 187 188 rhnMail.send(headers, outstring) 189 190 exc.close() 191 return
192 193
194 -def fetchTraceback(method=None, req=None, extra=None, with_locals=0):
195 """ a cheat for snagging just the string value of a Traceback """ 196 exc = StringIO() 197 Traceback(method=method, req=req, mail=0, ostream=exc, extra=extra, 198 severity=None, with_locals=with_locals) 199 return exc.getvalue()
200 201
202 -def exitWithTraceback(e, msg, exitnum, mail=0):
203 tbOut = StringIO() 204 Traceback(mail, ostream=tbOut, with_locals=1) 205 log_error(-1, _('ERROR: %s %s: %s') % 206 (e.__class__.__name__, msg, e)) 207 log_error(-1, _('TRACEBACK: %s') % tbOut.getvalue()) 208 sys.exit(exitnum)
209 210
211 -class SecurityList:
212 213 """ The SecurityList is a list of strings that are censored out of a debug email. 214 Right now it's only used for censoring traceback emails. 215 """ 216 _flag_string = "security-list" 217
218 - def __init__(self):
219 # We store the security list in the global flags. This way, we don't 220 # have to worry about clearing it up. 221 if rhnFlags.test(self._flag_string): 222 self.sec = rhnFlags.get(self._flag_string) 223 else: 224 self.sec = [] 225 rhnFlags.set(self._flag_string, self.sec)
226
227 - def add(self, obj):
228 self.sec.append(obj)
229
230 - def check(self, obj):
231 return obj in self.sec
232 233
234 -def get_seclist():
235 """ Returns the list of strings to be censored. """ 236 return SecurityList().sec
237 238
239 -def censor_string(strval):
240 """ Remove all instances of the strings in seclist.sec from strval """ 241 censorlist = get_seclist() 242 for c in censorlist: 243 # Censor it with a fixed length string. This way the length of the hidden string isn't revealed. 244 strval = strval.replace(c, "<CENSORED!>") 245 return strval
246 247
248 -def add_to_seclist(obj):
249 """ Adds a string to seclist.sec, but only if it's not already there. """ 250 seclist = SecurityList() 251 if not seclist.check(obj): 252 seclist.add(obj)
253