cgminer_api_client 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,201 @@
1
+ module CgminerApiClient
2
+ class Miner
3
+ module Commands
4
+ module ReadOnly
5
+ def asc(number)
6
+ query(:asc, number)
7
+ end
8
+
9
+ def asccount
10
+ query(:asccount)
11
+ end
12
+
13
+ def check(command)
14
+ query(:check, command)[0]
15
+ end
16
+
17
+ def coin
18
+ query(:coin)[0]
19
+ end
20
+
21
+ def config
22
+ query(:config)[0]
23
+ end
24
+
25
+ def devdetails
26
+ query(:devdetails)
27
+ end
28
+
29
+ def devs
30
+ query(:devs)
31
+ end
32
+
33
+ def pga(number)
34
+ query(:pga, number)
35
+ end
36
+
37
+ def pgacount
38
+ query(:pgacount)
39
+ end
40
+
41
+ def pools
42
+ query(:pools)
43
+ end
44
+
45
+ def privileged
46
+ query(:privileged)
47
+ true
48
+ rescue
49
+ false
50
+
51
+ end
52
+
53
+ def notify
54
+ query(:notify)
55
+ end
56
+
57
+ def stats
58
+ query(:stats)
59
+ end
60
+
61
+ def summary
62
+ query(:summary)[0]
63
+ end
64
+
65
+ def usbstats
66
+ query(:usbstats)
67
+ end
68
+
69
+ def version
70
+ query(:version)[0]
71
+ end
72
+ end
73
+
74
+ module Privileged
75
+ module Asc
76
+ def ascdisable(number)
77
+ query(:ascdisable, number) unless access_denied?
78
+ end
79
+
80
+ def ascenable(number)
81
+ query(:ascenable, number) unless access_denied?
82
+ end
83
+
84
+ def ascidentify(number)
85
+ query(:ascidentify, number) unless access_denied?
86
+ end
87
+
88
+ def ascset(number, option, value = nil)
89
+ unless access_denied?
90
+ value ? query(:ascset, number, option, value) : query(:ascset, number, option)
91
+ end
92
+ end
93
+ end
94
+
95
+ module Pga
96
+ def pgadisable(number)
97
+ query(:pgadisable, number) unless access_denied?
98
+ end
99
+
100
+ def pgaenable(number)
101
+ query(:pgaenable, number) unless access_denied?
102
+ end
103
+
104
+ def pgaidentify(number)
105
+ query(:pgaidentify, number) unless access_denied?
106
+ end
107
+
108
+ def pgaset(number, option, value = nil)
109
+ unless access_denied?
110
+ value ? query(:pgaset, number, option, value) : query(:pgaset, number, option)
111
+ end
112
+ end
113
+ end
114
+
115
+ module Pool
116
+ def addpool(url, user, pass)
117
+ query(:addpool, url, user, pass) unless access_denied?
118
+ end
119
+
120
+ def disablepool(number)
121
+ query(:disablepool, number) unless access_denied?
122
+ end
123
+
124
+ def enablepool(number)
125
+ query(:enablepool, number) unless access_denied?
126
+ end
127
+
128
+ def poolpriority(*id_order)
129
+ query(:poolpriority, *id_order) unless access_denied?
130
+ end
131
+
132
+ def poolquota(number, value)
133
+ query(:poolquota, number, value) unless access_denied?
134
+ end
135
+
136
+ def removepool(number)
137
+ query(:removepool, number) unless access_denied?
138
+ end
139
+
140
+ def switchpool(number)
141
+ query(:switchpool, number) unless access_denied?
142
+ end
143
+ end
144
+
145
+ module System
146
+ def debug(setting = 'D')
147
+ query(:debug, setting) unless access_denied?
148
+ end
149
+
150
+ def failover_only(value)
151
+ query(:'failover-only', value) unless access_denied?
152
+ end
153
+
154
+ def hotplug(seconds)
155
+ query(:hotplug, seconds) unless access_denied?
156
+ end
157
+
158
+ def quit
159
+ query(:quit) unless access_denied?
160
+ end
161
+
162
+ def restart
163
+ query(:restart) unless access_denied?
164
+ end
165
+
166
+ def save(filename = nil)
167
+ unless access_denied?
168
+ filename ? query(:save, filename) : query(:save)
169
+ end
170
+ end
171
+
172
+ def setconfig(name, value)
173
+ query(:setconfig, name, value) unless access_denied?
174
+ end
175
+
176
+ def zero(which = 'All', full_summary = false)
177
+ query(:zero, which, full_summary) unless access_denied?
178
+ end
179
+ end
180
+
181
+ private
182
+
183
+ def access_denied?
184
+ if !privileged
185
+ raise 'access_denied'
186
+ else
187
+ return false
188
+ end
189
+ end
190
+
191
+ include Miner::Commands::Privileged::Asc
192
+ include Miner::Commands::Privileged::Pga
193
+ include Miner::Commands::Privileged::Pool
194
+ include Miner::Commands::Privileged::System
195
+ end
196
+
197
+ include Miner::Commands::ReadOnly
198
+ include Miner::Commands::Privileged
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,68 @@
1
+ module CgminerApiClient
2
+ class MinerPool
3
+ include Miner::Commands
4
+
5
+ attr_accessor :miners
6
+
7
+ def initialize
8
+ load_miners!
9
+ end
10
+
11
+ def reload_miners!
12
+ @miners = nil
13
+ load_miners!
14
+ end
15
+
16
+ def query(method, *params)
17
+ threads = @miners.collect do |miner|
18
+ Thread.new do
19
+ begin
20
+ miner.query(method, *params)
21
+ rescue => e
22
+ $stderr.puts "#{e.class}: #{e}"
23
+ []
24
+ end
25
+ end
26
+ end
27
+ threads.each { |thr| thr.join }
28
+ threads.collect(&:value)
29
+ end
30
+
31
+ def available_miners(force_reload = false)
32
+ threads = @miners.collect do |miner|
33
+ Thread.new do
34
+ begin
35
+ miner if miner.available?(force_reload)
36
+ rescue
37
+ nil
38
+ end
39
+ end
40
+ end
41
+ threads.each { |thr| thr.join }
42
+ threads.collect(&:value).compact
43
+ end
44
+
45
+ def unavailable_miners(force_reload = false)
46
+ @miners - available_miners(force_reload)
47
+ end
48
+
49
+ def method_missing(name, *args)
50
+ query(name, *args)
51
+ end
52
+
53
+ private
54
+
55
+ def load_miners!
56
+ raise 'Please create config/miners.yml' unless File.exist?('config/miners.yml')
57
+
58
+ miners_config = YAML.load_file('config/miners.yml')
59
+ @miners = miners_config.collect{|miner|
60
+ CgminerApiClient::Miner.new(
61
+ miner['host'],
62
+ miner['port'],
63
+ miner['timeout']
64
+ )
65
+ }
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,30 @@
1
+ module CgminerApiClient
2
+ module SocketWithTimeout
3
+ def open_socket(host, port, timeout)
4
+ addr = Socket.getaddrinfo(host, nil)
5
+ sockaddr = Socket.pack_sockaddr_in(port, addr[0][3])
6
+
7
+ Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0).tap do |socket|
8
+ socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
9
+
10
+ begin
11
+ socket.connect_nonblock(sockaddr)
12
+ rescue IO::WaitWritable
13
+ if IO.select(nil, [socket], nil, timeout)
14
+ begin
15
+ socket.connect_nonblock(sockaddr)
16
+ rescue Errno::EISCONN
17
+ # the socket is connected
18
+ rescue
19
+ socket.close
20
+ raise
21
+ end
22
+ else
23
+ socket.close
24
+ raise "Connection timeout"
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ module CgminerApiClient
2
+ VERSION = "0.2.6"
3
+ end
@@ -0,0 +1,501 @@
1
+ require 'spec_helper'
2
+
3
+ describe CgminerApiClient::Miner::Commands do
4
+ let(:host) { '127.0.0.1' }
5
+ let(:port) { 4028 }
6
+ let(:instance) { CgminerApiClient::Miner.new(host, port) }
7
+
8
+ describe CgminerApiClient::Miner::Commands::ReadOnly do
9
+ context '#asc' do
10
+ it 'should require one argument' do
11
+ expect {
12
+ instance.asc
13
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
14
+ end
15
+
16
+ it 'should query the miner' do
17
+ expect(instance).to receive(:query).with(:asc, 0).and_return('asc' => {})
18
+ instance.asc(0)
19
+ end
20
+ end
21
+
22
+ context '#asccount' do
23
+ it 'should query the miner' do
24
+ expect(instance).to receive(:query).with(:asccount).and_return('asccount' => {})
25
+ instance.asccount
26
+ end
27
+ end
28
+
29
+ context '#check' do
30
+ it 'should require one argument' do
31
+ expect {
32
+ instance.check
33
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
34
+ end
35
+
36
+ it 'should query the miner' do
37
+ expect(instance).to receive(:query).with(:check, :foo).and_return('foo' => [{}])
38
+ instance.check(:foo)
39
+ end
40
+ end
41
+
42
+ context '#coin' do
43
+ it 'should query the miner' do
44
+ expect(instance).to receive(:query).with(:coin).and_return('coin' => [{}])
45
+ instance.coin
46
+ end
47
+ end
48
+
49
+ context '#config' do
50
+ it 'should query the miner' do
51
+ expect(instance).to receive(:query).with(:config).and_return('config' => [{}])
52
+ instance.config
53
+ end
54
+ end
55
+
56
+ context '#devdetails' do
57
+ it 'should query the miner' do
58
+ expect(instance).to receive(:query).with(:devdetails).and_return('devdetails' => [{}])
59
+ instance.devdetails
60
+ end
61
+ end
62
+
63
+ context '#devs' do
64
+ it 'should query the miner' do
65
+ expect(instance).to receive(:query).with(:devs).and_return('devs' => [{}])
66
+ instance.devs
67
+ end
68
+ end
69
+
70
+ context '#pga' do
71
+ it 'should require one argument' do
72
+ expect {
73
+ instance.pga
74
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
75
+ end
76
+
77
+ it 'should query the miner' do
78
+ expect(instance).to receive(:query).with(:pga, 0).and_return('pga' => [{}])
79
+ instance.pga(0)
80
+ end
81
+ end
82
+
83
+ context '#pgacount' do
84
+ it 'should query the miner' do
85
+ expect(instance).to receive(:query).with(:pgacount).and_return('pgacount' => [{}])
86
+ instance.pgacount
87
+ end
88
+ end
89
+
90
+ context '#pools' do
91
+ it 'should query the miner' do
92
+ expect(instance).to receive(:query).with(:pools).and_return('pools' => [{}])
93
+ instance.pools
94
+ end
95
+ end
96
+
97
+ context '#privileged' do
98
+ it 'should query the miner' do
99
+ expect(instance).to receive(:query).with(:privileged).and_return(nil)
100
+ instance.privileged
101
+ end
102
+
103
+ context 'an exception' do
104
+ before do
105
+ expect(instance).to receive(:query).with(:privileged).and_raise('something')
106
+ end
107
+
108
+ it 'should return false' do
109
+ expect(instance.privileged).to eq false
110
+ end
111
+ end
112
+
113
+ context 'success' do
114
+ before do
115
+ expect(instance).to receive(:query).with(:privileged).and_return(nil)
116
+ end
117
+
118
+ it 'should return true' do
119
+ expect(instance.privileged).to eq true
120
+ end
121
+ end
122
+ end
123
+
124
+ context '#notify' do
125
+ it 'should query the miner' do
126
+ expect(instance).to receive(:query).with(:notify).and_return('notify' => [{}])
127
+ instance.notify
128
+ end
129
+ end
130
+
131
+ context '#stats' do
132
+ it 'should query the miner' do
133
+ expect(instance).to receive(:query).with(:stats).and_return('stats' => [{}])
134
+ instance.stats
135
+ end
136
+ end
137
+
138
+ context '#summary' do
139
+ it 'should query the miner' do
140
+ expect(instance).to receive(:query).with(:summary).and_return('summary' => [{}])
141
+ instance.summary
142
+ end
143
+ end
144
+
145
+ context '#usbstats' do
146
+ it 'should query the miner' do
147
+ expect(instance).to receive(:query).with(:usbstats).and_return('usbstats' => [{}])
148
+ instance.usbstats
149
+ end
150
+ end
151
+
152
+ context '#version' do
153
+ it 'should query the miner' do
154
+ expect(instance).to receive(:query).with(:version).and_return('version' => [{}])
155
+ instance.version
156
+ end
157
+ end
158
+ end
159
+
160
+ describe CgminerApiClient::Miner::Commands::Privileged do
161
+ context 'access_denied?' do
162
+ context 'when not privileged' do
163
+ before do
164
+ allow(instance).to receive(:privileged).and_return(false)
165
+ end
166
+
167
+ it 'should raise an error' do
168
+ expect {
169
+ instance.send(:access_denied?)
170
+ }.to raise_error('access_denied')
171
+ end
172
+ end
173
+
174
+ context 'when privileged' do
175
+ before do
176
+ allow(instance).to receive(:privileged).and_return(true)
177
+ end
178
+
179
+ it 'should return false' do
180
+ expect(instance.send(:access_denied?)).to eq false
181
+ end
182
+ end
183
+ end
184
+
185
+ describe CgminerApiClient::Miner::Commands::Privileged::Asc do
186
+ before do
187
+ allow(instance).to receive(:access_denied?).and_return(false)
188
+ end
189
+
190
+ context 'ascdisable' do
191
+ it 'should require one argument' do
192
+ expect {
193
+ instance.ascdisable
194
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
195
+ end
196
+
197
+ it 'should query the miner with arguments' do
198
+ expect(instance).to receive(:query).with(:ascdisable, :number)
199
+ instance.ascdisable(:number)
200
+ end
201
+ end
202
+
203
+ context 'ascenable' do
204
+ it 'should require one argument' do
205
+ expect {
206
+ instance.ascenable
207
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
208
+ end
209
+
210
+ it 'should query the miner with arguments' do
211
+ expect(instance).to receive(:query).with(:ascenable, :number)
212
+ instance.ascenable(:number)
213
+ end
214
+ end
215
+
216
+ context 'ascidentify' do
217
+ it 'should require one argument' do
218
+ expect {
219
+ instance.ascidentify
220
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
221
+ end
222
+
223
+ it 'should query the miner with arguments' do
224
+ expect(instance).to receive(:query).with(:ascidentify, :number)
225
+ instance.ascidentify(:number)
226
+ end
227
+ end
228
+
229
+ context 'ascset' do
230
+ it 'should require 2-3 arguments' do
231
+ expect {
232
+ instance.ascset
233
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 2..3)')
234
+ end
235
+
236
+ it 'should query the miner with 2 arguments' do
237
+ expect(instance).to receive(:query).with(:ascset, :number, :foo)
238
+ instance.ascset(:number, :foo)
239
+ end
240
+
241
+ it 'should query the miner with 3 arguments' do
242
+ expect(instance).to receive(:query).with(:ascset, :number, :foo, :bar)
243
+ instance.ascset(:number, :foo, :bar)
244
+ end
245
+ end
246
+ end
247
+
248
+ describe CgminerApiClient::Miner::Commands::Privileged::Pga do
249
+ before do
250
+ allow(instance).to receive(:access_denied?).and_return(false)
251
+ end
252
+
253
+ context 'pgadisable' do
254
+ it 'should require one argument' do
255
+ expect {
256
+ instance.pgadisable
257
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
258
+ end
259
+
260
+ it 'should query the miner with arguments' do
261
+ expect(instance).to receive(:query).with(:pgadisable, :number)
262
+ instance.pgadisable(:number)
263
+ end
264
+ end
265
+
266
+ context 'pgaenable' do
267
+ it 'should require one argument' do
268
+ expect {
269
+ instance.pgaenable
270
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
271
+ end
272
+
273
+ it 'should query the miner with arguments' do
274
+ expect(instance).to receive(:query).with(:pgaenable, :number)
275
+ instance.pgaenable(:number)
276
+ end
277
+ end
278
+
279
+ context 'pgaidentify' do
280
+ it 'should require one argument' do
281
+ expect {
282
+ instance.pgaidentify
283
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
284
+ end
285
+
286
+ it 'should query the miner with arguments' do
287
+ expect(instance).to receive(:query).with(:pgaidentify, :number)
288
+ instance.pgaidentify(:number)
289
+ end
290
+ end
291
+
292
+ context 'pgaset' do
293
+ it 'should require 2-3 arguments' do
294
+ expect {
295
+ instance.pgaset
296
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 2..3)')
297
+ end
298
+
299
+ it 'should query the miner with 2 arguments' do
300
+ expect(instance).to receive(:query).with(:pgaset, :number, :foo)
301
+ instance.pgaset(:number, :foo)
302
+ end
303
+
304
+ it 'should query the miner with 3 arguments' do
305
+ expect(instance).to receive(:query).with(:pgaset, :number, :foo, :bar)
306
+ instance.pgaset(:number, :foo, :bar)
307
+ end
308
+ end
309
+ end
310
+
311
+ describe CgminerApiClient::Miner::Commands::Privileged::Pool do
312
+ before do
313
+ allow(instance).to receive(:access_denied?).and_return(false)
314
+ end
315
+
316
+ context 'addpool' do
317
+ it 'should require three arguments' do
318
+ expect {
319
+ instance.addpool
320
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 3)')
321
+ end
322
+
323
+ it 'should query the miner with arguments' do
324
+ expect(instance).to receive(:query).with(:addpool, :url, :user, :pass)
325
+ instance.addpool(:url, :user, :pass)
326
+ end
327
+ end
328
+
329
+ context 'disablepool' do
330
+ it 'should require one argument' do
331
+ expect {
332
+ instance.disablepool
333
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
334
+ end
335
+
336
+ it 'should query the miner with arguments' do
337
+ expect(instance).to receive(:query).with(:disablepool, :pool_number)
338
+ instance.disablepool(:pool_number)
339
+ end
340
+ end
341
+
342
+ context 'enablepool' do
343
+ it 'should require one argument' do
344
+ expect {
345
+ instance.enablepool
346
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
347
+ end
348
+
349
+ it 'should query the miner with arguments' do
350
+ expect(instance).to receive(:query).with(:enablepool, :pool_number)
351
+ instance.enablepool(:pool_number)
352
+ end
353
+ end
354
+
355
+ context 'poolpriority' do
356
+ it 'should query the miner with arguments' do
357
+ expect(instance).to receive(:query).with(:poolpriority, :pool_number_1, :pool_number_2, :pool_number_3)
358
+ instance.poolpriority(:pool_number_1, :pool_number_2, :pool_number_3)
359
+ end
360
+ end
361
+
362
+ context 'poolquota' do
363
+ it 'should require two arguments' do
364
+ expect {
365
+ instance.poolquota
366
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 2)')
367
+ end
368
+
369
+ it 'should query the miner with arguments' do
370
+ expect(instance).to receive(:query).with(:poolquota, :pool_number, :quota)
371
+ instance.poolquota(:pool_number, :quota)
372
+ end
373
+ end
374
+
375
+ context 'removepool' do
376
+ it 'should require one argument' do
377
+ expect {
378
+ instance.removepool
379
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
380
+ end
381
+
382
+ it 'should query the miner with arguments' do
383
+ expect(instance).to receive(:query).with(:removepool, :pool_number)
384
+ instance.removepool(:pool_number)
385
+ end
386
+ end
387
+
388
+ context 'switchpool' do
389
+ it 'should require one argument' do
390
+ expect {
391
+ instance.switchpool
392
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
393
+ end
394
+
395
+ it 'should query the miner with arguments' do
396
+ expect(instance).to receive(:query).with(:switchpool, :pool_number)
397
+ instance.switchpool(:pool_number)
398
+ end
399
+ end
400
+ end
401
+
402
+ describe CgminerApiClient::Miner::Commands::Privileged::System do
403
+ before do
404
+ allow(instance).to receive(:access_denied?).and_return(false)
405
+ end
406
+
407
+ context 'debug' do
408
+ it 'should query the miner with defaults' do
409
+ expect(instance).to receive(:query).with(:debug, 'D')
410
+ instance.debug
411
+ end
412
+
413
+ it 'should query the miner with arguments' do
414
+ expect(instance).to receive(:query).with(:debug, :setting)
415
+ instance.debug(:setting)
416
+ end
417
+ end
418
+
419
+ context 'failover_only' do
420
+ it 'should require one argument' do
421
+ expect {
422
+ instance.failover_only
423
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
424
+ end
425
+
426
+ it 'should query the miner with arguments' do
427
+ expect(instance).to receive(:query).with(:'failover-only', :value)
428
+ instance.failover_only(:value)
429
+ end
430
+ end
431
+
432
+ context 'hotplug' do
433
+ it 'should require one argument' do
434
+ expect {
435
+ instance.hotplug
436
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 1)')
437
+ end
438
+
439
+ it 'should query the miner with arguments' do
440
+ expect(instance).to receive(:query).with(:hotplug, :value)
441
+ instance.hotplug(:value)
442
+ end
443
+ end
444
+
445
+ context 'quit' do
446
+ it 'should query the miner' do
447
+ expect(instance).to receive(:query).with(:quit)
448
+ instance.quit
449
+ end
450
+ end
451
+
452
+ context 'restart' do
453
+ it 'should query the miner' do
454
+ expect(instance).to receive(:query).with(:restart)
455
+ instance.restart
456
+ end
457
+ end
458
+
459
+ context 'save' do
460
+ context 'without filename' do
461
+ it 'should query the miner' do
462
+ expect(instance).to receive(:query).with(:save)
463
+ instance.save
464
+ end
465
+ end
466
+
467
+ context 'with filename' do
468
+ it 'should query the miner with arguments' do
469
+ expect(instance).to receive(:query).with(:save, :filename)
470
+ instance.save(:filename)
471
+ end
472
+ end
473
+ end
474
+
475
+ context 'setconfig' do
476
+ it 'should require two arguments' do
477
+ expect {
478
+ instance.setconfig
479
+ }.to raise_error(ArgumentError, 'wrong number of arguments (given 0, expected 2)')
480
+ end
481
+
482
+ it 'should query the miner with arguments' do
483
+ expect(instance).to receive(:query).with(:setconfig, :name, :value)
484
+ instance.setconfig(:name, :value)
485
+ end
486
+ end
487
+
488
+ context 'zero' do
489
+ it 'should query the miner with defaults' do
490
+ expect(instance).to receive(:query).with(:zero, 'All', false)
491
+ instance.zero
492
+ end
493
+
494
+ it 'should query the miner with arguments' do
495
+ expect(instance).to receive(:query).with(:zero, :which, :full_summary)
496
+ instance.zero(:which, :full_summary)
497
+ end
498
+ end
499
+ end
500
+ end
501
+ end