github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/state/model_test.go (about)

     1  // Copyright 2013 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"
    12  	jc "github.com/juju/testing/checkers"
    13  	"github.com/juju/utils"
    14  	gc "gopkg.in/check.v1"
    15  
    16  	"github.com/juju/juju/environs/config"
    17  	"github.com/juju/juju/state"
    18  	"github.com/juju/juju/testing"
    19  	"github.com/juju/juju/testing/factory"
    20  )
    21  
    22  type ModelSuite struct {
    23  	ConnSuite
    24  }
    25  
    26  var _ = gc.Suite(&ModelSuite{})
    27  
    28  func (s *ModelSuite) TestModel(c *gc.C) {
    29  	model, err := s.State.Model()
    30  	c.Assert(err, jc.ErrorIsNil)
    31  
    32  	expectedTag := names.NewModelTag(model.UUID())
    33  	c.Assert(model.Tag(), gc.Equals, expectedTag)
    34  	c.Assert(model.ControllerTag(), gc.Equals, expectedTag)
    35  	c.Assert(model.Name(), gc.Equals, "testenv")
    36  	c.Assert(model.Owner(), gc.Equals, s.Owner)
    37  	c.Assert(model.Life(), gc.Equals, state.Alive)
    38  	c.Assert(model.MigrationMode(), gc.Equals, state.MigrationModeActive)
    39  }
    40  
    41  func (s *ModelSuite) TestModelDestroy(c *gc.C) {
    42  	env, err := s.State.Model()
    43  	c.Assert(err, jc.ErrorIsNil)
    44  
    45  	now := state.NowToTheSecond()
    46  	s.PatchValue(&state.NowToTheSecond, func() time.Time {
    47  		return now
    48  	})
    49  
    50  	err = env.Destroy()
    51  	c.Assert(err, jc.ErrorIsNil)
    52  	err = env.Refresh()
    53  	c.Assert(err, jc.ErrorIsNil)
    54  	c.Assert(env.Life(), gc.Equals, state.Dying)
    55  }
    56  
    57  func (s *ModelSuite) TestNewModelNonExistentLocalUser(c *gc.C) {
    58  	cfg, _ := s.createTestEnvConfig(c)
    59  	owner := names.NewUserTag("non-existent@local")
    60  
    61  	_, _, err := s.State.NewModel(state.ModelArgs{Config: cfg, Owner: owner})
    62  	c.Assert(err, gc.ErrorMatches, `cannot create model: user "non-existent" not found`)
    63  }
    64  
    65  func (s *ModelSuite) TestNewModelSameUserSameNameFails(c *gc.C) {
    66  	cfg, _ := s.createTestEnvConfig(c)
    67  	owner := s.Factory.MakeUser(c, nil).UserTag()
    68  
    69  	// Create the first model.
    70  	_, st1, err := s.State.NewModel(state.ModelArgs{Config: cfg, Owner: owner})
    71  	c.Assert(err, jc.ErrorIsNil)
    72  	defer st1.Close()
    73  
    74  	// Attempt to create another model with a different UUID but the
    75  	// same owner and name as the first.
    76  	newUUID, err := utils.NewUUID()
    77  	c.Assert(err, jc.ErrorIsNil)
    78  	cfg2 := testing.CustomModelConfig(c, testing.Attrs{
    79  		"name": cfg.Name(),
    80  		"uuid": newUUID.String(),
    81  	})
    82  	_, _, err = s.State.NewModel(state.ModelArgs{Config: cfg2, Owner: owner})
    83  	errMsg := fmt.Sprintf("model %q for %s already exists", cfg2.Name(), owner.Canonical())
    84  	c.Assert(err, gc.ErrorMatches, errMsg)
    85  	c.Assert(errors.IsAlreadyExists(err), jc.IsTrue)
    86  
    87  	// Remove the first model.
    88  	env1, err := st1.Model()
    89  	c.Assert(err, jc.ErrorIsNil)
    90  	err = env1.Destroy()
    91  	c.Assert(err, jc.ErrorIsNil)
    92  	// Destroy only sets the model to dying and RemoveAllModelDocs can
    93  	// only be called on a dead model. Normally, the environ's lifecycle
    94  	// would be set to dead after machines and services have been cleaned up.
    95  	err = state.SetModelLifeDead(st1, env1.ModelTag().Id())
    96  	c.Assert(err, jc.ErrorIsNil)
    97  	err = st1.RemoveAllModelDocs()
    98  	c.Assert(err, jc.ErrorIsNil)
    99  
   100  	// We should now be able to create the other model.
   101  	env2, st2, err := s.State.NewModel(state.ModelArgs{Config: cfg2, Owner: owner})
   102  	c.Assert(err, jc.ErrorIsNil)
   103  	defer st2.Close()
   104  	c.Assert(env2, gc.NotNil)
   105  	c.Assert(st2, gc.NotNil)
   106  }
   107  
   108  func (s *ModelSuite) TestNewModel(c *gc.C) {
   109  	cfg, uuid := s.createTestEnvConfig(c)
   110  	owner := names.NewUserTag("test@remote")
   111  
   112  	env, st, err := s.State.NewModel(state.ModelArgs{Config: cfg, Owner: owner})
   113  	c.Assert(err, jc.ErrorIsNil)
   114  	defer st.Close()
   115  
   116  	modelTag := names.NewModelTag(uuid)
   117  	assertEnvMatches := func(env *state.Model) {
   118  		c.Assert(env.UUID(), gc.Equals, modelTag.Id())
   119  		c.Assert(env.Tag(), gc.Equals, modelTag)
   120  		c.Assert(env.ControllerTag(), gc.Equals, s.modelTag)
   121  		c.Assert(env.Owner(), gc.Equals, owner)
   122  		c.Assert(env.Name(), gc.Equals, "testing")
   123  		c.Assert(env.Life(), gc.Equals, state.Alive)
   124  	}
   125  	assertEnvMatches(env)
   126  
   127  	// Since the model tag for the State connection is different,
   128  	// asking for this model through FindEntity returns a not found error.
   129  	env, err = s.State.GetModel(modelTag)
   130  	c.Assert(err, jc.ErrorIsNil)
   131  	assertEnvMatches(env)
   132  
   133  	env, err = st.Model()
   134  	c.Assert(err, jc.ErrorIsNil)
   135  	assertEnvMatches(env)
   136  
   137  	_, err = s.State.FindEntity(modelTag)
   138  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   139  
   140  	entity, err := st.FindEntity(modelTag)
   141  	c.Assert(err, jc.ErrorIsNil)
   142  	c.Assert(entity.Tag(), gc.Equals, modelTag)
   143  
   144  	// Ensure the model is functional by adding a machine
   145  	_, err = st.AddMachine("quantal", state.JobHostUnits)
   146  	c.Assert(err, jc.ErrorIsNil)
   147  }
   148  
   149  func (s *ModelSuite) TestNewModelImportingMode(c *gc.C) {
   150  	cfg, _ := s.createTestEnvConfig(c)
   151  	owner := names.NewUserTag("test@remote")
   152  
   153  	env, st, err := s.State.NewModel(state.ModelArgs{
   154  		Config:        cfg,
   155  		Owner:         owner,
   156  		MigrationMode: state.MigrationModeImporting,
   157  	})
   158  	c.Assert(err, jc.ErrorIsNil)
   159  	defer st.Close()
   160  
   161  	c.Assert(env.MigrationMode(), gc.Equals, state.MigrationModeImporting)
   162  }
   163  
   164  func (s *ModelSuite) TestSetMigrationMode(c *gc.C) {
   165  	cfg, _ := s.createTestEnvConfig(c)
   166  	owner := names.NewUserTag("test@remote")
   167  
   168  	env, st, err := s.State.NewModel(state.ModelArgs{Config: cfg, Owner: owner})
   169  	c.Assert(err, jc.ErrorIsNil)
   170  	defer st.Close()
   171  
   172  	err = env.SetMigrationMode(state.MigrationModeExporting)
   173  	c.Assert(err, jc.ErrorIsNil)
   174  	c.Assert(env.MigrationMode(), gc.Equals, state.MigrationModeExporting)
   175  }
   176  
   177  func (s *ModelSuite) TestControllerModel(c *gc.C) {
   178  	env, err := s.State.ControllerModel()
   179  	c.Assert(err, jc.ErrorIsNil)
   180  
   181  	expectedTag := names.NewModelTag(env.UUID())
   182  	c.Assert(env.Tag(), gc.Equals, expectedTag)
   183  	c.Assert(env.ControllerTag(), gc.Equals, expectedTag)
   184  	c.Assert(env.Name(), gc.Equals, "testenv")
   185  	c.Assert(env.Owner(), gc.Equals, s.Owner)
   186  	c.Assert(env.Life(), gc.Equals, state.Alive)
   187  }
   188  
   189  func (s *ModelSuite) TestControllerModelAccessibleFromOtherModels(c *gc.C) {
   190  	cfg, _ := s.createTestEnvConfig(c)
   191  	_, st, err := s.State.NewModel(state.ModelArgs{
   192  		Config: cfg,
   193  		Owner:  names.NewUserTag("test@remote"),
   194  	})
   195  	defer st.Close()
   196  
   197  	env, err := st.ControllerModel()
   198  	c.Assert(err, jc.ErrorIsNil)
   199  	c.Assert(env.Tag(), gc.Equals, s.modelTag)
   200  	c.Assert(env.Name(), gc.Equals, "testenv")
   201  	c.Assert(env.Owner(), gc.Equals, s.Owner)
   202  	c.Assert(env.Life(), gc.Equals, state.Alive)
   203  }
   204  
   205  func (s *ModelSuite) TestConfigForControllerEnv(c *gc.C) {
   206  	otherState := s.Factory.MakeModel(c, &factory.ModelParams{Name: "other"})
   207  	defer otherState.Close()
   208  
   209  	env, err := otherState.GetModel(s.modelTag)
   210  	c.Assert(err, jc.ErrorIsNil)
   211  
   212  	conf, err := env.Config()
   213  	c.Assert(err, jc.ErrorIsNil)
   214  	c.Assert(conf.Name(), gc.Equals, "testenv")
   215  	c.Assert(conf.UUID(), gc.Equals, s.modelTag.Id())
   216  }
   217  
   218  func (s *ModelSuite) TestConfigForOtherEnv(c *gc.C) {
   219  	otherState := s.Factory.MakeModel(c, &factory.ModelParams{Name: "other"})
   220  	defer otherState.Close()
   221  	otherEnv, err := otherState.Model()
   222  	c.Assert(err, jc.ErrorIsNil)
   223  
   224  	// By getting the model through a different state connection,
   225  	// the underlying state pointer in the *state.Model struct has
   226  	// a different model tag.
   227  	env, err := s.State.GetModel(otherEnv.ModelTag())
   228  	c.Assert(err, jc.ErrorIsNil)
   229  
   230  	conf, err := env.Config()
   231  	c.Assert(err, jc.ErrorIsNil)
   232  	c.Assert(conf.Name(), gc.Equals, "other")
   233  	c.Assert(conf.UUID(), gc.Equals, otherEnv.UUID())
   234  }
   235  
   236  // createTestEnvConfig returns a new model config and its UUID for testing.
   237  func (s *ModelSuite) createTestEnvConfig(c *gc.C) (*config.Config, string) {
   238  	uuid, err := utils.NewUUID()
   239  	c.Assert(err, jc.ErrorIsNil)
   240  	return testing.CustomModelConfig(c, testing.Attrs{
   241  		"name": "testing",
   242  		"uuid": uuid.String(),
   243  	}), uuid.String()
   244  }
   245  
   246  func (s *ModelSuite) TestModelConfigSameEnvAsState(c *gc.C) {
   247  	env, err := s.State.Model()
   248  	c.Assert(err, jc.ErrorIsNil)
   249  	cfg, err := env.Config()
   250  	c.Assert(err, jc.ErrorIsNil)
   251  	c.Assert(cfg.UUID(), gc.Equals, s.State.ModelUUID())
   252  }
   253  
   254  func (s *ModelSuite) TestModelConfigDifferentEnvThanState(c *gc.C) {
   255  	otherState := s.Factory.MakeModel(c, nil)
   256  	defer otherState.Close()
   257  	env, err := otherState.Model()
   258  	c.Assert(err, jc.ErrorIsNil)
   259  	cfg, err := env.Config()
   260  	c.Assert(err, jc.ErrorIsNil)
   261  	uuid := cfg.UUID()
   262  	c.Assert(uuid, gc.Equals, env.UUID())
   263  	c.Assert(uuid, gc.Not(gc.Equals), s.State.ModelUUID())
   264  }
   265  
   266  func (s *ModelSuite) TestDestroyControllerModel(c *gc.C) {
   267  	env, err := s.State.Model()
   268  	c.Assert(err, jc.ErrorIsNil)
   269  	err = env.Destroy()
   270  	c.Assert(err, jc.ErrorIsNil)
   271  }
   272  
   273  func (s *ModelSuite) TestDestroyOtherModel(c *gc.C) {
   274  	st2 := s.Factory.MakeModel(c, nil)
   275  	defer st2.Close()
   276  	env, err := st2.Model()
   277  	c.Assert(err, jc.ErrorIsNil)
   278  	err = env.Destroy()
   279  	c.Assert(err, jc.ErrorIsNil)
   280  }
   281  
   282  func (s *ModelSuite) TestDestroyControllerNonEmptyModelFails(c *gc.C) {
   283  	st2 := s.Factory.MakeModel(c, nil)
   284  	defer st2.Close()
   285  	factory.NewFactory(st2).MakeService(c, nil)
   286  
   287  	env, err := s.State.Model()
   288  	c.Assert(err, jc.ErrorIsNil)
   289  	c.Assert(env.Destroy(), gc.ErrorMatches, "failed to destroy model: hosting 1 other models")
   290  }
   291  
   292  func (s *ModelSuite) TestDestroyControllerEmptyModel(c *gc.C) {
   293  	st2 := s.Factory.MakeModel(c, nil)
   294  	defer st2.Close()
   295  
   296  	controllerModel, err := s.State.Model()
   297  	c.Assert(err, jc.ErrorIsNil)
   298  	c.Assert(controllerModel.Destroy(), jc.ErrorIsNil)
   299  	c.Assert(controllerModel.Refresh(), jc.ErrorIsNil)
   300  	c.Assert(controllerModel.Life(), gc.Equals, state.Dying)
   301  
   302  	hostedModel, err := st2.Model()
   303  	c.Assert(err, jc.ErrorIsNil)
   304  	c.Assert(hostedModel.Life(), gc.Equals, state.Dead)
   305  }
   306  
   307  func (s *ModelSuite) TestDestroyControllerAndHostedModels(c *gc.C) {
   308  	st2 := s.Factory.MakeModel(c, nil)
   309  	defer st2.Close()
   310  	factory.NewFactory(st2).MakeService(c, nil)
   311  
   312  	controllerEnv, err := s.State.Model()
   313  	c.Assert(err, jc.ErrorIsNil)
   314  	c.Assert(controllerEnv.DestroyIncludingHosted(), jc.ErrorIsNil)
   315  
   316  	env, err := s.State.Model()
   317  	c.Assert(err, jc.ErrorIsNil)
   318  	c.Assert(env.Life(), gc.Equals, state.Dying)
   319  
   320  	assertNeedsCleanup(c, s.State)
   321  	assertCleanupRuns(c, s.State)
   322  
   323  	// Cleanups for hosted model enqueued by controller model cleanups.
   324  	assertNeedsCleanup(c, st2)
   325  	assertCleanupRuns(c, st2)
   326  
   327  	env2, err := st2.Model()
   328  	c.Assert(err, jc.ErrorIsNil)
   329  	c.Assert(env2.Life(), gc.Equals, state.Dying)
   330  
   331  	c.Assert(st2.ProcessDyingModel(), jc.ErrorIsNil)
   332  
   333  	c.Assert(env2.Refresh(), jc.ErrorIsNil)
   334  	c.Assert(env2.Life(), gc.Equals, state.Dead)
   335  
   336  	c.Assert(s.State.ProcessDyingModel(), jc.ErrorIsNil)
   337  	c.Assert(env.Refresh(), jc.ErrorIsNil)
   338  	c.Assert(env2.Life(), gc.Equals, state.Dead)
   339  }
   340  
   341  func (s *ModelSuite) TestDestroyControllerAndHostedModelsWithResources(c *gc.C) {
   342  	otherSt := s.Factory.MakeModel(c, nil)
   343  	defer otherSt.Close()
   344  
   345  	assertEnv := func(env *state.Model, st *state.State, life state.Life, expectedMachines, expectedServices int) {
   346  		c.Assert(env.Refresh(), jc.ErrorIsNil)
   347  		c.Assert(env.Life(), gc.Equals, life)
   348  
   349  		machines, err := st.AllMachines()
   350  		c.Assert(err, jc.ErrorIsNil)
   351  		c.Assert(machines, gc.HasLen, expectedMachines)
   352  
   353  		services, err := st.AllServices()
   354  		c.Assert(err, jc.ErrorIsNil)
   355  		c.Assert(services, gc.HasLen, expectedServices)
   356  	}
   357  
   358  	// add some machines and services
   359  	otherEnv, err := otherSt.Model()
   360  	c.Assert(err, jc.ErrorIsNil)
   361  	_, err = otherSt.AddMachine("quantal", state.JobHostUnits)
   362  	c.Assert(err, jc.ErrorIsNil)
   363  	service := s.Factory.MakeService(c, &factory.ServiceParams{Creator: otherEnv.Owner()})
   364  	ch, _, err := service.Charm()
   365  	c.Assert(err, jc.ErrorIsNil)
   366  
   367  	args := state.AddServiceArgs{
   368  		Name:  service.Name(),
   369  		Owner: service.GetOwnerTag(),
   370  		Charm: ch,
   371  	}
   372  	service, err = otherSt.AddService(args)
   373  	c.Assert(err, jc.ErrorIsNil)
   374  
   375  	controllerEnv, err := s.State.Model()
   376  	c.Assert(err, jc.ErrorIsNil)
   377  	c.Assert(controllerEnv.DestroyIncludingHosted(), jc.ErrorIsNil)
   378  
   379  	assertCleanupRuns(c, s.State)
   380  	assertDoesNotNeedCleanup(c, s.State)
   381  	assertAllMachinesDeadAndRemove(c, s.State)
   382  	assertEnv(controllerEnv, s.State, state.Dying, 0, 0)
   383  
   384  	err = s.State.ProcessDyingModel()
   385  	c.Assert(err, gc.ErrorMatches, `one or more hosted models are not yet dead`)
   386  
   387  	assertCleanupCount(c, otherSt, 3)
   388  	assertAllMachinesDeadAndRemove(c, otherSt)
   389  	assertEnv(otherEnv, otherSt, state.Dying, 0, 0)
   390  	c.Assert(otherSt.ProcessDyingModel(), jc.ErrorIsNil)
   391  
   392  	c.Assert(otherEnv.Refresh(), jc.ErrorIsNil)
   393  	c.Assert(otherEnv.Life(), gc.Equals, state.Dead)
   394  
   395  	c.Assert(s.State.ProcessDyingModel(), jc.ErrorIsNil)
   396  	c.Assert(controllerEnv.Refresh(), jc.ErrorIsNil)
   397  	c.Assert(controllerEnv.Life(), gc.Equals, state.Dead)
   398  }
   399  
   400  func (s *ModelSuite) TestDestroyControllerEmptyModelRace(c *gc.C) {
   401  	defer s.Factory.MakeModel(c, nil).Close()
   402  
   403  	// Simulate an empty model being added just before the
   404  	// remove txn is called.
   405  	defer state.SetBeforeHooks(c, s.State, func() {
   406  		s.Factory.MakeModel(c, nil).Close()
   407  	}).Check()
   408  
   409  	env, err := s.State.Model()
   410  	c.Assert(err, jc.ErrorIsNil)
   411  	c.Assert(env.Destroy(), jc.ErrorIsNil)
   412  }
   413  
   414  func (s *ModelSuite) TestDestroyControllerRemoveEmptyAddNonEmptyModel(c *gc.C) {
   415  	st2 := s.Factory.MakeModel(c, nil)
   416  	defer st2.Close()
   417  
   418  	// Simulate an empty model being removed, and a new non-empty
   419  	// model being added, just before the remove txn is called.
   420  	defer state.SetBeforeHooks(c, s.State, func() {
   421  		// Destroy the empty model, which should move it right
   422  		// along to Dead, and then remove it.
   423  		model, err := st2.Model()
   424  		c.Assert(err, jc.ErrorIsNil)
   425  		c.Assert(model.Destroy(), jc.ErrorIsNil)
   426  		err = st2.RemoveAllModelDocs()
   427  		c.Assert(err, jc.ErrorIsNil)
   428  
   429  		// Add a new, non-empty model. This should still prevent
   430  		// the controller from being destroyed.
   431  		st3 := s.Factory.MakeModel(c, nil)
   432  		defer st3.Close()
   433  		factory.NewFactory(st3).MakeService(c, nil)
   434  	}).Check()
   435  
   436  	env, err := s.State.Model()
   437  	c.Assert(err, jc.ErrorIsNil)
   438  	c.Assert(env.Destroy(), gc.ErrorMatches, "failed to destroy model: hosting 1 other models")
   439  }
   440  
   441  func (s *ModelSuite) TestDestroyControllerNonEmptyModelRace(c *gc.C) {
   442  	// Simulate an empty model being added just before the
   443  	// remove txn is called.
   444  	defer state.SetBeforeHooks(c, s.State, func() {
   445  		st := s.Factory.MakeModel(c, nil)
   446  		defer st.Close()
   447  		factory.NewFactory(st).MakeService(c, nil)
   448  	}).Check()
   449  
   450  	env, err := s.State.Model()
   451  	c.Assert(err, jc.ErrorIsNil)
   452  	c.Assert(env.Destroy(), gc.ErrorMatches, "failed to destroy model: hosting 1 other models")
   453  }
   454  
   455  func (s *ModelSuite) TestDestroyControllerAlreadyDyingRaceNoOp(c *gc.C) {
   456  	env, err := s.State.Model()
   457  	c.Assert(err, jc.ErrorIsNil)
   458  
   459  	// Simulate an model being destroyed by another client just before
   460  	// the remove txn is called.
   461  	defer state.SetBeforeHooks(c, s.State, func() {
   462  		c.Assert(env.Destroy(), jc.ErrorIsNil)
   463  	}).Check()
   464  
   465  	c.Assert(env.Destroy(), jc.ErrorIsNil)
   466  }
   467  
   468  func (s *ModelSuite) TestDestroyControllerAlreadyDyingNoOp(c *gc.C) {
   469  	env, err := s.State.Model()
   470  	c.Assert(err, jc.ErrorIsNil)
   471  
   472  	c.Assert(env.Destroy(), jc.ErrorIsNil)
   473  	c.Assert(env.Destroy(), jc.ErrorIsNil)
   474  }
   475  
   476  func (s *ModelSuite) TestDestroyModelNonEmpty(c *gc.C) {
   477  	m, err := s.State.Model()
   478  	c.Assert(err, jc.ErrorIsNil)
   479  
   480  	// Add a service to prevent the model from transitioning directly to Dead.
   481  	s.Factory.MakeService(c, nil)
   482  
   483  	c.Assert(m.Destroy(), jc.ErrorIsNil)
   484  	c.Assert(m.Refresh(), jc.ErrorIsNil)
   485  	c.Assert(m.Life(), gc.Equals, state.Dying)
   486  }
   487  
   488  func (s *ModelSuite) TestDestroyModelAddServiceConcurrently(c *gc.C) {
   489  	st := s.Factory.MakeModel(c, nil)
   490  	defer st.Close()
   491  	m, err := st.Model()
   492  	c.Assert(err, jc.ErrorIsNil)
   493  
   494  	defer state.SetBeforeHooks(c, st, func() {
   495  		factory.NewFactory(st).MakeService(c, nil)
   496  	}).Check()
   497  
   498  	c.Assert(m.Destroy(), jc.ErrorIsNil)
   499  	c.Assert(m.Refresh(), jc.ErrorIsNil)
   500  	c.Assert(m.Life(), gc.Equals, state.Dying)
   501  }
   502  
   503  func (s *ModelSuite) TestDestroyModelAddMachineConcurrently(c *gc.C) {
   504  	st := s.Factory.MakeModel(c, nil)
   505  	defer st.Close()
   506  	m, err := st.Model()
   507  	c.Assert(err, jc.ErrorIsNil)
   508  
   509  	defer state.SetBeforeHooks(c, st, func() {
   510  		factory.NewFactory(st).MakeMachine(c, nil)
   511  	}).Check()
   512  
   513  	c.Assert(m.Destroy(), jc.ErrorIsNil)
   514  	c.Assert(m.Refresh(), jc.ErrorIsNil)
   515  	c.Assert(m.Life(), gc.Equals, state.Dying)
   516  }
   517  
   518  func (s *ModelSuite) TestDestroyModelEmpty(c *gc.C) {
   519  	st := s.Factory.MakeModel(c, nil)
   520  	defer st.Close()
   521  	m, err := st.Model()
   522  	c.Assert(err, jc.ErrorIsNil)
   523  
   524  	c.Assert(m.Destroy(), jc.ErrorIsNil)
   525  	c.Assert(m.Refresh(), jc.ErrorIsNil)
   526  	c.Assert(m.Life(), gc.Equals, state.Dead)
   527  }
   528  
   529  func (s *ModelSuite) TestProcessDyingServerEnvironTransitionDyingToDead(c *gc.C) {
   530  	s.assertDyingEnvironTransitionDyingToDead(c, s.State)
   531  }
   532  
   533  func (s *ModelSuite) TestProcessDyingHostedEnvironTransitionDyingToDead(c *gc.C) {
   534  	st := s.Factory.MakeModel(c, nil)
   535  	defer st.Close()
   536  	s.assertDyingEnvironTransitionDyingToDead(c, st)
   537  }
   538  
   539  func (s *ModelSuite) assertDyingEnvironTransitionDyingToDead(c *gc.C, st *state.State) {
   540  	// Add a service to prevent the model from transitioning directly to Dead.
   541  	// Add the service before getting the Model, otherwise we'll have to run
   542  	// the transaction twice, and hit the hook point too early.
   543  	svc := factory.NewFactory(st).MakeService(c, nil)
   544  	env, err := st.Model()
   545  	c.Assert(err, jc.ErrorIsNil)
   546  
   547  	// ProcessDyingModel is called by a worker after Destroy is called. To
   548  	// avoid a race, we jump the gun here and test immediately after the
   549  	// environement was set to dead.
   550  	defer state.SetAfterHooks(c, st, func() {
   551  		c.Assert(env.Refresh(), jc.ErrorIsNil)
   552  		c.Assert(env.Life(), gc.Equals, state.Dying)
   553  
   554  		err := svc.Destroy()
   555  		c.Assert(err, jc.ErrorIsNil)
   556  
   557  		c.Assert(st.ProcessDyingModel(), jc.ErrorIsNil)
   558  
   559  		c.Assert(env.Refresh(), jc.ErrorIsNil)
   560  		c.Assert(env.Life(), gc.Equals, state.Dead)
   561  	}).Check()
   562  
   563  	c.Assert(env.Destroy(), jc.ErrorIsNil)
   564  }
   565  
   566  func (s *ModelSuite) TestProcessDyingEnvironWithMachinesAndServicesNoOp(c *gc.C) {
   567  	st := s.Factory.MakeModel(c, nil)
   568  	defer st.Close()
   569  
   570  	// calling ProcessDyingModel on a live environ should fail.
   571  	err := st.ProcessDyingModel()
   572  	c.Assert(err, gc.ErrorMatches, "model is not dying")
   573  
   574  	// add some machines and services
   575  	env, err := st.Model()
   576  	c.Assert(err, jc.ErrorIsNil)
   577  	_, err = st.AddMachine("quantal", state.JobHostUnits)
   578  	c.Assert(err, jc.ErrorIsNil)
   579  	service := s.Factory.MakeService(c, &factory.ServiceParams{Creator: env.Owner()})
   580  	ch, _, err := service.Charm()
   581  	c.Assert(err, jc.ErrorIsNil)
   582  	args := state.AddServiceArgs{
   583  		Name:  service.Name(),
   584  		Owner: service.GetOwnerTag(),
   585  		Charm: ch,
   586  	}
   587  	service, err = st.AddService(args)
   588  	c.Assert(err, jc.ErrorIsNil)
   589  
   590  	assertEnv := func(life state.Life, expectedMachines, expectedServices int) {
   591  		c.Assert(env.Refresh(), jc.ErrorIsNil)
   592  		c.Assert(env.Life(), gc.Equals, life)
   593  
   594  		machines, err := st.AllMachines()
   595  		c.Assert(err, jc.ErrorIsNil)
   596  		c.Assert(machines, gc.HasLen, expectedMachines)
   597  
   598  		services, err := st.AllServices()
   599  		c.Assert(err, jc.ErrorIsNil)
   600  		c.Assert(services, gc.HasLen, expectedServices)
   601  	}
   602  
   603  	// Simulate processing a dying envrionment after an envrionment is set to
   604  	// dying, but before the cleanup has removed machines and services.
   605  	defer state.SetAfterHooks(c, st, func() {
   606  		assertEnv(state.Dying, 1, 1)
   607  		err := st.ProcessDyingModel()
   608  		c.Assert(err, gc.ErrorMatches, `model not empty, found 1 machine\(s\)`)
   609  		assertEnv(state.Dying, 1, 1)
   610  	}).Check()
   611  
   612  	c.Assert(env.Refresh(), jc.ErrorIsNil)
   613  	c.Assert(env.Destroy(), jc.ErrorIsNil)
   614  }
   615  
   616  func (s *ModelSuite) TestProcessDyingControllerEnvironWithHostedEnvsNoOp(c *gc.C) {
   617  	// Add a non-empty model to the controller.
   618  	st := s.Factory.MakeModel(c, nil)
   619  	defer st.Close()
   620  	factory.NewFactory(st).MakeService(c, nil)
   621  
   622  	controllerEnv, err := s.State.Model()
   623  	c.Assert(err, jc.ErrorIsNil)
   624  	c.Assert(controllerEnv.DestroyIncludingHosted(), jc.ErrorIsNil)
   625  
   626  	err = s.State.ProcessDyingModel()
   627  	c.Assert(err, gc.ErrorMatches, `one or more hosted models are not yet dead`)
   628  
   629  	c.Assert(controllerEnv.Refresh(), jc.ErrorIsNil)
   630  	c.Assert(controllerEnv.Life(), gc.Equals, state.Dying)
   631  }
   632  
   633  func (s *ModelSuite) TestListModelUsers(c *gc.C) {
   634  	env, err := s.State.Model()
   635  	c.Assert(err, jc.ErrorIsNil)
   636  
   637  	expected := addModelUsers(c, s.State)
   638  	obtained, err := env.Users()
   639  	c.Assert(err, gc.IsNil)
   640  
   641  	assertObtainedUsersMatchExpectedUsers(c, obtained, expected)
   642  }
   643  
   644  func (s *ModelSuite) TestMisMatchedEnvs(c *gc.C) {
   645  	// create another model
   646  	otherEnvState := s.Factory.MakeModel(c, nil)
   647  	defer otherEnvState.Close()
   648  	otherEnv, err := otherEnvState.Model()
   649  	c.Assert(err, jc.ErrorIsNil)
   650  
   651  	// get that model from State
   652  	env, err := s.State.GetModel(otherEnv.ModelTag())
   653  	c.Assert(err, jc.ErrorIsNil)
   654  
   655  	// check that the Users method errors
   656  	users, err := env.Users()
   657  	c.Assert(users, gc.IsNil)
   658  	c.Assert(err, gc.ErrorMatches, "cannot lookup model users outside the current model")
   659  }
   660  
   661  func (s *ModelSuite) TestListUsersTwoModels(c *gc.C) {
   662  	env, err := s.State.Model()
   663  	c.Assert(err, jc.ErrorIsNil)
   664  
   665  	otherEnvState := s.Factory.MakeModel(c, nil)
   666  	defer otherEnvState.Close()
   667  	otherEnv, err := otherEnvState.Model()
   668  	c.Assert(err, jc.ErrorIsNil)
   669  
   670  	// Add users to both models
   671  	expectedUsers := addModelUsers(c, s.State)
   672  	expectedUsersOtherEnv := addModelUsers(c, otherEnvState)
   673  
   674  	// test that only the expected users are listed for each model
   675  	obtainedUsers, err := env.Users()
   676  	c.Assert(err, jc.ErrorIsNil)
   677  	assertObtainedUsersMatchExpectedUsers(c, obtainedUsers, expectedUsers)
   678  
   679  	obtainedUsersOtherEnv, err := otherEnv.Users()
   680  	c.Assert(err, jc.ErrorIsNil)
   681  	assertObtainedUsersMatchExpectedUsers(c, obtainedUsersOtherEnv, expectedUsersOtherEnv)
   682  }
   683  
   684  func addModelUsers(c *gc.C, st *state.State) (expected []*state.ModelUser) {
   685  	// get the model owner
   686  	testAdmin := names.NewUserTag("test-admin")
   687  	owner, err := st.ModelUser(testAdmin)
   688  	c.Assert(err, jc.ErrorIsNil)
   689  
   690  	f := factory.NewFactory(st)
   691  	return []*state.ModelUser{
   692  		// we expect the owner to be an existing model user
   693  		owner,
   694  		// add new users to the model
   695  		f.MakeModelUser(c, nil),
   696  		f.MakeModelUser(c, nil),
   697  		f.MakeModelUser(c, nil),
   698  	}
   699  }
   700  
   701  func assertObtainedUsersMatchExpectedUsers(c *gc.C, obtainedUsers, expectedUsers []*state.ModelUser) {
   702  	c.Assert(len(obtainedUsers), gc.Equals, len(expectedUsers))
   703  	for i, obtained := range obtainedUsers {
   704  		c.Assert(obtained.ModelTag().Id(), gc.Equals, expectedUsers[i].ModelTag().Id())
   705  		c.Assert(obtained.UserName(), gc.Equals, expectedUsers[i].UserName())
   706  		c.Assert(obtained.DisplayName(), gc.Equals, expectedUsers[i].DisplayName())
   707  		c.Assert(obtained.CreatedBy(), gc.Equals, expectedUsers[i].CreatedBy())
   708  	}
   709  }
   710  
   711  func (s *ModelSuite) TestAllModels(c *gc.C) {
   712  	s.Factory.MakeModel(c, &factory.ModelParams{
   713  		Name: "test", Owner: names.NewUserTag("bob@remote")}).Close()
   714  	s.Factory.MakeModel(c, &factory.ModelParams{
   715  		Name: "test", Owner: names.NewUserTag("mary@remote")}).Close()
   716  	envs, err := s.State.AllModels()
   717  	c.Assert(err, jc.ErrorIsNil)
   718  	c.Assert(envs, gc.HasLen, 3)
   719  	var obtained []string
   720  	for _, env := range envs {
   721  		obtained = append(obtained, fmt.Sprintf("%s/%s", env.Owner().Canonical(), env.Name()))
   722  	}
   723  	expected := []string{
   724  		"test-admin@local/testenv",
   725  		"bob@remote/test",
   726  		"mary@remote/test",
   727  	}
   728  	c.Assert(obtained, jc.SameContents, expected)
   729  }
   730  
   731  func (s *ModelSuite) TestHostedModelCount(c *gc.C) {
   732  	c.Assert(state.HostedModelCount(c, s.State), gc.Equals, 0)
   733  
   734  	st1 := s.Factory.MakeModel(c, nil)
   735  	defer st1.Close()
   736  	c.Assert(state.HostedModelCount(c, s.State), gc.Equals, 1)
   737  
   738  	st2 := s.Factory.MakeModel(c, nil)
   739  	defer st2.Close()
   740  	c.Assert(state.HostedModelCount(c, s.State), gc.Equals, 2)
   741  
   742  	env1, err := st1.Model()
   743  	c.Assert(err, jc.ErrorIsNil)
   744  	c.Assert(env1.Destroy(), jc.ErrorIsNil)
   745  	c.Assert(st1.RemoveAllModelDocs(), jc.ErrorIsNil)
   746  	c.Assert(state.HostedModelCount(c, s.State), gc.Equals, 1)
   747  
   748  	env2, err := st2.Model()
   749  	c.Assert(err, jc.ErrorIsNil)
   750  	c.Assert(env2.Destroy(), jc.ErrorIsNil)
   751  	c.Assert(st2.RemoveAllModelDocs(), jc.ErrorIsNil)
   752  	c.Assert(state.HostedModelCount(c, s.State), gc.Equals, 0)
   753  }
   754  
   755  func assertCleanupRuns(c *gc.C, st *state.State) {
   756  	err := st.Cleanup()
   757  	c.Assert(err, jc.ErrorIsNil)
   758  }
   759  
   760  func assertNeedsCleanup(c *gc.C, st *state.State) {
   761  	actual, err := st.NeedsCleanup()
   762  	c.Assert(err, jc.ErrorIsNil)
   763  	c.Assert(actual, jc.IsTrue)
   764  }
   765  
   766  func assertDoesNotNeedCleanup(c *gc.C, st *state.State) {
   767  	actual, err := st.NeedsCleanup()
   768  	c.Assert(err, jc.ErrorIsNil)
   769  	c.Assert(actual, jc.IsFalse)
   770  }
   771  
   772  // assertCleanupCount is useful because certain cleanups cause other cleanups
   773  // to be queued; it makes more sense to just run cleanup again than to unpick
   774  // object destruction so that we run the cleanups inline while running cleanups.
   775  func assertCleanupCount(c *gc.C, st *state.State, count int) {
   776  	for i := 0; i < count; i++ {
   777  		c.Logf("checking cleanups %d", i)
   778  		assertNeedsCleanup(c, st)
   779  		assertCleanupRuns(c, st)
   780  	}
   781  	assertDoesNotNeedCleanup(c, st)
   782  }
   783  
   784  // The provisioner will remove dead machines once their backing instances are
   785  // stopped. For the tests, we remove them directly.
   786  func assertAllMachinesDeadAndRemove(c *gc.C, st *state.State) {
   787  	machines, err := st.AllMachines()
   788  	c.Assert(err, jc.ErrorIsNil)
   789  	for _, m := range machines {
   790  		if m.IsManager() {
   791  			continue
   792  		}
   793  		if _, isContainer := m.ParentId(); isContainer {
   794  			continue
   795  		}
   796  		manual, err := m.IsManual()
   797  		c.Assert(err, jc.ErrorIsNil)
   798  		if manual {
   799  			continue
   800  		}
   801  
   802  		c.Assert(m.Life(), gc.Equals, state.Dead)
   803  		c.Assert(m.Remove(), jc.ErrorIsNil)
   804  	}
   805  }