--- /dev/null
+#!/bin/bash
+declare -A WWIDMAP
+declare -A NAMEMAP
+declare -A TYPEMAP
+
+WM_DEBUG=yes
+WM_DEFAULT_USER="oracle"
+WM_DEFAULT_GROUP="oracle"
+WM_CONF_PATH="/etc/wwidmap"
+WM_DEV_PATH="oracleasm/disks"
+WM_MAP_PATH="${WM_CONF_PATH}/map"
+WM_CONF="${WM_CONF_PATH}/conf"
+WM_USER="$WM_DEFAULT_USER"
+WM_GROUP="$WM_DEFAULT_GROUP"
+WM_LOCK="/var/lock/wm.lock"
+WM_SCSI_ID="/sbin/scsi_id"
+WM_SCSI_ID_FLAGS="-g -u"
+
+# load config
+. $WM_CONF
+
+error () {
+ echo "ERROR: $@" 1>&2
+}
+
+warn () {
+ echo "WARNING: $@" 1>&2
+}
+
+debug () {
+ [ "$WM_DEBUG" == "yes" ] && echo "$@" 1>&2
+}
+
+# debug print
+print_wwid_mapping() {
+ local WWID=$1
+ if [ "$WWID" == "" ]; then
+ return
+ fi
+ debug "NNAME for WWID '$WWID' is: '${WWIDMAP[$WWID]}' (${TYPEMAP[$WWID]})"
+}
+
+# store the WWID map to disk
+wm_store_wwid_map() {
+ TMP_MAP=$(mktemp --tmpdir=$WM_CONF_DIR)
+ if [ ! -f $TMP_MAP ]; then
+ error "could not write temporary file"
+ exit 1
+ fi
+ for WWID in ${!WWIDMAP[@]}; do
+ echo "$WWID ${WWIDMAP[$WWID]} ${TYPEMAP[$WWID]}"
+ done >> $TMP_MAP
+ mv $TMP_MAP $WM_MAP_PATH
+}
+
+# read the WWID map from disk
+wm_load_wwid_map() {
+ if [ ! -f $WM_MAP_PATH ] || [ ! -r $WM_MAP_PATH ]; then
+ error "$WM_MAP_PATH does not exist or is not readable"
+ exit 1
+ fi
+ while read WWID NNAME TYPE; do
+ if [[ $WWID == \#* ]]; then
+ continue
+ fi
+ WWIDMAP[$WWID]="$NNAME"
+ NAMEMAP[$NNAME]="$WWID"
+ TYPEMAP[$WWID]="$TYPE"
+ done < $WM_MAP_PATH
+}
+
+# add_wwid_mapping <wwid> <nickname> <sd|mpath>
+add_wwid_mapping() {
+ local WWID
+ WWID="$1"
+ NNAME="$2"
+ if [ "$WWID" == "" ]; then
+ warn "no wwid given"
+ return
+ fi
+ if [ "$NNAME" == "" ]; then
+ warn "no nickname given"
+ return
+ fi
+ if [ "${NAMEMAP[$WWID]}" != "" ]; then
+ warn "$WWID already mapped to name ${NAMEMAP[$WWID]}; replacing it."
+ fi
+ WWIDMAP[$WWID]="$NNAME"
+ NAMEMAP[$NNAME]="$WWID"
+ TYPEMAP[$WWID]="sd"
+}
+
+# del_wwid_mapping <wwid>
+del_wwid_mapping() {
+ local WWID NNAME
+ WWID="$1"
+ if [ "$WWID" == "" ]; then
+ return 1
+ fi
+ if [ "${WWIDMAP[$WWID]}" == "" ]; then
+ warn "WARNING: $WWID does not exist; doing nothing."
+ return 1
+ fi
+ NNAME=${WWIDMAP[$WWID]}
+ unset WWIDMAP[$WWID]
+ unset NAMEMAP[$NNAME]
+ unset TYPEMAP[$WWID]
+}
+
+wm_scsi_id () {
+ $WM_SCSI_ID $WM_SCSI_ID_FLAGS $1
+}
+
+wm_configure () {
+ cat <<EOF
+Configuring the udev wwid map.
+
+This will configure persistent mappings and permissions for storage
+devices. The current values will be shown in brackets ('[]'). Hitting
+<ENTER> without typing an answer will keep the current value. Ctrl-C
+will abort.
+
+EOF
+
+ echo -n "Default user to own device nodes [$WM_USER]: "
+ read _WM_USER
+ if [ "$_WM_USER" != "" ]; then
+ WM_USER=$_WM_USER;
+ fi
+ echo -n "Default group to own device nodes [$WM_GROUP]: "
+ read _WM_GROUP
+ if [ "$_WM_GROUP" != "" ]; then
+ WM_GROUP=$_WM_GROUP;
+ fi
+ echo -n "Default device directory [$WM_DEV_PATH]: "
+ read _WM_DEV_PATH
+ if [ "$_WM_DEV_PATH" != "" ]; then
+ WM_DEV_PATH=$_WM_DEV_PATH;
+ fi
+ debug "WM_DEV_PATH=\"$WM_DEV_PATH\""
+ debug "WM_USER=\"$WM_USER\""
+ debug "WM_GROUP=\"$WM_GROUP\""
+ echo -n "Writing wwid map configuration: "
+ TMP_CONF=$(mktemp --tmpdir=$WM_CONF_PATH)
+ if [ ! -f $TMP_CONF ]; then
+ echo
+ error "could not write temporary file"
+ exit 1
+ fi
+ echo "WM_DEV_PATH=\"$WM_DEV_PATH\"" >> $TMP_CONF
+ echo "WM_USER=\"$WM_USER\"" >> $TMP_CONF
+ echo "WM_GROUP=\"$WM_GROUP\"" >> $TMP_CONF
+ mv $TMP_CONF $WM_CONF
+ if [ "$?" != 0 ]; then
+ error "could not create configuration file $WM_CONF"
+ exit
+ fi
+ echo "done"
+}
+
+# createdisk <nickname> <device>
+wm_createdisk () {
+ local WWID DEV NNAME
+ NNAME="$1"
+ DEV="$2"
+ if [ "$DEV" == "" ] || [ "$NNAME" == "" ]; then
+ echo "Usage: $0 createdisk <nickname> <device>"
+ exit 2
+ fi
+ WWID=$(wm_scsi_id $DEV)
+ add_wwid_mapping $WWID $NNAME "sd"
+ wm_store_wwid_map
+}
+
+wm_deletedisk () {
+ local WWID NNAME
+ NNAME=$1
+ if [ "$NNAME" == "" ]; then
+ echo "Usage: $0 deletedisk <nickname>"
+ exit 2
+ fi
+ WWID=${NAMEMAP[$NNAME]}
+ if [ "$WWID" == "" ]; then
+ error "\"$NNAME\" does not exist"
+ echo "Usage: $0 deletedisk <nickname>"
+ exit 2
+ fi
+ echo -n "Removing wwid map disk \"$NNAME\":"
+ del_wwid_mapping $WWID \
+ && echo " [ OK ]"
+ wm_store_wwid_map
+}
+
+wm_list_disks () {
+ for D in ${WWIDMAP[@]}; do
+ echo $D
+ done | sort -V
+}
+
+wm_querydisk () {
+ warn "(unimplemented)"
+}
+
+wm_scandisks () {
+ warn "(unimplemented)"
+}
+
+wm_map () {
+ local WWID
+ WWID="$1"
+ if [ "$WWID" == "" ] || [ "${WWIDMAP[$WWID]}" == "" ]; then
+ echo "Usage: $0 map <wwid>" 1>&2
+ exit 2
+ fi
+ echo "WM_WWID=$WWID"
+ echo "WM_NAME=$WM_DEV_PATH/${WWIDMAP[$WWID]}"
+ echo "WM_TYPE=${TYPEMAP[$WWID]}"
+ echo "WM_USER=$WM_USER"
+ echo "WM_GROUP=$WM_GROUP"
+}
+
+case "$1" in
+ configure)
+ wm_configure
+ ;;
+ createdisk)
+ wm_load_wwid_map
+ wm_createdisk $2 $3
+ ;;
+ deletedisk)
+ wm_load_wwid_map
+ wm_deletedisk $2
+ ;;
+ listdisks)
+ wm_load_wwid_map
+ wm_list_disks
+ ;;
+ querydisk)
+ wm_querydisk
+ ;;
+ scandisks)
+ wm_scandisks
+ ;;
+ map)
+ wm_load_wwid_map
+ wm_map $2
+ ;;
+ *)
+ echo -n "Usage: $0 "
+ echo "{configure|createdisk|deletedisk|scandisks|querydisk|map}"
+ exit 2
+esac
+