github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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 ) 12 13 // defaultCpuPower is larger the smallest instance's cpuPower, and no larger than 14 // any other instance type's cpuPower. It is used when no explicit CpuPower 15 // constraint exists, preventing the smallest instance from being chosen unless 16 // the user has clearly indicated that they are willing to accept poor performance. 17 const defaultCpuPower = 100 18 19 // filterImages returns only that subset of the input (in the same order) that 20 // this provider finds suitable. 21 func filterImages(images []*imagemetadata.ImageMetadata, ic *instances.InstanceConstraint) []*imagemetadata.ImageMetadata { 22 // Gather the images for each available storage type. 23 imagesByStorage := make(map[string][]*imagemetadata.ImageMetadata) 24 for _, image := range images { 25 imagesByStorage[image.Storage] = append(imagesByStorage[image.Storage], image) 26 } 27 logger.Debugf("images by storage type %+v", imagesByStorage) 28 // If a storage constraint has been specified, use that or else default to ssd. 29 storageTypes := []string{ssdStorage} 30 if ic != nil && len(ic.Storage) > 0 { 31 storageTypes = ic.Storage 32 } 33 logger.Debugf("filtering storage types %+v", storageTypes) 34 // Return the first set of images for which we have a storage type match. 35 for _, storageType := range storageTypes { 36 if len(imagesByStorage[storageType]) > 0 { 37 return imagesByStorage[storageType] 38 } 39 } 40 // If the user specifies an image ID during bootstrap, then it will not 41 // have a storage type. 42 return imagesByStorage[""] 43 } 44 45 // findInstanceSpec returns an InstanceSpec satisfying the supplied instanceConstraint. 46 func findInstanceSpec( 47 allImageMetadata []*imagemetadata.ImageMetadata, 48 ic *instances.InstanceConstraint, 49 ) (*instances.InstanceSpec, error) { 50 logger.Debugf("received %d image(s)", len(allImageMetadata)) 51 // If the instance type is set, don't also set a default CPU power 52 // as this is implied. 53 cons := ic.Constraints 54 if cons.CpuPower == nil && (cons.InstanceType == nil || *cons.InstanceType == "") { 55 ic.Constraints.CpuPower = instances.CpuPower(defaultCpuPower) 56 } 57 suitableImages := filterImages(allImageMetadata, ic) 58 logger.Debugf("found %d suitable image(s)", len(suitableImages)) 59 images := instances.ImageMetadataToImages(suitableImages) 60 61 // Make a copy of the known EC2 instance types, filling in the cost for the specified region. 62 regionCosts := allRegionCosts[ic.Region] 63 if len(regionCosts) == 0 && len(allRegionCosts) > 0 { 64 return nil, fmt.Errorf("no instance types found in %s", ic.Region) 65 } 66 67 var itypesWithCosts []instances.InstanceType 68 for _, itype := range allInstanceTypes { 69 cost, ok := regionCosts[itype.Name] 70 if !ok { 71 continue 72 } 73 itWithCost := itype 74 itWithCost.Cost = cost 75 itypesWithCosts = append(itypesWithCosts, itWithCost) 76 } 77 return instances.FindInstanceSpec(images, ic, itypesWithCosts) 78 }