#!/usr/bin/env bash
set -euo pipefail
# Ön hazırlık
#Paket Kur

apt install fio

#test klasörünü aç

mkdir /mnt/datastore_test

# -----------------------
# AYARLAR (DÜZENLE)
# -----------------------
TEST_DIR="/mnt/datastore_test"         # SAN üzerinden gelen FS mount noktası (ÖRN: VMFS/NFS/FC LUN mount)
TEST_FILE="fio_san_testfile.bin"
FILE_SIZE="5G"
RUNTIME_SEC=$((24*60*60))              # 24 saat
RWMIXREAD="50"                         # % okuma (50/50 agresif)
BS="4k"                                # küçük blok = yüksek IOPS
IODEPTH="256"                          # derin kuyruk
IOENGINE="libaio"
DIRECT="1"                             # page cache bypass
GROUP_REPORTING="1"
LOG_DIR="/var/log/fio_san_24h_$(date +%F_%H%M%S)"
# -----------------------

require_bin() { command -v "$1" >/dev/null 2>&1 || { echo "ERROR: '$1' yok. Kur: yum/apt install $1"; exit 1; }; }

require_bin fio
require_bin df
require_bin awk
require_bin sed
require_bin date
require_bin dmesg
command -v iostat >/dev/null 2>&1 || echo "WARN: iostat yok (sysstat). Olsa iyi olur."
command -v sar    >/dev/null 2>&1 || echo "WARN: sar yok (sysstat). Olsa iyi olur."

mkdir -p "$LOG_DIR"

# -----------------------
# GÜVENLİK KONTROLLERİ
# -----------------------
if [[ ! -d "$TEST_DIR" ]]; then
  echo "ERROR: TEST_DIR yok: $TEST_DIR"
  exit 1
fi

# Asla block device yazma:
if [[ "$TEST_DIR" =~ ^/dev/ ]]; then
  echo "ERROR: TEST_DIR bir /dev path'i olamaz. (Raw block device yazma riski)"
  exit 1
fi

# Boş alan kontrolü (en az 6G öneri)
FREE_GB=$(df -BG --output=avail "$TEST_DIR" | tail -n1 | tr -dc '0-9')
if [[ -z "${FREE_GB:-}" || "$FREE_GB" -lt 6 ]]; then
  echo "ERROR: TEST_DIR içinde yeterli boş alan yok. En az 6G önerilir. Free=${FREE_GB}G"
  exit 1
fi

TEST_PATH="${TEST_DIR%/}/$TEST_FILE"

echo "============================================================"
echo "FIO 24h SAN Stress Test"
echo "TEST_DIR   : $TEST_DIR"
echo "TEST_PATH  : $TEST_PATH"
echo "FILE_SIZE  : $FILE_SIZE"
echo "RUNTIME    : ${RUNTIME_SEC}s (24h)"
echo "BS         : $BS"
echo "IODEPTH    : $IODEPTH"
echo "DIRECT     : $DIRECT"
echo "LOG_DIR    : $LOG_DIR"
echo "============================================================"

# CPU sayısına göre paralellik (tüm kaynaklara abanır)
CPU_JOBS=$(nproc)
# Çok abartıp sistemi öldürmemek için üst limit (istersen yükselt)
if [[ "$CPU_JOBS" -gt 32 ]]; then CPU_JOBS=32; fi

echo "numjobs: $CPU_JOBS"

# -----------------------
# MONITOR (opsiyonel)
# -----------------------
# dmesg takip
( while true; do
    echo "----- $(date -Is) dmesg (errors filtered) -----" >> "$LOG_DIR/dmesg_errors.log"
    dmesg -T | egrep -i "error|fail|timeout|reset|abort|scsi|fc|nvme|blk_update_request|I/O error" | tail -n 200 >> "$LOG_DIR/dmesg_errors.log" || true
    sleep 60
  done ) &
DMESG_PID=$!

# iostat takip (varsa)
IOSTAT_PID=""
if command -v iostat >/dev/null 2>&1; then
  ( iostat -x 5 > "$LOG_DIR/iostat_x_5s.log" ) &
  IOSTAT_PID=$!
fi

# sar takip (varsa)
SAR_PID=""
if command -v sar >/dev/null 2>&1; then
  ( sar -n DEV 5 > "$LOG_DIR/sar_net_5s.log" ) &
  SAR_PID=$!
fi

cleanup() {
  echo "Cleaning up..."
  [[ -n "${DMESG_PID:-}" ]]  && kill "$DMESG_PID" 2>/dev/null || true
  [[ -n "${IOSTAT_PID:-}" ]] && kill "$IOSTAT_PID" 2>/dev/null || true
  [[ -n "${SAR_PID:-}" ]]    && kill "$SAR_PID" 2>/dev/null || true
  echo "Loglar: $LOG_DIR"
}
trap cleanup EXIT

# -----------------------
# FIO JOB
# -----------------------
# Notlar:
# - time_based + runtime = 24 saat
# - randrw + 4k + iodepth 256 = yüksek IOPS basar
# - direct=1 cache'i bypass eder
# - test dosyası: 5G (dosya üzerinde çalışır, disk kompleye yaymaz)
# - refill_buffers=1 + randrepeat=0: pattern çeşitliliği
# - verify=0: ekstra yük azaltır, saf IO
FIO_JOB="$LOG_DIR/fio_job.fio"
cat > "$FIO_JOB" <<EOF
[global]
ioengine=${IOENGINE}
direct=${DIRECT}
time_based=1
runtime=${RUNTIME_SEC}
ramp_time=30
group_reporting=${GROUP_REPORTING}
thread=1
norandommap=1
randrepeat=0
refill_buffers=1
invalidate=1
fsync_on_close=0
size=${FILE_SIZE}
filename=${TEST_PATH}
iodepth=${IODEPTH}
numjobs=${CPU_JOBS}
bs=${BS}
rw=randrw
rwmixread=${RWMIXREAD}
# Loglar
write_bw_log=${LOG_DIR}/bw
write_iops_log=${LOG_DIR}/iops
write_lat_log=${LOG_DIR}/lat
log_avg_msec=1000

[job1]
EOF

echo "FIO başlıyor..."
fio "$FIO_JOB" | tee "$LOG_DIR/fio_stdout.log"

echo "Bitti. Özet:"
egrep -i "read:|write:|IOPS=|BW=|lat|clat|slat|error" "$LOG_DIR/fio_stdout.log" | tail -n 80 || true

echo "Log dizini: $LOG_DIR"

