Merge lp:~axwalk/juju-core/lp1306902-ha-upgrade into lp:~go-bot/juju-core/trunk
- lp1306902-ha-upgrade
- Merge into trunk
Proposed by
Andrew Wilkins
Status: | Merged |
---|---|
Merged at revision: | 2654 |
Proposed branch: | lp:~axwalk/juju-core/lp1306902-ha-upgrade |
Merge into: | lp:~go-bot/juju-core/trunk |
Diff against target: |
687 lines (+146/-179) 9 files modified
agent/format-1.18.go (+7/-4) agent/mongo/mongo.go (+4/-7) cmd/jujud/bootstrap.go (+6/-4) cmd/jujud/machine.go (+97/-29) cmd/jujud/machine_test.go (+18/-8) worker/peergrouper/desired_test.go (+0/-6) worker/peergrouper/initiate.go (+0/-76) worker/peergrouper/initiate_test.go (+0/-45) worker/peergrouper/suite_test.go (+14/-0) |
To merge this branch: | bzr merge lp:~axwalk/juju-core/lp1306902-ha-upgrade |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+216231@code.launchpad.net |
Commit message
Description of the change
HA: upgrade upstart and initiate replset
The machine agent will now upgrade the
Mongo upstart script and initiate the
replicaset when upgrading from a version
prior to 1.19.0.
Tested upgrading 1.18.1 to 1.19.1 with and
without HA enabled; tested straight bootstrap
to 1.19.1 with and without HA enabled.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'agent/format-1.18.go' |
2 | --- agent/format-1.18.go 2014-04-11 17:51:58 +0000 |
3 | +++ agent/format-1.18.go 2014-04-17 00:02:12 +0000 |
4 | @@ -46,6 +46,7 @@ |
5 | StateServerKey string `yaml:",omitempty"` |
6 | APIPort int `yaml:",omitempty"` |
7 | StatePort int `yaml:",omitempty"` |
8 | + SharedSecret string `yaml:",omitempty"` |
9 | } |
10 | |
11 | func init() { |
12 | @@ -99,10 +100,11 @@ |
13 | } |
14 | if len(format.StateServerKey) != 0 { |
15 | config.servingInfo = ¶ms.StateServingInfo{ |
16 | - Cert: format.StateServerCert, |
17 | - PrivateKey: format.StateServerKey, |
18 | - APIPort: format.APIPort, |
19 | - StatePort: format.StatePort, |
20 | + Cert: format.StateServerCert, |
21 | + PrivateKey: format.StateServerKey, |
22 | + APIPort: format.APIPort, |
23 | + StatePort: format.StatePort, |
24 | + SharedSecret: format.SharedSecret, |
25 | } |
26 | // There's a private key, then we need the state port, |
27 | // which wasn't always in the 1.18 format. If it's not present |
28 | @@ -144,6 +146,7 @@ |
29 | format.StateServerKey = config.servingInfo.PrivateKey |
30 | format.APIPort = config.servingInfo.APIPort |
31 | format.StatePort = config.servingInfo.StatePort |
32 | + format.SharedSecret = config.servingInfo.SharedSecret |
33 | } |
34 | if config.stateDetails != nil { |
35 | format.StateAddresses = config.stateDetails.addresses |
36 | |
37 | === modified file 'agent/mongo/mongo.go' |
38 | --- agent/mongo/mongo.go 2014-04-15 15:12:49 +0000 |
39 | +++ agent/mongo/mongo.go 2014-04-17 00:02:12 +0000 |
40 | @@ -162,6 +162,7 @@ |
41 | return fmt.Errorf("cannot write SSL key: %v", err) |
42 | } |
43 | |
44 | + logger.Debugf("writing %d byte shared secret", len(info.SharedSecret)) |
45 | err = utils.AtomicWriteFile(sharedSecretPath(dataDir), []byte(info.SharedSecret), 0600) |
46 | if err != nil { |
47 | return fmt.Errorf("cannot write mongod shared secret: %v", err) |
48 | @@ -189,15 +190,11 @@ |
49 | if err != nil { |
50 | return err |
51 | } |
52 | - |
53 | - // TODO(natefinch) 2014-04-12 https://launchpad.net/bugs/1306902 |
54 | - // remove this once we support upgrading to HA |
55 | - if upstartConf.Installed() { |
56 | - return nil |
57 | + if err := upstartServiceStop(&upstartConf.Service); err != nil { |
58 | + return fmt.Errorf("failed to stop mongo: %v", err) |
59 | } |
60 | - |
61 | if err := makeJournalDirs(dbDir); err != nil { |
62 | - return fmt.Errorf("Error creating journal directories: %v", err) |
63 | + return fmt.Errorf("error creating journal directories: %v", err) |
64 | } |
65 | return upstartConfInstall(upstartConf) |
66 | } |
67 | |
68 | === modified file 'cmd/jujud/bootstrap.go' |
69 | --- cmd/jujud/bootstrap.go 2014-04-15 18:51:24 +0000 |
70 | +++ cmd/jujud/bootstrap.go 2014-04-17 00:02:12 +0000 |
71 | @@ -18,7 +18,6 @@ |
72 | "launchpad.net/juju-core/environs" |
73 | "launchpad.net/juju-core/environs/config" |
74 | "launchpad.net/juju-core/instance" |
75 | - "launchpad.net/juju-core/provider" |
76 | "launchpad.net/juju-core/state" |
77 | "launchpad.net/juju-core/state/api/params" |
78 | "launchpad.net/juju-core/worker/peergrouper" |
79 | @@ -108,6 +107,7 @@ |
80 | return fmt.Errorf("bootstrap machine config has no state serving info") |
81 | } |
82 | info.SharedSecret = sharedSecret |
83 | + logger.Debugf("shared secret: %d bytes", len(info.SharedSecret)) |
84 | err = c.ChangeConfig(func(agentConfig agent.ConfigSetter) { |
85 | agentConfig.SetStateServingInfo(info) |
86 | }) |
87 | @@ -165,20 +165,22 @@ |
88 | if !ok { |
89 | return fmt.Errorf("agent config has no state serving info") |
90 | } |
91 | + logger.Debugf("shared secret: %d bytes", len(servingInfo.SharedSecret)) |
92 | // Use localhost to dial the mongo server, because it's running in |
93 | // auth mode and will refuse to perform any operations unless |
94 | // we dial that address. |
95 | dialInfo.Addrs = []string{ |
96 | net.JoinHostPort("127.0.0.1", fmt.Sprint(servingInfo.StatePort)), |
97 | } |
98 | + |
99 | logger.Debugf("calling ensureMongoServer") |
100 | - providerType := agentConfig.Value(agent.ProviderType) |
101 | - withHA := providerType != provider.Local |
102 | + withHA := shouldEnableHA(agentConfig) |
103 | err = ensureMongoServer( |
104 | agentConfig.DataDir(), |
105 | agentConfig.Value(agent.Namespace), |
106 | servingInfo, |
107 | - withHA) |
108 | + withHA, |
109 | + ) |
110 | if err != nil { |
111 | return err |
112 | } |
113 | |
114 | === modified file 'cmd/jujud/machine.go' |
115 | --- cmd/jujud/machine.go 2014-04-15 18:51:24 +0000 |
116 | +++ cmd/jujud/machine.go 2014-04-17 00:02:12 +0000 |
117 | @@ -5,6 +5,7 @@ |
118 | |
119 | import ( |
120 | "fmt" |
121 | + "net" |
122 | "os" |
123 | "path/filepath" |
124 | "runtime" |
125 | @@ -418,52 +419,118 @@ |
126 | }) |
127 | } |
128 | |
129 | -// StateJobs returns a worker running all the workers that require |
130 | -// a *state.State connection. |
131 | -func (a *MachineAgent) StateWorker() (worker.Worker, error) { |
132 | - agentConfig := a.CurrentConfig() |
133 | - |
134 | +func isPreHAVersion(v version.Number) bool { |
135 | + return v.Compare(version.MustParse("1.19.0")) < 0 |
136 | +} |
137 | + |
138 | +// shouldEnableHA reports whether HA should be enabled. |
139 | +// |
140 | +// Eventually this should always be true, and ideally |
141 | +// it should be true before 1.20 is released or we'll |
142 | +// have more upgrade scenarios on our hands. |
143 | +func shouldEnableHA(agentConfig agent.Config) bool { |
144 | + return true // XXX |
145 | + providerType := agentConfig.Value(agent.ProviderType) |
146 | + return providerType != provider.Local |
147 | +} |
148 | + |
149 | +// ensureMongoServer ensures that mongo is installed and running, |
150 | +// and ready for opening a state connection. |
151 | +func (a *MachineAgent) ensureMongoServer(agentConfig agent.Config) error { |
152 | servingInfo, ok := agentConfig.StateServingInfo() |
153 | if !ok { |
154 | - return nil, fmt.Errorf("state worker was started with no state serving info") |
155 | + return fmt.Errorf("state worker was started with no state serving info") |
156 | } |
157 | - providerType := agentConfig.Value(agent.ProviderType) |
158 | namespace := agentConfig.Value(agent.Namespace) |
159 | - withHA := providerType != provider.Local |
160 | - err := ensureMongoServer( |
161 | + withHA := shouldEnableHA(agentConfig) |
162 | + |
163 | + // When upgrading from a pre-HA-capable environment, |
164 | + // we must add machine-0 to the admin database and |
165 | + // initiate its replicaset. |
166 | + // |
167 | + // TODO(axw) remove this when we no longer need |
168 | + // to upgrade from pre-HA-capable environments. |
169 | + var shouldInitiateMongoServer bool |
170 | + var addrs []instance.Address |
171 | + if isPreHAVersion(agentConfig.UpgradedToVersion()) { |
172 | + _, err := a.ensureMongoAdminUser(agentConfig, servingInfo.StatePort, namespace) |
173 | + if err != nil { |
174 | + return err |
175 | + } |
176 | + if servingInfo.SharedSecret == "" { |
177 | + servingInfo.SharedSecret, err = mongo.GenerateSharedSecret() |
178 | + if err != nil { |
179 | + return err |
180 | + } |
181 | + if err = a.ChangeConfig(func(config agent.ConfigSetter) { |
182 | + config.SetStateServingInfo(servingInfo) |
183 | + }); err != nil { |
184 | + return err |
185 | + } |
186 | + } |
187 | + st, m, err := openState(agentConfig) |
188 | + if err != nil { |
189 | + return err |
190 | + } |
191 | + if err := st.SetStateServingInfo(servingInfo); err != nil { |
192 | + st.Close() |
193 | + return fmt.Errorf("cannot set state serving info: %v", err) |
194 | + } |
195 | + st.Close() |
196 | + addrs = m.Addresses() |
197 | + shouldInitiateMongoServer = withHA |
198 | + } |
199 | + |
200 | + // ensureMongoServer installs/upgrades the upstart config as necessary. |
201 | + if err := ensureMongoServer( |
202 | agentConfig.DataDir(), |
203 | namespace, |
204 | servingInfo, |
205 | withHA, |
206 | - ) |
207 | + ); err != nil { |
208 | + return err |
209 | + } |
210 | + if !shouldInitiateMongoServer { |
211 | + return nil |
212 | + } |
213 | + |
214 | + // Initiate the replicaset for upgraded environments. |
215 | + // |
216 | + // TODO(axw) remove this when we no longer need |
217 | + // to upgrade from pre-HA-capable environments. |
218 | + stateInfo, ok := agentConfig.StateInfo() |
219 | + if !ok { |
220 | + return fmt.Errorf("state worker was started with no state serving info") |
221 | + } |
222 | + dialInfo, err := state.DialInfo(stateInfo, state.DefaultDialOpts()) |
223 | if err != nil { |
224 | + return err |
225 | + } |
226 | + peerAddr := mongo.SelectPeerAddress(addrs) |
227 | + if peerAddr == "" { |
228 | + return fmt.Errorf("no appropriate peer address found in %q", addrs) |
229 | + } |
230 | + return maybeInitiateMongoServer(peergrouper.InitiateMongoParams{ |
231 | + DialInfo: dialInfo, |
232 | + MemberHostPort: net.JoinHostPort(peerAddr, fmt.Sprint(servingInfo.StatePort)), |
233 | + User: stateInfo.Tag, |
234 | + Password: stateInfo.Password, |
235 | + }) |
236 | +} |
237 | + |
238 | +// StateJobs returns a worker running all the workers that require |
239 | +// a *state.State connection. |
240 | +func (a *MachineAgent) StateWorker() (worker.Worker, error) { |
241 | + agentConfig := a.CurrentConfig() |
242 | + if err := a.ensureMongoServer(agentConfig); err != nil { |
243 | return nil, err |
244 | } |
245 | - |
246 | st, m, err := openState(agentConfig) |
247 | - if errors.IsUnauthorizedError(err) { |
248 | - // TODO(axw) remove this when we no longer need |
249 | - // to upgrade from pre-HA-capable environments. |
250 | - logger.Debugf("failed to open state, reattempt after ensuring admin user exists: %v", err) |
251 | - added, ensureErr := a.ensureMongoAdminUser(agentConfig, servingInfo.StatePort, namespace) |
252 | - if ensureErr != nil { |
253 | - err = ensureErr |
254 | - } |
255 | - if !added { |
256 | - // No user added, so it's probably a genuine unauthorized error. |
257 | - return nil, err |
258 | - } |
259 | - st, m, err = openState(agentConfig) |
260 | - } |
261 | if err != nil { |
262 | return nil, err |
263 | } |
264 | reportOpenedState(st) |
265 | |
266 | - // TODO(rog) call maybeInitiateMongoServer to upgrade mongo |
267 | - // from old environments. We'll need to acquire a non-localhost |
268 | - // address for the current instance before we do. |
269 | - |
270 | singularStateConn := singularStateConn{st.MongoSession(), m} |
271 | runner := newRunner(connectionIsFatal(st), moreImportant) |
272 | singularRunner, err := newSingularRunner(runner, singularStateConn) |
273 | @@ -473,6 +540,7 @@ |
274 | |
275 | // Take advantage of special knowledge here in that we will only ever want |
276 | // the storage provider on one machine, and that is the "bootstrap" node. |
277 | + providerType := agentConfig.Value(agent.ProviderType) |
278 | if (providerType == provider.Local || provider.IsManual(providerType)) && m.Id() == bootstrapMachineId { |
279 | a.startWorkerAfterUpgrade(runner, "local-storage", func() (worker.Worker, error) { |
280 | // TODO(axw) 2013-09-24 bug #1229507 |
281 | |
282 | === modified file 'cmd/jujud/machine_test.go' |
283 | --- cmd/jujud/machine_test.go 2014-04-15 11:54:15 +0000 |
284 | +++ cmd/jujud/machine_test.go 2014-04-17 00:02:12 +0000 |
285 | @@ -59,6 +59,7 @@ |
286 | agentSuite |
287 | singularRecord *singularRunnerRecord |
288 | lxctesting.TestSuite |
289 | + fakeEnsureMongo fakeEnsure |
290 | } |
291 | |
292 | func (s *commonMachineSuite) SetUpSuite(c *gc.C) { |
293 | @@ -93,6 +94,10 @@ |
294 | |
295 | s.singularRecord = &singularRunnerRecord{} |
296 | testing.PatchValue(&newSingularRunner, s.singularRecord.newSingularRunner) |
297 | + |
298 | + s.fakeEnsureMongo = fakeEnsure{} |
299 | + s.PatchValue(&ensureMongoServer, s.fakeEnsureMongo.fakeEnsureMongo) |
300 | + s.PatchValue(&maybeInitiateMongoServer, s.fakeEnsureMongo.fakeInitiateMongo) |
301 | } |
302 | |
303 | func fakeCmd(path string) { |
304 | @@ -120,6 +125,10 @@ |
305 | inst, md := jujutesting.AssertStartInstance(c, s.Conn.Environ, m.Id()) |
306 | c.Assert(m.SetProvisioned(inst.Id(), state.BootstrapNonce, md), gc.IsNil) |
307 | |
308 | + // Add an address for the tests in case the maybeInitiateMongoServer |
309 | + // codepath is exercised. |
310 | + s.setFakeMachineAddresses(c, m) |
311 | + |
312 | // Set up the new machine. |
313 | err = m.SetAgentVersion(vers) |
314 | c.Assert(err, gc.IsNil) |
315 | @@ -320,7 +329,7 @@ |
316 | return ctx, func() { newDeployContext = orig } |
317 | } |
318 | |
319 | -func (s *MachineSuite) setFakeMachineAddresses(c *gc.C, machine *state.Machine) { |
320 | +func (s *commonMachineSuite) setFakeMachineAddresses(c *gc.C, machine *state.Machine) { |
321 | addrs := []instance.Address{ |
322 | instance.NewAddress("0.1.2.3", instance.NetworkUnknown), |
323 | } |
324 | @@ -340,7 +349,6 @@ |
325 | usefulVersion.Series = "quantal" // to match the charm created below |
326 | envtesting.AssertUploadFakeToolsVersions(c, s.Conn.Environ.Storage(), usefulVersion) |
327 | m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron) |
328 | - s.setFakeMachineAddresses(c, m) |
329 | op := make(chan dummy.Operation, 200) |
330 | dummy.Listen(op) |
331 | |
332 | @@ -398,7 +406,6 @@ |
333 | usefulVersion.Series = "quantal" // to match the charm created below |
334 | envtesting.AssertUploadFakeToolsVersions(c, s.Conn.Environ.Storage(), usefulVersion) |
335 | m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron) |
336 | - s.setFakeMachineAddresses(c, m) |
337 | a := s.newAgent(c, m) |
338 | defer a.Stop() |
339 | go func() { |
340 | @@ -440,7 +447,6 @@ |
341 | usefulVersion.Series = "quantal" |
342 | envtesting.AssertUploadFakeToolsVersions(c, s.Conn.Environ.Storage(), usefulVersion) |
343 | m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron) |
344 | - s.setFakeMachineAddresses(c, m) |
345 | calledChan := make(chan struct{}, 1) |
346 | s.PatchValue(&useMultipleCPUs, func() { calledChan <- struct{}{} }) |
347 | // Now, start the agent, and observe that a JobManageEnviron agent |
348 | @@ -460,7 +466,6 @@ |
349 | c.Check(a.Stop(), gc.IsNil) |
350 | // However, an agent that just JobHostUnits doesn't call UseMultipleCPUs |
351 | m2, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits) |
352 | - s.setFakeMachineAddresses(c, m2) |
353 | a2 := s.newAgent(c, m2) |
354 | defer a2.Stop() |
355 | go func() { |
356 | @@ -896,9 +901,12 @@ |
357 | c.Fatalf("timeout while waiting for agent config to change") |
358 | } |
359 | |
360 | -func (s *MachineSuite) TestMachineAgentEnsureAdminUser(c *gc.C) { |
361 | - m, _, _ := s.primeAgent(c, version.Current, state.JobManageEnviron) |
362 | - err := s.State.MongoSession().DB("admin").RemoveUser(m.Tag()) |
363 | +func (s *MachineSuite) TestMachineAgentUpgradeMongo(c *gc.C) { |
364 | + m, agentConfig, _ := s.primeAgent(c, version.Current, state.JobManageEnviron) |
365 | + agentConfig.SetUpgradedToVersion(version.MustParse("1.18.0")) |
366 | + err := agentConfig.Write() |
367 | + c.Assert(err, gc.IsNil) |
368 | + err = s.State.MongoSession().DB("admin").RemoveUser(m.Tag()) |
369 | c.Assert(err, gc.IsNil) |
370 | |
371 | s.PatchValue(&ensureMongoAdminUser, func(p mongo.EnsureAdminUserParams) (bool, error) { |
372 | @@ -927,6 +935,8 @@ |
373 | c.Fatalf("state not opened") |
374 | } |
375 | s.waitStopped(c, state.JobManageEnviron, a, done) |
376 | + c.Assert(s.fakeEnsureMongo.ensureCount, gc.Equals, 1) |
377 | + c.Assert(s.fakeEnsureMongo.initiateCount, gc.Equals, 1) |
378 | } |
379 | |
380 | // MachineWithCharmsSuite provides infrastructure for tests which need to |
381 | |
382 | === modified file 'worker/peergrouper/desired_test.go' |
383 | --- worker/peergrouper/desired_test.go 2014-04-11 11:30:12 +0000 |
384 | +++ worker/peergrouper/desired_test.go 2014-04-17 00:02:12 +0000 |
385 | @@ -8,21 +8,15 @@ |
386 | "sort" |
387 | "strconv" |
388 | "strings" |
389 | - stdtesting "testing" |
390 | |
391 | jc "github.com/juju/testing/checkers" |
392 | gc "launchpad.net/gocheck" |
393 | |
394 | "launchpad.net/juju-core/instance" |
395 | "launchpad.net/juju-core/replicaset" |
396 | - coretesting "launchpad.net/juju-core/testing" |
397 | "launchpad.net/juju-core/testing/testbase" |
398 | ) |
399 | |
400 | -func TestPackage(t *stdtesting.T) { |
401 | - coretesting.MgoTestPackage(t) |
402 | -} |
403 | - |
404 | type desiredPeerGroupSuite struct { |
405 | testbase.LoggingSuite |
406 | } |
407 | |
408 | === added file 'worker/peergrouper/initiate.go' |
409 | --- worker/peergrouper/initiate.go 1970-01-01 00:00:00 +0000 |
410 | +++ worker/peergrouper/initiate.go 2014-04-17 00:02:12 +0000 |
411 | @@ -0,0 +1,76 @@ |
412 | +// Copyright 2014 Canonical Ltd. |
413 | +// Licensed under the AGPLv3, see LICENCE file for details. |
414 | + |
415 | +package peergrouper |
416 | + |
417 | +import ( |
418 | + "fmt" |
419 | + |
420 | + "labix.org/v2/mgo" |
421 | + |
422 | + "launchpad.net/juju-core/agent" |
423 | + "launchpad.net/juju-core/agent/mongo" |
424 | + "launchpad.net/juju-core/replicaset" |
425 | +) |
426 | + |
427 | +// InitiateMongoParams holds parameters for the MaybeInitiateMongo call. |
428 | +type InitiateMongoParams struct { |
429 | + // DialInfo specifies how to connect to the mongo server. |
430 | + DialInfo *mgo.DialInfo |
431 | + |
432 | + // MemberHostPort provides the address to use for |
433 | + // the first replica set member. |
434 | + MemberHostPort string |
435 | + |
436 | + // User holds the user to log as in to the mongo server. |
437 | + // If it is empty, no login will take place. |
438 | + User string |
439 | + Password string |
440 | +} |
441 | + |
442 | +// MaybeInitiateMongoServer checks for an existing mongo configuration. |
443 | +// If no existing configuration is found one is created using Initiate. |
444 | +func MaybeInitiateMongoServer(p InitiateMongoParams) error { |
445 | + logger.Debugf("Initiating mongo replicaset; dialInfo %#v; memberHostport %q; user %q; password %q", p.DialInfo, p.MemberHostPort, p.User, p.Password) |
446 | + defer logger.Infof("finished MaybeInitiateMongoServer") |
447 | + |
448 | + if len(p.DialInfo.Addrs) > 1 { |
449 | + logger.Infof("more than one member; replica set must be already initiated") |
450 | + return nil |
451 | + } |
452 | + p.DialInfo.Direct = true |
453 | + |
454 | + // TODO(rog) remove this code when we no longer need to upgrade |
455 | + // from pre-HA-capable environments. |
456 | + if p.User != "" { |
457 | + p.DialInfo.Username = p.User |
458 | + p.DialInfo.Password = p.Password |
459 | + } |
460 | + |
461 | + session, err := mgo.DialWithInfo(p.DialInfo) |
462 | + if err != nil { |
463 | + return fmt.Errorf("can't dial mongo to initiate replicaset: %v", err) |
464 | + } |
465 | + defer session.Close() |
466 | + |
467 | + cfg, err := replicaset.CurrentConfig(session) |
468 | + if err == nil && len(cfg.Members) > 0 { |
469 | + logger.Infof("replica set configuration already found: %#v", cfg) |
470 | + return nil |
471 | + } |
472 | + if err != nil && err != mgo.ErrNotFound { |
473 | + return fmt.Errorf("cannot get replica set configuration: %v", err) |
474 | + } |
475 | + err = replicaset.Initiate( |
476 | + session, |
477 | + p.MemberHostPort, |
478 | + mongo.ReplicaSetName, |
479 | + map[string]string{ |
480 | + jujuMachineTag: agent.BootstrapMachineId, |
481 | + }, |
482 | + ) |
483 | + if err != nil { |
484 | + return fmt.Errorf("cannot initiate replica set: %v", err) |
485 | + } |
486 | + return nil |
487 | +} |
488 | |
489 | === removed file 'worker/peergrouper/initiate.go' |
490 | --- worker/peergrouper/initiate.go 2014-04-14 19:23:22 +0000 |
491 | +++ worker/peergrouper/initiate.go 1970-01-01 00:00:00 +0000 |
492 | @@ -1,76 +0,0 @@ |
493 | -// Copyright 2014 Canonical Ltd. |
494 | -// Licensed under the AGPLv3, see LICENCE file for details. |
495 | - |
496 | -package peergrouper |
497 | - |
498 | -import ( |
499 | - "fmt" |
500 | - |
501 | - "labix.org/v2/mgo" |
502 | - |
503 | - "launchpad.net/juju-core/agent" |
504 | - "launchpad.net/juju-core/agent/mongo" |
505 | - "launchpad.net/juju-core/replicaset" |
506 | -) |
507 | - |
508 | -// InitiateMongoParams holds parameters for the MaybeInitiateMongo call. |
509 | -type InitiateMongoParams struct { |
510 | - // DialInfo specifies how to connect to the mongo server. |
511 | - DialInfo *mgo.DialInfo |
512 | - |
513 | - // MemberHostPort provides the address to use for |
514 | - // the first replica set member. |
515 | - MemberHostPort string |
516 | - |
517 | - // User holds the user to log as in to the mongo server. |
518 | - // If it is empty, no login will take place. |
519 | - User string |
520 | - Password string |
521 | -} |
522 | - |
523 | -// MaybeInitiateMongoServer checks for an existing mongo configuration. |
524 | -// If no existing configuration is found one is created using Initiate. |
525 | -func MaybeInitiateMongoServer(p InitiateMongoParams) error { |
526 | - logger.Debugf("Initiating mongo replicaset; dialInfo %#v; memberHostport %q; user %q; password %q", p.DialInfo, p.MemberHostPort, p.User, p.Password) |
527 | - defer logger.Infof("finished MaybeInitiateMongoServer") |
528 | - |
529 | - if len(p.DialInfo.Addrs) > 1 { |
530 | - logger.Infof("more than one member; replica set must be already initiated") |
531 | - return nil |
532 | - } |
533 | - p.DialInfo.Direct = true |
534 | - session, err := mgo.DialWithInfo(p.DialInfo) |
535 | - if err != nil { |
536 | - return fmt.Errorf("can't dial mongo to initiate replicaset: %v", err) |
537 | - } |
538 | - defer session.Close() |
539 | - |
540 | - // TODO(rog) remove this code when we no longer need to upgrade |
541 | - // from pre-HA-capable environments. |
542 | - if p.User != "" { |
543 | - err := session.DB("admin").Login(p.User, p.Password) |
544 | - if err != nil { |
545 | - logger.Errorf("cannot login to admin db as %q, password %q, falling back: %v", p.User, p.Password, err) |
546 | - } |
547 | - } |
548 | - cfg, err := replicaset.CurrentConfig(session) |
549 | - if err == nil && len(cfg.Members) > 0 { |
550 | - logger.Infof("replica set configuration already found: %#v", cfg) |
551 | - return nil |
552 | - } |
553 | - if err != nil && err != mgo.ErrNotFound { |
554 | - return fmt.Errorf("cannot get replica set configuration: %v", err) |
555 | - } |
556 | - err = replicaset.Initiate( |
557 | - session, |
558 | - p.MemberHostPort, |
559 | - mongo.ReplicaSetName, |
560 | - map[string]string{ |
561 | - jujuMachineTag: agent.BootstrapMachineId, |
562 | - }, |
563 | - ) |
564 | - if err != nil { |
565 | - return fmt.Errorf("cannot initiate replica set: %v", err) |
566 | - } |
567 | - return nil |
568 | -} |
569 | |
570 | === added file 'worker/peergrouper/initiate_test.go' |
571 | --- worker/peergrouper/initiate_test.go 1970-01-01 00:00:00 +0000 |
572 | +++ worker/peergrouper/initiate_test.go 2014-04-17 00:02:12 +0000 |
573 | @@ -0,0 +1,45 @@ |
574 | +// Copyright 2014 Canonical Ltd. |
575 | +// Licensed under the AGPLv3, see LICENCE file for details. |
576 | + |
577 | +package peergrouper_test |
578 | + |
579 | +import ( |
580 | + gc "launchpad.net/gocheck" |
581 | + |
582 | + coretesting "launchpad.net/juju-core/testing" |
583 | + "launchpad.net/juju-core/testing/testbase" |
584 | + "launchpad.net/juju-core/worker/peergrouper" |
585 | +) |
586 | + |
587 | +type InitiateSuite struct { |
588 | + testbase.LoggingSuite |
589 | +} |
590 | + |
591 | +var _ = gc.Suite(&InitiateSuite{}) |
592 | + |
593 | +// TODO(natefinch) add a test that InitiateMongoServer works when |
594 | +// we support upgrading of existing environments. |
595 | + |
596 | +func (s *InitiateSuite) TestInitiateReplicaSet(c *gc.C) { |
597 | + var err error |
598 | + inst := &coretesting.MgoInstance{Params: []string{"--replSet", "juju"}} |
599 | + err = inst.Start(true) |
600 | + c.Assert(err, gc.IsNil) |
601 | + |
602 | + info := inst.DialInfo() |
603 | + args := peergrouper.InitiateMongoParams{ |
604 | + DialInfo: info, |
605 | + MemberHostPort: inst.Addr(), |
606 | + } |
607 | + |
608 | + err = peergrouper.MaybeInitiateMongoServer(args) |
609 | + c.Assert(err, gc.IsNil) |
610 | + |
611 | + // This would return a mgo.QueryError if a ReplicaSet |
612 | + // configuration already existed but we tried to create |
613 | + // one with replicaset.Initiate again. |
614 | + err = peergrouper.MaybeInitiateMongoServer(args) |
615 | + c.Assert(err, gc.IsNil) |
616 | + |
617 | + // TODO test login |
618 | +} |
619 | |
620 | === removed file 'worker/peergrouper/initiate_test.go' |
621 | --- worker/peergrouper/initiate_test.go 2014-04-14 19:23:22 +0000 |
622 | +++ worker/peergrouper/initiate_test.go 1970-01-01 00:00:00 +0000 |
623 | @@ -1,45 +0,0 @@ |
624 | -// Copyright 2014 Canonical Ltd. |
625 | -// Licensed under the AGPLv3, see LICENCE file for details. |
626 | - |
627 | -package peergrouper_test |
628 | - |
629 | -import ( |
630 | - gc "launchpad.net/gocheck" |
631 | - |
632 | - coretesting "launchpad.net/juju-core/testing" |
633 | - "launchpad.net/juju-core/testing/testbase" |
634 | - "launchpad.net/juju-core/worker/peergrouper" |
635 | -) |
636 | - |
637 | -type InitiateSuite struct { |
638 | - testbase.LoggingSuite |
639 | -} |
640 | - |
641 | -var _ = gc.Suite(&InitiateSuite{}) |
642 | - |
643 | -// TODO(natefinch) add a test that InitiateMongoServer works when |
644 | -// we support upgrading of existing environments. |
645 | - |
646 | -func (s *InitiateSuite) TestInitiateReplicaSet(c *gc.C) { |
647 | - var err error |
648 | - inst := &coretesting.MgoInstance{Params: []string{"--replSet", "juju"}} |
649 | - err = inst.Start(true) |
650 | - c.Assert(err, gc.IsNil) |
651 | - |
652 | - info := inst.DialInfo() |
653 | - args := peergrouper.InitiateMongoParams{ |
654 | - DialInfo: info, |
655 | - MemberHostPort: inst.Addr(), |
656 | - } |
657 | - |
658 | - err = peergrouper.MaybeInitiateMongoServer(args) |
659 | - c.Assert(err, gc.IsNil) |
660 | - |
661 | - // This would return a mgo.QueryError if a ReplicaSet |
662 | - // configuration already existed but we tried to create |
663 | - // one with replicaset.Initiate again. |
664 | - err = peergrouper.MaybeInitiateMongoServer(args) |
665 | - c.Assert(err, gc.IsNil) |
666 | - |
667 | - // TODO test login |
668 | -} |
669 | |
670 | === added file 'worker/peergrouper/suite_test.go' |
671 | --- worker/peergrouper/suite_test.go 1970-01-01 00:00:00 +0000 |
672 | +++ worker/peergrouper/suite_test.go 2014-04-17 00:02:12 +0000 |
673 | @@ -0,0 +1,14 @@ |
674 | +// Copyright 2014 Canonical Ltd. |
675 | +// Licensed under the AGPLv3, see LICENCE file for details. |
676 | + |
677 | +package peergrouper_test |
678 | + |
679 | +import ( |
680 | + stdtesting "testing" |
681 | + |
682 | + "launchpad.net/juju-core/testing" |
683 | +) |
684 | + |
685 | +func TestPackage(t *stdtesting.T) { |
686 | + testing.MgoTestPackage(t) |
687 | +} |