github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/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/replicaset" 17 "github.com/juju/retry" 18 jc "github.com/juju/testing/checkers" 19 "github.com/juju/utils/clock" 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) 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 274 f.ranCommands = append(f.ranCommands, ran) 275 return nil 276 } 277 func (f *fakeRunCommand) mongoDialInfo(info mongo.Info, opts mongo.DialOpts) (*mgo.DialInfo, error) { 278 ran := []string{"mongo.DialInfo"} 279 f.ranCommands = append(f.ranCommands, ran) 280 return &mgo.DialInfo{}, nil 281 } 282 func (f *fakeRunCommand) initiateMongoServer(args peergrouper.InitiateMongoParams) error { 283 ran := []string{"peergrouper.InitiateMongoServer"} 284 f.ranCommands = append(f.ranCommands, ran) 285 return nil 286 } 287 288 func (f *fakeRunCommand) discoverService(serviceName string, c common.Conf) (service.Service, error) { 289 ran := []string{"service.DiscoverService", serviceName} 290 f.ranCommands = append(f.ranCommands, ran) 291 return f.service, nil 292 } 293 294 func (f *fakeRunCommand) fsCopy(src, dst string) error { 295 ran := []string{"fs.Copy", src, dst} 296 f.ranCommands = append(f.ranCommands, ran) 297 return nil 298 } 299 300 func (f *fakeRunCommand) replicaRemove(s mgoSession, addrs ...string) error { 301 ran := []string{"replicaRemove"} 302 f.ranCommands = append(f.ranCommands, ran) 303 return nil 304 } 305 306 func (f *fakeRunCommand) replicaAdd(s mgoSession, members ...replicaset.Member) error { 307 ran := []string{"replicaAdd"} 308 f.ranCommands = append(f.ranCommands, ran) 309 return nil 310 } 311 312 type fakeService struct { 313 ranCommands []string 314 } 315 316 func (f *fakeService) Start() error { 317 f.ranCommands = append(f.ranCommands, "Start") 318 return nil 319 } 320 321 func (f *fakeService) Stop() error { 322 f.ranCommands = append(f.ranCommands, "Stop") 323 return nil 324 } 325 326 func (f *fakeService) Install() error { 327 f.ranCommands = append(f.ranCommands, "Install") 328 return nil 329 } 330 331 func (f *fakeService) Remove() error { 332 f.ranCommands = append(f.ranCommands, "Remove") 333 return nil 334 } 335 336 func (f *fakeService) Name() string { 337 f.ranCommands = append(f.ranCommands, "Name") 338 return "FakeService" 339 } 340 341 func (f *fakeService) Conf() common.Conf { 342 f.ranCommands = append(f.ranCommands, "Conf") 343 return common.Conf{} 344 } 345 346 func (f *fakeService) Running() (bool, error) { 347 f.ranCommands = append(f.ranCommands, "Running") 348 return true, nil 349 } 350 351 func (f *fakeService) Exists() (bool, error) { 352 f.ranCommands = append(f.ranCommands, "Exists") 353 return true, nil 354 } 355 356 func (f *fakeService) Installed() (bool, error) { 357 f.ranCommands = append(f.ranCommands, "Installed") 358 return true, nil 359 } 360 361 func (f *fakeService) InstallCommands() ([]string, error) { 362 f.ranCommands = append(f.ranCommands, "InstalledCommands") 363 return []string{"echo", "install"}, nil 364 } 365 366 func (f *fakeService) StartCommands() ([]string, error) { 367 f.ranCommands = append(f.ranCommands, "StartCommands") 368 return []string{"echo", "start"}, nil 369 } 370 371 func (s *UpgradeMongoCommandSuite) createFakeAgentConf(c *gc.C, agentDir string, mongoVersion mongo.Version) { 372 attributeParams := agent.AgentConfigParams{ 373 Paths: agent.Paths{ 374 DataDir: agentDir, 375 }, 376 Tag: names.NewMachineTag("0"), 377 UpgradedToVersion: jujuversion.Current, 378 Password: "sekrit", 379 CACert: "ca cert", 380 StateAddresses: []string{"localhost:1234"}, 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 []string{"getenv", "UPSTART_JOB"}, 452 []string{"service.DiscoverService", "bogus_daemon"}, 453 []string{"CreateTempDir"}, 454 []string{"SatisfyPrerequisites"}, 455 []string{"CreateTempDir"}, 456 []string{"mongo.StopService"}, 457 []string{"stat", "/var/lib/juju/db"}, 458 []string{"mkdir", "/fake/temp/dir/24"}, 459 []string{"fs.Copy", "/var/lib/juju/db", "/fake/temp/dir/24/db"}, 460 []string{"mongo.StartService"}, 461 []string{"mongo.StopService"}, 462 []string{"/usr/lib/juju/bin/mongod", "--dbpath", "/var/lib/juju/db", "--replSet", "juju", "--upgrade"}, 463 []string{"mongo.EnsureServiceInstalled", testDir, "69", "0", "false", "2.6/mmapv1", "true"}, 464 []string{"mongo.StartService"}, 465 []string{"DialAndlogin"}, 466 []string{"mongo.ReStartService"}, 467 []string{"/usr/lib/juju/mongo2.6/bin/mongodump", "--ssl", "-u", "admin", "-p", "sekrit", "--port", "69", "--host", "localhost", "--out", "/fake/temp/dir/migrateTo30dump"}, 468 []string{"mongo.StopService"}, 469 []string{"mongo.EnsureServiceInstalled", testDir, "69", "0", "false", "3.2/mmapv1", "true"}, 470 []string{"mongo.StartService"}, 471 []string{"/usr/lib/juju/mongo3.2/bin/mongodump", "--ssl", "-u", "admin", "-p", "sekrit", "--port", "69", "--host", "localhost", "--out", "/fake/temp/dir/migrateToTigerdump"}, 472 []string{"mongo.StopService"}, 473 []string{"stat", dbDir}, 474 []string{"remove", dbDir}, 475 []string{"mkdir", dbDir}, 476 []string{"mongo.EnsureServiceInstalled", testDir, "69", "0", "false", "3.2/wiredTiger", "false"}, 477 []string{"mongo.DialInfo"}, 478 []string{"mongo.StartService"}, 479 []string{"peergrouper.InitiateMongoServer"}, 480 []string{"/usr/lib/juju/mongo3.2/bin/mongorestore", "--ssl", "--port", "69", "--host", "localhost", "--sslAllowInvalidCertificates", "--batchSize", "100", "/fake/temp/dir/migrateToTigerdump"}, 481 []string{"mongo.EnsureServiceInstalled", testDir, "69", "0", "false", "3.2/wiredTiger", "true"}, 482 []string{"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 []string{"getenv", "UPSTART_JOB"}, 539 []string{"service.DiscoverService", "bogus_daemon"}, 540 []string{"CreateTempDir"}, 541 []string{"SatisfyPrerequisites"}, 542 []string{"CreateTempDir"}, 543 []string{"mongo.StopService"}, 544 []string{"stat", "/var/lib/juju/db"}, 545 []string{"mkdir", "/fake/temp/dir/24"}, 546 []string{"fs.Copy", "/var/lib/juju/db", "/fake/temp/dir/24/db"}, 547 []string{"mongo.StartService"}, 548 []string{"mongo.StopService"}, 549 []string{"/usr/lib/juju/bin/mongod", "--dbpath", "/var/lib/juju/db", "--replSet", "juju", "--upgrade"}, 550 []string{"mongo.EnsureServiceInstalled", tempDir, "69", "0", "false", "2.6/mmapv1", "true"}, 551 []string{"mongo.StartService"}, 552 []string{"DialAndlogin"}, 553 []string{"mongo.ReStartServiceFail"}, 554 []string{"mongo.StopService"}, 555 []string{"remove", "/var/lib/juju/db"}, 556 []string{"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 []string{"getenv", "UPSTART_JOB"}, 614 []string{"service.DiscoverService", "bogus_daemon"}, 615 []string{"CreateTempDir"}, 616 []string{"SatisfyPrerequisites"}, 617 []string{"/usr/lib/juju/mongo2.6/bin/mongodump", "--ssl", "-u", "admin", "-p", "sekrit", "--port", "69", "--host", "localhost", "--out", "/fake/temp/dir/migrateTo30dump"}, 618 []string{"mongo.StopService"}, 619 []string{"mongo.EnsureServiceInstalled", testDir, "69", "0", "false", "3.2/mmapv1", "true"}, 620 []string{"mongo.StartService"}, 621 []string{"/usr/lib/juju/mongo3.2/bin/mongodump", "--ssl", "-u", "admin", "-p", "sekrit", "--port", "69", "--host", "localhost", "--out", "/fake/temp/dir/migrateToTigerdump"}, 622 []string{"mongo.StopService"}, 623 []string{"stat", dbDir}, 624 []string{"remove", dbDir}, 625 []string{"mkdir", dbDir}, 626 []string{"mongo.EnsureServiceInstalled", testDir, "69", "0", "false", "3.2/wiredTiger", "false"}, 627 []string{"mongo.DialInfo"}, 628 []string{"mongo.StartService"}, 629 []string{"peergrouper.InitiateMongoServer"}, 630 []string{"/usr/lib/juju/mongo3.2/bin/mongorestore", "--ssl", "--port", "69", "--host", "localhost", "--sslAllowInvalidCertificates", "--batchSize", "100", "/fake/temp/dir/migrateToTigerdump"}, 631 []string{"mongo.EnsureServiceInstalled", testDir, "69", "0", "false", "3.2/wiredTiger", "true"}, 632 []string{"mongo.ReStartService"}, 633 } 634 c.Assert(command.ranCommands, gc.DeepEquals, expectedCommands) 635 }