#!/bin/sh
# iscsistart on Google Compute Engine
# * Make sure routing is set up (https://tools.ietf.org/html/rfc3442)
# * Make sure interface name is renamed to ibft0 to avoid configuration clashes
#   with user network config files

PREREQ="udev"
PATH=/sbin:/bin:/usr/sbin:/usr/bin

prereqs() { echo "$PREREQ"; }

case $1 in
prereqs)
  prereqs
  exit 0
  ;;
esac

. /scripts/functions
. /scripts/migrate-functions

modprobe iscsi_ibft

if [ ! -e /sys/firmware/ibft ] ; then
  console_log "no iBFT detected - skipping iscsi boot"
  exit 0
fi

console_log "iBFT detected - configuring iscsi boot"

hook_binary() {
  if [ ! -e "$1" ] ; then
    return
  fi
  if [ -n "$2" ] ; then
    orig="$2"
  else
    orig="$1.orig"
  fi
  mv -f "$1" "${orig}"
  cat > "$1" << EOF
#!/bin/sh
# Added for Google Cloud by Migrate for Compute Engine
. /scripts/migrate-functions
run_hook_and_log "${orig}" "\$@"
EOF
  chmod +x "$1"
}

# Uncomment to enable multipath debug mode
#debug_multipath=y

# shellcheck disable=SC2154
if [ -n "${debug_multipath}" ] ; then
  hook_binary "/sbin/dmsetup"
  hook_binary "/sbin/multipath"
  # lvm binary name is queried in runtime and must not be renamed
  hook_binary "/sbin/lvm" "/tmp/lvm"
  hook_binary "/usr/bin/partx"

  if [ -e "/etc/multipath.conf" ] ; then
    run_and_console_log cat "/etc/multipath.conf"
  fi
  if [ -e "/etc/multipath/bindings" ] ; then
    run_and_console_log cat "/etc/multipath/bindings"
  fi
  if [ -e "/etc/multipath/wwids" ] ; then
    run_and_console_log cat "/etc/multipath/wwids"
  fi
fi

# Workaround for Debian 9 (Stretch) lvm & multipath issue (#892193).
# Multipath is handled by local-top scripts after udev rules already run
# for added iSCSI devices.
# One of those udev rules is 69-lvm-metad, which invokes lvm creation before
# local-top/multipath can claim this device. Remove this rule, lvm will still
# activate with local-top/lvm2 script, after local-top/multipath.
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=892193
if [ -e "/lib/udev/rules.d/69-lvm-metad.rules" ] &&
   [ -e "/scripts/local-top/lvm2" ] &&
   [ -e "/scripts/local-top/multipath" ] ; then
  console_log "Fixing lvm-multipath issue in udev rule: 69-lvm-metad"
  run_and_console_log rm /lib/udev/rules.d/69-lvm-metad.rules
  run_and_console_log udevadm control --reload-rules
fi

# Workaround for Ubuntu 14/16
# The udev rule 12-dm-mpath-lvm uses "multipath -c" in order to test
# whether the device should be multipathed. If it tests positive, it uses
# "partx -d" to delete all the partitions found on this device and sets the
# filesystem type to mpath_member.
# This is done in order to avoid subsequent detection of lvm device in rule
# 85-lvm2.
# Later on, multipath picks up this device and lvm is retried on top of it.
# However, the first time multipath is called through 12-dm-mpath-lvm on
# VELOS_FE devices it fails with:
#   /dev/sdX is not a valid multipath device path
# This causes 85-lvm2 to detect this device, which will prevent multipath
# from claiming the device.
# To avoid this, all VELOS_FE devices are explicitly marked for multipath.
# This is needed even if lvm is not installed since multipath may not be
# able to claim devices after they were partitioned.
if [ -e "/lib/udev/rules.d/12-dm-mpath-lvm.rules" ] ; then
  console_log "Fixing multipath issue in udev rule: 12-dm-mpath-lvm"
  cat > "/tmp/mpath-velos-log" << EOF
#!/bin/sh
# Added for Google Cloud by Migrate for Compute Engine
. /scripts/migrate-functions
console_log "Marking \$1 as mpath_member"
EOF
  chmod +x "/tmp/mpath-velos-log"
  cat > "/lib/udev/rules.d/13-dm-mpath-lvm-velos.rules" << EOF
# Added for Google Cloud by Migrate for Compute Engine
ACTION=="add", \
SUBSYSTEM=="block", \
ENV{DEVTYPE}!="partition", \
ATTRS{vendor}=="VELOS_FE", \
ATTRS{model}=="VDISK           ", \
ENV{DM_MULTIPATH_DEVICE_PATH}="1", \
ENV{ID_FS_TYPE}="mpath_member", \
RUN+="/usr/bin/partx -d --nr 1-1024 \$devnode", \
RUN+="/tmp/mpath-velos-log \$devnode"
EOF
  run_and_console_log udevadm control --reload-rules
fi

# Workaround for Ubuntu 18
if [ -e "/lib/udev/rules.d/60-multipath.rules" ] ; then
  console_log "Fixing multipath issue in udev rule: 60-multipath"
  cat > "/tmp/mpath-velos-log" << EOF
#!/bin/sh
# Added for Google Cloud by Migrate for Compute Engine
. /scripts/migrate-functions
console_log "Marking \$1 as mpath_member"
EOF
  chmod +x "/tmp/mpath-velos-log"
  cat > "/tmp/fstype-none-velos-log" << EOF
#!/bin/sh
# Added for Google Cloud by Migrate for Compute Engine
. /scripts/migrate-functions
console_log "Marking fs type of \$1 as none"
EOF
  chmod +x "/tmp/fstype-none-velos-log"
  cat > "/lib/udev/rules.d/61-multipath-velos.rules" << EOF
# Added for Google Cloud by Migrate for Compute Engine
ACTION=="add", \
SUBSYSTEM=="block", \
ENV{DEVTYPE}!="partition", \
ATTRS{vendor}=="VELOS_FE", \
ATTRS{model}=="VDISK           ", \
ENV{DM_MULTIPATH_DEVICE_PATH}="1", \
ENV{SYSTEMD_READY}="0", \
ENV{ID_FS_TYPE}="mpath_member", \
RUN+="/tmp/mpath-velos-log %k"
ACTION=="add", \
SUBSYSTEM=="block", \
ENV{DEVTYPE}=="partition", \
ATTRS{vendor}=="VELOS_FE", \
ATTRS{model}=="VDISK           ", \
ENV{ID_FS_TYPE}="none", \
ENV{SYSTEMD_READY}="0", \
RUN+="/tmp/fstype-none-velos-log %k"
EOF
  run_and_console_log udevadm control --reload-rules
fi

wait_for_udev

ibft_path=/sys/firmware/ibft

for device in "$ibft_path"/ethernet0/device/*/net/* ; do
  device="${device##*/}"
  break
done
target_device="ibft0"
if [ "$device" != "$target_device" ] ; then
  console_log "rename ${device} to ${target_device}"
  run_and_console_log ip link set "${device}" name "${target_device}"
  device=$target_device
fi

configure_networking

console_log "configure routes"
gateway=$(cat "$ibft_path"/ethernet0/gateway)
run_and_console_log ip route add "${gateway}" dev "${device}"
run_and_console_log ip route add default via "${gateway}"

exit 0
