ceph/src/rbdmap
Marc Schoechlin fca5ef8aba common: fix for broken rbdmap parameter parsing
This improves the broken parameter parsing discussed in #36327

Test expression for the parsing function:

PARAMS="options='lock_on_read,queue_depth=1024',id=archiv,keyring=/etc/ceph/ceph.client.archiv.keyring"
echo -e " ORIGINAL PARAM: >>>$PARAMS<<<\nCONVERTED PARAM: >>>$(create_cmd_params "$PARAMS")<<<"

PARAMS="id=archiv,keyring=/etc/ceph/ceph.client.archiv.keyring,options='lock_on_read,queue_depth=1024'"
echo -e " ORIGINAL PARAM: >>>$PARAMS<<<\nCONVERTED PARAM: >>>$(create_cmd_params "$PARAMS")<<<"

PARAMS=""
echo -e " ORIGINAL PARAM: >>>$PARAMS<<<\nCONVERTED PARAM: >>>$(create_cmd_params "$PARAMS")<<<"

PARAMS=",keyring=/etc/ceph/ceph.client.archiv.keyring,options='lock_on_read,queue_depth=1024',id=archiv,"
echo -e " ORIGINAL PARAM: >>>$PARAMS<<<\nCONVERTED PARAM: >>>$(create_cmd_params "$PARAMS")<<<"

PARAMS="'keyring'=/etc/ceph/ceph.client.archiv.keyring,options='lock_on_read,queue_depth=1024',id=archiv,"
echo -e " ORIGINAL PARAM: >>>$PARAMS<<<\nCONVERTED PARAM: >>>$(create_cmd_params "$PARAMS")<<<"

PARAMS="--keyring=/etc/ceph/ceph.client.archiv.keyring,options='lock_on_read,queue_depth=1024',id=archiv, # a comment"
echo -e " ORIGINAL PARAM: >>>$PARAMS<<<\nCONVERTED PARAM: >>>$(create_cmd_params "$PARAMS")<<<"

Fixes: https://tracker.ceph.com/issues/36327
Signed-off-by: Marc Schoechlin <ms@256bit.org]>
2019-01-14 14:29:59 -05:00

211 lines
4.4 KiB
Bash
Executable File

#!/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