github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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/provider/common" 15 "github.com/juju/juju/tools/lxdclient" 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.allInstances() 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 LXD: %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 func findInst(id instance.Id, instances []*environInstance) instance.Instance { 60 for _, inst := range instances { 61 if id == inst.Id() { 62 return inst 63 } 64 } 65 return nil 66 } 67 68 // instances returns a list of all "alive" instances in the environment. 69 // We match machine names to the pattern "juju-<model-UUID>-machine-*" 70 // to ensure that only machines for the environment are returned. This 71 // is necessary to isolate multiple models within the same LXD. 72 func (env *environ) allInstances() ([]*environInstance, error) { 73 prefix := common.MachineFullName(env.Config().UUID(), "") 74 return env.prefixedInstances(prefix) 75 } 76 77 // prefixedInstances returns instances with the specified prefix. 78 func (env *environ) prefixedInstances(prefix string) ([]*environInstance, error) { 79 instances, err := env.raw.Instances(prefix, lxdclient.AliveStatuses...) 80 err = errors.Trace(err) 81 82 // Turn lxdclient.Instance values into *environInstance values, 83 // whether or not we got an error. 84 var results []*environInstance 85 for _, base := range instances { 86 // If we don't make a copy then the same pointer is used for the 87 // base of all resulting instances. 88 copied := base 89 inst := newInstance(&copied, env) 90 results = append(results, inst) 91 } 92 return results, err 93 } 94 95 // ControllerInstances returns the IDs of the instances corresponding 96 // to juju controllers. 97 func (env *environ) ControllerInstances() ([]instance.Id, error) { 98 prefix := common.MachineFullName(env.Config().ControllerUUID(), "") 99 instances, err := env.raw.Instances(prefix, lxdclient.AliveStatuses...) 100 if err != nil { 101 return nil, errors.Trace(err) 102 } 103 104 var results []instance.Id 105 for _, inst := range instances { 106 if inst.Metadata()[tags.JujuIsController] == "true" { 107 results = append(results, instance.Id(inst.Name)) 108 } 109 } 110 if len(results) == 0 { 111 return nil, environs.ErrNotBootstrapped 112 } 113 return results, nil 114 } 115 116 type instPlacement struct{} 117 118 func (env *environ) parsePlacement(placement string) (*instPlacement, error) { 119 if placement == "" { 120 return &instPlacement{}, nil 121 } 122 123 return nil, errors.Errorf("unknown placement directive: %v", placement) 124 }