summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorAlexandru DAMIAN <alexandru.damian@intel.com>2014-12-05 15:14:20 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2014-12-18 10:24:06 +0000
commitf99f2cdd69f1015953a7e9ab07af46dd63e50ad4 (patch)
treef7f13e4ef5e92f6158d405887da187ad07b5f7ec /bitbake
parentc467bbd841d6ef2caae7fb2693456c50584d23ec (diff)
downloadpoky-f99f2cdd69f1015953a7e9ab07af46dd63e50ad4.tar.gz
bitbake: add build artifacts table and other improvements
We add a BuildArtifacts class to store data about files discovered during the build process and not stored anywhere else. Small cosmetic changes in the toasterui. Add model methods to return file path display data relative to the build environment instead of absolute file paths. [YOCTO #6834] (Bitbake rev: bbe24d912869312d561be199b2c029b0c898e049) Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/bb/ui/buildinfohelper.py26
-rw-r--r--bitbake/lib/bb/ui/toasterui.py4
-rw-r--r--bitbake/lib/toaster/bldcontrol/models.py10
-rw-r--r--bitbake/lib/toaster/orm/migrations/0019_auto__add_buildartifact.py342
-rw-r--r--bitbake/lib/toaster/orm/models.py29
5 files changed, 404 insertions, 7 deletions
diff --git a/bitbake/lib/bb/ui/buildinfohelper.py b/bitbake/lib/bb/ui/buildinfohelper.py
index 9aa8fe319f..6f4f56870a 100644
--- a/bitbake/lib/bb/ui/buildinfohelper.py
+++ b/bitbake/lib/bb/ui/buildinfohelper.py
@@ -26,7 +26,7 @@ os.environ["DJANGO_SETTINGS_MODULE"] = "toaster.toastermain.settings"
26 26
27import toaster.toastermain.settings as toaster_django_settings 27import toaster.toastermain.settings as toaster_django_settings
28from toaster.orm.models import Build, Task, Recipe, Layer_Version, Layer, Target, LogMessage, HelpText 28from toaster.orm.models import Build, Task, Recipe, Layer_Version, Layer, Target, LogMessage, HelpText
29from toaster.orm.models import Target_Image_File 29from toaster.orm.models import Target_Image_File, BuildArtifact
30from toaster.orm.models import Variable, VariableHistory 30from toaster.orm.models import Variable, VariableHistory
31from toaster.orm.models import Package, Package_File, Target_Installed_Package, Target_File 31from toaster.orm.models import Package, Package_File, Target_Installed_Package, Target_File
32from toaster.orm.models import Task_Dependency, Package_Dependency 32from toaster.orm.models import Task_Dependency, Package_Dependency
@@ -156,8 +156,7 @@ class ORMWrapper(object):
156 build.outcome = outcome 156 build.outcome = outcome
157 build.save() 157 build.save()
158 158
159 def update_target_object(self, target, license_manifest_path): 159 def update_target_set_license_manifest(self, target, license_manifest_path):
160
161 target.license_manifest_path = license_manifest_path 160 target.license_manifest_path = license_manifest_path
162 target.save() 161 target.save()
163 162
@@ -447,7 +446,17 @@ class ORMWrapper(object):
447 target_image_file = Target_Image_File.objects.create( target = target_obj, 446 target_image_file = Target_Image_File.objects.create( target = target_obj,
448 file_name = file_name, 447 file_name = file_name,
449 file_size = file_size) 448 file_size = file_size)
450 target_image_file.save() 449
450 def save_artifact_information(self, build_obj, file_name, file_size):
451 # we skip the image files from other builds
452 if Target_Image_File.objects.filter(file_name = file_name).count() > 0:
453 return
454
455 # do not update artifacts found in other builds
456 if BuildArtifact.objects.filter(file_name = file_name).count() > 0:
457 return
458
459 BuildArtifact.objects.create(build = build_obj, file_name = file_name, file_size = file_size)
451 460
452 def create_logmessage(self, log_information): 461 def create_logmessage(self, log_information):
453 assert 'build' in log_information 462 assert 'build' in log_information
@@ -752,6 +761,11 @@ class BuildInfoHelper(object):
752 if t.target in output and output.split('.rootfs.')[1] in image_fstypes: 761 if t.target in output and output.split('.rootfs.')[1] in image_fstypes:
753 self.orm_wrapper.save_target_image_file_information(t, output, evdata[output]) 762 self.orm_wrapper.save_target_image_file_information(t, output, evdata[output])
754 763
764 def update_artifact_image_file(self, event):
765 evdata = BuildInfoHelper._get_data_from_event(event)
766 for artifact_path in evdata.keys():
767 self.orm_wrapper.save_artifact_information(self.internal_state['build'], artifact_path, evdata[artifact_path])
768
755 def update_build_information(self, event, errors, warnings, taskfailures): 769 def update_build_information(self, event, errors, warnings, taskfailures):
756 if 'build' in self.internal_state: 770 if 'build' in self.internal_state:
757 self.orm_wrapper.update_build_object(self.internal_state['build'], errors, warnings, taskfailures) 771 self.orm_wrapper.update_build_object(self.internal_state['build'], errors, warnings, taskfailures)
@@ -760,10 +774,10 @@ class BuildInfoHelper(object):
760 def store_license_manifest_path(self, event): 774 def store_license_manifest_path(self, event):
761 deploy_dir = BuildInfoHelper._get_data_from_event(event)['deploy_dir'] 775 deploy_dir = BuildInfoHelper._get_data_from_event(event)['deploy_dir']
762 image_name = BuildInfoHelper._get_data_from_event(event)['image_name'] 776 image_name = BuildInfoHelper._get_data_from_event(event)['image_name']
763 path = deploy_dir + "/licenses/" + image_name + "/" 777 path = deploy_dir + "/licenses/" + image_name + "/license.manifest"
764 for target in self.internal_state['targets']: 778 for target in self.internal_state['targets']:
765 if target.target in image_name: 779 if target.target in image_name:
766 self.orm_wrapper.update_target_object(target, path) 780 self.orm_wrapper.update_target_set_license_manifest(target, path)
767 781
768 782
769 def store_started_task(self, event): 783 def store_started_task(self, event):
diff --git a/bitbake/lib/bb/ui/toasterui.py b/bitbake/lib/bb/ui/toasterui.py
index 3a6104bcab..9aff489c1d 100644
--- a/bitbake/lib/bb/ui/toasterui.py
+++ b/bitbake/lib/bb/ui/toasterui.py
@@ -261,8 +261,12 @@ def main(server, eventHandler, params ):
261 buildinfohelper.store_missed_state_tasks(event) 261 buildinfohelper.store_missed_state_tasks(event)
262 elif event.type == "ImageFileSize": 262 elif event.type == "ImageFileSize":
263 buildinfohelper.update_target_image_file(event) 263 buildinfohelper.update_target_image_file(event)
264 elif event.type == "ArtifactFileSize":
265 buildinfohelper.update_artifact_image_file(event)
264 elif event.type == "LicenseManifestPath": 266 elif event.type == "LicenseManifestPath":
265 buildinfohelper.store_license_manifest_path(event) 267 buildinfohelper.store_license_manifest_path(event)
268 else:
269 logger.error("Unprocessed MetadataEvent %s " % str(event))
266 continue 270 continue
267 271
268 if isinstance(event, bb.cooker.CookerExit): 272 if isinstance(event, bb.cooker.CookerExit):
diff --git a/bitbake/lib/toaster/bldcontrol/models.py b/bitbake/lib/toaster/bldcontrol/models.py
index e643d08603..cab4463647 100644
--- a/bitbake/lib/toaster/bldcontrol/models.py
+++ b/bitbake/lib/toaster/bldcontrol/models.py
@@ -70,11 +70,19 @@ class BuildEnvironment(models.Model):
70 return "binary/octet-stream" 70 return "binary/octet-stream"
71 except ImportError: 71 except ImportError:
72 return "binary/octet-stream" 72 return "binary/octet-stream"
73 raise Exception("FIXME: artifact type not implemented for build environment type %s" % be.get_betype_display())
74
73 75
74 def get_artifact(self, path): 76 def get_artifact(self, path):
75 if self.betype == BuildEnvironment.TYPE_LOCAL: 77 if self.betype == BuildEnvironment.TYPE_LOCAL:
76 return open(path, "r") 78 return open(path, "r")
77 raise Exception("FIXME: not implemented") 79 raise Exception("FIXME: artifact download not implemented for build environment type %s" % be.get_betype_display())
80
81 def has_artifact(self, path):
82 import os
83 if self.betype == BuildRequest.TYPE_LOCAL:
84 return os.path.exists(path)
85 raise Exception("FIXME: has artifact not implemented for build environment type %s" % be.get_betype_display())
78 86
79# a BuildRequest is a request that the scheduler will build using a BuildEnvironment 87# a BuildRequest is a request that the scheduler will build using a BuildEnvironment
80# the build request queue is the table itself, ordered by state 88# the build request queue is the table itself, ordered by state
diff --git a/bitbake/lib/toaster/orm/migrations/0019_auto__add_buildartifact.py b/bitbake/lib/toaster/orm/migrations/0019_auto__add_buildartifact.py
new file mode 100644
index 0000000000..0dce9ead20
--- /dev/null
+++ b/bitbake/lib/toaster/orm/migrations/0019_auto__add_buildartifact.py
@@ -0,0 +1,342 @@
1# -*- coding: utf-8 -*-
2from south.utils import datetime_utils as datetime
3from south.db import db
4from south.v2 import SchemaMigration
5from django.db import models
6
7
8class Migration(SchemaMigration):
9
10 def forwards(self, orm):
11 # Adding model 'BuildArtifact'
12 db.create_table(u'orm_buildartifact', (
13 (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
14 ('build', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Build'])),
15 ('file_name', self.gf('django.db.models.fields.FilePathField')(max_length=100)),
16 ('file_size', self.gf('django.db.models.fields.IntegerField')()),
17 ))
18 db.send_create_signal(u'orm', ['BuildArtifact'])
19
20
21 def backwards(self, orm):
22 # Deleting model 'BuildArtifact'
23 db.delete_table(u'orm_buildartifact')
24
25
26 models = {
27 u'orm.bitbakeversion': {
28 'Meta': {'object_name': 'BitbakeVersion'},
29 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
30 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
31 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
32 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
33 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
34 },
35 u'orm.branch': {
36 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
37 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
38 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
39 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
40 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
41 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
42 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
43 },
44 u'orm.build': {
45 'Meta': {'object_name': 'Build'},
46 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
47 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
48 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
49 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
50 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
51 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
52 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
53 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
54 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
55 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
56 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
57 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
58 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
59 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
60 },
61 u'orm.buildartifact': {
62 'Meta': {'object_name': 'BuildArtifact'},
63 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
64 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
65 'file_size': ('django.db.models.fields.IntegerField', [], {}),
66 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
67 },
68 u'orm.helptext': {
69 'Meta': {'object_name': 'HelpText'},
70 'area': ('django.db.models.fields.IntegerField', [], {}),
71 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
72 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
73 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
74 'text': ('django.db.models.fields.TextField', [], {})
75 },
76 u'orm.layer': {
77 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
78 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
79 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
80 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
81 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
82 'local_path': ('django.db.models.fields.FilePathField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
83 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
84 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
85 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
86 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
87 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
88 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
89 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
90 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
91 },
92 u'orm.layer_version': {
93 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
94 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
95 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
96 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
97 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
98 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
99 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
100 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
101 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
102 'project': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Project']", 'null': 'True'}),
103 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
104 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
105 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
106 },
107 u'orm.layersource': {
108 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
109 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
110 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
111 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '63'}),
112 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
113 },
114 u'orm.layerversiondependency': {
115 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
116 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
117 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
118 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
119 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
120 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
121 },
122 u'orm.logmessage': {
123 'Meta': {'object_name': 'LogMessage'},
124 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
125 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
126 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
127 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
128 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
129 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
130 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
131 },
132 u'orm.machine': {
133 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
134 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
135 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
136 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
137 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
138 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
139 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
140 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
141 },
142 u'orm.package': {
143 'Meta': {'object_name': 'Package'},
144 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
145 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
146 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
147 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
148 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
149 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
150 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
151 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
152 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
153 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
154 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
155 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
156 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
157 },
158 u'orm.package_dependency': {
159 'Meta': {'object_name': 'Package_Dependency'},
160 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
161 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
162 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
163 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
164 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
165 },
166 u'orm.package_file': {
167 'Meta': {'object_name': 'Package_File'},
168 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
169 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
170 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
171 'size': ('django.db.models.fields.IntegerField', [], {})
172 },
173 u'orm.project': {
174 'Meta': {'object_name': 'Project'},
175 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
176 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
177 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
178 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
179 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"}),
180 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
181 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
182 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
183 },
184 u'orm.projectlayer': {
185 'Meta': {'unique_together': "(('project', 'layercommit'),)", 'object_name': 'ProjectLayer'},
186 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
187 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
188 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
189 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
190 },
191 u'orm.projecttarget': {
192 'Meta': {'object_name': 'ProjectTarget'},
193 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
194 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
195 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
196 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
197 },
198 u'orm.projectvariable': {
199 'Meta': {'object_name': 'ProjectVariable'},
200 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
201 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
202 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
203 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
204 },
205 u'orm.recipe': {
206 'Meta': {'unique_together': "(('layer_version', 'file_path'),)", 'object_name': 'Recipe'},
207 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
208 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
209 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
210 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
211 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
212 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
213 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
214 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
215 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
216 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
217 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
218 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
219 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
220 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
221 },
222 u'orm.recipe_dependency': {
223 'Meta': {'object_name': 'Recipe_Dependency'},
224 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
225 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
226 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
227 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
228 },
229 u'orm.release': {
230 'Meta': {'object_name': 'Release'},
231 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
232 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
233 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
234 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
235 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
236 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
237 },
238 u'orm.releasedefaultlayer': {
239 'Meta': {'object_name': 'ReleaseDefaultLayer'},
240 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
241 'layer_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
242 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
243 },
244 u'orm.releaselayersourcepriority': {
245 'Meta': {'unique_together': "(('release', 'layer_source'),)", 'object_name': 'ReleaseLayerSourcePriority'},
246 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
247 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.LayerSource']"}),
248 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
249 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
250 },
251 u'orm.target': {
252 'Meta': {'object_name': 'Target'},
253 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
254 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
255 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
256 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
257 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
258 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
259 },
260 u'orm.target_file': {
261 'Meta': {'object_name': 'Target_File'},
262 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
263 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
264 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
265 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
266 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
267 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
268 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
269 'size': ('django.db.models.fields.IntegerField', [], {}),
270 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
271 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
272 },
273 u'orm.target_image_file': {
274 'Meta': {'object_name': 'Target_Image_File'},
275 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
276 'file_size': ('django.db.models.fields.IntegerField', [], {}),
277 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
278 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
279 },
280 u'orm.target_installed_package': {
281 'Meta': {'object_name': 'Target_Installed_Package'},
282 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
283 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
284 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
285 },
286 u'orm.task': {
287 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
288 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
289 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
290 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
291 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
292 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
293 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
294 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
295 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
296 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
297 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
298 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
299 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
300 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
301 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
302 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
303 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
304 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
305 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
306 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
307 },
308 u'orm.task_dependency': {
309 'Meta': {'object_name': 'Task_Dependency'},
310 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
311 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
312 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
313 },
314 u'orm.toastersetting': {
315 'Meta': {'object_name': 'ToasterSetting'},
316 'helptext': ('django.db.models.fields.TextField', [], {}),
317 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
318 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
319 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
320 },
321 u'orm.variable': {
322 'Meta': {'object_name': 'Variable'},
323 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
324 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
325 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
326 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
327 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
328 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
329 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
330 },
331 u'orm.variablehistory': {
332 'Meta': {'object_name': 'VariableHistory'},
333 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
334 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
335 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
336 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
337 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
338 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
339 }
340 }
341
342 complete_apps = ['orm'] \ No newline at end of file
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
index 34d37542e1..f5c600ba9f 100644
--- a/bitbake/lib/toaster/orm/models.py
+++ b/bitbake/lib/toaster/orm/models.py
@@ -25,6 +25,7 @@ from django.utils import timezone
25 25
26 26
27from django.core import validators 27from django.core import validators
28from django.conf import settings
28 29
29class GitURLValidator(validators.URLValidator): 30class GitURLValidator(validators.URLValidator):
30 import re 31 import re
@@ -183,6 +184,28 @@ class Build(models.Model):
183 return self.logmessage_set.filter(level=LogMessage.EXCEPTION) 184 return self.logmessage_set.filter(level=LogMessage.EXCEPTION)
184 185
185 186
187# an Artifact is anything that results from a Build, and may be of interest to the user, and is not stored elsewhere
188class BuildArtifact(models.Model):
189 build = models.ForeignKey(Build)
190 file_name = models.FilePathField()
191 file_size = models.IntegerField()
192
193
194 def get_local_file_name(self):
195 try:
196 deploydir = Variable.objects.get(build = self.build, variable_name="DEPLOY_DIR").variable_value
197 return self.file_name[len(deploydir)+1:]
198 except:
199 raise
200
201 return self.file_name
202
203
204 def is_available(self):
205 if settings.MANAGED and build.project is not None:
206 return build.buildrequest.environment.has_artifact(file_path)
207 return False
208
186class ProjectTarget(models.Model): 209class ProjectTarget(models.Model):
187 project = models.ForeignKey(Project) 210 project = models.ForeignKey(Project)
188 target = models.CharField(max_length=100) 211 target = models.CharField(max_length=100)
@@ -457,6 +480,12 @@ class Recipe(models.Model):
457 def __unicode__(self): 480 def __unicode__(self):
458 return "Recipe " + self.name + ":" + self.version 481 return "Recipe " + self.name + ":" + self.version
459 482
483 def get_local_path(self):
484 if settings.MANAGED and self.layer_version.build.project is not None:
485 return self.file_path[len(self.layer_version.layer.local_path)+1:]
486
487 return self.file_path
488
460 class Meta: 489 class Meta:
461 unique_together = ("layer_version", "file_path") 490 unique_together = ("layer_version", "file_path")
462 491