]> git.ipfire.org Git - ipfire.org.git/blame - build/builder.py
[build] Added "jobs" and "log".
[ipfire.org.git] / build / builder.py
CommitLineData
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
22import os
23import sys
24import time
25import socket
10da7ad4 26import base64
2b60fce9
MT
27from pysqlite2 import dbapi2 as sqlite
28
29sys.path.append(".")
30
31from constants import config
32
33class Database:
34 def __init__(self, path):
35 self.db = sqlite.connect(os.path.join(path, config["db_name"]))
36 c = self.cursor()
37 c.executescript("""
38 create table if not exists config(key, value, date);
39 create table if not exists durations(duration);
40 """)
41 c.close()
42
43 def __call__(self):
44 return self.cursor()
45
46 def __del__(self):
47 self.commit()
48 self.db.close()
49
50 def cursor(self):
51 return self.db.cursor()
52
53 def commit(self):
54 self.db.commit()
55
56class DatabaseConfig:
57 def __init__(self, db, key):
58 self.db = db
59 self.key = key
60 self.data = None
61 self.date = None
62
63 def get(self):
64 if not self.data:
65 c = self.db.cursor()
66 c.execute("SELECT value FROM %(table)s WHERE key = '%(key)s'" \
67 % { "table" : "config",
68 "key" : self.key, })
69 try:
70 self.data = c.fetchone()[0]
71 except TypeError:
72 self.data = None
73 c.close()
74 return self.data
75
76 __call__ = get
77
78 def time(self):
79 if not self.date:
80 c = self.db.cursor()
81 c.execute("SELECT date FROM %(table)s WHERE key = '%(key)s'" \
82 % { "table" : "config",
83 "key" : self.key, })
84 try:
85 self.date = float("%s" % c.fetchone()[0])
86 except TypeError:
87 self.date = None
88 c.close()
89 return self.date or float(0)
90
91 def set(self, value):
92 #value = (value,)
93 c = self.db.cursor()
94 if not self.get():
95 sql = "INSERT INTO %(table)s(key, value, date) VALUES('%(key)s', '%(value)s', '%(date)s')" \
96 % { "table" : "config",
97 "key" : self.key,
98 "value" : value,
99 "date" : time.time(), }
100
101 else:
102 sql = "UPDATE %(table)s SET value='%(value)s', date='%(date)s' WHERE key='%(key)s'" \
103 % { "table" : "config",
104 "key" : self.key,
105 "value" : value,
106 "date" : time.time(), }
107 c.execute(sql)
108 c.close()
109 self.data = value
110 self.db.commit()
111
112class DurationsConfig:
113 def __init__(self, db):
114 self.db = db
115
116 def get(self, sort=0):
117 c = self.db.cursor()
118 c.execute("SELECT duration FROM durations")
1e0061eb
MT
119 ret = []
120 for value in c.fetchall():
121 value = int("%s" % value)
122 if value < 5400: # 1,5h
123 continue
124 ret.append(value)
2b60fce9
MT
125 c.close()
126 if sort: ret.sort()
127 return ret
128
129 def set(self, value):
130 #value = (value,)
131 c = self.db.cursor()
132 c.execute("INSERT INTO %(table)s(duration) VALUES('%(value)s')" \
133 % { "table" : "durations",
134 "value" : value, })
135 c.close()
136 self.db.commit()
137
138 def get_avg(self):
139 sum = 0
140 durations = self.get()
141 if not len(durations):
142 return None
143 for value in durations:
1e0061eb 144 sum += value
2b60fce9
MT
145 avg = sum / len(durations)
146 return avg
147
148 def get_eta(self, timestamp):
149 avg = self.get_avg()
150 if not avg:
151 return "N/A"
152 eta = int(timestamp) + avg
153 return time.ctime(eta)
154
155class DistccConfig(DatabaseConfig):
10da7ad4 156 def __init__(self, db, key, hostname, jobs):
2b60fce9
MT
157 DatabaseConfig.__init__(self, db, key)
158 self.hostname = hostname
10da7ad4 159 self.jobs = jobs
2b60fce9
MT
160
161 def __str__(self):
fda98c60 162 if not self.ping() or self.get() == "0":
2b60fce9 163 return ""
10da7ad4
MT
164 return "%s:%s/%s,lzo \t# %s" % \
165 (socket.gethostbyname(self.hostname), self.get(), self.jobs or "4", self.hostname)
2b60fce9
MT
166
167 def ping(self):
168 if not self.hostname:
169 return False
170 return not os.system("ping -c1 -w1 %s &>/dev/null" % self.hostname)
171
172 def version(self):
173 return os.popen("distcc --version").readlines()
174
10da7ad4
MT
175class FileConfig:
176 def __init__(self, path, filetype):
177 self.filename = os.path.join(path, config["path"][filetype])
178
179 # Create the file if not existant
180 if not os.access(self.filename, os.R_OK):
181 f = open(self.filename, "w")
182 f.close()
183
184 def get(self):
185 ret = []
186 try:
187 f = open(self.filename)
188 ret = f.readlines()
189 f.close()
190 except:
191 pass
192 return ret or ["Log is empty."]
193
194 __call__ = get
195
196 def set(self, lines):
197 f = open(self.filename, "w")
198 for line in base64.b64decode(lines).split("\n"):
199 f.write("%s\n" % line.rstrip("\n"))
200 f.close()
201
2b60fce9
MT
202class Builder:
203 def __init__(self, config, uuid):
204 self.uuid = uuid
205 self.config = config
206 self.path = os.path.join(self.config['path']['db'], self.uuid)
207
208 if not os.access(self.path, os.R_OK):
209 try:
210 os.mkdir(self.path)
211 except:
212 pass
213
214 self.db = Database(self.path)
10da7ad4 215
2b60fce9
MT
216 self.hostname = DatabaseConfig(self.db, "hostname")
217 self.state = DatabaseConfig(self.db, "state")
218 self.package = DatabaseConfig(self.db, "package")
10da7ad4 219
2b60fce9 220 self.duration = DurationsConfig(self.db)
10da7ad4
MT
221 self.jobs = DatabaseConfig(self.db, "jobs")
222 self.distcc = DistccConfig(self.db, "distcc", self.hostname(), self.jobs())
223
224 self.log = FileConfig(self.path, "log")
2b60fce9
MT
225
226 def set(self, key, value):
227 eval("self.%s.set(\"%s\")" % (key, value,))
228
229 def get(self, key):
230 return eval("self.%s.get()" % (key,))
231
205adcfe 232def getAllBuilders(age=0):
2b60fce9
MT
233 builders = []
234 for uuid in os.listdir(config["path"]["db"]):
235 if uuid == "empty.txt": continue
236 builder = Builder(config, uuid)
205adcfe
MT
237 # If there was no activity since "age" days -> continue...
238 if age and (time.time() - builder.state.time()) > age*24*60*60:
239 continue
2b60fce9
MT
240 builders.append(builder)
241 return builders