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