github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/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  	"github.com/juju/juju/constraints"
     8  	"github.com/juju/juju/environs/imagemetadata"
     9  	"github.com/juju/juju/environs/instances"
    10  )
    11  
    12  // filterImages returns only that subset of the input (in the same order) that
    13  // this provider finds suitable.
    14  func filterImages(images []*imagemetadata.ImageMetadata, ic *instances.InstanceConstraint) []*imagemetadata.ImageMetadata {
    15  	// Gather the images for each available storage type.
    16  	imagesByStorage := make(map[string][]*imagemetadata.ImageMetadata)
    17  	for _, image := range images {
    18  		imagesByStorage[image.Storage] = append(imagesByStorage[image.Storage], image)
    19  	}
    20  	logger.Debugf("images by storage type %+v", imagesByStorage)
    21  	// If a storage constraint has been specified, use that or else default to ssd.
    22  	storageTypes := []string{ssdStorage}
    23  	if ic != nil && len(ic.Storage) > 0 {
    24  		storageTypes = ic.Storage
    25  	}
    26  	logger.Debugf("filtering storage types %+v", storageTypes)
    27  	// Return the first set of images for which we have a storage type match.
    28  	for _, storageType := range storageTypes {
    29  		if len(imagesByStorage[storageType]) > 0 {
    30  			return imagesByStorage[storageType]
    31  		}
    32  	}
    33  	// If the user specifies an image ID during bootstrap, then it will not
    34  	// have a storage type.
    35  	return imagesByStorage[""]
    36  }
    37  
    38  // findInstanceSpec returns an InstanceSpec satisfying the supplied instanceConstraint.
    39  func findInstanceSpec(
    40  	controller bool,
    41  	allImageMetadata []*imagemetadata.ImageMetadata,
    42  	instanceTypes []instances.InstanceType,
    43  	ic *instances.InstanceConstraint,
    44  ) (*instances.InstanceSpec, error) {
    45  	logger.Debugf("received %d image(s)", len(allImageMetadata))
    46  	if controller {
    47  		ic.Constraints = withDefaultControllerConstraints(ic.Constraints)
    48  	} else {
    49  		ic.Constraints = withDefaultNonControllerConstraints(ic.Constraints)
    50  	}
    51  	suitableImages := filterImages(allImageMetadata, ic)
    52  	logger.Debugf("found %d suitable image(s)", len(suitableImages))
    53  	images := instances.ImageMetadataToImages(suitableImages)
    54  	return instances.FindInstanceSpec(images, ic, instanceTypes)
    55  }
    56  
    57  // withDefaultControllerConstraints returns the given constraints,
    58  // updated to choose a default instance type appropriate for a
    59  // controller machine. We use this only if the user does not specify
    60  // any constraints that would otherwise control the instance type
    61  // selection.
    62  //
    63  // At the time of writing, this will choose
    64  //   - t2.medium, for VPC
    65  //   - m3.medium, for EC2-Classic
    66  func withDefaultControllerConstraints(cons constraints.Value) constraints.Value {
    67  	if !cons.HasInstanceType() && !cons.HasCpuCores() && !cons.HasCpuPower() && !cons.HasMem() {
    68  		var mem uint64 = 3.75 * 1024
    69  		cons.Mem = &mem
    70  	}
    71  	return cons
    72  }
    73  
    74  // withDefaultNonControllerConstraints returns the given constraints,
    75  // updated to choose a default instance type appropriate for a
    76  // non-controller machine. We use this only if the user does not
    77  // specify an instance-type, or cpu-power.
    78  //
    79  // At the time of writing, this will choose the cheapest non-burstable
    80  // instance available in the account/region. At the time of writing, that
    81  // is, for example:
    82  //   - m3.medium (for EC2-Classic)
    83  //   - c4.large (e.g. in ap-south-1)
    84  func withDefaultNonControllerConstraints(cons constraints.Value) constraints.Value {
    85  	if !cons.HasInstanceType() && !cons.HasCpuPower() {
    86  		cons.CpuPower = instances.CpuPower(100)
    87  	}
    88  	return cons
    89  }