xcat-core/xCAT-server/share/xcat/scripts/xcatconf4z
2014-12-18 10:45:33 -05:00

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