tracker: Add workaround for our natted seeder.
[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
c9698a0b
MT
97 @property
98 def basename(self):
99 return os.path.basename(self.filename)
100
940227cb
MT
101
102class Release(object):
103 @property
104 def db(self):
105 return Releases().db
106
107 def __init__(self, id):
108 self.id = id
109
110 # get all data from database
111 self.__data = \
112 self.db.get("SELECT * FROM releases WHERE id = %s", self.id)
113 assert self.__data
114
115 self.__files = []
116
117 def __repr__(self):
118 return "<%s %s>" % (self.__class__.__name__, self.name)
119
120 @property
121 def files(self):
122 if not self.__files:
123 files = self.db.query("SELECT id FROM files WHERE releases = %s \
124 AND loadable = 'Y'", self.id)
125
126 self.__files = [File(self, f.id) for f in files]
127 self.__files.sort(lambda a, b: cmp(a.prio, b.prio))
128
129 return self.__files
130
131 @property
132 def name(self):
133 return self.__data.get("name")
134
135 @property
136 def stable(self):
137 return self.__data.get("stable")
138
139 @property
140 def published(self):
141 return self.__data.get("published")
142
143 @property
144 def date(self):
145 return self.__data.get("date")
146
3c4f2edc
MT
147 @property
148 def path(self):
149 return self.__data.get("path")
150
940227cb
MT
151 @property
152 def torrent_hash(self):
153 h = self.__data.get("torrent_hash")
154 if h:
155 return h.lower()
156
157 def get_file(self, type):
158 for file in self.files:
159 if file.type == type:
160 return file
161
3c4f2edc
MT
162 def __file_hash(self, filename):
163 sha1 = hashlib.sha1()
164
165 with open(filename) as f:
166 sha1.update(f.read())
167
168 return sha1.hexdigest()
169
170 def __guess_filetype(self, filename):
171 if filename.endswith(".iso"):
172 return "iso"
173
174 if filename.endswith(".torrent"):
175 return "torrent"
176
177 if "xen" in filename:
178 return "xen"
179
180 if "sources" in filename:
181 return "source"
182
183 if "usb-fdd" in filename:
184 return "usbfdd"
185
186 if "usb-hdd" in filename:
187 return "usbhdd"
188
189 if "scon" in filename:
190 return "alix"
191
192 if filename.endswith(".img.gz"):
193 return "flash"
194
195 return "unknown"
196
197 def scan_files(self, basepath="/srv/mirror0"):
198 if not self.path:
199 return
200
201 path = os.path.join(basepath, self.path)
202
203 files = [f.filename for f in self.files]
204
205 # Make files that do not exists not loadable.
206 for filename in files:
207 _filename = os.path.join(basepath, filename)
208 if not os.path.exists(_filename):
209 self.db.execute("UPDATE files SET loadable='N' WHERE filename = %s", filename)
210
211 for filename in os.listdir(path):
212 filename = os.path.join(path, filename)
213
214 if os.path.isdir(filename):
215 continue
216
217 _filename = re.match(".*(releases/.*)", filename).group(1)
218 if _filename in files:
219 continue
220
221 if filename.endswith(".md5"):
222 continue
223
224 filehash = self.__file_hash(filename)
225 filesize = os.path.getsize(filename)
226 filetype = self.__guess_filetype(filename)
227
228 self.db.execute("""INSERT INTO files(releases, filename, filesize, filetype, sha1)
229 VALUES(%s, %s, %s, %s, %s)""", self.id, _filename, filesize, filetype, filehash)
230
940227cb
MT
231
232class Releases(object):
233 __metaclass__ = Singleton
234
235 @property
236 def db(self):
237 return Databases().webapp
238
239 def list(self):
240 return [Release(r.id) for r in self.db.query("SELECT id FROM releases ORDER BY date DESC")]
241
242 def get_by_id(self, id):
243 id = int(id)
244 if id in [r.id for r in self.db.query("SELECT id FROM releases")]:
245 return Release(id)
246
247 def get_latest(self, stable=1):
248 query = "SELECT id FROM releases WHERE published='Y' AND"
249 if stable:
250 query += " stable='Y'"
251 else:
252 query += " stable='N'"
253
254 query += " ORDER BY date DESC LIMIT 1"
255
256 release = self.db.get(query)
257 if release:
258 return Release(release.id)
259
260 def get_stable(self):
261 releases = self.db.query("""SELECT id FROM releases
262 WHERE published='Y' AND stable='Y'
263 ORDER BY date DESC""")
264
265 return [Release(r.id) for r in releases]
266
267 def get_unstable(self):
268 releases = self.db.query("""SELECT id FROM releases
269 WHERE published='Y' AND stable='N'
270 ORDER BY date DESC""")
271
272 return [Release(r.id) for r in releases]
273
274 def get_all(self):
275 releases = self.db.query("""SELECT id FROM releases
276 WHERE published='Y' ORDER BY date DESC""")
277
278 return [Release(r.id) for r in releases]
279
280
281if __name__ == "__main__":
282 r = Releases()
283
284 for release in r.get_all():
285 print release.name
286
287 print r.get_latest()