github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/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 env = env.getSnapshot() 66 67 prefix := common.MachineFullName(env, "") 68 instances, err := env.client.Instances(prefix) 69 err = errors.Trace(err) 70 71 // Turn mo.VirtualMachine values into *environInstance values, 72 // whether or not we got an error. 73 var results []instance.Instance 74 for _, base := range instances { 75 inst := newInstance(base, env) 76 results = append(results, inst) 77 } 78 79 return results, err 80 } 81 82 // StateServerInstances returns the IDs of the instances corresponding 83 // to juju state servers. 84 func (env *environ) StateServerInstances() ([]instance.Id, error) { 85 env = env.getSnapshot() 86 87 prefix := common.MachineFullName(env, "") 88 instances, err := env.client.Instances(prefix) 89 if err != nil { 90 return nil, errors.Trace(err) 91 } 92 93 var results []instance.Id 94 for _, inst := range instances { 95 metadata := inst.Config.ExtraConfig 96 for _, item := range metadata { 97 value := item.GetOptionValue() 98 if value.Key == metadataKeyIsState && value.Value == metadataValueIsState { 99 results = append(results, instance.Id(inst.Name)) 100 break 101 } 102 } 103 } 104 if len(results) == 0 { 105 return nil, environs.ErrNotBootstrapped 106 } 107 return results, nil 108 } 109 110 // parsePlacement extracts the availability zone from the placement 111 // string and returns it. If no zone is found there then an error is 112 // returned. 113 func (env *environ) parsePlacement(placement string) (*vmwareAvailZone, error) { 114 if placement == "" { 115 return nil, nil 116 } 117 118 pos := strings.IndexRune(placement, '=') 119 if pos == -1 { 120 return nil, errors.Errorf("unknown placement directive: %v", placement) 121 } 122 123 switch key, value := placement[:pos], placement[pos+1:]; key { 124 case "zone": 125 zone, err := env.availZone(value) 126 if err != nil { 127 return nil, errors.Trace(err) 128 } 129 return zone, nil 130 } 131 return nil, errors.Errorf("unknown placement directive: %v", placement) 132 }