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