From 484d211edbbe719a362431d2c18ac1c3703202d6 Mon Sep 17 00:00:00 2001 From: Oleg Strizhechenko Date: Wed, 20 Dec 2017 13:20:03 +0500 Subject: [PATCH] Folding (#181). Added: folding of server-info-rate output Can be used only manually now. --- netutils_linux_hardware/assessor.py | 75 ++++++++++++++++++++--------- netutils_linux_hardware/parsers.py | 2 +- utils/server-info-rate | 16 +++--- 3 files changed, 62 insertions(+), 31 deletions(-) diff --git a/netutils_linux_hardware/assessor.py b/netutils_linux_hardware/assessor.py index d387505..43eec8a 100644 --- a/netutils_linux_hardware/assessor.py +++ b/netutils_linux_hardware/assessor.py @@ -1,7 +1,16 @@ +# coding: utf-8 +import argparse + import yaml + from netutils_linux_hardware.assessor_math import extract from netutils_linux_hardware.grade import Grade +FOLDING_NO = 0 +FOLDING_DEVICE = 1 +FOLDING_SUBSYSTEM = 2 +FOLDING_SERVER = 3 + class Assessor(object): """ Calculates rates for important system components """ @@ -10,25 +19,35 @@ class Assessor(object): def __init__(self, data): self.data = data + self.args = self.parse_args() if self.data: self.assess() + def fold(self, data, level): + """ Схлапывает значения в дикте до среднего арифметического """ + if not data: + return 1 + if self.args.folding < level: + return data + result = sum(data.values()) / len(data.keys()) + return result if level < FOLDING_SERVER else {'server': result} + def __str__(self): return yaml.dump(self.info, default_flow_style=False).strip() def assess(self): - self.info = { + self.info = self.fold({ 'net': self.__assess(self.assess_netdev, 'net'), 'cpu': self.assess_cpu(), 'memory': self.assess_memory(), 'system': self.assess_system(), 'disk': self.__assess(self.assess_disk, 'disk'), - } + }, FOLDING_SERVER) def assess_cpu(self): cpuinfo = extract(self.data, ['cpu', 'info']) if cpuinfo: - return { + return self.fold({ 'CPU MHz': Grade.int(cpuinfo.get('CPU MHz'), 2000, 4000), 'BogoMIPS': Grade.int(cpuinfo.get('BogoMIPS'), 4000, 8000), 'CPU(s)': Grade.int(cpuinfo.get('CPU(s)'), 2, 32), @@ -37,51 +56,55 @@ def assess_cpu(self): 'Thread(s) per core': Grade.int(cpuinfo.get('Thread(s) per core'), 2, 1), 'L3 cache': Grade.int(cpuinfo.get('L3 cache'), 1000, 30000), 'Vendor ID': Grade.str(cpuinfo.get('Vendor ID'), good=['GenuineIntel']), - } + }, FOLDING_SUBSYSTEM) def assess_memory_device(self, device): - return { - 'size': Grade.int(device.data.get('size', 0), 512, 8196), - 'type': Grade.known_values(device.data.get('type', 'RAM'), { + return self.fold({ + 'size': Grade.int(device.get('size', 0), 512, 8196), + 'type': Grade.known_values(device.get('type', 'RAM'), { 'DDR1': 2, 'DDR2': 3, 'DDR3': 6, 'DDR4': 10, }), - 'speed': Grade.int(device.data.get('speed', 0), 200, 4000), - } + 'speed': Grade.int(device.get('speed', 0), 200, 4000), + }, FOLDING_DEVICE) def assess_memory_devices(self, devices): - return dict((handle, self.assess_memory_device(device)) for handle, device in devices.items()) + if not devices: + return 1 + return self.fold(dict((handle, self.assess_memory_device(device)) + for handle, device in devices.items()), + FOLDING_SUBSYSTEM) def assess_memory_size(self, size): - return { + return self.fold({ 'MemTotal': Grade.int(size.get('MemTotal'), 2 * (1024 ** 2), 16 * (1024 ** 2)), 'SwapTotal': Grade.int(size.get('SwapTotal'), 512 * 1024, 4 * (1024 ** 2)), - } + }, FOLDING_DEVICE) def assess_memory(self): meminfo = self.data.get('memory') if meminfo: - return { + return self.fold({ 'devices': self.assess_memory_devices(meminfo.get('devices')), 'size': self.assess_memory_size(meminfo.get('size')), - } + }, FOLDING_SUBSYSTEM) def assess_system(self): cpuinfo = extract(self.data, ['cpu', 'info']) if cpuinfo: - return { + return self.fold({ 'Hypervisor vendor': Grade.fact(cpuinfo.get('Hypervisor vendor'), False), 'Virtualization type': Grade.fact(cpuinfo.get('Hypervisor vendor'), False), - } + }, FOLDING_SUBSYSTEM) def assess_netdev(self, netdev): netdevinfo = extract(self.data, ['net', netdev]) queues = sum( len(extract(netdevinfo, ['queues', x])) for x in ('rx', 'rxtx')) buffers = netdevinfo.get('buffers') or {} - return { + return self.fold({ 'queues': Grade.int(queues, 2, 8), 'driver': { 'mlx5_core': 10, # 7500 mbit/s @@ -94,21 +117,27 @@ def assess_netdev(self, netdev): 'e1000': 3, # 50 mbit/s 'r8169': 1, 'ATL1E': 1, '8139too': 1, # real trash, you should never use it }.get(netdevinfo.get('driver').get('driver'), 2), - 'buffers': { + 'buffers': self.fold({ 'cur': Grade.int(buffers.get('cur'), 256, 4096), 'max': Grade.int(buffers.get('max'), 256, 4096), - }, - } + }, FOLDING_DEVICE) + }, FOLDING_DEVICE) def assess_disk(self, disk): diskinfo = extract(self.data, ['disk', disk]) - return { + return self.fold({ 'type': Grade.str(diskinfo.get('type'), ['SDD'], ['HDD']), # 50Gb - good, 1Tb - good enough 'size': Grade.int(diskinfo.get('size'), 50 * (1000 ** 3), 1000 ** 4), - } + }, FOLDING_DEVICE) def __assess(self, func, key): items = self.data.get(key) if items: - return dict((item, func(item)) for item in items) + return self.fold(dict((item, func(item)) for item in items), FOLDING_SUBSYSTEM) + + def parse_args(self): + parser = argparse.ArgumentParser() + parser.add_argument('-f', '--folding', action='count', help='-f - device, -ff - subsystem, -fff - server', + default=FOLDING_NO) + return parser.parse_args() diff --git a/netutils_linux_hardware/parsers.py b/netutils_linux_hardware/parsers.py index 8ce7bf8..33d4019 100644 --- a/netutils_linux_hardware/parsers.py +++ b/netutils_linux_hardware/parsers.py @@ -162,7 +162,7 @@ def __parse(devices): for device in devices: if 'Memory Device' in device: mem_dev = MemInfoDMIDevice(device) - output[mem_dev.handle] = mem_dev + output[mem_dev.handle] = mem_dev.data return output diff --git a/utils/server-info-rate b/utils/server-info-rate index 8ed71e3..dff5119 100755 --- a/utils/server-info-rate +++ b/utils/server-info-rate @@ -9,12 +9,14 @@ from six import print_ from netutils_linux_hardware.assessor import Assessor from netutils_linux_hardware.reader import Reader -def get_datadir(): - default_data_directory = 'tests/autotune_network.tests/2xE5-2640.i350_and_82599ES.l2_mixed.masterconf' - if os.path.isfile(os.path.join(os.getcwd(), 'lspci')): - return os.getcwd() - return os.environ.get('DATADIR', default_data_directory) - + +def main(): + cwd = os.getcwd() + directory = cwd if os.path.isfile(os.path.join(cwd, 'lspci')) else os.getenv('DATADIR') + reader = Reader(directory) + assessor = Assessor(reader.info) + print_(assessor) + if __name__ == '__main__': - print_(Assessor(Reader(get_datadir()).info)) + main()