59 lines
2.2 KiB
Python
59 lines
2.2 KiB
Python
|
|
# =============================================================================
|
|||
|
|
# 企微IT智能服务台 — 阶段5 自动化 回滚补偿
|
|||
|
|
# =============================================================================
|
|||
|
|
# 说明:动作执行失败时,对「已执行的前置动作」做补偿(逆向操作)。
|
|||
|
|
# 本期支持:病毒隔离(virus_quarantine) → 解除隔离(unisolate)。
|
|||
|
|
# 其余动作(只读/推送类)无需补偿,仅记录日志。
|
|||
|
|
# 补偿失败不阻断主流程(仅告警),由转人工接管兜底。
|
|||
|
|
# =============================================================================
|
|||
|
|
|
|||
|
|
from __future__ import annotations
|
|||
|
|
|
|||
|
|
import logging
|
|||
|
|
from typing import Any
|
|||
|
|
|
|||
|
|
from app.integrations.base import BaseClientError
|
|||
|
|
from app.integrations.factory import build_huorong_client
|
|||
|
|
|
|||
|
|
logger = logging.getLogger(__name__)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class RollbackService:
|
|||
|
|
"""回滚补偿服务。"""
|
|||
|
|
|
|||
|
|
def __init__(self, db: Any):
|
|||
|
|
self.db = db
|
|||
|
|
|
|||
|
|
async def compensate(self, session: Any, failed_action: Any) -> None:
|
|||
|
|
"""对失败动作做补偿(如有可逆操作)。
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
session: 自动化会话(含 meta.mapping)
|
|||
|
|
failed_action: 失败的动作
|
|||
|
|
"""
|
|||
|
|
action_type = failed_action.action_type
|
|||
|
|
if action_type != "virus_quarantine":
|
|||
|
|
# 只读/推送类动作无需补偿
|
|||
|
|
logger.info(f"动作 {action_type} 无需回滚补偿")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
client = await build_huorong_client(self.db)
|
|||
|
|
except Exception as e: # noqa: BLE001
|
|||
|
|
logger.warning(f"构建火绒客户端失败,跳过回滚: {e}")
|
|||
|
|
return
|
|||
|
|
if client is None:
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
mapping = (session.meta or {}).get("mapping") or {}
|
|||
|
|
client_ids = (failed_action.payload or {}).get("client_ids") or mapping.get(
|
|||
|
|
"client_ids"
|
|||
|
|
) or []
|
|||
|
|
if not client_ids:
|
|||
|
|
return
|
|||
|
|
try:
|
|||
|
|
await client.unisolate_terminal(client_ids=client_ids)
|
|||
|
|
logger.info(f"已对终端 {client_ids} 执行解除隔离补偿")
|
|||
|
|
except BaseClientError as e:
|
|||
|
|
logger.warning(f"回滚补偿(解除隔离)失败: {e}")
|