added settings.py file for managing retries and "threads", as well as fixing some bugs in the APIs

This commit is contained in:
UpstreamData
2021-12-21 11:57:34 -07:00
parent 43af332199
commit df6858d718
8 changed files with 40 additions and 23 deletions

View File

@@ -16,6 +16,7 @@ from config.bos import bos_config_convert, general_config_convert_bos
from API import APIError from API import APIError
from settings import CFG_UTIL_GET_VERSION_THREADS as GET_VERSION_THREADS
async def update_ui_with_data(key, data, append=False): async def update_ui_with_data(key, data, append=False):
if append: if append:
@@ -92,7 +93,6 @@ async def export_iplist(file_location, ip_list_selected):
await update_ui_with_data("status", "") await update_ui_with_data("status", "")
async def send_config(ips: list, config): async def send_config(ips: list, config):
await update_ui_with_data("status", "Configuring") await update_ui_with_data("status", "Configuring")
tasks = [] tasks = []
@@ -101,8 +101,11 @@ async def send_config(ips: list, config):
miners = await asyncio.gather(*tasks) miners = await asyncio.gather(*tasks)
tasks = [] tasks = []
for miner in miners: for miner in miners:
tasks.append(miner.send_config(config)) if len(tasks) < GET_VERSION_THREADS:
await asyncio.gather(*tasks) tasks.append(miner.send_config(config))
else:
await asyncio.gather(*tasks)
tasks = []
await update_ui_with_data("status", "") await update_ui_with_data("status", "")

View File

@@ -13,7 +13,7 @@ class BMMiner(BaseMiner):
async def get_hostname(self) -> str: async def get_hostname(self) -> str:
return "BMMiner Unknown" return "BMMiner Unknown"
async def send_config(self): async def send_config(self, _):
return None # ignore for now return None # ignore for now
async def restart_backend(self) -> None: async def restart_backend(self) -> None:

View File

@@ -13,7 +13,7 @@ class BTMiner(BaseMiner):
async def get_hostname(self) -> str: async def get_hostname(self) -> str:
return "BTMiner Unknown" return "BTMiner Unknown"
async def send_config(self): async def send_config(self, _):
return None # ignore for now return None # ignore for now
async def restart_backend(self) -> None: async def restart_backend(self) -> None:

View File

@@ -22,10 +22,10 @@ class CGMiner(BaseMiner):
return data.stdout.strip() return data.stdout.strip()
else: else:
return "CGMiner Unknown" return "CGMiner Unknown"
except Exception as e: except Exception:
return "CGMiner Unknown" return "CGMiner Unknown"
async def send_config(self): async def send_config(self, _):
return None # ignore for now return None # ignore for now
async def _get_ssh_connection(self) -> asyncssh.connect: async def _get_ssh_connection(self) -> asyncssh.connect:
@@ -36,7 +36,7 @@ class CGMiner(BaseMiner):
password=self.pwd, password=self.pwd,
server_host_key_algs=['ssh-rsa']) server_host_key_algs=['ssh-rsa'])
return conn return conn
except asyncssh.misc.PermissionDenied as e: except asyncssh.misc.PermissionDenied:
try: try:
conn = await asyncssh.connect(str(self.ip), conn = await asyncssh.connect(str(self.ip),
known_hosts=None, known_hosts=None,
@@ -50,7 +50,6 @@ class CGMiner(BaseMiner):
print(str(self.ip) + " Connection refused.") print(str(self.ip) + " Connection refused.")
return None return None
async def send_ssh_command(self, cmd): async def send_ssh_command(self, cmd):
result = None result = None
async with (await self._get_ssh_connection()) as conn: async with (await self._get_ssh_connection()) as conn:

View File

@@ -8,6 +8,8 @@ import asyncio
import ipaddress import ipaddress
import json import json
from settings import MINER_FACTORY_GET_VERSION_RETRIES as GET_VERSION_RETRIES
class MinerFactory: class MinerFactory:
def __init__(self): def __init__(self):
@@ -19,11 +21,13 @@ class MinerFactory:
if ip in self.miners: if ip in self.miners:
return self.miners[ip] return self.miners[ip]
# get the version data # get the version data
version_data = await self._get_version_data(ip)
version = None version = None
if version_data: for i in range(GET_VERSION_RETRIES):
# if we got version data, get a list of the keys so we can check type of miner version_data = await self._get_version_data(ip)
version = list(version_data['VERSION'][0].keys()) if version_data:
# if we got version data, get a list of the keys so we can check type of miner
version = list(version_data['VERSION'][0].keys())
break
if version: if version:
# check version against different return miner types # check version against different return miner types
if "BOSminer" in version or "BOSminer+" in version: if "BOSminer" in version or "BOSminer+" in version:
@@ -35,9 +39,11 @@ class MinerFactory:
elif "BTMiner" in version: elif "BTMiner" in version:
miner = BTMiner(str(ip)) miner = BTMiner(str(ip))
else: else:
print(f"Bad API response: {version}")
miner = UnknownMiner(str(ip)) miner = UnknownMiner(str(ip))
else: else:
# if we don't get version, miner type is unknown # if we don't get version, miner type is unknown
print(f"No API response: {str(ip)}")
miner = UnknownMiner(str(ip)) miner = UnknownMiner(str(ip))
# save the miner in cache # save the miner in cache
self.miners[ip] = miner self.miners[ip] = miner

View File

@@ -10,7 +10,7 @@ class UnknownMiner(BaseMiner):
def __repr__(self) -> str: def __repr__(self) -> str:
return f"Unknown: {str(self.ip)}" return f"Unknown: {str(self.ip)}"
async def send_config(self): async def send_config(self, _):
return None return None
async def get_hostname(self): async def get_hostname(self):

View File

@@ -1,9 +1,7 @@
import ipaddress import ipaddress
import asyncio import asyncio
from miners.miner_factory import MinerFactory from miners.miner_factory import MinerFactory
from settings import NETWORK_PING_RETRIES as PING_RETRIES, NETWORK_PING_TIMEOUT as PING_TIMEOUT, NETWORK_SCAN_THREADS as SCAN_THREADS
PING_RETRIES: int = 3
PING_TIMEOUT: int = 3
class MinerNetwork: class MinerNetwork:
@@ -29,13 +27,18 @@ class MinerNetwork:
return ipaddress.ip_network(f"{default_gateway}/{subnet_mask}", strict=False) return ipaddress.ip_network(f"{default_gateway}/{subnet_mask}", strict=False)
async def scan_network_for_miners(self) -> None or list: async def scan_network_for_miners(self) -> None or list:
"""Scan the network for miners, and use the miner factory to get correct types.""" """Scan the network for miners, and """
local_network = self.get_network() local_network = self.get_network()
print(f"Scanning {local_network} for miners...") print(f"Scanning {local_network} for miners...")
scan_tasks = [] scan_tasks = []
miner_ips = []
for host in local_network.hosts(): for host in local_network.hosts():
scan_tasks.append(self.ping_miner(host)) if len(scan_tasks) < SCAN_THREADS:
miner_ips = await asyncio.gather(*scan_tasks) scan_tasks.append(self.ping_miner(host))
else:
miner_ips_scan = await asyncio.gather(*scan_tasks)
miner_ips.extend(miner_ips_scan)
scan_tasks = []
miner_ips = list(filter(None, miner_ips)) miner_ips = list(filter(None, miner_ips))
print(f"Found {len(miner_ips)} connected miners...") print(f"Found {len(miner_ips)} connected miners...")
create_miners_tasks = [] create_miners_tasks = []
@@ -47,7 +50,6 @@ class MinerNetwork:
@staticmethod @staticmethod
async def ping_miner(ip: ipaddress.ip_address) -> None or ipaddress.ip_address: async def ping_miner(ip: ipaddress.ip_address) -> None or ipaddress.ip_address:
"""Send ping requests to a miner."""
for i in range(PING_RETRIES): for i in range(PING_RETRIES):
connection_fut = asyncio.open_connection(str(ip), 4028) connection_fut = asyncio.open_connection(str(ip), 4028)
try: try:
@@ -64,7 +66,7 @@ class MinerNetwork:
continue continue
except ConnectionRefusedError: except ConnectionRefusedError:
# handle for other connection errors # handle for other connection errors
print("Unknown error...") print(f"{str(ip)}: Connection Refused.")
# ping failed, likely with an exception # ping failed, likely with an exception
except Exception as e: except Exception as e:
print(e) print(e)

7
settings.py Normal file
View File

@@ -0,0 +1,7 @@
NETWORK_PING_RETRIES: int = 3
NETWORK_PING_TIMEOUT: int = 5
NETWORK_SCAN_THREADS: int = 100
CFG_UTIL_GET_VERSION_THREADS: int = 100
MINER_FACTORY_GET_VERSION_RETRIES: int = 3