~rogpeppe/juju-core/azure

1206.2.1 by Martin Packman
Add copyright statement at the top of all go files bar thirdparty
1
// Copyright 2012, 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
3
377.6.3 by Dave Cheney
wip
4
package cloudinit
39.3.2 by Roger Peppe
added initial cloudinit.go file
5
6
import (
390.3.3 by Dave Cheney
cloudinit tests
7
	"encoding/base64"
39.3.2 by Roger Peppe
added initial cloudinit.go file
8
	"fmt"
1389.4.6 by Tim Penhey
Use filepath instead of just path.
9
	"path/filepath"
10
390.3.3 by Dave Cheney
cloudinit tests
11
	"launchpad.net/goyaml"
1389.4.6 by Tim Penhey
Use filepath instead of just path.
12
1409.2.2 by John Arbash Meinel
Turn environs/agent into a top level agent/ package.
13
	"launchpad.net/juju-core/agent"
377.6.5 by Dave Cheney
responding to review feedback
14
	"launchpad.net/juju-core/cloudinit"
1010.3.13 by Benji York
more indirect conflict-fixing; tests pass
15
	"launchpad.net/juju-core/constraints"
450.1.1 by Roger Peppe
environs/cloudinit: use config.Config
16
	"launchpad.net/juju-core/environs/config"
1325.3.7 by Ian Booth
Fix tests
17
	"launchpad.net/juju-core/instance"
1059.1.1 by Ian Booth
Generate rsyslog config for unit log file
18
	"launchpad.net/juju-core/log/syslog"
255 by Gustavo Niemeyer
launchpad.net/juju-core/juju => launchpad.net/juju-core
19
	"launchpad.net/juju-core/state"
849.3.3 by Roger Peppe
environs/cloudinit: some fixed tests
20
	"launchpad.net/juju-core/state/api"
266.1.2 by Dave Cheney
fixed paths
21
	"launchpad.net/juju-core/upstart"
1151.1.1 by Tim Penhey
Trivial rename of trivial -> utils.
22
	"launchpad.net/juju-core/utils"
39.3.2 by Roger Peppe
added initial cloudinit.go file
23
)
24
377.6.1 by Dave Cheney
1029957
25
// MachineConfig represents initialization information for a new juju machine.
26
type MachineConfig struct {
851.1.2 by Roger Peppe
environs/agent, environs/cloudinit: add server ports
27
	// StateServer specifies whether the new machine will run the
28
	// mongo and API servers.
438.1.2 by Dave Cheney
responding to review feedback
29
	StateServer bool
377.6.1 by Dave Cheney
1029957
30
715.3.19 by Roger Peppe
delete more PEM suffixes
31
	// StateServerCert and StateServerKey hold the state server
735.1.1 by Roger Peppe
environs/cloudinit: split server PEM
32
	// certificate and private key in PEM format; they are required when
33
	// StateServer is set, and ignored otherwise.
715.3.19 by Roger Peppe
delete more PEM suffixes
34
	StateServerCert []byte
35
	StateServerKey  []byte
713.4.1 by Roger Peppe
environs/cloudinit: add Config.ServerCertAndKey
36
1236.3.28 by Francesco Banconi
s/MongoPort/StatePort.
37
	// StatePort specifies the TCP port that will be used
851.1.2 by Roger Peppe
environs/agent, environs/cloudinit: add server ports
38
	// by the MongoDB server. It must be non-zero
39
	// if StateServer is true.
1236.3.28 by Francesco Banconi
s/MongoPort/StatePort.
40
	StatePort int
851.1.2 by Roger Peppe
environs/agent, environs/cloudinit: add server ports
41
42
	// APIPort specifies the TCP port that will be used
43
	// by the API server. It must be non-zero
44
	// if StateServer is true.
45
	APIPort int
46
377.6.1 by Dave Cheney
1029957
47
	// StateInfo holds the means for the new instance to communicate with the
544.2.12 by Roger Peppe
all: more zookeeper -> mgo changes
48
	// juju state. Unless the new machine is running a state server (StateServer is
49
	// set), there must be at least one state server address supplied.
619.1.8 by Roger Peppe
environs/cloudinit: check EntityName
50
	// The entity name must match that of the machine being started,
51
	// or be empty when starting a state server.
377.6.1 by Dave Cheney
1029957
52
	StateInfo *state.Info
53
849.4.2 by Roger Peppe
wip
54
	// APIInfo holds the means for the new instance to communicate with the
55
	// juju state API. Unless the new machine is running a state server (StateServer is
56
	// set), there must be at least one state server address supplied.
57
	// The entity name must match that of the machine being started,
58
	// or be empty when starting a state server.
849.3.3 by Roger Peppe
environs/cloudinit: some fixed tests
59
	APIInfo *api.Info
849.4.2 by Roger Peppe
wip
60
1114.1.1 by Dimiter Naydenov
Added MachineNonce to agent.Conf and MachineConfig
61
	// MachineNonce is set at provisioning/bootstrap time and used to
62
	// ensure the agent is running on the correct instance.
63
	MachineNonce string
64
377.6.1 by Dave Cheney
1029957
65
	// Tools is juju tools to be used on the new machine.
66
	Tools *state.Tools
67
478.6.12 by Roger Peppe
rename varDir to dataDir
68
	// DataDir holds the directory that juju state will be put in the new
478.6.2 by Roger Peppe
environs/cloudinit: fix for vardir
69
	// machine.
478.6.12 by Roger Peppe
rename varDir to dataDir
70
	DataDir string
478.6.2 by Roger Peppe
environs/cloudinit: fix for vardir
71
730.3.1 by William Reade
machine IDs are now strings
72
	// MachineId identifies the new machine.
73
	MachineId string
377.6.1 by Dave Cheney
1029957
74
1263.2.14 by Tim Penhey
Don't install lxc on lxc containers just yet.
75
	// MachineContainerType specifies the type of container that the machine
76
	// is.  If the machine is not a container, then the type is "".
1325.3.7 by Ian Booth
Fix tests
77
	MachineContainerType instance.ContainerType
1263.2.14 by Tim Penhey
Don't install lxc on lxc containers just yet.
78
377.6.1 by Dave Cheney
1029957
79
	// AuthorizedKeys specifies the keys that are allowed to
39.4.11 by Roger Peppe
remove admin-secret; make tests run (but not pass)
80
	// connect to the machine (see cloudinit.SSHAddAuthorizedKeys)
81
	// If no keys are supplied, there can be no ssh access to the node.
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
82
	// On a bootstrap machine, that is fatal. On other
83
	// machines it will mean that the ssh, scp and debug-hooks
84
	// commands cannot work.
377.6.1 by Dave Cheney
1029957
85
	AuthorizedKeys string
390.3.1 by Dave Cheney
wip
86
450.1.1 by Roger Peppe
environs/cloudinit: use config.Config
87
	// Config holds the initial environment configuration.
88
	Config *config.Config
1005.5.1 by William Reade
send bootstrap constraints into state via cloudinit bootstrap-state
89
90
	// Constraints holds the initial environment constraints.
1010.3.13 by Benji York
more indirect conflict-fixing; tests pass
91
	Constraints constraints.Value
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
92
}
93
774.2.5 by Roger Peppe
environs/cloudint: unrevert
94
func addScripts(c *cloudinit.Config, scripts ...string) {
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
95
	for _, s := range scripts {
96
		c.AddRunCmd(s)
97
	}
98
}
99
450.1.1 by Roger Peppe
environs/cloudinit: use config.Config
100
func base64yaml(m *config.Config) string {
101
	data, err := goyaml.Marshal(m.AllAttrs())
390.3.1 by Dave Cheney
wip
102
	if err != nil {
103
		// can't happen, these values have been validated a number of times
104
		panic(err)
105
	}
106
	return base64.StdEncoding.EncodeToString(data)
107
}
108
377.6.5 by Dave Cheney
responding to review feedback
109
func New(cfg *MachineConfig) (*cloudinit.Config, error) {
110
	c := cloudinit.New()
866.34.1 by Raphael Badin
Add cloudinit.Configure() and use it in the MAAS provider.
111
	return Configure(cfg, c)
112
}
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
113
866.34.1 by Raphael Badin
Add cloudinit.Configure() and use it in the MAAS provider.
114
func Configure(cfg *MachineConfig, c *cloudinit.Config) (*cloudinit.Config, error) {
115
	if err := verifyConfig(cfg); err != nil {
116
		return nil, err
117
	}
377.6.1 by Dave Cheney
1029957
118
	c.AddSSHAuthorizedKeys(cfg.AuthorizedKeys)
503.1.1 by William Reade
add git package
119
	c.AddPackage("git")
1263.2.14 by Tim Penhey
Don't install lxc on lxc containers just yet.
120
	// Perfectly reasonable to install lxc on environment instances and kvm
121
	// containers.
1325.3.7 by Ian Booth
Fix tests
122
	if cfg.MachineContainerType != instance.LXC {
1263.2.14 by Tim Penhey
Don't install lxc on lxc containers just yet.
123
		c.AddPackage("lxc")
124
	}
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
125
126
	addScripts(c,
1142.4.3 by Roger Peppe
gofmt
127
		"set -xe", // ensure we run all the scripts or abort.
657.2.2 by Roger Peppe
container: use environs.AgentDir
128
		fmt.Sprintf("mkdir -p %s", cfg.DataDir),
129
		"mkdir -p /var/log/juju")
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
130
254.2.2 by Roger Peppe
environs/ec2: add upstart script for provisioning agent
131
	// Make a directory for the tools to live in, then fetch the
132
	// tools and unarchive them into it.
143.5.1 by Roger Peppe
environs/ec2: update cloudinit to (hopefully) run Go on the cloud.
133
	addScripts(c,
299.3.8 by Dave Cheney
addressing review commentss
134
		"bin="+shquote(cfg.jujuTools()),
143.5.1 by Roger Peppe
environs/ec2: update cloudinit to (hopefully) run Go on the cloud.
135
		"mkdir -p $bin",
560.4.5 by Roger Peppe
environs/cloudinit: use --no-verbose
136
		fmt.Sprintf("wget --no-verbose -O - %s | tar xz -C $bin", shquote(cfg.Tools.URL)),
379.4.11 by Roger Peppe
environs/jujutest: machine agent upgrade succeeds
137
		fmt.Sprintf("echo -n %s > $bin/downloaded-url.txt", shquote(cfg.Tools.URL)),
143.5.1 by Roger Peppe
environs/ec2: update cloudinit to (hopefully) run Go on the cloud.
138
	)
139
1240.3.3 by Tim Penhey
Builds at least.
140
	// TODO (thumper): work out how to pass the logging config to the children
254.2.2 by Roger Peppe
environs/ec2: add upstart script for provisioning agent
141
	debugFlag := ""
457.3.7 by Roger Peppe
environs/ec2: internal authorization now works
142
	// TODO: disable debug mode by default when the system is stable.
1240.3.10 by Tim Penhey
More test tweaks.
143
	if true {
144
		debugFlag = " --debug"
145
	}
254.2.2 by Roger Peppe
environs/ec2: add upstart script for provisioning agent
146
1216.3.12 by Roger Peppe
environs/cloudinit: write machine agent config before calling bootstrap-state
147
	if err := cfg.addLogging(c); err != nil {
148
		return nil, err
149
	}
150
151
	// We add the machine agent's configuration info
152
	// before running bootstrap-state so that bootstrap-state
153
	// has a chance to rerwrite it to change the password.
154
	// It would be cleaner to change bootstrap-state to
155
	// be responsible for starting the machine agent itself,
156
	// but this would not be backwardly compatible.
157
	machineTag := state.MachineTag(cfg.MachineId)
158
	_, err := cfg.addAgentInfo(c, machineTag)
159
	if err != nil {
160
		return nil, err
161
	}
162
438.1.2 by Dave Cheney
responding to review feedback
163
	if cfg.StateServer {
1142.1.1 by Dave Cheney
merge from screwed branch
164
		if cfg.NeedMongoPPA() {
165
			c.AddAptSource("ppa:juju/experimental", "1024R/C8068B11")
166
		}
167
		c.AddPackage("mongodb-server")
824.2.2 by Roger Peppe
environs/cloudinit: set StateServerCert and Key in agent.Conf
168
		certKey := string(cfg.StateServerCert) + string(cfg.StateServerKey)
169
		addFile(c, cfg.dataFile("server.pem"), certKey, 0600)
1216.3.12 by Roger Peppe
environs/cloudinit: write machine agent config before calling bootstrap-state
170
		if err := cfg.addMongoToBoot(c); err != nil {
547.1.1 by Gustavo Niemeyer
environs/cloudinit: bootstrap with MongoDB rather than ZK
171
			return nil, err
172
		}
774.2.5 by Roger Peppe
environs/cloudint: unrevert
173
		// We temporarily give bootstrap-state a directory
174
		// of its own so that it can get the state info via the
175
		// same mechanism as other jujud commands.
1216.3.12 by Roger Peppe
environs/cloudinit: write machine agent config before calling bootstrap-state
176
		acfg, err := cfg.addAgentInfo(c, "bootstrap")
774.2.8 by Roger Peppe
wip
177
		if err != nil {
178
			return nil, err
179
		}
774.2.5 by Roger Peppe
environs/cloudint: unrevert
180
		addScripts(c,
181
			cfg.jujuTools()+"/jujud bootstrap-state"+
182
				" --data-dir "+shquote(cfg.DataDir)+
183
				" --env-config "+shquote(base64yaml(cfg.Config))+
1005.5.1 by William Reade
send bootstrap constraints into state via cloudinit bootstrap-state
184
				" --constraints "+shquote(cfg.Constraints.String())+
774.2.5 by Roger Peppe
environs/cloudint: unrevert
185
				debugFlag,
774.2.8 by Roger Peppe
wip
186
			"rm -rf "+shquote(acfg.Dir()),
547.1.1 by Gustavo Niemeyer
environs/cloudinit: bootstrap with MongoDB rather than ZK
187
		)
1216.3.12 by Roger Peppe
environs/cloudinit: write machine agent config before calling bootstrap-state
188
	}
189
1389.4.1 by Tim Penhey
Move the machine agent and mongo upstart service definitions into the upstart package.
190
	if err := cfg.addMachineAgentToBoot(c, machineTag, cfg.MachineId, debugFlag); err != nil {
299.3.8 by Dave Cheney
addressing review commentss
191
		return nil, err
192
	}
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
193
299.3.8 by Dave Cheney
addressing review commentss
194
	// general options
1189.5.1 by Martin Packman
Revert change to cloud-init apt-get upgrade process in r1188
195
	c.SetAptUpgrade(true)
299.3.8 by Dave Cheney
addressing review commentss
196
	c.SetAptUpdate(true)
377.6.5 by Dave Cheney
responding to review feedback
197
	c.SetOutput(cloudinit.OutAll, "| tee -a /var/log/cloud-init-output.log", "")
299.3.8 by Dave Cheney
addressing review commentss
198
	return c, nil
199
}
200
1216.3.12 by Roger Peppe
environs/cloudinit: write machine agent config before calling bootstrap-state
201
func (cfg *MachineConfig) addLogging(c *cloudinit.Config) error {
202
	var configRenderer syslog.SyslogConfigRenderer
203
	if cfg.StateServer {
204
		configRenderer = syslog.NewAccumulateConfig(
205
			state.MachineTag(cfg.MachineId))
206
	} else {
207
		configRenderer = syslog.NewForwardConfig(
208
			state.MachineTag(cfg.MachineId), cfg.stateHostAddrs())
209
	}
210
	content, err := configRenderer.Render()
211
	if err != nil {
212
		return err
213
	}
214
	addScripts(c,
215
		fmt.Sprintf("cat > /etc/rsyslog.d/25-juju.conf << 'EOF'\n%sEOF\n", string(content)),
216
	)
217
	c.AddRunCmd("restart rsyslog")
218
	return nil
219
}
220
774.2.5 by Roger Peppe
environs/cloudint: unrevert
221
func addFile(c *cloudinit.Config, filename, data string, mode uint) {
774.2.1 by Roger Peppe
environs/cloudinit: work in progress - cloudConfig.addFile implementation
222
	p := shquote(filename)
774.2.5 by Roger Peppe
environs/cloudint: unrevert
223
	addScripts(c,
224
		fmt.Sprintf("echo %s > %s", shquote(data), p),
225
		fmt.Sprintf("chmod %o %s", mode, p),
226
	)
774.2.1 by Roger Peppe
environs/cloudinit: work in progress - cloudConfig.addFile implementation
227
}
228
229
func (cfg *MachineConfig) dataFile(name string) string {
1389.4.6 by Tim Penhey
Use filepath instead of just path.
230
	return filepath.Join(cfg.DataDir, name)
774.2.1 by Roger Peppe
environs/cloudinit: work in progress - cloudConfig.addFile implementation
231
}
232
1058.6.1 by Matthew Scott
Builds
233
func (cfg *MachineConfig) agentConfig(tag string) *agent.Conf {
846.1.3 by Roger Peppe
all: changes to use pointer state.Info in agent.Conf
234
	info := *cfg.StateInfo
849.3.3 by Roger Peppe
environs/cloudinit: some fixed tests
235
	apiInfo := *cfg.APIInfo
774.2.14 by Roger Peppe
environs/cloudinit: use agent package
236
	c := &agent.Conf{
824.2.3 by Roger Peppe
gofmt
237
		DataDir:         cfg.DataDir,
846.1.3 by Roger Peppe
all: changes to use pointer state.Info in agent.Conf
238
		StateInfo:       &info,
849.3.7 by Roger Peppe
gofmt
239
		APIInfo:         &apiInfo,
824.2.2 by Roger Peppe
environs/cloudinit: set StateServerCert and Key in agent.Conf
240
		StateServerCert: cfg.StateServerCert,
824.2.3 by Roger Peppe
gofmt
241
		StateServerKey:  cfg.StateServerKey,
1236.3.28 by Francesco Banconi
s/MongoPort/StatePort.
242
		StatePort:       cfg.StatePort,
851.1.6 by Roger Peppe
gofmt
243
		APIPort:         cfg.APIPort,
1114.1.1 by Dimiter Naydenov
Added MachineNonce to agent.Conf and MachineConfig
244
		MachineNonce:    cfg.MachineNonce,
774.2.8 by Roger Peppe
wip
245
	}
1216.3.17 by Roger Peppe
wip
246
	c.OldPassword = cfg.StateInfo.Password
247
774.2.14 by Roger Peppe
environs/cloudinit: use agent package
248
	c.StateInfo.Addrs = cfg.stateHostAddrs()
1058.6.3 by Matthew Scott
Tests pass. This includes refactor for 'Info' objects.
249
	c.StateInfo.Tag = tag
774.2.23 by Roger Peppe
environs/cloudinit: fixes
250
	c.StateInfo.Password = ""
849.3.3 by Roger Peppe
environs/cloudinit: some fixed tests
251
252
	c.APIInfo.Addrs = cfg.apiHostAddrs()
1058.6.3 by Matthew Scott
Tests pass. This includes refactor for 'Info' objects.
253
	c.APIInfo.Tag = tag
849.3.3 by Roger Peppe
environs/cloudinit: some fixed tests
254
	c.APIInfo.Password = ""
255
774.2.14 by Roger Peppe
environs/cloudinit: use agent package
256
	return c
774.2.8 by Roger Peppe
wip
257
}
258
774.2.5 by Roger Peppe
environs/cloudint: unrevert
259
// addAgentInfo adds agent-required information to the agent's directory
260
// and returns the agent directory name.
1216.3.12 by Roger Peppe
environs/cloudinit: write machine agent config before calling bootstrap-state
261
func (cfg *MachineConfig) addAgentInfo(c *cloudinit.Config, tag string) (*agent.Conf, error) {
1058.6.1 by Matthew Scott
Builds
262
	acfg := cfg.agentConfig(tag)
774.2.8 by Roger Peppe
wip
263
	cmds, err := acfg.WriteCommands()
264
	if err != nil {
265
		return nil, err
266
	}
774.2.14 by Roger Peppe
environs/cloudinit: use agent package
267
	addScripts(c, cmds...)
774.2.8 by Roger Peppe
wip
268
	return acfg, nil
774.2.5 by Roger Peppe
environs/cloudint: unrevert
269
}
270
1389.4.1 by Tim Penhey
Move the machine agent and mongo upstart service definitions into the upstart package.
271
func (cfg *MachineConfig) addMachineAgentToBoot(c *cloudinit.Config, tag, machineId, logConfig string) error {
346.2.1 by Roger Peppe
environs/ec2: run agents through symbolic link
272
	// Make the agent run via a symbolic link to the actual tools
273
	// directory, so it can upgrade itself without needing to change
274
	// the upstart script.
1058.6.1 by Matthew Scott
Builds
275
	toolsDir := agent.ToolsDir(cfg.DataDir, tag)
547.1.4 by Gustavo Niemeyer
Applied Dave's review.
276
	// TODO(dfc) ln -nfs, so it doesn't fail if for some reason that the target already exists
657.2.1 by Roger Peppe
environs: add AgentDir
277
	addScripts(c, fmt.Sprintf("ln -s %v %s", cfg.Tools.Binary, shquote(toolsDir)))
278
1389.4.1 by Tim Penhey
Move the machine agent and mongo upstart service definitions into the upstart package.
279
	name := "jujud-" + tag
280
	conf := upstart.MachineAgentUpstartService(name, toolsDir, cfg.DataDir, "/var/log/juju/", tag, machineId, logConfig)
774.2.30 by Roger Peppe
environs/cloudinit: minor changes for review
281
	cmds, err := conf.InstallCommands()
299.3.5 by Dave Cheney
removed cfg.machiner
282
	if err != nil {
1216.3.12 by Roger Peppe
environs/cloudinit: write machine agent config before calling bootstrap-state
283
		return fmt.Errorf("cannot make cloud-init upstart script for the %s agent: %v", tag, err)
547.1.1 by Gustavo Niemeyer
environs/cloudinit: bootstrap with MongoDB rather than ZK
284
	}
774.2.5 by Roger Peppe
environs/cloudint: unrevert
285
	addScripts(c, cmds...)
1216.3.12 by Roger Peppe
environs/cloudinit: write machine agent config before calling bootstrap-state
286
	return nil
547.1.1 by Gustavo Niemeyer
environs/cloudinit: bootstrap with MongoDB rather than ZK
287
}
288
1216.3.12 by Roger Peppe
environs/cloudinit: write machine agent config before calling bootstrap-state
289
func (cfg *MachineConfig) addMongoToBoot(c *cloudinit.Config) error {
1389.4.6 by Tim Penhey
Use filepath instead of just path.
290
	dbDir := filepath.Join(cfg.DataDir, "db")
580.2.1 by Gustavo Niemeyer
environs/cloudinit: prealloc smaller journal files
291
	addScripts(c,
1389.4.1 by Tim Penhey
Move the machine agent and mongo upstart service definitions into the upstart package.
292
		"mkdir -p "+dbDir+"/journal",
580.2.1 by Gustavo Niemeyer
environs/cloudinit: prealloc smaller journal files
293
		// Otherwise we get three files with 100M+ each, which takes time.
1389.4.1 by Tim Penhey
Move the machine agent and mongo upstart service definitions into the upstart package.
294
		"dd bs=1M count=1 if=/dev/zero of="+dbDir+"/journal/prealloc.0",
295
		"dd bs=1M count=1 if=/dev/zero of="+dbDir+"/journal/prealloc.1",
296
		"dd bs=1M count=1 if=/dev/zero of="+dbDir+"/journal/prealloc.2",
580.2.2 by Gustavo Niemeyer
gofmt
297
	)
1389.4.1 by Tim Penhey
Move the machine agent and mongo upstart service definitions into the upstart package.
298
299
	conf := upstart.MongoUpstartService("juju-db", cfg.DataDir, dbDir, cfg.StatePort)
547.1.1 by Gustavo Niemeyer
environs/cloudinit: bootstrap with MongoDB rather than ZK
300
	cmds, err := conf.InstallCommands()
301
	if err != nil {
302
		return fmt.Errorf("cannot make cloud-init upstart script for the state database: %v", err)
299.3.5 by Dave Cheney
removed cfg.machiner
303
	}
774.2.5 by Roger Peppe
environs/cloudint: unrevert
304
	addScripts(c, cmds...)
299.3.8 by Dave Cheney
addressing review commentss
305
	return nil
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
306
}
307
143.5.1 by Roger Peppe
environs/ec2: update cloudinit to (hopefully) run Go on the cloud.
308
// versionDir converts a tools URL into a name
309
// to use as a directory for storing the tools executables in
310
// by using the last element stripped of its extension.
311
func versionDir(toolsURL string) string {
1389.4.6 by Tim Penhey
Use filepath instead of just path.
312
	name := filepath.Base(toolsURL)
313
	ext := filepath.Ext(name)
143.5.2 by Roger Peppe
environs/ec2: working Go code on server
314
	return name[:len(name)-len(ext)]
143.5.1 by Roger Peppe
environs/ec2: update cloudinit to (hopefully) run Go on the cloud.
315
}
316
377.6.1 by Dave Cheney
1029957
317
func (cfg *MachineConfig) jujuTools() string {
924.3.3 by William Reade
address review
318
	return agent.SharedToolsDir(cfg.DataDir, cfg.Tools.Binary)
299.3.8 by Dave Cheney
addressing review commentss
319
}
320
774.2.14 by Roger Peppe
environs/cloudinit: use agent package
321
func (cfg *MachineConfig) stateHostAddrs() []string {
39.4.14 by Roger Peppe
add test for bootstrap cloudinit data
322
	var hosts []string
438.1.2 by Dave Cheney
responding to review feedback
323
	if cfg.StateServer {
1236.3.28 by Francesco Banconi
s/MongoPort/StatePort.
324
		hosts = append(hosts, fmt.Sprintf("localhost:%d", cfg.StatePort))
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
325
	}
377.6.1 by Dave Cheney
1029957
326
	if cfg.StateInfo != nil {
327
		hosts = append(hosts, cfg.StateInfo.Addrs...)
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
328
	}
774.2.14 by Roger Peppe
environs/cloudinit: use agent package
329
	return hosts
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
330
}
331
849.3.3 by Roger Peppe
environs/cloudinit: some fixed tests
332
func (cfg *MachineConfig) apiHostAddrs() []string {
333
	var hosts []string
334
	if cfg.StateServer {
851.1.2 by Roger Peppe
environs/agent, environs/cloudinit: add server ports
335
		hosts = append(hosts, fmt.Sprintf("localhost:%d", cfg.APIPort))
849.3.3 by Roger Peppe
environs/cloudinit: some fixed tests
336
	}
1432.6.1 by Martin Packman
Check the right Info object before using in apiHostAddrs
337
	if cfg.APIInfo != nil {
849.3.3 by Roger Peppe
environs/cloudinit: some fixed tests
338
		hosts = append(hosts, cfg.APIInfo.Addrs...)
339
	}
340
	return hosts
341
}
342
1142.1.1 by Dave Cheney
merge from screwed branch
343
func (cfg *MachineConfig) NeedMongoPPA() bool {
344
	series := cfg.Tools.Series
345
	// 11.10 and earlier are not supported.
346
	// 13.04 and later ship a compatible version in the archive.
347
	return series == "precise" || series == "quantal"
348
}
349
774.2.8 by Roger Peppe
wip
350
func shquote(p string) string {
1151.1.1 by Tim Penhey
Trivial rename of trivial -> utils.
351
	return utils.ShQuote(p)
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
352
}
353
619.1.8 by Roger Peppe
environs/cloudinit: check EntityName
354
type requiresError string
355
356
func (e requiresError) Error() string {
357
	return "invalid machine configuration: missing " + string(e)
358
}
359
360
func verifyConfig(cfg *MachineConfig) (err error) {
1151.1.1 by Tim Penhey
Trivial rename of trivial -> utils.
361
	defer utils.ErrorContextf(&err, "invalid machine configuration")
730.3.1 by William Reade
machine IDs are now strings
362
	if !state.IsMachineId(cfg.MachineId) {
363
		return fmt.Errorf("invalid machine id")
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
364
	}
478.6.12 by Roger Peppe
rename varDir to dataDir
365
	if cfg.DataDir == "" {
619.1.8 by Roger Peppe
environs/cloudinit: check EntityName
366
		return fmt.Errorf("missing var directory")
478.6.2 by Roger Peppe
environs/cloudinit: fix for vardir
367
	}
377.6.1 by Dave Cheney
1029957
368
	if cfg.Tools == nil {
619.1.8 by Roger Peppe
environs/cloudinit: check EntityName
369
		return fmt.Errorf("missing tools")
365.1.1 by Roger Peppe
environs: add JujuDir, ToolsDir etc
370
	}
377.6.1 by Dave Cheney
1029957
371
	if cfg.Tools.URL == "" {
619.1.8 by Roger Peppe
environs/cloudinit: check EntityName
372
		return fmt.Errorf("missing tools URL")
143.5.1 by Roger Peppe
environs/ec2: update cloudinit to (hopefully) run Go on the cloud.
373
	}
619.1.2 by Roger Peppe
environs/cloudinit: add --initial-password support
374
	if cfg.StateInfo == nil {
619.1.8 by Roger Peppe
environs/cloudinit: check EntityName
375
		return fmt.Errorf("missing state info")
619.1.2 by Roger Peppe
environs/cloudinit: add --initial-password support
376
	}
734.5.28 by Roger Peppe
residual merge
377
	if len(cfg.StateInfo.CACert) == 0 {
734.5.8 by Roger Peppe
environs/cloudinit: use CA certificate from StateInfo
378
		return fmt.Errorf("missing CA certificate")
379
	}
849.3.3 by Roger Peppe
environs/cloudinit: some fixed tests
380
	if cfg.APIInfo == nil {
381
		return fmt.Errorf("missing API info")
382
	}
383
	if len(cfg.APIInfo.CACert) == 0 {
384
		return fmt.Errorf("missing API CA certificate")
385
	}
438.1.2 by Dave Cheney
responding to review feedback
386
	if cfg.StateServer {
450.1.1 by Roger Peppe
environs/cloudinit: use config.Config
387
		if cfg.Config == nil {
619.1.8 by Roger Peppe
environs/cloudinit: check EntityName
388
			return fmt.Errorf("missing environment configuration")
389
		}
1058.6.3 by Matthew Scott
Tests pass. This includes refactor for 'Info' objects.
390
		if cfg.StateInfo.Tag != "" {
1058.6.7 by Matthew Scott
Responding to review - deployerName to deployerTag
391
			return fmt.Errorf("entity tag must be blank when starting a state server")
450.1.1 by Roger Peppe
environs/cloudinit: use config.Config
392
		}
1058.6.3 by Matthew Scott
Tests pass. This includes refactor for 'Info' objects.
393
		if cfg.APIInfo.Tag != "" {
1058.6.7 by Matthew Scott
Responding to review - deployerName to deployerTag
394
			return fmt.Errorf("entity tag must be blank when starting a state server")
849.3.3 by Roger Peppe
environs/cloudinit: some fixed tests
395
		}
715.3.19 by Roger Peppe
delete more PEM suffixes
396
		if len(cfg.StateServerCert) == 0 {
735.1.1 by Roger Peppe
environs/cloudinit: split server PEM
397
			return fmt.Errorf("missing state server certificate")
398
		}
715.3.19 by Roger Peppe
delete more PEM suffixes
399
		if len(cfg.StateServerKey) == 0 {
735.1.1 by Roger Peppe
environs/cloudinit: split server PEM
400
			return fmt.Errorf("missing state server private key")
713.4.1 by Roger Peppe
environs/cloudinit: add Config.ServerCertAndKey
401
		}
1236.3.28 by Francesco Banconi
s/MongoPort/StatePort.
402
		if cfg.StatePort == 0 {
403
			return fmt.Errorf("missing state port")
851.1.2 by Roger Peppe
environs/agent, environs/cloudinit: add server ports
404
		}
405
		if cfg.APIPort == 0 {
406
			return fmt.Errorf("missing API port")
407
		}
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
408
	} else {
619.1.2 by Roger Peppe
environs/cloudinit: add --initial-password support
409
		if len(cfg.StateInfo.Addrs) == 0 {
619.1.8 by Roger Peppe
environs/cloudinit: check EntityName
410
			return fmt.Errorf("missing state hosts")
411
		}
1058.6.3 by Matthew Scott
Tests pass. This includes refactor for 'Info' objects.
412
		if cfg.StateInfo.Tag != state.MachineTag(cfg.MachineId) {
1058.6.7 by Matthew Scott
Responding to review - deployerName to deployerTag
413
			return fmt.Errorf("entity tag must match started machine")
619.1.2 by Roger Peppe
environs/cloudinit: add --initial-password support
414
		}
849.3.3 by Roger Peppe
environs/cloudinit: some fixed tests
415
		if len(cfg.APIInfo.Addrs) == 0 {
416
			return fmt.Errorf("missing API hosts")
417
		}
1058.6.3 by Matthew Scott
Tests pass. This includes refactor for 'Info' objects.
418
		if cfg.APIInfo.Tag != state.MachineTag(cfg.MachineId) {
1058.6.7 by Matthew Scott
Responding to review - deployerName to deployerTag
419
			return fmt.Errorf("entity tag must match started machine")
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
420
		}
421
	}
1114.1.1 by Dimiter Naydenov
Added MachineNonce to agent.Conf and MachineConfig
422
	if cfg.MachineNonce == "" {
423
		return fmt.Errorf("missing machine nonce")
424
	}
39.3.3 by Roger Peppe
more new ec2 cloudinit stuff
425
	return nil
426
}