added install file to do the basic install
This commit is contained in:
@@ -44,6 +44,10 @@ class BaseMiner:
|
|||||||
logging.warning(f"{self} raised an exception: {e}")
|
logging.warning(f"{self} raised an exception: {e}")
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
async def send_file(self, src, dest):
|
||||||
|
conn = self._get_ssh_connection()
|
||||||
|
await asyncssh.scp((conn, src), dest)
|
||||||
|
|
||||||
async def get_board_info(self):
|
async def get_board_info(self):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -135,25 +135,29 @@ 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:
|
||||||
for i in range(PING_RETRIES):
|
return await ping_miner(ip)
|
||||||
connection_fut = asyncio.open_connection(str(ip), 4028)
|
|
||||||
try:
|
|
||||||
# get the read and write streams from the connection
|
async def ping_miner(ip: ipaddress.ip_address, port=4028) -> None or ipaddress.ip_address:
|
||||||
reader, writer = await asyncio.wait_for(connection_fut, timeout=PING_TIMEOUT)
|
for i in range(PING_RETRIES):
|
||||||
# immediately close connection, we know connection happened
|
connection_fut = asyncio.open_connection(str(ip), port)
|
||||||
writer.close()
|
try:
|
||||||
# make sure the writer is closed
|
# get the read and write streams from the connection
|
||||||
await writer.wait_closed()
|
reader, writer = await asyncio.wait_for(connection_fut, timeout=PING_TIMEOUT)
|
||||||
# ping was successful
|
# immediately close connection, we know connection happened
|
||||||
return ip
|
writer.close()
|
||||||
except asyncio.exceptions.TimeoutError:
|
# make sure the writer is closed
|
||||||
# ping failed if we time out
|
await writer.wait_closed()
|
||||||
continue
|
# ping was successful
|
||||||
except ConnectionRefusedError:
|
return ip
|
||||||
# handle for other connection errors
|
except asyncio.exceptions.TimeoutError:
|
||||||
print(f"{str(ip)}: Connection Refused.")
|
# ping failed if we time out
|
||||||
# ping failed, likely with an exception
|
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
continue
|
continue
|
||||||
return
|
except ConnectionRefusedError:
|
||||||
|
# handle for other connection errors
|
||||||
|
print(f"{str(ip)}: Connection Refused.")
|
||||||
|
# ping failed, likely with an exception
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
continue
|
||||||
|
return
|
||||||
|
|||||||
191
tools/web_testbench/__init__.py
Normal file
191
tools/web_testbench/__init__.py
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
from ipaddress import ip_address
|
||||||
|
import asyncio
|
||||||
|
import os
|
||||||
|
|
||||||
|
from network import ping_miner
|
||||||
|
from network.net_range import MinerNetworkRange
|
||||||
|
from miners.miner_factory import MinerFactory
|
||||||
|
from miners.antminer.S9.bosminer import BOSMinerS9
|
||||||
|
|
||||||
|
miner_network = MinerNetworkRange("192.168.1.1-192.168.1.38")
|
||||||
|
|
||||||
|
REFERRAL_FILE_S9 = os.path.join(os.path.dirname(__file__), "files", "referral.ipk")
|
||||||
|
UPDATE_FILE_S9 = os.path.join(os.path.dirname(__file__), "files", "update.tar")
|
||||||
|
CONFIG_FILE = os.path.join(os.path.dirname(__file__), "files", "config.toml")
|
||||||
|
|
||||||
|
|
||||||
|
# static states
|
||||||
|
(
|
||||||
|
START,
|
||||||
|
UNLOCK,
|
||||||
|
INSTALL,
|
||||||
|
UPDATE,
|
||||||
|
REFERRAL,
|
||||||
|
DONE
|
||||||
|
) = range(6)
|
||||||
|
|
||||||
|
|
||||||
|
class testbenchMiner():
|
||||||
|
def __init__(self, host: ip_address):
|
||||||
|
self.host = host
|
||||||
|
self.state = START
|
||||||
|
|
||||||
|
async def add_to_output(self, message):
|
||||||
|
# send a message to web server
|
||||||
|
return
|
||||||
|
|
||||||
|
async def remove_from_cache(self):
|
||||||
|
if self.host in MinerFactory().miners.keys():
|
||||||
|
MinerFactory().miners.remove(self.host)
|
||||||
|
|
||||||
|
async def wait_for_disconnect(self):
|
||||||
|
while await ping_miner(self.host):
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
async def install_start(self):
|
||||||
|
if not await ping_miner(self.host):
|
||||||
|
return
|
||||||
|
await self.remove_from_cache()
|
||||||
|
miner = MinerFactory().get_miner(self.host)
|
||||||
|
if isinstance(miner, BOSMinerS9):
|
||||||
|
self.state = UPDATE
|
||||||
|
return
|
||||||
|
if await ping_miner(self.host, 22):
|
||||||
|
self.state = INSTALL
|
||||||
|
return
|
||||||
|
self.state = UNLOCK
|
||||||
|
|
||||||
|
async def install_unlock(self):
|
||||||
|
if await self.ssh_unlock():
|
||||||
|
self.state = INSTALL
|
||||||
|
return
|
||||||
|
self.state = START
|
||||||
|
await self.wait_for_disconnect()
|
||||||
|
|
||||||
|
async def ssh_unlock(self):
|
||||||
|
proc = await asyncio.create_subprocess_shell(
|
||||||
|
f'{os.path.join(os.path.dirname(__file__), "files", "asicseer_installer.exe")} -p -f {str(self.host)} root',
|
||||||
|
stdout=asyncio.subprocess.PIPE,
|
||||||
|
stderr=asyncio.subprocess.PIPE)
|
||||||
|
stdout, stderr = await proc.communicate()
|
||||||
|
if str(stdout).find("webUI") != -1:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def do_install(self):
|
||||||
|
proc = await asyncio.create_subprocess_shell(
|
||||||
|
f'{os.path.join(os.path.dirname(__file__), "files", "bos-toolbox", "bos-toolbox.bat")} install {str(self.host)} --no-keep-pools --psu-power-limit 900 --no-nand-backup --feeds-url file:./feeds/',
|
||||||
|
stdout=asyncio.subprocess.PIPE,
|
||||||
|
stderr=asyncio.subprocess.PIPE)
|
||||||
|
# get stdout of the install
|
||||||
|
while True:
|
||||||
|
stdout = await proc.stderr.readuntil(b'\r')
|
||||||
|
if stdout == b'':
|
||||||
|
break
|
||||||
|
await proc.wait()
|
||||||
|
while not await ping_miner(self.host):
|
||||||
|
await asyncio.sleep(3)
|
||||||
|
await asyncio.sleep(5)
|
||||||
|
self.state = REFERRAL
|
||||||
|
|
||||||
|
async def install_update(self):
|
||||||
|
await self.remove_from_cache()
|
||||||
|
miner = await MinerFactory().get_miner(self.host)
|
||||||
|
try:
|
||||||
|
await miner.send_file(UPDATE_FILE_S9, "/tmp/firmware.tar")
|
||||||
|
await miner.send_ssh_command("sysupgrade /tmp/firmware.tar")
|
||||||
|
except:
|
||||||
|
self.state = START
|
||||||
|
return
|
||||||
|
self.state = REFERRAL
|
||||||
|
|
||||||
|
async def install_referral(self):
|
||||||
|
miner = await MinerFactory().get_miner(self.host)
|
||||||
|
if os.path.exists(REFERRAL_FILE_S9):
|
||||||
|
try:
|
||||||
|
await miner.send_file(REFERRAL_FILE_S9, '/tmp/referral.ipk')
|
||||||
|
await miner.send_file(CONFIG_FILE, '/etc/bosminer.toml')
|
||||||
|
|
||||||
|
await miner.send_ssh_command('opkg install /tmp/referral.ipk && /etc/init.d/bosminer restart')
|
||||||
|
except:
|
||||||
|
self.state = START
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.state = START
|
||||||
|
return
|
||||||
|
self.state = DONE
|
||||||
|
|
||||||
|
async def get_web_data(self):
|
||||||
|
miner = await MinerFactory().get_miner(self.host)
|
||||||
|
|
||||||
|
if not isinstance(miner, BOSMinerS9):
|
||||||
|
self.state = START
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
all_data = await miner.api.multicommand("devs", "temps", "fans")
|
||||||
|
|
||||||
|
devs_raw = all_data['devs'][0]
|
||||||
|
temps_raw = all_data['temps'][0]
|
||||||
|
fans_raw = all_data['fans'][0]
|
||||||
|
|
||||||
|
# parse temperature data
|
||||||
|
temps_data = {}
|
||||||
|
for board in range(len(temps_raw['TEMPS'])):
|
||||||
|
temps_data[f"board_{temps_raw['TEMPS'][board]['ID']}"] = {}
|
||||||
|
temps_data[f"board_{temps_raw['TEMPS'][board]['ID']}"]["Board"] = temps_raw['TEMPS'][board]['Board']
|
||||||
|
temps_data[f"board_{temps_raw['TEMPS'][board]['ID']}"]["Chip"] = temps_raw['TEMPS'][board]['Chip']
|
||||||
|
|
||||||
|
# parse individual board and chip temperature data
|
||||||
|
for board in temps_data.keys():
|
||||||
|
if "Board" not in temps_data[board].keys():
|
||||||
|
temps_data[board]["Board"] = 0
|
||||||
|
if "Chip" not in temps_data[board].keys():
|
||||||
|
temps_data[board]["Chip"] = 0
|
||||||
|
|
||||||
|
# parse hashrate data
|
||||||
|
hr_data = {}
|
||||||
|
for board in range(len(devs_raw['DEVS'])):
|
||||||
|
hr_data[f"board_{devs_raw['DEVS'][board]['ID']}"] = {}
|
||||||
|
hr_data[f"board_{devs_raw['DEVS'][board]['ID']}"]["HR"] = round(
|
||||||
|
devs_raw['DEVS'][board]['MHS 5s'] / 1000000,
|
||||||
|
2)
|
||||||
|
|
||||||
|
# parse fan data
|
||||||
|
fans_data = {}
|
||||||
|
for fan in range(len(fans_raw['FANS'])):
|
||||||
|
fans_data[f"fan_{fans_raw['FANS'][fan]['ID']}"] = {}
|
||||||
|
fans_data[f"fan_{fans_raw['FANS'][fan]['ID']}"]['RPM'] = fans_raw['FANS'][fan]['RPM']
|
||||||
|
|
||||||
|
# set the miner data
|
||||||
|
miner_data = {
|
||||||
|
'IP': self.host,
|
||||||
|
"Light": "show",
|
||||||
|
'Fans': fans_data,
|
||||||
|
'HR': hr_data,
|
||||||
|
'Temps': temps_data
|
||||||
|
}
|
||||||
|
|
||||||
|
# return stats
|
||||||
|
return miner_data
|
||||||
|
except:
|
||||||
|
return
|
||||||
|
|
||||||
|
async def install_done(self):
|
||||||
|
while await ping_miner(self.host) and self.state == DONE:
|
||||||
|
print(await self.get_web_data())
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
async def install_loop(self):
|
||||||
|
while True:
|
||||||
|
if self.state == START:
|
||||||
|
await self.install_start()
|
||||||
|
if self.state == UNLOCK:
|
||||||
|
await self.install_unlock()
|
||||||
|
if self.state == INSTALL:
|
||||||
|
await self.do_install()
|
||||||
|
if self.state == UPDATE:
|
||||||
|
await self.install_update()
|
||||||
|
if self.state == REFERRAL:
|
||||||
|
await self.install_referral()
|
||||||
|
if self.state == DONE:
|
||||||
|
await self.install_done()
|
||||||
Reference in New Issue
Block a user