domain.miningrules.BrokenRule.__str__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 1
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
'''Mining Rules'''
2
import domain.minerstatistics
3
from domain.mining import Miner
4
5
class RuleParameters(object):
6
    '''configurable parameters for rules'''
7
    def __init__(self, minertype, hashlimit, controllertemplimit, boardtemplimit, restartaftersec, 
8
                 maxtempreset=None, hardware_errors_limit=None, hardware_errors_limit_time=None):
9
        self.minertype = minertype
10
        self.hashlimit = hashlimit
11
        self.controllertemplimit = controllertemplimit
12
        self.boardtemplimit = boardtemplimit
13
        self.restartaftersec = restartaftersec
14
        self.maxtempreset = maxtempreset
15
        self.hardware_errors_limit = hardware_errors_limit
16
        #hours (24h), minutes (60m), seconds (10s)
17
        self.hardware_errors_limit_time = hardware_errors_limit_time
18
19
class BrokenRule(object):
20
    '''broken rules'''
21
    def __init__(self, miner, action, parameter):
22
        self.miner = miner
23
        self.action = action
24
        self.parameter = parameter
25
26
    def __str__(self):
27
        return 'broke {0}:{1} {2}'.format(self.miner.name, self.action, self.parameter)
28
29
class MinerStatisticsRule(object):
30
    '''Rule for evaluating miner statistics'''
31
32
    def __init__(self, miner: Miner, statistics: domain.minerstatistics.MinerStatistics, ruleparameters: RuleParameters):
33
        self.miner = miner
34
        self.statistics = statistics
35
        self.ruleparameters = ruleparameters
36
        self.brokenrules = []
37
38
    @classmethod
39
    def hasreading(cls, reading):
40
        '''True when the reading is not empty'''
41
        if reading is None:
42
            return False
43
        if reading:
44
            return True
45
        return False
46
47
    @classmethod
48
    def hasreading_num(cls, reading):
49
        '''True when the reading is numeric and not empty'''
50
        if reading is None:
51
            return False
52
        if reading == 0:
53
            return False
54
        if isinstance(reading, int):
55
            return True
56
        if isinstance(reading, float):
57
            return True
58
        return False
59
60
    def has_reboot_rule(self):
61
        return any(therule.action == 'restart' and therule.parameter == 'reboot' for therule in self.brokenrules)
62
63
    def addbrokenrule(self, rule):
64
        if rule.action == 'restart':
65
            if not self.has_reboot_rule():
66
                self.brokenrules = [therule for therule in self.brokenrules if therule.action != 'restart']
67
                self.brokenrules.append(rule)
68
        else:
69
            self.brokenrules.append(rule)
70
71
    def isbroken(self):
72
        '''true when the rule is broken'''
73
        self.brokenrules = []
74
        if self.miner.miner_type != self.ruleparameters.minertype:
75
            return False
76
77
        self.check_hash()
78
        self.check_temp_controller()
79
        self.check_temp_boards()
80
        self.check_hardware_errors()
81
82
        return len(self.brokenrules) > 0
83
84
    def check_hardware_errors(self):
85
        if MinerStatisticsRule.hasreading_num(self.statistics.hardware_errors):
86
            #TODO:for now compare absolute values instead of time normalized
87
            if self.statistics.hardware_errors >= self.ruleparameters.hardware_errors_limit:
88
                self.addbrokenrule(BrokenRule(self.miner, 'alert', 'on {} high error rate {}'.format(self.miner.name, self.statistics.hardware_errors)))
89
90
    def check_hash(self):
91
        if MinerStatisticsRule.hasreading_num(self.statistics.currenthash):
92
            if self.statistics.currenthash < self.ruleparameters.hashlimit:
93
                self.brokenrules.append(BrokenRule(self.miner, 'alert', 'on {0} low hash {1} below {2}'.format(self.miner.name, self.statistics.currenthash, self.ruleparameters.hashlimit)))
94
                if self.statistics.elapsed > self.ruleparameters.restartaftersec:
95
                    self.addbrokenrule(BrokenRule(self.miner, 'restart', 'restart'))
96
                    self.addbrokenrule(BrokenRule(self.miner, 'alert', 'restarting {0} '.format(self.miner.name)))
97
98
    def check_temp_controller(self):
99
        if MinerStatisticsRule.hasreading_num(self.statistics.controllertemp):
100
            if self.statistics.controllertemp and self.statistics.controllertemp > self.ruleparameters.controllertemplimit:
101
                self.addbrokenrule(BrokenRule(self.miner, 'alert', 'on {0} controller temp {1} exceeded {2}'.format(self.miner.name, self.statistics.controllertemp, self.ruleparameters.controllertemplimit)))
102
103
    def check_temp_boards(self):
104
        if MinerStatisticsRule.hasreading_num(self.statistics.tempboardmax()):
105
            if self.statistics.tempboardmax() > self.ruleparameters.boardtemplimit:
106
                self.addbrokenrule(BrokenRule(self.miner, 'alert', 'on {0} board temp {1} exceeded {2}'.format(self.miner.name, self.statistics.tempboardmax(), self.ruleparameters.boardtemplimit)))
107
            if self.ruleparameters.maxtempreset and self.statistics.tempboardmax() > self.ruleparameters.maxtempreset:
108
                if self.statistics.elapsed > self.ruleparameters.restartaftersec:
109
                    self.addbrokenrule(BrokenRule(self.miner, 'restart', 'reboot'))
110