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:
parent
150e5588a0
commit
587275eefd
|
@ -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
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue