]>
Commit | Line | Data |
---|---|---|
372efc19 MT |
1 | #!/usr/bin/python |
2 | ||
3 | import hwdata | |
4 | import logging | |
5 | import pymongo | |
6 | ||
7 | from misc import Singleton | |
8 | ||
9 | DATABASE_HOST = ["irma.ipfire.org", "madeye.ipfire.org"] | |
10 | DATABASE_NAME = "stasy" | |
11 | ||
12 | MEMORY_CONSTRAINTS = (0, 64, 128, 256, 512, 1024, 2048, 4096, 8128, 16384) | |
13 | ||
14 | class ProfileDict(object): | |
15 | def __init__(self, data): | |
16 | self._data = data | |
17 | ||
18 | ||
19 | class ProfileCPU(ProfileDict): | |
20 | @property | |
21 | def arch(self): | |
22 | return self._data.get("arch") | |
23 | ||
24 | @property | |
25 | def vendor(self): | |
26 | return self._data.get("vendor") | |
27 | ||
28 | @property | |
29 | def model(self): | |
30 | return self._data.get("model") | |
31 | ||
32 | @property | |
33 | def model_string(self): | |
34 | return self._data.get("model_string") | |
35 | ||
36 | @property | |
37 | def flags(self): | |
38 | return self._data.get("flags") | |
39 | ||
40 | @property | |
41 | def capable_64bit(self): | |
42 | return "lm" in self.flags | |
43 | ||
44 | @property | |
45 | def capable_pae(self): | |
46 | return "pae" in self.flags | |
47 | ||
48 | @property | |
49 | def capable_virt(self): | |
50 | return "vmx" in self.flags or "svm" in self.flags | |
51 | ||
52 | ||
53 | class ProfileHypervisor(ProfileDict): | |
54 | def __repr__(self): | |
55 | return "<%s %s-%s>" % (self.__class__.__name__, self.vendor, self.type) | |
56 | ||
57 | @property | |
58 | def vendor(self): | |
59 | return self._data.get("vendor") | |
60 | ||
61 | @property | |
62 | def model(self): | |
63 | return self._data.get("model") | |
64 | ||
65 | @property | |
66 | def type(self): | |
67 | return self._data.get("type") | |
68 | ||
69 | ||
70 | class ProfileDevice(ProfileDict): | |
71 | subsystem2class = { | |
72 | "pci" : hwdata.PCI, | |
73 | "usb" : hwdata.USB, | |
74 | } | |
75 | ||
76 | @property | |
77 | def model(self): | |
78 | return self._data.get("model") | |
79 | ||
80 | @property | |
81 | def model_string(self): | |
82 | cls = self.subsystem2class[self.subsystem] | |
83 | ||
84 | return cls().get_device(self.vendor, self.model) | |
85 | ||
86 | @property | |
87 | def subsystem(self): | |
88 | return self._data.get("subsystem") | |
89 | ||
90 | @property | |
91 | def vendor(self): | |
92 | return self._data.get("vendor") | |
93 | ||
94 | @property | |
95 | def vendor_string(self): | |
96 | cls = self.subsystem2class[self.subsystem] | |
97 | ||
98 | return cls().get_vendor(self.vendor) | |
99 | ||
100 | @property | |
101 | def driver(self): | |
102 | return self._data.get("driver") | |
103 | ||
104 | ||
105 | class Profile(ProfileDict): | |
106 | def __init__(self, public_id, updated, data): | |
107 | ProfileDict.__init__(self, data) | |
108 | ||
109 | self.public_id = public_id | |
110 | self.updated = updated | |
111 | ||
112 | def __repr__(self): | |
113 | return "<%s %s>" % (self.__class__.__name__, self.public_id) | |
114 | ||
115 | @property | |
116 | def cpu(self): | |
117 | return ProfileCPU(self._data.get("cpu")) | |
118 | ||
119 | @property | |
120 | def devices(self): | |
121 | devices = [] | |
122 | for d in self._data.get("devices"): | |
123 | d = ProfileDevice(d) | |
124 | ||
125 | if d.driver in ("usb", "hub"): | |
126 | continue | |
127 | ||
128 | devices.append(d) | |
129 | ||
130 | return devices | |
131 | ||
132 | @property | |
133 | def hypervisor(self): | |
134 | if self.virtual: | |
135 | return ProfileHypervisor(self._data.get("hypervisor")) | |
136 | ||
137 | @property | |
138 | def virtual(self): | |
139 | return self.system.get("virtual") | |
140 | ||
141 | @property | |
142 | def system(self): | |
143 | return self._data.get("system") | |
144 | ||
145 | @property | |
146 | def release(self): | |
147 | return self.system.get("release") | |
148 | ||
149 | @property | |
150 | def kernel(self): | |
151 | return self.system.get("kernel_release") | |
152 | ||
153 | @property | |
154 | def memory(self): | |
155 | return self.system.get("memory") | |
156 | ||
157 | @property | |
158 | def root_size(self): | |
159 | return self.system.get("root_size") | |
160 | ||
161 | ||
162 | ||
163 | class Stasy(object): | |
164 | __metaclass__ = Singleton | |
165 | ||
166 | def __init__(self): | |
167 | # Initialize database connection | |
168 | self._conn = pymongo.Connection(DATABASE_HOST) | |
169 | self._db = self._conn[DATABASE_NAME] | |
170 | ||
171 | def get_profile_count(self): | |
172 | # XXX need to implement something to get profiles updated since | |
173 | # a given date | |
174 | ||
175 | # All distinct profiles (based on public_id) | |
176 | return self._db.profiles.distinct("public_id").count() | |
177 | ||
178 | #def _get_profile_cursor(self, public_id): | |
179 | # c = self._db.profiles.find({ "public_id" : public_id }) | |
180 | # c.sort("updated", pymongo.ASCENDING) | |
181 | # | |
182 | # return c | |
183 | ||
184 | def get_profile(self, public_id): | |
185 | # XXX should only find one object in the end | |
186 | for p in self._db.profiles.find({ "public_id" : public_id }): | |
187 | p = Profile(p.get("public_id"), p.get("updated"), p.get("profile")) | |
188 | ||
189 | return p | |
190 | ||
191 | def get_profiles(self): | |
192 | # XXX needs nicer database query | |
193 | profiles = [] | |
194 | for p in self._db.profiles.find(): | |
195 | if not p.get("public_id") in profiles: | |
196 | profiles.append(p.get("public_id")) | |
197 | ||
198 | return profiles | |
199 | ||
200 | @property | |
201 | def secret_ids(self): | |
202 | return self._db.profiles.distinct("secret_id") | |
203 | ||
204 | @property | |
205 | def cpus(self): | |
206 | return self._db.profiles.distinct("profile.cpu") | |
207 | ||
208 | @property | |
209 | def cpu_vendors(self): | |
210 | return self._db.profiles.distinct("profile.cpu.vendor") | |
211 | ||
212 | @property | |
213 | def cpu_map(self): | |
214 | cpus = {} | |
215 | ||
216 | for vendor in self.cpu_vendors: | |
217 | cpus[vendor] = \ | |
218 | self._db.profiles.find({ | |
219 | "profile.cpu.vendor" : vendor | |
220 | }).count() | |
221 | ||
222 | return cpus | |
223 | ||
224 | @property | |
225 | def memory_map(self): | |
226 | memory = {} | |
227 | ||
228 | for i in range(len(MEMORY_CONSTRAINTS) - 1): | |
229 | min, max = MEMORY_CONSTRAINTS[i:i+2] | |
230 | ||
231 | memory[min, max] = \ | |
232 | self._db.profiles.find( | |
233 | { "profile.system.memory" : { | |
234 | "$gte" : min * 1024, "$lt" : max * 1024 | |
235 | } | |
236 | }).count() | |
237 | ||
238 | return memory | |
239 | ||
240 | @property | |
241 | def memory_average(self): | |
242 | memory = 0 | |
243 | ||
244 | all = self._db.profiles.find() | |
245 | ||
246 | # XXX ugly. needs to be done by group() | |
247 | for m in all: | |
248 | if not m.has_key("profile"): | |
249 | continue | |
250 | memory += int(m.get("profile").get("system").get("memory")) | |
251 | ||
252 | return (memory / all.count()) / 1024 | |
253 | ||
254 | @property | |
255 | def hypervisor_vendors(self): | |
256 | return self._db.profiles.distinct("profile.hypervisor.vendor") | |
257 | ||
258 | @property | |
259 | def hypervisor_map(self): | |
260 | hypervisors = {} | |
261 | ||
262 | for hypervisor in self.hypervisor_vendors: | |
263 | hypervisors[hypervisor] = \ | |
264 | self._db.profiles.find({ | |
265 | "profile.hypervisor.vendor" : hypervisor | |
266 | }).count() | |
267 | ||
268 | return hypervisors | |
269 | ||
270 | @property | |
271 | def hypervisor_models(self): | |
272 | return self._db.profiles.distinct("profile.hypervisor.model") | |
273 | ||
274 | @property | |
275 | def virtual_map(self): | |
276 | virtual = { | |
277 | True: None, | |
278 | False: None, | |
279 | } | |
280 | ||
281 | for k in virtual.keys(): | |
282 | virtual[k] = \ | |
283 | self._db.profiles.find({ "profile.system.virtual": k }).count() | |
284 | ||
285 | return virtual | |
286 | ||
287 | @property | |
288 | def languages(self): | |
289 | return self._db.profiles.distinct("profile.system.language") | |
290 | ||
291 | @property | |
292 | def vendors(self): | |
293 | return self._db.profiles.distinct("profile.system.vendor") | |
294 | ||
295 | @property | |
296 | def vendor_map(self): | |
297 | vendors = {} | |
298 | ||
299 | for vendor in self.vendors: | |
300 | vendors[vendor] = \ | |
301 | self._db.profiles.find({ | |
302 | "profile.system.vendor" : vendor | |
303 | }).count() | |
304 | ||
305 | return vendors | |
306 | ||
307 | @property | |
308 | def models(self): | |
309 | return self._db.profiles.distinct("profile.system.model") | |
310 | ||
311 | ||
312 | ||
313 | if __name__ == "__main__": | |
314 | s = Stasy() | |
315 | ||
316 | print s.get_profile("0" * 40) | |
317 | print s.cpu_vendors | |
318 | for id in s.secret_ids: | |
319 | print "\t", id | |
320 | ||
321 | #for p in s._db.profiles.find(): | |
322 | # print p | |
323 | ||
324 | print s.cpu_map | |
325 | print s.memory_map | |
326 | print s.memory_average | |
327 | print s.hypervisor_vendors | |
328 | print s.hypervisor_models | |
329 | print s.languages | |
330 | print s.vendors | |
331 | print s.vendor_map | |
332 | print s.models | |
333 | print s.cpus | |
334 | ||
335 | p = s.get_profile("0b5f4fe2162fdfbfa29b632610e317078fa70d34") | |
336 | print p | |
337 | print p.hypervisor |