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