#!/bin/bash
# 실습 #17 ② — RAID-5 (3 data + 1 parity) + 디스크 장애 + 핫스페어 rebuild
# - 4 disk: 3개에 데이터, 1개는 parity (XOR). 1대 죽어도 정상.
# - rebuild 중에 또 1대 죽으면 데이터 손실 (= 그래서 운영은 RAID-6 권장)
set -e

WORK=/tmp/lab_raid5
sudo mkdir -p "$WORK"
N=5  # 4 active + 1 spare

cleanup_loops() {
    sudo umount /mnt/raid5 2>/dev/null || true
    sudo mdadm --stop /dev/md5 2>/dev/null || true
    for i in $(seq 0 $((N-1))); do
        IMG="$WORK/disk${i}.img"
        for L in $(sudo losetup -j "$IMG" 2>/dev/null | cut -d: -f1); do
            sudo losetup -d "$L" 2>/dev/null || true
        done
    done
}
trap cleanup_loops INT TERM

# 1) 5개 디스크 (4 RAID + 1 핫스페어)
LOOPS=()
for i in $(seq 0 $((N-1))); do
    sudo dd if=/dev/zero of="$WORK/disk${i}.img" bs=1M count=200 status=none
    L=$(sudo losetup -f --show "$WORK/disk${i}.img")
    LOOPS+=("$L")
done
echo "→ loops: ${LOOPS[*]}"

ACTIVE=("${LOOPS[@]:0:4}")
SPARE="${LOOPS[4]}"

# 2) RAID-5 생성 — 4 active + 1 spare
sudo mdadm --create /dev/md5 --metadata=1.2 \
    --level=5 --raid-devices=4 \
    "${ACTIVE[@]}" \
    --spare-devices=1 "$SPARE" \
    --run

while grep -q "resync\|recovery" /proc/mdstat; do sleep 1; done

echo
echo "=== /proc/mdstat ==="
cat /proc/mdstat
echo "→ [UUUU] 4개 active. spare 가 (S) 로 표시됨."

# 3) 포맷 + 데이터 + 체크섬
sudo mkfs.ext4 -F /dev/md5 >/dev/null
sudo mkdir -p /mnt/raid5
sudo mount /dev/md5 /mnt/raid5
sudo dd if=/dev/urandom of=/mnt/raid5/big.bin bs=1M count=100 status=none
CKSUM=$(sudo sha256sum /mnt/raid5/big.bin | awk '{print $1}')

echo
echo "=== 데이터 sha256 (기준) ==="
echo "$CKSUM"

# 4) 첫 active disk fail — 핫스페어가 자동 투입되어 rebuild 시작
FAIL_DISK="${ACTIVE[0]}"
echo
echo "=== fail: $FAIL_DISK ==="
sudo mdadm --fail /dev/md5 "$FAIL_DISK"
sleep 1
cat /proc/mdstat
echo "→ spare 가 자리잡고 recovery 시작 (수십 초)"

# 5) rebuild 대기
echo
echo "=== rebuild 대기 ==="
while grep -q "recovery" /proc/mdstat; do
    sleep 2
    grep "recovery" /proc/mdstat | head -1 || true
done

echo
echo "=== rebuild 완료 후 ==="
cat /proc/mdstat
sudo mdadm --detail /dev/md5 | grep -E "State|Active|Working|Failed|Spare"

# 6) 데이터 무결성 (rebuild 후에도 sha256 동일해야)
echo
echo "=== 무결성 검증 ==="
NEW=$(sudo sha256sum /mnt/raid5/big.bin | awk '{print $1}')
[ "$CKSUM" = "$NEW" ] && echo "→ OK (일치)" || { echo "→ 불일치!"; exit 1; }

# 7) 죽은 디스크 제거
sudo mdadm --remove /dev/md5 "$FAIL_DISK"

# 8) 정리
sudo umount /mnt/raid5
sudo mdadm --stop /dev/md5
cleanup_loops
echo
echo "정리 완료."
