397 lines
11 KiB
Bash
Executable File
397 lines
11 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
PREREQ=""
|
|
|
|
prereqs()
|
|
{
|
|
echo "$PREREQ"
|
|
}
|
|
|
|
case $1 in
|
|
# get pre-requisites
|
|
prereqs)
|
|
prereqs
|
|
exit 0
|
|
;;
|
|
esac
|
|
|
|
parse_root_param ()
|
|
{
|
|
target="$1"
|
|
auth="$2"
|
|
OLDIFS="$IFS"
|
|
IFS=":"
|
|
set -- $target
|
|
IFS="$OLDIFS"
|
|
|
|
tmp_ISCSI_TARGET_IP="$1"
|
|
if [ -n "$2" ] ; then
|
|
if [ x"$2" != x"6" ] ; then
|
|
echo "Warning: unsupported protocol specified for iSCSI root parameter, assuming 6 (TCP)" >&2
|
|
fi
|
|
fi
|
|
tmp_ISCSI_TARGET_PORT="$3"
|
|
tmp_ISCSI_ROOT_LUN="$4"
|
|
tmp_ISCSI_TARGET_NAME="$5"
|
|
shift 5
|
|
while [ -n "$1" ] ; do
|
|
tmp_ISCSI_TARGET_NAME="${tmp_ISCSI_TARGET_NAME}:$1"
|
|
shift
|
|
done
|
|
|
|
if [ -z "$tmp_ISCSI_TARGET_IP" ] || [ -z "$tmp_ISCSI_TARGET_NAME" ] ; then
|
|
echo "Warning: empty iSCSI IP / target name currently not supported for root=iscsi:, ignoring parameter" >&2
|
|
return
|
|
fi
|
|
|
|
OLDIFS="$IFS"
|
|
IFS=":"
|
|
set -- $auth
|
|
IFS="$OLDIFS"
|
|
|
|
tmp_ISCSI_USERNAME=""
|
|
tmp_ISCSI_PASSWORD=""
|
|
tmp_ISCSI_IN_USERNAME=""
|
|
tmp_ISCSI_IN_PASSWORD=""
|
|
|
|
if [ $# -gt 4 ] ; then
|
|
echo "Warning: invalid authentication for root=iscsi:, ignoring" >&2
|
|
return
|
|
fi
|
|
|
|
if [ $# -gt 0 ] ; then
|
|
tmp_ISCSI_USERNAME="$1"
|
|
tmp_ISCSI_PASSWORD="$2"
|
|
if [ $# -gt 2 ] ; then
|
|
tmp_ISCSI_IN_USERNAME="$3"
|
|
tmp_ISCSI_IN_PASSWORD="$4"
|
|
fi
|
|
fi
|
|
|
|
ISCSI_TARGET_IP="$tmp_ISCSI_TARGET_IP"
|
|
ISCSI_TARGET_PORT="$tmp_ISCSI_TARGET_PORT"
|
|
ISCSI_TARGET_NAME="$tmp_ISCSI_TARGET_NAME"
|
|
ISCSI_ROOT_LUN="$tmp_ISCSI_ROOT_LUN"
|
|
if [ -n "$tmp_ISCSI_USERNAME" ] ; then
|
|
ISCSI_USERNAME="$tmp_ISCSI_USERNAME"
|
|
ISCSI_PASSWORD="$tmp_ISCSI_PASSWORD"
|
|
fi
|
|
if [ -n "$tmp_ISCSI_IN_USERNAME" ] ; then
|
|
ISCSI_IN_USERNAME="$tmp_ISCSI_IN_USERNAME"
|
|
ISCSI_IN_PASSWORD="$tmp_ISCSI_IN_PASSWORD"
|
|
fi
|
|
ISCSI_HAD_ROOT=yes
|
|
}
|
|
|
|
do_iscsi_login ()
|
|
{
|
|
# Bring in the main config
|
|
. /conf/initramfs.conf
|
|
for conf in conf/conf.d/*; do
|
|
[ -f ${conf} ] && . ${conf}
|
|
done
|
|
. /scripts/functions
|
|
|
|
udevadm settle
|
|
IBFT_DHCP_DEVICE=""
|
|
|
|
if [ -n "$ISCSI_AUTO" ] ; then
|
|
# try to auto-configure network interface based
|
|
# on firmware values
|
|
modprobe iscsi_ibft
|
|
iscsistart -N
|
|
|
|
# write out /run/net-$IFACE.conf based on what
|
|
# was in the firmware
|
|
iscsistart -f | while read k eq v; do
|
|
case "${k} ${eq} ${v}" in
|
|
("# BEGIN RECORD"*)
|
|
DEVICE=""
|
|
PROTO="none"
|
|
IPV4ADDR=""
|
|
IPV4NETMASK=""
|
|
IPV4GATEWAY=""
|
|
IPV4DNS0=""
|
|
IPV4DNS1=""
|
|
UPTIME="0"
|
|
DHCPLEASETIME="0"
|
|
DOMAINSEARCH=""
|
|
continue
|
|
;;
|
|
("# END RECORD"*)
|
|
if [ -n "$DEVICE" ] ; then
|
|
{
|
|
echo "DEVICE='${DEVICE}'"
|
|
echo "PROTO='${PROTO}'"
|
|
echo "IPV4ADDR='${IPV4ADDR}'"
|
|
echo "IPV4BROADCAST=''"
|
|
echo "IPV4NETMASK='${IPV4NETMASK}'"
|
|
echo "IPV4GATEWAY='${IPV4GATEWAY}'"
|
|
echo "IPV4DNS0='${IPV4DNS0}'"
|
|
echo "IPV4DNS1='${IPV4DNS1}'"
|
|
echo "HOSTNAME=''"
|
|
echo "DNSDOMAIN=''"
|
|
echo "NISDOMAIN=''"
|
|
echo "ROOTSERVER=''"
|
|
echo "ROOTPATH=''"
|
|
echo "UPTIME='${UPTIME}'"
|
|
echo "DHCPLEASETIME='${DHCPLEASETIME}'"
|
|
echo "DOMAINSEARCH=''"
|
|
} > "/run/net-${DEVICE}.conf.ibft"
|
|
if [ "$PROTO" != "dhcp" -a "$DHCPLEASETIME" = "0" ]; then
|
|
# this is static ibft configuration.
|
|
mv "/run/net-${DEVICE}.conf.ibft" "/run/net-${DEVICE}.conf"
|
|
else
|
|
IBFT_DHCP_DEVICE="$DEVICE"
|
|
fi
|
|
echo "${DEVICE}" > /run/initramfs/open-iscsi.interface
|
|
# iscsistart -N doesn't set the default gateway. Therefore,
|
|
# we need to add it ourselves. However, the ip command is
|
|
# only available if we use busybox in the initramfs (it's
|
|
# in open-iscsi's Recommends), so check for that.
|
|
if [ -n "${IPV4GATEWAY}" ] && which ip >/dev/null 2>&1 ; then
|
|
ip route add default via "${IPV4GATEWAY}"
|
|
fi
|
|
fi
|
|
continue
|
|
;;
|
|
esac
|
|
if [ "${eq}" != "=" ] ; then
|
|
continue
|
|
fi
|
|
case "${k}" in
|
|
iface.ipaddress) IPV4ADDR="${v}" ;;
|
|
iface.subnet_mask) IPV4NETMASK="${v}" ;;
|
|
iface.gateway) IPV4GATEWAY="${v}" ;;
|
|
iface.primary_dns) IPV4DNS0="${v}" ;;
|
|
iface.secondary_dns) IPV4DNS1="${v}" ;;
|
|
iface.net_ifacename) DEVICE="${v}" ;;
|
|
iface.bootproto)
|
|
case "${v}" in
|
|
DHCP) PROTO="dhcp" ;;
|
|
STATIC) PROTO="static" ;;
|
|
*) PROTO="${v}" ;;
|
|
esac
|
|
;;
|
|
esac
|
|
done
|
|
fi
|
|
|
|
# If ISCSI is set to auto and there is no IBFT device/data,
|
|
# then configuring ISCSI "automatically" isn't possible,
|
|
# so there is no point in trying to configure networking.
|
|
# If the opt-in cmdline option iscsi_auto_skip_initramfs_networking is set,
|
|
# then we skip the unnecessary call to configure_networking.
|
|
if [ -n "$ISCSI_AUTO_SKIP_INITRAMFS_NETWORKING" ] && [ -n "$ISCSI_AUTO" ] && ! [ -e /sys/firmware/ibft ]; then
|
|
echo "No iBFT data found and cmdline option iscsi_auto_skip_initramfs_networking is set. Skipping unnecessary attempt to configure networking."
|
|
else
|
|
# run configure_networking even if we have iscsi_auto, because there
|
|
# could be other network interfaces that need to be configured
|
|
# also, if we set up DHCP iBFT, we need ipconfig to run so it creates
|
|
# a proper /run/net-${DEVICE}.conf file that includes the DNS search
|
|
# domain, which we don't get in our iBFT data (see LP: #1806777)
|
|
configure_networking
|
|
fi
|
|
|
|
if [ -n "$IBFT_DHCP_DEVICE" ]; then
|
|
if ! [ -e "/run/net-${DEVICE}.conf" ] ; then
|
|
echo "WARN: ipconfig dhcp failed, using iSCSI iBFT config - DNS search domain may be missing at runtime" >&2
|
|
# We have DHCP iBFT, but ipconfig DHCP failed;
|
|
# so we should fallback to just using the iBFT config,
|
|
# though that will not include the DNS search domain
|
|
mv "/run/net-${DEVICE}.conf.ibft" "/run/net-${DEVICE}.conf"
|
|
# need to re-run configure_networking to process conf file
|
|
configure_networking
|
|
fi
|
|
fi
|
|
|
|
# Save network device we configured via configure_networking, but only
|
|
# if we didn't already get one from autoconfiguration (then we always
|
|
# prefer that).
|
|
if ! [ -e /run/initramfs/open-iscsi.interface ] ; then
|
|
if [ -z "${DEVICE}" ] || ! [ -e "/run/net-${DEVICE}.conf" ] ; then
|
|
for i in /run/net-*.conf ; do
|
|
[ -e "${i}" ] && { . "${i}" ; break ; }
|
|
done
|
|
fi
|
|
if [ -n "${DEVICE}" ] ; then
|
|
echo "${DEVICE}" > /run/initramfs/open-iscsi.interface
|
|
else
|
|
for i in /run/net6-*.conf; do
|
|
[ -e "${i}" ] && { . "${i}" ; break ; }
|
|
done
|
|
fi
|
|
if [ -z "${DEVICE}" ] && [ -n "${DEVICE6}" ] ; then
|
|
echo "${DEVICE6}" > /run/initramfs/open-iscsi.interface
|
|
fi
|
|
fi
|
|
|
|
modprobe iscsi_tcp
|
|
modprobe crc32c
|
|
|
|
# If iscsiuio is present in the initramfs, start it, in case UIO
|
|
# offloading is required.
|
|
if [ -x /usr/sbin/iscsiuio ] ; then
|
|
start-stop-daemon --start --quiet --pidfile /run/initramfs/iscsiuio.pid \
|
|
--startas /usr/sbin/iscsiuio --name iscsiuio \
|
|
--exec /usr/sbin/iscsiuio -- --pid=/run/initramfs/iscsiuio.pid || :
|
|
fi
|
|
|
|
if [ -z $ISCSI_AUTO ]; then
|
|
if [ -z $ISCSI_INITIATOR ]; then
|
|
. /etc/initiatorname.iscsi
|
|
ISCSI_INITIATOR=$InitiatorName
|
|
fi
|
|
|
|
if [ -z $ISCSI_TARGET_PORT ]; then
|
|
ISCSI_TARGET_PORT=3260
|
|
fi
|
|
|
|
if [ -z $ISCSI_TARGET_GROUP ]; then
|
|
ISCSI_TARGET_GROUP=1
|
|
fi
|
|
|
|
iscsistart -i $ISCSI_INITIATOR -t $ISCSI_TARGET_NAME \
|
|
-g $ISCSI_TARGET_GROUP -a $ISCSI_TARGET_IP \
|
|
-p $ISCSI_TARGET_PORT \
|
|
${ISCSI_USERNAME:+-u "$ISCSI_USERNAME"} \
|
|
${ISCSI_PASSWORD:+-w "$ISCSI_PASSWORD"} \
|
|
${ISCSI_IN_USERNAME:+-U "$ISCSI_IN_USERNAME"}\
|
|
${ISCSI_IN_PASSWORD:+-W "$ISCSI_IN_PASSWORD"}
|
|
else
|
|
modprobe iscsi_ibft
|
|
iscsistart -b
|
|
fi
|
|
|
|
if [ -z $ISCSI_TARGET_PORT ]; then
|
|
ISCSI_TARGET_PORT=3260
|
|
fi
|
|
|
|
if [ -z $ISCSI_TARGET_GROUP ]; then
|
|
ISCSI_TARGET_GROUP=1
|
|
fi
|
|
|
|
for i in $ISCSI_TARGET_IP; do
|
|
iscsistart -i $ISCSI_INITIATOR -t $ISCSI_TARGET_NAME \
|
|
-g $ISCSI_TARGET_GROUP -a $i \
|
|
-p $ISCSI_TARGET_PORT \
|
|
${ISCSI_USERNAME:+-u "$ISCSI_USERNAME"} \
|
|
${ISCSI_PASSWORD:+-w "$ISCSI_PASSWORD"} \
|
|
${ISCSI_IN_USERNAME:+-U "$ISCSI_IN_USERNAME"}\
|
|
${ISCSI_IN_PASSWORD:+-W "$ISCSI_IN_PASSWORD"}
|
|
done
|
|
}
|
|
|
|
parse_iscsi_ops ()
|
|
{
|
|
[ -r /etc/iscsi.initramfs ] && . /etc/iscsi.initramfs
|
|
|
|
for x in $(cat /proc/cmdline); do
|
|
case ${x} in
|
|
iscsi_auto)
|
|
ISCSI_AUTO=true
|
|
;;
|
|
iscsi_initiator=*)
|
|
ISCSI_INITIATOR="${x#iscsi_initiator=}"
|
|
;;
|
|
iscsi_target_name=*)
|
|
ISCSI_TARGET_NAME="${x#iscsi_target_name=}"
|
|
;;
|
|
iscsi_target_ip=*)
|
|
ISCSI_TARGET_IP="${x#iscsi_target_ip=}"
|
|
;;
|
|
iscsi_target_port=*)
|
|
ISCSI_TARGET_PORT="${x#iscsi_target_port=}"
|
|
;;
|
|
iscsi_target_group=*)
|
|
ISCSI_TARGET_GROUP="${x#iscsi_target_group=}"
|
|
;;
|
|
iscsi_username=*)
|
|
ISCSI_USERNAME="${x#iscsi_username=}"
|
|
;;
|
|
iscsi_password=*)
|
|
ISCSI_PASSWORD="${x#iscsi_password=}"
|
|
;;
|
|
iscsi_in_username=*)
|
|
ISCSI_IN_USERNAME="${x#iscsi_in_username=}"
|
|
;;
|
|
iscsi_in_password=*)
|
|
ISCSI_IN_PASSWORD="${x#iscsi_in_password=}"
|
|
;;
|
|
root=iscsi:*@*)
|
|
x="${x##root=iscsi:}"
|
|
parse_root_param "${x#*@}" "${x%%@*}"
|
|
;;
|
|
root=iscsi:*)
|
|
parse_root_param "${x##root=iscsi:}" ""
|
|
;;
|
|
iscsi_auto_skip_initramfs_networking)
|
|
ISCSI_AUTO_SKIP_INITRAMFS_NETWORKING=true
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
if [ ! -x /usr/sbin/iscsistart ]; then
|
|
exit 0
|
|
fi
|
|
|
|
parse_iscsi_ops
|
|
|
|
if ( [ -z $ISCSI_TARGET_NAME ] || [ -z $ISCSI_TARGET_IP ] ) && [ -z $ISCSI_AUTO ]; then
|
|
exit 0
|
|
fi
|
|
|
|
do_iscsi_login
|
|
|
|
udevadm settle
|
|
|
|
# The second check is to allow us to use multiple root= parameters. That way
|
|
# one may specify root=iscsi:... root=UUID=... to mount partitions on an iSCSI
|
|
# disk. (The latter value will overwrite the former for purposes of the main
|
|
# initramfs scripts, but our loop that scans /proc/cmdline will still detect
|
|
# the former and set proper parameters.
|
|
if [ -n "$ISCSI_HAD_ROOT" ] && [ x"${ROOT##iscsi:}" != x"${ROOT}" ] ; then
|
|
if [ -z "$ISCSI_ROOT_LUN" ] ; then
|
|
ISCSI_ROOT_LUN=0
|
|
fi
|
|
found=0
|
|
# FIXME: RFC 4173 defines the LUN field to be more complicated and that
|
|
# the same LUN may have multiple representations.
|
|
for disk in /dev/disk/by-path/*-iscsi-*-"${ISCSI_ROOT_LUN}" ; do
|
|
# Resolve device name, as the colons in the by-path name will
|
|
# cause mount to think that this is a NFS share, which we don't
|
|
# want.
|
|
if ! disk="$(readlink -f "$disk")" ; then
|
|
continue
|
|
fi
|
|
|
|
# Try to load file system type module (ignore errors), otherwise
|
|
# this won't succeed.
|
|
if fstype=$(get_fstype "$disk") ; then
|
|
modprobe "$fstype" || :
|
|
ROOTFSTYPE="$fstype"
|
|
fi
|
|
|
|
# Try to mount read-only and see if it's the right filesystem.
|
|
# If so, record the device name but umount again, because we
|
|
# want to be able to do an fsck on it.
|
|
if mount -r -t "${ROOTFSTYPE:-auto}" ${ROOTFLAGS} "${disk}" ${rootmnt} ; then
|
|
if [ -d ${rootmnt}/proc ] ; then
|
|
# This will be sourced by init after this hook has run.
|
|
echo "export ROOT=$disk" >> /conf/param.conf
|
|
if [ -n "$ROOTFSTYPE" ] && [ x"$ROOTFSTYPE" != x"auto" ] ; then
|
|
echo "export ROOTFSTYPE=$ROOTFSTYPE" >> /conf/param.conf
|
|
fi
|
|
found=1
|
|
fi
|
|
umount ${rootmnt}
|
|
if [ $found -eq 1 ] ; then
|
|
break
|
|
fi
|
|
fi
|
|
done
|
|
fi
|
|
|
|
exit 0
|