github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/provider/vsphere/environ_availzones.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // +build !gccgo 5 6 package vsphere 7 8 import ( 9 "github.com/juju/errors" 10 "github.com/juju/govmomi/vim25/mo" 11 12 "github.com/juju/juju/environs" 13 "github.com/juju/juju/instance" 14 "github.com/juju/juju/provider/common" 15 ) 16 17 type vmwareAvailZone struct { 18 r mo.ComputeResource 19 } 20 21 // Name implements common.AvailabilityZone 22 func (z *vmwareAvailZone) Name() string { 23 return z.r.Name 24 } 25 26 // Available implements common.AvailabilityZone 27 func (z *vmwareAvailZone) Available() bool { 28 return true 29 } 30 31 // AvailabilityZones returns all availability zones in the environment. 32 func (env *environ) AvailabilityZones() ([]common.AvailabilityZone, error) { 33 zones, err := env.client.AvailabilityZones() 34 if err != nil { 35 return nil, errors.Trace(err) 36 } 37 38 var result []common.AvailabilityZone 39 for _, zone := range zones { 40 result = append(result, &vmwareAvailZone{*zone}) 41 } 42 return result, nil 43 } 44 45 // InstanceAvailabilityZoneNames returns the names of the availability 46 // zones for the specified instances. The error returned follows the same 47 // rules as Environ.Instances. 48 func (env *environ) InstanceAvailabilityZoneNames(ids []instance.Id) ([]string, error) { 49 instances, err := env.Instances(ids) 50 if err != nil && err != environs.ErrPartialInstances && err != environs.ErrNoInstances { 51 return nil, errors.Trace(err) 52 } 53 54 zones, err := env.client.AvailabilityZones() 55 if err != nil { 56 return nil, errors.Trace(err) 57 } 58 results := make([]string, 0, len(ids)) 59 for _, inst := range instances { 60 for _, zone := range zones { 61 if eInst := inst.(*environInstance); eInst != nil && zone.ResourcePool.Value == eInst.base.ResourcePool.Value { 62 results = append(results, zone.Name) 63 break 64 } 65 } 66 } 67 68 return results, err 69 } 70 71 func (env *environ) availZone(name string) (*vmwareAvailZone, error) { 72 zones, err := env.client.AvailabilityZones() 73 if err != nil { 74 return nil, errors.Trace(err) 75 } 76 for _, z := range zones { 77 if z.Name == name { 78 return &vmwareAvailZone{*z}, nil 79 } 80 } 81 return nil, errors.NotFoundf("invalid availability zone %q", name) 82 } 83 84 //this variable is exported, because it has to be rewritten in external unit tests 85 var AvailabilityZoneAllocations = common.AvailabilityZoneAllocations 86 87 // parseAvailabilityZones returns the availability zones that should be 88 // tried for the given instance spec. If a placement argument was 89 // provided then only that one is returned. Otherwise the environment is 90 // queried for available zones. In that case, the resulting list is 91 // roughly ordered such that the environment's instances are spread 92 // evenly across the region. 93 func (env *environ) parseAvailabilityZones(args environs.StartInstanceParams) ([]string, error) { 94 if args.Placement != "" { 95 // args.Placement will always be a zone name or empty. 96 placement, err := env.parsePlacement(args.Placement) 97 if err != nil { 98 return nil, errors.Trace(err) 99 } 100 return []string{placement.Name()}, nil 101 } 102 103 // If no availability zone is specified, then automatically spread across 104 // the known zones for optimal spread across the instance distribution 105 // group. 106 var group []instance.Id 107 var err error 108 if args.DistributionGroup != nil { 109 group, err = args.DistributionGroup() 110 if err != nil { 111 return nil, errors.Trace(err) 112 } 113 } 114 zoneInstances, err := AvailabilityZoneAllocations(env, group) 115 if err != nil { 116 return nil, errors.Trace(err) 117 } 118 logger.Infof("found %d zones: %v", len(zoneInstances), zoneInstances) 119 120 var zoneNames []string 121 for _, z := range zoneInstances { 122 zoneNames = append(zoneNames, z.ZoneName) 123 } 124 125 if len(zoneNames) == 0 { 126 return nil, errors.NotFoundf("failed to determine availability zones") 127 } 128 129 return zoneNames, nil 130 }