--- /dev/null
+#!/bin/bash
+
+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
+ logger -p "daemon.debug" -t rbdmap "Mapping '${DEV}'"
+ newrbd=""
+ MAP_RV=""
+ OIFS=$IFS
+ IFS=','
+ CMDPARAMS=""
+ for PARAM in ${PARAMS[@]}; do
+ CMDPARAMS="$CMDPARAMS --$(echo $PARAM | tr '=' ' ')"
+ done
+ IFS=$OIFS
+ if [ -b /dev/rbd/$DEV ]; then
+ MAP_RV="$(readlink -f /dev/rbd/$DEV)"
+ else
+ MAP_RV="$(rbd 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 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