#!/bin/sh # Copyright 2016 Dell EMC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Notes: # - Please install "jq" package before using this driver. # - Please install and configure REX-Ray before using this driver # detect which binary is available: rexray-client or rexray if which -s rexray-client; then REXRAY_BIN=$(which rexray-client) elif which -s rexray; then REXRAY_BIN=$(which rexray) else echo "error: rexray-client/rexray not detected" exit 1 fi err() { printf "%b" "$*" 1>&2 } log() { printf "%b" "$*" >&1 } success() { log '{"status": "Success"}' exit 0 } usage() { err "error: invalid usage\n" err "\t$0 init\n" err "\t$0 attach \n" err "\t$0 detach \n" err "\t$0 mount \n" err "\t$0 unmount \n" exit 1 } ismounted() { MOUNT=$(findmnt -n "${MNTPATH}" 2>/dev/null | cut -d' ' -f1) if [ "${MOUNT}" = "${MNTPATH}" ]; then echo "1" else echo "0" fi } attach() { VOLUMEID=$(echo "$1" | jq -r '.volumeID') FORCE_ATTACH=$(echo "$1" | jq -r '.forceAttach') FORCE_ATTACH_DELAY=$(echo "$1" | jq -r '.forceAttachDelay') if [ -z "$VOLUMEID" ]; then err '{"status": "Failure", "message": "Unable to extract volumeID"}' exit 1 fi if [ "$FORCE_ATTACH" = "true" ]; then if echo "$FORCE_ATTACH_DELAY" | grep '^-\{0,1\}[[:digit:]]\{1,\}$' > /dev/null; then STATUS_CHECKS=$(( FORCE_ATTACH_DELAY / 5 )) COUNTER=0 COUNTER_LOGGED=1 while [ "$COUNTER" -lt "$STATUS_CHECKS" ]; do VOLUME_STATUS=$(${REXRAY_BIN} volume ls "${VOLUMEID}" --format json 2>/dev/null | jq '.[0].attachmentState') if [ "$FLEXREX_DEBUG" -eq "1" ]; then echo "checked volume status. volume status is ${VOLUME_STATUS}" >> /var/log/flexrex_force.log fi if [ "$VOLUME_STATUS" -eq "3" ] || [ "$VOLUME_STATUS" -eq "2" ]; then if [ "$FLEXREX_DEBUG" -eq "1" ]; then echo "volume is available, breaking loop" >> /var/log/flexrex_force.log fi break; fi if [ "$FLEXREX_DEBUG" -eq "1" ]; then echo "sleeping for 5 seconds after status check #${COUNTER_LOGGED}" >> /var/log/flexrex_force.log fi sleep 5 [ "$(( COUNTER=COUNTER+1 ))" -ne 0 ] [ "$(( COUNTER_LOGGED=COUNTER_LOGGED+1 ))" -ne 0 ] done fi OUTPUT=$(${REXRAY_BIN} volume attach "${VOLUMEID}" -i --force --format json 2>/dev/null) ATTACH_EXIT_CODE=$? else OUTPUT=$(${REXRAY_BIN} volume attach "${VOLUMEID}" -i --format json 2>/dev/null) ATTACH_EXIT_CODE=$? fi if [ "$ATTACH_EXIT_CODE" -ne "0" ]; then err "{\"status\": \"Failure\", \"message\": \"REX-Ray returned error during attach\"}" exit 1 fi # Make second call to get device info OUTPUT=$(${REXRAY_BIN} volume ls "${VOLUMEID}" --path --format json 2>/dev/null) DEV=$(echo "${OUTPUT}" | jq -r '.[0].attachments[0].deviceName') if [ -z "$DEV" ]; then err '{"status": "Failure", "message": "REX-Ray did not return attached device name"}' exit 1 fi if [ ! -b "${DEV}" ]; then err "{\"status\": \"Failure\", \"message\": \"Volume ${VOLUMEID} not present at ${DEV}\"}" exit 1 fi log "{\"status\": \"Success\", \"device\":\"${DEV}\"}" exit 0 } detach() { DEV=$1 if [ ! -b "${DEV}" ]; then err "{\"status\": \"Failure\", \"message\": \"Device ${DEV} does not exist\"}" exit 1 fi VOLUMES=$(${REXRAY_BIN} volume ls --path --format json 2>/dev/null) VOLUMEID=$(echo "${VOLUMES}" | jq -r "[.[] | {id: .id, device:.attachments[0].deviceName}] | .[] | select(.device == '${DEV}') | .id") if [ -z "$VOLUMEID" ]; then err "{\"status\": \"Failure\", \"message\": \"Could not find source volume for device ${DEV}\"}" exit 1 fi ${REXRAY_BIN} volume detach -i "${VOLUMEID}" >/dev/null 2>&1 DETACH_EXIT_CODE=$? if [ "$DETACH_EXIT_CODE" -ne "0" ]; then err "{\"status\": \"Failure\", \"message\": \"REX-Ray returned error during detach\"}" exit 1 fi log "{\"status\": \"Success\"}" exit 0 } domount() { MNTPATH=$1 DEV=$2 FSTYPE=$(echo "$3" | jq -r '.["kubernetes.io/fsType"]') if [ ! -b "${DEV}" ]; then err "{\"status\": \"Failure\", \"message\": \"${DEV} does not exist\"}" exit 1 fi if [ "$(ismounted)" -eq "1" ] ; then success fi VOLFSTYPE=$(blkid -o udev "${DEV}" 2>/dev/null | grep "ID_FS_TYPE"| cut -d"=" -f2) if [ "${VOLFSTYPE}" = "" ]; then CMD="mkfs -t ${FSTYPE}" if [ "$FSTYPE" = "ext4" ]; then CMD="${CMD} -F" elif [ "$FSTYPE" = "xfs" ]; then CMD="${CMD} -f" fi if ! ${CMD} "${DEV}" > /dev/null 2>&1; then err "{ \"status\": \"Failure\", \"message\": \"Failed to create fs ${FSTYPE} on device ${DEV}\"}" exit 1 fi fi mkdir -p "${MNTPATH}" > /dev/null 2>&1 if ! mount "${DEV}" "${MNTPATH}" > /dev/null 2>&1; then err "{ \"status\": \"Failure\", \"message\": \"Failed to mount device ${DEV} at ${MNTPATH}\"}" exit 1 fi success } unmount() { MNTPATH=$1 if [ "$(ismounted)" -eq "0" ] ; then success; fi if ! umount "${MNTPATH}" > /dev/null 2>&1; then err "{ \"status\": \"Failed\", \"message\": \"Failed to unmount volume at ${MNTPATH}\"}" exit 1 fi rmdir "${MNTPATH}" > /dev/null 2>&1 success } op=$1 if [ "$op" = "init" ]; then success; fi if [ "$#" -lt "2" ]; then usage; fi shift case "$op" in attach) if [ "$FLEXREX_DEBUG" -eq "1" ]; then printf "%s\t%b\n" "$(date)" "$*" >> /var/log/flexrex_attach.log fi attach "$@" ;; detach) detach "$@" ;; mount) if [ "$FLEXREX_DEBUG" -eq "1" ]; then printf "%s\t%b\n" "$(date)" "$*" >> /var/log/flexrex_mount.log fi domount "$@" ;; unmount) unmount "$@" ;; *) usage esac exit 1