#!/usr/bin/python
+from __future__ import division
+
import hwdata
import logging
import pymongo
DATABASE_HOST = ["irma.ipfire.org", "madeye.ipfire.org"]
DATABASE_NAME = "stasy"
+CPU_SPEED_CONSTRAINTS = (0, 500, 1000, 1500, 2000, 2500, 3000, 3500)
MEMORY_CONSTRAINTS = (0, 64, 128, 256, 512, 1024, 2048, 4096, 8128, 16384)
class ProfileDict(object):
def vendor(self):
return self._data.get("vendor")
+ @property
+ def speed(self):
+ return self._data.get("speed")
+
+ @property
+ def bogomips(self):
+ return self._data.get("bogomips")
+
@property
def model(self):
return self._data.get("model")
def flags(self):
return self._data.get("flags")
+ @property
+ def count(self):
+ return self._data.get("count")
+
@property
def capable_64bit(self):
return "lm" in self.flags
def vendor(self):
return self._data.get("vendor")
- @property
- def model(self):
- return self._data.get("model")
-
@property
def type(self):
return self._data.get("type")
"usb" : hwdata.USB,
}
+ classid2name = {
+ "pci" : {
+ "00" : "unclassified",
+ "01" : "Mass storage",
+ "02" : "Network",
+ "03" : "Display",
+ "04" : "Multimedia",
+ "05" : "Memory controller",
+ "06" : "Bridge",
+ "07" : "Communication",
+ "08" : "Generic system peripheral",
+ "09" : "Input device",
+ "0a" : "Docking station",
+ "0b" : "Processor",
+ "0c" : "Serial bus",
+ "0d" : "Wireless",
+ "0e" : "Intelligent controller",
+ "0f" : "Satellite communications controller",
+ "10" : "Encryption controller",
+ "11" : "Signal processing controller",
+ "ff" : "Unassigned class",
+ },
+
+ "usb" : {
+ "00" : "???",
+ "01" : "Multimedia",
+ "02" : "Communication",
+ "03" : "Input device",
+ "05" : "Physical ???",
+ "06" : "Image ???",
+ "07" : "Printer",
+ "08" : "Mass storage",
+ "09" : "Hub",
+ "0a" : "CDC-Data ???",
+ "0b" : "Smart card ???",
+ "0d" : "Content Security ???",
+ "0e" : "Display",
+ "0f" : "Personal healthcare ???",
+ "dc" : "Diagnostic Device",
+ "e0" : "Wireless",
+ "ef" : "Misc",
+ "fe" : "Application specific ???",
+ "ff" : "Vendor specific ???",
+ }
+ }
+
+ def __cmp__(self, other):
+ return cmp(self.vendor, other.vendor) or \
+ cmp(self.model, other.model) or \
+ cmp(self.driver, other.driver)
+
@property
def model(self):
return self._data.get("model")
def driver(self):
return self._data.get("driver")
+ @property
+ def cls(self):
+ classid = self._data.get("deviceclass")
+
+ if self.subsystem == "pci":
+ classid = classid[:-4]
+ if len(classid) == 1:
+ classid = "0%s" % classid
+
+ elif self.subsystem == "usb" and classid:
+ classid = classid.split("/")[0]
+ classid = "%02x" % int(classid)
+
+ try:
+ return self.classid2name[self.subsystem][classid]
+ except KeyError:
+ return "N/A"
+
class Profile(ProfileDict):
- def __init__(self, public_id, updated, data):
- ProfileDict.__init__(self, data)
+ def __init__(self, profile_blob):
+ ProfileDict.__init__(self, profile_blob.get("profile"))
- self.public_id = public_id
- self.updated = updated
+ self.public_id = profile_blob.get("public_id")
+ self.updated = profile_blob.get("updated")
+ self._geoip = profile_blob.get("geoip", None)
def __repr__(self):
return "<%s %s>" % (self.__class__.__name__, self.public_id)
for d in self._data.get("devices"):
d = ProfileDevice(d)
- if d.driver in ("usb", "hub"):
+ if d.driver in ("pcieport", "usb", "hub"):
continue
devices.append(d)
@property
def root_size(self):
- return self.system.get("root_size")
+ return self.system.get("root_size") or 0
+
+ @property
+ def vendor(self):
+ return self.system.get("vendor")
+
+ @property
+ def model(self):
+ return self.system.get("model")
+
+ @property
+ def country_code(self):
+ if self._geoip:
+ return self._geoip["country_code"].lower()
+ return "unknown"
class Stasy(object):
#
# return c
+ def profile_exists(self, public_id):
+ return self._db.profiles.find({ "public_id" : public_id }).count() >= 1
+
def get_profile(self, public_id):
# XXX should only find one object in the end
for p in self._db.profiles.find({ "public_id" : public_id }):
- p = Profile(p.get("public_id"), p.get("updated"), p.get("profile"))
+ p = Profile(p)
return p
return self._db.profiles.distinct("profile.cpu.vendor")
@property
- def cpu_map(self):
+ def cpu_vendors_map(self):
cpus = {}
for vendor in self.cpu_vendors:
return cpus
@property
- def memory_map(self):
+ def cpu_speed_average(self):
+ speed = 0
+
+ all = self._db.profiles.find()
+
+ # XXX ugly. needs to be done by group()
+ for m in all:
+ if not m.has_key("profile"):
+ continue
+ speed += m.get("profile").get("cpu").get("speed")
+
+ return (speed / all.count())
+
+ @property
+ def cpu_speed_map(self):
+ cpu_speeds = {}
+
+ for i in range(len(CPU_SPEED_CONSTRAINTS) - 1):
+ min, max = CPU_SPEED_CONSTRAINTS[i:i+2]
+
+ cpu_speeds[min, max] = \
+ self._db.profiles.find(
+ { "profile.cpu.speed" : {
+ "$gte" : min, "$lt" : max
+ }
+ }).count()
+
+ return cpu_speeds
+
+ def get_memory_map(self):
memory = {}
for i in range(len(MEMORY_CONSTRAINTS) - 1):
def languages(self):
return self._db.profiles.distinct("profile.system.language")
+ def get_language_map(self):
+ languages = {}
+
+ for language in self.languages:
+ languages[language] = \
+ self._db.profiles.find({
+ "profile.system.language" : language
+ }).count()
+
+ return languages
+
@property
def vendors(self):
return self._db.profiles.distinct("profile.system.vendor")
def models(self):
return self._db.profiles.distinct("profile.system.model")
+ @property
+ def model_map(self):
+ models = {}
+
+ for model in self.models:
+ models[model] = \
+ self._db.profiles.find({
+ "profile.system.model" : model
+ }).count()
+
+ return models
+
+ @property
+ def arches(self):
+ return self._db.profiles.distinct("profile.cpu.arch")
+
+ @property
+ def arch_map(self):
+ arches = {}
+
+ for arch in self.arches:
+ arches[arch] = \
+ self._db.profiles.find({
+ "profile.cpu.arch" : arch
+ }).count()
+
+ return arches
+
+ @property
+ def kernels(self):
+ return self._db.profiles.distinct("profile.system.kernel_release")
+
+ @property
+ def kernel_map(self):
+ kernels = {}
+
+ for kernel in self.kernels:
+ kernels[kernel] = \
+ self._db.profiles.find({
+ "profile.system.kernel_release" : kernel
+ }).count()
+
+ return kernels
+
+ @property
+ def releases(self):
+ return self._db.profiles.distinct("profile.system.release")
+
+ @property
+ def release_map(self):
+ releases = {}
+
+ for release in self.releases:
+ releases[release] = \
+ self._db.profiles.find({
+ "profile.system.release" : release
+ }).count()
+
+ return releases
+
+ def get_device_percentage(self, bus, vendor_id, model_id):
+ profiles_with_device = self._db.profiles.find({
+ "profile.devices.subsystem" : bus,
+ "profile.devices.vendor" : vendor_id,
+ "profile.devices.model" : model_id,
+ })
+
+ # XXX must only be systems that have profile data
+ profiles_all = self._db.profiles.find()
+
+ if not profiles_all.count():
+ return 0
+
+ return profiles_with_device.count() / profiles_all.count()
+
+ def get_cpu_flag_map(self, flag):
+ flags = {}
+
+ flags[True] = \
+ self._db.profiles.find({
+ "profile.cpu.flags" : flag,
+ }).count()
+
+ # XXX must only be systems that have profile data
+ profiles_all = self._db.profiles.find()
+
+ flags[False] = profiles_all.count() - flags[True]
+
+ return flags
+
+ @property
+ def geo_locations(self):
+ return [code.lower() for code in self._db.profiles.distinct("geoip.country_code")]
+
+ def get_geo_location_map(self):
+ geo_locations = {}
+
+ count = 0
+ for geo_location in self.geo_locations:
+ geo_locations[geo_location] = \
+ self._db.profiles.find({
+ "geoip.country_code" : geo_location
+ }).count()
+
+ count += geo_locations[geo_location]
+
+ # XXX must only be systems that have profile data
+ profiles_all = self._db.profiles.find()
+
+ unknown_count = profiles_all.count() - count
+ if unknown_count:
+ geo_locations["unknown"] = unknown_count
+
+ return geo_locations
+
+ def get_models_by_vendor(self, subsystem, vendor_id):
+ devices = []
+
+ # XXX must only be systems that have profile data
+ profiles_all = self._db.profiles.find()
+
+ for profile in profiles_all:
+ if not profile.has_key("profile"):
+ continue
+
+ profile = Profile(profile)
+
+ for device in profile.devices:
+ if not device.vendor == vendor_id:
+ continue
+
+ if not device in devices:
+ devices.append(device)
+
+ return devices
if __name__ == "__main__":
print s.hypervisor_vendors
print s.hypervisor_models
print s.languages
+ print s.language_maps
print s.vendors
print s.vendor_map
print s.models
print s.cpus
+ print s.cpu_map
+ print s.arches
+ print s.arch_map
+ print s.kernels
+ print s.kernel_map
+ print s.releases
+ print s.release_map
p = s.get_profile("0b5f4fe2162fdfbfa29b632610e317078fa70d34")
- print p
- print p.hypervisor
+ print p._data
+# print p.hypervisor
+