github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/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  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/loggo"
    11  	"github.com/juju/names"
    12  	jc "github.com/juju/testing/checkers"
    13  	jujutxn "github.com/juju/txn"
    14  	"github.com/juju/version"
    15  	gc "gopkg.in/check.v1"
    16  	"gopkg.in/mgo.v2"
    17  	"gopkg.in/mgo.v2/bson"
    18  
    19  	"github.com/juju/juju/constraints"
    20  	"github.com/juju/juju/environs/config"
    21  	"github.com/juju/juju/instance"
    22  	"github.com/juju/juju/mongo/mongotest"
    23  	"github.com/juju/juju/network"
    24  	"github.com/juju/juju/state"
    25  	"github.com/juju/juju/state/testing"
    26  	"github.com/juju/juju/status"
    27  	"github.com/juju/juju/storage/poolmanager"
    28  	"github.com/juju/juju/storage/provider"
    29  	"github.com/juju/juju/storage/provider/registry"
    30  	coretesting "github.com/juju/juju/testing"
    31  )
    32  
    33  type MachineSuite struct {
    34  	ConnSuite
    35  	machine0 *state.Machine
    36  	machine  *state.Machine
    37  }
    38  
    39  var _ = gc.Suite(&MachineSuite{})
    40  
    41  func (s *MachineSuite) SetUpTest(c *gc.C) {
    42  	s.ConnSuite.SetUpTest(c)
    43  	s.policy.GetConstraintsValidator = func(*config.Config, state.SupportedArchitecturesQuerier) (constraints.Validator, error) {
    44  		validator := constraints.NewValidator()
    45  		validator.RegisterConflicts([]string{constraints.InstanceType}, []string{constraints.Mem})
    46  		validator.RegisterUnsupported([]string{constraints.CpuPower})
    47  		return validator, nil
    48  	}
    49  	var err error
    50  	s.machine0, err = s.State.AddMachine("quantal", state.JobManageModel)
    51  	c.Assert(err, jc.ErrorIsNil)
    52  	s.machine, err = s.State.AddMachine("quantal", state.JobHostUnits)
    53  	c.Assert(err, jc.ErrorIsNil)
    54  }
    55  
    56  func (s *MachineSuite) TestSetRebootFlagDeadMachine(c *gc.C) {
    57  	err := s.machine.EnsureDead()
    58  	c.Assert(err, jc.ErrorIsNil)
    59  
    60  	err = s.machine.SetRebootFlag(true)
    61  	c.Assert(err, gc.Equals, mgo.ErrNotFound)
    62  
    63  	rFlag, err := s.machine.GetRebootFlag()
    64  	c.Assert(err, jc.ErrorIsNil)
    65  	c.Assert(rFlag, jc.IsFalse)
    66  
    67  	err = s.machine.SetRebootFlag(false)
    68  	c.Assert(err, jc.ErrorIsNil)
    69  
    70  	action, err := s.machine.ShouldRebootOrShutdown()
    71  	c.Assert(err, jc.ErrorIsNil)
    72  	c.Assert(action, gc.Equals, state.ShouldDoNothing)
    73  }
    74  
    75  func (s *MachineSuite) TestSetRebootFlagDeadMachineRace(c *gc.C) {
    76  	setFlag := jujutxn.TestHook{
    77  		Before: func() {
    78  			err := s.machine.EnsureDead()
    79  			c.Assert(err, jc.ErrorIsNil)
    80  		},
    81  	}
    82  	defer state.SetTestHooks(c, s.State, setFlag).Check()
    83  
    84  	err := s.machine.SetRebootFlag(true)
    85  	c.Assert(err, gc.Equals, mgo.ErrNotFound)
    86  }
    87  
    88  func (s *MachineSuite) TestSetRebootFlag(c *gc.C) {
    89  	err := s.machine.SetRebootFlag(true)
    90  	c.Assert(err, jc.ErrorIsNil)
    91  
    92  	rebootFlag, err := s.machine.GetRebootFlag()
    93  	c.Assert(err, jc.ErrorIsNil)
    94  	c.Assert(rebootFlag, jc.IsTrue)
    95  }
    96  
    97  func (s *MachineSuite) TestSetUnsetRebootFlag(c *gc.C) {
    98  	err := s.machine.SetRebootFlag(true)
    99  	c.Assert(err, jc.ErrorIsNil)
   100  
   101  	rebootFlag, err := s.machine.GetRebootFlag()
   102  	c.Assert(err, jc.ErrorIsNil)
   103  	c.Assert(rebootFlag, jc.IsTrue)
   104  
   105  	err = s.machine.SetRebootFlag(false)
   106  	c.Assert(err, jc.ErrorIsNil)
   107  
   108  	rebootFlag, err = s.machine.GetRebootFlag()
   109  	c.Assert(err, jc.ErrorIsNil)
   110  	c.Assert(rebootFlag, jc.IsFalse)
   111  }
   112  
   113  func (s *MachineSuite) TestAddMachineInsideMachineModelDying(c *gc.C) {
   114  	model, err := s.State.Model()
   115  	c.Assert(err, jc.ErrorIsNil)
   116  	c.Assert(model.Destroy(), jc.ErrorIsNil)
   117  
   118  	_, err = s.State.AddMachineInsideMachine(state.MachineTemplate{
   119  		Series: "quantal",
   120  		Jobs:   []state.MachineJob{state.JobHostUnits},
   121  	}, s.machine.Id(), instance.LXC)
   122  	c.Assert(err, gc.ErrorMatches, `model "testenv" is no longer alive`)
   123  }
   124  
   125  func (s *MachineSuite) TestAddMachineInsideMachineModelMigrating(c *gc.C) {
   126  	model, err := s.State.Model()
   127  	c.Assert(err, jc.ErrorIsNil)
   128  	c.Assert(model.SetMigrationMode(state.MigrationModeExporting), jc.ErrorIsNil)
   129  
   130  	_, err = s.State.AddMachineInsideMachine(state.MachineTemplate{
   131  		Series: "quantal",
   132  		Jobs:   []state.MachineJob{state.JobHostUnits},
   133  	}, s.machine.Id(), instance.LXC)
   134  	c.Assert(err, gc.ErrorMatches, `model "testenv" is being migrated`)
   135  }
   136  
   137  func (s *MachineSuite) TestShouldShutdownOrReboot(c *gc.C) {
   138  	// Add first container.
   139  	c1, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
   140  		Series: "quantal",
   141  		Jobs:   []state.MachineJob{state.JobHostUnits},
   142  	}, s.machine.Id(), instance.LXC)
   143  	c.Assert(err, jc.ErrorIsNil)
   144  
   145  	// Add second container.
   146  	c2, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
   147  		Series: "quantal",
   148  		Jobs:   []state.MachineJob{state.JobHostUnits},
   149  	}, c1.Id(), instance.LXC)
   150  	c.Assert(err, jc.ErrorIsNil)
   151  
   152  	err = c2.SetRebootFlag(true)
   153  	c.Assert(err, jc.ErrorIsNil)
   154  
   155  	rAction, err := s.machine.ShouldRebootOrShutdown()
   156  	c.Assert(err, jc.ErrorIsNil)
   157  	c.Assert(rAction, gc.Equals, state.ShouldDoNothing)
   158  
   159  	rAction, err = c1.ShouldRebootOrShutdown()
   160  	c.Assert(err, jc.ErrorIsNil)
   161  	c.Assert(rAction, gc.Equals, state.ShouldDoNothing)
   162  
   163  	rAction, err = c2.ShouldRebootOrShutdown()
   164  	c.Assert(err, jc.ErrorIsNil)
   165  	c.Assert(rAction, gc.Equals, state.ShouldReboot)
   166  
   167  	// // Reboot happens on the root node
   168  	err = c2.SetRebootFlag(false)
   169  	c.Assert(err, jc.ErrorIsNil)
   170  
   171  	err = s.machine.SetRebootFlag(true)
   172  	c.Assert(err, jc.ErrorIsNil)
   173  
   174  	rAction, err = s.machine.ShouldRebootOrShutdown()
   175  	c.Assert(err, jc.ErrorIsNil)
   176  	c.Assert(rAction, gc.Equals, state.ShouldReboot)
   177  
   178  	rAction, err = c1.ShouldRebootOrShutdown()
   179  	c.Assert(err, jc.ErrorIsNil)
   180  	c.Assert(rAction, gc.Equals, state.ShouldShutdown)
   181  
   182  	rAction, err = c2.ShouldRebootOrShutdown()
   183  	c.Assert(err, jc.ErrorIsNil)
   184  	c.Assert(rAction, gc.Equals, state.ShouldShutdown)
   185  }
   186  
   187  func (s *MachineSuite) TestContainerDefaults(c *gc.C) {
   188  	c.Assert(string(s.machine.ContainerType()), gc.Equals, "")
   189  	containers, err := s.machine.Containers()
   190  	c.Assert(err, jc.ErrorIsNil)
   191  	c.Assert(containers, gc.DeepEquals, []string(nil))
   192  }
   193  
   194  func (s *MachineSuite) TestParentId(c *gc.C) {
   195  	parentId, ok := s.machine.ParentId()
   196  	c.Assert(parentId, gc.Equals, "")
   197  	c.Assert(ok, jc.IsFalse)
   198  	container, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
   199  		Series: "quantal",
   200  		Jobs:   []state.MachineJob{state.JobHostUnits},
   201  	}, s.machine.Id(), instance.LXC)
   202  	c.Assert(err, jc.ErrorIsNil)
   203  	parentId, ok = container.ParentId()
   204  	c.Assert(parentId, gc.Equals, s.machine.Id())
   205  	c.Assert(ok, jc.IsTrue)
   206  }
   207  
   208  func (s *MachineSuite) TestMachineIsManager(c *gc.C) {
   209  	c.Assert(s.machine0.IsManager(), jc.IsTrue)
   210  	c.Assert(s.machine.IsManager(), jc.IsFalse)
   211  }
   212  
   213  func (s *MachineSuite) TestMachineIsManualBootstrap(c *gc.C) {
   214  	cfg, err := s.State.ModelConfig()
   215  	c.Assert(err, jc.ErrorIsNil)
   216  	c.Assert(cfg.Type(), gc.Not(gc.Equals), "null")
   217  	c.Assert(s.machine.Id(), gc.Equals, "1")
   218  	manual, err := s.machine0.IsManual()
   219  	c.Assert(err, jc.ErrorIsNil)
   220  	c.Assert(manual, jc.IsFalse)
   221  	attrs := map[string]interface{}{"type": "null"}
   222  	err = s.State.UpdateModelConfig(attrs, nil, nil)
   223  	c.Assert(err, jc.ErrorIsNil)
   224  	manual, err = s.machine0.IsManual()
   225  	c.Assert(err, jc.ErrorIsNil)
   226  	c.Assert(manual, jc.IsTrue)
   227  }
   228  
   229  func (s *MachineSuite) TestMachineIsManual(c *gc.C) {
   230  	tests := []struct {
   231  		instanceId instance.Id
   232  		nonce      string
   233  		isManual   bool
   234  	}{
   235  		{instanceId: "x", nonce: "y", isManual: false},
   236  		{instanceId: "manual:", nonce: "y", isManual: false},
   237  		{instanceId: "x", nonce: "manual:", isManual: true},
   238  		{instanceId: "x", nonce: "manual:y", isManual: true},
   239  		{instanceId: "x", nonce: "manual", isManual: false},
   240  	}
   241  	for _, test := range tests {
   242  		m, err := s.State.AddOneMachine(state.MachineTemplate{
   243  			Series:     "quantal",
   244  			Jobs:       []state.MachineJob{state.JobHostUnits},
   245  			InstanceId: test.instanceId,
   246  			Nonce:      test.nonce,
   247  		})
   248  		c.Assert(err, jc.ErrorIsNil)
   249  		isManual, err := m.IsManual()
   250  		c.Assert(isManual, gc.Equals, test.isManual)
   251  	}
   252  }
   253  
   254  func (s *MachineSuite) TestMachineIsContainer(c *gc.C) {
   255  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   256  	c.Assert(err, jc.ErrorIsNil)
   257  
   258  	template := state.MachineTemplate{
   259  		Series: "quantal",
   260  		Jobs:   []state.MachineJob{state.JobHostUnits},
   261  	}
   262  	container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXC)
   263  	c.Assert(err, jc.ErrorIsNil)
   264  
   265  	c.Assert(machine.IsContainer(), jc.IsFalse)
   266  	c.Assert(container.IsContainer(), jc.IsTrue)
   267  }
   268  
   269  func (s *MachineSuite) TestLifeJobManageModel(c *gc.C) {
   270  	// A JobManageModel machine must never advance lifecycle.
   271  	m := s.machine0
   272  	err := m.Destroy()
   273  	c.Assert(err, gc.ErrorMatches, "machine 0 is required by the model")
   274  	err = m.ForceDestroy()
   275  	c.Assert(err, gc.ErrorMatches, "machine is required by the model")
   276  	err = m.EnsureDead()
   277  	c.Assert(err, gc.ErrorMatches, "machine 0 is required by the model")
   278  }
   279  
   280  func (s *MachineSuite) TestLifeMachineWithContainer(c *gc.C) {
   281  	// A machine hosting a container must not advance lifecycle.
   282  	_, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
   283  		Series: "quantal",
   284  		Jobs:   []state.MachineJob{state.JobHostUnits},
   285  	}, s.machine.Id(), instance.LXC)
   286  	c.Assert(err, jc.ErrorIsNil)
   287  	err = s.machine.Destroy()
   288  	c.Assert(err, gc.FitsTypeOf, &state.HasContainersError{})
   289  	c.Assert(err, gc.ErrorMatches, `machine 1 is hosting containers "1/lxc/0"`)
   290  	err1 := s.machine.EnsureDead()
   291  	c.Assert(err1, gc.DeepEquals, err)
   292  	c.Assert(s.machine.Life(), gc.Equals, state.Alive)
   293  }
   294  
   295  func (s *MachineSuite) TestLifeJobHostUnits(c *gc.C) {
   296  	// A machine with an assigned unit must not advance lifecycle.
   297  	svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   298  	unit, err := svc.AddUnit()
   299  	c.Assert(err, jc.ErrorIsNil)
   300  	err = unit.AssignToMachine(s.machine)
   301  	c.Assert(err, jc.ErrorIsNil)
   302  	err = s.machine.Destroy()
   303  	c.Assert(err, jc.Satisfies, state.IsHasAssignedUnitsError)
   304  	c.Assert(err, gc.ErrorMatches, `machine 1 has unit "wordpress/0" assigned`)
   305  	err1 := s.machine.EnsureDead()
   306  	c.Assert(err1, gc.DeepEquals, err)
   307  	c.Assert(s.machine.Life(), gc.Equals, state.Alive)
   308  
   309  	// Once no unit is assigned, lifecycle can advance.
   310  	err = unit.UnassignFromMachine()
   311  	c.Assert(err, jc.ErrorIsNil)
   312  	err = s.machine.Destroy()
   313  	c.Assert(s.machine.Life(), gc.Equals, state.Dying)
   314  	c.Assert(err, jc.ErrorIsNil)
   315  	err = s.machine.EnsureDead()
   316  	c.Assert(err, jc.ErrorIsNil)
   317  	c.Assert(s.machine.Life(), gc.Equals, state.Dead)
   318  
   319  	// A machine that has never had units assigned can advance lifecycle.
   320  	m, err := s.State.AddMachine("quantal", state.JobHostUnits)
   321  	c.Assert(err, jc.ErrorIsNil)
   322  	err = m.Destroy()
   323  	c.Assert(err, jc.ErrorIsNil)
   324  	c.Assert(m.Life(), gc.Equals, state.Dying)
   325  	err = m.EnsureDead()
   326  	c.Assert(err, jc.ErrorIsNil)
   327  	c.Assert(m.Life(), gc.Equals, state.Dead)
   328  }
   329  
   330  func (s *MachineSuite) TestDestroyRemovePorts(c *gc.C) {
   331  	svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   332  	unit, err := svc.AddUnit()
   333  	c.Assert(err, jc.ErrorIsNil)
   334  	err = unit.AssignToMachine(s.machine)
   335  	c.Assert(err, jc.ErrorIsNil)
   336  	err = unit.OpenPort("tcp", 8080)
   337  	c.Assert(err, jc.ErrorIsNil)
   338  	ports, err := state.GetPorts(s.State, s.machine.Id(), "")
   339  	c.Assert(ports, gc.NotNil)
   340  	c.Assert(err, jc.ErrorIsNil)
   341  	err = unit.UnassignFromMachine()
   342  	c.Assert(err, jc.ErrorIsNil)
   343  	err = s.machine.Destroy()
   344  	c.Assert(err, jc.ErrorIsNil)
   345  	err = s.machine.EnsureDead()
   346  	c.Assert(err, jc.ErrorIsNil)
   347  	err = s.machine.Remove()
   348  	c.Assert(err, jc.ErrorIsNil)
   349  	// once the machine is destroyed, there should be no ports documents present for it
   350  	ports, err = state.GetPorts(s.State, s.machine.Id(), "")
   351  	c.Assert(ports, gc.IsNil)
   352  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   353  }
   354  
   355  func (s *MachineSuite) TestDestroyOps(c *gc.C) {
   356  	m := s.Factory.MakeMachine(c, nil)
   357  	ops, err := state.ForceDestroyMachineOps(m)
   358  	c.Assert(err, jc.ErrorIsNil)
   359  	c.Assert(ops, gc.NotNil)
   360  }
   361  
   362  func (s *MachineSuite) TestDestroyOpsForManagerFails(c *gc.C) {
   363  	// s.Factory does not allow us to make a manager machine, so we grab one
   364  	// from State ...
   365  	machines, err := s.State.AllMachines()
   366  	c.Assert(err, jc.ErrorIsNil)
   367  	c.Assert(len(machines), jc.GreaterThan, 0)
   368  	m := machines[0]
   369  	c.Assert(m.IsManager(), jc.IsTrue)
   370  
   371  	// ... and assert that we cannot get the destroy ops for it.
   372  	ops, err := state.ForceDestroyMachineOps(m)
   373  	c.Assert(err, jc.Satisfies, state.IsManagerMachineError)
   374  	c.Assert(ops, gc.IsNil)
   375  }
   376  
   377  func (s *MachineSuite) TestDestroyAbort(c *gc.C) {
   378  	defer state.SetBeforeHooks(c, s.State, func() {
   379  		c.Assert(s.machine.Destroy(), gc.IsNil)
   380  	}).Check()
   381  	err := s.machine.Destroy()
   382  	c.Assert(err, jc.ErrorIsNil)
   383  }
   384  
   385  func (s *MachineSuite) TestDestroyCancel(c *gc.C) {
   386  	svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   387  	unit, err := svc.AddUnit()
   388  	c.Assert(err, jc.ErrorIsNil)
   389  
   390  	defer state.SetBeforeHooks(c, s.State, func() {
   391  		c.Assert(unit.AssignToMachine(s.machine), gc.IsNil)
   392  	}).Check()
   393  	err = s.machine.Destroy()
   394  	c.Assert(err, jc.Satisfies, state.IsHasAssignedUnitsError)
   395  }
   396  
   397  func (s *MachineSuite) TestDestroyContention(c *gc.C) {
   398  	svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   399  	unit, err := svc.AddUnit()
   400  	c.Assert(err, jc.ErrorIsNil)
   401  
   402  	perturb := jujutxn.TestHook{
   403  		Before: func() { c.Assert(unit.AssignToMachine(s.machine), gc.IsNil) },
   404  		After:  func() { c.Assert(unit.UnassignFromMachine(), gc.IsNil) },
   405  	}
   406  	defer state.SetTestHooks(c, s.State, perturb, perturb, perturb).Check()
   407  
   408  	err = s.machine.Destroy()
   409  	c.Assert(err, gc.ErrorMatches, "machine 1 cannot advance lifecycle: state changing too quickly; try again soon")
   410  }
   411  
   412  func (s *MachineSuite) TestDestroyWithServiceDestroyPending(c *gc.C) {
   413  	svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   414  	unit, err := svc.AddUnit()
   415  	c.Assert(err, jc.ErrorIsNil)
   416  	err = unit.AssignToMachine(s.machine)
   417  	c.Assert(err, jc.ErrorIsNil)
   418  
   419  	err = svc.Destroy()
   420  	c.Assert(err, jc.ErrorIsNil)
   421  	err = s.machine.Destroy()
   422  	c.Assert(err, jc.ErrorIsNil)
   423  	// Machine is still advanced to Dying.
   424  	life := s.machine.Life()
   425  	c.Assert(life, gc.Equals, state.Dying)
   426  }
   427  
   428  func (s *MachineSuite) TestDestroyFailsWhenNewUnitAdded(c *gc.C) {
   429  	svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   430  	unit, err := svc.AddUnit()
   431  	c.Assert(err, jc.ErrorIsNil)
   432  	err = unit.AssignToMachine(s.machine)
   433  	c.Assert(err, jc.ErrorIsNil)
   434  
   435  	err = svc.Destroy()
   436  	c.Assert(err, jc.ErrorIsNil)
   437  
   438  	defer state.SetBeforeHooks(c, s.State, func() {
   439  		anotherSvc := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql"))
   440  		anotherUnit, err := anotherSvc.AddUnit()
   441  		c.Assert(err, jc.ErrorIsNil)
   442  		err = anotherUnit.AssignToMachine(s.machine)
   443  		c.Assert(err, jc.ErrorIsNil)
   444  	}).Check()
   445  
   446  	err = s.machine.Destroy()
   447  	c.Assert(err, jc.Satisfies, state.IsHasAssignedUnitsError)
   448  	life := s.machine.Life()
   449  	c.Assert(life, gc.Equals, state.Alive)
   450  }
   451  
   452  func (s *MachineSuite) TestDestroyWithUnitDestroyPending(c *gc.C) {
   453  	svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   454  	unit, err := svc.AddUnit()
   455  	c.Assert(err, jc.ErrorIsNil)
   456  	err = unit.AssignToMachine(s.machine)
   457  	c.Assert(err, jc.ErrorIsNil)
   458  
   459  	err = unit.Destroy()
   460  	c.Assert(err, jc.ErrorIsNil)
   461  	err = s.machine.Destroy()
   462  	c.Assert(err, jc.ErrorIsNil)
   463  	// Machine is still advanced to Dying.
   464  	life := s.machine.Life()
   465  	c.Assert(life, gc.Equals, state.Dying)
   466  }
   467  
   468  func (s *MachineSuite) TestDestroyFailsWhenNewContainerAdded(c *gc.C) {
   469  	svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   470  	unit, err := svc.AddUnit()
   471  	c.Assert(err, jc.ErrorIsNil)
   472  	err = unit.AssignToMachine(s.machine)
   473  	c.Assert(err, jc.ErrorIsNil)
   474  
   475  	err = svc.Destroy()
   476  	c.Assert(err, jc.ErrorIsNil)
   477  
   478  	defer state.SetBeforeHooks(c, s.State, func() {
   479  		_, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
   480  			Series: "quantal",
   481  			Jobs:   []state.MachineJob{state.JobHostUnits},
   482  		}, s.machine.Id(), instance.LXC)
   483  		c.Assert(err, jc.ErrorIsNil)
   484  	}).Check()
   485  
   486  	err = s.machine.Destroy()
   487  	c.Assert(err, jc.Satisfies, state.IsHasAssignedUnitsError)
   488  	life := s.machine.Life()
   489  	c.Assert(life, gc.Equals, state.Alive)
   490  }
   491  
   492  func (s *MachineSuite) TestRemove(c *gc.C) {
   493  	err := s.State.SetSSHHostKeys(s.machine.MachineTag(), state.SSHHostKeys{"rsa", "dsa"})
   494  	c.Assert(err, jc.ErrorIsNil)
   495  
   496  	err = s.machine.Remove()
   497  	c.Assert(err, gc.ErrorMatches, "cannot remove machine 1: machine is not dead")
   498  
   499  	err = s.machine.EnsureDead()
   500  	c.Assert(err, jc.ErrorIsNil)
   501  
   502  	err = s.machine.Remove()
   503  	c.Assert(err, jc.ErrorIsNil)
   504  
   505  	err = s.machine.Refresh()
   506  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   507  
   508  	_, err = s.machine.HardwareCharacteristics()
   509  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   510  
   511  	_, err = s.machine.Containers()
   512  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   513  
   514  	_, err = s.State.GetSSHHostKeys(s.machine.MachineTag())
   515  	c.Assert(errors.IsNotFound(err), jc.IsTrue)
   516  
   517  	// Removing an already removed machine is OK.
   518  	err = s.machine.Remove()
   519  	c.Assert(err, jc.ErrorIsNil)
   520  }
   521  
   522  func (s *MachineSuite) TestRemoveMarksAddressesAsDead(c *gc.C) {
   523  	err := s.machine.SetProvisioned("fake", "totally-fake", nil)
   524  	c.Assert(err, jc.ErrorIsNil)
   525  
   526  	addr1, err := s.State.AddIPAddress(network.NewAddress("10.0.0.1"), "foo")
   527  	c.Assert(err, jc.ErrorIsNil)
   528  	err = addr1.AllocateTo(s.machine.Id(), "bar", "01:23:45:67:89:ab")
   529  	c.Assert(err, jc.ErrorIsNil)
   530  
   531  	addr2, err := s.State.AddIPAddress(network.NewAddress("10.0.0.2"), "foo")
   532  	c.Assert(err, jc.ErrorIsNil)
   533  	err = addr2.AllocateTo(s.machine.Id(), "bar", "01:23:45:67:89:ab")
   534  	c.Assert(err, jc.ErrorIsNil)
   535  
   536  	addr3, err := s.State.AddIPAddress(network.NewAddress("10.0.0.3"), "bar")
   537  	c.Assert(err, jc.ErrorIsNil)
   538  	err = addr3.AllocateTo(s.machine0.Id(), "bar", "01:23:45:67:89:ab")
   539  	c.Assert(err, jc.ErrorIsNil)
   540  
   541  	addr4, err := s.State.AddIPAddress(network.NewAddress("10.0.0.4"), "foo")
   542  	c.Assert(err, jc.ErrorIsNil)
   543  	err = addr4.AllocateTo(s.machine.Id(), "bar", "01:23:45:67:89:ab")
   544  	c.Assert(err, jc.ErrorIsNil)
   545  	err = addr4.EnsureDead()
   546  	c.Assert(err, jc.ErrorIsNil)
   547  
   548  	err = s.machine.EnsureDead()
   549  	c.Assert(err, jc.ErrorIsNil)
   550  	err = s.machine.Remove()
   551  	c.Assert(err, jc.ErrorIsNil)
   552  
   553  	err = addr1.Refresh()
   554  	c.Assert(err, jc.ErrorIsNil)
   555  	c.Assert(addr1.Life(), gc.Equals, state.Dead)
   556  	err = addr2.Refresh()
   557  	c.Assert(err, jc.ErrorIsNil)
   558  	c.Assert(addr2.Life(), gc.Equals, state.Dead)
   559  	err = addr3.Refresh()
   560  	c.Assert(err, jc.ErrorIsNil)
   561  	c.Assert(addr3.Life(), gc.Equals, state.Alive)
   562  	err = addr4.Refresh()
   563  	c.Assert(err, jc.ErrorIsNil)
   564  	c.Assert(addr4.Life(), gc.Equals, state.Dead)
   565  }
   566  
   567  func (s *MachineSuite) TestHasVote(c *gc.C) {
   568  	c.Assert(s.machine.HasVote(), jc.IsFalse)
   569  
   570  	// Make another machine value so that
   571  	// it won't have the cached HasVote value.
   572  	m, err := s.State.Machine(s.machine.Id())
   573  	c.Assert(err, jc.ErrorIsNil)
   574  
   575  	err = s.machine.SetHasVote(true)
   576  	c.Assert(err, jc.ErrorIsNil)
   577  	c.Assert(s.machine.HasVote(), jc.IsTrue)
   578  	c.Assert(m.HasVote(), jc.IsFalse)
   579  
   580  	err = m.Refresh()
   581  	c.Assert(err, jc.ErrorIsNil)
   582  	c.Assert(m.HasVote(), jc.IsTrue)
   583  
   584  	err = m.SetHasVote(false)
   585  	c.Assert(err, jc.ErrorIsNil)
   586  	c.Assert(m.HasVote(), jc.IsFalse)
   587  
   588  	c.Assert(s.machine.HasVote(), jc.IsTrue)
   589  	err = s.machine.Refresh()
   590  	c.Assert(err, jc.ErrorIsNil)
   591  	c.Assert(s.machine.HasVote(), jc.IsFalse)
   592  }
   593  
   594  func (s *MachineSuite) TestCannotDestroyMachineWithVote(c *gc.C) {
   595  	err := s.machine.SetHasVote(true)
   596  	c.Assert(err, jc.ErrorIsNil)
   597  
   598  	// Make another machine value so that
   599  	// it won't have the cached HasVote value.
   600  	m, err := s.State.Machine(s.machine.Id())
   601  	c.Assert(err, jc.ErrorIsNil)
   602  
   603  	err = s.machine.Destroy()
   604  	c.Assert(err, gc.ErrorMatches, "machine "+s.machine.Id()+" is a voting replica set member")
   605  
   606  	err = m.Destroy()
   607  	c.Assert(err, gc.ErrorMatches, "machine "+s.machine.Id()+" is a voting replica set member")
   608  }
   609  
   610  func (s *MachineSuite) TestRemoveAbort(c *gc.C) {
   611  	err := s.machine.EnsureDead()
   612  	c.Assert(err, jc.ErrorIsNil)
   613  
   614  	defer state.SetBeforeHooks(c, s.State, func() {
   615  		c.Assert(s.machine.Remove(), gc.IsNil)
   616  	}).Check()
   617  	err = s.machine.Remove()
   618  	c.Assert(err, jc.ErrorIsNil)
   619  }
   620  
   621  func (s *MachineSuite) TestMachineSetAgentPresence(c *gc.C) {
   622  	alive, err := s.machine.AgentPresence()
   623  	c.Assert(err, jc.ErrorIsNil)
   624  	c.Assert(alive, jc.IsFalse)
   625  
   626  	pinger, err := s.machine.SetAgentPresence()
   627  	c.Assert(err, jc.ErrorIsNil)
   628  	c.Assert(pinger, gc.NotNil)
   629  	defer pinger.Stop()
   630  
   631  	s.State.StartSync()
   632  	alive, err = s.machine.AgentPresence()
   633  	c.Assert(err, jc.ErrorIsNil)
   634  	c.Assert(alive, jc.IsTrue)
   635  }
   636  
   637  func (s *MachineSuite) TestTag(c *gc.C) {
   638  	tag := s.machine.MachineTag()
   639  	c.Assert(tag.Kind(), gc.Equals, names.MachineTagKind)
   640  	c.Assert(tag.Id(), gc.Equals, "1")
   641  
   642  	// To keep gccgo happy, don't compare an interface with a struct.
   643  	var asTag names.Tag = tag
   644  	c.Assert(s.machine.Tag(), gc.Equals, asTag)
   645  }
   646  
   647  func (s *MachineSuite) TestSetMongoPassword(c *gc.C) {
   648  	info := testing.NewMongoInfo()
   649  	st, err := state.Open(s.modelTag, info, mongotest.DialOpts(), state.Policy(nil))
   650  	c.Assert(err, jc.ErrorIsNil)
   651  	defer func() {
   652  		// Remove the admin password so that the test harness can reset the state.
   653  		err := st.SetAdminMongoPassword("")
   654  		c.Check(err, jc.ErrorIsNil)
   655  		err = st.Close()
   656  		c.Check(err, jc.ErrorIsNil)
   657  	}()
   658  
   659  	// Turn on fully-authenticated mode.
   660  	err = st.SetAdminMongoPassword("admin-secret")
   661  	c.Assert(err, jc.ErrorIsNil)
   662  	err = st.MongoSession().DB("admin").Login("admin", "admin-secret")
   663  	c.Assert(err, jc.ErrorIsNil)
   664  
   665  	// Set the password for the entity
   666  	ent, err := st.Machine("0")
   667  	c.Assert(err, jc.ErrorIsNil)
   668  	err = ent.SetMongoPassword("foo")
   669  	c.Assert(err, jc.ErrorIsNil)
   670  
   671  	// Check that we cannot log in with the wrong password.
   672  	info.Tag = ent.Tag()
   673  	info.Password = "bar"
   674  	err = tryOpenState(s.modelTag, info)
   675  	c.Check(errors.Cause(err), jc.Satisfies, errors.IsUnauthorized)
   676  	c.Check(err, gc.ErrorMatches, `cannot log in to admin database as "machine-0": unauthorized mongo access: .*`)
   677  
   678  	// Check that we can log in with the correct password.
   679  	info.Password = "foo"
   680  	st1, err := state.Open(s.modelTag, info, mongotest.DialOpts(), state.Policy(nil))
   681  	c.Assert(err, jc.ErrorIsNil)
   682  	defer st1.Close()
   683  
   684  	// Change the password with an entity derived from the newly
   685  	// opened and authenticated state.
   686  	ent, err = st.Machine("0")
   687  	c.Assert(err, jc.ErrorIsNil)
   688  	err = ent.SetMongoPassword("bar")
   689  	c.Assert(err, jc.ErrorIsNil)
   690  
   691  	// Check that we cannot log in with the old password.
   692  	info.Password = "foo"
   693  	err = tryOpenState(s.modelTag, info)
   694  	c.Check(errors.Cause(err), jc.Satisfies, errors.IsUnauthorized)
   695  	c.Check(err, gc.ErrorMatches, `cannot log in to admin database as "machine-0": unauthorized mongo access: .*`)
   696  
   697  	// Check that we can log in with the correct password.
   698  	info.Password = "bar"
   699  	err = tryOpenState(s.modelTag, info)
   700  	c.Assert(err, jc.ErrorIsNil)
   701  
   702  	// Check that the administrator can still log in.
   703  	info.Tag, info.Password = nil, "admin-secret"
   704  	err = tryOpenState(s.modelTag, info)
   705  	c.Assert(err, jc.ErrorIsNil)
   706  }
   707  
   708  func (s *MachineSuite) TestSetPassword(c *gc.C) {
   709  	testSetPassword(c, func() (state.Authenticator, error) {
   710  		return s.State.Machine(s.machine.Id())
   711  	})
   712  }
   713  
   714  func (s *MachineSuite) TestSetPasswordPreModelUUID(c *gc.C) {
   715  	// Ensure that SetPassword works for machines even when the env
   716  	// UUID upgrade migrations haven't run yet.
   717  	type oldMachineDoc struct {
   718  		Id     string `bson:"_id"`
   719  		Series string
   720  	}
   721  	s.machines.Insert(&oldMachineDoc{"99", "quantal"})
   722  
   723  	m, err := s.State.Machine("99")
   724  	c.Assert(err, jc.ErrorIsNil)
   725  
   726  	// Set the password and make sure it sticks.
   727  	c.Assert(m.PasswordValid(goodPassword), jc.IsFalse)
   728  	err = m.SetPassword(goodPassword)
   729  	c.Assert(err, jc.ErrorIsNil)
   730  	c.Assert(m.PasswordValid(goodPassword), jc.IsTrue)
   731  
   732  	// Check a newly-fetched entity has the same password.
   733  	err = m.Refresh()
   734  	c.Assert(err, jc.ErrorIsNil)
   735  	c.Assert(m.PasswordValid(goodPassword), jc.IsTrue)
   736  }
   737  
   738  func (s *MachineSuite) TestMachineWaitAgentPresence(c *gc.C) {
   739  	alive, err := s.machine.AgentPresence()
   740  	c.Assert(err, jc.ErrorIsNil)
   741  	c.Assert(alive, jc.IsFalse)
   742  
   743  	s.State.StartSync()
   744  	err = s.machine.WaitAgentPresence(coretesting.ShortWait)
   745  	c.Assert(err, gc.ErrorMatches, `waiting for agent of machine 1: still not alive after timeout`)
   746  
   747  	pinger, err := s.machine.SetAgentPresence()
   748  	c.Assert(err, jc.ErrorIsNil)
   749  
   750  	s.State.StartSync()
   751  	err = s.machine.WaitAgentPresence(coretesting.LongWait)
   752  	c.Assert(err, jc.ErrorIsNil)
   753  
   754  	alive, err = s.machine.AgentPresence()
   755  	c.Assert(err, jc.ErrorIsNil)
   756  	c.Assert(alive, jc.IsTrue)
   757  
   758  	err = pinger.KillForTesting()
   759  	c.Assert(err, jc.ErrorIsNil)
   760  
   761  	s.State.StartSync()
   762  	alive, err = s.machine.AgentPresence()
   763  	c.Assert(err, jc.ErrorIsNil)
   764  	c.Assert(alive, jc.IsFalse)
   765  }
   766  
   767  func (s *MachineSuite) TestMachineInstanceIdCorrupt(c *gc.C) {
   768  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   769  	c.Assert(err, jc.ErrorIsNil)
   770  	err = s.machines.Update(
   771  		bson.D{{"_id", state.DocID(s.State, machine.Id())}},
   772  		bson.D{{"$set", bson.D{{"instanceid", bson.D{{"foo", "bar"}}}}}},
   773  	)
   774  	c.Assert(err, jc.ErrorIsNil)
   775  
   776  	err = machine.Refresh()
   777  	c.Assert(err, jc.ErrorIsNil)
   778  	iid, err := machine.InstanceId()
   779  	c.Assert(err, jc.Satisfies, errors.IsNotProvisioned)
   780  	c.Assert(iid, gc.Equals, instance.Id(""))
   781  }
   782  
   783  func (s *MachineSuite) TestMachineInstanceIdMissing(c *gc.C) {
   784  	iid, err := s.machine.InstanceId()
   785  	c.Assert(err, jc.Satisfies, errors.IsNotProvisioned)
   786  	c.Assert(string(iid), gc.Equals, "")
   787  }
   788  
   789  func (s *MachineSuite) TestMachineInstanceIdBlank(c *gc.C) {
   790  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   791  	c.Assert(err, jc.ErrorIsNil)
   792  	err = s.machines.Update(
   793  		bson.D{{"_id", state.DocID(s.State, machine.Id())}},
   794  		bson.D{{"$set", bson.D{{"instanceid", ""}}}},
   795  	)
   796  	c.Assert(err, jc.ErrorIsNil)
   797  
   798  	err = machine.Refresh()
   799  	c.Assert(err, jc.ErrorIsNil)
   800  	iid, err := machine.InstanceId()
   801  	c.Assert(err, jc.Satisfies, errors.IsNotProvisioned)
   802  	c.Assert(string(iid), gc.Equals, "")
   803  }
   804  
   805  func (s *MachineSuite) TestMachineSetProvisionedUpdatesCharacteristics(c *gc.C) {
   806  	// Before provisioning, there is no hardware characteristics.
   807  	_, err := s.machine.HardwareCharacteristics()
   808  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   809  	arch := "amd64"
   810  	mem := uint64(4096)
   811  	expected := &instance.HardwareCharacteristics{
   812  		Arch: &arch,
   813  		Mem:  &mem,
   814  	}
   815  	err = s.machine.SetProvisioned("umbrella/0", "fake_nonce", expected)
   816  	c.Assert(err, jc.ErrorIsNil)
   817  	md, err := s.machine.HardwareCharacteristics()
   818  	c.Assert(err, jc.ErrorIsNil)
   819  	c.Assert(*md, gc.DeepEquals, *expected)
   820  
   821  	// Reload machine and check again.
   822  	err = s.machine.Refresh()
   823  	c.Assert(err, jc.ErrorIsNil)
   824  	md, err = s.machine.HardwareCharacteristics()
   825  	c.Assert(err, jc.ErrorIsNil)
   826  	c.Assert(*md, gc.DeepEquals, *expected)
   827  }
   828  
   829  func (s *MachineSuite) TestMachineAvailabilityZone(c *gc.C) {
   830  	zone := "a_zone"
   831  	hwc := &instance.HardwareCharacteristics{
   832  		AvailabilityZone: &zone,
   833  	}
   834  	err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", hwc)
   835  	c.Assert(err, jc.ErrorIsNil)
   836  
   837  	zone, err = s.machine.AvailabilityZone()
   838  	c.Assert(err, jc.ErrorIsNil)
   839  	c.Check(zone, gc.Equals, "a_zone")
   840  }
   841  
   842  func (s *MachineSuite) TestMachineAvailabilityZoneEmpty(c *gc.C) {
   843  	zone := ""
   844  	hwc := &instance.HardwareCharacteristics{
   845  		AvailabilityZone: &zone,
   846  	}
   847  	err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", hwc)
   848  	c.Assert(err, jc.ErrorIsNil)
   849  
   850  	zone, err = s.machine.AvailabilityZone()
   851  	c.Assert(err, jc.ErrorIsNil)
   852  	c.Check(zone, gc.Equals, "")
   853  }
   854  
   855  func (s *MachineSuite) TestMachineAvailabilityZoneMissing(c *gc.C) {
   856  	zone := "a_zone"
   857  	hwc := &instance.HardwareCharacteristics{}
   858  	err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", hwc)
   859  	c.Assert(err, jc.ErrorIsNil)
   860  
   861  	zone, err = s.machine.AvailabilityZone()
   862  	c.Assert(err, jc.ErrorIsNil)
   863  	c.Check(zone, gc.Equals, "")
   864  }
   865  
   866  func (s *MachineSuite) TestMachineSetCheckProvisioned(c *gc.C) {
   867  	// Check before provisioning.
   868  	c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse)
   869  
   870  	// Either one should not be empty.
   871  	err := s.machine.SetProvisioned("umbrella/0", "", nil)
   872  	c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`)
   873  	err = s.machine.SetProvisioned("", "fake_nonce", nil)
   874  	c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`)
   875  	err = s.machine.SetProvisioned("", "", nil)
   876  	c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`)
   877  
   878  	err = s.machine.SetProvisioned("umbrella/0", "fake_nonce", nil)
   879  	c.Assert(err, jc.ErrorIsNil)
   880  
   881  	m, err := s.State.Machine(s.machine.Id())
   882  	c.Assert(err, jc.ErrorIsNil)
   883  	id, err := m.InstanceId()
   884  	c.Assert(err, jc.ErrorIsNil)
   885  	c.Assert(string(id), gc.Equals, "umbrella/0")
   886  	c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue)
   887  	id, err = s.machine.InstanceId()
   888  	c.Assert(err, jc.ErrorIsNil)
   889  	c.Assert(string(id), gc.Equals, "umbrella/0")
   890  	c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue)
   891  
   892  	// Try it twice, it should fail.
   893  	err = s.machine.SetProvisioned("doesn't-matter", "phony", nil)
   894  	c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": already set`)
   895  
   896  	// Check it with invalid nonce.
   897  	c.Assert(s.machine.CheckProvisioned("not-really"), jc.IsFalse)
   898  }
   899  
   900  func (s *MachineSuite) TestMachineSetInstanceInfoFailureDoesNotProvision(c *gc.C) {
   901  	assertNotProvisioned := func() {
   902  		c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse)
   903  	}
   904  
   905  	assertNotProvisioned()
   906  
   907  	invalidVolumes := map[names.VolumeTag]state.VolumeInfo{
   908  		names.NewVolumeTag("1065"): state.VolumeInfo{VolumeId: "vol-ume"},
   909  	}
   910  	err := s.machine.SetInstanceInfo("umbrella/0", "fake_nonce", nil, nil, nil, invalidVolumes, nil)
   911  	c.Assert(err, gc.ErrorMatches, `cannot set info for volume \"1065\": volume \"1065\" not found`)
   912  	assertNotProvisioned()
   913  
   914  	invalidVolumes = map[names.VolumeTag]state.VolumeInfo{
   915  		names.NewVolumeTag("1065"): state.VolumeInfo{},
   916  	}
   917  	err = s.machine.SetInstanceInfo("umbrella/0", "fake_nonce", nil, nil, nil, invalidVolumes, nil)
   918  	c.Assert(err, gc.ErrorMatches, `cannot set info for volume \"1065\": volume ID not set`)
   919  	assertNotProvisioned()
   920  
   921  	// TODO(axw) test invalid volume attachment
   922  }
   923  
   924  func (s *MachineSuite) addVolume(c *gc.C, params state.VolumeParams, machineId string) names.VolumeTag {
   925  	ops, tag, err := state.AddVolumeOps(s.State, params, machineId)
   926  	c.Assert(err, jc.ErrorIsNil)
   927  	err = state.RunTransaction(s.State, ops)
   928  	c.Assert(err, jc.ErrorIsNil)
   929  	return tag
   930  }
   931  
   932  func (s *MachineSuite) TestMachineSetInstanceInfoSuccess(c *gc.C) {
   933  	pm := poolmanager.New(state.NewStateSettings(s.State))
   934  	_, err := pm.Create("loop-pool", provider.LoopProviderType, map[string]interface{}{})
   935  	c.Assert(err, jc.ErrorIsNil)
   936  	registry.RegisterEnvironStorageProviders("someprovider", provider.LoopProviderType)
   937  
   938  	// Must create the requested block device prior to SetInstanceInfo.
   939  	volumeTag := s.addVolume(c, state.VolumeParams{Size: 1000, Pool: "loop-pool"}, "123")
   940  	c.Assert(volumeTag, gc.Equals, names.NewVolumeTag("123/0"))
   941  
   942  	c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse)
   943  	volumeInfo := state.VolumeInfo{
   944  		VolumeId: "storage-123",
   945  		Size:     1234,
   946  	}
   947  	volumes := map[names.VolumeTag]state.VolumeInfo{volumeTag: volumeInfo}
   948  	err = s.machine.SetInstanceInfo("umbrella/0", "fake_nonce", nil, nil, nil, volumes, nil)
   949  	c.Assert(err, jc.ErrorIsNil)
   950  	c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue)
   951  
   952  	volume, err := s.State.Volume(volumeTag)
   953  	c.Assert(err, jc.ErrorIsNil)
   954  	info, err := volume.Info()
   955  	c.Assert(err, jc.ErrorIsNil)
   956  	volumeInfo.Pool = "loop-pool" // taken from params
   957  	c.Assert(info, gc.Equals, volumeInfo)
   958  }
   959  
   960  func (s *MachineSuite) TestMachineSetProvisionedWhenNotAlive(c *gc.C) {
   961  	testWhenDying(c, s.machine, notAliveErr, notAliveErr, func() error {
   962  		return s.machine.SetProvisioned("umbrella/0", "fake_nonce", nil)
   963  	})
   964  }
   965  
   966  func (s *MachineSuite) TestMachineSetInstanceStatus(c *gc.C) {
   967  	// Machine needs to be provisioned first.
   968  	err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", nil)
   969  	c.Assert(err, jc.ErrorIsNil)
   970  
   971  	err = s.machine.SetInstanceStatus(status.StatusRunning, "alive", map[string]interface{}{})
   972  	c.Assert(err, jc.ErrorIsNil)
   973  
   974  	// Reload machine and check result.
   975  	err = s.machine.Refresh()
   976  	c.Assert(err, jc.ErrorIsNil)
   977  	machineStatus, err := s.machine.InstanceStatus()
   978  	c.Assert(err, jc.ErrorIsNil)
   979  	c.Assert(machineStatus.Status, gc.DeepEquals, status.StatusRunning)
   980  	c.Assert(machineStatus.Message, gc.DeepEquals, "alive")
   981  }
   982  
   983  func (s *MachineSuite) TestMachineRefresh(c *gc.C) {
   984  	m0, err := s.State.AddMachine("quantal", state.JobHostUnits)
   985  	c.Assert(err, jc.ErrorIsNil)
   986  	oldTools, _ := m0.AgentTools()
   987  	m1, err := s.State.Machine(m0.Id())
   988  	c.Assert(err, jc.ErrorIsNil)
   989  	err = m0.SetAgentVersion(version.MustParseBinary("0.0.3-quantal-amd64"))
   990  	c.Assert(err, jc.ErrorIsNil)
   991  	newTools, _ := m0.AgentTools()
   992  
   993  	m1Tools, _ := m1.AgentTools()
   994  	c.Assert(m1Tools, gc.DeepEquals, oldTools)
   995  	err = m1.Refresh()
   996  	c.Assert(err, jc.ErrorIsNil)
   997  	m1Tools, _ = m1.AgentTools()
   998  	c.Assert(*m1Tools, gc.Equals, *newTools)
   999  
  1000  	err = m0.EnsureDead()
  1001  	c.Assert(err, jc.ErrorIsNil)
  1002  	err = m0.Remove()
  1003  	c.Assert(err, jc.ErrorIsNil)
  1004  	err = m0.Refresh()
  1005  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
  1006  }
  1007  
  1008  func (s *MachineSuite) TestRefreshWhenNotAlive(c *gc.C) {
  1009  	// Refresh should work regardless of liveness status.
  1010  	testWhenDying(c, s.machine, noErr, noErr, func() error {
  1011  		return s.machine.Refresh()
  1012  	})
  1013  }
  1014  
  1015  func (s *MachineSuite) TestMachinePrincipalUnits(c *gc.C) {
  1016  	// Check that Machine.Units and st.UnitsFor work correctly.
  1017  
  1018  	// Make three machines, three services and three units for each service;
  1019  	// variously assign units to machines and check that Machine.Units
  1020  	// tells us the right thing.
  1021  
  1022  	m1 := s.machine
  1023  	m2, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1024  	c.Assert(err, jc.ErrorIsNil)
  1025  	m3, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1026  	c.Assert(err, jc.ErrorIsNil)
  1027  
  1028  	dummy := s.AddTestingCharm(c, "dummy")
  1029  	logging := s.AddTestingCharm(c, "logging")
  1030  	s0 := s.AddTestingService(c, "s0", dummy)
  1031  	s1 := s.AddTestingService(c, "s1", dummy)
  1032  	s2 := s.AddTestingService(c, "s2", dummy)
  1033  	s3 := s.AddTestingService(c, "s3", logging)
  1034  
  1035  	units := make([][]*state.Unit, 4)
  1036  	for i, svc := range []*state.Service{s0, s1, s2} {
  1037  		units[i] = make([]*state.Unit, 3)
  1038  		for j := range units[i] {
  1039  			units[i][j], err = svc.AddUnit()
  1040  			c.Assert(err, jc.ErrorIsNil)
  1041  		}
  1042  	}
  1043  	// Add the logging units subordinate to the s2 units.
  1044  	eps, err := s.State.InferEndpoints("s2", "s3")
  1045  	c.Assert(err, jc.ErrorIsNil)
  1046  	rel, err := s.State.AddRelation(eps...)
  1047  	c.Assert(err, jc.ErrorIsNil)
  1048  	for _, u := range units[2] {
  1049  		ru, err := rel.Unit(u)
  1050  		c.Assert(err, jc.ErrorIsNil)
  1051  		err = ru.EnterScope(nil)
  1052  		c.Assert(err, jc.ErrorIsNil)
  1053  	}
  1054  	units[3], err = s3.AllUnits()
  1055  	c.Assert(err, jc.ErrorIsNil)
  1056  	c.Assert(sortedUnitNames(units[3]), jc.DeepEquals, []string{"s3/0", "s3/1", "s3/2"})
  1057  
  1058  	assignments := []struct {
  1059  		machine      *state.Machine
  1060  		units        []*state.Unit
  1061  		subordinates []*state.Unit
  1062  	}{
  1063  		{m1, []*state.Unit{units[0][0]}, nil},
  1064  		{m2, []*state.Unit{units[0][1], units[1][0], units[1][1], units[2][0]}, []*state.Unit{units[3][0]}},
  1065  		{m3, []*state.Unit{units[2][2]}, []*state.Unit{units[3][2]}},
  1066  	}
  1067  
  1068  	for _, a := range assignments {
  1069  		for _, u := range a.units {
  1070  			err := u.AssignToMachine(a.machine)
  1071  			c.Assert(err, jc.ErrorIsNil)
  1072  		}
  1073  	}
  1074  
  1075  	for i, a := range assignments {
  1076  		c.Logf("test %d", i)
  1077  		expect := sortedUnitNames(append(a.units, a.subordinates...))
  1078  
  1079  		// The units can be retrieved from the machine model.
  1080  		got, err := a.machine.Units()
  1081  		c.Assert(err, jc.ErrorIsNil)
  1082  		c.Assert(sortedUnitNames(got), jc.DeepEquals, expect)
  1083  
  1084  		// The units can be retrieved from the machine id.
  1085  		got, err = s.State.UnitsFor(a.machine.Id())
  1086  		c.Assert(err, jc.ErrorIsNil)
  1087  		c.Assert(sortedUnitNames(got), jc.DeepEquals, expect)
  1088  	}
  1089  }
  1090  
  1091  func sortedUnitNames(units []*state.Unit) []string {
  1092  	names := make([]string, len(units))
  1093  	for i, u := range units {
  1094  		names[i] = u.Name()
  1095  	}
  1096  	sort.Strings(names)
  1097  	return names
  1098  }
  1099  
  1100  func (s *MachineSuite) assertMachineDirtyAfterAddingUnit(c *gc.C) (*state.Machine, *state.Service, *state.Unit) {
  1101  	m, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1102  	c.Assert(err, jc.ErrorIsNil)
  1103  	c.Assert(m.Clean(), jc.IsTrue)
  1104  
  1105  	svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
  1106  	unit, err := svc.AddUnit()
  1107  	c.Assert(err, jc.ErrorIsNil)
  1108  	err = unit.AssignToMachine(m)
  1109  	c.Assert(err, jc.ErrorIsNil)
  1110  	c.Assert(m.Clean(), jc.IsFalse)
  1111  	return m, svc, unit
  1112  }
  1113  
  1114  func (s *MachineSuite) TestMachineDirtyAfterAddingUnit(c *gc.C) {
  1115  	s.assertMachineDirtyAfterAddingUnit(c)
  1116  }
  1117  
  1118  func (s *MachineSuite) TestMachineDirtyAfterUnassigningUnit(c *gc.C) {
  1119  	m, _, unit := s.assertMachineDirtyAfterAddingUnit(c)
  1120  	err := unit.UnassignFromMachine()
  1121  	c.Assert(err, jc.ErrorIsNil)
  1122  	c.Assert(m.Clean(), jc.IsFalse)
  1123  }
  1124  
  1125  func (s *MachineSuite) TestMachineDirtyAfterRemovingUnit(c *gc.C) {
  1126  	m, svc, unit := s.assertMachineDirtyAfterAddingUnit(c)
  1127  	err := unit.EnsureDead()
  1128  	c.Assert(err, jc.ErrorIsNil)
  1129  	err = unit.Remove()
  1130  	c.Assert(err, jc.ErrorIsNil)
  1131  	err = svc.Destroy()
  1132  	c.Assert(err, jc.ErrorIsNil)
  1133  	c.Assert(m.Clean(), jc.IsFalse)
  1134  }
  1135  
  1136  func (s *MachineSuite) TestWatchMachine(c *gc.C) {
  1137  	w := s.machine.Watch()
  1138  	defer testing.AssertStop(c, w)
  1139  
  1140  	// Initial event.
  1141  	wc := testing.NewNotifyWatcherC(c, s.State, w)
  1142  	wc.AssertOneChange()
  1143  
  1144  	// Make one change (to a separate instance), check one event.
  1145  	machine, err := s.State.Machine(s.machine.Id())
  1146  	c.Assert(err, jc.ErrorIsNil)
  1147  	err = machine.SetProvisioned("m-foo", "fake_nonce", nil)
  1148  	c.Assert(err, jc.ErrorIsNil)
  1149  	wc.AssertOneChange()
  1150  
  1151  	// Make two changes, check one event.
  1152  	err = machine.SetAgentVersion(version.MustParseBinary("0.0.3-quantal-amd64"))
  1153  	c.Assert(err, jc.ErrorIsNil)
  1154  	err = machine.Destroy()
  1155  	c.Assert(err, jc.ErrorIsNil)
  1156  	wc.AssertOneChange()
  1157  
  1158  	// Stop, check closed.
  1159  	testing.AssertStop(c, w)
  1160  	wc.AssertClosed()
  1161  
  1162  	// Remove machine, start new watch, check single event.
  1163  	err = machine.EnsureDead()
  1164  	c.Assert(err, jc.ErrorIsNil)
  1165  	err = machine.Remove()
  1166  	c.Assert(err, jc.ErrorIsNil)
  1167  	w = s.machine.Watch()
  1168  	defer testing.AssertStop(c, w)
  1169  	testing.NewNotifyWatcherC(c, s.State, w).AssertOneChange()
  1170  }
  1171  
  1172  func (s *MachineSuite) TestWatchDiesOnStateClose(c *gc.C) {
  1173  	// This test is testing logic in watcher.entityWatcher, which
  1174  	// is also used by:
  1175  	//  Machine.WatchHardwareCharacteristics
  1176  	//  Service.Watch
  1177  	//  Unit.Watch
  1178  	//  State.WatchForModelConfigChanges
  1179  	//  Unit.WatchConfigSettings
  1180  	testWatcherDiesWhenStateCloses(c, s.modelTag, func(c *gc.C, st *state.State) waiter {
  1181  		m, err := st.Machine(s.machine.Id())
  1182  		c.Assert(err, jc.ErrorIsNil)
  1183  		w := m.Watch()
  1184  		<-w.Changes()
  1185  		return w
  1186  	})
  1187  }
  1188  
  1189  func (s *MachineSuite) TestWatchPrincipalUnits(c *gc.C) {
  1190  	// TODO(mjs) - MODELUUID - test with multiple models with
  1191  	// identically named units and ensure there's no leakage.
  1192  
  1193  	// Start a watch on an empty machine; check no units reported.
  1194  	w := s.machine.WatchPrincipalUnits()
  1195  	defer testing.AssertStop(c, w)
  1196  	wc := testing.NewStringsWatcherC(c, s.State, w)
  1197  	wc.AssertChange()
  1198  	wc.AssertNoChange()
  1199  
  1200  	// Change machine, and create a unit independently; no change.
  1201  	err := s.machine.SetProvisioned("cheese", "fake_nonce", nil)
  1202  	c.Assert(err, jc.ErrorIsNil)
  1203  	wc.AssertNoChange()
  1204  	mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql"))
  1205  	mysql0, err := mysql.AddUnit()
  1206  	c.Assert(err, jc.ErrorIsNil)
  1207  	wc.AssertNoChange()
  1208  
  1209  	// Assign that unit (to a separate machine instance); change detected.
  1210  	machine, err := s.State.Machine(s.machine.Id())
  1211  	c.Assert(err, jc.ErrorIsNil)
  1212  	err = mysql0.AssignToMachine(machine)
  1213  	c.Assert(err, jc.ErrorIsNil)
  1214  	wc.AssertChange("mysql/0")
  1215  	wc.AssertNoChange()
  1216  
  1217  	// Change the unit; no change.
  1218  	err = mysql0.SetAgentStatus(status.StatusIdle, "", nil)
  1219  	c.Assert(err, jc.ErrorIsNil)
  1220  	wc.AssertNoChange()
  1221  
  1222  	// Assign another unit and make the first Dying; check both changes detected.
  1223  	mysql1, err := mysql.AddUnit()
  1224  	c.Assert(err, jc.ErrorIsNil)
  1225  	err = mysql1.AssignToMachine(machine)
  1226  	c.Assert(err, jc.ErrorIsNil)
  1227  	err = mysql0.Destroy()
  1228  	c.Assert(err, jc.ErrorIsNil)
  1229  	wc.AssertChange("mysql/0", "mysql/1")
  1230  	wc.AssertNoChange()
  1231  
  1232  	// Add a subordinate to the Alive unit; no change.
  1233  	s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging"))
  1234  	eps, err := s.State.InferEndpoints("mysql", "logging")
  1235  	c.Assert(err, jc.ErrorIsNil)
  1236  	rel, err := s.State.AddRelation(eps...)
  1237  	c.Assert(err, jc.ErrorIsNil)
  1238  	mysqlru1, err := rel.Unit(mysql1)
  1239  	c.Assert(err, jc.ErrorIsNil)
  1240  	err = mysqlru1.EnterScope(nil)
  1241  	c.Assert(err, jc.ErrorIsNil)
  1242  	logging0, err := s.State.Unit("logging/0")
  1243  	c.Assert(err, jc.ErrorIsNil)
  1244  	wc.AssertNoChange()
  1245  
  1246  	// Change the subordinate; no change.
  1247  	err = logging0.SetAgentStatus(status.StatusIdle, "", nil)
  1248  	c.Assert(err, jc.ErrorIsNil)
  1249  	wc.AssertNoChange()
  1250  
  1251  	// Make the Dying unit Dead; change detected.
  1252  	err = mysql0.EnsureDead()
  1253  	c.Assert(err, jc.ErrorIsNil)
  1254  	wc.AssertChange("mysql/0")
  1255  	wc.AssertNoChange()
  1256  
  1257  	// Stop watcher; check Changes chan closed.
  1258  	testing.AssertStop(c, w)
  1259  	wc.AssertClosed()
  1260  
  1261  	// Start a fresh watcher; check both principals reported.
  1262  	w = s.machine.WatchPrincipalUnits()
  1263  	defer testing.AssertStop(c, w)
  1264  	wc = testing.NewStringsWatcherC(c, s.State, w)
  1265  	wc.AssertChange("mysql/0", "mysql/1")
  1266  	wc.AssertNoChange()
  1267  
  1268  	// Remove the Dead unit; no change.
  1269  	err = mysql0.Remove()
  1270  	c.Assert(err, jc.ErrorIsNil)
  1271  	wc.AssertNoChange()
  1272  
  1273  	// Destroy the subordinate; no change.
  1274  	err = logging0.Destroy()
  1275  	c.Assert(err, jc.ErrorIsNil)
  1276  	wc.AssertNoChange()
  1277  
  1278  	// Unassign the unit; check change.
  1279  	err = mysql1.UnassignFromMachine()
  1280  	c.Assert(err, jc.ErrorIsNil)
  1281  	wc.AssertChange("mysql/1")
  1282  	wc.AssertNoChange()
  1283  }
  1284  
  1285  func (s *MachineSuite) TestWatchPrincipalUnitsDiesOnStateClose(c *gc.C) {
  1286  	// This test is testing logic in watcher.unitsWatcher, which
  1287  	// is also used by Unit.WatchSubordinateUnits.
  1288  	testWatcherDiesWhenStateCloses(c, s.modelTag, func(c *gc.C, st *state.State) waiter {
  1289  		m, err := st.Machine(s.machine.Id())
  1290  		c.Assert(err, jc.ErrorIsNil)
  1291  		w := m.WatchPrincipalUnits()
  1292  		<-w.Changes()
  1293  		return w
  1294  	})
  1295  }
  1296  
  1297  func (s *MachineSuite) TestWatchUnits(c *gc.C) {
  1298  	// Start a watch on an empty machine; check no units reported.
  1299  	w := s.machine.WatchUnits()
  1300  	defer testing.AssertStop(c, w)
  1301  	wc := testing.NewStringsWatcherC(c, s.State, w)
  1302  	wc.AssertChange()
  1303  	wc.AssertNoChange()
  1304  
  1305  	// Change machine; no change.
  1306  	err := s.machine.SetProvisioned("cheese", "fake_nonce", nil)
  1307  	c.Assert(err, jc.ErrorIsNil)
  1308  	wc.AssertNoChange()
  1309  
  1310  	// Assign a unit (to a separate instance); change detected.
  1311  	mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql"))
  1312  	mysql0, err := mysql.AddUnit()
  1313  	c.Assert(err, jc.ErrorIsNil)
  1314  	machine, err := s.State.Machine(s.machine.Id())
  1315  	c.Assert(err, jc.ErrorIsNil)
  1316  	err = mysql0.AssignToMachine(machine)
  1317  	c.Assert(err, jc.ErrorIsNil)
  1318  	wc.AssertChange("mysql/0")
  1319  	wc.AssertNoChange()
  1320  
  1321  	// Change the unit; no change.
  1322  	err = mysql0.SetAgentStatus(status.StatusIdle, "", nil)
  1323  	c.Assert(err, jc.ErrorIsNil)
  1324  	wc.AssertNoChange()
  1325  
  1326  	// Assign another unit and make the first Dying; check both changes detected.
  1327  	mysql1, err := mysql.AddUnit()
  1328  	c.Assert(err, jc.ErrorIsNil)
  1329  	err = mysql1.AssignToMachine(machine)
  1330  	c.Assert(err, jc.ErrorIsNil)
  1331  	err = mysql0.Destroy()
  1332  	c.Assert(err, jc.ErrorIsNil)
  1333  	wc.AssertChange("mysql/0", "mysql/1")
  1334  	wc.AssertNoChange()
  1335  
  1336  	// Add a subordinate to the Alive unit; change detected.
  1337  	s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging"))
  1338  	eps, err := s.State.InferEndpoints("mysql", "logging")
  1339  	c.Assert(err, jc.ErrorIsNil)
  1340  	rel, err := s.State.AddRelation(eps...)
  1341  	c.Assert(err, jc.ErrorIsNil)
  1342  	mysqlru1, err := rel.Unit(mysql1)
  1343  	c.Assert(err, jc.ErrorIsNil)
  1344  	err = mysqlru1.EnterScope(nil)
  1345  	c.Assert(err, jc.ErrorIsNil)
  1346  	logging0, err := s.State.Unit("logging/0")
  1347  	c.Assert(err, jc.ErrorIsNil)
  1348  	wc.AssertChange("logging/0")
  1349  	wc.AssertNoChange()
  1350  
  1351  	// Change the subordinate; no change.
  1352  	err = logging0.SetAgentStatus(status.StatusIdle, "", nil)
  1353  	c.Assert(err, jc.ErrorIsNil)
  1354  	wc.AssertNoChange()
  1355  
  1356  	// Make the Dying unit Dead; change detected.
  1357  	err = mysql0.EnsureDead()
  1358  	c.Assert(err, jc.ErrorIsNil)
  1359  	wc.AssertChange("mysql/0")
  1360  	wc.AssertNoChange()
  1361  
  1362  	// Stop watcher; check Changes chan closed.
  1363  	testing.AssertStop(c, w)
  1364  	wc.AssertClosed()
  1365  
  1366  	// Start a fresh watcher; check all units reported.
  1367  	w = s.machine.WatchUnits()
  1368  	defer testing.AssertStop(c, w)
  1369  	wc = testing.NewStringsWatcherC(c, s.State, w)
  1370  	wc.AssertChange("mysql/0", "mysql/1", "logging/0")
  1371  	wc.AssertNoChange()
  1372  
  1373  	// Remove the Dead unit; no change.
  1374  	err = mysql0.Remove()
  1375  	c.Assert(err, jc.ErrorIsNil)
  1376  	wc.AssertNoChange()
  1377  
  1378  	// Destroy the subordinate; change detected.
  1379  	err = logging0.Destroy()
  1380  	c.Assert(err, jc.ErrorIsNil)
  1381  	wc.AssertChange("logging/0")
  1382  	wc.AssertNoChange()
  1383  
  1384  	// Unassign the principal; check subordinate departure also reported.
  1385  	err = mysql1.UnassignFromMachine()
  1386  	c.Assert(err, jc.ErrorIsNil)
  1387  	wc.AssertChange("mysql/1", "logging/0")
  1388  	wc.AssertNoChange()
  1389  }
  1390  
  1391  func (s *MachineSuite) TestWatchUnitsDiesOnStateClose(c *gc.C) {
  1392  	testWatcherDiesWhenStateCloses(c, s.modelTag, func(c *gc.C, st *state.State) waiter {
  1393  		m, err := st.Machine(s.machine.Id())
  1394  		c.Assert(err, jc.ErrorIsNil)
  1395  		w := m.WatchUnits()
  1396  		<-w.Changes()
  1397  		return w
  1398  	})
  1399  }
  1400  
  1401  func (s *MachineSuite) TestConstraintsFromModel(c *gc.C) {
  1402  	econs1 := constraints.MustParse("mem=1G")
  1403  	econs2 := constraints.MustParse("mem=2G")
  1404  
  1405  	// A newly-created machine gets a copy of the model constraints.
  1406  	err := s.State.SetModelConstraints(econs1)
  1407  	c.Assert(err, jc.ErrorIsNil)
  1408  	machine1, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1409  	c.Assert(err, jc.ErrorIsNil)
  1410  	mcons1, err := machine1.Constraints()
  1411  	c.Assert(err, jc.ErrorIsNil)
  1412  	c.Assert(mcons1, gc.DeepEquals, econs1)
  1413  
  1414  	// Change model constraints and add a new machine.
  1415  	err = s.State.SetModelConstraints(econs2)
  1416  	c.Assert(err, jc.ErrorIsNil)
  1417  	machine2, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1418  	c.Assert(err, jc.ErrorIsNil)
  1419  	mcons2, err := machine2.Constraints()
  1420  	c.Assert(err, jc.ErrorIsNil)
  1421  	c.Assert(mcons2, gc.DeepEquals, econs2)
  1422  
  1423  	// Check the original machine has its original constraints.
  1424  	mcons1, err = machine1.Constraints()
  1425  	c.Assert(err, jc.ErrorIsNil)
  1426  	c.Assert(mcons1, gc.DeepEquals, econs1)
  1427  }
  1428  
  1429  func (s *MachineSuite) TestSetConstraints(c *gc.C) {
  1430  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1431  	c.Assert(err, jc.ErrorIsNil)
  1432  
  1433  	// Constraints can be set...
  1434  	cons1 := constraints.MustParse("mem=1G")
  1435  	err = machine.SetConstraints(cons1)
  1436  	c.Assert(err, jc.ErrorIsNil)
  1437  	mcons, err := machine.Constraints()
  1438  	c.Assert(err, jc.ErrorIsNil)
  1439  	c.Assert(mcons, gc.DeepEquals, cons1)
  1440  
  1441  	// ...until the machine is provisioned, at which point they stick.
  1442  	err = machine.SetProvisioned("i-mstuck", "fake_nonce", nil)
  1443  	c.Assert(err, jc.ErrorIsNil)
  1444  	cons2 := constraints.MustParse("mem=2G")
  1445  	err = machine.SetConstraints(cons2)
  1446  	c.Assert(err, gc.ErrorMatches, "cannot set constraints: machine is already provisioned")
  1447  
  1448  	// Check the failed set had no effect.
  1449  	mcons, err = machine.Constraints()
  1450  	c.Assert(err, jc.ErrorIsNil)
  1451  	c.Assert(mcons, gc.DeepEquals, cons1)
  1452  }
  1453  
  1454  func (s *MachineSuite) TestSetAmbiguousConstraints(c *gc.C) {
  1455  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1456  	c.Assert(err, jc.ErrorIsNil)
  1457  	cons := constraints.MustParse("mem=4G instance-type=foo")
  1458  	err = machine.SetConstraints(cons)
  1459  	c.Assert(err, gc.ErrorMatches, `cannot set constraints: ambiguous constraints: "instance-type" overlaps with "mem"`)
  1460  }
  1461  
  1462  func (s *MachineSuite) TestSetUnsupportedConstraintsWarning(c *gc.C) {
  1463  	defer loggo.ResetWriters()
  1464  	logger := loggo.GetLogger("test")
  1465  	logger.SetLogLevel(loggo.DEBUG)
  1466  	var tw loggo.TestWriter
  1467  	c.Assert(loggo.RegisterWriter("constraints-tester", &tw, loggo.DEBUG), gc.IsNil)
  1468  
  1469  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1470  	c.Assert(err, jc.ErrorIsNil)
  1471  	cons := constraints.MustParse("mem=4G cpu-power=10")
  1472  	err = machine.SetConstraints(cons)
  1473  	c.Assert(err, jc.ErrorIsNil)
  1474  	c.Assert(tw.Log(), jc.LogMatches, jc.SimpleMessages{{
  1475  		loggo.WARNING,
  1476  		`setting constraints on machine "2": unsupported constraints: cpu-power`},
  1477  	})
  1478  	mcons, err := machine.Constraints()
  1479  	c.Assert(err, jc.ErrorIsNil)
  1480  	c.Assert(mcons, gc.DeepEquals, cons)
  1481  }
  1482  
  1483  func (s *MachineSuite) TestConstraintsLifecycle(c *gc.C) {
  1484  	cons := constraints.MustParse("mem=1G")
  1485  	cannotSet := `cannot set constraints: not found or not alive`
  1486  	testWhenDying(c, s.machine, cannotSet, cannotSet, func() error {
  1487  		err := s.machine.SetConstraints(cons)
  1488  		mcons, err1 := s.machine.Constraints()
  1489  		c.Assert(err1, gc.IsNil)
  1490  		c.Assert(&mcons, jc.Satisfies, constraints.IsEmpty)
  1491  		return err
  1492  	})
  1493  
  1494  	err := s.machine.Remove()
  1495  	c.Assert(err, jc.ErrorIsNil)
  1496  	err = s.machine.SetConstraints(cons)
  1497  	c.Assert(err, gc.ErrorMatches, cannotSet)
  1498  	_, err = s.machine.Constraints()
  1499  	c.Assert(err, gc.ErrorMatches, `constraints not found`)
  1500  }
  1501  
  1502  func (s *MachineSuite) TestSetProviderAddresses(c *gc.C) {
  1503  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1504  	c.Assert(err, jc.ErrorIsNil)
  1505  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1506  
  1507  	addresses := network.NewAddresses("127.0.0.1", "8.8.8.8")
  1508  	err = machine.SetProviderAddresses(addresses...)
  1509  	c.Assert(err, jc.ErrorIsNil)
  1510  	err = machine.Refresh()
  1511  	c.Assert(err, jc.ErrorIsNil)
  1512  
  1513  	expectedAddresses := network.NewAddresses("8.8.8.8", "127.0.0.1")
  1514  	c.Assert(machine.Addresses(), jc.DeepEquals, expectedAddresses)
  1515  }
  1516  
  1517  func (s *MachineSuite) TestSetProviderAddressesWithContainers(c *gc.C) {
  1518  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1519  	c.Assert(err, jc.ErrorIsNil)
  1520  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1521  
  1522  	// Create subnet and pick two addresses.
  1523  	subnetInfo := state.SubnetInfo{
  1524  		CIDR:              "192.168.1.0/24",
  1525  		AllocatableIPLow:  "192.168.1.0",
  1526  		AllocatableIPHigh: "192.168.1.10",
  1527  	}
  1528  	subnet, err := s.State.AddSubnet(subnetInfo)
  1529  	c.Assert(err, jc.ErrorIsNil)
  1530  
  1531  	ipAddr1, err := subnet.PickNewAddress()
  1532  	c.Assert(err, jc.ErrorIsNil)
  1533  	err = ipAddr1.SetState(state.AddressStateAllocated)
  1534  	c.Assert(err, jc.ErrorIsNil)
  1535  	ipAddr2, err := subnet.PickNewAddress()
  1536  	c.Assert(err, jc.ErrorIsNil)
  1537  	err = ipAddr2.SetState(state.AddressStateAllocated)
  1538  	c.Assert(err, jc.ErrorIsNil)
  1539  
  1540  	// When setting all addresses the subnet addresses have to be
  1541  	// filtered out.
  1542  	addresses := network.NewAddresses(
  1543  		"127.0.0.1",
  1544  		"8.8.8.8",
  1545  		ipAddr1.Value(),
  1546  		ipAddr2.Value(),
  1547  	)
  1548  	err = machine.SetProviderAddresses(addresses...)
  1549  	c.Assert(err, jc.ErrorIsNil)
  1550  	err = machine.Refresh()
  1551  	c.Assert(err, jc.ErrorIsNil)
  1552  
  1553  	expectedAddresses := network.NewAddresses("8.8.8.8", "127.0.0.1")
  1554  	c.Assert(machine.Addresses(), jc.DeepEquals, expectedAddresses)
  1555  }
  1556  
  1557  func (s *MachineSuite) TestSetProviderAddressesOnContainer(c *gc.C) {
  1558  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1559  	c.Assert(err, jc.ErrorIsNil)
  1560  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1561  
  1562  	// Create subnet and pick two addresses.
  1563  	subnetInfo := state.SubnetInfo{
  1564  		CIDR:              "192.168.1.0/24",
  1565  		AllocatableIPLow:  "192.168.1.0",
  1566  		AllocatableIPHigh: "192.168.1.10",
  1567  	}
  1568  	subnet, err := s.State.AddSubnet(subnetInfo)
  1569  	c.Assert(err, jc.ErrorIsNil)
  1570  
  1571  	ipAddr, err := subnet.PickNewAddress()
  1572  	c.Assert(err, jc.ErrorIsNil)
  1573  	err = ipAddr.SetState(state.AddressStateAllocated)
  1574  	c.Assert(err, jc.ErrorIsNil)
  1575  
  1576  	// Create an LXC container inside the machine.
  1577  	template := state.MachineTemplate{
  1578  		Series: "quantal",
  1579  		Jobs:   []state.MachineJob{state.JobHostUnits},
  1580  	}
  1581  	container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXC)
  1582  	c.Assert(err, jc.ErrorIsNil)
  1583  
  1584  	// When setting all addresses the subnet address has to accepted.
  1585  	addresses := network.NewAddresses("127.0.0.1", ipAddr.Value())
  1586  	err = container.SetProviderAddresses(addresses...)
  1587  	c.Assert(err, jc.ErrorIsNil)
  1588  	err = container.Refresh()
  1589  	c.Assert(err, jc.ErrorIsNil)
  1590  
  1591  	expectedAddresses := network.NewAddresses(ipAddr.Value(), "127.0.0.1")
  1592  	c.Assert(container.Addresses(), jc.DeepEquals, expectedAddresses)
  1593  }
  1594  
  1595  func (s *MachineSuite) TestSetMachineAddresses(c *gc.C) {
  1596  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1597  	c.Assert(err, jc.ErrorIsNil)
  1598  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1599  
  1600  	addresses := network.NewAddresses("127.0.0.1", "8.8.8.8")
  1601  	err = machine.SetMachineAddresses(addresses...)
  1602  	c.Assert(err, jc.ErrorIsNil)
  1603  	err = machine.Refresh()
  1604  	c.Assert(err, jc.ErrorIsNil)
  1605  
  1606  	expectedAddresses := network.NewAddresses("8.8.8.8", "127.0.0.1")
  1607  	c.Assert(machine.MachineAddresses(), jc.DeepEquals, expectedAddresses)
  1608  }
  1609  
  1610  func (s *MachineSuite) TestSetEmptyMachineAddresses(c *gc.C) {
  1611  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1612  	c.Assert(err, jc.ErrorIsNil)
  1613  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1614  
  1615  	// Add some machine addresses initially to make sure they're removed.
  1616  	addresses := network.NewAddresses("127.0.0.1", "8.8.8.8")
  1617  	err = machine.SetMachineAddresses(addresses...)
  1618  	c.Assert(err, jc.ErrorIsNil)
  1619  	err = machine.Refresh()
  1620  	c.Assert(err, jc.ErrorIsNil)
  1621  	c.Assert(machine.MachineAddresses(), gc.HasLen, 2)
  1622  
  1623  	// Make call with empty address list.
  1624  	err = machine.SetMachineAddresses()
  1625  	c.Assert(err, jc.ErrorIsNil)
  1626  	err = machine.Refresh()
  1627  	c.Assert(err, jc.ErrorIsNil)
  1628  
  1629  	c.Assert(machine.MachineAddresses(), gc.HasLen, 0)
  1630  }
  1631  
  1632  func (s *MachineSuite) TestMergedAddresses(c *gc.C) {
  1633  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1634  	c.Assert(err, jc.ErrorIsNil)
  1635  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1636  
  1637  	providerAddresses := network.NewAddresses(
  1638  		"127.0.0.2",
  1639  		"8.8.8.8",
  1640  		"fc00::1",
  1641  		"::1",
  1642  		"",
  1643  		"2001:db8::1",
  1644  		"127.0.0.2",
  1645  		"example.org",
  1646  	)
  1647  	err = machine.SetProviderAddresses(providerAddresses...)
  1648  	c.Assert(err, jc.ErrorIsNil)
  1649  
  1650  	machineAddresses := network.NewAddresses(
  1651  		"127.0.0.1",
  1652  		"localhost",
  1653  		"2001:db8::1",
  1654  		"192.168.0.1",
  1655  		"fe80::1",
  1656  		"::1",
  1657  		"fd00::1",
  1658  	)
  1659  	err = machine.SetMachineAddresses(machineAddresses...)
  1660  	c.Assert(err, jc.ErrorIsNil)
  1661  	err = machine.Refresh()
  1662  	c.Assert(err, jc.ErrorIsNil)
  1663  
  1664  	// Before setting the addresses coming from either the provider or
  1665  	// the machine itself, they are sorted to prefer public IPs on
  1666  	// top, then hostnames, cloud-local, machine-local, link-local.
  1667  	// Duplicates are removed, then when calling Addresses() both
  1668  	// sources are merged while preservig the provider addresses
  1669  	// order.
  1670  	c.Assert(machine.Addresses(), jc.DeepEquals, network.NewAddresses(
  1671  		"8.8.8.8",
  1672  		"2001:db8::1",
  1673  		"example.org",
  1674  		"fc00::1",
  1675  		"127.0.0.2",
  1676  		"::1",
  1677  		"localhost",
  1678  		"192.168.0.1",
  1679  		"fd00::1",
  1680  		"127.0.0.1",
  1681  		"fe80::1",
  1682  	))
  1683  
  1684  	// Now simulate prefer-ipv6: true
  1685  	c.Assert(
  1686  		s.State.UpdateModelConfig(
  1687  			map[string]interface{}{"prefer-ipv6": true},
  1688  			nil, nil,
  1689  		),
  1690  		gc.IsNil,
  1691  	)
  1692  
  1693  	err = machine.SetProviderAddresses(providerAddresses...)
  1694  	c.Assert(err, jc.ErrorIsNil)
  1695  	err = machine.SetMachineAddresses(machineAddresses...)
  1696  	c.Assert(err, jc.ErrorIsNil)
  1697  	err = machine.Refresh()
  1698  	c.Assert(err, jc.ErrorIsNil)
  1699  	c.Assert(machine.Addresses(), jc.DeepEquals, network.NewAddresses(
  1700  		"2001:db8::1",
  1701  		"8.8.8.8",
  1702  		"example.org",
  1703  		"fc00::1",
  1704  		"::1",
  1705  		"127.0.0.2",
  1706  		"localhost",
  1707  		"fd00::1",
  1708  		"192.168.0.1",
  1709  		"127.0.0.1",
  1710  		"fe80::1",
  1711  	))
  1712  }
  1713  
  1714  func (s *MachineSuite) TestSetProviderAddressesConcurrentChangeDifferent(c *gc.C) {
  1715  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1716  	c.Assert(err, jc.ErrorIsNil)
  1717  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1718  
  1719  	addr0 := network.NewAddress("127.0.0.1")
  1720  	addr1 := network.NewAddress("8.8.8.8")
  1721  
  1722  	defer state.SetBeforeHooks(c, s.State, func() {
  1723  		machine, err := s.State.Machine(machine.Id())
  1724  		c.Assert(err, jc.ErrorIsNil)
  1725  		err = machine.SetProviderAddresses(addr1, addr0)
  1726  		c.Assert(err, jc.ErrorIsNil)
  1727  	}).Check()
  1728  
  1729  	err = machine.SetProviderAddresses(addr0, addr1)
  1730  	c.Assert(err, jc.ErrorIsNil)
  1731  	c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0, addr1})
  1732  }
  1733  
  1734  func (s *MachineSuite) TestSetProviderAddressesConcurrentChangeEqual(c *gc.C) {
  1735  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1736  	c.Assert(err, jc.ErrorIsNil)
  1737  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1738  	machineDocID := state.DocID(s.State, machine.Id())
  1739  	revno0, err := state.TxnRevno(s.State, "machines", machineDocID)
  1740  	c.Assert(err, jc.ErrorIsNil)
  1741  
  1742  	addr0 := network.NewAddress("127.0.0.1")
  1743  	addr1 := network.NewAddress("8.8.8.8")
  1744  
  1745  	var revno1 int64
  1746  	defer state.SetBeforeHooks(c, s.State, func() {
  1747  		machine, err := s.State.Machine(machine.Id())
  1748  		c.Assert(err, jc.ErrorIsNil)
  1749  		err = machine.SetProviderAddresses(addr0, addr1)
  1750  		c.Assert(err, jc.ErrorIsNil)
  1751  		revno1, err = state.TxnRevno(s.State, "machines", machineDocID)
  1752  		c.Assert(err, jc.ErrorIsNil)
  1753  		c.Assert(revno1, jc.GreaterThan, revno0)
  1754  	}).Check()
  1755  
  1756  	err = machine.SetProviderAddresses(addr0, addr1)
  1757  	c.Assert(err, jc.ErrorIsNil)
  1758  
  1759  	// Doc will be updated; concurrent changes are explicitly ignored.
  1760  	revno2, err := state.TxnRevno(s.State, "machines", machineDocID)
  1761  	c.Assert(err, jc.ErrorIsNil)
  1762  	c.Assert(revno2, jc.GreaterThan, revno1)
  1763  	c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0, addr1})
  1764  }
  1765  
  1766  func (s *MachineSuite) TestSetProviderAddressesInvalidateMemory(c *gc.C) {
  1767  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1768  	c.Assert(err, jc.ErrorIsNil)
  1769  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1770  	machineDocID := state.DocID(s.State, machine.Id())
  1771  
  1772  	addr0 := network.NewAddress("127.0.0.1")
  1773  	addr1 := network.NewAddress("8.8.8.8")
  1774  
  1775  	// Set addresses to [addr0] initially. We'll get a separate Machine
  1776  	// object to update addresses, to ensure that the in-memory cache of
  1777  	// addresses does not prevent the initial Machine from updating
  1778  	// addresses back to the original value.
  1779  	err = machine.SetProviderAddresses(addr0)
  1780  	c.Assert(err, jc.ErrorIsNil)
  1781  	revno0, err := state.TxnRevno(s.State, "machines", machineDocID)
  1782  	c.Assert(err, jc.ErrorIsNil)
  1783  
  1784  	machine2, err := s.State.Machine(machine.Id())
  1785  	c.Assert(err, jc.ErrorIsNil)
  1786  	err = machine2.SetProviderAddresses(addr1)
  1787  	c.Assert(err, jc.ErrorIsNil)
  1788  	revno1, err := state.TxnRevno(s.State, "machines", machineDocID)
  1789  	c.Assert(err, jc.ErrorIsNil)
  1790  	c.Assert(revno1, jc.GreaterThan, revno0)
  1791  	c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0})
  1792  	c.Assert(machine2.Addresses(), jc.SameContents, []network.Address{addr1})
  1793  
  1794  	err = machine.SetProviderAddresses(addr0)
  1795  	c.Assert(err, jc.ErrorIsNil)
  1796  	revno2, err := state.TxnRevno(s.State, "machines", machineDocID)
  1797  	c.Assert(err, jc.ErrorIsNil)
  1798  	c.Assert(revno2, jc.GreaterThan, revno1)
  1799  	c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0})
  1800  }
  1801  
  1802  func (s *MachineSuite) TestPublicAddressSetOnNewMachine(c *gc.C) {
  1803  	m, err := s.State.AddOneMachine(state.MachineTemplate{
  1804  		Series:    "quantal",
  1805  		Jobs:      []state.MachineJob{state.JobHostUnits},
  1806  		Addresses: network.NewAddresses("10.0.0.1", "8.8.8.8"),
  1807  	})
  1808  	c.Assert(err, jc.ErrorIsNil)
  1809  	addr, err := m.PublicAddress()
  1810  	c.Assert(err, jc.ErrorIsNil)
  1811  	c.Assert(addr, jc.DeepEquals, network.NewAddress("8.8.8.8"))
  1812  }
  1813  
  1814  func (s *MachineSuite) TestPrivateAddressSetOnNewMachine(c *gc.C) {
  1815  	m, err := s.State.AddOneMachine(state.MachineTemplate{
  1816  		Series:    "quantal",
  1817  		Jobs:      []state.MachineJob{state.JobHostUnits},
  1818  		Addresses: network.NewAddresses("10.0.0.1", "8.8.8.8"),
  1819  	})
  1820  	c.Assert(err, jc.ErrorIsNil)
  1821  	addr, err := m.PrivateAddress()
  1822  	c.Assert(err, jc.ErrorIsNil)
  1823  	c.Assert(addr, jc.DeepEquals, network.NewAddress("10.0.0.1"))
  1824  }
  1825  
  1826  func (s *MachineSuite) TestPublicAddressEmptyAddresses(c *gc.C) {
  1827  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1828  	c.Assert(err, jc.ErrorIsNil)
  1829  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1830  
  1831  	addr, err := machine.PublicAddress()
  1832  	c.Assert(err, jc.Satisfies, network.IsNoAddress)
  1833  	c.Assert(addr.Value, gc.Equals, "")
  1834  }
  1835  
  1836  func (s *MachineSuite) TestPrivateAddressEmptyAddresses(c *gc.C) {
  1837  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1838  	c.Assert(err, jc.ErrorIsNil)
  1839  	c.Assert(machine.Addresses(), gc.HasLen, 0)
  1840  
  1841  	addr, err := machine.PrivateAddress()
  1842  	c.Assert(err, jc.Satisfies, network.IsNoAddress)
  1843  	c.Assert(addr.Value, gc.Equals, "")
  1844  }
  1845  
  1846  func (s *MachineSuite) TestPublicAddress(c *gc.C) {
  1847  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1848  	c.Assert(err, jc.ErrorIsNil)
  1849  
  1850  	err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"))
  1851  	c.Assert(err, jc.ErrorIsNil)
  1852  
  1853  	addr, err := machine.PublicAddress()
  1854  	c.Assert(err, jc.ErrorIsNil)
  1855  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  1856  }
  1857  
  1858  func (s *MachineSuite) TestPrivateAddress(c *gc.C) {
  1859  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1860  	c.Assert(err, jc.ErrorIsNil)
  1861  
  1862  	err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1"))
  1863  	c.Assert(err, jc.ErrorIsNil)
  1864  
  1865  	addr, err := machine.PrivateAddress()
  1866  	c.Assert(err, jc.ErrorIsNil)
  1867  	c.Assert(addr.Value, gc.Equals, "10.0.0.1")
  1868  }
  1869  
  1870  func (s *MachineSuite) TestPublicAddressBetterMatch(c *gc.C) {
  1871  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1872  	c.Assert(err, jc.ErrorIsNil)
  1873  
  1874  	err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1"))
  1875  	c.Assert(err, jc.ErrorIsNil)
  1876  
  1877  	addr, err := machine.PublicAddress()
  1878  	c.Assert(err, jc.ErrorIsNil)
  1879  	c.Assert(addr.Value, gc.Equals, "10.0.0.1")
  1880  
  1881  	err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"))
  1882  	c.Assert(err, jc.ErrorIsNil)
  1883  
  1884  	addr, err = machine.PublicAddress()
  1885  	c.Assert(err, jc.ErrorIsNil)
  1886  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  1887  }
  1888  
  1889  func (s *MachineSuite) TestPrivateAddressBetterMatch(c *gc.C) {
  1890  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1891  	c.Assert(err, jc.ErrorIsNil)
  1892  
  1893  	err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"))
  1894  	c.Assert(err, jc.ErrorIsNil)
  1895  
  1896  	addr, err := machine.PrivateAddress()
  1897  	c.Assert(err, jc.ErrorIsNil)
  1898  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  1899  
  1900  	err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.1"))
  1901  	c.Assert(err, jc.ErrorIsNil)
  1902  
  1903  	addr, err = machine.PrivateAddress()
  1904  	c.Assert(err, jc.ErrorIsNil)
  1905  	c.Assert(addr.Value, gc.Equals, "10.0.0.1")
  1906  }
  1907  
  1908  func (s *MachineSuite) TestPublicAddressChanges(c *gc.C) {
  1909  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1910  	c.Assert(err, jc.ErrorIsNil)
  1911  
  1912  	err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"))
  1913  	c.Assert(err, jc.ErrorIsNil)
  1914  
  1915  	addr, err := machine.PublicAddress()
  1916  	c.Assert(err, jc.ErrorIsNil)
  1917  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  1918  
  1919  	err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4"))
  1920  	c.Assert(err, jc.ErrorIsNil)
  1921  
  1922  	addr, err = machine.PublicAddress()
  1923  	c.Assert(err, jc.ErrorIsNil)
  1924  	c.Assert(addr.Value, gc.Equals, "8.8.4.4")
  1925  }
  1926  
  1927  func (s *MachineSuite) TestPrivateAddressChanges(c *gc.C) {
  1928  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1929  	c.Assert(err, jc.ErrorIsNil)
  1930  
  1931  	err = machine.SetMachineAddresses(network.NewAddress("10.0.0.2"))
  1932  	c.Assert(err, jc.ErrorIsNil)
  1933  
  1934  	addr, err := machine.PrivateAddress()
  1935  	c.Assert(err, jc.ErrorIsNil)
  1936  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  1937  
  1938  	err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1"))
  1939  	c.Assert(err, jc.ErrorIsNil)
  1940  
  1941  	addr, err = machine.PrivateAddress()
  1942  	c.Assert(err, jc.ErrorIsNil)
  1943  	c.Assert(addr.Value, gc.Equals, "10.0.0.1")
  1944  }
  1945  
  1946  func (s *MachineSuite) TestAddressesDeadMachine(c *gc.C) {
  1947  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1948  	c.Assert(err, jc.ErrorIsNil)
  1949  
  1950  	err = machine.SetProviderAddresses(network.NewAddress("10.0.0.2"), network.NewAddress("8.8.4.4"))
  1951  	c.Assert(err, jc.ErrorIsNil)
  1952  
  1953  	addr, err := machine.PrivateAddress()
  1954  	c.Assert(err, jc.ErrorIsNil)
  1955  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  1956  
  1957  	addr, err = machine.PublicAddress()
  1958  	c.Assert(err, jc.ErrorIsNil)
  1959  	c.Assert(addr.Value, gc.Equals, "8.8.4.4")
  1960  
  1961  	err = machine.EnsureDead()
  1962  	c.Assert(err, jc.ErrorIsNil)
  1963  
  1964  	// A dead machine should still report the last known addresses.
  1965  	addr, err = machine.PrivateAddress()
  1966  	c.Assert(err, jc.ErrorIsNil)
  1967  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  1968  
  1969  	addr, err = machine.PublicAddress()
  1970  	c.Assert(err, jc.ErrorIsNil)
  1971  	c.Assert(addr.Value, gc.Equals, "8.8.4.4")
  1972  }
  1973  
  1974  func (s *MachineSuite) TestStablePrivateAddress(c *gc.C) {
  1975  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1976  	c.Assert(err, jc.ErrorIsNil)
  1977  
  1978  	err = machine.SetMachineAddresses(network.NewAddress("10.0.0.2"))
  1979  	c.Assert(err, jc.ErrorIsNil)
  1980  
  1981  	addr, err := machine.PrivateAddress()
  1982  	c.Assert(err, jc.ErrorIsNil)
  1983  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  1984  
  1985  	// Now add an address that would previously have sorted before the
  1986  	// default.
  1987  	err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1"), network.NewAddress("10.0.0.2"))
  1988  	c.Assert(err, jc.ErrorIsNil)
  1989  
  1990  	// Assert the address is unchanged.
  1991  	addr, err = machine.PrivateAddress()
  1992  	c.Assert(err, jc.ErrorIsNil)
  1993  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  1994  }
  1995  
  1996  func (s *MachineSuite) TestStablePublicAddress(c *gc.C) {
  1997  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  1998  	c.Assert(err, jc.ErrorIsNil)
  1999  
  2000  	err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"))
  2001  	c.Assert(err, jc.ErrorIsNil)
  2002  
  2003  	addr, err := machine.PublicAddress()
  2004  	c.Assert(err, jc.ErrorIsNil)
  2005  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  2006  
  2007  	// Now add an address that would previously have sorted before the
  2008  	// default.
  2009  	err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4"), network.NewAddress("8.8.8.8"))
  2010  	c.Assert(err, jc.ErrorIsNil)
  2011  
  2012  	// Assert the address is unchanged.
  2013  	addr, err = machine.PublicAddress()
  2014  	c.Assert(err, jc.ErrorIsNil)
  2015  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  2016  }
  2017  
  2018  func (s *MachineSuite) TestAddressesRaceMachineFirst(c *gc.C) {
  2019  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  2020  	c.Assert(err, jc.ErrorIsNil)
  2021  
  2022  	changeAddresses := jujutxn.TestHook{
  2023  		Before: func() {
  2024  			err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"))
  2025  			c.Assert(err, jc.ErrorIsNil)
  2026  			address, err := machine.PublicAddress()
  2027  			c.Assert(err, jc.ErrorIsNil)
  2028  			c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8"))
  2029  			address, err = machine.PrivateAddress()
  2030  			c.Assert(err, jc.ErrorIsNil)
  2031  			c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8"))
  2032  		},
  2033  	}
  2034  	defer state.SetTestHooks(c, s.State, changeAddresses).Check()
  2035  
  2036  	err = machine.SetMachineAddresses(network.NewAddress("8.8.4.4"))
  2037  	c.Assert(err, jc.ErrorIsNil)
  2038  
  2039  	machine, err = s.State.Machine(machine.Id())
  2040  	c.Assert(err, jc.ErrorIsNil)
  2041  	address, err := machine.PublicAddress()
  2042  	c.Assert(err, jc.ErrorIsNil)
  2043  	c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8"))
  2044  	address, err = machine.PrivateAddress()
  2045  	c.Assert(err, jc.ErrorIsNil)
  2046  	c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8"))
  2047  }
  2048  
  2049  func (s *MachineSuite) TestAddressesRaceProviderFirst(c *gc.C) {
  2050  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  2051  	c.Assert(err, jc.ErrorIsNil)
  2052  
  2053  	changeAddresses := jujutxn.TestHook{
  2054  		Before: func() {
  2055  			err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1"))
  2056  			c.Assert(err, jc.ErrorIsNil)
  2057  			address, err := machine.PublicAddress()
  2058  			c.Assert(err, jc.ErrorIsNil)
  2059  			c.Assert(address, jc.DeepEquals, network.NewAddress("10.0.0.1"))
  2060  			address, err = machine.PrivateAddress()
  2061  			c.Assert(err, jc.ErrorIsNil)
  2062  			c.Assert(address, jc.DeepEquals, network.NewAddress("10.0.0.1"))
  2063  		},
  2064  	}
  2065  	defer state.SetTestHooks(c, s.State, changeAddresses).Check()
  2066  
  2067  	err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4"))
  2068  	c.Assert(err, jc.ErrorIsNil)
  2069  
  2070  	machine, err = s.State.Machine(machine.Id())
  2071  	c.Assert(err, jc.ErrorIsNil)
  2072  	address, err := machine.PublicAddress()
  2073  	c.Assert(err, jc.ErrorIsNil)
  2074  	c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.4.4"))
  2075  	address, err = machine.PrivateAddress()
  2076  	c.Assert(err, jc.ErrorIsNil)
  2077  	c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.4.4"))
  2078  }
  2079  
  2080  func (s *MachineSuite) TestPrivateAddressPrefersProvider(c *gc.C) {
  2081  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  2082  	c.Assert(err, jc.ErrorIsNil)
  2083  
  2084  	err = machine.SetMachineAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.2"))
  2085  	c.Assert(err, jc.ErrorIsNil)
  2086  
  2087  	addr, err := machine.PublicAddress()
  2088  	c.Assert(err, jc.ErrorIsNil)
  2089  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  2090  	addr, err = machine.PrivateAddress()
  2091  	c.Assert(err, jc.ErrorIsNil)
  2092  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  2093  
  2094  	err = machine.SetProviderAddresses(network.NewAddress("10.0.0.1"))
  2095  	c.Assert(err, jc.ErrorIsNil)
  2096  
  2097  	addr, err = machine.PublicAddress()
  2098  	c.Assert(err, jc.ErrorIsNil)
  2099  	c.Assert(addr.Value, gc.Equals, "10.0.0.1")
  2100  	addr, err = machine.PrivateAddress()
  2101  	c.Assert(err, jc.ErrorIsNil)
  2102  	c.Assert(addr.Value, gc.Equals, "10.0.0.1")
  2103  }
  2104  
  2105  func (s *MachineSuite) TestPublicAddressPrefersProvider(c *gc.C) {
  2106  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  2107  	c.Assert(err, jc.ErrorIsNil)
  2108  
  2109  	err = machine.SetMachineAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.2"))
  2110  	c.Assert(err, jc.ErrorIsNil)
  2111  
  2112  	addr, err := machine.PublicAddress()
  2113  	c.Assert(err, jc.ErrorIsNil)
  2114  	c.Assert(addr.Value, gc.Equals, "8.8.8.8")
  2115  	addr, err = machine.PrivateAddress()
  2116  	c.Assert(err, jc.ErrorIsNil)
  2117  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  2118  
  2119  	err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4"))
  2120  	c.Assert(err, jc.ErrorIsNil)
  2121  
  2122  	addr, err = machine.PublicAddress()
  2123  	c.Assert(err, jc.ErrorIsNil)
  2124  	c.Assert(addr.Value, gc.Equals, "8.8.4.4")
  2125  	addr, err = machine.PrivateAddress()
  2126  	c.Assert(err, jc.ErrorIsNil)
  2127  	c.Assert(addr.Value, gc.Equals, "8.8.4.4")
  2128  }
  2129  
  2130  func (s *MachineSuite) TestAddressesPrefersProviderBoth(c *gc.C) {
  2131  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  2132  	c.Assert(err, jc.ErrorIsNil)
  2133  
  2134  	err = machine.SetMachineAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.1"))
  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  	addr, err = machine.PrivateAddress()
  2141  	c.Assert(err, jc.ErrorIsNil)
  2142  	c.Assert(addr.Value, gc.Equals, "10.0.0.1")
  2143  
  2144  	err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4"), network.NewAddress("10.0.0.2"))
  2145  	c.Assert(err, jc.ErrorIsNil)
  2146  
  2147  	addr, err = machine.PublicAddress()
  2148  	c.Assert(err, jc.ErrorIsNil)
  2149  	c.Assert(addr.Value, gc.Equals, "8.8.4.4")
  2150  	addr, err = machine.PrivateAddress()
  2151  	c.Assert(err, jc.ErrorIsNil)
  2152  	c.Assert(addr.Value, gc.Equals, "10.0.0.2")
  2153  }
  2154  
  2155  func (s *MachineSuite) addMachineWithSupportedContainer(c *gc.C, container instance.ContainerType) *state.Machine {
  2156  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  2157  	c.Assert(err, jc.ErrorIsNil)
  2158  	containers := []instance.ContainerType{container}
  2159  	err = machine.SetSupportedContainers(containers)
  2160  	c.Assert(err, jc.ErrorIsNil)
  2161  	assertSupportedContainers(c, machine, containers)
  2162  	return machine
  2163  }
  2164  
  2165  // assertSupportedContainers checks the document in memory has the specified
  2166  // containers and then reloads the document from the database to assert saved
  2167  // values match also.
  2168  func assertSupportedContainers(c *gc.C, machine *state.Machine, containers []instance.ContainerType) {
  2169  	supportedContainers, known := machine.SupportedContainers()
  2170  	c.Assert(known, jc.IsTrue)
  2171  	c.Assert(supportedContainers, gc.DeepEquals, containers)
  2172  	// Reload so we can check the saved values.
  2173  	err := machine.Refresh()
  2174  	c.Assert(err, jc.ErrorIsNil)
  2175  	supportedContainers, known = machine.SupportedContainers()
  2176  	c.Assert(known, jc.IsTrue)
  2177  	c.Assert(supportedContainers, gc.DeepEquals, containers)
  2178  }
  2179  
  2180  func assertSupportedContainersUnknown(c *gc.C, machine *state.Machine) {
  2181  	containers, known := machine.SupportedContainers()
  2182  	c.Assert(known, jc.IsFalse)
  2183  	c.Assert(containers, gc.HasLen, 0)
  2184  }
  2185  
  2186  func (s *MachineSuite) TestSupportedContainersInitiallyUnknown(c *gc.C) {
  2187  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  2188  	c.Assert(err, jc.ErrorIsNil)
  2189  	assertSupportedContainersUnknown(c, machine)
  2190  }
  2191  
  2192  func (s *MachineSuite) TestSupportsNoContainers(c *gc.C) {
  2193  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  2194  	c.Assert(err, jc.ErrorIsNil)
  2195  
  2196  	err = machine.SupportsNoContainers()
  2197  	c.Assert(err, jc.ErrorIsNil)
  2198  	assertSupportedContainers(c, machine, []instance.ContainerType{})
  2199  }
  2200  
  2201  func (s *MachineSuite) TestSetSupportedContainerTypeNoneIsError(c *gc.C) {
  2202  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  2203  	c.Assert(err, jc.ErrorIsNil)
  2204  
  2205  	err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXC, instance.NONE})
  2206  	c.Assert(err, gc.ErrorMatches, `"none" is not a valid container type`)
  2207  	assertSupportedContainersUnknown(c, machine)
  2208  	err = machine.Refresh()
  2209  	c.Assert(err, jc.ErrorIsNil)
  2210  	assertSupportedContainersUnknown(c, machine)
  2211  }
  2212  
  2213  func (s *MachineSuite) TestSupportsNoContainersOverwritesExisting(c *gc.C) {
  2214  	machine := s.addMachineWithSupportedContainer(c, instance.LXC)
  2215  
  2216  	err := machine.SupportsNoContainers()
  2217  	c.Assert(err, jc.ErrorIsNil)
  2218  	assertSupportedContainers(c, machine, []instance.ContainerType{})
  2219  }
  2220  
  2221  func (s *MachineSuite) TestSetSupportedContainersSingle(c *gc.C) {
  2222  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  2223  	c.Assert(err, jc.ErrorIsNil)
  2224  
  2225  	err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXC})
  2226  	c.Assert(err, jc.ErrorIsNil)
  2227  	assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXC})
  2228  }
  2229  
  2230  func (s *MachineSuite) TestSetSupportedContainersSame(c *gc.C) {
  2231  	machine := s.addMachineWithSupportedContainer(c, instance.LXC)
  2232  
  2233  	err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXC})
  2234  	c.Assert(err, jc.ErrorIsNil)
  2235  	assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXC})
  2236  }
  2237  
  2238  func (s *MachineSuite) TestSetSupportedContainersNew(c *gc.C) {
  2239  	machine := s.addMachineWithSupportedContainer(c, instance.LXC)
  2240  
  2241  	err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXC, instance.KVM})
  2242  	c.Assert(err, jc.ErrorIsNil)
  2243  	assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXC, instance.KVM})
  2244  }
  2245  
  2246  func (s *MachineSuite) TestSetSupportedContainersMultipeNew(c *gc.C) {
  2247  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  2248  	c.Assert(err, jc.ErrorIsNil)
  2249  
  2250  	err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXC, instance.KVM})
  2251  	c.Assert(err, jc.ErrorIsNil)
  2252  	assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXC, instance.KVM})
  2253  }
  2254  
  2255  func (s *MachineSuite) TestSetSupportedContainersMultipleExisting(c *gc.C) {
  2256  	machine := s.addMachineWithSupportedContainer(c, instance.LXC)
  2257  
  2258  	err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXC, instance.KVM})
  2259  	c.Assert(err, jc.ErrorIsNil)
  2260  	assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXC, instance.KVM})
  2261  }
  2262  
  2263  func (s *MachineSuite) TestSetSupportedContainersSetsUnknownToError(c *gc.C) {
  2264  	// Create a machine and add lxc and kvm containers prior to calling SetSupportedContainers
  2265  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  2266  	template := state.MachineTemplate{
  2267  		Series: "quantal",
  2268  		Jobs:   []state.MachineJob{state.JobHostUnits},
  2269  	}
  2270  	container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXC)
  2271  	c.Assert(err, jc.ErrorIsNil)
  2272  	supportedContainer, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.KVM)
  2273  	c.Assert(err, jc.ErrorIsNil)
  2274  	err = machine.SetSupportedContainers([]instance.ContainerType{instance.KVM})
  2275  	c.Assert(err, jc.ErrorIsNil)
  2276  
  2277  	// A supported (kvm) container will have a pending status.
  2278  	err = supportedContainer.Refresh()
  2279  	c.Assert(err, jc.ErrorIsNil)
  2280  	statusInfo, err := supportedContainer.Status()
  2281  	c.Assert(err, jc.ErrorIsNil)
  2282  	c.Assert(statusInfo.Status, gc.Equals, status.StatusPending)
  2283  
  2284  	// An unsupported (lxc) container will have an error status.
  2285  	err = container.Refresh()
  2286  	c.Assert(err, jc.ErrorIsNil)
  2287  	statusInfo, err = container.Status()
  2288  	c.Assert(err, jc.ErrorIsNil)
  2289  	c.Assert(statusInfo.Status, gc.Equals, status.StatusError)
  2290  	c.Assert(statusInfo.Message, gc.Equals, "unsupported container")
  2291  	c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{"type": "lxc"})
  2292  }
  2293  
  2294  func (s *MachineSuite) TestSupportsNoContainersSetsAllToError(c *gc.C) {
  2295  	// Create a machine and add all container types prior to calling SupportsNoContainers
  2296  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
  2297  	var containers []*state.Machine
  2298  	template := state.MachineTemplate{
  2299  		Series: "quantal",
  2300  		Jobs:   []state.MachineJob{state.JobHostUnits},
  2301  	}
  2302  	for _, containerType := range instance.ContainerTypes {
  2303  		container, err := s.State.AddMachineInsideMachine(template, machine.Id(), containerType)
  2304  		c.Assert(err, jc.ErrorIsNil)
  2305  		containers = append(containers, container)
  2306  	}
  2307  
  2308  	err = machine.SupportsNoContainers()
  2309  	c.Assert(err, jc.ErrorIsNil)
  2310  
  2311  	// All containers should be in error state.
  2312  	for _, container := range containers {
  2313  		err = container.Refresh()
  2314  		c.Assert(err, jc.ErrorIsNil)
  2315  		statusInfo, err := container.Status()
  2316  		c.Assert(err, jc.ErrorIsNil)
  2317  		c.Assert(statusInfo.Status, gc.Equals, status.StatusError)
  2318  		c.Assert(statusInfo.Message, gc.Equals, "unsupported container")
  2319  		containerType := state.ContainerTypeFromId(container.Id())
  2320  		c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{"type": string(containerType)})
  2321  	}
  2322  }
  2323  
  2324  func (s *MachineSuite) TestMachineAgentTools(c *gc.C) {
  2325  	m, err := s.State.AddMachine("quantal", state.JobHostUnits)
  2326  	c.Assert(err, jc.ErrorIsNil)
  2327  	testAgentTools(c, m, "machine "+m.Id())
  2328  }
  2329  
  2330  func (s *MachineSuite) TestMachineValidActions(c *gc.C) {
  2331  	m, err := s.State.AddMachine("trusty", state.JobHostUnits)
  2332  	c.Assert(err, jc.ErrorIsNil)
  2333  
  2334  	var tests = []struct {
  2335  		actionName      string
  2336  		errString       string
  2337  		givenPayload    map[string]interface{}
  2338  		expectedPayload map[string]interface{}
  2339  	}{
  2340  		{
  2341  			actionName: "juju-run",
  2342  			errString:  `validation failed: (root) : "command" property is missing and required, given {}; (root) : "timeout" property is missing and required, given {}`,
  2343  		},
  2344  		{
  2345  			actionName:      "juju-run",
  2346  			givenPayload:    map[string]interface{}{"command": "allyourbasearebelongtous", "timeout": 5.0},
  2347  			expectedPayload: map[string]interface{}{"command": "allyourbasearebelongtous", "timeout": 5.0},
  2348  		},
  2349  		{
  2350  			actionName: "baiku",
  2351  			errString:  `cannot add action "baiku" to a machine; only predefined actions allowed`,
  2352  		},
  2353  	}
  2354  
  2355  	for i, t := range tests {
  2356  		c.Logf("running test %d", i)
  2357  		action, err := m.AddAction(t.actionName, t.givenPayload)
  2358  		if t.errString != "" {
  2359  			c.Assert(err.Error(), gc.Equals, t.errString)
  2360  			continue
  2361  		} else {
  2362  			c.Assert(err, jc.ErrorIsNil)
  2363  			c.Assert(action.Parameters(), jc.DeepEquals, t.expectedPayload)
  2364  		}
  2365  	}
  2366  }
  2367  
  2368  func (s *MachineSuite) TestMachineAddDifferentAction(c *gc.C) {
  2369  	m, err := s.State.AddMachine("trusty", state.JobHostUnits)
  2370  	c.Assert(err, jc.ErrorIsNil)
  2371  
  2372  	_, err = m.AddAction("benchmark", nil)
  2373  	c.Assert(err, gc.ErrorMatches, `cannot add action "benchmark" to a machine; only predefined actions allowed`)
  2374  }