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