~ubuntu-branches/ubuntu/utopic/maas/utopic-updates

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez, Michael McCracken
  • Date: 2014-10-22 12:55:08 UTC
  • mfrom: (1.3.2)
  • Revision ID: package-import@ubuntu.com-20141022125508-02a2o8f3y0tw5ig4
Tags: 1.7.0~beta8+bzr3272-0ubuntu1
* New Upstream Release, Beta 8 bzr 3272.
  - Maintain backward compatibility with status codes to not break
    client MAAS API users.  (LP: #1383609)
  - Allow users to disable DHCP NIC scanning during commissioning otherwise
    this can lead machines not being able to commission (LP: #1383384)
  - Ensure that MAAS can correctly download, and install HWE Kernels, and 
    not crash in the process. (LP: #1357532, LP: #1382281)
  - Add a lock to ensure we don't give the same 2 systems to two different
    users when acquiring a machine. (LP: #1382575)

[ Michael McCracken ]
* debian/maas-dns.postrm: ensure named.conf is cleaned of maas
  includes (LP: #1346538)

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
    BootSourceCache,
54
54
    BootSourceSelection,
55
55
    Config,
 
56
    LargeFile,
56
57
    Node,
57
58
    )
58
59
from maasserver.views import HelpfulDeleteView
460
461
            self.add_resource_template_attributes(resource)
461
462
        return resources
462
463
 
 
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
 
463
601
    def ajax(self, request, *args, **kwargs):
464
602
        """Return all resources in a json object.
465
603
 
466
604
        This is used by the image model list on the client side to update
467
605
        the status of images."""
468
 
        resources = list(BootResource.objects.all())
469
 
        for resource in resources:
470
 
            self.add_resource_template_attributes(resource)
 
606
        resources = self.combine_hwe_resources(BootResource.objects.all())
471
607
        json_resources = [
472
608
            dict(
473
609
                id=resource.id,