354 lines
12 KiB
Python
354 lines
12 KiB
Python
"""
|
|
Dell 펌웨어 카탈로그 대안 방법들
|
|
backend/services/dell_catalog_alternatives.py
|
|
|
|
Dell의 공식 Catalog.xml이 차단된 경우 사용할 수 있는 대안들
|
|
"""
|
|
|
|
import requests
|
|
from typing import List, Dict, Optional
|
|
from backend.models.firmware_version import FirmwareVersion, db
|
|
from datetime import datetime
|
|
|
|
|
|
class DellFirmwareCatalogAlternatives:
|
|
"""Dell 펌웨어 정보를 가져오는 대안 방법들"""
|
|
|
|
def __init__(self):
|
|
self.session = requests.Session()
|
|
self.session.headers.update({
|
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
|
})
|
|
|
|
# ========================================
|
|
# 방법 1: Dell Support API (공식 API)
|
|
# ========================================
|
|
|
|
def fetch_from_dell_support_api(self, model: str = "PowerEdge R750") -> List[Dict]:
|
|
"""
|
|
Dell Support API를 통한 펌웨어 정보 조회
|
|
|
|
Dell의 공식 Support API 엔드포인트:
|
|
https://www.dell.com/support/home/api/
|
|
|
|
참고: API 키가 필요할 수 있음
|
|
"""
|
|
try:
|
|
# Dell Support API 엔드포인트 (예시)
|
|
# 실제 API는 Dell 개발자 포털에서 확인 필요
|
|
url = f"https://www.dell.com/support/home/api/products/{model}/drivers"
|
|
|
|
response = self.session.get(url, timeout=30)
|
|
|
|
if response.status_code == 200:
|
|
data = response.json()
|
|
return self._parse_support_api_response(data, model)
|
|
else:
|
|
print(f"Dell Support API 오류: {response.status_code}")
|
|
return []
|
|
|
|
except Exception as e:
|
|
print(f"Dell Support API 조회 실패: {str(e)}")
|
|
return []
|
|
|
|
# ========================================
|
|
# 방법 2: Dell TechDirect (파트너 전용)
|
|
# ========================================
|
|
|
|
def fetch_from_techdirect(self, model: str = "PowerEdge R750") -> List[Dict]:
|
|
"""
|
|
Dell TechDirect API를 통한 펌웨어 정보 조회
|
|
|
|
TechDirect는 Dell 파트너용 플랫폼
|
|
API 키 필요: https://techdirect.dell.com/
|
|
"""
|
|
# TechDirect API 구현
|
|
# 실제 사용 시 API 키 필요
|
|
pass
|
|
|
|
# ========================================
|
|
# 방법 3: 로컬 카탈로그 파일 사용
|
|
# ========================================
|
|
|
|
def load_from_local_catalog(self, catalog_path: str) -> List[Dict]:
|
|
"""
|
|
로컬에 저장된 Catalog.xml 파일 사용
|
|
|
|
사용법:
|
|
1. Dell 공식 사이트에서 수동으로 Catalog.xml 다운로드
|
|
2. 로컬에 저장
|
|
3. 이 함수로 파싱
|
|
|
|
Args:
|
|
catalog_path: 로컬 Catalog.xml 파일 경로
|
|
"""
|
|
try:
|
|
from xml.etree import ElementTree as ET
|
|
|
|
with open(catalog_path, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
|
|
root = ET.fromstring(content)
|
|
return self._parse_catalog_xml(root)
|
|
|
|
except Exception as e:
|
|
print(f"로컬 카탈로그 파일 로드 실패: {str(e)}")
|
|
return []
|
|
|
|
# ========================================
|
|
# 방법 4: iDRAC에서 직접 조회
|
|
# ========================================
|
|
|
|
def fetch_from_idrac(self, idrac_ip: str, username: str, password: str) -> List[Dict]:
|
|
"""
|
|
iDRAC Redfish API를 통해 사용 가능한 업데이트 조회
|
|
|
|
iDRAC는 Dell Update Service를 통해 사용 가능한 업데이트를 확인할 수 있음
|
|
|
|
장점:
|
|
- 실제 서버에 맞는 정확한 펌웨어 정보
|
|
- 외부 카탈로그 불필요
|
|
|
|
단점:
|
|
- 각 서버마다 조회 필요
|
|
- 네트워크 연결 필요
|
|
"""
|
|
try:
|
|
from backend.services.idrac_redfish_client import DellRedfishClient
|
|
|
|
client = DellRedfishClient(idrac_ip, username, password)
|
|
|
|
# UpdateService에서 사용 가능한 업데이트 조회
|
|
url = f"https://{idrac_ip}/redfish/v1/UpdateService"
|
|
response = client.session.get(url, timeout=30)
|
|
|
|
if response.status_code == 200:
|
|
data = response.json()
|
|
# UpdateService의 Actions 확인
|
|
# SimpleUpdate 또는 CheckForUpdate 액션 사용
|
|
return self._parse_idrac_updates(data)
|
|
|
|
return []
|
|
|
|
except Exception as e:
|
|
print(f"iDRAC 업데이트 조회 실패: {str(e)}")
|
|
return []
|
|
|
|
# ========================================
|
|
# 방법 5: 수동 입력 (가장 간단하고 확실)
|
|
# ========================================
|
|
|
|
def create_manual_catalog(self) -> List[Dict]:
|
|
"""
|
|
수동으로 작성한 펌웨어 버전 정보
|
|
|
|
Dell 공식 사이트에서 확인한 최신 버전을 수동으로 입력
|
|
https://www.dell.com/support/
|
|
|
|
장점:
|
|
- 가장 확실하고 안정적
|
|
- 외부 의존성 없음
|
|
- 검증된 버전만 사용
|
|
|
|
단점:
|
|
- 수동 업데이트 필요
|
|
"""
|
|
manual_catalog = [
|
|
{
|
|
'component_name': 'BIOS',
|
|
'latest_version': '2.15.2',
|
|
'server_model': 'PowerEdge R750',
|
|
'vendor': 'Dell',
|
|
'release_date': '2024-03-15',
|
|
'download_url': 'https://www.dell.com/support/home/drivers/driversdetails?driverid=...',
|
|
'notes': 'PowerEdge R750 BIOS - 2024년 3월 릴리즈',
|
|
'is_critical': False
|
|
},
|
|
{
|
|
'component_name': 'iDRAC',
|
|
'latest_version': '7.00.00.00',
|
|
'server_model': None, # 모든 모델
|
|
'vendor': 'Dell',
|
|
'release_date': '2024-02-20',
|
|
'download_url': 'https://www.dell.com/support/home/drivers/driversdetails?driverid=...',
|
|
'notes': 'iDRAC9 최신 펌웨어 (14G/15G/16G 공용)',
|
|
'is_critical': True
|
|
},
|
|
{
|
|
'component_name': 'PERC H755',
|
|
'latest_version': '25.5.9.0001',
|
|
'server_model': 'PowerEdge R750',
|
|
'vendor': 'Dell',
|
|
'release_date': '2024-01-10',
|
|
'notes': 'PERC H755 RAID 컨트롤러',
|
|
'is_critical': False
|
|
},
|
|
# 더 많은 컴포넌트 추가...
|
|
]
|
|
|
|
return manual_catalog
|
|
|
|
# ========================================
|
|
# 방법 6: Dell Repository Manager (DRM)
|
|
# ========================================
|
|
|
|
def fetch_from_drm_export(self, drm_export_path: str) -> List[Dict]:
|
|
"""
|
|
Dell Repository Manager (DRM)에서 내보낸 데이터 사용
|
|
|
|
DRM은 Dell의 공식 펌웨어 관리 도구
|
|
https://www.dell.com/support/kbdoc/en-us/000177083/
|
|
|
|
사용법:
|
|
1. DRM 설치 및 실행
|
|
2. 필요한 서버 모델 선택
|
|
3. 카탈로그 내보내기
|
|
4. 내보낸 파일을 이 함수로 파싱
|
|
"""
|
|
try:
|
|
# DRM 내보내기 파일 파싱 로직
|
|
# XML 또는 CSV 형식일 수 있음
|
|
pass
|
|
except Exception as e:
|
|
print(f"DRM 내보내기 파일 로드 실패: {str(e)}")
|
|
return []
|
|
|
|
# ========================================
|
|
# 헬퍼 함수들
|
|
# ========================================
|
|
|
|
def _parse_support_api_response(self, data: Dict, model: str) -> List[Dict]:
|
|
"""Dell Support API 응답 파싱"""
|
|
# API 응답 구조에 따라 구현
|
|
return []
|
|
|
|
def _parse_catalog_xml(self, root) -> List[Dict]:
|
|
"""Catalog.xml 파싱"""
|
|
from xml.etree import ElementTree as ET
|
|
|
|
firmware_list = []
|
|
|
|
for pkg in root.findall(".//SoftwareComponent"):
|
|
name = pkg.findtext("Name")
|
|
version = pkg.findtext("Version")
|
|
release_date = pkg.findtext("ReleaseDate")
|
|
path = pkg.findtext("path")
|
|
|
|
if name and version:
|
|
firmware_list.append({
|
|
'component_name': name,
|
|
'latest_version': version,
|
|
'release_date': release_date,
|
|
'download_url': f"https://downloads.dell.com/{path}" if path else None,
|
|
'vendor': 'Dell'
|
|
})
|
|
|
|
return firmware_list
|
|
|
|
def _parse_idrac_updates(self, data: Dict) -> List[Dict]:
|
|
"""iDRAC UpdateService 응답 파싱"""
|
|
# UpdateService 데이터 파싱
|
|
return []
|
|
|
|
# ========================================
|
|
# DB에 저장
|
|
# ========================================
|
|
|
|
def save_to_database(self, firmware_list: List[Dict]) -> int:
|
|
"""
|
|
펌웨어 목록을 데이터베이스에 저장
|
|
|
|
Returns:
|
|
저장된 항목 수
|
|
"""
|
|
count = 0
|
|
|
|
for fw in firmware_list:
|
|
# 중복 확인
|
|
existing = FirmwareVersion.query.filter_by(
|
|
component_name=fw.get('component_name'),
|
|
latest_version=fw.get('latest_version'),
|
|
server_model=fw.get('server_model')
|
|
).first()
|
|
|
|
if not existing:
|
|
version = FirmwareVersion(
|
|
component_name=fw.get('component_name'),
|
|
latest_version=fw.get('latest_version'),
|
|
server_model=fw.get('server_model'),
|
|
vendor=fw.get('vendor', 'Dell'),
|
|
release_date=fw.get('release_date'),
|
|
download_url=fw.get('download_url'),
|
|
notes=fw.get('notes'),
|
|
is_critical=fw.get('is_critical', False)
|
|
)
|
|
db.session.add(version)
|
|
count += 1
|
|
|
|
db.session.commit()
|
|
return count
|
|
|
|
|
|
# ========================================
|
|
# 사용 예시
|
|
# ========================================
|
|
|
|
def sync_firmware_alternative(method: str = 'manual', **kwargs) -> Dict:
|
|
"""
|
|
대안 방법으로 펌웨어 정보 동기화
|
|
|
|
Args:
|
|
method: 'manual', 'local_catalog', 'idrac', 'support_api' 중 선택
|
|
**kwargs: 각 방법에 필요한 추가 인자
|
|
|
|
Returns:
|
|
{'success': bool, 'count': int, 'message': str}
|
|
"""
|
|
catalog = DellFirmwareCatalogAlternatives()
|
|
firmware_list = []
|
|
|
|
try:
|
|
if method == 'manual':
|
|
# 가장 권장: 수동으로 작성한 카탈로그
|
|
firmware_list = catalog.create_manual_catalog()
|
|
|
|
elif method == 'local_catalog':
|
|
# 로컬 Catalog.xml 파일 사용
|
|
catalog_path = kwargs.get('catalog_path')
|
|
if not catalog_path:
|
|
return {'success': False, 'count': 0, 'message': 'catalog_path 필요'}
|
|
firmware_list = catalog.load_from_local_catalog(catalog_path)
|
|
|
|
elif method == 'idrac':
|
|
# iDRAC에서 직접 조회
|
|
idrac_ip = kwargs.get('idrac_ip')
|
|
username = kwargs.get('username')
|
|
password = kwargs.get('password')
|
|
if not all([idrac_ip, username, password]):
|
|
return {'success': False, 'count': 0, 'message': 'iDRAC 정보 필요'}
|
|
firmware_list = catalog.fetch_from_idrac(idrac_ip, username, password)
|
|
|
|
elif method == 'support_api':
|
|
# Dell Support API 사용
|
|
model = kwargs.get('model', 'PowerEdge R750')
|
|
firmware_list = catalog.fetch_from_dell_support_api(model)
|
|
|
|
else:
|
|
return {'success': False, 'count': 0, 'message': f'알 수 없는 방법: {method}'}
|
|
|
|
# DB에 저장
|
|
count = catalog.save_to_database(firmware_list)
|
|
|
|
return {
|
|
'success': True,
|
|
'count': count,
|
|
'message': f'{count}개 펌웨어 정보 동기화 완료'
|
|
}
|
|
|
|
except Exception as e:
|
|
return {
|
|
'success': False,
|
|
'count': 0,
|
|
'message': f'오류: {str(e)}'
|
|
}
|