Skip to content

Commit

Permalink
Server info oop (#192)
Browse files Browse the repository at this point in the history
* Release(v2.7.5)
* Added(server-info): server-info --rate run-tests
* Added(server-info): Server class (merged from cli, Assessor, Reader and Collector)
* Added(server-info): base Subsystem class
* Added(server-info): CPU, Disk, Net, Memory and "System" subsystems with all of their specific
* Added(server-info): Folding class with all the folding logic/constants
* Refactoring(server-info): removed -f, -ff, -fff args, use --device, --subsystem, --server instead.
* Refactoring(server-info): simplified any2int, dmidecode parsing and invert_dict_nesting
  • Loading branch information
strizhechenko committed Jan 21, 2018
1 parent 49ce4f4 commit 8069cb5
Show file tree
Hide file tree
Showing 28 changed files with 631 additions and 584 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ test:
./tests/utils_runnable
./tests/rss-ladder-test
./tests/server-info-show
./tests/server-info-rate
./tests/link_rate_units.sh

env:
Expand Down
8 changes: 4 additions & 4 deletions docs/hardware.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@
yum -y install epel-release
yum -y install python-pip
pip install netutils-linux
sudo server-info rate
sudo server-info --rate
```

Для более общей оценки можно:

```
cd /root/server/
# оценка с точностью до девайса
server-info-rate -f
server-info --rate --device
# оценка с точностью до подсистемы
server-info-rate -ff
server-info --rate -subsystem
# оценка сервера целиком
server-info-rate -fff
server-info --rate --server
```

Если что-то идёт не так или оценка крайне неправильна: не стесняйтесь создавать на гитхаб репорты о проблемах: https://github.com/strizhechenko/netutils-linux/issues
Expand Down
8 changes: 2 additions & 6 deletions netutils_linux_hardware/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
from netutils_linux_hardware import netdev
from netutils_linux_hardware import parsers
from netutils_linux_hardware import interrupts
from netutils_linux_hardware.reader import Reader
from netutils_linux_hardware.assessor import Assessor
from netutils_linux_hardware.server import Server

__all__ = ['parsers', 'netdev', 'interrupts', 'Reader', 'Assessor']
__all__ = ['Server']
151 changes: 0 additions & 151 deletions netutils_linux_hardware/assessor.py

This file was deleted.

29 changes: 0 additions & 29 deletions netutils_linux_hardware/collect.py

This file was deleted.

44 changes: 44 additions & 0 deletions netutils_linux_hardware/cpu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# coding=utf-8

from netutils_linux_hardware.grade import Grade
from netutils_linux_hardware.parser import Parser, YAMLLike
from netutils_linux_hardware.rate_math import extract
from netutils_linux_hardware.subsystem import Subsystem


class CPU(Subsystem):
""" Everything about CPU: layouts, NUMA, HZ, L3, lscpu """

def rate(self):
cpuinfo = extract(self.data, ['cpu', 'info'])
if cpuinfo: # None if no cpuinfo key
return self.folding.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),
'Core(s) per socket': Grade.int(cpuinfo.get('Core(s) per socket'), 1, 2),
'Socket(s)': Grade.int(cpuinfo.get('Socket(s)'), 1, 2),
'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']),
}, self.folding.SUBSYSTEM)

def parse(self):
output = {
'info': self.read(YAMLLike, 'lscpu_info'),
'layout': self.read(CPULayout, 'lscpu_layout'),
}
for key in ('CPU MHz', 'BogoMIPS'):
if output.get('info', {}).get(key):
output['info'][key] = int(output['info'][key])
return output


class CPULayout(Parser):
@staticmethod
def parse(text):
output = dict((line.strip().split())
for line in text.strip().split('\n'))
if output.get('CPU'):
del output['CPU']
return output
97 changes: 97 additions & 0 deletions netutils_linux_hardware/disk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# coding=utf-8

from collections import defaultdict

import yaml

from netutils_linux_hardware.grade import Grade
from netutils_linux_hardware.parser import Parser
from netutils_linux_hardware.rate_math import extract
from netutils_linux_hardware.subsystem import Subsystem


class Disk(Subsystem):
def parse(self):
return DiskInfo().parse(
self.path('disks_types'),
self.path('lsblk_sizes'),
self.path('lsblk_models')
)

def rate(self):
return self.map(self.rate_disk, 'disk')

def rate_disk(self, disk):
diskinfo = extract(self.data, ['disk', disk])
return self.folding.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),
}, self.folding.DEVICE)


class DiskInfo(object):
@staticmethod
def invert_dict_nesting(origin):
"""
origin = {
'x': {'xx': 1, 'yy': 2},
'y': {'xx': 3, 'yy': 4},
}
result = {
'xx': {'x': 1, 'y': 3},
'yy': {'x': 2, 'y': 4},
}
"""
result = defaultdict()
for out_key, out_value in origin.items():
for in_key, in_value in out_value.items():
result.setdefault(in_key, dict())
result[in_key][out_key] = in_value
return dict(result)

def parse(self, types, sizes, models):
types_data = self.DiskTypesInfo().parse_file_safe(types)
if not types_data:
return
disk_data = {
'type': types_data,
'size': self.DiskSizeInfo(types_data).parse_file_safe(sizes),
'model': self.DiskModelsInfo(types_data).parse_file_safe(models),
}
return self.invert_dict_nesting(disk_data)

class DiskTypesInfo(Parser):

@staticmethod
def parse(text):
types = ['SSD', 'HDD']
if not text:
return dict()
data = yaml.load(text.replace(':', ': ').replace('/sys/block/', '').replace('/queue/rotational', ''))
return dict((k, types[v]) for k, v in data.items())

class DiskSizeInfo(Parser):

def __init__(self, types_data):
self.types_data = set(types_data)

def parse(self, text):
# split grepped text into list
data = (line.split() for line in text.strip().split('\n'))
# remove partitions, we're interested only in disk-drives
data = (line if len(line) == 2 else [line[0], line[2]] for line in data if
set(line).intersection(self.types_data))
return dict((k, int(v)) for v, k in data)

class DiskModelsInfo(Parser):

def __init__(self, types_data):
self.types_data = types_data

def parse(self, text):
lines = [line.split(None, 1) for line in text.strip().split('\n')]
data = dict(line if len(line) == 2 else line + [None] for line in lines)
if data.get('NAME'):
del data['NAME']
return data
20 changes: 20 additions & 0 deletions netutils_linux_hardware/folding.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# coding=utf-8


class Folding(object):
NO = 0
DEVICE = 1
SUBSYSTEM = 2
SERVER = 3

def __init__(self, args):
self.args = args

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}
2 changes: 1 addition & 1 deletion netutils_linux_hardware/grade.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# coding: utf-8
from netutils_linux_hardware.assessor_math import any2int, round_
from netutils_linux_hardware.rate_math import any2int, round_


class Grade(object):
Expand Down
Loading

0 comments on commit 8069cb5

Please sign in to comment.