Files
iDRAC_Info/data/scripts/Intel_Server_info.py
2025-12-19 20:23:59 +09:00

193 lines
8.9 KiB
Python

import subprocess
import os
import re
import time
from pathlib import Path
import logging
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [INFO] root: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# --- [설정] iDRAC 접속 정보 ---
IDRAC_USER = "root"
IDRAC_PASS = "calvin"
def resolve_output_dir() -> Path:
"""
사용자가 지정한 로직에 따라 저장 위치를 결정합니다.
스크립트 위치가 /data/scripts/ 일 경우 /data/idrac_info/ 에 저장합니다.
"""
here = Path(__file__).resolve().parent
if here.name.lower() == "scripts" and here.parent.name.lower() == "data":
base = here.parent
elif here.name.lower() == "scripts":
base = here.parent
else:
base = here.parent
out = base / "idrac_info"
out.mkdir(parents=True, exist_ok=True)
return out
def run_racadm(ip: str, command: str) -> str:
"""racadm 명령어를 실행하고 결과를 문자열로 반환합니다."""
full_cmd = f"racadm -r {ip} -u {IDRAC_USER} -p {IDRAC_PASS} {command}"
try:
# 쉘 명령 실행 (stderr도 포함하여 수집)
result = subprocess.check_output(full_cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True)
return result
except subprocess.CalledProcessError as e:
# 통신 실패 시 빈 문자열 반환
return ""
def get_val(text: str, pattern: str) -> str:
"""텍스트 내에서 특정 키워드를 찾아 해당 줄의 설정값(= 이후의 값)을 추출합니다."""
for line in text.splitlines():
if re.search(pattern, line, re.IGNORECASE):
parts = line.split('=')
if len(parts) >= 2:
return parts[1].strip()
return "N/A"
def fetch_idrac_info(ip: str, output_dir: Path):
logging.info(f">>> {ip} 정보 수집 중...")
# 1. 원시 데이터 벌크 수집 (네트워크 오버헤드 감소)
getsysinfo = run_racadm(ip, "getsysinfo")
hwinventory = run_racadm(ip, "hwinventory")
sys_profile = run_racadm(ip, "get bios.SysProfileSettings")
proc_settings = run_racadm(ip, "get bios.ProcSettings")
mem_settings = run_racadm(ip, "get bios.MemSettings")
storage_ctrl = run_racadm(ip, "get STORAGE.Controller.1")
# 서비스 태그 추출 (파일명 결정용)
svc_tag = get_val(getsysinfo, "SVC Tag")
if svc_tag == "N/A":
logging.error(f"[경고] {ip} 접속 실패 혹은 SVC Tag 확인 불가. 건너뜁니다.")
return
report_path = output_dir / f"{svc_tag}.txt"
with open(report_path, "w", encoding="utf-8") as f:
# 헤더 기록
f.write(f"Dell EMC Server Bios,iDRAC,R/C Setting (SVC Tag: {svc_tag})\n\n")
# --- Section 1: Firmware Version 정보 ---
f.write("-" * 42 + " Firmware Version 정보 " + "-" * 42 + "\n")
f.write(f"1. SVC Tag : {svc_tag}\n")
f.write(f"2. Bios Firmware : {get_val(getsysinfo, 'System BIOS Version')}\n")
f.write(f"3. iDRAC Firmware Version : {get_val(getsysinfo, 'Firmware Version')}\n")
nic1 = run_racadm(ip, "get NIC.FrmwImgMenu.1")
f.write(f"4. NIC Integrated Firmware Version : {get_val(nic1, '#FamilyVersion')}\n")
nic5 = run_racadm(ip, "get NIC.FrmwImgMenu.5")
f.write(f"5. OnBoard NIC Firmware Version : {get_val(nic5, '#FamilyVersion')}\n")
f.write(f"6. Raid Controller Firmware Version : {get_val(hwinventory, 'ControllerFirmwareVersion')}\n\n")
# --- Section 2: Bios 설정 정보 ---
f.write("-" * 45 + " Bios 설정 정보 " + "-" * 46 + "\n")
boot_settings = run_racadm(ip, "get bios.BiosBootSettings")
f.write(f"01. Bios Boot Mode : {get_val(boot_settings, 'BootMode')}\n")
f.write(f"02. System Profile : {get_val(sys_profile, 'SysProfile=')}\n")
f.write(f"03. CPU Power Management : {get_val(sys_profile, 'EnergyPerformanceBias')}\n")
f.write(f"04. Memory Frequency : {get_val(sys_profile, 'MemFrequency')}\n")
f.write(f"05. Turbo Boost : {get_val(sys_profile, 'ProcTurboMode')}\n")
f.write(f"06. C1E : {get_val(sys_profile, 'ProcC1E')}\n")
f.write(f"07. C-States : {get_val(sys_profile, 'ProcCStates')}\n")
f.write(f"08. Monitor/Mwait : {get_val(sys_profile, 'MonitorMwait')}\n")
f.write(f"09. Logical Processor : {get_val(proc_settings, 'LogicalProc')}\n")
f.write(f"10. Virtualization Technology : {get_val(proc_settings, 'ProcVirtualization')}\n")
f.write(f"11. LLC Prefetch : {get_val(proc_settings, 'LlcPrefetch')}\n")
f.write(f"12. x2APIC Mode : {get_val(proc_settings, 'ProcX2Apic')}\n")
f.write(f"13. Node Interleaving : {get_val(mem_settings, 'NodeInterleave')}\n")
f.write(f"14. DIMM Self Healing : {get_val(mem_settings, 'PPROnUCE')}\n")
f.write(f"15. Correctable Error Logging : {get_val(mem_settings, 'CECriticalSEL')}\n")
thermal = run_racadm(ip, "get System.ThermalSettings")
f.write(f"16. Thermal Profile Optimization : {get_val(thermal, 'ThermalProfile')}\n")
sriov = run_racadm(ip, "get Bios.IntegratedDevices")
f.write(f"17. SR-IOV Global Enable : {get_val(sriov, 'SriovGlobalEnable')}\n")
misc = run_racadm(ip, "get bios.MiscSettings")
f.write(f"18. F1/F2 Prompt on Error : {get_val(misc, 'ErrPrompt')}\n\n")
# --- Section 3: iDRAC 설정 정보 ---
f.write("-" * 45 + " iDRAC 설정 정보 " + "-" * 45 + "\n")
f.write(f"01. Timezone : {get_val(run_racadm(ip, 'get iDRAC.Time.Timezone'), 'Timezone')}\n")
f.write(f"02. IPMI LAN Selection : {get_val(run_racadm(ip, 'get iDRAC.CurrentNIC'), 'ActiveNIC')}\n")
f.write(f"03. IPMI IP(IPv4) DHCP : {get_val(run_racadm(ip, 'get iDRAC.CurrentIPv4'), 'DHCPEnable')}\n")
f.write(f"04. IPMI IP(IPv6) Enable : {get_val(run_racadm(ip, 'get iDRAC.CurrentIPv6'), 'Enable=')}\n")
f.write(f"05. Redfish Support : {get_val(run_racadm(ip, 'get iDRAC.Redfish.Enable'), 'Enable=')}\n")
f.write(f"06. SSH Support : {get_val(run_racadm(ip, 'get iDRAC.SSH'), 'Enable=')}\n")
f.write(f"07. AD User Domain Name : {get_val(run_racadm(ip, 'get iDRAC.USERDomain.1.Name'), 'Name')}\n")
f.write(f"08. SC Server Address : {get_val(run_racadm(ip, 'get iDRAC.ActiveDirectory.DomainController1'), 'DomainController1')}\n")
# Syslog 관련
f.write(f"15. Remote Log (syslog) : {get_val(run_racadm(ip, 'get iDRAC.SysLog.SysLogEnable'), 'SysLogEnable')}\n")
f.write(f"16. syslog server 1 : {get_val(run_racadm(ip, 'get iDRAC.SysLog.Server1'), 'Server1')}\n")
f.write(f"17. syslog server 2 : {get_val(run_racadm(ip, 'get iDRAC.SysLog.Server2'), 'Server2')}\n")
f.write(f"18. syslog server port : {get_val(run_racadm(ip, 'get iDRAC.SysLog.Port'), 'Port')}\n")
f.write(f"19. VirtualConsole Port : {get_val(run_racadm(ip, 'get iDRAC.VirtualConsole.Port'), 'Port')}\n\n")
# --- Section 4: Raid 설정 정보 ---
f.write("-" * 45 + " Raid 설정 정보 " + "-" * 46 + "\n")
f.write(f"01. Raid ProductName : {get_val(hwinventory, 'ProductName = BOSS')}, {get_val(hwinventory, 'ProductName = PERC')}\n")
f.write(f"02. RAID Types : {get_val(hwinventory, 'RAIDTypes')}\n")
f.write(f"03. StripeSize : {get_val(hwinventory, 'StripeSize')}\n")
f.write(f"04. ReadCachePolicy : {get_val(hwinventory, 'ReadCachePolicy')}\n")
f.write(f"05. WriteCachePolicy : {get_val(hwinventory, 'WriteCachePolicy')}\n")
f.write(f"06. CheckConsistencyMode : {get_val(storage_ctrl, 'CheckConsistencyMode')}\n")
f.write(f"07. PatrolReadRate : {get_val(storage_ctrl, 'PatrolReadRate')}\n")
f.write(f"08. period : 168h\n")
f.write(f"09. Power Save : No\n")
f.write(f"10. JBODMODE : Controller does not support JBOD\n")
f.write(f"11. maxconcurrentpd : 240\n")
logging.info(f" ㄴ 완료: {report_path.name}")
def main():
import sys
if len(sys.argv) < 2:
logging.error("Usage: python script.py <ip_list_file>")
return
ip_file = sys.argv[1]
if not os.path.exists(ip_file):
logging.error(f"파일을 찾을 수 없습니다: {ip_file}")
return
# 저장 위치 결정
output_dir = resolve_output_dir()
logging.info(f"[*] 결과 저장 폴더: {output_dir}")
# 시간 측정 시작
start_time = time.time()
# IP 파일 읽기
with open(ip_file, "r") as f:
ips = [line.strip() for line in f if line.strip()]
# 순차적 정보 수집
for ip in ips:
fetch_idrac_info(ip, output_dir)
# 소요 시간 계산
elapsed = time.time() - start_time
hours = int(elapsed // 3600)
minutes = int((elapsed % 3600) // 60)
seconds = int(elapsed % 60)
logging.info("=" * 50)
logging.info(f"정보 수집 완료.")
logging.info(f"소요 시간: {hours}시간 {minutes}{seconds}")
logging.info("=" * 50)
if __name__ == "__main__":
main()