diff --git a/bitbake/lib/bb/ui/buildinfohelper.py b/bitbake/lib/bb/ui/buildinfohelper.py
index a907a0337b..a3401ceda9 100644
--- a/bitbake/lib/bb/ui/buildinfohelper.py
+++ b/bitbake/lib/bb/ui/buildinfohelper.py
@@ -381,7 +381,7 @@ class ORMWrapper(object):
searchname = pkgpnmap[p]['OPKGN']
packagedict[p]['object'], created = Package.objects.get_or_create( build = build_obj, name = searchname )
- if created or package[p]['object'].size == -1: # save the data anyway we can, not just if it was not created here; bug [YOCTO #6887]
+ if created or packagedict[p]['object'].size == -1: # save the data anyway we can, not just if it was not created here; bug [YOCTO #6887]
# fill in everything we can from the runtime-reverse package data
try:
packagedict[p]['object'].recipe = recipes[pkgpnmap[p]['PN']]
@@ -462,7 +462,7 @@ class ORMWrapper(object):
if 'OPKGN' in package_info.keys():
pname = package_info['OPKGN']
- bp_object = Package.objects.create( build = build_obj,
+ bp_object, created = Package.objects.get_or_create( build = build_obj,
name = pname )
bp_object.installed_name = package_info['PKG']
@@ -1043,6 +1043,15 @@ class BuildInfoHelper(object):
mockevent.lineno = -1
self.store_log_event(mockevent)
+ def store_log_exception(self, text, backtrace = ""):
+ mockevent = MockEvent()
+ mockevent.levelno = -1
+ mockevent.msg = text
+ mockevent.pathname = backtrace
+ mockevent.lineno = -1
+ self.store_log_event(mockevent)
+
+
def store_log_event(self, event):
if event.levelno < format.WARNING:
return
@@ -1078,6 +1087,8 @@ class BuildInfoHelper(object):
log_information['level'] = LogMessage.ERROR
elif event.levelno == format.WARNING:
log_information['level'] = LogMessage.WARNING
+ elif event.levelno == -1: # toaster self-logging
+ log_information['level'] = -1
else:
log_information['level'] = LogMessage.INFO
diff --git a/bitbake/lib/bb/ui/toasterui.py b/bitbake/lib/bb/ui/toasterui.py
index b9e8029da1..9bd04df1c6 100644
--- a/bitbake/lib/bb/ui/toasterui.py
+++ b/bitbake/lib/bb/ui/toasterui.py
@@ -299,12 +299,13 @@ def main(server, eventHandler, params ):
logger.error(e)
import traceback
exception_data = traceback.format_exc()
+ print(exception_data)
# save them to database, if possible; if it fails, we already logged to console.
try:
- buildinfohelper.store_log_error("%s\n%s" % (str(e), exception_data))
- except Exception:
- pass
+ buildinfohelper.store_log_exception("%s\n%s" % (str(e), exception_data))
+ except Exception as ce:
+ print("CRITICAL: failed to to save toaster exception to the database: %s" % str(ce))
pass
diff --git a/bitbake/lib/toaster/bldcontrol/management/commands/checksettings.py b/bitbake/lib/toaster/bldcontrol/management/commands/checksettings.py
index cd604eba7e..96d2d51691 100644
--- a/bitbake/lib/toaster/bldcontrol/management/commands/checksettings.py
+++ b/bitbake/lib/toaster/bldcontrol/management/commands/checksettings.py
@@ -139,4 +139,12 @@ class Command(NoArgsCommand):
ToasterSetting.objects.filter(name = 'DEFAULT_RELEASE').delete()
ToasterSetting.objects.get_or_create(name = 'DEFAULT_RELEASE', value = '')
+ # we are just starting up. we must not have any builds in progress, or build environments taken
+ for b in BuildRequest.objects.filter(state = BuildRequest.REQ_INPROGRESS):
+ BRError.objects.create(req = b, errtype = "toaster", errmsg = "Toaster found this build IN PROGRESS while Toaster started up. This is an inconsistent state, and the build was marked as failed")
+
+ BuildRequest.objects.filter(state = BuildRequest.REQ_INPROGRESS).update(state = BuildRequest.REQ_FAILED)
+
+ BuildEnvironment.objects.update(lock = BuildEnvironment.LOCK_FREE)
+
return 0
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
index 364b215814..34d37542e1 100644
--- a/bitbake/lib/toaster/orm/models.py
+++ b/bitbake/lib/toaster/orm/models.py
@@ -178,6 +178,11 @@ class Build(models.Model):
tgts = Target.objects.filter(build_id = self.id).order_by( 'target' );
return( tgts );
+ @property
+ def toaster_exceptions(self):
+ return self.logmessage_set.filter(level=LogMessage.EXCEPTION)
+
+
class ProjectTarget(models.Model):
project = models.ForeignKey(Project)
target = models.CharField(max_length=100)
@@ -966,13 +971,15 @@ class HelpText(models.Model):
text = models.TextField()
class LogMessage(models.Model):
+ EXCEPTION = -1 # used to signal self-toaster-exceptions
INFO = 0
WARNING = 1
ERROR = 2
LOG_LEVEL = ( (INFO, "info"),
(WARNING, "warn"),
- (ERROR, "error") )
+ (ERROR, "error"),
+ (EXCEPTION, "toaster exception"))
build = models.ForeignKey(Build)
task = models.ForeignKey(Task, blank = True, null=True)
diff --git a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
index 4983ef6f6d..8e76ecb85a 100644
--- a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
+++ b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
@@ -252,6 +252,13 @@ $(document).ready(function() {
$('.toggle-warnings').click(function() {
$('#collapse-warnings').toggleClass('in');
});
+ $('.show-exceptions').click(function() {
+ $('#collapse-exceptions').addClass('in');
+ });
+ $('.toggle-exceptions').click(function() {
+ $('#collapse-exceptions').toggleClass('in');
+ });
+
//show warnings section when requested from the previous page
if (location.href.search('#warnings') > -1) {
$('#collapse-warnings').addClass('in');
diff --git a/bitbake/lib/toaster/toastergui/templates/base.html b/bitbake/lib/toaster/toastergui/templates/base.html
index f457b91dce..8170a3db88 100644
--- a/bitbake/lib/toaster/toastergui/templates/base.html
+++ b/bitbake/lib/toaster/toastergui/templates/base.html
@@ -8,7 +8,7 @@
-
+