]>
git.ipfire.org Git - people/shoehn/ipfire.org.git/blob - webapp/handlers_stasy.py
d384bc57d4eea838bdb5ec144f22da8d45a62b39
3 from __future__
import division
15 from handlers_base
import *
17 class StasyBaseHandler(BaseHandler
):
18 def format_size(self
, s
):
19 units
= ("K", "M", "G", "T")
22 while s
>= 1024 and unit
< len(units
):
26 return "%.1f%s" % (s
, units
[unit
])
28 def cut_string(self
, s
, limit
=15):
34 def render(self
, *args
, **kwargs
):
36 "cut_string" : self
.cut_string
,
37 "format_size" : self
.format_size
,
40 return BaseHandler
.render(self
, *args
, **kwargs
)
43 MIN_PROFILE_VERSION
= 0
44 MAX_PROFILE_VERSION
= 0
47 def __getattr__(self
, key
):
51 raise AttributeError, key
53 def __setattr__(self
, key
, val
):
57 class StasyProfileSendHandler(StasyBaseHandler
):
58 def check_xsrf_cookie(self
):
59 # This cookie is not required here.
64 return self
.stasy
.archives
68 return self
.stasy
.profiles
71 # Create an empty profile.
72 self
.profile
= Profile()
74 def __check_attributes(self
, profile
):
76 Check for attributes that must be provided,
85 for attr
in attributes
:
86 if not profile
.has_key(attr
):
87 raise tornado
.web
.HTTPError(400, "Profile lacks '%s' attribute: %s" % (attr
, profile
))
89 def __check_valid_ids(self
, profile
):
91 Check if IDs contain valid data.
94 for id in ("public_id", "private_id"):
95 if re
.match(r
"^([a-f0-9]{40})$", "%s" % profile
[id]) is None:
96 raise tornado
.web
.HTTPError(400, "ID '%s' has wrong format: %s" % (id, profile
))
98 def __check_equal_ids(self
, profile
):
100 Check if public_id and private_id are equal.
103 if profile
.public_id
== profile
.private_id
:
104 raise tornado
.web
.HTTPError(400, "Public and private IDs are equal: %s" % profile
)
106 def __check_matching_ids(self
, profile
):
108 Check if a profile with the given public_id is already in the
109 database. If so we need to check if the private_id matches.
111 p
= self
.profiles
.find_one({ "public_id" : profile
["public_id"]})
116 if p
.private_id
!= profile
.private_id
:
117 raise tornado
.web
.HTTPError(400, "Mismatch of private_id: %s" % profile
)
119 def __check_profile_version(self
, profile
):
121 Check if this version of the server software does support the
124 version
= profile
.profile_version
126 if version
< MIN_PROFILE_VERSION
or version
> MAX_PROFILE_VERSION
:
127 raise tornado
.web
.HTTPError(400,
128 "Profile version is not supported: %s" % version
)
130 def check_profile(self
):
132 This method checks if the blob is sane.
136 self
.__check
_attributes
,
137 self
.__check
_valid
_ids
,
138 self
.__check
_equal
_ids
,
139 self
.__check
_profile
_version
,
140 # These checks require at least one database query and should be done
142 self
.__check
_matching
_ids
,
148 # If we got here, everything is okay and we can go on...
150 # The GET method is only allowed in debugging mode.
151 def get(self
, public_id
):
152 if not self
.application
.settings
["debug"]:
153 return tornado
.web
.HTTPError(405)
155 return self
.post(public_id
)
157 def post(self
, public_id
):
158 profile
= self
.get_argument("profile", None)
160 # Send "400 bad request" if no profile was provided
162 raise tornado
.web
.HTTPError(400, "No profile received.")
164 # Try to decode the profile.
166 self
.profile
.update(simplejson
.loads(profile
))
167 except simplejson
.decoder
.JSONDecodeError
, e
:
168 raise tornado
.web
.HTTPError(400, "Profile could not be decoded: %s" % e
)
170 # Create a shortcut and overwrite public_id from query string
171 profile
= self
.profile
172 profile
.public_id
= public_id
174 # Add timestamp to the profile
175 profile
.updated
= datetime
.datetime
.utcnow()
177 # Check if profile contains proper data.
180 # Get GeoIP information if address is not defined in rfc1918
181 remote_ips
= self
.request
.remote_ip
.split(", ")
182 for remote_ip
in remote_ips
:
184 addr
= ipaddr
.IPAddress(remote_ip
)
186 # Skip invalid IP addresses.
189 # Check if the given IP address is from a
194 location
= self
.geoip
.get_location(remote_ip
)
197 "country_code" : location
.country
,
204 # Move previous profiles to archive and keep only the latest one
205 # in profiles. This will make full table lookups faster.
206 self
.stasy
.move_profiles({ "public_id" : profile
.public_id
})
208 # Write profile to database
209 id = self
.profiles
.save(profile
)
211 self
.write("Your profile was successfully saved to the database.")
214 logging
.debug("Saved profile: %s" % profile
)
217 logging
.debug("Starting automatic cleanup...")
219 # Remove all profiles that were not updated since 4 weeks.
220 not_updated_since
= datetime
.datetime
.utcnow() - \
221 datetime
.timedelta(weeks
=4)
223 self
.stasy
.move_profiles({ "updated" : { "$lt" : not_updated_since
}})
226 class StasyIndexHandler(StasyBaseHandler
):
227 def _profile_not_found(self
, profile_id
):
229 self
.render("fireinfo/profile-notfound.html", profile_id
=profile_id
)
232 self
.render("fireinfo/index.html")
235 profile_id
= self
.get_argument("profile_id", None)
237 raise tornado
.web
.HTTPError(400, "No profile ID was given.")
239 if not self
.stasy
.profile_exists(profile_id
):
240 self
._profile
_not
_found
(profile_id
)
243 self
.redirect("/profile/%s" % profile_id
)
246 class StasyProfileDetailHandler(StasyIndexHandler
):
247 def get(self
, profile_id
):
248 profile
= self
.stasy
.get_profile(profile_id
)
250 self
._profile
_not
_found
(profile_id
)
253 self
.render("fireinfo/profile-detail.html", profile
=profile
)
256 class StasyStatsHandler(StasyBaseHandler
):
258 self
.render("fireinfo/stats.html")
261 class StasyStatsCPUHandler(StasyBaseHandler
):
263 return self
.render("fireinfo/stats-cpus.html",
264 cpu_vendors
=self
.stasy
.cpu_vendors_map
,
265 average_speed
=self
.stasy
.cpu_speed_average
,
266 cpu_speeds
=self
.stasy
.cpu_speed_map
,
267 cpu_cores
=self
.stasy
.get_cpu_cores_map(),
268 bogomips
=self
.stasy
.get_cpu_bogomips_accumulated())
271 class StasyStatsCPUFlagsHandler(StasyBaseHandler
):
278 ("virt", ("vmx", "svm")),
281 for name
, flag
in flags
:
282 kwargs
["cpus_" + name
] = self
.stasy
.get_cpu_flag_map(flag
)
284 return self
.render("fireinfo/stats-cpu-flags.html", **kwargs
)
286 class StasyStatsMemoryHandler(StasyBaseHandler
):
288 return self
.render("fireinfo/stats-memory.html",
289 average_memory
=self
.stasy
.memory_average
,
290 memory
=self
.stasy
.get_memory_map())
293 class StasyStatsOSesHandler(StasyBaseHandler
):
295 return self
.render("fireinfo/stats-oses.html",
296 arches
=self
.stasy
.arch_map
,
297 kernels
=self
.stasy
.kernel_map
,
298 releases
=self
.stasy
.release_map
)
301 class StasyStatsVirtualHandler(StasyBaseHandler
):
303 return self
.render("fireinfo/stats-virtual.html",
304 hypervisor_vendors
= self
.stasy
.hypervisor_map
,
305 is_virtual
= self
.stasy
.virtual_map
)
307 class StasyStatsGeoHandler(StasyBaseHandler
):
309 return self
.render("fireinfo/stats-geo.html",
310 languages
= self
.stasy
.get_language_map(),
311 geo_locations
= self
.stasy
.get_geo_location_map())
314 class StasyStatsNetworkHandler(StasyBaseHandler
):
316 return self
.render("fireinfo/stats-network.html",
317 network_zones
=self
.stasy
.get_network_zones_map())
320 class StasyStatsVendorDetail(StasyBaseHandler
):
321 def get(self
, bus
, vendor_id
):
327 cls
= bus2cls
[bus
.lower()]
328 vendor_name
= cls().get_vendor(vendor_id
)
330 # Get a list of all models we know from this vendor
331 models
= self
.stasy
.get_models_by_vendor(bus
, vendor_id
)
333 self
.render("fireinfo/vendor-detail.html",
334 vendor_name
=vendor_name
, models
=models
)
337 class StasyStatsModelDetail(StasyBaseHandler
):
338 def get(self
, bus
, vendor_id
, model_id
):
344 cls
= bus2cls
[bus
.lower()]
346 vendor_name
= cls().get_vendor(vendor_id
)
347 model_name
= cls().get_device(vendor_id
, model_id
)
350 self
.stasy
.get_device_percentage(bus
, vendor_id
, model_id
) * 100
352 self
.render("fireinfo/model-detail.html",
354 vendor_name
=vendor_name
,
356 model_name
=model_name
,
357 percentage
=percentage
,
361 class AdminFireinfoStatsHandler(StasyBaseHandler
):
363 _
= self
.locale
.translate
367 data
["profiles_count"], data
["profiles_count_all"] = \
368 self
.stasy
.get_profile_ratio()
370 data
["archives_count"] = self
.stasy
.get_archives_count()
373 #since = { "hours" : 24 }
374 #updates = self.stasy.get_updates_by_release_since(since)
375 #updates[_("All versions")] = self.stasy.get_updated_since(since).count()
376 #data["updated_since_24h"] = updates
378 self
.render("fireinfo/stats-admin.html", **data
)