This commit is contained in:
unknown
2026-03-21 07:26:38 +09:00
parent 166d94fca4
commit 40150cd66d
406 changed files with 34179 additions and 55658 deletions
+154
View File
@@ -0,0 +1,154 @@
#!/usr/bin/env python3
"""
통합 시스템 제어 스크립트 (Unified System Control Script)
기존의 개별 제어 스크립트들을 하나로 통합하였습니다.
지원 기능:
- power_on (06-PowerON.py)
- power_off (07-PowerOFF.py)
- log_clear (05-clrsel.py)
- job_delete (08-job_delete_all.py)
- tsr_collect (03-tsr_log.py)
- tsr_save (04-tsr_save.py)
"""
import os
import sys
import argparse
import subprocess
import time
import logging
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
from dotenv import load_dotenv
# -----------------------------------------------------------------------------
# Configuration
# -----------------------------------------------------------------------------
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [INFO] %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger(__name__)
# Load .env relative to script location or current directory
load_dotenv()
IDRAC_USER = os.getenv("IDRAC_USER", "root")
IDRAC_PASS = os.getenv("IDRAC_PASS", "calvin")
OME_USER = os.getenv("OME_USER", "")
OME_PASS = os.getenv("OME_PASS", "")
# -----------------------------------------------------------------------------
# Command Definitions
# -----------------------------------------------------------------------------
# Each action maps to a function that returns the racadm command list
def cmd_power_on(ip):
return ["racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "serveraction", "powerup"]
def cmd_power_off(ip):
return ["racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "serveraction", "powerdown"]
def cmd_log_clear(ip):
return ["racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "clrsel"]
def cmd_job_delete(ip):
return ["racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "jobqueue", "delete", "-i", "ALL"]
def cmd_tsr_collect(ip):
return ["racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS, "techsupreport", "collect"]
def cmd_tsr_save(ip):
# Note: This command assumes a specific share path (legacy behavior)
# Ideally this path should also be configurable via env
share_path = "//10.10.3.15/share/"
return [
"racadm", "-r", ip, "-u", IDRAC_USER, "-p", IDRAC_PASS,
"techsupreport", "export", "-l", share_path, "-u", OME_USER, "-p", OME_PASS
]
ACTION_MAP = {
"power_on": cmd_power_on,
"power_off": cmd_power_off,
"log_clear": cmd_log_clear,
"job_delete": cmd_job_delete,
"tsr_collect": cmd_tsr_collect,
"tsr_save": cmd_tsr_save,
}
# -----------------------------------------------------------------------------
# Execution Logic
# -----------------------------------------------------------------------------
def execute_action(ip: str, action_name: str) -> None:
"""Run the racadm command for a single IP."""
try:
cmd_func = ACTION_MAP.get(action_name)
if not cmd_func:
logger.error(f"[{ip}] Unknown action: {action_name}")
return
cmd = cmd_func(ip)
logger.info(f"[{ip}] Executing {action_name}...")
# Run command
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=600 # Generous timeout for TSR operations
)
if result.returncode == 0:
logger.info(f"[{ip}] Success: {result.stdout.strip()}")
else:
logger.error(f"[{ip}] Failed: {result.stderr.strip()}")
except Exception as e:
logger.error(f"[{ip}] Exception: {e}")
def main():
parser = argparse.ArgumentParser(description="Unified System Control Script")
parser.add_argument("action", choices=ACTION_MAP.keys(), help="Action to perform")
parser.add_argument("ip_file", type=Path, help="Path to the IP list file")
# Optional: Allow passing IP directly via args instead of file (future extension)
args = parser.parse_args()
ip_file = args.ip_file
action = args.action
if not ip_file.is_file():
logger.error(f"IP file not found: {ip_file}")
sys.exit(1)
# Read IPs
try:
with ip_file.open("r", encoding="utf-8") as f:
ips = [line.strip() for line in f if line.strip()]
except Exception as e:
logger.error(f"Failed to read IP file: {e}")
sys.exit(1)
if not ips:
logger.warning("No IPs found in file.")
sys.exit(0)
logger.info(f"Starting '{action}' for {len(ips)} servers...")
start_time = time.time()
# Parallel Execution
# Adjust max_workers as needed. 20 is a safe defaults for I/O bound network tasks.
with ThreadPoolExecutor(max_workers=20) as executor:
futures = [executor.submit(execute_action, ip, action) for ip in ips]
for future in futures:
future.result() # Wait for all to complete
elapsed = time.time() - start_time
logger.info(f"Completed '{action}' in {elapsed:.2f} seconds.")
if __name__ == "__main__":
main()