| #!/usr/bin/env bash | |
| # Licensed to the Apache Software Foundation (ASF) under one | |
| # or more contributor license agreements. See the NOTICE file | |
| # distributed with this work for additional information | |
| # regarding copyright ownership. The ASF licenses this file | |
| # to you 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. | |
| ##################################################################################### | |
| # | |
| # Given a lun # and a WWID for a volume provisioned externally, find the volume | |
| # through the SCSI bus and make sure its visable via multipath | |
| # | |
| ##################################################################################### | |
| LUN=${1:?"LUN required"} | |
| WWID=${2:?"WWID required"} | |
| WWID=$(echo $WWID | tr '[:upper:]' '[:lower:]') | |
| systemctl is-active multipathd || systemctl restart multipathd || { | |
| echo "$(date): Multipathd is NOT running and cannot be started. This must be corrected before this host can access this storage volume." | |
| logger -t "CS_SCSI_VOL_FIND" "${WWID} cannot be mapped to this host because multipathd is not currently running and cannot be started" | |
| exit 1 | |
| } | |
| echo "$(date): Looking for ${WWID} on lun ${LUN}" | |
| # get vendor OUI. we will only delete a device on the designated lun if it matches the | |
| # incoming WWN OUI value. This is because multiple storage arrays may be mapped to the | |
| # host on different fiber channel hosts with the same LUN | |
| INCOMING_OUI=$(echo ${WWID} | cut -c2-7) | |
| echo "$(date): Incoming OUI: ${INCOMING_OUI}" | |
| # first we need to check if any stray references are left from a previous use of this lun | |
| for fchost in $(ls /sys/class/fc_host | sed -e 's/host//g'); do | |
| lingering_devs=$(lsscsi -w "${fchost}:*:*:${LUN}" | grep /dev | awk '{if (NF > 6) { printf("%s:%s ", $NF, $(NF-1));} }' | sed -e 's/0x/3/g') | |
| if [ ! -z "${lingering_devs}" ]; then | |
| for dev in ${lingering_devs}; do | |
| LSSCSI_WWID=$(echo $dev | awk -F: '{print $2}' | sed -e 's/0x/3/g') | |
| FOUND_OUI=$(echo ${LSSCSI_WWID} | cut -c3-8) | |
| if [ "${INCOMING_OUI}" != "${FOUND_OUI}" ]; then | |
| continue; | |
| fi | |
| dev=$(echo $dev | awk -F: '{ print $1}') | |
| logger -t "CS_SCSI_VOL_FIND" "${WWID} processing identified a lingering device ${dev} from previous lun use, attempting to clean up" | |
| MP_WWID=$(multipath -l ${dev} | head -1 | awk '{print $1}') | |
| MP_WWID=${MP_WWID:1} # strip first character (3) off | |
| # don't do this if the WWID passed in matches the WWID from multipath | |
| if [ ! -z "${MP_WWID}" ] && [ "${MP_WWID}" != "${WWID}" ]; then | |
| # run full removal again so all devices and multimap are cleared | |
| $(dirname $0)/disconnectVolume.sh ${MP_WWID} | |
| # we don't have a multimap but we may still have some stranded devices to clean up | |
| elif [ "${LSSCSI_WWID}" != "${WWID}" ]; then | |
| echo "1" > /sys/block/$(echo ${dev} | awk -F'/' '{print $NF}')/device/delete | |
| fi | |
| done | |
| sleep 3 | |
| fi | |
| done | |
| logger -t "CS_SCSI_VOL_FIND" "${WWID} awaiting disk path at /dev/mapper/3${WWID}" | |
| # wait for multipath to map the new lun to the WWID | |
| echo "$(date): Waiting for multipath entry to show up for the WWID" | |
| while true; do | |
| ls /dev/mapper/3${WWID} >/dev/null 2>&1 | |
| if [ $? == 0 ]; then | |
| break | |
| fi | |
| logger -t "CS_SCSI_VOL_FIND" "${WWID} not available yet, triggering scan" | |
| # instruct bus to scan for new lun | |
| for fchost in $(ls /sys/class/fc_host); do | |
| echo " --> Scanning ${fchost}" | |
| echo "- - ${LUN}" > /sys/class/scsi_host/${fchost}/scan | |
| done | |
| multipath -v2 2>/dev/null | |
| ls /dev/mapper/3${WWID} >/dev/null 2>&1 | |
| if [ $? == 0 ]; then | |
| break | |
| fi | |
| sleep 5 | |
| done | |
| echo "$(date): Doing a recan to make sure we have proper current size locally" | |
| for device in $(multipath -ll 3${WWID} | grep -E '^ ' | awk '{print $2}'); do | |
| echo "1" > /sys/bus/scsi/drivers/sd/${device}/rescan; | |
| done | |
| sleep 3 | |
| multipathd reconfigure | |
| sleep 3 | |
| # cleanup any old/faulty paths | |
| delete_needed=false | |
| multipath -l 3${WWID} | |
| for dev in $(multipath -l 3${WWID} 2>/dev/null| grep failed | awk '{print $3}' ); do | |
| logger -t "CS_SCSI_VOL_FIND" "${WWID} multipath contains faulty path ${dev}, removing" | |
| echo 1 > /sys/block/${dev}/device/delete; | |
| delete_needed=true | |
| done | |
| if [ "${delete_needed}" == "true" ]; then | |
| sleep 10 | |
| multipath -v2 >/dev/null | |
| fi | |
| multipath -l 3${WWID} | |
| logger -t "CS_SCSI_VOL_FIND" "${WWID} successfully discovered and available" | |
| echo "$(date): Complete - found mapped LUN at /dev/mapper/3${WWID}" | |
| exit 0 |