aboutsummaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/toaster')
-rw-r--r--bitbake/lib/toaster/orm/migrations/0008_refactor_artifact_models.py39
-rw-r--r--bitbake/lib/toaster/orm/migrations/0008_targetartifactfile.py23
-rw-r--r--bitbake/lib/toaster/orm/models.py112
-rw-r--r--bitbake/lib/toaster/toastergui/templates/builddashboard.html64
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py19
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":