diff options
Diffstat (limited to 'bitbake/lib/toaster/orm/models.py')
| -rw-r--r-- | bitbake/lib/toaster/orm/models.py | 112 |
1 files changed, 70 insertions, 42 deletions
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): | |||
| 581 | def __str__(self): | 581 | def __str__(self): |
| 582 | return "%d %s %s" % (self.id, self.project, ",".join([t.target for t in self.target_set.all()])) | 582 | return "%d %s %s" % (self.id, self.project, ",".join([t.target for t in self.target_set.all()])) |
| 583 | 583 | ||
| 584 | |||
| 585 | # an Artifact is anything that results from a Build, and may be of interest to the user, and is not stored elsewhere | ||
| 586 | class BuildArtifact(models.Model): | ||
| 587 | build = models.ForeignKey(Build) | ||
| 588 | file_name = models.FilePathField() | ||
| 589 | file_size = models.IntegerField() | ||
| 590 | |||
| 591 | def get_local_file_name(self): | ||
| 592 | try: | ||
| 593 | deploydir = Variable.objects.get(build = self.build, variable_name="DEPLOY_DIR").variable_value | ||
| 594 | return self.file_name[len(deploydir)+1:] | ||
| 595 | except: | ||
| 596 | raise | ||
| 597 | |||
| 598 | return self.file_name | ||
| 599 | |||
| 600 | def get_basename(self): | ||
| 601 | return os.path.basename(self.file_name) | ||
| 602 | |||
| 603 | def is_available(self): | ||
| 604 | return self.build.buildrequest.environment.has_artifact(self.file_name) | ||
| 605 | |||
| 606 | class ProjectTarget(models.Model): | 584 | class ProjectTarget(models.Model): |
| 607 | project = models.ForeignKey(Project) | 585 | project = models.ForeignKey(Project) |
| 608 | target = models.CharField(max_length=100) | 586 | target = models.CharField(max_length=100) |
| @@ -625,13 +603,19 @@ class Target(models.Model): | |||
| 625 | 603 | ||
| 626 | def get_similar_targets(self): | 604 | def get_similar_targets(self): |
| 627 | """ | 605 | """ |
| 628 | Get targets for the same machine, task and target name | 606 | Get target sfor the same machine, task and target name |
| 629 | (e.g. 'core-image-minimal') from a successful build for this project | 607 | (e.g. 'core-image-minimal') from a successful build for this project |
| 630 | (but excluding this target). | 608 | (but excluding this target). |
| 631 | 609 | ||
| 632 | Note that we look for targets built by this project because projects | 610 | Note that we only look for targets built by this project because |
| 633 | can have different configurations from each other, and put their | 611 | projects can have different configurations from each other, and put |
| 634 | artifacts in different directories. | 612 | their artifacts in different directories. |
| 613 | |||
| 614 | The possibility of error when retrieving candidate targets | ||
| 615 | is minimised by the fact that bitbake will rebuild artifacts if MACHINE | ||
| 616 | (or various other variables) change. In this case, there is no need to | ||
| 617 | clone artifacts from another target, as those artifacts will have | ||
| 618 | been re-generated for this target anyway. | ||
| 635 | """ | 619 | """ |
| 636 | query = ~Q(pk=self.pk) & \ | 620 | query = ~Q(pk=self.pk) & \ |
| 637 | Q(target=self.target) & \ | 621 | Q(target=self.target) & \ |
| @@ -649,29 +633,54 @@ class Target(models.Model): | |||
| 649 | similar_target = None | 633 | similar_target = None |
| 650 | 634 | ||
| 651 | candidates = self.get_similar_targets() | 635 | candidates = self.get_similar_targets() |
| 652 | if candidates.count() < 1: | 636 | if candidates.count() == 0: |
| 653 | return similar_target | 637 | return similar_target |
| 654 | 638 | ||
| 655 | task_subquery = Q(task=self.task) | 639 | task_subquery = Q(task=self.task) |
| 656 | 640 | ||
| 657 | # we can look for a 'build' task if this task is a 'populate_sdk_ext' | 641 | # 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 | 642 | # task, as the latter also creates images; and vice versa; note that |
| 659 | # 'build' targets can have their task set to ''; | 643 | # 'build' targets can have their task set to ''; |
| 660 | # also note that 'populate_sdk' does not produce image files | 644 | # also note that 'populate_sdk' does not produce image files |
| 661 | image_tasks = [ | 645 | image_tasks = [ |
| 662 | '', # aka 'build' | 646 | '', # aka 'build' |
| 663 | 'build', | 647 | 'build', |
| 648 | 'image', | ||
| 664 | 'populate_sdk_ext' | 649 | 'populate_sdk_ext' |
| 665 | ] | 650 | ] |
| 666 | if self.task in image_tasks: | 651 | if self.task in image_tasks: |
| 667 | task_subquery = Q(task__in=image_tasks) | 652 | task_subquery = Q(task__in=image_tasks) |
| 668 | 653 | ||
| 654 | # annotate with the count of files, to exclude any targets which | ||
| 655 | # don't have associated files | ||
| 656 | candidates = candidates.annotate(num_files=Count('target_image_file')) | ||
| 657 | |||
| 669 | query = task_subquery & Q(num_files__gt=0) | 658 | query = task_subquery & Q(num_files__gt=0) |
| 670 | 659 | ||
| 660 | candidates = candidates.filter(query) | ||
| 661 | |||
| 662 | if candidates.count() > 0: | ||
| 663 | candidates.order_by('build__completed_on') | ||
| 664 | similar_target = candidates.last() | ||
| 665 | |||
| 666 | return similar_target | ||
| 667 | |||
| 668 | def get_similar_target_with_sdk_files(self): | ||
| 669 | """ | ||
| 670 | Get the most recent similar target with TargetSDKFiles associated | ||
| 671 | with it, for the purpose of cloning those files onto this target. | ||
| 672 | """ | ||
| 673 | similar_target = None | ||
| 674 | |||
| 675 | candidates = self.get_similar_targets() | ||
| 676 | if candidates.count() == 0: | ||
| 677 | return similar_target | ||
| 678 | |||
| 671 | # annotate with the count of files, to exclude any targets which | 679 | # annotate with the count of files, to exclude any targets which |
| 672 | # don't have associated files | 680 | # don't have associated files |
| 673 | candidates = candidates.annotate( | 681 | candidates = candidates.annotate(num_files=Count('targetsdkfile')) |
| 674 | num_files=Count('target_image_file')) | 682 | |
| 683 | query = Q(task=self.task) & Q(num_files__gt=0) | ||
| 675 | 684 | ||
| 676 | candidates = candidates.filter(query) | 685 | candidates = candidates.filter(query) |
| 677 | 686 | ||
| @@ -681,11 +690,10 @@ class Target(models.Model): | |||
| 681 | 690 | ||
| 682 | return similar_target | 691 | return similar_target |
| 683 | 692 | ||
| 684 | def clone_artifacts_from(self, target): | 693 | def clone_image_artifacts_from(self, target): |
| 685 | """ | 694 | """ |
| 686 | Make clones of the BuildArtifacts, Target_Image_Files and | 695 | Make clones of the Target_Image_Files and TargetKernelFile objects |
| 687 | TargetArtifactFile objects associated with Target target, then | 696 | associated with Target target, then associate them with this target. |
| 688 | associate them with this target. | ||
| 689 | 697 | ||
| 690 | Note that for Target_Image_Files, we only want files from the previous | 698 | 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 | 699 | build whose suffix matches one of the suffixes defined in this |
| @@ -711,18 +719,38 @@ class Target(models.Model): | |||
| 711 | image_file.target = self | 719 | image_file.target = self |
| 712 | image_file.save() | 720 | image_file.save() |
| 713 | 721 | ||
| 714 | artifact_files = target.targetartifactfile_set.all() | 722 | kernel_files = target.targetkernelfile_set.all() |
| 715 | for artifact_file in artifact_files: | 723 | for kernel_file in kernel_files: |
| 716 | artifact_file.pk = None | 724 | kernel_file.pk = None |
| 717 | artifact_file.target = self | 725 | kernel_file.target = self |
| 718 | artifact_file.save() | 726 | kernel_file.save() |
| 719 | 727 | ||
| 720 | self.license_manifest_path = target.license_manifest_path | 728 | self.license_manifest_path = target.license_manifest_path |
| 721 | self.save() | 729 | self.save() |
| 722 | 730 | ||
| 723 | # an Artifact is anything that results from a target being built, and may | 731 | def clone_sdk_artifacts_from(self, target): |
| 724 | # be of interest to the user, and is not an image file | 732 | """ |
| 725 | class TargetArtifactFile(models.Model): | 733 | Clone TargetSDKFile objects from target and associate them with this |
| 734 | target. | ||
| 735 | """ | ||
| 736 | sdk_files = target.targetsdkfile_set.all() | ||
| 737 | for sdk_file in sdk_files: | ||
| 738 | sdk_file.pk = None | ||
| 739 | sdk_file.target = self | ||
| 740 | sdk_file.save() | ||
| 741 | |||
| 742 | # kernel artifacts for a target: bzImage and modules* | ||
| 743 | class TargetKernelFile(models.Model): | ||
| 744 | target = models.ForeignKey(Target) | ||
| 745 | file_name = models.FilePathField() | ||
| 746 | file_size = models.IntegerField() | ||
| 747 | |||
| 748 | @property | ||
| 749 | def basename(self): | ||
| 750 | return os.path.basename(self.file_name) | ||
| 751 | |||
| 752 | # SDK artifacts for a target: sh and manifest files | ||
| 753 | class TargetSDKFile(models.Model): | ||
| 726 | target = models.ForeignKey(Target) | 754 | target = models.ForeignKey(Target) |
| 727 | file_name = models.FilePathField() | 755 | file_name = models.FilePathField() |
| 728 | file_size = models.IntegerField() | 756 | file_size = models.IntegerField() |
