Files
iDRAC_Info/backend/routes/idrac_routes.py
T
2026-05-05 17:14:11 +09:00

250 lines
9.2 KiB
Python

"""
Dell iDRAC 멀티 서버 관리 라우트
backend/routes/idrac_routes.py
- CSRF 보호 제외 추가
- 펌웨어 관리 기능 제거됨 (Server Config Analysis로 대체)
"""
from flask import Blueprint, request, jsonify, current_app
from backend.services.idrac_redfish_client import DellRedfishClient
from backend.models.idrac_server import IdracServer, db
from datetime import datetime
import threading
# Blueprint 생성
idrac_bp = Blueprint('idrac', __name__, url_prefix='/idrac')
# ========================================
# 페이지 라우트
# ========================================
@idrac_bp.route('/')
def index():
"""iDRAC 서버 관리 메인 페이지"""
from flask import render_template
return render_template('idrac_firmware.html')
# ========================================
# 서버 관리 API (CRUD)
# ========================================
@idrac_bp.route('/api/servers', methods=['GET'])
def get_servers():
"""서버 목록 조회"""
try:
group_filter = request.args.get('group')
query = IdracServer.query.filter_by(is_active=True)
if group_filter and group_filter != 'all':
query = query.filter_by(group_name=group_filter)
servers = query.order_by(IdracServer.name).all()
return jsonify({
'success': True,
'servers': [s.to_dict() for s in servers]
})
except Exception as e:
return jsonify({'success': False, 'message': str(e)})
@idrac_bp.route('/api/servers', methods=['POST'])
def add_server():
"""서버 추가"""
try:
data = request.json
# 필수 필드 체크
if not all(k in data for k in ['name', 'ip_address', 'password']):
return jsonify({'success': False, 'message': '필수 필드 누락'})
# 활성 서버 중복 체크
if IdracServer.query.filter_by(ip_address=data['ip_address'], is_active=True).first():
return jsonify({'success': False, 'message': '이미 등록된 IP입니다.'})
# Soft delete된 서버가 있는지 확인하고 재활성화
existing_server = IdracServer.query.filter_by(ip_address=data['ip_address'], is_active=False).first()
if existing_server:
# 기존 서버 재활성화 및 정보 업데이트
existing_server.is_active = True
existing_server.name = data['name']
existing_server.username = data.get('username', 'root')
existing_server.password = data['password']
existing_server.group_name = data.get('group_name')
existing_server.model = data.get('model')
existing_server.notes = data.get('notes')
existing_server.status = 'registered'
existing_server.updated_at = datetime.utcnow()
db.session.commit()
return jsonify({'success': True, 'message': '서버 재등록 완료', 'server': existing_server.to_dict()})
# 새 서버 생성
new_server = IdracServer(
name=data['name'],
ip_address=data['ip_address'],
username=data.get('username', 'root'),
password=data['password'],
group_name=data.get('group_name'),
model=data.get('model'),
notes=data.get('notes')
)
db.session.add(new_server)
db.session.commit()
return jsonify({'success': True, 'message': '서버 추가 완료', 'server': new_server.to_dict()})
except Exception as e:
db.session.rollback()
return jsonify({'success': False, 'message': str(e)})
@idrac_bp.route('/api/servers/<int:server_id>', methods=['DELETE'])
def delete_server(server_id):
"""서버 삭제 (Soft Delete)"""
try:
server = IdracServer.query.get(server_id)
if not server:
return jsonify({'success': False, 'message': '서버를 찾을 수 없습니다'})
# Soft delete: is_active를 False로 설정
# IP 주소는 유지하여 재등록 시 재활성화 가능
server.is_active = False
server.status = 'deleted'
db.session.commit()
return jsonify({'success': True, 'message': '서버 삭제 완료'})
except Exception as e:
db.session.rollback()
return jsonify({'success': False, 'message': str(e)})
@idrac_bp.route('/api/groups', methods=['GET'])
def get_groups():
"""등록된 그룹 목록"""
try:
groups = db.session.query(IdracServer.group_name).filter(
IdracServer.group_name != None,
IdracServer.is_active == True
).distinct().all()
return jsonify({
'success': True,
'groups': [g[0] for g in groups if g[0]]
})
except Exception as e:
return jsonify({'success': False, 'message': str(e)})
# ========================================
# 연결 테스트 API
# ========================================
@idrac_bp.route('/api/servers/<int:server_id>/test', methods=['POST'])
def test_connection(server_id):
"""단일 서버 연결 테스트"""
try:
server = IdracServer.query.get(server_id)
if not server:
return jsonify({'success': False, 'message': '서버 없음'})
client = DellRedfishClient(server.ip_address, server.username, server.password)
if client.check_connection():
server.status = 'online'
server.last_connected = datetime.utcnow()
db.session.commit()
return jsonify({'success': True, 'message': '연결 성공'})
else:
server.status = 'offline'
db.session.commit()
return jsonify({'success': False, 'message': '연결 실패'})
except Exception as e:
return jsonify({'success': False, 'message': str(e)})
@idrac_bp.route('/api/servers/test-multi', methods=['POST'])
def test_connections_multi():
"""다중 서버 연결 테스트"""
try:
data = request.json
server_ids = data.get('server_ids', [])
results = []
for sid in server_ids:
server = IdracServer.query.get(sid)
if not server: continue
try:
client = DellRedfishClient(server.ip_address, server.username, server.password)
if client.check_connection():
server.status = 'online'
server.last_connected = datetime.utcnow()
results.append({'server_id': sid, 'success': True})
else:
server.status = 'offline'
results.append({'server_id': sid, 'success': False, 'message': 'Failed'})
except Exception as e:
server.status = 'offline'
results.append({'server_id': sid, 'success': False, 'message': str(e)})
db.session.commit()
success = sum(1 for r in results if r['success'])
return jsonify({
'success': True,
'summary': {'success': success, 'failed': len(results)-success},
'results': results
})
except Exception as e:
return jsonify({'success': False, 'message': str(e)})
# ========================================
# 전원 제어 API
# ========================================
@idrac_bp.route('/api/servers/reboot-multi', methods=['POST'])
def reboot_servers_multi():
"""다중 서버 재부팅"""
try:
data = request.json
server_ids = data.get('server_ids', [])
reboot_type = data.get('type', 'GracefulRestart')
results = []
for sid in server_ids:
server = IdracServer.query.get(sid)
if not server: continue
try:
client = DellRedfishClient(server.ip_address, server.username, server.password)
if client.reboot_server(reboot_type):
results.append({'server_id': sid, 'success': True, 'message': 'Reboot initiated'})
else:
results.append({'server_id': sid, 'success': False, 'message': 'Reboot failed'})
except Exception as e:
results.append({'server_id': sid, 'success': False, 'message': str(e)})
success = sum(1 for r in results if r['success'])
return jsonify({
'success': True,
'summary': {'success': success, 'failed': len(results)-success},
'results': results
})
except Exception as e:
return jsonify({'success': False, 'message': str(e)})
# ========================================
# Blueprint 등록 함수
# ========================================
def register_idrac_routes(app):
"""
idrac_routes 등록 및 초기화
"""
# Blueprint 등록
app.register_blueprint(idrac_bp)
# CSRF 제외 - app에 이미 설정된 csrf 인스턴스 사용
try:
from flask_wtf.csrf import CSRFProtect
# app에 이미 csrf가 설정되어 있으므로, 해당 인스턴스를 가져와서 exempt 설정
csrf = app.extensions.get('csrf')
if csrf:
csrf.exempt(idrac_bp)
except Exception as e:
app.logger.warning(f"CSRF exemption failed for idrac_bp: {e}")
# DB 생성
with app.app_context():
db.create_all()