286
286
// that we can avoid transaction overhead in most cases.
287
287
// We don't care what the error is - if it's something
288
288
// unexpected, it'll be picked up again below.
289
if _, err := st.stateServerMachineIds(); err == nil {
289
if info, err := st.StateServerInfo(); err == nil {
290
if len(info.MachineIds) > 0 && len(info.VotingMachineIds) > 0 {
294
logger.Infof("adding state server info to legacy environment")
292
295
// Find all current state servers and add the state servers
293
// record containing them. We need this to work
294
// even if this is called concurrently. Fortunately
295
// we're safe because legacy environments
296
// do not allow the removal of state server machines
297
// or allow their configured jobs to change.
299
// Thus even if we call this concurrently with an old
300
// environment, we know that the old environment
301
// cannot change the set of state servers, so it's
302
// always valid to add them to the stateServers doc,
303
// assuming all new environments call createStateServersDoc
304
// before doing any operations that may affect the current
305
// set of state servers.
296
// record containing them. We don't need to worry about
297
// this being concurrent-safe, because in the juju versions
298
// we're concerned about, there is only ever one state connection
299
// (from the single bootstrap machine).
306
300
var machineDocs []machineDoc
307
err := st.machines.Find(D{{"jobs", JobManageState}}).All(&machineDocs)
301
err := st.machines.Find(D{{"jobs", JobManageEnviron}}).All(&machineDocs)
312
306
for _, m := range machineDocs {
313
307
doc.MachineIds = append(doc.MachineIds, m.Id)
309
doc.VotingMachineIds = doc.MachineIds
310
logger.Infof("found existing state servers %v", doc.MachineIds)
312
// We update the document before inserting it because
313
// an earlier version of this code did not insert voting machine
314
// ids or maintain the ids correctly. If that was the case,
315
// the insert will be a no-op.
315
316
ops := []txn.Op{{
317
C: st.stateServers.Name,
318
Id: environGlobalKey,
319
Update: D{{"$set", D{
320
{"machineids", doc.MachineIds},
321
{"votingmachineids", doc.VotingMachineIds},
316
324
C: st.stateServers.Name,
317
325
Id: environGlobalKey,
318
Assert: txn.DocMissing,
321
err = st.runTransaction(ops)
322
// If the transaction aborted, it's because the record has already
323
// been created, so we return a nil error because our work
325
return onAbort(err, nil)
329
return st.runTransaction(ops)
328
332
// CACert returns the certificate used to validate the state connection.