import ctrl.db as db import ctrl.settings as settings import requests def parse_worker(spec): """'host:port' -> {'url': 'http://host:port', 'host': host, 'port': port}.""" host, _, port = spec.strip().rpartition(":") if not host or not port.isdigit(): raise ValueError(f"Invalid worker spec: {spec!r} (expected host:port)") return {"url": f"http://{host}:{port}", "host": host, "port": int(port)} def configured_workers(): out = [] for w in db.list_workers(): out.append({ "url": f"http://{w['host']}:{w['port']}", "host": w["host"], "port": w["port"], }) return out def probe_worker(url, timeout=None): """Return a normalized worker status dict, or None if unreachable.""" timeout = timeout or settings.WORKER_STATUS_TIMEOUT try: resp = requests.get(f"{url}/status", timeout=timeout) resp.raise_for_status() info = resp.json() except (requests.RequestException, ValueError): return None info["url"] = url info["online"] = True return info def probe_all(): workers = [] for w in configured_workers(): status = probe_worker(w["url"]) if status: workers.append(status) else: workers.append({"url": w["url"], "host": w["host"], "port": w["port"], "online": False}) return workers def matches(job, worker): if worker.get("status") != "ready": return False if job.get("os_req") and job["os_req"].lower() not in str(worker.get("os", "")).lower(): return False if job.get("cpu_req") and job["cpu_req"].lower() not in str(worker.get("cpu", "")).lower(): return False return True