/
when_provision.py
161 lines (144 loc) · 6.4 KB
/
when_provision.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
'''# use to provision miners with default pools
# runs behind firewall
# Listens for Discovered event
'''
from threading import Thread
from queue import Queue
from colorama import Fore
from helpers import antminerhelper
from helpers.queuehelper import QueueName, QueueEntries
import domain.minerpool
from domain import services
from domain.mining import MinerAccessLevel
from backend.fcmapp import Component
PROVISION = Component('provision', option='')
def enthread(target, args):
'''put a method on a queue to be run in background'''
thread_queue = Queue()
def wrapper():
thread_queue.put(target(*args))
thread = Thread(target=wrapper)
thread.start()
return thread_queue
def when_provision(channel, method, properties, body):
'''when provision event raised'''
try:
print("[{0}] Received provision command".format(PROVISION.app.now()))
minermsg = PROVISION.app.messagedecodeminer(body)
entries = None
qprov = enthread(target=doprovision, args=(minermsg, ))
while True:
try:
entries = qprov.get(False, timeout=3)
break
except Exception as ex:
PROVISION.app.bus.sleep(3)
PROVISION.app.enqueue(entries)
PROVISION.app.bus.acknowledge(PROVISION.listeningqueue, method.delivery_tag)
except Exception as ex:
PROVISION.app.bus.reject(PROVISION.listeningqueue, method.delivery_tag)
PROVISION.app.logexception(ex)
def doprovision(miner):
'''provision/configure a miner'''
entries = QueueEntries()
poollist = PROVISION.app.pools.get_all_pools()
print("{0} pools configured".format(len(poollist)))
print('{0} {1}'.format(miner.name, miner.ipaddress))
mineraccess = ''
addpools = None
minerinfo = None
minerpool = None
try:
minerstats, minerinfo, apicall, minerpool = antminerhelper.stats(miner)
miner.setminerinfo(minerinfo)
#find the current pool in known pools
knownpool = PROVISION.app.pools.findpool(minerpool)
if knownpool is not None:
minerpool.poolname = knownpool.name
miner.minerpool = minerpool
PROVISION.app.updateknownminer(miner)
#find pools that need to be added and add them
addpools = services.poolstoadd(miner, minerpool, poollist)
mineraccess = PROVISION.app.antminer.getaccesslevel(miner)
except antminerhelper.MinerMonitorException as ex:
if ex.istimedout():
mineraccess = MinerAccessLevel.Waiting
if mineraccess == MinerAccessLevel.Restricted or mineraccess == MinerAccessLevel.Waiting:
if mineraccess == MinerAccessLevel.Restricted:
PROVISION.app.antminer.set_privileged(miner)
PROVISION.app.antminer.waitforonline(miner)
mineraccess = PROVISION.app.antminer.getaccesslevel(miner)
if mineraccess == MinerAccessLevel.Restricted:
entries.addalert('could not set {0} to privileged access'.format(miner.name))
#try a few more times then give up
else:
addpoolstominer(miner, addpools)
addminerpools(miner)
switchtodefaultpool(miner, poollist, minerpool)
enforcedefaultpool(miner, poollist, minerpool)
entries.add(QueueName.Q_MONITORMINER, PROVISION.app.messageencode(miner))
return entries
def enforcedefaultpool(miner, poollist, minerpool):
#enforce default pool if it doesnt have one. find highest priority pool
if not miner.defaultpool:
def sort_by_priority(j):
return j.priority
filtered = [x for x in poollist if miner.miner_type.startswith(x.pool_type)]
filtered.sort(key=sort_by_priority)
#foundpriority = next((p for p in poollist if p.priority == 0), None)
if filtered:
switchtopool(miner, filtered[0], minerpool)
def switchtodefaultpool(miner, poollist, minerpool):
#enforce default pool if miner has one set up
pol = None #dummy variable to make scrutinize happy
if miner.defaultpool:
founddefault = next((pol for pol in poollist if pol.name == miner.defaultpool), None)
if founddefault is not None:
switchtopool(miner, founddefault, minerpool)
def addminerpools(miner):
namedpools = PROVISION.app.pools.get_all_pools()
#process the pools found on the miner. This will pick up any pools added manually
for pool in miner.pools_available:
#check if pools is a named pool...
foundnamed = None
for namedpool in namedpools:
if namedpool.is_same_as(pool):
foundnamed = namedpool
break
if foundnamed:
#pool should take on the cononical attributes of the named pool
pool.named_pool = foundnamed
pool.user = foundnamed.user
PROVISION.app.pools.add_pool(domain.minerpool.MinerPool(miner, pool.priority, pool))
def addpoolstominer(miner, addpools):
for pool in addpools or []:
print(Fore.YELLOW + " Add", pool.name, "(addpool|{0},{1},{2})".format(pool.url, pool.user + miner.name, "x"))
#this command adds the pool to miner and prints the result
result = antminerhelper.addpool(miner, pool)
if result.startswith("Access denied"):
print(Fore.RED + result)
else:
print(result)
def switchtopool(miner, pooltoswitch, minerpool):
'''switch pool'''
if minerpool is not None:
#find pool number of default pool and switch to it
switchtopoolnumber = minerpool.findpoolnumberforpool(pooltoswitch.url, pooltoswitch.user)
if switchtopoolnumber is not None and switchtopoolnumber > 0:
antminerhelper.switch(miner, switchtopoolnumber)
print(Fore.YELLOW + PROVISION.app.now(), miner.name, 'switched to {0}({1})'.format(pooltoswitch.name, pooltoswitch.url))
else:
print(Fore.RED + PROVISION.app.now(), miner.name, 'could not switch to {0}({1})'.format(pooltoswitch.name, pooltoswitch.url))
def main():
if PROVISION.app.isrunnow or PROVISION.app.isdebug:
for miner in PROVISION.app.knownminers():
try:
doprovision(miner)
except Exception as ex:
PROVISION.app.logexception(ex)
PROVISION.app.shutdown()
else:
PROVISION.listeningqueue = PROVISION.app.subscribe(QueueName.Q_PROVISION, when_provision, no_acknowledge=False)
PROVISION.app.listen(PROVISION.listeningqueue)
if __name__ == "__main__":
main()