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 }