jdeip/app/rotation_service.py

78 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from typing import Any, Dict, List, Optional, Tuple
from .config import settings
from .eip_client import client_singleton as eip
from .redis_store import store_singleton as kv
def _extract_device_ip_and_id(device: Dict[str, Any]) -> Tuple[Optional[str], Optional[str]]:
# 由于未知后端返回结构,尽可能容错地提取
ip = (
device.get("ip")
or device.get("public_ip")
or device.get("eip")
or device.get("addr")
or device.get("address")
)
edge_id = device.get("id") or device.get("edge") or device.get("mac") or device.get("device_id")
# 若 edge 是数组或对象,尝试取可打印的第一项
if isinstance(edge_id, list) and edge_id:
edge_id = edge_id[0]
if isinstance(edge_id, dict):
edge_id = edge_id.get("id") or edge_id.get("mac") or edge_id.get("edge")
return (str(ip) if ip else None, str(edge_id) if edge_id else None)
def select_unused_ip(devices: List[Dict[str, Any]]) -> Tuple[Optional[str], Optional[str]]:
for d in devices:
ip, edge_id = _extract_device_ip_and_id(d)
if not ip:
# 没有可识别的 IP跳过
continue
if not kv.is_ip_used_today(ip):
return ip, edge_id
return None, None
def apply_gateway_route(edge_id: Optional[str], ip: str) -> Dict[str, Any]:
# 将选中的 edge 配置到网关规则中
rule = {
"table": 1,
"enable": True,
"edge": [edge_id] if edge_id else [],
"network": [],
"cityhash": settings.eip_default_cityhash or "",
}
config = {"id": 1, "rules": [rule]}
return eip.gateway_config_set(settings.eip_gateway_mac, config)
def rotate(cityhash: Optional[str] = None, num: Optional[int] = None) -> Dict[str, Any]:
geo = cityhash or settings.eip_default_cityhash
if not geo:
raise ValueError("cityhash 不能为空,请在请求中或环境变量中提供")
n = int(num or settings.eip_default_num or 10)
devices = eip.list_devices(geo=geo, offset=0, num=n)
ip, edge_id = select_unused_ip(devices)
if not ip:
return {"changed": False, "reason": "没有可用且今天未使用的 IP"}
_ = apply_gateway_route(edge_id=edge_id, ip=ip)
kv.add_used_ip_today(ip)
kv.set_current(ip=ip, edge_id=edge_id)
status = eip.gateway_status(settings.eip_gateway_mac)
return {"changed": True, "ip": ip, "edge": edge_id, "status": status}
def status() -> Dict[str, Any]:
cur = kv.get_current()
used_count = kv.get_used_count_today()
gw = {}
try:
gw = eip.gateway_status(settings.eip_gateway_mac)
except Exception:
pass
return {"current": cur, "used_today": used_count, "gateway": gw}