github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/provider/lxd/environ_instance.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // +build go1.3 5 6 package lxd 7 8 import ( 9 "github.com/juju/errors" 10 11 "github.com/juju/juju/environs" 12 "github.com/juju/juju/environs/tags" 13 "github.com/juju/juju/instance" 14 "github.com/juju/juju/tools/lxdclient" 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.allInstances() 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 LXD: %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 func findInst(id instance.Id, instances []*environInstance) instance.Instance { 59 for _, inst := range instances { 60 if id == inst.Id() { 61 return inst 62 } 63 } 64 return nil 65 } 66 67 // instances returns a list of all "alive" instances in the environment. 68 // We match machine names to the pattern "juju-<model-UUID>-machine-*" 69 // to ensure that only machines for the environment are returned. This 70 // is necessary to isolate multiple models within the same LXD. 71 func (env *environ) allInstances() ([]*environInstance, error) { 72 prefix := env.namespace.Prefix() 73 return env.prefixedInstances(prefix) 74 } 75 76 // prefixedInstances returns instances with the specified prefix. 77 func (env *environ) prefixedInstances(prefix string) ([]*environInstance, error) { 78 instances, err := env.raw.Instances(prefix, lxdclient.AliveStatuses...) 79 err = errors.Trace(err) 80 81 // Turn lxdclient.Instance values into *environInstance values, 82 // whether or not we got an error. 83 var results []*environInstance 84 for _, base := range instances { 85 // If we don't make a copy then the same pointer is used for the 86 // base of all resulting instances. 87 copied := base 88 inst := newInstance(&copied, env) 89 results = append(results, inst) 90 } 91 return results, err 92 } 93 94 // ControllerInstances returns the IDs of the instances corresponding 95 // to juju controllers. 96 func (env *environ) ControllerInstances(controllerUUID string) ([]instance.Id, error) { 97 instances, err := env.raw.Instances("juju-", lxdclient.AliveStatuses...) 98 if err != nil { 99 return nil, errors.Trace(err) 100 } 101 102 var results []instance.Id 103 for _, inst := range instances { 104 if inst.Metadata()[tags.JujuController] != controllerUUID { 105 continue 106 } 107 if inst.Metadata()[tags.JujuIsController] == "true" { 108 results = append(results, instance.Id(inst.Name)) 109 } 110 } 111 if len(results) == 0 { 112 return nil, environs.ErrNotBootstrapped 113 } 114 return results, nil 115 } 116 117 type instPlacement struct{} 118 119 func (env *environ) parsePlacement(placement string) (*instPlacement, error) { 120 if placement == "" { 121 return &instPlacement{}, nil 122 } 123 124 return nil, errors.Errorf("unknown placement directive: %v", placement) 125 }