]>
git.ipfire.org Git - people/shoehn/ipfire.org.git/blob - www/webapp/backend/stasy.py
3 from __future__
import division
9 from misc
import Singleton
11 DATABASE_HOST
= ["irma.ipfire.org", "madeye.ipfire.org"]
12 DATABASE_NAME
= "stasy"
14 CPU_SPEED_CONSTRAINTS
= (0, 500, 1000, 1500, 2000, 2500, 3000, 3500)
15 MEMORY_CONSTRAINTS
= (0, 64, 128, 256, 512, 1024, 2048, 4096, 8128, 16384)
17 class ProfileDict(object):
18 def __init__(self
, data
):
22 class ProfileCPU(ProfileDict
):
25 return self
._data
.get("arch")
29 return self
._data
.get("vendor")
33 return self
._data
.get("speed")
37 return self
._data
.get("bogomips")
41 return self
._data
.get("model")
44 def model_string(self
):
45 return self
._data
.get("model_string")
49 return self
._data
.get("flags")
53 return self
._data
.get("count")
56 def capable_64bit(self
):
57 return "lm" in self
.flags
60 def capable_pae(self
):
61 return "pae" in self
.flags
64 def capable_virt(self
):
65 return "vmx" in self
.flags
or "svm" in self
.flags
68 class ProfileHypervisor(ProfileDict
):
70 return "<%s %s-%s>" % (self
.__class
__.__name
__, self
.vendor
, self
.type)
74 return self
._data
.get("vendor")
78 return self
._data
.get("type")
81 class ProfileNetwork(ProfileDict
):
82 def has_zone(self
, name
):
83 return self
._data
.get(name
)
87 return self
._data
.get("green")
91 return self
._data
.get("red")
95 return self
._data
.get("blue")
99 return self
._data
.get("orange")
102 class ProfileDevice(ProfileDict
):
110 "00" : "Unclassified",
111 "01" : "Mass storage",
115 "05" : "Memory controller",
117 "07" : "Communication",
118 "08" : "Generic system peripheral",
119 "09" : "Input device",
120 "0a" : "Docking station",
124 "0e" : "Intelligent controller",
125 "0f" : "Satellite communications controller",
127 "11" : "Signal processing controller",
128 "ff" : "Unassigned class",
132 "00" : "Unclassified",
134 "02" : "Communication",
135 "03" : "Input device",
136 "05" : "Generic system peripheral",
139 "08" : "Mass storage",
141 "0a" : "Communication",
145 "0f" : "Personal Healthcare",
146 "dc" : "Diagnostic Device",
148 "ef" : "Unclassified",
149 "fe" : "Unclassified",
150 "ff" : "Unclassified",
154 def __cmp__(self
, other
):
155 return cmp(self
.vendor
, other
.vendor
) or \
156 cmp(self
.model
, other
.model
) or \
157 cmp(self
.driver
, other
.driver
)
161 return self
._data
.get("model")
164 def model_string(self
):
165 cls
= self
.subsystem2class
[self
.subsystem
]
167 return cls().get_device(self
.vendor
, self
.model
)
171 return self
._data
.get("subsystem")
175 return self
._data
.get("vendor")
178 def vendor_string(self
):
179 cls
= self
.subsystem2class
[self
.subsystem
]
181 return cls().get_vendor(self
.vendor
)
185 return self
._data
.get("driver")
189 classid
= self
._data
.get("deviceclass")
191 if self
.subsystem
== "pci":
192 classid
= classid
[:-4]
193 if len(classid
) == 1:
194 classid
= "0%s" % classid
196 elif self
.subsystem
== "usb" and classid
:
197 classid
= classid
.split("/")[0]
198 classid
= "%02x" % int(classid
)
201 return self
.classid2name
[self
.subsystem
][classid
]
206 class Profile(ProfileDict
):
207 def __init__(self
, profile_blob
):
208 ProfileDict
.__init
__(self
, profile_blob
.get("profile"))
210 self
.public_id
= profile_blob
.get("public_id")
211 self
.updated
= profile_blob
.get("updated")
212 self
._geoip
= profile_blob
.get("geoip", None)
215 return "<%s %s>" % (self
.__class
__.__name
__, self
.public_id
)
219 return ProfileCPU(self
._data
.get("cpu"))
224 for d
in self
._data
.get("devices"):
227 if d
.driver
in ("pcieport", "usb", "hub"):
235 def hypervisor(self
):
237 return ProfileHypervisor(self
._data
.get("hypervisor"))
241 return self
.system
.get("virtual")
245 return self
._data
.get("system")
249 return self
.system
.get("release")
253 return self
.system
.get("kernel_release")
257 return self
.system
.get("memory")
261 return self
.system
.get("root_size") or 0
265 return self
.system
.get("vendor")
269 return self
.system
.get("model")
272 def country_code(self
):
274 return self
._geoip
["country_code"].lower()
280 network
= self
._data
.get("network", None)
282 return ProfileNetwork(network
)
286 __metaclass__
= Singleton
289 # Initialize database connection
290 self
._conn
= pymongo
.Connection(DATABASE_HOST
)
291 self
._db
= self
._conn
[DATABASE_NAME
]
293 def get_profile_count(self
):
294 # XXX need to implement something to get profiles updated since
297 # All distinct profiles (based on public_id)
298 return self
._db
.profiles
.distinct("public_id").count()
300 #def _get_profile_cursor(self, public_id):
301 # c = self._db.profiles.find({ "public_id" : public_id })
302 # c.sort("updated", pymongo.ASCENDING)
306 def profile_exists(self
, public_id
):
307 return self
.query({ "public_id" : public_id
}).count() >= 1
309 def get_profile(self
, public_id
):
311 # XXX should only find one object in the end
312 for p
in self
.query({ "public_id" : public_id
}):
317 def get_profiles(self
):
318 # XXX needs nicer database query
320 for p
in self
._db
.profiles
.find():
321 if not p
.get("public_id") in profiles
:
322 profiles
.append(p
.get("public_id"))
326 def query(self
, query
, archives
=False, no_virt
=False, all
=False):
327 db
= self
._db
.profiles
330 db
= self
.db
.archives
333 # XXX cannot use the index?
334 query
.update({ "profile" : { "$exists" : True }})
337 query
.update({ "profile.system.virtual" : False })
339 logging
.debug("Executing query: %s" % query
)
341 return db
.find(query
)
344 def secret_ids(self
):
345 return self
._db
.profiles
.distinct("secret_id")
349 return self
.query({}, no_virt
=True).distinct("profile.cpu")
352 def cpu_vendors(self
):
353 return self
.query({}, no_virt
=True).distinct("profile.cpu.vendor")
356 def cpu_vendors_map(self
):
359 for vendor
in self
.cpu_vendors
:
362 "profile.cpu.vendor" : vendor
363 }, no_virt
=True).count()
368 def cpu_speed_average(self
):
371 all
= self
.query({}, no_virt
=True)
373 # XXX ugly. needs to be done by group()
375 if not m
.has_key("profile"):
377 speed
+= m
.get("profile").get("cpu").get("speed")
379 return (speed
/ all
.count())
382 def cpu_speed_map(self
):
385 for i
in range(len(CPU_SPEED_CONSTRAINTS
) - 1):
386 min, max = CPU_SPEED_CONSTRAINTS
[i
:i
+2]
388 cpu_speeds
[min, max] = \
390 "profile.cpu.speed" : {
391 "$gte" : min, "$lt" : max
393 }, no_virt
=True).count()
397 def get_memory_map(self
):
400 for i
in range(len(MEMORY_CONSTRAINTS
) - 1):
401 min, max = MEMORY_CONSTRAINTS
[i
:i
+2]
405 { "profile.system.memory" : {
406 "$gte" : min * 1024, "$lt" : max * 1024
408 }, no_virt
=True).count()
413 def memory_average(self
):
416 all
= self
.query({}, no_virt
=True)
418 # XXX ugly. needs to be done by group()
420 if not m
.has_key("profile"):
422 memory
+= int(m
.get("profile").get("system").get("memory"))
424 return (memory
/ all
.count()) / 1024
427 def hypervisor_vendors(self
):
428 return self
.query({}).distinct("profile.hypervisor.vendor")
431 def hypervisor_map(self
):
434 for hypervisor
in self
.hypervisor_vendors
:
435 hypervisors
[hypervisor
] = \
437 "profile.hypervisor.vendor" : hypervisor
443 def hypervisor_models(self
):
444 return self
.query({}).distinct("profile.hypervisor.model")
447 def virtual_map(self
):
453 for k
in virtual
.keys():
455 self
.query({ "profile.system.virtual": k
}).count()
461 return self
.query({}).distinct("profile.system.language")
463 def get_language_map(self
):
466 for language
in self
.languages
:
467 languages
[language
] = \
469 "profile.system.language" : language
476 return self
.query({}).distinct("profile.system.vendor")
479 def vendor_map(self
):
482 for vendor
in self
.vendors
:
485 "profile.system.vendor" : vendor
492 return self
.query({}).distinct("profile.system.model")
498 for model
in self
.models
:
501 "profile.system.model" : model
508 return self
.query({}).distinct("profile.cpu.arch")
514 for arch
in self
.arches
:
517 "profile.cpu.arch" : arch
524 return self
.query({}).distinct("profile.system.kernel_release")
527 def kernel_map(self
):
530 for kernel
in self
.kernels
:
533 "profile.system.kernel_release" : kernel
540 return self
.query({}).distinct("profile.system.release")
543 def release_map(self
):
546 for release
in self
.releases
:
547 releases
[release
] = \
549 "profile.system.release" : release
554 def get_device_percentage(self
, bus
, vendor_id
, model_id
):
555 profiles_with_device
= self
.query({
556 "profile.devices.subsystem" : bus
,
557 "profile.devices.vendor" : vendor_id
,
558 "profile.devices.model" : model_id
,
561 profiles_all
= self
.query({})
563 if not profiles_all
.count():
566 return profiles_with_device
.count() / profiles_all
.count()
568 def get_cpu_flag_map(self
, flags
):
569 # XXX needs a cleanup
571 _flags
= { True : 0 }
573 if type(flags
) == type("a"):
579 "profile.cpu.flags" : flag
,
580 }, no_virt
=True).count()
582 _flags
[False] = self
.query({}, no_virt
=True).count() - _flags
[True]
587 def geo_locations(self
):
588 return [code
.lower() for code
in self
.query({}).distinct("geoip.country_code")]
590 def get_geo_location_map(self
):
594 for geo_location
in self
.geo_locations
:
595 geo_locations
[geo_location
] = \
597 "geoip.country_code" : geo_location
600 count
+= geo_locations
[geo_location
]
602 # XXX must only be systems that have profile data
603 profiles_all
= self
.query({})
605 unknown_count
= profiles_all
.count() - count
607 geo_locations
["unknown"] = unknown_count
611 def get_models_by_vendor(self
, subsystem
, vendor_id
):
614 # XXX must only be systems that have profile data
615 profiles_all
= self
.query({})
617 for profile
in profiles_all
:
618 if not profile
.has_key("profile"):
621 profile
= Profile(profile
)
623 for device
in profile
.devices
:
624 if not device
.vendor
== vendor_id
:
627 if not device
in devices
:
628 devices
.append(device
)
632 def get_network_zones_map(self
):
633 zones
= { "green" : 0, "blue" : 0, "orange" : 0, "red" : 0 }
635 for zone
in zones
.keys():
636 zones
[zone
] = self
.query({
637 "profile.network.%s" % zone
: True,
643 if __name__
== "__main__":
646 print s
.get_profile("0" * 40)
648 for id in s
.secret_ids
:
651 #for p in s._db.profiles.find():
656 print s
.memory_average
657 print s
.hypervisor_vendors
658 print s
.hypervisor_models
660 print s
.language_maps
673 p
= s
.get_profile("0b5f4fe2162fdfbfa29b632610e317078fa70d34")