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  }