Skip to content

Commit c5993b6

Browse files
committed
Fix mongo set up so it works with ha
1 parent dd9828e commit c5993b6

File tree

6 files changed

+32
-318
lines changed

6 files changed

+32
-318
lines changed

cmd/jujud/agent/machine.go

+16-172
Original file line numberDiff line numberDiff line change
@@ -1167,79 +1167,36 @@ func (a *MachineAgent) ensureMongoServer(agentConfig agent.Config) (err error) {
11671167
}
11681168
}()
11691169

1170-
// Many of the steps here, such as adding the controller to the
1171-
// admin DB and initiating the replicaset, are once-only actions,
1172-
// required when upgrading from a pre-HA-capable
1173-
// environment. These calls won't do anything if the thing they
1174-
// need to set up has already been done.
1175-
var needReplicasetInit = false
1176-
var machineAddrs []network.Address
1177-
11781170
mongoInstalled, err := mongo.IsServiceInstalled()
11791171
if err != nil {
11801172
return errors.Annotate(err, "error while checking if mongodb service is installed")
11811173
}
11821174

1183-
if mongoInstalled {
1184-
logger.Debugf("mongodb service is installed")
1185-
1186-
if _, err := a.ensureMongoAdminUser(agentConfig); err != nil {
1187-
return errors.Trace(err)
1188-
}
1189-
1190-
if err := a.ensureMongoSharedSecret(agentConfig); err != nil {
1191-
return errors.Trace(err)
1192-
}
1193-
agentConfig = a.CurrentConfig() // ensureMongoSharedSecret may have updated the config
1194-
1195-
mongoInfo, ok := agentConfig.MongoInfo()
1196-
if !ok {
1197-
return errors.New("unable to retrieve mongo info to check replicaset")
1198-
}
1199-
1200-
needReplicasetInit, err = isReplicasetInitNeeded(mongoInfo)
1175+
if !mongoInstalled {
1176+
// EnsureMongoServer installs/upgrades the init config as necessary.
1177+
ensureServerParams, err := cmdutil.NewEnsureServerParams(agentConfig)
12011178
if err != nil {
1202-
return errors.Annotate(err, "error while checking replicaset")
1179+
return err
12031180
}
1204-
1205-
// If the replicaset is to be initialised the machine addresses
1206-
// need to be retrieved *before* MongoDB is restarted with the
1207-
// --replset option (in EnsureMongoServer). Once MongoDB is
1208-
// started with --replset it won't respond to queries until the
1209-
// replicaset is initiated.
1210-
if needReplicasetInit {
1211-
logger.Infof("replicaset not yet configured")
1212-
machineAddrs, err = getMachineAddresses(agentConfig)
1213-
if err != nil {
1214-
return errors.Trace(err)
1215-
}
1181+
if err := cmdutil.EnsureMongoServer(ensureServerParams); err != nil {
1182+
return err
12161183
}
12171184
}
1185+
logger.Debugf("mongodb service is installed")
12181186

1219-
// EnsureMongoServer installs/upgrades the init config as necessary.
1220-
ensureServerParams, err := cmdutil.NewEnsureServerParams(agentConfig)
1187+
// Mongo is installed, record the version.
1188+
err = a.ChangeConfig(func(config agent.ConfigSetter) error {
1189+
config.SetMongoVersion(mongo.InstalledVersion())
1190+
return nil
1191+
})
12211192
if err != nil {
1222-
return err
1223-
}
1224-
if err := cmdutil.EnsureMongoServer(ensureServerParams); err != nil {
1225-
return err
1193+
return errors.Annotate(err, "cannot set mongo version")
12261194
}
1195+
agentConfig = a.CurrentConfig()
12271196

1228-
// Initiate the replicaset if required.
1229-
if needReplicasetInit {
1230-
servingInfo, ok := agentConfig.StateServingInfo()
1231-
if !ok {
1232-
return stateWorkerServingConfigErr
1233-
}
1234-
mongoInfo, ok := agentConfig.MongoInfo()
1235-
if !ok {
1236-
return errors.New("unable to retrieve mongo info to initiate replicaset")
1237-
}
1238-
if err := initiateReplicaSet(mongoInfo, servingInfo.StatePort, machineAddrs); err != nil {
1239-
return err
1240-
}
1197+
if _, err := a.ensureMongoAdminUser(agentConfig); err != nil {
1198+
return errors.Trace(err)
12411199
}
1242-
12431200
return nil
12441201
}
12451202

@@ -1269,119 +1226,6 @@ func (a *MachineAgent) ensureMongoAdminUser(agentConfig agent.Config) (added boo
12691226
})
12701227
}
12711228

1272-
// ensureMongoSharedSecret generates a MongoDB shared secret if
1273-
// required, updating the agent's config and state.
1274-
func (a *MachineAgent) ensureMongoSharedSecret(agentConfig agent.Config) error {
1275-
servingInfo, ok := agentConfig.StateServingInfo()
1276-
if !ok {
1277-
return stateWorkerServingConfigErr
1278-
}
1279-
1280-
if servingInfo.SharedSecret != "" {
1281-
return nil // Already done
1282-
}
1283-
1284-
logger.Infof("state serving info has no shared secret - generating")
1285-
1286-
var err error
1287-
servingInfo.SharedSecret, err = mongo.GenerateSharedSecret()
1288-
if err != nil {
1289-
return err
1290-
}
1291-
logger.Debugf("updating state serving info in agent config")
1292-
if err = a.ChangeConfig(func(config agent.ConfigSetter) error {
1293-
config.SetStateServingInfo(servingInfo)
1294-
return nil
1295-
}); err != nil {
1296-
return err
1297-
}
1298-
agentConfig = a.CurrentConfig()
1299-
1300-
logger.Debugf("updating state serving info in state")
1301-
1302-
// Note: we set Direct=true in the mongo options because it's
1303-
// possible that we've previously upgraded the mongo server's
1304-
// configuration to form a replicaset, but failed to initiate it.
1305-
dialOpts := mongo.DefaultDialOpts()
1306-
dialOpts.Direct = true
1307-
st, _, err := openState(agentConfig, dialOpts)
1308-
if err != nil {
1309-
return err
1310-
}
1311-
defer st.Close()
1312-
1313-
ssi := cmdutil.ParamsStateServingInfoToStateStateServingInfo(servingInfo)
1314-
if err := st.SetStateServingInfo(ssi); err != nil {
1315-
return errors.Errorf("cannot set state serving info: %v", err)
1316-
}
1317-
1318-
logger.Infof("shared secret updated in state serving info")
1319-
return nil
1320-
}
1321-
1322-
// isReplicasetInitNeeded returns true if the replicaset needs to be
1323-
// initiated.
1324-
func isReplicasetInitNeeded(mongoInfo *mongo.MongoInfo) (bool, error) {
1325-
dialInfo, err := mongo.DialInfo(mongoInfo.Info, mongo.DefaultDialOpts())
1326-
if err != nil {
1327-
return false, errors.Annotate(err, "cannot generate dial info to check replicaset")
1328-
}
1329-
dialInfo.Username = mongoInfo.Tag.String()
1330-
dialInfo.Password = mongoInfo.Password
1331-
1332-
session, err := mgo.DialWithInfo(dialInfo)
1333-
if err != nil {
1334-
return false, errors.Annotate(err, "cannot dial mongo to check replicaset")
1335-
}
1336-
defer session.Close()
1337-
1338-
cfg, err := replicaset.CurrentConfig(session)
1339-
if err != nil {
1340-
logger.Debugf("couldn't retrieve replicaset config (not fatal): %v", err)
1341-
return true, nil
1342-
}
1343-
numMembers := len(cfg.Members)
1344-
logger.Debugf("replicaset member count: %d", numMembers)
1345-
return numMembers < 1, nil
1346-
}
1347-
1348-
// getMachineAddresses connects to state to determine the machine's
1349-
// network addresses.
1350-
func getMachineAddresses(agentConfig agent.Config) ([]network.Address, error) {
1351-
logger.Debugf("opening state to get machine addresses")
1352-
dialOpts := mongo.DefaultDialOpts()
1353-
dialOpts.Direct = true
1354-
st, m, err := openState(agentConfig, dialOpts)
1355-
if err != nil {
1356-
return nil, errors.Annotate(err, "failed to open state to retrieve machine addresses")
1357-
}
1358-
defer st.Close()
1359-
return m.Addresses(), nil
1360-
}
1361-
1362-
// initiateReplicaSet connects to MongoDB and sets up the replicaset.
1363-
func initiateReplicaSet(mongoInfo *mongo.MongoInfo, statePort int, machineAddrs []network.Address) error {
1364-
peerAddr := mongo.SelectPeerAddress(machineAddrs)
1365-
if peerAddr == "" {
1366-
return errors.Errorf("no appropriate peer address found in %q", machineAddrs)
1367-
}
1368-
1369-
dialInfo, err := mongo.DialInfo(mongoInfo.Info, mongo.DefaultDialOpts())
1370-
if err != nil {
1371-
return errors.Annotate(err, "cannot generate dial info to initiate replicaset")
1372-
}
1373-
1374-
if err := maybeInitiateMongoServer(peergrouper.InitiateMongoParams{
1375-
DialInfo: dialInfo,
1376-
MemberHostPort: net.JoinHostPort(peerAddr, fmt.Sprint(statePort)),
1377-
User: mongoInfo.Tag.String(), // TODO(dfc) InitiateMongoParams should take a Tag
1378-
Password: mongoInfo.Password,
1379-
}); err != nil && err != peergrouper.ErrReplicaSetAlreadyInitiated {
1380-
return err
1381-
}
1382-
return nil
1383-
}
1384-
13851229
func openState(agentConfig agent.Config, dialOpts mongo.DialOpts) (_ *state.State, _ *state.Machine, err error) {
13861230
info, ok := agentConfig.MongoInfo()
13871231
if !ok {

cmd/jujud/agent/machine_test.go

-38
Original file line numberDiff line numberDiff line change
@@ -1532,8 +1532,6 @@ func (s *MachineSuite) TestMachineAgentUpgradeMongo(c *gc.C) {
15321532
c.Fatalf("state not opened")
15331533
}
15341534
s.waitStopped(c, state.JobManageModel, a, done)
1535-
c.Assert(s.fakeEnsureMongo.EnsureCount, gc.Equals, 1)
1536-
c.Assert(s.fakeEnsureMongo.InitiateCount, gc.Equals, 1)
15371535
}
15381536

15391537
func (s *MachineSuite) TestMachineAgentSetsPrepareRestore(c *gc.C) {
@@ -1741,42 +1739,6 @@ func (s *MachineSuite) setUpNewModel(c *gc.C) (newSt *state.State, closer func()
17411739
}
17421740
}
17431741

1744-
func (s *MachineSuite) TestReplicasetInitiation(c *gc.C) {
1745-
if runtime.GOOS == "windows" {
1746-
c.Skip("controllers on windows aren't supported")
1747-
}
1748-
1749-
s.fakeEnsureMongo.ReplicasetInitiated = false
1750-
1751-
m, _, _ := s.primeAgent(c, state.JobManageModel)
1752-
a := s.newAgent(c, m)
1753-
agentConfig := a.CurrentConfig()
1754-
1755-
err := a.ensureMongoServer(agentConfig)
1756-
c.Assert(err, jc.ErrorIsNil)
1757-
1758-
c.Assert(s.fakeEnsureMongo.EnsureCount, gc.Equals, 1)
1759-
c.Assert(s.fakeEnsureMongo.InitiateCount, gc.Equals, 1)
1760-
}
1761-
1762-
func (s *MachineSuite) TestReplicasetAlreadyInitiated(c *gc.C) {
1763-
if runtime.GOOS == "windows" {
1764-
c.Skip("controllers on windows aren't supported")
1765-
}
1766-
1767-
s.fakeEnsureMongo.ReplicasetInitiated = true
1768-
1769-
m, _, _ := s.primeAgent(c, state.JobManageModel)
1770-
a := s.newAgent(c, m)
1771-
agentConfig := a.CurrentConfig()
1772-
1773-
err := a.ensureMongoServer(agentConfig)
1774-
c.Assert(err, jc.ErrorIsNil)
1775-
1776-
c.Assert(s.fakeEnsureMongo.EnsureCount, gc.Equals, 1)
1777-
c.Assert(s.fakeEnsureMongo.InitiateCount, gc.Equals, 0)
1778-
}
1779-
17801742
func (s *MachineSuite) TestReplicasetInitForNewController(c *gc.C) {
17811743
if runtime.GOOS == "windows" {
17821744
c.Skip("controllers on windows aren't supported")

cmd/jujud/bootstrap.go

-14
Original file line numberDiff line numberDiff line change
@@ -225,20 +225,6 @@ func (c *BootstrapCommand) Run(_ *cmd.Context) error {
225225
return fmt.Errorf("cannot write agent config: %v", err)
226226
}
227227

228-
err = c.ChangeConfig(func(config agent.ConfigSetter) error {
229-
// We'll try for mongo 3.2 first and fallback to
230-
// mongo 2.4 if the newer binaries are not available.
231-
if mongo.BinariesAvailable(mongo.Mongo32wt) {
232-
config.SetMongoVersion(mongo.Mongo32wt)
233-
} else {
234-
config.SetMongoVersion(mongo.Mongo24)
235-
}
236-
return nil
237-
})
238-
if err != nil {
239-
return errors.Annotate(err, "cannot set mongo version")
240-
}
241-
242228
agentConfig = c.CurrentConfig()
243229

244230
// Create system-identity file

cmd/jujud/util/util.go

-2
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,6 @@ func NewEnsureServerParams(agentConfig agent.Config) (mongo.EnsureServerParams,
193193
DataDir: agentConfig.DataDir(),
194194
OplogSize: oplogSize,
195195
SetNumaControlPolicy: numaCtlPolicy,
196-
197-
Version: agentConfig.MongoVersion(),
198196
}
199197
return params, nil
200198
}

mongo/mongo.go

+16-17
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,20 @@ var (
193193
}
194194
)
195195

196-
// BinariesAvailable returns true if the binaries for the
196+
// InstalledVersion returns the version of mongo installed.
197+
// We look for a specific, known version supported by this Juju,
198+
// and fall back to the original mongo 2.4.
199+
func InstalledVersion() Version {
200+
mgoVersion := Mongo24
201+
if binariesAvailable(Mongo32wt) {
202+
mgoVersion = Mongo32wt
203+
}
204+
return mgoVersion
205+
}
206+
207+
// binariesAvailable returns true if the binaries for the
197208
// given Version of mongo are available.
198-
func BinariesAvailable(v Version) bool {
209+
func binariesAvailable(v Version) bool {
199210
var path string
200211
switch v {
201212
case Mongo24:
@@ -362,9 +373,6 @@ type EnsureServerParams struct {
362373
// SetNumaControlPolicy preference - whether the user
363374
// wants to set the numa control policy when starting mongo.
364375
SetNumaControlPolicy bool
365-
366-
// Version is the mongod version to be used.
367-
Version Version
368376
}
369377

370378
// EnsureServer ensures that the MongoDB server is installed,
@@ -400,7 +408,8 @@ func EnsureServer(args EnsureServerParams) error {
400408
// (LP #1441904)
401409
logger.Errorf("cannot install/upgrade mongod (will proceed anyway): %v", err)
402410
}
403-
mongoPath, err := Path(args.Version)
411+
mgoVersion := InstalledVersion()
412+
mongoPath, err := Path(mgoVersion)
404413
if err != nil {
405414
return err
406415
}
@@ -429,7 +438,7 @@ func EnsureServer(args EnsureServerParams) error {
429438
}
430439
}
431440

432-
svcConf := newConf(args.DataDir, dbDir, mongoPath, args.StatePort, oplogSizeMB, args.SetNumaControlPolicy, args.Version, true)
441+
svcConf := newConf(args.DataDir, dbDir, mongoPath, args.StatePort, oplogSizeMB, args.SetNumaControlPolicy, mgoVersion, true)
433442
svc, err := newService(ServiceName, svcConf)
434443
if err != nil {
435444
return err
@@ -524,16 +533,6 @@ func installMongod(operatingsystem string, numaCtl bool) error {
524533
return err
525534
}
526535

527-
// Only Quantal requires the PPA.
528-
if operatingsystem == "quantal" {
529-
// install python-software-properties:
530-
if err := pacman.InstallPrerequisite(); err != nil {
531-
return err
532-
}
533-
if err := pacman.AddRepository("ppa:juju/stable"); err != nil {
534-
return err
535-
}
536-
}
537536
// CentOS requires "epel-release" for the epel repo mongodb-server is in.
538537
if operatingsystem == "centos7" {
539538
// install epel-release

0 commit comments

Comments
 (0)