diff options
author | Alexandru DAMIAN <alexandru.damian@intel.com> | 2015-02-05 13:18:06 +0000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-02-10 23:07:48 +0000 |
commit | da8110a86ad8b57b8c41873d40aeac346ee66b88 (patch) | |
tree | 0c25d2757da8ed119316af0886ebb64818bdc8cd /bitbake | |
parent | 0c89846dafa229b5af9653d6e141011c35451825 (diff) | |
download | poky-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>
Diffstat (limited to 'bitbake')
-rwxr-xr-x | bitbake/bin/toaster | 41 | ||||
-rw-r--r-- | bitbake/lib/bb/ui/buildinfohelper.py | 47 | ||||
-rw-r--r-- | bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py | 2 | ||||
-rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 2 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastermain/settings.py | 6 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastermain/urls.py | 18 |
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 |
217 | fi | 244 | fi |
@@ -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 | |||
23 | from django.views.generic import RedirectView | 23 | from django.views.generic import RedirectView |
24 | from django.views.decorators.cache import never_cache | 24 | from django.views.decorators.cache import never_cache |
25 | 25 | ||
26 | import logging | ||
27 | |||
28 | logger = 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: |
28 | from django.contrib import admin | 31 | from django.contrib import admin |
@@ -47,10 +50,12 @@ import toastermain.settings | |||
47 | 50 | ||
48 | if toastermain.settings.FRESH_ENABLED: | 51 | if 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 | ||
51 | if toastermain.settings.DEBUG_PANEL_ENABLED: | 55 | if 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 | ||
56 | if toastermain.settings.MANAGED: | 61 | if 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 | |||
88 | from pprint import pformat | ||
89 | logger.debug("urlpatterns list %s", pformat(urlpatterns)) | ||