github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/provider/azure/instancetype.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package azure
     5  
     6  import (
     7  	"github.com/Azure/azure-sdk-for-go/Godeps/_workspace/src/github.com/Azure/go-autorest/autorest/to"
     8  	"github.com/Azure/azure-sdk-for-go/arm/compute"
     9  	"github.com/juju/errors"
    10  	"github.com/juju/utils/arch"
    11  
    12  	"github.com/juju/juju/constraints"
    13  	"github.com/juju/juju/environs/instances"
    14  	"github.com/juju/juju/provider/azure/internal/imageutils"
    15  )
    16  
    17  const defaultMem = 1024 // 1GiB
    18  
    19  // newInstanceType creates an InstanceType based on a VirtualMachineSize.
    20  func newInstanceType(size compute.VirtualMachineSize) instances.InstanceType {
    21  	// We're not doing real costs for now; just made-up, relative
    22  	// costs, to ensure we choose the right VMs given matching
    23  	// constraints. This was based on the pricing for West US,
    24  	// and assumes that all regions have the same relative costs.
    25  	//
    26  	// DS is the same price as D, but is targeted at Premium Storage.
    27  	// Likewise for GS and G. We put the premium storage variants
    28  	// directly after their non-premium counterparts.
    29  	machineSizeCost := []string{
    30  		"Standard_A0",
    31  		"Standard_A1",
    32  		"Standard_D1",
    33  		"Standard_DS1",
    34  		"Standard_D1_v2",
    35  		"Standard_A2",
    36  		"Standard_D2",
    37  		"Standard_DS2",
    38  		"Standard_D2_v2",
    39  		"Standard_D11",
    40  		"Standard_DS11",
    41  		"Standard_D11_v2",
    42  		"Standard_A3",
    43  		"Standard_D3",
    44  		"Standard_DS3",
    45  		"Standard_D3_v2",
    46  		"Standard_D12",
    47  		"Standard_DS12",
    48  		"Standard_D12_v2",
    49  		"Standard_A5", // Yes, A5 is cheaper than A4.
    50  		"Standard_A4",
    51  		"Standard_A6",
    52  		"Standard_G1",
    53  		"Standard_GS1",
    54  		"Standard_D4",
    55  		"Standard_DS4",
    56  		"Standard_D4_v2",
    57  		"Standard_D13",
    58  		"Standard_DS13",
    59  		"Standard_D13_v2",
    60  		"Standard_A7",
    61  		"Standard_A10",
    62  		"Standard_G2",
    63  		"Standard_GS2",
    64  		"Standard_D5_v2",
    65  		"Standard_D14",
    66  		"Standard_DS14",
    67  		"Standard_D14_v2",
    68  		"Standard_A8",
    69  		"Standard_A11",
    70  		"Standard_G3",
    71  		"Standard_GS3",
    72  		"Standard_A9",
    73  		"Standard_G4",
    74  		"Standard_GS4",
    75  		"Standard_GS5",
    76  		"Standard_G5",
    77  
    78  		// Basic instances are less capable than standard
    79  		// ones, so we don't want to be providing them as
    80  		// a default. This is achieved by costing them at
    81  		// a higher price, even though they are cheaper
    82  		// in reality.
    83  		"Basic_A0",
    84  		"Basic_A1",
    85  		"Basic_A2",
    86  		"Basic_A3",
    87  		"Basic_A4",
    88  	}
    89  
    90  	// Anything not in the list is more expensive that is in the list.
    91  	cost := len(machineSizeCost)
    92  	sizeName := to.String(size.Name)
    93  	for i, name := range machineSizeCost {
    94  		if sizeName == name {
    95  			cost = i
    96  			break
    97  		}
    98  	}
    99  	if cost == len(machineSizeCost) {
   100  		logger.Warningf("found unknown VM size %q", sizeName)
   101  	}
   102  
   103  	vtype := "Hyper-V"
   104  	return instances.InstanceType{
   105  		Id:       sizeName,
   106  		Name:     sizeName,
   107  		Arches:   []string{arch.AMD64},
   108  		CpuCores: uint64(to.Int(size.NumberOfCores)),
   109  		Mem:      uint64(to.Int(size.MemoryInMB)),
   110  		// NOTE(axw) size.OsDiskSizeInMB is the maximum root disk
   111  		// size, but the actual disk size is limited to the size
   112  		// of the image/VHD that the machine is backed by. The
   113  		// Azure Resource Manager APIs do not provide a way of
   114  		// determining the image size.
   115  		//
   116  		// All of the published images that we use are ~30GiB.
   117  		RootDisk: uint64(29495),
   118  		Cost:     uint64(cost),
   119  		VirtType: &vtype,
   120  		// tags are not currently supported by azure
   121  	}
   122  }
   123  
   124  // findInstanceSpec returns the InstanceSpec that best satisfies the supplied
   125  // InstanceConstraint.
   126  //
   127  // NOTE(axw) for now we ignore simplestreams altogether, and go straight to
   128  // Azure's image registry.
   129  func findInstanceSpec(
   130  	client compute.VirtualMachineImagesClient,
   131  	instanceTypesMap map[string]instances.InstanceType,
   132  	constraint *instances.InstanceConstraint,
   133  	imageStream string,
   134  ) (*instances.InstanceSpec, error) {
   135  
   136  	if !constraintHasArch(constraint, arch.AMD64) {
   137  		// Azure only supports AMD64.
   138  		return nil, errors.NotFoundf("%s in arch constraints", arch.AMD64)
   139  	}
   140  
   141  	image, err := imageutils.SeriesImage(constraint.Series, imageStream, constraint.Region, client)
   142  	if err != nil {
   143  		return nil, errors.Trace(err)
   144  	}
   145  	images := []instances.Image{*image}
   146  
   147  	instanceTypes := make([]instances.InstanceType, 0, len(instanceTypesMap))
   148  	for _, instanceType := range instanceTypesMap {
   149  		instanceTypes = append(instanceTypes, instanceType)
   150  	}
   151  	constraint.Constraints = defaultToBaselineSpec(constraint.Constraints)
   152  	return instances.FindInstanceSpec(images, constraint, instanceTypes)
   153  }
   154  
   155  func constraintHasArch(constraint *instances.InstanceConstraint, arch string) bool {
   156  	for _, constraintArch := range constraint.Arches {
   157  		if constraintArch == arch {
   158  			return true
   159  		}
   160  	}
   161  	return false
   162  }
   163  
   164  // If you specify no constraints at all, you're going to get the smallest
   165  // instance type available. In practice that one's a bit small, so unless
   166  // the constraints are deliberately set lower, this gives you a set of
   167  // baseline constraints that are just slightly more ambitious than that.
   168  func defaultToBaselineSpec(constraint constraints.Value) constraints.Value {
   169  	result := constraint
   170  	if !result.HasInstanceType() && result.Mem == nil {
   171  		var value uint64 = defaultMem
   172  		result.Mem = &value
   173  	}
   174  	return result
   175  }