from typing import List, Optional, Dict, Any from sqlalchemy.orm import Session from datetime import datetime from app.models.network import IPAddress as IPAddressModel from app.models.network import Network as NetworkModel from app.models.network import IPStatus from app.schemas.network import IPAddressUpdate, IPAddressCreate class IPService: """IP地址管理服务""" @staticmethod def get_by_id(db: Session, ip_id: int) -> Optional[IPAddressModel]: """根据ID获取IP""" return db.query(IPAddressModel).filter(IPAddressModel.id == ip_id).first() @staticmethod def get_by_ip(db: Session, ip_address: str) -> Optional[IPAddressModel]: """根据IP地址获取""" return db.query(IPAddressModel).filter(IPAddressModel.ip_address == ip_address).first() @staticmethod def get_list( db: Session, network_id: Optional[int] = None, status: Optional[IPStatus] = None, skip: int = 0, limit: int = 100, search: Optional[str] = None ) -> tuple[int, List[IPAddressModel]]: """获取IP列表""" query = db.query(IPAddressModel) if network_id: query = query.filter(IPAddressModel.network_id == network_id) if status: query = query.filter(IPAddressModel.status == status) if search: search_pattern = f"%{search}%" query = query.filter( (IPAddressModel.ip_address.like(search_pattern)) | (IPAddressModel.mac_address.like(search_pattern)) | (IPAddressModel.hostname.like(search_pattern)) | (IPAddressModel.owner.like(search_pattern)) ) total = query.count() items = query.order_by(IPAddressModel.ip_address).offset(skip).limit(limit).all() return total, items @staticmethod def create(db: Session, ip_in: IPAddressCreate) -> IPAddressModel: """手动创建IP(通常由网段创建自动创建)""" db_ip = IPAddressModel(**ip_in.model_dump()) db.add(db_ip) db.commit() db.refresh(db_ip) return db_ip @staticmethod def update(db: Session, ip_id: int, ip_in: IPAddressUpdate) -> Optional[IPAddressModel]: """更新IP信息""" db_ip = IPService.get_by_id(db, ip_id) if not db_ip: return None update_data = ip_in.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(db_ip, field, value) db.commit() db.refresh(db_ip) return db_ip @staticmethod def update_status(db: Session, ip_address: str, status: IPStatus, mac_address: Optional[str] = None, hostname: Optional[str] = None) -> Optional[IPAddressModel]: """更新IP状态和扫描信息""" db_ip = IPService.get_by_ip(db, ip_address) if not db_ip: return None db_ip.status = status db_ip.last_seen = datetime.utcnow() if mac_address: db_ip.mac_address = mac_address if hostname: db_ip.hostname = hostname db.commit() db.refresh(db_ip) return db_ip @staticmethod def set_reserved(db: Session, ip_id: int, reserved: bool = True) -> Optional[IPAddressModel]: """设置/取消保留IP""" db_ip = IPService.get_by_id(db, ip_id) if not db_ip: return None db_ip.status = IPStatus.RESERVED if reserved else IPStatus.AVAILABLE db.commit() db.refresh(db_ip) return db_ip @staticmethod def bulk_update_status(db: Session, results: List[Dict[str, Any]]): """批量更新IP状态 Args: results: 扫描结果列表,每个元素包含 ip_address, status, mac_address, hostname """ for result in results: ip_address = result.get('ip_address') status = result.get('status') mac_address = result.get('mac_address') hostname = result.get('hostname') db_ip = IPService.get_by_ip(db, ip_address) if db_ip: db_ip.status = status db_ip.last_seen = datetime.utcnow() if mac_address: db_ip.mac_address = mac_address if hostname: db_ip.hostname = hostname db.commit() @staticmethod def get_by_network(db: Session, network_id: int) -> List[IPAddressModel]: """获取指定网段下的所有IP""" return db.query(IPAddressModel).filter( IPAddressModel.network_id == network_id ).order_by(IPAddressModel.ip_address).all()