Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Folding #181

Merged
merged 3 commits into from
Dec 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 52 additions & 23 deletions netutils_linux_hardware/assessor.py
Original file line number Diff line number Diff line change
@@ -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 """
Expand All @@ -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),
Expand All @@ -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
Expand All @@ -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()
2 changes: 1 addition & 1 deletion netutils_linux_hardware/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
16 changes: 9 additions & 7 deletions utils/server-info-rate
Original file line number Diff line number Diff line change
Expand Up @@ -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()