~mpontillo/maas/dns-template-changes-1.7

« back to all changes in this revision

Viewing changes to src/maasserver/views/images.py

  • Committer: MaaS Lander
  • Author(s): Raphael Badin
  • Date: 2014-10-17 16:21:20 UTC
  • mfrom: (3263.2.1 revert-r-3263)
  • Revision ID: maas_lander-20141017162120-2f1sa7apve0uiryq
[r=andreserl][bug=][author=rvb] Revert revision 3263;  this change broke the CI: nodes cannot be commissioned (no-such-image error) with this change.

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
    BootSourceCache,
54
54
    BootSourceSelection,
55
55
    Config,
56
 
    LargeFile,
57
56
    Node,
58
57
    )
59
58
from maasserver.views import HelpfulDeleteView
461
460
            self.add_resource_template_attributes(resource)
462
461
        return resources
463
462
 
464
 
    def is_hwe_resource(self, resource):
465
 
        """Return True if the resource is an Ubuntu HWE resource."""
466
 
        if resource.rtype != BOOT_RESOURCE_TYPE.SYNCED:
467
 
            return False
468
 
        if not resource.name.startswith('ubuntu/'):
469
 
            return False
470
 
        arch, subarch = resource.split_arch()
471
 
        return subarch.startswith('hwe-')
472
 
 
473
 
    def pick_latest_datetime(self, time, other_time):
474
 
        """Return the datetime that is the latest."""
475
 
        if time is None:
476
 
            return other_time
477
 
        return max([time, other_time])
478
 
 
479
 
    def calculate_unique_size_for_resources(self, resources):
480
 
        """Return size of all unique largefiles for the given resources."""
481
 
        shas = set()
482
 
        size = 0
483
 
        for resource in resources:
484
 
            resource_set = resource.get_latest_set()
485
 
            if resource_set is None:
486
 
                continue
487
 
            for rfile in resource_set.files.all():
488
 
                try:
489
 
                    largefile = rfile.largefile
490
 
                except LargeFile.DoesNotExist:
491
 
                    continue
492
 
                if largefile.sha256 not in shas:
493
 
                    size += largefile.total_size
494
 
                    shas.add(largefile.sha256)
495
 
        return size
496
 
 
497
 
    def are_all_resources_complete(self, resources):
498
 
        """Return the complete status for all the given resources."""
499
 
        for resource in resources:
500
 
            resource_set = resource.get_latest_set()
501
 
            if resource_set is None:
502
 
                return False
503
 
            if not resource_set.complete:
504
 
                return False
505
 
        return True
506
 
 
507
 
    def get_last_update_for_resources(self, resources):
508
 
        """Return the latest updated time for all resources."""
509
 
        last_update = None
510
 
        for resource in resources:
511
 
            last_update = self.pick_latest_datetime(
512
 
                last_update, resource.updated)
513
 
            resource_set = resource.get_latest_set()
514
 
            if resource_set is not None:
515
 
                last_update = self.pick_latest_datetime(
516
 
                    last_update, resource_set.updated)
517
 
        return last_update
518
 
 
519
 
    def get_number_of_nodes_for_resources(self, resources):
520
 
        """Return the number of nodes used by all resources."""
521
 
        return sum([
522
 
            self.get_number_of_nodes_deployed_for(resource)
523
 
            for resource in resources])
524
 
 
525
 
    def get_progress_for_resources(self, resources):
526
 
        """Return the overall progress for all resources."""
527
 
        size = 0
528
 
        total_size = 0
529
 
        for resource in resources:
530
 
            resource_set = resource.get_latest_set()
531
 
            if resource_set is not None:
532
 
                size += resource_set.size
533
 
                total_size += resource_set.total_size
534
 
        if size <= 0:
535
 
            # Handle division by zero
536
 
            return 0
537
 
        return 100.0 * (size / float(total_size))
538
 
 
539
 
    def hwes_to_resource(self, hwes):
540
 
        """Convert the list of hwes into one resource to be used in the UI."""
541
 
        # Calculate all of the values using all of the hwe resources for
542
 
        # this combination of resources.
543
 
        last_update = self.get_last_update_for_resources(hwes)
544
 
        unique_size = self.calculate_unique_size_for_resources(hwes)
545
 
        number_of_nodes = self.get_number_of_nodes_for_resources(hwes)
546
 
        complete = self.are_all_resources_complete(hwes)
547
 
        progress = self.get_progress_for_resources(hwes)
548
 
 
549
 
        # Set the computed attributes on the first resource as that will
550
 
        # be the only one returned to the UI.
551
 
        resource = hwes[0]
552
 
        resource.arch, resource.subarch = resource.split_arch()
553
 
        resource.title = self.get_resource_title(resource)
554
 
        resource.complete = complete
555
 
        resource.size = format_size(unique_size)
556
 
        resource.last_update = last_update
557
 
        resource.number_of_nodes = number_of_nodes
558
 
        resource.complete = complete
559
 
        if not complete:
560
 
            if progress > 0:
561
 
                resource.status = "Downloading %3.0f%%" % progress
562
 
                resource.downloading = True
563
 
            else:
564
 
                resource.status = "Queued for download"
565
 
                resource.downloading = False
566
 
        else:
567
 
            # See if all the hwe resources exist on all the clusters.
568
 
            cluster_has_hwes = any(
569
 
                hwe in hwes for hwe in self.cluster_resources)
570
 
            if cluster_has_hwes:
571
 
                resource.status = "Complete"
572
 
                resource.downloading = False
573
 
            else:
574
 
                resource.complete = False
575
 
                if self.clusters_syncing:
576
 
                    resource.status = "Syncing to clusters"
577
 
                    resource.downloading = True
578
 
                else:
579
 
                    resource.status = "Waiting for clusters to sync"
580
 
                    resource.downloading = False
581
 
        return resource
582
 
 
583
 
    def combine_hwe_resources(self, resources):
584
 
        """Return a list of resources removing the duplicate hwe resources."""
585
 
        none_hwe_resources = []
586
 
        hwe_resources = defaultdict(list)
587
 
        for resource in resources:
588
 
            if not self.is_hwe_resource(resource):
589
 
                self.add_resource_template_attributes(resource)
590
 
                none_hwe_resources.append(resource)
591
 
            else:
592
 
                arch = resource.split_arch()[0]
593
 
                key = '%s/%s' % (resource.name, arch)
594
 
                hwe_resources[key].append(resource)
595
 
        combined_hwes = [
596
 
            self.hwes_to_resource(hwes)
597
 
            for _, hwes in hwe_resources.items()
598
 
            ]
599
 
        return none_hwe_resources + combined_hwes
600
 
 
601
463
    def ajax(self, request, *args, **kwargs):
602
464
        """Return all resources in a json object.
603
465
 
604
466
        This is used by the image model list on the client side to update
605
467
        the status of images."""
606
 
        resources = self.combine_hwe_resources(BootResource.objects.all())
 
468
        resources = list(BootResource.objects.all())
 
469
        for resource in resources:
 
470
            self.add_resource_template_attributes(resource)
607
471
        json_resources = [
608
472
            dict(
609
473
                id=resource.id,