]> git.ipfire.org Git - ipfire.org.git/blob - build/builder.py
Save $TARGET in database.
[ipfire.org.git] / build / builder.py
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 import socket
26 import base64
27 from pysqlite2 import dbapi2 as sqlite
28
29 sys.path.append(".")
30
31 from constants import config
32
33 class 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
56 class 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
112 class 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")
119 ret = []
120 for value in c.fetchall():
121 value = int("%s" % value)
122 if value < 900: # 15min
123 continue
124 ret.append(value)
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:
144 sum += value
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
155 class DistccConfig(DatabaseConfig):
156 def __init__(self, db, key, hostname, jobs):
157 DatabaseConfig.__init__(self, db, key)
158 self.hostname = hostname
159 self.jobs = jobs
160
161 def __str__(self):
162 if not self.ping() or self.get() == "0":
163 return ""
164 return "%s:%s/%s,lzo \t# %s" % \
165 (socket.gethostbyname(self.hostname), self.get(), self.jobs or "4", self.hostname)
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
175 class 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
202 class 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)
215
216 self.hostname = DatabaseConfig(self.db, "hostname")
217 self.state = DatabaseConfig(self.db, "state")
218 self.package = DatabaseConfig(self.db, "package")
219 self.target = DatabaseConfig(self.db, "target")
220
221 self.duration = DurationsConfig(self.db)
222 self.jobs = DatabaseConfig(self.db, "jobs")
223 self.distcc = DistccConfig(self.db, "distcc", self.hostname(), self.jobs())
224
225 self.log = FileConfig(self.path, "log")
226
227 def set(self, key, value):
228 eval("self.%s.set(\"%s\")" % (key, value,))
229
230 def get(self, key):
231 return eval("self.%s.get()" % (key,))
232
233 def getAllBuilders(age=0):
234 builders = []
235 for uuid in os.listdir(config["path"]["db"]):
236 if uuid == "empty.txt": continue
237 builder = Builder(config, uuid)
238 # If there was no activity since "age" days -> continue...
239 if age and (time.time() - builder.state.time()) > age*24*60*60:
240 continue
241 builders.append(builder)
242 return builders