1
0
mirror of https://git.yoctoproject.org/poky synced 2026-06-01 00:59:48 +00:00

bitbake: toaster: bitbake cooker log saving and downloading

This patch brings in cooker log saving and proper download links.

* toasterui will now write the cooker log file if running in managed
mode
* the BuildRequest has a new state, REQ_ARCHIVE, indicating that the
build is completed, and the artifacts are ready to be grabbed
* the runbuild test execution commands will gather needed artifacts,
and save them to a storage directory selected during Toaster setup.
* the build dashboard, project builds and all builds pages have
permanent links for the cooker log

[YOCTO #7220]
[YOCTO #7206]

(Bitbake rev: fad80e36c9da663b000cdf2cb3c75440c6431d84)

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Alexandru DAMIAN
2015-02-16 17:47:07 +00:00
committed by Richard Purdie
parent a574f293fe
commit c368d83bd6
13 changed files with 335 additions and 43 deletions
@@ -62,6 +62,23 @@ class Command(NoArgsCommand):
def handle(self, **options):
# verify that we have a settings for downloading artifacts
while ToasterSetting.objects.filter(name="ARTIFACTS_STORAGE_DIR").count() == 0:
guessedpath = os.getcwd() + "/toaster_build_artifacts/"
print("Toaster needs to know in which directory it can download build log files and other artifacts.\n Toaster suggests \"%s\"." % guessedpath)
artifacts_storage_dir = raw_input(" Press Enter to select \"%s\" or type the full path to a different directory: " % guessedpath)
if len(artifacts_storage_dir) == 0:
artifacts_storage_dir = guessedpath
if len(artifacts_storage_dir) > 0 and artifacts_storage_dir.startswith("/"):
try:
os.makedirs(artifacts_storage_dir)
except OSError as ose:
if "File exists" in str(ose):
pass
else:
raise ose
ToasterSetting.objects.create(name="ARTIFACTS_STORAGE_DIR", value=artifacts_storage_dir)
self.guesspath = DN(DN(DN(DN(DN(DN(DN(__file__)))))))
# refuse to start if we have no build environments
while BuildEnvironment.objects.count() == 0:
@@ -1,6 +1,6 @@
from django.core.management.base import NoArgsCommand, CommandError
from django.db import transaction
from orm.models import Build
from orm.models import Build, ToasterSetting
from bldcontrol.bbcontroller import getBuildEnvironmentController, ShellCmdException, BuildSetupException
from bldcontrol.models import BuildRequest, BuildEnvironment, BRError, BRVariable
import os
@@ -93,7 +93,33 @@ class Command(NoArgsCommand):
bec.be.lock = BuildEnvironment.LOCK_FREE
bec.be.save()
def archive(self):
''' archives data from the builds '''
artifact_storage_dir = ToasterSetting.objects.get(name="ARTIFACTS_STORAGE_DIR").value
for br in BuildRequest.objects.filter(state = BuildRequest.REQ_ARCHIVE):
# save cooker log
if br.build == None:
br.state = BuildRequest.REQ_FAILED
br.save()
continue
build_artifact_storage_dir = os.path.join(artifact_storage_dir, "%d" % br.build.pk)
try:
os.makedirs(build_artifact_storage_dir)
except OSError as ose:
if "File exists" in str(ose):
pass
else:
raise ose
file_name = os.path.join(build_artifact_storage_dir, "cooker_log.txt")
try:
with open(file_name, "w") as f:
f.write(br.environment.get_artifact(br.build.cooker_log_path).read())
except IOError:
os.unlink(file_name)
br.state = BuildRequest.REQ_COMPLETED
br.save()
def cleanup(self):
from django.utils import timezone
@@ -104,4 +130,5 @@ class Command(NoArgsCommand):
def handle_noargs(self, **options):
self.cleanup()
self.archive()
self.schedule()
@@ -0,0 +1,138 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
class Migration(DataMigration):
# ids that cannot be imported from BuildRequest
def forwards(self, orm):
REQ_COMPLETED = 3
REQ_ARCHIVE = 6
"Write your forwards methods here."
# Note: Don't use "from appname.models import ModelName".
# Use orm.ModelName to refer to models in this application,
# and orm['appname.ModelName'] for models in other applications.
orm.BuildRequest.objects.filter(state=REQ_COMPLETED).update(state=REQ_ARCHIVE)
def backwards(self, orm):
REQ_COMPLETED = 3
REQ_ARCHIVE = 6
"Write your backwards methods here."
orm.BuildRequest.objects.filter(state=REQ_ARCHIVE).update(state=REQ_COMPLETED)
models = {
u'bldcontrol.brbitbake': {
'Meta': {'object_name': 'BRBitbake'},
'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']", 'unique': 'True'})
},
u'bldcontrol.brerror': {
'Meta': {'object_name': 'BRError'},
'errmsg': ('django.db.models.fields.TextField', [], {}),
'errtype': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
'traceback': ('django.db.models.fields.TextField', [], {})
},
u'bldcontrol.brlayer': {
'Meta': {'object_name': 'BRLayer'},
'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"})
},
u'bldcontrol.brtarget': {
'Meta': {'object_name': 'BRTarget'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
},
u'bldcontrol.brvariable': {
'Meta': {'object_name': 'BRVariable'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
u'bldcontrol.buildenvironment': {
'Meta': {'object_name': 'BuildEnvironment'},
'address': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
'bbaddress': ('django.db.models.fields.CharField', [], {'max_length': '254', 'blank': 'True'}),
'bbport': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
'bbstate': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'bbtoken': ('django.db.models.fields.CharField', [], {'max_length': '126', 'blank': 'True'}),
'betype': ('django.db.models.fields.IntegerField', [], {}),
'builddir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'lock': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'sourcedir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
u'bldcontrol.buildrequest': {
'Meta': {'object_name': 'BuildRequest'},
'build': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['orm.Build']", 'unique': 'True', 'null': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'environment': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildEnvironment']", 'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
'state': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
u'orm.bitbakeversion': {
'Meta': {'object_name': 'BitbakeVersion'},
'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
},
u'orm.build': {
'Meta': {'object_name': 'Build'},
'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
'started_on': ('django.db.models.fields.DateTimeField', [], {}),
'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
u'orm.project': {
'Meta': {'object_name': 'Project'},
'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"}),
'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
},
u'orm.release': {
'Meta': {'object_name': 'Release'},
'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
}
}
complete_apps = ['bldcontrol']
symmetrical = True
+2
View File
@@ -94,6 +94,7 @@ class BuildRequest(models.Model):
REQ_COMPLETED = 3
REQ_FAILED = 4
REQ_DELETED = 5
REQ_ARCHIVE = 6
REQUEST_STATE = (
(REQ_CREATED, "created"),
@@ -102,6 +103,7 @@ class BuildRequest(models.Model):
(REQ_COMPLETED, "completed"),
(REQ_FAILED, "failed"),
(REQ_DELETED, "deleted"),
(REQ_ARCHIVE, "archive"),
)
search_allowed_fields = ("brtarget__target",)