#!/bin/bash set -e # ---------------------------------------------------------------------- # File: eos-qos-test # Author: Mihai Patrascoiu - CERN # ---------------------------------------------------------------------- # ****************************************************************************** # EOS - the CERN Disk Storage System # Copyright (C) 2019 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 . # ****************************************************************************** #------------------------------------------------------------------------------ # Description: Script testing the QoS class functionality of EOS. # The following requirements must be met: # - MGM running with Converter Engine enabled # - At least 3 FSTs should be available # - "disk_plain" and "disk_replica" QoS classes # are expected to be defined # # Usage: eos-qos-test [] #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ # Helper functions #------------------------------------------------------------------------------ function usage() { echo "Usage: $0 []" echo " - the /eos// to access" echo " - optional MGM hostname (will use EOS_MGM_URL env variable otherwise)" echo "" exit 1 } function check_preconditions() { local N_FSTS=$1 if (( N_FSTS < 3 )); then echo "error: not enough FSTs booted (should be at least 3)" exit 1 fi eos ns | grep "In-flight FileMD" &> /dev/null if [[ $? -ne 0 ]]; then echo "error: MGM not running with QuarkDB" exit 1 fi rc=$(eos -j qos list | jq '.name[0]' | grep "disk_plain" &> /dev/null && eos -j qos list | jq '.name[1]' | grep "disk_replica" &> /dev/null ; echo $?) if [[ $rc -ne 0 ]]; then echo "error: expected QoS classes [ \"disk_plain\", \"disk_replica\" ] are not defined" exit 1 fi } function element_in_array() { local element=$1 shift for array_item in "$@"; do [[ "$element" == "$array_item" ]] && return 0 done return 1 } function replicate_file() { n_fsts=$(eos fs ls | grep "online" | grep -c "booted") file=$1 locations=($(eos -j fileinfo ${file} | jq '.locations[].fsid')) target_fsid=0 for i in $(seq 1 ${n_fsts}); do if ! element_in_array ${i} "${locations[@]}" ; then target_fsid=${i} break fi done if [[ -z ${target_fsid} ]]; then echo "error: failed to replicate ${file}" exit 1 fi eos file replicate ${file} ${locations[0]} ${target_fsid} sleep 5 } function wait_conversion() { timeout=$1 interval=5 count=0 echo "Waiting ${timeout} seconds for conversion to finish" while true; do pending=$(eos -j convert status | jq .pending) running=$(eos -j convert status | jq .running) if [[ ${pending} -eq "0" && ${running} -eq "0" ]]; then echo "Conversion finished (${count}s)" break fi sleep ${interval} count=$((count + interval)) if [[ ${count} -eq ${timeout} ]]; then echo "error: conversion timeout at ${timeout} seconds" exit 1 fi done } #------------------------------------------------------------------------------ # Global setup #------------------------------------------------------------------------------ if [[ $# -eq 0 || $# -gt 2 ]]; then usage fi # Setup EOS instance variables EOS_INSTANCE_NAME=$1 EOS_MGM_HOSTNAME=$2 if [[ -z "$EOS_MGM_HOSTNAME" ]]; then if [[ -n "$EOS_MGM_URL" ]]; then EOS_MGM_HOSTNAME=${EOS_MGM_URL#root://} EOS_MGM_HOSTNAME=${EOS_MGM_HOSTNAME%:1094/} else EOS_MGM_HOSTNAME=localhost fi fi export EOS_MGM_URL=${EOS_MGM_HOSTNAME} echo "EOS_INSTANCE_NAME=${EOS_INSTANCE_NAME}" echo "EOS_MGM_HOSTNAME=${EOS_MGM_HOSTNAME}" N_FSTS_INITIAL=$(eos fs ls | grep "online" | grep -c "booted") check_preconditions ${N_FSTS_INITIAL} # Create dummy test file TEST_FILE=/tmp/1mb.dat dd if=/dev/urandom of=${TEST_FILE} bs=1k count=1000 &> /dev/null # Setup EOS qos directory eos mkdir /eos/${EOS_INSTANCE_NAME}/qos/ eos chmod 2777 /eos/${EOS_INSTANCE_NAME}/qos/ &> /dev/null eos attr set default=replica /eos/${EOS_INSTANCE_NAME}/qos/ eos cp ${TEST_FILE} root://${EOS_MGM_HOSTNAME}:1094//eos/${EOS_INSTANCE_NAME}/qos/file.dat #------------------------------------------------------------------------------ # Run QoS tests #------------------------------------------------------------------------------ eos -j qos get /eos/${EOS_INSTANCE_NAME}/qos/file.dat | jq '"path=" + .path, "current_qos=" + .current_qos' eos -j qos get /eos/${EOS_INSTANCE_NAME}/qos/file.dat | jq '.current_qos' | grep "disk_replica" &> /dev/null # Replicate file to another file system replicate_file /eos/${EOS_INSTANCE_NAME}/qos/file.dat # Set new QoS class echo "" ; echo "Setting QoS class transition to: \"disk_plain\"" eos -j qos set /eos/${EOS_INSTANCE_NAME}/qos/file.dat disk_plain eos -j qos get /eos/${EOS_INSTANCE_NAME}/qos/file.dat | jq '"current_qos=" + .current_qos, "target_qos=" + (.target_qos|tostring)' eos -j qos get /eos/${EOS_INSTANCE_NAME}/qos/file.dat | jq '.target_qos' | grep "disk_plain" &> /dev/null # Wait for conversion wait_conversion 120 #------------------------------------------------------------------------------ # Perform validations #------------------------------------------------------------------------------ # Check all FSTs are still online N_FSTS_FINAL=$(eos fs ls | grep "online" | grep -c "booted") if [ ${N_FSTS_INITIAL} != ${N_FSTS_FINAL} ]; then echo "error: some FSTs are not online anymore" eos fs ls exit 1 fi # Validate QoS class echo "Verify transition took place" eos -j qos get /eos/${EOS_INSTANCE_NAME}/qos/file.dat | jq '"current_qos=" + .current_qos, "target_qos=" + (.target_qos|tostring)' eos -j qos get /eos/${EOS_INSTANCE_NAME}/qos/file.dat | jq '.current_qos' | grep "disk_plain" &> /dev/null eos -j qos get /eos/${EOS_INSTANCE_NAME}/qos/file.dat | jq '.target_qos' | grep "null" &> /dev/null echo "QoS transition successful" #------------------------------------------------------------------------------ # Perform clean-up #------------------------------------------------------------------------------ eos rm -rf /eos/${EOS_INSTANCE_NAME}/qos/* &> /dev/null eos rmdir /eos/${EOS_INSTANCE_NAME}/qos/ rm ${TEST_FILE} exit 0