#!/bin/bash

# ******************************************************************************
# EOS - the CERN Disk Storage System
# Copyright (C) 2018 CERN/Switzerland
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# ******************************************************************************

#------------------------------------------------------------------------------
# Description: Script testing the draining mechanism of EOS. It assumes that
#              there are at least 7 FSTs available in the instance.
#
# Usage:
# eos-drain-test <eos_mgm_hostname>
#------------------------------------------------------------------------------

if [[ $# -eq 0 || $# -gt 2 ]]; then
      echo "Usage: $0 <eos_mgm_hostname>"
      exit 1
fi

EOS_MGM_HOSTNAME=$1

# Check preconditions and make sure central draining is enabled
FST_ONLINE=$(eos fs ls | grep "online" | wc -l)

if [[ ${FST_ONLINE} -lt 7 ]]; then
      echo "error: not enough FSTs configured"
      exit 1
fi

eos space config default space.drainer.node.nfs=1
eos space config default space.drainer.node.ntx=5

# Create dummy test files
TEST_FN0=/tmp/zero.dat
TEST_FN1=/tmp/32kb.dat
TEST_FN2=/tmp/5mb.dat

touch ${TEST_FN0}
dd if=/dev/urandom of=${TEST_FN1} bs=1k count=32 &> /dev/null
dd if=/dev/urandom of=${TEST_FN2} bs=1M count=5  &> /dev/null

# Create eos directory for tests and copy some files in
eos mkdir -p /eos/dockertest/drain_test/replica/
eos mkdir -p /eos/dockertest/drain_test/raiddp/
eos mkdir -p /eos/dockertest/drain_test/rain/
eos chmod 2777 /eos/dockertest/
eos chmod 2777 /eos/dockertest/drain_test/replica/
eos chmod 2777 /eos/dockertest/drain_test/raiddp/
eos chmod 2777 /eos/dockertest/drain_test/rain/
eos attr set default=replica /eos/dockertest/drain_test/replica/
eos attr set default=raiddp /eos/dockertest/drain_test/raiddp/
eos attr set default=raid6 /eos/dockertest/drain_test/rain/
eos fs ls

for i in {1..4}; do
      xrdcp -f --nopbar ${TEST_FN0} root://${EOS_MGM_HOSTNAME}//eos/dockertest/drain_test/replica/0kb_file${i}.dat
      xrdcp -f --nopbar ${TEST_FN0} root://${EOS_MGM_HOSTNAME}//eos/dockertest/drain_test/raiddp/0kb_file${i}.dat
      xrdcp -f --nopbar ${TEST_FN0} root://${EOS_MGM_HOSTNAME}//eos/dockertest/drain_test/rain/0kb_file${i}.dat
      xrdcp -f --nopbar ${TEST_FN1} root://${EOS_MGM_HOSTNAME}//eos/dockertest/drain_test/replica/32kb_file${i}.dat
      xrdcp -f --nopbar ${TEST_FN1} root://${EOS_MGM_HOSTNAME}//eos/dockertest/drain_test/raiddp/32kb_file${i}.dat
      xrdcp -f --nopbar ${TEST_FN1} root://${EOS_MGM_HOSTNAME}//eos/dockertest/drain_test/rain/32kb_file${i}.dat
      xrdcp -f --nopbar ${TEST_FN2} root://${EOS_MGM_HOSTNAME}//eos/dockertest/drain_test/replica/5mb_file${i}.dat
      xrdcp -f --nopbar ${TEST_FN2} root://${EOS_MGM_HOSTNAME}//eos/dockertest/drain_test/raiddp/5mb_file${i}.dat
      xrdcp -f --nopbar ${TEST_FN2} root://${EOS_MGM_HOSTNAME}//eos/dockertest/drain_test/rain/5mb_file${i}.dat
done

# Check that the file system is ready
eos fs ls | grep " 1 " | grep "rw" | grep "nodrain" | grep "online"

if [[ $? -ne 0 ]]; then
      echo "error: file system 1 is not online  ..."
      eos fs ls
      exit 1
fi

# Set all file systems in RO mode except for fsid 1 and 2 - then start a long
# running process which writes a file. The purpose is to test the draining of
# files being written when the draining is started.
for (( i=3; i<=${FST_ONLINE}; i++ )); do
    eos fs config $i configstatus=ro
done

# Start long running write operation which should select fsts 1 and 2 as destination
xrdcpslowwriter root://${EOS_MGM_HOSTNAME}//eos/dockertest/drain_test/replica/slow_writer.dat &
xrdcpslowwriter_pid=$!
sleep 2

# Put back the rest of the file systems in rw mode so that the draining can
# select them as destination.
for (( i=3; i<=${FST_ONLINE}; i++ )); do
    eos fs config $i configstatus=rw
done

eos file info /eos/dockertest/drain_test/replica/slow_writer.dat

# Start draining and wait for it to finish
eos fs config 1 configstatus=drain
eos fs ls | grep " 1 " | grep "drain" | grep "prepare\|draining"

while [[ $? -eq 0 ]]; do
      sleep 2
      eos fs ls | grep " 1 " | grep "drain" | grep "prepare\|draining"
done

eos fs ls | grep " 1 " | grep "empty" | grep "drained"

if [[ $? -ne 0 ]]; then
      echo "error: file system 1 is not drained"
      exit 1
else
    echo "File system 1 successfully drained"
fi

# Put back the file system in rw mode
eos fs config 1 configstatus=rw

if [[ $? -ne 0 ]]; then
      echo "error: failed to put file system in rw mode"
      exit 1
fi

# Wait for the slow writer to finish before clean-up
wait ${xrdcpslowwriter_pid}

# Remove all the files and directories
eos rm -rF "/eos/dockertest/drain_test/replica/*"
eos rm -rF "/eos/dockertest/drain_test/raiddp/*"
eos rm -rF "/eos/dockertest/drain_test/rain/*"
eos rmdir "/eos/dockertest/drain_test/replica/"
eos rmdir "/eos/dockertest/drain_test/raiddp/"
eos rmdir "/eos/dockertest/drain_test/rain/"
eos rmdir "/eos/dockertest/drain_test/"
exit 0
