400 lines
13 KiB
Python
400 lines
13 KiB
Python
"""
|
|
펌웨어 버전 비교 API 코드
|
|
idrac_routes.py 파일의 register_idrac_routes 함수 위에 추가하세요
|
|
"""
|
|
|
|
# ========================================
|
|
# 펌웨어 버전 관리 API
|
|
# ========================================
|
|
|
|
@idrac_bp.route('/api/firmware-versions', methods=['GET'])
|
|
def get_firmware_versions():
|
|
"""등록된 최신 펌웨어 버전 목록"""
|
|
try:
|
|
server_model = request.args.get('model') # 서버 모델 필터
|
|
|
|
query = FirmwareVersion.query.filter_by(is_active=True)
|
|
|
|
if server_model:
|
|
# 특정 모델 또는 범용
|
|
query = query.filter(
|
|
(FirmwareVersion.server_model == server_model) |
|
|
(FirmwareVersion.server_model == None)
|
|
)
|
|
|
|
versions = query.order_by(FirmwareVersion.component_name).all()
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'versions': [v.to_dict() for v in versions]
|
|
})
|
|
|
|
except Exception as e:
|
|
return jsonify({
|
|
'success': False,
|
|
'message': f'오류: {str(e)}'
|
|
})
|
|
|
|
@idrac_bp.route('/api/firmware-versions', methods=['POST'])
|
|
def add_firmware_version():
|
|
"""최신 펌웨어 버전 등록"""
|
|
try:
|
|
data = request.json
|
|
|
|
# 필수 필드 확인
|
|
if not all([data.get('component_name'), data.get('latest_version')]):
|
|
return jsonify({
|
|
'success': False,
|
|
'message': '컴포넌트명과 버전을 입력하세요'
|
|
})
|
|
|
|
# 중복 확인 (같은 컴포넌트, 같은 모델)
|
|
existing = FirmwareVersion.query.filter_by(
|
|
component_name=data['component_name'],
|
|
server_model=data.get('server_model')
|
|
).first()
|
|
|
|
if existing:
|
|
return jsonify({
|
|
'success': False,
|
|
'message': f'이미 등록된 컴포넌트입니다'
|
|
})
|
|
|
|
# 버전 생성
|
|
version = FirmwareVersion(
|
|
component_name=data['component_name'],
|
|
component_type=data.get('component_type'),
|
|
vendor=data.get('vendor'),
|
|
server_model=data.get('server_model'),
|
|
latest_version=data['latest_version'],
|
|
release_date=data.get('release_date'),
|
|
download_url=data.get('download_url'),
|
|
file_name=data.get('file_name'),
|
|
file_size_mb=data.get('file_size_mb'),
|
|
notes=data.get('notes'),
|
|
is_critical=data.get('is_critical', False)
|
|
)
|
|
|
|
db.session.add(version)
|
|
db.session.commit()
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'message': f'{version.component_name} 버전 정보 등록 완료',
|
|
'version': version.to_dict()
|
|
})
|
|
|
|
except Exception as e:
|
|
db.session.rollback()
|
|
return jsonify({
|
|
'success': False,
|
|
'message': f'오류: {str(e)}'
|
|
})
|
|
|
|
@idrac_bp.route('/api/firmware-versions/<int:version_id>', methods=['PUT'])
|
|
def update_firmware_version(version_id):
|
|
"""펌웨어 버전 정보 수정"""
|
|
try:
|
|
version = FirmwareVersion.query.get(version_id)
|
|
if not version:
|
|
return jsonify({
|
|
'success': False,
|
|
'message': '버전 정보를 찾을 수 없습니다'
|
|
})
|
|
|
|
data = request.json
|
|
|
|
# 업데이트
|
|
if 'component_name' in data:
|
|
version.component_name = data['component_name']
|
|
if 'latest_version' in data:
|
|
version.latest_version = data['latest_version']
|
|
if 'release_date' in data:
|
|
version.release_date = data['release_date']
|
|
if 'download_url' in data:
|
|
version.download_url = data['download_url']
|
|
if 'file_name' in data:
|
|
version.file_name = data['file_name']
|
|
if 'notes' in data:
|
|
version.notes = data['notes']
|
|
if 'is_critical' in data:
|
|
version.is_critical = data['is_critical']
|
|
|
|
db.session.commit()
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'message': '버전 정보 수정 완료',
|
|
'version': version.to_dict()
|
|
})
|
|
|
|
except Exception as e:
|
|
db.session.rollback()
|
|
return jsonify({
|
|
'success': False,
|
|
'message': f'오류: {str(e)}'
|
|
})
|
|
|
|
@idrac_bp.route('/api/firmware-versions/<int:version_id>', methods=['DELETE'])
|
|
def delete_firmware_version(version_id):
|
|
"""펌웨어 버전 정보 삭제"""
|
|
try:
|
|
version = FirmwareVersion.query.get(version_id)
|
|
if not version:
|
|
return jsonify({
|
|
'success': False,
|
|
'message': '버전 정보를 찾을 수 없습니다'
|
|
})
|
|
|
|
version.is_active = False
|
|
db.session.commit()
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'message': f'{version.component_name} 버전 정보 삭제 완료'
|
|
})
|
|
|
|
except Exception as e:
|
|
db.session.rollback()
|
|
return jsonify({
|
|
'success': False,
|
|
'message': f'오류: {str(e)}'
|
|
})
|
|
|
|
@idrac_bp.route('/api/servers/<int:server_id>/firmware/compare', methods=['GET'])
|
|
def compare_server_firmware(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)
|
|
current_inventory = client.get_firmware_inventory()
|
|
|
|
# 최신 버전 정보 조회
|
|
latest_versions = FirmwareVersion.query.filter_by(is_active=True).all()
|
|
|
|
# 비교 결과
|
|
comparisons = []
|
|
|
|
for current_fw in current_inventory:
|
|
component_name = current_fw['Name']
|
|
current_version = current_fw['Version']
|
|
|
|
# 최신 버전 찾기 (컴포넌트명 매칭)
|
|
latest = None
|
|
for lv in latest_versions:
|
|
if lv.component_name.lower() in component_name.lower():
|
|
# 서버 모델 확인
|
|
if not lv.server_model or lv.server_model == server.model:
|
|
latest = lv
|
|
break
|
|
|
|
# 비교
|
|
comparison = FirmwareComparisonResult(
|
|
component_name=component_name,
|
|
current_version=current_version,
|
|
latest_version=latest.latest_version if latest else None
|
|
)
|
|
|
|
result = comparison.to_dict()
|
|
|
|
# 추가 정보
|
|
if latest:
|
|
result['latest_info'] = {
|
|
'release_date': latest.release_date,
|
|
'download_url': latest.download_url,
|
|
'file_name': latest.file_name,
|
|
'is_critical': latest.is_critical,
|
|
'notes': latest.notes
|
|
}
|
|
|
|
comparisons.append(result)
|
|
|
|
# 통계
|
|
total = len(comparisons)
|
|
outdated = len([c for c in comparisons if c['status'] == 'outdated'])
|
|
latest_count = len([c for c in comparisons if c['status'] == 'latest'])
|
|
unknown = len([c for c in comparisons if c['status'] == 'unknown'])
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'server': {
|
|
'id': server.id,
|
|
'name': server.name,
|
|
'model': server.model
|
|
},
|
|
'comparisons': comparisons,
|
|
'summary': {
|
|
'total': total,
|
|
'outdated': outdated,
|
|
'latest': latest_count,
|
|
'unknown': unknown
|
|
}
|
|
})
|
|
|
|
except Exception as e:
|
|
return jsonify({
|
|
'success': False,
|
|
'message': f'오류: {str(e)}'
|
|
})
|
|
|
|
@idrac_bp.route('/api/servers/firmware/compare-multi', methods=['POST'])
|
|
def compare_multi_servers_firmware():
|
|
"""
|
|
여러 서버의 펌웨어 버전 비교
|
|
"""
|
|
try:
|
|
data = request.json
|
|
server_ids = data.get('server_ids', [])
|
|
|
|
if not server_ids:
|
|
return jsonify({
|
|
'success': False,
|
|
'message': '서버를 선택하세요'
|
|
})
|
|
|
|
results = []
|
|
|
|
for server_id in server_ids:
|
|
server = IdracServer.query.get(server_id)
|
|
if not server:
|
|
continue
|
|
|
|
try:
|
|
# 각 서버 비교
|
|
client = DellRedfishClient(server.ip_address, server.username, server.password)
|
|
current_inventory = client.get_firmware_inventory()
|
|
|
|
latest_versions = FirmwareVersion.query.filter_by(is_active=True).all()
|
|
|
|
outdated_count = 0
|
|
outdated_items = []
|
|
|
|
for current_fw in current_inventory:
|
|
component_name = current_fw['Name']
|
|
current_version = current_fw['Version']
|
|
|
|
# 최신 버전 찾기
|
|
for lv in latest_versions:
|
|
if lv.component_name.lower() in component_name.lower():
|
|
comparison = FirmwareComparisonResult(
|
|
component_name=component_name,
|
|
current_version=current_version,
|
|
latest_version=lv.latest_version
|
|
)
|
|
|
|
if comparison.status == 'outdated':
|
|
outdated_count += 1
|
|
outdated_items.append({
|
|
'component': component_name,
|
|
'current': current_version,
|
|
'latest': lv.latest_version
|
|
})
|
|
break
|
|
|
|
results.append({
|
|
'server_id': server.id,
|
|
'server_name': server.name,
|
|
'outdated_count': outdated_count,
|
|
'outdated_items': outdated_items,
|
|
'status': 'needs_update' if outdated_count > 0 else 'up_to_date'
|
|
})
|
|
|
|
except Exception as e:
|
|
results.append({
|
|
'server_id': server.id,
|
|
'server_name': server.name,
|
|
'error': str(e)
|
|
})
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'results': results
|
|
})
|
|
|
|
except Exception as e:
|
|
return jsonify({
|
|
'success': False,
|
|
'message': f'오류: {str(e)}'
|
|
})
|
|
|
|
|
|
# ========================================
|
|
# 초기 데이터 생성 함수
|
|
# ========================================
|
|
|
|
def init_firmware_versions():
|
|
"""초기 펌웨어 버전 데이터 생성"""
|
|
initial_versions = [
|
|
{
|
|
'component_name': 'BIOS',
|
|
'component_type': 'Firmware',
|
|
'vendor': 'Dell',
|
|
'server_model': 'PowerEdge R750',
|
|
'latest_version': '2.15.0',
|
|
'release_date': '2024-01-15',
|
|
'notes': 'PowerEdge R750 최신 BIOS'
|
|
},
|
|
{
|
|
'component_name': 'iDRAC',
|
|
'component_type': 'Firmware',
|
|
'vendor': 'Dell',
|
|
'latest_version': '6.10.30.00',
|
|
'release_date': '2024-02-20',
|
|
'notes': 'iDRAC9 최신 펌웨어 (모든 모델 공용)'
|
|
},
|
|
{
|
|
'component_name': 'PERC H755',
|
|
'component_type': 'Firmware',
|
|
'vendor': 'Dell',
|
|
'server_model': 'PowerEdge R750',
|
|
'latest_version': '25.5.9.0001',
|
|
'release_date': '2024-01-10',
|
|
'notes': 'PERC H755 RAID 컨트롤러'
|
|
},
|
|
{
|
|
'component_name': 'BIOS',
|
|
'component_type': 'Firmware',
|
|
'vendor': 'Dell',
|
|
'server_model': 'PowerEdge R640',
|
|
'latest_version': '2.19.2',
|
|
'release_date': '2024-02-01',
|
|
'notes': 'PowerEdge R640 최신 BIOS'
|
|
},
|
|
{
|
|
'component_name': 'CPLD',
|
|
'component_type': 'Firmware',
|
|
'vendor': 'Dell',
|
|
'latest_version': '1.0.6',
|
|
'release_date': '2023-12-15',
|
|
'notes': '시스템 보드 CPLD (14G/15G 공용)'
|
|
},
|
|
]
|
|
|
|
for data in initial_versions:
|
|
# 중복 체크
|
|
existing = FirmwareVersion.query.filter_by(
|
|
component_name=data['component_name'],
|
|
server_model=data.get('server_model')
|
|
).first()
|
|
|
|
if not existing:
|
|
version = FirmwareVersion(**data)
|
|
db.session.add(version)
|
|
|
|
try:
|
|
db.session.commit()
|
|
print("✓ 초기 펌웨어 버전 데이터 생성 완료")
|
|
except:
|
|
db.session.rollback()
|
|
print("⚠ 초기 데이터 생성 중 오류 (이미 있을 수 있음)")
|