Files
iDRAC_Info/backend/templates/bios_baseline.html
T
2026-05-05 17:14:11 +09:00

512 lines
26 KiB
HTML

{% extends "base.html" %}
{% block content %}
<style>
/* 모달이 Navbar 위에 오도록 z-index 조정 */
.modal {
z-index: 1060 !important;
}
.modal-backdrop {
z-index: 1050 !important;
}
/* 모달 헤더가 항상 잘 보이도록 배경색 및 위치 조정 */
.modal-header {
background-color: #fff;
border-bottom: 1px solid #dee2e6;
padding: 1rem 1rem;
position: sticky;
top: 0;
z-index: 1070;
}
/* 모달이 너무 위로 붙지 않게 여백 추가 */
.modal-dialog {
margin-top: 5rem;
}
/* ===== 탭 가시성 개선 ===== */
/* Pills 스타일 탭 버튼 */
.nav-pills .nav-link {
color: #495057 !important;
background-color: #e9ecef !important;
border: 1px solid #ced4da !important;
margin-right: 0.25rem;
font-weight: 500;
padding: 0.5rem 1rem;
transition: all 0.2s ease;
}
.nav-pills .nav-link:hover {
background-color: #dee2e6 !important;
border-color: #adb5bd !important;
color: #212529 !important;
}
.nav-pills .nav-link.active {
background-color: #0d6efd !important;
border-color: #0d6efd !important;
color: #ffffff !important;
font-weight: 600;
}
/* Select 드롭다운 가시성 개선 */
.form-select {
border: 2px solid #ced4da !important;
font-weight: 500;
color: #212529 !important;
background-color: #ffffff !important;
}
.form-select:focus {
border-color: #0d6efd !important;
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25) !important;
}
.form-select option {
color: #212529 !important;
background-color: #ffffff !important;
padding: 0.5rem;
}
/* 탭 컨테이너 배경 */
.nav-pills-container {
background-color: #f8f9fa;
padding: 0.75rem;
border-radius: 0.375rem;
margin-bottom: 1rem;
}
</style>
<div class="container-fluid py-4">
<!-- 헤더 -->
<div class="row mb-4">
<div class="col">
<h2 class="fw-bold mb-1">
<i class="bi bi-clipboard-data text-primary me-2"></i>
BIOS Baseline 비교
</h2>
<p class="text-muted mb-0">납품 전 서버의 BIOS 설정을 표준 설정과 비교합니다</p>
</div>
</div>
<!-- 메인 작업 영역 -->
<div class="row g-4 mb-4">
<!-- 왼쪽: IP 입력 및 설정 -->
<div class="col-lg-5">
<div class="card border shadow-sm h-100">
<div class="card-header bg-light border-0 py-2">
<h6 class="mb-0">
<i class="bi bi-search me-2"></i>
비교 설정
</h6>
</div>
<div class="card-body p-4 d-flex flex-column">
<!-- Baseline 선택 -->
<div class="mb-3">
<label for="baseline-select" class="form-label">Baseline 선택</label>
<select id="baseline-select" class="form-select">
<option value="">Baseline을 선택하세요</option>
</select>
<button class="btn btn-sm btn-outline-primary mt-2 w-100" onclick="showBaselineManageModal()">
<i class="bi bi-plus-circle me-1"></i> 새 Baseline 생성
</button>
</div>
<!-- IP 주소 입력 -->
<div class="mb-3 flex-grow-1 d-flex flex-column">
<label for="ip-addresses"
class="form-label w-100 d-flex justify-content-between align-items-end mb-2">
<span class="mb-1">
서버 IP 주소
<span class="badge bg-secondary ms-1" id="ip-count">0</span>
</span>
<button type="button" class="btn btn-sm btn-outline-secondary px-2 py-1"
onclick="clearIPs()" title="입력 내용 지우기" style="font-size: 0.75rem;">
<i class="bi bi-trash me-1"></i>지우기
</button>
</label>
<textarea id="ip-addresses" class="form-control font-monospace flex-grow-1"
placeholder="예:&#10;10.10.0.1&#10;10.10.0.2&#10;10.10.0.3" style="resize: none;"></textarea>
</div>
<!-- 인증 정보 -->
<div class="row g-2 mb-3">
<div class="col-6">
<input type="text" id="username" class="form-control" value="root" placeholder="Username">
</div>
<div class="col-6">
<input type="password" id="password" class="form-control" placeholder="Password">
</div>
</div>
<!-- 비교 시작 버튼 -->
<button onclick="startComparison()" class="btn btn-primary w-100 py-2">
<i class="bi bi-arrows-angle-contract me-1"></i> 비교 시작
</button>
</div>
</div>
</div>
<!-- 오른쪽: 결과 요약 -->
<div class="col-lg-7">
<div class="card border shadow-sm h-100">
<div class="card-header bg-light border-0 py-2">
<h6 class="mb-0">
<i class="bi bi-bar-chart me-2"></i>
비교 결과 요약
</h6>
</div>
<div class="card-body p-4" id="summary-section">
<div class="text-center text-muted py-5">
<i class="bi bi-info-circle fs-1 mb-3"></i>
<p class="mb-0">비교를 시작하면 결과가 여기에 표시됩니다</p>
</div>
</div>
</div>
</div>
</div>
<!-- 진행률 -->
<div class="row mb-4" id="progress-section" style="display: none;">
<div class="col">
<div class="card border-0 shadow-sm">
<div class="card-body p-3">
<div class="d-flex align-items-center mb-2">
<i class="bi bi-activity text-primary me-2"></i>
<span class="fw-semibold">처리 진행률</span>
</div>
<div class="progress" style="height: 25px;">
<div id="progress-bar"
class="progress-bar progress-bar-striped progress-bar-animated bg-success"
role="progressbar" style="width: 0%">
<span class="fw-semibold">0%</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 상세 비교 결과 -->
<div class="row" id="results-section" style="display: none;">
<div class="col">
<div class="card border shadow-sm">
<div class="card-header bg-light border-0 py-2 d-flex justify-content-between align-items-center">
<h6 class="mb-0">
<i class="bi bi-list-check me-2"></i>
상세 비교 결과
</h6>
<div>
<button class="btn btn-sm btn-outline-secondary" onclick="toggleDiffOnly()" id="diff-only-btn">
<i class="bi bi-funnel me-1"></i> 차이점만 보기
</button>
<button class="btn btn-sm btn-outline-primary" onclick="downloadResults()">
<i class="bi bi-download me-1"></i> Excel 다운로드
</button>
</div>
</div>
<div class="card-body p-4" id="results-container">
<!-- 서버별 결과가 여기에 표시됨 -->
</div>
</div>
</div>
</div>
</div>
<!-- Baseline 관리 모달 -->
<div class="modal fade" id="baseline-manage-modal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="bi bi-clipboard-data me-2"></i>
Baseline 관리
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<!---->
<div class="nav-pills-container">
<ul class="nav nav-pills mb-0" role="tablist">
<li class="nav-item">
<button class="nav-link active" data-bs-toggle="pill" data-bs-target="#create-tab">
새로 생성
</button>
</li>
<li class="nav-item">
<button class="nav-link" data-bs-toggle="pill" data-bs-target="#list-tab">
목록 관리
</button>
</li>
</ul>
</div>
<div class="tab-content">
<!-- 생성 탭 -->
<div class="tab-pane fade show active" id="create-tab">
<form id="create-baseline-form">
<div class="mb-3">
<label class="form-label">서버 IP 주소 *</label>
<input type="text" class="form-control" id="create-ip" placeholder="10.10.0.1" required>
</div>
<div class="row g-2 mb-3">
<div class="col-6">
<label class="form-label">Username</label>
<input type="text" class="form-control" id="create-username" value="root">
</div>
<div class="col-6">
<label class="form-label">Password *</label>
<input type="password" class="form-control" id="create-password" required>
</div>
</div>
<div class="mb-3">
<label class="form-label">Baseline 이름 *</label>
<input type="text" class="form-control" id="create-name"
placeholder="R6615_GPU_Standard_2024" required>
</div>
<div class="mb-3">
<label class="form-label">서버 타입</label>
<input type="text" class="form-control" id="create-type" placeholder="GPU Server">
</div>
<div class="mb-3">
<label class="form-label">설명</label>
<textarea class="form-control" id="create-description" rows="2"
placeholder="표준 GPU 서버 설정"></textarea>
</div>
<button type="submit" class="btn btn-primary w-100">
<i class="bi bi-download me-1"></i> Redfish로 가져와서 생성
</button>
</form>
</div>
<!-- 목록 탭 -->
<div class="tab-pane fade" id="list-tab">
<div id="baseline-list">
<div class="text-center text-muted py-4">
<i class="bi bi-hourglass-split"></i> 로딩 중...
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Baseline 상세 편집 모달 -->
<div class="modal fade" id="edit-baseline-modal" tabindex="-1" aria-hidden="true" data-bs-backdrop="static">
<div class="modal-dialog modal-xl modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="bi bi-pencil-square me-2"></i>
Baseline 상세 편집
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body bg-light">
<div class="row g-3">
<!-- 왼쪽: 메타데이터 편집 -->
<div class="col-lg-4">
<div class="card h-100">
<div class="card-header bg-white fw-bold">기본 정보</div>
<div class="card-body">
<form id="edit-baseline-meta-form">
<input type="hidden" id="edit-id">
<div class="mb-3">
<label class="form-label small text-muted">Baseline 이름</label>
<input type="text" class="form-control" id="edit-name" required>
</div>
<div class="mb-3">
<label class="form-label small text-muted">서버 모델</label>
<input type="text" class="form-control bg-light" id="edit-model" readonly>
</div>
<div class="mb-3">
<label class="form-label small text-muted">서버 타입</label>
<input type="text" class="form-control" id="edit-type">
</div>
<div class="mb-3">
<label class="form-label small text-muted">설명</label>
<textarea class="form-control" id="edit-description" rows="4"></textarea>
</div>
<div class="text-muted small">
<p class="mb-1"><i class="bi bi-calendar me-1"></i>생성일: <span
id="edit-created-at">-</span></p>
<p class="mb-1"><i class="bi bi-cpu me-1"></i>원본 IP: <span
id="edit-source-ip">-</span></p>
</div>
</form>
</div>
</div>
</div>
<!-- 오른쪽: BIOS 설정 편집 -->
<!-- 오른쪽: 상세 설정 편집 -->
<div class="col-lg-8">
<div class="card h-100 border shadow-sm">
<div class="card-body p-3">
<!-- 탭 메뉴 -->
<div class="nav-pills-container">
<ul class="nav nav-pills mb-0" id="edit-tabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="tab-edit-bios" data-bs-toggle="pill"
data-bs-target="#content-edit-bios" type="button">BIOS</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="tab-edit-idrac" data-bs-toggle="pill"
data-bs-target="#content-edit-idrac" type="button">iDRAC</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="tab-edit-raid" data-bs-toggle="pill"
data-bs-target="#content-edit-raid" type="button">RAID</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="tab-edit-nic" data-bs-toggle="pill"
data-bs-target="#content-edit-nic" type="button">NIC</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="tab-edit-boot" data-bs-toggle="pill"
data-bs-target="#content-edit-boot" type="button">Boot</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="tab-edit-firmware" data-bs-toggle="pill"
data-bs-target="#content-edit-firmware" type="button">Firmware</button>
</li>
</ul>
</div>
<div class="tab-content h-100">
<!-- BIOS 탭 -->
<div class="tab-pane fade show active h-100" id="content-edit-bios">
<div
class="d-flex justify-content-between align-items-center p-2 border-bottom bg-light">
<span class="small text-muted fw-bold ms-2">항목 수: <span
id="edit-bios-count">0</span></span>
<button class="btn btn-sm btn-outline-primary bg-white"
onclick="addSettingRow('bios')">
<i class="bi bi-plus-lg"></i> 항목 추가
</button>
</div>
<div class="table-responsive" style="max-height: 450px;">
<table class="table table-hover mb-0" id="table-edit-bios">
<thead class="table-light sticky-top">
<tr>
<th style="width: 40%;">설정 항목 (Key)</th>
<th style="width: 40%;">설정값 (Value)</th>
<th style="width: 20%;">작업</th>
</tr>
</thead>
<tbody><!-- JS 채움 --></tbody>
</table>
</div>
</div>
<!-- iDRAC 탭 -->
<div class="tab-pane fade h-100" id="content-edit-idrac">
<div
class="d-flex justify-content-between align-items-center p-2 border-bottom bg-light">
<span class="small text-muted fw-bold ms-2">항목 수: <span
id="edit-idrac-count">0</span></span>
<button class="btn btn-sm btn-outline-primary bg-white"
onclick="addSettingRow('idrac')">
<i class="bi bi-plus-lg"></i> 항목 추가
</button>
</div>
<div class="table-responsive" style="max-height: 450px;">
<table class="table table-hover mb-0" id="table-edit-idrac">
<thead class="table-light sticky-top">
<tr>
<th style="width: 40%;">설정 항목 (Key)</th>
<th style="width: 40%;">설정값 (Value)</th>
<th style="width: 20%;">작업</th>
</tr>
</thead>
<tbody><!-- JS 채움 --></tbody>
</table>
</div>
</div>
<!-- RAID 탭 -->
<div class="tab-pane fade h-100 p-3" id="content-edit-raid">
<div class="alert alert-info py-2 small">
<i class="bi bi-info-circle me-1"></i>
RAID 구성은 복잡하므로 현재 JSON 직접 편집만 지원합니다. (Read-Only 권장)
</div>
<textarea class="form-control font-monospace small" id="json-edit-raid"
rows="15" style="height: 400px;"></textarea>
</div>
<!-- NIC 탭 -->
<div class="tab-pane fade h-100 p-3" id="content-edit-nic">
<div class="alert alert-info py-2 small">
<i class="bi bi-info-circle me-1"></i>
NIC 설정은 JSON 형식으로 편집합니다.
</div>
<textarea class="form-control font-monospace small" id="json-edit-nic" rows="15"
style="height: 400px;"></textarea>
</div>
<!-- Boot 탭 -->
<div class="tab-pane fade h-100 p-3" id="content-edit-boot">
<div class="alert alert-info py-2 small">
<i class="bi bi-info-circle me-1"></i>
부팅 순서 및 설정을 JSON 형식으로 편집합니다.
</div>
<textarea class="form-control font-monospace small" id="json-edit-boot"
rows="15" style="height: 400px;"></textarea>
</div>
<!-- Firmware 탭 -->
<div class="tab-pane fade h-100" id="content-edit-firmware">
<div
class="d-flex justify-content-between align-items-center p-2 border-bottom bg-light">
<span class="small text-muted fw-bold ms-2">항목 수: <span
id="edit-firmware-count">0</span></span>
<button class="btn btn-sm btn-outline-primary bg-white"
onclick="addSettingRow('firmware')">
<i class="bi bi-plus-lg"></i> 항목 추가
</button>
</div>
<div class="table-responsive" style="max-height: 450px;">
<table class="table table-hover mb-0" id="table-edit-firmware">
<thead class="table-light sticky-top">
<tr>
<th style="width: 40%;">컴포넌트</th>
<th style="width: 40%;">버전</th>
<th style="width: 20%;">작업</th>
</tr>
</thead>
<tbody><!-- JS 채움 --></tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">취소</button>
<button type="button" class="btn btn-primary" onclick="saveBaselineChanges()">
<i class="bi bi-save me-1"></i> 변경사항 저장
</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
{{ super() }}
<script src="{{ url_for('static', filename='js/bios_baseline.js') }}?v={{ range(1, 100000) | random }}"></script>
{% endblock %}