1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 import os
18 import sys
19 import time
20 import traceback
21 import socket
22 try:
23
24 from StringIO import StringIO
25 except ImportError:
26
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
38 hostname = socket.gethostname()
39
40
41
42
43
44 QUIET_MAIL = None
45
46
48 """ Dump the environment. """
49 dct = os.environ
50 fd.write("\nEnvironment for PID=%d on exception:\n" % os.getpid())
51 el = list(dct.keys())
52 el.sort()
53 for k in el:
54 fd.write("%s = %s\n" % (to_string(k), to_string(dct[k])))
55
56
58 """ Dump a listing of all local variables and their value for better debugging
59 chance.
60 """
61 if tb is None:
62 tb = sys.exc_info()[2]
63 stack = []
64
65 while 1:
66 if not tb.tb_next:
67 break
68 tb = tb.tb_next
69
70 f = tb.tb_frame
71 while f:
72 stack.append(f)
73 f = f.f_back
74 fd.write("\nLocal variables by frame\n")
75 for frame in stack:
76 fd.write("Frame %s in %s at line %s\n" % (frame.f_code.co_name,
77 frame.f_code.co_filename,
78 frame.f_lineno))
79 for key, value in frame.f_locals.items():
80 fd.write("\t%20s = " % to_string(key))
81
82
83
84
85 try:
86 s = str(to_string(value))
87 except:
88 s = "<ERROR WHILE PRINTING VALUE>"
89 if len(s) > 100 * 1024:
90 s = "<ERROR WHILE PRINTING VALUE: string representation too large>"
91 fd.write("%s %s\n" % (type(value), s))
92 fd.write("\n")
93
94
96 """ get some debugging information about the current exception for sending
97 out when we raise an exception
98 """
99
100 fd.write("Request object information:\n")
101 fd.write("URI: %s\n" % req.unparsed_uri)
102 fd.write("Remote Host: %s\nServer Name: %s:%d\n" % (
103 req.get_remote_host(), req.server.server_hostname, req.server.port))
104 fd.write("Headers passed in:\n")
105 kl = list(req.headers_in.keys())
106 kl.sort()
107 for k in kl:
108 fd.write("\t%s: %s\n" % (to_string(k), to_string(req.headers_in[k])))
109 return 0
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
118
119 global QUIET_MAIL
120
121 if mail:
122
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:
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
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
148 exc.write("\nException Handler Information\n")
149 traceback.print_exc(None, exc)
150
151 if with_locals and not mail:
152
153 print_locals(exc)
154
155
156 if ostream:
157 ostream.write(to_string(exc.getvalue()))
158 ostream.write("\n")
159
160 if mail:
161
162 print_locals(exc)
163
164 print_env(exc)
165
166
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
181
182 outstring = to_string(exc.getvalue())
183
184
185
186 outstring = censor_string(outstring)
187
188 rhnMail.send(headers, outstring)
189
190 exc.close()
191 return
192
193
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
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
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
226
227 - def add(self, obj):
229
231 return obj in self.sec
232
233
235 """ Returns the list of strings to be censored. """
236 return SecurityList().sec
237
238
240 """ Remove all instances of the strings in seclist.sec from strval """
241 censorlist = get_seclist()
242 for c in censorlist:
243
244 strval = strval.replace(c, "<CENSORED!>")
245 return strval
246
247
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