import os import re import subprocess from dotenv import load_dotenv from concurrent.futures import ThreadPoolExecutor, as_completed import logging # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s [INFO] root: %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) # .env 파일에서 사용자 이름 및 비밀번호 설정 load_dotenv() IDRAC_USER = os.getenv("IDRAC_USER") IDRAC_PASS = os.getenv("IDRAC_PASS") def fetch_idrac_info(idrac_ip, output_dir): try: # 서비스 태그 가져오기 (get 제외) cmd_getsysinfo = f"racadm -r {idrac_ip} -u {IDRAC_USER} -p {IDRAC_PASS} getsysinfo" getsysinfo = subprocess.getoutput(cmd_getsysinfo) svc_tag_match = re.search(r"SVC Tag\s*=\s*(\S+)", getsysinfo) svc_tag = svc_tag_match.group(1) if svc_tag_match else None if not svc_tag: logging.error(f"Failed to retrieve SVC Tag for IP: {idrac_ip}") return # InfiniBand.VndrConfigPage 목록 가져오기 cmd_list = f"racadm -r {idrac_ip} -u {IDRAC_USER} -p {IDRAC_PASS} get InfiniBand.VndrConfigPage" output_list = subprocess.getoutput(cmd_list) # InfiniBand.VndrConfigPage.<숫자> 및 Key 값 추출 matches = re.findall(r"InfiniBand\.VndrConfigPage\.(\d+)\s+\[Key=InfiniBand\.Slot\.(\d+)-\d+#VndrConfigPage]", output_list) # 결과를 저장할 파일 생성 output_file = os.path.join(output_dir, f"{svc_tag}.txt") os.makedirs(output_dir, exist_ok=True) with open(output_file, "w") as f: # 서비스 태그 저장 f.write(f"{svc_tag}\n") # 슬롯별 GUID를 딕셔너리로 수집 slot_to_guid = {} slots_found = [] # 각 InfiniBand.VndrConfigPage.<숫자> 처리 for number, slot in matches: cmd_detail = f"racadm -r {idrac_ip} -u {IDRAC_USER} -p {IDRAC_PASS} get InfiniBand.VndrConfigPage.{number}" output_detail = subprocess.getoutput(cmd_detail) # PortGUID 값 추출 match_guid = re.search(r"PortGUID=(\S+)", output_detail) port_guid = match_guid.group(1) if match_guid else "Not Found" slot_to_guid[slot] = port_guid slots_found.append(slot) # 환경변수에서 슬롯 우선순위 읽기 slot_priority_str = os.getenv("GUID_SLOT_PRIORITY", "") if slot_priority_str: # 사용자 지정 슬롯 우선순위 사용 desired_order = [s.strip() for s in slot_priority_str.split(",") if s.strip()] logging.info(f"사용자 지정 슬롯 우선순위 사용: {desired_order}") else: # 기본: 발견된 순서대로 desired_order = slots_found logging.info(f"기본 순서 사용 (발견된 순서): {desired_order}") # 지정된 순서대로 파일에 기록 + GUID 합치기 hex_guid_list = [] for slot in desired_order: port_guid = slot_to_guid.get(slot, "Not Found") # Slot.<숫자>: 형식으로 저장 f.write(f"Slot.{slot}: {port_guid}\n") # PortGUID를 0x 형식으로 변환하여 리스트에 추가 if port_guid != "Not Found": hex_guid_list.append(f"0x{port_guid.replace(':', '').upper()}") # 모든 PortGUID를 "GUID: 0x;0x" 형식으로 저장 if hex_guid_list: f.write(f"GUID: {';'.join(hex_guid_list)}\n") logging.info(f"GUID 합치기 완료: {len(hex_guid_list)}개 슬롯") logging.info(f"✅ Completed: {idrac_ip}") except Exception as e: logging.error(f"Error processing IP {idrac_ip}: {e}") def main(ip_file): if not os.path.isfile(ip_file): logging.error(f"IP file {ip_file} does not exist.") return # Output directory resolution # Try to find 'data/idrac_info' relative to this script script_dir = os.path.dirname(os.path.abspath(__file__)) # Assuming script is in data/scripts, parent is data data_dir = os.path.dirname(script_dir) output_dir = os.path.join(data_dir, "idrac_info") # Fallback to current directory if structure is different if not os.path.basename(data_dir) == "data": output_dir = os.path.join(os.getcwd(), "idrac_info") os.makedirs(output_dir, exist_ok=True) logging.info(f"Output directory set to: {output_dir}") with open(ip_file, "r") as file: ip_addresses = [line.strip() for line in file.readlines()] with ThreadPoolExecutor(max_workers=100) as executor: future_to_ip = {executor.submit(fetch_idrac_info, ip, output_dir): ip for ip in ip_addresses} for future in as_completed(future_to_ip): try: future.result() except Exception as e: logging.error(f"Error processing task: {e}") if __name__ == "__main__": import sys if len(sys.argv) != 2: logging.error("Usage: python script.py ") sys.exit(1) ip_file = sys.argv[1] main(ip_file)