added get_model to get the model of the miner, and reformatted the style of the miner factory getting miner to get a different miner for each type of supported miner

This commit is contained in:
UpstreamData
2022-01-07 10:08:20 -07:00
parent 48aa7232b1
commit 8ec8c57e31
13 changed files with 352 additions and 247 deletions

View File

@@ -10,3 +10,8 @@ class BaseMiner:
def __init__(self, ip: str, api: BMMinerAPI | BOSMinerAPI | CGMinerAPI | BTMinerAPI | UnknownAPI) -> None:
self.ip = ipaddress.ip_address(ip)
self.api = api
self.api_type = None
self.model = None
def _init(self):
pass

View File

@@ -0,0 +1,11 @@
from miners.bmminer import BMMiner
class BMMinerS9(BMMiner):
def __init__(self, ip: str) -> None:
super().__init__(ip)
self.model = "S9"
self.api_type = "BMMiner"
def __repr__(self) -> str:
return f"BMMinerS9: {str(self.ip)}"

View File

@@ -1,118 +0,0 @@
from miners import BaseMiner
from API.bosminer import BOSMinerAPI
import asyncssh
import toml
from config.bos import bos_config_convert, general_config_convert_bos
class BOSMinerS9(BaseMiner):
def __init__(self, ip: str) -> None:
api = BOSMinerAPI(ip)
super().__init__(ip, api)
self.config = None
self.uname = 'root'
self.pwd = 'admin'
def __repr__(self) -> str:
return f"S9 - BOSminer: {str(self.ip)}"
async def _get_ssh_connection(self) -> asyncssh.connect:
"""Create a new asyncssh connection"""
conn = await asyncssh.connect(str(self.ip), known_hosts=None, username=self.uname, password=self.pwd,
server_host_key_algs=['ssh-rsa'])
# return created connection
return conn
async def send_ssh_command(self, cmd: str) -> None:
"""Sends SSH command to miner."""
# creates result variable
result = None
# runs the command on the miner
async with (await self._get_ssh_connection()) as conn:
# attempt to run command up to 3 times
for i in range(3):
try:
# save result of the command
result = await conn.run(cmd)
except Exception as e:
print(f"{cmd} error: {e}")
if i == 3:
return
continue
# let the user know the result of the command
if result is not None:
if result.stdout != "":
print(result.stdout)
if result.stderr != "":
print("ERROR: " + result.stderr)
elif result.stderr != "":
print("ERROR: " + result.stderr)
else:
print(cmd)
async def fault_light_on(self) -> None:
"""Sends command to turn on fault light on the miner."""
await self.send_ssh_command('miner fault_light on')
async def fault_light_off(self) -> None:
"""Sends command to turn off fault light on the miner."""
await self.send_ssh_command('miner fault_light off')
async def restart_backend(self) -> None:
"""Restart bosminer hashing process."""
await self.send_ssh_command('/etc/init.d/bosminer restart')
async def reboot(self) -> None:
"""Reboots power to the physical miner."""
await self.send_ssh_command('/sbin/reboot')
async def get_config(self) -> None:
async with (await self._get_ssh_connection()) as conn:
async with conn.start_sftp_client() as sftp:
async with sftp.open('/etc/bosminer.toml') as file:
toml_data = toml.loads(await file.read())
cfg = await bos_config_convert(toml_data)
self.config = cfg
async def get_hostname(self) -> str:
"""Attempts to get hostname from miner."""
try:
async with (await self._get_ssh_connection()) as conn:
data = await conn.run('cat /proc/sys/kernel/hostname')
return data.stdout.strip()
except Exception as e:
print(self.ip, e)
return "BOSMiner Unknown"
async def send_config(self, yaml_config) -> None:
"""Configures miner with yaml config."""
toml_conf = await general_config_convert_bos(yaml_config)
async with (await self._get_ssh_connection()) as conn:
async with conn.start_sftp_client() as sftp:
async with sftp.open('/etc/bosminer.toml', 'w+') as file:
await file.write(toml_conf)
await conn.run("/etc/init.d/bosminer restart")
async def get_bad_boards(self) -> list:
"""Checks for and provides list of non working boards."""
devs = await self.api.devdetails()
bad = 0
chains = devs['DEVDETAILS']
for chain in chains:
if chain['Chips'] == 0:
bad += 1
if bad > 0:
return [str(self.ip), bad]
async def check_good_boards(self) -> str:
"""Checks for and provides list for working boards."""
devs = await self.api.devdetails()
bad = 0
chains = devs['DEVDETAILS']
for chain in chains:
if chain['Chips'] == 0:
bad += 1
if not bad > 0:
return str(self.ip)

View File

@@ -0,0 +1,11 @@
from miners.bosminer import BOSminer
class BOSMinerS9(BOSminer):
def __init__(self, ip: str) -> None:
super().__init__(ip)
self.model = "S9"
self.api_type = "BOSMiner"
def __repr__(self) -> str:
return f"BOSminerS9: {str(self.ip)}"

View File

@@ -0,0 +1,11 @@
from miners.cgminer import CGMiner
class CGMinerS9(CGMiner):
def __init__(self, ip: str) -> None:
super().__init__(ip)
self.model = "S9"
self.api_type = "CGMiner"
def __repr__(self) -> str:
return f"CGMinerS9: {str(self.ip)}"

View File

@@ -0,0 +1,7 @@
from miners.bmminer import BMMiner
class BMMinerX17(BMMiner):
def __init__(self, ip: str) -> None:
super().__init__(ip)

View File

@@ -1,118 +0,0 @@
from miners import BaseMiner
from API.bosminer import BOSMinerAPI
import asyncssh
import toml
from config.bos import bos_config_convert, general_config_convert_bos
class BOSMinerX17(BaseMiner):
def __init__(self, ip: str) -> None:
api = BOSMinerAPI(ip)
super().__init__(ip, api)
self.config = None
self.uname = 'root'
self.pwd = 'admin'
def __repr__(self) -> str:
return f"X17 - BOSminer: {str(self.ip)}"
async def _get_ssh_connection(self) -> asyncssh.connect:
"""Create a new asyncssh connection"""
conn = await asyncssh.connect(str(self.ip), known_hosts=None, username=self.uname, password=self.pwd,
server_host_key_algs=['ssh-rsa'])
# return created connection
return conn
async def send_ssh_command(self, cmd: str) -> None:
"""Sends SSH command to miner."""
# creates result variable
result = None
# runs the command on the miner
async with (await self._get_ssh_connection()) as conn:
# attempt to run command up to 3 times
for i in range(3):
try:
# save result of the command
result = await conn.run(cmd)
except Exception as e:
print(f"{cmd} error: {e}")
if i == 3:
return
continue
# let the user know the result of the command
if result is not None:
if result.stdout != "":
print(result.stdout)
if result.stderr != "":
print("ERROR: " + result.stderr)
elif result.stderr != "":
print("ERROR: " + result.stderr)
else:
print(cmd)
async def fault_light_on(self) -> None:
"""Sends command to turn on fault light on the miner."""
await self.send_ssh_command('miner fault_light on')
async def fault_light_off(self) -> None:
"""Sends command to turn off fault light on the miner."""
await self.send_ssh_command('miner fault_light off')
async def restart_backend(self) -> None:
"""Restart bosminer hashing process."""
await self.send_ssh_command('/etc/init.d/bosminer restart')
async def reboot(self) -> None:
"""Reboots power to the physical miner."""
await self.send_ssh_command('/sbin/reboot')
async def get_config(self) -> None:
async with (await self._get_ssh_connection()) as conn:
async with conn.start_sftp_client() as sftp:
async with sftp.open('/etc/bosminer.toml') as file:
toml_data = toml.loads(await file.read())
cfg = await bos_config_convert(toml_data)
self.config = cfg
async def get_hostname(self) -> str:
"""Attempts to get hostname from miner."""
try:
async with (await self._get_ssh_connection()) as conn:
data = await conn.run('cat /proc/sys/kernel/hostname')
return data.stdout.strip()
except Exception as e:
print(self.ip, e)
return "BOSMiner Unknown"
async def send_config(self, yaml_config) -> None:
"""Configures miner with yaml config."""
toml_conf = await general_config_convert_bos(yaml_config)
async with (await self._get_ssh_connection()) as conn:
async with conn.start_sftp_client() as sftp:
async with sftp.open('/etc/bosminer.toml', 'w+') as file:
await file.write(toml_conf)
await conn.run("/etc/init.d/bosminer restart")
async def get_bad_boards(self) -> list:
"""Checks for and provides list of non working boards."""
devs = await self.api.devdetails()
bad = 0
chains = devs['DEVDETAILS']
for chain in chains:
if chain['Chips'] == 0:
bad += 1
if bad > 0:
return [str(self.ip), bad]
async def check_good_boards(self) -> str:
"""Checks for and provides list for working boards."""
devs = await self.api.devdetails()
bad = 0
chains = devs['DEVDETAILS']
for chain in chains:
if chain['Chips'] == 0:
bad += 1
if not bad > 0:
return str(self.ip)

View File

@@ -0,0 +1,10 @@
from miners.bosminer import BOSminer
class BOSMinerX17(BOSminer):
def __init__(self, ip: str) -> None:
super().__init__(ip)
self.api_type = "BOSMiner"
def __repr__(self) -> str:
return f"BOSminerX17: {str(self.ip)}"

View File

@@ -0,0 +1,123 @@
from miners import BaseMiner
from API.cgminer import CGMinerAPI
import asyncssh
class CGMinerX17(BaseMiner):
def __init__(self, ip: str) -> None:
api = CGMinerAPI(ip)
super().__init__(ip, api)
self.config = None
self.uname = 'root'
self.pwd = 'admin'
def __repr__(self) -> str:
return f"CGMiner: {str(self.ip)}"
async def get_hostname(self) -> str:
try:
async with (await self._get_ssh_connection()) as conn:
if conn is not None:
data = await conn.run('cat /proc/sys/kernel/hostname')
return data.stdout.strip()
else:
return "CGMiner Unknown"
except Exception:
return "CGMiner Unknown"
async def send_config(self, _):
return None # ignore for now
async def _get_ssh_connection(self) -> asyncssh.connect:
try:
conn = await asyncssh.connect(str(self.ip),
known_hosts=None,
username=self.uname,
password=self.pwd,
server_host_key_algs=['ssh-rsa'])
return conn
except asyncssh.misc.PermissionDenied:
try:
conn = await asyncssh.connect(str(self.ip),
known_hosts=None,
username="admin",
password="admin",
server_host_key_algs=['ssh-rsa'])
return conn
except Exception as e:
print(e)
except OSError:
print(str(self.ip) + " Connection refused.")
return None
async def send_ssh_command(self, cmd):
result = None
async with (await self._get_ssh_connection()) as conn:
for i in range(3):
try:
result = await conn.run(cmd)
except Exception as e:
print(f"{cmd} error: {e}")
if i == 3:
return
continue
# handle result
self._result_handler(result)
@staticmethod
def _result_handler(result: asyncssh.process.SSHCompletedProcess) -> None:
if result is not None:
# noinspection PyUnresolvedReferences
if len(result.stdout) > 0:
# noinspection PyUnresolvedReferences
print("ssh stdout: \n" + result.stdout)
# noinspection PyUnresolvedReferences
if len(result.stderr) > 0:
# noinspection PyUnresolvedReferences
print("ssh stderr: \n" + result.stderrr)
# noinspection PyUnresolvedReferences
if len(result.stdout) <= 0 and len(result.stderr) <= 0:
print("ssh stdout stderr empty")
# if result.stdout != "":
# print(result.stdout)
# if result.stderr != "":
# print("ERROR: " + result.stderr)
# elif result.stderr != "":
# print("ERROR: " + result.stderr)
# else:
# print(cmd)
async def restart_cgminer(self) -> None:
commands = ['cgminer-api restart',
'/usr/bin/cgminer-monitor >/dev/null 2>&1']
commands = ';'.join(commands)
await self.send_ssh_command(commands)
async def reboot(self) -> None:
commands = ['reboot']
commands = ';'.join(commands)
await self.send_ssh_command(commands)
async def start_cgminer(self) -> None:
commands = ['mkdir -p /etc/tmp/',
'echo \"*/3 * * * * /usr/bin/cgminer-monitor\" > /etc/tmp/root',
'crontab -u root /etc/tmp/root',
'/usr/bin/cgminer-monitor >/dev/null 2>&1']
commands = ';'.join(commands)
await self.send_ssh_command(commands)
async def stop_cgminer(self) -> None:
commands = ['mkdir -p /etc/tmp/',
'echo \"\" > /etc/tmp/root',
'crontab -u root /etc/tmp/root',
'killall cgminer']
commands = ';'.join(commands)
await self.send_ssh_command(commands)
async def get_config(self) -> None:
async with (await self._get_ssh_connection()) as conn:
command = 'cat /etc/config/cgminer'
result = await conn.run(command, check=True)
self._result_handler(result)
self.config = result.stdout
print(str(self.config))

View File

@@ -0,0 +1,26 @@
from API.bmminer import BMMinerAPI
from miners import BaseMiner
class BMMinerX19(BaseMiner):
def __init__(self, ip: str) -> None:
api = BMMinerAPI(ip)
super().__init__(ip, api)
def __repr__(self) -> str:
return f"BMMiner: {str(self.ip)}"
async def get_hostname(self) -> str:
return "BMMiner Unknown"
async def send_config(self, _):
return None # ignore for now
async def restart_backend(self) -> None:
return None # Murray
async def reboot(self) -> None:
return None # Murray
async def get_config(self) -> None:
return None # Murray

View File

@@ -0,0 +1,123 @@
from miners import BaseMiner
from API.cgminer import CGMinerAPI
import asyncssh
class CGMinerX19(BaseMiner):
def __init__(self, ip: str) -> None:
api = CGMinerAPI(ip)
super().__init__(ip, api)
self.config = None
self.uname = 'root'
self.pwd = 'admin'
def __repr__(self) -> str:
return f"CGMiner: {str(self.ip)}"
async def get_hostname(self) -> str:
try:
async with (await self._get_ssh_connection()) as conn:
if conn is not None:
data = await conn.run('cat /proc/sys/kernel/hostname')
return data.stdout.strip()
else:
return "CGMiner Unknown"
except Exception:
return "CGMiner Unknown"
async def send_config(self, _):
return None # ignore for now
async def _get_ssh_connection(self) -> asyncssh.connect:
try:
conn = await asyncssh.connect(str(self.ip),
known_hosts=None,
username=self.uname,
password=self.pwd,
server_host_key_algs=['ssh-rsa'])
return conn
except asyncssh.misc.PermissionDenied:
try:
conn = await asyncssh.connect(str(self.ip),
known_hosts=None,
username="admin",
password="admin",
server_host_key_algs=['ssh-rsa'])
return conn
except Exception as e:
print(e)
except OSError:
print(str(self.ip) + " Connection refused.")
return None
async def send_ssh_command(self, cmd):
result = None
async with (await self._get_ssh_connection()) as conn:
for i in range(3):
try:
result = await conn.run(cmd)
except Exception as e:
print(f"{cmd} error: {e}")
if i == 3:
return
continue
# handle result
self._result_handler(result)
@staticmethod
def _result_handler(result: asyncssh.process.SSHCompletedProcess) -> None:
if result is not None:
# noinspection PyUnresolvedReferences
if len(result.stdout) > 0:
# noinspection PyUnresolvedReferences
print("ssh stdout: \n" + result.stdout)
# noinspection PyUnresolvedReferences
if len(result.stderr) > 0:
# noinspection PyUnresolvedReferences
print("ssh stderr: \n" + result.stderrr)
# noinspection PyUnresolvedReferences
if len(result.stdout) <= 0 and len(result.stderr) <= 0:
print("ssh stdout stderr empty")
# if result.stdout != "":
# print(result.stdout)
# if result.stderr != "":
# print("ERROR: " + result.stderr)
# elif result.stderr != "":
# print("ERROR: " + result.stderr)
# else:
# print(cmd)
async def restart_cgminer(self) -> None:
commands = ['cgminer-api restart',
'/usr/bin/cgminer-monitor >/dev/null 2>&1']
commands = ';'.join(commands)
await self.send_ssh_command(commands)
async def reboot(self) -> None:
commands = ['reboot']
commands = ';'.join(commands)
await self.send_ssh_command(commands)
async def start_cgminer(self) -> None:
commands = ['mkdir -p /etc/tmp/',
'echo \"*/3 * * * * /usr/bin/cgminer-monitor\" > /etc/tmp/root',
'crontab -u root /etc/tmp/root',
'/usr/bin/cgminer-monitor >/dev/null 2>&1']
commands = ';'.join(commands)
await self.send_ssh_command(commands)
async def stop_cgminer(self) -> None:
commands = ['mkdir -p /etc/tmp/',
'echo \"\" > /etc/tmp/root',
'crontab -u root /etc/tmp/root',
'killall cgminer']
commands = ';'.join(commands)
await self.send_ssh_command(commands)
async def get_config(self) -> None:
async with (await self._get_ssh_connection()) as conn:
command = 'cat /etc/config/cgminer'
result = await conn.run(command, check=True)
self._result_handler(result)
self.config = result.stdout
print(str(self.config))

View File

@@ -86,6 +86,12 @@ class BOSminer(BaseMiner):
print(self.ip, e)
return "BOSMiner Unknown"
async def get_model(self):
version_data = await self.api.devdetails()
if version_data:
return version_data["DEVDETAILS"][0]["Model"].replace("Antminer ", "")
return None
async def send_config(self, yaml_config) -> None:
"""Configures miner with yaml config."""
toml_conf = await general_config_convert_bos(yaml_config)

View File

@@ -1,5 +1,14 @@
from miners.antminer.S9.bos import BOSMinerS9
from miners.antminer.X17.bos import BOSMinerX17
from miners.antminer.S9.bosminer import BOSMinerS9
from miners.antminer.S9.bmminer import BMMinerS9
from miners.antminer.S9.cgminer import CGMinerS9
from miners.antminer.X17.bosminer import BOSMinerX17
from miners.antminer.X17.bmminer import BMMinerX17
from miners.antminer.X17.cgminer import CGMinerX17
from miners.antminer.X19.bmminer import BMMinerX19
from miners.antminer.X19.cgminer import CGMinerX19
from miners.whatsminer.M20 import BTMinerM20
from miners.whatsminer.M21 import BTMinerM21
@@ -7,10 +16,8 @@ from miners.whatsminer.M30 import BTMinerM30
from miners.whatsminer.M31 import BTMinerM31
from miners.whatsminer.M32 import BTMinerM32
from miners.bosminer import BOSminer
from miners.bmminer import BMMiner
from miners.cgminer import CGMiner
from miners.btminer import BTMiner
from miners.unknown import UnknownMiner
from API import APIError
import asyncio
@@ -41,7 +48,7 @@ class MinerFactory:
for miner in scanned:
yield await miner
async def get_miner(self, ip: ipaddress.ip_address) -> BOSminer or CGMiner or BMMiner or BTMiner or UnknownMiner:
async def get_miner(self, ip: ipaddress.ip_address):
"""Decide a miner type using the IP address of the miner."""
# check if the miner already exists in cache
if ip in self.miners:
@@ -63,21 +70,21 @@ class MinerFactory:
if "BOSMiner" in api:
miner = BOSMinerS9(str(ip))
elif "CGMiner" in api:
miner = CGMiner(str(ip))
miner = CGMinerS9(str(ip))
elif "BMMiner" in api:
miner = BMMiner(str(ip))
miner = BMMinerS9(str(ip))
elif "17" in model:
if "BOSMiner" in api:
miner = BOSMinerX17(str(ip))
elif "CGMiner" in api:
miner = CGMiner(str(ip))
miner = CGMinerX17(str(ip))
elif "BMMiner" in api:
miner = BMMiner(str(ip))
miner = BMMinerX17(str(ip))
elif "19" in model:
if "CGMiner" in api:
miner = CGMiner(str(ip))
miner = CGMinerX19(str(ip))
elif "BMMiner" in api:
miner = BMMiner(str(ip))
miner = BMMinerX19(str(ip))
elif "M20" in model:
miner = BTMinerM20(str(ip))
elif "M21" in model:
@@ -117,6 +124,7 @@ class MinerFactory:
print(ip, e)
return None
async def _send_api_command(self, ip: ipaddress.ip_address or str, command: str):
try:
# get reader and writer streams