def switchtopool(miner, pooltoswitch): '''switch pool''' minerpool = antminerhelper.pools(miner) 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))
def doprovision(miner): '''provision/configure a miner''' entries = QueueEntries() poollist = PROVISION.app.pools() print("{0} pools configured".format(len(poollist))) print('{0} {1}'.format(miner.name, miner.ipaddress)) mineraccess = '' addpools = None minerinfo = None minerpool = None try: minerinfo = antminerhelper.getminerinfo(miner) miner.minerinfo = minerinfo minerpool = antminerhelper.pools(miner) #find the current pool in known pools knownpool = PROVISION.app.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: 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) namedpools = PROVISION.app.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.add_pool(MinerPool(miner, pool.priority, pool)) #enforce default pool if miner has one set up if miner.defaultpool: founddefault = next( (p for p in poollist if p.name == miner.defaultpool), None) if founddefault is not None: switchtopool(miner, founddefault) #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]) entries.add(QueueName.Q_MONITORMINER, PROVISION.app.messageencode(miner)) return entries
POOLS = APP.pools() for miner in MINERS: try: savedminer = APP.getminer(miner) if not miner.is_manually_disabled(): minerpool = None start = time.perf_counter() minerinfo = antminerhelper.getminerinfo(miner) minerstats = antminerhelper.stats(miner) #minerlcd = antminerhelper.getminerlcd(miner) if minerstats is None: APP.logerror('{0} Offline? {1}'.format(miner.name, miner.ipaddress)) else: minerpool = antminerhelper.pools(miner) end = time.perf_counter() monitorperf = end - start poolname = '{0} {1}'.format(minerpool.currentpool, minerpool.currentworker) foundpool = APP.findpool(minerpool) if foundpool is not None: minerpool.poolname = foundpool.name savedminer.monitored(minerstats, minerpool, minerinfo, monitorperf) print('{0} mining at {1}'.format(savedminer.name, minerpool.poolname)) print( Fore.CYAN + str(APP.now()), miner.name, miner.status, str(minerstats.currenthash), str(minerstats.minercount),
def domonitorminer(miner): '''get statistics from miner''' entries = QueueEntries() savedminer = APPMONITOR.app.getminer(miner) if savedminer is None: savedminer = miner try: #individual miner can be monitored even if manually disabled if not savedminer.should_monitor(): print('skipped monitoring {0}'.format(miner.name)) return entries mineroriginalstatus = savedminer.status start = time.perf_counter() minerinfo = getminerinfo(savedminer) minerstats = stats(savedminer) #minerlcd = antminerhelper.getminerlcd(miner) if minerstats is None: print('could not monitor {0}'.format(savedminer.name)) else: minerpool = pools(savedminer) end = time.perf_counter() monitorperf = end - start #what to do if monitored miner type conflicts with saved miner type??? #should probably provision? foundpool = APPMONITOR.app.findpool(minerpool) if foundpool is not None: minerpool.poolname = foundpool.name savedminer.monitored(minerstats, minerpool, minerinfo, monitorperf) if mineroriginalstatus == '': #first time monitoring since bootup print(Fore.GREEN + APPMONITOR.app.now(), savedminer.name, 'first time monitoring') elif savedminer.status == mining.MinerStatus.Online and (mineroriginalstatus == mining.MinerStatus.Disabled or mineroriginalstatus == mining.MinerStatus.Offline): #changing status from offline to online so raise event entries.add(QueueName.Q_ONLINE, APPMONITOR.app.messageencode(savedminer)) print(Fore.GREEN + APPMONITOR.app.now(), savedminer.name, 'back online!') #TODO: if stats.elapsed < previous.elapsed then raise provision or online events APPMONITOR.app.putminerandstats(savedminer, minerstats, minerpool) #TODO:show name of current pool instead of worker poolname = '{0} {1}'.format(minerpool.currentpool, minerpool.currentworker) foundpool = APPMONITOR.app.findpool(minerpool) if foundpool is not None: poolname = foundpool.name print('{0} mining at {1}'.format(savedminer.name, poolname)) #most users won't want to mine solo, so provision the miner if not APPMONITOR.app.configuration('mining.allowsolomining'): if minerpool.currentpool.startswith(APPMONITOR.app.configuration('mining.solopool')): entries.add(QueueName.Q_PROVISION, APPMONITOR.app.messageencode(savedminer)) print(Fore.CYAN+str(APPMONITOR.app.now()), savedminer.name, savedminer.status, 'h='+str(minerstats.currenthash), str(minerstats.minercount), '{0}/{1}/{2}'.format(str(minerstats.tempboard1), str(minerstats.tempboard2), str(minerstats.tempboard3)), savedminer.uptime(minerstats.elapsed), '{0:0f}ms'.format(savedminer.monitorresponsetime() * 1000)) msg = APPMONITOR.app.createmessagestats(savedminer, minerstats, minerpool) entries.addbroadcast(QueueName.Q_STATISTICSUPDATED, msg) except pika.exceptions.ConnectionClosed as qex: #could not enqueue a message print(Fore.RED + '{0} Queue Error: {1}'.format(savedminer.name, APPMONITOR.app.exceptionmessage(qex))) APPMONITOR.app.logexception(qex) except MinerMonitorException as monitorex: print(Fore.RED + '{0} Miner Error: {1}'.format(savedminer.name, APPMONITOR.app.exceptionmessage(monitorex))) savedminer.lastmonitor = datetime.datetime.utcnow() #TODO: this should be a rule. publish miner offline event #and let event handler decide how to handle it savedminer.offline_now() print(Fore.RED + APPMONITOR.app.now(), savedminer.name, savedminer.status) entries.add(QueueName.Q_OFFLINE, APPMONITOR.app.messageencode(savedminer)) except BaseException as ex: print(Fore.RED+'{0} Unexpected Error in monitorminer: {1}'.format(savedminer.name, APPMONITOR.app.exceptionmessage(ex))) # we have to consider any exception to be a miner error. sets status to offline #if str(e) == "timed out": #(timeout('timed out',),) APPMONITOR.app.logexception(ex) APPMONITOR.app.putminer(savedminer) APPMONITOR.app.updateknownminer(savedminer) return entries