blob: 5cf7817539f9415ffd06d753c4ed62f332fb8929 [file] [log] [blame]
#!/bin/bash
# Copyright (c) 2012 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.
set -e
. /usr/local/factory/sh/common.sh
FACTORY="$(dirname "$(dirname "$(readlink -f "$0")")")"
FACTORY_LOG_FILE=/var/factory/log/factory.log
SESSION_LOG_FILE=/var/log/factory_session.log
INTERACTIVE_CONSOLES=""
LOG_PROCESSES=""
BOARD_SETUP="${FACTORY}/board/board_setup_factory.sh"
# Put '/usr/local/factory/bin' at the head of PATH so that Goofy doesn't need to
# specify full path name when running factory binaries.
export PATH="/usr/local/factory/bin:${PATH}"
# Default args for Goofy.
GOOFY_ARGS=""
PRESENTER_ARGS=""
# Default implementation for factory_setup (no-op). May be overriden
# by board_setup_factory.sh.
factory_setup() {
true
}
# Clean up when error happens.
on_error() {
local pid
# Try to show console because stopping UI may take a while.
show_interactive_console
stop -n ui >/dev/null 2>&1 || true
for pid in ${LOG_PROCESSES}; do
kill -9 "${pid}" &
done
# Show console again because stopping UI may change active console.
show_interactive_console
}
# Initialize output system (create logs and redirect output).
init_output() {
echo "Redirecting output to ${SESSION_LOG_FILE}"
exec >"${SESSION_LOG_FILE}" 2>&1
echo "New factory session: $(date +'%Y%m%d %H:%M:%s')"
# When VT is available, TTYs were reserved as:
# 1 - UI (Chrome or X)
# 2 - getty (login)
# 3 - tail -f /var/log/factory.log
# So for Goofy session, we want to print the logs in following order:
# - /dev/tty4 if available (Systems with VT)
# - /dev/console if available
local tty
for tty in /dev/tty4 /dev/console $(tty); do
if [ -c "${tty}" ] && (echo "" >>"${tty}") 2>/dev/null; then
tail -f "${SESSION_LOG_FILE}" >>"${tty}" &
LOG_PROCESSES="${LOG_PROCESSES} $!"
INTERACTIVE_CONSOLES="${INTERACTIVE_CONSOLES} ${tty}"
fi
done
trap on_error EXIT
# This should already exist, but just in case...
mkdir -p "$(dirname "${FACTORY_LOG_FILE}")"
touch "${FACTORY_LOG_FILE}"
# To help reading archived logs (not on DUT), we assume the FACTORY_LOG_FILE
# starts with /var and try to create the symlink as relative path.
ln -sf "../${FACTORY_LOG_FILE#/var/}" /var/log
# Provide the latest factory log on TTY3 if available.
local tty_log=/dev/tty3
if [ -c "${tty_log}" ]; then
setsid sh -c \
"script -afqc 'while true; do less -W +F ${FACTORY_LOG_FILE}; done' \
/dev/null <${tty_log} >${tty_log}" &
fi
}
# Try to show the interactive console if available.
show_interactive_console() {
local tty
local vt_index
for tty in ${INTERACTIVE_CONSOLES}; do
vt_index="${tty#/dev/tty}"
if [ "${vt_index}" = "${tty}" ]; then
continue
fi
chvt "${vt_index}" && return || true
done
}
# Load board-specific parameters, if any.
load_setup() {
if [ -s "${BOARD_SETUP}" ]; then
echo "Loading board-specific parameters ${BOARD_SETUP}..."
. "${BOARD_SETUP}"
fi
if [[ -f ${AUTOMATION_MODE_TAG_FILE} ]]; then
local mode="$(cat ${AUTOMATION_MODE_TAG_FILE})"
if [[ -n "${mode}" ]]; then
echo "Enable factory test automation with mode: ${mode}"
GOOFY_ARGS="${GOOFY_ARGS} --automation-mode=${mode}"
fi
if [[ -f ${STOP_AUTO_RUN_ON_START_TAG_FILE} ]]; then
echo "Suppress test list auto-run on start"
GOOFY_ARGS="${GOOFY_ARGS} --no-auto-run-on-start"
fi
fi
factory_setup
}
# Checks disk usage and abort if running out of disk space.
check_disk_usage() {
# Show error in red
printf "\e[1;31m"
if "$FACTORY/bin/disk_space"; then
printf "\e[0m"
return
fi
echo "
/-\_ ___ ___ --------+ +--------|
\_ \ / |______ ________| |_________ |+----+ | | +----+ |
\ \ / _____. \ | .______________. | || | | | | | |
\_/ / / | | | | | | ||____| | | |____| |
| | | | | | | | | ____ | | ____ |
| | | | |_| /-| |-\_ |_| || | | | | | |
.--. _|/ __| | _/ / \_ \_ || | | | | | |
\ \ /_ | / / _/ _/ \ \ ||____| | | |____| |
\--\ \/ \___/ / / \_ \ | ______| |______ |
---/ \ | || | |
____________ \/ || ._________. | |
\ ._____. | ___________________ || | _______ | | |
/-+ | | | | |________ ________| || | | | | | |
| | \ | | / | | || | |_____| | | |
/ / | \ _| | | | || | _____ | | |
| | \ \ / / | | || | | | | | |
/ / \ v / | | || | |_____| | | |
| / _> < | | || |_________| | |
/ | ___/ /\ \____ ._______| |________. || | |
|-/ /_____/ \______\ |__________________| |/ \_|
_ _ ____ _ _ ____ _ _ _
| \ | | ___ | _ \(_)___| | __ / ___| _ __ __ _ ___ ___| | | |
| \| |/ _ \ | | | | / __| |/ / \___ \| ._ \ / _\ |/ __/ _ \ | | |
| |\ | (_) | | |_| | \__ \ < ___) | |_) | (_| | (_| __/_|_|_|
|_| \_|\___/ |____/|_|___/_|\_\ |____/| .__/ \__,_|\___\___(_|_|_)
|_|
"
printf "\e[0m"
exit 1
}
# Initialize system TTY.
init_tty() {
# Preventing ttyN (developer shell console) to go blank after some idle time
local tty=""
for tty in /dev/tty[2-4]; do
(setterm -cursor on -blank 0 -powerdown 0 -powersave off
>"${tty}") 2>/dev/null || true
done
}
# Initialize kernel modules and system daemons.
init_modules() {
# We disable powerd in factory image, but this folder is needed for some
# commands like power_supply_info to work.
mkdir -p /var/lib/power_manager
# Preload modules here
modprobe i2c-dev 2>/dev/null || true
}
# Initialize network settings.
init_network() {
# Make sure local loopback device is activated
ifconfig lo up
}
start_factory() {
init_output
echo "
Starting factory program...
If you don't see factory window after more than one minute,
try to switch to VT2 (Ctrl-Alt-F2), log in, and check the messages by:
tail $SESSION_LOG_FILE $FACTORY_LOG_FILE
If it keeps failing, try to reset by:
factory_restart -a
"
load_setup
init_modules
init_tty
init_network
check_disk_usage
if [ -z "$(status ui | grep start)" ]; then
echo "Request to start UI..."
start -n ui &
fi
export DISPLAY=":0"
export XAUTHORITY="/home/chronos/.Xauthority"
# Rules to start Goofy. Not this has to sync with init/startup.
local tag_device="${RUN_GOOFY_DEVICE_TAG_FILE}"
local tag_presenter="${RUN_GOOFY_PRESENTER_TAG_FILE}"
local run_device=true
if [ -f "${tag_presenter}" ]; then
if [ -f "${tag_device}" ]; then
PRESENTER_ARGS="${PRESENTER_ARGS} --standalone"
GOOFY_ARGS="${GOOFY_ARGS} --standalone"
else
# Presenter-only.
run_device=false
fi
# Note presenter output is only kept in SESSION_LOG_FILE.
echo "Starting Goofy Presenter... ($PRESENTER_ARGS)"
"$FACTORY/bin/goofy_presenter" $PRESENTER_ARGS &
elif [ ! -f "${tag_device}" ]; then
# Monolithic mode.
GOOFY_ARGS="${GOOFY_ARGS} --monolithic"
fi
if "${run_device}"; then
echo "Starting Goofy Device... ($GOOFY_ARGS)"
echo "
--- $(date +'%Y%m%d %H:%M:%S') Starting new Goofy session ($GOOFY_ARGS) ---
" >>"$FACTORY_LOG_FILE"
"$FACTORY/bin/goofy" $GOOFY_ARGS >>"$FACTORY_LOG_FILE" 2>&1 &
fi
wait
}
stop_factory() {
# Try to kill X, and any other Python scripts, five times.
echo -n "Stopping factory."
for i in $(seq 5); do
pkill 'python' || break
sleep 1
echo -n "."
done
echo "
Factory tests terminated. To check error messages, try
tail ${SESSION_LOG_FILE} ${FACTORY_LOG_FILE}
To restart, press Ctrl-Alt-F2, log in, and type:
factory_restart
If restarting does not work, try to reset by:
factory_restart -a
"
}
main() {
case "$1" in
"start" )
start_factory "$@"
;;
"stop" )
stop_factory "$@"
;;
* )
echo "Usage: $0 [start|stop]" >&2
exit 1
;;
esac
}
main "$@"