github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/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  	"sort"
     9  	"time"
    10  
    11  	"github.com/juju/charm/v12"
    12  	"github.com/juju/clock"
    13  	"github.com/juju/errors"
    14  	"github.com/juju/mgo/v3/bson"
    15  	mgotesting "github.com/juju/mgo/v3/testing"
    16  	"github.com/juju/names/v5"
    17  	jc "github.com/juju/testing/checkers"
    18  	"github.com/juju/utils/v3"
    19  	gc "gopkg.in/check.v1"
    20  
    21  	"github.com/juju/juju/cloud"
    22  	"github.com/juju/juju/core/crossmodel"
    23  	"github.com/juju/juju/core/network"
    24  	"github.com/juju/juju/core/permission"
    25  	"github.com/juju/juju/environs/config"
    26  	"github.com/juju/juju/state"
    27  	stateerrors "github.com/juju/juju/state/errors"
    28  	"github.com/juju/juju/storage"
    29  	"github.com/juju/juju/testing"
    30  	"github.com/juju/juju/testing/factory"
    31  )
    32  
    33  type ModelSuite struct {
    34  	ConnSuite
    35  }
    36  
    37  var _ = gc.Suite(&ModelSuite{})
    38  
    39  func (s *ModelSuite) TestModel(c *gc.C) {
    40  	model, err := s.State.Model()
    41  	c.Assert(err, jc.ErrorIsNil)
    42  	c.Check(model.IsControllerModel(), jc.IsTrue)
    43  
    44  	expectedTag := names.NewModelTag(model.UUID())
    45  	c.Assert(model.Tag(), gc.Equals, expectedTag)
    46  	c.Assert(model.ControllerTag(), gc.Equals, s.State.ControllerTag())
    47  	c.Assert(model.Name(), gc.Equals, "testmodel")
    48  	c.Assert(model.Owner(), gc.Equals, s.Owner)
    49  	c.Assert(model.Life(), gc.Equals, state.Alive)
    50  	c.Assert(model.MigrationMode(), gc.Equals, state.MigrationModeNone)
    51  }
    52  
    53  func (s *ModelSuite) TestModelDestroy(c *gc.C) {
    54  	model, err := s.State.Model()
    55  	c.Assert(err, jc.ErrorIsNil)
    56  
    57  	err = model.Destroy(state.DestroyModelParams{})
    58  	c.Assert(err, jc.ErrorIsNil)
    59  	err = model.Refresh()
    60  	c.Assert(err, jc.ErrorIsNil)
    61  	c.Assert(model.Life(), gc.Equals, state.Dying)
    62  }
    63  
    64  func (s *ModelSuite) TestModelDestroyWithoutVolumes(c *gc.C) {
    65  	//https://bugs.launchpad.net/juju/+bug/1800872
    66  	// Models introduced in 2.1 and then upgraded to 2.2 don't have Volumes or Filesystem attributes
    67  	// on their modelEntitiesRefs documents
    68  	model, err := s.State.Model()
    69  	c.Assert(err, jc.ErrorIsNil)
    70  	modelEntities, closer := state.GetCollection(s.State, state.ModelEntityRefsC)
    71  	defer closer()
    72  	rawModelEntities := modelEntities.Writeable().Underlying()
    73  	err = rawModelEntities.Update(bson.M{"_id": model.UUID()}, bson.M{"$unset": bson.M{"volumes": 1, "filesystems": 1}})
    74  	c.Assert(err, jc.ErrorIsNil)
    75  	c.Assert(model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
    76  	c.Assert(model.Refresh(), jc.ErrorIsNil)
    77  	c.Assert(model.Life(), gc.Equals, state.Dying)
    78  }
    79  
    80  func (s *ModelSuite) TestSetPassword(c *gc.C) {
    81  	testSetPassword(c, func() (state.Authenticator, error) {
    82  		return s.State.Model()
    83  	})
    84  }
    85  
    86  func (s *ModelSuite) TestNewModelSameUserSameNameFails(c *gc.C) {
    87  	cfg, _ := s.createTestModelConfig(c)
    88  	owner := s.Factory.MakeUser(c, nil).UserTag()
    89  
    90  	// Create the first model.
    91  	model, st1, err := s.Controller.NewModel(state.ModelArgs{
    92  		Type:                    state.ModelTypeIAAS,
    93  		CloudName:               "dummy",
    94  		CloudRegion:             "dummy-region",
    95  		Config:                  cfg,
    96  		Owner:                   owner,
    97  		StorageProviderRegistry: storage.StaticProviderRegistry{},
    98  	})
    99  	c.Assert(err, jc.ErrorIsNil)
   100  	defer st1.Close()
   101  	c.Assert(model.UniqueIndexExists(), jc.IsTrue)
   102  
   103  	// Attempt to create another model with a different UUID but the
   104  	// same owner and name as the first.
   105  	newUUID, err := utils.NewUUID()
   106  	c.Assert(err, jc.ErrorIsNil)
   107  	cfg2 := testing.CustomModelConfig(c, testing.Attrs{
   108  		"name": cfg.Name(),
   109  		"uuid": newUUID.String(),
   110  	})
   111  	_, _, err = s.Controller.NewModel(state.ModelArgs{
   112  		Type:                    state.ModelTypeIAAS,
   113  		CloudName:               "dummy",
   114  		CloudRegion:             "dummy-region",
   115  		Config:                  cfg2,
   116  		Owner:                   owner,
   117  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   118  	})
   119  	errMsg := fmt.Sprintf("model %q for %s already exists", cfg2.Name(), owner.Id())
   120  	c.Assert(err, gc.ErrorMatches, errMsg)
   121  	c.Assert(errors.IsAlreadyExists(err), jc.IsTrue)
   122  
   123  	// Remove the first model.
   124  	model1, err := st1.Model()
   125  	c.Assert(err, jc.ErrorIsNil)
   126  	err = model1.Destroy(state.DestroyModelParams{})
   127  	c.Assert(err, jc.ErrorIsNil)
   128  	// Destroy only sets the model to dying and RemoveDyingModel can
   129  	// only be called on a dead model. Normally, the environ's lifecycle
   130  	// would be set to dead after machines and applications have been cleaned up.
   131  	err = model1.SetDead()
   132  	c.Assert(err, jc.ErrorIsNil)
   133  	err = st1.RemoveDyingModel()
   134  	c.Assert(err, jc.ErrorIsNil)
   135  
   136  	// We should now be able to create the other model.
   137  	model2, st2, err := s.Controller.NewModel(state.ModelArgs{
   138  		Type:                    state.ModelTypeIAAS,
   139  		CloudName:               "dummy",
   140  		CloudRegion:             "dummy-region",
   141  		Config:                  cfg2,
   142  		Owner:                   owner,
   143  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   144  	})
   145  	c.Assert(err, jc.ErrorIsNil)
   146  	defer st2.Close()
   147  	c.Assert(model2, gc.NotNil)
   148  	c.Assert(st2, gc.NotNil)
   149  }
   150  
   151  func (s *ModelSuite) TestNewCAASModelDifferentUser(c *gc.C) {
   152  	cfg, _ := s.createTestModelConfig(c)
   153  	owner := s.Factory.MakeUser(c, nil).UserTag()
   154  	owner2 := s.Factory.MakeUser(c, nil).UserTag()
   155  
   156  	// Create the first model.
   157  	model, st1, err := s.Controller.NewModel(state.ModelArgs{
   158  		Type:                    state.ModelTypeCAAS,
   159  		CloudName:               "dummy",
   160  		CloudRegion:             "dummy-region",
   161  		Config:                  cfg,
   162  		Owner:                   owner,
   163  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   164  	})
   165  	c.Assert(err, jc.ErrorIsNil)
   166  	defer st1.Close()
   167  	c.Assert(model.UniqueIndexExists(), jc.IsTrue)
   168  
   169  	// Attempt to create another model with a different UUID and owner
   170  	// but the name as the first.
   171  	newUUID, err := utils.NewUUID()
   172  	c.Assert(err, jc.ErrorIsNil)
   173  	cfg2 := testing.CustomModelConfig(c, testing.Attrs{
   174  		"name": cfg.Name(),
   175  		"uuid": newUUID.String(),
   176  	})
   177  
   178  	// We should now be able to create the other model.
   179  	model2, st2, err := s.Controller.NewModel(state.ModelArgs{
   180  		Type:                    state.ModelTypeCAAS,
   181  		CloudName:               "dummy",
   182  		CloudRegion:             "dummy-region",
   183  		Config:                  cfg2,
   184  		Owner:                   owner2,
   185  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   186  	})
   187  	c.Assert(err, jc.ErrorIsNil)
   188  	defer st2.Close()
   189  	c.Assert(model2.UniqueIndexExists(), jc.IsTrue)
   190  }
   191  
   192  func (s *ModelSuite) TestNewCAASModelSameUserFails(c *gc.C) {
   193  	cfg, _ := s.createTestModelConfig(c)
   194  	owner := s.Factory.MakeUser(c, nil).UserTag()
   195  
   196  	// Create the first model.
   197  	model, st1, err := s.Controller.NewModel(state.ModelArgs{
   198  		Type:                    state.ModelTypeCAAS,
   199  		CloudName:               "dummy",
   200  		CloudRegion:             "dummy-region",
   201  		Config:                  cfg,
   202  		Owner:                   owner,
   203  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   204  	})
   205  	c.Assert(err, jc.ErrorIsNil)
   206  	defer st1.Close()
   207  	c.Assert(model.UniqueIndexExists(), jc.IsTrue)
   208  
   209  	// Attempt to create another model with a different UUID but the
   210  	// same owner and name as the first.
   211  	newUUID, err := utils.NewUUID()
   212  	c.Assert(err, jc.ErrorIsNil)
   213  	cfg2 := testing.CustomModelConfig(c, testing.Attrs{
   214  		"name": cfg.Name(),
   215  		"uuid": newUUID.String(),
   216  	})
   217  	_, _, err = s.Controller.NewModel(state.ModelArgs{
   218  		Type:                    state.ModelTypeCAAS,
   219  		CloudName:               "dummy",
   220  		CloudRegion:             "dummy-region",
   221  		Config:                  cfg2,
   222  		Owner:                   owner,
   223  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   224  	})
   225  	errMsg := fmt.Sprintf("model %q for %s already exists", cfg2.Name(), owner.Name())
   226  	c.Assert(err, gc.ErrorMatches, errMsg)
   227  	c.Assert(errors.IsAlreadyExists(err), jc.IsTrue)
   228  
   229  	// Remove the first model.
   230  	model1, err := st1.Model()
   231  	c.Assert(err, jc.ErrorIsNil)
   232  	err = model1.Destroy(state.DestroyModelParams{})
   233  	c.Assert(err, jc.ErrorIsNil)
   234  	// Destroy only sets the model to dying and RemoveDyingModel can
   235  	// only be called on a dead model. Normally, the environ's lifecycle
   236  	// would be set to dead after machines and applications have been cleaned up.
   237  	err = model1.SetDead()
   238  	c.Assert(err, jc.ErrorIsNil)
   239  	err = st1.RemoveDyingModel()
   240  	c.Assert(err, jc.ErrorIsNil)
   241  
   242  	// We should now be able to create the other model.
   243  	model2, st2, err := s.Controller.NewModel(state.ModelArgs{
   244  		Type:                    state.ModelTypeCAAS,
   245  		CloudName:               "dummy",
   246  		CloudRegion:             "dummy-region",
   247  		Config:                  cfg2,
   248  		Owner:                   owner,
   249  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   250  	})
   251  	c.Assert(err, jc.ErrorIsNil)
   252  	defer st2.Close()
   253  	c.Assert(model2, gc.NotNil)
   254  	c.Assert(st2, gc.NotNil)
   255  }
   256  
   257  func (s *ModelSuite) TestNewModelMissingType(c *gc.C) {
   258  	cfg, _ := s.createTestModelConfig(c)
   259  	owner := names.NewUserTag("test@remote")
   260  	_, _, err := s.Controller.NewModel(state.ModelArgs{
   261  		// No type
   262  		CloudName:               "dummy",
   263  		CloudRegion:             "dummy-region",
   264  		Config:                  cfg,
   265  		Owner:                   owner,
   266  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   267  	})
   268  	c.Assert(err, gc.ErrorMatches, "empty Type not valid")
   269  
   270  }
   271  
   272  func (s *ModelSuite) TestNewModel(c *gc.C) {
   273  	cfg, uuid := s.createTestModelConfig(c)
   274  	owner := names.NewUserTag("test@remote")
   275  
   276  	model, st, err := s.Controller.NewModel(state.ModelArgs{
   277  		Type:                    state.ModelTypeIAAS,
   278  		CloudName:               "dummy",
   279  		CloudRegion:             "dummy-region",
   280  		Config:                  cfg,
   281  		Owner:                   owner,
   282  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   283  	})
   284  	c.Assert(err, jc.ErrorIsNil)
   285  	c.Check(model.IsControllerModel(), jc.IsFalse)
   286  	defer st.Close()
   287  
   288  	modelTag := names.NewModelTag(uuid)
   289  	assertModelMatches := func(model *state.Model) {
   290  		c.Assert(model.UUID(), gc.Equals, modelTag.Id())
   291  		c.Assert(model.Type(), gc.Equals, state.ModelTypeIAAS)
   292  		c.Assert(model.Tag(), gc.Equals, modelTag)
   293  		c.Assert(model.ControllerTag(), gc.Equals, s.State.ControllerTag())
   294  		c.Assert(model.Owner(), gc.Equals, owner)
   295  		c.Assert(model.Name(), gc.Equals, "testing")
   296  		c.Assert(model.Life(), gc.Equals, state.Alive)
   297  		c.Assert(model.CloudRegion(), gc.Equals, "dummy-region")
   298  	}
   299  	assertModelMatches(model)
   300  
   301  	model, ph, err := s.StatePool.GetModel(uuid)
   302  	c.Assert(err, jc.ErrorIsNil)
   303  	defer ph.Release()
   304  	assertModelMatches(model)
   305  
   306  	model, err = st.Model()
   307  	c.Assert(err, jc.ErrorIsNil)
   308  	assertModelMatches(model)
   309  
   310  	// Check that the cloud's model count is incremented.
   311  	testCloud, err := s.State.Cloud("dummy")
   312  	c.Assert(err, jc.ErrorIsNil)
   313  	refCount, err := state.CloudModelRefCount(st, testCloud.Name)
   314  	c.Assert(err, jc.ErrorIsNil)
   315  	c.Assert(refCount, gc.Equals, 2)
   316  
   317  	// Since the model tag for the State connection is different,
   318  	// asking for this model through FindEntity returns a not found error.
   319  	_, err = s.State.FindEntity(modelTag)
   320  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   321  
   322  	entity, err := st.FindEntity(modelTag)
   323  	c.Assert(err, jc.ErrorIsNil)
   324  	c.Assert(entity.Tag(), gc.Equals, modelTag)
   325  
   326  	// Ensure the model is functional by adding a machine
   327  	_, err = st.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
   328  	c.Assert(err, jc.ErrorIsNil)
   329  
   330  	// Ensure the default model was created.
   331  	_, err = st.SpaceByName(network.AlphaSpaceName)
   332  	c.Assert(err, jc.ErrorIsNil)
   333  }
   334  
   335  func (s *ModelSuite) TestNewModelRegionNameEscaped(c *gc.C) {
   336  	cfg, _ := s.createTestModelConfig(c)
   337  	model, st, err := s.Controller.NewModel(state.ModelArgs{
   338  		Type:                    state.ModelTypeIAAS,
   339  		CloudName:               "dummy",
   340  		CloudRegion:             "dotty.region",
   341  		Config:                  cfg,
   342  		Owner:                   names.NewUserTag("test@remote"),
   343  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   344  	})
   345  	c.Assert(err, jc.ErrorIsNil)
   346  	defer st.Close()
   347  	c.Assert(model.CloudRegion(), gc.Equals, "dotty.region")
   348  }
   349  
   350  func (s *ModelSuite) TestNewModelImportingMode(c *gc.C) {
   351  	cfg, _ := s.createTestModelConfig(c)
   352  	owner := names.NewUserTag("test@remote")
   353  
   354  	model, st, err := s.Controller.NewModel(state.ModelArgs{
   355  		Type:                    state.ModelTypeIAAS,
   356  		CloudName:               "dummy",
   357  		CloudRegion:             "dummy-region",
   358  		Config:                  cfg,
   359  		Owner:                   owner,
   360  		MigrationMode:           state.MigrationModeImporting,
   361  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   362  	})
   363  	c.Assert(err, jc.ErrorIsNil)
   364  	defer st.Close()
   365  
   366  	c.Assert(model.MigrationMode(), gc.Equals, state.MigrationModeImporting)
   367  }
   368  
   369  func (s *ModelSuite) TestSetMigrationMode(c *gc.C) {
   370  	cfg, _ := s.createTestModelConfig(c)
   371  	owner := names.NewUserTag("test@remote")
   372  
   373  	model, st, err := s.Controller.NewModel(state.ModelArgs{
   374  		Type:                    state.ModelTypeIAAS,
   375  		CloudName:               "dummy",
   376  		CloudRegion:             "dummy-region",
   377  		Config:                  cfg,
   378  		Owner:                   owner,
   379  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   380  	})
   381  	c.Assert(err, jc.ErrorIsNil)
   382  	defer st.Close()
   383  
   384  	err = model.SetMigrationMode(state.MigrationModeExporting)
   385  	c.Assert(err, jc.ErrorIsNil)
   386  	c.Assert(model.MigrationMode(), gc.Equals, state.MigrationModeExporting)
   387  }
   388  
   389  func (s *ModelSuite) TestModelExists(c *gc.C) {
   390  	modelExists, err := s.State.ModelExists(s.State.ModelUUID())
   391  	c.Assert(err, jc.ErrorIsNil)
   392  	c.Check(modelExists, jc.IsTrue)
   393  }
   394  
   395  func (s *ModelSuite) TestModelExistsNoModel(c *gc.C) {
   396  	modelExists, err := s.State.ModelExists("foo")
   397  	c.Assert(err, jc.ErrorIsNil)
   398  	c.Check(modelExists, jc.IsFalse)
   399  }
   400  
   401  func (s *ModelSuite) TestSLA(c *gc.C) {
   402  	cfg, _ := s.createTestModelConfig(c)
   403  	owner := names.NewUserTag("test@remote")
   404  
   405  	model, st, err := s.Controller.NewModel(state.ModelArgs{
   406  		Type:                    state.ModelTypeIAAS,
   407  		CloudName:               "dummy",
   408  		CloudRegion:             "dummy-region",
   409  		Config:                  cfg,
   410  		Owner:                   owner,
   411  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   412  	})
   413  	c.Assert(err, jc.ErrorIsNil)
   414  	defer st.Close()
   415  
   416  	level, err := st.SLALevel()
   417  	c.Assert(err, jc.ErrorIsNil)
   418  	c.Assert(level, gc.Equals, "unsupported")
   419  	c.Assert(model.SLACredential(), gc.DeepEquals, []byte{})
   420  	for _, goodLevel := range []string{"unsupported", "essential", "standard", "advanced"} {
   421  		err = st.SetSLA(goodLevel, "bob", []byte("auth "+goodLevel))
   422  		c.Assert(err, jc.ErrorIsNil)
   423  		c.Assert(model.Refresh(), jc.ErrorIsNil)
   424  		level, err = st.SLALevel()
   425  		c.Assert(err, jc.ErrorIsNil)
   426  		c.Assert(level, gc.Equals, goodLevel)
   427  		c.Assert(model.SLALevel(), gc.Equals, goodLevel)
   428  		c.Assert(model.SLAOwner(), gc.Equals, "bob")
   429  		c.Assert(model.SLACredential(), gc.DeepEquals, []byte("auth "+goodLevel))
   430  	}
   431  
   432  	defaultLevel, err := state.NewSLALevel("")
   433  	c.Assert(err, jc.ErrorIsNil)
   434  	c.Assert(defaultLevel, gc.Equals, state.SLAUnsupported)
   435  
   436  	err = model.SetSLA("nope", "nobody", []byte("auth nope"))
   437  	c.Assert(err, gc.ErrorMatches, `.*SLA level "nope" not valid.*`)
   438  
   439  	c.Assert(model.SLALevel(), gc.Equals, "advanced")
   440  	c.Assert(model.SLAOwner(), gc.Equals, "bob")
   441  	c.Assert(model.SLACredential(), gc.DeepEquals, []byte("auth advanced"))
   442  	slaCreds, err := st.SLACredential()
   443  	c.Assert(err, jc.ErrorIsNil)
   444  	c.Assert(slaCreds, gc.DeepEquals, []byte("auth advanced"))
   445  }
   446  
   447  func (s *ModelSuite) TestMeterStatus(c *gc.C) {
   448  	cfg, _ := s.createTestModelConfig(c)
   449  	owner := names.NewUserTag("test@remote")
   450  
   451  	model, st, err := s.Controller.NewModel(state.ModelArgs{
   452  		Type:                    state.ModelTypeIAAS,
   453  		CloudName:               "dummy",
   454  		CloudRegion:             "dummy-region",
   455  		Config:                  cfg,
   456  		Owner:                   owner,
   457  		StorageProviderRegistry: storage.StaticProviderRegistry{},
   458  	})
   459  	c.Assert(err, jc.ErrorIsNil)
   460  	defer st.Close()
   461  
   462  	ms, err := st.ModelMeterStatus()
   463  	c.Assert(err, jc.ErrorIsNil)
   464  	c.Assert(ms.Code, gc.Equals, state.MeterNotAvailable)
   465  	c.Assert(ms.Info, gc.Equals, "")
   466  
   467  	for i, validStatus := range []string{"RED", "GREEN", "AMBER"} {
   468  		info := fmt.Sprintf("info setting %d", i)
   469  		err = st.SetModelMeterStatus(validStatus, info)
   470  		c.Assert(err, jc.ErrorIsNil)
   471  		c.Assert(model.Refresh(), jc.ErrorIsNil)
   472  		ms, err = st.ModelMeterStatus()
   473  		c.Assert(err, jc.ErrorIsNil)
   474  		c.Assert(ms.Code.String(), gc.Equals, validStatus)
   475  		c.Assert(ms.Info, gc.Equals, info)
   476  	}
   477  
   478  	err = model.SetMeterStatus("PURPLE", "foobar")
   479  	c.Assert(err, gc.ErrorMatches, `meter status "PURPLE" not valid`)
   480  
   481  	c.Assert(ms.Code, gc.Equals, state.MeterAmber)
   482  	c.Assert(ms.Info, gc.Equals, "info setting 2")
   483  }
   484  
   485  func (s *ModelSuite) TestConfigForOtherModel(c *gc.C) {
   486  	otherState := s.Factory.MakeModel(c, &factory.ModelParams{Name: "other"})
   487  	defer otherState.Close()
   488  	otherModel, err := otherState.Model()
   489  	c.Assert(err, jc.ErrorIsNil)
   490  
   491  	// Obtain another instance of the model via the StatePool
   492  	model, ph, err := s.StatePool.GetModel(otherModel.UUID())
   493  	c.Assert(err, jc.ErrorIsNil)
   494  	defer ph.Release()
   495  
   496  	conf, err := model.Config()
   497  	c.Assert(err, jc.ErrorIsNil)
   498  	c.Assert(conf.Name(), gc.Equals, "other")
   499  	c.Assert(conf.UUID(), gc.Equals, otherModel.UUID())
   500  }
   501  
   502  func (s *ModelSuite) TestAllUnits(c *gc.C) {
   503  	wordpress := s.Factory.MakeApplication(c, &factory.ApplicationParams{
   504  		Name: "wordpress",
   505  	})
   506  	mysql := s.Factory.MakeApplication(c, &factory.ApplicationParams{
   507  		Name: "mysql",
   508  	})
   509  	s.Factory.MakeUnit(c, &factory.UnitParams{Application: wordpress})
   510  	s.Factory.MakeUnit(c, &factory.UnitParams{Application: wordpress})
   511  	s.Factory.MakeUnit(c, &factory.UnitParams{Application: mysql})
   512  
   513  	model, err := s.State.Model()
   514  	c.Assert(err, jc.ErrorIsNil)
   515  	units, err := model.AllUnits()
   516  	c.Assert(err, jc.ErrorIsNil)
   517  
   518  	var unitNames []string
   519  	for _, u := range units {
   520  		if !u.ShouldBeAssigned() {
   521  			c.Fail()
   522  		}
   523  		unitNames = append(unitNames, u.Name())
   524  	}
   525  	sort.Strings(unitNames)
   526  	c.Assert(unitNames, jc.DeepEquals, []string{
   527  		"mysql/0", "wordpress/0", "wordpress/1",
   528  	})
   529  }
   530  
   531  func (s *ModelSuite) TestMetrics(c *gc.C) {
   532  	wordpress := s.Factory.MakeApplication(c, &factory.ApplicationParams{
   533  		Name: "wordpress",
   534  	})
   535  	mysql := s.Factory.MakeApplication(c, &factory.ApplicationParams{
   536  		Name: "mysql",
   537  	})
   538  	s.Factory.MakeUnit(c, &factory.UnitParams{Application: wordpress})
   539  	s.Factory.MakeUnit(c, &factory.UnitParams{Application: wordpress})
   540  	s.Factory.MakeUnit(c, &factory.UnitParams{Application: mysql})
   541  
   542  	// Add a machine/unit/application and destroy it, to
   543  	// ensure we're only counting entities that are alive.
   544  	m := s.Factory.MakeMachine(c, &factory.MachineParams{})
   545  	err := m.Destroy()
   546  	c.Assert(err, jc.ErrorIsNil)
   547  	one := s.Factory.MakeApplication(c, &factory.ApplicationParams{
   548  		Name: "one",
   549  	})
   550  	u := s.Factory.MakeUnit(c, &factory.UnitParams{Application: mysql})
   551  	err = one.Destroy()
   552  	c.Assert(err, jc.ErrorIsNil)
   553  	err = u.Destroy()
   554  	c.Assert(err, jc.ErrorIsNil)
   555  
   556  	model, err := s.State.Model()
   557  	c.Assert(err, jc.ErrorIsNil)
   558  
   559  	obtained, err := model.Metrics()
   560  	c.Assert(err, jc.ErrorIsNil)
   561  
   562  	expected := state.ModelMetrics{
   563  		ApplicationCount: "2",
   564  		MachineCount:     "3",
   565  		UnitCount:        "3",
   566  		CloudName:        "dummy",
   567  		CloudRegion:      "dummy-region",
   568  		Provider:         "dummy",
   569  		UUID:             s.Model.UUID(),
   570  		ControllerUUID:   s.Model.ControllerUUID(),
   571  	}
   572  
   573  	c.Assert(obtained, jc.DeepEquals, expected)
   574  }
   575  
   576  func (s *ModelSuite) TestAllEndpointBindings(c *gc.C) {
   577  	oneSpace := s.Factory.MakeSpace(c, &factory.SpaceParams{
   578  		Name: "one", ProviderID: network.Id("provider"), IsPublic: true})
   579  	app := state.AddTestingApplicationWithBindings(
   580  		c, s.State, "wordpress", state.AddTestingCharm(c, s.State, "wordpress"),
   581  		map[string]string{"db": oneSpace.Id()})
   582  
   583  	model, err := s.State.Model()
   584  	c.Assert(err, jc.ErrorIsNil)
   585  
   586  	listBindings, err := model.AllEndpointBindings()
   587  	c.Assert(err, jc.ErrorIsNil)
   588  	c.Assert(listBindings, gc.HasLen, 1)
   589  
   590  	expected := map[string]string{
   591  		"":                network.AlphaSpaceId,
   592  		"cache":           network.AlphaSpaceId,
   593  		"foo-bar":         network.AlphaSpaceId,
   594  		"db-client":       network.AlphaSpaceId,
   595  		"admin-api":       network.AlphaSpaceId,
   596  		"url":             network.AlphaSpaceId,
   597  		"logging-dir":     network.AlphaSpaceId,
   598  		"monitoring-port": network.AlphaSpaceId,
   599  		"db":              oneSpace.Id(),
   600  	}
   601  	c.Assert(listBindings[app.Name()].Map(), gc.DeepEquals, expected)
   602  }
   603  
   604  func (s *ModelSuite) TestAllEndpointBindingsSpaceNames(c *gc.C) {
   605  	oneSpace := s.Factory.MakeSpace(c, &factory.SpaceParams{
   606  		Name: "one", ProviderID: network.Id("provider"), IsPublic: true})
   607  	state.AddTestingApplicationWithBindings(
   608  		c, s.State, "wordpress", state.AddTestingCharm(c, s.State, "wordpress"),
   609  		map[string]string{"db": oneSpace.Id()})
   610  
   611  	spaceNames, err := s.State.AllEndpointBindingsSpaceNames()
   612  	c.Assert(err, jc.ErrorIsNil)
   613  	c.Assert(spaceNames.Size(), gc.Equals, 2)
   614  	c.Assert(spaceNames.SortedValues(), gc.DeepEquals, []string{"alpha", "one"})
   615  }
   616  
   617  func (s *ModelSuite) TestAllEndpointBindingsSpaceNamesWithoutAnySpaces(c *gc.C) {
   618  	spaceNames, err := s.State.AllEndpointBindingsSpaceNames()
   619  	c.Assert(err, jc.ErrorIsNil)
   620  	c.Assert(spaceNames.Size(), gc.Equals, 0)
   621  }
   622  
   623  // createTestModelConfig returns a new model config and its UUID for testing.
   624  func (s *ModelSuite) createTestModelConfig(c *gc.C) (*config.Config, string) {
   625  	return createTestModelConfig(c, s.modelTag.Id())
   626  }
   627  
   628  func createTestModelConfig(c *gc.C, controllerUUID string) (*config.Config, string) {
   629  	uuid, err := utils.NewUUID()
   630  	c.Assert(err, jc.ErrorIsNil)
   631  	return testing.CustomModelConfig(c, testing.Attrs{
   632  		"name": "testing",
   633  		"uuid": uuid.String(),
   634  	}), uuid.String()
   635  }
   636  
   637  func (s *ModelSuite) TestModelConfigSameModelAsState(c *gc.C) {
   638  	model, err := s.State.Model()
   639  	c.Assert(err, jc.ErrorIsNil)
   640  	cfg, err := model.Config()
   641  	c.Assert(err, jc.ErrorIsNil)
   642  	c.Assert(cfg.UUID(), gc.Equals, s.State.ModelUUID())
   643  }
   644  
   645  func (s *ModelSuite) TestModelConfigDifferentModelThanState(c *gc.C) {
   646  	otherState := s.Factory.MakeModel(c, nil)
   647  	defer otherState.Close()
   648  	model, err := otherState.Model()
   649  	c.Assert(err, jc.ErrorIsNil)
   650  	cfg, err := model.Config()
   651  	c.Assert(err, jc.ErrorIsNil)
   652  	uuid := cfg.UUID()
   653  	c.Assert(uuid, gc.Equals, model.UUID())
   654  	c.Assert(uuid, gc.Not(gc.Equals), s.State.ModelUUID())
   655  }
   656  
   657  func (s *ModelSuite) TestDestroyControllerModel(c *gc.C) {
   658  	model, err := s.State.Model()
   659  	c.Assert(err, jc.ErrorIsNil)
   660  	err = model.Destroy(state.DestroyModelParams{})
   661  	c.Assert(err, jc.ErrorIsNil)
   662  	c.Assert(model.Refresh(), jc.ErrorIsNil)
   663  	c.Assert(model.Life(), gc.Equals, state.Dying)
   664  }
   665  
   666  func (s *ModelSuite) TestDestroyOtherModel(c *gc.C) {
   667  	st2 := s.Factory.MakeModel(c, nil)
   668  	defer st2.Close()
   669  	model, err := st2.Model()
   670  	c.Assert(err, jc.ErrorIsNil)
   671  	c.Assert(model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
   672  	c.Assert(model.Refresh(), jc.ErrorIsNil)
   673  	c.Assert(model.Life(), gc.Equals, state.Dying)
   674  	c.Assert(st2.RemoveDyingModel(), jc.ErrorIsNil)
   675  	c.Assert(model.Refresh(), jc.Satisfies, errors.IsNotFound)
   676  	// Destroying an empty model also removes the name index doc.
   677  	c.Assert(model.UniqueIndexExists(), jc.IsFalse)
   678  }
   679  
   680  func (s *ModelSuite) TestDestroyControllerNonEmptyModelFails(c *gc.C) {
   681  	s.assertDestroyControllerNonEmptyModelFails(c, nil)
   682  }
   683  
   684  func (s *ModelSuite) TestDestroyControllerNonEmptyModelWithForceFails(c *gc.C) {
   685  	force := true
   686  	s.assertDestroyControllerNonEmptyModelFails(c, &force)
   687  }
   688  
   689  func (s *ModelSuite) assertDestroyControllerNonEmptyModelFails(c *gc.C, force *bool) {
   690  	st2 := s.Factory.MakeModel(c, nil)
   691  	defer st2.Close()
   692  	factory.NewFactory(st2, s.StatePool).MakeApplication(c, nil)
   693  
   694  	model, err := s.State.Model()
   695  	c.Assert(err, jc.ErrorIsNil)
   696  	c.Assert(model.Destroy(state.DestroyModelParams{Force: force}), gc.ErrorMatches, "failed to destroy model: hosting 1 other model")
   697  	c.Assert(model.Refresh(), jc.ErrorIsNil)
   698  	c.Assert(model.Life(), gc.Equals, state.Alive)
   699  	model2, err := st2.Model()
   700  	c.Assert(err, jc.ErrorIsNil)
   701  	c.Assert(model2.Refresh(), jc.ErrorIsNil)
   702  	c.Assert(model2.Life(), gc.Equals, state.Alive)
   703  }
   704  
   705  func (s *ModelSuite) TestDestroyControllerWithEmptyModel(c *gc.C) {
   706  	st2 := s.Factory.MakeModel(c, nil)
   707  	defer st2.Close()
   708  
   709  	controllerModel, err := s.State.Model()
   710  	c.Assert(err, jc.ErrorIsNil)
   711  	c.Assert(controllerModel.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
   712  	c.Assert(controllerModel.Refresh(), jc.ErrorIsNil)
   713  	c.Assert(controllerModel.Life(), gc.Equals, state.Dying)
   714  	assertNeedsCleanup(c, s.State)
   715  	assertCleanupRuns(c, s.State)
   716  
   717  	hostedModel, err := st2.Model()
   718  	c.Assert(err, jc.ErrorIsNil)
   719  	c.Assert(hostedModel.Refresh(), jc.ErrorIsNil)
   720  	c.Logf("model %s, life %s", hostedModel.UUID(), hostedModel.Life())
   721  	c.Assert(hostedModel.Life(), gc.Equals, state.Dying)
   722  	c.Assert(st2.RemoveDyingModel(), jc.ErrorIsNil)
   723  	c.Assert(hostedModel.Refresh(), jc.Satisfies, errors.IsNotFound)
   724  }
   725  
   726  func (s *ModelSuite) TestDestroyControllerAndHostedModels(c *gc.C) {
   727  	st2 := s.Factory.MakeModel(c, nil)
   728  	defer st2.Close()
   729  	factory.NewFactory(st2, s.StatePool).MakeApplication(c, nil)
   730  
   731  	controllerModel, err := s.State.Model()
   732  	c.Assert(err, jc.ErrorIsNil)
   733  	destroyStorage := true
   734  	c.Assert(controllerModel.Destroy(state.DestroyModelParams{
   735  		DestroyHostedModels: true,
   736  		DestroyStorage:      &destroyStorage,
   737  	}), jc.ErrorIsNil)
   738  
   739  	model, err := s.State.Model()
   740  	c.Assert(err, jc.ErrorIsNil)
   741  	c.Assert(model.Life(), gc.Equals, state.Dying)
   742  
   743  	assertNeedsCleanup(c, s.State)
   744  	assertCleanupRuns(c, s.State)
   745  
   746  	// Cleanups for hosted model enqueued by controller model cleanups.
   747  	assertNeedsCleanup(c, st2)
   748  	assertCleanupRuns(c, st2)
   749  
   750  	model2, err := st2.Model()
   751  	c.Assert(err, jc.ErrorIsNil)
   752  	c.Assert(model2.Life(), gc.Equals, state.Dying)
   753  
   754  	c.Assert(st2.ProcessDyingModel(), jc.ErrorIsNil)
   755  	c.Assert(st2.RemoveDyingModel(), jc.ErrorIsNil)
   756  
   757  	c.Assert(model2.Refresh(), jc.Satisfies, errors.IsNotFound)
   758  
   759  	c.Assert(s.State.ProcessDyingModel(), jc.ErrorIsNil)
   760  	c.Assert(s.State.RemoveDyingModel(), jc.ErrorIsNil)
   761  	c.Assert(model.Refresh(), jc.Satisfies, errors.IsNotFound)
   762  }
   763  
   764  func (s *ModelSuite) TestDestroyControllerAndHostedModelsWithResources(c *gc.C) {
   765  	otherSt := s.Factory.MakeModel(c, nil)
   766  	defer otherSt.Close()
   767  
   768  	assertModel := func(model *state.Model, st *state.State, life state.Life, expectedMachines, expectedApplications int) {
   769  		c.Assert(model.Refresh(), jc.ErrorIsNil)
   770  		c.Assert(model.Life(), gc.Equals, life)
   771  
   772  		machines, err := st.AllMachines()
   773  		c.Assert(err, jc.ErrorIsNil)
   774  		c.Assert(machines, gc.HasLen, expectedMachines)
   775  
   776  		applications, err := st.AllApplications()
   777  		c.Assert(err, jc.ErrorIsNil)
   778  		c.Assert(applications, gc.HasLen, expectedApplications)
   779  	}
   780  
   781  	// add some machines and applications
   782  	otherModel, err := otherSt.Model()
   783  	c.Assert(err, jc.ErrorIsNil)
   784  	_, err = otherSt.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
   785  	c.Assert(err, jc.ErrorIsNil)
   786  	application := s.Factory.MakeApplication(c, nil)
   787  
   788  	ch := state.AddTestingCharm(c, otherSt, "dummy")
   789  	args := state.AddApplicationArgs{
   790  		Name:  application.Name(),
   791  		Charm: ch,
   792  		CharmOrigin: &state.CharmOrigin{Platform: &state.Platform{
   793  			OS:      "ubuntu",
   794  			Channel: "12.10/stable",
   795  		}},
   796  	}
   797  	_, err = otherSt.AddApplication(args)
   798  	c.Assert(err, jc.ErrorIsNil)
   799  
   800  	controllerModel, err := s.State.Model()
   801  	c.Assert(err, jc.ErrorIsNil)
   802  	destroyStorage := true
   803  	force := true
   804  	c.Assert(controllerModel.Destroy(state.DestroyModelParams{
   805  		Force:               &force,
   806  		DestroyHostedModels: true,
   807  		DestroyStorage:      &destroyStorage,
   808  	}), jc.ErrorIsNil)
   809  
   810  	assertCleanupCountDirty(c, s.State, 4)
   811  	assertAllMachinesDeadAndRemove(c, s.State)
   812  	assertModel(controllerModel, s.State, state.Dying, 0, 0)
   813  
   814  	err = s.State.ProcessDyingModel()
   815  	c.Assert(errors.Is(err, stateerrors.HasHostedModelsError), jc.IsTrue)
   816  	c.Assert(err, gc.ErrorMatches, `hosting 1 other model`)
   817  
   818  	assertCleanupCount(c, otherSt, 3)
   819  	assertAllMachinesDeadAndRemove(c, otherSt)
   820  	assertModel(otherModel, otherSt, state.Dying, 0, 0)
   821  	c.Assert(otherSt.ProcessDyingModel(), jc.ErrorIsNil)
   822  	c.Assert(otherSt.RemoveDyingModel(), jc.ErrorIsNil)
   823  
   824  	c.Assert(otherModel.Refresh(), jc.Satisfies, errors.IsNotFound)
   825  
   826  	c.Assert(s.State.ProcessDyingModel(), jc.ErrorIsNil)
   827  	c.Assert(s.State.RemoveDyingModel(), jc.ErrorIsNil)
   828  	c.Assert(controllerModel.Refresh(), jc.Satisfies, errors.IsNotFound)
   829  }
   830  
   831  func (s *ModelSuite) assertDestroyControllerAndHostedModelsWithPersistentStorage(c *gc.C, force *bool) {
   832  	otherSt := s.Factory.MakeModel(c, nil)
   833  	defer otherSt.Close()
   834  
   835  	// Add a unit with persistent storage, which will prevent Destroy
   836  	// from succeeding on account of DestroyStorage being nil.
   837  	otherFactory := factory.NewFactory(otherSt, s.StatePool)
   838  	otherFactory.MakeUnit(c, &factory.UnitParams{
   839  		Application: otherFactory.MakeApplication(c, &factory.ApplicationParams{
   840  			Charm: otherFactory.MakeCharm(c, &factory.CharmParams{
   841  				Name: "storage-block",
   842  				URL:  "ch:quantal/storage-block-1",
   843  			}),
   844  			Storage: map[string]state.StorageConstraints{
   845  				"data": {Count: 1, Size: 1024, Pool: "modelscoped"},
   846  			},
   847  		}),
   848  	})
   849  
   850  	controllerModel, err := s.State.Model()
   851  	c.Assert(err, jc.ErrorIsNil)
   852  	err = controllerModel.Destroy(state.DestroyModelParams{
   853  		DestroyHostedModels: true,
   854  		Force:               force,
   855  	})
   856  	c.Assert(errors.Is(err, stateerrors.PersistentStorageError), jc.IsTrue)
   857  }
   858  
   859  func (s *ModelSuite) TestDestroyControllerAndHostedModelsWithPersistentStorage(c *gc.C) {
   860  	s.assertDestroyControllerAndHostedModelsWithPersistentStorage(c, nil)
   861  }
   862  
   863  func (s *ModelSuite) TestDestroyControllerAndHostedModelsWithPersistentStorageWithForce(c *gc.C) {
   864  	force := true
   865  	s.assertDestroyControllerAndHostedModelsWithPersistentStorage(c, &force)
   866  }
   867  
   868  func (s *ModelSuite) TestDestroyControllerEmptyModelRace(c *gc.C) {
   869  	defer s.Factory.MakeModel(c, nil).Close()
   870  
   871  	// Simulate an empty model being added just before the
   872  	// remove txn is called.
   873  	defer state.SetBeforeHooks(c, s.State, func() {
   874  		s.Factory.MakeModel(c, nil).Close()
   875  	}).Check()
   876  
   877  	model, err := s.State.Model()
   878  	c.Assert(err, jc.ErrorIsNil)
   879  	c.Assert(model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
   880  }
   881  
   882  func (s *ModelSuite) TestDestroyControllerRemoveEmptyAddNonEmptyModel(c *gc.C) {
   883  	st2 := s.Factory.MakeModel(c, nil)
   884  	defer st2.Close()
   885  
   886  	// Simulate an empty model being removed, and a new non-empty
   887  	// model being added, just before the remove txn is called.
   888  	defer state.SetBeforeHooks(c, s.State, func() {
   889  		// Destroy the empty model, which should move it right
   890  		// along to Dead, and then remove it.
   891  		model, err := st2.Model()
   892  		c.Assert(err, jc.ErrorIsNil)
   893  		c.Assert(model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
   894  		err = st2.RemoveDyingModel()
   895  		c.Assert(err, jc.ErrorIsNil)
   896  
   897  		// Add a new, non-empty model. This should still prevent
   898  		// the controller from being destroyed.
   899  		st3 := s.Factory.MakeModel(c, nil)
   900  		defer st3.Close()
   901  		factory.NewFactory(st3, s.StatePool).MakeApplication(c, nil)
   902  	}).Check()
   903  
   904  	model, err := s.State.Model()
   905  	c.Assert(err, jc.ErrorIsNil)
   906  	c.Assert(model.Destroy(state.DestroyModelParams{}), gc.ErrorMatches, "failed to destroy model: hosting 1 other model")
   907  }
   908  
   909  func (s *ModelSuite) TestDestroyControllerNonEmptyModelRace(c *gc.C) {
   910  	// Simulate an empty model being added just before the
   911  	// remove txn is called.
   912  	defer state.SetBeforeHooks(c, s.State, func() {
   913  		st := s.Factory.MakeModel(c, nil)
   914  		defer st.Close()
   915  		factory.NewFactory(st, s.StatePool).MakeApplication(c, nil)
   916  	}).Check()
   917  
   918  	model, err := s.State.Model()
   919  	c.Assert(err, jc.ErrorIsNil)
   920  	c.Assert(model.Destroy(state.DestroyModelParams{}), gc.ErrorMatches, "failed to destroy model: hosting 1 other model")
   921  }
   922  
   923  func (s *ModelSuite) TestDestroyControllerAlreadyDyingRaceNoOp(c *gc.C) {
   924  	model, err := s.State.Model()
   925  	c.Assert(err, jc.ErrorIsNil)
   926  
   927  	// Simulate an model being destroyed by another client just before
   928  	// the remove txn is called.
   929  	defer state.SetBeforeHooks(c, s.State, func() {
   930  		c.Assert(model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
   931  	}).Check()
   932  
   933  	c.Assert(model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
   934  }
   935  
   936  func (s *ModelSuite) TestDestroyControllerAlreadyDyingNoOp(c *gc.C) {
   937  	model, err := s.State.Model()
   938  	c.Assert(err, jc.ErrorIsNil)
   939  
   940  	c.Assert(model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
   941  	c.Assert(model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
   942  }
   943  
   944  func (s *ModelSuite) TestDestroyModelNonEmpty(c *gc.C) {
   945  	m, err := s.State.Model()
   946  	c.Assert(err, jc.ErrorIsNil)
   947  
   948  	// Add a application to prevent the model from transitioning directly to Dead.
   949  	s.Factory.MakeApplication(c, nil)
   950  
   951  	c.Assert(m.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
   952  	c.Assert(m.Refresh(), jc.ErrorIsNil)
   953  	c.Assert(m.Life(), gc.Equals, state.Dying)
   954  
   955  	// Since the model is only dying and not dead, the unique index is still there.
   956  	c.Assert(m.UniqueIndexExists(), jc.IsTrue)
   957  }
   958  
   959  func (s *ModelSuite) assertDestroyModelPersistentStorage(c *gc.C, force *bool) {
   960  	m, err := s.State.Model()
   961  	c.Assert(err, jc.ErrorIsNil)
   962  
   963  	// Add a unit with persistent storage, which will prevent Destroy
   964  	// from succeeding on account of DestroyStorage being nil.
   965  	s.Factory.MakeUnit(c, &factory.UnitParams{
   966  		Application: s.Factory.MakeApplication(c, &factory.ApplicationParams{
   967  			Charm: s.AddTestingCharm(c, "storage-block"),
   968  			Storage: map[string]state.StorageConstraints{
   969  				"data": {Count: 1, Size: 1024, Pool: "modelscoped"},
   970  			},
   971  		}),
   972  	})
   973  
   974  	err = m.Destroy(state.DestroyModelParams{Force: force})
   975  	c.Assert(errors.Is(err, stateerrors.PersistentStorageError), jc.IsTrue)
   976  	c.Assert(m.Refresh(), jc.ErrorIsNil)
   977  	c.Assert(m.Life(), gc.Equals, state.Alive)
   978  }
   979  
   980  func (s *ModelSuite) TestDestroyModelPersistentStorage(c *gc.C) {
   981  	s.assertDestroyModelPersistentStorage(c, nil)
   982  }
   983  
   984  func (s *ModelSuite) TestDestroyModelPersistentStorageWithForce(c *gc.C) {
   985  	force := true
   986  	s.assertDestroyModelPersistentStorage(c, &force)
   987  }
   988  
   989  func (s *ModelSuite) TestDestroyModelNonPersistentStorage(c *gc.C) {
   990  	m, err := s.State.Model()
   991  	c.Assert(err, jc.ErrorIsNil)
   992  
   993  	// Add a unit with non-persistent storage, which should not prevent
   994  	// Destroy from succeeding.
   995  	s.Factory.MakeUnit(c, &factory.UnitParams{
   996  		Application: s.Factory.MakeApplication(c, &factory.ApplicationParams{
   997  			Charm: s.AddTestingCharm(c, "storage-block"),
   998  			Storage: map[string]state.StorageConstraints{
   999  				"data": {Count: 1, Size: 1024, Pool: "loop"},
  1000  			},
  1001  		}),
  1002  	})
  1003  
  1004  	err = m.Destroy(state.DestroyModelParams{})
  1005  	c.Assert(err, jc.ErrorIsNil)
  1006  	c.Assert(m.Refresh(), jc.ErrorIsNil)
  1007  	c.Assert(m.Life(), gc.Equals, state.Dying)
  1008  }
  1009  
  1010  func (s *ModelSuite) TestDestroyModelDestroyStorage(c *gc.C) {
  1011  	s.testDestroyModelDestroyStorage(c, true)
  1012  }
  1013  
  1014  func (s *ModelSuite) TestDestroyModelReleaseStorage(c *gc.C) {
  1015  	s.testDestroyModelDestroyStorage(c, false)
  1016  }
  1017  
  1018  func (s *ModelSuite) testDestroyModelDestroyStorage(c *gc.C, destroyStorage bool) {
  1019  	s.Factory.MakeUnit(c, &factory.UnitParams{
  1020  		Application: s.Factory.MakeApplication(c, &factory.ApplicationParams{
  1021  			Charm: s.AddTestingCharm(c, "storage-block"),
  1022  			Storage: map[string]state.StorageConstraints{
  1023  				"data": {Count: 1, Size: 1024, Pool: "modelscoped"},
  1024  			},
  1025  		}),
  1026  	})
  1027  
  1028  	err := s.Model.Destroy(state.DestroyModelParams{DestroyStorage: &destroyStorage})
  1029  	c.Assert(err, jc.ErrorIsNil)
  1030  	c.Assert(s.Model.Refresh(), jc.ErrorIsNil)
  1031  	c.Assert(s.Model.Life(), gc.Equals, state.Dying)
  1032  
  1033  	assertNeedsCleanup(c, s.State)
  1034  	assertCleanupRuns(c, s.State) // destroy application
  1035  	assertCleanupRuns(c, s.State) // destroy unit
  1036  	assertCleanupRuns(c, s.State) // destroy/release storage
  1037  
  1038  	sb, err := state.NewStorageBackend(s.State)
  1039  	c.Assert(err, jc.ErrorIsNil)
  1040  	volume, err := sb.Volume(names.NewVolumeTag("0"))
  1041  	c.Assert(err, jc.ErrorIsNil)
  1042  	c.Assert(volume.Life(), gc.Equals, state.Dying)
  1043  	c.Assert(volume.Releasing(), gc.Equals, !destroyStorage)
  1044  }
  1045  
  1046  func (s *ModelSuite) assertDestroyModelReleaseStorageUnreleasable(c *gc.C, force *bool) {
  1047  	s.Factory.MakeUnit(c, &factory.UnitParams{
  1048  		Application: s.Factory.MakeApplication(c, &factory.ApplicationParams{
  1049  			Charm: s.AddTestingCharm(c, "storage-block"),
  1050  			Storage: map[string]state.StorageConstraints{
  1051  				"data": {Count: 1, Size: 1024, Pool: "modelscoped-unreleasable"},
  1052  			},
  1053  		}),
  1054  	})
  1055  
  1056  	destroyStorage := false
  1057  	err := s.Model.Destroy(state.DestroyModelParams{DestroyStorage: &destroyStorage, Force: force})
  1058  	expectedErr := fmt.Sprintf(`failed to destroy model: cannot release volume 0: ` +
  1059  		`storage provider "modelscoped-unreleasable" does not support releasing storage`)
  1060  	c.Assert(err, gc.ErrorMatches, expectedErr)
  1061  	c.Assert(s.Model.Refresh(), jc.ErrorIsNil)
  1062  	c.Assert(s.Model.Life(), gc.Equals, state.Alive)
  1063  	assertDoesNotNeedCleanup(c, s.State)
  1064  }
  1065  
  1066  func (s *ModelSuite) TestDestroyModelReleaseStorageUnreleasable(c *gc.C) {
  1067  	s.assertDestroyModelReleaseStorageUnreleasable(c, nil)
  1068  }
  1069  
  1070  func (s *ModelSuite) TestDestroyModelReleaseStorageUnreleasableWithForce(c *gc.C) {
  1071  	force := true
  1072  	s.assertDestroyModelReleaseStorageUnreleasable(c, &force)
  1073  }
  1074  
  1075  func (s *ModelSuite) TestDestroyModelAddApplicationConcurrently(c *gc.C) {
  1076  	st := s.Factory.MakeModel(c, nil)
  1077  	defer st.Close()
  1078  	m, err := st.Model()
  1079  	c.Assert(err, jc.ErrorIsNil)
  1080  
  1081  	defer state.SetBeforeHooks(c, st, func() {
  1082  		factory.NewFactory(st, s.StatePool).MakeApplication(c, nil)
  1083  	}).Check()
  1084  
  1085  	c.Assert(m.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
  1086  	c.Assert(m.Refresh(), jc.ErrorIsNil)
  1087  	c.Assert(m.Life(), gc.Equals, state.Dying)
  1088  }
  1089  
  1090  func (s *ModelSuite) TestDestroyModelAddMachineConcurrently(c *gc.C) {
  1091  	st := s.Factory.MakeModel(c, nil)
  1092  	defer st.Close()
  1093  	m, err := st.Model()
  1094  	c.Assert(err, jc.ErrorIsNil)
  1095  
  1096  	defer state.SetBeforeHooks(c, st, func() {
  1097  		factory.NewFactory(st, s.StatePool).MakeMachine(c, nil)
  1098  	}).Check()
  1099  
  1100  	c.Assert(m.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
  1101  	c.Assert(m.Refresh(), jc.ErrorIsNil)
  1102  	c.Assert(m.Life(), gc.Equals, state.Dying)
  1103  }
  1104  
  1105  func (s *ModelSuite) TestDestroyModelEmpty(c *gc.C) {
  1106  	st := s.Factory.MakeModel(c, nil)
  1107  	defer st.Close()
  1108  	m, err := st.Model()
  1109  	c.Assert(err, jc.ErrorIsNil)
  1110  
  1111  	c.Assert(m.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
  1112  	c.Assert(m.Refresh(), jc.ErrorIsNil)
  1113  	c.Assert(m.Life(), gc.Equals, state.Dying)
  1114  	c.Assert(st.RemoveDyingModel(), jc.ErrorIsNil)
  1115  	c.Assert(m.Refresh(), jc.Satisfies, errors.IsNotFound)
  1116  }
  1117  
  1118  func (s *ModelSuite) TestDestroyModelWithApplicationOffers(c *gc.C) {
  1119  	m, err := s.State.Model()
  1120  	c.Assert(err, jc.ErrorIsNil)
  1121  
  1122  	app := s.AddTestingApplication(c, "mysql", s.AddTestingCharm(c, "mysql"))
  1123  
  1124  	ao := state.NewApplicationOffers(s.State)
  1125  	offer, err := ao.AddOffer(crossmodel.AddApplicationOfferArgs{
  1126  		OfferName:       "hosted-mysql",
  1127  		ApplicationName: "mysql",
  1128  		Endpoints:       map[string]string{"server": "server"},
  1129  		Owner:           s.Owner.Id(),
  1130  	})
  1131  	c.Assert(err, jc.ErrorIsNil)
  1132  
  1133  	err = m.Destroy(state.DestroyModelParams{})
  1134  	c.Assert(err, jc.ErrorIsNil)
  1135  	c.Assert(m.Refresh(), jc.ErrorIsNil)
  1136  	c.Assert(m.Life(), gc.Equals, state.Dying)
  1137  
  1138  	// Run the cleanups, check that the application and offer are
  1139  	// both removed.
  1140  	assertCleanupCount(c, s.State, 2)
  1141  
  1142  	_, err = ao.ApplicationOffer(offer.OfferName)
  1143  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1144  	err = app.Refresh()
  1145  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1146  }
  1147  
  1148  func (s *ModelSuite) TestForceDestroySetsForceDestroyed(c *gc.C) {
  1149  	st := s.Factory.MakeModel(c, nil)
  1150  	defer st.Close()
  1151  
  1152  	model, err := st.Model()
  1153  	c.Assert(err, jc.ErrorIsNil)
  1154  
  1155  	c.Assert(model.ForceDestroyed(), gc.Equals, false)
  1156  
  1157  	force := true
  1158  	err = model.Destroy(state.DestroyModelParams{
  1159  		Force: &force,
  1160  	})
  1161  	c.Assert(err, jc.ErrorIsNil)
  1162  
  1163  	err = model.Refresh()
  1164  	c.Assert(err, jc.ErrorIsNil)
  1165  
  1166  	c.Assert(model.Life(), gc.Equals, state.Dying)
  1167  	c.Assert(model.ForceDestroyed(), gc.Equals, true)
  1168  }
  1169  
  1170  func (s *ModelSuite) TestDestroyWithTimeoutSetsTimeout(c *gc.C) {
  1171  	st := s.Factory.MakeModel(c, nil)
  1172  	defer st.Close()
  1173  
  1174  	model, err := st.Model()
  1175  	c.Assert(err, jc.ErrorIsNil)
  1176  
  1177  	c.Assert(model.DestroyTimeout(), gc.IsNil)
  1178  
  1179  	timeout := time.Minute
  1180  	err = model.Destroy(state.DestroyModelParams{
  1181  		Timeout: &timeout,
  1182  	})
  1183  	c.Assert(err, jc.ErrorIsNil)
  1184  
  1185  	err = model.Refresh()
  1186  	c.Assert(err, jc.ErrorIsNil)
  1187  
  1188  	c.Assert(model.Life(), gc.Equals, state.Dying)
  1189  	got := model.DestroyTimeout()
  1190  	c.Assert(got, gc.NotNil)
  1191  	c.Assert(*got, gc.Equals, time.Minute)
  1192  }
  1193  
  1194  func (s *ModelSuite) TestNonForceDestroy(c *gc.C) {
  1195  	st := s.Factory.MakeModel(c, nil)
  1196  	defer st.Close()
  1197  	model, err := st.Model()
  1198  	c.Assert(err, jc.ErrorIsNil)
  1199  
  1200  	noForce := false
  1201  	err = model.Destroy(state.DestroyModelParams{
  1202  		Force: &noForce,
  1203  	})
  1204  	c.Assert(err, jc.ErrorIsNil)
  1205  
  1206  	err = model.Refresh()
  1207  	c.Assert(err, jc.ErrorIsNil)
  1208  
  1209  	c.Assert(model.Life(), gc.Equals, state.Dying)
  1210  	c.Assert(model.ForceDestroyed(), gc.Equals, false)
  1211  }
  1212  
  1213  func (s *ModelSuite) TestProcessDyingServerModelTransitionDyingToDead(c *gc.C) {
  1214  	s.assertDyingModelTransitionDyingToDead(c, s.State)
  1215  }
  1216  
  1217  func (s *ModelSuite) TestProcessDyingHostedModelTransitionDyingToDead(c *gc.C) {
  1218  	st := s.Factory.MakeModel(c, nil)
  1219  	defer st.Close()
  1220  	s.assertDyingModelTransitionDyingToDead(c, st)
  1221  }
  1222  
  1223  func (s *ModelSuite) assertDyingModelTransitionDyingToDead(c *gc.C, st *state.State) {
  1224  	// Add a application to prevent the model from transitioning directly to Dead.
  1225  	// Add the application before getting the Model, otherwise we'll have to run
  1226  	// the transaction twice, and hit the hook point too early.
  1227  	app := factory.NewFactory(st, s.StatePool).MakeApplication(c, nil)
  1228  	model, err := st.Model()
  1229  	c.Assert(err, jc.ErrorIsNil)
  1230  
  1231  	// ProcessDyingModel is called by a worker after Destroy is called. To
  1232  	// avoid a race, we jump the gun here and test immediately after the
  1233  	// environement was set to dead.
  1234  	defer state.SetAfterHooks(c, st, func() {
  1235  		c.Assert(model.Refresh(), jc.ErrorIsNil)
  1236  		c.Assert(model.Life(), gc.Equals, state.Dying)
  1237  
  1238  		err := app.Destroy()
  1239  		c.Assert(err, jc.ErrorIsNil)
  1240  
  1241  		c.Check(model.UniqueIndexExists(), jc.IsTrue)
  1242  		c.Assert(st.ProcessDyingModel(), jc.ErrorIsNil)
  1243  		c.Assert(st.RemoveDyingModel(), jc.ErrorIsNil)
  1244  
  1245  		c.Assert(model.Refresh(), jc.Satisfies, errors.IsNotFound)
  1246  		c.Check(model.UniqueIndexExists(), jc.IsFalse)
  1247  	}).Check()
  1248  
  1249  	c.Assert(model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
  1250  }
  1251  
  1252  func (s *ModelSuite) TestProcessDyingModelWithMachinesAndApplicationsNoOp(c *gc.C) {
  1253  	st := s.Factory.MakeModel(c, nil)
  1254  	defer st.Close()
  1255  
  1256  	// calling ProcessDyingModel on a live environ should fail.
  1257  	err := st.ProcessDyingModel()
  1258  	c.Assert(err, gc.ErrorMatches, "model is not dying")
  1259  
  1260  	// add some machines and applications
  1261  	model, err := st.Model()
  1262  	c.Assert(err, jc.ErrorIsNil)
  1263  	_, err = st.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1264  	c.Assert(err, jc.ErrorIsNil)
  1265  	application := s.Factory.MakeApplication(c, nil)
  1266  
  1267  	ch := state.AddTestingCharm(c, st, "dummy")
  1268  	args := state.AddApplicationArgs{
  1269  		Name:  application.Name(),
  1270  		Charm: ch,
  1271  		CharmOrigin: &state.CharmOrigin{Platform: &state.Platform{
  1272  			OS:      "ubuntu",
  1273  			Channel: "12.10/stable",
  1274  		}},
  1275  	}
  1276  	_, err = st.AddApplication(args)
  1277  	c.Assert(err, jc.ErrorIsNil)
  1278  
  1279  	assertModel := func(life state.Life, expectedMachines, expectedApplications int) {
  1280  		c.Assert(model.Refresh(), jc.ErrorIsNil)
  1281  		c.Assert(model.Life(), gc.Equals, life)
  1282  
  1283  		machines, err := st.AllMachines()
  1284  		c.Assert(err, jc.ErrorIsNil)
  1285  		c.Assert(machines, gc.HasLen, expectedMachines)
  1286  
  1287  		applications, err := st.AllApplications()
  1288  		c.Assert(err, jc.ErrorIsNil)
  1289  		c.Assert(applications, gc.HasLen, expectedApplications)
  1290  	}
  1291  
  1292  	// Simulate processing a dying model after an model is set to
  1293  	// dying, but before the cleanup has removed machines and applications.
  1294  	defer state.SetAfterHooks(c, st, func() {
  1295  		assertModel(state.Dying, 1, 1)
  1296  		err := st.ProcessDyingModel()
  1297  		c.Assert(errors.Is(err, stateerrors.ModelNotEmptyError), jc.IsTrue)
  1298  		c.Assert(err, gc.ErrorMatches, `model not empty, found 1 machine, 1 application`)
  1299  	}).Check()
  1300  
  1301  	c.Assert(model.Refresh(), jc.ErrorIsNil)
  1302  	c.Assert(model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
  1303  }
  1304  
  1305  func (s *ModelSuite) TestProcessDyingModelWithVolumeBackedFilesystems(c *gc.C) {
  1306  	st := s.Factory.MakeModel(c, nil)
  1307  	defer st.Close()
  1308  
  1309  	model, err := st.Model()
  1310  	c.Assert(err, jc.ErrorIsNil)
  1311  
  1312  	machine, err := st.AddOneMachine(state.MachineTemplate{
  1313  		Base: state.UbuntuBase("12.10"),
  1314  		Jobs: []state.MachineJob{state.JobHostUnits},
  1315  		Filesystems: []state.HostFilesystemParams{{
  1316  			Filesystem: state.FilesystemParams{
  1317  				Pool: "modelscoped-block",
  1318  				Size: 123,
  1319  			},
  1320  		}},
  1321  	})
  1322  	c.Assert(err, jc.ErrorIsNil)
  1323  
  1324  	sb, err := state.NewStorageBackend(st)
  1325  	c.Assert(err, jc.ErrorIsNil)
  1326  	filesystems, err := sb.AllFilesystems()
  1327  	c.Assert(err, jc.ErrorIsNil)
  1328  	c.Assert(filesystems, gc.HasLen, 1)
  1329  
  1330  	err = model.Destroy(state.DestroyModelParams{})
  1331  	c.Assert(errors.Is(err, stateerrors.PersistentStorageError), jc.IsTrue)
  1332  
  1333  	destroyStorage := true
  1334  	c.Assert(model.Destroy(state.DestroyModelParams{
  1335  		DestroyStorage: &destroyStorage,
  1336  	}), jc.ErrorIsNil)
  1337  
  1338  	err = sb.DetachFilesystem(machine.MachineTag(), names.NewFilesystemTag("0"))
  1339  	c.Assert(err, jc.ErrorIsNil)
  1340  	err = sb.RemoveFilesystemAttachment(machine.MachineTag(), names.NewFilesystemTag("0"), false)
  1341  	c.Assert(err, jc.ErrorIsNil)
  1342  	err = sb.DetachVolume(machine.MachineTag(), names.NewVolumeTag("0"), false)
  1343  	c.Assert(err, jc.ErrorIsNil)
  1344  	err = sb.RemoveVolumeAttachment(machine.MachineTag(), names.NewVolumeTag("0"), false)
  1345  	c.Assert(err, jc.ErrorIsNil)
  1346  	c.Assert(machine.EnsureDead(), jc.ErrorIsNil)
  1347  	c.Assert(machine.Remove(), jc.ErrorIsNil)
  1348  
  1349  	// The filesystem will be gone, but the volume is persistent and should
  1350  	// not have been removed.
  1351  	err = st.ProcessDyingModel()
  1352  	c.Assert(errors.Is(err, stateerrors.ModelNotEmptyError), jc.IsTrue)
  1353  	c.Assert(err, gc.ErrorMatches, `model not empty, found 1 volume, 1 filesystem`)
  1354  }
  1355  
  1356  func (s *ModelSuite) TestProcessDyingModelWithVolumes(c *gc.C) {
  1357  	st := s.Factory.MakeModel(c, nil)
  1358  	defer st.Close()
  1359  
  1360  	model, err := st.Model()
  1361  	c.Assert(err, jc.ErrorIsNil)
  1362  
  1363  	machine, err := st.AddOneMachine(state.MachineTemplate{
  1364  		Base: state.UbuntuBase("12.10"),
  1365  		Jobs: []state.MachineJob{state.JobHostUnits},
  1366  		Volumes: []state.HostVolumeParams{{
  1367  			Volume: state.VolumeParams{
  1368  				Pool: "modelscoped",
  1369  				Size: 123,
  1370  			},
  1371  		}},
  1372  	})
  1373  	c.Assert(err, jc.ErrorIsNil)
  1374  
  1375  	sb, err := state.NewStorageBackend(st)
  1376  	c.Assert(err, jc.ErrorIsNil)
  1377  	volumes, err := sb.AllVolumes()
  1378  	c.Assert(err, jc.ErrorIsNil)
  1379  	c.Assert(volumes, gc.HasLen, 1)
  1380  	volumeTag := volumes[0].VolumeTag()
  1381  
  1382  	err = model.Destroy(state.DestroyModelParams{})
  1383  	c.Assert(errors.Is(err, stateerrors.PersistentStorageError), jc.IsTrue)
  1384  
  1385  	destroyStorage := true
  1386  	c.Assert(model.Destroy(state.DestroyModelParams{
  1387  		DestroyStorage: &destroyStorage,
  1388  	}), jc.ErrorIsNil)
  1389  
  1390  	err = sb.DetachVolume(machine.MachineTag(), volumeTag, false)
  1391  	c.Assert(err, jc.ErrorIsNil)
  1392  	err = sb.RemoveVolumeAttachment(machine.MachineTag(), volumeTag, false)
  1393  	c.Assert(err, jc.ErrorIsNil)
  1394  	c.Assert(machine.EnsureDead(), jc.ErrorIsNil)
  1395  	c.Assert(machine.Remove(), jc.ErrorIsNil)
  1396  
  1397  	// The volume is persistent and should not have been removed along with
  1398  	// the machine it was attached to.
  1399  	err = st.ProcessDyingModel()
  1400  	c.Assert(errors.Is(err, stateerrors.ModelNotEmptyError), jc.IsTrue)
  1401  	c.Assert(err, gc.ErrorMatches, `model not empty, found 1 volume`)
  1402  }
  1403  
  1404  func (s *ModelSuite) TestProcessDyingControllerModelWithHostedModelsNoOp(c *gc.C) {
  1405  	// Add a non-empty model to the controller.
  1406  	st := s.Factory.MakeModel(c, nil)
  1407  	defer st.Close()
  1408  	factory.NewFactory(st, s.StatePool).MakeApplication(c, nil)
  1409  
  1410  	controllerModel, err := s.State.Model()
  1411  	c.Assert(err, jc.ErrorIsNil)
  1412  	c.Assert(controllerModel.Destroy(state.DestroyModelParams{
  1413  		DestroyHostedModels: true,
  1414  	}), jc.ErrorIsNil)
  1415  
  1416  	err = s.State.ProcessDyingModel()
  1417  	c.Assert(errors.Is(err, stateerrors.HasHostedModelsError), jc.IsTrue)
  1418  	c.Assert(err, gc.ErrorMatches, `hosting 1 other model`)
  1419  
  1420  	c.Assert(controllerModel.Refresh(), jc.ErrorIsNil)
  1421  	c.Assert(controllerModel.Life(), gc.Equals, state.Dying)
  1422  }
  1423  
  1424  func (s *ModelSuite) TestListModelUsers(c *gc.C) {
  1425  	model, err := s.State.Model()
  1426  	c.Assert(err, jc.ErrorIsNil)
  1427  
  1428  	expected := s.addModelUsers(c, s.State)
  1429  	obtained, err := model.Users()
  1430  	c.Assert(err, gc.IsNil)
  1431  
  1432  	assertObtainedUsersMatchExpectedUsers(c, obtained, expected)
  1433  }
  1434  
  1435  func (s *ModelSuite) TestListUsersIgnoredDeletedUsers(c *gc.C) {
  1436  	model, err := s.State.Model()
  1437  	c.Assert(err, jc.ErrorIsNil)
  1438  
  1439  	expectedUsers := s.addModelUsers(c, s.State)
  1440  
  1441  	obtainedUsers, err := model.Users()
  1442  	c.Assert(err, jc.ErrorIsNil)
  1443  	assertObtainedUsersMatchExpectedUsers(c, obtainedUsers, expectedUsers)
  1444  
  1445  	lastUser := obtainedUsers[len(obtainedUsers)-1]
  1446  	err = s.State.RemoveUser(lastUser.UserTag)
  1447  	c.Assert(err, jc.ErrorIsNil)
  1448  	expectedAfterDeletion := obtainedUsers[:len(obtainedUsers)-1]
  1449  
  1450  	obtainedUsers, err = model.Users()
  1451  	c.Assert(err, jc.ErrorIsNil)
  1452  	assertObtainedUsersMatchExpectedUsers(c, obtainedUsers, expectedAfterDeletion)
  1453  }
  1454  
  1455  func (s *ModelSuite) TestListUsersTwoModels(c *gc.C) {
  1456  	model, err := s.State.Model()
  1457  	c.Assert(err, jc.ErrorIsNil)
  1458  
  1459  	otherModelState := s.Factory.MakeModel(c, nil)
  1460  	defer otherModelState.Close()
  1461  	otherModel, err := otherModelState.Model()
  1462  	c.Assert(err, jc.ErrorIsNil)
  1463  
  1464  	// Add users to both models
  1465  	expectedUsers := s.addModelUsers(c, s.State)
  1466  	expectedUsersOtherModel := s.addModelUsers(c, otherModelState)
  1467  
  1468  	// test that only the expected users are listed for each model
  1469  	obtainedUsers, err := model.Users()
  1470  	c.Assert(err, jc.ErrorIsNil)
  1471  	assertObtainedUsersMatchExpectedUsers(c, obtainedUsers, expectedUsers)
  1472  
  1473  	obtainedUsersOtherModel, err := otherModel.Users()
  1474  	c.Assert(err, jc.ErrorIsNil)
  1475  	assertObtainedUsersMatchExpectedUsers(c, obtainedUsersOtherModel, expectedUsersOtherModel)
  1476  
  1477  	// It doesn't matter how you obtain the Model.
  1478  	otherModel2, ph, err := s.StatePool.GetModel(otherModel.UUID())
  1479  	c.Assert(err, jc.ErrorIsNil)
  1480  	defer ph.Release()
  1481  	obtainedUsersOtherModel2, err := otherModel2.Users()
  1482  	c.Assert(err, jc.ErrorIsNil)
  1483  	assertObtainedUsersMatchExpectedUsers(c, obtainedUsersOtherModel2, expectedUsersOtherModel)
  1484  }
  1485  
  1486  func (s *ModelSuite) addModelUsers(c *gc.C, st *state.State) (expected []permission.UserAccess) {
  1487  	// get the model owner
  1488  	testAdmin := names.NewUserTag("test-admin")
  1489  	m, err := st.Model()
  1490  	c.Assert(err, jc.ErrorIsNil)
  1491  	owner, err := st.UserAccess(testAdmin, m.ModelTag())
  1492  	c.Assert(err, jc.ErrorIsNil)
  1493  
  1494  	f := factory.NewFactory(st, s.StatePool)
  1495  	return []permission.UserAccess{
  1496  		// we expect the owner to be an existing model user
  1497  		owner,
  1498  		// add new users to the model
  1499  		f.MakeModelUser(c, nil),
  1500  		f.MakeModelUser(c, nil),
  1501  		f.MakeModelUser(c, nil),
  1502  	}
  1503  }
  1504  
  1505  func assertObtainedUsersMatchExpectedUsers(c *gc.C, obtainedUsers, expectedUsers []permission.UserAccess) {
  1506  	c.Assert(len(obtainedUsers), gc.Equals, len(expectedUsers))
  1507  	expectedByUser := make(map[string]permission.UserAccess, len(expectedUsers))
  1508  	for _, access := range expectedUsers {
  1509  		expectedByUser[access.UserName] = access
  1510  	}
  1511  	for _, obtained := range obtainedUsers {
  1512  		expect := expectedByUser[obtained.UserName]
  1513  		// We shouldn't get the same entry again
  1514  		delete(expectedByUser, obtained.UserName)
  1515  		c.Check(obtained.Object.Id(), gc.Equals, expect.Object.Id())
  1516  		c.Check(obtained.UserTag, gc.Equals, expect.UserTag)
  1517  		c.Check(obtained.DisplayName, gc.Equals, expect.DisplayName)
  1518  		c.Check(obtained.CreatedBy, gc.Equals, expect.CreatedBy)
  1519  	}
  1520  	c.Check(expectedByUser, jc.DeepEquals, map[string]permission.UserAccess{})
  1521  }
  1522  
  1523  func (s *ModelSuite) TestAllModelUUIDs(c *gc.C) {
  1524  	st1 := s.Factory.MakeModel(c, nil)
  1525  	defer st1.Close()
  1526  
  1527  	st2 := s.Factory.MakeModel(c, nil)
  1528  	defer st2.Close()
  1529  
  1530  	obtained, err := s.State.AllModelUUIDs()
  1531  	c.Assert(err, jc.ErrorIsNil)
  1532  	expected := []string{
  1533  		s.State.ModelUUID(),
  1534  		st1.ModelUUID(),
  1535  		st2.ModelUUID(),
  1536  	}
  1537  	c.Assert(obtained, jc.DeepEquals, expected)
  1538  }
  1539  
  1540  func (s *ModelSuite) TestAllModelUUIDsExcludesDead(c *gc.C) {
  1541  	expected := []string{
  1542  		s.State.ModelUUID(),
  1543  	}
  1544  
  1545  	st1 := s.Factory.MakeModel(c, nil)
  1546  	defer st1.Close()
  1547  
  1548  	m1, err := st1.Model()
  1549  	c.Assert(err, jc.ErrorIsNil)
  1550  	expectedWithAddition := append(expected, m1.UUID())
  1551  	obtained, err := s.State.AllModelUUIDs()
  1552  	c.Assert(err, jc.ErrorIsNil)
  1553  	c.Assert(obtained, jc.DeepEquals, expectedWithAddition)
  1554  
  1555  	err = m1.SetDead()
  1556  	c.Assert(err, jc.ErrorIsNil)
  1557  
  1558  	obtained, err = s.State.AllModelUUIDs()
  1559  	c.Assert(err, jc.ErrorIsNil)
  1560  	c.Assert(obtained, jc.DeepEquals, expected)
  1561  
  1562  	obtained, err = s.State.AllModelUUIDsIncludingDead()
  1563  	c.Assert(err, jc.ErrorIsNil)
  1564  	c.Assert(obtained, jc.DeepEquals, expectedWithAddition)
  1565  }
  1566  
  1567  func (s *ModelSuite) TestHostedModelCount(c *gc.C) {
  1568  	c.Assert(state.HostedModelCount(c, s.State), gc.Equals, 0)
  1569  
  1570  	st1 := s.Factory.MakeModel(c, nil)
  1571  	defer st1.Close()
  1572  	c.Assert(state.HostedModelCount(c, s.State), gc.Equals, 1)
  1573  
  1574  	st2 := s.Factory.MakeModel(c, nil)
  1575  	defer st2.Close()
  1576  	c.Assert(state.HostedModelCount(c, s.State), gc.Equals, 2)
  1577  
  1578  	model1, err := st1.Model()
  1579  	c.Assert(err, jc.ErrorIsNil)
  1580  	c.Assert(model1.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
  1581  	c.Assert(st1.RemoveDyingModel(), jc.ErrorIsNil)
  1582  	c.Assert(state.HostedModelCount(c, s.State), gc.Equals, 1)
  1583  
  1584  	model2, err := st2.Model()
  1585  	c.Assert(err, jc.ErrorIsNil)
  1586  	c.Assert(model2.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
  1587  	c.Assert(st2.RemoveDyingModel(), jc.ErrorIsNil)
  1588  	c.Assert(state.HostedModelCount(c, s.State), gc.Equals, 0)
  1589  }
  1590  
  1591  func (s *ModelSuite) TestNewModelEnvironVersion(c *gc.C) {
  1592  	v := 123
  1593  	st := s.Factory.MakeModel(c, &factory.ModelParams{
  1594  		EnvironVersion: v,
  1595  	})
  1596  	defer st.Close()
  1597  
  1598  	m, err := st.Model()
  1599  	c.Assert(err, jc.ErrorIsNil)
  1600  	c.Assert(m.EnvironVersion(), gc.Equals, v)
  1601  }
  1602  
  1603  func (s *ModelSuite) TestSetEnvironVersion(c *gc.C) {
  1604  	v := 123
  1605  	m, err := s.State.Model()
  1606  	c.Assert(err, jc.ErrorIsNil)
  1607  
  1608  	defer state.SetBeforeHooks(c, s.State, func() {
  1609  		m, err := s.State.Model()
  1610  		c.Assert(err, jc.ErrorIsNil)
  1611  		c.Assert(m.EnvironVersion(), gc.Equals, 0)
  1612  		err = m.SetEnvironVersion(v)
  1613  		c.Assert(err, jc.ErrorIsNil)
  1614  		c.Assert(m.EnvironVersion(), gc.Equals, v)
  1615  	}).Check()
  1616  
  1617  	err = m.SetEnvironVersion(v)
  1618  	c.Assert(err, jc.ErrorIsNil)
  1619  	c.Assert(m.EnvironVersion(), gc.Equals, v)
  1620  }
  1621  
  1622  func (s *ModelSuite) TestSetEnvironVersionCannotDecrease(c *gc.C) {
  1623  	m, err := s.State.Model()
  1624  	c.Assert(err, jc.ErrorIsNil)
  1625  
  1626  	defer state.SetBeforeHooks(c, s.State, func() {
  1627  		m, err := s.State.Model()
  1628  		c.Assert(err, jc.ErrorIsNil)
  1629  		err = m.SetEnvironVersion(2)
  1630  		c.Assert(err, jc.ErrorIsNil)
  1631  		c.Assert(m.EnvironVersion(), gc.Equals, 2)
  1632  	}).Check()
  1633  
  1634  	err = m.SetEnvironVersion(1)
  1635  	c.Assert(err, gc.ErrorMatches, `cannot set environ version to 1, which is less than the current version 2`)
  1636  	// m's cached version is only updated on success
  1637  	c.Assert(m.EnvironVersion(), gc.Equals, 0)
  1638  
  1639  	err = m.Refresh()
  1640  	c.Assert(err, jc.ErrorIsNil)
  1641  	c.Assert(m.EnvironVersion(), gc.Equals, 2)
  1642  }
  1643  
  1644  func (s *ModelSuite) TestDestroyForceWorksWhenRemoteRelationScopesAreStuck(c *gc.C) {
  1645  	mysqlEps := []charm.Relation{
  1646  		{
  1647  			Interface: "mysql",
  1648  			Name:      "db",
  1649  			Role:      charm.RoleProvider,
  1650  			Scope:     charm.ScopeGlobal,
  1651  		},
  1652  	}
  1653  	ms := s.Factory.MakeModel(c, nil)
  1654  	defer ms.Close()
  1655  	remoteApp, err := ms.AddRemoteApplication(state.AddRemoteApplicationParams{
  1656  		Name:        "mysql",
  1657  		SourceModel: s.Model.ModelTag(),
  1658  		Token:       "t0",
  1659  		Endpoints:   mysqlEps,
  1660  	})
  1661  	c.Assert(err, jc.ErrorIsNil)
  1662  
  1663  	wordpress := state.AddTestingApplication(c, ms, "wordpress", state.AddTestingCharm(c, ms, "wordpress"))
  1664  	eps, err := ms.InferEndpoints("wordpress", "mysql")
  1665  	c.Assert(err, jc.ErrorIsNil)
  1666  	rel, err := ms.AddRelation(eps...)
  1667  	c.Assert(err, jc.ErrorIsNil)
  1668  
  1669  	unit, err := wordpress.AddUnit(state.AddUnitParams{})
  1670  	c.Assert(err, jc.ErrorIsNil)
  1671  	f := factory.NewFactory(ms, s.StatePool)
  1672  	machine := f.MakeMachine(c, nil)
  1673  	err = unit.AssignToMachine(machine)
  1674  	c.Assert(err, jc.ErrorIsNil)
  1675  	localRelUnit, err := rel.Unit(unit)
  1676  	c.Assert(err, jc.ErrorIsNil)
  1677  	err = localRelUnit.EnterScope(nil)
  1678  	c.Assert(err, jc.ErrorIsNil)
  1679  
  1680  	remoteRelUnit, err := rel.RemoteUnit("mysql/0")
  1681  	c.Assert(err, jc.ErrorIsNil)
  1682  	err = remoteRelUnit.EnterScope(nil)
  1683  	c.Assert(err, jc.ErrorIsNil)
  1684  
  1685  	// Refetch the remoteapp to ensure that its relationcount is
  1686  	// current. Otherwise it just silently fails? (See errRefresh
  1687  	// handling in DestroyRemoteApplicationOperation.Build)
  1688  	err = remoteApp.Refresh()
  1689  	c.Assert(err, jc.ErrorIsNil)
  1690  	err = remoteApp.Destroy()
  1691  	c.Assert(err, jc.ErrorIsNil)
  1692  	assertLife(c, remoteApp, state.Dying)
  1693  
  1694  	err = wordpress.Destroy()
  1695  	c.Assert(err, jc.ErrorIsNil)
  1696  
  1697  	err = localRelUnit.LeaveScope()
  1698  	c.Assert(err, jc.ErrorIsNil)
  1699  	err = unit.EnsureDead()
  1700  	c.Assert(err, jc.ErrorIsNil)
  1701  	err = unit.Remove()
  1702  	c.Assert(err, jc.ErrorIsNil)
  1703  
  1704  	// Cleanups
  1705  	assertCleanupCount(c, ms, 1)
  1706  
  1707  	// wordpress is kept around because the relation can't be removed.
  1708  	assertLife(c, wordpress, state.Dying)
  1709  
  1710  	// Force-destroying the model cleans them up.
  1711  	model, err := ms.Model()
  1712  	c.Assert(err, jc.ErrorIsNil)
  1713  	force := true
  1714  	err = model.Destroy(state.DestroyModelParams{
  1715  		Force: &force,
  1716  	})
  1717  	c.Assert(err, jc.ErrorIsNil)
  1718  
  1719  	assertCleanupCount(c, ms, 4)
  1720  	assertRemoved(c, wordpress)
  1721  	c.Assert(model.Refresh(), jc.ErrorIsNil)
  1722  	c.Assert(model.Life(), gc.Equals, state.Dying)
  1723  	c.Assert(ms.ProcessDyingModel(), jc.ErrorIsNil)
  1724  	c.Assert(ms.RemoveDyingModel(), jc.ErrorIsNil)
  1725  }
  1726  
  1727  type ModelCloudValidationSuite struct {
  1728  	mgotesting.MgoSuite
  1729  }
  1730  
  1731  var _ = gc.Suite(&ModelCloudValidationSuite{})
  1732  
  1733  // TODO(axw) concurrency tests when we can modify the cloud definition,
  1734  // and update/remove credentials.
  1735  
  1736  func (s *ModelCloudValidationSuite) TestNewModelDifferentCloud(c *gc.C) {
  1737  	controller, owner := s.initializeState(c, []cloud.Region{{Name: "some-region"}}, []cloud.AuthType{cloud.EmptyAuthType}, nil)
  1738  	defer controller.Close()
  1739  	st, err := controller.SystemState()
  1740  	c.Assert(err, jc.ErrorIsNil)
  1741  	aCloud := cloud.Cloud{
  1742  		Name:      "another",
  1743  		Type:      "dummy",
  1744  		AuthTypes: cloud.AuthTypes{"empty", "userpass"},
  1745  	}
  1746  	err = st.AddCloud(aCloud, owner.Name())
  1747  	c.Assert(err, jc.ErrorIsNil)
  1748  	cfg, _ := createTestModelConfig(c, st.ModelUUID())
  1749  	cfg, err = cfg.Apply(map[string]interface{}{"name": "whatever"})
  1750  	c.Assert(err, jc.ErrorIsNil)
  1751  	m, newSt, err := controller.NewModel(state.ModelArgs{
  1752  		Type:                    state.ModelTypeIAAS,
  1753  		CloudName:               "another",
  1754  		Config:                  cfg,
  1755  		Owner:                   owner,
  1756  		StorageProviderRegistry: storage.StaticProviderRegistry{},
  1757  	})
  1758  	c.Assert(err, jc.ErrorIsNil)
  1759  	defer newSt.Close()
  1760  	c.Assert(m.CloudName(), gc.Equals, "another")
  1761  	cloudValue, err := m.Cloud()
  1762  	c.Assert(err, jc.ErrorIsNil)
  1763  	c.Assert(cloudValue, jc.DeepEquals, aCloud)
  1764  }
  1765  
  1766  func (s *ModelCloudValidationSuite) TestNewModelUnknownCloudRegion(c *gc.C) {
  1767  	controller, owner := s.initializeState(c, []cloud.Region{{Name: "some-region"}}, []cloud.AuthType{cloud.EmptyAuthType}, nil)
  1768  	defer controller.Close()
  1769  	st, err := controller.SystemState()
  1770  	c.Assert(err, jc.ErrorIsNil)
  1771  	cfg, _ := createTestModelConfig(c, st.ModelUUID())
  1772  	_, _, err = controller.NewModel(state.ModelArgs{
  1773  		Type:                    state.ModelTypeIAAS,
  1774  		CloudName:               "dummy",
  1775  		CloudRegion:             "dummy-region",
  1776  		Config:                  cfg,
  1777  		Owner:                   owner,
  1778  		StorageProviderRegistry: storage.StaticProviderRegistry{},
  1779  	})
  1780  	c.Assert(err, gc.ErrorMatches, `region "dummy-region" not found \(expected one of \["some-region"\]\)`)
  1781  }
  1782  
  1783  func (s *ModelCloudValidationSuite) TestNewModelDefaultCloudRegion(c *gc.C) {
  1784  	controller, owner := s.initializeState(c, []cloud.Region{{Name: "dummy-region"}}, []cloud.AuthType{cloud.EmptyAuthType}, nil)
  1785  	defer controller.Close()
  1786  	st, err := controller.SystemState()
  1787  	c.Assert(err, jc.ErrorIsNil)
  1788  	cfg, _ := createTestModelConfig(c, st.ModelUUID())
  1789  	cfg, err = cfg.Apply(map[string]interface{}{"name": "whatever"})
  1790  	c.Assert(err, jc.ErrorIsNil)
  1791  	m, newSt, err := controller.NewModel(state.ModelArgs{
  1792  		Type:                    state.ModelTypeIAAS,
  1793  		CloudName:               "dummy",
  1794  		Config:                  cfg,
  1795  		Owner:                   owner,
  1796  		StorageProviderRegistry: storage.StaticProviderRegistry{},
  1797  	})
  1798  	c.Assert(err, jc.ErrorIsNil)
  1799  	defer newSt.Close()
  1800  	c.Assert(m.CloudRegion(), gc.Equals, "dummy-region")
  1801  }
  1802  
  1803  func (s *ModelCloudValidationSuite) TestNewModelMissingCloudRegion(c *gc.C) {
  1804  	controller, owner := s.initializeState(c, []cloud.Region{{Name: "dummy-region"}, {Name: "dummy-region2"}}, []cloud.AuthType{cloud.EmptyAuthType}, nil)
  1805  	defer controller.Close()
  1806  	st, err := controller.SystemState()
  1807  	c.Assert(err, jc.ErrorIsNil)
  1808  	cfg, _ := createTestModelConfig(c, st.ModelUUID())
  1809  	_, _, err = controller.NewModel(state.ModelArgs{
  1810  		Type:                    state.ModelTypeIAAS,
  1811  		CloudName:               "dummy",
  1812  		Config:                  cfg,
  1813  		Owner:                   owner,
  1814  		StorageProviderRegistry: storage.StaticProviderRegistry{},
  1815  	})
  1816  	c.Assert(err, gc.ErrorMatches, "missing cloud region not valid")
  1817  }
  1818  
  1819  func (s *ModelCloudValidationSuite) TestNewModelUnknownCloudCredential(c *gc.C) {
  1820  	regions := []cloud.Region{{Name: "dummy-region"}}
  1821  	controllerCredentialTag := names.NewCloudCredentialTag("dummy/test@remote/controller-credential")
  1822  	controller, owner := s.initializeState(
  1823  		c, regions, []cloud.AuthType{cloud.UserPassAuthType}, map[names.CloudCredentialTag]cloud.Credential{
  1824  			controllerCredentialTag: cloud.NewCredential(cloud.UserPassAuthType, nil),
  1825  		},
  1826  	)
  1827  	defer controller.Close()
  1828  	st, err := controller.SystemState()
  1829  	c.Assert(err, jc.ErrorIsNil)
  1830  	unknownCredentialTag := names.NewCloudCredentialTag("dummy/" + owner.Id() + "/unknown-credential")
  1831  	cfg, _ := createTestModelConfig(c, st.ModelUUID())
  1832  	_, _, err = controller.NewModel(state.ModelArgs{
  1833  		Type:                    state.ModelTypeIAAS,
  1834  		CloudName:               "dummy",
  1835  		CloudRegion:             "dummy-region",
  1836  		Config:                  cfg,
  1837  		Owner:                   owner,
  1838  		CloudCredential:         unknownCredentialTag,
  1839  		StorageProviderRegistry: storage.StaticProviderRegistry{},
  1840  	})
  1841  	c.Assert(err, gc.ErrorMatches, `credential "dummy/test@remote/unknown-credential" not found`)
  1842  }
  1843  
  1844  func (s *ModelCloudValidationSuite) TestNewModelMissingCloudCredential(c *gc.C) {
  1845  	regions := []cloud.Region{{Name: "dummy-region"}}
  1846  	controllerCredentialTag := names.NewCloudCredentialTag("dummy/test@remote/controller-credential")
  1847  	controller, owner := s.initializeState(
  1848  		c, regions, []cloud.AuthType{cloud.UserPassAuthType}, map[names.CloudCredentialTag]cloud.Credential{
  1849  			controllerCredentialTag: cloud.NewCredential(cloud.UserPassAuthType, nil),
  1850  		},
  1851  	)
  1852  	defer controller.Close()
  1853  	st, err := controller.SystemState()
  1854  	c.Assert(err, jc.ErrorIsNil)
  1855  	cfg, _ := createTestModelConfig(c, st.ModelUUID())
  1856  	_, _, err = controller.NewModel(state.ModelArgs{
  1857  		Type:                    state.ModelTypeIAAS,
  1858  		CloudName:               "dummy",
  1859  		CloudRegion:             "dummy-region",
  1860  		Config:                  cfg,
  1861  		Owner:                   owner,
  1862  		StorageProviderRegistry: storage.StaticProviderRegistry{},
  1863  	})
  1864  	c.Assert(err, gc.ErrorMatches, "missing CloudCredential not valid")
  1865  }
  1866  
  1867  func (s *ModelCloudValidationSuite) TestNewModelMissingCloudCredentialSupportsEmptyAuth(c *gc.C) {
  1868  	regions := []cloud.Region{
  1869  		{
  1870  			Name:             "dummy-region",
  1871  			Endpoint:         "dummy-endpoint",
  1872  			IdentityEndpoint: "dummy-identity-endpoint",
  1873  			StorageEndpoint:  "dummy-storage-endpoint",
  1874  		},
  1875  	}
  1876  	controller, owner := s.initializeState(c, regions, []cloud.AuthType{cloud.EmptyAuthType}, nil)
  1877  	defer controller.Close()
  1878  	st, err := controller.SystemState()
  1879  	c.Assert(err, jc.ErrorIsNil)
  1880  	cfg, _ := createTestModelConfig(c, st.ModelUUID())
  1881  	cfg, err = cfg.Apply(map[string]interface{}{"name": "whatever"})
  1882  	c.Assert(err, jc.ErrorIsNil)
  1883  	_, newSt, err := controller.NewModel(state.ModelArgs{
  1884  		Type:      state.ModelTypeIAAS,
  1885  		CloudName: "dummy", CloudRegion: "dummy-region", Config: cfg, Owner: owner,
  1886  		StorageProviderRegistry: storage.StaticProviderRegistry{},
  1887  	})
  1888  	c.Assert(err, jc.ErrorIsNil)
  1889  	newSt.Close()
  1890  }
  1891  
  1892  func (s *ModelCloudValidationSuite) TestNewModelOtherUserCloudCredential(c *gc.C) {
  1893  	controllerCredentialTag := names.NewCloudCredentialTag("dummy/test@remote/controller-credential")
  1894  	controller, _ := s.initializeState(
  1895  		c, nil, []cloud.AuthType{cloud.UserPassAuthType}, map[names.CloudCredentialTag]cloud.Credential{
  1896  			controllerCredentialTag: cloud.NewCredential(cloud.UserPassAuthType, nil),
  1897  		},
  1898  	)
  1899  	defer controller.Close()
  1900  	st, err := controller.SystemState()
  1901  	c.Assert(err, jc.ErrorIsNil)
  1902  	owner := factory.NewFactory(st, controller.StatePool()).MakeUser(c, nil).UserTag()
  1903  	cfg, _ := createTestModelConfig(c, st.ModelUUID())
  1904  	_, _, err = controller.NewModel(state.ModelArgs{
  1905  		Type:                    state.ModelTypeIAAS,
  1906  		CloudName:               "dummy",
  1907  		Config:                  cfg,
  1908  		Owner:                   owner,
  1909  		CloudCredential:         controllerCredentialTag,
  1910  		StorageProviderRegistry: storage.StaticProviderRegistry{},
  1911  	})
  1912  	c.Assert(err, gc.ErrorMatches, `credential "dummy/test@remote/controller-credential" not found`)
  1913  }
  1914  
  1915  func (s *ModelCloudValidationSuite) initializeState(
  1916  	c *gc.C,
  1917  	regions []cloud.Region,
  1918  	authTypes []cloud.AuthType,
  1919  	credentials map[names.CloudCredentialTag]cloud.Credential,
  1920  ) (*state.Controller, names.UserTag) {
  1921  	owner := names.NewUserTag("test@remote")
  1922  	cfg, _ := createTestModelConfig(c, "")
  1923  	var controllerRegion string
  1924  	var controllerCredential names.CloudCredentialTag
  1925  	if len(regions) > 0 {
  1926  		controllerRegion = regions[0].Name
  1927  	}
  1928  	if len(credentials) > 0 {
  1929  		// pick an arbitrary credential
  1930  		for controllerCredential = range credentials {
  1931  		}
  1932  	}
  1933  	controllerCfg := testing.FakeControllerConfig()
  1934  	controller, err := state.Initialize(state.InitializeParams{
  1935  		Clock:            clock.WallClock,
  1936  		ControllerConfig: controllerCfg,
  1937  		ControllerModelArgs: state.ModelArgs{
  1938  			Type:                    state.ModelTypeIAAS,
  1939  			Owner:                   owner,
  1940  			Config:                  cfg,
  1941  			CloudName:               "dummy",
  1942  			CloudRegion:             controllerRegion,
  1943  			CloudCredential:         controllerCredential,
  1944  			StorageProviderRegistry: storage.StaticProviderRegistry{},
  1945  		},
  1946  		Cloud: cloud.Cloud{
  1947  			Name:      "dummy",
  1948  			Type:      "dummy",
  1949  			AuthTypes: authTypes,
  1950  			Regions:   regions,
  1951  		},
  1952  		CloudCredentials: credentials,
  1953  		MongoSession:     s.Session,
  1954  		AdminPassword:    "dummy-secret",
  1955  	})
  1956  	c.Assert(err, jc.ErrorIsNil)
  1957  	return controller, owner
  1958  }
  1959  
  1960  func assertCleanupRuns(c *gc.C, st *state.State) {
  1961  	err := st.Cleanup()
  1962  	c.Assert(err, jc.ErrorIsNil)
  1963  }
  1964  
  1965  func assertNeedsCleanup(c *gc.C, st *state.State) {
  1966  	actual, err := st.NeedsCleanup()
  1967  	c.Assert(err, jc.ErrorIsNil)
  1968  	c.Assert(actual, jc.IsTrue)
  1969  }
  1970  
  1971  func assertDoesNotNeedCleanup(c *gc.C, st *state.State) {
  1972  	actual, err := st.NeedsCleanup()
  1973  	c.Assert(err, jc.ErrorIsNil)
  1974  	c.Assert(actual, jc.IsFalse)
  1975  }
  1976  
  1977  // assertCleanupCount is useful because certain cleanups cause other cleanups
  1978  // to be queued; it makes more sense to just run cleanup again than to unpick
  1979  // object destruction so that we run the cleanups inline while running cleanups.
  1980  func assertCleanupCount(c *gc.C, st *state.State, count int) {
  1981  	for i := 0; i < count; i++ {
  1982  		c.Logf("checking cleanups %d", i)
  1983  		assertNeedsCleanup(c, st)
  1984  		assertCleanupRuns(c, st)
  1985  	}
  1986  	assertDoesNotNeedCleanup(c, st)
  1987  }
  1988  
  1989  // assertCleanupCountDirty is the same as assertCleanupCount, but it
  1990  // checks that there are still cleanups to run.
  1991  func assertCleanupCountDirty(c *gc.C, st *state.State, count int) {
  1992  	for i := 0; i < count; i++ {
  1993  		c.Logf("checking cleanups %d", i)
  1994  		assertNeedsCleanup(c, st)
  1995  		assertCleanupRuns(c, st)
  1996  	}
  1997  	assertNeedsCleanup(c, st)
  1998  }
  1999  
  2000  // The provisioner will remove dead machines once their backing instances are
  2001  // stopped. For the tests, we remove them directly.
  2002  func assertAllMachinesDeadAndRemove(c *gc.C, st *state.State) {
  2003  	machines, err := st.AllMachines()
  2004  	c.Assert(err, jc.ErrorIsNil)
  2005  	for _, m := range machines {
  2006  		if m.IsManager() {
  2007  			continue
  2008  		}
  2009  		if _, isContainer := m.ParentId(); isContainer {
  2010  			continue
  2011  		}
  2012  		manual, err := m.IsManual()
  2013  		c.Assert(err, jc.ErrorIsNil)
  2014  		if manual {
  2015  			continue
  2016  		}
  2017  
  2018  		c.Assert(m.Life(), gc.Equals, state.Dead)
  2019  		c.Assert(m.Remove(), jc.ErrorIsNil)
  2020  	}
  2021  }