feature: add so_linger option to settings.
This commit is contained in:
@@ -13,8 +13,6 @@
|
||||
# See the License for the specific language governing permissions and -
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
import asyncio
|
||||
import enum
|
||||
import ipaddress
|
||||
@@ -25,6 +23,7 @@ from typing import AsyncGenerator, Callable, List, Optional, Tuple, Union
|
||||
import anyio
|
||||
import httpx
|
||||
|
||||
from pyasic import settings
|
||||
from pyasic.logger import logger
|
||||
from pyasic.miners.antminer import *
|
||||
from pyasic.miners.avalonminer import *
|
||||
@@ -45,8 +44,6 @@ from pyasic.miners.innosilicon import *
|
||||
from pyasic.miners.unknown import UnknownMiner
|
||||
from pyasic.miners.whatsminer import *
|
||||
|
||||
from pyasic import settings
|
||||
|
||||
|
||||
class MinerTypes(enum.Enum):
|
||||
ANTMINER = 0
|
||||
@@ -479,11 +476,15 @@ class MinerFactory:
|
||||
|
||||
async def _get_miner_web(self, ip: str):
|
||||
urls = [f"http://{ip}/", f"https://{ip}/"]
|
||||
async with httpx.AsyncClient(verify=False) as session:
|
||||
async with httpx.AsyncClient(
|
||||
transport=settings.transport(verify=False)
|
||||
) as session:
|
||||
tasks = [asyncio.create_task(self._web_ping(session, url)) for url in urls]
|
||||
|
||||
text, resp = await concurrent_get_first_result(
|
||||
tasks, lambda x: x[0] is not None and self._parse_web_type(x[0], x[1]) is not None
|
||||
tasks,
|
||||
lambda x: x[0] is not None
|
||||
and self._parse_web_type(x[0], x[1]) is not None,
|
||||
)
|
||||
if text is not None:
|
||||
return self._parse_web_type(text, resp)
|
||||
@@ -612,7 +613,7 @@ class MinerFactory:
|
||||
location: str,
|
||||
auth: Optional[httpx.DigestAuth] = None,
|
||||
) -> Optional[dict]:
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as session:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as session:
|
||||
try:
|
||||
data = await session.get(
|
||||
f"http://{str(ip)}{location}",
|
||||
@@ -808,7 +809,7 @@ class MinerFactory:
|
||||
|
||||
async def get_miner_model_innosilicon(self, ip: str) -> Optional[str]:
|
||||
try:
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as session:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as session:
|
||||
auth_req = await session.post(
|
||||
f"http://{ip}/api/auth",
|
||||
data={"username": "admin", "password": "admin"},
|
||||
@@ -838,7 +839,7 @@ class MinerFactory:
|
||||
pass
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as session:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as session:
|
||||
d = await session.post(
|
||||
f"http://{ip}/graphql",
|
||||
json={"query": "{bosminer {info{modelName}}}"},
|
||||
|
||||
@@ -45,7 +45,7 @@ class MinerNetwork:
|
||||
"""
|
||||
hosts = []
|
||||
for address in addresses:
|
||||
hosts = [*hosts, *cls.from_address(address)]
|
||||
hosts = [*hosts, *cls.from_address(address).hosts]
|
||||
return cls(sorted(list(set(hosts))))
|
||||
|
||||
@classmethod
|
||||
@@ -63,7 +63,9 @@ class MinerNetwork:
|
||||
return cls.from_octets(*octets)
|
||||
|
||||
@classmethod
|
||||
def from_octets(cls, oct_1: str, oct_2: str, oct_3: str, oct_4: str) -> "MinerNetwork":
|
||||
def from_octets(
|
||||
cls, oct_1: str, oct_2: str, oct_3: str, oct_4: str
|
||||
) -> "MinerNetwork":
|
||||
"""Parse 4 octet constructors into a MinerNetwork.
|
||||
|
||||
Parameters:
|
||||
@@ -167,7 +169,9 @@ class MinerNetwork:
|
||||
try:
|
||||
return await ping_and_get_miner(ip)
|
||||
except ConnectionRefusedError:
|
||||
tasks = [ping_and_get_miner(ip, port=port) for port in [4028, 4029, 8889]]
|
||||
tasks = [
|
||||
ping_and_get_miner(ip, port=port) for port in [4028, 4029, 8889]
|
||||
]
|
||||
for miner in asyncio.as_completed(tasks):
|
||||
try:
|
||||
return await miner
|
||||
|
||||
@@ -13,10 +13,13 @@
|
||||
# See the License for the specific language governing permissions and -
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
from typing import Any
|
||||
import socket
|
||||
import struct
|
||||
from ssl import SSLContext
|
||||
from typing import Any, Union
|
||||
|
||||
import httpx
|
||||
from httpx import AsyncHTTPTransport
|
||||
|
||||
_settings = { # defaults
|
||||
"network_ping_retries": 1,
|
||||
@@ -32,14 +35,25 @@ _settings = { # defaults
|
||||
"default_bosminer_password": "root",
|
||||
"default_vnish_password": "admin",
|
||||
"default_goldshell_password": "123456789",
|
||||
"so_linger_time": 1000,
|
||||
}
|
||||
|
||||
|
||||
ssl_cxt = httpx.create_ssl_context()
|
||||
|
||||
|
||||
def transport(verify: Union[str, bool, SSLContext] = ssl_cxt):
|
||||
l_onoff = 1
|
||||
l_linger = get("so_linger_time", 1000)
|
||||
|
||||
opts = [(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack("ii", l_onoff, l_linger))]
|
||||
|
||||
return AsyncHTTPTransport(socket_options=opts, verify=verify)
|
||||
|
||||
|
||||
def get(key: str, other: Any = None) -> Any:
|
||||
return _settings.get(key, other)
|
||||
|
||||
|
||||
def update(key: str, val: Any) -> Any:
|
||||
_settings[key] = val
|
||||
|
||||
ssl_cxt = httpx.create_ssl_context()
|
||||
@@ -38,10 +38,13 @@ class AntminerModernWebAPI(BaseWebAPI):
|
||||
url = f"http://{self.ip}/cgi-bin/{command}.cgi"
|
||||
auth = httpx.DigestAuth(self.username, self.pwd)
|
||||
try:
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as client:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
if parameters:
|
||||
data = await client.post(
|
||||
url, data=json.dumps(parameters), auth=auth, timeout=settings.get("api_function_timeout", 3) # noqa
|
||||
url,
|
||||
data=json.dumps(parameters),
|
||||
auth=auth,
|
||||
timeout=settings.get("api_function_timeout", 3), # noqa
|
||||
)
|
||||
else:
|
||||
data = await client.get(url, auth=auth)
|
||||
@@ -57,7 +60,7 @@ class AntminerModernWebAPI(BaseWebAPI):
|
||||
async def multicommand(
|
||||
self, *commands: str, ignore_errors: bool = False, allow_warning: bool = True
|
||||
) -> dict:
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as client:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
tasks = [
|
||||
asyncio.create_task(self._handle_multicommand(client, command))
|
||||
for command in commands
|
||||
@@ -149,10 +152,13 @@ class AntminerOldWebAPI(BaseWebAPI):
|
||||
url = f"http://{self.ip}/cgi-bin/{command}.cgi"
|
||||
auth = httpx.DigestAuth(self.username, self.pwd)
|
||||
try:
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as client:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
if parameters:
|
||||
data = await client.post(
|
||||
url, data=parameters, auth=auth, timeout=settings.get("api_function_timeout", 3)
|
||||
url,
|
||||
data=parameters,
|
||||
auth=auth,
|
||||
timeout=settings.get("api_function_timeout", 3),
|
||||
)
|
||||
else:
|
||||
data = await client.get(url, auth=auth)
|
||||
@@ -170,7 +176,7 @@ class AntminerOldWebAPI(BaseWebAPI):
|
||||
) -> dict:
|
||||
data = {k: None for k in commands}
|
||||
auth = httpx.DigestAuth(self.username, self.pwd)
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as client:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
for command in commands:
|
||||
try:
|
||||
url = f"http://{self.ip}/cgi-bin/{command}.cgi"
|
||||
|
||||
@@ -186,7 +186,7 @@ class BOSMinerGQLAPI:
|
||||
if command.get("query") is None:
|
||||
query = {"query": self.parse_command(command)}
|
||||
try:
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as client:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
await self.auth(client)
|
||||
data = await client.post(url, json=query)
|
||||
except httpx.HTTPError:
|
||||
@@ -239,7 +239,7 @@ class BOSMinerLuCIAPI:
|
||||
|
||||
async def send_command(self, path: str, ignore_errors: bool = False) -> dict:
|
||||
try:
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as client:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
await self.auth(client)
|
||||
data = await client.get(
|
||||
f"http://{self.ip}{path}", headers={"User-Agent": "BTC Tools v0.1"}
|
||||
|
||||
@@ -31,7 +31,7 @@ class GoldshellWebAPI(BaseWebAPI):
|
||||
self.jwt = None
|
||||
|
||||
async def auth(self):
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as client:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
try:
|
||||
await client.get(f"http://{self.ip}/user/logout")
|
||||
auth = (
|
||||
@@ -71,7 +71,7 @@ class GoldshellWebAPI(BaseWebAPI):
|
||||
parameters.pop("pool_pwd")
|
||||
if not self.jwt:
|
||||
await self.auth()
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as client:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
for i in range(settings.get("get_data_retries", 1)):
|
||||
try:
|
||||
if parameters:
|
||||
@@ -102,7 +102,7 @@ class GoldshellWebAPI(BaseWebAPI):
|
||||
data = {k: None for k in commands}
|
||||
data["multicommand"] = True
|
||||
await self.auth()
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as client:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
for command in commands:
|
||||
try:
|
||||
response = await client.get(
|
||||
|
||||
@@ -32,7 +32,7 @@ class InnosiliconWebAPI(BaseWebAPI):
|
||||
self.jwt = None
|
||||
|
||||
async def auth(self):
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as client:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
try:
|
||||
auth = await client.post(
|
||||
f"http://{self.ip}/api/auth",
|
||||
@@ -54,7 +54,7 @@ class InnosiliconWebAPI(BaseWebAPI):
|
||||
) -> dict:
|
||||
if not self.jwt:
|
||||
await self.auth()
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as client:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
for i in range(settings.get("get_data_retries", 1)):
|
||||
try:
|
||||
response = await client.post(
|
||||
@@ -90,7 +90,7 @@ class InnosiliconWebAPI(BaseWebAPI):
|
||||
data = {k: None for k in commands}
|
||||
data["multicommand"] = True
|
||||
await self.auth()
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as client:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
for command in commands:
|
||||
try:
|
||||
response = await client.post(
|
||||
|
||||
@@ -31,7 +31,7 @@ class VNishWebAPI(BaseWebAPI):
|
||||
self.token = None
|
||||
|
||||
async def auth(self):
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as client:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
try:
|
||||
auth = await client.post(
|
||||
f"http://{self.ip}/api/v1/unlock",
|
||||
@@ -58,7 +58,7 @@ class VNishWebAPI(BaseWebAPI):
|
||||
) -> dict:
|
||||
if not self.token:
|
||||
await self.auth()
|
||||
async with httpx.AsyncClient(verify=settings.ssl_cxt) as client:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
for i in range(settings.get("get_data_retries", 1)):
|
||||
try:
|
||||
auth = self.token
|
||||
|
||||
@@ -9,9 +9,9 @@ readme = "README.md"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.8"
|
||||
httpx = "^0.25.0"
|
||||
httpx = "^0.25.2"
|
||||
asyncssh = "^2.14.1"
|
||||
grpc-requests = "^0.1.11"
|
||||
grpc-requests = "^0.1.12"
|
||||
passlib = "^1.7.4"
|
||||
pyaml = "^23.9.7"
|
||||
toml = "^0.10.2"
|
||||
|
||||
@@ -22,7 +22,7 @@ from pyasic.network import MinerNetwork
|
||||
|
||||
class NetworkTest(unittest.TestCase):
|
||||
def test_net_range(self):
|
||||
net_range_str = "192.168.1.29, 192.168.1.40-192.168.1.43, 192.168.1.60"
|
||||
net_range_str = ["192.168.1.29", "192.168.1.40-43", "192.168.1.60"]
|
||||
net_range_list = [
|
||||
"192.168.1.29",
|
||||
"192.168.1.40",
|
||||
@@ -32,8 +32,8 @@ class NetworkTest(unittest.TestCase):
|
||||
"192.168.1.60",
|
||||
]
|
||||
|
||||
net_1 = list(MinerNetwork(net_range_str).get_network().hosts())
|
||||
net_2 = list(MinerNetwork(net_range_list).get_network().hosts())
|
||||
net_1 = list(MinerNetwork.from_list(net_range_list).hosts)
|
||||
net_2 = list(MinerNetwork.from_list(net_range_str).hosts)
|
||||
|
||||
correct_net = [
|
||||
ipaddress.IPv4Address("192.168.1.29"),
|
||||
@@ -51,11 +51,9 @@ class NetworkTest(unittest.TestCase):
|
||||
net_1_str = "192.168.1.0"
|
||||
net_1_mask = "/29"
|
||||
|
||||
net_1 = list(MinerNetwork(net_1_str, mask=net_1_mask).get_network().hosts())
|
||||
net_1 = list(MinerNetwork.from_subnet(net_1_str + net_1_mask).hosts)
|
||||
|
||||
net_2 = list(
|
||||
MinerNetwork("192.168.1.1-192.168.1.5, 192.168.1.6").get_network().hosts()
|
||||
)
|
||||
net_2 = list(MinerNetwork.from_list(["192.168.1.1-5", "192.168.1.6"]).hosts)
|
||||
|
||||
correct_net = [
|
||||
ipaddress.IPv4Address("192.168.1.1"),
|
||||
@@ -70,11 +68,10 @@ class NetworkTest(unittest.TestCase):
|
||||
self.assertTrue(net_2 == correct_net)
|
||||
|
||||
def test_net_defaults(self):
|
||||
net = MinerNetwork()
|
||||
net_obj = net.get_network()
|
||||
self.assertEqual(net_obj, MinerNetwork("192.168.1.0", mask=24).get_network())
|
||||
|
||||
self.assertEqual(net_obj, net.get_network())
|
||||
net = MinerNetwork.from_subnet("192.168.1.1/24")
|
||||
self.assertEqual(
|
||||
net.hosts, list(ipaddress.ip_network("192.168.1.0/24").hosts())
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user