From 13c457acb3c3467ac61f356a27ec6f6992f4ce2c Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 23 Jul 2026 15:33:13 +0800 Subject: [PATCH] =?UTF-8?q?fix(network):=20=E4=BF=AE=E5=A4=8D=E7=BD=91?= =?UTF-8?q?=E6=AE=B5=20total=5Fips=20=E5=8C=85=E5=90=AB=E7=BD=91=E7=BB=9C?= =?UTF-8?q?=E5=9C=B0=E5=9D=80=E5=92=8C=E5=B9=BF=E6=92=AD=E5=9C=B0=E5=9D=80?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题原因: - calculate_total_ips 使用 network.num_addresses 计算总IP数量 - 该值包含网络地址(第一个IP)和广播地址(最后一个IP) - 而 _create_ip_addresses 使用 hosts() 生成IP列表,排除这两个地址 - 导致 total_ips 比实际存储的IP记录多2个 - 例: /24 显示 256 个IP,实际只有 254 条记录 解决方案: 1. calculate_total_ips 改为 num_addresses - 2(排除网络地址和广播地址) 2. 对于 /31 /32 等没有网络/广播地址的网段,特殊处理 3. 提供 fix_network_total_ips.py 迁移脚本修复已有数据 --- backend/app/services/network_service.py | 4 +-- backend/scripts/fix_network_total_ips.py | 39 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 backend/scripts/fix_network_total_ips.py diff --git a/backend/app/services/network_service.py b/backend/app/services/network_service.py index f72557c..5914752 100644 --- a/backend/app/services/network_service.py +++ b/backend/app/services/network_service.py @@ -14,9 +14,9 @@ class NetworkService: @staticmethod def calculate_total_ips(cidr: str) -> int: - """计算网段的总IP数量""" + """计算网段中实际分配的IP数量(排除网络地址和广播地址)""" network = ipaddress.ip_network(cidr, strict=False) - return network.num_addresses + return network.num_addresses - 2 if network.num_addresses > 2 else network.num_addresses @staticmethod def get_network_addresses(cidr: str) -> List[str]: diff --git a/backend/scripts/fix_network_total_ips.py b/backend/scripts/fix_network_total_ips.py new file mode 100644 index 0000000..8e579d6 --- /dev/null +++ b/backend/scripts/fix_network_total_ips.py @@ -0,0 +1,39 @@ +""" +修复已有网段的 total_ips 字段:将 num_addresses 改为 hosts 数量(排除网络地址和广播地址) + +用法: cd /root/ipam/backend && source venv/bin/activate && python scripts/fix_network_total_ips.py +""" +import sys +import os + +# 确保能找到 app 模块 +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from app.core.database import SessionLocal +from app.models.network import Network +from app.services.network_service import NetworkService + + +def fix_total_ips(): + db = SessionLocal() + try: + networks = db.query(Network).all() + fixed = 0 + for net in networks: + correct = NetworkService.calculate_total_ips(net.cidr) + actual_hosts = len(list(NetworkService.get_network_addresses(net.cidr))) + if net.total_ips != correct: + print(f" [{net.cidr:20s}] {net.total_ips:>5} -> {correct:>5} (hosts={actual_hosts})") + net.total_ips = correct + fixed += 1 + db.commit() + print(f"\n✅ 已修复 {fixed} 个网段") + except Exception as e: + db.rollback() + print(f"❌ 错误: {e}") + finally: + db.close() + + +if __name__ == "__main__": + fix_total_ips()