update to a better way to handle settings

This commit is contained in:
UpstreamData
2022-07-18 11:44:22 -06:00
parent ce7b006c8f
commit 6a0dc03b9d
20 changed files with 70 additions and 120 deletions

View File

@@ -10,7 +10,7 @@ from passlib.handlers.md5_crypt import md5_crypt
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from pyasic.API import BaseMinerAPI, APIError from pyasic.API import BaseMinerAPI, APIError
from pyasic.settings import WHATSMINER_PWD from pyasic.settings import PyasicSettings
### IMPORTANT ### ### IMPORTANT ###
@@ -161,7 +161,12 @@ class BTMinerAPI(BaseMinerAPI):
pwd: The admin password of the miner. Default is admin. pwd: The admin password of the miner. Default is admin.
""" """
def __init__(self, ip: str, port: int = 4028, pwd: str = WHATSMINER_PWD): def __init__(
self,
ip: str,
port: int = 4028,
pwd: str = PyasicSettings().global_whatsminer_password,
):
super().__init__(ip, port) super().__init__(ip, port)
self.admin_pwd = pwd self.admin_pwd = pwd
self.current_token = None self.current_token = None

View File

@@ -1,9 +1,9 @@
import logging import logging
from pyasic.settings import DEBUG, LOGFILE from pyasic.settings import PyasicSettings
def init_logger(): def init_logger():
if LOGFILE: if PyasicSettings().logfile:
logging.basicConfig( logging.basicConfig(
filename="logfile.txt", filename="logfile.txt",
filemode="a", filemode="a",
@@ -18,7 +18,7 @@ def init_logger():
_logger = logging.getLogger() _logger = logging.getLogger()
if DEBUG: if PyasicSettings().debug:
_logger.setLevel(logging.DEBUG) _logger.setLevel(logging.DEBUG)
logging.getLogger("asyncssh").setLevel(logging.DEBUG) logging.getLogger("asyncssh").setLevel(logging.DEBUG)
else: else:

View File

@@ -8,7 +8,7 @@ from pyasic.miners import BaseMiner
from pyasic.data import MinerData from pyasic.data import MinerData
from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES from pyasic.settings import PyasicSettings
class BMMiner(BaseMiner): class BMMiner(BaseMiner):
@@ -165,7 +165,7 @@ class BMMiner(BaseMiner):
data.mac = mac data.mac = mac
miner_data = None miner_data = None
for i in range(DATA_RETRIES): for i in range(PyasicSettings().miner_get_data_retries):
miner_data = await self.api.multicommand( miner_data = await self.api.multicommand(
"summary", "pools", "stats", ignore_x19_error=True "summary", "pools", "stats", ignore_x19_error=True
) )

View File

@@ -15,7 +15,7 @@ from pyasic.data import MinerData
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES from pyasic.settings import PyasicSettings
class BOSMiner(BaseMiner): class BOSMiner(BaseMiner):
@@ -97,7 +97,7 @@ class BOSMiner(BaseMiner):
return True return True
return False return False
async def get_config(self) -> str: async def get_config(self) -> MinerConfig:
"""Gets the config for the miner and sets it as `self.config`. """Gets the config for the miner and sets it as `self.config`.
Returns: Returns:
@@ -217,13 +217,14 @@ class BOSMiner(BaseMiner):
.as_bos(model=self.model.replace(" (BOS)", "")) .as_bos(model=self.model.replace(" (BOS)", ""))
) )
async with (await self._get_ssh_connection()) as conn: async with (await self._get_ssh_connection()) as conn:
await conn.run("/etc/init.d/bosminer stop")
logging.debug(f"{self}: Opening SFTP connection.") logging.debug(f"{self}: Opening SFTP connection.")
async with conn.start_sftp_client() as sftp: async with conn.start_sftp_client() as sftp:
logging.debug(f"{self}: Opening config file.") logging.debug(f"{self}: Opening config file.")
async with sftp.open("/etc/bosminer.toml", "w+") as file: async with sftp.open("/etc/bosminer.toml", "w+") as file:
await file.write(toml_conf) await file.write(toml_conf)
logging.debug(f"{self}: Restarting BOSMiner") logging.debug(f"{self}: Restarting BOSMiner")
await conn.run("/etc/init.d/bosminer restart") await conn.run("/etc/init.d/bosminer start")
async def get_data(self) -> MinerData: async def get_data(self) -> MinerData:
"""Get data from the miner. """Get data from the miner.
@@ -250,7 +251,7 @@ class BOSMiner(BaseMiner):
data.mac = mac data.mac = mac
miner_data = None miner_data = None
for i in range(DATA_RETRIES): for i in range(PyasicSettings().miner_get_data_retries):
try: try:
miner_data = await self.api.multicommand( miner_data = await self.api.multicommand(
"summary", "summary",

View File

@@ -10,7 +10,7 @@ from pyasic.API import APIError
from pyasic.data import MinerData from pyasic.data import MinerData
from pyasic.data.error_codes import WhatsminerError from pyasic.data.error_codes import WhatsminerError
from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES from pyasic.settings import PyasicSettings
class BTMiner(BaseMiner): class BTMiner(BaseMiner):
@@ -116,7 +116,7 @@ class BTMiner(BaseMiner):
data.hostname = hostname data.hostname = hostname
miner_data = None miner_data = None
for i in range(DATA_RETRIES): for i in range(PyasicSettings().miner_get_data_retries):
try: try:
miner_data = await self.api.multicommand("summary", "devs", "pools") miner_data = await self.api.multicommand("summary", "devs", "pools")
if miner_data: if miner_data:

View File

@@ -9,7 +9,7 @@ from pyasic.API import APIError
from pyasic.data import MinerData from pyasic.data import MinerData
from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES from pyasic.settings import PyasicSettings
class CGMiner(BaseMiner): class CGMiner(BaseMiner):
@@ -162,7 +162,7 @@ class CGMiner(BaseMiner):
data.mac = mac data.mac = mac
miner_data = None miner_data = None
for i in range(DATA_RETRIES): for i in range(PyasicSettings().miner_get_data_retries):
miner_data = await self.api.multicommand( miner_data = await self.api.multicommand(
"summary", "pools", "stats", ignore_x19_error=True "summary", "pools", "stats", ignore_x19_error=True
) )

View File

@@ -2,7 +2,7 @@ from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module
from pyasic.miners._types import Avalon1026 # noqa - Ignore access to _module from pyasic.miners._types import Avalon1026 # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData
from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES from pyasic.settings import PyasicSettings
import re import re
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
import logging import logging
@@ -67,7 +67,7 @@ class CGMinerAvalon1026(CGMiner, Avalon1026):
data.model = model data.model = model
miner_data = None miner_data = None
for i in range(DATA_RETRIES): for i in range(PyasicSettings().miner_get_data_retries):
miner_data = await self.api.multicommand( miner_data = await self.api.multicommand(
"version", "summary", "pools", "stats" "version", "summary", "pools", "stats"
) )

View File

@@ -2,7 +2,7 @@ from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module
from pyasic.miners._types import Avalon1047 # noqa - Ignore access to _module from pyasic.miners._types import Avalon1047 # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData
from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES from pyasic.settings import PyasicSettings
import re import re
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
import logging import logging
@@ -67,7 +67,7 @@ class CGMinerAvalon1047(CGMiner, Avalon1047):
data.model = model data.model = model
miner_data = None miner_data = None
for i in range(DATA_RETRIES): for i in range(PyasicSettings().miner_get_data_retries):
miner_data = await self.api.multicommand( miner_data = await self.api.multicommand(
"version", "summary", "pools", "stats" "version", "summary", "pools", "stats"
) )

View File

@@ -2,7 +2,7 @@ from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module
from pyasic.miners._types import Avalon1066 # noqa - Ignore access to _module from pyasic.miners._types import Avalon1066 # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData
from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES from pyasic.settings import PyasicSettings
import re import re
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
import logging import logging
@@ -67,7 +67,7 @@ class CGMinerAvalon1066(CGMiner, Avalon1066):
data.model = model data.model = model
miner_data = None miner_data = None
for i in range(DATA_RETRIES): for i in range(PyasicSettings().miner_get_data_retries):
miner_data = await self.api.multicommand( miner_data = await self.api.multicommand(
"version", "summary", "pools", "stats" "version", "summary", "pools", "stats"
) )

View File

@@ -2,7 +2,7 @@ from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module
from pyasic.miners._types import Avalon721 # noqa - Ignore access to _module from pyasic.miners._types import Avalon721 # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData
from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES from pyasic.settings import PyasicSettings
import re import re
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
import logging import logging
@@ -67,7 +67,7 @@ class CGMinerAvalon721(CGMiner, Avalon721):
data.model = model data.model = model
miner_data = None miner_data = None
for i in range(DATA_RETRIES): for i in range(PyasicSettings().miner_get_data_retries):
miner_data = await self.api.multicommand( miner_data = await self.api.multicommand(
"version", "summary", "pools", "stats" "version", "summary", "pools", "stats"
) )

View File

@@ -2,7 +2,7 @@ from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module
from pyasic.miners._types import Avalon741 # noqa - Ignore access to _module from pyasic.miners._types import Avalon741 # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData
from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES from pyasic.settings import PyasicSettings
import re import re
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
import logging import logging
@@ -67,7 +67,7 @@ class CGMinerAvalon741(CGMiner, Avalon741):
data.model = model data.model = model
miner_data = None miner_data = None
for i in range(DATA_RETRIES): for i in range(PyasicSettings().miner_get_data_retries):
miner_data = await self.api.multicommand( miner_data = await self.api.multicommand(
"version", "summary", "pools", "stats" "version", "summary", "pools", "stats"
) )

View File

@@ -2,7 +2,7 @@ from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module
from pyasic.miners._types import Avalon761 # noqa - Ignore access to _module from pyasic.miners._types import Avalon761 # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData
from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES from pyasic.settings import PyasicSettings
import re import re
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
import logging import logging
@@ -67,7 +67,7 @@ class CGMinerAvalon761(CGMiner, Avalon761):
data.model = model data.model = model
miner_data = None miner_data = None
for i in range(DATA_RETRIES): for i in range(PyasicSettings().miner_get_data_retries):
miner_data = await self.api.multicommand( miner_data = await self.api.multicommand(
"version", "summary", "pools", "stats" "version", "summary", "pools", "stats"
) )

View File

@@ -2,7 +2,7 @@ from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module
from pyasic.miners._types import Avalon821 # noqa - Ignore access to _module from pyasic.miners._types import Avalon821 # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData
from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES from pyasic.settings import PyasicSettings
import re import re
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
import logging import logging
@@ -67,7 +67,7 @@ class CGMinerAvalon821(CGMiner, Avalon821):
data.model = model data.model = model
miner_data = None miner_data = None
for i in range(DATA_RETRIES): for i in range(PyasicSettings().miner_get_data_retries):
miner_data = await self.api.multicommand( miner_data = await self.api.multicommand(
"version", "summary", "pools", "stats" "version", "summary", "pools", "stats"
) )

View File

@@ -2,7 +2,7 @@ from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module
from pyasic.miners._types import Avalon841 # noqa - Ignore access to _module from pyasic.miners._types import Avalon841 # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData
from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES from pyasic.settings import PyasicSettings
import re import re
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
import logging import logging
@@ -67,7 +67,7 @@ class CGMinerAvalon841(CGMiner, Avalon841):
data.model = model data.model = model
miner_data = None miner_data = None
for i in range(DATA_RETRIES): for i in range(PyasicSettings().miner_get_data_retries):
miner_data = await self.api.multicommand( miner_data = await self.api.multicommand(
"version", "summary", "pools", "stats" "version", "summary", "pools", "stats"
) )

View File

@@ -2,7 +2,7 @@ from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module
from pyasic.miners._types import Avalon851 # noqa - Ignore access to _module from pyasic.miners._types import Avalon851 # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData
from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES from pyasic.settings import PyasicSettings
import re import re
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
import logging import logging
@@ -67,7 +67,7 @@ class CGMinerAvalon851(CGMiner, Avalon851):
data.model = model data.model = model
miner_data = None miner_data = None
for i in range(DATA_RETRIES): for i in range(PyasicSettings().miner_get_data_retries):
miner_data = await self.api.multicommand( miner_data = await self.api.multicommand(
"version", "summary", "pools", "stats" "version", "summary", "pools", "stats"
) )

View File

@@ -2,7 +2,7 @@ from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module
from pyasic.miners._types import Avalon921 # noqa - Ignore access to _module from pyasic.miners._types import Avalon921 # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData
from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES from pyasic.settings import PyasicSettings
import re import re
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
import logging import logging
@@ -67,7 +67,7 @@ class CGMinerAvalon921(CGMiner, Avalon921):
data.model = model data.model = model
miner_data = None miner_data = None
for i in range(DATA_RETRIES): for i in range(PyasicSettings().miner_get_data_retries):
miner_data = await self.api.multicommand( miner_data = await self.api.multicommand(
"version", "summary", "pools", "stats" "version", "summary", "pools", "stats"
) )

View File

@@ -23,10 +23,7 @@ import ipaddress
import json import json
import logging import logging
from pyasic.settings import ( from pyasic.settings import PyasicSettings
MINER_FACTORY_GET_VERSION_RETRIES as GET_VERSION_RETRIES,
NETWORK_PING_TIMEOUT as PING_TIMEOUT,
)
import asyncssh import asyncssh
@@ -284,7 +281,7 @@ class MinerFactory(metaclass=Singleton):
ver = None ver = None
# try to get the API multiple times based on retries # try to get the API multiple times based on retries
for i in range(GET_VERSION_RETRIES): for i in range(PyasicSettings().miner_factory_get_version_retries):
try: try:
# get the API type, should be BOSMiner, CGMiner, BMMiner, BTMiner, or None # get the API type, should be BOSMiner, CGMiner, BMMiner, BTMiner, or None
new_model, new_api, new_ver = await asyncio.wait_for( new_model, new_api, new_ver = await asyncio.wait_for(

View File

@@ -5,11 +5,7 @@ from typing import Union
from pyasic.network.net_range import MinerNetworkRange from pyasic.network.net_range import MinerNetworkRange
from pyasic.miners.miner_factory import MinerFactory, AnyMiner from pyasic.miners.miner_factory import MinerFactory, AnyMiner
from pyasic.settings import ( from pyasic.settings import PyasicSettings
NETWORK_PING_RETRIES as PING_RETRIES,
NETWORK_PING_TIMEOUT as PING_TIMEOUT,
NETWORK_SCAN_THREADS as SCAN_THREADS,
)
class MinerNetwork: class MinerNetwork:
@@ -91,7 +87,7 @@ class MinerNetwork:
for host in local_network.hosts(): for host in local_network.hosts():
# make sure we don't exceed the allowed async tasks # make sure we don't exceed the allowed async tasks
if len(scan_tasks) < SCAN_THREADS: if len(scan_tasks) < PyasicSettings().network_scan_threads:
# add the task to the list # add the task to the list
scan_tasks.append(self.ping_and_get_miner(host)) scan_tasks.append(self.ping_and_get_miner(host))
else: else:
@@ -130,7 +126,7 @@ class MinerNetwork:
# for each ip on the network, loop through and scan it # for each ip on the network, loop through and scan it
for host in local_network.hosts(): for host in local_network.hosts():
# make sure we don't exceed the allowed async tasks # make sure we don't exceed the allowed async tasks
if len(scan_tasks) >= SCAN_THREADS: if len(scan_tasks) >= PyasicSettings().network_scan_threads:
# scanned is a loopable list of awaitables # scanned is a loopable list of awaitables
scanned = asyncio.as_completed(scan_tasks) scanned = asyncio.as_completed(scan_tasks)
# when we scan, empty the scan tasks # when we scan, empty the scan tasks
@@ -180,12 +176,12 @@ class MinerNetwork:
async def ping_miner( async def ping_miner(
ip: ipaddress.ip_address, port=4028 ip: ipaddress.ip_address, port=4028
) -> None or ipaddress.ip_address: ) -> None or ipaddress.ip_address:
for i in range(PING_RETRIES): for i in range(PyasicSettings().network_ping_retries):
connection_fut = asyncio.open_connection(str(ip), port) connection_fut = asyncio.open_connection(str(ip), port)
try: try:
# get the read and write streams from the connection # get the read and write streams from the connection
reader, writer = await asyncio.wait_for( reader, writer = await asyncio.wait_for(
connection_fut, timeout=PING_TIMEOUT connection_fut, timeout=PyasicSettings().network_ping_timeout
) )
# immediately close connection, we know connection happened # immediately close connection, we know connection happened
writer.close() writer.close()
@@ -207,12 +203,12 @@ async def ping_miner(
async def ping_and_get_miner(ip: ipaddress.ip_address, port=4028) -> None or AnyMiner: async def ping_and_get_miner(ip: ipaddress.ip_address, port=4028) -> None or AnyMiner:
for i in range(PING_RETRIES): for i in range(PyasicSettings().network_ping_retries):
connection_fut = asyncio.open_connection(str(ip), port) connection_fut = asyncio.open_connection(str(ip), port)
try: try:
# get the read and write streams from the connection # get the read and write streams from the connection
reader, writer = await asyncio.wait_for( reader, writer = await asyncio.wait_for(
connection_fut, timeout=PING_TIMEOUT connection_fut, timeout=PyasicSettings().network_ping_timeout
) )
# immediately close connection, we know connection happened # immediately close connection, we know connection happened
writer.close() writer.close()

View File

@@ -1,53 +1,26 @@
import toml from dataclasses import dataclass
import os
NETWORK_PING_RETRIES: int = 3
NETWORK_PING_TIMEOUT: int = 5
NETWORK_SCAN_THREADS: int = 300
CFG_UTIL_REBOOT_THREADS: int = 300
CFG_UTIL_CONFIG_THREADS: int = 300
MINER_FACTORY_GET_VERSION_RETRIES: int = 3
WHATSMINER_PWD = "admin"
DEBUG = False
LOGFILE = False
settings_keys = {}
try:
with open(
os.path.join(os.path.dirname(__file__), "settings.toml"), "r"
) as settings_file:
settings = toml.loads(settings_file.read())
settings_keys = settings.keys()
except:
pass
if "ping_retries" in settings_keys:
NETWORK_PING_RETRIES: int = settings["ping_retries"]
if "ping_timeout" in settings_keys:
NETWORK_PING_TIMEOUT: int = settings["ping_timeout"]
if "scan_threads" in settings_keys:
NETWORK_SCAN_THREADS: int = settings["scan_threads"]
if "reboot_threads" in settings_keys:
CFG_UTIL_REBOOT_THREADS: int = settings["reboot_threads"]
if "config_threads" in settings_keys:
CFG_UTIL_CONFIG_THREADS: int = settings["config_threads"]
if "get_version_retries" in settings_keys: class Singleton(type):
MINER_FACTORY_GET_VERSION_RETRIES: int = settings["get_version_retries"] _instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
if "whatsminer_pwd" in settings_keys: @dataclass
WHATSMINER_PWD: str = settings["whatsminer_pwd"] class PyasicSettings(metaclass=Singleton):
network_ping_retries: int = 3
network_ping_timeout: int = 5
network_scan_threads: int = 300
if "debug" in settings_keys: miner_factory_get_version_retries: int = 1
DEBUG: int = settings["debug"]
if "logfile" in settings_keys: miner_get_data_retries: int = 1
LOGFILE: bool = settings["logfile"]
global_whatsminer_password = "admin"
debug: bool = False
logfile: bool = False

View File

@@ -1,22 +0,0 @@
get_version_retries = 3
ping_retries = 3
ping_timeout = 3 # Seconds
scan_threads = 300
config_threads = 300
reboot_threads = 300
### IMPORTANT ###
# You need to change the password of the miners using the whatsminer
# tool or the privileged API will not work using admin as the password.
# If you change the password, you can pass that password here.
whatsminer_pwd = "admin"
logfile = true
### DEBUG MODE ###
# change this to debug = true
# to enable debug mode.
debug = false
# debug = true