summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandru DAMIAN <alexandru.damian@intel.com>2015-02-05 13:18:06 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-02-10 23:07:48 +0000
commitda8110a86ad8b57b8c41873d40aeac346ee66b88 (patch)
tree0c25d2757da8ed119316af0886ebb64818bdc8cd
parent0c89846dafa229b5af9653d6e141011c35451825 (diff)
downloadpoky-da8110a86ad8b57b8c41873d40aeac346ee66b88.tar.gz
bitbake: toaster: improve logging facilities for toaster
This patch improves the logging facilities for toaster in order to help diagnose bugs that happen on user machines. The logs are stored now under "/tmp/toaster_$$" where $$ is a PID-based unique identifier. On shutdown, toaster will automatically erase all logs unless errors are listed in the log file. On error, Toaster provides suggestions on what to do. This patch includes a minor fix found as a result of logging improvements. (Bitbake rev: 8a8248f7b7e30469f592e2f8adbf6ce21e8685c5) Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rwxr-xr-xbitbake/bin/toaster41
-rw-r--r--bitbake/lib/bb/ui/buildinfohelper.py47
-rw-r--r--bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py2
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py2
-rw-r--r--bitbake/lib/toaster/toastermain/settings.py6
-rw-r--r--bitbake/lib/toaster/toastermain/urls.py18
6 files changed, 91 insertions, 25 deletions
diff --git a/bitbake/bin/toaster b/bitbake/bin/toaster
index c3b8633c25..04f2e99378 100755
--- a/bitbake/bin/toaster
+++ b/bitbake/bin/toaster
@@ -69,7 +69,7 @@ function webserverStartAll()
69 fi 69 fi
70 if [ $retval -eq 0 ]; then 70 if [ $retval -eq 0 ]; then
71 echo "Starting webserver..." 71 echo "Starting webserver..."
72 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 72 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
73 sleep 1 73 sleep 1
74 if ! cat "${BUILDDIR}/.toastermain.pid" | xargs -I{} kill -0 {} ; then 74 if ! cat "${BUILDDIR}/.toastermain.pid" | xargs -I{} kill -0 {} ; then
75 retval=1 75 retval=1
@@ -189,17 +189,43 @@ if [ -z "$ZSH_NAME" ] && [ `basename \"$0\"` = `basename \"$BASH_SOURCE\"` ]; th
189 fi 189 fi
190 190
191 # Define a fake builddir where only the pid files are actually created. No real builds will take place here. 191 # Define a fake builddir where only the pid files are actually created. No real builds will take place here.
192 BUILDDIR=/tmp 192 BUILDDIR=/tmp/toaster_$$
193 if [ -d "$BUILDDIR" ]; then
194 echo -e "Previous toaster run directory $BUILDDIR found, cowardly refusing to start. Please remove the directory when that toaster instance is over" 2>&1
195 exit 1;
196 fi
197
198 mkdir -p "$BUILDDIR"
199
193 RUNNING=1 200 RUNNING=1
194 function trap_ctrlc() { 201 function trap_ctrlc() {
195 echo "** Stopping system" 202 echo "** Stopping system"
196 webserverKillAll 203 webserverKillAll
197 RUNNING=0 204 RUNNING=0
198 } 205 }
206
207 function do_cleanup() {
208 find "$BUILDDIR" -type f | xargs rm
209 rmdir "$BUILDDIR"
210 }
211 function cleanup() {
212 if grep -ir error "$BUILDDIR" >/dev/null; then
213 if grep -irn "That port is already in use" "$BUILDDIR"; then
214 echo "You can use the \"webport=PORTNUMBER\" parameter to start Toaster on a different port (port $WEB_PORT is already in use)"
215 do_cleanup
216 else
217 echo -e "\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"
218 fi
219 else
220 echo "No errors found, removing the run directory '$BUILDDIR'"
221 do_cleanup
222 fi;
223 }
199 TOASTER_MANAGED=1 224 TOASTER_MANAGED=1
200 export TOASTER_MANAGED=1 225 export TOASTER_MANAGED=1
201 if [ $WEBSERVER -gt 0 ] && ! webserverStartAll; then 226 if [ $WEBSERVER -gt 0 ] && ! webserverStartAll; then
202 echo "Failed to start the web server, stopping" 1>&2; 227 echo "Failed to start the web server, stopping" 1>&2;
228 cleanup
203 exit 1; 229 exit 1;
204 fi 230 fi
205 if [ $WEBSERVER -gt 0 ]; then 231 if [ $WEBSERVER -gt 0 ]; then
@@ -209,9 +235,10 @@ if [ -z "$ZSH_NAME" ] && [ `basename \"$0\"` = `basename \"$BASH_SOURCE\"` ]; th
209 trap trap_ctrlc SIGINT 235 trap trap_ctrlc SIGINT
210 echo "Toaster is now running. You can stop it with Ctrl-C" 236 echo "Toaster is now running. You can stop it with Ctrl-C"
211 while [ $RUNNING -gt 0 ]; do 237 while [ $RUNNING -gt 0 ]; do
212 python $BBBASEDIR/lib/toaster/manage.py runbuilds 238 python $BBBASEDIR/lib/toaster/manage.py runbuilds 2>&1 | tee -a "$BUILDDIR/toaster.log"
213 sleep 1 239 sleep 1
214 done 240 done
241 cleanup
215 echo "**** Exit" 242 echo "**** Exit"
216 exit 0 243 exit 0
217fi 244fi
@@ -275,8 +302,8 @@ case $CMD in
275 fi 302 fi
276 unset BBSERVER 303 unset BBSERVER
277 PREREAD="" 304 PREREAD=""
278 if [ -e conf/toaster-pre.conf ]; then 305 if [ -e ${BUILDDIR}/conf/toaster-pre.conf ]; then
279 PREREAD="--read conf/toaster-pre.conf" 306 rm ${BUILDDIR}/conf/toaster-pre.conf
280 fi 307 fi
281 bitbake $PREREAD --postread conf/toaster.conf --server-only -t xmlrpc -B 0.0.0.0:0 308 bitbake $PREREAD --postread conf/toaster.conf --server-only -t xmlrpc -B 0.0.0.0:0
282 if [ $? -ne 0 ]; then 309 if [ $? -ne 0 ]; then
@@ -285,7 +312,7 @@ case $CMD in
285 else 312 else
286 export BBSERVER=0.0.0.0:-1 313 export BBSERVER=0.0.0.0:-1
287 if [ $NOTOASTERUI == 0 ]; then # we start the TOASTERUI only if not inhibited 314 if [ $NOTOASTERUI == 0 ]; then # we start the TOASTERUI only if not inhibited
288 bitbake --observe-only -u toasterui >${BUILDDIR}/toaster_ui.log 2>&1 & echo $! >${BUILDDIR}/.toasterui.pid 315 bitbake --observe-only -u toasterui >>${BUILDDIR}/toaster_ui.log 2>&1 & echo $! >${BUILDDIR}/.toasterui.pid
289 fi 316 fi
290 fi 317 fi
291 if [ $start_success -eq 1 ]; then 318 if [ $start_success -eq 1 ]; then
diff --git a/bitbake/lib/bb/ui/buildinfohelper.py b/bitbake/lib/bb/ui/buildinfohelper.py
index 4e2d4a7dec..491fd1566d 100644
--- a/bitbake/lib/bb/ui/buildinfohelper.py
+++ b/bitbake/lib/bb/ui/buildinfohelper.py
@@ -656,18 +656,41 @@ class BuildInfoHelper(object):
656 assert path.startswith("/") 656 assert path.startswith("/")
657 assert 'build' in self.internal_state 657 assert 'build' in self.internal_state
658 658
659 def _slkey(layer_version): 659 if self.brbe is None:
660 assert isinstance(layer_version, Layer_Version) 660 def _slkey_interactive(layer_version):
661 return len(layer_version.layer.local_path) 661 assert isinstance(layer_version, Layer_Version)
662 662 return len(layer_version.layer.local_path)
663 # Heuristics: we always match recipe to the deepest layer path that 663
664 # we can match to the recipe file path 664 # Heuristics: we always match recipe to the deepest layer path in the discovered layers
665 for bl in sorted(self.orm_wrapper.layer_version_objects, reverse=True, key=_slkey): 665 for lvo in sorted(self.orm_wrapper.layer_version_objects, reverse=True, key=_slkey_interactive):
666 if (path.startswith(bl.layer.local_path)): 666 # we can match to the recipe file path
667 return bl 667 if path.startswith(lvo.layer.local_path):
668 668 return lvo
669 #if we get here, we didn't read layers correctly; mockup the new layer 669
670 unknown_layer, created = Layer.objects.get_or_create(name="unknown", local_path="/", layer_index_url="") 670 else:
671 br_id, be_id = self.brbe.split(":")
672 from bldcontrol.bbcontroller import getBuildEnvironmentController
673 from bldcontrol.models import BuildRequest
674 bc = getBuildEnvironmentController(pk = be_id)
675
676 def _slkey_managed(layer_version):
677 return len(bc.getGitCloneDirectory(layer_version.giturl, layer_version.commit) + layer_version.dirpath)
678
679 # Heuristics: we match the path to where the layers have been checked out
680 for brl in sorted(BuildRequest.objects.get(pk = br_id).brlayer_set.all(), reverse = True, key = _slkey_managed):
681 localdirname = os.path.join(os.path.join(bc.be.sourcedir, bc.getGitCloneDirectory(brl.giturl, brl.commit)), brl.dirpath)
682 if path.startswith(localdirname):
683 #logger.warn("-- managed: matched path %s with layer %s " % (path, localdirname))
684 # we matched the BRLayer, but we need the layer_version that generated this br
685 for lvo in self.orm_wrapper.layer_version_objects:
686 if brl.name == lvo.layer.name:
687 return lvo
688
689 #if we get here, we didn't read layers correctly; dump whatever information we have on the error log
690 logger.error("Could not match layer version for recipe path %s : %s" % (path, self.orm_wrapper.layer_version_objects))
691
692 #mockup the new layer
693 unknown_layer, created = Layer.objects.get_or_create(name="__FIXME__unidentified_layer", local_path="/", layer_index_url="")
671 unknown_layer_version_obj, created = Layer_Version.objects.get_or_create(layer = unknown_layer, build = self.internal_state['build']) 694 unknown_layer_version_obj, created = Layer_Version.objects.get_or_create(layer = unknown_layer, build = self.internal_state['build'])
672 695
673 return unknown_layer_version_obj 696 return unknown_layer_version_obj
diff --git a/bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py b/bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py
index 3b539b591a..c4ab87bdc9 100644
--- a/bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py
+++ b/bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py
@@ -68,7 +68,7 @@ class Command(NoArgsCommand):
68 task = None 68 task = None
69 bbctrl.build(list(map(lambda x:x.target, br.brtarget_set.all())), task) 69 bbctrl.build(list(map(lambda x:x.target, br.brtarget_set.all())), task)
70 70
71 logger.debug("runbuilds: Build launched, exiting") 71 logger.debug("runbuilds: Build launched, exiting. Follow build logs at %s/toaster_ui.log" % bec.be.builddir)
72 # disconnect from the server 72 # disconnect from the server
73 bbctrl.disconnect() 73 bbctrl.disconnect()
74 74
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index 7353844bf1..b67a6767b3 100755
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -3248,7 +3248,7 @@ else:
3248 def xhr_build(request, pid): 3248 def xhr_build(request, pid):
3249 raise Exception("page not available in interactive mode") 3249 raise Exception("page not available in interactive mode")
3250 3250
3251 def xhr_projectinfo(request, pid): 3251 def xhr_projectinfo(request):
3252 raise Exception("page not available in interactive mode") 3252 raise Exception("page not available in interactive mode")
3253 3253
3254 def xhr_projectedit(request, pid): 3254 def xhr_projectedit(request, pid):
diff --git a/bitbake/lib/toaster/toastermain/settings.py b/bitbake/lib/toaster/toastermain/settings.py
index 7cf905266d..ea7c3534da 100644
--- a/bitbake/lib/toaster/toastermain/settings.py
+++ b/bitbake/lib/toaster/toastermain/settings.py
@@ -344,7 +344,7 @@ LOGGING = {
344 }, 344 },
345 'formatters': { 345 'formatters': {
346 'datetime': { 346 'datetime': {
347 'format': '%(levelname)s %(asctime)s %(message)s' 347 'format': '%(asctime)s %(levelname)s %(message)s'
348 } 348 }
349 }, 349 },
350 'handlers': { 350 'handlers': {
@@ -365,8 +365,8 @@ LOGGING = {
365 'level': 'DEBUG', 365 'level': 'DEBUG',
366 }, 366 },
367 'django.request': { 367 'django.request': {
368 'handlers': ['mail_admins'], 368 'handlers': ['console'],
369 'level': 'ERROR', 369 'level': 'WARN',
370 'propagate': True, 370 'propagate': True,
371 }, 371 },
372 } 372 }
diff --git a/bitbake/lib/toaster/toastermain/urls.py b/bitbake/lib/toaster/toastermain/urls.py
index 6112067579..f66f11dcde 100644
--- a/bitbake/lib/toaster/toastermain/urls.py
+++ b/bitbake/lib/toaster/toastermain/urls.py
@@ -23,6 +23,9 @@ from django.conf.urls import patterns, include, url
23from django.views.generic import RedirectView 23from django.views.generic import RedirectView
24from django.views.decorators.cache import never_cache 24from django.views.decorators.cache import never_cache
25 25
26import logging
27
28logger = logging.getLogger("toaster")
26 29
27# Uncomment the next two lines to enable the admin: 30# Uncomment the next two lines to enable the admin:
28from django.contrib import admin 31from django.contrib import admin
@@ -47,10 +50,12 @@ import toastermain.settings
47 50
48if toastermain.settings.FRESH_ENABLED: 51if toastermain.settings.FRESH_ENABLED:
49 urlpatterns.insert(1, url(r'', include('fresh.urls'))) 52 urlpatterns.insert(1, url(r'', include('fresh.urls')))
53 logger.info("Enabled django-fresh extension")
50 54
51if toastermain.settings.DEBUG_PANEL_ENABLED: 55if toastermain.settings.DEBUG_PANEL_ENABLED:
52 import debug_toolbar 56 import debug_toolbar
53 urlpatterns.insert(1, url(r'', include(debug_toolbar.urls))) 57 urlpatterns.insert(1, url(r'', include(debug_toolbar.urls)))
58 logger.info("Enabled django_toolbar extension")
54 59
55 60
56if toastermain.settings.MANAGED: 61if toastermain.settings.MANAGED:
@@ -70,4 +75,15 @@ for t in os.walk(os.path.dirname(currentdir)):
70 75
71 if "urls.py" in t[2] and t[0] != currentdir: 76 if "urls.py" in t[2] and t[0] != currentdir:
72 modulename = os.path.basename(t[0]) 77 modulename = os.path.basename(t[0])
73 urlpatterns.insert(0, url(r'^' + modulename + '/', include ( modulename + '.urls'))) 78 # make sure we don't have this module name in
79 conflict = False
80 for p in urlpatterns:
81 if p.regex.pattern == '^' + modulename + '/':
82 conflict = True
83 if not conflict:
84 urlpatterns.insert(0, url(r'^' + modulename + '/', include ( modulename + '.urls')))
85 else:
86 logger.warn("Module \'%s\' has a regexp conflict, was not added to the urlpatterns" % modulename)
87
88from pprint import pformat
89logger.debug("urlpatterns list %s", pformat(urlpatterns))