]> git.ipfire.org Git - people/shoehn/ipfire.org.git/blame - webapp/handlers_fireinfo.py
adjust touch target on mobile Feature page
[people/shoehn/ipfire.org.git] / webapp / handlers_fireinfo.py
CommitLineData
66862195
MT
1#!/usr/bin/python
2
3from __future__ import division
4
5import datetime
6import hwdata
7import logging
8import re
9import simplejson
10import tornado.web
11
12import backend
13
14from handlers_base import *
15
16class FireinfoBaseHandler(BaseHandler):
17 def cut_string(self, s, limit=15):
18 if len(s) > limit:
19 s = s[:limit] + "..."
20
21 return s
22
23 def render(self, *args, **kwargs):
24 kwargs.update({
25 "cut_string" : self.cut_string,
26 })
27
28 return BaseHandler.render(self, *args, **kwargs)
29
30 @property
31 def when(self):
32 return self.get_argument_date("when", None)
33
34
35MIN_PROFILE_VERSION = 0
36MAX_PROFILE_VERSION = 0
37
38class Profile(dict):
39 def __getattr__(self, key):
40 try:
41 return self[key]
42 except KeyError:
43 raise AttributeError, key
44
45 def __setattr__(self, key, val):
46 self[key] = val
47
48
49class FireinfoProfileSendHandler(FireinfoBaseHandler):
50 def check_xsrf_cookie(self):
51 # This cookie is not required here.
52 pass
53
54 def prepare(self):
55 # Create an empty profile.
56 self.profile = Profile()
57
58 def __check_attributes(self, profile):
59 """
60 Check for attributes that must be provided,
61 """
62 attributes = (
63 "private_id",
64 "profile_version",
65 "public_id",
66 )
67 for attr in attributes:
68 if not profile.has_key(attr):
69 raise tornado.web.HTTPError(400, "Profile lacks '%s' attribute: %s" % (attr, profile))
70
71 def __check_valid_ids(self, profile):
72 """
73 Check if IDs contain valid data.
74 """
75 for id in ("public_id", "private_id"):
76 if re.match(r"^([a-f0-9]{40})$", "%s" % profile[id]) is None:
77 raise tornado.web.HTTPError(400, "ID '%s' has wrong format: %s" % (id, profile))
78
79 def __check_equal_ids(self, profile):
80 """
81 Check if public_id and private_id are equal.
82 """
83 if profile.public_id == profile.private_id:
84 raise tornado.web.HTTPError(400, "Public and private IDs are equal: %s" % profile)
85
86 def __check_matching_ids(self, profile):
87 """
88 Check if a profile with the given public_id is already in the
89 database. If so we need to check if the private_id matches.
90 """
91 p = self.profiles.find_one({ "public_id" : profile["public_id"]})
92 if not p:
93 return
94
95 p = Profile(p)
96 if p.private_id != profile.private_id:
97 raise tornado.web.HTTPError(400, "Mismatch of private_id: %s" % profile)
98
99 def __check_profile_version(self, profile):
100 """
101 Check if this version of the server software does support the
102 received profile.
103 """
104 version = profile.profile_version
105
106 if version < MIN_PROFILE_VERSION or version > MAX_PROFILE_VERSION:
107 raise tornado.web.HTTPError(400,
108 "Profile version is not supported: %s" % version)
109
110 def check_profile_blob(self, profile):
111 """
112 This method checks if the blob is sane.
113 """
114 checks = (
115 self.__check_attributes,
116 self.__check_valid_ids,
117 self.__check_equal_ids,
118 self.__check_profile_version,
119 # These checks require at least one database query and should be done
120 # at last.
121 self.__check_matching_ids,
122 )
123
124 for check in checks:
125 check(profile)
126
127 # If we got here, everything is okay and we can go on...
128
129 def get_profile_blob(self):
130 profile = self.get_argument("profile", None)
131
132 # Send "400 bad request" if no profile was provided
133 if not profile:
134 raise tornado.web.HTTPError(400, "No profile received")
135
136 # Try to decode the profile.
137 try:
138 return simplejson.loads(profile)
139 except simplejson.decoder.JSONDecodeError, e:
140 raise tornado.web.HTTPError(400, "Profile could not be decoded: %s" % e)
141
142 # The GET method is only allowed in debugging mode.
143 def get(self, public_id):
144 if not self.application.settings["debug"]:
145 return tornado.web.HTTPError(405)
146
147 return self.post(public_id)
148
149 def post(self, public_id):
150 profile_blob = self.get_profile_blob()
151 #self.check_profile_blob(profile_blob)
152
153 # Get location
154 location = self.get_remote_location()
155 if location:
156 location = location.country
157
158 # Handle the profile.
159 try:
160 self.fireinfo.handle_profile(public_id, profile_blob, location=location)
161
162 except backend.fireinfo.ProfileParserError:
163 raise tornado.web.HTTPError(400)
164
165 self.finish("Your profile was successfully saved to the database.")
166
167
168class FireinfoIndexHandler(FireinfoBaseHandler):
169 def _profile_not_found(self, profile_id):
170 self.set_status(404)
171 self.render("fireinfo/profile-notfound.html", profile_id=profile_id)
172
173 def get(self):
174 self.render("fireinfo/index.html")
175
176 def post(self):
177 profile_id = self.get_argument("profile_id", None)
178 if not profile_id:
179 raise tornado.web.HTTPError(400, "No profile ID was given.")
180
181 if not self.fireinfo.profile_exists(profile_id):
182 self._profile_not_found(profile_id)
183 return
184
185 self.redirect("/profile/%s" % profile_id)
186
187
188class FireinfoProfileDetailHandler(FireinfoIndexHandler):
189 def get(self, profile_id):
190 profile = self.fireinfo.get_profile(profile_id, when=self.when)
191
192 if not profile or not profile.is_showable():
193 self._profile_not_found(profile_id)
194 return
195
196 self.render("fireinfo/profile-detail.html", profile=profile)
197
198
199class FireinfoRandomProfileHandler(FireinfoBaseHandler):
200 def get(self):
201 profile_id = self.fireinfo.get_random_profile(when=self.when)
202 if profile_id is None:
203 raise tornado.web.HTTPError(404)
204
205 self.redirect("/profile/%s" % profile_id)
206
207
208class FireinfoDeviceDriverDetail(FireinfoBaseHandler):
209 def get(self, driver):
210 self.render("fireinfo/driver.html", driver=driver,
211 driver_map=self.fireinfo.get_driver_map(driver, when=self.when))
212
213
214class FireinfoDeviceVendorsHandler(FireinfoBaseHandler):
215 def get(self):
216 vendors = self.fireinfo.get_vendor_list(when=self.when)
217
218 self.render("fireinfo/vendors.html", vendors=vendors)
219
220
221class FireinfoStatsHandler(FireinfoBaseHandler):
222 def get(self):
223 self.render("fireinfo/stats.html")
224
225
226class FireinfoStatsProcessorsHandler(FireinfoBaseHandler):
227 def get(self):
228 avg, stddev, min, max = self.fireinfo.get_cpu_clock_speeds(when=self.when)
229 arch_map = self.fireinfo.get_arch_map(when=self.when)
230
231 data = {
232 "arch_map" : arch_map,
233 "cpu_vendors" : self.fireinfo.get_cpu_vendors_map(when=self.when),
234 "clock_speed_avg" : avg,
235 "clock_speed_stddev" : stddev,
236 "clock_speed_min" : min,
237 "clock_speed_max" : max,
238 }
239
240 return self.render("fireinfo/stats-cpus.html", **data)
241
242
243class FireinfoStatsProcessorDetailHandler(FireinfoBaseHandler):
244 def get(self, platform):
245 assert platform in ("arm", "x86")
246
247 flags = self.fireinfo.get_common_cpu_flags_by_platform(platform, when=self.when)
248
249 return self.render("fireinfo/stats-cpus-detail.html",
250 platform=platform, flags=flags)
251
252
253class FireinfoStatsMemoryHandler(FireinfoBaseHandler):
254 def get(self):
255 avg, stddev, min, max = self.fireinfo.get_memory_amounts(when=self.when)
256 amounts = self.fireinfo.get_common_memory_amounts(when=self.when)
257
258 data = {
259 "mem_avg" : avg,
260 "mem_stddev" : stddev,
261 "mem_min" : min,
262 "mem_max" : max,
263 "amounts" : amounts,
264 }
265
266 return self.render("fireinfo/stats-memory.html", **data)
267
268
269class FireinfoStatsReleasesHandler(FireinfoBaseHandler):
270 def get(self):
271 data = {
272 "releases" : self.fireinfo.get_releases_map(when=self.when),
273 "kernels" : self.fireinfo.get_kernels_map(when=self.when),
274 }
275 return self.render("fireinfo/stats-oses.html", **data)
276
277
278class FireinfoStatsVirtualHandler(FireinfoBaseHandler):
279 def get(self):
280 data = {
281 "hypervisors" : self.fireinfo.get_hypervisor_map(when=self.when),
282 "virtual" : self.fireinfo.get_virtual_ratio(when=self.when),
283 }
284
285 return self.render("fireinfo/stats-virtual.html", **data)
286
287
288class FireinfoStatsGeoHandler(FireinfoBaseHandler):
289 def get(self):
290 return self.render("fireinfo/stats-geo.html",
291 geo_locations = self.fireinfo.get_geo_location_map(when=self.when))
292
293
294class FireinfoStatsLanguagesHandler(FireinfoBaseHandler):
295 def get(self):
296 return self.render("fireinfo/stats-languages.html",
297 languages = self.fireinfo.get_language_map(when=self.when))
298
299
300class FireinfoStatsNetworkingHandler(FireinfoBaseHandler):
301 def get(self):
302 network=self.fireinfo.get_network_zones_map(when=self.when)
303
304 return self.render("fireinfo/stats-network.html", network=network)
305
306
307class FireinfoDeviceVendorHandler(FireinfoBaseHandler):
308 def get(self, subsystem, vendor_id):
309 devices = self.fireinfo.get_devices_by_vendor(subsystem, vendor_id,
310 when=self.when)
311
312 vendor_name = self.fireinfo.get_vendor_string(subsystem, vendor_id)
313
314 self.render("fireinfo/vendor-detail.html", vendor_name=vendor_name,
315 devices=devices)
316
317
318class FireinfoDeviceVendorCompatHandler(FireinfoBaseHandler):
319 def get(self, subsystem, vendor_id):
320 self.redirect("/device/%s/%s" % (subsystem, vendor_id))
321
322
323class FireinfoDeviceModelHandler(FireinfoBaseHandler):
324 def get(self, subsystem, vendor, model):
325 percentage = self.fireinfo.get_device_percentage(subsystem, vendor,
326 model, when=self.when)
327 percentage *= 100
328
329 profiles = self.fireinfo.get_device_in_profile(subsystem, vendor,
330 model, when=self.when)
331
332 vendor_name = self.fireinfo.get_vendor_string(subsystem, vendor)
333 model_name = self.fireinfo.get_model_string(subsystem, vendor, model)
334
335 self.render("fireinfo/model-detail.html", profiles=profiles,
336 vendor_id=vendor, vendor_name=vendor_name,
337 model_id=model, model_name=model_name,
338 percentage=percentage, subsystem=subsystem)
339
340
341class FireinfoDeviceModelCompatHandler(FireinfoBaseHandler):
342 def get(self, subsystem, vendor_id, model_id):
343 self.redirect("/device/%s/%s/%s" % (subsystem, vendor_id, model_id))
344
345
346class AdminFireinfoHandler(FireinfoBaseHandler):
347 def get(self):
348 profiles_with_data, profiles_all = self.fireinfo.get_active_profiles(when=self.when)
349
350 data = {
351 "archive_size" : self.fireinfo.get_archive_size(when=self.when),
de14b297 352 "total_updates" : self.fireinfo.get_total_updates_count(when=self.when),
66862195
MT
353 "profiles_with_data" : profiles_with_data,
354 "profiles_all" : profiles_all,
355 }
356
357 self.render("fireinfo/stats-admin.html", **data)