Files
QuangMinh_123 edc4fc44c5 monitorconfig
2026-05-29 11:10:51 +07:00

189 lines
7.0 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
}
# ============================================
# INSERT DEFAULT: Tạo cấu hình giám sát mặc định cho thiết bị mới
# ============================================
def insert_default_monitor_config_db(device_id, cursor=None):
"""
Thêm cấu hình giám sát mặc định cho thiết bị mới.
Nếu có cursor được truyền vào (từ transaction của device), dùng chung cursor đó.
Nếu không, tự tạo connection riêng.
"""
sql = """
INSERT INTO monitor_config (device_id, enable_ping, ping_count, ping_timeout, ping_interval, enable_snmp)
VALUES (%s, %s, %s, %s, %s, %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
"""
# Mặc định bật Ping giám sát (enable_ping=True), ping_count=3, timeout=5s, interval=60s
params = (device_id, True, 3, 5, 60, False)
if cursor:
cursor.execute(sql, params)
row = cursor.fetchone()
return _row_to_dict(row)
else:
conn = get_connection()
cur = None
try:
cur = conn.cursor()
cur.execute(sql, params)
row = cur.fetchone()
conn.commit()
return _row_to_dict(row)
except Exception:
conn.rollback()
raise
finally:
if cur:
cur.close()
release_connection(conn)
# ============================================
# 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)