]>
git.ipfire.org Git - oddments/fireinfo.git/blob - fireinfo/system.py
135c29b04324c9ce600e46ba135d41cddfcce732
2 ###############################################################################
5 # Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
36 SYS_CLASS_DMI
= "/sys/class/dmi/id"
37 SECRET_ID_FILE
= "/etc/fireinfo-id"
39 INVALID_ID_STRINGS
= (
40 "OEM", "O.E.M.", "o.e.m.",
42 "12345", "54321", "202020",
46 class Singleton(type):
47 def __init__(cls
, name
, bases
, dict):
48 super(Singleton
, cls
).__init
__(name
, bases
, dict)
51 def __call__(cls
, *args
, **kw
):
52 if cls
.instance
is None:
53 cls
.instance
= super(Singleton
, cls
).__call
__(*args
, **kw
)
58 def read_from_file(filename
):
60 Read all data from filename.
62 if not os
.path
.exists(filename
):
66 with
open(filename
) as f
:
67 return f
.read().strip()
72 __metaclass__
= Singleton
79 self
.hypervisor
= hypervisor
.Hypervisor()
86 "vendor" : self
.vendor
,
88 # Indicator if the system is running in a
89 # virtual environment.
90 "virtual" : self
.virtual
,
93 "language" : self
.language
,
96 "release" : self
.release
,
97 "kernel_release" : self
.kernel_release
,
99 "memory" : self
.memory
,
100 "root_size" : self
.root_size
,
104 for device
in self
.devices
:
106 "subsystem" : device
.subsystem
.lower(),
107 "vendor" : device
.vendor
.lower(),
108 "model" : device
.model
.lower(),
109 "deviceclass" : device
.deviceclass
,
110 "driver" : device
.driver
,
113 # PCI devices provide subsystem information, USB don't.
114 if d
["subsystem"] == "pci":
115 d
["sub_model"] = device
.sub_model
116 d
["sub_vendor"] = device
.sub_vendor
118 p
["devices"].append(d
)
122 "vendor" : self
.cpu
.vendor
,
123 "model" : self
.cpu
.model
,
124 "model_string" : self
.cpu
.model_string
,
125 "stepping" : self
.cpu
.stepping
,
126 "flags" : self
.cpu
.flags
,
127 "bogomips" : self
.cpu
.bogomips
,
128 "speed" : self
.cpu
.speed
,
129 "family" : self
.cpu
.family
,
130 "count" : self
.cpu
.count
134 "green" : self
.network
.has_green(),
135 "blue" : self
.network
.has_blue(),
136 "orange" : self
.network
.has_orange(),
137 "red" : self
.network
.has_red(),
140 # Only append hypervisor information if we are virtualized.
143 "type" : self
.hypervisor
.type,
144 "vendor" : self
.hypervisor
.vendor
,
149 "profile_version" : PROFILE_VERSION
,
151 # Identification and authorization codes
152 "public_id" : self
.public_id
,
153 "private_id" : self
.private_id
,
155 # Actual profile data
167 This returns a globally (hopefully) ID to identify the host
168 later (by request) in the database.
170 public_id
= self
.secret_id
174 return hashlib
.sha1(public_id
).hexdigest()
177 def private_id(self
):
179 The private ID is built out of the _unique_id and used to
180 permit a host to do changes on the database.
182 No one could ever guess this without access to the host.
185 for i
in reversed(self
.secret_id
):
191 return hashlib
.sha1(private_id
).hexdigest()
196 Read a "secret" ID from a file if available
197 or calculate it from the hardware.
199 if os
.path
.exists(SECRET_ID_FILE
):
200 return read_from_file(SECRET_ID_FILE
)
202 return hashlib
.sha1(self
._unique
_id
).hexdigest()
205 def _unique_id(self
):
207 This is a helper ID which is generated out of some hardware information
208 that is considered to be constant over a PC's lifetime.
210 None of the data here is ever sent to the server.
214 # Virtual machines (for example) and some boards have a UUID
215 # which is globally unique.
216 for file in ("product_uuid", "product_serial", "chassis_serial"):
217 id = read_from_file(os
.path
.join(SYS_CLASS_DMI
, file))
220 # Sort out all bogous or invalid strings from the list.
226 for i
in INVALID_ID_STRINGS
:
236 # Use serial number from root disk (if available) and if
237 # no other ID was found, yet.
239 root_disk_serial
= self
.root_disk_serial
240 if root_disk_serial
and not root_disk_serial
.startswith("QM000"):
241 ids
.append(root_disk_serial
)
243 # As last resort, we use the UUID from pakfire.
245 id = read_from_file("/opt/pakfire/db/uuid")
253 Return the language code of IPFire or "unknown" if we cannot get it.
255 # Return "unknown" if settings file does not exist.
256 filename
= "/var/ipfire/main/settings"
257 if not os
.path
.exists(filename
):
260 with
open(filename
, "r") as f
:
261 for line
in f
.readlines():
262 key
, val
= line
.split("=", 1)
263 if key
== "LANGUAGE":
269 Return the system release string.
271 return read_from_file("/etc/system-release")
274 def bios_vendor(self
):
276 Return the bios vendor name.
278 return read_from_file("/sys/class/dmi/id/bios_vendor")
283 Return the vendor string of this system (if any).
286 for file in ("sys_vendor", "board_vendor", "chassis_vendor",):
287 ret
= read_from_file(os
.path
.join(SYS_CLASS_DMI
, file))
296 Return the model string of this system (if any).
299 for file in ("product_name", "board_model", "chassis_model",):
300 ret
= read_from_file(os
.path
.join(SYS_CLASS_DMI
, file))
309 Return the amount of memory in kilobytes.
311 with
open("/proc/meminfo", "r") as f
:
312 firstline
= f
.readline().strip()
313 return int(firstline
.split()[1])
316 def kernel_release(self
):
318 Return the kernel release string.
325 Return the dev node of the root disk.
327 with
open("/etc/mtab", "r") as f
:
328 dev
, mountpoint
, rest
= f
.readline().split(" ", 2)
329 if mountpoint
== "/":
332 # Cut off all digits at end of string
333 while dev
[-1] in string
.digits
:
341 Return the size of the root disk in kilobytes.
343 path
= "/sys/block/%s/size" % self
.root_disk
344 if not os
.path
.exists(path
):
347 with
open(path
, "r") as f
:
348 return int(f
.readline()) * 512 / 1024
351 def root_disk_serial(self
):
353 Return the serial number of the root disk (if any).
355 serial
= _fireinfo
.get_harddisk_serial("/dev/%s" % self
.root_disk
)
359 return serial
.strip()
363 Scan for all devices (PCI/USB) in the system and append them
369 ("/sys/bus/pci/devices", device
.PCIDevice
),
370 ("/sys/bus/usb/devices", device
.USBDevice
)
372 for path
, cls
in toscan
:
373 if not os
.path
.exists(path
):
376 dirlist
= os
.listdir(path
)
378 self
.devices
.append(cls(os
.path
.join(path
, dir)))
383 Say if the host is running in a virtual environment.
385 return self
.hypervisor
.virtual
390 Reference to the network class.
392 return network
.Network()
395 if __name__
== "__main__":
405 print "------------\n", s
.devices
, "\n------------\n"
406 print json
.dumps(s
.profile(), sort_keys
=True, indent
=4)