ia64/xen-unstable

view tools/python/xen/util/bugtool.py @ 8159:fbbb8a2a6013

Work around the fact that the physinfo dom0 call is not implemented for IA64.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Thu Dec 01 03:26:47 2005 +0000 (2005-12-01)
parents ec370b3d2df3
children 1caed7031f6b
line source
1 #!/usr/bin/env python
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of version 2.1 of the GNU Lesser General Public
5 # License as published by the Free Software Foundation.
6 #
7 # This library is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 # Lesser General Public License for more details.
11 #
12 # You should have received a copy of the GNU Lesser General Public
13 # License along with this library; if not, write to the Free Software
14 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 #
16 # Copyright (c) 2005, XenSource Ltd.
19 import errno
20 import getpass
21 import httplib
22 import re
23 import os
24 import os.path
25 import StringIO
26 import sys
27 import tarfile
28 import tempfile
29 import time
30 import urllib
32 import xen.lowlevel.xc
34 from xen.xend import encode
37 SERVER = 'bugzilla.xensource.com'
38 SHOW_BUG_PATTERN = 'http://%s/bugzilla/show_bug.cgi?id=%%d' % SERVER
39 ATTACH_PATTERN = \
40 'http://%s/bugzilla/attachment.cgi?bugid=%%d&action=enter' % SERVER
42 TITLE_RE = re.compile(r'<title>(.*)</title>')
44 FILES_TO_SEND = [ '/var/log/syslog', '/var/log/messages', '/var/log/debug',
45 '/var/log/xend.log', '/var/log/xend-debug.log',
46 '/var/log/xenstored-trace.log' ]
47 #FILES_TO_SEND = [ ]
50 def main(argv = None):
51 if argv is None:
52 argv = sys.argv
54 print '''
55 This application will collate the Xen dmesg output, details of the hardware
56 configuration of your machine, information about the build of Xen that you are
57 using, plus, if you allow it, various logs.
59 The information collated can either be posted to a Xen Bugzilla bug (this bug
60 must already exist in the system, and you must be a registered user there), or
61 it can be saved as a .tar.bz2 for sending or archiving.
63 The collated logs may contain private information, and if you are at all
64 worried about that, you should exit now, or you should explicitly exclude
65 those logs from the archive.
67 '''
69 bugball = []
71 xc = xen.lowlevel.xc.xc()
73 def do(n, f):
74 try:
75 s = f()
76 except Exception, exn:
77 s = str(exn)
78 bugball.append(string_iterator(n, s))
80 do('xen-dmesg', lambda: xc.readconsolering())
81 do('physinfo', lambda: prettyDict(xc.physinfo()))
82 do('xeninfo', lambda: prettyDict(xc.xeninfo()))
84 for filename in FILES_TO_SEND:
85 if not os.path.exists(filename):
86 continue
88 if yes('Include %s? [Y/n] ' % filename):
89 bugball.append(file(filename))
91 maybeAttach(bugball)
93 if (yes('''
94 Do you wish to save these details as a tarball (.tar.bz2)? [Y/n] ''')):
95 tar(bugball)
97 return 0
100 def maybeAttach(bugball):
101 if not yes('''
102 Do you wish to attach these details to a Bugzilla bug? [Y/n] '''):
103 return
105 bug = int(raw_input('Bug number? '))
107 bug_title = getBugTitle(bug)
109 if bug_title == 'Search by bug number' or bug_title == 'Invalid Bug ID':
110 print >>sys.stderr, 'Bug %d does not exist!' % bug
111 maybeAttach(bugball)
112 elif yes('Are you sure that you want to attach to %s? [Y/n] ' %
113 bug_title):
114 attach(bug, bugball)
115 else:
116 maybeAttach(bugball)
119 def attach(bug, bugball):
120 username = raw_input('Bugzilla username: ')
121 password = getpass.getpass('Bugzilla password: ')
123 conn = httplib.HTTPConnection(SERVER)
124 try:
125 for f in bugball:
126 send(bug, conn, f, f.name, username, password)
127 finally:
128 conn.close()
131 def getBugTitle(bug):
132 f = urllib.urlopen(SHOW_BUG_PATTERN % bug)
134 try:
135 for line in f:
136 m = TITLE_RE.search(line)
137 if m:
138 return m.group(1)
139 finally:
140 f.close()
142 raise "Could not find title of bug %d!" % bug
145 def send(bug, conn, fd, filename, username, password):
147 print "Attaching %s to bug %d." % (filename, bug)
149 headers, data = encode.encode_data(
150 { 'bugid' : str(bug),
151 'action' : 'insert',
152 'data' : fd,
153 'description' : '%s from %s' % (filename, username),
154 'contenttypeselection' : 'text/plain',
155 'contenttypemethod' : 'list',
156 'ispatch' : '0',
157 'GoAheadAndLogIn' : '1',
158 'Bugzilla_login' : username,
159 'Bugzilla_password' : password,
160 })
162 conn.request('POST',ATTACH_PATTERN % bug, data, headers)
163 response = conn.getresponse()
164 try:
165 body = response.read()
166 m = TITLE_RE.search(body)
168 if response.status != 200:
169 print >>sys.stderr, (
170 'Attach failed: %s %s.' % (response.status, response.reason))
171 elif not m or m.group(1) != 'Changes Submitted':
172 print >>sys.stderr, (
173 'Attach failed: got a page titled %s.' % m.group(1))
174 else:
175 print "Attaching %s to bug %d succeeded." % (filename, bug)
176 finally:
177 response.close()
180 def tar(bugball):
181 filename = raw_input('Tarball destination filename? ')
183 now = time.time()
185 tf = tarfile.open(filename, 'w:bz2')
187 try:
188 for f in bugball:
189 ti = tarfile.TarInfo(f.name.split('/')[-1])
190 if hasattr(f, 'size'):
191 ti.size = f.size()
192 else:
193 ti.size = os.stat(f.name).st_size
195 ti.mtime = now
196 ti.type = tarfile.REGTYPE
197 ti.uid = 0
198 ti.gid = 0
199 ti.uname = 'root'
200 ti.gname = 'root'
202 f.seek(0) # If we've added this file to a bug, it will have been
203 # read once already, so reset it.
204 tf.addfile(ti, f)
205 finally:
206 tf.close()
208 print 'Writing tarball %s successful.' % filename
211 def prettyDict(d):
212 format = '%%-%ds: %%s' % max(map(len, [k for k, _ in d.items()]))
213 return '\n'.join([format % i for i in d.items()]) + '\n'
216 class string_iterator(StringIO.StringIO):
217 def __init__(self, name, val):
218 StringIO.StringIO.__init__(self, val)
219 self.name = name
221 def size(self):
222 return len(self.getvalue())
225 def yes(prompt):
226 yn = raw_input(prompt)
228 return len(yn) == 0 or yn.lower()[0] == 'y'
231 if __name__ == "__main__":
232 sys.exit(main())