import requests from xml.etree import ElementTree as ET from backend.models.firmware_version import FirmwareVersion, db from datetime import datetime def get_manual_firmware_catalog(model="PowerEdge R750"): """ 수동으로 작성한 펌웨어 카탈로그 Dell 공식 사이트에서 확인한 최신 버전 정보 https://www.dell.com/support/ Dell Catalog.xml이 차단된 경우 이 데이터 사용 """ # 2024년 11월 기준 최신 버전 (정기적으로 업데이트 필요) catalog = { "PowerEdge R750": [ { 'component_name': 'BIOS', 'latest_version': '2.15.2', 'release_date': '2024-03-15', 'notes': 'PowerEdge R750 BIOS - 보안 업데이트 포함', 'is_critical': False }, { 'component_name': 'iDRAC', 'latest_version': '7.00.00.00', 'release_date': '2024-02-20', 'notes': 'iDRAC9 최신 펌웨어', 'is_critical': True }, { 'component_name': 'PERC H755', 'latest_version': '25.5.9.0001', 'release_date': '2024-01-10', 'notes': 'PERC H755 RAID 컨트롤러', 'is_critical': False }, { 'component_name': 'CPLD', 'latest_version': '1.0.6', 'release_date': '2023-12-15', 'notes': '시스템 보드 CPLD', 'is_critical': False }, ], "PowerEdge R640": [ { 'component_name': 'BIOS', 'latest_version': '2.19.2', 'release_date': '2024-02-01', 'notes': 'PowerEdge R640 BIOS', 'is_critical': False }, { 'component_name': 'iDRAC', 'latest_version': '7.00.00.00', 'release_date': '2024-02-20', 'notes': 'iDRAC9 최신 펌웨어', 'is_critical': True }, ] } return catalog.get(model, []) def sync_dell_catalog(model="PowerEdge R750"): """ Dell 펌웨어 정보 동기화 1차: Dell 공식 Catalog.xml 시도 2차: 수동 카탈로그 사용 (Fallback) """ count = 0 # 1차 시도: Dell 공식 Catalog.xml try: url = "https://downloads.dell.com/catalog/Catalog.xml" print(f"[INFO] Dell Catalog 다운로드 시도... ({url})") response = requests.get(url, timeout=30) response.raise_for_status() root = ET.fromstring(response.content) for pkg in root.findall(".//SoftwareComponent"): # 이 컴포넌트가 지정된 모델에 해당하는지 확인 supported = [ sys.text.strip() for sys in pkg.findall(".//SupportedSystems/Brand/Model/Display") if sys.text ] if model not in supported: continue name = pkg.findtext("Name") version = pkg.findtext("Version") release_date = pkg.findtext("ReleaseDate") path = pkg.findtext("path") vendor = "Dell" if not name or not version: continue # 중복 방지 existing = FirmwareVersion.query.filter_by( component_name=name, latest_version=version, server_model=model ).first() if not existing: db.session.add( FirmwareVersion( component_name=name, latest_version=version, release_date=release_date, vendor=vendor, server_model=model, download_url=f"https://downloads.dell.com/{path}", ) ) count += 1 db.session.commit() print(f"✓ {model} 관련 펌웨어 {count}개 동기화 완료 (Dell Catalog)") return count except requests.exceptions.HTTPError as e: if e.response.status_code == 404: print(f"[경고] Dell Catalog.xml 접근 불가 (404). 수동 카탈로그 사용...") else: print(f"[경고] Dell Catalog 다운로드 실패: {e}. 수동 카탈로그 사용...") except Exception as e: print(f"[경고] Dell Catalog 처리 중 오류: {e}. 수동 카탈로그 사용...") # 2차 시도: 수동 카탈로그 사용 try: print(f"[INFO] 수동 카탈로그에서 {model} 펌웨어 정보 로드 중...") manual_catalog = get_manual_firmware_catalog(model) if not manual_catalog: print(f"[경고] {model}에 대한 수동 카탈로그 데이터가 없습니다") return 0 for fw in manual_catalog: # 중복 방지 existing = FirmwareVersion.query.filter_by( component_name=fw['component_name'], latest_version=fw['latest_version'], server_model=model ).first() if not existing: db.session.add( FirmwareVersion( component_name=fw['component_name'], latest_version=fw['latest_version'], release_date=fw.get('release_date'), vendor='Dell', server_model=model, notes=fw.get('notes'), is_critical=fw.get('is_critical', False) ) ) count += 1 db.session.commit() print(f"✓ {model} 관련 펌웨어 {count}개 동기화 완료 (수동 카탈로그)") return count except Exception as e: print(f"[오류] 수동 카탈로그 처리 실패: {e}") db.session.rollback() return 0