~juju-qa/ubuntu/yakkety/juju/2.0-rc3-again

« back to all changes in this revision

Viewing changes to src/launchpad.net/juju-core/environs/tools.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-04-24 22:34:47 UTC
  • Revision ID: package-import@ubuntu.com-20130424223447-f0qdji7ubnyo0s71
Tags: upstream-1.10.0.1
ImportĀ upstreamĀ versionĀ 1.10.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package environs
 
2
 
 
3
import (
 
4
        "fmt"
 
5
        "launchpad.net/juju-core/constraints"
 
6
        "launchpad.net/juju-core/environs/tools"
 
7
        "launchpad.net/juju-core/log"
 
8
        "launchpad.net/juju-core/state"
 
9
        "launchpad.net/juju-core/version"
 
10
)
 
11
 
 
12
// FindAvailableTools returns a tools.List containing all tools with a given
 
13
// major version number available in the environment.
 
14
// If *any* tools are present in private storage, *only* tools from private
 
15
// storage are available.
 
16
// If *no* tools are present in private storage, *only* tools from public
 
17
// storage are available.
 
18
// If no *available* tools have the supplied major version number, the function
 
19
// returns a *NotFoundError.
 
20
func FindAvailableTools(environ Environ, majorVersion int) (list tools.List, err error) {
 
21
        log.Infof("environs: reading tools with major version %d", majorVersion)
 
22
        defer convertToolsError(&err)
 
23
        list, err = tools.ReadList(environ.Storage(), majorVersion)
 
24
        if err == tools.ErrNoTools {
 
25
                log.Infof("environs: falling back to public bucket")
 
26
                list, err = tools.ReadList(environ.PublicStorage(), majorVersion)
 
27
        }
 
28
        return list, err
 
29
}
 
30
 
 
31
// FindBootstrapTools returns a ToolsList containing only those tools with
 
32
// which it would be reasonable to launch an environment's first machine,
 
33
// given the supplied constraints.
 
34
// If the environment was not already configured to use a specific agent
 
35
// version, the newest available version will be chosen and set in the
 
36
// environment's configuration.
 
37
func FindBootstrapTools(environ Environ, cons constraints.Value) (list tools.List, err error) {
 
38
        defer convertToolsError(&err)
 
39
        // Collect all possible compatible tools.
 
40
        cliVersion := version.Current.Number
 
41
        if list, err = FindAvailableTools(environ, cliVersion.Major); err != nil {
 
42
                return nil, err
 
43
        }
 
44
 
 
45
        // Discard all that are known to be irrelevant.
 
46
        cfg := environ.Config()
 
47
        series := cfg.DefaultSeries()
 
48
        log.Infof("environs: filtering tools by series: %s", series)
 
49
        filter := tools.Filter{Series: series}
 
50
        if cons.Arch != nil && *cons.Arch != "" {
 
51
                log.Infof("environs: filtering tools by architecture: %s", *cons.Arch)
 
52
                filter.Arch = *cons.Arch
 
53
        }
 
54
        if agentVersion, ok := cfg.AgentVersion(); ok {
 
55
                // If we already have an explicit agent version set, we're done.
 
56
                log.Infof("environs: filtering tools by version: %s", agentVersion)
 
57
                filter.Number = agentVersion
 
58
                return list.Match(filter)
 
59
        }
 
60
        if dev := cliVersion.IsDev() || cfg.Development(); !dev {
 
61
                log.Infof("environs: filtering tools by released version")
 
62
                filter.Released = true
 
63
        }
 
64
        if list, err = list.Match(filter); err != nil {
 
65
                return nil, err
 
66
        }
 
67
 
 
68
        // We probably still have a mix of versions available; discard older ones
 
69
        // and update environment configuration to use only those remaining.
 
70
        agentVersion, list := list.Newest()
 
71
        log.Infof("environs: picked newest version: %s", agentVersion)
 
72
        cfg, err = cfg.Apply(map[string]interface{}{
 
73
                "agent-version": agentVersion.String(),
 
74
        })
 
75
        if err == nil {
 
76
                err = environ.SetConfig(cfg)
 
77
        }
 
78
        if err != nil {
 
79
                return nil, fmt.Errorf("failed to update environment configuration: %v", err)
 
80
        }
 
81
        return list, nil
 
82
}
 
83
 
 
84
// FindInstanceTools returns a ToolsList containing only those tools with which
 
85
// it would be reasonable to start a new instance, given the supplied series and
 
86
// constraints.
 
87
// It is an error to call it with an environment not already configured to use
 
88
// a specific agent version.
 
89
func FindInstanceTools(environ Environ, series string, cons constraints.Value) (list tools.List, err error) {
 
90
        defer convertToolsError(&err)
 
91
        // Collect all possible compatible tools.
 
92
        agentVersion, ok := environ.Config().AgentVersion()
 
93
        if !ok {
 
94
                return nil, fmt.Errorf("no agent version set in environment configuration")
 
95
        }
 
96
        if list, err = FindAvailableTools(environ, agentVersion.Major); err != nil {
 
97
                return nil, err
 
98
        }
 
99
 
 
100
        // Discard all that are known to be irrelevant.
 
101
        log.Infof("environs: filtering tools by version: %s", agentVersion)
 
102
        log.Infof("environs: filtering tools by series: %s", series)
 
103
        filter := tools.Filter{
 
104
                Number: agentVersion,
 
105
                Series: series,
 
106
        }
 
107
        if cons.Arch != nil && *cons.Arch != "" {
 
108
                log.Infof("environs: filtering tools by architecture: %s", *cons.Arch)
 
109
                filter.Arch = *cons.Arch
 
110
        }
 
111
        return list.Match(filter)
 
112
}
 
113
 
 
114
// FindExactTools returns only the tools that match the supplied version.
 
115
// TODO(fwereade) this should not exist: it's used by cmd/jujud/Upgrader,
 
116
// which needs to run on every agent and must absolutely *not* in general
 
117
// have access to an Environ.
 
118
func FindExactTools(environ Environ, vers version.Binary) (t *state.Tools, err error) {
 
119
        defer convertToolsError(&err)
 
120
        list, err := FindAvailableTools(environ, vers.Major)
 
121
        if err != nil {
 
122
                return nil, err
 
123
        }
 
124
        log.Infof("environs: finding exact version %s", vers)
 
125
        list, err = list.Match(tools.Filter{
 
126
                Number: vers.Number,
 
127
                Series: vers.Series,
 
128
                Arch:   vers.Arch,
 
129
        })
 
130
        if err != nil {
 
131
                return nil, err
 
132
        }
 
133
        return list[0], nil
 
134
}
 
135
 
 
136
func isToolsError(err error) bool {
 
137
        switch err {
 
138
        case tools.ErrNoTools, tools.ErrNoMatches:
 
139
                return true
 
140
        }
 
141
        return false
 
142
}
 
143
 
 
144
func convertToolsError(err *error) {
 
145
        if isToolsError(*err) {
 
146
                *err = &NotFoundError{*err}
 
147
        }
 
148
}