diff options
Diffstat (limited to 'python.d/mdstat.chart.py')
-rw-r--r-- | python.d/mdstat.chart.py | 189 |
1 files changed, 0 insertions, 189 deletions
diff --git a/python.d/mdstat.chart.py b/python.d/mdstat.chart.py deleted file mode 100644 index 35ba9058..00000000 --- a/python.d/mdstat.chart.py +++ /dev/null @@ -1,189 +0,0 @@ -# -*- coding: utf-8 -*- -# Description: mdstat netdata python.d module -# Author: l2isbad - -import re - -from collections import defaultdict - -from bases.FrameworkServices.SimpleService import SimpleService - -priority = 60000 -retries = 60 -update_every = 1 - -ORDER = ['mdstat_health'] -CHARTS = { - 'mdstat_health': { - 'options': [None, 'Faulty Devices In MD', 'failed disks', 'health', 'md.health', 'line'], - 'lines': list() - } -} - -OPERATIONS = ('check', 'resync', 'reshape', 'recovery', 'finish', 'speed') - -RE_DISKS = re.compile(r' (?P<array>[a-zA-Z_0-9]+) : active .+\[' - r'(?P<total_disks>[0-9]+)/' - r'(?P<inuse_disks>[0-9]+)\]') - -RE_STATUS = re.compile(r' (?P<array>[a-zA-Z_0-9]+) : active .+ ' - r'(?P<operation>[a-z]+) =[ ]{1,2}' - r'(?P<operation_status>[0-9.]+).+finish=' - r'(?P<finish>([0-9.]+))min speed=' - r'(?P<speed>[0-9]+)') - - -def md_charts(md): - order = ['{0}_disks'.format(md.name), - '{0}_operation'.format(md.name), - '{0}_finish'.format(md.name), - '{0}_speed'.format(md.name) - ] - - charts = dict() - charts[order[0]] = { - 'options': [None, 'Disks Stats', 'disks', md.name, 'md.disks', 'stacked'], - 'lines': [ - ['{0}_total_disks'.format(md.name), 'total', 'absolute'], - ['{0}_inuse_disks'.format(md.name), 'inuse', 'absolute'] - ] - } - - charts['_'.join([md.name, 'operation'])] = { - 'options': [None, 'Current Status', 'percent', md.name, 'md.status', 'line'], - 'lines': [ - ['{0}_resync'.format(md.name), 'resync', 'absolute', 1, 100], - ['{0}_recovery'.format(md.name), 'recovery', 'absolute', 1, 100], - ['{0}_reshape'.format(md.name), 'reshape', 'absolute', 1, 100], - ['{0}_check'.format(md.name), 'check', 'absolute', 1, 100] - ] - } - - charts['_'.join([md.name, 'finish'])] = { - 'options': [None, 'Approximate Time Until Finish', 'seconds', md.name, 'md.rate', 'line'], - 'lines': [ - ['{0}_finish'.format(md.name), 'finish in', 'absolute', 1, 1000] - ] - } - - charts['_'.join([md.name, 'speed'])] = { - 'options': [None, 'Operation Speed', 'KB/s', md.name, 'md.rate', 'line'], - 'lines': [ - ['{0}_speed'.format(md.name), 'speed', 'absolute', 1, 1000] - ] - } - - return order, charts - - -class MD: - def __init__(self, name, stats): - self.name = name - self.stats = stats - - def update_stats(self, stats): - self.stats = stats - - def data(self): - stats = dict(('_'.join([self.name, k]), v) for k, v in self.stats.items()) - stats['{0}_health'.format(self.name)] = int(self.stats['total_disks']) - int(self.stats['inuse_disks']) - return stats - - -class Service(SimpleService): - def __init__(self, configuration=None, name=None): - SimpleService.__init__(self, configuration=configuration, name=name) - self.order = ORDER - self.definitions = CHARTS - self.mds = dict() - - def check(self): - arrays = find_arrays(self._get_raw_data()) - if not arrays: - self.error('Failed to read data from /proc/mdstat or there is no active arrays') - return None - return True - - @staticmethod - def _get_raw_data(): - """ - Read data from /proc/mdstat - :return: str - """ - try: - with open('/proc/mdstat', 'rt') as proc_mdstat: - return proc_mdstat.readlines() or None - except (OSError, IOError): - return None - - def get_data(self): - """ - Parse data from _get_raw_data() - :return: dict - """ - arrays = find_arrays(self._get_raw_data()) - if not arrays: - return None - - data = dict() - for array, values in arrays.items(): - - if array not in self.mds: - md = MD(array, values) - self.mds[md.name] = md - self.create_new_array_charts(md) - else: - md = self.mds[array] - md.update_stats(values) - - data.update(md.data()) - - return data - - def create_new_array_charts(self, md): - order, charts = md_charts(md) - - self.charts['mdstat_health'].add_dimension(['{0}_health'.format(md.name), md.name]) - for chart_name in order: - params = [chart_name] + charts[chart_name]['options'] - dimensions = charts[chart_name]['lines'] - - new_chart = self.charts.add_chart(params) - for dimension in dimensions: - new_chart.add_dimension(dimension) - - -def find_arrays(raw_data): - if raw_data is None: - return None - data = defaultdict(str) - counter = 1 - - for row in (elem.strip() for elem in raw_data): - if not row: - counter += 1 - continue - data[counter] = ' '.join([data[counter], row]) - - arrays = dict() - for value in data.values(): - match = RE_DISKS.search(value) - if not match: - continue - - match = match.groupdict() - array = match.pop('array') - arrays[array] = match - for operation in OPERATIONS: - arrays[array][operation] = 0 - - match = RE_STATUS.search(value) - if match: - match = match.groupdict() - if match['operation'] in OPERATIONS: - arrays[array]['operation'] = match['operation'] - arrays[array][match['operation']] = float(match['operation_status']) * 100 - arrays[array]['finish'] = float(match['finish']) * 1000 * 60 - arrays[array]['speed'] = float(match['speed']) * 1000 - - return arrays or None |