summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/orm/models.py
diff options
context:
space:
mode:
authorElliot Smith <elliot.smith@intel.com>2016-07-12 15:54:46 -0700
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-07-19 08:56:51 +0100
commit4125da7763ffc70cc77578c677bb7e5fc7ebaf57 (patch)
tree3c303f0070365d73217950b96ef234cfe9bcc022 /bitbake/lib/toaster/orm/models.py
parente9808576daad137695bdedd0883ee0a35b7d870a (diff)
downloadpoky-4125da7763ffc70cc77578c677bb7e5fc7ebaf57.tar.gz
bitbake: toaster: attach kernel artifacts to targets
The bzImage and modules files were previously attached to a build, rather than to the target which produced them. This meant it was not possible to determine which kernel artifact produced by a build came from which target; which in turn made it difficult to associate existing kernel artifact with targets when those targets didn't produce artifacts (e.g. if the same machine + target combination was built again and didn't produce a bzImage or modules file because those files already existed). By associating kernel artifacts with the target (via a new TargetArtifactFile model), we make it possible to find all the artifacts for a given machine + target combination. Then, in cases where a build is completed but its targets don't produce any artifacts, we can find a previous Target object with the same machine + target and copy its artifacts to the targets for a just-completed build. Note that this doesn't cover SDK artifacts yet, which are still retrieved in toaster.bbclass and show up as "Other artifacts", lumped together for the whole build rather than by target. [YOCTO #8556] (Bitbake rev: 9b151416e428c2565a27d89116439f9a8d578e3d) 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>
Diffstat (limited to 'bitbake/lib/toaster/orm/models.py')
-rw-r--r--bitbake/lib/toaster/orm/models.py123
1 files changed, 121 insertions, 2 deletions
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
index 40cdb9e5c5..9edbef3396 100644
--- a/bitbake/lib/toaster/orm/models.py
+++ b/bitbake/lib/toaster/orm/models.py
@@ -22,7 +22,7 @@
22from __future__ import unicode_literals 22from __future__ import unicode_literals
23 23
24from django.db import models, IntegrityError 24from django.db import models, IntegrityError
25from django.db.models import F, Q, Avg, Max, Sum 25from django.db.models import F, Q, Avg, Max, Sum, Count
26from django.utils import timezone 26from django.utils import timezone
27from django.utils.encoding import force_bytes 27from django.utils.encoding import force_bytes
28 28
@@ -438,7 +438,9 @@ class Build(models.Model):
438 438
439 def get_image_file_extensions(self): 439 def get_image_file_extensions(self):
440 """ 440 """
441 Get list of file name extensions for images produced by this build 441 Get list of file name extensions for images produced by this build;
442 note that this is the actual list of extensions stored on Target objects
443 for this build, and not the value of IMAGE_FSTYPES.
442 """ 444 """
443 extensions = [] 445 extensions = []
444 446
@@ -458,6 +460,15 @@ class Build(models.Model):
458 460
459 return ', '.join(extensions) 461 return ', '.join(extensions)
460 462
463 def get_image_fstypes(self):
464 """
465 Get the IMAGE_FSTYPES variable value for this build as a de-duplicated
466 list of image file suffixes.
467 """
468 image_fstypes = Variable.objects.get(
469 build=self, variable_name='IMAGE_FSTYPES').variable_value
470 return list(set(re.split(r' {1,}', image_fstypes)))
471
461 def get_sorted_target_list(self): 472 def get_sorted_target_list(self):
462 tgts = Target.objects.filter(build_id = self.id).order_by( 'target' ); 473 tgts = Target.objects.filter(build_id = self.id).order_by( 'target' );
463 return( tgts ); 474 return( tgts );
@@ -612,6 +623,114 @@ class Target(models.Model):
612 def __unicode__(self): 623 def __unicode__(self):
613 return self.target 624 return self.target
614 625
626 def get_similar_targets(self):
627 """
628 Get targets for the same machine, task and target name
629 (e.g. 'core-image-minimal') from a successful build for this project
630 (but excluding this target).
631
632 Note that we look for targets built by this project because projects
633 can have different configurations from each other, and put their
634 artifacts in different directories.
635 """
636 query = ~Q(pk=self.pk) & \
637 Q(target=self.target) & \
638 Q(build__machine=self.build.machine) & \
639 Q(build__outcome=Build.SUCCEEDED) & \
640 Q(build__project=self.build.project)
641
642 return Target.objects.filter(query)
643
644 def get_similar_target_with_image_files(self):
645 """
646 Get the most recent similar target with Target_Image_Files associated
647 with it, for the purpose of cloning those files onto this target.
648 """
649 similar_target = None
650
651 candidates = self.get_similar_targets()
652 if candidates.count() < 1:
653 return similar_target
654
655 task_subquery = Q(task=self.task)
656
657 # we can look for a 'build' task if this task is a 'populate_sdk_ext'
658 # task, as it will have created images; and vice versa; note that
659 # 'build' targets can have their task set to '';
660 # also note that 'populate_sdk' does not produce image files
661 image_tasks = [
662 '', # aka 'build'
663 'build',
664 'populate_sdk_ext'
665 ]
666 if self.task in image_tasks:
667 task_subquery = Q(task__in=image_tasks)
668
669 query = task_subquery & Q(num_files__gt=0)
670
671 # annotate with the count of files, to exclude any targets which
672 # don't have associated files
673 candidates = candidates.annotate(
674 num_files=Count('target_image_file'))
675
676 candidates = candidates.filter(query)
677
678 if candidates.count() > 0:
679 candidates.order_by('build__completed_on')
680 similar_target = candidates.last()
681
682 return similar_target
683
684 def clone_artifacts_from(self, target):
685 """
686 Make clones of the BuildArtifacts, Target_Image_Files and
687 TargetArtifactFile objects associated with Target target, then
688 associate them with this target.
689
690 Note that for Target_Image_Files, we only want files from the previous
691 build whose suffix matches one of the suffixes defined in this
692 target's build's IMAGE_FSTYPES configuration variable. This prevents the
693 Target_Image_File object for an ext4 image being associated with a
694 target for a project which didn't produce an ext4 image (for example).
695
696 Also sets the license_manifest_path of this target to the same path
697 as that of target being cloned from, as the license manifest path is
698 also a build artifact but is treated differently.
699 """
700
701 image_fstypes = self.build.get_image_fstypes()
702
703 # filter out any image files whose suffixes aren't in the
704 # IMAGE_FSTYPES suffixes variable for this target's build
705 image_files = [target_image_file \
706 for target_image_file in target.target_image_file_set.all() \
707 if target_image_file.suffix in image_fstypes]
708
709 for image_file in image_files:
710 image_file.pk = None
711 image_file.target = self
712 image_file.save()
713
714 artifact_files = target.targetartifactfile_set.all()
715 for artifact_file in artifact_files:
716 artifact_file.pk = None
717 artifact_file.target = self
718 artifact_file.save()
719
720 self.license_manifest_path = target.license_manifest_path
721 self.save()
722
723# an Artifact is anything that results from a target being built, and may
724# be of interest to the user, and is not an image file
725class TargetArtifactFile(models.Model):
726 target = models.ForeignKey(Target)
727 file_name = models.FilePathField()
728 file_size = models.IntegerField()
729
730 @property
731 def basename(self):
732 return os.path.basename(self.file_name)
733
615class Target_Image_File(models.Model): 734class Target_Image_File(models.Model):
616 # valid suffixes for image files produced by a build 735 # valid suffixes for image files produced by a build
617 SUFFIXES = { 736 SUFFIXES = {