github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/jujud/upgrade_mongo_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // +build !windows 5 6 package main 7 8 import ( 9 "fmt" 10 "os" 11 "path/filepath" 12 "strconv" 13 "time" 14 15 "github.com/juju/clock" 16 "github.com/juju/errors" 17 "github.com/juju/replicaset" 18 "github.com/juju/retry" 19 jc "github.com/juju/testing/checkers" 20 gc "gopkg.in/check.v1" 21 "gopkg.in/juju/names.v2" 22 "gopkg.in/mgo.v2" 23 "gopkg.in/mgo.v2/bson" 24 25 "github.com/juju/juju/agent" 26 "github.com/juju/juju/apiserver/params" 27 "github.com/juju/juju/mongo" 28 "github.com/juju/juju/service" 29 "github.com/juju/juju/service/common" 30 "github.com/juju/juju/testing" 31 jujuversion "github.com/juju/juju/version" 32 "github.com/juju/juju/worker/peergrouper" 33 ) 34 35 type UpgradeMongoSuite struct { 36 testing.BaseSuite 37 } 38 39 type UpgradeMongoCommandSuite struct { 40 testing.BaseSuite 41 } 42 43 // TODO(wallyworld) - create a common mock clock in juju/utils/clock 44 type mockClock struct { 45 now time.Time 46 } 47 48 func (mock *mockClock) Now() time.Time { 49 return mock.now 50 } 51 52 func (mock *mockClock) NewTimer(time.Duration) clock.Timer { 53 panic("unexpected call to NewTimer") 54 } 55 56 func (mock *mockClock) After(wait time.Duration) <-chan time.Time { 57 mock.now = mock.now.Add(wait) 58 return time.After(time.Microsecond) 59 } 60 61 func (mock *mockClock) AfterFunc(d time.Duration, f func()) clock.Timer { 62 panic("unexpected call to AfterFunc") 63 } 64 65 func retryCallArgs() retry.CallArgs { 66 args := defaultCallArgs 67 args.Clock = &mockClock{} 68 return args 69 } 70 71 var _ = gc.Suite(&UpgradeMongoSuite{}) 72 var _ = gc.Suite(&UpgradeMongoCommandSuite{}) 73 74 type fakeFileInfo struct { 75 isDir bool 76 } 77 78 func (f fakeFileInfo) Name() string { return "" } 79 func (f fakeFileInfo) Size() int64 { return 0 } 80 func (f fakeFileInfo) Mode() os.FileMode { return 0 } 81 func (f fakeFileInfo) ModTime() time.Time { return time.Now() } 82 func (f fakeFileInfo) IsDir() bool { return f.isDir } 83 func (f fakeFileInfo) Sys() interface{} { return nil } 84 85 type fakeRunCommand struct { 86 ranCommands [][]string 87 mgoSession mgoSession 88 mgoDb mgoDb 89 service service.Service 90 } 91 92 func (f *fakeRunCommand) runCommand(command string, args ...string) (string, error) { 93 ran := []string{ 94 command, 95 } 96 ran = append(ran, args...) 97 f.ranCommands = append(f.ranCommands, ran) 98 return "", nil 99 } 100 101 func (f *fakeRunCommand) runCommandFail(command string, args ...string) (string, error) { 102 ran := []string{ 103 command, 104 } 105 ran = append(ran, args...) 106 f.ranCommands = append(f.ranCommands, ran) 107 return "this failed", errors.New("a generic error") 108 } 109 110 func (f *fakeRunCommand) stat(statFile string) (os.FileInfo, error) { 111 f.ranCommands = append(f.ranCommands, []string{"stat", statFile}) 112 return fakeFileInfo{}, nil 113 } 114 115 func (f *fakeRunCommand) remove(toremove string) error { 116 f.ranCommands = append(f.ranCommands, []string{"remove", toremove}) 117 return nil 118 } 119 120 func (f *fakeRunCommand) mkdir(dirname string, mode os.FileMode) error { 121 f.ranCommands = append(f.ranCommands, []string{"mkdir", dirname}) 122 return nil 123 } 124 125 func (f *fakeRunCommand) getenv(key string) string { 126 f.ranCommands = append(f.ranCommands, []string{"getenv", key}) 127 return "bogus_daemon" 128 } 129 130 func (s *UpgradeMongoSuite) TestMongo26UpgradeStep(c *gc.C) { 131 command := fakeRunCommand{} 132 err := mongo26UpgradeStepCall(command.runCommand, "/a/fake/datadir") 133 c.Assert(err, jc.ErrorIsNil) 134 c.Assert(command.ranCommands, gc.HasLen, 1) 135 c.Assert(command.ranCommands[0], gc.DeepEquals, []string{"/usr/lib/juju/bin/mongod", "--dbpath", "/a/fake/datadir/db", "--replSet", "juju", "--upgrade"}) 136 137 command = fakeRunCommand{} 138 err = mongo26UpgradeStepCall(command.runCommandFail, "/a/fake/datadir") 139 c.Assert(err, gc.ErrorMatches, "cannot upgrade mongo 2.4 data: a generic error") 140 } 141 142 func (s *UpgradeMongoSuite) TestRemoveOldDb(c *gc.C) { 143 command := fakeRunCommand{} 144 err := removeOldDbCall("/a/fake/datadir", command.stat, command.remove, command.mkdir) 145 c.Assert(err, jc.ErrorIsNil) 146 c.Assert(command.ranCommands, gc.HasLen, 3) 147 c.Assert(command.ranCommands[0], gc.DeepEquals, []string{"stat", "/a/fake/datadir/db"}) 148 c.Assert(command.ranCommands[1], gc.DeepEquals, []string{"remove", "/a/fake/datadir/db"}) 149 c.Assert(command.ranCommands[2], gc.DeepEquals, []string{"mkdir", "/a/fake/datadir/db"}) 150 } 151 152 func (s *UpgradeMongoSuite) TestMongoDump(c *gc.C) { 153 command := fakeRunCommand{} 154 callArgs := retryCallArgs() 155 out, err := mongoDumpCall(command.runCommand, "/fake/tmp/dir", "/fake/mongo/path", "adminpass", "aMigrationName", 1234, callArgs) 156 c.Assert(err, jc.ErrorIsNil) 157 c.Assert(out, gc.Equals, "") 158 c.Assert(command.ranCommands, gc.HasLen, 1) 159 c.Assert(command.ranCommands[0], gc.DeepEquals, []string{"/fake/mongo/path/mongodump", "--ssl", "-u", "admin", "-p", "adminpass", "--port", "1234", "--host", "localhost", "--out", "/fake/tmp/dir/migrateToaMigrationNamedump"}) 160 } 161 162 func (s *UpgradeMongoSuite) TestMongoDumpRetries(c *gc.C) { 163 command := fakeRunCommand{} 164 callArgs := retryCallArgs() 165 out, err := mongoDumpCall(command.runCommandFail, "/fake/tmp/dir", "/fake/mongo/path", "", "aMigrationName", 1234, callArgs) 166 c.Assert(err, gc.ErrorMatches, "cannot dump mongo db: attempt count exceeded: a generic error") 167 c.Assert(out, gc.Equals, "this failed") 168 c.Assert(command.ranCommands, gc.HasLen, 60) 169 for i := range command.ranCommands { 170 c.Logf("Checking attempt %d", i) 171 c.Assert(command.ranCommands[i], gc.DeepEquals, []string{"/fake/mongo/path/mongodump", "--ssl", "-u", "admin", "-p", "", "--port", "1234", "--host", "localhost", "--out", "/fake/tmp/dir/migrateToaMigrationNamedump"}) 172 } 173 } 174 175 func (s *UpgradeMongoSuite) TestMongoRestore(c *gc.C) { 176 command := fakeRunCommand{} 177 callArgs := retryCallArgs() 178 err := mongoRestoreCall(command.runCommand, "/fake/tmp/dir", "/fake/mongo/path", "adminpass", "aMigrationName", []string{}, 1234, true, 100, callArgs) 179 c.Assert(err, jc.ErrorIsNil) 180 c.Assert(command.ranCommands, gc.HasLen, 1) 181 c.Assert(command.ranCommands[0], gc.DeepEquals, []string{"/fake/mongo/path/mongorestore", "--ssl", "--port", "1234", "--host", "localhost", "--sslAllowInvalidCertificates", "--batchSize", "100", "-u", "admin", "-p", "adminpass", "/fake/tmp/dir/migrateToaMigrationNamedump"}) 182 } 183 184 func (s *UpgradeMongoSuite) TestMongoRestoreWithoutAdmin(c *gc.C) { 185 command := fakeRunCommand{} 186 callArgs := retryCallArgs() 187 err := mongoRestoreCall(command.runCommand, "/fake/tmp/dir", "/fake/mongo/path", "", "aMigrationName", []string{}, 1234, false, 0, callArgs) 188 c.Assert(err, jc.ErrorIsNil) 189 c.Assert(command.ranCommands, gc.HasLen, 1) 190 c.Assert(command.ranCommands[0], gc.DeepEquals, []string{"/fake/mongo/path/mongorestore", "--ssl", "--port", "1234", "--host", "localhost", "/fake/tmp/dir/migrateToaMigrationNamedump"}) 191 } 192 193 func (s *UpgradeMongoSuite) TestMongoRestoreWithDBs(c *gc.C) { 194 command := fakeRunCommand{} 195 callArgs := retryCallArgs() 196 err := mongoRestoreCall(command.runCommand, "/fake/tmp/dir", "/fake/mongo/path", "adminpass", "aMigrationName", []string{"onedb", "twodb"}, 1234, false, 0, callArgs) 197 c.Assert(err, jc.ErrorIsNil) 198 c.Assert(command.ranCommands, gc.HasLen, 2) 199 c.Assert(command.ranCommands[0], gc.DeepEquals, []string{"/fake/mongo/path/mongorestore", "--ssl", "--port", "1234", "--host", "localhost", "-u", "admin", "-p", "adminpass", "--db=onedb", "/fake/tmp/dir/migrateToaMigrationNamedump/onedb"}) 200 c.Assert(command.ranCommands[1], gc.DeepEquals, []string{"/fake/mongo/path/mongorestore", "--ssl", "--port", "1234", "--host", "localhost", "-u", "admin", "-p", "adminpass", "--db=twodb", "/fake/tmp/dir/migrateToaMigrationNamedump/twodb"}) 201 } 202 203 func (s *UpgradeMongoSuite) TestMongoRestoreRetries(c *gc.C) { 204 command := fakeRunCommand{} 205 callArgs := retryCallArgs() 206 err := mongoRestoreCall(command.runCommandFail, "/fake/tmp/dir", "/fake/mongo/path", "", "aMigrationName", []string{}, 1234, false, 0, callArgs) 207 c.Assert(err, gc.ErrorMatches, "cannot restore dbs got: this failed: attempt count exceeded: a generic error") 208 c.Assert(command.ranCommands, gc.HasLen, 60) 209 for i := range command.ranCommands { 210 c.Log(fmt.Sprintf("Checking attempt %d", i)) 211 c.Assert(command.ranCommands[i], gc.DeepEquals, []string{"/fake/mongo/path/mongorestore", "--ssl", "--port", "1234", "--host", "localhost", "/fake/tmp/dir/migrateToaMigrationNamedump"}) 212 } 213 } 214 215 type fakeMgoSesion struct { 216 ranClose int 217 } 218 219 func (f *fakeMgoSesion) Close() { 220 f.ranClose++ 221 } 222 223 type fakeMgoDb struct { 224 ranAction string 225 } 226 227 func (f *fakeMgoDb) Run(action interface{}, res interface{}) error { 228 f.ranAction = action.(string) 229 resM := res.(*bson.M) 230 (*resM)["ok"] = float64(1) 231 return nil 232 } 233 234 func (f *fakeRunCommand) dialAndLogin(*mongo.MongoInfo, retry.CallArgs) (mgoSession, mgoDb, error) { 235 f.ranCommands = append(f.ranCommands, []string{"DialAndlogin"}) 236 return f.mgoSession, f.mgoDb, nil 237 } 238 239 func (f *fakeRunCommand) satisfyPrerequisites(string) error { 240 f.ranCommands = append(f.ranCommands, []string{"SatisfyPrerequisites"}) 241 return nil 242 } 243 244 func (f *fakeRunCommand) createTempDir() (string, error) { 245 f.ranCommands = append(f.ranCommands, []string{"CreateTempDir"}) 246 return "/fake/temp/dir", nil 247 } 248 249 func (f *fakeRunCommand) startService() error { 250 f.ranCommands = append(f.ranCommands, []string{"mongo.StartService"}) 251 return nil 252 } 253 func (f *fakeRunCommand) stopService() error { 254 f.ranCommands = append(f.ranCommands, []string{"mongo.StopService"}) 255 return nil 256 } 257 func (f *fakeRunCommand) reStartService() error { 258 f.ranCommands = append(f.ranCommands, []string{"mongo.ReStartService"}) 259 return nil 260 } 261 func (f *fakeRunCommand) reStartServiceFail() error { 262 f.ranCommands = append(f.ranCommands, []string{"mongo.ReStartServiceFail"}) 263 return errors.New("failing restart") 264 } 265 func (f *fakeRunCommand) ensureServiceInstalled(dataDir string, statePort, oplogSizeMB int, setNUMAControlPolicy bool, version mongo.Version, auth bool, mmprof mongo.MemoryProfile) error { 266 ran := []string{"mongo.EnsureServiceInstalled", 267 dataDir, 268 strconv.Itoa(statePort), 269 strconv.Itoa(oplogSizeMB), 270 strconv.FormatBool(setNUMAControlPolicy), 271 version.String(), 272 strconv.FormatBool(auth), 273 mmprof.String()} 274 275 f.ranCommands = append(f.ranCommands, ran) 276 return nil 277 } 278 func (f *fakeRunCommand) mongoDialInfo(info mongo.Info, opts mongo.DialOpts) (*mgo.DialInfo, error) { 279 ran := []string{"mongo.DialInfo"} 280 f.ranCommands = append(f.ranCommands, ran) 281 return &mgo.DialInfo{}, nil 282 } 283 func (f *fakeRunCommand) initiateMongoServer(args peergrouper.InitiateMongoParams) error { 284 ran := []string{"peergrouper.InitiateMongoServer"} 285 f.ranCommands = append(f.ranCommands, ran) 286 return nil 287 } 288 289 func (f *fakeRunCommand) discoverService(serviceName string, c common.Conf) (service.Service, error) { 290 ran := []string{"service.DiscoverService", serviceName} 291 f.ranCommands = append(f.ranCommands, ran) 292 return f.service, nil 293 } 294 295 func (f *fakeRunCommand) fsCopy(src, dst string) error { 296 ran := []string{"fs.Copy", src, dst} 297 f.ranCommands = append(f.ranCommands, ran) 298 return nil 299 } 300 301 func (f *fakeRunCommand) replicaRemove(s mgoSession, addrs ...string) error { 302 ran := []string{"replicaRemove"} 303 f.ranCommands = append(f.ranCommands, ran) 304 return nil 305 } 306 307 func (f *fakeRunCommand) replicaAdd(s mgoSession, members ...replicaset.Member) error { 308 ran := []string{"replicaAdd"} 309 f.ranCommands = append(f.ranCommands, ran) 310 return nil 311 } 312 313 type fakeService struct { 314 ranCommands []string 315 } 316 317 func (f *fakeService) Start() error { 318 f.ranCommands = append(f.ranCommands, "Start") 319 return nil 320 } 321 322 func (f *fakeService) Stop() error { 323 f.ranCommands = append(f.ranCommands, "Stop") 324 return nil 325 } 326 327 func (f *fakeService) Install() error { 328 f.ranCommands = append(f.ranCommands, "Install") 329 return nil 330 } 331 332 func (f *fakeService) Remove() error { 333 f.ranCommands = append(f.ranCommands, "Remove") 334 return nil 335 } 336 337 func (f *fakeService) Name() string { 338 f.ranCommands = append(f.ranCommands, "Name") 339 return "FakeService" 340 } 341 342 func (f *fakeService) Conf() common.Conf { 343 f.ranCommands = append(f.ranCommands, "Conf") 344 return common.Conf{} 345 } 346 347 func (f *fakeService) Running() (bool, error) { 348 f.ranCommands = append(f.ranCommands, "Running") 349 return true, nil 350 } 351 352 func (f *fakeService) Exists() (bool, error) { 353 f.ranCommands = append(f.ranCommands, "Exists") 354 return true, nil 355 } 356 357 func (f *fakeService) Installed() (bool, error) { 358 f.ranCommands = append(f.ranCommands, "Installed") 359 return true, nil 360 } 361 362 func (f *fakeService) InstallCommands() ([]string, error) { 363 f.ranCommands = append(f.ranCommands, "InstalledCommands") 364 return []string{"echo", "install"}, nil 365 } 366 367 func (f *fakeService) StartCommands() ([]string, error) { 368 f.ranCommands = append(f.ranCommands, "StartCommands") 369 return []string{"echo", "start"}, nil 370 } 371 372 func (s *UpgradeMongoCommandSuite) createFakeAgentConf(c *gc.C, agentDir string, mongoVersion mongo.Version) { 373 attributeParams := agent.AgentConfigParams{ 374 Paths: agent.Paths{ 375 DataDir: agentDir, 376 }, 377 Tag: names.NewMachineTag("0"), 378 UpgradedToVersion: jujuversion.Current, 379 Password: "sekrit", 380 CACert: "ca cert", 381 APIAddresses: []string{"localhost:1235"}, 382 Nonce: "a nonce", 383 Controller: testing.ControllerTag, 384 Model: testing.ModelTag, 385 } 386 387 servingInfo := params.StateServingInfo{ 388 Cert: "cert", 389 PrivateKey: "key", 390 CAPrivateKey: "ca key", 391 StatePort: 69, 392 APIPort: 47, 393 SharedSecret: "shared", 394 SystemIdentity: "identity", 395 } 396 conf, err := agent.NewStateMachineConfig(attributeParams, servingInfo) 397 c.Check(err, jc.ErrorIsNil) 398 conf.SetMongoVersion(mongoVersion) 399 err = conf.Write() 400 c.Check(err, jc.ErrorIsNil) 401 } 402 403 func (s *UpgradeMongoCommandSuite) TestRun(c *gc.C) { 404 session := fakeMgoSesion{} 405 db := fakeMgoDb{} 406 service := fakeService{} 407 command := fakeRunCommand{ 408 mgoSession: &session, 409 mgoDb: &db, 410 service: &service, 411 } 412 413 testDir := c.MkDir() 414 testAgentConfig := agent.ConfigPath(testDir, names.NewMachineTag("0")) 415 s.createFakeAgentConf(c, testDir, mongo.Mongo24) 416 417 callArgs := retryCallArgs() 418 upgradeMongoCommand := &UpgradeMongoCommand{ 419 machineTag: "0", 420 series: "vivid", 421 configFilePath: testAgentConfig, 422 tmpDir: "/fake/temp/dir", 423 callArgs: callArgs, 424 425 stat: command.stat, 426 remove: command.remove, 427 mkdir: command.mkdir, 428 runCommand: command.runCommand, 429 dialAndLogin: command.dialAndLogin, 430 satisfyPrerequisites: command.satisfyPrerequisites, 431 createTempDir: command.createTempDir, 432 discoverService: command.discoverService, 433 fsCopy: command.fsCopy, 434 osGetenv: command.getenv, 435 436 mongoStart: command.startService, 437 mongoStop: command.stopService, 438 mongoRestart: command.reStartService, 439 mongoEnsureServiceInstalled: command.ensureServiceInstalled, 440 mongoDialInfo: command.mongoDialInfo, 441 initiateMongoServer: command.initiateMongoServer, 442 replicasetAdd: command.replicaAdd, 443 replicasetRemove: command.replicaRemove, 444 } 445 446 err := upgradeMongoCommand.run() 447 c.Assert(err, jc.ErrorIsNil) 448 449 dbDir := filepath.Join(testDir, "db") 450 expectedCommands := [][]string{ 451 {"getenv", "UPSTART_JOB"}, 452 {"service.DiscoverService", "bogus_daemon"}, 453 {"CreateTempDir"}, 454 {"SatisfyPrerequisites"}, 455 {"CreateTempDir"}, 456 {"mongo.StopService"}, 457 {"stat", "/var/lib/juju/db"}, 458 {"mkdir", "/fake/temp/dir/24"}, 459 {"fs.Copy", "/var/lib/juju/db", "/fake/temp/dir/24/db"}, 460 {"mongo.StartService"}, 461 {"mongo.StopService"}, 462 {"/usr/lib/juju/bin/mongod", "--dbpath", "/var/lib/juju/db", "--replSet", "juju", "--upgrade"}, 463 {"mongo.EnsureServiceInstalled", testDir, "69", "0", "false", "2.6/mmapv1", "true", "low"}, 464 {"mongo.StartService"}, 465 {"DialAndlogin"}, 466 {"mongo.ReStartService"}, 467 {"/usr/lib/juju/mongo2.6/bin/mongodump", "--ssl", "-u", "admin", "-p", "sekrit", "--port", "69", "--host", "localhost", "--out", "/fake/temp/dir/migrateTo30dump"}, 468 {"mongo.StopService"}, 469 {"mongo.EnsureServiceInstalled", testDir, "69", "0", "false", "3.2/mmapv1", "true", "low"}, 470 {"mongo.StartService"}, 471 {"/usr/lib/juju/mongo3.2/bin/mongodump", "--ssl", "-u", "admin", "-p", "sekrit", "--port", "69", "--host", "localhost", "--out", "/fake/temp/dir/migrateToTigerdump"}, 472 {"mongo.StopService"}, 473 {"stat", dbDir}, 474 {"remove", dbDir}, 475 {"mkdir", dbDir}, 476 {"mongo.EnsureServiceInstalled", testDir, "69", "0", "false", "3.2/wiredTiger", "false", "low"}, 477 {"mongo.DialInfo"}, 478 {"mongo.StartService"}, 479 {"peergrouper.InitiateMongoServer"}, 480 {"/usr/lib/juju/mongo3.2/bin/mongorestore", "--ssl", "--port", "69", "--host", "localhost", "--sslAllowInvalidCertificates", "--batchSize", "100", "/fake/temp/dir/migrateToTigerdump"}, 481 {"mongo.EnsureServiceInstalled", testDir, "69", "0", "false", "3.2/wiredTiger", "true", "low"}, 482 {"mongo.ReStartService"}, 483 } 484 c.Assert(command.ranCommands, jc.DeepEquals, expectedCommands) 485 c.Assert(session.ranClose, gc.Equals, 2) 486 c.Assert(db.ranAction, gc.Equals, "authSchemaUpgrade") 487 c.Assert(service.ranCommands, jc.DeepEquals, []string{"Stop", "Start"}) 488 } 489 490 func (s *UpgradeMongoCommandSuite) TestRunRollback(c *gc.C) { 491 session := fakeMgoSesion{} 492 db := fakeMgoDb{} 493 service := fakeService{} 494 command := fakeRunCommand{ 495 mgoSession: &session, 496 mgoDb: &db, 497 service: &service, 498 } 499 500 tempDir := c.MkDir() 501 testAgentConfig := agent.ConfigPath(tempDir, names.NewMachineTag("0")) 502 s.createFakeAgentConf(c, tempDir, mongo.Mongo24) 503 504 callArgs := retryCallArgs() 505 upgradeMongoCommand := &UpgradeMongoCommand{ 506 machineTag: "0", 507 series: "vivid", 508 configFilePath: testAgentConfig, 509 tmpDir: "/fake/temp/dir", 510 callArgs: callArgs, 511 512 stat: command.stat, 513 remove: command.remove, 514 mkdir: command.mkdir, 515 runCommand: command.runCommand, 516 dialAndLogin: command.dialAndLogin, 517 satisfyPrerequisites: command.satisfyPrerequisites, 518 createTempDir: command.createTempDir, 519 discoverService: command.discoverService, 520 fsCopy: command.fsCopy, 521 osGetenv: command.getenv, 522 523 mongoStart: command.startService, 524 mongoStop: command.stopService, 525 mongoRestart: command.reStartServiceFail, 526 mongoEnsureServiceInstalled: command.ensureServiceInstalled, 527 mongoDialInfo: command.mongoDialInfo, 528 initiateMongoServer: command.initiateMongoServer, 529 replicasetAdd: command.replicaAdd, 530 replicasetRemove: command.replicaRemove, 531 } 532 533 err := upgradeMongoCommand.run() 534 // It is nil because making Stop fail would be a less useful test. 535 c.Assert(err, gc.ErrorMatches, "failed upgrade and juju start after rollbacking upgrade: <nil>: cannot upgrade from mongo 2.4 to 2.6: cannot restart mongodb 2.6 service: failing restart") 536 537 expectedCommands := [][]string{ 538 {"getenv", "UPSTART_JOB"}, 539 {"service.DiscoverService", "bogus_daemon"}, 540 {"CreateTempDir"}, 541 {"SatisfyPrerequisites"}, 542 {"CreateTempDir"}, 543 {"mongo.StopService"}, 544 {"stat", "/var/lib/juju/db"}, 545 {"mkdir", "/fake/temp/dir/24"}, 546 {"fs.Copy", "/var/lib/juju/db", "/fake/temp/dir/24/db"}, 547 {"mongo.StartService"}, 548 {"mongo.StopService"}, 549 {"/usr/lib/juju/bin/mongod", "--dbpath", "/var/lib/juju/db", "--replSet", "juju", "--upgrade"}, 550 {"mongo.EnsureServiceInstalled", tempDir, "69", "0", "false", "2.6/mmapv1", "true", "low"}, 551 {"mongo.StartService"}, 552 {"DialAndlogin"}, 553 {"mongo.ReStartServiceFail"}, 554 {"mongo.StopService"}, 555 {"remove", "/var/lib/juju/db"}, 556 {"mongo.StartService"}, 557 } 558 559 c.Assert(command.ranCommands, jc.DeepEquals, expectedCommands) 560 c.Assert(session.ranClose, gc.Equals, 2) 561 c.Assert(db.ranAction, gc.Equals, "authSchemaUpgrade") 562 c.Assert(service.ranCommands, jc.DeepEquals, []string{"Stop", "Start"}) 563 } 564 565 func (s *UpgradeMongoCommandSuite) TestRunContinuesWhereLeft(c *gc.C) { 566 session := fakeMgoSesion{} 567 db := fakeMgoDb{} 568 service := fakeService{} 569 570 command := fakeRunCommand{ 571 mgoSession: &session, 572 mgoDb: &db, 573 service: &service, 574 } 575 576 testDir := c.MkDir() 577 testAgentConfig := agent.ConfigPath(testDir, names.NewMachineTag("0")) 578 s.createFakeAgentConf(c, testDir, mongo.Mongo26) 579 580 callArgs := retryCallArgs() 581 upgradeMongoCommand := &UpgradeMongoCommand{ 582 machineTag: "0", 583 series: "vivid", 584 configFilePath: testAgentConfig, 585 tmpDir: "/fake/temp/dir", 586 callArgs: callArgs, 587 588 stat: command.stat, 589 remove: command.remove, 590 mkdir: command.mkdir, 591 runCommand: command.runCommand, 592 dialAndLogin: command.dialAndLogin, 593 satisfyPrerequisites: command.satisfyPrerequisites, 594 createTempDir: command.createTempDir, 595 discoverService: command.discoverService, 596 fsCopy: command.fsCopy, 597 osGetenv: command.getenv, 598 599 mongoStart: command.startService, 600 mongoStop: command.stopService, 601 mongoRestart: command.reStartService, 602 mongoEnsureServiceInstalled: command.ensureServiceInstalled, 603 mongoDialInfo: command.mongoDialInfo, 604 initiateMongoServer: command.initiateMongoServer, 605 replicasetAdd: command.replicaAdd, 606 replicasetRemove: command.replicaRemove, 607 } 608 609 err := upgradeMongoCommand.run() 610 c.Assert(err, jc.ErrorIsNil) 611 dbDir := filepath.Join(testDir, "db") 612 expectedCommands := [][]string{ 613 {"getenv", "UPSTART_JOB"}, 614 {"service.DiscoverService", "bogus_daemon"}, 615 {"CreateTempDir"}, 616 {"SatisfyPrerequisites"}, 617 {"/usr/lib/juju/mongo2.6/bin/mongodump", "--ssl", "-u", "admin", "-p", "sekrit", "--port", "69", "--host", "localhost", "--out", "/fake/temp/dir/migrateTo30dump"}, 618 {"mongo.StopService"}, 619 {"mongo.EnsureServiceInstalled", testDir, "69", "0", "false", "3.2/mmapv1", "true", "low"}, 620 {"mongo.StartService"}, 621 {"/usr/lib/juju/mongo3.2/bin/mongodump", "--ssl", "-u", "admin", "-p", "sekrit", "--port", "69", "--host", "localhost", "--out", "/fake/temp/dir/migrateToTigerdump"}, 622 {"mongo.StopService"}, 623 {"stat", dbDir}, 624 {"remove", dbDir}, 625 {"mkdir", dbDir}, 626 {"mongo.EnsureServiceInstalled", testDir, "69", "0", "false", "3.2/wiredTiger", "false", "low"}, 627 {"mongo.DialInfo"}, 628 {"mongo.StartService"}, 629 {"peergrouper.InitiateMongoServer"}, 630 {"/usr/lib/juju/mongo3.2/bin/mongorestore", "--ssl", "--port", "69", "--host", "localhost", "--sslAllowInvalidCertificates", "--batchSize", "100", "/fake/temp/dir/migrateToTigerdump"}, 631 {"mongo.EnsureServiceInstalled", testDir, "69", "0", "false", "3.2/wiredTiger", "true", "low"}, 632 {"mongo.ReStartService"}, 633 } 634 c.Assert(command.ranCommands, gc.DeepEquals, expectedCommands) 635 }