manager: Fix crash is release directory does not exist, yet.
[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
921d98cc
MT
203 if not os.path.exists(path):
204 return
205
3c4f2edc
MT
206 files = [f.filename for f in self.files]
207
208 # Make files that do not exists not loadable.
209 for filename in files:
210 _filename = os.path.join(basepath, filename)
211 if not os.path.exists(_filename):
212 self.db.execute("UPDATE files SET loadable='N' WHERE filename = %s", filename)
213
214 for filename in os.listdir(path):
215 filename = os.path.join(path, filename)
216
217 if os.path.isdir(filename):
218 continue
219
220 _filename = re.match(".*(releases/.*)", filename).group(1)
221 if _filename in files:
222 continue
223
224 if filename.endswith(".md5"):
225 continue
226
227 filehash = self.__file_hash(filename)
228 filesize = os.path.getsize(filename)
229 filetype = self.__guess_filetype(filename)
230
231 self.db.execute("""INSERT INTO files(releases, filename, filesize, filetype, sha1)
232 VALUES(%s, %s, %s, %s, %s)""", self.id, _filename, filesize, filetype, filehash)
233
940227cb
MT
234
235class Releases(object):
236 __metaclass__ = Singleton
237
238 @property
239 def db(self):
240 return Databases().webapp
241
242 def list(self):
243 return [Release(r.id) for r in self.db.query("SELECT id FROM releases ORDER BY date DESC")]
244
245 def get_by_id(self, id):
246 id = int(id)
247 if id in [r.id for r in self.db.query("SELECT id FROM releases")]:
248 return Release(id)
249
250 def get_latest(self, stable=1):
251 query = "SELECT id FROM releases WHERE published='Y' AND"
252 if stable:
253 query += " stable='Y'"
254 else:
255 query += " stable='N'"
256
257 query += " ORDER BY date DESC LIMIT 1"
258
259 release = self.db.get(query)
260 if release:
261 return Release(release.id)
262
263 def get_stable(self):
264 releases = self.db.query("""SELECT id FROM releases
265 WHERE published='Y' AND stable='Y'
266 ORDER BY date DESC""")
267
268 return [Release(r.id) for r in releases]
269
270 def get_unstable(self):
271 releases = self.db.query("""SELECT id FROM releases
272 WHERE published='Y' AND stable='N'
273 ORDER BY date DESC""")
274
275 return [Release(r.id) for r in releases]
276
277 def get_all(self):
278 releases = self.db.query("""SELECT id FROM releases
279 WHERE published='Y' ORDER BY date DESC""")
280
281 return [Release(r.id) for r in releases]
282
283
284if __name__ == "__main__":
285 r = Releases()
286
287 for release in r.get_all():
288 print release.name
289
290 print r.get_latest()