Files
NetworkDeviceManagementSystem/backend/modules/monitor_config/repository.py
QuangMinh_123 2683cdb882 Device
2026-05-27 13:50:27 +07:00

148 lines
5.5 KiB
Python

import json
from config.database import get_connection, release_connection
# ============================================
# REPOSITORY LAYER: Tương tác trực tiếp với bảng monitor_config trong PostgreSQL
# ============================================
# Luồng đi tổng thể:
# Controller → Service → Repository → Database
# Repository CHỈ chịu trách nhiệm thực thi SQL, KHÔNG chứa logic nghiệp vụ.
#
# Bảng monitor_config có quan hệ 1-1 với bảng device:
# - Mỗi device có đúng 1 bản ghi monitor_config (tạo tự động khi tạo device)
# - Khóa ngoại: device_id → device(id) ON DELETE CASCADE
# - Ràng buộc UNIQUE trên device_id → đảm bảo không trùng
# ============================================
def _row_to_dict(row):
"""
Chuyển đổi một dòng kết quả (tuple) từ câu query thành dictionary.
Thứ tự các cột phải khớp với SELECT trong các hàm bên dưới.
"""
if not row:
return None
return {
"id": str(row[0]),
"device_id": str(row[1]),
"enable_ping": row[2],
"ping_count": row[3],
"ping_timeout": row[4],
"ping_interval": row[5],
"enable_snmp": row[6],
"snmp_version": row[7],
"snmp_community": row[8],
"snmp_port": row[9],
"snmp_interval": row[10],
"snmp_timeout": row[11],
"snmp_custom_oids": row[12], # PostgreSQL JSONB → Python dict (tự động)
"created": row[13].isoformat() if row[13] else None,
"modified": row[14].isoformat() if row[14] else None
}
# ============================================
# FIND BY DEVICE ID: Lấy cấu hình giám sát của một thiết bị
# ============================================
# Luồng đi:
# GET /api/devices/{device_id}/monitor-config
# → Controller → Service gọi hàm này
# → Trả về dict nếu tìm thấy, None nếu không
# ============================================
def find_monitor_config_by_device_id(device_id):
conn = get_connection()
cur = None
try:
cur = conn.cursor()
cur.execute("""
SELECT id, device_id, enable_ping, ping_count, ping_timeout, ping_interval,
enable_snmp, snmp_version, snmp_community, snmp_port, snmp_interval,
snmp_timeout, snmp_custom_oids, created, modified
FROM monitor_config
WHERE device_id = %s
""", (device_id,))
row = cur.fetchone()
return _row_to_dict(row) if row else None
finally:
if cur:
cur.close()
release_connection(conn)
# ============================================
# UPDATE: Cập nhật cấu hình giám sát của thiết bị
# ============================================
# Luồng đi:
# PUT /api/devices/{device_id}/monitor-config
# → Controller validate body → Service kiểm tra tồn tại → Repository cập nhật DB
#
# Cách hoạt động:
# - Dùng Dynamic UPDATE: chỉ cập nhật các trường có trong data (không ghi đè toàn bộ)
# - Trường snmp_custom_oids cần chuyển sang JSON string trước khi lưu vào JSONB
# - Tự động cập nhật cột modified = CURRENT_TIMESTAMP
# - RETURNING: trả về toàn bộ row sau khi update (tránh phải SELECT lại)
# ============================================
def update_monitor_config_db(device_id, data):
conn = get_connection()
cur = None
try:
cur = conn.cursor()
# Xây dựng câu lệnh UPDATE động — chỉ SET các trường có trong data
update_fields = []
params = []
# Danh sách các trường được phép cập nhật
allowed_fields = [
"enable_ping", "ping_count", "ping_timeout", "ping_interval",
"enable_snmp", "snmp_version", "snmp_community", "snmp_port",
"snmp_interval", "snmp_timeout", "snmp_custom_oids"
]
for key in allowed_fields:
if key in data:
value = data[key]
# ⚠️ XỬ LÝ ĐẶC BIỆT: snmp_custom_oids là JSONB trong PostgreSQL
# Python dict cần chuyển sang JSON string trước khi INSERT/UPDATE
# Ví dụ: {"sysName": "1.3.6.1.2.1.1.5.0"} → '{"sysName": "1.3.6.1.2.1.1.5.0"}'
if key == "snmp_custom_oids" and isinstance(value, dict):
value = json.dumps(value)
update_fields.append(f"{key} = %s")
params.append(value)
if not update_fields:
# Không có trường nào cần cập nhật → trả về config hiện tại
return find_monitor_config_by_device_id(device_id)
# Thêm cập nhật thời gian modified
update_fields.append("modified = CURRENT_TIMESTAMP")
sql = f"""
UPDATE monitor_config
SET {', '.join(update_fields)}
WHERE device_id = %s
RETURNING id, device_id, enable_ping, ping_count, ping_timeout, ping_interval,
enable_snmp, snmp_version, snmp_community, snmp_port, snmp_interval,
snmp_timeout, snmp_custom_oids, created, modified
"""
params.append(device_id)
cur.execute(sql, tuple(params))
row = cur.fetchone()
conn.commit()
return _row_to_dict(row) if row else None
except Exception:
conn.rollback()
raise
finally:
if cur:
cur.close()
release_connection(conn)