496 lines
17 KiB
Bash
496 lines
17 KiB
Bash
#!/bin/sh
|
|
|
|
### BEGIN INIT INFO
|
|
# Provides: xcatconf4z
|
|
# Default-Start: 2 3 5
|
|
# Default-stop: 0 1 4 6
|
|
# Required-Start: $syslog
|
|
# Should-Start:
|
|
# Required-Stop:
|
|
# Short-Description: xCAT disk initialization and configuration
|
|
# Description: Reads class x files from the reader and acts based on the type of file.
|
|
# Files of filetype "disk" cause SCSI disks be configured.
|
|
# Other files are used to generate an ISO9660 disk for transporting xCAT configurations.
|
|
### END INIT INFO
|
|
|
|
###############################################################################
|
|
# Authorized senders of configuration files listed here. Specify a list a
|
|
# blank delimited list of userids with each userid in uppercase
|
|
# (e.g. "ZHCP" or "ZHCP ZHCP2"), or '*' to indicate all are authorized.
|
|
# If nothing is specified then this function will not process any
|
|
# configuration files in the reader.
|
|
###############################################################################
|
|
authorizedSenders=''
|
|
|
|
function getOsVersion {
|
|
# @Description:
|
|
# Returns the Linux distro version in an easy to parse format.
|
|
# @Input:
|
|
# None
|
|
# @Output:
|
|
# os - Variable set with OS and version information. For example:
|
|
# "rhel62" or "sles11sp2"
|
|
# @Code:
|
|
release=`cat /etc/*release`
|
|
|
|
if echo $release | grep -i "SUSE Linux Enterprise Server" > /dev/null ; then
|
|
os='sles'
|
|
version=`echo "$release" | grep "VERSION =" | sed \
|
|
-e 's/^.*VERSION =//' \
|
|
-e 's/\s*$//' \
|
|
-e 's/.//' \
|
|
-e 's/[^0-9]*([0-9]+).*/$1/'`
|
|
os=$os$version;
|
|
|
|
# Append service level
|
|
level=`echo "$release" | grep "LEVEL =" | sed \
|
|
-e 's/^.*LEVEL =//' \
|
|
-e 's/\s*$//' \
|
|
-e 's/.//' \
|
|
-e 's/[^0-9]*([0-9]+).*/$1/'`
|
|
os=$os'sp'$level
|
|
|
|
elif version=`echo $release | grep -i "Red Hat Enterprise Linux Server"`; then
|
|
os='rhel'
|
|
version=`echo $version | sed \
|
|
-e 's/[A-Za-z\/\.\(\)]//g' \
|
|
-e 's/^ *//g' \
|
|
-e 's/ *$//g' \
|
|
-e 's/\s.*$//'`
|
|
os=$os$version
|
|
fi
|
|
return
|
|
}
|
|
|
|
function onlineDevice {
|
|
# @Description:
|
|
# Brings a Linux device online.
|
|
# @Input:
|
|
# Device number, e.g. "0.0.000c"
|
|
# @Output:
|
|
# Return code indicates success or failure
|
|
# @Code:
|
|
device=$1
|
|
local funcName="onlineDevice"
|
|
rc=$(/sbin/chccwdev -e $device > /dev/null; echo $?)
|
|
if (( rc != 0 )); then
|
|
if [[ -e /sbin/cio_ignore ]]; then
|
|
rc=$(/sbin/cio_ignore -r 0.0.$device > /dev/null; echo $?)
|
|
which udevadm &> /dev/null && udevadm settle || udevsettle
|
|
fi
|
|
rc=$(/sbin/chccwdev -e $device > /dev/null; echo $?)
|
|
if (( rc != 0 )); then
|
|
echo "xcatconf4z $funcName (Error) Could not activate the virtual reader"
|
|
return 1
|
|
fi
|
|
fi
|
|
which udevadm &> /dev/null && udevadm settle || udevsettle
|
|
return 0
|
|
}
|
|
|
|
function pullReader {
|
|
# @Description:
|
|
# Reads class x spool files from the reader if sent by an authorized sender.
|
|
# Drives special processing functions for files of a specific type.
|
|
# Files with a filetype of:
|
|
# tgz are unpacked into the transport directory
|
|
# disk files are read and cause the setupDisk function to be driven
|
|
# all other files are unpacked into the transport directory
|
|
# @Input:
|
|
# None
|
|
# @Output:
|
|
# Return code indicates success if reader was brought online.
|
|
# @Code:
|
|
local funcName="pullReader"
|
|
/sbin/modprobe vmcp
|
|
|
|
# Online reader
|
|
rc= onlineDevice "000c"
|
|
if (( rc != 0 )); then
|
|
return $rc
|
|
fi
|
|
|
|
# Grab the spool Id, class file name, and file type
|
|
eval records=($(/usr/sbin/vmur li | tail -n +2 | cut -c 1-72 | awk '{print $1":"$2":"$3":"$10":"$11"\n"}' ))
|
|
|
|
# Process each spool file that is class "x"
|
|
for record in "${records[@]}"
|
|
do
|
|
record=$(echo $record | tr ":" " ")
|
|
set $record
|
|
originid=$1
|
|
spoolid=$2
|
|
class=$3
|
|
filename=$4
|
|
type=$5
|
|
|
|
if [[ $class != "X" ]]; then
|
|
# Spool file is not of the class required for processing by this script.
|
|
continue
|
|
fi
|
|
|
|
if [[ $authorizedSenders != "*" ]]; then
|
|
if [[ " $authorizedSenders " != *" $originid "* ]]; then
|
|
# Originator is not authorized to send configuration files.
|
|
continue
|
|
fi
|
|
fi
|
|
|
|
if [[ -n $type ]]; then
|
|
file="$filename.$type"
|
|
else
|
|
file=$filename
|
|
fi
|
|
|
|
# Receive the spool file
|
|
echo "Downloading record $spoolid: $file"
|
|
|
|
if [[ $type == "txt" ]] || [[ $type == "sh" ]]; then
|
|
# Receiving text
|
|
rc=$(/usr/sbin/vmur re -t $spoolid $file)
|
|
elif [[ $type == "tgz" ]]; then
|
|
rc=$(/usr/sbin/vmur re $spoolid $file)
|
|
/bin/tar xzf $file -C $transportdir
|
|
rm $file
|
|
elif [[ $type == "disk" ]]; then
|
|
rc=$(/usr/sbin/vmur re $spoolid $file)
|
|
if (( rc == 0 )); then
|
|
setupDisk $transportdir'/'$file
|
|
rc=0
|
|
fi
|
|
else
|
|
# Receive block
|
|
rc=$(/usr/sbin/vmur re $spoolid $file)
|
|
fi
|
|
|
|
if (( rc != 0 )); then
|
|
echo "xcatconf4z funcName (Error) Failed to download record $spoolid"
|
|
fi
|
|
done
|
|
return 0
|
|
}
|
|
|
|
function setupIso {
|
|
# @Description:
|
|
# Makes an ISO filesystem using the contents of the transport directory and
|
|
# creates a loop device pointing to the ISO image. If an "init.sh" script
|
|
# exists in the transport directory then it is driven.
|
|
# @Input:
|
|
# None
|
|
# @Output:
|
|
# None
|
|
# @Code:
|
|
iso="/var/opt/xcat/transport.iso"
|
|
|
|
# If there are files in the transport directory then create an ISO system.
|
|
if [ "$(ls -A .)" ]; then
|
|
/usr/bin/mkisofs -l -o $iso $transportdir
|
|
fi
|
|
|
|
# If the ISO filesystem exists then create loop back device pointing
|
|
# to the ISO9660 image
|
|
if [[ -e $iso ]]; then
|
|
nextLoopDev=`/sbin/losetup -f`
|
|
if [[ -n $nextLoopDev ]]; then
|
|
/sbin/losetup $nextLoopDev $iso
|
|
fi
|
|
fi
|
|
|
|
# Execute init script (if one exists)
|
|
if [[ -e ${transportdir}/init.sh ]]; then
|
|
chmod 755 ${transportdir}/init.sh
|
|
${transportdir}/init.sh
|
|
fi
|
|
}
|
|
|
|
function setupDisk {
|
|
# @Description:
|
|
# Processes a disk file for the following functions:
|
|
# create a file system node
|
|
# Setup a SCSI volume
|
|
# Removes a SCSI volume
|
|
# @Input:
|
|
# Location and name of the disk file.
|
|
# @Output:
|
|
# None
|
|
# @Code:
|
|
diskFile=$1
|
|
local funcName="setupDisk"
|
|
|
|
# Read the file and verify we want to handle it
|
|
if ! grep -q "# xCAT Init" "$diskFile"; then
|
|
# File is not one that we handle. Leave it alone.
|
|
return
|
|
fi
|
|
|
|
# Read the file now that we know it is our file
|
|
oldIFS=$IFS
|
|
IFS=$'\n'
|
|
for line in $(cat "$diskFile"); do
|
|
if [[ $line == \#* ]]; then
|
|
# Ignore comment lines
|
|
continue
|
|
fi
|
|
keyName=${line%\=*}
|
|
value=${line#*\=}
|
|
value=$(echo ${value} | sed -e 's/^ *//g')
|
|
newKey='xcat_'$keyName
|
|
eval $newKey=$value
|
|
done
|
|
IFS=$oldIFS
|
|
|
|
# Remove the disk file after we have read it
|
|
rm $diskFile
|
|
|
|
##########################################################################
|
|
# Handle creating a file system node
|
|
# Disk file input parameters:
|
|
# action - "createfilesysnode"
|
|
# srcFile - location/name of the source file for the mknod command
|
|
# tgtFile - location/name of the target file for the mknod command
|
|
##########################################################################
|
|
if [[ $xcat_action == "createfilesysnode" ]]; then
|
|
echo "Creating a file system node, source: $xcat_srcFile, target: $xcat_tgtFile"
|
|
|
|
if [[ ! -n $xcat_srcFile ]]; then
|
|
echo "xcatconf4z $funcName (Error) Source file for creating a file system node was not specified"
|
|
return
|
|
fi
|
|
|
|
if [[ ! -n $xcat_tgtFile ]]; then
|
|
echo "xcatconf4z $funcName (Error) Target file for creating a file system node was not specified"
|
|
return
|
|
fi
|
|
if [[ -e $xcat_tgtFile ]]; then
|
|
echo "xcatconf4z $funcName (Error) Target file for creating a file system node already exists"
|
|
return
|
|
fi
|
|
|
|
out=`/usr/bin/stat --printf=%n ${xcat_srcFile}`
|
|
if (( $? != 0 )); then
|
|
echo "xcatconf4z $funcName (Error) Unable to stat the source file: $xcat_srcFile"
|
|
return
|
|
fi
|
|
|
|
configFile='/etc/udev/rules.d/56-zfcp.rules'
|
|
tgtNode=$(echo ${xcat_tgtFile} | sed -e 's/^\/dev\///')
|
|
wwpn_lun=$(echo ${xcat_srcFile} | sed -e 's/^\/dev.*-zfcp-//')
|
|
wwpn=$(echo ${wwpn_lun} | sed -e 's/:0x.*//')
|
|
lun=$(echo ${wwpn_lun} | sed -e 's/^0x.*://')
|
|
|
|
echo "KERNEL==\"sd*\", SYSFS{wwpn}==\"${wwpn}\", SYSFS{fcp_lun}==\"${lun}\", SYMLINK+=\"${tgtNode}%n\"" >> ${configFile}
|
|
udevadm trigger --sysname-match=sd*
|
|
|
|
##########################################################################
|
|
# Handle removing a file system node
|
|
# Disk file input parameters:
|
|
# action - "removefilesysnode"
|
|
# tgtFile - location/name of the target file for the mknod command
|
|
##########################################################################
|
|
elif [[ $xcat_action == "removefilesysnode" ]]; then
|
|
echo "Removing a file system node, target: $xcat_tgtFile"
|
|
if [[ ! -n $xcat_tgtFile ]]; then
|
|
echo "xcatconf4z $funcName (Error) Target file for creating a file system node was not specified"
|
|
return
|
|
fi
|
|
|
|
configFile='/etc/udev/rules.d/56-zfcp.rules'
|
|
tgtNode=$(echo ${xcat_tgtFile} | sed -e 's/^\/dev\///')
|
|
|
|
sed -i -e /SYMLINK+=\"${tgtNode}%n\"/d ${configFile}
|
|
udevadm trigger --sysname-match=sd*
|
|
|
|
##########################################################################
|
|
# Handle adding a SCSI volume
|
|
# Disk file input parameters:
|
|
# action - "addScsiVolume"
|
|
# fcpAddr - FCP device address
|
|
# wwpn - WWPN number
|
|
# lun - LUN number
|
|
##########################################################################
|
|
elif [[ $xcat_action == "addScsiVolume" ]]; then
|
|
echo "Adding a SCSI Volume, FCP addr: $xcat_fcpAddr, WWPN: $xcat_wwpn, LUN: $xcat_lun"
|
|
|
|
# Validate the input
|
|
if [[ ! -n $xcat_fcpAddr ]]; then
|
|
echo "xcatconf4z $funcName (Error) FCP address was not specified"
|
|
return
|
|
fi
|
|
xcat_fcpAddr=`echo $xcat_fcpAddr | tr '[A-Z]' '[a-z]'`
|
|
|
|
if [[ ! -n $xcat_wwpn ]]; then
|
|
echo "xcatconf4z $funcName (Error) WWPN was not specified"
|
|
return
|
|
fi
|
|
xcat_wwpn=`echo $xcat_wwpn | tr '[A-Z]' '[a-z]'`
|
|
|
|
if [[ ! -n $xcat_lun ]]; then
|
|
echo "xcatconf4z $funcName (Error) LUN was not specified"
|
|
return
|
|
fi
|
|
xcat_lun=`echo $xcat_lun | tr '[A-Z]' '[a-z]'`
|
|
|
|
# Online the device
|
|
rc= onlineDevice $xcat_fcpAddr
|
|
if (( rc != 0 )); then
|
|
return
|
|
fi
|
|
|
|
# Set WWPN and LUN in sysfs
|
|
if [[ -e /sys/bus/ccw/drivers/zfcp/0.0.$xcat_fcpAddr/port_add ]]; then
|
|
echo 0x$xcat_wwpn > /sys/bus/ccw/drivers/zfcp/0.0.$xcat_fcpAddr/port_add
|
|
fi
|
|
echo 0x$xcat_lun > /sys/bus/ccw/drivers/zfcp/0.0.$xcat_fcpAddr/0x$xcat_wwpn/unit_add
|
|
|
|
# Set WWPN and LUN in configuration files
|
|
# RHEL: /etc/zfcp.conf
|
|
# SLES 10: /etc/sysconfig/hardware/hwcfg-zfcp-bus-ccw-*
|
|
# SLES 11: /etc/udev/rules.d/51-zfcp*
|
|
if [[ $os == sles10* ]]; then
|
|
/sbin/zfcp_host_configure 0.0.$xcat_fcpAddr 1
|
|
/sbin/zfcp_disk_configure 0.0.$xcat_fcpAddr $xcat_wwpn $xcat_lun 1
|
|
echo "0x$xcat_wwpn:0x$xcat_lun" >> /etc/sysconfig/hardware/hwcfg-zfcp-bus-ccw-0.0.$xcat_fcpAddr
|
|
elif [[ $os == sles* ]]; then
|
|
/sbin/zfcp_host_configure 0.0.$xcat_fcpAddr 1
|
|
/sbin/zfcp_disk_configure 0.0.$xcat_fcpAddr $xcat_wwpn $xcat_lun 1
|
|
|
|
# Configure zFCP device to be persistent
|
|
touch /etc/udev/rules.d/51-zfcp-0.0.$xcat_fcpAddr.rules
|
|
|
|
# Check if the file already contains the zFCP channel
|
|
out=`cat "/etc/udev/rules.d/51-zfcp-0.0.$xcat_fcpAddr.rules" | egrep -i "ccw/0.0.$xcat_fcpAddr]online"`
|
|
if [[ ! $out ]]; then
|
|
echo "ACTION==\"add\", SUBSYSTEM==\"ccw\", KERNEL==\"0.0.$xcat_fcpAddr\", IMPORT{program}=\"collect 0.0.$xcat_fcpAddr %k 0.0.$xcat_fcpAddr zfcp\"" \
|
|
| tee -a /etc/udev/rules.d/51-zfcp-0.0.$xcat_fcpAddr.rules
|
|
echo "ACTION==\"add\", SUBSYSTEM==\"drivers\", KERNEL==\"zfcp\", IMPORT{program}=\"collect 0.0.$xcat_fcpAddr %k 0.0.$xcat_fcpAddr zfcp\"" \
|
|
| tee -a /etc/udev/rules.d/51-zfcp-0.0.$xcat_fcpAddr.rules
|
|
echo "ACTION==\"add\", ENV{COLLECT_0.0.$xcat_fcpAddr}==\"0\", ATTR{[ccw/0.0.$xcat_fcpAddr]online}=\"1\"" \
|
|
| tee -a /etc/udev/rules.d/51-zfcp-0.0.$xcat_fcpAddr.rules
|
|
fi
|
|
|
|
echo "ACTION==\"add\", KERNEL==\"rport-*\", ATTR{port_name}==\"0x$xcat_wwpn\", SUBSYSTEMS==\"ccw\", KERNELS==\"0.0.$xcat_fcpAddr\", ATTR{[ccw/0.0.$xcat_fcpAddr]0x$xcat_wwpn/unit_add}=\"0x$xcat_lun\"" \
|
|
| tee -a /etc/udev/rules.d/51-zfcp-0.0.$device.rules
|
|
elif [[ $os == rhel* ]]; then
|
|
echo "0.0.$xcat_fcpAddr 0x$xcat_wwpn 0x$xcat_lun" >> /etc/zfcp.conf
|
|
|
|
if [[ $os == rhel6* ]]; then
|
|
echo "add" > /sys/bus/ccw/devices/0.0.$xcat_fcpAddr/uevent
|
|
fi
|
|
fi
|
|
|
|
# Settle the file system so when we are done the device is fully available
|
|
if [[ $(which udevadm 2> /dev/null) != '' ]]; then
|
|
udevadm settle
|
|
else
|
|
udevsettle
|
|
fi
|
|
if [[ ! -e "/dev/disk/by-path/ccw-0.0.${xcat_fcpAddr}-zfcp-0x${xcat_wwpn}:0x${xcat_lun}" ]]; then
|
|
# Sometimes the file takes longer to appear. We will wait up to 3 minutes.
|
|
maxTime=0
|
|
for time in 1 2 2 5 10 10 30 60 60
|
|
do
|
|
if [[ -e "/dev/disk/by-path/ccw-0.0.${xcat_fcpAddr}-zfcp-0x${xcat_wwpn}:0x${xcat_lun}" ]]; then
|
|
# Leave the loop now that the file exists
|
|
break
|
|
fi
|
|
maxTime=$maxTime+$time
|
|
echo "Sleeping for $time seconds to allow /dev/disk/by-path/ccw-0.0.${xcat_fcpAddr}-zfcp-0x${xcat_wwpn}:0x${xcat_lun} to be created"
|
|
sleep $time
|
|
done
|
|
fi
|
|
if [[ ! -e "/dev/disk/by-path/ccw-0.0.${xcat_fcpAddr}-zfcp-0x${xcat_wwpn}:0x${xcat_lun}" ]]; then
|
|
echo "/dev/disk/by-path/ccw-0.0.${xcat_fcpAddr}-zfcp-0x${xcat_wwpn}:0x${xcat_lun} did not appear in $maxTime seconds, continuing."
|
|
fi
|
|
|
|
##########################################################################
|
|
# Handle removing a SCSI volume
|
|
# Disk file input parameters:
|
|
# action - "removeScsiVolume"
|
|
# fcpAddr - FCP device address
|
|
# wwpn - WWPN number
|
|
# lun - LUN number
|
|
##########################################################################
|
|
elif [[ $xcat_action == "removeScsiVolume" ]]; then
|
|
echo "Removing a SCSI Volume, FCP addr: $xcat_fcpAddr, WWPN: $xcat_wwpn, LUN: $xcat_lun"
|
|
|
|
# Validate the input
|
|
if [[ ! -n $xcat_fcpAddr ]]; then
|
|
echo "xcatconf4z $funcName (Error) FCP address was not specified"
|
|
return
|
|
fi
|
|
xcat_fcpAddr=`echo $xcat_fcpAddr | tr '[A-Z]' '[a-z]'`
|
|
|
|
if [[ ! -n $xcat_wwpn ]]; then
|
|
echo "xcatconf4z $funcName (Error) WWPN was not specified"
|
|
return
|
|
fi
|
|
xcat_wwpn=`echo $xcat_wwpn | tr '[A-Z]' '[a-z]'`
|
|
|
|
if [[ ! -n $xcat_lun ]]; then
|
|
echo "xcatconf4z $funcName (Error) LUN was not specified"
|
|
return
|
|
fi
|
|
xcat_lun=`echo $xcat_lun | tr '[A-Z]' '[a-z]'`
|
|
|
|
# Delete the SCSI device
|
|
scsiDevice=`lszfcp -l 0x$xcat_lun | grep 0x$xcat_lun | cut -d " " -f2`
|
|
if [[ -n $scsiDevice ]]; then
|
|
echo 1 > "/sys/bus/scsi/devices/$scsiDevice/delete"
|
|
fi
|
|
|
|
# Delete WWPN and LUN from sysfs
|
|
if [[ -e /sys/bus/ccw/drivers/zfcp/0.0.$xcat_fcpAddr/0x$xcat_wwpn/unit_remove ]]; then
|
|
if [[ $(which udevadm 2> /dev/null) != '' ]]; then
|
|
udevadm settle
|
|
else
|
|
udevsettle
|
|
fi
|
|
echo 0x$xcat_lun > /sys/bus/ccw/drivers/zfcp/0.0.$xcat_fcpAddr/0x$xcat_wwpn/unit_remove
|
|
fi
|
|
|
|
# Delete WWPN and LUN from configuration files
|
|
# RHEL: /etc/zfcp.conf
|
|
# SLES 10: /etc/sysconfig/hardware/hwcfg-zfcp-bus-ccw-*
|
|
# SLES 11: /etc/udev/rules.d/51-zfcp*
|
|
if [[ $os == sles10* ]]; then
|
|
expression="/$xcat_lun/d"
|
|
sed --in-place -e $expression /etc/sysconfig/hardware/hwcfg-zfcp-bus-ccw-0.0.$xcat_fcpAddr
|
|
elif [[ $os == sles* ]]; then
|
|
expression="/$xcat_lun/d"
|
|
sed --in-place -e $expression /etc/udev/rules.d/51-zfcp-0.0.$xcat_fcpAddr.rules
|
|
elif [[ $os == rhel* ]]; then
|
|
expression="/$xcat_lun/d"
|
|
sed --in-place -e $expression /etc/zfcp.conf
|
|
fi
|
|
fi
|
|
|
|
return
|
|
}
|
|
|
|
############################################################################
|
|
# Main Code Section
|
|
############################################################################
|
|
case "$1" in
|
|
start)
|
|
echo "xcatconf4z is starting"
|
|
transportdir="/var/opt/xcat/transport"
|
|
rm -Rf $transportdir
|
|
/bin/mkdir -p $transportdir
|
|
cd $transportdir
|
|
|
|
# Get Linux version
|
|
getOsVersion
|
|
|
|
if [[ -n "$authorizedSenders" ]]; then
|
|
pullReader
|
|
else
|
|
echo "xcatconf4z is disabled from accepting configuration reader files."
|
|
fi
|
|
|
|
setupIso
|
|
;;
|
|
stop|status|restart|reload|force-reload)
|
|
# Do nothing
|
|
;;
|
|
esac
|