Add job that updates the file database from the main mirror.
[people/shoehn/ipfire.org.git] / www / webapp / backend / releases.py
CommitLineData
940227cb
MT
1#!/usr/bin/python
2
3c4f2edc 3import hashlib
940227cb 4import logging
3c4f2edc
MT
5import os
6import re
940227cb
MT
7import urlparse
8
9from databases import Databases
10from misc import Singleton
11from settings import Settings
12
13class File(object):
14 def __init__(self, release, id):
15 self.release = release
16
17 # get all data from database
18 self.__data = self.db.get("SELECT * FROM files WHERE id = %s", id)
19
20 @property
21 def db(self):
22 return self.release.db
23
24 @property
25 def type(self):
26 return self.__data.get("filetype")
27
28 @property
29 def url(self):
30 baseurl = Settings().get("download_url")
31
32 return urlparse.urljoin(baseurl, self.filename)
33
34 @property
35 def desc(self):
36 _ = lambda x: x
37
38 descriptions = {
39 "iso" : _("Installable CD image"),
40 "torrent" : _("Torrent file"),
41 "flash" : _("Flash image"),
42 "alix" : _("Alix image"),
43 "usbfdd" : _("USB FDD Image"),
44 "usbhdd" : _("USB HDD Image"),
45 "xen" : _("Pregenerated Xen image"),
46 }
47
48 try:
49 return descriptions[self.type]
50 except KeyError:
51 return _("Unknown image type")
52
53 @property
54 def prio(self):
55 priorities = {
56 "iso" : 10,
57 "torrent" : 20,
58 "flash" : 40,
59 "alix" : 41,
60 "usbfdd" : 31,
61 "usbhdd" : 30,
62 "xen" : 50,
63 }
64
65 try:
66 return priorities[self.type]
67 except KeyError:
68 return 999
69
70 @property
71 def rem(self):
72 _ = lambda x: x
73
74 remarks = {
75 "iso" : _("Use this image to burn a CD and install IPFire from it."),
76 "torrent" : _("Download the CD image from the torrent network."),
77 "flash" : _("An image that is meant to run on embedded devices."),
78 "alix" : _("Flash image where a serial console is enabled by default."),
79 "usbfdd" : _("Install IPFire from a floppy-formated USB key."),
80 "usbhdd" : _("If the floppy image doesn't work, use this image instead."),
81 "xen" : _("A ready-to-run image for Xen."),
82 }
83
84 try:
85 return remarks[self.type]
86 except KeyError:
87 return _("Unknown image type")
88
89 @property
90 def sha1(self):
91 return self.__data.get("sha1")
92
93 @property
94 def filename(self):
95 return self.__data.get("filename")
96
97
98class Release(object):
99 @property
100 def db(self):
101 return Releases().db
102
103 def __init__(self, id):
104 self.id = id
105
106 # get all data from database
107 self.__data = \
108 self.db.get("SELECT * FROM releases WHERE id = %s", self.id)
109 assert self.__data
110
111 self.__files = []
112
113 def __repr__(self):
114 return "<%s %s>" % (self.__class__.__name__, self.name)
115
116 @property
117 def files(self):
118 if not self.__files:
119 files = self.db.query("SELECT id FROM files WHERE releases = %s \
120 AND loadable = 'Y'", self.id)
121
122 self.__files = [File(self, f.id) for f in files]
123 self.__files.sort(lambda a, b: cmp(a.prio, b.prio))
124
125 return self.__files
126
127 @property
128 def name(self):
129 return self.__data.get("name")
130
131 @property
132 def stable(self):
133 return self.__data.get("stable")
134
135 @property
136 def published(self):
137 return self.__data.get("published")
138
139 @property
140 def date(self):
141 return self.__data.get("date")
142
3c4f2edc
MT
143 @property
144 def path(self):
145 return self.__data.get("path")
146
940227cb
MT
147 @property
148 def torrent_hash(self):
149 h = self.__data.get("torrent_hash")
150 if h:
151 return h.lower()
152
153 def get_file(self, type):
154 for file in self.files:
155 if file.type == type:
156 return file
157
3c4f2edc
MT
158 def __file_hash(self, filename):
159 sha1 = hashlib.sha1()
160
161 with open(filename) as f:
162 sha1.update(f.read())
163
164 return sha1.hexdigest()
165
166 def __guess_filetype(self, filename):
167 if filename.endswith(".iso"):
168 return "iso"
169
170 if filename.endswith(".torrent"):
171 return "torrent"
172
173 if "xen" in filename:
174 return "xen"
175
176 if "sources" in filename:
177 return "source"
178
179 if "usb-fdd" in filename:
180 return "usbfdd"
181
182 if "usb-hdd" in filename:
183 return "usbhdd"
184
185 if "scon" in filename:
186 return "alix"
187
188 if filename.endswith(".img.gz"):
189 return "flash"
190
191 return "unknown"
192
193 def scan_files(self, basepath="/srv/mirror0"):
194 if not self.path:
195 return
196
197 path = os.path.join(basepath, self.path)
198
199 files = [f.filename for f in self.files]
200
201 # Make files that do not exists not loadable.
202 for filename in files:
203 _filename = os.path.join(basepath, filename)
204 if not os.path.exists(_filename):
205 self.db.execute("UPDATE files SET loadable='N' WHERE filename = %s", filename)
206
207 for filename in os.listdir(path):
208 filename = os.path.join(path, filename)
209
210 if os.path.isdir(filename):
211 continue
212
213 _filename = re.match(".*(releases/.*)", filename).group(1)
214 if _filename in files:
215 continue
216
217 if filename.endswith(".md5"):
218 continue
219
220 filehash = self.__file_hash(filename)
221 filesize = os.path.getsize(filename)
222 filetype = self.__guess_filetype(filename)
223
224 self.db.execute("""INSERT INTO files(releases, filename, filesize, filetype, sha1)
225 VALUES(%s, %s, %s, %s, %s)""", self.id, _filename, filesize, filetype, filehash)
226
940227cb
MT
227
228class Releases(object):
229 __metaclass__ = Singleton
230
231 @property
232 def db(self):
233 return Databases().webapp
234
235 def list(self):
236 return [Release(r.id) for r in self.db.query("SELECT id FROM releases ORDER BY date DESC")]
237
238 def get_by_id(self, id):
239 id = int(id)
240 if id in [r.id for r in self.db.query("SELECT id FROM releases")]:
241 return Release(id)
242
243 def get_latest(self, stable=1):
244 query = "SELECT id FROM releases WHERE published='Y' AND"
245 if stable:
246 query += " stable='Y'"
247 else:
248 query += " stable='N'"
249
250 query += " ORDER BY date DESC LIMIT 1"
251
252 release = self.db.get(query)
253 if release:
254 return Release(release.id)
255
256 def get_stable(self):
257 releases = self.db.query("""SELECT id FROM releases
258 WHERE published='Y' AND stable='Y'
259 ORDER BY date DESC""")
260
261 return [Release(r.id) for r in releases]
262
263 def get_unstable(self):
264 releases = self.db.query("""SELECT id FROM releases
265 WHERE published='Y' AND stable='N'
266 ORDER BY date DESC""")
267
268 return [Release(r.id) for r in releases]
269
270 def get_all(self):
271 releases = self.db.query("""SELECT id FROM releases
272 WHERE published='Y' ORDER BY date DESC""")
273
274 return [Release(r.id) for r in releases]
275
276
277if __name__ == "__main__":
278 r = Releases()
279
280 for release in r.get_all():
281 print release.name
282
283 print r.get_latest()