"""Cloud Hypervisor REST API 传输(叶子模块,不依赖 cloud.sandbox,避免循环导入)。 只用标准库 raw HTTP over Unix socket,无第三方依赖。 """ import json import os import socket def _unix_socket_api(socket_path, method, path, payload=None): """Cloud Hypervisor REST API 的默认传输:标准库 raw HTTP over Unix socket(无第三方依赖)。返回 (status, body), body 能解析 JSON 时为 dict,否则为原文本。socket 不存在 或连接失败时 raise RuntimeError(调用方据此判 api 超时 /失败,不编造 200)。""" if not os.path.exists(socket_path): raise RuntimeError("api socket 不存在:%s" % socket_path) body = b"" if payload is not None: body = json.dumps(payload).encode("utf-8") req_lines = ["%s /api/v1%s HTTP/1.1" % (method, path), "Host: localhost", "Accept: application/json", "Content-Type: application/json", "Content-Length: %d" % len(body), "Connection: close", "", ""] raw = "\r\n".join(req_lines).encode("utf-8") + body sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.settimeout(5) try: sock.connect(socket_path) sock.sendall(raw) chunks = [] while True: try: data = sock.recv(65536) except socket.timeout: break if not data: break chunks.append(data) finally: sock.close() text = b"".join(chunks).decode("utf-8", errors="replace") status = 0 if text.startswith("HTTP/"): try: status = int(text.split()[1]) except (IndexError, ValueError): status = 0 body_text = text.split("\r\n\r\n", 1)[1] if "\r\n\r\n" in text \ else "" try: parsed = json.loads(body_text) if body_text.strip() else {} except ValueError: parsed = body_text return status, parsed def normalize_api_result(result): """API 调用归一化:fake api_client 可返回 (status, body) 或 {"status":..., "body":...} 或带 .status 的对象,本 函数统一成 (status:int, body)。""" if isinstance(result, tuple) and len(result) == 2: return int(result[0]), result[1] if isinstance(result, dict): status = result.get("status", result.get("status_code")) body = result.get("body", result) return (int(status) if status is not None else 0), body status = getattr(result, "status", None) \ or getattr(result, "status_code", None) return (int(status) if status is not None else 0), result