xref: /openbmc/openbmc/poky/bitbake/bin/toaster (revision 82c905dc)
1#!/bin/echo ERROR: This script needs to be sourced. Please run as .
2
3# toaster - shell script to start Toaster
4
5# Copyright (C) 2013-2015 Intel Corp.
6#
7# SPDX-License-Identifier: GPL-2.0-or-later
8#
9
10HELP="
11Usage 1: source toaster start|stop [webport=<address:port>] [noweb] [nobuild] [toasterdir]
12    Optional arguments:
13        [nobuild] Setup the environment for capturing builds with toaster but disable managed builds
14        [noweb] Setup the environment for capturing builds with toaster but don't start the web server
15        [webport] Set the development server (default: localhost:8000)
16        [toasterdir] Set absolute path to be used as TOASTER_DIR (default: BUILDDIR/../)
17Usage 2: source toaster manage [createsuperuser|lsupdates|migrate|makemigrations|checksettings|collectstatic|...]
18"
19
20custom_extention()
21{
22    custom_extension=$BBBASEDIR/lib/toaster/orm/fixtures/custom_toaster_append.sh
23    if [ -f $custom_extension ] ; then
24        $custom_extension $*
25    fi
26}
27
28databaseCheck()
29{
30    retval=0
31    # you can always add a superuser later via
32    # ../bitbake/lib/toaster/manage.py createsuperuser --username=<ME>
33    $MANAGE migrate --noinput || retval=1
34
35    if [ $retval -eq 1 ]; then
36        echo "Failed migrations, aborting system start" 1>&2
37        return $retval
38    fi
39    # Make sure that checksettings can pick up any value for TEMPLATECONF
40    export TEMPLATECONF
41    $MANAGE checksettings --traceback || retval=1
42
43    if [ $retval -eq 1 ]; then
44        printf "\nError while checking settings; aborting\n"
45        return $retval
46    fi
47
48    return $retval
49}
50
51webserverKillAll()
52{
53    local pidfile
54    if [ -f ${BUILDDIR}/.toastermain.pid ] ; then
55        custom_extention web_stop_postpend
56    else
57        custom_extention noweb_stop_postpend
58    fi
59    for pidfile in ${BUILDDIR}/.toastermain.pid ${BUILDDIR}/.runbuilds.pid; do
60        if [ -f ${pidfile} ]; then
61            pid=`cat ${pidfile}`
62            while kill -0 $pid 2>/dev/null; do
63                kill -SIGTERM $pid 2>/dev/null
64                sleep 1
65            done
66            rm  ${pidfile}
67        fi
68    done
69}
70
71webserverStartAll()
72{
73    # do not start if toastermain points to a valid process
74    if ! cat "${BUILDDIR}/.toastermain.pid" 2>/dev/null | xargs -I{} kill -0 {} ; then
75        retval=1
76        rm "${BUILDDIR}/.toastermain.pid"
77    fi
78
79    retval=0
80
81    # check the database
82    databaseCheck || return 1
83
84    echo "Starting webserver..."
85
86    $MANAGE runserver --noreload "$ADDR_PORT" \
87           </dev/null >>${BUILDDIR}/toaster_web.log 2>&1 \
88           & echo $! >${BUILDDIR}/.toastermain.pid
89
90    sleep 1
91
92    if ! cat "${BUILDDIR}/.toastermain.pid" | xargs -I{} kill -0 {} ; then
93        retval=1
94        rm "${BUILDDIR}/.toastermain.pid"
95    else
96        echo "Toaster development webserver started at http://$ADDR_PORT"
97        echo -e "\nYou can now run 'bitbake <target>' on the command line and monitor your build in Toaster.\nYou can also use a Toaster project to configure and run a build.\n"
98        custom_extention web_start_postpend $ADDR_PORT
99    fi
100
101    return $retval
102}
103
104INSTOPSYSTEM=0
105
106# define the stop command
107stop_system()
108{
109    # prevent reentry
110    if [ $INSTOPSYSTEM -eq 1 ]; then return; fi
111    INSTOPSYSTEM=1
112    webserverKillAll
113    # unset exported variables
114    unset TOASTER_DIR
115    unset BITBAKE_UI
116    unset BBBASEDIR
117    trap - SIGHUP
118    #trap - SIGCHLD
119    INSTOPSYSTEM=0
120}
121
122verify_prereq() {
123    # Verify Django version
124    reqfile=$(python3 -c "import os; print(os.path.realpath('$BBBASEDIR/toaster-requirements.txt'))")
125    exp='s/Django\([><=]\+\)\([^,]\+\),\([><=]\+\)\(.\+\)/'
126    # expand version parts to 2 digits to support 1.10.x > 1.8
127    # (note:helper functions hard to insert in-line)
128    exp=$exp'import sys,django;'
129    exp=$exp'version=["%02d" % int(n) for n in django.get_version().split(".")];'
130    exp=$exp'vmin=["%02d" % int(n) for n in "\2".split(".")];'
131    exp=$exp'vmax=["%02d" % int(n) for n in "\4".split(".")];'
132    exp=$exp'sys.exit(not (version \1 vmin and version \3 vmax))'
133    exp=$exp'/p'
134    if ! sed -n "$exp" $reqfile | python3 - ; then
135        req=`grep ^Django $reqfile`
136        echo "This program needs $req"
137        echo "Please install with pip3 install -r $reqfile"
138        return 2
139    fi
140
141    return 0
142}
143
144# read command line parameters
145if [ -n "$BASH_SOURCE" ] ; then
146    TOASTER=${BASH_SOURCE}
147elif [ -n "$ZSH_NAME" ] ; then
148    TOASTER=${(%):-%x}
149else
150    TOASTER=$0
151fi
152
153export BBBASEDIR=`dirname $TOASTER`/..
154MANAGE="python3 $BBBASEDIR/lib/toaster/manage.py"
155if [ -z "$OE_ROOT" ]; then
156    OE_ROOT=`dirname $TOASTER`/../..
157fi
158
159# this is the configuraton file we are using for toaster
160# we are using the same logic that oe-setup-builddir uses
161# (based on TEMPLATECONF and .templateconf) to determine
162# which toasterconf.json to use.
163# note: There are a number of relative path assumptions
164# in the local layers that currently make using an arbitrary
165# toasterconf.json difficult.
166
167. $OE_ROOT/.templateconf
168if [ -n "$TEMPLATECONF" ]; then
169    if [ ! -d "$TEMPLATECONF" ]; then
170        # Allow TEMPLATECONF=meta-xyz/conf as a shortcut
171        if [ -d "$OE_ROOT/$TEMPLATECONF" ]; then
172            TEMPLATECONF="$OE_ROOT/$TEMPLATECONF"
173        fi
174    fi
175fi
176
177unset OE_ROOT
178
179
180WEBSERVER=1
181export TOASTER_BUILDSERVER=1
182ADDR_PORT="localhost:8000"
183TOASTERDIR=`dirname $BUILDDIR`
184unset CMD
185for param in $*; do
186    case $param in
187    noweb )
188            WEBSERVER=0
189    ;;
190    nobuild )
191            TOASTER_BUILDSERVER=0
192    ;;
193    start )
194            CMD=$param
195    ;;
196    stop )
197            CMD=$param
198    ;;
199    webport=*)
200            ADDR_PORT="${param#*=}"
201            # Split the addr:port string
202            ADDR=`echo $ADDR_PORT | cut -f 1 -d ':'`
203            PORT=`echo $ADDR_PORT | cut -f 2 -d ':'`
204            # If only a port has been speified then set address to localhost.
205            if [ $ADDR = $PORT ] ; then
206                ADDR_PORT="localhost:$PORT"
207            fi
208    ;;
209    toasterdir=*)
210            TOASTERDIR="${param#*=}"
211    ;;
212    manage )
213            CMD=$param
214            manage_cmd=""
215    ;;
216    --help)
217            echo "$HELP"
218            return 0
219    ;;
220    *)
221            if [ "manage" == "$CMD" ] ; then
222                manage_cmd="$manage_cmd $param"
223            else
224                echo "$HELP"
225                exit 1
226            fi
227    ;;
228
229    esac
230done
231
232if [ `basename \"$0\"` = `basename \"${TOASTER}\"` ]; then
233    echo "Error: This script needs to be sourced. Please run as . $TOASTER"
234    return 1
235fi
236
237verify_prereq || return 1
238
239# We make sure we're running in the current shell and in a good environment
240if [ -z "$BUILDDIR" ] ||  ! which bitbake >/dev/null 2>&1 ; then
241    echo "Error: Build environment is not setup or bitbake is not in path." 1>&2
242    return 2
243fi
244
245# this defines the dir toaster will use for
246# 1) clones of layers (in _toaster_clones )
247# 2) the build dir (in build)
248# 3) the sqlite db if that is being used.
249# 4) pid's we need to clean up on exit/shutdown
250export TOASTER_DIR=$TOASTERDIR
251export BB_ENV_EXTRAWHITE="$BB_ENV_EXTRAWHITE TOASTER_DIR"
252
253# Determine the action. If specified by arguments, fine, if not, toggle it
254if [ "$CMD" = "start" ] ; then
255    if [ -n "$BBSERVER" ]; then
256	echo " Toaster is already running. Exiting..."
257	return 1
258fi
259elif [ "$CMD" = "" ]; then
260    echo "No command specified"
261    echo "$HELP"
262    return 1
263fi
264
265echo "The system will $CMD."
266
267# Execute the commands
268custom_extention toaster_prepend $CMD $ADDR_PORT
269
270case $CMD in
271    start )
272        # check if addr:port is not in use
273        if [ "$CMD" == 'start' ]; then
274            if [ $WEBSERVER -gt 0 ]; then
275                $MANAGE checksocket "$ADDR_PORT" || return 1
276            fi
277        fi
278
279        # Create configuration file
280        conf=${BUILDDIR}/conf/local.conf
281        line='INHERIT+="toaster buildhistory"'
282        grep -q "$line" $conf || echo $line >> $conf
283
284        if [ $WEBSERVER -eq 0 ] ; then
285            # Do not update the database for "noweb" unless
286            # it does not yet exist
287            if [ ! -f "$TOASTER_DIR/toaster.sqlite" ] ; then
288                if ! databaseCheck; then
289                    echo "Failed ${CMD}."
290                    return 4
291                fi
292            fi
293            custom_extention noweb_start_postpend $ADDR_PORT
294        fi
295        if [ $WEBSERVER -gt 0 ] && ! webserverStartAll; then
296            echo "Failed ${CMD}."
297            return 4
298        fi
299        export BITBAKE_UI='toasterui'
300        if [ $TOASTER_BUILDSERVER -eq 1 ] ; then
301            $MANAGE runbuilds \
302               </dev/null >>${BUILDDIR}/toaster_runbuilds.log 2>&1 \
303               & echo $! >${BUILDDIR}/.runbuilds.pid
304        else
305            echo "Toaster build server not started."
306        fi
307
308        # set fail safe stop system on terminal exit
309        trap stop_system SIGHUP
310        echo "Successful ${CMD}."
311        custom_extention toaster_postpend $CMD $ADDR_PORT
312        return 0
313    ;;
314    stop )
315        stop_system
316        echo "Successful ${CMD}."
317    ;;
318    manage )
319        cd $BBBASEDIR/lib/toaster
320        $MANAGE $manage_cmd
321    ;;
322esac
323custom_extention toaster_postpend $CMD $ADDR_PORT
324
325