Files
H3ConuMS-v2/backend/app/services/provision_service.py
T
2026-04-02 23:40:04 +08:00

115 lines
4.0 KiB
Python

"""业务下发服务"""
from typing import Dict
from sqlalchemy.orm import Session
from app.services.ssh_service import SSHService
from app.models.device import ONUDevice, OLTDevice
import time
class ProvisionService:
"""业务下发服务"""
def __init__(self, db: Session):
self.db = db
def provision_device(self, device_id: int) -> Dict[str, any]:
"""
业务下发流程(参照下发业务流程.md):
1. system-view
2. interface Onu{port_id}
3. uni 1 vlan-mode trunk pvid 4094 2000 to 2000 3000 to 3010
4. port link-type trunk
5. undo port trunk permit vlan 1
6. port trunk permit vlan 2000 3000 to 3010 4094
7. save force
"""
device = self.db.query(ONUDevice).filter(ONUDevice.id == device_id).first()
if not device:
return {"success": False, "error": f"设备不存在: {device_id}"}
if not device.olt_id:
return {"success": False, "error": "设备未关联 OLT,请先进行扫描"}
olt = self.db.query(OLTDevice).filter(OLTDevice.id == device.olt_id).first()
if not olt:
return {"success": False, "error": "关联的 OLT 设备不存在"}
if not device.port_id:
return {"success": False, "error": "设备端口信息不完整,请先对 OLT 执行扫描"}
port_name = f"Onu{device.port_id}"
ssh = SSHService(olt.ip_address, olt.username, olt.password)
try:
ssh.connect()
def send_and_wait(cmd: str, expect: str, timeout: int = 15) -> str:
ssh.shell.send(cmd + "\n")
buf = ""
deadline = time.time() + timeout
while time.time() < deadline:
if ssh.shell.recv_ready():
buf += ssh.shell.recv(4096).decode("utf-8", errors="ignore")
if expect in buf:
return buf
else:
time.sleep(0.2)
return buf
# 进入系统视图
out = send_and_wait("system-view", "]")
if "]" not in out:
raise Exception("进入 system-view 失败")
# 进入端口
out = send_and_wait(f"interface {port_name}", "]")
if "]" not in out:
raise Exception(f"进入端口 {port_name} 失败")
# 配置 VLAN
send_and_wait("uni 1 vlan-mode trunk pvid 4094 2000 to 2000 3000 to 3010", "]")
send_and_wait("port link-type trunk", "]")
send_and_wait("undo port trunk permit vlan 1", "]")
send_and_wait("port trunk permit vlan 2000 3000 to 3010 4094", "]")
# 保存配置(等待 "successfully" 出现)
save_out = send_and_wait("save force", "successfully", timeout=30)
if "successfully" not in save_out:
raise Exception("save force 未确认成功,请检查 OLT 日志")
return {
"success": True,
"device_id": device_id,
"mac_address": device.mac_address,
"olt_ip": olt.ip_address,
"port": port_name,
}
except Exception as e:
return {
"success": False,
"device_id": device_id,
"mac_address": device.mac_address,
"error": str(e),
}
finally:
ssh.close()
def batch_provision(self, device_ids: list) -> Dict[str, any]:
results = []
success_count = 0
fail_count = 0
for device_id in device_ids:
result = self.provision_device(device_id)
results.append(result)
if result.get("success"):
success_count += 1
else:
fail_count += 1
return {
"total": len(device_ids),
"success": success_count,
"failed": fail_count,
"results": results,
}