blob: 9d389133bc9d5de1eac7568a7aa67cc1e0ff31b1 [file] [log] [blame]
koder aka kdanilovf86d7af2015-05-06 04:01:54 +03001import re
2import xml.etree.ElementTree as ET
3
4from wally import ssh_utils, utils
5
6
7def get_data(rr, data):
8 match_res = re.search("(?ims)" + rr, data)
9 return match_res.group(0)
10
11
12class HWInfo(object):
13 def __init__(self):
14 self.hostname = None
15 self.cores = []
16
17 # /dev/... devices
18 self.disks_info = {}
19
20 # real disks on raid controller
21 self.disks_raw_info = {}
22
23 self.net_info = {}
24 self.ram_size = 0
25 self.sys_name = None
26 self.mb = None
27 self.raw = None
28 self.storage_controllers = []
29
30 def get_summary(self):
31 cores = sum(count for _, count in self.cores)
32 disks = sum(size for _, size in self.disks_info.values())
33
34 return {'cores': cores, 'ram': self.ram_size, 'storage': disks}
35
36 def __str__(self):
37 res = []
38
39 summ = self.get_summary()
40 summary = "Simmary: {cores} cores, {ram}B RAM, {disk}B storage"
41 res.append(summary.format(cores=summ['cores'],
42 ram=utils.b2ssize(summ['ram']),
43 disk=utils.b2ssize(summ['storage'])))
44 res.append(str(self.sys_name))
45 if self.mb is not None:
46 res.append("Motherboard: " + self.mb)
47
48 if self.ram_size == 0:
49 res.append("RAM: Failed to get RAM size")
50 else:
51 res.append("RAM " + utils.b2ssize(self.ram_size) + "B")
52
53 if self.cores == []:
54 res.append("CPU cores: Failed to get CPU info")
55 else:
56 res.append("CPU cores:")
57 for name, count in self.cores:
58 if count > 1:
59 res.append(" {0} * {1}".format(count, name))
60 else:
61 res.append(" " + name)
62
63 if self.storage_controllers != []:
64 res.append("Disk controllers:")
65 for descr in self.storage_controllers:
66 res.append(" " + descr)
67
68 if self.disks_info != {}:
69 res.append("Storage devices:")
70 for dev, (model, size) in sorted(self.disks_info.items()):
71 ssize = utils.b2ssize(size) + "B"
72 res.append(" {0} {1} {2}".format(dev, ssize, model))
73 else:
74 res.append("Storage devices's: Failed to get info")
75
76 if self.disks_raw_info != {}:
77 res.append("Disks devices:")
78 for dev, descr in sorted(self.disks_raw_info.items()):
79 res.append(" {0} {1}".format(dev, descr))
80 else:
81 res.append("Disks devices's: Failed to get info")
82
83 if self.net_info != {}:
84 res.append("Net adapters:")
85 for name, (speed, dtype) in self.net_info.items():
86 res.append(" {0} {2} duplex={1}".format(name, dtype, speed))
87 else:
88 res.append("Net adapters: Failed to get net info")
89
90 return str(self.hostname) + ":\n" + "\n".join(" " + i for i in res)
91
92
93class SWInfo(object):
94 def __init__(self):
95 self.os = None
96 self.partitions = None
97 self.kernel_version = None
98 self.fio_version = None
99 self.libvirt_version = None
100 self.kvm_version = None
101 self.qemu_version = None
102 self.OS_version = None
103 self.ceph_version = None
104
105
106def get_sw_info(conn):
107 res = SWInfo()
108 return res
109
110
111def get_hw_info(conn):
112 res = HWInfo()
113 lshw_out = ssh_utils.run_over_ssh(conn, 'sudo lshw -xml 2>/dev/null',
114 nolog=True)
115
116 res.raw = lshw_out
117 lshw_et = ET.fromstring(lshw_out)
118
119 try:
120 res.hostname = lshw_et.find("node").attrib['id']
121 except:
122 pass
123
124 try:
125 res.sys_name = (lshw_et.find("node/vendor").text + " " +
126 lshw_et.find("node/product").text)
127 res.sys_name = res.sys_name.replace("(To be filled by O.E.M.)", "")
128 res.sys_name = res.sys_name.replace("(To be Filled by O.E.M.)", "")
129 except:
130 pass
131
132 core = lshw_et.find("node/node[@id='core']")
133 if core is None:
134 return
135
136 try:
137 res.mb = " ".join(core.find(node).text
138 for node in ['vendor', 'product', 'version'])
139 except:
140 pass
141
142 for cpu in core.findall("node[@class='processor']"):
143 try:
144 model = cpu.find('product').text
145 threads_node = cpu.find("configuration/setting[@id='threads']")
146 if threads_node is None:
147 threads = 1
148 else:
149 threads = int(threads_node.attrib['value'])
150 res.cores.append((model, threads))
151 except:
152 pass
153
154 res.ram_size = 0
155 for mem_node in core.findall(".//node[@class='memory']"):
156 descr = mem_node.find('description')
157 try:
158 if descr is not None and descr.text == 'System Memory':
159 mem_sz = mem_node.find('size')
160 if mem_sz is None:
161 for slot_node in mem_node.find("node[@class='memory']"):
162 slot_sz = slot_node.find('size')
163 if slot_sz is not None:
164 assert slot_sz.attrib['units'] == 'bytes'
165 res.ram_size += int(slot_sz.text)
166 else:
167 assert mem_sz.attrib['units'] == 'bytes'
168 res.ram_size += int(mem_sz.text)
169 except:
170 pass
171
172 for net in core.findall(".//node[@class='network']"):
173 try:
174 link = net.find("configuration/setting[@id='link']")
175 if link.attrib['value'] == 'yes':
176 name = net.find("logicalname").text
177 speed_node = net.find("configuration/setting[@id='speed']")
178
179 if speed_node is None:
180 speed = None
181 else:
182 speed = speed_node.attrib['value']
183
184 dup_node = net.find("configuration/setting[@id='duplex']")
185 if dup_node is None:
186 dup = None
187 else:
188 dup = dup_node.attrib['value']
189
190 res.net_info[name] = (speed, dup)
191 except:
192 pass
193
194 for controller in core.findall(".//node[@class='storage']"):
195 try:
196 description = getattr(controller.find("description"), 'text', "")
197 product = getattr(controller.find("product"), 'text', "")
198 vendor = getattr(controller.find("vendor"), 'text', "")
199 dev = getattr(controller.find("logicalname"), 'text', "")
200 if dev != "":
201 res.storage_controllers.append(
202 "{0}: {1} {2} {3}".format(dev, description,
203 vendor, product))
204 else:
205 res.storage_controllers.append(
206 "{0} {1} {2}".format(description,
207 vendor, product))
208 except:
209 pass
210
211 for disk in core.findall(".//node[@class='disk']"):
212 try:
213 lname_node = disk.find('logicalname')
214 if lname_node is not None:
215 dev = lname_node.text.split('/')[-1]
216
217 if dev == "" or dev[-1].isdigit():
218 continue
219
220 sz_node = disk.find('size')
221 assert sz_node.attrib['units'] == 'bytes'
222 sz = int(sz_node.text)
223 res.disks_info[dev] = ('', sz)
224 else:
225 description = disk.find('description').text
226 product = disk.find('product').text
227 vendor = disk.find('vendor').text
228 version = disk.find('version').text
229 serial = disk.find('serial').text
230
231 full_descr = "{0} {1} {2} {3} {4}".format(
232 description, product, vendor, version, serial)
233
234 businfo = disk.find('businfo').text
235 res.disks_raw_info[businfo] = full_descr
236 except:
237 pass
238
239 return res
240
241# import traceback
242# print ET.tostring(disk)
243# traceback.print_exc()
244
245# print get_hw_info(None)
246
247# def get_hw_info(conn):
248# res = HWInfo(None)
249# remote_run = functools.partial(ssh_utils.run_over_ssh, conn, nolog=True)
250
251# # some data
252# with conn.open_sftp() as sftp:
253# proc_data = ssh_utils.read_from_remote(sftp, '/proc/cpuinfo')
254# mem_data = ssh_utils.read_from_remote(sftp, '/proc/meminfo')
255
256# # cpu info
257# curr_core = {}
258# for line in proc_data.split("\n"):
259# if line.strip() == "":
260# if curr_core != {}:
261# res.cores.append(curr_core)
262# curr_core = {}
263# else:
264# param, val = line.split(":", 1)
265# curr_core[param.strip()] = val.strip()
266
267# if curr_core != {}:
268# res.cores.append(curr_core)
269
270# # RAM info
271# for line in mem_data.split("\n"):
272# if line.startswith("MemTotal"):
273# res.ram_size = int(line.split(":", 1)[1].split()[0]) * 1024
274# break
275
276# # HDD info
277# for dev in remote_run('ls /dev').split():
278# if dev[-1].isdigit():
279# continue
280
281# if dev.startswith('sd') or dev.startswith('hd'):
282# model = None
283# size = None
284
285# for line in remote_run('sudo hdparm -I /dev/' + dev).split("\n"):
286# if "Model Number:" in line:
287# model = line.split(':', 1)[1]
288# elif "device size with M = 1024*1024" in line:
289# size = int(line.split(':', 1)[1].split()[0])
290# size *= 1024 ** 2
291
292# res.disks_info[dev] = (model, size)
293
294# # Network info
295# separator = '*-network'
296# net_info = remote_run('sudo lshw -class network')
297# for net_dev_info in net_info.split(separator):
298# if net_dev_info.strip().startswith("DISABLED"):
299# continue
300
301# if ":" not in net_dev_info:
302# continue
303
304# dev_params = {}
305# for line in net_dev_info.split("\n"):
306# line = line.strip()
307# if ':' in line:
308# key, data = line.split(":", 1)
309# dev_params[key.strip()] = data.strip()
310
311# if 'configuration' not in dev_params:
312# print "!!!!!", net_dev_info
313# continue
314
315# conf = dev_params['configuration']
316# if 'link=yes' in conf:
317# if 'speed=' in conf:
318# speed = conf.split('speed=', 1)[1]
319# speed = speed.strip().split()[0]
320# else:
321# speed = None
322
323# if "duplex=" in conf:
324# dtype = conf.split("duplex=", 1)[1]
325# dtype = dtype.strip().split()[0]
326# else:
327# dtype = None
328
329# res.net_info[dev_params['logical name']] = (speed, dtype)
330# return res