blob: 4fdf816bbf20ca1233da7e1de556e3597109bb2b [file] [log] [blame]
# Copyright 2016 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
description "Starts and stops the iSCSI initiator services and logs in to default targets"
author "chromium-os-dev@chromium.org"
# TODO(printesoi): For now, booting from iSCSI will not work because
# InitiatorName file and idbm database must be writable and are located on the
# stateful partition.
start on started system-services
stop on stopping system-services
respawn
env CONFIG_FILE="/etc/iscsi/iscsid.conf"
env ISCSID_RUNTIME_DIR="/var/lib/iscsi"
env INITIATORNAME_FILE="/var/lib/iscsi/initiatorname.iscsi"
pre-start script
log_msg() {
logger -is -p daemon.info -t "$UPSTART_JOB" -- "$@"
}
log_error() {
logger -is -p daemon.error -t "$UPSTART_JOB" -- "$@"
}
log_warning() {
logger -is -p daemon.warning -t "$UPSTART_JOB" -- "$@"
}
check_runtime_dir() {
local out ret=0
if [ -d "${ISCSID_RUNTIME_DIR}" ]; then
return 0
fi
out=$(mkdir -p "${ISCSID_RUNTIME_DIR}" 2>&1) || ret=$?
if [ ${ret} -ne 0 ]; then
log_error "Cannot create directory ${ISCSID_RUNTIME_DIR}: ${out}"
log_error "The iSCSI driver cannot start."
return 1
fi
}
check_config() {
if [ ! -e "${CONFIG_FILE}" ]; then
log_error "Configuration file ${CONFIG_FILE} is missing!"
log_error "The iSCSI driver has not been correctly installed and cannot start."
return 1
fi
if [ ! -e "${INITIATORNAME_FILE}" ]; then
log_error "InitiatorName file ${INITIATORNAME_FILE} is missing!"
log_error "The iSCSI driver has not been correctly installed and cannot start."
return 1
fi
if ! grep -q "^InitiatorName=[^[:space:]]" "${INITIATORNAME_FILE}"; then
log_error "${INITIATORNAME_FILE} does not contain a valid InitiatorName"
log_error "The iSCSI driver has not been correctly installed and cannot start."
return 1
fi
}
check_modules() {
# Ensure that the kernel modules are loaded.
modprobe -q iscsi_tcp 2>/dev/null || true
modprobe -q ib_iser 2>/dev/null || true
}
if ! check_runtime_dir ; then
stop
exit 1
fi
if ! check_config ; then
stop
exit 2
fi
check_modules
end script
exec /sbin/minijail0 -I -l -v -r -p -- /usr/sbin/iscsid -c "${CONFIG_FILE}" \
-i "${INITIATORNAME_FILE}"
post-start script
log_msg() {
logger -is -p daemon.info -t "$UPSTART_JOB" -- "$@"
}
log_warning() {
logger -is -p daemon.warning -t "$UPSTART_JOB" -- "$@"
}
start_targets() {
local ret=0
log_msg "Setting up iSCSI targets"
iscsiadm -m node --loginall=automatic 2>/dev/null || ret=$?
if [ ${ret} -eq 21 ]; then
ret=0
fi
return ${ret}
}
if ! start_targets ; then
log_warning "Cannot start automatic target!"
return 0
fi
end script
pre-stop script
log_msg() {
logger -is -p daemon.info -t "$UPSTART_JOB" -- "$@"
}
log_warning() {
logger -is -p daemon.warning -t "$UPSTART_JOB" -- "$@"
}
umount_path() {
if [ $# -ne 1 ]; then
return 1
fi
local ret=0 mount_point
# Use printf because mount points may contain special characters like
# spaces. Posix printf does not have '-v' so run a subshell.
mount_point=$(printf "%b" "$1")
out=$(sudo umount "${mount_point}" 2>&1)
if [ $? -ne 0 ]; then
log_warning "Could not unmount ${mount_point}"
ret=1
fi
return ${ret}
}
block_is_iscsi() {
if [ $# -ne 1 ]; then
return 1
fi
local block_name="$1" platform_dev session_dir
platform_dev="$(readlink -f "/sys/class/block/${block_name}")"
session_dir="${platform_dev%%/target*/*:*}"
if [ ! -d "${session_dir}/iscsi_session" ]; then
return 1
fi
return 0
}
umount_iscsi() {
local ret=0 block_dev mount_point tmp block_name platform_dev
while IFS=' ' read -r block_dev mount_point tmp; do
# Only check block devices.
if [ "${block_dev#/dev/}" = "${block_dev}" ]; then
continue;
fi
block_dev=$(readlink -f "${block_dev}")
block_name="${block_dev##*/}"
# TODO(printesoi): We must also unmount virtual block devices, such as
# LVM2, software RAID or dm-crypt that contain iscsi slaves.
if [ ! "${block_name#dm-}" = "${block_name}" ]; then
continue
fi
if ! block_is_iscsi "${block_name}"; then
continue
fi
if ! umount_path "${mount_point}"; then
ret=1
fi
done </proc/mounts
return ${ret}
}
stop_targets() {
local ret=0
log_msg "Disconnecting iSCSI targets"
iscsiadm -m node --logoutall=all 2>/dev/null || ret=$?
if [ ${ret} -eq 21 ]; then
ret=0
fi
return ${ret}
}
if ! umount_iscsi ; then
stop
exit 1
fi
if ! stop_targets ; then
stop
exit 2
fi
end script