import requests import nomad_client import re def parse_litefs_status(output): """ Parses the output of 'litefs status'. """ status = {} # Extract Primary primary_match = re.search(r"Primary:\s+(true|false)", output, re.IGNORECASE) if primary_match: status["is_primary"] = primary_match.group(1).lower() == "true" # Extract Uptime uptime_match = re.search(r"Uptime:\s+(\S+)", output) if uptime_match: status["uptime"] = uptime_match.group(1) # Extract Replication Lag lag_match = re.search(r"Replication Lag:\s+(\S+)", output) if lag_match: status["replication_lag"] = lag_match.group(1) return status def get_node_status(node_address, port=20202, alloc_id=None): """ Queries the LiteFS HTTP API on a specific node for its status. Tries /status first, then /debug/vars, then falls back to nomad alloc exec. """ # 1. Try /status url = f"http://{node_address}:{port}/status" try: response = requests.get(url, timeout=3) if response.status_code == 200: data = response.json() status = { "is_primary": data.get("primary", False), "uptime": data.get("uptime", 0), "advertise_url": data.get("advertiseURL", ""), "dbs": data.get("dbs", {}) } if "replicationLag" in data: status["replication_lag"] = data["replicationLag"] if "primaryURL" in data: status["primary_url"] = data["primaryURL"] return status except Exception: pass # 2. Try /debug/vars url = f"http://{node_address}:{port}/debug/vars" try: response = requests.get(url, timeout=3) if response.status_code == 200: data = response.json() store = data.get("store", {}) status = { "is_primary": store.get("isPrimary", False), "candidate": store.get("candidate", False), "uptime": "N/A", # Will be filled by Nomad uptime "advertise_url": f"http://{node_address}:{port}", "dbs": store.get("dbs", {}) } if "replicationLag" in store: status["replication_lag"] = store["replicationLag"] return status except Exception: pass # 3. Fallback to nomad alloc exec if alloc_id: try: output = nomad_client.exec_command(alloc_id, ["litefs", "status"]) if output and "Error" not in output: parsed_status = parse_litefs_status(output) if parsed_status: if "is_primary" not in parsed_status: parsed_status["is_primary"] = False if "uptime" not in parsed_status: parsed_status["uptime"] = "N/A" parsed_status["advertise_url"] = f"nomad://{alloc_id}" return parsed_status except Exception: pass return { "error": "All status retrieval methods failed", "is_primary": False, "uptime": "N/A" }