]>
Commit | Line | Data |
---|---|---|
b45f0e98 MT |
1 | #!/usr/bin/python |
2 | ||
31a30328 | 3 | import hashlib |
b45f0e98 MT |
4 | import json |
5 | import os | |
6 | import string | |
7 | ||
8 | import cpu | |
9 | import device | |
715ba5ac | 10 | import hypervisor |
b45f0e98 | 11 | |
32aeec73 MT |
12 | class Singleton(type): |
13 | def __init__(cls, name, bases, dict): | |
14 | super(Singleton, cls).__init__(name, bases, dict) | |
15 | cls.instance = None | |
16 | ||
17 | def __call__(cls, *args, **kw): | |
18 | if cls.instance is None: | |
19 | cls.instance = super(Singleton, cls).__call__(*args, **kw) | |
20 | ||
21 | return cls.instance | |
22 | ||
23 | ||
b45f0e98 | 24 | class System(object): |
32aeec73 | 25 | __metaclass__ = Singleton |
b45f0e98 MT |
26 | |
27 | def __init__(self): | |
28 | # find all devices | |
29 | self.devices = [] | |
30 | self.scan() | |
31 | self.cpu = cpu.CPU() | |
715ba5ac MT |
32 | self.hypervisor = hypervisor.Hypervisor() |
33 | ||
b45f0e98 MT |
34 | def profile(self): |
35 | p = { | |
36 | "public_id" : self.public_id, | |
37 | "private_id" : self.private_id, | |
38 | ||
39 | "arch" : self.arch, | |
40 | "language" : self.language, | |
41 | "release" : self.release, | |
42 | "memory" : self.memory, | |
43 | "kernel" : self.kernel, | |
44 | "root_size" : self.root_size, | |
45 | "devices" : [], | |
d8614fc3 MT |
46 | |
47 | "virtual" : self.virtual, | |
b45f0e98 MT |
48 | } |
49 | ||
50 | for device in self.devices: | |
51 | p["devices"].append({ | |
52 | "subsystem" : device.subsystem.lower(), | |
53 | "vendor" : device.vendor.lower(), | |
54 | "model" : device.model.lower(), | |
55 | "deviceclass" : device.deviceclass | |
56 | }) | |
57 | ||
58 | p["cpu"] = { | |
59 | "vendor" : self.cpu.vendor, | |
60 | "model" : self.cpu.model, | |
61 | "stepping" : self.cpu.stepping, | |
62 | "flags" : self.cpu.flags, | |
63 | "bogomips" : self.cpu.bogomips, | |
64 | "speed" : self.cpu.speed, | |
b45f0e98 MT |
65 | "family" : self.cpu.family, |
66 | "count" : self.cpu.count | |
67 | } | |
715ba5ac MT |
68 | |
69 | # Only append hypervisor information if we are virtualized. | |
70 | if self.virtual: | |
71 | p["hypervisor"] = { | |
72 | "type" : self.hypervisor.type, | |
73 | "vendor" : self.hypervisor.vendor, | |
74 | } | |
75 | ||
65891720 | 76 | return p |
b45f0e98 MT |
77 | |
78 | ||
79 | @property | |
80 | def arch(self): | |
81 | return os.uname()[4] | |
82 | ||
83 | @property | |
84 | def public_id(self): | |
31a30328 MT |
85 | """ |
86 | This returns a globally (hopefully) ID to identify the host | |
87 | later (by request) in the database. | |
88 | """ | |
89 | return hashlib.sha1(self._unique_id).hexdigest() | |
b45f0e98 MT |
90 | |
91 | @property | |
92 | def private_id(self): | |
31a30328 MT |
93 | """ |
94 | The private ID is built out of the _unique_id and used to | |
95 | permit a host to do changes on the database. | |
96 | ||
97 | No one could ever guess this without access to the host. | |
98 | """ | |
5e2ba24e MT |
99 | private_id = "" |
100 | for i in reversed(self._unique_id): | |
101 | private_id += i | |
102 | ||
103 | return hashlib.sha1(private_id).hexdigest() | |
31a30328 MT |
104 | |
105 | @property | |
106 | def _unique_id(self): | |
107 | """ | |
108 | This is a helper ID which is generated out of some hardware information | |
109 | that is considered to be constant over a PC's lifetime. | |
110 | ||
111 | None of the data here is ever sent to the server. | |
112 | """ | |
113 | return "123456789" # XXX just a dummy | |
114 | ||
b45f0e98 MT |
115 | @property |
116 | def language(self): | |
b3ea53a7 MT |
117 | # Return "unknown" if settings file does not exist. |
118 | filename = "/var/ipfire/main/settings" | |
119 | if not os.path.exists(filename): | |
120 | return "unknown" | |
121 | ||
122 | with open(filename, "r") as f: | |
b45f0e98 MT |
123 | for line in f.readlines(): |
124 | key, val = line.split("=", 1) | |
125 | if key=="LANGUAGE": | |
126 | return val.strip() | |
127 | ||
128 | @property | |
129 | def release(self): | |
130 | with open("/etc/system-release", "r") as f: | |
131 | return f.read().strip() | |
b56bde73 SP |
132 | |
133 | @property | |
134 | def bios_vendor(self): | |
135 | with open("/sys/class/dmi/id/bios_vendor", "r") as f: | |
136 | return f.read().strip() | |
137 | ||
b45f0e98 MT |
138 | @property |
139 | def memory(self): | |
140 | with open("/proc/meminfo", "r") as f: | |
141 | firstline = f.readline().strip() | |
142 | return firstline.split()[1] | |
143 | ||
144 | @property | |
145 | def kernel(self): | |
146 | return os.uname()[2] | |
147 | ||
148 | @property | |
149 | def root_disk(self): | |
150 | with open("/etc/mtab", "r") as f: | |
151 | dev, mountpoint, rest = f.readline().split(" ",2) | |
152 | if mountpoint == "/": | |
153 | dev = dev[5:] | |
154 | # cut off all digits at end of string | |
155 | while dev[-1] in string.digits: | |
156 | dev = dev[:-1] | |
157 | return dev | |
158 | ||
159 | @property | |
160 | def root_size(self): | |
161 | path="/sys/block/%s/size" %self.root_disk | |
162 | if not os.path.exists(path): | |
163 | return | |
164 | with open(path, "r") as f: | |
165 | return int(f.readline())*512/1024 | |
166 | ||
167 | def scan(self): | |
168 | toscan = (("/sys/bus/pci/devices", device.PCIDevice), | |
169 | ("/sys/bus/usb/devices", device.USBDevice)) | |
170 | for path, cls in toscan: | |
171 | dirlist = os.listdir(path) | |
172 | for dir in dirlist: | |
173 | self.devices.append(cls(os.path.join(path, dir))) | |
d8614fc3 MT |
174 | |
175 | @property | |
176 | def virtual(self): | |
177 | """ | |
178 | Say if the host is running in a virtual environment. | |
179 | """ | |
715ba5ac | 180 | return self.hypervisor.virtual |
b45f0e98 MT |
181 | |
182 | ||
183 | ||
184 | if __name__ == "__main__": | |
185 | s=System() | |
186 | print s.arch | |
187 | print s.language | |
188 | print s.release | |
b56bde73 | 189 | print s.bios_vendor |
b45f0e98 MT |
190 | print s.memory |
191 | print s.kernel | |
192 | print s.root_disk | |
193 | print s.root_size | |
194 | print "------------\n", s.devices, "\n------------\n" | |
65891720 | 195 | print json.dumps(s.profile(), sort_keys=True, indent=4) |