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"
20
23
// jobs on the local system.
21
24
type SimpleContext struct {
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
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.
31
// DeployerTag identifies the agent on whose behalf this context is running.
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".
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".
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".
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 {
64
64
dataDir = "/var/lib/juju"
66
66
return &SimpleContext{
69
deployerTag: deployerTag,
72
logDir: "/var/log/juju",
71
logDir: "/var/log/juju",
86
85
toolsDir := agent.ToolsDir(ctx.dataDir, tag)
87
86
defer removeOnErr(&err, toolsDir)
90
Addrs: ctx.addresser.Addresses(),
88
// Retrieve addresses from state.
89
stateAddrs, err := ctx.addresser.Addresses()
93
apiAddrs, err := ctx.addresser.APIAddresses()
98
stateInfo := state.Info{
92
106
CACert: ctx.caCert,
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 {
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)
118
132
defer removeOnErr(&err, ctx.syslogConfigPath)
132
146
return uconf.Install()
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()
158
if job, ok := unitsAndJobs[unitName]; ok {
159
svc := upstart.NewService(job)
160
svc.InitDir = ctx.initDir
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)
140
171
if err := svc.Remove(); err != nil {
145
176
if err := os.RemoveAll(agentDir); err != nil {
148
if e := os.Remove(ctx.syslogConfigPath); e != nil {
149
log.Warningf("installer: cannot remove %q: %v", ctx.syslogConfigPath, e)
151
if e := syslog.Restart(); e != nil {
152
log.Warningf("installer: cannot restart syslog daemon: %v", e)
179
if err := os.Remove(ctx.syslogConfigPath); err != nil && !os.IsNotExist(err) {
180
logger.Warningf("installer: cannot remove %q: %v", ctx.syslogConfigPath, err)
182
// Defer this so a failure here does not impede the cleanup (as in tests).
184
if err := syslog.Restart(); err != nil {
185
logger.Warningf("installer: cannot restart syslog daemon: %v", err)
154
188
toolsDir := agent.ToolsDir(ctx.dataDir, tag)
155
189
return os.Remove(toolsDir)
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$")
160
func (ctx *SimpleContext) DeployedUnits() ([]string, error) {
194
func (ctx *SimpleContext) deployedUnitsUpstartJobs() (map[string]string, error) {
161
195
fis, err := ioutil.ReadDir(ctx.initDir)
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 {
171
202
unitName := groups[2] + "/" + groups[3]
172
203
if !state.IsUnitName(unitName) {
175
installed = append(installed, unitName)
206
installed[unitName] = groups[1]
178
209
return installed, nil
212
func (ctx *SimpleContext) DeployedUnits() ([]string, error) {
213
unitsAndJobs, err := ctx.deployedUnitsUpstartJobs()
217
var installed []string
218
for unitName := range unitsAndJobs {
219
installed = append(installed, unitName)
221
return installed, nil
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
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
193
234
func removeOnErr(err *error, path string) {
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)