148 lines
5.5 KiB
Python
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)
|