diff options
Diffstat (limited to 'bitbake/lib/toaster')
-rw-r--r-- | bitbake/lib/toaster/orm/migrations/0008_refactor_artifact_models.py | 39 | ||||
-rw-r--r-- | bitbake/lib/toaster/orm/migrations/0008_targetartifactfile.py | 23 | ||||
-rw-r--r-- | bitbake/lib/toaster/orm/models.py | 112 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/builddashboard.html | 64 | ||||
-rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 19 |
5 files changed, 162 insertions, 95 deletions
diff --git a/bitbake/lib/toaster/orm/migrations/0008_refactor_artifact_models.py b/bitbake/lib/toaster/orm/migrations/0008_refactor_artifact_models.py new file mode 100644 index 0000000000..3367582a81 --- /dev/null +++ b/bitbake/lib/toaster/orm/migrations/0008_refactor_artifact_models.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('orm', '0007_auto_20160523_1446'), + ] + + operations = [ + migrations.CreateModel( + name='TargetKernelFile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', serialize=False)), + ('file_name', models.FilePathField()), + ('file_size', models.IntegerField()), + ('target', models.ForeignKey(to='orm.Target')), + ], + ), + migrations.CreateModel( + name='TargetSDKFile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', serialize=False)), + ('file_name', models.FilePathField()), + ('file_size', models.IntegerField()), + ('target', models.ForeignKey(to='orm.Target')), + ], + ), + migrations.RemoveField( + model_name='buildartifact', + name='build', + ), + migrations.DeleteModel( + name='BuildArtifact', + ), + ] diff --git a/bitbake/lib/toaster/orm/migrations/0008_targetartifactfile.py b/bitbake/lib/toaster/orm/migrations/0008_targetartifactfile.py deleted file mode 100644 index 9f1d9bf4ec..0000000000 --- a/bitbake/lib/toaster/orm/migrations/0008_targetartifactfile.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('orm', '0007_auto_20160523_1446'), - ] - - operations = [ - migrations.CreateModel( - name='TargetArtifactFile', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False, auto_created=True, verbose_name='ID')), - ('file_name', models.FilePathField()), - ('file_size', models.IntegerField()), - ('target', models.ForeignKey(to='orm.Target')), - ], - ), - ] diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py index 9edbef3396..61f6a2072e 100644 --- a/bitbake/lib/toaster/orm/models.py +++ b/bitbake/lib/toaster/orm/models.py @@ -581,28 +581,6 @@ class Build(models.Model): def __str__(self): return "%d %s %s" % (self.id, self.project, ",".join([t.target for t in self.target_set.all()])) - -# an Artifact is anything that results from a Build, and may be of interest to the user, and is not stored elsewhere -class BuildArtifact(models.Model): - build = models.ForeignKey(Build) - file_name = models.FilePathField() - file_size = models.IntegerField() - - def get_local_file_name(self): - try: - deploydir = Variable.objects.get(build = self.build, variable_name="DEPLOY_DIR").variable_value - return self.file_name[len(deploydir)+1:] - except: - raise - - return self.file_name - - def get_basename(self): - return os.path.basename(self.file_name) - - def is_available(self): - return self.build.buildrequest.environment.has_artifact(self.file_name) - class ProjectTarget(models.Model): project = models.ForeignKey(Project) target = models.CharField(max_length=100) @@ -625,13 +603,19 @@ class Target(models.Model): def get_similar_targets(self): """ - Get targets for the same machine, task and target name + Get target sfor the same machine, task and target name (e.g. 'core-image-minimal') from a successful build for this project (but excluding this target). - Note that we look for targets built by this project because projects - can have different configurations from each other, and put their - artifacts in different directories. + Note that we only look for targets built by this project because + projects can have different configurations from each other, and put + their artifacts in different directories. + + The possibility of error when retrieving candidate targets + is minimised by the fact that bitbake will rebuild artifacts if MACHINE + (or various other variables) change. In this case, there is no need to + clone artifacts from another target, as those artifacts will have + been re-generated for this target anyway. """ query = ~Q(pk=self.pk) & \ Q(target=self.target) & \ @@ -649,29 +633,54 @@ class Target(models.Model): similar_target = None candidates = self.get_similar_targets() - if candidates.count() < 1: + if candidates.count() == 0: return similar_target task_subquery = Q(task=self.task) # we can look for a 'build' task if this task is a 'populate_sdk_ext' - # task, as it will have created images; and vice versa; note that + # task, as the latter also creates images; and vice versa; note that # 'build' targets can have their task set to ''; # also note that 'populate_sdk' does not produce image files image_tasks = [ '', # aka 'build' 'build', + 'image', 'populate_sdk_ext' ] if self.task in image_tasks: task_subquery = Q(task__in=image_tasks) + # annotate with the count of files, to exclude any targets which + # don't have associated files + candidates = candidates.annotate(num_files=Count('target_image_file')) + query = task_subquery & Q(num_files__gt=0) + candidates = candidates.filter(query) + + if candidates.count() > 0: + candidates.order_by('build__completed_on') + similar_target = candidates.last() + + return similar_target + + def get_similar_target_with_sdk_files(self): + """ + Get the most recent similar target with TargetSDKFiles associated + with it, for the purpose of cloning those files onto this target. + """ + similar_target = None + + candidates = self.get_similar_targets() + if candidates.count() == 0: + return similar_target + # annotate with the count of files, to exclude any targets which # don't have associated files - candidates = candidates.annotate( - num_files=Count('target_image_file')) + candidates = candidates.annotate(num_files=Count('targetsdkfile')) + + query = Q(task=self.task) & Q(num_files__gt=0) candidates = candidates.filter(query) @@ -681,11 +690,10 @@ class Target(models.Model): return similar_target - def clone_artifacts_from(self, target): + def clone_image_artifacts_from(self, target): """ - Make clones of the BuildArtifacts, Target_Image_Files and - TargetArtifactFile objects associated with Target target, then - associate them with this target. + Make clones of the Target_Image_Files and TargetKernelFile objects + associated with Target target, then associate them with this target. Note that for Target_Image_Files, we only want files from the previous build whose suffix matches one of the suffixes defined in this @@ -711,18 +719,38 @@ class Target(models.Model): image_file.target = self image_file.save() - artifact_files = target.targetartifactfile_set.all() - for artifact_file in artifact_files: - artifact_file.pk = None - artifact_file.target = self - artifact_file.save() + kernel_files = target.targetkernelfile_set.all() + for kernel_file in kernel_files: + kernel_file.pk = None + kernel_file.target = self + kernel_file.save() self.license_manifest_path = target.license_manifest_path self.save() -# an Artifact is anything that results from a target being built, and may -# be of interest to the user, and is not an image file -class TargetArtifactFile(models.Model): + def clone_sdk_artifacts_from(self, target): + """ + Clone TargetSDKFile objects from target and associate them with this + target. + """ + sdk_files = target.targetsdkfile_set.all() + for sdk_file in sdk_files: + sdk_file.pk = None + sdk_file.target = self + sdk_file.save() + +# kernel artifacts for a target: bzImage and modules* +class TargetKernelFile(models.Model): + target = models.ForeignKey(Target) + file_name = models.FilePathField() + file_size = models.IntegerField() + + @property + def basename(self): + return os.path.basename(self.file_name) + +# SDK artifacts for a target: sh and manifest files +class TargetSDKFile(models.Model): target = models.ForeignKey(Target) file_name = models.FilePathField() file_size = models.IntegerField() diff --git a/bitbake/lib/toaster/toastergui/templates/builddashboard.html b/bitbake/lib/toaster/toastergui/templates/builddashboard.html index f6d62b9951..e1bde21e99 100644 --- a/bitbake/lib/toaster/toastergui/templates/builddashboard.html +++ b/bitbake/lib/toaster/toastergui/templates/builddashboard.html @@ -80,29 +80,30 @@ <dd><a href="{% url 'target' build.pk target.target.pk %}">{{target.npkg}}</a></dd> <dt>Total package size</dt> <dd>{{target.pkgsz|filtered_filesizeformat}}</dd> - {% if target.targetHasNoImages %} - </dl> - <div class="row"> - <div class="col-md-7"> - <div class="alert alert-info"> - <p> - <strong>This build did not create any image files</strong> - </p> - <p> - This is probably because valid image and license manifest - files from a previous build already exist in your - <code>build/tmp/deploy</code> - directory. You can - also <a href="{% url 'target' build.pk target.target.pk %}">view the - license manifest information</a> in Toaster. - </p> - </div> - </div> + </dl> + {% if target.targetHasNoImages %} + <div class="row"> + <div class="col-md-7"> + <div class="alert alert-info"> + <p> + <strong>This build did not create any image files</strong> + </p> + <p> + This is probably because valid image and license manifest + files from a previous build already exist in your + <code>build/tmp/deploy</code> + directory. You can + also <a href="{% url 'target' build.pk target.target.pk %}">view the + license manifest information</a> in Toaster. + </p> </div> - {% else %} + </div> + </div> + {% endif %} + {% if not target.targetHasNoImages %} + <dl class="dl-horizontal"> <dt> <span class="glyphicon glyphicon-question-sign get-help" title="The location in disk of the license manifest, a document listing all packages installed in your image and their licenses"></span> - License manifest </dt> <dd> @@ -129,15 +130,32 @@ </dt> <dd> <ul class="list-unstyled"> - {% for artifact in target.target_artifacts|dictsort:"basename" %} + {% for artifact in target.target_kernel_artifacts|dictsort:"basename" %} <li> - <a href="{% url 'build_artifact' build.id 'targetartifactfile' artifact.id %}">{{artifact.basename}}</a> + <a href="{% url 'build_artifact' build.id 'targetkernelartifact' artifact.id %}">{{artifact.basename}}</a> ({{artifact.file_size|filtered_filesizeformat}}) </li> {% endfor %} </ul> </dd> - </dl> + </dl> + {% endif %} + {% if target.target_sdk_artifacts_count > 0 %} + <dl class="dl-horizontal"> + <dt> + SDK artifacts + </dt> + <dd> + <ul class="list-unstyled"> + {% for artifact in target.target_sdk_artifacts|dictsort:"basename" %} + <li> + <a href="{% url 'build_artifact' build.id 'targetsdkartifact' artifact.id %}">{{artifact.basename}}</a> + ({{artifact.file_size|filtered_filesizeformat}}) + </li> + {% endfor %} + </ul> + </dd> + </dl> {% endif %} </div> {% endif %} diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 0ec88d9a77..a82a261e0d 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py @@ -30,8 +30,8 @@ from django.db import IntegrityError, Error from django.shortcuts import render, redirect, get_object_or_404 from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, LogMessage, Variable from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File, Package_Dependency -from orm.models import Target_Installed_Package, Target_File, Target_Image_File, BuildArtifact, CustomImagePackage -from orm.models import TargetArtifactFile +from orm.models import Target_Installed_Package, Target_File, Target_Image_File, CustomImagePackage +from orm.models import TargetKernelFile, TargetSDKFile from orm.models import BitbakeVersion, CustomImageRecipe from bldcontrol import bbcontroller from django.views.decorators.cache import cache_control @@ -510,7 +510,11 @@ def builddashboard( request, build_id ): targetHasNoImages = True elem[ 'imageFiles' ] = imageFiles elem[ 'targetHasNoImages' ] = targetHasNoImages - elem['target_artifacts'] = t.targetartifactfile_set.all() + elem['target_kernel_artifacts'] = t.targetkernelfile_set.all() + + target_sdk_files = t.targetsdkfile_set.all() + elem['target_sdk_artifacts_count'] = target_sdk_files.count() + elem['target_sdk_artifacts'] = target_sdk_files targets.append( elem ) @@ -2294,11 +2298,12 @@ if True: elif artifact_type == "imagefile": file_name = Target_Image_File.objects.get(target__build = build, pk = artifact_id).file_name - elif artifact_type == "buildartifact": - file_name = BuildArtifact.objects.get(build = build, pk = artifact_id).file_name + elif artifact_type == "targetkernelartifact": + target = TargetKernelFile.objects.get(pk=artifact_id) + file_name = target.file_name - elif artifact_type == "targetartifactfile": - target = TargetArtifactFile.objects.get(pk=artifact_id) + elif artifact_type == "targetsdkartifact": + target = TargetSDKFile.objects.get(pk=artifact_id) file_name = target.file_name elif artifact_type == "licensemanifest": |