1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """Provides an interface to an abstract system
20
21 """
22
23 from threading import Lock,Timer
24 import re
25 import callback
28 """Represents an abstract system and implements some basic logic.
29
30 """
31
45
47 """Returns the identifying name of the system.
48 """
49 return self._name
50
52 """Runs the system monitor.
53
54 All parts are updated immediately, and then again at the
55 interval specified in the parts' configuration.
56 """
57 for part in self.parts():
58 part.update()
59
61 """Stops the system monitor.
62
63 The monitor may safely be stopped and run and indefinite
64 number of times.
65 """
66 for part in self.parts():
67 part.timer.cancel()
68
70 """Acquire the lock object hidden in this system,
71 """
72 self.lock.acquire()
73
75 """Release the lock object hidden in this system.
76 """
77 self.lock.release()
78
80 """Performs an update of the system.
81
82 These updates are done periodically (depending on the delay
83 setting), so there is ordinarily no reason to call it from
84 outside of the system.
85
86 Implementation note: this method updates the entire
87 system. Since each part may have its own delay interval, the
88 parts are responsible for calling their own update methods
89 independently of the system. In other words, this method is
90 ordinarily never called.
91 """
92 for part in self.parts():
93 part.update()
94
96 """Sets the update interval after which information is
97 refreshed, in seconds. This may be a fraction.
98 """
99 self._delay=interval
100
102 """Returns the update interval after which information is
103 refreshed in seconds.
104 """
105 return self._delay
106
108 """Sets the callback class to be used
109
110 Generally, this function is not needed, as a callback class is
111 usually created that can be used without setting a new one.
112 """
113 self._callback=callback
114
116 """Returns the callback class being used
117 """
118 return self._callback
119
121 """Returns a list of all parts of the system.
122 """
123 return (self._processors+
124 [self._memory]+
125 self._filesystems+
126 self._drives+
127 [self._uptime]+
128 self._netconns+
129 [self._processlist])
130
136
138 """Returns the system's uptime object.
139 """
140 return self._uptime
141
147
149 """Returns a list of processors in the system.
150 """
151 return self._processors
152
154 """Returns the processor with the specified name, or None if
155 there is none.
156 """
157 for p in self.processors():
158 if p.name()==name:
159 return p
160 return None
161
167
169 """Returns the system's memory bank.
170 """
171 return self._memory
172
174 """adds a drive to the system
175 """
176 drive.set_system(self)
177 self._drives+=[drive]
178
180 """Returns a list of all physical drives in the system.
181 """
182 return self._drives
183
185 """adds a filesystem to the system
186 """
187 filesystem.set_system(self)
188 self._filesystems+=[filesystem]
189
191 """Returns a list of all filesystems in the system.
192 """
193 return self._filesystems
194
196 """Adds a network connection to the system.
197 """
198 nc.set_system(self)
199 self._netconns+=[nc]
200
202 """Returns a list of all network connections in the system
203 """
204 return self._netconns
205
211
213 """Returns the object representing the process list.
214 """
215 return self._processlist
216
219 """Represents a part of a system.
220 """
222 self._delay=None
223 self._system=None
224 self.timer=None
225
226 @staticmethod
228 """Returns a null part to be used when no real part is
229 available.
230 """
231 return SystemPart()
232
234 """Performs an update of the part's information.
235
236 This method is called periodically (depending on the delay
237 setting), so there is ordinarily no reason to call it from
238 outside of the system.
239 """
240
241 if not self.delay():
242 self.set_delay(self.system().delay())
243
244
245
246 self.system().acquire()
247
248 self.do_update()
249
250
251 if not self.delay()==-1:
252
253 self.timer=Timer(self.delay(),self.update)
254 self.timer.daemon=True
255 self.timer.start()
256
257 self.system().release()
258
261
263 """Perform the actual update.
264
265 Part implementations should override this method.
266 """
267 self.system().callback().call("misc.updated",self)
268
270 """Sets the delay between updates.
271 """
272 self._delay=delay
273
275 """Returns the current delay between updates.
276 """
277 return self._delay
278
280 """Sets the system that this part is in.
281
282 A part may only be in one system at once - if a part is in two
283 systems at once IRL, it may be best to have a representation
284 of it in each system, or to make it its own system.
285 """
286 self._system=system
287
290
293 """Represents the uptime of a system.
294 """
296 """Returns the uptime in seconds.
297 """
298 return 0
299
301 """Represents a single abstract processor.
302 """
304 """An appropriate name for the processor, like cpu4.
305 """
306 return "cpu"
307
309 """The modelname of this processor.
310 """
311 return self.dict()['model name']
312
314 """The maximum frequency of this processor, in MHz.
315 """
316 mf=self.freq()
317
318 mn=self.modelname()
319 match=re.search('([0-9.]+)GHz',mn)
320 if match:
321 mf=float(match.group(1))*1000
322 return float(mf)
323
325 """The current operating frequency of this processor, in MHz.
326 """
327 return self.dict()['cpu MHz']
328
330 """The current usage of this processor, as a fraction.
331 """
332 return float(self.dict()['usage'])
333
335 """Returns a dictionary with a massive amount of
336 meta-information, by string.
337
338 Most implementations will take this directly out of
339 /proc/cpuinfo. It is generally bad form to use this directly
340 in an application.
341 """
342 return dict()
343
346 """Represents a memory (RAM) bank.
347 """
349 """Returns the total amount of memory, in bytes.
350 """
351 return self.dict()['MemTotal']
352
354 """Returns the amount of completely free memory, in bytes.
355
356 Generally, it's better to use unused_memory, since
357 free_memory doesn't count caching and other such "essentially
358 free" types of memory.
359 """
360 return self.dict()['MemFree']
361
363 """Returns the number of bytes of active memory.
364 """
365 return self.dict()['Active']
366
368 """Returns the amount of inactive memory, in bytes.
369 """
370 return self.dict()['Inactive']
371
376
378 """Returns the total amount of swap, in bytes.
379 """
380 return self.dict()['SwapTotal']
381
383 """Returns the amount of free swap, in bytes.
384 """
385 return self.dict()['SwapFree']
386
388 """Returns a dictionary with a massive amount of
389 meta-information, by string.
390
391 Most implementations will take this directly out of
392 /proc/meminfo. It is generally bad form to use this in an
393 application.
394 """
395 return dict()
396
399 """Represents a filesystem.
400 """
402 """Returns the size, in bytes, of the filesystem.
403 """
404 return 0
405
407 """Returns the amount of used space, in bytes, of the
408 filesystem.
409 """
410 return 0
411
413 """Returns the available space, in bytes, of the filesystem.
414 """
415 return self.size()-self.used()
416
418 """Returns the device name (the relative path from /dev).
419 """
420 pass
421
423 """Returns the mount point of the drive, or None if not
424 mounted.
425 """
426 pass
427
429 """Returns True if the drive is mounted, or False otherwise.
430 """
431 return self.mount_point()==None
432
433
434 -class Drive(SystemPart):
435 """Represents a physical drive.
436 """
437 pass
438
440 """Represents a list of processes.
441 """
442 pass
443
446 """Represents a single network connection
447 """
448 pass
449
452 """Represents a single process
453 """
454 pass
455
458 """Represents running server software (sshd, httpd, etc...)
459 """
460 pass
461