github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/state/api/provisioner/provisioner_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package provisioner_test
     5  
     6  import (
     7  	stdtesting "testing"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/names"
    11  	jc "github.com/juju/testing/checkers"
    12  	"github.com/juju/utils"
    13  	gc "launchpad.net/gocheck"
    14  
    15  	"github.com/juju/juju/constraints"
    16  	"github.com/juju/juju/container"
    17  	"github.com/juju/juju/instance"
    18  	"github.com/juju/juju/juju/testing"
    19  	"github.com/juju/juju/state"
    20  	"github.com/juju/juju/state/api"
    21  	"github.com/juju/juju/state/api/params"
    22  	"github.com/juju/juju/state/api/provisioner"
    23  	apitesting "github.com/juju/juju/state/api/testing"
    24  	statetesting "github.com/juju/juju/state/testing"
    25  	coretesting "github.com/juju/juju/testing"
    26  	"github.com/juju/juju/tools"
    27  	"github.com/juju/juju/version"
    28  )
    29  
    30  func TestAll(t *stdtesting.T) {
    31  	coretesting.MgoTestPackage(t)
    32  }
    33  
    34  type provisionerSuite struct {
    35  	testing.JujuConnSuite
    36  	*apitesting.EnvironWatcherTests
    37  	*apitesting.APIAddresserTests
    38  
    39  	st      *api.State
    40  	machine *state.Machine
    41  
    42  	provisioner *provisioner.State
    43  }
    44  
    45  var _ = gc.Suite(&provisionerSuite{})
    46  
    47  func (s *provisionerSuite) SetUpTest(c *gc.C) {
    48  	s.JujuConnSuite.SetUpTest(c)
    49  
    50  	var err error
    51  	s.machine, err = s.State.AddMachine("quantal", state.JobManageEnviron)
    52  	c.Assert(err, gc.IsNil)
    53  	password, err := utils.RandomPassword()
    54  	c.Assert(err, gc.IsNil)
    55  	err = s.machine.SetPassword(password)
    56  	c.Assert(err, gc.IsNil)
    57  	err = s.machine.SetInstanceInfo("i-manager", "fake_nonce", nil, nil, nil)
    58  	c.Assert(err, gc.IsNil)
    59  	s.st = s.OpenAPIAsMachine(c, s.machine.Tag(), password, "fake_nonce")
    60  	c.Assert(s.st, gc.NotNil)
    61  	err = s.machine.SetAddresses(instance.NewAddress("0.1.2.3", instance.NetworkUnknown))
    62  	c.Assert(err, gc.IsNil)
    63  
    64  	// Create the provisioner API facade.
    65  	s.provisioner = s.st.Provisioner()
    66  	c.Assert(s.provisioner, gc.NotNil)
    67  
    68  	s.EnvironWatcherTests = apitesting.NewEnvironWatcherTests(s.provisioner, s.BackingState, apitesting.HasSecrets)
    69  	s.APIAddresserTests = apitesting.NewAPIAddresserTests(s.provisioner, s.BackingState)
    70  }
    71  
    72  func (s *provisionerSuite) TestMachineTagAndId(c *gc.C) {
    73  	apiMachine, err := s.provisioner.Machine("machine-42")
    74  	c.Assert(err, gc.ErrorMatches, "machine 42 not found")
    75  	c.Assert(err, jc.Satisfies, params.IsCodeNotFound)
    76  	c.Assert(apiMachine, gc.IsNil)
    77  
    78  	apiMachine, err = s.provisioner.Machine(s.machine.Tag())
    79  	c.Assert(err, gc.IsNil)
    80  	c.Assert(apiMachine.Tag(), gc.Equals, s.machine.Tag())
    81  	c.Assert(apiMachine.Id(), gc.Equals, s.machine.Id())
    82  }
    83  
    84  func (s *provisionerSuite) TestGetSetStatus(c *gc.C) {
    85  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
    86  	c.Assert(err, gc.IsNil)
    87  
    88  	status, info, err := apiMachine.Status()
    89  	c.Assert(err, gc.IsNil)
    90  	c.Assert(status, gc.Equals, params.StatusPending)
    91  	c.Assert(info, gc.Equals, "")
    92  
    93  	err = apiMachine.SetStatus(params.StatusStarted, "blah", nil)
    94  	c.Assert(err, gc.IsNil)
    95  
    96  	status, info, err = apiMachine.Status()
    97  	c.Assert(err, gc.IsNil)
    98  	c.Assert(status, gc.Equals, params.StatusStarted)
    99  	c.Assert(info, gc.Equals, "blah")
   100  	_, _, data, err := s.machine.Status()
   101  	c.Assert(err, gc.IsNil)
   102  	c.Assert(data, gc.HasLen, 0)
   103  }
   104  
   105  func (s *provisionerSuite) TestGetSetStatusWithData(c *gc.C) {
   106  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   107  	c.Assert(err, gc.IsNil)
   108  
   109  	err = apiMachine.SetStatus(params.StatusError, "blah", params.StatusData{"foo": "bar"})
   110  	c.Assert(err, gc.IsNil)
   111  
   112  	status, info, err := apiMachine.Status()
   113  	c.Assert(err, gc.IsNil)
   114  	c.Assert(status, gc.Equals, params.StatusError)
   115  	c.Assert(info, gc.Equals, "blah")
   116  	_, _, data, err := s.machine.Status()
   117  	c.Assert(err, gc.IsNil)
   118  	c.Assert(data, gc.DeepEquals, params.StatusData{"foo": "bar"})
   119  }
   120  
   121  func (s *provisionerSuite) TestMachinesWithTransientErrors(c *gc.C) {
   122  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   123  	c.Assert(err, gc.IsNil)
   124  	err = machine.SetStatus(params.StatusError, "blah", params.StatusData{"transient": true})
   125  	c.Assert(err, gc.IsNil)
   126  	machines, info, err := s.provisioner.MachinesWithTransientErrors()
   127  	c.Assert(err, gc.IsNil)
   128  	c.Assert(machines, gc.HasLen, 1)
   129  	c.Assert(machines[0].Id(), gc.Equals, "1")
   130  	c.Assert(info, gc.HasLen, 1)
   131  	c.Assert(info[0], gc.DeepEquals, params.StatusResult{
   132  		Id:     "1",
   133  		Life:   "alive",
   134  		Status: "error",
   135  		Info:   "blah",
   136  		Data:   params.StatusData{"transient": true},
   137  	})
   138  }
   139  
   140  func (s *provisionerSuite) TestEnsureDeadAndRemove(c *gc.C) {
   141  	// Create a fresh machine to test the complete scenario.
   142  	otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   143  	c.Assert(err, gc.IsNil)
   144  	c.Assert(otherMachine.Life(), gc.Equals, state.Alive)
   145  
   146  	apiMachine, err := s.provisioner.Machine(otherMachine.Tag())
   147  	c.Assert(err, gc.IsNil)
   148  
   149  	err = apiMachine.Remove()
   150  	c.Assert(err, gc.ErrorMatches, `cannot remove entity "machine-1": still alive`)
   151  	err = apiMachine.EnsureDead()
   152  	c.Assert(err, gc.IsNil)
   153  
   154  	err = otherMachine.Refresh()
   155  	c.Assert(err, gc.IsNil)
   156  	c.Assert(otherMachine.Life(), gc.Equals, state.Dead)
   157  
   158  	err = apiMachine.EnsureDead()
   159  	c.Assert(err, gc.IsNil)
   160  	err = otherMachine.Refresh()
   161  	c.Assert(err, gc.IsNil)
   162  	c.Assert(otherMachine.Life(), gc.Equals, state.Dead)
   163  
   164  	err = apiMachine.Remove()
   165  	c.Assert(err, gc.IsNil)
   166  	err = otherMachine.Refresh()
   167  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   168  
   169  	err = apiMachine.EnsureDead()
   170  	c.Assert(err, gc.ErrorMatches, "machine 1 not found")
   171  	c.Assert(err, jc.Satisfies, params.IsCodeNotFound)
   172  
   173  	// Now try to EnsureDead machine 0 - should fail.
   174  	apiMachine, err = s.provisioner.Machine(s.machine.Tag())
   175  	c.Assert(err, gc.IsNil)
   176  	err = apiMachine.EnsureDead()
   177  	c.Assert(err, gc.ErrorMatches, "machine 0 is required by the environment")
   178  }
   179  
   180  func (s *provisionerSuite) TestRefreshAndLife(c *gc.C) {
   181  	// Create a fresh machine to test the complete scenario.
   182  	otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   183  	c.Assert(err, gc.IsNil)
   184  	c.Assert(otherMachine.Life(), gc.Equals, state.Alive)
   185  
   186  	apiMachine, err := s.provisioner.Machine(otherMachine.Tag())
   187  	c.Assert(err, gc.IsNil)
   188  	c.Assert(apiMachine.Life(), gc.Equals, params.Alive)
   189  
   190  	err = apiMachine.EnsureDead()
   191  	c.Assert(err, gc.IsNil)
   192  	c.Assert(apiMachine.Life(), gc.Equals, params.Alive)
   193  
   194  	err = apiMachine.Refresh()
   195  	c.Assert(err, gc.IsNil)
   196  	c.Assert(apiMachine.Life(), gc.Equals, params.Dead)
   197  }
   198  
   199  func (s *provisionerSuite) TestSetInstanceInfo(c *gc.C) {
   200  	// Create a fresh machine, since machine 0 is already provisioned.
   201  	notProvisionedMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   202  	c.Assert(err, gc.IsNil)
   203  
   204  	apiMachine, err := s.provisioner.Machine(notProvisionedMachine.Tag())
   205  	c.Assert(err, gc.IsNil)
   206  
   207  	instanceId, err := apiMachine.InstanceId()
   208  	c.Assert(err, jc.Satisfies, params.IsCodeNotProvisioned)
   209  	c.Assert(err, gc.ErrorMatches, "machine 1 is not provisioned")
   210  	c.Assert(instanceId, gc.Equals, instance.Id(""))
   211  
   212  	hwChars := instance.MustParseHardware("cpu-cores=123", "mem=4G")
   213  
   214  	_, err = s.State.Network("net1")
   215  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   216  	_, err = s.State.Network("vlan42")
   217  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   218  
   219  	ifacesMachine, err := notProvisionedMachine.NetworkInterfaces()
   220  	c.Assert(err, gc.IsNil)
   221  	c.Assert(ifacesMachine, gc.HasLen, 0)
   222  
   223  	networks := []params.Network{{
   224  		Tag:        "network-net1",
   225  		ProviderId: "net1",
   226  		CIDR:       "0.1.2.0/24",
   227  		VLANTag:    0,
   228  	}, {
   229  		Tag:        "network-vlan42",
   230  		ProviderId: "vlan42",
   231  		CIDR:       "0.2.2.0/24",
   232  		VLANTag:    42,
   233  	}, {
   234  		Tag:        "network-vlan69",
   235  		ProviderId: "vlan69",
   236  		CIDR:       "0.3.2.0/24",
   237  		VLANTag:    69,
   238  	}, {
   239  		Tag:        "network-vlan42", // duplicated; ignored
   240  		ProviderId: "vlan42",
   241  		CIDR:       "0.2.2.0/24",
   242  		VLANTag:    42,
   243  	}}
   244  	ifaces := []params.NetworkInterface{{
   245  		MACAddress:    "aa:bb:cc:dd:ee:f0",
   246  		NetworkTag:    "network-net1",
   247  		InterfaceName: "eth0",
   248  		IsVirtual:     false,
   249  	}, {
   250  		MACAddress:    "aa:bb:cc:dd:ee:f1",
   251  		NetworkTag:    "network-net1",
   252  		InterfaceName: "eth1",
   253  		IsVirtual:     false,
   254  	}, {
   255  		MACAddress:    "aa:bb:cc:dd:ee:f1",
   256  		NetworkTag:    "network-vlan42",
   257  		InterfaceName: "eth1.42",
   258  		IsVirtual:     true,
   259  	}, {
   260  		MACAddress:    "aa:bb:cc:dd:ee:f1",
   261  		NetworkTag:    "network-vlan69",
   262  		InterfaceName: "eth1.69",
   263  		IsVirtual:     true,
   264  	}, {
   265  		MACAddress:    "aa:bb:cc:dd:ee:f1", // duplicated mac+net; ignored
   266  		NetworkTag:    "network-vlan42",
   267  		InterfaceName: "eth2",
   268  		IsVirtual:     true,
   269  	}, {
   270  		MACAddress:    "aa:bb:cc:dd:ee:f4",
   271  		NetworkTag:    "network-net1",
   272  		InterfaceName: "eth1", // duplicated name+machine id; ignored
   273  		IsVirtual:     false,
   274  	}}
   275  
   276  	err = apiMachine.SetInstanceInfo("i-will", "fake_nonce", &hwChars, networks, ifaces)
   277  	c.Assert(err, gc.IsNil)
   278  
   279  	instanceId, err = apiMachine.InstanceId()
   280  	c.Assert(err, gc.IsNil)
   281  	c.Assert(instanceId, gc.Equals, instance.Id("i-will"))
   282  
   283  	// Try it again - should fail.
   284  	err = apiMachine.SetInstanceInfo("i-wont", "fake", nil, nil, nil)
   285  	c.Assert(err, gc.ErrorMatches, `aborted instance "i-wont": cannot set instance data for machine "1": already set`)
   286  
   287  	// Now try to get machine 0's instance id.
   288  	apiMachine, err = s.provisioner.Machine(s.machine.Tag())
   289  	c.Assert(err, gc.IsNil)
   290  	instanceId, err = apiMachine.InstanceId()
   291  	c.Assert(err, gc.IsNil)
   292  	c.Assert(instanceId, gc.Equals, instance.Id("i-manager"))
   293  
   294  	// Check the networks are created.
   295  	for i, _ := range networks {
   296  		if i == 3 {
   297  			// Last one was ignored, so skip it.
   298  			break
   299  		}
   300  		_, networkName, err := names.ParseTag(networks[i].Tag, names.NetworkTagKind)
   301  		c.Assert(err, gc.IsNil)
   302  		network, err := s.State.Network(networkName)
   303  		c.Assert(err, gc.IsNil)
   304  		c.Check(network.Name(), gc.Equals, networkName)
   305  		c.Check(network.ProviderId(), gc.Equals, networks[i].ProviderId)
   306  		c.Check(network.Tag(), gc.Equals, networks[i].Tag)
   307  		c.Check(network.VLANTag(), gc.Equals, networks[i].VLANTag)
   308  		c.Check(network.CIDR(), gc.Equals, networks[i].CIDR)
   309  	}
   310  
   311  	// And the network interfaces as well.
   312  	ifacesMachine, err = notProvisionedMachine.NetworkInterfaces()
   313  	c.Assert(err, gc.IsNil)
   314  	c.Assert(ifacesMachine, gc.HasLen, 4)
   315  	actual := make([]params.NetworkInterface, len(ifacesMachine))
   316  	for i, iface := range ifacesMachine {
   317  		actual[i].InterfaceName = iface.InterfaceName()
   318  		actual[i].NetworkTag = iface.NetworkTag()
   319  		actual[i].MACAddress = iface.MACAddress()
   320  		actual[i].IsVirtual = iface.IsVirtual()
   321  		c.Check(iface.MachineTag(), gc.Equals, notProvisionedMachine.Tag())
   322  		c.Check(iface.MachineId(), gc.Equals, notProvisionedMachine.Id())
   323  	}
   324  	c.Assert(actual, jc.SameContents, ifaces[:4]) // skip the rest as they are ignored.
   325  }
   326  
   327  func (s *provisionerSuite) TestSeries(c *gc.C) {
   328  	// Create a fresh machine with different series.
   329  	foobarMachine, err := s.State.AddMachine("foobar", state.JobHostUnits)
   330  	c.Assert(err, gc.IsNil)
   331  
   332  	apiMachine, err := s.provisioner.Machine(foobarMachine.Tag())
   333  	c.Assert(err, gc.IsNil)
   334  	series, err := apiMachine.Series()
   335  	c.Assert(err, gc.IsNil)
   336  	c.Assert(series, gc.Equals, "foobar")
   337  
   338  	// Now try machine 0.
   339  	apiMachine, err = s.provisioner.Machine(s.machine.Tag())
   340  	c.Assert(err, gc.IsNil)
   341  	series, err = apiMachine.Series()
   342  	c.Assert(err, gc.IsNil)
   343  	c.Assert(series, gc.Equals, "quantal")
   344  }
   345  
   346  func (s *provisionerSuite) TestDistributionGroup(c *gc.C) {
   347  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   348  	c.Assert(err, gc.IsNil)
   349  	instances, err := apiMachine.DistributionGroup()
   350  	c.Assert(err, gc.IsNil)
   351  	c.Assert(instances, gc.DeepEquals, []instance.Id{"i-manager"})
   352  
   353  	machine1, err := s.State.AddMachine("quantal", state.JobHostUnits)
   354  	c.Assert(err, gc.IsNil)
   355  	apiMachine, err = s.provisioner.Machine(machine1.Tag())
   356  	c.Assert(err, gc.IsNil)
   357  	wordpress := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
   358  
   359  	err = apiMachine.SetInstanceInfo("i-d", "fake", nil, nil, nil)
   360  	c.Assert(err, gc.IsNil)
   361  	instances, err = apiMachine.DistributionGroup()
   362  	c.Assert(err, gc.IsNil)
   363  	c.Assert(instances, gc.HasLen, 0) // no units assigned
   364  
   365  	var unitNames []string
   366  	for i := 0; i < 3; i++ {
   367  		unit, err := wordpress.AddUnit()
   368  		c.Assert(err, gc.IsNil)
   369  		unitNames = append(unitNames, unit.Name())
   370  		err = unit.AssignToMachine(machine1)
   371  		c.Assert(err, gc.IsNil)
   372  		instances, err := apiMachine.DistributionGroup()
   373  		c.Assert(err, gc.IsNil)
   374  		c.Assert(instances, gc.DeepEquals, []instance.Id{"i-d"})
   375  	}
   376  }
   377  
   378  func (s *provisionerSuite) TestDistributionGroupMachineNotFound(c *gc.C) {
   379  	stateMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   380  	c.Assert(err, gc.IsNil)
   381  	apiMachine, err := s.provisioner.Machine(stateMachine.Tag())
   382  	c.Assert(err, gc.IsNil)
   383  	err = apiMachine.EnsureDead()
   384  	c.Assert(err, gc.IsNil)
   385  	err = apiMachine.Remove()
   386  	c.Assert(err, gc.IsNil)
   387  	_, err = apiMachine.DistributionGroup()
   388  	c.Assert(err, gc.ErrorMatches, "machine 1 not found")
   389  	c.Assert(err, jc.Satisfies, params.IsCodeNotFound)
   390  }
   391  
   392  func (s *provisionerSuite) TestProvisioningInfo(c *gc.C) {
   393  	cons := constraints.MustParse("cpu-cores=12 mem=8G networks=^net3,^net4")
   394  	template := state.MachineTemplate{
   395  		Series:            "quantal",
   396  		Jobs:              []state.MachineJob{state.JobHostUnits},
   397  		Placement:         "valid",
   398  		Constraints:       cons,
   399  		RequestedNetworks: []string{"net1", "net2"},
   400  	}
   401  	machine, err := s.State.AddOneMachine(template)
   402  	c.Assert(err, gc.IsNil)
   403  	apiMachine, err := s.provisioner.Machine(machine.Tag())
   404  	c.Assert(err, gc.IsNil)
   405  	provisioningInfo, err := apiMachine.ProvisioningInfo()
   406  	c.Assert(err, gc.IsNil)
   407  	c.Assert(provisioningInfo.Series, gc.Equals, template.Series)
   408  	c.Assert(provisioningInfo.Placement, gc.Equals, template.Placement)
   409  	c.Assert(provisioningInfo.Constraints, gc.DeepEquals, template.Constraints)
   410  	c.Assert(provisioningInfo.Networks, gc.DeepEquals, template.RequestedNetworks)
   411  }
   412  
   413  func (s *provisionerSuite) TestProvisioningInfoMachineNotFound(c *gc.C) {
   414  	stateMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   415  	c.Assert(err, gc.IsNil)
   416  	apiMachine, err := s.provisioner.Machine(stateMachine.Tag())
   417  	c.Assert(err, gc.IsNil)
   418  	err = apiMachine.EnsureDead()
   419  	c.Assert(err, gc.IsNil)
   420  	err = apiMachine.Remove()
   421  	c.Assert(err, gc.IsNil)
   422  	_, err = apiMachine.ProvisioningInfo()
   423  	c.Assert(err, gc.ErrorMatches, "machine 1 not found")
   424  	c.Assert(err, jc.Satisfies, params.IsCodeNotFound)
   425  	// auth tests in apiserver
   426  }
   427  
   428  func (s *provisionerSuite) TestWatchContainers(c *gc.C) {
   429  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   430  	c.Assert(err, gc.IsNil)
   431  
   432  	// Add one LXC container.
   433  	template := state.MachineTemplate{
   434  		Series: "quantal",
   435  		Jobs:   []state.MachineJob{state.JobHostUnits},
   436  	}
   437  	container, err := s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC)
   438  	c.Assert(err, gc.IsNil)
   439  
   440  	w, err := apiMachine.WatchContainers(instance.LXC)
   441  	c.Assert(err, gc.IsNil)
   442  	defer statetesting.AssertStop(c, w)
   443  	wc := statetesting.NewStringsWatcherC(c, s.BackingState, w)
   444  
   445  	// Initial event.
   446  	wc.AssertChange(container.Id())
   447  
   448  	// Change something other than the containers and make sure it's
   449  	// not detected.
   450  	err = apiMachine.SetStatus(params.StatusStarted, "not really", nil)
   451  	c.Assert(err, gc.IsNil)
   452  	wc.AssertNoChange()
   453  
   454  	// Add a KVM container and make sure it's not detected.
   455  	container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.KVM)
   456  	c.Assert(err, gc.IsNil)
   457  	wc.AssertNoChange()
   458  
   459  	// Add another LXC container and make sure it's detected.
   460  	container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC)
   461  	c.Assert(err, gc.IsNil)
   462  	wc.AssertChange(container.Id())
   463  
   464  	statetesting.AssertStop(c, w)
   465  	wc.AssertClosed()
   466  }
   467  
   468  func (s *provisionerSuite) TestWatchContainersAcceptsSupportedContainers(c *gc.C) {
   469  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   470  	c.Assert(err, gc.IsNil)
   471  
   472  	for _, ctype := range instance.ContainerTypes {
   473  		w, err := apiMachine.WatchContainers(ctype)
   474  		c.Assert(w, gc.NotNil)
   475  		c.Assert(err, gc.IsNil)
   476  	}
   477  }
   478  
   479  func (s *provisionerSuite) TestWatchContainersErrors(c *gc.C) {
   480  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   481  	c.Assert(err, gc.IsNil)
   482  
   483  	_, err = apiMachine.WatchContainers(instance.NONE)
   484  	c.Assert(err, gc.ErrorMatches, `unsupported container type "none"`)
   485  
   486  	_, err = apiMachine.WatchContainers("")
   487  	c.Assert(err, gc.ErrorMatches, "container type must be specified")
   488  }
   489  
   490  func (s *provisionerSuite) TestWatchEnvironMachines(c *gc.C) {
   491  	w, err := s.provisioner.WatchEnvironMachines()
   492  	c.Assert(err, gc.IsNil)
   493  	defer statetesting.AssertStop(c, w)
   494  	wc := statetesting.NewStringsWatcherC(c, s.BackingState, w)
   495  
   496  	// Initial event.
   497  	wc.AssertChange(s.machine.Id())
   498  
   499  	// Add another 2 machines make sure they are detected.
   500  	otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   501  	c.Assert(err, gc.IsNil)
   502  	otherMachine, err = s.State.AddMachine("quantal", state.JobHostUnits)
   503  	c.Assert(err, gc.IsNil)
   504  	wc.AssertChange("1", "2")
   505  
   506  	// Change the lifecycle of last machine.
   507  	err = otherMachine.EnsureDead()
   508  	c.Assert(err, gc.IsNil)
   509  	wc.AssertChange("2")
   510  
   511  	// Add a container and make sure it's not detected.
   512  	template := state.MachineTemplate{
   513  		Series: "quantal",
   514  		Jobs:   []state.MachineJob{state.JobHostUnits},
   515  	}
   516  	_, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC)
   517  	c.Assert(err, gc.IsNil)
   518  	wc.AssertNoChange()
   519  
   520  	statetesting.AssertStop(c, w)
   521  	wc.AssertClosed()
   522  }
   523  
   524  func (s *provisionerSuite) TestStateAddresses(c *gc.C) {
   525  	err := s.machine.SetAddresses(instance.NewAddress("0.1.2.3", instance.NetworkUnknown))
   526  	c.Assert(err, gc.IsNil)
   527  
   528  	stateAddresses, err := s.State.Addresses()
   529  	c.Assert(err, gc.IsNil)
   530  
   531  	addresses, err := s.provisioner.StateAddresses()
   532  	c.Assert(err, gc.IsNil)
   533  	c.Assert(addresses, gc.DeepEquals, stateAddresses)
   534  }
   535  
   536  func (s *provisionerSuite) TestContainerManagerConfigKVM(c *gc.C) {
   537  	args := params.ContainerManagerConfigParams{Type: instance.KVM}
   538  	result, err := s.provisioner.ContainerManagerConfig(args)
   539  	c.Assert(err, gc.IsNil)
   540  	c.Assert(result.ManagerConfig, gc.DeepEquals, map[string]string{
   541  		container.ConfigName: "juju",
   542  	})
   543  }
   544  
   545  func (s *provisionerSuite) TestContainerManagerConfigLXC(c *gc.C) {
   546  	args := params.ContainerManagerConfigParams{Type: instance.LXC}
   547  	st, err := state.Open(s.StateInfo(c), state.DialOpts{}, state.Policy(nil))
   548  	c.Assert(err, gc.IsNil)
   549  	defer st.Close()
   550  
   551  	tests := []struct {
   552  		lxcUseClone          bool
   553  		lxcUseCloneAufs      bool
   554  		expectedUseClone     string
   555  		expectedUseCloneAufs string
   556  	}{{
   557  		lxcUseClone:          true,
   558  		expectedUseClone:     "true",
   559  		expectedUseCloneAufs: "false",
   560  	}, {
   561  		lxcUseClone:          false,
   562  		expectedUseClone:     "false",
   563  		expectedUseCloneAufs: "false",
   564  	}, {
   565  		lxcUseCloneAufs:      false,
   566  		expectedUseClone:     "false",
   567  		expectedUseCloneAufs: "false",
   568  	}, {
   569  		lxcUseClone:          true,
   570  		lxcUseCloneAufs:      true,
   571  		expectedUseClone:     "true",
   572  		expectedUseCloneAufs: "true",
   573  	}}
   574  
   575  	result, err := s.provisioner.ContainerManagerConfig(args)
   576  	c.Assert(err, gc.IsNil)
   577  	c.Assert(result.ManagerConfig[container.ConfigName], gc.Equals, "juju")
   578  	c.Assert(result.ManagerConfig["use-clone"], gc.Equals, "")
   579  
   580  	// Change lxc-clone, and ensure it gets picked up.
   581  	for i, t := range tests {
   582  		c.Logf("test %d: %+v", i, t)
   583  		err = st.UpdateEnvironConfig(map[string]interface{}{
   584  			"lxc-clone":      t.lxcUseClone,
   585  			"lxc-clone-aufs": t.lxcUseCloneAufs,
   586  		}, nil, nil)
   587  		c.Assert(err, gc.IsNil)
   588  		result, err := s.provisioner.ContainerManagerConfig(args)
   589  		c.Assert(err, gc.IsNil)
   590  		c.Assert(result.ManagerConfig[container.ConfigName], gc.Equals, "juju")
   591  		c.Assert(result.ManagerConfig["use-clone"], gc.Equals, t.expectedUseClone)
   592  		c.Assert(result.ManagerConfig["use-aufs"], gc.Equals, t.expectedUseCloneAufs)
   593  	}
   594  }
   595  
   596  func (s *provisionerSuite) TestContainerManagerConfigPermissive(c *gc.C) {
   597  	// ContainerManagerConfig is permissive of container types, and
   598  	// will just return the basic type-independent configuration.
   599  	args := params.ContainerManagerConfigParams{Type: "invalid"}
   600  	result, err := s.provisioner.ContainerManagerConfig(args)
   601  	c.Assert(err, gc.IsNil)
   602  	c.Assert(result.ManagerConfig, gc.DeepEquals, map[string]string{
   603  		container.ConfigName: "juju",
   604  	})
   605  }
   606  
   607  func (s *provisionerSuite) TestContainerConfig(c *gc.C) {
   608  	result, err := s.provisioner.ContainerConfig()
   609  	c.Assert(err, gc.IsNil)
   610  	c.Assert(result.ProviderType, gc.Equals, "dummy")
   611  	c.Assert(result.AuthorizedKeys, gc.Equals, coretesting.FakeAuthKeys)
   612  	c.Assert(result.SSLHostnameVerification, jc.IsTrue)
   613  }
   614  
   615  func (s *provisionerSuite) TestToolsWrongMachine(c *gc.C) {
   616  	tools, err := s.provisioner.Tools("42")
   617  	c.Assert(err, gc.ErrorMatches, "permission denied")
   618  	c.Assert(err, jc.Satisfies, params.IsCodeUnauthorized)
   619  	c.Assert(tools, gc.IsNil)
   620  }
   621  
   622  func (s *provisionerSuite) TestTools(c *gc.C) {
   623  	cur := version.Current
   624  	curTools := &tools.Tools{Version: cur, URL: ""}
   625  	curTools.Version.Minor++
   626  	s.machine.SetAgentVersion(cur)
   627  	// Provisioner.Tools returns the *desired* set of tools, not the
   628  	// currently running set. We want to be upgraded to cur.Version
   629  	stateTools, err := s.provisioner.Tools(s.machine.Tag())
   630  	c.Assert(err, gc.IsNil)
   631  	c.Assert(stateTools.Version, gc.Equals, cur)
   632  	c.Assert(stateTools.URL, gc.Not(gc.Equals), "")
   633  }
   634  
   635  func (s *provisionerSuite) TestSetSupportedContainers(c *gc.C) {
   636  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   637  	c.Assert(err, gc.IsNil)
   638  	err = apiMachine.SetSupportedContainers(instance.LXC, instance.KVM)
   639  	c.Assert(err, gc.IsNil)
   640  
   641  	err = s.machine.Refresh()
   642  	c.Assert(err, gc.IsNil)
   643  	containers, ok := s.machine.SupportedContainers()
   644  	c.Assert(ok, jc.IsTrue)
   645  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC, instance.KVM})
   646  }
   647  
   648  func (s *provisionerSuite) TestSupportsNoContainers(c *gc.C) {
   649  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   650  	c.Assert(err, gc.IsNil)
   651  	err = apiMachine.SupportsNoContainers()
   652  	c.Assert(err, gc.IsNil)
   653  
   654  	err = s.machine.Refresh()
   655  	c.Assert(err, gc.IsNil)
   656  	containers, ok := s.machine.SupportedContainers()
   657  	c.Assert(ok, jc.IsTrue)
   658  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{})
   659  }