2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
10 # | Copyright Mathias Kettner 2013 mk@mathias-kettner.de |
11 # +------------------------------------------------------------------+
13 # This file is part of Check_MK.
14 # The official homepage is at http://mathias-kettner.de/check_mk.
16 # check_mk is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation in version 2. check_mk is distributed
19 # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
20 # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 # PARTICULAR PURPOSE. See the GNU General Public License for more de-
22 # tails. You should have received a copy of the GNU General Public
23 # License along with GNU Make; see the file COPYING. If not, write
24 # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 # Boston, MA 02110-1301 USA.
30 # Version: 6FET49WW (1.19 )
31 # Release Date: 10/17/2008
33 # Runtime Size: 128 kB
37 # PC Card (PCMCIA) is supported
40 # BIOS shadowing is allowed
41 # ESCD support is available
42 # Boot from CD is supported
43 # Selectable boot is supported
44 # BIOS ROM is socketed
47 # USB legacy is supported
48 # BIOS boot specification is supported
49 # Targeted content distribution is supported
51 # Firmware Revision: 1.1
54 # Manufacturer: LENOVO
55 # Product Name: 4061AR7
56 # Version: ThinkPad W500
57 # Serial Number: L3AFB3L
58 # UUID: AD137E01-4A86-11CB-A580-BE0E287D2679
59 # Wake-up Type: Power Switch
60 # SKU Number: Not Specified
61 # Family: ThinkPad W500
63 # ... any many other sections...
66 # Note: on Linux \t is replaced by : and then the split
67 # is done by :. On Windows the \t comes 1:1 and no splitting
68 # is being done. So we need to split manually here
69 def inv_dmidecode(info
):
73 # Windows plugin keeps tabs and has no separator
75 parts
= line
[0].replace("\t", ":").split(":")
76 line
= [x
.strip() for x
in parts
]
79 inv_dmidecode_parse_section(section_name
, section_lines
)
80 section_name
= line
[0]
83 section_lines
.append(line
[1:])
85 inv_dmidecode_parse_section(section_name
, section_lines
)
88 def inv_dmidecode_parse_section(name
, lines
):
89 lines
= [[w
.strip() for w
in words
] for words
in lines
]
90 if name
== "BIOS Information":
91 inv_dmidecode_parse_bios(lines
)
92 elif name
== "System Information":
93 inv_dmidecode_parse_system(lines
)
94 elif name
== "Chassis Information":
95 inv_dmidecode_parse_chassis(lines
)
96 elif name
== "Processor Information":
97 inv_dmidecode_parse_processor(lines
)
100 # elif name == "Memory Controller Information":
101 # inv_dmidecode_parse_mem_controller(lines)
102 # elif name == "Memory Module Information":
103 # inv_dmidecode_parse_mem_module(lines)
104 elif name
== "Physical Memory Array":
105 inv_dmidecode_parse_physical_mem_array(lines
)
106 elif name
== "Memory Device":
107 inv_dmidecode_parse_mem_device(lines
)
109 # TODO: Summe ueber alle Arrays ausrechnen
112 def inv_dmidecode_parse_date(value
):
115 return time
.mktime(time
.strptime(value
, "%m/%d/%Y"))
120 def inv_dmidecode_parse_bios(lines
):
121 inv_dmidecode_parse_generic(
122 "software.bios.", lines
, {
124 "Version": "version",
125 "Release Date": ("date", inv_dmidecode_parse_date
),
126 "BIOS Revision": "revision",
127 "Firmware Revision": "firmware",
131 def inv_dmidecode_parse_system(lines
):
132 inv_dmidecode_parse_generic(
133 "hardware.system.", lines
, {
134 "Manufacturer": "manufacturer",
135 "Product Name": "product",
136 "Version": "version",
137 "Serial Number": "serial",
143 def inv_dmidecode_parse_chassis(lines
):
144 inv_dmidecode_parse_generic("hardware.chassis.", lines
, {
145 "Manufacturer": "manufacturer",
150 # Note: This node is also being filled by lnx_cpuinfo
151 def inv_dmidecode_parse_processor(lines
):
154 if line
[0] == "Manufacturer":
155 cpu_info
["vendor"] = {
156 "GenuineIntel": "intel",
157 "Intel(R) Corporation": "intel",
158 "AuthenticAMD": "amd",
159 }.get(line
[1], line
[1])
160 elif line
[0] == "Max Speed": # 2530 MHz
161 cpu_info
["max_speed"] = dmidecode_parse_speed(line
[1])
162 elif line
[0] == "Voltage":
163 cpu_info
["voltage"] = dmidecode_parse_voltage(line
[1])
164 elif line
[0] == "Status":
165 if line
[1] == "Unpopulated":
168 # Only update our CPU information if the socket is populated
169 inv_tree("hardware.cpu.").update(cpu_info
)
172 # def inv_dmidecode_parse_mem_controller(lines):
173 # # TODO: Can we have multiple memory controllers
174 # node = inv_tree("hardware.memory.")
176 # if line[0] == "Maximum Memory Module Size":
177 # node["max_module_size"] = dmidecode_parse_size(line[1])
178 # elif line[0] == "Maximum Total Memory Size":
179 # node["max_memory_size"] = dmidecode_parse_size(line[1])
180 # elif line[0] == "Memory Module Voltage":
181 # node["module_voltage"] = dmidecode_parse_voltage(line[1])
183 # def inv_dmidecode_parse_mem_module(lines):
184 # node = inv_tree_list("hardware.memory.modules:")
186 # node.append(module)
188 # if line[0] == "Socket Designation":
189 # module["disignation"] = line[1]
190 # elif line[0] == "Type":
191 # module["type"] = line[1]
192 # elif line[0] == "Installed Size":
193 # module["size"] = dmidecode_parse_size(line[1])
194 # elif line[0] == "Enabled Size":
195 # module["enabled_size"] = dmidecode_parse_size(line[1])
196 # elif line[0] == "Current Speed":
197 # time_sec = dmidecode_parse_time(line[1])
198 # speed = 1.0 / time_sec
199 # module["current_speed"] = speed
202 def inv_dmidecode_parse_physical_mem_array(lines
):
203 # We expect several possible arrays
204 node
= inv_tree_list("hardware.memory.arrays:")
206 # If we have a dummy entry from previous Memory Devices (see below)
207 # then we fill that entry rather than creating a new one
208 if len(node
) == 1 and node
[0].keys() == ["devices"]:
211 array
= {"devices": []}
215 if line
[0] == "Location":
216 array
["location"] = line
[1]
217 elif line
[0] == "Use":
218 array
["use"] = line
[1]
219 elif line
[0] == "Error Correction Type":
220 array
["error_correction"] = line
[1]
221 elif line
[0] == "Maximum Capacity":
222 array
["maximum_capacity"] = dmidecode_parse_size(line
[1])
225 def inv_dmidecode_parse_mem_device(lines
):
226 node
= inv_tree_list("hardware.memory.arrays:")
229 inv_dmidecode_parse_generic(
233 "Total Width": "total_width", # 64 bits
234 "Data Width": "data_width", # 64 bits
235 "Form Factor": "form_factor", # SODIMM
237 "Locator": "locator", # PROC 1 DIMM 2
238 "Bank Locator": "bank_locator", # Bank 2/3
239 "Type": "type", # DDR2
240 "Type Detail": "type_detail", # Synchronous
241 "Manufacturer": "manufacturer", # Not Specified
242 "Serial Number": "serial", # Not Specified
243 "Asset Tag": "asset_tag", # Not Specified
244 "Part Number": "part_number", # Not Specified
245 "Speed": "speed", # 667 MHz
246 "Size": "size", # 2048 MB
249 # Do we already have an entry for a memory array? Then
250 # we assume that this device belongs to the most recently
251 # read array. Otherwise we create a dummy entry and replace
252 # that later with actual information
253 # If there are already arrays we try to find the right index of
256 if device
.get("locator") and device
["locator"].startswith("PROC"):
257 index
= device
["locator"].split()[1]
261 array
= node
[int(index
) - 1]
265 array
= {"devices": []}
268 if device
["size"] != "No Module Installed":
269 # Convert speed and size into numbers
270 device
["speed"] = dmidecode_parse_speed(device
.get("speed", "Unknown"))
271 device
["size"] = dmidecode_parse_size(device
.get("size", "Unknown"))
272 array
["devices"].append(device
)
275 def inv_dmidecode_parse_generic(node
, lines
, keyinfo
):
276 if isinstance(node
, str):
277 node
= inv_tree(node
)
279 if line
[0] in keyinfo
:
280 key
= keyinfo
[line
[0]]
281 if line
[1] != "Not Specified":
283 if isinstance(key
, tuple):
285 value
= transform(value
)
291 def dmidecode_parse_size(v
): # into Bytes (int)
296 if parts
[1].lower() == "tb":
297 return int(parts
[0]) * 1024 * 1024 * 1024 * 1024
298 elif parts
[1].lower() == "gb":
299 return int(parts
[0]) * 1024 * 1024 * 1024
300 elif parts
[1].lower() == "mb":
301 return int(parts
[0]) * 1024 * 1024
302 elif parts
[1].lower() == "kb":
303 return int(parts
[0]) * 1024
307 def dmidecode_parse_speed(v
): # into Hz (float)
312 if parts
[1] == "GHz":
313 return float(parts
[0]) * 1000000000.0
314 elif parts
[1] == "MHz":
315 return float(parts
[0]) * 1000000.0
316 elif parts
[1] == "kHz":
317 return float(parts
[0]) * 1000.0
318 elif parts
[1] == "Hz":
319 return float(parts
[0])
322 def dmidecode_parse_voltage(v
):
325 return float(v
.split()[0])
328 def dmidecode_parse_time(v
): # 155 ns
331 return float(parts
[0]) / 1000000000.0
332 return float(parts
[0]) # assume seconds
335 inv_info
['dmidecode'] = {
336 "inv_function": inv_dmidecode
,