#!/bin/bash # License: BeeGFS EULA # constant definitions # (for configurables see below) DEFAULT_CFG_PATH="/etc/beegfs/beegfs-storage.conf" STORAGE_PATH_CFG_KEY="storeStorageDirectory" MGMTD_CFG_KEY="sysMgmtdHost" ALLOW_INIT_CFG_KEY="storeAllowFirstRunInit" FS_UUID_CFG_KEY="storeFsUUID" TARGET_NUMID_FILE="targetNumID" TARGET_STRID_FILE="targetID" SERVER_NUMID_FILE="nodeNumID" STORAGEPOOL_ID_FILE="storagePoolID" FORMAT_FILENAME="format.conf" FORMAT_FILE_VERSION="3" CHUNKS_DIRNAME="chunks" BUDDYMIRROR_DIRNAME="buddymir" print_usage() { echo echo "DESCRIPTION: Initialize storage target directory for beegfs-storage server daemon" echo "and update the beegfs-storage config file." echo echo "USAGE: `basename $0` -p [options]" echo echo " Mandatory Options:" echo echo " -p - Path to storage target directory that is to be initialized." echo " (Path will also be added to config file.)" echo echo " Recommended Options:" echo echo " -i - Assign the given numeric ID to storage target (range 1..65535)." echo " (Default: Randomly select a free ID.)" echo echo " -s - Assign the given numeric ID to the server of this storage target" echo " (range 1..65535). (Default: Randomly select a free ID.)" echo echo " -m - Hostname (or IP address) of management server." echo " (Will be stored in server config file.)" echo echo " Other Options:" echo echo " -C - Do not update server config file." echo echo " -c - Path to server config file." echo " (Default: ${DEFAULT_CFG_PATH})" echo echo " -f - Force actions, ignore warnings." echo echo " -h - Print this help." echo echo " -P - Automatically add the configured target to storage pool with the" echo " given ID on first start." echo echo " -r - Replace current list of target directories with the given path." echo " (Default: Append directory to current target list in server" echo " config file.)" echo echo " -u - Do not disable usage of uninitialized target directories in" echo " config file and do not store the UUID of the underlying fs." echo echo "NOTES:" echo " * All given IDs must be unique in their service class for the whole file system" echo " instance, i.e. there can only be one beegfs-meta service with ID 2, but there" echo " can also be a beegfs-storage service with ID 2 in the file system." echo echo " * BeeGFS servers can also run without pre-initializing storage directories, if" echo " storeAllowFirstRunInit=true is set in the server config files (which is" echo " usually not recommended)." echo echo "EXAMPLES:" echo " * Numeric IDs can generally be chosen arbitrarily. However, in the examples" echo " below they were chosen in a way that reflects the assignment of targets to" echo " their corresponding servers." echo echo " * Example 1) Initialize first target directory \"/mnt/myraid1\" of first" echo " storage server and set \"storage01\" as management daemon host in server" echo " config file:" echo " $ `basename $0` -p /mnt/myraid1/beegfs-storage -s 1 -i 101 -m storage01" echo echo " * Example 2) Initialize second target directory \"/mnt/myraid2\" of fourth" echo " storage server:" echo " $ `basename $0` -p /mnt/myraid2/beegfs-storage -s 4 -i 402" echo } # initialize storage directory (if enabled) init_storage_dir() { # check if storage path is defined if [ -z "${STORAGE_PATH}" ]; then return 0 fi # create storage path echo "Preparing storage target directory: ${STORAGE_PATH}" mkdir -p "${STORAGE_PATH}" # make sure target dir is empty if [ -z "${FORCE_ACTIONS}" ] && [ "$(ls -AI lost+found ${STORAGE_PATH} )" ]; then echo " * ERROR: Storage target directory is not empty. Initialization of non-empty" \ "directories can lead to data loss or orphaned data. ('-f' disables this check.)" exit 1 fi # create format file echo " * Creating ${FORMAT_FILENAME} file..." FORMAT_FILE_PATH="${STORAGE_PATH}/${FORMAT_FILENAME}" echo "# This file was auto-generated. Do not modify it!" >> ${FORMAT_FILE_PATH} echo "version=${FORMAT_FILE_VERSION}" >> ${FORMAT_FILE_PATH} # create chunks dir echo " * Creating ${CHUNKS_DIRNAME} directory..." CHUNKS_DIR_PATH="${STORAGE_PATH}/${CHUNKS_DIRNAME}" mkdir -p ${CHUNKS_DIR_PATH} # create mirror dir echo " * Creating ${BUDDYMIRROR_DIRNAME} directory..." BUDDYMIRROR_DIR_PATH="${STORAGE_PATH}/${BUDDYMIRROR_DIRNAME}" mkdir -p ${BUDDYMIRROR_DIR_PATH} # create ID files if [ -n "${TARGET_NUMID}" ]; then echo " * Creating target numeric ID file: ${STORAGE_PATH}/${TARGET_NUMID_FILE}" echo "${TARGET_NUMID}" > "${STORAGE_PATH}/${TARGET_NUMID_FILE}" fi if [ -n "${TARGET_STRID}" ]; then echo " * Creating target string ID file: ${STORAGE_PATH}/${TARGET_STRID_FILE}" echo "${TARGET_STRID}" > "${STORAGE_PATH}/${TARGET_STRID_FILE}" fi if [ -n "${SERVER_NUMID}" ]; then echo " * Creating server numeric ID file: ${STORAGE_PATH}/${SERVER_NUMID_FILE}" echo "${SERVER_NUMID}" > "${STORAGE_PATH}/${SERVER_NUMID_FILE}" fi if [ -n "${STORAGEPOOL_ID}" ]; then echo " * Creating storage pool ID file: ${STORAGE_PATH}/${STORAGEPOOL_ID_FILE}" echo "${STORAGEPOOL_ID}" > "${STORAGE_PATH}/${STORAGEPOOL_ID_FILE}" fi } # update config file (if enabled) update_config_file() { # check if config file is defined if [ -z "${CFG_PATH}" ]; then return 0 fi echo "Updating config file: ${CFG_PATH}" if [ ! -f "${CFG_PATH}" ]; then echo " * ERROR: Config file not found: ${CFG_PATH}" exit 1 fi if [ -n "${MGMTD_HOST}" ]; then echo " * Setting management host: ${MGMTD_HOST}" sed -i "s/\(^${MGMTD_CFG_KEY}.*=\).*/\1 ${MGMTD_HOST}/" ${CFG_PATH} fi if [ -n "${STORAGE_PATH}" ]; then if [ -n "${REPLACE_TARGETS}" ]; then echo " * Replacing target directory list in config file..." sed -i "s|\(^${STORAGE_PATH_CFG_KEY}.*=\).*$|\1 ${STORAGE_PATH}|" ${CFG_PATH} else echo " * Appending to target directory list in config file..." set +e grep "^${STORAGE_PATH_CFG_KEY}.*=.*${STORAGE_PATH}\([, ]\|$\)" "${CFG_PATH}" >/dev/null GREP_RES=$? set -e if [ "$GREP_RES" -eq 0 ] && [ -z "${FORCE_ACTIONS}" ]; then echo " * WARNING: Skipping append. Target directory seems to be included in" \ "current targets list already. ('-f' disables this check.)" APPEND_SKIPPED=1 else sed -i "s|\(^${STORAGE_PATH_CFG_KEY}.*=.*$\)|\0 ,${STORAGE_PATH}|" ${CFG_PATH} fi fi fi if [ -n "${DISABLE_UNINITED_TARGETS}" ] && [ -n "${STORAGE_PATH}" ]; then echo " * Disabling usage of uninitialized storage targets in config file..." sed -i "s/\(^${ALLOW_INIT_CFG_KEY}.*=\).*/\1 false/" ${CFG_PATH} if [ -z "${APPEND_SKIPPED}" ]; then echo " * Fetching the underlying device..." DEVICE=$(df "${STORAGE_PATH}" | tail -n1 | cut -d\ -f1) echo "Underlying device detected: ${DEVICE}" echo "Fetching UUID of the file system on that device..." UUID=$(blkid -s UUID ${DEVICE} | cut -d= -f2 | sed "s/\"//g") echo "Found UUID ${UUID}" echo "Appending UUID to config file..." sed -i "s|\(^${FS_UUID_CFG_KEY}.*=.*$\)|\0 ,${UUID}|" ${CFG_PATH} fi fi } ################## end of function definitions ############## # configurable values and their defaults # (for constants see above) CFG_PATH="$DEFAULT_CFG_PATH" # empty path means "don't update cfg file" FORCE_ACTIONS="" TARGET_NUMID="" TARGET_STRID="" MGMTD_HOST="" REPLACE_TARGETS="" SERVER_NUMID="" STORAGE_PATH="" STORAGEPOOL_ID="" DISABLE_UNINITED_TARGETS="1" # parse command line arguments # (see print_usage() for description of parameters) while getopts "Cc:fhI:i:m:p:P:rS:s:u" opt; do case $opt in C) CFG_PATH="" ;; c) CFG_PATH="$OPTARG" ;; f) FORCE_ACTIONS="1" ;; h) print_usage exit 0 ;; I) TARGET_STRID="$OPTARG" ;; i) TARGET_NUMID="$OPTARG" ;; m) MGMTD_HOST="$OPTARG" ;; p) STORAGE_PATH="$OPTARG" ;; P) STORAGEPOOL_ID="$OPTARG" ;; r) REPLACE_TARGETS="1" ;; S) echo "WARNING: The -S flag previously used to specify a string ID been deprecated and now has no effect. Starting in BeeGFS string IDs were replaced with aliases configured using BeeGFS CTL." ;; s) SERVER_NUMID="$OPTARG" ;; u) DISABLE_UNINITED_TARGETS="" ;; *) echo "ERROR: Invalid argument" >&2 print_usage exit 1 ;; esac done set -e # don't do anything if no arguments are provided if [ $# -eq 0 ]; then print_usage exit 1 fi # make sure target dir is defined if [ -z "${STORAGE_PATH}" ]; then echo "ERROR: Storage target directory is undefined." >&2 echo print_usage exit 1 fi # initialize storage directory init_storage_dir # update config file update_config_file echo "All done."