Compare commits

...

18 Commits

Author SHA1 Message Date
empresa 87a7265edc Wallet config debugging. More. 2025-09-10 00:44:15 +07:00
empresa b109094683 Wallet config debugging. More. 2025-09-10 00:35:47 +07:00
empresa f5f247dcd8 Wallet config debugging. More. 2025-09-10 00:20:09 +07:00
empresa 9e684062f9 Wallet config debugging. More. 2025-09-10 00:13:58 +07:00
empresa 9ccd0aba8a Wallet config debugging. More. 2025-09-10 00:11:15 +07:00
empresa 7ff426f9ba Wallet config debugging. More. 2025-09-09 23:55:30 +07:00
empresa 07134d26d7 Wallet config debugging. More. 2025-09-09 22:13:52 +07:00
empresa a60adedafd Wallet config debugging. More. 2025-09-09 19:07:15 +07:00
empresa 2263d293c8 Wallet config debugging. More. 2025-09-09 19:02:46 +07:00
empresa 4953ffe965 Wallet config debugging. More. 2025-09-09 18:58:54 +07:00
empresa de683b989e Wallet config debugging. More. 2025-09-09 18:58:01 +07:00
empresa cfba5d729d Wallet config debugging. More. 2025-09-09 18:53:53 +07:00
empresa 9a36cf99bf Wallet config debugging. More. 2025-09-09 18:52:54 +07:00
empresa 90a76735e2 Wallet config debugging. More. 2025-09-09 18:49:22 +07:00
empresa b74bb34f40 Wallet config debugging. More. 2025-09-09 18:40:59 +07:00
empresa b3502c8778 Wallet config debugging. Part 3. 2025-09-09 18:38:45 +07:00
empresa 92dac6755b Wallet config debugging. Part 2. 2025-09-09 18:37:18 +07:00
empresa 6fc2ac9b93 Wallet config debugging. 2025-09-09 18:33:23 +07:00
1 changed files with 60 additions and 7 deletions

View File

@ -11,6 +11,7 @@ import re
import os import os
import socket import socket
import asyncio import asyncio
import traceback
from urllib.parse import urlparse from urllib.parse import urlparse
import subprocess import subprocess
from functools import partial from functools import partial
@ -20,22 +21,34 @@ class logger:
GREEN = '\033[92m' GREEN = '\033[92m'
BLUE = '\033[94m' BLUE = '\033[94m'
RESET = '\033[0m' RESET = '\033[0m'
LOG_FILE = '/opt/clore-hosting/clore_onboarding.log'
@staticmethod @staticmethod
def _get_current_time(): def _get_current_time():
return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
@staticmethod
def _log_to_file(level, message):
try:
with open(logger.LOG_FILE, 'a') as f:
f.write(f"{logger._get_current_time()} | {level} | {message}\n")
except Exception:
pass
@staticmethod @staticmethod
def error(message): def error(message):
print(f"{logger.RED}{logger._get_current_time()} | ERROR | {message}{logger.RESET}") print(f"{logger.RED}{logger._get_current_time()} | ERROR | {message}{logger.RESET}")
logger._log_to_file("ERROR", message)
@staticmethod @staticmethod
def success(message): def success(message):
print(f"{logger.GREEN}{logger._get_current_time()} | SUCCESS | {message}{logger.RESET}") print(f"{logger.GREEN}{logger._get_current_time()} | SUCCESS | {message}{logger.RESET}")
logger._log_to_file("SUCCESS", message)
@staticmethod @staticmethod
def info(message): def info(message):
print(f"{logger.BLUE}{logger._get_current_time()} | INFO | {message}{logger.RESET}") print(f"{logger.BLUE}{logger._get_current_time()} | INFO | {message}{logger.RESET}")
logger._log_to_file("INFO", message)
if os.geteuid() != 0: if os.geteuid() != 0:
logger.error("This script must be run as root!") logger.error("This script must be run as root!")
@ -89,7 +102,7 @@ def validate_clore_config(clore_config):
1 <= value["on_demand_multiplier"] <= 50 and 1 <= value["spot_multiplier"] <= 50 1 <= value["on_demand_multiplier"] <= 50 and 1 <= value["spot_multiplier"] <= 50
def is_valid_mrl(value): def is_valid_mrl(value):
return isinstance(value, int) and 6 <= value <= 1440 return isinstance(value, int) and 6 <= value <= 3000
def is_valid_keep_params(value): def is_valid_keep_params(value):
return isinstance(value, bool) return isinstance(value, bool)
@ -98,9 +111,9 @@ def validate_clore_config(clore_config):
required_keys = {"on_demand_bitcoin", "on_demand_clore", "spot_bitcoin", "spot_clore"} required_keys = {"on_demand_bitcoin", "on_demand_clore", "spot_bitcoin", "spot_clore"}
if required_keys.issubset(clore_config): if required_keys.issubset(clore_config):
return 0.000001 <= clore_config["on_demand_bitcoin"] <= 0.005 and \ return 0.000001 <= clore_config["on_demand_bitcoin"] <= 0.005 and \
0.1 <= clore_config["on_demand_clore"] <= 5000 and \ 0.1 <= clore_config["on_demand_clore"] <= 10000 and \
0.000001 <= clore_config["spot_bitcoin"] <= 0.005 and \ 0.000001 <= clore_config["spot_bitcoin"] <= 0.005 and \
0.1 <= clore_config["spot_clore"] <= 5000 0.1 <= clore_config["spot_clore"] <= 10000
return False return False
def is_valid_usd_pricing(autoprice): def is_valid_usd_pricing(autoprice):
@ -126,7 +139,7 @@ def validate_clore_config(clore_config):
errors.append("multipliers are not following spec") errors.append("multipliers are not following spec")
if "mrl" not in clore_config or not is_valid_mrl(clore_config["mrl"]): if "mrl" not in clore_config or not is_valid_mrl(clore_config["mrl"]):
errors.append("mrl is mandatory and must be an integer in range 6-1440") errors.append("mrl is mandatory and must be an integer in range 6-3000")
if "keep_params" in clore_config and not is_valid_keep_params(clore_config["keep_params"]): if "keep_params" in clore_config and not is_valid_keep_params(clore_config["keep_params"]):
errors.append("keep_params must be a boolean value") errors.append("keep_params must be a boolean value")
@ -257,6 +270,20 @@ async def hive_load_configs(default_power_limits, static_config):
clore_config = possible_clore_config clore_config = possible_clore_config
elif key == "CUSTOM_MINER" and value == "clore": elif key == "CUSTOM_MINER" and value == "clore":
clore_miner_present = True clore_miner_present = True
elif key == "CLORE_RENTALS_TOKEN":
possible_clore_config = base64_string_to_json(value)
if possible_clore_config:
clore_config = possible_clore_config
elif key == "META":
try:
meta_value = json.loads(value)
if (isinstance(meta_value, dict) and
"clore-rentals" in meta_value and
isinstance(meta_value["clore-rentals"], dict) and
meta_value["clore-rentals"].get("coin") == "CLORE-Rentals"):
clore_miner_present = True
except (json.JSONDecodeError, TypeError, KeyError) as e:
pass
if (not clore_miner_present or not clore_config) and parsed_static_config: if (not clore_miner_present or not clore_config) and parsed_static_config:
clore_miner_present = True clore_miner_present = True
@ -368,7 +395,13 @@ async def post_request(url, body, headers=None, timeout=15):
return status_code, response_data return status_code, response_data
except (http.client.HTTPException, TimeoutError) as e: except (http.client.HTTPException, TimeoutError) as e:
print(f"Request failed: {e}") logger.error(f"Request failed: {e}")
return None, None
except socket.gaierror as e:
logger.error(f"DNS resolution failed for {url}: {e}")
return None, None
except Exception as e:
logger.error(f"Unexpected error in post_request: {e}")
return None, None return None, None
finally: finally:
conn.close() conn.close()
@ -425,8 +458,11 @@ if args.write_linux_config:
sys.exit(1) sys.exit(1)
async def main(machine_specs): async def main(machine_specs):
logger.info("Started onboarding")
global next_retry_reached_server_limit global next_retry_reached_server_limit
last_used_config = None last_used_config = None
logger.info("logger.info(last_used_config) 1")
logger.info(last_used_config)
ever_pending_creation = False ever_pending_creation = False
machine_id = get_machine_id() machine_id = get_machine_id()
@ -440,9 +476,13 @@ async def main(machine_specs):
logger.error("Can't load default power limits of nVidia GPU(s)") logger.error("Can't load default power limits of nVidia GPU(s)")
sys.exit(1) sys.exit(1)
logger.info("logger.info(last_used_config) 2")
logger.info(last_used_config)
oc_config = {} oc_config = {}
while True: while True:
try: try:
logger.info("Looping")
if args.mode == "linux": if args.mode == "linux":
clore_config = await async_read_file(clore_conf_path) clore_config = await async_read_file(clore_conf_path)
clore_config = json.loads(clore_config) clore_config = json.loads(clore_config)
@ -452,7 +492,10 @@ async def main(machine_specs):
machine_name, clore_config, oc_config = await hive_load_configs(default_power_limits, static_clore_config) machine_name, clore_config, oc_config = await hive_load_configs(default_power_limits, static_clore_config)
#print(f"Machine Name: {machine_name}") #print(f"Machine Name: {machine_name}")
logger.info(args.mode)
config_validation = validate_clore_config(clore_config) config_validation = validate_clore_config(clore_config)
if config_validation == "Validation successful": if config_validation == "Validation successful":
if "save_config" in clore_config and args.mode == "hive": if "save_config" in clore_config and args.mode == "hive":
verify_or_update_file(clore_conf_path, json.dumps(clore_config)) verify_or_update_file(clore_conf_path, json.dumps(clore_config))
@ -461,6 +504,12 @@ async def main(machine_specs):
clore_config["clear_oc_override"] = True clore_config["clear_oc_override"] = True
else: else:
clore_config["stock_oc_override"] = oc_config clore_config["stock_oc_override"] = oc_config
logger.info("Is config different")
logger.info(clore_config != last_used_config)
logger.info(clore_config)
logger.info(last_used_config)
if clore_config != last_used_config or (time.time() > next_retry_reached_server_limit and next_retry_reached_server_limit > 0): if clore_config != last_used_config or (time.time() > next_retry_reached_server_limit and next_retry_reached_server_limit > 0):
last_used_config = clore_config.copy() last_used_config = clore_config.copy()
if type(clore_config) == dict and "hostname_override" in clore_config: if type(clore_config) == dict and "hostname_override" in clore_config:
@ -490,7 +539,7 @@ async def main(machine_specs):
await asyncio.sleep(60 if ever_pending_creation else 10) await asyncio.sleep(60 if ever_pending_creation else 10)
ever_pending_creation = True ever_pending_creation = True
last_used_config = None last_used_config = None
elif "init_communication_token" in response_data and "private_communication_token": elif "init_communication_token" in response_data and "private_communication_token" in response_data:
clore_hosting_sw_auth_str = f"{response_data['init_communication_token']}:{response_data['private_communication_token']}" clore_hosting_sw_auth_str = f"{response_data['init_communication_token']}:{response_data['private_communication_token']}"
was_ok = verify_or_update_file(args.auth_file, clore_hosting_sw_auth_str) was_ok = verify_or_update_file(args.auth_file, clore_hosting_sw_auth_str)
if was_ok: if was_ok:
@ -507,9 +556,13 @@ async def main(machine_specs):
logger.error(f"Could not parse config - {' | '.join(config_validation)}") logger.error(f"Could not parse config - {' | '.join(config_validation)}")
except Exception as e: except Exception as e:
print(e) logger.error(f"Exception: {e}")
logger.error(f"Traceback: {traceback.format_exc()}")
await asyncio.sleep(5) await asyncio.sleep(5)
logger.info("logger.info(last_used_config) 3")
logger.info(last_used_config)
if __name__ == "__main__": if __name__ == "__main__":
machine_specs = specs.get(benchmark_disk=True, mock=args.mock) machine_specs = specs.get(benchmark_disk=True, mock=args.mock)
asyncio.run(main(machine_specs)) asyncio.run(main(machine_specs))