// findInstanceSpec returns an InstanceSpec satisfying the supplied instanceConstraint. func findInstanceSpec(baseURLs []string, ic *instances.InstanceConstraint) (*instances.InstanceSpec, error) { if ic.Constraints.CpuPower == nil { ic.Constraints.CpuPower = instances.CpuPower(defaultCpuPower) } ec2Region := allRegions[ic.Region] imageConstraint := imagemetadata.ImageConstraint{ CloudSpec: imagemetadata.CloudSpec{ic.Region, ec2Region.EC2Endpoint}, Series: ic.Series, Arches: ic.Arches, } matchingImages, err := imagemetadata.Fetch( baseURLs, imagemetadata.DefaultIndexPath, &imageConstraint, signedImageDataOnly) if err != nil { return nil, err } if len(matchingImages) == 0 { logger.Warningf("no matching image meta data for constraints: %v", ic) } var images []instances.Image for _, imageMetadata := range matchingImages { // For now, we only want images with "ebs" storage. if imageMetadata.Storage != ebsStorage { continue } im := *imageMetadata images = append(images, instances.Image{ Id: im.Id, VType: im.VType, Arch: im.Arch, }) } // 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) }
// findInstanceSpec returns an image and instance type satisfying the constraint. // The instance type comes from querying the flavors supported by the deployment. func findInstanceSpec(e *environ, ic *instances.InstanceConstraint) (*instances.InstanceSpec, error) { // first construct all available instance types from the supported flavors. nova := e.nova() flavors, err := nova.ListFlavorsDetail() if err != nil { return nil, err } allInstanceTypes := []instances.InstanceType{} for _, flavor := range flavors { instanceType := instances.InstanceType{ Id: flavor.Id, Name: flavor.Name, Arches: ic.Arches, Mem: uint64(flavor.RAM), CpuCores: uint64(flavor.VCPUs), Cost: uint64(flavor.RAM), } allInstanceTypes = append(allInstanceTypes, instanceType) } imageConstraint := imagemetadata.ImageConstraint{ CloudSpec: imagemetadata.CloudSpec{ic.Region, e.ecfg().authURL()}, Series: ic.Series, Arches: ic.Arches, } baseURLs, err := e.getImageBaseURLs() if err != nil { return nil, err } // TODO (wallyworld): use an env parameter (default true) to mandate use of only signed image metadata. matchingImages, err := imagemetadata.Fetch(baseURLs, imagemetadata.DefaultIndexPath, &imageConstraint, false) if err != nil { return nil, err } var images []instances.Image for _, imageMetadata := range matchingImages { im := *imageMetadata images = append(images, instances.Image{ Id: im.Id, VType: im.VType, Arch: im.Arch, }) } spec, err := instances.FindInstanceSpec(images, ic, allInstanceTypes) if err != nil { return nil, err } return spec, nil }