github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/modelmigration_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "fmt" 8 "time" 9 10 "github.com/juju/errors" 11 "github.com/juju/names/v5" 12 jc "github.com/juju/testing/checkers" 13 "github.com/juju/utils/v3" 14 gc "gopkg.in/check.v1" 15 "gopkg.in/macaroon.v2" 16 17 "github.com/juju/juju/core/migration" 18 "github.com/juju/juju/core/permission" 19 "github.com/juju/juju/state" 20 statetesting "github.com/juju/juju/state/testing" 21 "github.com/juju/juju/testing/factory" 22 ) 23 24 type MigrationSuite struct { 25 ConnSuite 26 State2 *state.State 27 stdSpec state.MigrationSpec 28 } 29 30 var _ = gc.Suite(new(MigrationSuite)) 31 32 func (s *MigrationSuite) SetUpTest(c *gc.C) { 33 s.ConnSuite.SetUpTest(c) 34 35 // Create a hosted model to migrate. 36 s.State2 = s.Factory.MakeModel(c, nil) 37 s.AddCleanup(func(*gc.C) { s.State2.Close() }) 38 39 targetControllerTag := names.NewControllerTag(utils.MustNewUUID().String()) 40 41 mac, err := macaroon.New([]byte("secret"), []byte("id"), "location", macaroon.LatestVersion) 42 c.Assert(err, jc.ErrorIsNil) 43 44 // Plausible migration arguments to test with. 45 s.stdSpec = state.MigrationSpec{ 46 InitiatedBy: names.NewUserTag("admin"), 47 TargetInfo: migration.TargetInfo{ 48 ControllerTag: targetControllerTag, 49 ControllerAlias: "target-controller", 50 Addrs: []string{"1.2.3.4:5555", "4.3.2.1:6666"}, 51 CACert: "cert", 52 AuthTag: names.NewUserTag("user"), 53 Password: "password", 54 Macaroons: []macaroon.Slice{{mac}}, 55 }, 56 } 57 // Before we get into the tests, ensure that all the creation events have flowed through the system. 58 s.WaitForModelWatchersIdle(c, s.State2.ModelUUID()) 59 } 60 61 func (s *MigrationSuite) TestCreate(c *gc.C) { 62 model, err := s.State2.Model() 63 c.Assert(err, jc.ErrorIsNil) 64 c.Assert(model.MigrationMode(), gc.Equals, state.MigrationModeNone) 65 66 mig, err := s.State2.CreateMigration(s.stdSpec) 67 c.Assert(err, jc.ErrorIsNil) 68 69 c.Check(mig.ModelUUID(), gc.Equals, s.State2.ModelUUID()) 70 checkIdAndAttempt(c, mig, 0) 71 72 c.Check(mig.StartTime().IsZero(), jc.IsFalse) 73 c.Check(mig.StartTime().Before(s.Clock.Now()), jc.IsTrue) 74 c.Check(mig.SuccessTime().IsZero(), jc.IsTrue) 75 c.Check(mig.EndTime().IsZero(), jc.IsTrue) 76 c.Check(mig.StatusMessage(), gc.Equals, "starting") 77 c.Check(mig.InitiatedBy(), gc.Equals, "admin") 78 79 info, err := mig.TargetInfo() 80 c.Assert(err, jc.ErrorIsNil) 81 // Extract macaroons so we can compare them separately 82 // (as they can't be compared using DeepEquals due to 'UnmarshaledAs') 83 infoMacs := info.Macaroons 84 info.Macaroons = nil 85 assertMacaroonsEqual(c, infoMacs, s.stdSpec.TargetInfo.Macaroons) 86 s.stdSpec.TargetInfo.Macaroons = nil 87 c.Check(*info, jc.DeepEquals, s.stdSpec.TargetInfo) 88 c.Check(info.ControllerAlias, gc.Equals, s.stdSpec.TargetInfo.ControllerAlias) 89 90 assertPhase(c, mig, migration.QUIESCE) 91 c.Check(mig.PhaseChangedTime(), gc.Equals, mig.StartTime()) 92 93 assertMigrationActive(c, s.State2) 94 95 c.Assert(model.Refresh(), jc.ErrorIsNil) 96 c.Check(model.MigrationMode(), gc.Equals, state.MigrationModeExporting) 97 } 98 99 func (s *MigrationSuite) TestIsMigrationActive(c *gc.C) { 100 check := func(expected bool) { 101 isActive, err := s.State2.IsMigrationActive() 102 c.Assert(err, jc.ErrorIsNil) 103 c.Check(isActive, gc.Equals, expected) 104 105 isActive2, err := state.IsMigrationActive(s.State, s.State2.ModelUUID()) 106 c.Assert(err, jc.ErrorIsNil) 107 c.Check(isActive2, gc.Equals, expected) 108 } 109 110 check(false) 111 112 _, err := s.State2.CreateMigration(s.stdSpec) 113 c.Assert(err, jc.ErrorIsNil) 114 115 check(true) 116 } 117 118 func (s *MigrationSuite) TestIdSequencesAreIndependent(c *gc.C) { 119 st2 := s.State2 120 st3 := s.Factory.MakeModel(c, nil) 121 s.AddCleanup(func(*gc.C) { st3.Close() }) 122 123 mig2, err := st2.CreateMigration(s.stdSpec) 124 c.Assert(err, jc.ErrorIsNil) 125 checkIdAndAttempt(c, mig2, 0) 126 127 mig3, err := st3.CreateMigration(s.stdSpec) 128 c.Assert(err, jc.ErrorIsNil) 129 checkIdAndAttempt(c, mig3, 0) 130 } 131 132 func (s *MigrationSuite) TestIdSequencesIncrement(c *gc.C) { 133 for attempt := 0; attempt < 3; attempt++ { 134 mig, err := s.State2.CreateMigration(s.stdSpec) 135 c.Assert(err, jc.ErrorIsNil) 136 checkIdAndAttempt(c, mig, attempt) 137 c.Check(mig.SetPhase(migration.ABORT), jc.ErrorIsNil) 138 c.Check(mig.SetPhase(migration.ABORTDONE), jc.ErrorIsNil) 139 } 140 } 141 142 func (s *MigrationSuite) TestIdSequencesIncrementOnlyWhenNecessary(c *gc.C) { 143 // Ensure that sequence numbers aren't "used up" unnecessarily 144 // when the create txn is going to fail. 145 146 mig, err := s.State2.CreateMigration(s.stdSpec) 147 c.Assert(err, jc.ErrorIsNil) 148 checkIdAndAttempt(c, mig, 0) 149 150 // This attempt will fail because a migration is already in 151 // progress. 152 _, err = s.State2.CreateMigration(s.stdSpec) 153 c.Assert(err, gc.ErrorMatches, ".+already in progress") 154 155 // Now abort the migration and create another. The Id sequence 156 // should have only incremented by 1. 157 c.Assert(mig.SetPhase(migration.ABORT), jc.ErrorIsNil) 158 c.Assert(mig.SetPhase(migration.ABORTDONE), jc.ErrorIsNil) 159 160 mig, err = s.State2.CreateMigration(s.stdSpec) 161 c.Assert(err, jc.ErrorIsNil) 162 checkIdAndAttempt(c, mig, 1) 163 } 164 165 func (s *MigrationSuite) TestSpecValidation(c *gc.C) { 166 tests := []struct { 167 label string 168 tweakSpec func(*state.MigrationSpec) 169 errorPattern string 170 }{{ 171 "invalid InitiatedBy", 172 func(spec *state.MigrationSpec) { 173 spec.InitiatedBy = names.UserTag{} 174 }, 175 "InitiatedBy not valid", 176 }, { 177 "TargetInfo is validated", 178 func(spec *state.MigrationSpec) { 179 spec.TargetInfo.Addrs = nil 180 }, 181 "empty Addrs not valid", 182 }} 183 for _, test := range tests { 184 c.Logf("---- %s -----------", test.label) 185 186 // Set up spec. 187 spec := s.stdSpec 188 test.tweakSpec(&spec) 189 190 // Check Validate directly. 191 err := spec.Validate() 192 c.Check(errors.IsNotValid(err), jc.IsTrue) 193 c.Check(err, gc.ErrorMatches, test.errorPattern) 194 195 // Ensure that CreateMigration rejects the bad spec too. 196 mig, err := s.State2.CreateMigration(spec) 197 c.Check(mig, gc.IsNil) 198 c.Check(errors.IsNotValid(err), jc.IsTrue) 199 c.Check(err, gc.ErrorMatches, test.errorPattern) 200 } 201 } 202 203 func (s *MigrationSuite) TestCreateWithControllerModel(c *gc.C) { 204 // This is the State for the controller 205 mig, err := s.State.CreateMigration(s.stdSpec) 206 c.Check(mig, gc.IsNil) 207 c.Check(err, gc.ErrorMatches, "controllers can't be migrated") 208 } 209 210 func (s *MigrationSuite) TestCreateMigrationInProgress(c *gc.C) { 211 mig, err := s.State2.CreateMigration(s.stdSpec) 212 c.Assert(mig, gc.Not(gc.IsNil)) 213 c.Assert(err, jc.ErrorIsNil) 214 215 mig2, err := s.State2.CreateMigration(s.stdSpec) 216 c.Check(mig2, gc.IsNil) 217 c.Check(err, gc.ErrorMatches, "failed to create migration: already in progress") 218 } 219 220 func (s *MigrationSuite) TestCreateMigrationRace(c *gc.C) { 221 defer state.SetBeforeHooks(c, s.State2, func() { 222 mig, err := s.State2.CreateMigration(s.stdSpec) 223 c.Assert(mig, gc.Not(gc.IsNil)) 224 c.Assert(err, jc.ErrorIsNil) 225 }).Check() 226 227 mig, err := s.State2.CreateMigration(s.stdSpec) 228 c.Check(mig, gc.IsNil) 229 c.Check(err, gc.ErrorMatches, "failed to create migration: already in progress") 230 } 231 232 func (s *MigrationSuite) TestCreateMigrationWhenModelNotAlive(c *gc.C) { 233 // Set the hosted model to Dying. 234 model, err := s.State2.Model() 235 c.Assert(err, jc.ErrorIsNil) 236 c.Assert(model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil) 237 238 mig, err := s.State2.CreateMigration(s.stdSpec) 239 c.Check(mig, gc.IsNil) 240 c.Check(err, gc.ErrorMatches, "failed to create migration: model is not alive") 241 } 242 243 func (s *MigrationSuite) TestMigrationToSameController(c *gc.C) { 244 spec := s.stdSpec 245 spec.TargetInfo.ControllerTag = s.State.ControllerTag() 246 247 mig, err := s.State2.CreateMigration(spec) 248 c.Check(mig, gc.IsNil) 249 c.Check(err, gc.ErrorMatches, "model already attached to target controller") 250 } 251 252 func (s *MigrationSuite) TestLatestMigration(c *gc.C) { 253 mig1, err := s.State2.CreateMigration(s.stdSpec) 254 c.Assert(err, jc.ErrorIsNil) 255 256 mig2, err := s.State2.LatestMigration() 257 c.Assert(err, jc.ErrorIsNil) 258 259 c.Assert(mig1.Id(), gc.Equals, mig2.Id()) 260 } 261 262 func (s *MigrationSuite) TestLatestMigrationNotExist(c *gc.C) { 263 mig, err := s.State.LatestMigration() 264 c.Check(mig, gc.IsNil) 265 c.Check(errors.IsNotFound(err), jc.IsTrue) 266 } 267 268 func (s *MigrationSuite) TestGetsLatestAttempt(c *gc.C) { 269 modelUUID := s.State2.ModelUUID() 270 271 for i := 0; i < 10; i++ { 272 c.Logf("loop %d", i) 273 _, err := s.State2.CreateMigration(s.stdSpec) 274 c.Assert(err, jc.ErrorIsNil) 275 276 mig, err := s.State2.LatestMigration() 277 c.Assert(err, jc.ErrorIsNil) 278 c.Check(mig.Id(), gc.Equals, fmt.Sprintf("%s:%d", modelUUID, i)) 279 280 c.Assert(mig.SetPhase(migration.ABORT), jc.ErrorIsNil) 281 c.Assert(mig.SetPhase(migration.ABORTDONE), jc.ErrorIsNil) 282 } 283 } 284 285 func (s *MigrationSuite) TestLatestMigrationWithPrevious(c *gc.C) { 286 // Check the scenario of a model having been migrated away and 287 // then migrated back several times. The previous migrations 288 // shouldn't be reported by LatestMigration. 289 290 // Make it appear as if the model has been successfully 291 // migrated. Don't actually remove model documents to simulate it 292 // having been migrated back to the controller. 293 phases := []migration.Phase{ 294 migration.IMPORT, 295 migration.PROCESSRELATIONS, 296 migration.VALIDATION, 297 migration.SUCCESS, 298 migration.LOGTRANSFER, 299 migration.REAP, 300 migration.DONE, 301 } 302 for i := 0; i < 10; i++ { 303 mig, err := s.State2.CreateMigration(s.stdSpec) 304 c.Assert(err, jc.ErrorIsNil) 305 for _, phase := range phases { 306 c.Assert(mig.SetPhase(phase), jc.ErrorIsNil) 307 } 308 state.ResetMigrationMode(c, s.State2) 309 } 310 311 // Previous migration shouldn't be reported. 312 _, err := s.State2.LatestMigration() 313 c.Check(errors.IsNotFound(err), jc.IsTrue) 314 315 // Start a new migration attempt, which should be reported. 316 migNext, err := s.State2.CreateMigration(s.stdSpec) 317 c.Assert(err, jc.ErrorIsNil) 318 319 migNextb, err := s.State2.LatestMigration() 320 c.Check(err, jc.ErrorIsNil) 321 c.Check(migNextb.Id(), gc.Equals, migNext.Id()) 322 phase, err := migNextb.Phase() 323 c.Assert(err, jc.ErrorIsNil) 324 c.Check(phase, gc.Equals, migration.QUIESCE) 325 } 326 327 func (s *MigrationSuite) TestLatestRemovedModelMigration(c *gc.C) { 328 model, err := s.State2.Model() 329 c.Assert(err, jc.ErrorIsNil) 330 331 mig1, err := s.State2.CreateMigration(s.stdSpec) 332 c.Assert(err, jc.ErrorIsNil) 333 334 for _, phase := range migration.SuccessfulMigrationPhases() { 335 c.Assert(mig1.SetPhase(phase), jc.ErrorIsNil) 336 } 337 338 // CompletedMigration should fail as the model docs are still there 339 _, err = s.State2.CompletedMigration() 340 c.Assert(errors.IsNotFound(err), gc.Equals, true) 341 342 // Delete the model and check that we get back the MigrationModel 343 c.Assert(model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil) 344 c.Assert(s.State2.RemoveDyingModel(), jc.ErrorIsNil) 345 346 mig2, err := s.State2.CompletedMigration() 347 c.Assert(err, jc.ErrorIsNil) 348 c.Assert(mig2, jc.DeepEquals, mig1) 349 } 350 351 func (s *MigrationSuite) TestMigration(c *gc.C) { 352 mig1, err := s.State2.CreateMigration(s.stdSpec) 353 c.Assert(err, jc.ErrorIsNil) 354 355 mig2, err := s.State2.Migration(mig1.Id()) 356 c.Check(err, jc.ErrorIsNil) 357 c.Check(mig1.Id(), gc.Equals, mig2.Id()) 358 c.Check(mig2.StartTime().IsZero(), jc.IsFalse) 359 c.Check(mig2.StartTime().Before(s.Clock.Now()), jc.IsTrue) 360 } 361 362 func (s *MigrationSuite) TestMigrationNotFound(c *gc.C) { 363 _, err := s.State2.Migration("does not exist") 364 c.Check(err, jc.Satisfies, errors.IsNotFound) 365 c.Check(err, gc.ErrorMatches, "migration not found") 366 } 367 368 func (s *MigrationSuite) TestRefresh(c *gc.C) { 369 mig1, err := s.State2.CreateMigration(s.stdSpec) 370 c.Assert(err, jc.ErrorIsNil) 371 372 mig2, err := s.State2.LatestMigration() 373 c.Assert(err, jc.ErrorIsNil) 374 375 err = mig1.SetPhase(migration.IMPORT) 376 c.Assert(err, jc.ErrorIsNil) 377 378 assertPhase(c, mig2, migration.QUIESCE) 379 err = mig2.Refresh() 380 c.Assert(err, jc.ErrorIsNil) 381 assertPhase(c, mig2, migration.IMPORT) 382 } 383 384 func (s *MigrationSuite) TestSuccessfulPhaseTransitions(c *gc.C) { 385 st := s.State2 386 387 mig, err := st.CreateMigration(s.stdSpec) 388 c.Assert(err, jc.ErrorIsNil) 389 c.Assert(mig, gc.NotNil) 390 391 mig2, err := st.LatestMigration() 392 c.Assert(err, jc.ErrorIsNil) 393 394 phases := migration.SuccessfulMigrationPhases() 395 396 var successTime time.Time 397 for _, phase := range phases[:len(phases)-1] { 398 err := mig.SetPhase(phase) 399 c.Assert(err, jc.ErrorIsNil) 400 401 assertPhase(c, mig, phase) 402 c.Check(mig.PhaseChangedTime().IsZero(), jc.IsFalse) 403 c.Assert(mig.PhaseChangedTime().Before(s.Clock.Now()), jc.IsTrue) 404 405 // Check success timestamp is set only when SUCCESS is 406 // reached. 407 if phase < migration.SUCCESS { 408 c.Assert(mig.SuccessTime().IsZero(), jc.IsTrue) 409 } else { 410 if phase == migration.SUCCESS { 411 successTime = s.Clock.Now() 412 } 413 if successTime.IsZero() { 414 c.Assert(mig.SuccessTime().IsZero(), jc.IsTrue) 415 } else { 416 c.Assert(mig.SuccessTime().IsZero(), jc.IsFalse) 417 c.Assert(mig.SuccessTime().Before(successTime), jc.IsTrue) 418 } 419 } 420 421 // Check still marked as active. 422 assertMigrationActive(c, s.State2) 423 c.Assert(mig.EndTime().IsZero(), jc.IsTrue) 424 425 // Ensure change was peristed. 426 c.Assert(mig2.Refresh(), jc.ErrorIsNil) 427 assertPhase(c, mig2, phase) 428 429 s.Clock.Advance(time.Millisecond) 430 } 431 432 // Now move to the final phase (DONE) and ensure fields are set as 433 // expected. 434 err = mig.SetPhase(migration.DONE) 435 c.Assert(err, jc.ErrorIsNil) 436 assertPhase(c, mig, migration.DONE) 437 s.assertMigrationCleanedUp(c, mig) 438 } 439 440 func (s *MigrationSuite) TestABORTCleanup(c *gc.C) { 441 mig, err := s.State2.CreateMigration(s.stdSpec) 442 c.Assert(err, jc.ErrorIsNil) 443 444 s.Clock.Advance(time.Millisecond) 445 c.Assert(mig.SetPhase(migration.ABORT), jc.ErrorIsNil) 446 s.Clock.Advance(time.Millisecond) 447 c.Assert(mig.SetPhase(migration.ABORTDONE), jc.ErrorIsNil) 448 449 s.assertMigrationCleanedUp(c, mig) 450 451 // Model should be set back to active. 452 model, err := s.State2.Model() 453 c.Assert(err, jc.ErrorIsNil) 454 c.Assert(model.MigrationMode(), gc.Equals, state.MigrationModeNone) 455 } 456 457 func (s *MigrationSuite) TestREAPFAILEDCleanup(c *gc.C) { 458 mig, err := s.State2.CreateMigration(s.stdSpec) 459 c.Assert(err, jc.ErrorIsNil) 460 461 // Advance the migration to REAPFAILED. 462 phases := []migration.Phase{ 463 migration.IMPORT, 464 migration.PROCESSRELATIONS, 465 migration.VALIDATION, 466 migration.SUCCESS, 467 migration.LOGTRANSFER, 468 migration.REAP, 469 migration.REAPFAILED, 470 } 471 for _, phase := range phases { 472 s.Clock.Advance(time.Millisecond) 473 c.Assert(mig.SetPhase(phase), jc.ErrorIsNil) 474 } 475 476 s.assertMigrationCleanedUp(c, mig) 477 } 478 479 func (s *MigrationSuite) assertMigrationCleanedUp(c *gc.C, mig state.ModelMigration) { 480 c.Check(mig.PhaseChangedTime().IsZero(), jc.IsFalse) 481 c.Assert(mig.PhaseChangedTime().Before(s.Clock.Now()), jc.IsTrue) 482 c.Check(mig.EndTime().IsZero(), jc.IsFalse) 483 c.Assert(mig.EndTime().Before(s.Clock.Now()), jc.IsTrue) 484 assertMigrationNotActive(c, s.State2) 485 } 486 487 func (s *MigrationSuite) TestIllegalPhaseTransition(c *gc.C) { 488 mig, err := s.State2.CreateMigration(s.stdSpec) 489 c.Assert(err, jc.ErrorIsNil) 490 491 err = mig.SetPhase(migration.SUCCESS) 492 c.Check(err, gc.ErrorMatches, "illegal phase change: QUIESCE -> SUCCESS") 493 } 494 495 func (s *MigrationSuite) TestPhaseChangeRace(c *gc.C) { 496 mig, err := s.State2.CreateMigration(s.stdSpec) 497 c.Assert(err, jc.ErrorIsNil) 498 c.Assert(mig, gc.Not(gc.IsNil)) 499 500 defer state.SetBeforeHooks(c, s.State2, func() { 501 mig, err := s.State2.LatestMigration() 502 c.Assert(err, jc.ErrorIsNil) 503 c.Assert(mig.SetPhase(migration.IMPORT), jc.ErrorIsNil) 504 }).Check() 505 506 err = mig.SetPhase(migration.IMPORT) 507 c.Assert(err, gc.ErrorMatches, "phase already changed") 508 assertPhase(c, mig, migration.QUIESCE) 509 510 // After a refresh it the phase change should be ok. 511 c.Assert(mig.Refresh(), jc.ErrorIsNil) 512 err = mig.SetPhase(migration.IMPORT) 513 c.Assert(err, jc.ErrorIsNil) 514 assertPhase(c, mig, migration.IMPORT) 515 } 516 517 func (s *MigrationSuite) TestStatusMessage(c *gc.C) { 518 mig, err := s.State2.CreateMigration(s.stdSpec) 519 c.Assert(err, jc.ErrorIsNil) 520 c.Assert(mig, gc.Not(gc.IsNil)) 521 522 mig2, err := s.State2.LatestMigration() 523 c.Assert(err, jc.ErrorIsNil) 524 525 c.Check(mig.StatusMessage(), gc.Equals, "starting") 526 c.Check(mig2.StatusMessage(), gc.Equals, "starting") 527 528 err = mig.SetStatusMessage("foo bar") 529 c.Assert(err, jc.ErrorIsNil) 530 531 c.Check(mig.StatusMessage(), gc.Equals, "foo bar") 532 533 c.Assert(mig2.Refresh(), jc.ErrorIsNil) 534 c.Check(mig2.StatusMessage(), gc.Equals, "foo bar") 535 } 536 537 func (s *MigrationSuite) TestWatchForMigration(c *gc.C) { 538 // Start watching for migration. 539 w, wc := s.createMigrationWatcher(c, s.State2) 540 wc.AssertOneChange() 541 542 // Create the migration - should be reported. 543 mig, err := s.State2.CreateMigration(s.stdSpec) 544 c.Assert(err, jc.ErrorIsNil) 545 wc.AssertOneChange() 546 547 // Mere phase changes should not be reported. 548 c.Check(mig.SetPhase(migration.ABORT), jc.ErrorIsNil) 549 wc.AssertNoChange() 550 551 // Ending the migration should be reported. 552 c.Check(mig.SetPhase(migration.ABORTDONE), jc.ErrorIsNil) 553 wc.AssertOneChange() 554 555 statetesting.AssertStop(c, w) 556 wc.AssertClosed() 557 } 558 559 func (s *MigrationSuite) TestWatchForMigrationInProgress(c *gc.C) { 560 // Create a migration. 561 _, err := s.State2.CreateMigration(s.stdSpec) 562 c.Assert(err, jc.ErrorIsNil) 563 // Ensure that all the creation events have flowed through the system. 564 s.WaitForModelWatchersIdle(c, s.State2.ModelUUID()) 565 566 // Start watching for a migration - the in progress one should be reported. 567 _, wc := s.createMigrationWatcher(c, s.State2) 568 wc.AssertOneChange() 569 } 570 571 func (s *MigrationSuite) TestWatchForMigrationMultiModel(c *gc.C) { 572 _, wc2 := s.createMigrationWatcher(c, s.State2) 573 wc2.AssertOneChange() 574 575 // Create another hosted model to migrate and watch for 576 // migrations. 577 State3 := s.Factory.MakeModel(c, nil) 578 s.AddCleanup(func(*gc.C) { State3.Close() }) 579 // Ensure that all the creation events have flowed through the system. 580 s.WaitForModelWatchersIdle(c, State3.ModelUUID()) 581 _, wc3 := s.createMigrationWatcher(c, State3) 582 wc3.AssertOneChange() 583 584 // Create a migration for 2. 585 _, err := s.State2.CreateMigration(s.stdSpec) 586 c.Assert(err, jc.ErrorIsNil) 587 wc2.AssertOneChange() 588 wc3.AssertNoChange() 589 590 // Create a migration for 3. 591 _, err = State3.CreateMigration(s.stdSpec) 592 c.Assert(err, jc.ErrorIsNil) 593 wc2.AssertNoChange() 594 wc3.AssertOneChange() 595 } 596 597 func (s *MigrationSuite) createMigrationWatcher(c *gc.C, st *state.State) ( 598 state.NotifyWatcher, statetesting.NotifyWatcherC, 599 ) { 600 w := st.WatchForMigration() 601 s.AddCleanup(func(c *gc.C) { statetesting.AssertStop(c, w) }) 602 return w, statetesting.NewNotifyWatcherC(c, w) 603 } 604 605 func (s *MigrationSuite) TestWatchMigrationStatus(c *gc.C) { 606 w, wc := s.createStatusWatcher(c, s.State2) 607 wc.AssertOneChange() // Initial event. 608 609 // Create a migration. 610 mig, err := s.State2.CreateMigration(s.stdSpec) 611 c.Assert(err, jc.ErrorIsNil) 612 wc.AssertOneChange() 613 614 // End it. 615 c.Assert(mig.SetPhase(migration.ABORT), jc.ErrorIsNil) 616 wc.AssertOneChange() 617 c.Assert(mig.SetPhase(migration.ABORTDONE), jc.ErrorIsNil) 618 wc.AssertOneChange() 619 620 // Start another. 621 mig2, err := s.State2.CreateMigration(s.stdSpec) 622 c.Assert(err, jc.ErrorIsNil) 623 wc.AssertOneChange() 624 625 // Change phase. 626 c.Assert(mig2.SetPhase(migration.IMPORT), jc.ErrorIsNil) 627 wc.AssertOneChange() 628 629 // End it. 630 c.Assert(mig2.SetPhase(migration.ABORT), jc.ErrorIsNil) 631 wc.AssertOneChange() 632 633 statetesting.AssertStop(c, w) 634 wc.AssertClosed() 635 } 636 637 func (s *MigrationSuite) TestWatchMigrationStatusPreexisting(c *gc.C) { 638 // Create an aborted migration. 639 mig, err := s.State2.CreateMigration(s.stdSpec) 640 c.Assert(err, jc.ErrorIsNil) 641 c.Assert(mig.SetPhase(migration.ABORT), jc.ErrorIsNil) 642 643 // Ensure that all the creation events have flowed through the system. 644 s.WaitForModelWatchersIdle(c, s.State2.ModelUUID()) 645 646 _, wc := s.createStatusWatcher(c, s.State2) 647 wc.AssertOneChange() 648 } 649 650 func (s *MigrationSuite) TestWatchMigrationStatusMultiModel(c *gc.C) { 651 _, wc2 := s.createStatusWatcher(c, s.State2) 652 wc2.AssertOneChange() // initial event 653 654 // Create another hosted model to migrate and watch for 655 // migrations. 656 State3 := s.Factory.MakeModel(c, nil) 657 s.AddCleanup(func(*gc.C) { State3.Close() }) 658 // Ensure that all the creation events have flowed through the system. 659 s.WaitForModelWatchersIdle(c, State3.ModelUUID()) 660 661 _, wc3 := s.createStatusWatcher(c, State3) 662 wc3.AssertOneChange() // initial event 663 664 // Create a migration for 2. 665 mig, err := s.State2.CreateMigration(s.stdSpec) 666 c.Assert(err, jc.ErrorIsNil) 667 wc2.AssertOneChange() 668 wc3.AssertNoChange() 669 670 // Create a migration for 3. 671 _, err = State3.CreateMigration(s.stdSpec) 672 c.Assert(err, jc.ErrorIsNil) 673 wc2.AssertNoChange() 674 wc3.AssertOneChange() 675 676 // Update the migration for 2. 677 err = mig.SetPhase(migration.ABORT) 678 c.Assert(err, jc.ErrorIsNil) 679 wc2.AssertOneChange() 680 wc3.AssertNoChange() 681 } 682 683 func (s *MigrationSuite) TestMinionReports(c *gc.C) { 684 // Create some machines and units to report with. 685 factory2 := factory.NewFactory(s.State2, s.StatePool) 686 m0 := factory2.MakeMachine(c, nil) 687 u0 := factory2.MakeUnit(c, &factory.UnitParams{Machine: m0}) 688 m1 := factory2.MakeMachine(c, nil) 689 m2 := factory2.MakeMachine(c, nil) 690 691 mig, err := s.State2.CreateMigration(s.stdSpec) 692 c.Assert(err, jc.ErrorIsNil) 693 694 const phase = migration.QUIESCE 695 c.Assert(mig.SubmitMinionReport(m0.Tag(), phase, true), jc.ErrorIsNil) 696 c.Assert(mig.SubmitMinionReport(m1.Tag(), phase, false), jc.ErrorIsNil) 697 c.Assert(mig.SubmitMinionReport(u0.Tag(), phase, true), jc.ErrorIsNil) 698 699 reports, err := mig.MinionReports() 700 c.Assert(err, jc.ErrorIsNil) 701 c.Check(reports.Succeeded, jc.SameContents, []names.Tag{m0.Tag(), u0.Tag()}) 702 c.Check(reports.Failed, jc.SameContents, []names.Tag{m1.Tag()}) 703 c.Check(reports.Unknown, jc.SameContents, []names.Tag{m2.Tag()}) 704 } 705 706 func (s *MigrationSuite) TestMinionReportsCAASLegacy(c *gc.C) { 707 // Create some machines and units to report with. 708 st := s.Factory.MakeCAASModel(c, nil) 709 defer st.Close() 710 factory2 := factory.NewFactory(st, s.StatePool) 711 ch := factory2.MakeCharm(c, &factory.CharmParams{Name: "gitlab", Series: "kubernetes"}) 712 a0 := factory2.MakeApplication(c, &factory.ApplicationParams{Name: "a0", Charm: ch}) 713 a1 := factory2.MakeApplication(c, &factory.ApplicationParams{Name: "a1", Charm: ch}) 714 a2 := factory2.MakeApplication(c, &factory.ApplicationParams{Name: "a2", Charm: ch}) 715 716 mig, err := st.CreateMigration(s.stdSpec) 717 c.Assert(err, jc.ErrorIsNil) 718 719 const phase = migration.QUIESCE 720 c.Assert(mig.SubmitMinionReport(a0.Tag(), phase, true), jc.ErrorIsNil) 721 c.Assert(mig.SubmitMinionReport(a1.Tag(), phase, false), jc.ErrorIsNil) 722 723 reports, err := mig.MinionReports() 724 c.Assert(err, jc.ErrorIsNil) 725 c.Check(reports.Succeeded, jc.SameContents, []names.Tag{a0.Tag()}) 726 c.Check(reports.Failed, jc.SameContents, []names.Tag{a1.Tag()}) 727 c.Check(reports.Unknown, jc.SameContents, []names.Tag{a2.Tag()}) 728 } 729 730 func (s *MigrationSuite) TestMinionReportsCAASEmbedded(c *gc.C) { 731 // Create some machines and units to report with. 732 st := s.Factory.MakeCAASModel(c, nil) 733 defer st.Close() 734 factory2 := factory.NewFactory(st, s.StatePool) 735 ch := factory2.MakeCharmV2(c, &factory.CharmParams{ 736 Name: "snappass-test", 737 Series: "quantal", 738 }) 739 a0 := factory2.MakeApplication(c, &factory.ApplicationParams{Name: "a0", Charm: ch}) 740 u1a0, err := a0.AddUnit(state.AddUnitParams{ProviderId: strPtr("provider-id0")}) 741 c.Assert(err, jc.ErrorIsNil) 742 a1 := factory2.MakeApplication(c, &factory.ApplicationParams{Name: "a1", Charm: ch}) 743 u1a1, err := a1.AddUnit(state.AddUnitParams{ProviderId: strPtr("provider-id1")}) 744 c.Assert(err, jc.ErrorIsNil) 745 a2 := factory2.MakeApplication(c, &factory.ApplicationParams{Name: "a2", Charm: ch}) 746 u1a2, err := a2.AddUnit(state.AddUnitParams{ProviderId: strPtr("provider-id2")}) 747 c.Assert(err, jc.ErrorIsNil) 748 749 mig, err := st.CreateMigration(s.stdSpec) 750 c.Assert(err, jc.ErrorIsNil) 751 752 const phase = migration.QUIESCE 753 c.Assert(mig.SubmitMinionReport(u1a0.Tag(), phase, true), jc.ErrorIsNil) 754 c.Assert(mig.SubmitMinionReport(u1a1.Tag(), phase, false), jc.ErrorIsNil) 755 756 reports, err := mig.MinionReports() 757 c.Assert(err, jc.ErrorIsNil) 758 c.Check(reports.Succeeded, jc.SameContents, []names.Tag{u1a0.Tag()}) 759 c.Check(reports.Failed, jc.SameContents, []names.Tag{u1a1.Tag()}) 760 c.Check(reports.Unknown, jc.SameContents, []names.Tag{u1a2.Tag()}) 761 } 762 763 func (s *MigrationSuite) TestDuplicateMinionReportsSameSuccess(c *gc.C) { 764 // It should be OK for a minion report to arrive more than once 765 // for the same migration, agent and phase as long as the value of 766 // "success" is the same. 767 mig, err := s.State2.CreateMigration(s.stdSpec) 768 c.Assert(err, jc.ErrorIsNil) 769 tag := names.NewMachineTag("42") 770 c.Check(mig.SubmitMinionReport(tag, migration.QUIESCE, true), jc.ErrorIsNil) 771 c.Check(mig.SubmitMinionReport(tag, migration.QUIESCE, true), jc.ErrorIsNil) 772 } 773 774 func (s *MigrationSuite) TestDuplicateMinionReportsDifferingSuccess(c *gc.C) { 775 // It is not OK for a minion report to arrive more than once for 776 // the same migration, agent and phase when the "success" value 777 // changes. 778 mig, err := s.State2.CreateMigration(s.stdSpec) 779 c.Assert(err, jc.ErrorIsNil) 780 tag := names.NewMachineTag("42") 781 c.Check(mig.SubmitMinionReport(tag, migration.QUIESCE, true), jc.ErrorIsNil) 782 err = mig.SubmitMinionReport(tag, migration.QUIESCE, false) 783 c.Check(err, gc.ErrorMatches, 784 fmt.Sprintf("conflicting reports received for %s/QUIESCE/machine-42", mig.Id())) 785 } 786 787 func (s *MigrationSuite) TestMinionReportWithOldPhase(c *gc.C) { 788 // It is OK for a report to arrive for even a migration has moved 789 // on. 790 mig, err := s.State2.CreateMigration(s.stdSpec) 791 c.Assert(err, jc.ErrorIsNil) 792 793 // Get another reference to the same migration. 794 migalt, err := s.State2.LatestMigration() 795 c.Assert(err, jc.ErrorIsNil) 796 797 // Confirm that there's no reports when starting. 798 reports, err := mig.MinionReports() 799 c.Assert(err, jc.ErrorIsNil) 800 c.Check(reports.Succeeded, gc.HasLen, 0) 801 802 // Advance the migration 803 c.Assert(mig.SetPhase(migration.IMPORT), jc.ErrorIsNil) 804 805 // Submit minion report for the old phase. 806 tag := names.NewMachineTag("42") 807 c.Assert(mig.SubmitMinionReport(tag, migration.QUIESCE, true), jc.ErrorIsNil) 808 809 // The report should still have been recorded. 810 reports, err = migalt.MinionReports() 811 c.Assert(err, jc.ErrorIsNil) 812 c.Check(reports.Succeeded, jc.SameContents, []names.Tag{tag}) 813 } 814 815 func (s *MigrationSuite) TestMinionReportWithInactiveMigration(c *gc.C) { 816 // Create a migration. 817 mig, err := s.State2.CreateMigration(s.stdSpec) 818 c.Assert(err, jc.ErrorIsNil) 819 820 // Get another reference to the same migration. 821 migalt, err := s.State2.LatestMigration() 822 c.Assert(err, jc.ErrorIsNil) 823 824 // Abort the migration. 825 c.Assert(mig.SetPhase(migration.ABORT), jc.ErrorIsNil) 826 c.Assert(mig.SetPhase(migration.ABORTDONE), jc.ErrorIsNil) 827 828 // Confirm that there's no reports when starting. 829 reports, err := mig.MinionReports() 830 c.Assert(err, jc.ErrorIsNil) 831 c.Check(reports.Succeeded, gc.HasLen, 0) 832 833 // Submit a minion report for it. 834 tag := names.NewMachineTag("42") 835 c.Assert(mig.SubmitMinionReport(tag, migration.QUIESCE, true), jc.ErrorIsNil) 836 837 // The report should still have been recorded. 838 reports, err = migalt.MinionReports() 839 c.Assert(err, jc.ErrorIsNil) 840 c.Check(reports.Succeeded, jc.SameContents, []names.Tag{tag}) 841 } 842 843 func (s *MigrationSuite) TestWatchMinionReports(c *gc.C) { 844 mig, wc := s.createMigAndWatchReports(c, s.State2) 845 wc.AssertOneChange() // initial event 846 847 // A report should trigger the watcher. 848 c.Assert(mig.SubmitMinionReport(names.NewMachineTag("0"), migration.QUIESCE, true), jc.ErrorIsNil) 849 wc.AssertOneChange() 850 851 // A report for a different phase shouldn't trigger the watcher. 852 c.Assert(mig.SubmitMinionReport(names.NewMachineTag("1"), migration.IMPORT, true), jc.ErrorIsNil) 853 wc.AssertNoChange() 854 } 855 856 func (s *MigrationSuite) TestWatchMinionReportsMultiModel(c *gc.C) { 857 mig, wc := s.createMigAndWatchReports(c, s.State2) 858 wc.AssertOneChange() // initial event 859 860 State3 := s.Factory.MakeModel(c, nil) 861 s.AddCleanup(func(*gc.C) { State3.Close() }) 862 mig3, wc3 := s.createMigAndWatchReports(c, State3) 863 wc3.AssertOneChange() // initial event 864 865 // Ensure the correct watchers are triggered. 866 c.Assert(mig.SubmitMinionReport(names.NewMachineTag("0"), migration.QUIESCE, true), jc.ErrorIsNil) 867 wc.AssertOneChange() 868 wc3.AssertNoChange() 869 870 c.Assert(mig3.SubmitMinionReport(names.NewMachineTag("0"), migration.QUIESCE, true), jc.ErrorIsNil) 871 wc.AssertNoChange() 872 wc3.AssertOneChange() 873 } 874 875 func (s *MigrationSuite) TestModelUserAccess(c *gc.C) { 876 model, err := s.State2.Model() 877 c.Assert(err, jc.ErrorIsNil) 878 c.Assert(model.MigrationMode(), gc.Equals, state.MigrationModeNone) 879 880 // Get users that had access to the model before the migration 881 modelUsers, err := model.Users() 882 c.Assert(err, jc.ErrorIsNil) 883 c.Assert(len(modelUsers), gc.Not(gc.Equals), 0) 884 885 mig, err := s.State2.CreateMigration(s.stdSpec) 886 c.Assert(err, jc.ErrorIsNil) 887 888 for _, modelUser := range modelUsers { 889 c.Logf("check that migration doc lists user %q having permission %q", modelUser.UserTag, modelUser.Access) 890 perm := mig.ModelUserAccess(modelUser.UserTag) 891 c.Assert(perm, gc.Equals, modelUser.Access) 892 } 893 894 // Querying for any other user should yield permission.NoAccess 895 perm := mig.ModelUserAccess(names.NewUserTag("bogus")) 896 c.Assert(perm, gc.Equals, permission.NoAccess) 897 } 898 899 func (s *MigrationSuite) createStatusWatcher(c *gc.C, st *state.State) ( 900 state.NotifyWatcher, statetesting.NotifyWatcherC, 901 ) { 902 s.WaitForModelWatchersIdle(c, st.ModelUUID()) 903 w := st.WatchMigrationStatus() 904 s.AddCleanup(func(c *gc.C) { statetesting.AssertStop(c, w) }) 905 return w, statetesting.NewNotifyWatcherC(c, w) 906 } 907 908 func (s *MigrationSuite) createMigAndWatchReports(c *gc.C, st *state.State) ( 909 state.ModelMigration, statetesting.NotifyWatcherC, 910 ) { 911 mig, err := st.CreateMigration(s.stdSpec) 912 c.Assert(err, jc.ErrorIsNil) 913 // Ensure that all the creation events have flowed through the system. 914 s.WaitForModelWatchersIdle(c, st.ModelUUID()) 915 916 w, err := mig.WatchMinionReports() 917 c.Assert(err, jc.ErrorIsNil) 918 s.AddCleanup(func(*gc.C) { statetesting.AssertStop(c, w) }) 919 wc := statetesting.NewNotifyWatcherC(c, w) 920 921 return mig, wc 922 } 923 924 func assertPhase(c *gc.C, mig state.ModelMigration, phase migration.Phase) { 925 actualPhase, err := mig.Phase() 926 c.Assert(err, jc.ErrorIsNil) 927 c.Check(actualPhase, gc.Equals, phase) 928 } 929 930 func assertMigrationActive(c *gc.C, st *state.State) { 931 c.Check(isMigrationActive(c, st), jc.IsTrue) 932 } 933 934 func assertMigrationNotActive(c *gc.C, st *state.State) { 935 c.Check(isMigrationActive(c, st), jc.IsFalse) 936 } 937 938 func isMigrationActive(c *gc.C, st *state.State) bool { 939 isActive, err := st.IsMigrationActive() 940 c.Assert(err, jc.ErrorIsNil) 941 return isActive 942 } 943 944 func checkIdAndAttempt(c *gc.C, mig state.ModelMigration, expected int) { 945 c.Check(mig.Id(), gc.Equals, fmt.Sprintf("%s:%d", mig.ModelUUID(), expected)) 946 c.Check(mig.Attempt(), gc.Equals, expected) 947 }