summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/orm/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/toaster/orm/models.py')
-rw-r--r--bitbake/lib/toaster/orm/models.py369
1 files changed, 369 insertions, 0 deletions
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
new file mode 100644
index 0000000000..c344c66bee
--- /dev/null
+++ b/bitbake/lib/toaster/orm/models.py
@@ -0,0 +1,369 @@
1#
2# ex:ts=4:sw=4:sts=4:et
3# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4#
5# BitBake Toaster Implementation
6#
7# Copyright (C) 2013 Intel Corporation
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License version 2 as
11# published by the Free Software Foundation.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License along
19# with this program; if not, write to the Free Software Foundation, Inc.,
20# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22from django.db import models
23from django.db.models import F
24from django.utils.encoding import python_2_unicode_compatible
25
26
27class Build(models.Model):
28 SUCCEEDED = 0
29 FAILED = 1
30 IN_PROGRESS = 2
31
32 BUILD_OUTCOME = (
33 (SUCCEEDED, 'Succeeded'),
34 (FAILED, 'Failed'),
35 (IN_PROGRESS, 'In Progress'),
36 )
37
38 search_allowed_fields = ['machine', 'cooker_log_path', "target__target", "target__target_image_file__file_name"]
39
40 machine = models.CharField(max_length=100)
41 distro = models.CharField(max_length=100)
42 distro_version = models.CharField(max_length=100)
43 started_on = models.DateTimeField()
44 completed_on = models.DateTimeField()
45 timespent = models.IntegerField(default=0)
46 outcome = models.IntegerField(choices=BUILD_OUTCOME, default=IN_PROGRESS)
47 errors_no = models.IntegerField(default=0)
48 warnings_no = models.IntegerField(default=0)
49 cooker_log_path = models.CharField(max_length=500)
50 build_name = models.CharField(max_length=100)
51 bitbake_version = models.CharField(max_length=50)
52
53 def get_sorted_target_list(self):
54 tgts = Target.objects.filter(build_id = self.id).order_by( 'target' );
55 return( tgts );
56
57
58@python_2_unicode_compatible
59class Target(models.Model):
60 search_allowed_fields = ['target', 'file_name']
61 build = models.ForeignKey(Build)
62 target = models.CharField(max_length=100)
63 is_image = models.BooleanField(default = False)
64 image_size = models.IntegerField(default=0)
65 license_manifest_path = models.CharField(max_length=500, null=True)
66
67 def package_count(self):
68 return Target_Installed_Package.objects.filter(target_id__exact=self.id).count()
69
70 def __str__(self):
71 return self.target
72
73class Target_Image_File(models.Model):
74 target = models.ForeignKey(Target)
75 file_name = models.FilePathField(max_length=100)
76 file_size = models.IntegerField()
77
78class Target_File(models.Model):
79 ITYPE_REGULAR = 1
80 ITYPE_DIRECTORY = 2
81 ITYPE_SYMLINK = 3
82 ITYPE_SOCKET = 4
83 ITYPE_FIFO = 5
84 ITYPE_CHARACTER = 6
85 ITYPE_BLOCK = 7
86 ITYPES = ( (ITYPE_REGULAR ,'regular'),
87 ( ITYPE_DIRECTORY ,'directory'),
88 ( ITYPE_SYMLINK ,'symlink'),
89 ( ITYPE_SOCKET ,'socket'),
90 ( ITYPE_FIFO ,'fifo'),
91 ( ITYPE_CHARACTER ,'character'),
92 ( ITYPE_BLOCK ,'block'),
93 )
94
95 target = models.ForeignKey(Target)
96 path = models.FilePathField()
97 size = models.IntegerField()
98 inodetype = models.IntegerField(choices = ITYPES)
99 permission = models.CharField(max_length=16)
100 owner = models.CharField(max_length=128)
101 group = models.CharField(max_length=128)
102 directory = models.ForeignKey('Target_File', related_name="directory_set", null=True)
103 sym_target = models.ForeignKey('Target_File', related_name="symlink_set", null=True)
104
105
106class TaskManager(models.Manager):
107 def related_setscene(self, task_object):
108 return Task.objects.filter(task_executed=True, build = task_object.build, recipe = task_object.recipe, task_name=task_object.task_name+"_setscene")
109
110class Task(models.Model):
111
112 SSTATE_NA = 0
113 SSTATE_MISS = 1
114 SSTATE_FAILED = 2
115 SSTATE_RESTORED = 3
116
117 SSTATE_RESULT = (
118 (SSTATE_NA, 'Not Applicable'), # For rest of tasks, but they still need checking.
119 (SSTATE_MISS, 'File not in cache'), # the sstate object was not found
120 (SSTATE_FAILED, 'Failed'), # there was a pkg, but the script failed
121 (SSTATE_RESTORED, 'Succeeded'), # successfully restored
122 )
123
124 CODING_NA = 0
125 CODING_PYTHON = 2
126 CODING_SHELL = 3
127
128 TASK_CODING = (
129 (CODING_NA, 'N/A'),
130 (CODING_PYTHON, 'Python'),
131 (CODING_SHELL, 'Shell'),
132 )
133
134 OUTCOME_NA = -1
135 OUTCOME_SUCCESS = 0
136 OUTCOME_COVERED = 1
137 OUTCOME_CACHED = 2
138 OUTCOME_PREBUILT = 3
139 OUTCOME_FAILED = 4
140 OUTCOME_EMPTY = 5
141
142 TASK_OUTCOME = (
143 (OUTCOME_NA, 'Not Available'),
144 (OUTCOME_SUCCESS, 'Succeeded'),
145 (OUTCOME_COVERED, 'Covered'),
146 (OUTCOME_CACHED, 'Cached'),
147 (OUTCOME_PREBUILT, 'Prebuilt'),
148 (OUTCOME_FAILED, 'Failed'),
149 (OUTCOME_EMPTY, 'Empty'),
150 )
151
152 TASK_OUTCOME_HELP = (
153 (OUTCOME_SUCCESS, 'This task successfully completed'),
154 (OUTCOME_COVERED, 'This task did not run because its output is provided by another task'),
155 (OUTCOME_CACHED, 'This task restored output from the sstate-cache directory or mirrors'),
156 (OUTCOME_PREBUILT, 'This task did not run because its outcome was reused from a previous build'),
157 (OUTCOME_FAILED, 'This task did not complete'),
158 (OUTCOME_EMPTY, 'This task has no executable content'),
159 (OUTCOME_NA, ''),
160 )
161
162 search_allowed_fields = [ "recipe__name", "recipe__version", "task_name", "logfile" ]
163
164 objects = TaskManager()
165
166 def get_related_setscene(self):
167 return Task.objects.related_setscene(self)
168
169 def get_outcome_help(self):
170 return Task.TASK_OUTCOME_HELP[self.outcome][1]
171
172 def get_executed_display(self):
173 if self.task_executed:
174 return "Executed"
175 return "Not Executed"
176
177 def get_description(self):
178 helptext = HelpText.objects.filter(key=self.task_name, area=HelpText.VARIABLE, build=self.build)
179 try:
180 return helptext[0].text
181 except IndexError:
182 return ''
183
184 build = models.ForeignKey(Build, related_name='task_build')
185 order = models.IntegerField(null=True)
186 task_executed = models.BooleanField(default=False) # True means Executed, False means Not/Executed
187 outcome = models.IntegerField(choices=TASK_OUTCOME, default=OUTCOME_NA)
188 sstate_checksum = models.CharField(max_length=100, blank=True)
189 path_to_sstate_obj = models.FilePathField(max_length=500, blank=True)
190 recipe = models.ForeignKey('Recipe', related_name='build_recipe')
191 task_name = models.CharField(max_length=100)
192 source_url = models.FilePathField(max_length=255, blank=True)
193 work_directory = models.FilePathField(max_length=255, blank=True)
194 script_type = models.IntegerField(choices=TASK_CODING, default=CODING_NA)
195 line_number = models.IntegerField(default=0)
196 disk_io = models.IntegerField(null=True)
197 cpu_usage = models.DecimalField(max_digits=6, decimal_places=2, null=True)
198 elapsed_time = models.DecimalField(max_digits=6, decimal_places=2, null=True)
199 sstate_result = models.IntegerField(choices=SSTATE_RESULT, default=SSTATE_NA)
200 message = models.CharField(max_length=240)
201 logfile = models.FilePathField(max_length=255, blank=True)
202
203 class Meta:
204 ordering = ('order', 'recipe' ,)
205 unique_together = ('build', 'recipe', 'task_name', )
206
207
208class Task_Dependency(models.Model):
209 task = models.ForeignKey(Task, related_name='task_dependencies_task')
210 depends_on = models.ForeignKey(Task, related_name='task_dependencies_depends')
211
212class Package(models.Model):
213 search_allowed_fields = ['name', 'version', 'revision', 'recipe__name', 'recipe__version', 'recipe__license', 'recipe__layer_version__layer__name', 'recipe__layer_version__branch', 'recipe__layer_version__commit', 'recipe__layer_version__layer__local_path', 'installed_name']
214 build = models.ForeignKey('Build')
215 recipe = models.ForeignKey('Recipe', null=True)
216 name = models.CharField(max_length=100)
217 installed_name = models.CharField(max_length=100, default='')
218 version = models.CharField(max_length=100, blank=True)
219 revision = models.CharField(max_length=32, blank=True)
220 summary = models.CharField(max_length=200, blank=True)
221 description = models.CharField(max_length=200, blank=True)
222 size = models.IntegerField(default=0)
223 installed_size = models.IntegerField(default=0)
224 section = models.CharField(max_length=80, blank=True)
225 license = models.CharField(max_length=80, blank=True)
226
227class Package_DependencyManager(models.Manager):
228 use_for_related_fields = True
229
230 def get_query_set(self):
231 return super(Package_DependencyManager, self).get_query_set().exclude(package_id = F('depends_on__id'))
232
233class Package_Dependency(models.Model):
234 TYPE_RDEPENDS = 0
235 TYPE_TRDEPENDS = 1
236 TYPE_RRECOMMENDS = 2
237 TYPE_TRECOMMENDS = 3
238 TYPE_RSUGGESTS = 4
239 TYPE_RPROVIDES = 5
240 TYPE_RREPLACES = 6
241 TYPE_RCONFLICTS = 7
242 ' TODO: bpackage should be changed to remove the DEPENDS_TYPE access '
243 DEPENDS_TYPE = (
244 (TYPE_RDEPENDS, "depends"),
245 (TYPE_TRDEPENDS, "depends"),
246 (TYPE_TRECOMMENDS, "recommends"),
247 (TYPE_RRECOMMENDS, "recommends"),
248 (TYPE_RSUGGESTS, "suggests"),
249 (TYPE_RPROVIDES, "provides"),
250 (TYPE_RREPLACES, "replaces"),
251 (TYPE_RCONFLICTS, "conflicts"),
252 )
253 ''' Indexed by dep_type, in view order, key for short name and help
254 description which when viewed will be printf'd with the
255 package name.
256 '''
257 DEPENDS_DICT = {
258 TYPE_RDEPENDS : ("depends", "%s is required to run %s"),
259 TYPE_TRDEPENDS : ("depends", "%s is required to run %s"),
260 TYPE_TRECOMMENDS : ("recommends", "%s extends the usability of %s"),
261 TYPE_RRECOMMENDS : ("recommends", "%s extends the usability of %s"),
262 TYPE_RSUGGESTS : ("suggests", "%s is suggested for installation with %s"),
263 TYPE_RPROVIDES : ("provides", "%s is provided by %s"),
264 TYPE_RREPLACES : ("replaces", "%s is replaced by %s"),
265 TYPE_RCONFLICTS : ("conflicts", "%s conflicts with %s, which will not be installed if this package is not first removed"),
266 }
267
268 package = models.ForeignKey(Package, related_name='package_dependencies_source')
269 depends_on = models.ForeignKey(Package, related_name='package_dependencies_target') # soft dependency
270 dep_type = models.IntegerField(choices=DEPENDS_TYPE)
271 target = models.ForeignKey(Target, null=True)
272 objects = Package_DependencyManager()
273
274class Target_Installed_Package(models.Model):
275 target = models.ForeignKey(Target)
276 package = models.ForeignKey(Package, related_name='buildtargetlist_package')
277
278class Package_File(models.Model):
279 package = models.ForeignKey(Package, related_name='buildfilelist_package')
280 path = models.FilePathField(max_length=255, blank=True)
281 size = models.IntegerField()
282
283class Recipe(models.Model):
284 search_allowed_fields = ['name', 'version', 'file_path', 'section', 'license', 'layer_version__layer__name', 'layer_version__branch', 'layer_version__commit', 'layer_version__layer__local_path']
285 name = models.CharField(max_length=100, blank=True)
286 version = models.CharField(max_length=100, blank=True)
287 layer_version = models.ForeignKey('Layer_Version', related_name='recipe_layer_version')
288 summary = models.CharField(max_length=100, blank=True)
289 description = models.CharField(max_length=100, blank=True)
290 section = models.CharField(max_length=100, blank=True)
291 license = models.CharField(max_length=200, blank=True)
292 homepage = models.URLField(blank=True)
293 bugtracker = models.URLField(blank=True)
294 file_path = models.FilePathField(max_length=255)
295
296class Recipe_DependencyManager(models.Manager):
297 use_for_related_fields = True
298
299 def get_query_set(self):
300 return super(Recipe_DependencyManager, self).get_query_set().exclude(recipe_id = F('depends_on__id'))
301
302class Recipe_Dependency(models.Model):
303 TYPE_DEPENDS = 0
304 TYPE_RDEPENDS = 1
305
306 DEPENDS_TYPE = (
307 (TYPE_DEPENDS, "depends"),
308 (TYPE_RDEPENDS, "rdepends"),
309 )
310 recipe = models.ForeignKey(Recipe, related_name='r_dependencies_recipe')
311 depends_on = models.ForeignKey(Recipe, related_name='r_dependencies_depends')
312 dep_type = models.IntegerField(choices=DEPENDS_TYPE)
313 objects = Recipe_DependencyManager()
314
315class Layer(models.Model):
316 name = models.CharField(max_length=100)
317 local_path = models.FilePathField(max_length=255)
318 layer_index_url = models.URLField()
319
320
321class Layer_Version(models.Model):
322 build = models.ForeignKey(Build, related_name='layer_version_build')
323 layer = models.ForeignKey(Layer, related_name='layer_version_layer')
324 branch = models.CharField(max_length=50)
325 commit = models.CharField(max_length=100)
326 priority = models.IntegerField()
327
328
329class Variable(models.Model):
330 search_allowed_fields = ['variable_name', 'variable_value',
331 'vhistory__file_name', "description"]
332 build = models.ForeignKey(Build, related_name='variable_build')
333 variable_name = models.CharField(max_length=100)
334 variable_value = models.TextField(blank=True)
335 changed = models.BooleanField(default=False)
336 human_readable_name = models.CharField(max_length=200)
337 description = models.TextField(blank=True)
338
339class VariableHistory(models.Model):
340 variable = models.ForeignKey(Variable, related_name='vhistory')
341 value = models.TextField(blank=True)
342 file_name = models.FilePathField(max_length=255)
343 line_number = models.IntegerField(null=True)
344 operation = models.CharField(max_length=16)
345
346class HelpText(models.Model):
347 VARIABLE = 0
348 HELPTEXT_AREA = ((VARIABLE, 'variable'), )
349
350 build = models.ForeignKey(Build, related_name='helptext_build')
351 area = models.IntegerField(choices=HELPTEXT_AREA)
352 key = models.CharField(max_length=100)
353 text = models.TextField()
354
355class LogMessage(models.Model):
356 INFO = 0
357 WARNING = 1
358 ERROR = 2
359
360 LOG_LEVEL = ( (INFO, "info"),
361 (WARNING, "warn"),
362 (ERROR, "error") )
363
364 build = models.ForeignKey(Build)
365 task = models.ForeignKey(Task, blank = True, null=True)
366 level = models.IntegerField(choices=LOG_LEVEL, default=INFO)
367 message=models.CharField(max_length=240)
368 pathname = models.FilePathField(max_length=255, blank=True)
369 lineno = models.IntegerField(null=True)