arvicco-avalon 0.0.21 → 0.0.22
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +4 -2
- data/lib/avalon/config.rb +13 -1
- data/lib/avalon/miner.rb +27 -17
- data/lib/avalon/utils.rb +10 -0
- data/lib/avalon/version.rb +1 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -39,8 +39,10 @@ Monitor script is periodically polling the mining units and other types of objec
|
|
39
39
|
------- ~/.avalon/monitor.yml --------
|
40
40
|
# Prod configuration (default)
|
41
41
|
prod:
|
42
|
-
:alert_after:
|
43
|
-
:
|
42
|
+
:alert_after: 2 # missed pings or status reports from a miner
|
43
|
+
:alert_temp_high: 52 # degrees C and above
|
44
|
+
:alert_temp_low: 30 # degrees C and below
|
45
|
+
:alert_last_share: 2 # minutes since last share hashed
|
44
46
|
:alert_sounds:
|
45
47
|
:failure: Glass.aiff # [] for no sound
|
46
48
|
:restart: Frog.aiff # [] for no sound
|
data/lib/avalon/config.rb
CHANGED
@@ -4,9 +4,12 @@ module Avalon
|
|
4
4
|
extend Utils # Helper methods
|
5
5
|
|
6
6
|
DEFAULT_SOUNDS = {
|
7
|
-
failure: 'Glass.aiff',
|
8
7
|
restart: 'Frog.aiff',
|
8
|
+
failure: 'Glass.aiff',
|
9
|
+
perf_low: 'Glass.aiff',
|
10
|
+
last_share: 'Glass.aiff',
|
9
11
|
temp_high: 'Ping.aiff',
|
12
|
+
temp_low: 'Ping.aiff',
|
10
13
|
block_found: ['Dog.aiff', 'Purr.aiff', 'Dog.aiff'],
|
11
14
|
block_updated: ['Purr.aiff', 'Purr.aiff', 'Purr.aiff']
|
12
15
|
}
|
@@ -21,7 +24,16 @@ module Avalon
|
|
21
24
|
@config[:block_file] = find_file( '../../../config/blocks.yml', '~/.avalon/blocks.yml') ||
|
22
25
|
File.expand_path('~/.avalon/blocks.yml')
|
23
26
|
|
27
|
+
# Setting defaults
|
24
28
|
@config[:alert_sounds] = DEFAULT_SOUNDS.merge(@config[:alert_sounds] || {})
|
29
|
+
@config[:alert_last_share] ||= 2
|
30
|
+
@config[:alert_after] ||= @config[:status_fails_to_alarm] || 2
|
31
|
+
@config[:alert_temp_high] ||= @config[:alert_temp] || 55
|
32
|
+
@config[:alert_temp_low] ||= 30
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.config
|
36
|
+
@config
|
25
37
|
end
|
26
38
|
|
27
39
|
def self.[] key
|
data/lib/avalon/miner.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Avalon
|
2
4
|
# "STATUS=S,When=1368715953,Code=11,Msg=Summary,Description=cgminer 2.10.5|
|
3
5
|
# SUMMARY,Elapsed=58219,MHS av=70827.84,Found Blocks=0,Getworks=1899,Accepted=14755,
|
@@ -18,24 +20,24 @@ module Avalon
|
|
18
20
|
:uptime => [9, /(?<=Elapsed=)[\d\.]*/, ->(x){ my_time(x, :relative_time)}],
|
19
21
|
:last => [8, /(?<=Status=Alive,).*?Last Share Time=[\d\.]*/,
|
20
22
|
->(x){ convert_last(x)}],
|
21
|
-
:
|
23
|
+
:miner => [5, /(?<=Description=cgminer )[\d\.]*/, :s],
|
22
24
|
:freq => [4, /(?<=frequency=)[\d\.]*/, :i],
|
25
|
+
:'°C' => [2, /(?<=Temperature=)[\d\.]*/, :i],
|
23
26
|
:fan2 => [4, /(?<=fan2=)[\d\.]*/, :i],
|
24
27
|
:fan3 => [4, /(?<=fan3=)[\d\.]*/, :i],
|
25
|
-
:
|
28
|
+
:wu => [4, /(?<=,Work Utility=)[\d\.]*/, :i],
|
26
29
|
:getworks => [8, /(?<=Getworks=)[\d\.]*/, :i],
|
27
30
|
:accepted => [8, /(?<=,Accepted=)[\d\.]*/, :i],
|
28
31
|
:rejected => [8, /(?<=Rejected=)[\d\.]*/, :i],
|
29
32
|
:stale => [6, /(?<=Stale=)[\d\.]*/, :i],
|
30
33
|
:errors => [6, /(?<=Hardware Errors=)[\d\.]*/, :i],
|
31
34
|
:blocks => [6, /(?<=Network Blocks=)[\d\.]*/, :i],
|
32
|
-
# :found => [2, /(?<=Found Blocks=)[\d\.]*/, :i],
|
35
|
+
# :found => [2, /(?<=Found Blocks=)[\d\.]*/, :i],
|
33
36
|
}
|
34
37
|
|
35
38
|
# Last share converter (Miner-specific)
|
36
39
|
def self.convert_last x
|
37
40
|
y = x[/(?<=Last Share Time=)[\d\.]*/]
|
38
|
-
# p x, y
|
39
41
|
if y.nil? || y == '0'
|
40
42
|
"never"
|
41
43
|
else
|
@@ -48,13 +50,11 @@ module Avalon
|
|
48
50
|
FIELDS.map {|name, (width,_,_ )| name.to_s.ljust(width)}.join(' ')
|
49
51
|
end
|
50
52
|
|
51
|
-
def initialize ip, min_speed
|
53
|
+
def initialize ip, min_speed, config=Avalon::Config.config
|
52
54
|
@ip = ip
|
53
55
|
@min_speed = min_speed * 1000 # Gh/s to Mh/s
|
56
|
+
@config = config
|
54
57
|
@fails = 0
|
55
|
-
@alert_after = Avalon::Config[:alert_after] ||
|
56
|
-
Avalon::Config[:status_fails_to_alarm] || 2
|
57
|
-
@alert_temp = Avalon::Config[:alert_temp] || 55
|
58
58
|
super()
|
59
59
|
end
|
60
60
|
|
@@ -66,6 +66,7 @@ module Avalon
|
|
66
66
|
self[:ping] = ping @ip
|
67
67
|
|
68
68
|
status = get_api('summary') + get_api('pools') + get_api('devs') + get_api('stats')
|
69
|
+
# p get_api('summary')
|
69
70
|
# pools = get_api('pools')
|
70
71
|
# p pools[FIELDS[:last][1]]
|
71
72
|
# devs = get_api('devs')
|
@@ -83,25 +84,34 @@ module Avalon
|
|
83
84
|
end
|
84
85
|
|
85
86
|
def upminutes
|
86
|
-
|
87
|
-
|
87
|
+
duration(self[:uptime])
|
88
|
+
end
|
89
|
+
|
90
|
+
def temp
|
91
|
+
self[:'°C']
|
88
92
|
end
|
89
93
|
|
90
94
|
# Check for any exceptional situations in stats, sound alarm if any
|
91
95
|
def report
|
92
96
|
if data[:ping].nil?
|
93
97
|
@fails += 1
|
94
|
-
if @fails >= @alert_after
|
95
|
-
alarm "Miner #{num} did not respond to status query"
|
98
|
+
if @fails >= @config[:alert_after]
|
99
|
+
alarm "Miner #{num} did not respond to status query", :failure
|
96
100
|
end
|
97
101
|
else
|
98
102
|
@fails = 0
|
99
|
-
if self[:
|
100
|
-
alarm "Miner #{num} performance is #{self[:mhs]}, should be #{@min_speed}"
|
101
|
-
elsif self[:temp] >= @alert_temp
|
102
|
-
alarm "Miner #{num} too hot at #{self[:temp]}C, needs cooling", :temp_high
|
103
|
-
elsif upminutes < 2
|
103
|
+
if duration(self[:uptime]) < 2
|
104
104
|
alarm "Miner #{num} restarted", :restart
|
105
|
+
elsif duration(self[:uptime]) > 5 # Miner settled down
|
106
|
+
if self[:mhs] < @min_speed
|
107
|
+
alarm "Miner #{num} performance is #{self[:mhs]}, should be #{@min_speed}", :perf_low
|
108
|
+
elsif self[:last] == 'never' || duration(self[:last]) > @config[:alert_last_share]
|
109
|
+
alarm "Miner #{num} last shares was #{duration(self[:last])} min ago", :last_share
|
110
|
+
elsif temp >= @config[:alert_temp_high]
|
111
|
+
alarm "Miner #{num} too hot at #{temp}°C, needs cooling", :temp_high
|
112
|
+
elsif temp <= @config[:alert_temp_low]
|
113
|
+
alarm "Miner #{num} temp low at #{temp}°C, is it hashing at all?", :temp_low
|
114
|
+
end
|
105
115
|
end
|
106
116
|
end
|
107
117
|
end
|
data/lib/avalon/utils.rb
CHANGED
@@ -32,6 +32,16 @@ module Avalon
|
|
32
32
|
play sound
|
33
33
|
end
|
34
34
|
|
35
|
+
# Helper method: from time string 'hh:mm:ss' to duration in minutes
|
36
|
+
def duration time_string
|
37
|
+
if time_string == 'never'
|
38
|
+
'never'
|
39
|
+
else
|
40
|
+
hour, min, sec = *time_string.split(/:/).map(&:to_i)
|
41
|
+
hour*60.0 + min + sec/60.0
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
35
45
|
# Helper method: ping the Node, return ping time in ms
|
36
46
|
def ping ip
|
37
47
|
ping_result = `ping -c 1 #{ip}`
|
data/lib/avalon/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arvicco-avalon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.22
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-06-
|
12
|
+
date: 2013-06-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: faraday
|