]>
git.ipfire.org Git - ipfire.org.git/blob - src/web/fireinfo.py
10 from .. import fireinfo
13 from . import ui_modules
15 class BaseHandler(base
.BaseHandler
):
18 return self
.get_argument_date("when", None)
21 MIN_PROFILE_VERSION
= 0
22 MAX_PROFILE_VERSION
= 0
25 def __getattr__(self
, key
):
29 raise AttributeError(key
)
31 def __setattr__(self
, key
, val
):
35 class ProfileSendHandler(BaseHandler
):
36 def check_xsrf_cookie(self
):
37 # This cookie is not required here.
41 # Create an empty profile.
42 self
.profile
= Profile()
44 def __check_attributes(self
, profile
):
46 Check for attributes that must be provided,
53 for attr
in attributes
:
54 if attr
not in profile
:
55 raise tornado
.web
.HTTPError(400, "Profile lacks '%s' attribute: %s" % (attr
, profile
))
57 def __check_valid_ids(self
, profile
):
59 Check if IDs contain valid data.
61 for id in ("public_id", "private_id"):
62 if re
.match(r
"^([a-f0-9]{40})$", "%s" % profile
[id]) is None:
63 raise tornado
.web
.HTTPError(400, "ID '%s' has wrong format: %s" % (id, profile
))
65 def __check_equal_ids(self
, profile
):
67 Check if public_id and private_id are equal.
69 if profile
.public_id
== profile
.private_id
:
70 raise tornado
.web
.HTTPError(400, "Public and private IDs are equal: %s" % profile
)
72 def __check_matching_ids(self
, profile
):
74 Check if a profile with the given public_id is already in the
75 database. If so we need to check if the private_id matches.
77 p
= self
.profiles
.find_one({ "public_id" : profile
["public_id"]})
82 if p
.private_id
!= profile
.private_id
:
83 raise tornado
.web
.HTTPError(400, "Mismatch of private_id: %s" % profile
)
85 def __check_profile_version(self
, profile
):
87 Check if this version of the server software does support the
90 version
= profile
.profile_version
92 if version
< MIN_PROFILE_VERSION
or version
> MAX_PROFILE_VERSION
:
93 raise tornado
.web
.HTTPError(400,
94 "Profile version is not supported: %s" % version
)
96 def check_profile_blob(self
, profile
):
98 This method checks if the blob is sane.
101 self
.__check
_attributes
,
102 self
.__check
_valid
_ids
,
103 self
.__check
_equal
_ids
,
104 self
.__check
_profile
_version
,
105 # These checks require at least one database query and should be done
107 self
.__check
_matching
_ids
,
113 # If we got here, everything is okay and we can go on...
115 def get_profile_blob(self
):
116 profile
= self
.get_argument("profile", None)
118 # Send "400 bad request" if no profile was provided
120 raise tornado
.web
.HTTPError(400, "No profile received")
122 # Try to decode the profile.
124 return json
.loads(profile
)
125 except json
.decoder
.JSONDecodeError
as e
:
126 raise tornado
.web
.HTTPError(400, "Profile could not be decoded: %s" % e
)
128 # The GET method is only allowed in debugging mode.
129 def get(self
, public_id
):
130 if not self
.application
.settings
["debug"]:
131 raise tornado
.web
.HTTPError(405)
133 return self
.post(public_id
)
135 def post(self
, public_id
):
136 profile_blob
= self
.get_profile_blob()
137 #self.check_profile_blob(profile_blob)
140 location
= self
.get_remote_location()
142 location
= location
.country
144 # Handle the profile.
145 with self
.db
.transaction():
147 self
.fireinfo
.handle_profile(public_id
, profile_blob
, location
=location
)
149 except fireinfo
.ProfileParserError
:
150 raise tornado
.web
.HTTPError(400)
152 self
.finish("Your profile was successfully saved to the database.")
155 class IndexHandler(BaseHandler
):
156 def _profile_not_found(self
, profile_id
):
158 self
.render("fireinfo/profile-notfound.html", profile_id
=profile_id
)
161 self
.render("fireinfo/index.html")
164 profile_id
= self
.get_argument("profile_id", None)
166 raise tornado
.web
.HTTPError(400, "No profile ID was given.")
168 if not self
.fireinfo
.profile_exists(profile_id
):
169 self
._profile
_not
_found
(profile_id
)
172 self
.redirect("/profile/%s" % profile_id
)
175 class ProfileDetailHandler(BaseHandler
):
176 def get(self
, profile_id
):
177 profile
= self
.fireinfo
.get_profile(profile_id
, when
=self
.when
)
179 if not profile
or not profile
.is_showable():
180 self
._profile
_not
_found
(profile_id
)
183 self
.render("fireinfo/profile-detail.html", profile
=profile
)
186 class RandomProfileHandler(BaseHandler
):
188 profile_id
= self
.fireinfo
.get_random_profile(when
=self
.when
)
189 if profile_id
is None:
190 raise tornado
.web
.HTTPError(404)
192 self
.redirect("/profile/%s" % profile_id
)
195 class DeviceDriverDetail(BaseHandler
):
196 def get(self
, driver
):
197 self
.render("fireinfo/driver.html", driver
=driver
,
198 driver_map
=self
.fireinfo
.get_driver_map(driver
, when
=self
.when
))
201 class DeviceVendorsHandler(BaseHandler
):
203 vendors
= self
.fireinfo
.get_vendor_list(when
=self
.when
)
205 self
.render("fireinfo/vendors.html", vendors
=vendors
)
208 class StatsHandler(BaseHandler
):
210 self
.render("fireinfo/stats.html")
213 class StatsProcessorsHandler(BaseHandler
):
215 avg
, stddev
, min, max = self
.fireinfo
.get_cpu_clock_speeds(when
=self
.when
)
216 arch_map
= self
.fireinfo
.get_arch_map(when
=self
.when
)
219 "arch_map" : arch_map
,
220 "cpu_vendors" : self
.fireinfo
.get_cpu_vendors_map(when
=self
.when
),
221 "clock_speed_avg" : avg
,
222 "clock_speed_stddev" : stddev
,
223 "clock_speed_min" : min,
224 "clock_speed_max" : max,
227 return self
.render("fireinfo/stats-cpus.html", **data
)
230 class StatsProcessorDetailHandler(BaseHandler
):
231 def get(self
, platform
):
232 assert platform
in ("arm", "x86")
234 flags
= self
.fireinfo
.get_common_cpu_flags_by_platform(platform
, when
=self
.when
)
236 return self
.render("fireinfo/stats-cpus-detail.html",
237 platform
=platform
, flags
=flags
)
240 class StatsMemoryHandler(BaseHandler
):
242 avg
, stddev
, min, max = self
.fireinfo
.get_memory_amounts(when
=self
.when
)
243 amounts
= self
.fireinfo
.get_common_memory_amounts(when
=self
.when
)
247 "mem_stddev" : stddev
,
253 return self
.render("fireinfo/stats-memory.html", **data
)
256 class StatsReleasesHandler(BaseHandler
):
259 "releases" : self
.fireinfo
.get_releases_map(when
=self
.when
),
260 "kernels" : self
.fireinfo
.get_kernels_map(when
=self
.when
),
262 return self
.render("fireinfo/stats-oses.html", **data
)
265 class StatsVirtualHandler(BaseHandler
):
268 "hypervisors" : self
.fireinfo
.get_hypervisor_map(when
=self
.when
),
269 "virtual" : self
.fireinfo
.get_virtual_ratio(when
=self
.when
),
272 return self
.render("fireinfo/stats-virtual.html", **data
)
275 class StatsGeoHandler(BaseHandler
):
277 return self
.render("fireinfo/stats-geo.html",
278 geo_locations
= self
.fireinfo
.get_geo_location_map(when
=self
.when
))
281 class StatsLanguagesHandler(BaseHandler
):
283 return self
.render("fireinfo/stats-languages.html",
284 languages
= self
.fireinfo
.get_language_map(when
=self
.when
))
287 class StatsNetworkingHandler(BaseHandler
):
289 network
=self
.fireinfo
.get_network_zones_map(when
=self
.when
)
291 return self
.render("fireinfo/stats-network.html", network
=network
)
294 class DeviceVendorHandler(BaseHandler
):
295 def get(self
, subsystem
, vendor_id
):
296 devices
= self
.fireinfo
.get_devices_by_vendor(subsystem
, vendor_id
,
299 vendor_name
= self
.fireinfo
.get_vendor_string(subsystem
, vendor_id
)
301 self
.render("fireinfo/vendor-detail.html", vendor_name
=vendor_name
,
305 class DeviceVendorCompatHandler(BaseHandler
):
306 def get(self
, subsystem
, vendor_id
):
307 self
.redirect("/device/%s/%s" % (subsystem
, vendor_id
))
310 class DeviceModelHandler(BaseHandler
):
311 def get(self
, subsystem
, vendor
, model
):
312 percentage
= self
.fireinfo
.get_device_percentage(subsystem
, vendor
,
313 model
, when
=self
.when
)
316 profiles
= self
.fireinfo
.get_device_in_profile(subsystem
, vendor
,
317 model
, when
=self
.when
)
319 vendor_name
= self
.fireinfo
.get_vendor_string(subsystem
, vendor
)
320 model_name
= self
.fireinfo
.get_model_string(subsystem
, vendor
, model
)
322 self
.render("fireinfo/model-detail.html", profiles
=profiles
,
323 vendor_id
=vendor
, vendor_name
=vendor_name
,
324 model_id
=model
, model_name
=model_name
,
325 percentage
=percentage
, subsystem
=subsystem
)
328 class DeviceModelCompatHandler(BaseHandler
):
329 def get(self
, subsystem
, vendor_id
, model_id
):
330 self
.redirect("/device/%s/%s/%s" % (subsystem
, vendor_id
, model_id
))
333 class AdminFireinfoHandler(BaseHandler
):
335 profiles_with_data
, profiles_all
= self
.fireinfo
.get_active_profiles(when
=self
.when
)
338 "archive_size" : self
.fireinfo
.get_archive_size(when
=self
.when
),
339 "total_updates" : self
.fireinfo
.get_total_updates_count(when
=self
.when
),
340 "profiles_with_data" : profiles_with_data
,
341 "profiles_all" : profiles_all
,
344 self
.render("fireinfo/stats-admin.html", **data
)
347 class DeviceTableModule(ui_modules
.UIModule
):
348 def render(self
, devices
):
349 return self
.render_string("fireinfo/modules/table-devices.html",
353 class DeviceAndGroupsTableModule(ui_modules
.UIModule
):
354 def render(self
, devices
):
355 _
= self
.locale
.translate
359 for device
in devices
:
360 if device
.cls
not in groups
:
361 groups
[device
.cls
] = []
363 groups
[device
.cls
].append(device
)
366 for key
in list(groups
.keys()):
369 # Order the groups by their name
370 groups
= list(groups
.items())
373 return self
.render_string("fireinfo/modules/table-devices-and-groups.html",
377 class GeoTableModule(ui_modules
.UIModule
):
378 def render(self
, items
):
381 for code
, value
in items
:
382 # Skip the satellite providers in this ranking
383 if code
in (None, "A1", "A2"):
386 name
= self
.backend
.geoip
.get_country_name(code
)
388 # Don't add countries with a small share on the list
390 other_countries
.append(name
)
393 country
= database
.Row({
398 countries
.append(country
)
400 return self
.render_string("fireinfo/modules/table-geo.html",
401 countries
=countries
, other_countries
=other_countries
)