Update 2025-12-19 20:23:59
This commit is contained in:
@@ -3,6 +3,14 @@ import subprocess
|
||||
import time
|
||||
from dotenv import load_dotenv
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
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()
|
||||
@@ -99,9 +107,9 @@ def fetch_idrac_info(ip_address):
|
||||
f.write(f"01. RAID Settings - Raid ProductName : {get_value(hwinventory, 'ProductName = PERC')}\n")
|
||||
f.write(f"02. RAID Settings - Raid Types : No-Raid mode\n")
|
||||
|
||||
print(f"IP {ip_address} 에 대한 정보를 {output_file} 에 저장했습니다.")
|
||||
logging.info(f"IP {ip_address} 에 대한 정보를 {output_file} 에 저장했습니다.")
|
||||
except Exception as e:
|
||||
print(f"오류 발생: {e}")
|
||||
logging.error(f"오류 발생: {e}")
|
||||
|
||||
# 명령 결과에서 원하는 값 가져오기
|
||||
def get_value(output, key):
|
||||
@@ -117,7 +125,7 @@ start_time = time.time()
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
if len(sys.argv) != 2:
|
||||
print(f"Usage: {sys.argv[0]} <ip_file>")
|
||||
logging.error(f"Usage: {sys.argv[0]} <ip_file>")
|
||||
sys.exit(1)
|
||||
|
||||
ip_file_path = validate_ip_file(sys.argv[1])
|
||||
@@ -138,5 +146,5 @@ elapsed_hours = int(elapsed_time // 3600)
|
||||
elapsed_minutes = int((elapsed_time % 3600) // 60)
|
||||
elapsed_seconds = int(elapsed_time % 60)
|
||||
|
||||
print("정보 수집 완료.")
|
||||
print(f"수집 완료 시간: {elapsed_hours} 시간, {elapsed_minutes} 분, {elapsed_seconds} 초.")
|
||||
logging.info("정보 수집 완료.")
|
||||
logging.info(f"수집 완료 시간: {elapsed_hours} 시간, {elapsed_minutes} 분, {elapsed_seconds} 초.")
|
||||
|
||||
@@ -16,7 +16,8 @@ RACADM = os.getenv("RACADM_PATH", "racadm") # PATH에 있으면 'racadm'
|
||||
# 로깅
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(levelname)s - %(message)s"
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
def read_ip_list(ip_file: Path):
|
||||
@@ -66,7 +67,7 @@ def apply_xml(ip: str, xml_path: Path) -> tuple[bool, str]:
|
||||
# 대안:
|
||||
# cmd = [RACADM, "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "set", "-t", "xml", "-f", str(safe_path)]
|
||||
|
||||
logging.info("실행 명령(리스트) → %s", " ".join(cmd))
|
||||
logging.info(f"실행 명령(리스트) → {' '.join(cmd)}")
|
||||
try:
|
||||
p = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", shell=False, timeout=180)
|
||||
stdout = (p.stdout or "").strip()
|
||||
@@ -88,7 +89,7 @@ def apply_xml(ip: str, xml_path: Path) -> tuple[bool, str]:
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 3:
|
||||
print("Usage: python 02-set_config.py <ip_file> <xml_file>")
|
||||
logging.error("Usage: python 02-set_config.py <ip_file> <xml_file>")
|
||||
sys.exit(1)
|
||||
|
||||
ip_file = Path(sys.argv[1])
|
||||
|
||||
@@ -4,6 +4,14 @@ import time
|
||||
from dotenv import load_dotenv
|
||||
import sys
|
||||
from multiprocessing import Pool
|
||||
import logging
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
# 환경 변수 로드
|
||||
load_dotenv() # .env 파일에서 환경 변수 로드
|
||||
@@ -14,26 +22,27 @@ IDRAC_USER, IDRAC_PASS = os.getenv("IDRAC_USER"), os.getenv("IDRAC_PASS")
|
||||
# IP 주소 파일 로드 함수
|
||||
def load_ip_file(ip_file_path):
|
||||
if not os.path.isfile(ip_file_path):
|
||||
sys.exit(f"IP file {ip_file_path} does not exist.")
|
||||
logging.error(f"IP file {ip_file_path} does not exist.")
|
||||
sys.exit(1)
|
||||
with open(ip_file_path, "r") as file:
|
||||
return [line.strip() for line in file if line.strip()]
|
||||
|
||||
# iDRAC 정보를 가져오는 함수 정의
|
||||
def fetch_idrac_info(idrac_ip):
|
||||
print(f"Collecting TSR report for iDRAC IP: {idrac_ip}")
|
||||
logging.info(f"Collecting TSR report for iDRAC IP: {idrac_ip}")
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["racadm", "-r", idrac_ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "techsupreport", "collect"],
|
||||
capture_output=True,
|
||||
text=True
|
||||
)
|
||||
print(
|
||||
f"Successfully collected TSR report for {idrac_ip}"
|
||||
if result.returncode == 0
|
||||
else f"Failed to collect TSR report for {idrac_ip}: {result.stderr.strip()}"
|
||||
)
|
||||
if result.returncode == 0:
|
||||
logging.info(f"Successfully collected TSR report for {idrac_ip}")
|
||||
else:
|
||||
logging.error(f"Failed to collect TSR report for {idrac_ip}: {result.stderr.strip()}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Exception occurred for {idrac_ip}: {e}")
|
||||
logging.error(f"Exception occurred for {idrac_ip}: {e}")
|
||||
|
||||
# 메인 함수
|
||||
if __name__ == "__main__":
|
||||
@@ -48,4 +57,4 @@ if __name__ == "__main__":
|
||||
pool.map(fetch_idrac_info, ip_list)
|
||||
|
||||
elapsed_time = time.time() - start_time
|
||||
print(f"설정 완료. 수집 완료 시간: {int(elapsed_time // 3600)} 시간, {int((elapsed_time % 3600) // 60)} 분, {int(elapsed_time % 60)} 초.")
|
||||
logging.info(f"설정 완료. 수집 완료 시간: {int(elapsed_time // 3600)} 시간, {int((elapsed_time % 3600) // 60)} 분, {int(elapsed_time % 60)} 초.")
|
||||
@@ -3,6 +3,14 @@ import subprocess
|
||||
from dotenv import load_dotenv
|
||||
import sys
|
||||
from multiprocessing import Pool
|
||||
import logging
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
# 환경 변수 로드
|
||||
load_dotenv() # .env 파일에서 환경 변수 로드
|
||||
@@ -16,13 +24,14 @@ OME_PASS = os.getenv("OME_PASS")
|
||||
# IP 주소 파일 로드 및 유효성 검사
|
||||
def load_ip_file(ip_file_path):
|
||||
if not os.path.isfile(ip_file_path):
|
||||
sys.exit(f"IP file {ip_file_path} does not exist.")
|
||||
logging.error(f"IP file {ip_file_path} does not exist.")
|
||||
sys.exit(1)
|
||||
with open(ip_file_path, "r") as file:
|
||||
return [line.strip() for line in file if line.strip()]
|
||||
|
||||
# iDRAC 정보를 가져오는 함수
|
||||
def fetch_idrac_info(idrac_ip):
|
||||
print(f"Collecting TSR report for iDRAC IP: {idrac_ip}")
|
||||
logging.info(f"Collecting TSR report for iDRAC IP: {idrac_ip}")
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[
|
||||
@@ -32,13 +41,13 @@ def fetch_idrac_info(idrac_ip):
|
||||
capture_output=True,
|
||||
text=True
|
||||
)
|
||||
print(
|
||||
f"Successfully collected TSR report for {idrac_ip}"
|
||||
if result.returncode == 0
|
||||
else f"Failed to collect TSR report for {idrac_ip}: {result.stderr.strip()}"
|
||||
)
|
||||
if result.returncode == 0:
|
||||
logging.info(f"Successfully collected TSR report for {idrac_ip}")
|
||||
else:
|
||||
logging.error(f"Failed to collect TSR report for {idrac_ip}: {result.stderr.strip()}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Exception occurred for {idrac_ip}: {e}")
|
||||
logging.error(f"Exception occurred for {idrac_ip}: {e}")
|
||||
|
||||
# 메인 함수
|
||||
if __name__ == "__main__":
|
||||
@@ -51,4 +60,4 @@ if __name__ == "__main__":
|
||||
with Pool() as pool:
|
||||
pool.map(fetch_idrac_info, ip_list)
|
||||
|
||||
print("설정 완료.")
|
||||
logging.info("설정 완료.")
|
||||
|
||||
@@ -4,6 +4,14 @@ import time
|
||||
from dotenv import load_dotenv
|
||||
import sys
|
||||
from multiprocessing import Pool
|
||||
import logging
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv() # Load variables from .env file
|
||||
@@ -14,26 +22,27 @@ IDRAC_USER, IDRAC_PASS = os.getenv("IDRAC_USER"), os.getenv("IDRAC_PASS")
|
||||
# Load IP addresses from file
|
||||
def load_ip_file(ip_file_path):
|
||||
if not os.path.isfile(ip_file_path):
|
||||
sys.exit(f"IP file {ip_file_path} does not exist.")
|
||||
logging.error(f"IP file {ip_file_path} does not exist.")
|
||||
sys.exit(1)
|
||||
with open(ip_file_path, "r") as file:
|
||||
return [line.strip() for line in file if line.strip()]
|
||||
|
||||
# Power on the server for given iDRAC IP
|
||||
def poweron_idrac_server(idrac_ip):
|
||||
print(f"Powering on server for iDRAC IP: {idrac_ip}")
|
||||
logging.info(f"Powering on server for iDRAC IP: {idrac_ip}")
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["racadm", "-r", idrac_ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "serveraction", "powerup"],
|
||||
capture_output=True,
|
||||
text=True
|
||||
)
|
||||
print(
|
||||
f"Successfully powered on server for {idrac_ip}"
|
||||
if result.returncode == 0
|
||||
else f"Failed to power on server for {idrac_ip}: {result.stderr.strip()}"
|
||||
)
|
||||
if result.returncode == 0:
|
||||
logging.info(f"Successfully powered on server for {idrac_ip}")
|
||||
else:
|
||||
logging.error(f"Failed to power on server for {idrac_ip}: {result.stderr.strip()}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Exception occurred for {idrac_ip}: {e}")
|
||||
logging.error(f"Exception occurred for {idrac_ip}: {e}")
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
@@ -48,4 +57,4 @@ if __name__ == "__main__":
|
||||
pool.map(poweron_idrac_server, ip_list)
|
||||
|
||||
elapsed_time = time.time() - start_time
|
||||
print(f"Server Power On 완료. 완료 시간: {int(elapsed_time // 3600)} 시간, {int((elapsed_time % 3600) // 60)} 분, {int(elapsed_time % 60)} 초.")
|
||||
logging.info(f"Server Power On 완료. 완료 시간: {int(elapsed_time // 3600)} 시간, {int((elapsed_time % 3600) // 60)} 분, {int(elapsed_time % 60)} 초.")
|
||||
@@ -4,6 +4,14 @@ import time
|
||||
from dotenv import load_dotenv
|
||||
import sys
|
||||
from multiprocessing import Pool
|
||||
import logging
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv() # Load variables from .env file
|
||||
@@ -14,26 +22,27 @@ IDRAC_USER, IDRAC_PASS = os.getenv("IDRAC_USER"), os.getenv("IDRAC_PASS")
|
||||
# Load IP addresses from file
|
||||
def load_ip_file(ip_file_path):
|
||||
if not os.path.isfile(ip_file_path):
|
||||
sys.exit(f"IP file {ip_file_path} does not exist.")
|
||||
logging.error(f"IP file {ip_file_path} does not exist.")
|
||||
sys.exit(1)
|
||||
with open(ip_file_path, "r") as file:
|
||||
return [line.strip() for line in file if line.strip()]
|
||||
|
||||
# Power off the server for given iDRAC IP
|
||||
def poweroff_idrac_server(idrac_ip):
|
||||
print(f"Powering off server for iDRAC IP: {idrac_ip}")
|
||||
logging.info(f"Powering off server for iDRAC IP: {idrac_ip}")
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["racadm", "-r", idrac_ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "serveraction", "powerdown"],
|
||||
capture_output=True,
|
||||
text=True
|
||||
)
|
||||
print(
|
||||
f"Successfully powered off server for {idrac_ip}"
|
||||
if result.returncode == 0
|
||||
else f"Failed to power off server for {idrac_ip}: {result.stderr.strip()}"
|
||||
)
|
||||
if result.returncode == 0:
|
||||
logging.info(f"Successfully powered off server for {idrac_ip}")
|
||||
else:
|
||||
logging.error(f"Failed to power off server for {idrac_ip}: {result.stderr.strip()}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Exception occurred for {idrac_ip}: {e}")
|
||||
logging.error(f"Exception occurred for {idrac_ip}: {e}")
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
@@ -48,4 +57,4 @@ if __name__ == "__main__":
|
||||
pool.map(poweroff_idrac_server, ip_list)
|
||||
|
||||
elapsed_time = time.time() - start_time
|
||||
print(f"Server Power Off 완료. 완료 시간: {int(elapsed_time // 3600)} 시간, {int((elapsed_time % 3600) // 60)} 분, {int(elapsed_time % 60)} 초.")
|
||||
logging.info(f"Server Power Off 완료. 완료 시간: {int(elapsed_time // 3600)} 시간, {int((elapsed_time % 3600) // 60)} 분, {int(elapsed_time % 60)} 초.")
|
||||
@@ -4,6 +4,14 @@ import time
|
||||
from dotenv import load_dotenv
|
||||
import sys
|
||||
from multiprocessing import Pool
|
||||
import logging
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv() # Load variables from .env file
|
||||
@@ -14,26 +22,27 @@ IDRAC_USER, IDRAC_PASS = os.getenv("IDRAC_USER"), os.getenv("IDRAC_PASS")
|
||||
# Load IP addresses from file
|
||||
def load_ip_file(ip_file_path):
|
||||
if not os.path.isfile(ip_file_path):
|
||||
sys.exit(f"IP file {ip_file_path} does not exist.")
|
||||
logging.error(f"IP file {ip_file_path} does not exist.")
|
||||
sys.exit(1)
|
||||
with open(ip_file_path, "r") as file:
|
||||
return [line.strip() for line in file if line.strip()]
|
||||
|
||||
# Delete all jobs for given iDRAC IP
|
||||
def delete_all_jobs(idrac_ip):
|
||||
print(f"Deleting all jobs for iDRAC IP: {idrac_ip}")
|
||||
logging.info(f"Deleting all jobs for iDRAC IP: {idrac_ip}")
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["racadm", "-r", idrac_ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "jobqueue", "delete", "-i", "ALL"],
|
||||
capture_output=True,
|
||||
text=True
|
||||
)
|
||||
print(
|
||||
f"Successfully deleted all jobs for {idrac_ip}"
|
||||
if result.returncode == 0
|
||||
else f"Failed to delete jobs for {idrac_ip}: {result.stderr.strip()}"
|
||||
)
|
||||
if result.returncode == 0:
|
||||
logging.info(f"Successfully deleted all jobs for {idrac_ip}")
|
||||
else:
|
||||
logging.error(f"Failed to delete jobs for {idrac_ip}: {result.stderr.strip()}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Exception occurred for {idrac_ip}: {e}")
|
||||
logging.error(f"Exception occurred for {idrac_ip}: {e}")
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
@@ -48,4 +57,4 @@ if __name__ == "__main__":
|
||||
pool.map(delete_all_jobs, ip_list)
|
||||
|
||||
elapsed_time = time.time() - start_time
|
||||
print(f"Job delete 완료. 완료 시간: {int(elapsed_time // 3600)} 시간, {int((elapsed_time % 3600) // 60)} 분, {int(elapsed_time % 60)} 초.")
|
||||
logging.info(f"Job delete 완료. 완료 시간: {int(elapsed_time // 3600)} 시간, {int((elapsed_time % 3600) // 60)} 분, {int(elapsed_time % 60)} 초.")
|
||||
@@ -9,7 +9,11 @@ from concurrent.futures import ThreadPoolExecutor
|
||||
load_dotenv()
|
||||
|
||||
# 로깅 설정
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 사용자 이름 및 비밀번호 설정
|
||||
|
||||
206
data/scripts/AMD_Server_Info.py
Normal file
206
data/scripts/AMD_Server_Info.py
Normal file
@@ -0,0 +1,206 @@
|
||||
import subprocess
|
||||
import sys
|
||||
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:
|
||||
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, *args):
|
||||
"""racadm 명령어를 실행하고 결과를 반환합니다."""
|
||||
cmd = ["racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS] + list(args)
|
||||
try:
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, check=True, timeout=30)
|
||||
return result.stdout
|
||||
except Exception as e:
|
||||
# 에러 발생 시 빈 문자열 반환 (스크립트 중단 방지)
|
||||
return ""
|
||||
|
||||
def extract_value(text, pattern, delimiter='='):
|
||||
"""텍스트에서 특정 키의 값을 추출하고 공백을 제거합니다."""
|
||||
for line in text.splitlines():
|
||||
if re.search(pattern, line, re.IGNORECASE):
|
||||
if delimiter in line:
|
||||
# '=' 기준으로 쪼갠 후 값만 가져와서 공백 제거
|
||||
return line.split(delimiter, 1)[1].strip()
|
||||
return "N/A"
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# 메인 수집 함수
|
||||
def fetch_idrac_info(ip, output_dir):
|
||||
logging.info(f">>> [{ip}] 데이터 수집 시작...")
|
||||
|
||||
# 1. 원본 데이터 덩어리 가져오기 (API 호출 최소화)
|
||||
hwinventory = run_racadm(ip, "hwinventory")
|
||||
getsysinfo = run_racadm(ip, "getsysinfo")
|
||||
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 = extract_value(getsysinfo, "SVC Tag")
|
||||
if svc_tag == "N/A":
|
||||
logging.error(f"!!! [{ip}] SVC Tag 추출 실패. 작업을 건너뜁니다.")
|
||||
return
|
||||
|
||||
output_file = output_dir / f"{svc_tag}.txt"
|
||||
|
||||
with open(output_file, "w", encoding="utf-8") as f:
|
||||
# 헤더 작성
|
||||
f.write(f"Dell EMC Server Bios,iDRAC,R/C Setting (SVC Tag: {svc_tag})\n\n")
|
||||
|
||||
# --- 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 : {extract_value(getsysinfo, 'System BIOS Version')}\n")
|
||||
f.write(f"3. iDRAC Firmware Version : {extract_value(getsysinfo, 'Firmware Version')}\n")
|
||||
|
||||
# NIC 펌웨어 (별도 호출 필요)
|
||||
nic1 = run_racadm(ip, "get", "NIC.FrmwImgMenu.1")
|
||||
nic5 = run_racadm(ip, "get", "NIC.FrmwImgMenu.5")
|
||||
f.write(f"4. NIC Integrated Firmware Version : {extract_value(nic1, '#FamilyVersion')}\n")
|
||||
f.write(f"5. OnBoard NIC Firmware Version : {extract_value(nic5, '#FamilyVersion')}\n")
|
||||
f.write(f"6. Raid Controller Firmware Version : {extract_value(hwinventory, 'ControllerFirmwareVersion')}\n\n")
|
||||
|
||||
# --- 2. Bios 설정 정보 ---
|
||||
f.write("-" * 45 + " Bios 설정 정보 " + "-" * 45 + "\n")
|
||||
boot_mode = run_racadm(ip, "get", "bios.BiosBootSettings")
|
||||
f.write(f"01. Bios Boot Mode : {extract_value(boot_mode, 'BootMode')}\n")
|
||||
f.write(f"02. System Profile Settings - System Profile : {extract_value(sys_profile, 'SysProfile=')}\n")
|
||||
f.write(f"03. System Profile Settings - CPU Power Management : {extract_value(sys_profile, 'ProcPwrPerf')}\n")
|
||||
f.write(f"04. System Profile Settings - Memory Frequency : {extract_value(sys_profile, 'MemFrequency')}\n")
|
||||
f.write(f"05. System Profile Settings - Turbo Boost : {extract_value(sys_profile, 'ProcTurboMode')}\n")
|
||||
f.write(f"06. System Profile Settings - PCI ASPM L1 Link Power Management : {extract_value(sys_profile, 'PcieAspmL1')}\n")
|
||||
f.write(f"07. System Profile Settings - C-States : {extract_value(sys_profile, 'ProcCStates')}\n")
|
||||
f.write(f"08. System Profile Settings - Determinism Slider : {extract_value(sys_profile, 'DeterminismSlider')}\n")
|
||||
f.write(f"08-2. System Profile Settings - Dynamic Link Width Management (DLWM) : {extract_value(sys_profile, 'DynamicLinkWidthManagement')}\n")
|
||||
|
||||
f.write(f"09. Processor Settings - Logical Processor : {extract_value(proc_settings, 'LogicalProc')}\n")
|
||||
f.write(f"10. Processor Settings - Virtualization Technology : {extract_value(proc_settings, 'ProcVirtualization')}\n")
|
||||
f.write(f"11. Processor Settings - NUMA Nodes Per Socket : {extract_value(proc_settings, 'NumaNodesPerSocket')}\n")
|
||||
f.write(f"12. Processor Settings - x2APIC Mode : {extract_value(proc_settings, 'ProcX2Apic')}\n")
|
||||
|
||||
f.write(f"13. Memory Settings - Dram Refresh Delay : {extract_value(mem_settings, 'DramRefreshDelay')}\n")
|
||||
f.write(f"14. Memory Settings - DIMM Self Healing (PPR) : {extract_value(mem_settings, 'PPROnUCE')}\n")
|
||||
f.write(f"15. Memory Settings - Correctable Error Logging : {extract_value(mem_settings, 'CECriticalSEL')}\n")
|
||||
|
||||
thermal = run_racadm(ip, "get", "System.ThermalSettings")
|
||||
f.write(f"16. System Settings - Thermal Profile Optimization : {extract_value(thermal, 'ThermalProfile')}\n")
|
||||
|
||||
integrated = run_racadm(ip, "get", "Bios.IntegratedDevices")
|
||||
f.write(f"17. Integrated Devices Settings - SR-IOV Global Enable : {extract_value(integrated, 'SriovGlobalEnable')}\n")
|
||||
|
||||
misc = run_racadm(ip, "get", "bios.MiscSettings")
|
||||
f.write(f"18. Miscellaneous Settings - F1/F2 Prompt on Error : {extract_value(misc, 'ErrPrompt')}\n\n")
|
||||
|
||||
# --- 3. iDRAC 설정 정보 ---
|
||||
f.write("-" * 45 + " iDRAC 설정 정보 " + "-" * 45 + "\n")
|
||||
f.write(f"01. iDRAC Settings - Timezone : {extract_value(run_racadm(ip, 'get', 'iDRAC.Time.Timezone'), 'Timezone')}\n")
|
||||
f.write(f"02. iDRAC Settings - IPMI LAN Selection : {extract_value(run_racadm(ip, 'get', 'iDRAC.CurrentNIC'), 'ActiveNIC')}\n")
|
||||
f.write(f"03. iDRAC Settings - IPMI IP(IPv4) : {extract_value(run_racadm(ip, 'get', 'iDRAC.CurrentIPv4'), 'DHCPEnable')}\n")
|
||||
f.write(f"04. iDRAC Settings - IPMI IP(IPv6) : {extract_value(run_racadm(ip, 'get', 'iDRAC.CurrentIPv6'), 'Enable=')}\n")
|
||||
f.write(f"05. iDRAC Settings - Redfish Support : {extract_value(run_racadm(ip, 'get', 'iDRAC.Redfish.Enable'), 'Enable=')}\n")
|
||||
f.write(f"06. iDRAC Settings - SSH Support : {extract_value(run_racadm(ip, 'get', 'iDRAC.SSH'), 'Enable=')}\n")
|
||||
|
||||
# AD 관련 설정 (AD Group 1, 2 포함)
|
||||
f.write(f"07. iDRAC Settings - AD User Domain Name : {extract_value(run_racadm(ip, 'get', 'iDRAC.USERDomain.1.Name'), 'Name')}\n")
|
||||
f.write(f"08. iDRAC Settings - SC Server Address : {extract_value(run_racadm(ip, 'get', 'iDRAC.ActiveDirectory.DomainController1'), 'DomainController1')}\n")
|
||||
f.write(f"09. iDRAC Settings - SE AD RoleGroup Name : {extract_value(run_racadm(ip, 'get', 'iDRAC.ADGroup.1.Name'), 'Name')}\n")
|
||||
f.write(f"10. iDRAC Settings - SE AD RoleGroup Domain : {extract_value(run_racadm(ip, 'get', 'iDRAC.ADGroup.1.Domain'), 'Domain')}\n")
|
||||
f.write(f"11. iDRAC Settings - SE AD RoleGroup Privilege : {extract_value(run_racadm(ip, 'get', 'iDRAC.ADGroup.1.Privilege'), 'Privilege')}\n")
|
||||
f.write(f"12. iDRAC Settings - IDC AD RoleGroup Name : {extract_value(run_racadm(ip, 'get', 'iDRAC.ADGroup.2.Name'), 'Name')}\n")
|
||||
f.write(f"13. iDRAC Settings - IDC AD RoleGroup Domain : {extract_value(run_racadm(ip, 'get', 'iDRAC.ADGroup.2.Domain'), 'Domain')}\n")
|
||||
f.write(f"14. iDRAC Settings - IDC AD RoleGroup Privilege : {extract_value(run_racadm(ip, 'get', 'iDRAC.ADGroup.2.Privilege'), 'Privilege')}\n")
|
||||
|
||||
# Syslog 및 기타
|
||||
f.write(f"15. iDRAC Settings - Remote Log (syslog) : {extract_value(run_racadm(ip, 'get', 'iDRAC.SysLog.SysLogEnable'), 'SysLogEnable')}\n")
|
||||
f.write(f"16. iDRAC Settings - syslog server address 1 : {extract_value(run_racadm(ip, 'get', 'iDRAC.SysLog.Server1'), 'Server1')}\n")
|
||||
f.write(f"17. iDRAC Settings - syslog server address 2 : {extract_value(run_racadm(ip, 'get', 'iDRAC.SysLog.Server2'), 'Server2')}\n")
|
||||
f.write(f"18. iDRAC Settings - syslog server port : {extract_value(run_racadm(ip, 'get', 'iDRAC.SysLog.Port'), 'Port')}\n")
|
||||
f.write(f"19. iDRAC Settings - Remote KVM Nonsecure port : {extract_value(run_racadm(ip, 'get', 'iDRAC.VirtualConsole.Port'), 'Port')}\n\n")
|
||||
|
||||
# --- 4. Raid 설정 정보 (주석 해제 버전) ---
|
||||
f.write("-" * 45 + " Raid 설정 정보 " + "-" * 45 + "\n")
|
||||
f.write(f"01. RAID Settings - Raid ProductName : {extract_value(hwinventory, 'ProductName = PERC')}\n")
|
||||
f.write(f"02. RAID Settings - Raid Types : {extract_value(hwinventory, 'RAIDTypes')}\n")
|
||||
f.write(f"03. RAID Settings - StripeSize : {extract_value(hwinventory, 'StripeSize')}\n")
|
||||
f.write(f"04. RAID Settings - ReadCachePolicy : {extract_value(hwinventory, 'ReadCachePolicy')}\n")
|
||||
f.write(f"05. RAID Settings - WriteCachePolicy : {extract_value(hwinventory, 'WriteCachePolicy')}\n")
|
||||
f.write(f"06. RAID Settings - CheckConsistencyRate : {extract_value(storage_ctrl, 'CheckConsistencyRate')}\n")
|
||||
f.write(f"07. RAID Settings - PatrolReadMode : {extract_value(storage_ctrl, 'PatrolReadMode')}\n")
|
||||
f.write(f"08. RAID Settings - period : 168h\n")
|
||||
f.write(f"09. RAID Settings - Power Save : No\n")
|
||||
f.write(f"10. RAID Settings - JBODMODE : Controller does not support JBOD\n")
|
||||
f.write(f"11. RAID Settings - maxconcurrentpd : 240\n")
|
||||
|
||||
logging.info(f"✅ [{ip}] 저장 완료: {output_file.name}")
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# 실행 흐름 제어
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
logging.error(f"사용법: python {sys.argv[0]} <ip_file>")
|
||||
sys.exit(1)
|
||||
|
||||
ip_file = Path(sys.argv[1])
|
||||
if not ip_file.exists():
|
||||
logging.error(f"오류: IP 파일 '{ip_file}'이 존재하지 않습니다.")
|
||||
sys.exit(1)
|
||||
|
||||
output_dir = resolve_output_dir()
|
||||
start_time = time.time()
|
||||
|
||||
# IP 목록 읽기
|
||||
with open(ip_file, "r") as f:
|
||||
ips = [line.strip() for line in f if line.strip()]
|
||||
|
||||
# 각 IP별로 수집 실행
|
||||
for ip in ips:
|
||||
try:
|
||||
fetch_idrac_info(ip, output_dir)
|
||||
except Exception as e:
|
||||
logging.error(f"❌ [{ip}] 처리 중 예외 발생: {e}")
|
||||
|
||||
# 소요 시간 계산
|
||||
end_time = time.time()
|
||||
elapsed = end_time - start_time
|
||||
hours, rem = divmod(elapsed, 3600)
|
||||
minutes, seconds = divmod(rem, 60)
|
||||
|
||||
logging.info("="*50)
|
||||
logging.info("정보 수집 완료.")
|
||||
logging.info(f"총 소요 시간: {int(hours)}시간 {int(minutes)}분 {int(seconds)}초")
|
||||
logging.info(f"저장 경로: {output_dir}")
|
||||
logging.info("="*50)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -3,9 +3,17 @@ import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
import logging
|
||||
|
||||
from dotenv import load_dotenv, find_dotenv
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# .env 자동 탐색 로드 (현재 파일 기준 상위 디렉터리까지 검색)
|
||||
load_dotenv(find_dotenv())
|
||||
@@ -86,7 +94,7 @@ def fetch_idrac_info(idrac_ip: str, output_dir: Path) -> None:
|
||||
svc_tag = svc_tag_match.group(1) if svc_tag_match else None
|
||||
|
||||
if not svc_tag:
|
||||
print(f"Failed to retrieve SVC Tag for IP: {idrac_ip}")
|
||||
logging.error(f"Failed to retrieve SVC Tag for IP: {idrac_ip}")
|
||||
return
|
||||
|
||||
# 전체 하드웨어 인벤토리
|
||||
@@ -125,13 +133,13 @@ def fetch_idrac_info(idrac_ip: str, output_dir: Path) -> None:
|
||||
f.write(f"SERIALS: {';'.join(serials_only)}\n")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error processing IP {idrac_ip}: {e}")
|
||||
logging.error(f"Error processing IP {idrac_ip}: {e}")
|
||||
|
||||
|
||||
def main(ip_file: str) -> None:
|
||||
ip_path = Path(ip_file)
|
||||
if not ip_path.is_file():
|
||||
print(f"IP file {ip_file} does not exist.")
|
||||
logging.error(f"IP file {ip_file} does not exist.")
|
||||
return
|
||||
|
||||
output_dir = resolve_output_dir()
|
||||
@@ -146,14 +154,14 @@ def main(ip_file: str) -> None:
|
||||
ip = future_to_ip[future]
|
||||
try:
|
||||
future.result()
|
||||
print(f"✅ Completed: {ip}")
|
||||
logging.info(f"✅ Completed: {ip}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error processing {ip}: {e}")
|
||||
logging.error(f"❌ Error processing {ip}: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python GPU_Serial_v1.py <ip_file>")
|
||||
logging.error("Usage: python GPU_Serial_v1.py <ip_file>")
|
||||
sys.exit(1)
|
||||
main(sys.argv[1])
|
||||
|
||||
192
data/scripts/Intel_Server_info.py
Normal file
192
data/scripts/Intel_Server_info.py
Normal file
@@ -0,0 +1,192 @@
|
||||
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()
|
||||
174
data/scripts/JP_54EA_MAC_info.py
Normal file
174
data/scripts/JP_54EA_MAC_info.py
Normal file
@@ -0,0 +1,174 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
import logging
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# 저장 위치: data/scripts 아래에 있다면 → data/idrac_info 생성
|
||||
def resolve_output_dir() -> Path:
|
||||
here = Path(__file__).resolve().parent
|
||||
base = here.parent if here.name.lower() == "scripts" else here
|
||||
out = base / "idrac_info"
|
||||
out.mkdir(parents=True, exist_ok=True)
|
||||
return out
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# iDRAC 접속 계정
|
||||
IDRAC_USER = "root"
|
||||
IDRAC_PASS = "calvin"
|
||||
|
||||
|
||||
def run(cmd: list[str]) -> str:
|
||||
"""racadm 명령 실행 (stdout 수집)"""
|
||||
try:
|
||||
return subprocess.getoutput(" ".join(cmd))
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
|
||||
def parse_single_value(pattern: str, text: str) -> Optional[str]:
|
||||
"""단일 값 추출용"""
|
||||
m = re.search(pattern, text, flags=re.IGNORECASE)
|
||||
return m.group(1).strip() if m else None
|
||||
|
||||
|
||||
def find_mac_by_fqdd(fqdd: str, text: str) -> Optional[str]:
|
||||
"""
|
||||
swinventory 출력에서 FQDD = {fqdd} 라인을 찾고,
|
||||
그 주변(±10줄) 내에서 MAC 주소를 추출.
|
||||
"""
|
||||
lines = text.splitlines()
|
||||
for i, line in enumerate(lines):
|
||||
if f"FQDD = {fqdd}" in line:
|
||||
for j in range(max(0, i - 10), min(i + 10, len(lines))):
|
||||
m = re.search(r"([0-9A-Fa-f]{2}(?::[0-9A-Fa-f]{2}){5})", lines[j])
|
||||
if m:
|
||||
return m.group(1)
|
||||
return None
|
||||
|
||||
|
||||
def extract_vendors(hwinventory: str) -> tuple[str, str]:
|
||||
"""
|
||||
[InstanceID: DIMM...] 또는 [InstanceID: Disk.Bay...] 블록 내 Manufacturer 추출
|
||||
"""
|
||||
# Memory Vendors
|
||||
mem_vendors = re.findall(
|
||||
r"\[InstanceID:\s*DIMM[^\]]*\][^\[]*?Manufacturer\s*=\s*([^\n\r]+)",
|
||||
hwinventory,
|
||||
flags=re.IGNORECASE
|
||||
)
|
||||
mem_vendors = [v.strip() for v in mem_vendors if v.strip()]
|
||||
memory = ", ".join(sorted(set(mem_vendors))) if mem_vendors else "Not Found"
|
||||
|
||||
# SSD Vendors
|
||||
ssd_vendors = re.findall(
|
||||
r"\[InstanceID:\s*Disk\.Bay[^\]]*\][^\[]*?Manufacturer\s*=\s*([^\n\r]+)",
|
||||
hwinventory,
|
||||
flags=re.IGNORECASE
|
||||
)
|
||||
ssd_vendors = [v.strip() for v in ssd_vendors if v.strip()]
|
||||
ssd = ", ".join(sorted(set(ssd_vendors))) if ssd_vendors else "Not Found"
|
||||
|
||||
return memory, ssd
|
||||
|
||||
|
||||
def fetch_idrac_info_one(ip: str, output_dir: Path) -> None:
|
||||
"""단일 서버 iDRAC 정보 수집"""
|
||||
logging.info(f"[+] Collecting iDRAC info from {ip} ...")
|
||||
|
||||
getsysinfo = run(["racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "getsysinfo"])
|
||||
hwinventory = run(["racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "hwinventory"])
|
||||
swinventory = run(["racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "swinventory"])
|
||||
|
||||
# 서비스 태그
|
||||
svc_tag = parse_single_value(r"SVC\s*Tag\s*=\s*(\S+)", getsysinfo)
|
||||
if not svc_tag:
|
||||
logging.error(f"[!] Failed to retrieve SVC Tag for IP: {ip}")
|
||||
return
|
||||
|
||||
# iDRAC MAC
|
||||
idrac_mac = parse_single_value(r"MAC\s*Address\s*=\s*([0-9A-Fa-f:]{17})", getsysinfo)
|
||||
|
||||
# NIC.Integrated / Onboard MAC
|
||||
integrated_1 = parse_single_value(r"NIC\.Integrated\.1-1-1\s+Ethernet\s*=\s*([0-9A-Fa-f:]{17})", getsysinfo)
|
||||
integrated_2 = parse_single_value(r"NIC\.Integrated\.1-2-1\s+Ethernet\s*=\s*([0-9A-Fa-f:]{17})", getsysinfo)
|
||||
onboard_1 = parse_single_value(r"NIC\.Embedded\.1-1-1\s+Ethernet\s*=\s*([0-9A-Fa-f:]{17})", getsysinfo)
|
||||
onboard_2 = parse_single_value(r"NIC\.Embedded\.2-1-1\s+Ethernet\s*=\s*([0-9A-Fa-f:]{17})", getsysinfo)
|
||||
|
||||
# NIC Slot별 MAC
|
||||
NIC_Slot_2_1 = find_mac_by_fqdd("NIC.Slot.2-1-1", swinventory)
|
||||
NIC_Slot_2_2 = find_mac_by_fqdd("NIC.Slot.2-2-1", swinventory)
|
||||
NIC_Slot_3_1 = find_mac_by_fqdd("NIC.Slot.3-1-1", swinventory)
|
||||
NIC_Slot_3_2 = find_mac_by_fqdd("NIC.Slot.3-2-1", swinventory)
|
||||
|
||||
# 메모리 / SSD 제조사
|
||||
memory, ssd = extract_vendors(hwinventory)
|
||||
|
||||
# 결과 파일 저장
|
||||
out_file = output_dir / f"{svc_tag}.txt"
|
||||
with out_file.open("w", encoding="utf-8", newline="\n") as f:
|
||||
f.write(f"{svc_tag}\n")
|
||||
f.write(f"{integrated_1 or ''}\n")
|
||||
f.write(f"{integrated_2 or ''}\n")
|
||||
f.write(f"{onboard_1 or ''}\n")
|
||||
f.write(f"{onboard_2 or ''}\n")
|
||||
f.write(f"{NIC_Slot_2_1 or ''}\n")
|
||||
f.write(f"{NIC_Slot_2_2 or ''}\n")
|
||||
f.write(f"{idrac_mac or ''}\n")
|
||||
f.write(f"{memory}\n")
|
||||
f.write(f"{ssd}\n")
|
||||
|
||||
logging.info(f"[✔] {svc_tag} ({ip}) info saved.")
|
||||
|
||||
|
||||
def main(ip_file: str) -> None:
|
||||
ip_path = Path(ip_file)
|
||||
if not ip_path.is_file():
|
||||
logging.error(f"[!] IP file {ip_file} does not exist.")
|
||||
return
|
||||
|
||||
output_dir = resolve_output_dir()
|
||||
ips = [line.strip() for line in ip_path.read_text(encoding="utf-8").splitlines() if line.strip()]
|
||||
if not ips:
|
||||
logging.error("[!] No IP addresses found in the file.")
|
||||
return
|
||||
|
||||
for ip in ips:
|
||||
try:
|
||||
fetch_idrac_info_one(ip, output_dir)
|
||||
except Exception as e:
|
||||
logging.error(f"[!] Error processing {ip}: {e}")
|
||||
|
||||
try:
|
||||
ip_path.unlink(missing_ok=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
logging.info("\n정보 수집 완료.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys, time
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
logging.error("Usage: python script.py <ip_file>")
|
||||
sys.exit(1)
|
||||
|
||||
start = time.time()
|
||||
main(sys.argv[1])
|
||||
end = time.time()
|
||||
elapsed = int(end - start)
|
||||
h, m, s = elapsed // 3600, (elapsed % 3600) // 60, elapsed % 60
|
||||
logging.info(f"수집 완료 시간: {h}시간 {m}분 {s}초")
|
||||
234
data/scripts/MAC_info.py
Normal file
234
data/scripts/MAC_info.py
Normal file
@@ -0,0 +1,234 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Optional, List
|
||||
import logging
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# 출력 디렉토리 결정
|
||||
def resolve_output_dir() -> Path:
|
||||
here = Path(__file__).resolve().parent
|
||||
if here.name.lower() == "scripts" and here.parent.name.lower() == "data":
|
||||
base = here.parent
|
||||
else:
|
||||
base = here.parent
|
||||
|
||||
out = base / "idrac_info"
|
||||
out.mkdir(parents=True, exist_ok=True)
|
||||
return out
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# iDRAC 계정
|
||||
IDRAC_USER = "root"
|
||||
IDRAC_PASS = "calvin"
|
||||
|
||||
|
||||
def run(cmd: list[str]) -> str:
|
||||
"""racadm 명령 실행 (stdout만 반환)"""
|
||||
try:
|
||||
return subprocess.getoutput(" ".join(cmd))
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
|
||||
def parse_single_value(pattern: str, text: str) -> Optional[str]:
|
||||
m = re.search(pattern, text, flags=re.IGNORECASE)
|
||||
return m.group(1).strip() if m else None
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# NIC MAC 수집 (가변 포트 대응)
|
||||
def extract_nic_macs(text: str, nic_type: str) -> List[str]:
|
||||
"""
|
||||
nic_type:
|
||||
- 'Integrated'
|
||||
- 'Embedded'
|
||||
"""
|
||||
pattern = re.compile(
|
||||
rf"NIC\.{nic_type}\.\d+-\d+-\d+.*?([0-9A-Fa-f]{{2}}(?::[0-9A-Fa-f]{{2}}){{5}})",
|
||||
re.IGNORECASE
|
||||
)
|
||||
return sorted(set(m.group(1) for m in pattern.finditer(text)))
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# hwinventory 블록 기반 Manufacturer 추출 (DIMM)
|
||||
def extract_memory_vendors(hwinventory: str) -> List[str]:
|
||||
vendors = set()
|
||||
blocks = re.split(r"\n\s*\n", hwinventory)
|
||||
|
||||
for block in blocks:
|
||||
if "[InstanceID: DIMM." in block:
|
||||
m = re.search(r"Manufacturer\s*=\s*(.+)", block, re.IGNORECASE)
|
||||
if m:
|
||||
vendors.add(m.group(1).strip())
|
||||
|
||||
return sorted(vendors)
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# BOSS 디스크 Vendor 추출
|
||||
def extract_boss_vendors(hwinventory: str) -> List[str]:
|
||||
vendors = set()
|
||||
blocks = re.split(r"\n\s*\n", hwinventory)
|
||||
|
||||
for block in blocks:
|
||||
if "BOSS." in block:
|
||||
m = re.search(r"Manufacturer\s*=\s*(.+)", block, re.IGNORECASE)
|
||||
if m:
|
||||
vendors.add(m.group(1).strip())
|
||||
|
||||
return sorted(vendors)
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# 일반 Disk Vendor (BOSS 제외)
|
||||
DISK_PREFIXES = [
|
||||
"Disk.Bay.",
|
||||
"Disk.M.2.",
|
||||
"Disk.Direct.",
|
||||
"Disk.Slot."
|
||||
]
|
||||
|
||||
|
||||
def extract_disk_vendors_excluding_boss(hwinventory: str) -> List[str]:
|
||||
vendors = set()
|
||||
blocks = re.split(r"\n\s*\n", hwinventory)
|
||||
|
||||
for block in blocks:
|
||||
if "BOSS." in block:
|
||||
continue
|
||||
|
||||
for prefix in DISK_PREFIXES:
|
||||
if f"[InstanceID: {prefix}" in block:
|
||||
m = re.search(r"Manufacturer\s*=\s*(.+)", block, re.IGNORECASE)
|
||||
if m:
|
||||
vendors.add(m.group(1).strip())
|
||||
|
||||
return sorted(vendors)
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
def fetch_idrac_info_one(ip: str, output_dir: Path) -> None:
|
||||
getsysinfo = run([
|
||||
"racadm", "-r", ip,
|
||||
"-u", IDRAC_USER,
|
||||
"-p", IDRAC_PASS,
|
||||
"getsysinfo"
|
||||
])
|
||||
|
||||
hwinventory = run([
|
||||
"racadm", "-r", ip,
|
||||
"-u", IDRAC_USER,
|
||||
"-p", IDRAC_PASS,
|
||||
"hwinventory"
|
||||
])
|
||||
|
||||
# ── Service Tag
|
||||
svc_tag = parse_single_value(r"SVC\s*Tag\s*=\s*(\S+)", getsysinfo)
|
||||
if not svc_tag:
|
||||
logging.error(f"[ERROR] SVC Tag 수집 실패: {ip}")
|
||||
return
|
||||
|
||||
# ── iDRAC MAC
|
||||
idrac_mac = parse_single_value(
|
||||
r"MAC Address\s*=\s*([0-9A-Fa-f:]{17})", getsysinfo
|
||||
)
|
||||
|
||||
# ── NIC MAC
|
||||
integrated_macs = extract_nic_macs(getsysinfo, "Integrated")
|
||||
embedded_macs = extract_nic_macs(getsysinfo, "Embedded")
|
||||
|
||||
# ── Vendors
|
||||
memory_vendors = extract_memory_vendors(hwinventory)
|
||||
disk_vendors = extract_disk_vendors_excluding_boss(hwinventory)
|
||||
boss_vendors = extract_boss_vendors(hwinventory)
|
||||
|
||||
# ── 결과 파일 저장
|
||||
out_file = output_dir / f"{svc_tag}.txt"
|
||||
with out_file.open("w", encoding="utf-8", newline="\n") as f:
|
||||
f.write(f"{svc_tag}\n")
|
||||
|
||||
for mac in integrated_macs:
|
||||
f.write(f"{mac}\n")
|
||||
|
||||
for mac in embedded_macs:
|
||||
f.write(f"{mac}\n")
|
||||
|
||||
f.write(f"{idrac_mac or ''}\n")
|
||||
|
||||
# Memory Vendors
|
||||
for v in memory_vendors:
|
||||
f.write(f"{v}\n")
|
||||
|
||||
# Disk Vendors (일반)
|
||||
for v in disk_vendors:
|
||||
f.write(f"{v}\n")
|
||||
|
||||
# BOSS Vendors (있을 때만, 벤더명만)
|
||||
for v in boss_vendors:
|
||||
f.write(f"{v}\n")
|
||||
|
||||
logging.info(f"[OK] {svc_tag} 수집 완료")
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
def main(ip_file: str) -> None:
|
||||
ip_path = Path(ip_file)
|
||||
if not ip_path.is_file():
|
||||
logging.error(f"[ERROR] IP 파일 없음: {ip_file}")
|
||||
return
|
||||
|
||||
output_dir = resolve_output_dir()
|
||||
|
||||
ips = [
|
||||
line.strip()
|
||||
for line in ip_path.read_text(encoding="utf-8").splitlines()
|
||||
if line.strip()
|
||||
]
|
||||
|
||||
if not ips:
|
||||
logging.error("[ERROR] IP 목록이 비어 있습니다.")
|
||||
return
|
||||
|
||||
for ip in ips:
|
||||
try:
|
||||
fetch_idrac_info_one(ip, output_dir)
|
||||
except Exception as e:
|
||||
logging.error(f"[ERROR] {ip} 처리 실패: {e}")
|
||||
|
||||
# Bash 스크립트와 동일하게 입력 IP 파일 삭제
|
||||
try:
|
||||
ip_path.unlink(missing_ok=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
logging.info("정보 수집 완료.")
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
import time
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
logging.error("Usage: python script.py <ip_file>")
|
||||
sys.exit(1)
|
||||
|
||||
start = time.time()
|
||||
main(sys.argv[1])
|
||||
elapsed = int(time.time() - start)
|
||||
|
||||
h, m, s = elapsed // 3600, (elapsed % 3600) // 60, elapsed % 60
|
||||
logging.info(f"수집 완료 시간: {h} 시간, {m} 분, {s} 초.")
|
||||
@@ -3,6 +3,14 @@ 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()
|
||||
@@ -18,7 +26,7 @@ def fetch_idrac_info(idrac_ip, output_dir):
|
||||
svc_tag = svc_tag_match.group(1) if svc_tag_match else None
|
||||
|
||||
if not svc_tag:
|
||||
print(f"Failed to retrieve SVC Tag for IP: {idrac_ip}")
|
||||
logging.error(f"Failed to retrieve SVC Tag for IP: {idrac_ip}")
|
||||
return
|
||||
|
||||
# InfiniBand.VndrConfigPage 목록 가져오기
|
||||
@@ -58,13 +66,15 @@ def fetch_idrac_info(idrac_ip, output_dir):
|
||||
# 모든 PortGUID를 "GUID: 0x<GUID1>;0x<GUID2>" 형식으로 저장
|
||||
if hex_guid_list:
|
||||
f.write(f"GUID: {';'.join(hex_guid_list)}\n")
|
||||
|
||||
logging.info(f"✅ Completed: {idrac_ip}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error processing IP {idrac_ip}: {e}")
|
||||
logging.error(f"Error processing IP {idrac_ip}: {e}")
|
||||
|
||||
def main(ip_file):
|
||||
if not os.path.isfile(ip_file):
|
||||
print(f"IP file {ip_file} does not exist.")
|
||||
logging.error(f"IP file {ip_file} does not exist.")
|
||||
return
|
||||
|
||||
output_dir = "/app/idrac_info/idrac_info"
|
||||
@@ -80,12 +90,12 @@ def main(ip_file):
|
||||
try:
|
||||
future.result()
|
||||
except Exception as e:
|
||||
print(f"Error processing task: {e}")
|
||||
logging.error(f"Error processing task: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python script.py <ip_file>")
|
||||
logging.error("Usage: python script.py <ip_file>")
|
||||
sys.exit(1)
|
||||
|
||||
ip_file = sys.argv[1]
|
||||
|
||||
@@ -3,9 +3,17 @@ import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
import logging
|
||||
|
||||
from dotenv import load_dotenv, find_dotenv
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# .env 자동 탐색 로드 (현재 파일 기준 상위 디렉터리까지 검색)
|
||||
load_dotenv(find_dotenv())
|
||||
@@ -47,7 +55,7 @@ def fetch_idrac_info(idrac_ip: str, output_dir: Path) -> None:
|
||||
svc_tag = svc_tag_match.group(1) if svc_tag_match else None
|
||||
|
||||
if not svc_tag:
|
||||
print(f"Failed to retrieve SVC Tag for IP: {idrac_ip}")
|
||||
logging.error(f"Failed to retrieve SVC Tag for IP: {idrac_ip}")
|
||||
return
|
||||
|
||||
# InfiniBand.VndrConfigPage 목록 가져오기
|
||||
@@ -110,13 +118,13 @@ def fetch_idrac_info(idrac_ip: str, output_dir: Path) -> None:
|
||||
f.write(f"GUID: {';'.join(hex_guid_list)}\n")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error processing IP {idrac_ip}: {e}")
|
||||
logging.error(f"Error processing IP {idrac_ip}: {e}")
|
||||
|
||||
|
||||
def main(ip_file: str) -> None:
|
||||
ip_path = Path(ip_file)
|
||||
if not ip_path.is_file():
|
||||
print(f"IP file {ip_file} does not exist.")
|
||||
logging.error(f"IP file {ip_file} does not exist.")
|
||||
return
|
||||
|
||||
output_dir = resolve_output_dir() # ← 여기서 OS 무관 저장 위치 확정 (data/idrac_info)
|
||||
@@ -133,15 +141,15 @@ def main(ip_file: str) -> None:
|
||||
ip = future_to_ip[future]
|
||||
try:
|
||||
future.result()
|
||||
print(f"✅ Completed: {ip}")
|
||||
logging.info(f"Completed: {ip}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error processing {ip}: {e}")
|
||||
logging.error(f"Error processing {ip}: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python script.py <ip_file>")
|
||||
logging.error("Usage: python script.py <ip_file>")
|
||||
sys.exit(1)
|
||||
|
||||
main(sys.argv[1])
|
||||
|
||||
166
data/scripts/SP_18EA_MAC_info.py
Normal file
166
data/scripts/SP_18EA_MAC_info.py
Normal file
@@ -0,0 +1,166 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
import logging
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# 저장 위치: data/scripts 아래에 있다면 → data/idrac_info 생성
|
||||
def resolve_output_dir() -> Path:
|
||||
here = Path(__file__).resolve().parent
|
||||
base = here.parent if here.name.lower() == "scripts" else here
|
||||
out = base / "idrac_info"
|
||||
out.mkdir(parents=True, exist_ok=True)
|
||||
return out
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# iDRAC 접속 계정
|
||||
IDRAC_USER = "root"
|
||||
IDRAC_PASS = "calvin"
|
||||
|
||||
|
||||
def run(cmd: list[str]) -> str:
|
||||
"""racadm 명령 실행 (stdout 수집)"""
|
||||
try:
|
||||
return subprocess.getoutput(" ".join(cmd))
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
|
||||
def parse_single_value(pattern: str, text: str) -> Optional[str]:
|
||||
"""단일 값 추출용"""
|
||||
m = re.search(pattern, text, flags=re.IGNORECASE)
|
||||
return m.group(1).strip() if m else None
|
||||
|
||||
|
||||
def find_mac_by_fqdd(fqdd: str, text: str) -> Optional[str]:
|
||||
"""
|
||||
swinventory 출력에서 FQDD = {fqdd} 라인을 찾고,
|
||||
그 주변(±10줄) 내에서 MAC 주소를 추출.
|
||||
"""
|
||||
lines = text.splitlines()
|
||||
for i, line in enumerate(lines):
|
||||
if f"FQDD = {fqdd}" in line:
|
||||
for j in range(max(0, i - 10), min(i + 10, len(lines))):
|
||||
m = re.search(r"([0-9A-Fa-f]{2}(?::[0-9A-Fa-f]{2}){5})", lines[j])
|
||||
if m:
|
||||
return m.group(1)
|
||||
return None
|
||||
|
||||
|
||||
def extract_vendors(hwinventory: str) -> tuple[str, str]:
|
||||
"""
|
||||
[InstanceID: DIMM...] 또는 [InstanceID: Disk.Bay...] 블록 내 Manufacturer 추출
|
||||
"""
|
||||
# Memory Vendors
|
||||
mem_vendors = re.findall(
|
||||
r"\[InstanceID:\s*DIMM[^\]]*\][^\[]*?Manufacturer\s*=\s*([^\n\r]+)",
|
||||
hwinventory,
|
||||
flags=re.IGNORECASE
|
||||
)
|
||||
mem_vendors = [v.strip() for v in mem_vendors if v.strip()]
|
||||
memory = ", ".join(sorted(set(mem_vendors))) if mem_vendors else "Not Found"
|
||||
|
||||
# SSD Vendors
|
||||
ssd_vendors = re.findall(
|
||||
r"\[InstanceID:\s*Disk\.Bay[^\]]*\][^\[]*?Manufacturer\s*=\s*([^\n\r]+)",
|
||||
hwinventory,
|
||||
flags=re.IGNORECASE
|
||||
)
|
||||
ssd_vendors = [v.strip() for v in ssd_vendors if v.strip()]
|
||||
ssd = ", ".join(sorted(set(ssd_vendors))) if ssd_vendors else "Not Found"
|
||||
|
||||
return memory, ssd
|
||||
|
||||
|
||||
def fetch_idrac_info_one(ip: str, output_dir: Path) -> None:
|
||||
"""단일 서버 iDRAC 정보 수집"""
|
||||
logging.info(f"[+] Collecting iDRAC info from {ip} ...")
|
||||
|
||||
getsysinfo = run(["racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "getsysinfo"])
|
||||
hwinventory = run(["racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "hwinventory"])
|
||||
swinventory = run(["racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "swinventory"])
|
||||
|
||||
# 서비스 태그
|
||||
svc_tag = parse_single_value(r"SVC\s*Tag\s*=\s*(\S+)", getsysinfo)
|
||||
if not svc_tag:
|
||||
logging.error(f"[!] Failed to retrieve SVC Tag for IP: {ip}")
|
||||
return
|
||||
|
||||
# iDRAC MAC
|
||||
idrac_mac = parse_single_value(r"MAC\s*Address\s*=\s*([0-9A-Fa-f:]{17})", getsysinfo)
|
||||
|
||||
# NIC.Integrated / Onboard MAC
|
||||
integrated_1 = parse_single_value(r"NIC\.Integrated\.1-1-1\s+Ethernet\s*=\s*([0-9A-Fa-f:]{17})", getsysinfo)
|
||||
integrated_2 = parse_single_value(r"NIC\.Integrated\.1-2-1\s+Ethernet\s*=\s*([0-9A-Fa-f:]{17})", getsysinfo)
|
||||
onboard_1 = parse_single_value(r"NIC\.Embedded\.1-1-1\s+Ethernet\s*=\s*([0-9A-Fa-f:]{17})", getsysinfo)
|
||||
onboard_2 = parse_single_value(r"NIC\.Embedded\.2-1-1\s+Ethernet\s*=\s*([0-9A-Fa-f:]{17})", getsysinfo)
|
||||
|
||||
# 메모리 / SSD 제조사
|
||||
memory, ssd = extract_vendors(hwinventory)
|
||||
|
||||
# 결과 파일 저장
|
||||
out_file = output_dir / f"{svc_tag}.txt"
|
||||
with out_file.open("w", encoding="utf-8", newline="\n") as f:
|
||||
f.write(f"{svc_tag}\n")
|
||||
f.write(f"{integrated_1 or ''}\n")
|
||||
f.write(f"{integrated_2 or ''}\n")
|
||||
f.write(f"{onboard_1 or ''}\n")
|
||||
f.write(f"{onboard_2 or ''}\n")
|
||||
f.write(f"{idrac_mac or ''}\n")
|
||||
f.write(f"{memory}\n")
|
||||
f.write(f"{ssd}\n")
|
||||
|
||||
logging.info(f"[✔] {svc_tag} ({ip}) info saved.")
|
||||
|
||||
|
||||
def main(ip_file: str) -> None:
|
||||
ip_path = Path(ip_file)
|
||||
if not ip_path.is_file():
|
||||
logging.error(f"[!] IP file {ip_file} does not exist.")
|
||||
return
|
||||
|
||||
output_dir = resolve_output_dir()
|
||||
ips = [line.strip() for line in ip_path.read_text(encoding="utf-8").splitlines() if line.strip()]
|
||||
if not ips:
|
||||
logging.error("[!] No IP addresses found in the file.")
|
||||
return
|
||||
|
||||
for ip in ips:
|
||||
try:
|
||||
fetch_idrac_info_one(ip, output_dir)
|
||||
except Exception as e:
|
||||
logging.error(f"[!] Error processing {ip}: {e}")
|
||||
|
||||
try:
|
||||
ip_path.unlink(missing_ok=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
logging.info("\n정보 수집 완료.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys, time
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
logging.error("Usage: python script.py <ip_file>")
|
||||
sys.exit(1)
|
||||
|
||||
start = time.time()
|
||||
main(sys.argv[1])
|
||||
end = time.time()
|
||||
elapsed = int(end - start)
|
||||
h, m, s = elapsed // 3600, (elapsed % 3600) // 60, elapsed % 60
|
||||
logging.info(f"수집 완료 시간: {h}시간 {m}분 {s}초")
|
||||
@@ -6,37 +6,43 @@ import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
import logging
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# 저장 위치: 이 파일이 data/scripts/ 아래 있다면 → data/idrac_info
|
||||
# 그 외 위치여도 이 파일의 상위 폴더에 idrac_info 생성
|
||||
# 저장 위치 결정
|
||||
def resolve_output_dir() -> Path:
|
||||
here = Path(__file__).resolve().parent # 예: .../data/scripts
|
||||
here = Path(__file__).resolve().parent
|
||||
if here.name.lower() == "scripts" and here.parent.name.lower() == "data":
|
||||
base = here.parent # 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
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# 사용자 이름 및 비밀번호 (Bash 스크립트와 동일하게 하드코딩)
|
||||
# iDRAC 계정
|
||||
IDRAC_USER = "root"
|
||||
IDRAC_PASS = "calvin"
|
||||
|
||||
|
||||
def run(cmd: list[str]) -> str:
|
||||
"""racadm 호출을 간단히 실행 (stdout만 수집)"""
|
||||
"""racadm 명령 실행 (stdout만 반환)"""
|
||||
try:
|
||||
# join하여 getoutput로 호출 (Bash와 비슷한 동작)
|
||||
return subprocess.getoutput(" ".join(cmd))
|
||||
except Exception as e:
|
||||
return f"" # 실패 시 빈 문자열
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
|
||||
def parse_single_value(pattern: str, text: str) -> Optional[str]:
|
||||
@@ -44,61 +50,81 @@ def parse_single_value(pattern: str, text: str) -> Optional[str]:
|
||||
return m.group(1).strip() if m else None
|
||||
|
||||
|
||||
def parse_mac_list_from_lines(text: str, fqdd_key: str) -> Optional[str]:
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# hwinventory 블록 기반 Manufacturer 추출 (핵심 수정 부분)
|
||||
def extract_manufacturers(hwinventory: str, instance_prefix: str) -> list[str]:
|
||||
"""
|
||||
특정 FQDD 라인을 찾아 MAC 주소를 반환하는 간단한 도우미.
|
||||
(Bash의 grep/awk 파이프를 정규표현식으로 대체)
|
||||
instance_prefix:
|
||||
- 'DIMM.' → 메모리
|
||||
- 'Disk.Bay.' → 디스크
|
||||
"""
|
||||
# MAC 주소 패턴
|
||||
mac_pat = r"([0-9A-Fa-f]{2}(?::[0-9A-Fa-f]{2}){5})"
|
||||
# 해당 FQDD 문자열이 포함된 줄과 가까운 곳에서 MAC을 찾는 간단한 방식
|
||||
# (원 스크립트는 awk로 이전 줄을 보는 등 상세하지만 여기선 단순화)
|
||||
block_pat = rf"{re.escape(fqdd_key)}.*?{mac_pat}"
|
||||
m = re.search(block_pat, text, flags=re.IGNORECASE | re.DOTALL)
|
||||
if m:
|
||||
return m.group(1)
|
||||
# 라인 전체에서 MAC만 스캔하는 fallback
|
||||
m2 = re.search(mac_pat, text, flags=re.IGNORECASE)
|
||||
return m2.group(1) if m2 else None
|
||||
vendors = []
|
||||
|
||||
blocks = re.split(r"\n\s*\n", hwinventory)
|
||||
for block in blocks:
|
||||
if f"[InstanceID: {instance_prefix}" in block:
|
||||
m = re.search(r"Manufacturer\s*=\s*(.+)", block, re.IGNORECASE)
|
||||
if m:
|
||||
vendors.append(m.group(1).strip())
|
||||
|
||||
return vendors
|
||||
|
||||
|
||||
def fetch_idrac_info_one(ip: str, output_dir: Path) -> None:
|
||||
# getsysinfo / hwinventory 호출
|
||||
getsysinfo = run(["racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "getsysinfo"])
|
||||
hwinventory = run(["racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "hwinventory"])
|
||||
getsysinfo = run([
|
||||
"racadm", "-r", ip,
|
||||
"-u", IDRAC_USER,
|
||||
"-p", IDRAC_PASS,
|
||||
"getsysinfo"
|
||||
])
|
||||
|
||||
# 서비스 태그
|
||||
hwinventory = run([
|
||||
"racadm", "-r", ip,
|
||||
"-u", IDRAC_USER,
|
||||
"-p", IDRAC_PASS,
|
||||
"hwinventory"
|
||||
])
|
||||
|
||||
# ── Service Tag
|
||||
svc_tag = parse_single_value(r"SVC\s*Tag\s*=\s*(\S+)", getsysinfo)
|
||||
if not svc_tag:
|
||||
print(f"Failed to retrieve SVC Tag for IP: {ip}")
|
||||
logging.error(f"[ERROR] SVC Tag 수집 실패: {ip}")
|
||||
return
|
||||
|
||||
# iDRAC MAC
|
||||
idrac_mac = parse_single_value(r"MAC Address\s*=\s*([0-9A-Fa-f:]{17})", getsysinfo)
|
||||
# ── iDRAC MAC
|
||||
idrac_mac = parse_single_value(
|
||||
r"MAC Address\s*=\s*([0-9A-Fa-f:]{17})", getsysinfo
|
||||
)
|
||||
|
||||
# NIC.Integrated MAC (1-1-1, 1-2-1)
|
||||
integrated_1 = parse_single_value(r"NIC\.Integrated\.1-1-1.*?([0-9A-Fa-f]{2}(?::[0-9A-Fa-f]{2}){5})",
|
||||
getsysinfo)
|
||||
integrated_2 = parse_single_value(r"NIC\.Integrated\.1-2-1.*?([0-9A-Fa-f]{2}(?::[0-9A-Fa-f]{2}){5})",
|
||||
getsysinfo)
|
||||
# ── Integrated NIC
|
||||
integrated_1 = parse_single_value(
|
||||
r"NIC\.Integrated\.1-1-1.*?([0-9A-Fa-f]{2}(?::[0-9A-Fa-f]{2}){5})",
|
||||
getsysinfo
|
||||
)
|
||||
integrated_2 = parse_single_value(
|
||||
r"NIC\.Integrated\.1-2-1.*?([0-9A-Fa-f]{2}(?::[0-9A-Fa-f]{2}){5})",
|
||||
getsysinfo
|
||||
)
|
||||
|
||||
# Onboard MAC (Embedded 1-1-1, 2-1-1)
|
||||
onboard_1 = parse_single_value(r"NIC\.Embedded\.1-1-1.*?([0-9A-Fa-f]{2}(?::[0-9A-Fa-f]{2}){5})",
|
||||
getsysinfo)
|
||||
onboard_2 = parse_single_value(r"NIC\.Embedded\.2-1-1.*?([0-9A-Fa-f]{2}(?::[0-9A-Fa-f]{2}){5})",
|
||||
getsysinfo)
|
||||
# ── Embedded NIC
|
||||
onboard_1 = parse_single_value(
|
||||
r"NIC\.Embedded\.1-1-1.*?([0-9A-Fa-f]{2}(?::[0-9A-Fa-f]{2}){5})",
|
||||
getsysinfo
|
||||
)
|
||||
onboard_2 = parse_single_value(
|
||||
r"NIC\.Embedded\.2-1-1.*?([0-9A-Fa-f]{2}(?::[0-9A-Fa-f]{2}){5})",
|
||||
getsysinfo
|
||||
)
|
||||
|
||||
# 벤더(메모리/SSD) 첫 글자 모음 (원 스크립트는 uniq+sort+cut -c1)
|
||||
# 여기서는 Manufacturer= 값을 수집해 첫 글자만 취합 후 중복 제거.
|
||||
mem_vendors = re.findall(r"DIMM.*?Manufacturer\s*=\s*(.+)", hwinventory, flags=re.IGNORECASE)
|
||||
mem_vendors = [v.strip() for v in mem_vendors if v.strip()]
|
||||
memory = "".join(sorted(set(v[0] for v in mem_vendors if v)))
|
||||
# ─────────────────────────────────────────────
|
||||
# Memory / Disk Vendor (수정 완료)
|
||||
mem_vendors = sorted(set(extract_manufacturers(hwinventory, "DIMM.")))
|
||||
ssd_vendors = sorted(set(extract_manufacturers(hwinventory, "Disk.Bay.")))
|
||||
|
||||
ssd_vendors = re.findall(r"Disk\.Bay.*?Manufacturer\s*=\s*(.+)", hwinventory, flags=re.IGNORECASE)
|
||||
ssd_vendors = [v.strip() for v in ssd_vendors if v.strip()]
|
||||
ssd = "".join(sorted(set(v[0] for v in ssd_vendors if v)))
|
||||
memory = "\n".join(mem_vendors)
|
||||
ssd = "\n".join(ssd_vendors)
|
||||
|
||||
# 파일 저장
|
||||
# ── 결과 파일 저장
|
||||
out_file = output_dir / f"{svc_tag}.txt"
|
||||
with out_file.open("w", encoding="utf-8", newline="\n") as f:
|
||||
f.write(f"{svc_tag}\n")
|
||||
@@ -110,47 +136,53 @@ def fetch_idrac_info_one(ip: str, output_dir: Path) -> None:
|
||||
f.write(f"{memory}\n")
|
||||
f.write(f"{ssd}\n")
|
||||
|
||||
logging.info(f"[OK] {svc_tag} 수집 완료")
|
||||
|
||||
|
||||
def main(ip_file: str) -> None:
|
||||
ip_path = Path(ip_file)
|
||||
if not ip_path.is_file():
|
||||
print(f"IP file {ip_file} does not exist.")
|
||||
logging.error(f"[ERROR] IP 파일 없음: {ip_file}")
|
||||
return
|
||||
|
||||
output_dir = resolve_output_dir()
|
||||
|
||||
# Bash 스크립트는 파일 전체를 cat 하여 '하나의 IP'로 사용했지만,
|
||||
# 여기서는 줄 단위로 모두 처리(한 줄만 있어도 동일하게 동작).
|
||||
ips = [line.strip() for line in ip_path.read_text(encoding="utf-8").splitlines() if line.strip()]
|
||||
ips = [
|
||||
line.strip()
|
||||
for line in ip_path.read_text(encoding="utf-8").splitlines()
|
||||
if line.strip()
|
||||
]
|
||||
|
||||
if not ips:
|
||||
print("No IP addresses found in the file.")
|
||||
logging.error("[ERROR] IP 목록이 비어 있습니다.")
|
||||
return
|
||||
|
||||
# 순차 처리 (필요하면 ThreadPoolExecutor로 병렬화 가능)
|
||||
for ip in ips:
|
||||
try:
|
||||
fetch_idrac_info_one(ip, output_dir)
|
||||
except Exception as e:
|
||||
print(f"Error processing {ip}: {e}")
|
||||
logging.error(f"[ERROR] {ip} 처리 실패: {e}")
|
||||
|
||||
# 원본 Bash는 마지막에 입력 파일 삭제: rm -f $IP_FILE
|
||||
# 원본 Bash 스크립트 동작 유지
|
||||
try:
|
||||
ip_path.unlink(missing_ok=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
print("정보 수집 완료.")
|
||||
logging.info("정보 수집 완료.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys, time
|
||||
import sys
|
||||
import time
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python script.py <ip_file>")
|
||||
logging.error("Usage: python script.py <ip_file>")
|
||||
sys.exit(1)
|
||||
|
||||
start = time.time()
|
||||
main(sys.argv[1])
|
||||
end = time.time()
|
||||
elapsed = int(end - start)
|
||||
elapsed = int(time.time() - start)
|
||||
|
||||
h, m, s = elapsed // 3600, (elapsed % 3600) // 60, elapsed % 60
|
||||
print(f"수집 완료 시간: {h} 시간, {m} 분, {s} 초.")
|
||||
logging.info(f"수집 완료 시간: {h} 시간, {m} 분, {s} 초.")
|
||||
|
||||
@@ -6,7 +6,14 @@ import re
|
||||
import time
|
||||
import subprocess
|
||||
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'
|
||||
)
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# 저장 위치: 이 파일이 data/scripts/ 아래 있으면 → data/idrac_info
|
||||
@@ -168,7 +175,7 @@ def fetch_idrac_info(ip: str, output_dir: Path) -> None:
|
||||
r"Port")
|
||||
|
||||
if not svc_tag:
|
||||
print(f"Failed to retrieve SVC Tag for IP: {ip}")
|
||||
logging.error(f"Failed to retrieve SVC Tag for IP: {ip}")
|
||||
return
|
||||
|
||||
out_file = output_dir / f"{svc_tag}.txt"
|
||||
@@ -227,7 +234,7 @@ def fetch_idrac_info(ip: str, output_dir: Path) -> None:
|
||||
def main(ip_file: str) -> None:
|
||||
ip_path = Path(ip_file)
|
||||
if not ip_path.is_file():
|
||||
print(f"Usage: python script.py <ip_file>\nIP file {ip_file} does not exist.")
|
||||
logging.error(f"Usage: python script.py <ip_file>\nIP file {ip_file} does not exist.")
|
||||
return
|
||||
|
||||
output_dir = resolve_output_dir()
|
||||
@@ -237,7 +244,7 @@ def main(ip_file: str) -> None:
|
||||
lines = [ln.strip() for ln in ip_path.read_text(encoding="utf-8", errors="ignore").splitlines()]
|
||||
ip = next((ln for ln in lines if ln), None)
|
||||
if not ip:
|
||||
print("No IP address found in the file.")
|
||||
logging.error("No IP address found in the file.")
|
||||
return
|
||||
|
||||
start = time.time()
|
||||
@@ -252,13 +259,13 @@ def main(ip_file: str) -> None:
|
||||
|
||||
elapsed = int(end - start)
|
||||
h, m, s = elapsed // 3600, (elapsed % 3600) // 60, elapsed % 60
|
||||
print("정보 수집 완료.")
|
||||
print(f"수집 완료 시간: {h} 시간, {m} 분, {s} 초.")
|
||||
logging.info("정보 수집 완료.")
|
||||
logging.info(f"수집 완료 시간: {h} 시간, {m} 분, {s} 초.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python script.py <ip_file>")
|
||||
logging.error("Usage: python script.py <ip_file>")
|
||||
sys.exit(1)
|
||||
main(sys.argv[1])
|
||||
@@ -1,316 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 사용자 이름 및 비밀번호 설정
|
||||
IDRAC_USER="root"
|
||||
IDRAC_PASS="calvin"
|
||||
|
||||
# IP 주소 파일 경로 인자 받기
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 <ip_file>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IP_FILE=$1
|
||||
|
||||
if [ ! -f "$IP_FILE" ]; then
|
||||
echo "IP file $IP_FILE does not exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 정보 저장 디렉터리 설정
|
||||
OUTPUT_DIR="idrac_info"
|
||||
mkdir -p $OUTPUT_DIR
|
||||
|
||||
# iDRAC 정보를 가져오는 함수 정의
|
||||
fetch_idrac_info() {
|
||||
local IDRAC_IP=$(cat $IP_FILE)
|
||||
|
||||
# 모든 hwinventory 저장
|
||||
local hwinventory=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS hwinventory)
|
||||
# 모든 샷시 정보 저장
|
||||
local getsysinfo=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS getsysinfo)
|
||||
# 모든 SysProfileSettings 저장
|
||||
local SysProfileSettings=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get bios.SysProfileSettings)
|
||||
# ProcessorSettings 저장
|
||||
local ProcessorSettings=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get bios.ProcSettings)
|
||||
# Memory Settings 저장
|
||||
local MemorySettings=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get bios.MemSettings)
|
||||
# Raid Settings 저장
|
||||
local STORAGEController=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get STORAGE.Controller.1)
|
||||
|
||||
# 서비스 태그 가져오기
|
||||
local SVC_TAG=$(echo "$getsysinfo" | grep -i "SVC Tag" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# Bios Firmware Version 확인
|
||||
local Bios_firmware=$(echo "$getsysinfo" | grep -i "System BIOS Version" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Firmware Version 확인
|
||||
local iDRAC_firmware=$(echo "$getsysinfo" | grep -i "Firmware Version" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# Intel NIC Firmware Version 확인
|
||||
local Intel_NIC_firmware=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get NIC.FrmwImgMenu.1 | grep -i "#FamilyVersion" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# OnBoard NIC Firmware Version 확인
|
||||
local Onboard_NIC_firmware=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get NIC.FrmwImgMenu.5 | grep -i "#FamilyVersion" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# R/C Firmware Version 확인
|
||||
local Raid_firmware=$(echo "$hwinventory" | grep -i "ControllerFirmwareVersion" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# Bios 설정 Boot Mode 확인
|
||||
local Bios_BootMode=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get bios.BiosBootSettings | grep -i "BootMode" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
|
||||
# Bios SysProfileSettings 설정 정보 확인
|
||||
local SysProFileSettings_info1=$(echo "$SysProfileSettings" | grep -i "SysProfile=" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
local SysProFileSettings_info2=$(echo "$SysProfileSettings" | grep -i "ProcPwrPerf" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
local SysProFileSettings_info3=$(echo "$SysProfileSettings" | grep -i "MemFrequency" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
local SysProFileSettings_info4=$(echo "$SysProfileSettings" | grep -i "ProcTurboMode" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
local SysProFileSettings_info5=$(echo "$SysProfileSettings" | grep -i "PcieAspmL1" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
local SysProFileSettings_info6=$(echo "$SysProfileSettings" | grep -i "ProcCStates" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
local SysProFileSettings_info7=$(echo "$SysProfileSettings" | grep -i "DeterminismSlider" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
local SysProFileSettings_info8=$(echo "$SysProfileSettings" | grep -i "DynamicLinkWidthManagement" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
|
||||
# Processor Settings - Logical Processor
|
||||
local ProcessorSettings_info1=$(echo "$ProcessorSettings" | grep -i "LogicalProc" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
local ProcessorSettings_info2=$(echo "$ProcessorSettings" | grep -i "ProcVirtualization" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
local ProcessorSettings_info3=$(echo "$ProcessorSettings" | grep -i "NumaNodesPerSocket" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
local ProcessorSettings_info4=$(echo "$ProcessorSettings" | grep -i "ProcX2Apic" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
|
||||
# Memory Settings - Node Interleaving
|
||||
local MemorySettings_info1=$(echo "$MemorySettings" | grep -i "DramRefreshDelay" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
local MemorySettings_info2=$(echo "$MemorySettings" | grep -i "PPROnUCE" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
local MemorySettings_info3=$(echo "$MemorySettings" | grep -i "CECriticalSEL" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
|
||||
# System Settings - Thermal Profile Optimization
|
||||
local SystemSettings_info1=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get System.ThermalSettings | grep -i "ThermalProfile" | awk -F '=' '{print $2}')
|
||||
# Integrated Devices Settings - SR-IOV Global Enable
|
||||
local IntegratedDevicesSettings_info1=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get Bios.IntegratedDevices | grep -i "SriovGlobalEnable" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# Miscellaneous Settings - F1/F2 Prompt on Error
|
||||
local IMiscellaneousSettings_info1=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get bios.MiscSettings | grep -i "ErrPrompt" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
|
||||
# iDRAC Settings - Timezone
|
||||
local iDRAC_Settings_info1=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.Time.Timezone | grep -i "Timezone" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - IPMI LAN Selection
|
||||
local iDRAC_Settings_info2=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.CurrentNIC | grep -i "ActiveNIC" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - IPMI IP(IPv4)
|
||||
local iDRAC_Settings_info3=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.CurrentIPv4 | grep -i "DHCPEnable" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - IPMI IP(IPv6)
|
||||
local iDRAC_Settings_info4=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.CurrentIPv6 | grep -i "Enable=" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - Redfish Support
|
||||
local iDRAC_Settings_info5=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.Redfish.Enable | grep -i "Enable=" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - SSH Support
|
||||
local iDRAC_Settings_info6=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.SSH | grep -i "Enable=" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - AD User Domain Name
|
||||
local iDRAC_Settings_info7=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.USERDomain.1.Name | grep -i "Name" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - SC Server Address
|
||||
local iDRAC_Settings_info8=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.ActiveDirectory.DomainController1 | grep -i "DomainController1" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - SE AD RoleGroup Name
|
||||
local iDRAC_Settings_info9=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.ADGroup.1.Name | grep -i "Name" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - SE AD RoleGroup Dome인
|
||||
local iDRAC_Settings_info10=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.ADGroup.1.Domain | grep -i "Domain" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - SE AD RoleGroup Privilege
|
||||
local iDRAC_Settings_info11=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.ADGroup.1.Privilege | grep -i "Privilege" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - IDC AD RoleGroup name
|
||||
local iDRAC_Settings_info12=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.ADGroup.2.Name | grep -i "Name" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - IDC AD RoleGroup Dome인
|
||||
local iDRAC_Settings_info13=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.ADGroup.2.Domain | grep -i "Domain" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - IDC AD RoleGroup Privilege
|
||||
local iDRAC_Settings_info14=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.ADGroup.2.Privilege | grep -i "Privilege" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - Remote Log (syslog)
|
||||
local iDRAC_Settings_info15=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.SysLog.SysLogEnable | grep -i "SysLogEnable" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - syslog server address 1
|
||||
local iDRAC_Settings_info16=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.SysLog.Server1 | grep -i "Server1" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - syslog server address 2
|
||||
local iDRAC_Settings_info17=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.SysLog.Server2 | grep -i "Server2" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - syslog server port
|
||||
local iDRAC_Settings_info18=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.SysLog.Port | grep -i "Port" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# iDRAC Settings - VirtualConsole Port
|
||||
local iDRAC_Settings_info19=$(racadm -r $IDRAC_IP -u $IDRAC_USER -p $IDRAC_PASS get iDRAC.VirtualConsole.Port | grep -i "Port" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
|
||||
# RAID Settings - ProductName
|
||||
local RAID_info0=$(echo "$hwinventory" | grep -i "ProductName = PERC" | awk -F '=' '{print $2}')
|
||||
# RAID Settings - RAIDType
|
||||
local RAID_info1=$(echo "$hwinventory" | grep -i "RAIDTypes" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# RAID Settings - StripeSize
|
||||
local RAID_info2=$(echo "$hwinventory" | grep -i "StripeSize" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# RAID Settings - ReadCachePolicy
|
||||
local RAID_info3=$(echo "$hwinventory" | grep -i "ReadCachePolicy" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# RAID Settings - WriteCachePolicy
|
||||
local RAID_info4=$(echo "$hwinventory" | grep -i "WriteCachePolicy" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# RAID Settings - PatrolReadRate
|
||||
local RAID_info5=$(echo "$STORAGEController" | grep -i "CheckConsistencyRate" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
# RAID Settings - PatrolReadRate
|
||||
local RAID_info6=$(echo "$STORAGEController" | grep -i "PatrolReadMode" | awk -F '=' '{print $2}' | tr -d '[:space:]')
|
||||
|
||||
# 서비스 태그가 존재하는지 확인
|
||||
if [ -z "$SVC_TAG" ]; then
|
||||
echo "Failed to retrieve SVC Tag for IP: $IDRAC_IP"
|
||||
return
|
||||
fi
|
||||
|
||||
local OUTPUT_FILE="$OUTPUT_DIR/$SVC_TAG.txt"
|
||||
echo "Dell EMC Server Bios,iDRAC,R/C Setting (SVC Tag: $SVC_TAG)" | tee -a "$OUTPUT_FILE"
|
||||
echo -e "\n" >> "$OUTPUT_FILE"
|
||||
echo "------------------------------------------Firware Version 정보------------------------------------------" >> "$OUTPUT_FILE"
|
||||
# SVC Tag 확인
|
||||
echo "1. SVC Tag : $SVC_TAG" >> "$OUTPUT_FILE"
|
||||
|
||||
# Bios Firmware Version 확인
|
||||
echo "2. Bios Firmware : $Bios_firmware" >> "$OUTPUT_FILE"
|
||||
|
||||
# iDRAC Firmware Version 확인
|
||||
echo "3. iDRAC Firmware Version : $iDRAC_firmware" >> "$OUTPUT_FILE"
|
||||
|
||||
# Intel NIC Firmware Version 확인
|
||||
echo "4. NIC Integrated Firmware Version : $Intel_NIC_firmware" >> "$OUTPUT_FILE"
|
||||
|
||||
# OnBoard NIC Firmware Version 확인
|
||||
echo "5. OnBoard NIC Firmware Version : $Onboard_NIC_firmware" >> "$OUTPUT_FILE"
|
||||
|
||||
# Raid Controller Firmware Version 확인
|
||||
echo "6. Raid Controller Firmware Version : $Raid_firmware" >> "$OUTPUT_FILE"
|
||||
echo -e "\n" >> "$OUTPUT_FILE"
|
||||
|
||||
echo "---------------------------------------------Bios 설정 정보----------------------------------------------" >> "$OUTPUT_FILE"
|
||||
# bios Boot Mode 확인
|
||||
echo "01. Bios Boot Mode : $Bios_BootMode" >> "$OUTPUT_FILE"
|
||||
|
||||
# SysProfileSettings - System Profile
|
||||
echo "02. System Profile Settings - System Profile : $SysProFileSettings_info1" >> "$OUTPUT_FILE"
|
||||
|
||||
# SysProfileSettings - CPU Power Management
|
||||
echo "03. System Profile Settings - CPU Power Management : $SysProFileSettings_info2" >> "$OUTPUT_FILE"
|
||||
|
||||
# SysProfileSettings - Memory Frequency
|
||||
echo "04. System Profile Settings - Memory Frequency : $SysProFileSettings_info3" >> "$OUTPUT_FILE"
|
||||
|
||||
# SysProfileSettings - Turbo Boost
|
||||
echo "05. System Profile Settings - Turbo Boost : $SysProFileSettings_info4" >> "$OUTPUT_FILE"
|
||||
|
||||
# SysProfileSettings - C1E
|
||||
echo "06. System Profile Settings - PCI ASPM L1 Link Power Management : $SysProFileSettings_info5" >> "$OUTPUT_FILE"
|
||||
|
||||
# SysProfileSettings - C-States
|
||||
echo "07. System Profile Settings - C-States : $SysProFileSettings_info6" >> "$OUTPUT_FILE"
|
||||
|
||||
# SysProfileSettings - Determinism Slider
|
||||
echo "08. System Profile Settings - Determinism Slider : $SysProFileSettings_info7" >> "$OUTPUT_FILE"
|
||||
|
||||
# SysProfileSettings - Dynamic Link Width Management (DLWM)
|
||||
echo "08. System Profile Settings - Dynamic Link Width Management (DLWM) : $SysProFileSettings_info8" >> "$OUTPUT_FILE"
|
||||
|
||||
# Processor Settings - Logical Processor
|
||||
echo "09. Processor Settings - Logical Processor : $ProcessorSettings_info1" >> "$OUTPUT_FILE"
|
||||
|
||||
# Processor Settings - Virtualization Technology
|
||||
echo "10. Processor Settings - Virtualization Technology : $ProcessorSettings_info2" >> "$OUTPUT_FILE"
|
||||
|
||||
# Processor Settings - NUMA Nodes Per Socket
|
||||
echo "11. Processor Settings - NUMA Nodes Per Socket : $ProcessorSettings_info3" >> "$OUTPUT_FILE"
|
||||
|
||||
# Processor Settings - x2APIC Mode
|
||||
echo "12. Processor Settings - x2APIC Mode : $ProcessorSettings_info4" >> "$OUTPUT_FILE"
|
||||
|
||||
# Memory Settings - Dram Refresh Delayg
|
||||
echo "13. Memory Settings - Dram Refresh Delay : $MemorySettings_info1" >> "$OUTPUT_FILE"
|
||||
|
||||
# Memory Settings - DIMM Self Healing (Post Package Repair) on Uncorrectable Memory Error
|
||||
echo "14. Memory Settings - DIMM Self Healing (Post Package Repair) on Uncorrectable Memory Error : $MemorySettings_info2" >> "$OUTPUT_FILE"
|
||||
|
||||
# Memory Settings - Correctable Error Logging
|
||||
echo "15. Memory Settings - Correctable Error Logging : $MemorySettings_info3" >> "$OUTPUT_FILE"
|
||||
|
||||
# System Settings - Thermal Profile Optimization
|
||||
echo "16. System Settings - Thermal Profile Optimization : $SystemSettings_info1" >> "$OUTPUT_FILE"
|
||||
|
||||
# Integrated Devices Settings - SR-IOV Global Enable
|
||||
echo "17. Integrated Devices Settings - SR-IOV Global Enable : $IntegratedDevicesSettings_info1" >> "$OUTPUT_FILE"
|
||||
|
||||
# Miscellaneous Settings - F1/F2 Prompt on Error
|
||||
echo "18. Miscellaneous Settings - F1/F2 Prompt on Error : $IMiscellaneousSettings_info1" >> "$OUTPUT_FILE"
|
||||
echo -e "\n" >> "$OUTPUT_FILE"
|
||||
|
||||
echo "---------------------------------------------iDRAC 설정 정보----------------------------------------------" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - Timezone
|
||||
echo "01. iDRAC Settings - Timezone : $iDRAC_Settings_info1" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - IPMI LAN Selection
|
||||
echo "02. iDRAC Settings - IPMI LAN Selection : $iDRAC_Settings_info2" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - IPMI IP(IPv4)
|
||||
echo "03. iDRAC Settings - IPMI IP(IPv4) : $iDRAC_Settings_info3" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - IPMI IP(IPv6)
|
||||
echo "04. iDRAC Settings - IPMI IP(IPv6) : $iDRAC_Settings_info4" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - Redfish Support
|
||||
echo "05. iDRAC Settings - Redfish Support : $iDRAC_Settings_info5" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - SSH Support
|
||||
echo "06. iDRAC Settings - SSH Support : $iDRAC_Settings_info6" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - AD User Domain Name
|
||||
echo "07. iDRAC Settings - AD User Domain Name : $iDRAC_Settings_info7" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - SC Server Address
|
||||
echo "08. iDRAC Settings - SC Server Address : $iDRAC_Settings_info8" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - SE AD RoleGroup Name
|
||||
echo "09. iDRAC Settings - SE AD RoleGroup Name : $iDRAC_Settings_info9" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - SE AD RoleGroup Dome인
|
||||
echo "10. iDRAC Settings - SE AD RoleGroup Dome인 : $iDRAC_Settings_info10" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - SE AD RoleGroup Privilege
|
||||
echo "11. iDRAC Settings - SE AD RoleGroup Privilege : $iDRAC_Settings_info11" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - SE IDC RoleGroup Name
|
||||
echo "12. iDRAC Settings - IDC AD RoleGroup Name : $iDRAC_Settings_info12" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - SE IDC RoleGroup Dome인
|
||||
echo "13. iDRAC Settings - IDC AD RoleGroup Domain : $iDRAC_Settings_info13" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - SE IDC RoleGroup Dome인
|
||||
echo "14. iDRAC Settings - IDC AD RoleGroup Privilege : $iDRAC_Settings_info14" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - Remote Log (syslog)
|
||||
echo "15. iDRAC Settings - Remote Log (syslog) : $iDRAC_Settings_info15" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - Remote Log (syslog)
|
||||
echo "16. iDRAC Settings - syslog server address 1 : $iDRAC_Settings_info16" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - Remote Log (syslog)
|
||||
echo "17. iDRAC Settings - syslog server address 2 : $iDRAC_Settings_info17" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - syslog server port
|
||||
echo "18. iDRAC Settings - syslog server port : $iDRAC_Settings_info18" >> "$OUTPUT_FILE"
|
||||
# iDRAC Settings - Remote KVM Nonsecure port
|
||||
echo "19. iDRAC Settings - Remote KVM Nonsecure port : $iDRAC_Settings_info19" >> "$OUTPUT_FILE"
|
||||
echo -e "\n" >> "$OUTPUT_FILE"
|
||||
|
||||
# echo "---------------------------------------------Raid 설정 정보----------------------------------------------" >> "$OUTPUT_FILE"
|
||||
# RAID Settings - Raid Types
|
||||
#echo "01. RAID Settings - Raid ProductName : $RAID_info0" >> "$OUTPUT_FILE"
|
||||
# RAID Settings - Raid Types
|
||||
#echo "02. RAID Settings - Raid Typest : $RAID_info1" >> "$OUTPUT_FILE"
|
||||
# RAID Settings - StripeSize
|
||||
#echo "03. RAID Settings - StripeSize : $RAID_info2" >> "$OUTPUT_FILE"
|
||||
# RAID Settings - ReadCachePolicy
|
||||
#echo "04. RAID Settings - ReadCachePolicy : $RAID_info3" >> "$OUTPUT_FILE"
|
||||
# RAID Settings - ReadCachePolicy
|
||||
#echo "05. RAID Settings - WriteCachePolicy : $RAID_info4" >> "$OUTPUT_FILE"
|
||||
# RAID Settings - CheckConsistencyRate
|
||||
#echo "06. RAID Settings - CheckConsistencyRate : $RAID_info5" >> "$OUTPUT_FILE"
|
||||
# RAID Settings - PatrolReadMode
|
||||
#echo "07. RAID Settings - PatrolReadMode : $RAID_info6" >> "$OUTPUT_FILE"
|
||||
# RAID Settings - period
|
||||
#echo "08. RAID Settings - period : 168h" >> "$OUTPUT_FILE"
|
||||
# RAID Settings - Power Save
|
||||
#echo "09. RAID Settings - Power Save : No" >> "$OUTPUT_FILE"
|
||||
# RAID Settings - JBODMODE
|
||||
#echo "10. RAID Settings - JBODMODE : Controller does not support JBOD" >> "$OUTPUT_FILE"
|
||||
# RAID Settings - maxconcurrentpd
|
||||
#echo "11. RAID Settings - maxconcurrentpd : 240" >> "$OUTPUT_FILE"
|
||||
|
||||
# 임시 파일 삭제
|
||||
rm -f $IP_FILE
|
||||
}
|
||||
|
||||
export -f fetch_idrac_info
|
||||
export IDRAC_USER
|
||||
export IDRAC_PASS
|
||||
export OUTPUT_DIR
|
||||
|
||||
# 시작 시간 기록
|
||||
START_TIME=$(date +%s)
|
||||
|
||||
# IP 목록 파일을 읽어 병렬로 작업 수행
|
||||
fetch_idrac_info
|
||||
|
||||
# 종료 시간 기록
|
||||
END_TIME=$(date +%s)
|
||||
|
||||
# 소요 시간 계산
|
||||
ELAPSED_TIME=$(($END_TIME - $START_TIME))
|
||||
ELAPSED_HOURS=$(($ELAPSED_TIME / 3600))
|
||||
ELAPSED_MINUTES=$((($ELAPSED_TIME % 3600) / 60))
|
||||
ELAPSED_SECONDS=$(($ELAPSED_TIME % 60))
|
||||
|
||||
echo "정보 수집 완료."
|
||||
echo "수집 완료 시간: $ELAPSED_HOURS 시간, $ELAPSED_MINUTES 분, $ELAPSED_SECONDS 초."
|
||||
@@ -10,6 +10,14 @@ import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional, Tuple, List
|
||||
import logging
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
# ===== 설정: 기본 계정/비밀번호 (환경변수로 덮어쓰기 가능) =====
|
||||
IDRAC_USER = os.getenv("IDRAC_USER", "root")
|
||||
@@ -190,17 +198,17 @@ def main():
|
||||
|
||||
ip_file = Path(args.ip_file)
|
||||
if not ip_file.exists():
|
||||
print(f"IP 파일이 존재하지 않습니다: {ip_file}", file=sys.stderr)
|
||||
logging.error(f"IP 파일이 존재하지 않습니다: {ip_file}")
|
||||
sys.exit(1)
|
||||
|
||||
with ip_file.open("r", encoding="utf-8") as f:
|
||||
ips = [ln.strip() for ln in f if ln.strip()]
|
||||
|
||||
if not ips:
|
||||
print("IP 목록이 비어 있습니다.", file=sys.stderr)
|
||||
logging.error("IP 목록이 비어 있습니다.")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"[시작] 총 {len(ips)}대, workers={args.workers}, IDRAC_USER={IDRAC_USER}")
|
||||
logging.info(f"[시작] 총 {len(ips)}대, workers={args.workers}, IDRAC_USER={IDRAC_USER}")
|
||||
|
||||
t0 = time.time()
|
||||
ok = 0
|
||||
@@ -214,20 +222,23 @@ def main():
|
||||
try:
|
||||
_ip, success, msg = fut.result()
|
||||
prefix = "[OK] " if success else "[FAIL] "
|
||||
print(prefix + ip + " - " + msg)
|
||||
if success:
|
||||
logging.info(prefix + ip + " - " + msg)
|
||||
else:
|
||||
logging.error(prefix + ip + " - " + msg)
|
||||
ok += int(success)
|
||||
fail += int(not success)
|
||||
except Exception as e:
|
||||
print(f"[EXC] {ip} - {e}", file=sys.stderr)
|
||||
logging.error(f"[EXC] {ip} - {e}")
|
||||
fail += 1
|
||||
|
||||
dt = int(time.time() - t0)
|
||||
h, r = divmod(dt, 3600)
|
||||
m, s = divmod(r, 60)
|
||||
|
||||
print("\n정보 수집 완료.")
|
||||
print(f"성공 {ok}대 / 실패 {fail}대")
|
||||
print(f"수집 완료 시간: {h} 시간, {m} 분, {s} 초.")
|
||||
logging.info("\n정보 수집 완료.")
|
||||
logging.info(f"성공 {ok}대 / 실패 {fail}대")
|
||||
logging.info(f"수집 완료 시간: {h} 시간, {m} 분, {s} 초.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -10,6 +10,14 @@ import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional, Tuple, List
|
||||
import logging
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s [INFO] root: %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
# ===== 설정: 기본 계정/비밀번호 (환경변수로 덮어쓰기 가능) =====
|
||||
IDRAC_USER = os.getenv("IDRAC_USER", "root")
|
||||
@@ -189,17 +197,17 @@ def main():
|
||||
|
||||
ip_file = Path(args.ip_file)
|
||||
if not ip_file.exists():
|
||||
print(f"IP 파일이 존재하지 않습니다: {ip_file}", file=sys.stderr)
|
||||
logging.error(f"IP 파일이 존재하지 않습니다: {ip_file}")
|
||||
sys.exit(1)
|
||||
|
||||
with ip_file.open("r", encoding="utf-8") as f:
|
||||
ips = [ln.strip() for ln in f if ln.strip()]
|
||||
|
||||
if not ips:
|
||||
print("IP 목록이 비어 있습니다.", file=sys.stderr)
|
||||
logging.error("IP 목록이 비어 있습니다.")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"[시작] 총 {len(ips)}대, workers={args.workers}, IDRAC_USER={IDRAC_USER}")
|
||||
logging.info(f"[시작] 총 {len(ips)}대, workers={args.workers}, IDRAC_USER={IDRAC_USER}")
|
||||
|
||||
t0 = time.time()
|
||||
ok = 0
|
||||
@@ -213,20 +221,23 @@ def main():
|
||||
try:
|
||||
_ip, success, msg = fut.result()
|
||||
prefix = "[OK] " if success else "[FAIL] "
|
||||
print(prefix + ip + " - " + msg)
|
||||
if success:
|
||||
logging.info(prefix + ip + " - " + msg)
|
||||
else:
|
||||
logging.error(prefix + ip + " - " + msg)
|
||||
ok += int(success)
|
||||
fail += int(not success)
|
||||
except Exception as e:
|
||||
print(f"[EXC] {ip} - {e}", file=sys.stderr)
|
||||
logging.error(f"[EXC] {ip} - {e}")
|
||||
fail += 1
|
||||
|
||||
dt = int(time.time() - t0)
|
||||
h, r = divmod(dt, 3600)
|
||||
m, s = divmod(r, 60)
|
||||
|
||||
print("\n정보 수집 완료.")
|
||||
print(f"성공 {ok}대 / 실패 {fail}대")
|
||||
print(f"수집 완료 시간: {h} 시간, {m} 분, {s} 초.")
|
||||
logging.info("\n정보 수집 완료.")
|
||||
logging.info(f"성공 {ok}대 / 실패 {fail}대")
|
||||
logging.info(f"수집 완료 시간: {h} 시간, {m} 분, {s} 초.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
29
idrac-info.service
Normal file
29
idrac-info.service
Normal file
@@ -0,0 +1,29 @@
|
||||
[Unit]
|
||||
Description=iDRAC Info Web Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
# 실행할 사용자 (보안을 위해 root 대신 전용 계정 권장, 예: idrac)
|
||||
User=root
|
||||
Group=root
|
||||
|
||||
# 프로젝트 루트 디렉토리 (서버 환경에 맞게 수정 필요)
|
||||
WorkingDirectory=/data/app/idrac_info_new
|
||||
|
||||
# 가상환경의 python 실행 및 app.py 호출
|
||||
# ExecStart=<python_path> <script_path>
|
||||
ExecStart=/bin/bash -c '/data/app/idrac_info_new/venv/bin/python /data/app/idrac_info_new/app.py'
|
||||
|
||||
# 환경 변수 설정 (필요 시 수정)
|
||||
Environment="FLASK_HOST=0.0.0.0"
|
||||
Environment="FLASK_PORT=5000"
|
||||
Environment="FLASK_DEBUG=false"
|
||||
# Werkzeug 리로더 끄기 (프로덕션 모드) - Systemd에서는 이 설정이 오히려 오류(KeyError)를 유발하므로 제거
|
||||
# Environment="WERKZEUG_RUN_MAIN=true"
|
||||
|
||||
# 프로세스 종료 시 자동 재시작
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user