| # 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 |