-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsysteminfo.py
executable file
·380 lines (300 loc) · 11.3 KB
/
systeminfo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
#!/usr/bin/python
#
# Copyright (c) 2003 Intel Corporation
# All rights reserved.
#
# Copyright (c) 2004-2006 The Trustees of Princeton University
# All rights reserved.
# expected /proc/partitions format
#----------------------------------------------------
#major minor #blocks name
#
#3 0 40017915 hda
#3 1 208813 hda1
#3 2 20482875 hda2
#3 3 522112 hda3
#3 4 18804082 hda4
#----------------------------------------------------
import string
import sys
import os
import popen2
import re
import errno
import ModelOptions
from pypci import *
from Exceptions import *
"""
a utility class for finding and returning information about
block devices, memory, and other hardware on the system
"""
PROC_MEMINFO_PATH= "/proc/meminfo"
PROC_PARTITIONS_PATH= "/proc/partitions"
# set when the sfdisk -l <dev> trick has been done to make
# all devices show up
DEVICES_SCANNED_FLAG= "/tmp/devices_scanned"
# a /proc/partitions block is 1024 bytes
# a GB to a HDD manufacturer is 10^9 bytes
BLOCKS_PER_GB = pow(10, 9) / 1024.0;
MODULE_CLASS_NETWORK= "network"
MODULE_CLASS_SCSI= "scsi"
#PCI_* is now defined in the pypci modules
#PCI_BASE_CLASS_NETWORK=0x02L
#PCI_BASE_CLASS_STORAGE=0x01L
def get_total_phsyical_mem(vars = {}, log = sys.stderr):
"""
return the total physical memory of the machine, in kilobytes.
Return None if /proc/meminfo not readable.
"""
try:
meminfo_file= file(PROC_MEMINFO_PATH,"r")
except IOError, e:
return
total_memory= None
for line in meminfo_file:
try:
(fieldname,value)= string.split(line,":")
except ValueError, e:
# this will happen for lines that don't have two values
# (like the first line on 2.4 kernels)
continue
fieldname= string.strip(fieldname)
value= string.strip(value)
if fieldname == "MemTotal":
try:
(total_memory,units)= string.split(value)
except ValueError, e:
return
if total_memory == "" or total_memory == None or \
units == "" or units == None:
return
if string.lower(units) != "kb":
return
try:
total_memory= int(total_memory)
except ValueError, e:
return
break
meminfo_file.close()
return total_memory
def get_block_device_list(vars = {}, log = sys.stderr):
"""
get a list of block devices from this system.
return an associative array, where the device name
(full /dev/device path) is the key, and the value
is a tuple of (major,minor,numblocks,gb_size,readonly)
"""
# make sure we can access to the files/directories in /proc
if not os.access(PROC_PARTITIONS_PATH, os.F_OK):
return None
# table with valid scsi/sata/ide/raid block device names
valid_blk_names = {}
# add in valid sd and hd block device names
# also check for vd (virtio devices used with kvm)
for blk_prefix in ('sd','hd','vd'):
for blk_num in map ( \
lambda x: chr(x), range(ord('a'),ord('z')+1)):
devicename="%s%c" % (blk_prefix, blk_num)
valid_blk_names[devicename]=None
# add in valid scsi raid block device names
for M in range(0,1+1):
for N in range(0,7+1):
devicename = "cciss/c%dd%d" % (M,N)
valid_blk_names[devicename]=None
for devicename in valid_blk_names.keys():
# devfs under 2.4 (old boot cds) used to list partitions
# in a format such as scsi/host0/bus0/target0/lun0/disc
# and /dev/sda, etc. were just symlinks
try:
devfsname= os.readlink( "/dev/%s" % devicename )
valid_blk_names[devfsname]=None
except OSError:
pass
# only do this once every system boot
if not os.access(DEVICES_SCANNED_FLAG, os.R_OK):
# this is ugly. under devfs, device
# entries in /dev/scsi/.. and /dev/ide/...
# don't show up until you attempt to read
# from the associated device at /dev (/dev/sda).
# so, lets run sfdisk -l (list partitions) against
# most possible block devices, that way they show
# up when it comes time to do the install.
devicenames = valid_blk_names.keys()
devicenames.sort()
for devicename in devicenames:
os.system( "sfdisk -l /dev/%s > /dev/null 2>&1" % devicename )
# touch file
fb = open(DEVICES_SCANNED_FLAG,"w")
fb.close()
devicelist= {}
partitions_file= file(PROC_PARTITIONS_PATH,"r")
line_count= 0
for line in partitions_file:
line_count= line_count + 1
# skip the first two lines always
if line_count < 2:
continue
parts= string.split(line)
if len(parts) < 4:
continue
device= parts[3]
# skip and ignore any partitions
if not valid_blk_names.has_key(device):
continue
try:
major= int(parts[0])
minor= int(parts[1])
blocks= int(parts[2])
except ValueError, err:
continue
gb_size= blocks/BLOCKS_PER_GB
# check to see if the blk device is readonly
try:
# can we write to it?
dev_name= "/dev/%s" % device
fb = open(dev_name,"w")
fb.close()
readonly=False
except IOError, e:
# check if EROFS errno
if errno.errorcode.get(e.errno,None) == 'EROFS':
readonly=True
else:
# got some other errno, pretend device is readonly
readonly=True
devicelist[dev_name]= (major,minor,blocks,gb_size,readonly)
return devicelist
def get_system_modules( vars = {}, log = sys.stderr):
"""
Return a list of kernel modules that this system requires.
This requires access to the installed system's root
directory, as the following file must exist and is used:
<install_root>/lib/modules/(first entry if kernel_version unspecified)/modules.pcimap
If there are more than one kernels installed, and the kernel
version is not specified, then only the first one in
/lib/modules is used.
Returns a dictionary, keys being the type of module:
- scsi MODULE_CLASS_SCSI
- network MODULE_CLASS_NETWORK
The value being the kernel module name to load.
Some sata devices show up under an IDE device class,
hence the reason for checking for ide devices as well.
If there actually is a match in the pci -> module lookup
table, and its an ide device, its most likely sata,
as ide modules are built in to the kernel.
"""
if not vars.has_key("SYSIMG_PATH"):
vars["SYSIMG_PATH"]="/"
SYSIMG_PATH=vars["SYSIMG_PATH"]
if not vars.has_key("NODE_MODEL_OPTIONS"):
vars["NODE_MODEL_OPTIONS"] = 0;
initrd, kernel_version = getKernelVersion(vars, log)
# get the kernel version we are assuming
if kernel_version is None:
try:
kernel_version= os.listdir( "%s/lib/modules/" % SYSIMG_PATH )
except OSError, e:
return
if len(kernel_version) == 0:
return
if len(kernel_version) > 1:
print( "WARNING: We may be returning modules for the wrong kernel." )
kernel_version= kernel_version[0]
print( "Using kernel version %s" % kernel_version )
# test to make sure the file we need is present
modules_pcimap_path = "%s/lib/modules/%s/modules.pcimap" % \
(SYSIMG_PATH,kernel_version)
if not os.access(modules_pcimap_path,os.R_OK):
print( "WARNING: Unable to read %s" % modules_pcimap_path )
return
pcimap = pypcimap.PCIMap(modules_pcimap_path)
# this is the actual data structure we return
system_mods= {}
# these are the lists that will be in system_mods
network_mods= []
scsi_mods= []
# XXX: this is really similar to what BootCD/conf_files/pl_hwinit does. merge?
pcidevs = get_devices()
devlist=pcidevs.keys()
devlist.sort()
for slot in devlist:
dev = pcidevs[slot]
base = (dev[4] & 0xff0000) >> 16
modules = pcimap.get(dev)
if base not in (PCI_BASE_CLASS_STORAGE,
PCI_BASE_CLASS_NETWORK):
# special exception for forcedeth NICs whose base id
# claims to be a Bridge, even though it is clearly a
# network device
if "forcedeth" in modules:
base=PCI_BASE_CLASS_NETWORK
else:
continue
if len(modules) > 0:
if base == PCI_BASE_CLASS_NETWORK:
network_mods += modules
elif base == PCI_BASE_CLASS_STORAGE:
scsi_mods += modules
system_mods[MODULE_CLASS_SCSI]= scsi_mods
system_mods[MODULE_CLASS_NETWORK]= network_mods
return system_mods
def getKernelVersion( vars = {} , log = sys.stderr):
# make sure we have the variables we need
try:
SYSIMG_PATH= vars["SYSIMG_PATH"]
if SYSIMG_PATH == "":
raise ValueError, "SYSIMG_PATH"
NODE_MODEL_OPTIONS=vars["NODE_MODEL_OPTIONS"]
except KeyError, var:
raise BootManagerException, "Missing variable in vars: %s\n" % var
except ValueError, var:
raise BootManagerException, "Variable in vars, shouldn't be: %s\n" % var
option = ''
if NODE_MODEL_OPTIONS & ModelOptions.SMP:
option = 'smp'
try:
os.stat("%s/boot/kernel-boot%s" % (SYSIMG_PATH,option))
os.stat("%s/boot/initrd-boot%s" % (SYSIMG_PATH,option))
except OSError, e:
# smp kernel is not there; remove option from modeloptions
# such that the rest of the code base thinks we are just
# using the base kernel.
NODE_MODEL_OPTIONS = NODE_MODEL_OPTIONS & ~ModelOptions.SMP
vars["NODE_MODEL_OPTIONS"] = NODE_MODEL_OPTIONS
log.write( "WARNING: Couldn't locate smp kernel.\n")
option = ''
try:
initrd= os.readlink( "%s/boot/initrd-boot%s" % (SYSIMG_PATH,option) )
kernel_version= initrd.replace("initrd-", "").replace(".img", "")
except OSError, e:
initrd = None
kernel_version = None
return (initrd, kernel_version)
if __name__ == "__main__":
devices= get_block_device_list()
print "block devices detected:"
if not devices:
print "no devices found!"
else:
for dev in devices.keys():
print "%s %s" % (dev, repr(devices[dev]))
print ""
memory= get_total_phsyical_mem()
if not memory:
print "unable to read /proc/meminfo for memory"
else:
print "total physical memory: %d kb" % memory
print ""
kernel_version = None
if len(sys.argv) > 2:
kernel_version = sys.argv[1]
modules= get_system_modules()
if not modules:
print "unable to list system modules"
else:
for module_class in (MODULE_CLASS_SCSI,MODULE_CLASS_NETWORK):
if len(modules[module_class]) > 0:
module_list = ""
for a_mod in modules[module_class]:
module_list = module_list + "%s " % a_mod
print "all %s modules: %s" % (module_class, module_list)