Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 1 | #!/bin/sh |
| 2 | # (c) 2013 Intel Corp. |
| 3 | |
| 4 | # This program is free software; you can redistribute it and/or modify |
| 5 | # it under the terms of the GNU General Public License as published by |
| 6 | # the Free Software Foundation; either version 2 of the License, or |
| 7 | # (at your option) any later version. |
| 8 | # |
| 9 | # This program is distributed in the hope that it will be useful, |
| 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | # GNU General Public License for more details. |
| 13 | # |
| 14 | # You should have received a copy of the GNU General Public License |
| 15 | # along with this program; if not, write to the Free Software |
| 16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 17 | |
| 18 | |
| 19 | # This script can be run in two modes. |
| 20 | |
| 21 | # When used with "source", from a build directory, |
| 22 | # it enables toaster event logging and starts the bitbake resident server. |
| 23 | # use as: source toaster [start|stop] [noweb] [noui] |
| 24 | |
| 25 | # When it is called as a stand-alone script, it starts just the |
| 26 | # web server, and the building shall be done through the web interface. |
| 27 | # As script, it will not return to the command prompt. Stop with Ctrl-C. |
| 28 | |
| 29 | # Helper function to kill a background toaster development server |
| 30 | |
| 31 | webserverKillAll() |
| 32 | { |
| 33 | local pidfile |
| 34 | for pidfile in ${BUILDDIR}/.toastermain.pid; do |
| 35 | if [ -f ${pidfile} ]; then |
| 36 | pid=`cat ${pidfile}` |
| 37 | while kill -0 $pid 2>/dev/null; do |
| 38 | kill -SIGTERM -$pid 2>/dev/null |
| 39 | sleep 1 |
| 40 | # Kill processes if they are still running - may happen in interactive shells |
| 41 | ps fux | grep "python.*manage.py runserver" | awk '{print $2}' | xargs kill |
| 42 | done |
| 43 | rm ${pidfile} |
| 44 | fi |
| 45 | done |
| 46 | } |
| 47 | |
| 48 | webserverStartAll() |
| 49 | { |
| 50 | # do not start if toastermain points to a valid process |
| 51 | if ! cat "${BUILDDIR}/.toastermain.pid" 2>/dev/null | xargs -I{} kill -0 {} ; then |
| 52 | retval=1 |
| 53 | rm "${BUILDDIR}/.toastermain.pid" |
| 54 | fi |
| 55 | |
| 56 | retval=0 |
Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 57 | # you can always add a superuser later via |
| 58 | # python bitbake/lib/toaster/manage.py python manage.py createsuperuser --username=<ME> |
| 59 | python $BBBASEDIR/lib/toaster/manage.py syncdb --noinput || retval=1 |
| 60 | |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 61 | python $BBBASEDIR/lib/toaster/manage.py migrate orm || retval=2 |
Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 62 | |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 63 | if [ $retval -eq 1 ]; then |
Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 64 | echo "Failed db sync, aborting system start" 1>&2 |
| 65 | return $retval |
| 66 | fi |
| 67 | |
| 68 | python $BBBASEDIR/lib/toaster/manage.py migrate orm || retval=1 |
| 69 | |
| 70 | if [ $retval -eq 1 ]; then |
| 71 | printf "\nError on orm migration, rolling back...\n" |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 72 | python $BBBASEDIR/lib/toaster/manage.py migrate orm 0001_initial --fake |
Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 73 | return $retval |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 74 | fi |
Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 75 | |
| 76 | python $BBBASEDIR/lib/toaster/manage.py migrate bldcontrol || retval=1 |
| 77 | |
| 78 | if [ $retval -eq 1 ]; then |
| 79 | printf "\nError on bldcontrol migration, rolling back...\n" |
| 80 | python $BBBASEDIR/lib/toaster/manage.py migrate bldcontrol 0001_initial --fake |
| 81 | return $retval |
| 82 | fi |
| 83 | |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 84 | if [ "$TOASTER_MANAGED" = '1' ]; then |
Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 85 | python $BBBASEDIR/lib/toaster/manage.py checksettings --traceback || retval=1 |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 86 | fi |
Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 87 | |
| 88 | if [ $retval -eq 1 ]; then |
| 89 | printf "\nError while checking settings; aborting\n" |
| 90 | return $retval |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 91 | fi |
Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 92 | |
| 93 | echo "Starting webserver..." |
| 94 | |
| 95 | python $BBBASEDIR/lib/toaster/manage.py runserver "0.0.0.0:$WEB_PORT" </dev/null >>${BUILDDIR}/toaster_web.log 2>&1 & echo $! >${BUILDDIR}/.toastermain.pid |
| 96 | |
| 97 | sleep 1 |
| 98 | |
| 99 | if ! cat "${BUILDDIR}/.toastermain.pid" | xargs -I{} kill -0 {} ; then |
| 100 | retval=1 |
| 101 | rm "${BUILDDIR}/.toastermain.pid" |
| 102 | else |
| 103 | echo "Webserver address: http://0.0.0.0:$WEB_PORT/" |
| 104 | fi |
| 105 | |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 106 | return $retval |
| 107 | } |
| 108 | |
| 109 | # Helper functions to add a special configuration file |
| 110 | |
| 111 | addtoConfiguration() |
| 112 | { |
| 113 | file=$1 |
| 114 | shift |
| 115 | echo "#Created by toaster start script" > ${BUILDDIR}/conf/$file |
| 116 | for var in "$@"; do echo $var >> ${BUILDDIR}/conf/$file; done |
| 117 | } |
| 118 | |
| 119 | INSTOPSYSTEM=0 |
| 120 | |
| 121 | # define the stop command |
| 122 | stop_system() |
| 123 | { |
| 124 | # prevent reentry |
| 125 | if [ $INSTOPSYSTEM -eq 1 ]; then return; fi |
| 126 | INSTOPSYSTEM=1 |
| 127 | if [ -f ${BUILDDIR}/.toasterui.pid ]; then |
| 128 | kill `cat ${BUILDDIR}/.toasterui.pid` 2>/dev/null |
| 129 | rm ${BUILDDIR}/.toasterui.pid |
| 130 | fi |
| 131 | BBSERVER=0.0.0.0:-1 bitbake -m |
| 132 | unset BBSERVER |
| 133 | webserverKillAll |
| 134 | # force stop any misbehaving bitbake server |
| 135 | lsof bitbake.lock | awk '{print $2}' | grep "[0-9]\+" | xargs -n1 -r kill |
| 136 | trap - SIGHUP |
| 137 | #trap - SIGCHLD |
| 138 | INSTOPSYSTEM=0 |
| 139 | } |
| 140 | |
| 141 | check_pidbyfile() { |
| 142 | [ -e $1 ] && kill -0 `cat $1` 2>/dev/null |
| 143 | } |
| 144 | |
| 145 | |
| 146 | notify_chldexit() { |
| 147 | if [ $NOTOASTERUI -eq 0 ]; then |
| 148 | check_pidbyfile ${BUILDDIR}/.toasterui.pid && return |
| 149 | stop_system |
| 150 | fi |
| 151 | } |
| 152 | |
| 153 | |
| 154 | verify_prereq() { |
| 155 | # Verify prerequisites |
| 156 | |
| 157 | if ! echo "import django; print (1,) == django.VERSION[0:1] and django.VERSION[1:2][0] in (6,)" | python 2>/dev/null | grep True >/dev/null; then |
| 158 | printf "This program needs Django 1.6. Please install with\n\npip install django==1.6\n" |
| 159 | return 2 |
| 160 | fi |
| 161 | |
| 162 | if ! echo "import south; print reduce(lambda x, y: 2 if x==2 else 0 if x == 0 else y, map(lambda x: 1+cmp(x[1]-x[0],0), zip([0,8,4], map(int,south.__version__.split(\".\"))))) > 0" | python 2>/dev/null | grep True >/dev/null; then |
| 163 | printf "This program needs South 0.8.4. Please install with\n\npip install south==0.8.4\n" |
| 164 | return 2 |
| 165 | fi |
| 166 | return 0 |
| 167 | } |
| 168 | |
| 169 | |
| 170 | # read command line parameters |
| 171 | if [ -n "$BASH_SOURCE" ] ; then |
| 172 | TOASTER=${BASH_SOURCE} |
| 173 | elif [ -n "$ZSH_NAME" ] ; then |
| 174 | TOASTER=${(%):-%x} |
| 175 | else |
| 176 | TOASTER=$0 |
| 177 | fi |
| 178 | |
Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 179 | [ `basename \"$0\"` = `basename \"${TOASTER}\"` ] && TOASTER_MANAGED=1 |
| 180 | |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 181 | BBBASEDIR=`dirname $TOASTER`/.. |
| 182 | |
| 183 | RUNNING=0 |
| 184 | |
| 185 | NOTOASTERUI=0 |
| 186 | WEBSERVER=1 |
| 187 | TOASTER_BRBE="" |
Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 188 | if [ "$WEB_PORT" = "" ]; then |
| 189 | WEB_PORT="8000" |
| 190 | fi |
| 191 | # this is the configuraton file we are using for toaster |
| 192 | # note default is assuming yocto. Override this if you are |
| 193 | # running in a pure OE environment and use the toasterconf.json |
| 194 | # in meta/conf/toasterconf.json |
| 195 | # note: for future there are a number of relative path assumptions |
| 196 | # in the local layers that currently prevent using an arbitrary |
| 197 | # toasterconf.json |
| 198 | if [ "$TOASTER_CONF" = "" ]; then |
| 199 | TOASTER_CONF="$(dirname $TOASTER)/../../meta-yocto/conf/toasterconf.json" |
| 200 | export TOASTER_CONF=$(python -c "import os; print os.path.realpath('$TOASTER_CONF')") |
| 201 | fi |
| 202 | if [ ! -f $TOASTER_CONF ]; then |
| 203 | echo "$TOASTER_CONF configuration file not found. set TOASTER_CONF to specify a path" |
| 204 | [ "$TOASTER_MANAGED" = '1' ] && exit 1 || return 1 |
| 205 | fi |
| 206 | # this defines the dir toaster will use for |
| 207 | # 1) clones of layers (in _toaster_clones ) |
| 208 | # 2) the build dir (in build) |
| 209 | # 3) the sqlite db if that is being used. |
| 210 | # 4) pid's we need to clean up on exit/shutdown |
| 211 | # note: for future. in order to make this an arbitrary directory, we need to |
| 212 | # make sure that the toaster.sqlite file doesn't default to `pwd` like it currently does. |
| 213 | export TOASTER_DIR=`pwd` |
| 214 | |
| 215 | |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 216 | NOBROWSER=0 |
| 217 | |
| 218 | for param in $*; do |
| 219 | case $param in |
| 220 | noui ) |
| 221 | NOTOASTERUI=1 |
| 222 | ;; |
| 223 | noweb ) |
| 224 | WEBSERVER=0 |
| 225 | ;; |
| 226 | nobrowser ) |
| 227 | NOBROWSER=1 |
| 228 | ;; |
| 229 | brbe=* ) |
| 230 | TOASTER_BRBE=$'\n'"TOASTER_BRBE=\""${param#*=}"\"" |
| 231 | ;; |
| 232 | webport=*) |
| 233 | WEB_PORT="${param#*=}" |
| 234 | esac |
| 235 | done |
| 236 | |
Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 237 | if [ "$TOASTER_MANAGED" = '1' ]; then |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 238 | # We are called as standalone. We refuse to run in a build environment - we need the interactive mode for that. |
| 239 | # Start just the web server, point the web browser to the interface, and start any Django services. |
| 240 | |
| 241 | if ! verify_prereq; then |
| 242 | echo "Error: Could not verify that the needed dependencies are installed. Please use virtualenv and pip to install dependencies listed in toaster-requirements.txt" 1>&2 |
| 243 | exit 1 |
| 244 | fi |
| 245 | |
| 246 | if [ -n "$BUILDDIR" ]; then |
Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 247 | printf "Error: It looks like you sourced oe-init-build-env. Toaster cannot start in build mode from an oe-core build environment.\n You should be starting Toaster from a new terminal window.\n" 1>&2 |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 248 | exit 1 |
| 249 | fi |
| 250 | |
| 251 | # Define a fake builddir where only the pid files are actually created. No real builds will take place here. |
| 252 | BUILDDIR=/tmp/toaster_$$ |
| 253 | if [ -d "$BUILDDIR" ]; then |
| 254 | echo "Previous toaster run directory $BUILDDIR found, cowardly refusing to start. Please remove the directory when that toaster instance is over" 2>&1 |
| 255 | exit 1 |
| 256 | fi |
| 257 | |
| 258 | mkdir -p "$BUILDDIR" |
| 259 | |
| 260 | RUNNING=1 |
| 261 | trap_ctrlc() { |
| 262 | echo "** Stopping system" |
| 263 | webserverKillAll |
| 264 | RUNNING=0 |
| 265 | } |
| 266 | |
| 267 | do_cleanup() { |
| 268 | find "$BUILDDIR" -type f | xargs rm |
| 269 | rmdir "$BUILDDIR" |
| 270 | } |
| 271 | cleanup() { |
| 272 | if grep -ir error "$BUILDDIR" >/dev/null; then |
| 273 | if grep -irn "That port is already in use" "$BUILDDIR"; then |
| 274 | echo "You can use the \"webport=PORTNUMBER\" parameter to start Toaster on a different port (port $WEB_PORT is already in use)" |
| 275 | do_cleanup |
| 276 | else |
| 277 | printf "\nErrors found in the Toaster log files present in '$BUILDDIR'. Directory will not be cleaned.\n Please review the errors and notify toaster@yoctoproject.org or submit a bug https://bugzilla.yoctoproject.org/enter_bug.cgi?product=Toaster" |
| 278 | fi |
| 279 | else |
| 280 | echo "No errors found, removing the run directory '$BUILDDIR'" |
| 281 | do_cleanup |
| 282 | fi |
| 283 | } |
Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 284 | export TOASTER_MANAGED=1 |
| 285 | if [ $WEBSERVER -gt 0 ] && ! webserverStartAll; then |
| 286 | echo "Failed to start the web server, stopping" 1>&2 |
| 287 | cleanup |
| 288 | exit 1 |
| 289 | fi |
| 290 | if [ $WEBSERVER -gt 0 ] && [ $NOBROWSER -eq 0 ] ; then |
| 291 | echo "Starting browser..." |
| 292 | xdg-open http://127.0.0.1:$WEB_PORT/ >/dev/null 2>&1 & |
| 293 | fi |
| 294 | trap trap_ctrlc 2 |
| 295 | echo "Toaster is now running. You can stop it with Ctrl-C" |
| 296 | while [ $RUNNING -gt 0 ]; do |
| 297 | python $BBBASEDIR/lib/toaster/manage.py runbuilds 2>&1 | tee -a "$BUILDDIR/toaster.log" |
| 298 | sleep 1 |
| 299 | done |
| 300 | cleanup |
| 301 | echo "**** Exit" |
| 302 | exit 0 |
| 303 | fi |
| 304 | |
| 305 | |
| 306 | if ! verify_prereq; then |
| 307 | echo "Error: Could not verify that the needed dependencies are installed. Please use virtualenv and pip to install dependencies listed in toaster-requirements.txt" 1>&2 |
| 308 | return 1 |
| 309 | fi |
| 310 | |
| 311 | |
| 312 | # We make sure we're running in the current shell and in a good environment |
| 313 | if [ -z "$BUILDDIR" ] || ! which bitbake >/dev/null 2>&1 ; then |
| 314 | echo "Error: Build environment is not setup or bitbake is not in path." 1>&2 |
| 315 | return 2 |
| 316 | fi |
| 317 | |
| 318 | |
| 319 | # Determine the action. If specified by arguments, fine, if not, toggle it |
| 320 | if [ "$1" = 'start' ] || [ "$1" = 'stop' ]; then |
| 321 | CMD="$1" |
| 322 | else |
| 323 | if [ -z "$BBSERVER" ]; then |
| 324 | CMD="start" |
| 325 | else |
| 326 | CMD="stop" |
| 327 | fi |
| 328 | fi |
| 329 | |
| 330 | echo "The system will $CMD." |
| 331 | |
| 332 | # Make sure it's safe to run by checking bitbake lock |
| 333 | |
| 334 | lock=1 |
| 335 | if [ -e $BUILDDIR/bitbake.lock ]; then |
| 336 | python -c "import fcntl; fcntl.flock(open(\"$BUILDDIR/bitbake.lock\"), fcntl.LOCK_EX|fcntl.LOCK_NB)" 2>/dev/null || lock=0 |
| 337 | fi |
| 338 | |
| 339 | if [ ${CMD} = 'start' ] && [ $lock -eq 0 ]; then |
| 340 | echo "Error: bitbake lock state error. File locks show that the system is on." 1>&2 |
| 341 | echo "Please wait for the current build to finish, stop and then start the system again." 1>&2 |
| 342 | return 3 |
| 343 | fi |
| 344 | |
| 345 | if [ ${CMD} = 'start' ] && [ -e $BUILDDIR/.toastermain.pid ] && kill -0 `cat $BUILDDIR/.toastermain.pid`; then |
| 346 | echo "Warning: bitbake appears to be dead, but the Toaster web server is running. Something fishy is going on." 1>&2 |
| 347 | echo "Cleaning up the web server to start from a clean slate." |
| 348 | webserverKillAll |
| 349 | fi |
| 350 | |
| 351 | |
| 352 | # Execute the commands |
| 353 | |
| 354 | case $CMD in |
| 355 | start ) |
| 356 | start_success=1 |
| 357 | addtoConfiguration toaster.conf "INHERIT+=\"toaster buildhistory\"" $TOASTER_BRBE |
| 358 | if [ $WEBSERVER -gt 0 ] && ! webserverStartAll; then |
| 359 | echo "Failed ${CMD}." |
| 360 | return 4 |
| 361 | fi |
| 362 | unset BBSERVER |
| 363 | PREREAD="" |
| 364 | if [ -e ${BUILDDIR}/conf/toaster-pre.conf ]; then |
| 365 | rm ${BUILDDIR}/conf/toaster-pre.conf |
| 366 | fi |
| 367 | bitbake $PREREAD --postread conf/toaster.conf --server-only -t xmlrpc -B 0.0.0.0:0 |
| 368 | if [ $? -ne 0 ]; then |
| 369 | start_success=0 |
| 370 | echo "Bitbake server start failed" |
| 371 | else |
| 372 | export BBSERVER=0.0.0.0:-1 |
| 373 | if [ $NOTOASTERUI -eq 0 ]; then # we start the TOASTERUI only if not inhibited |
| 374 | bitbake --observe-only -u toasterui >>${BUILDDIR}/toaster_ui.log 2>&1 & echo $! >${BUILDDIR}/.toasterui.pid |
| 375 | fi |
| 376 | fi |
| 377 | if [ $start_success -eq 1 ]; then |
| 378 | # set fail safe stop system on terminal exit |
| 379 | trap stop_system SIGHUP |
| 380 | echo "Successful ${CMD}." |
| 381 | return 0 |
| 382 | else |
| 383 | # failed start, do stop |
| 384 | stop_system |
| 385 | echo "Failed ${CMD}." |
| 386 | return 1 |
| 387 | fi |
| 388 | # stop system on terminal exit |
| 389 | set -o monitor |
| 390 | trap stop_system SIGHUP |
| 391 | #trap notify_chldexit SIGCHLD |
| 392 | ;; |
| 393 | stop ) |
| 394 | stop_system |
| 395 | echo "Successful ${CMD}." |
| 396 | ;; |
| 397 | esac |
| 398 | |