~ubuntu-branches/ubuntu/saucy/juju-core/saucy-proposed

« back to all changes in this revision

Viewing changes to src/launchpad.net/juju-core/worker/deployer/simple.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-07-11 17:18:27 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20130711171827-vjqkg40r0dlf7ys2
Tags: 1.11.2-0ubuntu1
* New upstream release.
* Make juju-core the default juju (LP: #1190634):
  - d/control: Add virtual package juju -> juju-core.
  - d/juju-core.postinst.in: Bump priority of alternatives over that of
    python juju packages.
* Enable for all architectures (LP: #1172505):
  - d/control: Version BD on golang-go to >= 2:1.1.1 to ensure CGO
    support for non-x86 archs, make juju-core Arch: any.
  - d/README.source: Dropped - no longer required.
* d/watch: Updated for new upstream tarball naming.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2012, 2013 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
1
4
package deployer
2
5
 
3
6
import (
9
12
        "strings"
10
13
 
11
14
        "launchpad.net/juju-core/environs/agent"
12
 
        "launchpad.net/juju-core/log"
13
15
        "launchpad.net/juju-core/log/syslog"
14
16
        "launchpad.net/juju-core/state"
 
17
        "launchpad.net/juju-core/state/api"
15
18
        "launchpad.net/juju-core/upstart"
16
19
        "launchpad.net/juju-core/version"
17
20
)
20
23
// jobs on the local system.
21
24
type SimpleContext struct {
22
25
 
23
 
        // Addrser is used to get the current state server addresses at the time
 
26
        // addresser is used to get the current state server addresses at the time
24
27
        // the given unit is deployed.
25
28
        addresser Addresser
26
29
 
27
 
        // CACert holds the CA certificate that will be used
 
30
        // caCert holds the CA certificate that will be used
28
31
        // to validate the state server's certificate, in PEM format.
29
32
        caCert []byte
30
33
 
31
 
        // DeployerTag identifies the agent on whose behalf this context is running.
32
 
        deployerTag string
33
 
 
34
 
        // InitDir specifies the directory used by upstart on the local system.
 
34
        // initDir specifies the directory used by upstart on the local system.
35
35
        // It is typically set to "/etc/init".
36
36
        initDir string
37
37
 
38
 
        // DataDir specifies the directory used by juju to store its state. It
 
38
        // dataDir specifies the directory used by juju to store its state. It
39
39
        // is typically set to "/var/lib/juju".
40
40
        dataDir string
41
41
 
42
 
        // LogDir specifies the directory to which installed units will write
 
42
        // logDir specifies the directory to which installed units will write
43
43
        // their log files. It is typically set to "/var/log/juju".
44
44
        logDir string
45
45
 
59
59
// "/etc/init" logging to "/var/log/juju". Paths to which agents and tools
60
60
// are installed are relative to dataDir; if dataDir is empty, it will be
61
61
// set to "/var/lib/juju".
62
 
func NewSimpleContext(dataDir string, CACert []byte, deployerTag string, addresser Addresser) *SimpleContext {
 
62
func NewSimpleContext(dataDir string, caCert []byte, addresser Addresser) *SimpleContext {
63
63
        if dataDir == "" {
64
64
                dataDir = "/var/lib/juju"
65
65
        }
66
66
        return &SimpleContext{
67
 
                addresser:   addresser,
68
 
                caCert:      CACert,
69
 
                deployerTag: deployerTag,
70
 
                initDir:     "/etc/init",
71
 
                dataDir:     dataDir,
72
 
                logDir:      "/var/log/juju",
 
67
                addresser: addresser,
 
68
                caCert:    caCert,
 
69
                initDir:   "/etc/init",
 
70
                dataDir:   dataDir,
 
71
                logDir:    "/var/log/juju",
73
72
        }
74
73
}
75
74
 
86
85
        toolsDir := agent.ToolsDir(ctx.dataDir, tag)
87
86
        defer removeOnErr(&err, toolsDir)
88
87
 
89
 
        info := state.Info{
90
 
                Addrs:  ctx.addresser.Addresses(),
 
88
        // Retrieve addresses from state.
 
89
        stateAddrs, err := ctx.addresser.Addresses()
 
90
        if err != nil {
 
91
                return err
 
92
        }
 
93
        apiAddrs, err := ctx.addresser.APIAddresses()
 
94
        if err != nil {
 
95
                return err
 
96
        }
 
97
 
 
98
        stateInfo := state.Info{
 
99
                Addrs:  stateAddrs,
 
100
                Tag:    tag,
 
101
                CACert: ctx.caCert,
 
102
        }
 
103
        apiInfo := api.Info{
 
104
                Addrs:  apiAddrs,
91
105
                Tag:    tag,
92
106
                CACert: ctx.caCert,
93
107
        }
95
109
        conf := &agent.Conf{
96
110
                DataDir:     ctx.dataDir,
97
111
                OldPassword: initialPassword,
98
 
                StateInfo:   &info,
 
112
                StateInfo:   &stateInfo,
 
113
                APIInfo:     &apiInfo,
99
114
        }
100
115
        if err := conf.Write(); err != nil {
101
116
                return err
104
119
 
105
120
        // Install an upstart job that runs the unit agent.
106
121
        logPath := path.Join(ctx.logDir, tag+".log")
107
 
        syslogConfigRenderer := syslog.NewForwardConfig(
108
 
                tag, ctx.addresser.Addresses())
 
122
        syslogConfigRenderer := syslog.NewForwardConfig(tag, stateAddrs)
109
123
        syslogConfigRenderer.ConfigDir = ctx.syslogConfigDir
110
124
        syslogConfigRenderer.ConfigFileName = fmt.Sprintf("26-juju-%s.conf", tag)
111
125
        if err := syslogConfigRenderer.Write(); err != nil {
112
126
                return err
113
127
        }
114
128
        ctx.syslogConfigPath = syslogConfigRenderer.ConfigFilePath()
115
 
        if e := syslog.Restart(); e != nil {
116
 
                log.Warningf("installer: cannot restart syslog daemon: %v", e)
 
129
        if err := syslog.Restart(); err != nil {
 
130
                logger.Warningf("installer: cannot restart syslog daemon: %v", err)
117
131
        }
118
132
        defer removeOnErr(&err, ctx.syslogConfigPath)
119
133
 
132
146
        return uconf.Install()
133
147
}
134
148
 
 
149
// findUpstartJob tries to find an upstart job matching the
 
150
// given unit name in one of these formats:
 
151
//   jujud-<deployer-tag>:<unit-tag>.conf (for compatibility)
 
152
//   jujud-<unit-tag>.conf (default)
 
153
func (ctx *SimpleContext) findUpstartJob(unitName string) *upstart.Service {
 
154
        unitsAndJobs, err := ctx.deployedUnitsUpstartJobs()
 
155
        if err != nil {
 
156
                return nil
 
157
        }
 
158
        if job, ok := unitsAndJobs[unitName]; ok {
 
159
                svc := upstart.NewService(job)
 
160
                svc.InitDir = ctx.initDir
 
161
                return svc
 
162
        }
 
163
        return nil
 
164
}
 
165
 
135
166
func (ctx *SimpleContext) RecallUnit(unitName string) error {
136
 
        svc := ctx.upstartService(unitName)
137
 
        if !svc.Installed() {
 
167
        svc := ctx.findUpstartJob(unitName)
 
168
        if svc == nil || !svc.Installed() {
138
169
                return fmt.Errorf("unit %q is not deployed", unitName)
139
170
        }
140
171
        if err := svc.Remove(); err != nil {
145
176
        if err := os.RemoveAll(agentDir); err != nil {
146
177
                return err
147
178
        }
148
 
        if e := os.Remove(ctx.syslogConfigPath); e != nil {
149
 
                log.Warningf("installer: cannot remove %q: %v", ctx.syslogConfigPath, e)
150
 
        }
151
 
        if e := syslog.Restart(); e != nil {
152
 
                log.Warningf("installer: cannot restart syslog daemon: %v", e)
153
 
        }
 
179
        if err := os.Remove(ctx.syslogConfigPath); err != nil && !os.IsNotExist(err) {
 
180
                logger.Warningf("installer: cannot remove %q: %v", ctx.syslogConfigPath, err)
 
181
        }
 
182
        // Defer this so a failure here does not impede the cleanup (as in tests).
 
183
        defer func() {
 
184
                if err := syslog.Restart(); err != nil {
 
185
                        logger.Warningf("installer: cannot restart syslog daemon: %v", err)
 
186
                }
 
187
        }()
154
188
        toolsDir := agent.ToolsDir(ctx.dataDir, tag)
155
189
        return os.Remove(toolsDir)
156
190
}
157
191
 
158
 
var deployedRe = regexp.MustCompile("^jujud-([a-z0-9-]+):unit-([a-z0-9-]+)-([0-9]+)\\.conf$")
 
192
var deployedRe = regexp.MustCompile("^(jujud-.*unit-([a-z0-9-]+)-([0-9]+))\\.conf$")
159
193
 
160
 
func (ctx *SimpleContext) DeployedUnits() ([]string, error) {
 
194
func (ctx *SimpleContext) deployedUnitsUpstartJobs() (map[string]string, error) {
161
195
        fis, err := ioutil.ReadDir(ctx.initDir)
162
196
        if err != nil {
163
197
                return nil, err
164
198
        }
165
 
        var installed []string
 
199
        installed := make(map[string]string)
166
200
        for _, fi := range fis {
167
201
                if groups := deployedRe.FindStringSubmatch(fi.Name()); len(groups) == 4 {
168
 
                        if groups[1] != ctx.deployerTag {
169
 
                                continue
170
 
                        }
171
202
                        unitName := groups[2] + "/" + groups[3]
172
203
                        if !state.IsUnitName(unitName) {
173
204
                                continue
174
205
                        }
175
 
                        installed = append(installed, unitName)
 
206
                        installed[unitName] = groups[1]
176
207
                }
177
208
        }
178
209
        return installed, nil
179
210
}
180
211
 
 
212
func (ctx *SimpleContext) DeployedUnits() ([]string, error) {
 
213
        unitsAndJobs, err := ctx.deployedUnitsUpstartJobs()
 
214
        if err != nil {
 
215
                return nil, err
 
216
        }
 
217
        var installed []string
 
218
        for unitName := range unitsAndJobs {
 
219
                installed = append(installed, unitName)
 
220
        }
 
221
        return installed, nil
 
222
}
 
223
 
181
224
// upstartService returns an upstart.Service corresponding to the specified
182
 
// unit. Its name is badged according to the deployer name for the
183
 
// context, so as to distinguish its own jobs from those installed by other
184
 
// means.
 
225
// unit.
185
226
func (ctx *SimpleContext) upstartService(unitName string) *upstart.Service {
186
227
        tag := state.UnitTag(unitName)
187
 
        svcName := "jujud-" + ctx.deployerTag + ":" + tag
 
228
        svcName := "jujud-" + tag
188
229
        svc := upstart.NewService(svcName)
189
230
        svc.InitDir = ctx.initDir
190
231
        return svc
192
233
 
193
234
func removeOnErr(err *error, path string) {
194
235
        if *err != nil {
195
 
                if e := os.Remove(path); e != nil {
196
 
                        log.Warningf("installer: cannot remove %q: %v", path, e)
 
236
                if err := os.Remove(path); err != nil {
 
237
                        logger.Warningf("installer: cannot remove %q: %v", path, err)
197
238
                }
198
239
        }
199
240
}