]>
Commit | Line | Data |
---|---|---|
2b60fce9 MT |
1 | #!/usr/bin/python |
2 | ############################################################################### | |
3 | # # | |
4 | # IPFire.org - A linux based firewall # | |
5 | # Copyright (C) 2008 Michael Tremer & Christian Schmidt # | |
6 | # # | |
7 | # This program is free software: you can redistribute it and/or modify # | |
8 | # it under the terms of the GNU General Public License as published by # | |
9 | # the Free Software Foundation, either version 3 of the License, or # | |
10 | # (at your option) any later version. # | |
11 | # # | |
12 | # This program is distributed in the hope that it will be useful, # | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
15 | # GNU General Public License for more details. # | |
16 | # # | |
17 | # You should have received a copy of the GNU General Public License # | |
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
19 | # # | |
20 | ############################################################################### | |
21 | ||
22 | import os | |
23 | import sys | |
24 | import time | |
25 | ||
26 | sys.path.append(".") | |
27 | ||
28 | from builder import Builder, getAllBuilders | |
29 | from constants import * | |
30 | ||
31 | def format_time(seconds, use_hours=1): | |
32 | if seconds is None or seconds < 0: | |
33 | if use_hours: return '--:--:--' | |
34 | else: return '--:--' | |
35 | else: | |
36 | seconds = int(seconds) | |
37 | minutes = seconds / 60 | |
38 | seconds = seconds % 60 | |
39 | if use_hours: | |
40 | hours = minutes / 60 | |
41 | minutes = minutes % 60 | |
42 | return '%02i:%02i:%02i' % (hours, minutes, seconds) | |
43 | else: | |
44 | return '%02i:%02i' % (minutes, seconds) | |
45 | ||
46 | class Site: | |
47 | def __init__(self, config): | |
48 | self.builders = None | |
49 | self.config = config | |
50 | print "Content-type: text/html" | |
51 | ||
52 | ||
53 | def __call__(self, builders=None): | |
54 | self.builders = builders | |
55 | print """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" | |
56 | "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | |
57 | <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> | |
58 | <head> | |
59 | <title>%(title)s</title> | |
60 | <style type="text/css"> | |
61 | * { | |
62 | margin: auto; | |
63 | padding: 0; | |
64 | text-decoration: none; | |
65 | outline: none; | |
66 | } | |
67 | body { | |
68 | font-family: Verdana; | |
69 | font-size: 90%%; | |
70 | background-color:#f9f9f9; | |
71 | } | |
72 | h1 { | |
73 | text-decoration: underline; | |
74 | } | |
75 | #header { | |
76 | width: 800px; | |
2b60fce9 MT |
77 | text-align: center; |
78 | background: #E0E0E0; | |
79 | border: 1px solid #999; | |
80 | padding-top: 10px; | |
f3fdc4c6 | 81 | padding-bottom: 5px; |
2b60fce9 MT |
82 | } |
83 | #content { | |
84 | padding-top: 10px; | |
85 | width: 800px; | |
86 | } | |
87 | div.box { | |
88 | padding: 5px; | |
89 | margin: 10px 0 10px 0; | |
10da7ad4 | 90 | /* height: 80px; */ |
2b60fce9 MT |
91 | border: 1px solid; |
92 | } | |
93 | div.infobox { | |
94 | float: right; | |
95 | width: 240px; | |
96 | } | |
10da7ad4 MT |
97 | div.log { |
98 | background: #e55; | |
99 | border: 1px dotted; | |
100 | margin-top: 12px; | |
101 | /* visibility: hidden; */ | |
599cd3bb MT |
102 | height: 150px; |
103 | overflow: auto; | |
10da7ad4 MT |
104 | } |
105 | div.log p { | |
106 | font-family: Courier New; | |
107 | } | |
0e744e5a MT |
108 | div.footer { |
109 | } | |
110 | div.footer p { | |
111 | text-align: center; | |
112 | font-size: 5px; | |
113 | } | |
2b60fce9 MT |
114 | p { |
115 | margin: 2px; | |
116 | } | |
117 | p.boxheader { | |
118 | font-weight: bold; | |
119 | } | |
120 | p.online { | |
121 | color: green; | |
122 | } | |
123 | p.offline { | |
124 | color: red; | |
125 | } | |
126 | p.package { | |
127 | font: bold; | |
128 | font-size: 150%%; | |
129 | } | |
130 | img.right { | |
131 | float: right; | |
132 | } | |
133 | p.desc { | |
134 | text-decoration: bold; | |
135 | } | |
136 | a:link { | |
137 | color: black; text-decoration: none; | |
138 | } | |
139 | a:visited { | |
140 | color: black; text-decoration: none; | |
141 | } | |
142 | </style> | |
143 | <meta http-equiv="refresh" content="90; URL=%(script)s" /> | |
144 | </head> | |
145 | <body> | |
146 | <div id="header"> | |
147 | <h1>IPFire Builder</h1>""" % self.config | |
2b60fce9 MT |
148 | for i in self.config["nightly_url"]: |
149 | print """\ | |
150 | <p><a href="%s" target="_blank">%s</a></p>""" % (i, i,) | |
151 | print """\ | |
152 | </div>""" | |
153 | ||
154 | self.content() | |
155 | ||
156 | print "\t\t</body>\n</html>" | |
157 | ||
158 | def content(self): | |
159 | if self.builders: | |
2b60fce9 MT |
160 | print """\ |
161 | <div id="content">""" | |
162 | for builder in self.builders: | |
f006517e | 163 | builder() |
2b60fce9 MT |
164 | print """\ |
165 | </div>""" | |
166 | ||
167 | class Box: | |
168 | def __init__(self, builder): | |
f006517e MT |
169 | self.builder = builder |
170 | self.points = POINTS_UNKNOWN | |
2b60fce9 | 171 | |
f006517e MT |
172 | def __cmp__(self, other): |
173 | if self.points > other.points: | |
174 | return -1 | |
175 | elif self.points == other.points: | |
176 | return 0 | |
177 | elif self.points < other.points: | |
178 | return 1 | |
179 | ||
2b60fce9 MT |
180 | def __str__(self): |
181 | return """<a href="#%(hostname)s">%(hostname)s</a>""" % { "hostname" : self.builder.hostname(), } | |
182 | ||
f006517e MT |
183 | def open_bigbox(self): |
184 | print """<a name="%s"></a><div class="box" style="%s">""" \ | |
185 | % (self.builder.hostname(), state2style[self.builder.state()],) | |
186 | ||
187 | def open_infobox(self): | |
188 | print """<div class="infobox">""" | |
189 | ||
190 | def close_bigbox(self): | |
191 | print """</div>""" | |
192 | ||
193 | close_infobox = close_bigbox | |
194 | ||
2b60fce9 | 195 | def header(self): |
f006517e MT |
196 | print """<p class="boxheader">%(hostname)s <span>[%(uuid)s]</span></p>""" \ |
197 | % { "hostname" : self.builder.hostname(), | |
198 | "state" : self.builder.state(), | |
199 | "uuid" : self.builder.uuid, } | |
2b60fce9 MT |
200 | |
201 | def package(self): | |
202 | if self.builder.state() in [ "compiling", "error", ]: | |
203 | print """\ | |
204 | <p class="package">%s</p>"""\ | |
205 | % self.builder.package() | |
206 | ||
207 | def time(self): | |
f006517e MT |
208 | print """<p>%s</p>""" \ |
209 | % time.ctime(float(self.builder.state.time())) | |
2b60fce9 MT |
210 | |
211 | def stateinfo(self): | |
f006517e MT |
212 | print """<p class="desc">%s</p>""" \ |
213 | % statedesc[self.builder.state()] | |
2b60fce9 MT |
214 | |
215 | def durations(self): | |
f006517e MT |
216 | print """<p>Average Build Duration: %s</p>""" \ |
217 | % format_time(self.builder.duration.get_avg()) | |
2b60fce9 | 218 | if self.builder.state() == "compiling": |
f006517e | 219 | print """<p>ETA: %s</p>""" \ |
2b60fce9 MT |
220 | % self.builder.duration.get_eta(self.builder.state.time()) |
221 | ||
222 | def distccinfo(self): | |
223 | state = self.builder.distcc.ping() | |
fda98c60 MT |
224 | port = self.builder.distcc() |
225 | if port == "0": | |
226 | state = False | |
227 | port = "disabled" | |
f006517e | 228 | print """<p class="%s">Distcc: %s</p>""" \ |
fda98c60 | 229 | % (ping2class[state], port,) |
10da7ad4 MT |
230 | |
231 | def log(self): | |
232 | log = self.builder.log() | |
233 | if log: | |
f006517e | 234 | print """<div class="log"><p>""" |
599cd3bb | 235 | print "<br />".join(log) |
f006517e | 236 | print """</p></div>""" |
2b60fce9 | 237 | |
0e744e5a | 238 | def footer(self): |
599cd3bb MT |
239 | print """<div class="footer"><p>system: %s - cpu: %s <br /> machine: %s - target: %s - jobs: %s - toolchain: %s</p></div>""" \ |
240 | % (self.builder.system(), self.builder.cpu(), self.builder.machine(), self.builder.target(), self.builder.jobs(), self.builder.toolchain(),) | |
f006517e MT |
241 | |
242 | class BoxCompiling(Box): | |
243 | def __init__(self, builder): | |
244 | Box.__init__(self, builder) | |
245 | self.points = POINTS_COMPILING | |
246 | ||
247 | def __call__(self): | |
248 | self.open_bigbox() | |
249 | self.open_infobox() | |
250 | self.distccinfo() | |
251 | self.package() | |
252 | self.time() | |
253 | self.close_infobox() | |
254 | self.header() | |
255 | self.stateinfo() | |
256 | self.durations() | |
257 | self.footer() | |
258 | self.close_bigbox() | |
259 | ||
260 | class BoxError(Box): | |
261 | def __init__(self, builder): | |
262 | Box.__init__(self, builder) | |
263 | self.points = POINTS_ERROR | |
264 | ||
265 | def __call__(self): | |
266 | self.open_bigbox() | |
267 | self.open_infobox() | |
268 | self.distccinfo() | |
269 | self.package() | |
270 | self.time() | |
271 | self.close_infobox() | |
272 | self.header() | |
273 | self.stateinfo() | |
274 | self.durations() | |
275 | self.log() | |
276 | self.footer() | |
277 | self.close_bigbox() | |
278 | ||
279 | class BoxDistcc(Box): | |
280 | def __init__(self, builder): | |
281 | Box.__init__(self, builder) | |
282 | self.points = POINTS_DISTCC | |
283 | ||
284 | def __call__(self): | |
285 | self.open_bigbox() | |
286 | self.open_infobox() | |
287 | self.distccinfo() | |
288 | self.time() | |
289 | self.close_infobox() | |
290 | self.header() | |
291 | self.stateinfo() | |
292 | self.durations() | |
293 | self.footer() | |
294 | self.close_bigbox() | |
295 | ||
296 | class BoxIdle(Box): | |
297 | def __init__(self, builder): | |
298 | Box.__init__(self, builder) | |
299 | self.points = POINTS_IDLE | |
300 | ||
301 | def __call__(self): | |
302 | self.open_bigbox() | |
303 | self.open_infobox() | |
304 | self.distccinfo() | |
305 | self.time() | |
306 | self.close_infobox() | |
307 | self.header() | |
308 | self.stateinfo() | |
309 | self.durations() | |
310 | self.footer() | |
311 | self.close_bigbox() | |
0e744e5a | 312 | |
2b60fce9 MT |
313 | site = Site(config) |
314 | ||
315 | boxes = [] | |
f006517e MT |
316 | for builder in getAllBuilders(): |
317 | box = None | |
318 | if builder.state() == "compiling": | |
319 | box = BoxCompiling(builder) | |
320 | elif builder.state() == "error": | |
321 | box = BoxError(builder) | |
322 | elif builder.state() == "idle": | |
323 | box = BoxIdle(builder) | |
324 | elif builder.state() == "distcc": | |
325 | if builder.distcc() == "0": | |
326 | continue | |
327 | box = BoxDistcc(builder) | |
328 | if box: | |
329 | boxes.append(box) | |
2b60fce9 | 330 | |
f006517e | 331 | boxes.sort() |
2b60fce9 | 332 | site(boxes) |