Compare commits

...

2 Commits

Author SHA1 Message Date
QuangMinh_123
48c5183c12 FixServiceDevies 2026-05-29 11:34:03 +07:00
QuangMinh_123
edc4fc44c5 monitorconfig 2026-05-29 11:10:51 +07:00
8 changed files with 172 additions and 36 deletions

View File

@@ -18,6 +18,10 @@ from modules.device.routes import (
device_bp
)
from modules.monitor_config.routes import (
monitor_config_bp
)
app = Flask(__name__)
# Register Global Exception Handlers
@@ -39,6 +43,11 @@ app.register_blueprint(
url_prefix="/api/devices"
)
app.register_blueprint(
monitor_config_bp,
url_prefix="/api/devices"
)
# @app.route("/")
# def home():
# return {

View File

@@ -0,0 +1,57 @@
# pyrefly: ignore [missing-import]
from config.database import get_connection, release_connection
# ============================================
# REPOSITORY LAYER: Tương tác trực tiếp với bảng alert_config trong PostgreSQL
# ============================================
def insert_default_alert_config_db(device_id):
"""
Tạo cấu hình cảnh báo mặc định cho thiết bị mới.
Tham số mặc định trong DB/Đặc tả:
- is_enabled = True
- fail_threshold = 3 (lỗi 3 lần liên tiếp thì alert)
- cooldown_minutes = 30 (khoảng thời gian tối thiểu giữa 2 cảnh báo tránh spam)
- notify_web = True (thông báo hiển thị trên giao diện)
- notify_email = False (mặc định chưa bật gửi email)
"""
conn = get_connection()
cur = None
try:
cur = conn.cursor()
cur.execute("""
INSERT INTO alert_config (device_id, is_enabled, fail_threshold, cooldown_minutes, notify_web, notify_email)
VALUES (%s, %s, %s, %s, %s, %s)
RETURNING id, device_id, is_enabled, fail_threshold, cooldown_minutes, notify_web, notify_email, created, modified
""", (
device_id,
True, # is_enabled
3, # fail_threshold
30, # cooldown_minutes
True, # notify_web
False # notify_email
))
row = cur.fetchone()
conn.commit()
if row:
return {
"id": str(row[0]),
"device_id": str(row[1]),
"is_enabled": row[2],
"fail_threshold": row[3],
"cooldown_minutes": row[4],
"notify_web": row[5],
"notify_email": row[6],
"created": row[7].isoformat() if row[7] else None,
"modified": row[8].isoformat() if row[8] else None
}
return None
except Exception:
conn.rollback()
raise
finally:
if cur:
cur.close()
release_connection(conn)

View File

@@ -0,0 +1,12 @@
# pyrefly: ignore [missing-import]
from modules.alert.repository import insert_default_alert_config_db
# ============================================
# SERVICE LAYER: Xử lý nghiệp vụ cho Module Alert
# ============================================
def create_default_alert_config_service(device_id):
"""
Tạo cấu hình cảnh báo mặc định cho thiết bị mới.
"""
return insert_default_alert_config_db(device_id)

View File

@@ -134,8 +134,7 @@ def find_device_by_ip(ip_address):
def insert_device(data):
"""
Tạo mới một thiết bị và cấu hình mặc định (MonitorConfig & AlertConfig)
trong cùng một database transaction.
Tạo mới một thiết bị mạng (chỉ ghi nhận vào bảng device).
"""
conn = get_connection()
cur = None
@@ -163,34 +162,7 @@ def insert_device(data):
device_row = cur.fetchone()
device_id = device_row[0]
# 2. Thêm cấu hình giám sát mặc định (MonitorConfig) cho thiết bị vừa tạo
# enable_ping mặc định bật True để thực hiện Ping giám sát
cur.execute("""
INSERT INTO monitor_config (device_id, enable_ping, ping_count, ping_timeout, ping_interval, enable_snmp)
VALUES (%s, %s, %s, %s, %s, %s)
""", (
device_id,
True, # enable_ping
3, # ping_count
5, # ping_timeout (giây)
60, # ping_interval (giây)
False # enable_snmp
))
# 3. Thêm cấu hình cảnh báo mặc định (AlertConfig) cho thiết bị vừa tạo
cur.execute("""
INSERT INTO alert_config (device_id, is_enabled, fail_threshold, cooldown_minutes, notify_web, notify_email)
VALUES (%s, %s, %s, %s, %s, %s)
""", (
device_id,
True, # is_enabled
3, # fail_threshold (số lần fail liên tiếp trước khi alert)
30, # cooldown_minutes (thời gian tránh spam alert)
True, # notify_web (hiển thị thông báo trên web)
False # notify_email (mặc định tắt gửi email)
))
# 4. Lấy lại thiết bị kèm thông tin DeviceType đã JOIN để trả về đầy đủ dữ liệu
# 2. Lấy lại thiết bị kèm thông tin DeviceType đã JOIN để trả về đầy đủ dữ liệu
cur.execute("""
SELECT
d.id, d.device_type_id, d.name, d.description, d.ip_address, d.port,
@@ -202,7 +174,7 @@ def insert_device(data):
""", (device_id,))
full_row = cur.fetchone()
# Commit toàn bộ transaction
# Commit transaction
conn.commit()
return _row_to_dict(full_row)

View File

@@ -19,6 +19,8 @@ from scheduler.scheduler import (
remove_device_monitoring_job,
reschedule_device_monitoring_job
)
from modules.monitor_config.service import create_default_monitor_config_service
from modules.alert.service import create_default_alert_config_service
def get_devices_service():
@@ -62,12 +64,17 @@ def create_device_service(data):
if existing_ip:
raise DeviceIPAlreadyExistsException(data["ip_address"])
# 4. Insert DB
# 4. Insert DB (Chỉ lưu vào bảng device)
new_device = insert_device(data)
# 5. Kích hoạt Job giám sát trên Background Scheduler
# Truyền kèm thông tin cấu hình mặc định (enable_ping=True, v.v...)
add_device_monitoring_job(new_device["id"], None)
# 5. Tạo cấu hình giám sát mặc định (thuộc module monitor_config)
monitor_config = create_default_monitor_config_service(new_device["id"])
# 6. Tạo cấu hình cảnh báo mặc định (thuộc module alert)
create_default_alert_config_service(new_device["id"])
# 7. Kích hoạt Job giám sát trên Background Scheduler
add_device_monitoring_job(new_device["id"], monitor_config)
return new_device

View File

@@ -42,6 +42,47 @@ def _row_to_dict(row):
}
# ============================================
# 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ị
# ============================================

View File

@@ -0,0 +1,27 @@
# pyrefly: ignore [missing-import]
from flask import Blueprint
from modules.monitor_config.controller import (
get_monitor_config,
update_monitor_config,
test_connection
)
# Khởi tạo Blueprint cho Module Monitor Config
# Blueprint này sẽ được đăng ký dưới prefix /api/devices trong app.py
monitor_config_bp = Blueprint("monitor_config", __name__)
# Đăng ký các endpoints cấu hình giám sát thiết bị:
# Luồng đi:
# 1. Client gửi request tương ứng tới endpoint.
# 2. Flask định tuyến (routing) request dựa trên method và url path.
# 3. Chuyển tiếp request cho hàm xử lý tương ứng trong controller.py.
# GET /api/devices/<device_id>/monitor-config -> Lấy cấu hình giám sát
monitor_config_bp.route("/<device_id>/monitor-config", methods=["GET"])(get_monitor_config)
# PUT /api/devices/<device_id>/monitor-config -> Cập nhật cấu hình giám sát
monitor_config_bp.route("/<device_id>/monitor-config", methods=["PUT"])(update_monitor_config)
# POST /api/devices/<device_id>/monitor-config/test -> Kiểm tra kết nối (Ping/SNMP)
monitor_config_bp.route("/<device_id>/monitor-config/test", methods=["POST"])(test_connection)

View File

@@ -22,13 +22,24 @@ import platform
from modules.monitor_config.repository import (
find_monitor_config_by_device_id,
update_monitor_config_db
update_monitor_config_db,
insert_default_monitor_config_db
)
from modules.monitor_config.exceptions import MonitorConfigNotFoundException
from modules.device.repository import find_device_by_id
from modules.device.exceptions import DeviceNotFoundException
from scheduler.scheduler import reschedule_device_monitoring_job
# ============================================
# CREATE DEFAULT: Tạo cấu hình giám sát mặc định (Service Layer)
# ============================================
def create_default_monitor_config_service(device_id, cursor=None):
"""
Tạo cấu hình giám sát mặc định cho thiết bị mới.
"""
return insert_default_monitor_config_db(device_id, cursor)
# ============================================
# Dynamic Import: icmplib và pysnmp
# ============================================