github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/provider/vsphere/environ_instance.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 "strings" 10 11 "github.com/juju/errors" 12 13 "github.com/juju/juju/environs" 14 "github.com/juju/juju/instance" 15 ) 16 17 // Instances returns the available instances in the environment that 18 // match the provided instance IDs. For IDs that did not match any 19 // instances, the result at the corresponding index will be nil. In that 20 // case the error will be environs.ErrPartialInstances (or 21 // ErrNoInstances if none of the IDs match an instance). 22 func (env *environ) Instances(ids []instance.Id) ([]instance.Instance, error) { 23 if len(ids) == 0 { 24 return nil, environs.ErrNoInstances 25 } 26 27 instances, err := env.instances() 28 if err != nil { 29 // We don't return the error since we need to pack one instance 30 // for each ID into the result. If there is a problem then we 31 // will return either ErrPartialInstances or ErrNoInstances. 32 // TODO(ericsnow) Skip returning here only for certain errors? 33 logger.Errorf("failed to get instances from vmware: %v", err) 34 err = errors.Trace(err) 35 } 36 37 // Build the result, matching the provided instance IDs. 38 numFound := 0 // This will never be greater than len(ids). 39 results := make([]instance.Instance, len(ids)) 40 for i, id := range ids { 41 inst := findInst(id, instances) 42 if inst != nil { 43 numFound++ 44 } 45 results[i] = inst 46 } 47 48 if numFound == 0 { 49 if err == nil { 50 err = environs.ErrNoInstances 51 } 52 } else if numFound != len(ids) { 53 err = environs.ErrPartialInstances 54 } 55 return results, err 56 } 57 58 // instances returns a list of all "alive" instances in the environment. 59 // This means only instances where the IDs match 60 // "juju-<env name>-machine-*". This is important because otherwise juju 61 // will see they are not tracked in state, assume they're stale/rogue, 62 // and shut them down. 63 func (env *environ) instances() ([]instance.Instance, error) { 64 prefix := env.namespace.Prefix() 65 instances, err := env.client.Instances(prefix) 66 err = errors.Trace(err) 67 68 // Turn mo.VirtualMachine values into *environInstance values, 69 // whether or not we got an error. 70 var results []instance.Instance 71 for _, base := range instances { 72 inst := newInstance(base, env) 73 results = append(results, inst) 74 } 75 76 return results, err 77 } 78 79 // ControllerInstances returns the IDs of the instances corresponding 80 // to juju controllers. 81 func (env *environ) ControllerInstances(controllerUUID string) ([]instance.Id, error) { 82 instances, err := env.client.Instances("juju-") 83 if err != nil { 84 return nil, errors.Trace(err) 85 } 86 87 var results []instance.Id 88 for _, inst := range instances { 89 metadata := inst.Config.ExtraConfig 90 for _, item := range metadata { 91 value := item.GetOptionValue() 92 if value.Key == metadataKeyControllerUUID && value.Value != controllerUUID { 93 continue 94 } 95 if value.Key == metadataKeyIsController && value.Value == metadataValueIsController { 96 results = append(results, instance.Id(inst.Name)) 97 break 98 } 99 } 100 } 101 if len(results) == 0 { 102 return nil, environs.ErrNotBootstrapped 103 } 104 return results, nil 105 } 106 107 // parsePlacement extracts the availability zone from the placement 108 // string and returns it. If no zone is found there then an error is 109 // returned. 110 func (env *environ) parsePlacement(placement string) (*vmwareAvailZone, error) { 111 if placement == "" { 112 return nil, nil 113 } 114 115 pos := strings.IndexRune(placement, '=') 116 if pos == -1 { 117 return nil, errors.Errorf("unknown placement directive: %v", placement) 118 } 119 120 switch key, value := placement[:pos], placement[pos+1:]; key { 121 case "zone": 122 zone, err := env.availZone(value) 123 if err != nil { 124 return nil, errors.Trace(err) 125 } 126 return zone, nil 127 } 128 return nil, errors.Errorf("unknown placement directive: %v", placement) 129 }