bitbake: toaster: use has_images() methods to display images correctly

In the build dashboard, we had issues with showing images correctly,
as we were using the is_image property of targets to determine
whether a target would have image files. This property can
be set to True if a target refers to an image recipe
(e.g. "core-image-minimal"), even if the task used in the build
didn't produce any image files.

By adding has_images() methods to the Target and Build objects,
which count associated Target_Image_File objects,
we can correctly determine whether a target has image files
associated with it, and if any of the targets for a build has
image files. This means that we can screen out the left-hand
"Images" menu options for builds which contained image-related
targets (e.g. "core-image-minimal") but which didn't produce
any images (e.g. "rootfs" task).

[YOCTO #9500]
[YOCTO #9784]

(Bitbake rev: f6bba0ff254d5ed3163151d4b938f3a43c9acb0a)

Signed-off-by: Elliot Smith <elliot.smith@intel.com>
Signed-off-by: bavery <brian.avery@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Elliot Smith 2016-07-12 15:54:50 -07:00 committed by Richard Purdie
parent 150e5588a0
commit 587275eefd
3 changed files with 33 additions and 12 deletions

View File

@ -436,17 +436,32 @@ class Build(models.Model):
eta += ((eta - self.started_on)*(100-completeper))/completeper eta += ((eta - self.started_on)*(100-completeper))/completeper
return eta return eta
def has_images(self):
"""
Returns True if at least one of the targets for this build has an
image file associated with it, False otherwise
"""
targets = Target.objects.filter(build_id=self.id)
has_images = False
for target in targets:
if target.has_images():
has_images = True
break
return has_images
def get_image_file_extensions(self): def get_image_file_extensions(self):
""" """
Get list of file name extensions for images produced by this build; Get string of file name extensions for images produced by this build;
note that this is the actual list of extensions stored on Target objects note that this is the actual list of extensions stored on Target objects
for this build, and not the value of IMAGE_FSTYPES. for this build, and not the value of IMAGE_FSTYPES.
Returns comma-separated string, e.g. "vmdk, ext4"
""" """
extensions = [] extensions = []
targets = Target.objects.filter(build_id = self.id) targets = Target.objects.filter(build_id = self.id)
for target in targets: for target in targets:
if (not target.is_image): if not target.is_image:
continue continue
target_image_files = Target_Image_File.objects.filter( target_image_files = Target_Image_File.objects.filter(
@ -739,6 +754,12 @@ class Target(models.Model):
sdk_file.target = self sdk_file.target = self
sdk_file.save() sdk_file.save()
def has_images(self):
"""
Returns True if this target has one or more image files attached to it.
"""
return self.target_image_file_set.all().count() > 0
# kernel artifacts for a target: bzImage and modules* # kernel artifacts for a target: bzImage and modules*
class TargetKernelFile(models.Model): class TargetKernelFile(models.Model):
target = models.ForeignKey(Target) target = models.ForeignKey(Target)
@ -775,6 +796,9 @@ class Target_Image_File(models.Model):
@property @property
def suffix(self): def suffix(self):
"""
Suffix for image file, minus leading "."
"""
for suffix in Target_Image_File.SUFFIXES: for suffix in Target_Image_File.SUFFIXES:
if self.file_name.endswith(suffix): if self.file_name.endswith(suffix):
return suffix return suffix

View File

@ -33,7 +33,7 @@
$("#build-menu li a").each(function(){ $("#build-menu li a").each(function(){
/* Set the page active state in the Build menu */ /* Set the page active state in the Build menu */
var currentUrl = window.location.href.split('?')[0]; var currentUrl = window.location.href.split('?')[0];
if (currentUrl === $(this).prop("href")){ if (currentUrl === $(this).prop("href")){
$(this).parent().addClass("active"); $(this).parent().addClass("active");
} else { } else {
@ -62,11 +62,13 @@
{% endif %} > {% endif %} >
<a href="{% url 'builddashboard' build.pk %}">Build summary</a> <a href="{% url 'builddashboard' build.pk %}">Build summary</a>
</li> </li>
{% if build.target_set.all.0.is_image and build.outcome == 0 %} {% if build.has_images and build.outcome == build.SUCCEEDED %}
<li class="nav-header">Images</li> <li class="nav-header">Images</li>
{% block nav-target %} {% block nav-target %}
{% for t in build.get_sorted_target_list %} {% for t in build.get_sorted_target_list %}
<li id="menu-{{t.target}}"><a href="{% url 'target' build.pk t.pk %}">{{t.target}}</a><li> {% if t.has_images %}
<li id="menu-{{t.target}}"><a href="{% url 'target' build.pk t.pk %}">{{t.target}}</a><li>
{% endif %}
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}
{% endif %} {% endif %}

View File

@ -471,19 +471,14 @@ def builddashboard( request, build_id ):
recipeCount = Recipe.objects.filter( layer_version__id__in = layerVersionId ).count( ); recipeCount = Recipe.objects.filter( layer_version__id__in = layerVersionId ).count( );
tgts = Target.objects.filter( build_id = build_id ).order_by( 'target' ); tgts = Target.objects.filter( build_id = build_id ).order_by( 'target' );
##
# set up custom target list with computed package and image data # set up custom target list with computed package and image data
#
targets = [ ] targets = [ ]
ntargets = 0 ntargets = 0
hasImages = False
targetHasNoImages = False targetHasNoImages = False
for t in tgts: for t in tgts:
elem = { } elem = { }
elem[ 'target' ] = t elem[ 'target' ] = t
if t.is_image:
hasImages = True
npkg = 0 npkg = 0
pkgsz = 0 pkgsz = 0
package = None package = None
@ -533,7 +528,7 @@ def builddashboard( request, build_id ):
context = { context = {
'build' : build, 'build' : build,
'project' : build.project, 'project' : build.project,
'hasImages' : hasImages, 'hasImages' : build.has_images(),
'ntargets' : ntargets, 'ntargets' : ntargets,
'targets' : targets, 'targets' : targets,
'recipecount' : recipeCount, 'recipecount' : recipeCount,