Wipe branch
This commit is contained in:
		
							
								
								
									
										334
									
								
								checker.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										334
									
								
								checker.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,334 @@ | ||||
| from threading import Thread | ||||
| from mysql.connector import connect, Error | ||||
| from time import sleep, time | ||||
| from asics import ASICs | ||||
| from macros import * | ||||
| import os, re, json, socket, requests | ||||
|  | ||||
|  | ||||
| class CThread(Thread): | ||||
| 	conn = None | ||||
|  | ||||
| 	def __init__(self, event): | ||||
| 		super(CThread, self).__init__() | ||||
| 		self.event = event | ||||
|  | ||||
|  | ||||
| 	def getreg(self, reg, str): | ||||
| 		res = re.findall(reg, str) | ||||
| 		if res:		return res[0][1] | ||||
| 		else:		return False | ||||
|  | ||||
|  | ||||
| 	def getstat_AntminerL3(self, log): | ||||
| 		status = 'ok' | ||||
|  | ||||
| 		return status | ||||
|  | ||||
|  | ||||
| 	def getstat_Avalon1XXX(self, log, type): | ||||
| 		status = 'ok' | ||||
|  | ||||
| 		rej = float(self.getreg('("Device Rejected%":([0-9.]+),)', log)) | ||||
| 		ghs = int(float(self.getreg('(GHSmm\[([0-9.:,]+)\])', log))) | ||||
| 		avg = int(float(self.getreg('(GHSavg\[([0-9.: ]+)\])', log))) | ||||
| #		brd = self.getreg('(MGHS\[([0-9.:, ]+)\])', log) | ||||
| 		tmp = int(self.getreg('(TMax\[([0-9]+)\])', log)) | ||||
|  | ||||
| 		chash = CONF.get('asics', ASICs(type).name, 'crit', 'hash') | ||||
| 		whash = CONF.get('asics', ASICs(type).name, 'warn', 'hash') | ||||
|  | ||||
| 		ctemp = CONF.get('asics', ASICs(type).name, 'crit', 'temp') | ||||
| 		wtemp = CONF.get('asics', ASICs(type).name, 'warn', 'temp') | ||||
|  | ||||
| 		crej = CONF.get('asics', ASICs(type).name, 'crit', 'rej') | ||||
| 		wrej = CONF.get('asics', ASICs(type).name, 'warn', 'rej') | ||||
|  | ||||
| 		if rej > crej or ghs < chash or avg < chash or tmp > ctemp:		status = 'crit' | ||||
| 		elif rej > wrej or ghs < whash or avg < whash or tmp > wtemp:	status = 'warn' | ||||
|  | ||||
| 		DEBUG(f"{rej} | {ghs} | {avg} | {brd} | {tmp}") | ||||
|  | ||||
| 		return status | ||||
|  | ||||
|  | ||||
| 	def getstat_AntminerS19(self, log): | ||||
| 		status = 'ok' | ||||
|  | ||||
| 		rej = float(self.getreg('("Device Rejected%": ([0-9.]+),)', log)) | ||||
| 		ghs = int(float(self.getreg('("GHS 5s": ([0-9.]+),)', log))) | ||||
| 		avg = int(float(self.getreg('("GHS av": ([0-9.]+),)', log))) | ||||
| 		tmp = int(self.getreg('("TMax": ([0-9]+),)', log)) | ||||
|  | ||||
| 		chash = CONF.get('asics', ASICs(type).name, 'crit', 'hash') | ||||
| 		whash = CONF.get('asics', ASICs(type).name, 'warn', 'hash') | ||||
|  | ||||
| 		ctemp = CONF.get('asics', ASICs(type).name, 'crit', 'temp') | ||||
| 		wtemp = CONF.get('asics', ASICs(type).name, 'warn', 'temp') | ||||
|  | ||||
| 		crej = CONF.get('asics', ASICs(type).name, 'crit', 'rej') | ||||
| 		wrej = CONF.get('asics', ASICs(type).name, 'warn', 'rej') | ||||
|  | ||||
| 		if rej > crej or ghs < chash or avg < chash or tmp > ctemp:		status = 'crit' | ||||
| 		elif rej > wrej or ghs < whash or avg < whash or tmp > wtemp:	status = 'warn' | ||||
|  | ||||
| 		DEBUG(f"{rej} | {ghs} | {avg} | {brd} | {tmp}") | ||||
|  | ||||
| 		return status | ||||
|  | ||||
|  | ||||
| 	def gettype(self, ip): | ||||
| 		info = self.rtcp(ip, 4028, '{"command": "version"}') | ||||
|  | ||||
| 		if not info: | ||||
| 			return False | ||||
|  | ||||
| 		if CONF.get('debug') and info: | ||||
| 			info1 = self.rtcp(ip, 4028, '{"command": "stats"}') | ||||
| 			info2 = self.rtcp(ip, 4028, '{"command": "version"}') | ||||
| 			info3 = self.rtcp(ip, 4028, '{"command": "summary"}') | ||||
| 			info4 = self.rtcp(ip, 4028, '{"command": "pools"}') | ||||
| 			info5 = self.rtcp(ip, 4028, '{"command": "devdetails"}') | ||||
| 			info6 = self.rtcp(ip, 4028, '{"command": "get_version"}') | ||||
| 			info7 = self.rtcp(ip, 4028, '{"command": "status"}') | ||||
| 			info8 = self.rtcp(ip, 4028, '{"command": "get_miner_info"}') | ||||
| 			info9 = self.rtcp(ip, 4028, '{"command": "devs"}') | ||||
| 			info10 = self.rtcp(ip, 4028, '{"command": "notify"}') | ||||
| 			info11 = self.rtcp(ip, 4028, '{"command": "coin"}') | ||||
| 			info12 = self.rtcp(ip, 4028, '{"command": "edevs"}') | ||||
| 			info13 = self.rtcp(ip, 4028, '{"command": "estats"}') | ||||
|  | ||||
| 			DEBUG(f"[{ip}] {info1}") | ||||
| 			DEBUG(f"[{ip}] {info2}") | ||||
| 			DEBUG(f"[{ip}] {info3}") | ||||
| 			DEBUG(f"[{ip}] {info4}") | ||||
| 			DEBUG(f"[{ip}] {info5}") | ||||
| 			DEBUG(f"[{ip}] {info6}") | ||||
| 			DEBUG(f"[{ip}] {info7}") | ||||
| 			DEBUG(f"[{ip}] {info8}") | ||||
| 			DEBUG(f"[{ip}] {info9}") | ||||
| 			DEBUG(f"[{ip}] {info10}") | ||||
| 			DEBUG(f"[{ip}] {info11}") | ||||
| 			DEBUG(f"[{ip}] {info12}") | ||||
| 			DEBUG(f"[{ip}] {info13}") | ||||
|  | ||||
| 		info += self.rtcp(ip, 4028, '{"command": "devdetails"}') | ||||
|  | ||||
| 		# Bitmain | ||||
| 		if "Antminer" in info: | ||||
| 			if "S19J Pro" in info: | ||||
| 				return ASICs.AntminerS19JPro.value | ||||
| 			if "S19J" in info: | ||||
| 				return ASICs.AntminerS19J.value | ||||
| 			if "S19 Pro" in info: | ||||
| 				return ASICs.AntminerS19Pro.value | ||||
| 			if "S19" in info: | ||||
| 				return ASICs.AntminerS19.value | ||||
|  | ||||
| 			if "L3+" in info: | ||||
| 				return ASICs.AntminerL3plus.value | ||||
| 			if "L7" in info: | ||||
| 				return ASICs.AntminerL3plus.value | ||||
|  | ||||
| 			if "T17+" in info: | ||||
| 				return ASICs.AntminerT17plus.value | ||||
| 			if "T17" in info: | ||||
| 				return ASICs.AntminerT17.value | ||||
|  | ||||
| 		# Avalon | ||||
| 		if "Avalon" in info: | ||||
| 			if "1066" in info: | ||||
| 				return ASICs.Avalon1066.value | ||||
| 			if "1126" in info: | ||||
| 				return ASICs.Avalon1126.value | ||||
|  | ||||
| 		# WhatsMiner | ||||
| 		if "bitmicro" in info: | ||||
| 			if "M20s": | ||||
| 				return ASICs.WhatsMinerM20s.value | ||||
| 			if "M21s": | ||||
| 				return ASICs.WhatsMinerM21s.value | ||||
| 			if "M30": | ||||
| 				return ASICs.WhatsMinerM30.value | ||||
| 			if "M31": | ||||
| 				return ASICs.WhatsMinerM31.value | ||||
| 			if "M50": | ||||
| 				return ASICs.WhatsMinerM50.value | ||||
|  | ||||
| 		# Innosilicon | ||||
| 		if False: | ||||
| 			pass | ||||
|  | ||||
| 		return False | ||||
|  | ||||
|  | ||||
| 	def rtcp(self, ip, port, cmd): | ||||
| 		cmd = cmd.encode('utf-8') | ||||
| 		with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: | ||||
| 			try: | ||||
| 				s.connect((ip, port)) | ||||
| 				s.sendall(cmd) | ||||
| 				tdata = [] | ||||
| 				while 1: | ||||
| 					data = s.recv(1024*32) | ||||
| 					if not data: break | ||||
| 					tdata.append(data) | ||||
|  | ||||
| 				data = b''.join(tdata).decode("utf-8") | ||||
|  | ||||
| 				return data | ||||
| 			except OSError as e: | ||||
| 			#	ERR(e) | ||||
| 				return False | ||||
|  | ||||
|  | ||||
| 	def check_AntminerL3(self, ip): | ||||
| #		f'http://{ip}/cgi-bin/get_miner_status.cgi' | ||||
| #		f'http://{ip}/cgi-bin/get_miner_conf.cgi' | ||||
| 		summ = self.rtcp(ip, 4028, "summary") | ||||
| 		stat = self.rtcp(ip, 4028, "estats") | ||||
| 		info = self.rtcp(ip, 4028, "version") | ||||
|  | ||||
| 		if summ and stat: | ||||
| 			mac = json.loads(requests.get( | ||||
| 				f'http://{ip}/cgi-bin/get_system_info.cgi', | ||||
| 				auth=requests.auth.HTTPDigestAuth('root', 'root')).text)['macaddr'].lower() | ||||
|  | ||||
| 			log = f"{info} ||| {summ} ||| {stat}" | ||||
|  | ||||
| 			return log, mac | ||||
|  | ||||
| 		return False, False | ||||
|  | ||||
|  | ||||
| 	def check_AntminerS19(self, ip): | ||||
| #		f'http://{ip}/cgi-bin/get_miner_status.cgi' | ||||
| #		f'http://{ip}/cgi-bin/get_miner_conf.cgi' | ||||
| 		summ = self.rtcp(ip, 4028, "summary") | ||||
| 		stat = self.rtcp(ip, 4028, "stats") | ||||
| 		info = self.rtcp(ip, 4028, "version") | ||||
|  | ||||
| 		if summ and stat: | ||||
| 			mac = json.loads(requests.get( | ||||
| 				f'http://{ip}/cgi-bin/get_network_info.cgi', | ||||
| 				auth=requests.auth.HTTPDigestAuth('root', 'root')).text)['macaddr'].lower() | ||||
|  | ||||
| 			log = f"{info} ||| {summ} ||| {stat}" | ||||
|  | ||||
| 			return log, mac | ||||
|  | ||||
| 		return False, False | ||||
|  | ||||
|  | ||||
| 	def check_Avalon1XXX(self, ip): | ||||
| 		summ = self.rtcp(ip, 4028, "summary") | ||||
| 		stat = self.rtcp(ip, 4028, "estats") | ||||
| 		info = self.rtcp(ip, 4028, "version") | ||||
|  | ||||
| 		if summ and stat: | ||||
| 			mac = self.getreg(r'(MAC=([A-z0-9]+))', info) | ||||
| 			if mac: mac = ':'.join(mac[i:i+2] for i in range(0,12,2)) | ||||
| 			else: mac = ':' | ||||
|  | ||||
| 			log = f"{info} ||| {summ} ||| {stat}" | ||||
|  | ||||
| 			return log, mac | ||||
|  | ||||
| 		return False, False | ||||
|  | ||||
|  | ||||
| 	def check(self, ip): | ||||
| 		try: | ||||
| 			type = self.gettype(ip) | ||||
|  | ||||
| 			if not type: | ||||
| 				return (False, False, False, False, False), False | ||||
|  | ||||
| 			if type in [ASICs.AntminerL3plus.value]: | ||||
| 				log, mac = self.check_AntminerL3(ip) | ||||
| 				status = self.getstat_AntminerL3(log, type) | ||||
| 			elif type in [ASICs.Avalon1066.value, ASICs.Avalon1126.value]: | ||||
| 				log, mac = self.check_Avalon1XXX(ip) | ||||
| 				status = self.getstat_Avalon1XXX(log, type) | ||||
| 			elif type in [ASICs.AntminerS19.value, ASICs.AntminerS19J.value, ASICs.AntminerS19Pro.value, ASICs.AntminerS19JPro.value]: | ||||
| 				log, mac = self.check_AntminerS19(ip) | ||||
| 				status = self.getstat_AntminerS19(log, type) | ||||
|  | ||||
| 			return (ip, mac, type, int(time()), log), status | ||||
| 		except Exception as e: | ||||
| 			WARN('Minor error in <lambda>Thread: ' + str(e)) | ||||
| 			return (False, False, False, False, False), False | ||||
|  | ||||
|  | ||||
| 	def checkall(self): | ||||
| 		ips = [] | ||||
|  | ||||
| 		with self.conn.cursor(dictionary=True) as c: | ||||
| 			c.execute("SELECT * FROM `ips` WHERE `location` = %s", (CONF.get('location'),)) | ||||
|  | ||||
| 			for ip in c.fetchall(): | ||||
| 				ip = ip['ip'] | ||||
| 				if ip.isalpha() or not ip.find('-'): | ||||
| 					ips.append(ip) | ||||
| 				else: | ||||
| 					i_p = ip.split('.') | ||||
| 					i_p_new = [] | ||||
| 					for i in i_p: | ||||
| 						i_p_new.append(i.split('-')) | ||||
| 						i_p_new[-1][0] = int(i_p_new[-1][0]) | ||||
| 						i_p_new[-1][-1] = int(i_p_new[-1][-1]) | ||||
|  | ||||
| 					for i1 in range(i_p_new[0][0], i_p_new[0][-1] + 1): | ||||
| 						for i2 in range(i_p_new[1][0], i_p_new[1][-1] + 1): | ||||
| 							for i3 in range(i_p_new[2][0], i_p_new[2][-1] + 1): | ||||
| 								for i4 in range(i_p_new[3][0], i_p_new[3][-1] + 1): | ||||
| 									ips.append(f"{i1}.{i2}.{i3}.{i4}") | ||||
|  | ||||
| 		Tca = [] | ||||
| 		ca = [] | ||||
| 		for ip in ips: | ||||
| 			T = Thread(target=lambda x: ca.append(self.check(x)), args=(ip,)) | ||||
| 			Tca.append(T) | ||||
| 		for i in range(len(Tca)): | ||||
| 			Tca[i].start() | ||||
| 		for i in range(len(Tca)): | ||||
| 			Tca[i].join() | ||||
|  | ||||
| 		with self.conn.cursor() as c: | ||||
| 			c.execute(f"DELETE FROM `laststate` WHERE `location` = %s", (CONF.get('location'),)) | ||||
|  | ||||
| 			for i in ca: | ||||
| 				i, status = i | ||||
| 				if i[4]: | ||||
| 					c.execute(f"INSERT INTO `asiclogs` (`ip`, `mac`, `type`, `time`, `log`) VALUES (%s, %s, %s, %s, %s)", i) | ||||
|  | ||||
| 					if i[1] == ':': | ||||
| 						continue | ||||
| 					c.execute( | ||||
| 						f"INSERT INTO `laststate` (`ip`, `mac`, `type`, `location`, `status`, `time`) VALUES (%s, %s, %s, %s, %s, %s)", | ||||
| 						(i[0], i[1], i[2], CONF.get('location'), status, int(time()))) | ||||
|  | ||||
| 			self.conn.commit() | ||||
|  | ||||
|  | ||||
| 	def run(self): | ||||
| 		try: | ||||
| 			SUCC("Checker started!") | ||||
| 			sleep(5) | ||||
|  | ||||
| 			self.conn = connect( | ||||
| 				host=CONF.get('db', 'host'), | ||||
| 				user=CONF.get('db', 'user'), | ||||
| 				password=CONF.get('db', 'password'), | ||||
| 				database=CONF.get('db', 'name')) | ||||
|  | ||||
| 			while 1: | ||||
| 				if self.event.is_set(): | ||||
| 					SUCC("Checker stopped!") | ||||
| 					break | ||||
|  | ||||
| 				self.checkall() | ||||
| 				sleep(10) | ||||
| 		except Exception as e: | ||||
| 			CRIT(str(e)) | ||||
| 			os._exit(1) | ||||
		Reference in New Issue
	
	Block a user