Home | History | Annotate | Download | only in site_utils
      1 #!/bin/bash
      2 #
      3 # Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
      4 # Use of this source code is governed by a BSD-style license that can be
      5 # found in the LICENSE file.
      6 set -e
      7 
      8 function usage() {
      9   cat >&2 <<EOT
     10 Usage: setup_dev_autotest.sh [-pavnms]
     11 
     12 Install and configure software needed to run autotest locally.
     13 If you're just working on tests, you do not need to run this.
     14 Options:
     15   -p Desired Autotest DB password. Must be non-empty.
     16   -a Absolute path to autotest source tree.
     17   -v Show info logging from build_externals.py and compile_gwt_clients.py
     18   -n Non-interactive mode, doesn't ask for any user input.
     19      Requires -p and -a to be set.
     20   -m Allow remote access for database.
     21   -s Skip steps handled via puppet in prod.
     22      This is a transitional flag used to skip certain steps as they are migrated
     23      to puppet for use in the autotest lab. Not to be used by developers.
     24 
     25 EOT
     26 }
     27 
     28 
     29 function get_y_or_n_interactive {
     30     local ret
     31     while true; do
     32         read -p "$2" yn
     33         case $yn in
     34             [Yy]* ) ret="y"; break;;
     35             [Nn]* ) ret="n"; break;;
     36             * ) echo "Please enter y or n.";;
     37         esac
     38     done
     39     eval "$1=\$ret"
     40 }
     41 
     42 function get_y_or_n {
     43   local ret=$3
     44   if [ "${noninteractive}" = "FALSE" ]; then
     45     get_y_or_n_interactive sub "$2"
     46     ret=$sub
     47   fi
     48   eval "$1=\$ret"
     49 }
     50 
     51 AUTOTEST_DIR=
     52 PASSWD=
     53 verbose="FALSE"
     54 noninteractive="FALSE"
     55 remotedb="FALSE"
     56 skip_puppetized_steps="FALSE"
     57 while getopts ":p:a:vnmsh" opt; do
     58   case ${opt} in
     59     a)
     60       AUTOTEST_DIR=$OPTARG
     61       ;;
     62     p)
     63       PASSWD=$OPTARG
     64       ;;
     65     v)
     66       verbose="TRUE"
     67       ;;
     68     n)
     69       noninteractive="TRUE"
     70       ;;
     71     m)
     72       remotedb="TRUE"
     73       ;;
     74     s)
     75       skip_puppetized_steps="TRUE"
     76       ;;
     77     h)
     78       usage
     79       exit 0
     80       ;;
     81     \?)
     82       echo "Invalid option: -$OPTARG" >&2
     83       usage
     84       exit 1
     85       ;;
     86     :)
     87       echo "Option -$OPTARG requires an argument." >&2
     88       usage
     89       exit 1
     90       ;;
     91   esac
     92 done
     93 
     94 if [[ "${skip_puppetized_steps}" == "TRUE" ]]; then
     95   echo "Requested to skip certain steps. Will tell you when I skip things."
     96 fi
     97 
     98 if [[ $EUID -eq 0 ]]; then
     99   echo "Running with sudo / as root is not recommended"
    100   get_y_or_n verify "Continue as root? [y/N]: " "n"
    101   if [[ "${verify}" = 'n' ]]; then
    102     echo "Bailing!"
    103     exit 1
    104   fi
    105 fi
    106 
    107 if [ "${noninteractive}" = "TRUE" ]; then
    108   if [ -z "${AUTOTEST_DIR}" ]; then
    109     echo "-a must be specified in non-interactive mode." >&2
    110     exit 1
    111   fi
    112   if [ -z "${PASSWD}" ]; then
    113     echo "-p must be specified in non-interactive mode." >&2
    114     exit 1
    115   fi
    116 fi
    117 
    118 
    119 if [ -z "${PASSWD}" ]; then
    120   read -s -p "Autotest DB password: " PASSWD
    121   echo
    122   if [ -z "${PASSWD}" ]; then
    123     echo "Empty passwords not allowed." >&2
    124     exit 1
    125   fi
    126   read -s -p "Re-enter password: " PASSWD2
    127   echo
    128   if [ "${PASSWD}" != "${PASSWD2}" ]; then
    129     echo "Passwords don't match." >&2
    130     exit 1
    131   fi
    132 fi
    133 
    134 if [ -z "${AUTOTEST_DIR}" ]; then
    135   CANDIDATE=$(dirname "$(readlink -f "$0")" | egrep -o '(/[^/]+)*/files')
    136   read -p "Enter autotest dir [${CANDIDATE}]: " AUTOTEST_DIR
    137   if [ -z "${AUTOTEST_DIR}" ]; then
    138     AUTOTEST_DIR="${CANDIDATE}"
    139   fi
    140 fi
    141 
    142 
    143 # Sanity check AUTOTEST_DIR. If it's null, or doesn't exist on the filesystem
    144 # then die.
    145 if [ -z "${AUTOTEST_DIR}" ]; then
    146   echo "No AUTOTEST_DIR. Aborting script."
    147   exit 1
    148 fi
    149 
    150 if [ ! -d "${AUTOTEST_DIR}" ]; then
    151   echo "Directory $AUTOTEST_DIR does not exist. Aborting script."
    152   exit 1
    153 fi
    154 
    155 
    156 SHADOW_CONFIG_PATH="${AUTOTEST_DIR}/shadow_config.ini"
    157 echo "Autotest supports local overrides of global configuration through a "
    158 echo "'shadow' configuration file.  Setting one up for you now."
    159 CLOBBER=0
    160 if [ -f ${SHADOW_CONFIG_PATH} ]; then
    161   get_y_or_n clobber "Clobber existing shadow config? [Y/n]: " "n"
    162   if [[ "${clobber}" = 'n' ]]; then
    163     CLOBBER=1
    164     echo "Refusing to clobber existing shadow_config.ini."
    165   else
    166     echo "Clobbering existing shadow_config.ini."
    167   fi
    168 fi
    169 
    170 CROS_CHECKOUT=$(readlink -f "$AUTOTEST_DIR/../../../..")
    171 
    172 # Create clean shadow config if we're replacing it/creating a new one.
    173 if [ $CLOBBER -eq 0 ]; then
    174   cat > "${SHADOW_CONFIG_PATH}" <<EOF
    175 [AUTOTEST_WEB]
    176 host: localhost
    177 password: ${PASSWD}
    178 readonly_host: localhost
    179 readonly_user: chromeosqa-admin
    180 readonly_password: ${PASSWD}
    181 
    182 [SERVER]
    183 hostname: localhost
    184 
    185 [SCHEDULER]
    186 drones: localhost
    187 
    188 [CROS]
    189 source_tree: ${CROS_CHECKOUT}
    190 # Edit the following line as needed.
    191 #dev_server: http://10.10.10.10:8080
    192 enable_ssh_tunnel_for_servo: True
    193 enable_ssh_tunnel_for_chameleon: True
    194 enable_ssh_connection_for_devserver: True
    195 enable_ssh_tunnel_for_moblab: True
    196 EOF
    197   echo -e "Done!\n"
    198 fi
    199 
    200 echo "Installing needed Ubuntu packages..."
    201 PKG_LIST="libapache2-mod-wsgi gnuplot apache2-mpm-prefork unzip \
    202 python-imaging libpng12-dev libfreetype6-dev \
    203 sqlite3 python-pysqlite2 git-core pbzip2 openjdk-6-jre openjdk-6-jdk \
    204 python-crypto  python-dev subversion build-essential python-setuptools \
    205 python-numpy python-scipy libmysqlclient-dev"
    206 
    207 if ! sudo apt-get install -y ${PKG_LIST}; then
    208   echo "Could not install packages: $?"
    209   exit 1
    210 fi
    211 echo -e "Done!\n"
    212 
    213 INFRA_VENV_SYMLINK=/opt/infra_virtualenv
    214 if [ -e "${INFRA_VENV_SYMLINK}" ]; then
    215   echo "infra_virtualenv already set up at ${INFRA_VENV_SYMLINK}"
    216 else
    217   echo -n "Setting up symlink for infra_virtualenv..."
    218   INFRA_VENV_PATH=$(realpath "${CROS_CHECKOUT}/infra_virtualenv")
    219   if ! [ -e "$INFRA_VENV_PATH/bin/create_venv" ]; then
    220     echo "Could not find infra_virtualenv repo at ${INFRA_VENV_PATH}"
    221     echo "Make sure you're using a full repo checkout"
    222     exit 1
    223   fi
    224   sudo ln -s "$INFRA_VENV_PATH" "$INFRA_VENV_SYMLINK"
    225   echo -e "Done!\n"
    226 fi
    227 
    228 AT_DIR=/usr/local/autotest
    229 echo -n "Bind-mounting your autotest dir at ${AT_DIR}..."
    230 sudo mkdir -p "${AT_DIR}"
    231 sudo mount --bind "${AUTOTEST_DIR}" "${AT_DIR}"
    232 echo -e "Done!\n"
    233 
    234 sudo chown -R "$(whoami)" "${AT_DIR}"
    235 
    236 EXISTING_MOUNT=$(egrep "/.+[[:space:]]${AT_DIR}" /etc/fstab || /bin/true)
    237 if [ -n "${EXISTING_MOUNT}" ]; then
    238   echo "${EXISTING_MOUNT}" | awk '{print $1 " already automounting at " $2}'
    239   echo "We won't update /etc/fstab, but you should have a line line this:"
    240   echo -e "${AUTOTEST_DIR}\t${AT_DIR}\tbind defaults,bind\t0\t0"
    241 else
    242   echo -n "Adding aforementioned bind-mount to /etc/fstab..."
    243   # Is there a better way to elevate privs and do a redirect?
    244   sudo su -c \
    245     "echo -e '${AUTOTEST_DIR}\t${AT_DIR}\tbind defaults,bind\t0\t0' \
    246     >> /etc/fstab"
    247   echo -e "Done!\n"
    248 fi
    249 
    250 echo -n "Reticulating splines..."
    251 
    252 if [ "${verbose}" = "TRUE" ]; then
    253   "${AT_DIR}"/utils/build_externals.py
    254   "${AT_DIR}"/utils/compile_gwt_clients.py -a
    255 else
    256   "${AT_DIR}"/utils/build_externals.py &> /dev/null
    257   "${AT_DIR}"/utils/compile_gwt_clients.py -a &> /dev/null
    258 fi
    259 
    260 echo -e "Done!\n"
    261 
    262 echo "Start setting up Database..."
    263 get_y_or_n clobberdb "Clobber MySQL database if it exists? [Y/n]: " "n"
    264 opts_string="-p ${PASSWD} -a ${AT_DIR}"
    265 if [[ "${clobberdb}" = 'y' ]]; then
    266   opts_string="${opts_string} -c"
    267 fi
    268 if [[ "${remotedb}" = 'TRUE' ]]; then
    269   opts_string="${opts_string} -m"
    270 fi
    271 "${AT_DIR}"/site_utils/setup_db.sh ${opts_string}
    272 
    273 echo -e "Done!\n"
    274 
    275 echo "Configuring apache to run the autotest web interface..."
    276 if [ ! -d /etc/apache2/run ]; then
    277   sudo mkdir /etc/apache2/run
    278 fi
    279 sudo ln -sf "${AT_DIR}"/apache/apache-conf \
    280   /etc/apache2/sites-available/autotest-server.conf
    281 
    282 # Disable currently active default
    283 sudo a2dissite 000-default default || true
    284 sudo a2ensite autotest-server.conf
    285 
    286 sudo a2enmod rewrite
    287 sudo a2enmod wsgi
    288 sudo a2enmod version || true  # built-in on trusty
    289 sudo a2enmod headers
    290 sudo a2enmod cgid
    291 
    292 # Setup permissions so that Apache web user can read the proper files.
    293 chmod -R o+r "${AT_DIR}"
    294 find "${AT_DIR}"/ -type d -print0 | xargs --null chmod o+x
    295 chmod o+x "${AT_DIR}"/tko/*.cgi
    296 # restart server
    297 sudo /etc/init.d/apache2 restart
    298 
    299 # Setup lxc and base container for server-side packaging support.
    300 sudo apt-get install lxc -y
    301 sudo python "${AT_DIR}"/site_utils/lxc.py -s
    302 
    303 # Set up keys for www-data/apache user.
    304 APACHE_USER=www-data
    305 APACHE_HOME=/var/www
    306 APACHE_SSH_DIR="$APACHE_HOME/.ssh"
    307 SSH_KEYS_PATH=src/third_party/chromiumos-overlay/chromeos-base/chromeos-ssh-testkeys/files
    308 sudo mkdir -p "$APACHE_SSH_DIR"
    309 sudo bash <<EOF
    310 cd "${APACHE_SSH_DIR:-/dev/null}" || exit 1
    311 sudo cp "$CROS_CHECKOUT/$SSH_KEYS_PATH/"* .
    312 sudo tee config >/dev/null <<EOF2
    313 Host *
    314 User root
    315 IdentityFile ~/.ssh/testing_rsa
    316 EOF2
    317 sudo chown -R "$APACHE_USER:" .
    318 sudo chmod -R go-rwx .
    319 EOF
    320 if [ $? -ne 0 ]; then
    321   echo "apache user SSH setup failed."
    322 fi
    323 
    324 echo "Browse to http://localhost to see if Autotest is working."
    325 echo "For further necessary set up steps, see https://sites.google.com/a/chromium.org/dev/chromium-os/testing/autotest-developer-faq/setup-autotest-server?pli=1"
    326