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