github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/machine_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	"sort"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/juju/clock"
    12  	"github.com/juju/errors"
    13  	"github.com/juju/loggo"
    14  	"github.com/juju/mgo/v3"
    15  	"github.com/juju/mgo/v3/bson"
    16  	"github.com/juju/mgo/v3/txn"
    17  	"github.com/juju/names/v5"
    18  	jc "github.com/juju/testing/checkers"
    19  	jujutxn "github.com/juju/txn/v3"
    20  	"github.com/juju/version/v2"
    21  	gc "gopkg.in/check.v1"
    22  
    23  	"github.com/juju/juju/core/arch"
    24  	"github.com/juju/juju/core/constraints"
    25  	corecontainer "github.com/juju/juju/core/container"
    26  	"github.com/juju/juju/core/instance"
    27  	"github.com/juju/juju/core/network"
    28  	"github.com/juju/juju/core/status"
    29  	"github.com/juju/juju/mongo"
    30  	"github.com/juju/juju/mongo/mongotest"
    31  	"github.com/juju/juju/state"
    32  	stateerrors "github.com/juju/juju/state/errors"
    33  	"github.com/juju/juju/state/testing"
    34  	"github.com/juju/juju/storage"
    35  	"github.com/juju/juju/storage/poolmanager"
    36  	"github.com/juju/juju/storage/provider"
    37  	dummystorage "github.com/juju/juju/storage/provider/dummy"
    38  	coretesting "github.com/juju/juju/testing"
    39  	"github.com/juju/juju/testing/factory"
    40  )
    41  
    42  type MachineSuite struct {
    43  	ConnSuite
    44  	machine0 *state.Machine
    45  	machine  *state.Machine
    46  }
    47  
    48  var _ = gc.Suite(&MachineSuite{})
    49  
    50  func (s *MachineSuite) SetUpTest(c *gc.C) {
    51  	s.ConnSuite.SetUpTest(c)
    52  	s.policy.GetConstraintsValidator = func() (constraints.Validator, error) {
    53  		validator := constraints.NewValidator()
    54  		validator.RegisterConflicts([]string{constraints.InstanceType}, []string{constraints.Mem})
    55  		validator.RegisterUnsupported([]string{constraints.CpuPower})
    56  		return validator, nil
    57  	}
    58  	var err error
    59  	s.machine0, err = s.State.AddMachine(state.UbuntuBase("12.10"), state.JobManageModel)
    60  	c.Assert(err, jc.ErrorIsNil)
    61  	controllerNode, err := s.State.ControllerNode(s.machine0.Id())
    62  	c.Assert(err, jc.ErrorIsNil)
    63  	c.Assert(controllerNode.HasVote(), jc.IsFalse)
    64  	c.Assert(controllerNode.SetHasVote(true), jc.ErrorIsNil)
    65  	s.machine, err = s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
    66  	c.Assert(err, jc.ErrorIsNil)
    67  	_, err = s.State.ControllerNode(s.machine.Id())
    68  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
    69  }
    70  
    71  func (s *MachineSuite) TestSetRebootFlagDeadMachine(c *gc.C) {
    72  	err := s.machine.EnsureDead()
    73  	c.Assert(err, jc.ErrorIsNil)
    74  
    75  	err = s.machine.SetRebootFlag(true)
    76  	c.Assert(err, gc.Equals, mgo.ErrNotFound)
    77  
    78  	rFlag, err := s.machine.GetRebootFlag()
    79  	c.Assert(err, jc.ErrorIsNil)
    80  	c.Assert(rFlag, jc.IsFalse)
    81  
    82  	err = s.machine.SetRebootFlag(false)
    83  	c.Assert(err, jc.ErrorIsNil)
    84  
    85  	action, err := s.machine.ShouldRebootOrShutdown()
    86  	c.Assert(err, jc.ErrorIsNil)
    87  	c.Assert(action, gc.Equals, state.ShouldDoNothing)
    88  }
    89  
    90  func (s *MachineSuite) TestSetRebootFlagDeadMachineRace(c *gc.C) {
    91  	setFlag := jujutxn.TestHook{
    92  		Before: func() {
    93  			err := s.machine.EnsureDead()
    94  			c.Assert(err, jc.ErrorIsNil)
    95  		},
    96  	}
    97  	defer state.SetTestHooks(c, s.State, setFlag).Check()
    98  
    99  	err := s.machine.SetRebootFlag(true)
   100  	c.Assert(err, gc.Equals, mgo.ErrNotFound)
   101  }
   102  
   103  func (s *MachineSuite) TestSetRebootFlag(c *gc.C) {
   104  	err := s.machine.SetRebootFlag(true)
   105  	c.Assert(err, jc.ErrorIsNil)
   106  
   107  	rebootFlag, err := s.machine.GetRebootFlag()
   108  	c.Assert(err, jc.ErrorIsNil)
   109  	c.Assert(rebootFlag, jc.IsTrue)
   110  }
   111  
   112  func (s *MachineSuite) TestSetUnsetRebootFlag(c *gc.C) {
   113  	err := s.machine.SetRebootFlag(true)
   114  	c.Assert(err, jc.ErrorIsNil)
   115  
   116  	rebootFlag, err := s.machine.GetRebootFlag()
   117  	c.Assert(err, jc.ErrorIsNil)
   118  	c.Assert(rebootFlag, jc.IsTrue)
   119  
   120  	err = s.machine.SetRebootFlag(false)
   121  	c.Assert(err, jc.ErrorIsNil)
   122  
   123  	rebootFlag, err = s.machine.GetRebootFlag()
   124  	c.Assert(err, jc.ErrorIsNil)
   125  	c.Assert(rebootFlag, jc.IsFalse)
   126  }
   127  
   128  func (s *MachineSuite) TestRecordAgentStartInformation(c *gc.C) {
   129  	now := s.Clock.Now().Truncate(time.Minute)
   130  	err := s.machine.RecordAgentStartInformation("thundering-herds")
   131  	c.Assert(err, jc.ErrorIsNil)
   132  
   133  	err = s.machine.Refresh()
   134  	c.Assert(err, jc.ErrorIsNil)
   135  	c.Assert(s.machine.AgentStartTime().Truncate(time.Minute), gc.Equals, now)
   136  	c.Assert(s.machine.Hostname(), gc.Equals, "thundering-herds")
   137  
   138  	// Passing an empty hostname should be ignored
   139  	err = s.machine.RecordAgentStartInformation("")
   140  	c.Assert(err, jc.ErrorIsNil)
   141  	err = s.machine.Refresh()
   142  	c.Assert(err, jc.ErrorIsNil)
   143  	c.Assert(s.machine.AgentStartTime().Truncate(time.Minute), gc.Equals, now)
   144  	c.Assert(s.machine.Hostname(), gc.Equals, "thundering-herds", gc.Commentf("expected the host name not be changed"))
   145  }
   146  
   147  func (s *MachineSuite) TestSetKeepInstance(c *gc.C) {
   148  	err := s.machine.SetProvisioned("1234", "", "nonce", nil)
   149  	c.Assert(err, jc.ErrorIsNil)
   150  	err = s.machine.SetKeepInstance(true)
   151  	c.Assert(err, jc.ErrorIsNil)
   152  
   153  	m, err := s.State.Machine(s.machine.Id())
   154  	c.Assert(err, jc.ErrorIsNil)
   155  	keep, err := m.KeepInstance()
   156  	c.Assert(err, jc.ErrorIsNil)
   157  	c.Assert(keep, jc.IsTrue)
   158  }
   159  
   160  func (s *MachineSuite) TestAddMachineInsideMachineModelDying(c *gc.C) {
   161  	model, err := s.State.Model()
   162  	c.Assert(err, jc.ErrorIsNil)
   163  	c.Assert(model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil)
   164  
   165  	_, err = s.State.AddMachineInsideMachine(state.MachineTemplate{
   166  		Base: state.UbuntuBase("12.10"),
   167  		Jobs: []state.MachineJob{state.JobHostUnits},
   168  	}, s.machine.Id(), instance.LXD)
   169  	c.Assert(err, gc.ErrorMatches, `model "testmodel" is dying`)
   170  }
   171  
   172  func (s *MachineSuite) TestAddMachineInsideMachineModelMigrating(c *gc.C) {
   173  	model, err := s.State.Model()
   174  	c.Assert(err, jc.ErrorIsNil)
   175  	c.Assert(model.SetMigrationMode(state.MigrationModeExporting), jc.ErrorIsNil)
   176  
   177  	_, err = s.State.AddMachineInsideMachine(state.MachineTemplate{
   178  		Base: state.UbuntuBase("12.10"),
   179  		Jobs: []state.MachineJob{state.JobHostUnits},
   180  	}, s.machine.Id(), instance.LXD)
   181  	c.Assert(err, gc.ErrorMatches, `model "testmodel" is being migrated`)
   182  }
   183  
   184  func (s *MachineSuite) TestShouldShutdownOrReboot(c *gc.C) {
   185  	// Add first container.
   186  	c1, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
   187  		Base: state.UbuntuBase("12.10"),
   188  		Jobs: []state.MachineJob{state.JobHostUnits},
   189  	}, s.machine.Id(), instance.LXD)
   190  	c.Assert(err, jc.ErrorIsNil)
   191  
   192  	// Add second container.
   193  	c2, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
   194  		Base: state.UbuntuBase("12.10"),
   195  		Jobs: []state.MachineJob{state.JobHostUnits},
   196  	}, c1.Id(), instance.LXD)
   197  	c.Assert(err, jc.ErrorIsNil)
   198  
   199  	err = c2.SetRebootFlag(true)
   200  	c.Assert(err, jc.ErrorIsNil)
   201  
   202  	rAction, err := s.machine.ShouldRebootOrShutdown()
   203  	c.Assert(err, jc.ErrorIsNil)
   204  	c.Assert(rAction, gc.Equals, state.ShouldDoNothing)
   205  
   206  	rAction, err = c1.ShouldRebootOrShutdown()
   207  	c.Assert(err, jc.ErrorIsNil)
   208  	c.Assert(rAction, gc.Equals, state.ShouldDoNothing)
   209  
   210  	rAction, err = c2.ShouldRebootOrShutdown()
   211  	c.Assert(err, jc.ErrorIsNil)
   212  	c.Assert(rAction, gc.Equals, state.ShouldReboot)
   213  
   214  	// // Reboot happens on the root node
   215  	err = c2.SetRebootFlag(false)
   216  	c.Assert(err, jc.ErrorIsNil)
   217  
   218  	err = s.machine.SetRebootFlag(true)
   219  	c.Assert(err, jc.ErrorIsNil)
   220  
   221  	rAction, err = s.machine.ShouldRebootOrShutdown()
   222  	c.Assert(err, jc.ErrorIsNil)
   223  	c.Assert(rAction, gc.Equals, state.ShouldReboot)
   224  
   225  	rAction, err = c1.ShouldRebootOrShutdown()
   226  	c.Assert(err, jc.ErrorIsNil)
   227  	c.Assert(rAction, gc.Equals, state.ShouldShutdown)
   228  
   229  	rAction, err = c2.ShouldRebootOrShutdown()
   230  	c.Assert(err, jc.ErrorIsNil)
   231  	c.Assert(rAction, gc.Equals, state.ShouldShutdown)
   232  }
   233  
   234  func (s *MachineSuite) TestContainerDefaults(c *gc.C) {
   235  	c.Assert(string(s.machine.ContainerType()), gc.Equals, "")
   236  	containers, err := s.machine.Containers()
   237  	c.Assert(err, jc.ErrorIsNil)
   238  	c.Assert(containers, gc.DeepEquals, []string(nil))
   239  }
   240  
   241  func (s *MachineSuite) TestParentId(c *gc.C) {
   242  	parentId, ok := s.machine.ParentId()
   243  	c.Assert(parentId, gc.Equals, "")
   244  	c.Assert(ok, jc.IsFalse)
   245  	container, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
   246  		Base: state.UbuntuBase("12.10"),
   247  		Jobs: []state.MachineJob{state.JobHostUnits},
   248  	}, s.machine.Id(), instance.LXD)
   249  	c.Assert(err, jc.ErrorIsNil)
   250  	parentId, ok = container.ParentId()
   251  	c.Assert(parentId, gc.Equals, s.machine.Id())
   252  	c.Assert(ok, jc.IsTrue)
   253  }
   254  
   255  func (s *MachineSuite) TestMachineIsManager(c *gc.C) {
   256  	c.Assert(s.machine0.IsManager(), jc.IsTrue)
   257  	c.Assert(s.machine.IsManager(), jc.IsFalse)
   258  }
   259  
   260  func (s *MachineSuite) TestMachineIsManualBootstrap(c *gc.C) {
   261  	cfg, err := s.Model.ModelConfig()
   262  	c.Assert(err, jc.ErrorIsNil)
   263  	c.Assert(cfg.Type(), gc.Not(gc.Equals), "null")
   264  	c.Assert(s.machine.Id(), gc.Equals, "1")
   265  	manual, err := s.machine0.IsManual()
   266  	c.Assert(err, jc.ErrorIsNil)
   267  	c.Assert(manual, jc.IsFalse)
   268  	attrs := map[string]interface{}{"type": "null"}
   269  	err = s.Model.UpdateModelConfig(attrs, nil)
   270  	c.Assert(err, jc.ErrorIsNil)
   271  	manual, err = s.machine0.IsManual()
   272  	c.Assert(err, jc.ErrorIsNil)
   273  	c.Assert(manual, jc.IsTrue)
   274  }
   275  
   276  func (s *MachineSuite) TestMachineIsManual(c *gc.C) {
   277  	tests := []struct {
   278  		instanceId instance.Id
   279  		nonce      string
   280  		isManual   bool
   281  	}{
   282  		{instanceId: "x", nonce: "y", isManual: false},
   283  		{instanceId: "manual:", nonce: "y", isManual: false},
   284  		{instanceId: "x", nonce: "manual:", isManual: true},
   285  		{instanceId: "x", nonce: "manual:y", isManual: true},
   286  		{instanceId: "x", nonce: "manual", isManual: false},
   287  	}
   288  	for _, test := range tests {
   289  		m, err := s.State.AddOneMachine(state.MachineTemplate{
   290  			Base:       state.UbuntuBase("12.10"),
   291  			Jobs:       []state.MachineJob{state.JobHostUnits},
   292  			InstanceId: test.instanceId,
   293  			Nonce:      test.nonce,
   294  		})
   295  		c.Assert(err, jc.ErrorIsNil)
   296  		isManual, err := m.IsManual()
   297  		c.Assert(err, jc.ErrorIsNil)
   298  		c.Assert(isManual, gc.Equals, test.isManual)
   299  	}
   300  }
   301  
   302  func (s *MachineSuite) TestMachineIsContainer(c *gc.C) {
   303  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
   304  	c.Assert(err, jc.ErrorIsNil)
   305  
   306  	template := state.MachineTemplate{
   307  		Base: state.UbuntuBase("12.10"),
   308  		Jobs: []state.MachineJob{state.JobHostUnits},
   309  	}
   310  	container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXD)
   311  	c.Assert(err, jc.ErrorIsNil)
   312  
   313  	c.Assert(machine.IsContainer(), jc.IsFalse)
   314  	c.Assert(container.IsContainer(), jc.IsTrue)
   315  }
   316  
   317  func (s *MachineSuite) TestLifeJobController(c *gc.C) {
   318  	m := s.machine0
   319  	err := m.Destroy()
   320  	c.Assert(err, gc.ErrorMatches, "controller 0 is the only controller")
   321  	controllerNode, err := s.State.ControllerNode(m.Id())
   322  	c.Assert(err, jc.ErrorIsNil)
   323  	c.Assert(controllerNode.HasVote(), jc.IsTrue)
   324  	err = m.EnsureDead()
   325  	c.Assert(err, gc.ErrorMatches, "machine 0 is still a voting controller member")
   326  	controllerNode, err = s.State.ControllerNode(m.Id())
   327  	c.Assert(err, jc.ErrorIsNil)
   328  	c.Assert(controllerNode.HasVote(), jc.IsTrue)
   329  
   330  	// Since this is the only controller machine, we cannot even force destroy it
   331  	err = m.ForceDestroy(dontWait)
   332  	c.Assert(err, gc.ErrorMatches, "controller 0 is the only controller")
   333  	err = m.EnsureDead()
   334  	c.Assert(err, gc.ErrorMatches, "machine 0 is still a voting controller member")
   335  }
   336  
   337  func (s *MachineSuite) TestLifeJobManageModelWithControllerCharm(c *gc.C) {
   338  	cons := constraints.Value{
   339  		Mem: newUint64(100),
   340  	}
   341  	changes, err := s.State.EnableHA(3, cons, state.UbuntuBase("12.10"), nil)
   342  	c.Assert(err, jc.ErrorIsNil)
   343  	c.Assert(changes.Added, gc.HasLen, 2)
   344  
   345  	m2, err := s.State.Machine("2")
   346  	c.Assert(err, jc.ErrorIsNil)
   347  	c.Assert(m2.Jobs(), gc.DeepEquals, []state.MachineJob{
   348  		state.JobHostUnits,
   349  		state.JobManageModel,
   350  	})
   351  
   352  	ch := s.AddTestingCharmWithSeries(c, "juju-controller", "")
   353  	app := s.AddTestingApplicationForBase(c, state.UbuntuBase("12.10"), "controller", ch)
   354  	unit, err := app.AddUnit(state.AddUnitParams{})
   355  	c.Assert(err, jc.ErrorIsNil)
   356  	err = unit.SetCharmURL(ch.URL())
   357  	c.Assert(err, jc.ErrorIsNil)
   358  	err = unit.AssignToMachine(m2)
   359  	c.Assert(err, jc.ErrorIsNil)
   360  	err = m2.Destroy()
   361  	c.Assert(err, jc.ErrorIsNil)
   362  
   363  	c.Assert(m2.Life(), gc.Equals, state.Alive)
   364  	c.Assert(err, jc.ErrorIsNil)
   365  
   366  	for i := 0; i < 3; i++ {
   367  		needsCleanup, err := s.State.NeedsCleanup()
   368  		c.Assert(err, jc.ErrorIsNil)
   369  		c.Assert(needsCleanup, jc.IsTrue)
   370  		err = s.State.Cleanup()
   371  		c.Assert(err, jc.ErrorIsNil)
   372  	}
   373  	needsCleanup, err := s.State.NeedsCleanup()
   374  	c.Assert(err, jc.ErrorIsNil)
   375  	c.Assert(needsCleanup, jc.IsFalse)
   376  
   377  	err = m2.Refresh()
   378  	c.Assert(err, jc.ErrorIsNil)
   379  	c.Assert(m2.Life(), gc.Equals, state.Dying)
   380  
   381  	cn2, err := s.State.ControllerNode(m2.Id())
   382  	c.Assert(err, jc.ErrorIsNil)
   383  	err = s.State.RemoveControllerReference(cn2)
   384  	c.Assert(err, jc.ErrorIsNil)
   385  
   386  	err = m2.EnsureDead()
   387  	c.Assert(err, jc.ErrorIsNil)
   388  	c.Assert(m2.Life(), gc.Equals, state.Dead)
   389  }
   390  
   391  func (s *MachineSuite) TestLifeMachineWithContainer(c *gc.C) {
   392  	// A machine hosting a container must not advance lifecycle.
   393  	_, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
   394  		Base: state.UbuntuBase("12.10"),
   395  		Jobs: []state.MachineJob{state.JobHostUnits},
   396  	}, s.machine.Id(), instance.LXD)
   397  	c.Assert(err, jc.ErrorIsNil)
   398  
   399  	err = s.machine.Destroy()
   400  	c.Assert(errors.Is(err, stateerrors.HasContainersError), jc.IsTrue)
   401  	c.Assert(err, gc.ErrorMatches, `machine 1 is hosting containers "1/lxd/0"`)
   402  
   403  	err = s.machine.EnsureDead()
   404  	c.Assert(errors.Is(err, stateerrors.HasContainersError), jc.IsTrue)
   405  	c.Assert(err, gc.ErrorMatches, `machine 1 is hosting containers "1/lxd/0"`)
   406  
   407  	c.Assert(s.machine.Life(), gc.Equals, state.Alive)
   408  }
   409  
   410  func (s *MachineSuite) TestLifeMachineLockedForSeriesUpgrade(c *gc.C) {
   411  	err := s.machine.CreateUpgradeSeriesLock(nil, state.UbuntuBase("16.04"))
   412  	c.Assert(err, jc.ErrorIsNil)
   413  
   414  	err = s.machine.Destroy()
   415  	c.Assert(err, gc.ErrorMatches, `machine 1 is locked for series upgrade`)
   416  
   417  	err = s.machine.EnsureDead()
   418  	c.Assert(err, gc.ErrorMatches, `machine 1 is locked for series upgrade`)
   419  	c.Assert(s.machine.Life(), gc.Equals, state.Alive)
   420  }
   421  
   422  func (s *MachineSuite) TestLifeJobHostUnits(c *gc.C) {
   423  	// A machine with an assigned unit must not advance lifecycle.
   424  	app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   425  	unit, err := app.AddUnit(state.AddUnitParams{})
   426  	c.Assert(err, jc.ErrorIsNil)
   427  	err = unit.AssignToMachine(s.machine)
   428  	c.Assert(err, jc.ErrorIsNil)
   429  	err = s.machine.Destroy()
   430  	c.Assert(errors.Is(err, stateerrors.HasAssignedUnitsError), jc.IsTrue)
   431  	c.Assert(err, gc.ErrorMatches, `machine 1 has unit "wordpress/0" assigned`)
   432  
   433  	err = s.machine.EnsureDead()
   434  	c.Assert(errors.Is(err, stateerrors.HasAssignedUnitsError), jc.IsTrue)
   435  	c.Assert(err, gc.ErrorMatches, `machine 1 has unit "wordpress/0" assigned`)
   436  
   437  	c.Assert(s.machine.Life(), gc.Equals, state.Alive)
   438  
   439  	// Once no unit is assigned, lifecycle can advance.
   440  	err = unit.UnassignFromMachine()
   441  	c.Assert(err, jc.ErrorIsNil)
   442  	err = s.machine.Destroy()
   443  	c.Assert(s.machine.Life(), gc.Equals, state.Dying)
   444  	c.Assert(err, jc.ErrorIsNil)
   445  	err = s.machine.EnsureDead()
   446  	c.Assert(err, jc.ErrorIsNil)
   447  	c.Assert(s.machine.Life(), gc.Equals, state.Dead)
   448  
   449  	// A machine that has never had units assigned can advance lifecycle.
   450  	m, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
   451  	c.Assert(err, jc.ErrorIsNil)
   452  	err = m.Destroy()
   453  	c.Assert(err, jc.ErrorIsNil)
   454  	c.Assert(m.Life(), gc.Equals, state.Dying)
   455  	err = m.EnsureDead()
   456  	c.Assert(err, jc.ErrorIsNil)
   457  	c.Assert(m.Life(), gc.Equals, state.Dead)
   458  }
   459  
   460  func (s *MachineSuite) TestDestroyRemovePorts(c *gc.C) {
   461  	app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   462  	unit, err := app.AddUnit(state.AddUnitParams{})
   463  	c.Assert(err, jc.ErrorIsNil)
   464  	err = unit.AssignToMachine(s.machine)
   465  	c.Assert(err, jc.ErrorIsNil)
   466  
   467  	state.MustOpenUnitPortRange(c, s.State, s.machine, unit.Name(), allEndpoints, network.MustParsePortRange("8080/tcp"))
   468  
   469  	machPortRanges, err := s.machine.OpenedPortRanges()
   470  	c.Assert(err, jc.ErrorIsNil)
   471  	c.Assert(machPortRanges.UniquePortRanges(), gc.HasLen, 1)
   472  
   473  	err = unit.UnassignFromMachine()
   474  	c.Assert(err, jc.ErrorIsNil)
   475  	err = s.machine.Destroy()
   476  	c.Assert(err, jc.ErrorIsNil)
   477  	err = s.machine.EnsureDead()
   478  	c.Assert(err, jc.ErrorIsNil)
   479  	err = s.machine.Remove()
   480  	c.Assert(err, jc.ErrorIsNil)
   481  
   482  	// once the machine is destroyed, there should be no ports documents present for it
   483  	machPortRanges, err = s.machine.OpenedPortRanges()
   484  	c.Assert(err, jc.ErrorIsNil)
   485  	assertMachinePortsPersisted(c, machPortRanges, false) // we should get back a blank fresh doc
   486  }
   487  
   488  func (s *MachineSuite) TestDestroyOps(c *gc.C) {
   489  	m := s.Factory.MakeMachine(c, nil)
   490  	ops, err := state.ForceDestroyMachineOps(m)
   491  	c.Assert(err, jc.ErrorIsNil)
   492  	c.Assert(ops, gc.NotNil)
   493  }
   494  
   495  func (s *MachineSuite) TestDestroyOpsForManagerFails(c *gc.C) {
   496  	// s.Factory does not allow us to make a manager machine, so we grab one
   497  	// from State ...
   498  	machines, err := s.State.AllMachines()
   499  	c.Assert(err, jc.ErrorIsNil)
   500  	c.Assert(len(machines), jc.GreaterThan, 0)
   501  	m := machines[0]
   502  	c.Assert(m.IsManager(), jc.IsTrue)
   503  
   504  	// ... and assert that we cannot get the destroy ops for it.
   505  	ops, err := state.ForceDestroyMachineOps(m)
   506  	c.Assert(err, gc.ErrorMatches, `controller 0 is the only controller`)
   507  	c.Assert(ops, gc.IsNil)
   508  }
   509  
   510  func (s *MachineSuite) TestDestroyAbort(c *gc.C) {
   511  	defer state.SetBeforeHooks(c, s.State, func() {
   512  		c.Assert(s.machine.Destroy(), gc.IsNil)
   513  	}).Check()
   514  	err := s.machine.Destroy()
   515  	c.Assert(err, jc.ErrorIsNil)
   516  }
   517  
   518  func (s *MachineSuite) TestDestroyCancel(c *gc.C) {
   519  	app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   520  	unit, err := app.AddUnit(state.AddUnitParams{})
   521  	c.Assert(err, jc.ErrorIsNil)
   522  
   523  	defer state.SetBeforeHooks(c, s.State, func() {
   524  		c.Assert(unit.AssignToMachine(s.machine), gc.IsNil)
   525  	}).Check()
   526  	err = s.machine.Destroy()
   527  	c.Assert(errors.Is(err, stateerrors.HasAssignedUnitsError), jc.IsTrue)
   528  }
   529  
   530  func (s *MachineSuite) TestDestroyContention(c *gc.C) {
   531  	app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   532  	unit, err := app.AddUnit(state.AddUnitParams{})
   533  	c.Assert(err, jc.ErrorIsNil)
   534  
   535  	perturb := jujutxn.TestHook{
   536  		Before: func() { c.Assert(unit.AssignToMachine(s.machine), gc.IsNil) },
   537  		After:  func() { c.Assert(unit.UnassignFromMachine(), gc.IsNil) },
   538  	}
   539  	state.SetMaxTxnAttempts(c, s.State, 3)
   540  	defer state.SetTestHooks(c, s.State, perturb, perturb, perturb).Check()
   541  
   542  	err = s.machine.Destroy()
   543  	c.Assert(err, gc.ErrorMatches, "machine 1 cannot advance lifecycle: state changing too quickly; try again soon")
   544  }
   545  
   546  func (s *MachineSuite) TestDestroyWithApplicationDestroyPending(c *gc.C) {
   547  	app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   548  	unit, err := app.AddUnit(state.AddUnitParams{})
   549  	c.Assert(err, jc.ErrorIsNil)
   550  	err = unit.AssignToMachine(s.machine)
   551  	c.Assert(err, jc.ErrorIsNil)
   552  
   553  	err = app.Destroy()
   554  	c.Assert(err, jc.ErrorIsNil)
   555  	err = s.machine.Destroy()
   556  	c.Assert(err, jc.ErrorIsNil)
   557  	// Machine is still advanced to Dying.
   558  	life := s.machine.Life()
   559  	c.Assert(life, gc.Equals, state.Dying)
   560  }
   561  
   562  func (s *MachineSuite) TestDestroyFailsWhenNewUnitAdded(c *gc.C) {
   563  	app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   564  	unit, err := app.AddUnit(state.AddUnitParams{})
   565  	c.Assert(err, jc.ErrorIsNil)
   566  	err = unit.AssignToMachine(s.machine)
   567  	c.Assert(err, jc.ErrorIsNil)
   568  
   569  	err = app.Destroy()
   570  	c.Assert(err, jc.ErrorIsNil)
   571  
   572  	defer state.SetBeforeHooks(c, s.State, func() {
   573  		anotherApp := s.AddTestingApplication(c, "mysql", s.AddTestingCharm(c, "mysql"))
   574  		anotherUnit, err := anotherApp.AddUnit(state.AddUnitParams{})
   575  		c.Assert(err, jc.ErrorIsNil)
   576  		err = anotherUnit.AssignToMachine(s.machine)
   577  		c.Assert(err, jc.ErrorIsNil)
   578  	}).Check()
   579  
   580  	err = s.machine.Destroy()
   581  	c.Assert(errors.Is(err, stateerrors.HasAssignedUnitsError), jc.IsTrue)
   582  	life := s.machine.Life()
   583  	c.Assert(life, gc.Equals, state.Alive)
   584  }
   585  
   586  func (s *MachineSuite) TestDestroyWithUnitDestroyPending(c *gc.C) {
   587  	app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   588  	unit, err := app.AddUnit(state.AddUnitParams{})
   589  	c.Assert(err, jc.ErrorIsNil)
   590  	err = unit.AssignToMachine(s.machine)
   591  	c.Assert(err, jc.ErrorIsNil)
   592  
   593  	err = unit.Destroy()
   594  	c.Assert(err, jc.ErrorIsNil)
   595  	err = s.machine.Destroy()
   596  	c.Assert(err, jc.ErrorIsNil)
   597  	// Machine is still advanced to Dying.
   598  	life := s.machine.Life()
   599  	c.Assert(life, gc.Equals, state.Dying)
   600  }
   601  
   602  func (s *MachineSuite) TestDestroyFailsWhenNewContainerAdded(c *gc.C) {
   603  	app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   604  	unit, err := app.AddUnit(state.AddUnitParams{})
   605  	c.Assert(err, jc.ErrorIsNil)
   606  	err = unit.AssignToMachine(s.machine)
   607  	c.Assert(err, jc.ErrorIsNil)
   608  
   609  	err = app.Destroy()
   610  	c.Assert(err, jc.ErrorIsNil)
   611  
   612  	defer state.SetBeforeHooks(c, s.State, func() {
   613  		_, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
   614  			Base: state.UbuntuBase("12.10"),
   615  			Jobs: []state.MachineJob{state.JobHostUnits},
   616  		}, s.machine.Id(), instance.LXD)
   617  		c.Assert(err, jc.ErrorIsNil)
   618  	}).Check()
   619  
   620  	err = s.machine.Destroy()
   621  	c.Assert(errors.Is(err, stateerrors.HasAssignedUnitsError), jc.IsTrue)
   622  	life := s.machine.Life()
   623  	c.Assert(life, gc.Equals, state.Alive)
   624  }
   625  
   626  func (s *MachineSuite) TestRemove(c *gc.C) {
   627  	arch := arch.DefaultArchitecture
   628  	char := &instance.HardwareCharacteristics{
   629  		Arch: &arch,
   630  	}
   631  	err := s.machine.SetProvisioned("umbrella/0", "snowflake", "fake_nonce", char)
   632  	c.Assert(err, jc.ErrorIsNil)
   633  
   634  	err = s.State.SetSSHHostKeys(s.machine.MachineTag(), state.SSHHostKeys{"rsa", "dsa"})
   635  	c.Assert(err, jc.ErrorIsNil)
   636  
   637  	err = s.machine.Remove()
   638  	c.Assert(err, gc.ErrorMatches, "cannot remove machine 1: machine is not dead")
   639  
   640  	err = s.machine.EnsureDead()
   641  	c.Assert(err, jc.ErrorIsNil)
   642  
   643  	err = s.machine.Remove()
   644  	c.Assert(err, jc.ErrorIsNil)
   645  
   646  	err = s.machine.Refresh()
   647  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   648  
   649  	_, err = s.machine.HardwareCharacteristics()
   650  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   651  
   652  	_, err = s.machine.Containers()
   653  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   654  
   655  	_, err = s.State.GetSSHHostKeys(s.machine.MachineTag())
   656  	c.Assert(errors.IsNotFound(err), jc.IsTrue)
   657  
   658  	// Removing an already removed machine is OK.
   659  	err = s.machine.Remove()
   660  	c.Assert(err, jc.ErrorIsNil)
   661  }
   662  
   663  func (s *MachineSuite) TestRemoveAbort(c *gc.C) {
   664  	err := s.machine.EnsureDead()
   665  	c.Assert(err, jc.ErrorIsNil)
   666  
   667  	defer state.SetBeforeHooks(c, s.State, func() {
   668  		c.Assert(s.machine.Remove(), gc.IsNil)
   669  	}).Check()
   670  	err = s.machine.Remove()
   671  	c.Assert(err, jc.ErrorIsNil)
   672  }
   673  
   674  func (s *MachineSuite) TestTag(c *gc.C) {
   675  	tag := s.machine.MachineTag()
   676  	c.Assert(tag.Kind(), gc.Equals, names.MachineTagKind)
   677  	c.Assert(tag.Id(), gc.Equals, "1")
   678  
   679  	// To keep gccgo happy, don't compare an interface with a struct.
   680  	var asTag names.Tag = tag
   681  	c.Assert(s.machine.Tag(), gc.Equals, asTag)
   682  }
   683  
   684  func (s *MachineSuite) TestSetMongoPassword(c *gc.C) {
   685  	testSetMongoPassword(c, func(st *state.State, id string) (mongoPasswordSetter, error) {
   686  		return st.Machine("0")
   687  	}, s.State.ControllerTag(), s.modelTag, s.Session)
   688  }
   689  
   690  type mongoPasswordSetter interface {
   691  	SetMongoPassword(password string) error
   692  	Tag() names.Tag
   693  }
   694  
   695  type mongoPasswordSetterGetter func(st *state.State, id string) (mongoPasswordSetter, error)
   696  
   697  func testSetMongoPassword(
   698  	c *gc.C, entityFunc mongoPasswordSetterGetter,
   699  	controllerTag names.ControllerTag, modelTag names.ModelTag, mgoSession *mgo.Session,
   700  ) {
   701  	pool, err := state.OpenStatePool(state.OpenParams{
   702  		Clock:              clock.WallClock,
   703  		ControllerTag:      controllerTag,
   704  		ControllerModelTag: modelTag,
   705  		MongoSession:       mgoSession,
   706  	})
   707  	c.Assert(err, jc.ErrorIsNil)
   708  	st, err := pool.SystemState()
   709  	c.Assert(err, jc.ErrorIsNil)
   710  	defer func() {
   711  		// Remove the admin password so that the test harness can reset the state.
   712  		err := st.SetAdminMongoPassword("")
   713  		c.Check(err, jc.ErrorIsNil)
   714  		err = pool.Close()
   715  		c.Check(err, jc.ErrorIsNil)
   716  	}()
   717  
   718  	// Turn on fully-authenticated mode.
   719  	err = st.SetAdminMongoPassword("admin-secret")
   720  	c.Assert(err, jc.ErrorIsNil)
   721  	err = st.MongoSession().DB("admin").Login("admin", "admin-secret")
   722  	c.Assert(err, jc.ErrorIsNil)
   723  
   724  	// Set the password for the entity
   725  	ent, err := entityFunc(st, "0")
   726  	c.Assert(err, jc.ErrorIsNil)
   727  	err = ent.SetMongoPassword("foo")
   728  	c.Assert(err, jc.ErrorIsNil)
   729  
   730  	// Check that we cannot log in with the wrong password.
   731  	info := testing.NewMongoInfo()
   732  	info.Tag = ent.Tag()
   733  	info.Password = "bar"
   734  	err = tryOpenState(modelTag, controllerTag, info)
   735  	c.Check(errors.Cause(err), jc.Satisfies, errors.IsUnauthorized)
   736  	c.Check(err, gc.ErrorMatches, `cannot log in to admin database as "(machine|controller)-0": unauthorized mongo access: .*`)
   737  
   738  	// Check that we can log in with the correct password.
   739  	info.Password = "foo"
   740  	session, err := mongo.DialWithInfo(*info, mongotest.DialOpts())
   741  	c.Assert(err, jc.ErrorIsNil)
   742  	defer session.Close()
   743  
   744  	pool1, err := state.OpenStatePool(state.OpenParams{
   745  		Clock:              clock.WallClock,
   746  		ControllerTag:      controllerTag,
   747  		ControllerModelTag: modelTag,
   748  		MongoSession:       session,
   749  	})
   750  	c.Assert(err, jc.ErrorIsNil)
   751  	defer pool1.Close()
   752  	st1, err := pool1.SystemState()
   753  	c.Assert(err, jc.ErrorIsNil)
   754  
   755  	// Change the password with an entity derived from the newly
   756  	// opened and authenticated state.
   757  	ent, err = entityFunc(st1, "0")
   758  	c.Assert(err, jc.ErrorIsNil)
   759  	err = ent.SetMongoPassword("bar")
   760  	c.Assert(err, jc.ErrorIsNil)
   761  
   762  	// Check that we cannot log in with the old password.
   763  	info.Password = "foo"
   764  	err = tryOpenState(modelTag, controllerTag, info)
   765  	c.Check(errors.Cause(err), jc.Satisfies, errors.IsUnauthorized)
   766  	c.Check(err, gc.ErrorMatches, `cannot log in to admin database as "(machine|controller)-0": unauthorized mongo access: .*`)
   767  
   768  	// Check that we can log in with the correct password.
   769  	info.Password = "bar"
   770  	err = tryOpenState(modelTag, controllerTag, info)
   771  	c.Assert(err, jc.ErrorIsNil)
   772  
   773  	// Check that the administrator can still log in.
   774  	info.Tag, info.Password = nil, "admin-secret"
   775  	err = tryOpenState(modelTag, controllerTag, info)
   776  	c.Assert(err, jc.ErrorIsNil)
   777  }
   778  
   779  func (s *MachineSuite) TestSetPassword(c *gc.C) {
   780  	testSetPassword(c, func() (state.Authenticator, error) {
   781  		return s.State.Machine(s.machine.Id())
   782  	})
   783  }
   784  
   785  func (s *MachineSuite) TestMachineInstanceIdCorrupt(c *gc.C) {
   786  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
   787  	c.Assert(err, jc.ErrorIsNil)
   788  	err = s.machines.Update(
   789  		bson.D{{"_id", state.DocID(s.State, machine.Id())}},
   790  		bson.D{{"$set", bson.D{{"instanceid", bson.D{{"foo", "bar"}}}}}},
   791  	)
   792  	c.Assert(err, jc.ErrorIsNil)
   793  
   794  	err = machine.Refresh()
   795  	c.Assert(err, jc.ErrorIsNil)
   796  	iid, err := machine.InstanceId()
   797  	c.Assert(err, jc.Satisfies, errors.IsNotProvisioned)
   798  	c.Assert(iid, gc.Equals, instance.Id(""))
   799  }
   800  
   801  func (s *MachineSuite) TestMachineInstanceIdMissing(c *gc.C) {
   802  	iid, err := s.machine.InstanceId()
   803  	c.Assert(err, jc.Satisfies, errors.IsNotProvisioned)
   804  	c.Assert(string(iid), gc.Equals, "")
   805  }
   806  
   807  func (s *MachineSuite) TestMachineInstanceIdBlank(c *gc.C) {
   808  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
   809  	c.Assert(err, jc.ErrorIsNil)
   810  	err = s.machines.Update(
   811  		bson.D{{"_id", state.DocID(s.State, machine.Id())}},
   812  		bson.D{{"$set", bson.D{{"instanceid", ""}}}},
   813  	)
   814  	c.Assert(err, jc.ErrorIsNil)
   815  
   816  	err = machine.Refresh()
   817  	c.Assert(err, jc.ErrorIsNil)
   818  	iid, err := machine.InstanceId()
   819  	c.Assert(err, jc.Satisfies, errors.IsNotProvisioned)
   820  	c.Assert(string(iid), gc.Equals, "")
   821  }
   822  
   823  func (s *MachineSuite) TestMachineSetProvisionedStoresAndInstanceNamesReturnsDisplayName(c *gc.C) {
   824  	c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse)
   825  	err := s.machine.SetProvisioned("umbrella/0", "snowflake", "fake_nonce", nil)
   826  	c.Assert(err, jc.ErrorIsNil)
   827  
   828  	iid, iname, err := s.machine.InstanceNames()
   829  	c.Assert(err, jc.ErrorIsNil)
   830  	c.Assert(string(iid), gc.Equals, "umbrella/0")
   831  	c.Assert(iname, gc.Equals, "snowflake")
   832  
   833  	all, err := s.Model.AllInstanceData()
   834  	c.Assert(err, jc.ErrorIsNil)
   835  	iid, iname = all.InstanceNames(s.machine.Id())
   836  	c.Assert(string(iid), gc.Equals, "umbrella/0")
   837  	c.Assert(iname, gc.Equals, "snowflake")
   838  }
   839  
   840  func (s *MachineSuite) TestMachineInstanceNamesReturnsIsNotProvisionedWhenNotProvisioned(c *gc.C) {
   841  	iid, iname, err := s.machine.InstanceNames()
   842  	c.Assert(err, jc.Satisfies, errors.IsNotProvisioned)
   843  	c.Assert(string(iid), gc.Equals, "")
   844  	c.Assert(iname, gc.Equals, "")
   845  }
   846  
   847  func (s *MachineSuite) TestMachineSetProvisionedUpdatesCharacteristics(c *gc.C) {
   848  	// Before provisioning, there is no hardware characteristics.
   849  	_, err := s.machine.HardwareCharacteristics()
   850  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   851  	arch := arch.DefaultArchitecture
   852  	mem := uint64(4096)
   853  	expected := &instance.HardwareCharacteristics{
   854  		Arch: &arch,
   855  		Mem:  &mem,
   856  	}
   857  	err = s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", expected)
   858  	c.Assert(err, jc.ErrorIsNil)
   859  	md, err := s.machine.HardwareCharacteristics()
   860  	c.Assert(err, jc.ErrorIsNil)
   861  	c.Assert(*md, gc.DeepEquals, *expected)
   862  
   863  	// Reload machine and check again.
   864  	err = s.machine.Refresh()
   865  	c.Assert(err, jc.ErrorIsNil)
   866  	md, err = s.machine.HardwareCharacteristics()
   867  	c.Assert(err, jc.ErrorIsNil)
   868  	c.Assert(*md, gc.DeepEquals, *expected)
   869  
   870  	all, err := s.Model.AllInstanceData()
   871  	c.Assert(err, jc.ErrorIsNil)
   872  	md = all.HardwareCharacteristics(s.machine.Id())
   873  	c.Assert(*md, gc.DeepEquals, *expected)
   874  }
   875  
   876  func (s *MachineSuite) TestMachineCharmProfiles(c *gc.C) {
   877  	hwc := &instance.HardwareCharacteristics{}
   878  	err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", hwc)
   879  	c.Assert(err, jc.ErrorIsNil)
   880  
   881  	profiles := []string{"secure", "magic"}
   882  	err = s.machine.SetCharmProfiles(profiles)
   883  	c.Assert(err, jc.ErrorIsNil)
   884  
   885  	saved, err := s.machine.CharmProfiles()
   886  	c.Assert(err, jc.ErrorIsNil)
   887  	c.Assert(saved, jc.SameContents, profiles)
   888  
   889  	all, err := s.Model.AllInstanceData()
   890  	c.Assert(err, jc.ErrorIsNil)
   891  	saved = all.CharmProfiles(s.machine.Id())
   892  	c.Assert(saved, jc.SameContents, profiles)
   893  }
   894  
   895  func (s *MachineSuite) TestMachineAvailabilityZone(c *gc.C) {
   896  	zone := "a_zone"
   897  	hwc := &instance.HardwareCharacteristics{
   898  		AvailabilityZone: &zone,
   899  	}
   900  	err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", hwc)
   901  	c.Assert(err, jc.ErrorIsNil)
   902  
   903  	zone, err = s.machine.AvailabilityZone()
   904  	c.Assert(err, jc.ErrorIsNil)
   905  	c.Check(zone, gc.Equals, "a_zone")
   906  }
   907  
   908  func (s *MachineSuite) TestContainerAvailabilityZone(c *gc.C) {
   909  	zone := "a_zone"
   910  	hwc := &instance.HardwareCharacteristics{
   911  		AvailabilityZone: &zone,
   912  	}
   913  	err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", hwc)
   914  	c.Assert(err, jc.ErrorIsNil)
   915  
   916  	zone, err = s.machine.AvailabilityZone()
   917  	c.Assert(err, jc.ErrorIsNil)
   918  	c.Check(zone, gc.Equals, "a_zone")
   919  
   920  	// now add a container to that machine
   921  	container := s.Factory.MakeMachineNested(c, s.machine.Id(), nil)
   922  	c.Assert(err, jc.ErrorIsNil)
   923  
   924  	containerAvailabilityZone, err := container.AvailabilityZone()
   925  	c.Assert(err, jc.ErrorIsNil)
   926  	c.Assert(containerAvailabilityZone, gc.Equals, "")
   927  }
   928  
   929  func (s *MachineSuite) TestMachineAvailabilityZoneEmpty(c *gc.C) {
   930  	zone := ""
   931  	hwc := &instance.HardwareCharacteristics{
   932  		AvailabilityZone: &zone,
   933  	}
   934  	err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", hwc)
   935  	c.Assert(err, jc.ErrorIsNil)
   936  
   937  	zone, err = s.machine.AvailabilityZone()
   938  	c.Assert(err, jc.ErrorIsNil)
   939  	c.Check(zone, gc.Equals, "")
   940  }
   941  
   942  func (s *MachineSuite) TestMachineAvailabilityZoneMissing(c *gc.C) {
   943  	hwc := &instance.HardwareCharacteristics{}
   944  	err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", hwc)
   945  	c.Assert(err, jc.ErrorIsNil)
   946  
   947  	zone, err := s.machine.AvailabilityZone()
   948  	c.Assert(err, jc.ErrorIsNil)
   949  	c.Check(zone, gc.Equals, "")
   950  }
   951  
   952  func (s *MachineSuite) TestMachineSetCheckProvisioned(c *gc.C) {
   953  	// Check before provisioning.
   954  	c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse)
   955  
   956  	// Either one should not be empty.
   957  	err := s.machine.SetProvisioned("umbrella/0", "", "", nil)
   958  	c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`)
   959  	err = s.machine.SetProvisioned(instance.Id(""), "", "fake_nonce", nil)
   960  	c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`)
   961  	err = s.machine.SetProvisioned(instance.Id(""), "", "", nil)
   962  	c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`)
   963  
   964  	err = s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", nil)
   965  	c.Assert(err, jc.ErrorIsNil)
   966  
   967  	m, err := s.State.Machine(s.machine.Id())
   968  	c.Assert(err, jc.ErrorIsNil)
   969  	id, err := m.InstanceId()
   970  	c.Assert(err, jc.ErrorIsNil)
   971  	c.Assert(string(id), gc.Equals, "umbrella/0")
   972  	c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue)
   973  	id, err = s.machine.InstanceId()
   974  	c.Assert(err, jc.ErrorIsNil)
   975  	c.Assert(string(id), gc.Equals, "umbrella/0")
   976  	c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue)
   977  
   978  	// Try it twice, it should fail.
   979  	err = s.machine.SetProvisioned(instance.Id("doesn't-matter"), "", "phony", nil)
   980  	c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": already set`)
   981  
   982  	// Check it with invalid nonce.
   983  	c.Assert(s.machine.CheckProvisioned("not-really"), jc.IsFalse)
   984  }
   985  
   986  func (s *MachineSuite) TestSetProvisionedDupInstanceId(c *gc.C) {
   987  	var logWriter loggo.TestWriter
   988  	c.Assert(loggo.RegisterWriter("dupe-test", &logWriter), gc.IsNil)
   989  	s.AddCleanup(func(*gc.C) {
   990  		_, _ = loggo.RemoveWriter("dupe-test")
   991  	})
   992  
   993  	err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", nil)
   994  	c.Assert(err, jc.ErrorIsNil)
   995  
   996  	anotherMachine, _ := s.Factory.MakeUnprovisionedMachineReturningPassword(c, &factory.MachineParams{})
   997  	err = anotherMachine.SetProvisioned("umbrella/0", "", "another_nonce", nil)
   998  	c.Assert(err, jc.ErrorIsNil)
   999  	found := false
  1000  	for _, le := range logWriter.Log() {
  1001  		if found = strings.Contains(le.Message, "duplicate instance id"); found == true {
  1002  			break
  1003  		}
  1004  	}
  1005  	c.Assert(found, jc.IsTrue)
  1006  }
  1007  
  1008  func (s *MachineSuite) TestMachineSetInstanceInfoFailureDoesNotProvision(c *gc.C) {
  1009  	assertNotProvisioned := func() {
  1010  		c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse)
  1011  	}
  1012  
  1013  	assertNotProvisioned()
  1014  
  1015  	invalidVolumes := map[names.VolumeTag]state.VolumeInfo{
  1016  		names.NewVolumeTag("1065"): {VolumeId: "vol-ume"},
  1017  	}
  1018  	err := s.machine.SetInstanceInfo("umbrella/0", "", "fake_nonce", nil, nil, nil, invalidVolumes, nil, nil)
  1019  	c.Assert(err, gc.ErrorMatches, `cannot set info for volume \"1065\": volume \"1065\" not found`)
  1020  	assertNotProvisioned()
  1021  
  1022  	invalidVolumes = map[names.VolumeTag]state.VolumeInfo{
  1023  		names.NewVolumeTag("1065"): {},
  1024  	}
  1025  	err = s.machine.SetInstanceInfo("umbrella/0", "", "fake_nonce", nil, nil, nil, invalidVolumes, nil, nil)
  1026  	c.Assert(err, gc.ErrorMatches, `cannot set info for volume \"1065\": volume ID not set`)
  1027  	assertNotProvisioned()
  1028  
  1029  	// TODO(axw) test invalid volume attachment
  1030  }
  1031  
  1032  func (s *MachineSuite) addVolume(c *gc.C, params state.VolumeParams, machineId string) names.VolumeTag {
  1033  	ops, tag, err := state.AddVolumeOps(s.State, params, machineId)
  1034  	c.Assert(err, jc.ErrorIsNil)
  1035  	state.RunTransaction(c, s.State, ops)
  1036  	return tag
  1037  }
  1038  
  1039  func (s *MachineSuite) TestMachineSetInstanceInfoSuccess(c *gc.C) {
  1040  	pm := poolmanager.New(state.NewStateSettings(s.State), storage.ChainedProviderRegistry{
  1041  		dummystorage.StorageProviders(),
  1042  		provider.CommonStorageProviders(),
  1043  	})
  1044  	_, err := pm.Create("loop-pool", provider.LoopProviderType, map[string]interface{}{})
  1045  	c.Assert(err, jc.ErrorIsNil)
  1046  
  1047  	// Must create the requested block device prior to SetInstanceInfo.
  1048  	volumeTag := s.addVolume(c, state.VolumeParams{Size: 1000, Pool: "loop-pool"}, "123")
  1049  	c.Assert(volumeTag, gc.Equals, names.NewVolumeTag("123/0"))
  1050  
  1051  	c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse)
  1052  	volumeInfo := state.VolumeInfo{
  1053  		VolumeId: "storage-123",
  1054  		Size:     1234,
  1055  	}
  1056  	volumes := map[names.VolumeTag]state.VolumeInfo{volumeTag: volumeInfo}
  1057  	err = s.machine.SetInstanceInfo("umbrella/0", "", "fake_nonce", nil, nil, nil, volumes, nil, nil)
  1058  	c.Assert(err, jc.ErrorIsNil)
  1059  	c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue)
  1060  
  1061  	sb, err := state.NewStorageBackend(s.State)
  1062  	c.Assert(err, jc.ErrorIsNil)
  1063  	volume, err := sb.Volume(volumeTag)
  1064  	c.Assert(err, jc.ErrorIsNil)
  1065  	info, err := volume.Info()
  1066  	c.Assert(err, jc.ErrorIsNil)
  1067  	volumeInfo.Pool = "loop-pool" // taken from params
  1068  	c.Assert(info, gc.Equals, volumeInfo)
  1069  	volumeStatus, err := volume.Status()
  1070  	c.Assert(err, jc.ErrorIsNil)
  1071  	c.Assert(volumeStatus.Status, gc.Equals, status.Attaching)
  1072  }
  1073  
  1074  func (s *MachineSuite) TestMachineSetProvisionedWhenNotAlive(c *gc.C) {
  1075  	testWhenDying(c, s.machine, notAliveErr, notAliveErr, func() error {
  1076  		return s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", nil)
  1077  	})
  1078  }
  1079  
  1080  func (s *MachineSuite) TestMachineSetInstanceStatus(c *gc.C) {
  1081  	// Machine needs to be provisioned first.
  1082  	err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", nil)
  1083  	c.Assert(err, jc.ErrorIsNil)
  1084  
  1085  	now := coretesting.ZeroTime()
  1086  	sInfo := status.StatusInfo{
  1087  		Status:  status.Running,
  1088  		Message: "alive",
  1089  		Since:   &now,
  1090  	}
  1091  	err = s.machine.SetInstanceStatus(sInfo)
  1092  	c.Assert(err, jc.ErrorIsNil)
  1093  
  1094  	// Reload machine and check result.
  1095  	err = s.machine.Refresh()
  1096  	c.Assert(err, jc.ErrorIsNil)
  1097  	machineStatus, err := s.machine.InstanceStatus()
  1098  	c.Assert(err, jc.ErrorIsNil)
  1099  	c.Assert(machineStatus.Status, gc.DeepEquals, status.Running)
  1100  	c.Assert(machineStatus.Message, gc.DeepEquals, "alive")
  1101  }
  1102  
  1103  func (s *MachineSuite) TestMachineSetModificationStatus(c *gc.C) {
  1104  	// Machine needs to be provisioned first.
  1105  	err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", nil)
  1106  	c.Assert(err, jc.ErrorIsNil)
  1107  
  1108  	now := coretesting.ZeroTime()
  1109  	sInfo := status.StatusInfo{
  1110  		Status:  status.Applied,
  1111  		Message: "applied",
  1112  		Since:   &now,
  1113  	}
  1114  	err = s.machine.SetModificationStatus(sInfo)
  1115  	c.Assert(err, jc.ErrorIsNil)
  1116  
  1117  	// Reload machine and check result.
  1118  	err = s.machine.Refresh()
  1119  	c.Assert(err, jc.ErrorIsNil)
  1120  	machineStatus, err := s.machine.ModificationStatus()
  1121  	c.Assert(err, jc.ErrorIsNil)
  1122  	c.Assert(machineStatus.Status, gc.DeepEquals, status.Applied)
  1123  	c.Assert(machineStatus.Message, gc.DeepEquals, "applied")
  1124  }
  1125  
  1126  func (s *MachineSuite) TestMachineRefresh(c *gc.C) {
  1127  	m0, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1128  	c.Assert(err, jc.ErrorIsNil)
  1129  	oldTools, _ := m0.AgentTools()
  1130  	m1, err := s.State.Machine(m0.Id())
  1131  	c.Assert(err, jc.ErrorIsNil)
  1132  	err = m0.SetAgentVersion(version.MustParseBinary("0.0.3-ubuntu-amd64"))
  1133  	c.Assert(err, jc.ErrorIsNil)
  1134  	newTools, _ := m0.AgentTools()
  1135  
  1136  	m1Tools, _ := m1.AgentTools()
  1137  	c.Assert(m1Tools, gc.DeepEquals, oldTools)
  1138  	err = m1.Refresh()
  1139  	c.Assert(err, jc.ErrorIsNil)
  1140  	m1Tools, _ = m1.AgentTools()
  1141  	c.Assert(*m1Tools, gc.Equals, *newTools)
  1142  
  1143  	err = m0.EnsureDead()
  1144  	c.Assert(err, jc.ErrorIsNil)
  1145  	err = m0.Remove()
  1146  	c.Assert(err, jc.ErrorIsNil)
  1147  	err = m0.Refresh()
  1148  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1149  }
  1150  
  1151  func (s *MachineSuite) TestRefreshWhenNotAlive(c *gc.C) {
  1152  	// Refresh should work regardless of liveness status.
  1153  	testWhenDying(c, s.machine, noErr, noErr, func() error {
  1154  		return s.machine.Refresh()
  1155  	})
  1156  }
  1157  
  1158  func (s *MachineSuite) TestMachinePrincipalUnits(c *gc.C) {
  1159  	// Check that Machine.Units and st.UnitsFor work correctly.
  1160  
  1161  	// Make three machines, three applications and three units for each application;
  1162  	// variously assign units to machines and check that Machine.Units
  1163  	// tells us the right thing.
  1164  
  1165  	m1 := s.machine
  1166  	m2, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1167  	c.Assert(err, jc.ErrorIsNil)
  1168  	m3, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1169  	c.Assert(err, jc.ErrorIsNil)
  1170  
  1171  	dummy := s.AddTestingCharm(c, "dummy")
  1172  	logging := s.AddTestingCharm(c, "logging")
  1173  	s0 := s.AddTestingApplication(c, "s0", dummy)
  1174  	s1 := s.AddTestingApplication(c, "s1", dummy)
  1175  	s2 := s.AddTestingApplication(c, "s2", dummy)
  1176  	s3 := s.AddTestingApplication(c, "s3", logging)
  1177  
  1178  	units := make([][]*state.Unit, 4)
  1179  	for i, app := range []*state.Application{s0, s1, s2} {
  1180  		units[i] = make([]*state.Unit, 3)
  1181  		for j := range units[i] {
  1182  			units[i][j], err = app.AddUnit(state.AddUnitParams{})
  1183  			c.Assert(err, jc.ErrorIsNil)
  1184  		}
  1185  	}
  1186  
  1187  	// Principals must be assigned to a machine before then
  1188  	// enter scope to create subordinates.
  1189  	assignments := []struct {
  1190  		machine      *state.Machine
  1191  		units        []*state.Unit
  1192  		subordinates []*state.Unit
  1193  	}{
  1194  		{m1, []*state.Unit{units[0][0]}, nil},
  1195  		{m2, []*state.Unit{units[0][1], units[1][0], units[1][1], units[2][0]}, nil},
  1196  		{m3, []*state.Unit{units[2][2]}, nil},
  1197  	}
  1198  
  1199  	for _, a := range assignments {
  1200  		for _, u := range a.units {
  1201  			err := u.AssignToMachine(a.machine)
  1202  			c.Assert(err, jc.ErrorIsNil)
  1203  		}
  1204  	}
  1205  
  1206  	// Add the logging units subordinate to the s2 units.
  1207  	eps, err := s.State.InferEndpoints("s2", "s3")
  1208  	c.Assert(err, jc.ErrorIsNil)
  1209  	rel, err := s.State.AddRelation(eps...)
  1210  	c.Assert(err, jc.ErrorIsNil)
  1211  	for _, u := range units[2] {
  1212  		ru, err := rel.Unit(u)
  1213  		c.Assert(err, jc.ErrorIsNil)
  1214  		err = ru.EnterScope(nil)
  1215  		c.Assert(err, jc.ErrorIsNil)
  1216  	}
  1217  	units[3], err = s3.AllUnits()
  1218  	c.Assert(err, jc.ErrorIsNil)
  1219  	c.Assert(sortedUnitNames(units[3]), jc.DeepEquals, []string{"s3/0", "s3/1", "s3/2"})
  1220  	assignments[1].subordinates = []*state.Unit{units[3][0]}
  1221  	assignments[2].subordinates = []*state.Unit{units[3][2]}
  1222  
  1223  	for i, a := range assignments {
  1224  		c.Logf("test %d", i)
  1225  		expect := sortedUnitNames(append(a.units, a.subordinates...))
  1226  
  1227  		// The units can be retrieved from the machine model.
  1228  		got, err := a.machine.Units()
  1229  		c.Assert(err, jc.ErrorIsNil)
  1230  		c.Assert(sortedUnitNames(got), jc.DeepEquals, expect)
  1231  
  1232  		// The units can be retrieved from the machine id.
  1233  		got, err = s.State.UnitsFor(a.machine.Id())
  1234  		c.Assert(err, jc.ErrorIsNil)
  1235  		c.Assert(sortedUnitNames(got), jc.DeepEquals, expect)
  1236  	}
  1237  }
  1238  
  1239  func sortedUnitNames(units []*state.Unit) []string {
  1240  	names := make([]string, len(units))
  1241  	for i, u := range units {
  1242  		names[i] = u.Name()
  1243  	}
  1244  	sort.Strings(names)
  1245  	return names
  1246  }
  1247  
  1248  func (s *MachineSuite) assertMachineDirtyAfterAddingUnit(c *gc.C) (*state.Machine, *state.Application, *state.Unit) {
  1249  	m, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1250  	c.Assert(err, jc.ErrorIsNil)
  1251  	c.Assert(m.Clean(), jc.IsTrue)
  1252  
  1253  	app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
  1254  	unit, err := app.AddUnit(state.AddUnitParams{})
  1255  	c.Assert(err, jc.ErrorIsNil)
  1256  	err = unit.AssignToMachine(m)
  1257  	c.Assert(err, jc.ErrorIsNil)
  1258  	c.Assert(m.Clean(), jc.IsFalse)
  1259  	return m, app, unit
  1260  }
  1261  
  1262  func (s *MachineSuite) TestMachineDirtyAfterAddingUnit(c *gc.C) {
  1263  	s.assertMachineDirtyAfterAddingUnit(c)
  1264  }
  1265  
  1266  func (s *MachineSuite) TestMachineDirtyAfterUnassigningUnit(c *gc.C) {
  1267  	m, _, unit := s.assertMachineDirtyAfterAddingUnit(c)
  1268  	err := unit.UnassignFromMachine()
  1269  	c.Assert(err, jc.ErrorIsNil)
  1270  	c.Assert(m.Clean(), jc.IsFalse)
  1271  }
  1272  
  1273  func (s *MachineSuite) TestMachineDirtyAfterRemovingUnit(c *gc.C) {
  1274  	m, app, unit := s.assertMachineDirtyAfterAddingUnit(c)
  1275  	err := unit.EnsureDead()
  1276  	c.Assert(err, jc.ErrorIsNil)
  1277  	err = unit.Remove()
  1278  	c.Assert(err, jc.ErrorIsNil)
  1279  	err = app.Destroy()
  1280  	c.Assert(err, jc.ErrorIsNil)
  1281  	c.Assert(m.Clean(), jc.IsFalse)
  1282  }
  1283  
  1284  func (s *MachineSuite) TestWatchMachine(c *gc.C) {
  1285  	s.WaitForModelWatchersIdle(c, s.Model.UUID())
  1286  	w := s.machine.Watch()
  1287  	defer testing.AssertStop(c, w)
  1288  
  1289  	// Initial event.
  1290  	wc := testing.NewNotifyWatcherC(c, w)
  1291  	wc.AssertOneChange()
  1292  
  1293  	// Make one change (to a separate instance), check one event.
  1294  	machine, err := s.State.Machine(s.machine.Id())
  1295  	c.Assert(err, jc.ErrorIsNil)
  1296  	err = machine.SetProvisioned(instance.Id("m-foo"), "", "fake_nonce", nil)
  1297  	c.Assert(err, jc.ErrorIsNil)
  1298  	wc.AssertOneChange()
  1299  
  1300  	// Make two changes, check one event.
  1301  	err = machine.SetAgentVersion(version.MustParseBinary("0.0.3-ubuntu-amd64"))
  1302  	c.Assert(err, jc.ErrorIsNil)
  1303  	// TODO(quiescence): these two changes should be one event.
  1304  	wc.AssertOneChange()
  1305  	err = machine.Destroy()
  1306  	c.Assert(err, jc.ErrorIsNil)
  1307  	wc.AssertOneChange()
  1308  
  1309  	// Stop, check closed.
  1310  	testing.AssertStop(c, w)
  1311  	wc.AssertClosed()
  1312  
  1313  	// Remove machine, start new watch, check single event.
  1314  	err = machine.EnsureDead()
  1315  	c.Assert(err, jc.ErrorIsNil)
  1316  	err = machine.Remove()
  1317  	c.Assert(err, jc.ErrorIsNil)
  1318  	s.WaitForModelWatchersIdle(c, s.Model.UUID())
  1319  	w = s.machine.Watch()
  1320  	defer testing.AssertStop(c, w)
  1321  	testing.NewNotifyWatcherC(c, w).AssertOneChange()
  1322  }
  1323  
  1324  func (s *MachineSuite) TestWatchDiesOnStateClose(c *gc.C) {
  1325  	// This test is testing logic in watcher.entityWatcher, which
  1326  	// is also used by:
  1327  	//  Machine.WatchInstanceData
  1328  	//  Application.Watch
  1329  	//  Unit.Watch
  1330  	//  State.WatchForModelConfigChanges
  1331  	//  Unit.WatchConfigSettings
  1332  	testWatcherDiesWhenStateCloses(c, s.Session, s.modelTag, s.State.ControllerTag(), func(c *gc.C, st *state.State) waiter {
  1333  		m, err := st.Machine(s.machine.Id())
  1334  		c.Assert(err, jc.ErrorIsNil)
  1335  		w := m.Watch()
  1336  		select {
  1337  		case <-w.Changes():
  1338  		case <-time.After(coretesting.LongWait):
  1339  			c.Errorf("timeout waiting for Changes() to trigger")
  1340  		}
  1341  		return w
  1342  	})
  1343  }
  1344  
  1345  func (s *MachineSuite) TestWatchPrincipalUnits(c *gc.C) {
  1346  	// TODO(mjs) - MODELUUID - test with multiple models with
  1347  	// identically named units and ensure there's no leakage.
  1348  
  1349  	s.WaitForModelWatchersIdle(c, s.Model.UUID())
  1350  	// Start a watch on an empty machine; check no units reported.
  1351  	w := s.machine.WatchPrincipalUnits()
  1352  	defer testing.AssertStop(c, w)
  1353  	wc := testing.NewStringsWatcherC(c, w)
  1354  	wc.AssertChange()
  1355  	wc.AssertNoChange()
  1356  
  1357  	// Change machine, and create a unit independently; no change.
  1358  	err := s.machine.SetProvisioned("cheese", "", "fake_nonce", nil)
  1359  	c.Assert(err, jc.ErrorIsNil)
  1360  	wc.AssertNoChange()
  1361  	mysql := s.AddTestingApplication(c, "mysql", s.AddTestingCharm(c, "mysql"))
  1362  	mysql0, err := mysql.AddUnit(state.AddUnitParams{})
  1363  	c.Assert(err, jc.ErrorIsNil)
  1364  	wc.AssertNoChange()
  1365  
  1366  	// Assign that unit (to a separate machine instance); change detected.
  1367  	machine, err := s.State.Machine(s.machine.Id())
  1368  	c.Assert(err, jc.ErrorIsNil)
  1369  	err = mysql0.AssignToMachine(machine)
  1370  	c.Assert(err, jc.ErrorIsNil)
  1371  	wc.AssertChange("mysql/0")
  1372  	wc.AssertNoChange()
  1373  
  1374  	// Change the unit; no change.
  1375  	now := coretesting.ZeroTime()
  1376  	sInfo := status.StatusInfo{
  1377  		Status:  status.Idle,
  1378  		Message: "",
  1379  		Since:   &now,
  1380  	}
  1381  	err = mysql0.SetAgentStatus(sInfo)
  1382  	c.Assert(err, jc.ErrorIsNil)
  1383  	wc.AssertNoChange()
  1384  
  1385  	// Assign another unit and make the first Dying; check both changes detected.
  1386  	c.Logf("assigning unit and destroying other")
  1387  	mysql1, err := mysql.AddUnit(state.AddUnitParams{})
  1388  	c.Assert(err, jc.ErrorIsNil)
  1389  	err = mysql1.AssignToMachine(machine)
  1390  	c.Assert(err, jc.ErrorIsNil)
  1391  	err = mysql0.Destroy()
  1392  	c.Assert(err, jc.ErrorIsNil)
  1393  	wc.AssertChange("mysql/0", "mysql/1")
  1394  	wc.AssertNoChange()
  1395  
  1396  	// Add a subordinate to the Alive unit; no change.
  1397  	s.AddTestingApplication(c, "logging", s.AddTestingCharm(c, "logging"))
  1398  	eps, err := s.State.InferEndpoints("mysql", "logging")
  1399  	c.Assert(err, jc.ErrorIsNil)
  1400  	rel, err := s.State.AddRelation(eps...)
  1401  	c.Assert(err, jc.ErrorIsNil)
  1402  	mysqlru1, err := rel.Unit(mysql1)
  1403  	c.Assert(err, jc.ErrorIsNil)
  1404  	err = mysqlru1.EnterScope(nil)
  1405  	c.Assert(err, jc.ErrorIsNil)
  1406  	logging0, err := s.State.Unit("logging/0")
  1407  	c.Assert(err, jc.ErrorIsNil)
  1408  	wc.AssertNoChange()
  1409  
  1410  	// Change the subordinate; no change.
  1411  	sInfo = status.StatusInfo{
  1412  		Status:  status.Idle,
  1413  		Message: "",
  1414  		Since:   &now,
  1415  	}
  1416  	err = logging0.SetAgentStatus(sInfo)
  1417  	c.Assert(err, jc.ErrorIsNil)
  1418  	wc.AssertNoChange()
  1419  
  1420  	// Make the Dying unit Dead; change detected.
  1421  	err = mysql0.EnsureDead()
  1422  	c.Assert(err, jc.ErrorIsNil)
  1423  	wc.AssertChange("mysql/0")
  1424  	wc.AssertNoChange()
  1425  
  1426  	// Stop watcher; check Changes chan closed.
  1427  	testing.AssertStop(c, w)
  1428  	wc.AssertClosed()
  1429  
  1430  	s.WaitForModelWatchersIdle(c, s.Model.UUID())
  1431  	// Start a fresh watcher; check both principals reported.
  1432  	w = s.machine.WatchPrincipalUnits()
  1433  	defer testing.AssertStop(c, w)
  1434  	wc = testing.NewStringsWatcherC(c, w)
  1435  	wc.AssertChange("mysql/0", "mysql/1")
  1436  	wc.AssertNoChange()
  1437  
  1438  	// Remove the Dead unit; no change.
  1439  	err = mysql0.Remove()
  1440  	c.Assert(err, jc.ErrorIsNil)
  1441  	wc.AssertNoChange()
  1442  
  1443  	// Destroy the subordinate; no change.
  1444  	err = logging0.Destroy()
  1445  	c.Assert(err, jc.ErrorIsNil)
  1446  	wc.AssertNoChange()
  1447  
  1448  	// Unassign the unit; check change.
  1449  	err = mysql1.UnassignFromMachine()
  1450  	c.Assert(err, jc.ErrorIsNil)
  1451  	wc.AssertChange("mysql/1")
  1452  	wc.AssertNoChange()
  1453  }
  1454  
  1455  func (s *MachineSuite) TestWatchPrincipalUnitsDiesOnStateClose(c *gc.C) {
  1456  	// This test is testing logic in watcher.unitsWatcher, which
  1457  	// is also used by Unit.WatchSubordinateUnits.
  1458  	testWatcherDiesWhenStateCloses(c, s.Session, s.modelTag, s.State.ControllerTag(), func(c *gc.C, st *state.State) waiter {
  1459  		m, err := st.Machine(s.machine.Id())
  1460  		c.Assert(err, jc.ErrorIsNil)
  1461  		w := m.WatchPrincipalUnits()
  1462  		<-w.Changes()
  1463  		return w
  1464  	})
  1465  }
  1466  
  1467  func (s *MachineSuite) TestWatchUnits(c *gc.C) {
  1468  	s.WaitForModelWatchersIdle(c, s.Model.UUID())
  1469  	// Start a watch on an empty machine; check no units reported.
  1470  	w := s.machine.WatchUnits()
  1471  	defer testing.AssertStop(c, w)
  1472  	wc := testing.NewStringsWatcherC(c, w)
  1473  	wc.AssertChange()
  1474  	wc.AssertNoChange()
  1475  
  1476  	// Change machine; no change.
  1477  	err := s.machine.SetProvisioned("cheese", "", "fake_nonce", nil)
  1478  	c.Assert(err, jc.ErrorIsNil)
  1479  	wc.AssertNoChange()
  1480  
  1481  	// Assign a unit (to a separate instance); change detected.
  1482  	c.Logf("assigning mysql to machine %s", s.machine.Id())
  1483  	mysql := s.AddTestingApplication(c, "mysql", s.AddTestingCharm(c, "mysql"))
  1484  	mysql0, err := mysql.AddUnit(state.AddUnitParams{})
  1485  	c.Assert(err, jc.ErrorIsNil)
  1486  	machine, err := s.State.Machine(s.machine.Id())
  1487  	c.Assert(err, jc.ErrorIsNil)
  1488  	err = mysql0.AssignToMachine(machine)
  1489  	c.Assert(err, jc.ErrorIsNil)
  1490  	wc.AssertChange("mysql/0")
  1491  	wc.AssertNoChange()
  1492  
  1493  	// Change the unit; no change.
  1494  	c.Logf("changing unit mysql/0")
  1495  	now := coretesting.ZeroTime()
  1496  	sInfo := status.StatusInfo{
  1497  		Status:  status.Idle,
  1498  		Message: "",
  1499  		Since:   &now,
  1500  	}
  1501  	err = mysql0.SetAgentStatus(sInfo)
  1502  	c.Assert(err, jc.ErrorIsNil)
  1503  	wc.AssertNoChange()
  1504  
  1505  	// Assign another unit and make the first Dying; check both changes detected.
  1506  	c.Logf("assigning mysql/1, destroying mysql/0")
  1507  	mysql1, err := mysql.AddUnit(state.AddUnitParams{})
  1508  	c.Assert(err, jc.ErrorIsNil)
  1509  	err = mysql1.AssignToMachine(machine)
  1510  	c.Assert(err, jc.ErrorIsNil)
  1511  	err = mysql0.Destroy()
  1512  	c.Assert(err, jc.ErrorIsNil)
  1513  	wc.AssertChange("mysql/0", "mysql/1")
  1514  	wc.AssertNoChange()
  1515  
  1516  	// Add a subordinate to the Alive unit; change detected.
  1517  	c.Logf("adding subordinate logging/0")
  1518  	s.AddTestingApplication(c, "logging", s.AddTestingCharm(c, "logging"))
  1519  	eps, err := s.State.InferEndpoints("mysql", "logging")
  1520  	c.Assert(err, jc.ErrorIsNil)
  1521  	rel, err := s.State.AddRelation(eps...)
  1522  	c.Assert(err, jc.ErrorIsNil)
  1523  	mysqlru1, err := rel.Unit(mysql1)
  1524  	c.Assert(err, jc.ErrorIsNil)
  1525  	err = mysqlru1.EnterScope(nil)
  1526  	c.Assert(err, jc.ErrorIsNil)
  1527  	logging0, err := s.State.Unit("logging/0")
  1528  	c.Assert(err, jc.ErrorIsNil)
  1529  	wc.AssertChange("logging/0")
  1530  	wc.AssertNoChange()
  1531  
  1532  	// Change the subordinate; no change.
  1533  	c.Logf("changing subordinate")
  1534  	sInfo = status.StatusInfo{
  1535  		Status:  status.Idle,
  1536  		Message: "",
  1537  		Since:   &now,
  1538  	}
  1539  	err = logging0.SetAgentStatus(sInfo)
  1540  	c.Assert(err, jc.ErrorIsNil)
  1541  	wc.AssertNoChange()
  1542  
  1543  	// Make the Dying unit Dead; change detected.
  1544  	c.Logf("ensuring mysql/0 is Dead")
  1545  	err = mysql0.EnsureDead()
  1546  	c.Assert(err, jc.ErrorIsNil)
  1547  	wc.AssertChange("mysql/0")
  1548  	wc.AssertNoChange()
  1549  
  1550  	// Stop watcher; check Changes chan closed.
  1551  	testing.AssertStop(c, w)
  1552  	wc.AssertClosed()
  1553  
  1554  	// Start a fresh watcher; check all units reported.
  1555  	c.Logf("starting new watcher")
  1556  	w = s.machine.WatchUnits()
  1557  	defer testing.AssertStop(c, w)
  1558  	wc = testing.NewStringsWatcherC(c, w)
  1559  	wc.AssertChange("mysql/0", "mysql/1", "logging/0")
  1560  	wc.AssertNoChange()
  1561  
  1562  	// Remove the Dead unit; no change.
  1563  	c.Logf("removing Dead unit mysql/0")
  1564  	err = mysql0.Remove()
  1565  	c.Assert(err, jc.ErrorIsNil)
  1566  	wc.AssertNoChange()
  1567  
  1568  	// Destroy the subordinate; change detected.
  1569  	c.Logf("destroying subordinate logging/0")
  1570  	err = logging0.Destroy()
  1571  	c.Assert(err, jc.ErrorIsNil)
  1572  	wc.AssertChange("logging/0")
  1573  	wc.AssertNoChange()
  1574  
  1575  	// Unassign the principal; check subordinate departure also reported.
  1576  	c.Logf("unassigning mysql/1")
  1577  	err = mysql1.UnassignFromMachine()
  1578  	c.Assert(err, jc.ErrorIsNil)
  1579  	wc.AssertChange("mysql/1", "logging/0")
  1580  	wc.AssertNoChange()
  1581  }
  1582  
  1583  func (s *MachineSuite) TestWatchUnitsHandlesDeletedEntries(c *gc.C) {
  1584  	s.WaitForModelWatchersIdle(c, s.Model.UUID())
  1585  	w := s.machine.WatchUnits()
  1586  	defer testing.AssertStop(c, w)
  1587  	wc := testing.NewStringsWatcherC(c, w)
  1588  	wc.AssertChange()
  1589  	wc.AssertNoChange()
  1590  
  1591  	// Change machine; no change.
  1592  	err := s.machine.SetProvisioned("cheese", "", "fake_nonce", nil)
  1593  	c.Assert(err, jc.ErrorIsNil)
  1594  	wc.AssertNoChange()
  1595  
  1596  	// Assign a unit (to a separate instance); change detected.
  1597  	c.Logf("assigning mysql to machine %s", s.machine.Id())
  1598  	mysql := s.AddTestingApplication(c, "mysql", s.AddTestingCharm(c, "mysql"))
  1599  	mysql0, err := mysql.AddUnit(state.AddUnitParams{})
  1600  	c.Assert(err, jc.ErrorIsNil)
  1601  	machine, err := s.State.Machine(s.machine.Id())
  1602  	c.Assert(err, jc.ErrorIsNil)
  1603  	err = mysql0.AssignToMachine(machine)
  1604  	c.Assert(err, jc.ErrorIsNil)
  1605  	wc.AssertChange("mysql/0")
  1606  	wc.AssertNoChange()
  1607  
  1608  	// Destroy the instance before checking the change
  1609  	err = mysql0.EnsureDead()
  1610  	c.Assert(err, jc.ErrorIsNil)
  1611  	err = mysql0.Remove()
  1612  	c.Assert(err, jc.ErrorIsNil)
  1613  	wc.AssertChange("mysql/0")
  1614  	wc.AssertNoChange()
  1615  }
  1616  
  1617  func (s *MachineSuite) TestApplicationNames(c *gc.C) {
  1618  	mysql := s.AddTestingApplication(c, "mysql", s.AddTestingCharm(c, "mysql"))
  1619  	wordpress := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
  1620  
  1621  	mysql0, err := mysql.AddUnit(state.AddUnitParams{})
  1622  	c.Assert(err, jc.ErrorIsNil)
  1623  	mysql1, err := mysql.AddUnit(state.AddUnitParams{})
  1624  	c.Assert(err, jc.ErrorIsNil)
  1625  	worpress0, err := wordpress.AddUnit(state.AddUnitParams{})
  1626  	c.Assert(err, jc.ErrorIsNil)
  1627  
  1628  	machine, err := s.State.Machine(s.machine.Id())
  1629  	c.Assert(err, jc.ErrorIsNil)
  1630  	err = mysql0.AssignToMachine(machine)
  1631  	c.Assert(err, jc.ErrorIsNil)
  1632  	err = mysql1.AssignToMachine(machine)
  1633  	c.Assert(err, jc.ErrorIsNil)
  1634  	err = worpress0.AssignToMachine(machine)
  1635  	c.Assert(err, jc.ErrorIsNil)
  1636  
  1637  	apps, err := machine.ApplicationNames()
  1638  	c.Assert(err, jc.ErrorIsNil)
  1639  	c.Check(apps, jc.DeepEquals, []string{"mysql", "wordpress"})
  1640  }
  1641  
  1642  func (s *MachineSuite) TestWatchUnitsDiesOnStateClose(c *gc.C) {
  1643  	testWatcherDiesWhenStateCloses(c, s.Session, s.modelTag, s.State.ControllerTag(), func(c *gc.C, st *state.State) waiter {
  1644  		m, err := st.Machine(s.machine.Id())
  1645  		c.Assert(err, jc.ErrorIsNil)
  1646  		w := m.WatchUnits()
  1647  		<-w.Changes()
  1648  		return w
  1649  	})
  1650  }
  1651  
  1652  func (s *MachineSuite) TestWatchMachineStartTimes(c *gc.C) {
  1653  	// Machine needs to be provisioned first.
  1654  	err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", nil)
  1655  	c.Assert(err, jc.ErrorIsNil)
  1656  
  1657  	quiesceInterval := 10 * time.Second
  1658  	s.WaitForModelWatchersIdle(c, s.Model.UUID())
  1659  	w := s.State.WatchModelMachineStartTimes(quiesceInterval)
  1660  
  1661  	defer testing.AssertStop(c, w)
  1662  	wc := testing.NewStringsWatcherC(c, w)
  1663  
  1664  	// Get initial set of changes
  1665  	s.WaitForModelWatchersIdle(c, s.Model.UUID())
  1666  	s.Clock.Advance(quiesceInterval)
  1667  	wc.AssertChange("0", "1")
  1668  	wc.AssertNoChange()
  1669  
  1670  	// Update the agent start time for the new machine and wait for quiesceInterval
  1671  	// so the change gets processed and added to a new changeset.
  1672  	err = s.machine.RecordAgentStartInformation("machine-1")
  1673  	c.Assert(err, jc.ErrorIsNil)
  1674  	s.WaitForModelWatchersIdle(c, s.Model.UUID())
  1675  	s.Clock.Advance(quiesceInterval)
  1676  
  1677  	// Update the agent start time for machine 0 and wait for quiesceInterval
  1678  	// so the change gets processed and appended to the current changeset.
  1679  	err = s.machine0.RecordAgentStartInformation("machine-0")
  1680  	c.Assert(err, jc.ErrorIsNil)
  1681  	s.WaitForModelWatchersIdle(c, s.Model.UUID())
  1682  	s.Clock.Advance(quiesceInterval)
  1683  
  1684  	// Fetch the pending changes
  1685  	wc.AssertChange("1", "0")
  1686  	wc.AssertNoChange()
  1687  
  1688  	// Kill the machine, remove it from state and check ensure that we
  1689  	// still get back a change event.
  1690  	err = s.machine.Destroy()
  1691  	c.Assert(err, jc.ErrorIsNil)
  1692  	s.WaitForModelWatchersIdle(c, s.Model.UUID())
  1693  	err = s.machine.EnsureDead()
  1694  	c.Assert(err, jc.ErrorIsNil)
  1695  	err = s.machine.Remove()
  1696  	c.Assert(err, jc.ErrorIsNil)
  1697  	s.Clock.Advance(quiesceInterval)
  1698  	wc.AssertChange("1")
  1699  	wc.AssertNoChange()
  1700  }
  1701  
  1702  func (s *MachineSuite) TestConstraintsFromModel(c *gc.C) {
  1703  	econs1 := constraints.MustParse("mem=1G")
  1704  	econs2 := constraints.MustParse("mem=2G")
  1705  
  1706  	// A newly-created machine gets a copy of the model constraints.
  1707  	err := s.State.SetModelConstraints(econs1)
  1708  	c.Assert(err, jc.ErrorIsNil)
  1709  	machine1, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1710  	c.Assert(err, jc.ErrorIsNil)
  1711  	mcons1, err := machine1.Constraints()
  1712  	c.Assert(err, jc.ErrorIsNil)
  1713  	c.Assert(mcons1, gc.DeepEquals, econs1)
  1714  
  1715  	// Change model constraints and add a new machine.
  1716  	err = s.State.SetModelConstraints(econs2)
  1717  	c.Assert(err, jc.ErrorIsNil)
  1718  	machine2, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1719  	c.Assert(err, jc.ErrorIsNil)
  1720  	mcons2, err := machine2.Constraints()
  1721  	c.Assert(err, jc.ErrorIsNil)
  1722  	c.Assert(mcons2, gc.DeepEquals, econs2)
  1723  
  1724  	// Check the original machine has its original constraints.
  1725  	mcons1, err = machine1.Constraints()
  1726  	c.Assert(err, jc.ErrorIsNil)
  1727  	c.Assert(mcons1, gc.DeepEquals, econs1)
  1728  }
  1729  
  1730  func (s *MachineSuite) TestSetConstraints(c *gc.C) {
  1731  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1732  	c.Assert(err, jc.ErrorIsNil)
  1733  
  1734  	// Constraints can be set...
  1735  	cons1 := constraints.MustParse("mem=1G")
  1736  	err = machine.SetConstraints(cons1)
  1737  	c.Assert(err, jc.ErrorIsNil)
  1738  	mcons, err := machine.Constraints()
  1739  	c.Assert(err, jc.ErrorIsNil)
  1740  	c.Assert(mcons, gc.DeepEquals, cons1)
  1741  
  1742  	// ...until the machine is provisioned, at which point they stick.
  1743  	err = machine.SetProvisioned("i-mstuck", "", "fake_nonce", nil)
  1744  	c.Assert(err, jc.ErrorIsNil)
  1745  	cons2 := constraints.MustParse("mem=2G")
  1746  	err = machine.SetConstraints(cons2)
  1747  	c.Assert(err, gc.ErrorMatches, `updating machine "2": cannot set constraints: machine is already provisioned`)
  1748  
  1749  	// Check the failed set had no effect.
  1750  	mcons, err = machine.Constraints()
  1751  	c.Assert(err, jc.ErrorIsNil)
  1752  	c.Assert(mcons, gc.DeepEquals, cons1)
  1753  
  1754  	all, err := s.Model.AllConstraints()
  1755  	c.Assert(err, jc.ErrorIsNil)
  1756  	cons := all.Machine(machine.Id())
  1757  	c.Assert(cons, gc.DeepEquals, cons1)
  1758  }
  1759  
  1760  func (s *MachineSuite) TestSetAmbiguousConstraints(c *gc.C) {
  1761  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1762  	c.Assert(err, jc.ErrorIsNil)
  1763  	cons := constraints.MustParse("mem=4G instance-type=foo")
  1764  	err = machine.SetConstraints(cons)
  1765  	c.Assert(err, gc.ErrorMatches, `updating machine "2": cannot set constraints: ambiguous constraints: "instance-type" overlaps with "mem"`)
  1766  }
  1767  
  1768  func (s *MachineSuite) TestSetUnsupportedConstraintsWarning(c *gc.C) {
  1769  	defer loggo.ResetWriters()
  1770  	logger := loggo.GetLogger("test")
  1771  	logger.SetLogLevel(loggo.DEBUG)
  1772  	var tw loggo.TestWriter
  1773  	c.Assert(loggo.RegisterWriter("constraints-tester", &tw), gc.IsNil)
  1774  
  1775  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1776  	c.Assert(err, jc.ErrorIsNil)
  1777  	cons := constraints.MustParse("mem=4G cpu-power=10")
  1778  	err = machine.SetConstraints(cons)
  1779  	c.Assert(err, jc.ErrorIsNil)
  1780  	c.Assert(tw.Log(), jc.LogMatches, jc.SimpleMessages{{
  1781  		loggo.WARNING,
  1782  		`setting constraints on machine "2": unsupported constraints: cpu-power`},
  1783  	})
  1784  	mcons, err := machine.Constraints()
  1785  	c.Assert(err, jc.ErrorIsNil)
  1786  	c.Assert(mcons, gc.DeepEquals, cons)
  1787  }
  1788  
  1789  func (s *MachineSuite) TestConstraintsLifecycle(c *gc.C) {
  1790  	cons := constraints.MustParse("mem=1G")
  1791  	cannotSet := `updating machine "1": cannot set constraints: machine is not found or not alive`
  1792  	testWhenDying(c, s.machine, cannotSet, cannotSet, func() error {
  1793  		err := s.machine.SetConstraints(cons)
  1794  		mcons, err1 := s.machine.Constraints()
  1795  		c.Assert(err1, gc.IsNil)
  1796  		c.Assert(&mcons, jc.Satisfies, constraints.IsEmpty)
  1797  		return err
  1798  	})
  1799  
  1800  	err := s.machine.Remove()
  1801  	c.Assert(err, jc.ErrorIsNil)
  1802  	err = s.machine.SetConstraints(cons)
  1803  	c.Assert(err, gc.ErrorMatches, cannotSet)
  1804  	_, err = s.machine.Constraints()
  1805  	c.Assert(err, gc.ErrorMatches, `constraints not found`)
  1806  }
  1807  
  1808  func (s *MachineSuite) TestSetProviderAddresses(c *gc.C) {
  1809  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1810  	c.Assert(err, jc.ErrorIsNil)
  1811  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1812  
  1813  	addresses := network.SpaceAddresses{
  1814  		network.NewSpaceAddress("127.0.0.1"),
  1815  		{
  1816  			MachineAddress: network.MachineAddress{
  1817  				Value: "8.8.8.8",
  1818  				Type:  network.IPv4Address,
  1819  				Scope: network.ScopeCloudLocal,
  1820  			},
  1821  			SpaceID: "1",
  1822  		},
  1823  	}
  1824  	err = machine.SetProviderAddresses(addresses...)
  1825  	c.Assert(err, jc.ErrorIsNil)
  1826  	err = machine.Refresh()
  1827  	c.Assert(err, jc.ErrorIsNil)
  1828  
  1829  	sort.Sort(addresses)
  1830  	c.Assert(machine.Addresses(), jc.DeepEquals, addresses)
  1831  }
  1832  
  1833  func (s *MachineSuite) TestSetProviderAddressesWithContainers(c *gc.C) {
  1834  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1835  	c.Assert(err, jc.ErrorIsNil)
  1836  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1837  
  1838  	// When setting all addresses the subnet addresses have to be
  1839  	// filtered out.
  1840  	addresses := network.NewSpaceAddresses(
  1841  		"127.0.0.1",
  1842  		"8.8.8.8",
  1843  	)
  1844  	err = machine.SetProviderAddresses(addresses...)
  1845  	c.Assert(err, jc.ErrorIsNil)
  1846  	err = machine.Refresh()
  1847  	c.Assert(err, jc.ErrorIsNil)
  1848  
  1849  	expectedAddresses := network.NewSpaceAddresses("8.8.8.8", "127.0.0.1")
  1850  	c.Assert(machine.Addresses(), jc.DeepEquals, expectedAddresses)
  1851  }
  1852  
  1853  func (s *MachineSuite) TestSetProviderAddressesOnContainer(c *gc.C) {
  1854  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1855  	c.Assert(err, jc.ErrorIsNil)
  1856  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1857  
  1858  	// Create an LXC container inside the machine.
  1859  	template := state.MachineTemplate{
  1860  		Base: state.UbuntuBase("12.10"),
  1861  		Jobs: []state.MachineJob{state.JobHostUnits},
  1862  	}
  1863  	container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXD)
  1864  	c.Assert(err, jc.ErrorIsNil)
  1865  
  1866  	// When setting all addresses the subnet address has to accepted.
  1867  	addresses := network.NewSpaceAddresses("127.0.0.1")
  1868  	err = container.SetProviderAddresses(addresses...)
  1869  	c.Assert(err, jc.ErrorIsNil)
  1870  	err = container.Refresh()
  1871  	c.Assert(err, jc.ErrorIsNil)
  1872  
  1873  	expectedAddresses := network.NewSpaceAddresses("127.0.0.1")
  1874  	c.Assert(container.Addresses(), jc.DeepEquals, expectedAddresses)
  1875  }
  1876  
  1877  func (s *MachineSuite) TestSetMachineAddresses(c *gc.C) {
  1878  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1879  	c.Assert(err, jc.ErrorIsNil)
  1880  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1881  
  1882  	addresses := network.NewSpaceAddresses("127.0.0.1", "8.8.8.8")
  1883  	err = machine.SetMachineAddresses(addresses...)
  1884  	c.Assert(err, jc.ErrorIsNil)
  1885  	err = machine.Refresh()
  1886  	c.Assert(err, jc.ErrorIsNil)
  1887  
  1888  	expectedAddresses := network.NewSpaceAddresses("8.8.8.8", "127.0.0.1")
  1889  	c.Assert(machine.MachineAddresses(), jc.DeepEquals, expectedAddresses)
  1890  }
  1891  
  1892  func (s *MachineSuite) TestSetEmptyMachineAddresses(c *gc.C) {
  1893  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1894  	c.Assert(err, jc.ErrorIsNil)
  1895  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1896  
  1897  	// Add some machine addresses initially to make sure they're removed.
  1898  	addresses := network.NewSpaceAddresses("127.0.0.1", "8.8.8.8")
  1899  	err = machine.SetMachineAddresses(addresses...)
  1900  	c.Assert(err, jc.ErrorIsNil)
  1901  	err = machine.Refresh()
  1902  	c.Assert(err, jc.ErrorIsNil)
  1903  	c.Assert(machine.MachineAddresses(), gc.HasLen, 2)
  1904  
  1905  	// Make call with empty address list.
  1906  	err = machine.SetMachineAddresses()
  1907  	c.Assert(err, jc.ErrorIsNil)
  1908  	err = machine.Refresh()
  1909  	c.Assert(err, jc.ErrorIsNil)
  1910  
  1911  	c.Assert(machine.MachineAddresses(), gc.HasLen, 0)
  1912  }
  1913  
  1914  func (s *MachineSuite) TestMergedAddresses(c *gc.C) {
  1915  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1916  	c.Assert(err, jc.ErrorIsNil)
  1917  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1918  
  1919  	providerAddresses := network.NewSpaceAddresses(
  1920  		"127.0.0.2",
  1921  		"8.8.8.8",
  1922  		"fc00::1",
  1923  		"::1",
  1924  		"",
  1925  		"2001:db8::1",
  1926  		"127.0.0.2",
  1927  		"example.org",
  1928  	)
  1929  	err = machine.SetProviderAddresses(providerAddresses...)
  1930  	c.Assert(err, jc.ErrorIsNil)
  1931  
  1932  	machineAddresses := network.NewSpaceAddresses(
  1933  		"127.0.0.1",
  1934  		"localhost",
  1935  		"2001:db8::1",
  1936  		"192.168.0.1",
  1937  		"fe80::1",
  1938  		"::1",
  1939  		"fd00::1",
  1940  	)
  1941  	err = machine.SetMachineAddresses(machineAddresses...)
  1942  	c.Assert(err, jc.ErrorIsNil)
  1943  	err = machine.Refresh()
  1944  	c.Assert(err, jc.ErrorIsNil)
  1945  
  1946  	// Before setting the addresses coming from either the provider or
  1947  	// the machine itself, they are sorted to prefer public IPs on
  1948  	// top, then hostnames, cloud-local, machine-local, link-local.
  1949  	// Duplicates are removed, then when calling Addresses() both
  1950  	// sources are merged while preservig the provider addresses
  1951  	// order.
  1952  	c.Assert(machine.Addresses(), jc.DeepEquals, network.NewSpaceAddresses(
  1953  		"8.8.8.8",
  1954  		"2001:db8::1",
  1955  		"example.org",
  1956  		"fc00::1",
  1957  		"127.0.0.2",
  1958  		"::1",
  1959  		"localhost",
  1960  		"192.168.0.1",
  1961  		"fd00::1",
  1962  		"127.0.0.1",
  1963  		"fe80::1",
  1964  	))
  1965  }
  1966  
  1967  func (s *MachineSuite) TestSetProviderAddressesConcurrentChangeDifferent(c *gc.C) {
  1968  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1969  	c.Assert(err, jc.ErrorIsNil)
  1970  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1971  
  1972  	addr0 := network.NewSpaceAddress("127.0.0.1")
  1973  	addr1 := network.NewSpaceAddress("8.8.8.8")
  1974  
  1975  	defer state.SetBeforeHooks(c, s.State, func() {
  1976  		machine, err := s.State.Machine(machine.Id())
  1977  		c.Assert(err, jc.ErrorIsNil)
  1978  		err = machine.SetProviderAddresses(addr1, addr0)
  1979  		c.Assert(err, jc.ErrorIsNil)
  1980  	}).Check()
  1981  
  1982  	err = machine.SetProviderAddresses(addr0, addr1)
  1983  	c.Assert(err, jc.ErrorIsNil)
  1984  	c.Assert(machine.Addresses(), jc.SameContents, network.SpaceAddresses{addr0, addr1})
  1985  }
  1986  
  1987  func (s *MachineSuite) TestSetProviderAddressesConcurrentChangeEqual(c *gc.C) {
  1988  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  1989  	c.Assert(err, jc.ErrorIsNil)
  1990  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1991  	machineDocID := state.DocID(s.State, machine.Id())
  1992  	revno0, err := state.TxnRevno(s.State, "machines", machineDocID)
  1993  	c.Assert(err, jc.ErrorIsNil)
  1994  
  1995  	addr0 := network.NewSpaceAddress("127.0.0.1")
  1996  	addr1 := network.NewSpaceAddress("8.8.8.8")
  1997  
  1998  	var revno1 int64
  1999  	defer state.SetBeforeHooks(c, s.State, func() {
  2000  		machine, err := s.State.Machine(machine.Id())
  2001  		c.Assert(err, jc.ErrorIsNil)
  2002  		err = machine.SetProviderAddresses(addr0, addr1)
  2003  		c.Assert(err, jc.ErrorIsNil)
  2004  		revno1, err = state.TxnRevno(s.State, "machines", machineDocID)
  2005  		c.Assert(err, jc.ErrorIsNil)
  2006  		c.Assert(revno1, jc.GreaterThan, revno0)
  2007  	}).Check()
  2008  
  2009  	err = machine.SetProviderAddresses(addr0, addr1)
  2010  	c.Assert(err, jc.ErrorIsNil)
  2011  
  2012  	// Doc will be updated; concurrent changes are explicitly ignored.
  2013  	revno2, err := state.TxnRevno(s.State, "machines", machineDocID)
  2014  	c.Assert(err, jc.ErrorIsNil)
  2015  	c.Assert(revno2, jc.GreaterThan, revno1)
  2016  	c.Assert(machine.Addresses(), jc.SameContents, network.SpaceAddresses{addr0, addr1})
  2017  }
  2018  
  2019  func (s *MachineSuite) TestSetProviderAddressesInvalidateMemory(c *gc.C) {
  2020  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2021  	c.Assert(err, jc.ErrorIsNil)
  2022  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  2023  	machineDocID := state.DocID(s.State, machine.Id())
  2024  
  2025  	addr0 := network.NewSpaceAddress("127.0.0.1")
  2026  	addr1 := network.NewSpaceAddress("8.8.8.8")
  2027  
  2028  	// Set addresses to [addr0] initially. We'll get a separate Machine
  2029  	// object to update addresses, to ensure that the in-memory cache of
  2030  	// addresses does not prevent the initial Machine from updating
  2031  	// addresses back to the original value.
  2032  	err = machine.SetProviderAddresses(addr0)
  2033  	c.Assert(err, jc.ErrorIsNil)
  2034  	revno0, err := state.TxnRevno(s.State, "machines", machineDocID)
  2035  	c.Assert(err, jc.ErrorIsNil)
  2036  
  2037  	machine2, err := s.State.Machine(machine.Id())
  2038  	c.Assert(err, jc.ErrorIsNil)
  2039  	err = machine2.SetProviderAddresses(addr1)
  2040  	c.Assert(err, jc.ErrorIsNil)
  2041  	revno1, err := state.TxnRevno(s.State, "machines", machineDocID)
  2042  	c.Assert(err, jc.ErrorIsNil)
  2043  	c.Assert(revno1, jc.GreaterThan, revno0)
  2044  	c.Assert(machine.Addresses(), jc.SameContents, network.SpaceAddresses{addr0})
  2045  	c.Assert(machine2.Addresses(), jc.SameContents, network.SpaceAddresses{addr1})
  2046  
  2047  	err = machine.SetProviderAddresses(addr0)
  2048  	c.Assert(err, jc.ErrorIsNil)
  2049  	revno2, err := state.TxnRevno(s.State, "machines", machineDocID)
  2050  	c.Assert(err, jc.ErrorIsNil)
  2051  	c.Assert(revno2, jc.GreaterThan, revno1)
  2052  	c.Assert(machine.Addresses(), jc.SameContents, network.SpaceAddresses{addr0})
  2053  }
  2054  
  2055  func (s *MachineSuite) TestPublicAddressSetOnNewMachine(c *gc.C) {
  2056  	m, err := s.State.AddOneMachine(state.MachineTemplate{
  2057  		Base:      state.UbuntuBase("12.10"),
  2058  		Jobs:      []state.MachineJob{state.JobHostUnits},
  2059  		Addresses: network.NewSpaceAddresses("10.0.0.1", "8.8.8.8"),
  2060  	})
  2061  	c.Assert(err, jc.ErrorIsNil)
  2062  	addr, err := m.PublicAddress()
  2063  	c.Assert(err, jc.ErrorIsNil)
  2064  	c.Assert(addr, jc.DeepEquals, network.NewSpaceAddress("8.8.8.8"))
  2065  }
  2066  
  2067  func (s *MachineSuite) TestPrivateAddressSetOnNewMachine(c *gc.C) {
  2068  	m, err := s.State.AddOneMachine(state.MachineTemplate{
  2069  		Base:      state.UbuntuBase("12.10"),
  2070  		Jobs:      []state.MachineJob{state.JobHostUnits},
  2071  		Addresses: network.NewSpaceAddresses("10.0.0.1", "8.8.8.8"),
  2072  	})
  2073  	c.Assert(err, jc.ErrorIsNil)
  2074  	addr, err := m.PrivateAddress()
  2075  	c.Assert(err, jc.ErrorIsNil)
  2076  	c.Assert(addr, jc.DeepEquals, network.NewSpaceAddress("10.0.0.1"))
  2077  }
  2078  
  2079  func (s *MachineSuite) TestPublicAddressEmptyAddresses(c *gc.C) {
  2080  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2081  	c.Assert(err, jc.ErrorIsNil)
  2082  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  2083  
  2084  	addr, err := machine.PublicAddress()
  2085  	c.Assert(err, jc.Satisfies, network.IsNoAddressError)
  2086  	c.Assert(addr.Value, gc.Equals, "")
  2087  }
  2088  
  2089  func (s *MachineSuite) TestPrivateAddressEmptyAddresses(c *gc.C) {
  2090  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2091  	c.Assert(err, jc.ErrorIsNil)
  2092  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  2093  
  2094  	addr, err := machine.PrivateAddress()
  2095  	c.Assert(err, jc.Satisfies, network.IsNoAddressError)
  2096  	c.Assert(addr.Value, gc.Equals, "")
  2097  }
  2098  
  2099  func (s *MachineSuite) TestPublicAddress(c *gc.C) {
  2100  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2101  	c.Assert(err, jc.ErrorIsNil)
  2102  
  2103  	err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.8.8"))
  2104  	c.Assert(err, jc.ErrorIsNil)
  2105  
  2106  	addr, err := machine.PublicAddress()
  2107  	c.Assert(err, jc.ErrorIsNil)
  2108  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  2109  }
  2110  
  2111  func (s *MachineSuite) TestPrivateAddress(c *gc.C) {
  2112  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2113  	c.Assert(err, jc.ErrorIsNil)
  2114  
  2115  	err = machine.SetMachineAddresses(network.NewSpaceAddress("10.0.0.1"))
  2116  	c.Assert(err, jc.ErrorIsNil)
  2117  
  2118  	addr, err := machine.PrivateAddress()
  2119  	c.Assert(err, jc.ErrorIsNil)
  2120  	c.Assert(addr.Value, gc.Equals, "10.0.0.1")
  2121  }
  2122  
  2123  func (s *MachineSuite) TestPublicAddressBetterMatch(c *gc.C) {
  2124  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2125  	c.Assert(err, jc.ErrorIsNil)
  2126  
  2127  	err = machine.SetMachineAddresses(network.NewSpaceAddress("10.0.0.1"))
  2128  	c.Assert(err, jc.ErrorIsNil)
  2129  
  2130  	addr, err := machine.PublicAddress()
  2131  	c.Assert(err, jc.ErrorIsNil)
  2132  	c.Assert(addr.Value, gc.Equals, "10.0.0.1")
  2133  
  2134  	err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.8.8"))
  2135  	c.Assert(err, jc.ErrorIsNil)
  2136  
  2137  	addr, err = machine.PublicAddress()
  2138  	c.Assert(err, jc.ErrorIsNil)
  2139  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  2140  }
  2141  
  2142  func (s *MachineSuite) TestPrivateAddressBetterMatch(c *gc.C) {
  2143  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2144  	c.Assert(err, jc.ErrorIsNil)
  2145  
  2146  	err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.8.8"))
  2147  	c.Assert(err, jc.ErrorIsNil)
  2148  
  2149  	addr, err := machine.PrivateAddress()
  2150  	c.Assert(err, jc.ErrorIsNil)
  2151  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  2152  
  2153  	err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.8.8"), network.NewSpaceAddress("10.0.0.1"))
  2154  	c.Assert(err, jc.ErrorIsNil)
  2155  
  2156  	addr, err = machine.PrivateAddress()
  2157  	c.Assert(err, jc.ErrorIsNil)
  2158  	c.Assert(addr.Value, gc.Equals, "10.0.0.1")
  2159  }
  2160  
  2161  func (s *MachineSuite) TestPublicAddressChanges(c *gc.C) {
  2162  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2163  	c.Assert(err, jc.ErrorIsNil)
  2164  
  2165  	err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.8.8"))
  2166  	c.Assert(err, jc.ErrorIsNil)
  2167  
  2168  	addr, err := machine.PublicAddress()
  2169  	c.Assert(err, jc.ErrorIsNil)
  2170  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  2171  
  2172  	err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.4.4"))
  2173  	c.Assert(err, jc.ErrorIsNil)
  2174  
  2175  	addr, err = machine.PublicAddress()
  2176  	c.Assert(err, jc.ErrorIsNil)
  2177  	c.Assert(addr.Value, gc.Equals, "8.8.4.4")
  2178  }
  2179  
  2180  func (s *MachineSuite) TestPrivateAddressChanges(c *gc.C) {
  2181  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2182  	c.Assert(err, jc.ErrorIsNil)
  2183  
  2184  	err = machine.SetMachineAddresses(network.NewSpaceAddress("10.0.0.2"))
  2185  	c.Assert(err, jc.ErrorIsNil)
  2186  
  2187  	addr, err := machine.PrivateAddress()
  2188  	c.Assert(err, jc.ErrorIsNil)
  2189  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  2190  
  2191  	err = machine.SetMachineAddresses(network.NewSpaceAddress("10.0.0.1"))
  2192  	c.Assert(err, jc.ErrorIsNil)
  2193  
  2194  	addr, err = machine.PrivateAddress()
  2195  	c.Assert(err, jc.ErrorIsNil)
  2196  	c.Assert(addr.Value, gc.Equals, "10.0.0.1")
  2197  }
  2198  
  2199  func (s *MachineSuite) TestAddressesDeadMachine(c *gc.C) {
  2200  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2201  	c.Assert(err, jc.ErrorIsNil)
  2202  
  2203  	err = machine.SetProviderAddresses(network.NewSpaceAddress("10.0.0.2"), network.NewSpaceAddress("8.8.4.4"))
  2204  	c.Assert(err, jc.ErrorIsNil)
  2205  
  2206  	addr, err := machine.PrivateAddress()
  2207  	c.Assert(err, jc.ErrorIsNil)
  2208  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  2209  
  2210  	addr, err = machine.PublicAddress()
  2211  	c.Assert(err, jc.ErrorIsNil)
  2212  	c.Assert(addr.Value, gc.Equals, "8.8.4.4")
  2213  
  2214  	err = machine.EnsureDead()
  2215  	c.Assert(err, jc.ErrorIsNil)
  2216  
  2217  	// A dead machine should still report the last known addresses.
  2218  	addr, err = machine.PrivateAddress()
  2219  	c.Assert(err, jc.ErrorIsNil)
  2220  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  2221  
  2222  	addr, err = machine.PublicAddress()
  2223  	c.Assert(err, jc.ErrorIsNil)
  2224  	c.Assert(addr.Value, gc.Equals, "8.8.4.4")
  2225  }
  2226  
  2227  func (s *MachineSuite) TestStablePrivateAddress(c *gc.C) {
  2228  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2229  	c.Assert(err, jc.ErrorIsNil)
  2230  
  2231  	err = machine.SetMachineAddresses(network.NewSpaceAddress("10.0.0.2"))
  2232  	c.Assert(err, jc.ErrorIsNil)
  2233  
  2234  	addr, err := machine.PrivateAddress()
  2235  	c.Assert(err, jc.ErrorIsNil)
  2236  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  2237  
  2238  	// Now add an address that would previously have sorted before the
  2239  	// default.
  2240  	err = machine.SetMachineAddresses(network.NewSpaceAddress("10.0.0.1"), network.NewSpaceAddress("10.0.0.2"))
  2241  	c.Assert(err, jc.ErrorIsNil)
  2242  
  2243  	// Assert the address is unchanged.
  2244  	addr, err = machine.PrivateAddress()
  2245  	c.Assert(err, jc.ErrorIsNil)
  2246  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  2247  }
  2248  
  2249  func (s *MachineSuite) TestStablePublicAddress(c *gc.C) {
  2250  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2251  	c.Assert(err, jc.ErrorIsNil)
  2252  
  2253  	err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.8.8"))
  2254  	c.Assert(err, jc.ErrorIsNil)
  2255  
  2256  	addr, err := machine.PublicAddress()
  2257  	c.Assert(err, jc.ErrorIsNil)
  2258  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  2259  
  2260  	// Now add an address that would previously have sorted before the
  2261  	// default.
  2262  	err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.4.4"), network.NewSpaceAddress("8.8.8.8"))
  2263  	c.Assert(err, jc.ErrorIsNil)
  2264  
  2265  	// Assert the address is unchanged.
  2266  	addr, err = machine.PublicAddress()
  2267  	c.Assert(err, jc.ErrorIsNil)
  2268  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  2269  }
  2270  
  2271  func (s *MachineSuite) TestAddressesRaceMachineFirst(c *gc.C) {
  2272  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2273  	c.Assert(err, jc.ErrorIsNil)
  2274  
  2275  	changeAddresses := jujutxn.TestHook{
  2276  		Before: func() {
  2277  			err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.8.8"))
  2278  			c.Assert(err, jc.ErrorIsNil)
  2279  			address, err := machine.PublicAddress()
  2280  			c.Assert(err, jc.ErrorIsNil)
  2281  			c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("8.8.8.8"))
  2282  			address, err = machine.PrivateAddress()
  2283  			c.Assert(err, jc.ErrorIsNil)
  2284  			c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("8.8.8.8"))
  2285  		},
  2286  	}
  2287  	defer state.SetTestHooks(c, s.State, changeAddresses).Check()
  2288  
  2289  	err = machine.SetMachineAddresses(network.NewSpaceAddress("8.8.4.4"))
  2290  	c.Assert(err, jc.ErrorIsNil)
  2291  
  2292  	machine, err = s.State.Machine(machine.Id())
  2293  	c.Assert(err, jc.ErrorIsNil)
  2294  	address, err := machine.PublicAddress()
  2295  	c.Assert(err, jc.ErrorIsNil)
  2296  	c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("8.8.8.8"))
  2297  	address, err = machine.PrivateAddress()
  2298  	c.Assert(err, jc.ErrorIsNil)
  2299  	c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("8.8.8.8"))
  2300  }
  2301  
  2302  func (s *MachineSuite) TestAddressesRaceProviderFirst(c *gc.C) {
  2303  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2304  	c.Assert(err, jc.ErrorIsNil)
  2305  
  2306  	changeAddresses := jujutxn.TestHook{
  2307  		Before: func() {
  2308  			err = machine.SetMachineAddresses(network.NewSpaceAddress("10.0.0.1"))
  2309  			c.Assert(err, jc.ErrorIsNil)
  2310  			address, err := machine.PublicAddress()
  2311  			c.Assert(err, jc.ErrorIsNil)
  2312  			c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("10.0.0.1"))
  2313  			address, err = machine.PrivateAddress()
  2314  			c.Assert(err, jc.ErrorIsNil)
  2315  			c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("10.0.0.1"))
  2316  		},
  2317  	}
  2318  	defer state.SetTestHooks(c, s.State, changeAddresses).Check()
  2319  
  2320  	err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.4.4"))
  2321  	c.Assert(err, jc.ErrorIsNil)
  2322  
  2323  	machine, err = s.State.Machine(machine.Id())
  2324  	c.Assert(err, jc.ErrorIsNil)
  2325  	address, err := machine.PublicAddress()
  2326  	c.Assert(err, jc.ErrorIsNil)
  2327  	c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("8.8.4.4"))
  2328  	address, err = machine.PrivateAddress()
  2329  	c.Assert(err, jc.ErrorIsNil)
  2330  	c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("8.8.4.4"))
  2331  }
  2332  
  2333  func (s *MachineSuite) TestPrivateAddressPrefersProvider(c *gc.C) {
  2334  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2335  	c.Assert(err, jc.ErrorIsNil)
  2336  
  2337  	err = machine.SetMachineAddresses(network.NewSpaceAddress("8.8.8.8"), network.NewSpaceAddress("10.0.0.2"))
  2338  	c.Assert(err, jc.ErrorIsNil)
  2339  
  2340  	addr, err := machine.PublicAddress()
  2341  	c.Assert(err, jc.ErrorIsNil)
  2342  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  2343  	addr, err = machine.PrivateAddress()
  2344  	c.Assert(err, jc.ErrorIsNil)
  2345  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  2346  
  2347  	err = machine.SetProviderAddresses(network.NewSpaceAddress("10.0.0.1"))
  2348  	c.Assert(err, jc.ErrorIsNil)
  2349  
  2350  	addr, err = machine.PublicAddress()
  2351  	c.Assert(err, jc.ErrorIsNil)
  2352  	c.Assert(addr.Value, gc.Equals, "10.0.0.1")
  2353  	addr, err = machine.PrivateAddress()
  2354  	c.Assert(err, jc.ErrorIsNil)
  2355  	c.Assert(addr.Value, gc.Equals, "10.0.0.1")
  2356  }
  2357  
  2358  func (s *MachineSuite) TestPublicAddressPrefersProvider(c *gc.C) {
  2359  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2360  	c.Assert(err, jc.ErrorIsNil)
  2361  
  2362  	err = machine.SetMachineAddresses(network.NewSpaceAddress("8.8.8.8"), network.NewSpaceAddress("10.0.0.2"))
  2363  	c.Assert(err, jc.ErrorIsNil)
  2364  
  2365  	addr, err := machine.PublicAddress()
  2366  	c.Assert(err, jc.ErrorIsNil)
  2367  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  2368  	addr, err = machine.PrivateAddress()
  2369  	c.Assert(err, jc.ErrorIsNil)
  2370  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  2371  
  2372  	err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.4.4"))
  2373  	c.Assert(err, jc.ErrorIsNil)
  2374  
  2375  	addr, err = machine.PublicAddress()
  2376  	c.Assert(err, jc.ErrorIsNil)
  2377  	c.Assert(addr.Value, gc.Equals, "8.8.4.4")
  2378  	addr, err = machine.PrivateAddress()
  2379  	c.Assert(err, jc.ErrorIsNil)
  2380  	c.Assert(addr.Value, gc.Equals, "8.8.4.4")
  2381  }
  2382  
  2383  func (s *MachineSuite) TestAddressesPrefersProviderBoth(c *gc.C) {
  2384  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2385  	c.Assert(err, jc.ErrorIsNil)
  2386  
  2387  	err = machine.SetMachineAddresses(network.NewSpaceAddress("8.8.8.8"), network.NewSpaceAddress("10.0.0.1"))
  2388  	c.Assert(err, jc.ErrorIsNil)
  2389  
  2390  	addr, err := machine.PublicAddress()
  2391  	c.Assert(err, jc.ErrorIsNil)
  2392  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  2393  	addr, err = machine.PrivateAddress()
  2394  	c.Assert(err, jc.ErrorIsNil)
  2395  	c.Assert(addr.Value, gc.Equals, "10.0.0.1")
  2396  
  2397  	err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.4.4"), network.NewSpaceAddress("10.0.0.2"))
  2398  	c.Assert(err, jc.ErrorIsNil)
  2399  
  2400  	addr, err = machine.PublicAddress()
  2401  	c.Assert(err, jc.ErrorIsNil)
  2402  	c.Assert(addr.Value, gc.Equals, "8.8.4.4")
  2403  	addr, err = machine.PrivateAddress()
  2404  	c.Assert(err, jc.ErrorIsNil)
  2405  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  2406  }
  2407  
  2408  func (s *MachineSuite) addMachineWithSupportedContainer(c *gc.C, container instance.ContainerType) *state.Machine {
  2409  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2410  	c.Assert(err, jc.ErrorIsNil)
  2411  	containers := []instance.ContainerType{container}
  2412  	err = machine.SetSupportedContainers(containers)
  2413  	c.Assert(err, jc.ErrorIsNil)
  2414  	assertSupportedContainers(c, machine, containers)
  2415  	return machine
  2416  }
  2417  
  2418  // assertSupportedContainers checks the document in memory has the specified
  2419  // containers and then reloads the document from the database to assert saved
  2420  // values match also.
  2421  func assertSupportedContainers(c *gc.C, machine *state.Machine, containers []instance.ContainerType) {
  2422  	supportedContainers, known := machine.SupportedContainers()
  2423  	c.Assert(known, jc.IsTrue)
  2424  	c.Assert(supportedContainers, gc.DeepEquals, containers)
  2425  	// Reload so we can check the saved values.
  2426  	err := machine.Refresh()
  2427  	c.Assert(err, jc.ErrorIsNil)
  2428  	supportedContainers, known = machine.SupportedContainers()
  2429  	c.Assert(known, jc.IsTrue)
  2430  	c.Assert(supportedContainers, gc.DeepEquals, containers)
  2431  }
  2432  
  2433  func assertSupportedContainersUnknown(c *gc.C, machine *state.Machine) {
  2434  	containers, known := machine.SupportedContainers()
  2435  	c.Assert(known, jc.IsFalse)
  2436  	c.Assert(containers, gc.HasLen, 0)
  2437  }
  2438  
  2439  func (s *MachineSuite) TestSupportedContainersInitiallyUnknown(c *gc.C) {
  2440  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2441  	c.Assert(err, jc.ErrorIsNil)
  2442  	assertSupportedContainersUnknown(c, machine)
  2443  }
  2444  
  2445  func (s *MachineSuite) TestSupportsNoContainers(c *gc.C) {
  2446  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2447  	c.Assert(err, jc.ErrorIsNil)
  2448  
  2449  	err = machine.SupportsNoContainers()
  2450  	c.Assert(err, jc.ErrorIsNil)
  2451  	assertSupportedContainers(c, machine, []instance.ContainerType{})
  2452  }
  2453  
  2454  func (s *MachineSuite) TestSetSupportedContainerTypeNoneIsError(c *gc.C) {
  2455  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2456  	c.Assert(err, jc.ErrorIsNil)
  2457  
  2458  	err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.NONE})
  2459  	c.Assert(err, gc.ErrorMatches, `"none" is not a valid container type`)
  2460  	assertSupportedContainersUnknown(c, machine)
  2461  	err = machine.Refresh()
  2462  	c.Assert(err, jc.ErrorIsNil)
  2463  	assertSupportedContainersUnknown(c, machine)
  2464  }
  2465  
  2466  func (s *MachineSuite) TestSupportsNoContainersOverwritesExisting(c *gc.C) {
  2467  	machine := s.addMachineWithSupportedContainer(c, instance.LXD)
  2468  
  2469  	err := machine.SupportsNoContainers()
  2470  	c.Assert(err, jc.ErrorIsNil)
  2471  	assertSupportedContainers(c, machine, []instance.ContainerType{})
  2472  	// Calling it a second time should not invoke a db transaction
  2473  	defer state.SetFailIfTransaction(c, s.State).Check()
  2474  	err = machine.SupportsNoContainers()
  2475  	c.Assert(err, jc.ErrorIsNil)
  2476  	assertSupportedContainers(c, machine, []instance.ContainerType{})
  2477  }
  2478  
  2479  func (s *MachineSuite) TestSetSupportedContainersSingle(c *gc.C) {
  2480  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2481  	c.Assert(err, jc.ErrorIsNil)
  2482  
  2483  	err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD})
  2484  	c.Assert(err, jc.ErrorIsNil)
  2485  	assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD})
  2486  }
  2487  
  2488  func (s *MachineSuite) TestSetSupportedContainersSame(c *gc.C) {
  2489  	machine := s.addMachineWithSupportedContainer(c, instance.LXD)
  2490  
  2491  	defer state.SetFailIfTransaction(c, s.State).Check()
  2492  	err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXD})
  2493  	c.Assert(err, jc.ErrorIsNil)
  2494  	assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD})
  2495  }
  2496  
  2497  func (s *MachineSuite) TestSetSupportedContainersNew(c *gc.C) {
  2498  	machine := s.addMachineWithSupportedContainer(c, instance.LXD)
  2499  
  2500  	err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM})
  2501  	c.Assert(err, jc.ErrorIsNil)
  2502  	assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM})
  2503  }
  2504  
  2505  func (s *MachineSuite) TestSetSupportedContainersMultipeNew(c *gc.C) {
  2506  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2507  	c.Assert(err, jc.ErrorIsNil)
  2508  
  2509  	err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM})
  2510  	c.Assert(err, jc.ErrorIsNil)
  2511  	assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM})
  2512  }
  2513  
  2514  func (s *MachineSuite) TestSetSupportedContainersMultipleExisting(c *gc.C) {
  2515  	machine := s.addMachineWithSupportedContainer(c, instance.LXD)
  2516  
  2517  	err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM})
  2518  	c.Assert(err, jc.ErrorIsNil)
  2519  	assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM})
  2520  	// Setting it again will be a no-op
  2521  	defer state.SetFailIfTransaction(c, s.State).Check()
  2522  	err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM})
  2523  	c.Assert(err, jc.ErrorIsNil)
  2524  	assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM})
  2525  }
  2526  
  2527  func (s *MachineSuite) TestSetSupportedContainersMultipleExistingInvertedOrder(c *gc.C) {
  2528  	machine := s.addMachineWithSupportedContainer(c, instance.LXD)
  2529  
  2530  	err := machine.SetSupportedContainers([]instance.ContainerType{instance.KVM, instance.LXD})
  2531  	c.Assert(err, jc.ErrorIsNil)
  2532  	assertSupportedContainers(c, machine, []instance.ContainerType{instance.KVM, instance.LXD})
  2533  	// Setting it again will be a no-op
  2534  	defer state.SetFailIfTransaction(c, s.State).Check()
  2535  	err = machine.SetSupportedContainers([]instance.ContainerType{instance.KVM, instance.LXD})
  2536  	c.Assert(err, jc.ErrorIsNil)
  2537  	assertSupportedContainers(c, machine, []instance.ContainerType{instance.KVM, instance.LXD})
  2538  }
  2539  
  2540  func (s *MachineSuite) TestSetSupportedContainersMultipleExistingWithDifferentInstanceType(c *gc.C) {
  2541  	machine := s.addMachineWithSupportedContainer(c, instance.LXD)
  2542  
  2543  	err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM})
  2544  	c.Assert(err, jc.ErrorIsNil)
  2545  	assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM})
  2546  	// Setting it again will be a no-op
  2547  	err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.ContainerType("FOO")})
  2548  	c.Assert(err, jc.ErrorIsNil)
  2549  }
  2550  
  2551  func (s *MachineSuite) TestSetSupportedContainersSetsUnknownToError(c *gc.C) {
  2552  	// Create a machine and add lxd and kvm containers prior to calling SetSupportedContainers
  2553  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2554  	c.Assert(err, jc.ErrorIsNil)
  2555  	template := state.MachineTemplate{
  2556  		Base: state.UbuntuBase("12.10"),
  2557  		Jobs: []state.MachineJob{state.JobHostUnits},
  2558  	}
  2559  	container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXD)
  2560  	c.Assert(err, jc.ErrorIsNil)
  2561  	supportedContainer, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.KVM)
  2562  	c.Assert(err, jc.ErrorIsNil)
  2563  	err = machine.SetSupportedContainers([]instance.ContainerType{instance.KVM})
  2564  	c.Assert(err, jc.ErrorIsNil)
  2565  
  2566  	// A supported (kvm) container will have a pending status.
  2567  	err = supportedContainer.Refresh()
  2568  	c.Assert(err, jc.ErrorIsNil)
  2569  	statusInfo, err := supportedContainer.Status()
  2570  	c.Assert(err, jc.ErrorIsNil)
  2571  	c.Assert(statusInfo.Status, gc.Equals, status.Pending)
  2572  
  2573  	// An unsupported (lxd) container will have an error status.
  2574  	err = container.Refresh()
  2575  	c.Assert(err, jc.ErrorIsNil)
  2576  	statusInfo, err = container.Status()
  2577  	c.Assert(err, jc.ErrorIsNil)
  2578  	c.Assert(statusInfo.Status, gc.Equals, status.Error)
  2579  	c.Assert(statusInfo.Message, gc.Equals, "unsupported container")
  2580  	c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{"type": "lxd"})
  2581  }
  2582  
  2583  func (s *MachineSuite) TestSupportsNoContainersSetsAllToError(c *gc.C) {
  2584  	// Create a machine and add all container types prior to calling SupportsNoContainers
  2585  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2586  	c.Assert(err, jc.ErrorIsNil)
  2587  	var containers []*state.Machine
  2588  	template := state.MachineTemplate{
  2589  		Base: state.UbuntuBase("12.10"),
  2590  		Jobs: []state.MachineJob{state.JobHostUnits},
  2591  	}
  2592  	for _, containerType := range instance.ContainerTypes {
  2593  		container, err := s.State.AddMachineInsideMachine(template, machine.Id(), containerType)
  2594  		c.Assert(err, jc.ErrorIsNil)
  2595  		containers = append(containers, container)
  2596  	}
  2597  
  2598  	err = machine.SupportsNoContainers()
  2599  	c.Assert(err, jc.ErrorIsNil)
  2600  
  2601  	// All containers should be in error state.
  2602  	for _, container := range containers {
  2603  		err = container.Refresh()
  2604  		c.Assert(err, jc.ErrorIsNil)
  2605  		statusInfo, err := container.Status()
  2606  		c.Assert(err, jc.ErrorIsNil)
  2607  		c.Assert(statusInfo.Status, gc.Equals, status.Error)
  2608  		c.Assert(statusInfo.Message, gc.Equals, "unsupported container")
  2609  		containerType := corecontainer.ContainerTypeFromId(container.Id())
  2610  		c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{"type": string(containerType)})
  2611  	}
  2612  }
  2613  
  2614  func (s *MachineSuite) TestMachineAgentTools(c *gc.C) {
  2615  	m, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2616  	c.Assert(err, jc.ErrorIsNil)
  2617  	testAgentTools(c, m, "machine "+m.Id())
  2618  }
  2619  
  2620  func (s *MachineSuite) TestMachineValidActions(c *gc.C) {
  2621  	m, err := s.State.AddMachine(state.UbuntuBase("22.04"), state.JobHostUnits)
  2622  	c.Assert(err, jc.ErrorIsNil)
  2623  
  2624  	var tests = []struct {
  2625  		actionName      string
  2626  		errString       string
  2627  		givenPayload    map[string]interface{}
  2628  		expectedPayload map[string]interface{}
  2629  	}{
  2630  		{
  2631  			actionName: "juju-exec",
  2632  			errString:  `validation failed: (root) : "command" property is missing and required, given {}; (root) : "timeout" property is missing and required, given {}`,
  2633  		},
  2634  		{
  2635  			actionName:      "juju-exec",
  2636  			givenPayload:    map[string]interface{}{"command": "allyourbasearebelongtous", "timeout": 5.0},
  2637  			expectedPayload: map[string]interface{}{"command": "allyourbasearebelongtous", "timeout": 5.0},
  2638  		},
  2639  		{
  2640  			actionName: "baiku",
  2641  			errString:  `cannot add action "baiku" to a machine; only predefined actions allowed`,
  2642  		},
  2643  	}
  2644  
  2645  	for i, t := range tests {
  2646  		c.Logf("running test %d", i)
  2647  		operationID, err := s.Model.EnqueueOperation("a test", 1)
  2648  		c.Assert(err, jc.ErrorIsNil)
  2649  		action, err := s.Model.AddAction(m, operationID, t.actionName, t.givenPayload, nil, nil)
  2650  		if t.errString != "" {
  2651  			c.Assert(err.Error(), gc.Equals, t.errString)
  2652  			continue
  2653  		} else {
  2654  			c.Assert(err, jc.ErrorIsNil)
  2655  			c.Assert(action.Parameters(), jc.DeepEquals, t.expectedPayload)
  2656  		}
  2657  	}
  2658  }
  2659  
  2660  func (s *MachineSuite) TestAddActionWithError(c *gc.C) {
  2661  	m, err := s.State.AddMachine(state.UbuntuBase("22.04"), state.JobHostUnits)
  2662  	c.Assert(err, jc.ErrorIsNil)
  2663  
  2664  	operationID, err := s.Model.EnqueueOperation("a test", 1)
  2665  	c.Assert(err, jc.ErrorIsNil)
  2666  	_, err = s.Model.AddAction(m, operationID, "benchmark", nil, nil, nil)
  2667  	c.Assert(err, gc.ErrorMatches, `cannot add action "benchmark" to a machine; only predefined actions allowed`)
  2668  	op, err := s.Model.Operation(operationID)
  2669  	c.Assert(err, jc.ErrorIsNil)
  2670  	c.Assert(op.Status(), gc.Equals, state.ActionError)
  2671  }
  2672  
  2673  func (s *MachineSuite) setupTestUpdateMachineSeries(c *gc.C) *state.Machine {
  2674  	mach, err := s.State.AddMachine(state.UbuntuBase("12.04"), state.JobHostUnits)
  2675  	c.Assert(err, jc.ErrorIsNil)
  2676  
  2677  	ch := state.AddTestingCharmMultiSeries(c, s.State, "multi-series")
  2678  	app := state.AddTestingApplicationForBase(c, s.State, state.UbuntuBase("12.04"), "multi-series", ch)
  2679  	subCh := state.AddTestingCharmMultiSeries(c, s.State, "multi-series-subordinate")
  2680  	_ = state.AddTestingApplicationForBase(c, s.State, state.UbuntuBase("12.04"), "multi-series-subordinate", subCh)
  2681  
  2682  	eps, err := s.State.InferEndpoints("multi-series", "multi-series-subordinate")
  2683  	c.Assert(err, jc.ErrorIsNil)
  2684  	rel, err := s.State.AddRelation(eps...)
  2685  	c.Assert(err, jc.ErrorIsNil)
  2686  
  2687  	unit, err := app.AddUnit(state.AddUnitParams{})
  2688  	c.Assert(err, jc.ErrorIsNil)
  2689  	err = unit.AssignToMachine(mach)
  2690  	c.Assert(err, jc.ErrorIsNil)
  2691  
  2692  	ru, err := rel.Unit(unit)
  2693  	c.Assert(err, jc.ErrorIsNil)
  2694  	err = ru.EnterScope(nil)
  2695  	c.Assert(err, jc.ErrorIsNil)
  2696  
  2697  	return mach
  2698  }
  2699  
  2700  func (s *MachineSuite) assertMachineAndUnitSeriesChanged(c *gc.C, mach *state.Machine, base state.Base) {
  2701  	err := mach.Refresh()
  2702  	c.Assert(err, jc.ErrorIsNil)
  2703  	c.Assert(mach.Base().String(), gc.Equals, base.String())
  2704  	principals := mach.Principals()
  2705  	for _, p := range principals {
  2706  		u, err := s.State.Unit(p)
  2707  		c.Assert(err, jc.ErrorIsNil)
  2708  		c.Assert(u.Base().String(), jc.DeepEquals, base.String())
  2709  		subs := u.SubordinateNames()
  2710  		for _, sn := range subs {
  2711  			u, err := s.State.Unit(sn)
  2712  			c.Assert(err, jc.ErrorIsNil)
  2713  			c.Assert(u.Base().String(), jc.DeepEquals, base.String())
  2714  		}
  2715  	}
  2716  }
  2717  
  2718  func (s *MachineSuite) TestUpdateMachineSeries(c *gc.C) {
  2719  	mach := s.setupTestUpdateMachineSeries(c)
  2720  	err := mach.UpdateMachineSeries(state.UbuntuBase("22.04"))
  2721  	c.Assert(err, jc.ErrorIsNil)
  2722  	s.assertMachineAndUnitSeriesChanged(c, mach, state.UbuntuBase("22.04"))
  2723  }
  2724  
  2725  func (s *MachineSuite) TestUpdateMachineSeriesSameSeriesToStart(c *gc.C) {
  2726  	mach := s.setupTestUpdateMachineSeries(c)
  2727  	err := mach.UpdateMachineSeries(state.UbuntuBase("22.04"))
  2728  	c.Assert(err, jc.ErrorIsNil)
  2729  	s.assertMachineAndUnitSeriesChanged(c, mach, state.UbuntuBase("22.04"))
  2730  }
  2731  
  2732  func (s *MachineSuite) TestUpdateMachineSeriesSameSeriesAfterStart(c *gc.C) {
  2733  	mach := s.setupTestUpdateMachineSeries(c)
  2734  
  2735  	defer state.SetTestHooks(c, s.State,
  2736  		jujutxn.TestHook{
  2737  			Before: func() {
  2738  				ops := []txn.Op{{
  2739  					C:      state.MachinesC,
  2740  					Id:     state.DocID(s.State, mach.Id()),
  2741  					Update: bson.D{{"$set", bson.D{{"series", state.UbuntuBase("22.04")}}}},
  2742  				}}
  2743  				state.RunTransaction(c, s.State, ops)
  2744  			},
  2745  			After: func() {
  2746  				err := mach.Refresh()
  2747  				c.Assert(err, jc.ErrorIsNil)
  2748  				c.Assert(mach.Base().String(), gc.Equals, "ubuntu@22.04/stable")
  2749  			},
  2750  		},
  2751  	).Check()
  2752  
  2753  	err := mach.UpdateMachineSeries(state.UbuntuBase("22.04"))
  2754  	c.Assert(err, jc.ErrorIsNil)
  2755  	err = mach.Refresh()
  2756  	c.Assert(err, jc.ErrorIsNil)
  2757  	c.Assert(mach.Base().DisplayString(), gc.Equals, "ubuntu@22.04")
  2758  }
  2759  
  2760  func (s *MachineSuite) TestUpdateMachineSeriesPrincipalsListChange(c *gc.C) {
  2761  	mach := s.setupTestUpdateMachineSeries(c)
  2762  	err := mach.Refresh()
  2763  	c.Assert(err, jc.ErrorIsNil)
  2764  	c.Assert(len(mach.Principals()), gc.Equals, 1)
  2765  
  2766  	defer state.SetTestHooks(c, s.State,
  2767  		jujutxn.TestHook{
  2768  			Before: func() {
  2769  				app, err := s.State.Application("multi-series")
  2770  				c.Assert(err, jc.ErrorIsNil)
  2771  				unit, err := app.AddUnit(state.AddUnitParams{})
  2772  				c.Assert(err, jc.ErrorIsNil)
  2773  				err = unit.AssignToMachine(mach)
  2774  				c.Assert(err, jc.ErrorIsNil)
  2775  			},
  2776  		},
  2777  	).Check()
  2778  
  2779  	err = mach.UpdateMachineSeries(state.UbuntuBase("22.04"))
  2780  	c.Assert(err, jc.ErrorIsNil)
  2781  	s.assertMachineAndUnitSeriesChanged(c, mach, state.UbuntuBase("22.04"))
  2782  	c.Assert(len(mach.Principals()), gc.Equals, 2)
  2783  }
  2784  
  2785  func (s *MachineSuite) addMachineUnit(c *gc.C, mach *state.Machine) *state.Unit {
  2786  	units, err := mach.Units()
  2787  	c.Assert(err, jc.ErrorIsNil)
  2788  
  2789  	var app *state.Application
  2790  	if len(units) == 0 {
  2791  		ch := state.AddTestingCharmMultiSeries(c, s.State, "multi-series")
  2792  		app = state.AddTestingApplicationForBase(c, s.State, mach.Base(), "multi-series", ch)
  2793  		subCh := state.AddTestingCharmMultiSeries(c, s.State, "multi-series-subordinate")
  2794  		_ = state.AddTestingApplicationForBase(c, s.State, mach.Base(), "multi-series-subordinate", subCh)
  2795  	} else {
  2796  		app, err = units[0].Application()
  2797  		c.Assert(err, jc.ErrorIsNil)
  2798  	}
  2799  
  2800  	unit, err := app.AddUnit(state.AddUnitParams{})
  2801  	c.Assert(err, jc.ErrorIsNil)
  2802  	err = unit.AssignToMachine(mach)
  2803  	c.Assert(err, jc.ErrorIsNil)
  2804  	return unit
  2805  }
  2806  
  2807  func (s *MachineSuite) TestWatchAddresses(c *gc.C) {
  2808  	// Add a machine: reported.
  2809  	machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
  2810  	c.Assert(err, jc.ErrorIsNil)
  2811  
  2812  	s.WaitForModelWatchersIdle(c, s.Model.UUID())
  2813  	w := machine.WatchAddresses()
  2814  	defer w.Stop()
  2815  	wc := testing.NewNotifyWatcherC(c, w)
  2816  	wc.AssertOneChange()
  2817  
  2818  	// Change the machine: not reported.
  2819  	err = machine.SetProvisioned("i-blah", "", "fake-nonce", nil)
  2820  	c.Assert(err, jc.ErrorIsNil)
  2821  	wc.AssertNoChange()
  2822  
  2823  	// Set machine addresses: reported.
  2824  	err = machine.SetMachineAddresses(network.NewSpaceAddress("abc"))
  2825  	c.Assert(err, jc.ErrorIsNil)
  2826  	wc.AssertOneChange()
  2827  
  2828  	// Set provider addresses eclipsing machine addresses: reported.
  2829  	err = machine.SetProviderAddresses(network.NewSpaceAddress("abc", network.WithScope(network.ScopePublic)))
  2830  	c.Assert(err, jc.ErrorIsNil)
  2831  	wc.AssertOneChange()
  2832  
  2833  	// Set same machine eclipsed by provider addresses: not reported.
  2834  	err = machine.SetMachineAddresses(network.NewSpaceAddress("abc", network.WithScope(network.ScopeCloudLocal)))
  2835  	c.Assert(err, jc.ErrorIsNil)
  2836  	wc.AssertNoChange()
  2837  
  2838  	// Set different machine addresses: reported.
  2839  	err = machine.SetMachineAddresses(network.NewSpaceAddress("def"))
  2840  	c.Assert(err, jc.ErrorIsNil)
  2841  	wc.AssertOneChange()
  2842  
  2843  	// Set different provider addresses: reported.
  2844  	err = machine.SetMachineAddresses(network.NewSpaceAddress("def", network.WithScope(network.ScopePublic)))
  2845  	c.Assert(err, jc.ErrorIsNil)
  2846  	wc.AssertOneChange()
  2847  
  2848  	// Make it Dying: not reported.
  2849  	err = machine.Destroy()
  2850  	c.Assert(err, jc.ErrorIsNil)
  2851  	wc.AssertNoChange()
  2852  
  2853  	// Make it Dead: not reported.
  2854  	err = machine.EnsureDead()
  2855  	c.Assert(err, jc.ErrorIsNil)
  2856  	wc.AssertNoChange()
  2857  
  2858  	// Remove it: watcher eventually closed and Err
  2859  	// returns an IsNotFound error.
  2860  	err = machine.Remove()
  2861  	c.Assert(err, jc.ErrorIsNil)
  2862  	select {
  2863  	case _, ok := <-w.Changes():
  2864  		c.Assert(ok, jc.IsFalse)
  2865  	case <-time.After(coretesting.LongWait):
  2866  		c.Fatalf("watcher not closed")
  2867  	}
  2868  	c.Assert(w.Err(), jc.Satisfies, errors.IsNotFound)
  2869  }
  2870  
  2871  func (s *MachineSuite) TestGetManualMachineArches(c *gc.C) {
  2872  	_, err := s.State.AddOneMachine(state.MachineTemplate{
  2873  		Base:                    state.UbuntuBase("12.10"),
  2874  		Jobs:                    []state.MachineJob{state.JobHostUnits},
  2875  		InstanceId:              "manual:foo",
  2876  		Nonce:                   "manual:foo-nonce",
  2877  		HardwareCharacteristics: instance.MustParseHardware("arch=amd64"),
  2878  	})
  2879  	c.Assert(err, jc.ErrorIsNil)
  2880  
  2881  	_, err = s.State.AddOneMachine(state.MachineTemplate{
  2882  		Base:                    state.UbuntuBase("12.10"),
  2883  		Jobs:                    []state.MachineJob{state.JobHostUnits},
  2884  		InstanceId:              "manual:bar",
  2885  		Nonce:                   "manual:bar-nonce",
  2886  		HardwareCharacteristics: instance.MustParseHardware("arch=s390x"),
  2887  	})
  2888  	c.Assert(err, jc.ErrorIsNil)
  2889  
  2890  	_, err = s.State.AddOneMachine(state.MachineTemplate{
  2891  		Base:                    state.UbuntuBase("12.10"),
  2892  		Jobs:                    []state.MachineJob{state.JobHostUnits},
  2893  		InstanceId:              "lorem",
  2894  		Nonce:                   "lorem:nonce",
  2895  		HardwareCharacteristics: instance.MustParseHardware("arch=ppc64el"),
  2896  	})
  2897  	c.Assert(err, jc.ErrorIsNil)
  2898  
  2899  	manualArchSet, err := s.State.GetManualMachineArches()
  2900  	c.Assert(err, jc.ErrorIsNil)
  2901  	c.Assert(manualArchSet.SortedValues(), gc.DeepEquals, []string{"amd64", "s390x"})
  2902  }