#!/usr/bin/env bash create_cmd_params() { local PARAMS="$1" local CMDPARAMS="" local STATE="START" for (( i=0; i<${#PARAMS}; i++ )); do CHAR="${PARAMS:$i:1}" case $CHAR in "#") break ;; "'") if [ "$STATE" == "INQUOTE" ];then STATE="NORMAL" else STATE="INQUOTE" fi ;; "=") if [ "$STATE" == "INQUOTE" ]; then CMDPARAMS="${CMDPARAMS}${CHAR}" else CMDPARAMS="${CMDPARAMS} " fi ;; ",") if [ "$STATE" == "INQUOTE" ]; then CMDPARAMS="${CMDPARAMS}${CHAR}" elif [ "$STATE" == "START" ]; then STATE="NORMAL" CMDPARAMS="${CMDPARAMS} --" else CMDPARAMS="${CMDPARAMS} --" fi ;; *) if [ "$STATE" == "START" ];then STATE="NORMAL" CMDPARAMS="${CMDPARAMS}--${CHAR}" else CMDPARAMS="${CMDPARAMS}${CHAR}" fi ;; esac done echo -n "$CMDPARAMS" } do_map() { # Read /etc/rbdtab to create non-existant mapping RET=0 while read DEV PARAMS; do case "$DEV" in ""|\#*) continue ;; */*) ;; *) DEV=rbd/$DEV ;; esac CMDPARAMS="$(create_cmd_params "${PARAMS}")" logger -p "daemon.debug" -t rbdmap "Mapping '${DEV}'" newrbd="" MAP_RV="" if [ -b /dev/rbd/$DEV ]; then MAP_RV="$(readlink -f /dev/rbd/$DEV)" else MAP_RV="$(rbd device map $DEV $CMDPARAMS 2>&1)" if [ $? -eq 0 ]; then newrbd="yes" else RET=$((${RET}+$?)) logger -p "daemon.warning" -t rbdmap "Failed to map '${DEV}" continue fi fi logger -p "daemon.debug" -t rbdmap "Mapped '${DEV}' to '${MAP_RV}'" if [ "$newrbd" ]; then ## Mount new rbd MNT_RV="" mount --fake /dev/rbd/$DEV >>/dev/null 2>&1 \ && MNT_RV=$(mount -vn /dev/rbd/$DEV 2>&1) [ -n "${MNT_RV}" ] && logger -p "daemon.debug" -t rbdmap "Mounted '${MAP_RV}' to '${MNT_RV}'" ## post-mapping if [ -x "/etc/ceph/rbd.d/${DEV}" ]; then logger -p "daemon.debug" -t rbdmap "Running post-map hook '/etc/ceph/rbd.d/${DEV}'" /etc/ceph/rbd.d/${DEV} map "/dev/rbd/${DEV}" fi fi done < $RBDMAPFILE exit ${RET} } unmount_unmap() { local rbd_dev=$1 local mnts=$(findmnt --mtab --source ${rbd_dev} --noheadings \ | awk '{print $1'}) logger -p "daemon.debug" -t rbdmap "Unmapping '${rbd_dev}'" for mnt in ${mnts}; do logger -p "daemon.debug" -t rbdmap "Unmounting '${mnt}'" umount "${mnt}" >>/dev/null 2>&1 if mountpoint -q "${mnt}"; then ## Un-mounting failed. logger -p "daemon.warning" -t rbdmap "Failed to unmount '${mnt}'" return 1 fi done ## Un-mapping. rbd device unmap $rbd_dev >>/dev/null 2>&1 if [ $? -ne 0 ]; then logger -p "daemon.warning" -t rbdmap "Failed to unmap '${mnt}'" return 1 fi logger -p "daemon.debug" -t rbdmap "Unmapped '${rbd_dev}'" return 0 } do_unmap_all() { RET=0 ## Unmount and unmap all rbd devices if ls /dev/rbd[0-9]* >/dev/null 2>&1; then for DEV in /dev/rbd[0-9]*; do ## pre-unmapping for L in $(find /dev/rbd -type l); do LL="${L##/dev/rbd/}" if [ "$(readlink -f $L)" = "${DEV}" ] \ && [ -x "/etc/ceph/rbd.d/${LL}" ]; then logger -p "daemon.debug" -t rbdmap "Running pre-unmap hook for '${DEV}': '/etc/ceph/rbd.d/${LL}'" /etc/ceph/rbd.d/${LL} unmap "$L" break fi done unmount_unmap "$DEV" || RET=$((${RET}+$?)) done fi exit ${RET} } do_unmap() { RET=0 ## skip if nothing is mapped ls /dev/rbd[0-9]* >/dev/null 2>&1 || exit ${RET} # Read /etc/rbdtab to create non-existant mapping while read DEV PARAMS; do case "$DEV" in ""|\#*) continue ;; */*) ;; *) DEV=rbd/$DEV ;; esac MAP_RV="$(readlink -f /dev/rbd/$DEV)" if [ ! -b $MAP_RV ]; then logger -p "daemon.debug" -t rbdmap "$DEV not mapped, skipping unmap" continue fi ## pre-unmapping if [ -x "/etc/ceph/rbd.d/${DEV}" ]; then logger -p "daemon.debug" -t rbdmap "Running pre-unmap hook '/etc/ceph/rbd.d/${DEV}'" /etc/ceph/rbd.d/${DEV} unmap "/dev/rbd/${DEV}" fi unmount_unmap "$MAP_RV" || RET=$((${RET}+$?)) done < $RBDMAPFILE exit ${RET} } # default to reasonable value if RBDMAPFILE not set in environment RBDMAPFILE="${RBDMAPFILE:-/etc/ceph/rbdmap}" if [ ! -f "$RBDMAPFILE" ]; then logger -p "daemon.warning" -t rbdmap "No $RBDMAPFILE found." exit 0 fi case "$1" in map) do_map ;; unmap) do_unmap ;; unmap-all) do_unmap_all ;; *) echo "Usage: rbdmap map | unmap | unmap-all" esac