github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/provider/ec2/image.go (about)

     1  // Copyright 2011, 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package ec2
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/juju/environs/imagemetadata"
    10  	"github.com/juju/juju/environs/instances"
    11  	"github.com/juju/juju/environs/simplestreams"
    12  )
    13  
    14  // signedImageDataOnly is defined here to allow tests to override the content.
    15  // If true, only inline PGP signed image metadata will be used.
    16  var signedImageDataOnly = true
    17  
    18  // defaultCpuPower is larger the smallest instance's cpuPower, and no larger than
    19  // any other instance type's cpuPower. It is used when no explicit CpuPower
    20  // constraint exists, preventing the smallest instance from being chosen unless
    21  // the user has clearly indicated that they are willing to accept poor performance.
    22  const defaultCpuPower = 100
    23  
    24  // filterImages returns only that subset of the input (in the same order) that
    25  // this provider finds suitable.
    26  func filterImages(images []*imagemetadata.ImageMetadata, ic *instances.InstanceConstraint) []*imagemetadata.ImageMetadata {
    27  	// Gather the images for each available storage type.
    28  	imagesByStorage := make(map[string][]*imagemetadata.ImageMetadata)
    29  	for _, image := range images {
    30  		imagesByStorage[image.Storage] = append(imagesByStorage[image.Storage], image)
    31  	}
    32  	// If a storage constraint has been specified, use that or else default to ssd.
    33  	storageTypes := []string{ssdStorage}
    34  	if ic != nil && len(ic.Storage) > 0 {
    35  		storageTypes = ic.Storage
    36  	}
    37  	// Return the first set of images for which we have a storage type match.
    38  	for _, storageType := range storageTypes {
    39  		if len(imagesByStorage[storageType]) > 0 {
    40  			return imagesByStorage[storageType]
    41  		}
    42  	}
    43  	return nil
    44  }
    45  
    46  // findInstanceSpec returns an InstanceSpec satisfying the supplied instanceConstraint.
    47  func findInstanceSpec(
    48  	sources []simplestreams.DataSource, stream string, ic *instances.InstanceConstraint) (*instances.InstanceSpec, error) {
    49  
    50  	// If the instance type is set, don't also set a default CPU power
    51  	// as this is implied.
    52  	cons := ic.Constraints
    53  	if cons.CpuPower == nil && (cons.InstanceType == nil || *cons.InstanceType == "") {
    54  		ic.Constraints.CpuPower = instances.CpuPower(defaultCpuPower)
    55  	}
    56  	ec2Region := allRegions[ic.Region]
    57  	imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{
    58  		CloudSpec: simplestreams.CloudSpec{ic.Region, ec2Region.EC2Endpoint},
    59  		Series:    []string{ic.Series},
    60  		Arches:    ic.Arches,
    61  		Stream:    stream,
    62  	})
    63  	matchingImages, _, err := imagemetadata.Fetch(sources, imageConstraint, signedImageDataOnly)
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  	if len(matchingImages) == 0 {
    68  		logger.Warningf("no matching image meta data for constraints: %v", ic)
    69  	}
    70  	suitableImages := filterImages(matchingImages, ic)
    71  	images := instances.ImageMetadataToImages(suitableImages)
    72  
    73  	// Make a copy of the known EC2 instance types, filling in the cost for the specified region.
    74  	regionCosts := allRegionCosts[ic.Region]
    75  	if len(regionCosts) == 0 && len(allRegionCosts) > 0 {
    76  		return nil, fmt.Errorf("no instance types found in %s", ic.Region)
    77  	}
    78  
    79  	var itypesWithCosts []instances.InstanceType
    80  	for _, itype := range allInstanceTypes {
    81  		cost, ok := regionCosts[itype.Name]
    82  		if !ok {
    83  			continue
    84  		}
    85  		itWithCost := itype
    86  		itWithCost.Cost = cost
    87  		itypesWithCosts = append(itypesWithCosts, itWithCost)
    88  	}
    89  	return instances.FindInstanceSpec(images, ic, itypesWithCosts)
    90  }