github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/provider/vmware/environ_instance.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package vmware 5 6 import ( 7 "github.com/juju/errors" 8 9 "github.com/juju/juju/environs" 10 "github.com/juju/juju/instance" 11 "github.com/juju/juju/provider/common" 12 ) 13 14 // Instances returns the available instances in the environment that 15 // match the provided instance IDs. For IDs that did not match any 16 // instances, the result at the corresponding index will be nil. In that 17 // case the error will be environs.ErrPartialInstances (or 18 // ErrNoInstances if none of the IDs match an instance). 19 func (env *environ) Instances(ids []instance.Id) ([]instance.Instance, error) { 20 if len(ids) == 0 { 21 return nil, environs.ErrNoInstances 22 } 23 24 instances, err := getInstances(env) 25 if err != nil { 26 // We don't return the error since we need to pack one instance 27 // for each ID into the result. If there is a problem then we 28 // will return either ErrPartialInstances or ErrNoInstances. 29 // TODO(ericsnow) Skip returning here only for certain errors? 30 logger.Errorf("failed to get instances from vmware: %v", err) 31 err = errors.Trace(err) 32 } 33 34 // Build the result, matching the provided instance IDs. 35 numFound := 0 // This will never be greater than len(ids). 36 results := make([]instance.Instance, len(ids)) 37 for i, id := range ids { 38 inst := findInst(id, instances) 39 if inst != nil { 40 numFound++ 41 } 42 results[i] = inst 43 } 44 45 if numFound == 0 { 46 if err == nil { 47 err = environs.ErrNoInstances 48 } 49 } else if numFound != len(ids) { 50 err = environs.ErrPartialInstances 51 } 52 return results, err 53 } 54 55 var getInstances = func(env *environ) ([]instance.Instance, error) { 56 return env.instances() 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 google.Instance 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 { 99 results = append(results, instance.Id(inst.Config.Name)) 100 break 101 } 102 } 103 } 104 if len(results) == 0 { 105 return nil, environs.ErrNotBootstrapped 106 } 107 return results, nil 108 }