github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/apiserver/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  	"fmt"
     8  	stdtesting "testing"
     9  
    10  	"github.com/juju/errors"
    11  	"github.com/juju/names"
    12  	jc "github.com/juju/testing/checkers"
    13  	"github.com/juju/utils/proxy"
    14  	gc "gopkg.in/check.v1"
    15  
    16  	"github.com/juju/juju/apiserver/common"
    17  	commontesting "github.com/juju/juju/apiserver/common/testing"
    18  	"github.com/juju/juju/apiserver/params"
    19  	"github.com/juju/juju/apiserver/provisioner"
    20  	apiservertesting "github.com/juju/juju/apiserver/testing"
    21  	"github.com/juju/juju/constraints"
    22  	"github.com/juju/juju/container"
    23  	"github.com/juju/juju/environs/tags"
    24  	"github.com/juju/juju/feature"
    25  	"github.com/juju/juju/instance"
    26  	"github.com/juju/juju/juju/testing"
    27  	"github.com/juju/juju/network"
    28  	"github.com/juju/juju/provider/dummy"
    29  	"github.com/juju/juju/state"
    30  	"github.com/juju/juju/state/multiwatcher"
    31  	statetesting "github.com/juju/juju/state/testing"
    32  	"github.com/juju/juju/storage/poolmanager"
    33  	storagedummy "github.com/juju/juju/storage/provider/dummy"
    34  	"github.com/juju/juju/storage/provider/registry"
    35  	coretesting "github.com/juju/juju/testing"
    36  )
    37  
    38  func Test(t *stdtesting.T) {
    39  	coretesting.MgoTestPackage(t)
    40  }
    41  
    42  type provisionerSuite struct {
    43  	testing.JujuConnSuite
    44  
    45  	machines []*state.Machine
    46  
    47  	authorizer  apiservertesting.FakeAuthorizer
    48  	resources   *common.Resources
    49  	provisioner *provisioner.ProvisionerAPI
    50  }
    51  
    52  var _ = gc.Suite(&provisionerSuite{})
    53  
    54  func (s *provisionerSuite) SetUpTest(c *gc.C) {
    55  	s.setUpTest(c, false)
    56  }
    57  
    58  func (s *provisionerSuite) setUpTest(c *gc.C, withStateServer bool) {
    59  	s.JujuConnSuite.SetUpTest(c)
    60  	// We're testing with address allocation on by default. There are
    61  	// separate tests to check the behavior when the flag is not
    62  	// enabled.
    63  	s.SetFeatureFlags(feature.AddressAllocation)
    64  
    65  	// Reset previous machines (if any) and create 3 machines
    66  	// for the tests, plus an optional state server machine.
    67  	s.machines = nil
    68  	// Note that the specific machine ids allocated are assumed
    69  	// to be numerically consecutive from zero.
    70  	if withStateServer {
    71  		s.machines = append(s.machines, testing.AddStateServerMachine(c, s.State))
    72  	}
    73  	for i := 0; i < 5; i++ {
    74  		machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
    75  		c.Check(err, jc.ErrorIsNil)
    76  		s.machines = append(s.machines, machine)
    77  	}
    78  
    79  	// Create a FakeAuthorizer so we can check permissions,
    80  	// set up assuming we logged in as the environment manager.
    81  	s.authorizer = apiservertesting.FakeAuthorizer{
    82  		EnvironManager: true,
    83  	}
    84  
    85  	// Create the resource registry separately to track invocations to
    86  	// Register, and to register the root for tools URLs.
    87  	s.resources = common.NewResources()
    88  
    89  	// Create a provisioner API for the machine.
    90  	provisionerAPI, err := provisioner.NewProvisionerAPI(
    91  		s.State,
    92  		s.resources,
    93  		s.authorizer,
    94  	)
    95  	c.Assert(err, jc.ErrorIsNil)
    96  	s.provisioner = provisionerAPI
    97  }
    98  
    99  type withoutStateServerSuite struct {
   100  	provisionerSuite
   101  	*commontesting.EnvironWatcherTest
   102  }
   103  
   104  var _ = gc.Suite(&withoutStateServerSuite{})
   105  
   106  func (s *withoutStateServerSuite) SetUpTest(c *gc.C) {
   107  	s.setUpTest(c, false)
   108  	s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest(s.provisioner, s.State, s.resources, commontesting.HasSecrets)
   109  }
   110  
   111  func (s *withoutStateServerSuite) TestProvisionerFailsWithNonMachineAgentNonManagerUser(c *gc.C) {
   112  	anAuthorizer := s.authorizer
   113  	anAuthorizer.EnvironManager = true
   114  	// Works with an environment manager, which is not a machine agent.
   115  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   116  	c.Assert(err, jc.ErrorIsNil)
   117  	c.Assert(aProvisioner, gc.NotNil)
   118  
   119  	// But fails with neither a machine agent or an environment manager.
   120  	anAuthorizer.EnvironManager = false
   121  	aProvisioner, err = provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   122  	c.Assert(err, gc.NotNil)
   123  	c.Assert(aProvisioner, gc.IsNil)
   124  	c.Assert(err, gc.ErrorMatches, "permission denied")
   125  }
   126  
   127  func (s *withoutStateServerSuite) TestSetPasswords(c *gc.C) {
   128  	args := params.EntityPasswords{
   129  		Changes: []params.EntityPassword{
   130  			{Tag: s.machines[0].Tag().String(), Password: "xxx0-1234567890123457890"},
   131  			{Tag: s.machines[1].Tag().String(), Password: "xxx1-1234567890123457890"},
   132  			{Tag: s.machines[2].Tag().String(), Password: "xxx2-1234567890123457890"},
   133  			{Tag: s.machines[3].Tag().String(), Password: "xxx3-1234567890123457890"},
   134  			{Tag: s.machines[4].Tag().String(), Password: "xxx4-1234567890123457890"},
   135  			{Tag: "machine-42", Password: "foo"},
   136  			{Tag: "unit-foo-0", Password: "zzz"},
   137  			{Tag: "service-bar", Password: "abc"},
   138  		},
   139  	}
   140  	results, err := s.provisioner.SetPasswords(args)
   141  	c.Assert(err, jc.ErrorIsNil)
   142  	c.Assert(results, gc.DeepEquals, params.ErrorResults{
   143  		Results: []params.ErrorResult{
   144  			{nil},
   145  			{nil},
   146  			{nil},
   147  			{nil},
   148  			{nil},
   149  			{apiservertesting.NotFoundError("machine 42")},
   150  			{apiservertesting.ErrUnauthorized},
   151  			{apiservertesting.ErrUnauthorized},
   152  		},
   153  	})
   154  
   155  	// Verify the changes to both machines succeeded.
   156  	for i, machine := range s.machines {
   157  		c.Logf("trying %q password", machine.Tag())
   158  		err = machine.Refresh()
   159  		c.Assert(err, jc.ErrorIsNil)
   160  		changed := machine.PasswordValid(fmt.Sprintf("xxx%d-1234567890123457890", i))
   161  		c.Assert(changed, jc.IsTrue)
   162  	}
   163  }
   164  
   165  func (s *withoutStateServerSuite) TestShortSetPasswords(c *gc.C) {
   166  	args := params.EntityPasswords{
   167  		Changes: []params.EntityPassword{
   168  			{Tag: s.machines[1].Tag().String(), Password: "xxx1"},
   169  		},
   170  	}
   171  	results, err := s.provisioner.SetPasswords(args)
   172  	c.Assert(err, jc.ErrorIsNil)
   173  	c.Assert(results.Results, gc.HasLen, 1)
   174  	c.Assert(results.Results[0].Error, gc.ErrorMatches,
   175  		"password is only 4 bytes long, and is not a valid Agent password")
   176  }
   177  
   178  func (s *withoutStateServerSuite) TestLifeAsMachineAgent(c *gc.C) {
   179  	// NOTE: This and the next call serve to test the two
   180  	// different authorization schemes:
   181  	// 1. Machine agents can access their own machine and
   182  	// any container that has their own machine as parent;
   183  	// 2. Environment managers can access any machine without
   184  	// a parent.
   185  	// There's no need to repeat this test for each method,
   186  	// because the authorization logic is common.
   187  
   188  	// Login as a machine agent for machine 0.
   189  	anAuthorizer := s.authorizer
   190  	anAuthorizer.EnvironManager = false
   191  	anAuthorizer.Tag = s.machines[0].Tag()
   192  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   193  	c.Assert(err, jc.ErrorIsNil)
   194  	c.Assert(aProvisioner, gc.NotNil)
   195  
   196  	// Make the machine dead before trying to add containers.
   197  	err = s.machines[0].EnsureDead()
   198  	c.Assert(err, jc.ErrorIsNil)
   199  
   200  	// Create some containers to work on.
   201  	template := state.MachineTemplate{
   202  		Series: "quantal",
   203  		Jobs:   []state.MachineJob{state.JobHostUnits},
   204  	}
   205  	var containers []*state.Machine
   206  	for i := 0; i < 3; i++ {
   207  		container, err := s.State.AddMachineInsideMachine(template, s.machines[0].Id(), instance.LXC)
   208  		c.Check(err, jc.ErrorIsNil)
   209  		containers = append(containers, container)
   210  	}
   211  	// Make one container dead.
   212  	err = containers[1].EnsureDead()
   213  	c.Assert(err, jc.ErrorIsNil)
   214  
   215  	args := params.Entities{Entities: []params.Entity{
   216  		{Tag: s.machines[0].Tag().String()},
   217  		{Tag: s.machines[1].Tag().String()},
   218  		{Tag: containers[0].Tag().String()},
   219  		{Tag: containers[1].Tag().String()},
   220  		{Tag: containers[2].Tag().String()},
   221  		{Tag: "machine-42"},
   222  		{Tag: "unit-foo-0"},
   223  		{Tag: "service-bar"},
   224  	}}
   225  	result, err := aProvisioner.Life(args)
   226  	c.Assert(err, jc.ErrorIsNil)
   227  	c.Assert(result, gc.DeepEquals, params.LifeResults{
   228  		Results: []params.LifeResult{
   229  			{Life: "dead"},
   230  			{Error: apiservertesting.ErrUnauthorized},
   231  			{Life: "alive"},
   232  			{Life: "dead"},
   233  			{Life: "alive"},
   234  			{Error: apiservertesting.ErrUnauthorized},
   235  			{Error: apiservertesting.ErrUnauthorized},
   236  			{Error: apiservertesting.ErrUnauthorized},
   237  		},
   238  	})
   239  }
   240  
   241  func (s *withoutStateServerSuite) TestLifeAsEnvironManager(c *gc.C) {
   242  	err := s.machines[1].EnsureDead()
   243  	c.Assert(err, jc.ErrorIsNil)
   244  	err = s.machines[1].Refresh()
   245  	c.Assert(err, jc.ErrorIsNil)
   246  	c.Assert(s.machines[0].Life(), gc.Equals, state.Alive)
   247  	c.Assert(s.machines[1].Life(), gc.Equals, state.Dead)
   248  	c.Assert(s.machines[2].Life(), gc.Equals, state.Alive)
   249  
   250  	args := params.Entities{Entities: []params.Entity{
   251  		{Tag: s.machines[0].Tag().String()},
   252  		{Tag: s.machines[1].Tag().String()},
   253  		{Tag: s.machines[2].Tag().String()},
   254  		{Tag: "machine-42"},
   255  		{Tag: "unit-foo-0"},
   256  		{Tag: "service-bar"},
   257  	}}
   258  	result, err := s.provisioner.Life(args)
   259  	c.Assert(err, jc.ErrorIsNil)
   260  	c.Assert(result, gc.DeepEquals, params.LifeResults{
   261  		Results: []params.LifeResult{
   262  			{Life: "alive"},
   263  			{Life: "dead"},
   264  			{Life: "alive"},
   265  			{Error: apiservertesting.NotFoundError("machine 42")},
   266  			{Error: apiservertesting.ErrUnauthorized},
   267  			{Error: apiservertesting.ErrUnauthorized},
   268  		},
   269  	})
   270  
   271  	// Remove the subordinate and make sure it's detected.
   272  	err = s.machines[1].Remove()
   273  	c.Assert(err, jc.ErrorIsNil)
   274  	err = s.machines[1].Refresh()
   275  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   276  
   277  	result, err = s.provisioner.Life(params.Entities{
   278  		Entities: []params.Entity{
   279  			{Tag: s.machines[1].Tag().String()},
   280  		},
   281  	})
   282  	c.Assert(err, jc.ErrorIsNil)
   283  	c.Assert(result, gc.DeepEquals, params.LifeResults{
   284  		Results: []params.LifeResult{
   285  			{Error: apiservertesting.NotFoundError("machine 1")},
   286  		},
   287  	})
   288  }
   289  
   290  func (s *withoutStateServerSuite) TestRemove(c *gc.C) {
   291  	err := s.machines[1].EnsureDead()
   292  	c.Assert(err, jc.ErrorIsNil)
   293  	s.assertLife(c, 0, state.Alive)
   294  	s.assertLife(c, 1, state.Dead)
   295  	s.assertLife(c, 2, state.Alive)
   296  
   297  	args := params.Entities{Entities: []params.Entity{
   298  		{Tag: s.machines[0].Tag().String()},
   299  		{Tag: s.machines[1].Tag().String()},
   300  		{Tag: s.machines[2].Tag().String()},
   301  		{Tag: "machine-42"},
   302  		{Tag: "unit-foo-0"},
   303  		{Tag: "service-bar"},
   304  	}}
   305  	result, err := s.provisioner.Remove(args)
   306  	c.Assert(err, jc.ErrorIsNil)
   307  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   308  		Results: []params.ErrorResult{
   309  			{&params.Error{Message: `cannot remove entity "machine-0": still alive`}},
   310  			{nil},
   311  			{&params.Error{Message: `cannot remove entity "machine-2": still alive`}},
   312  			{apiservertesting.NotFoundError("machine 42")},
   313  			{apiservertesting.ErrUnauthorized},
   314  			{apiservertesting.ErrUnauthorized},
   315  		},
   316  	})
   317  
   318  	// Verify the changes.
   319  	s.assertLife(c, 0, state.Alive)
   320  	err = s.machines[2].Refresh()
   321  	c.Assert(err, jc.ErrorIsNil)
   322  	s.assertLife(c, 2, state.Alive)
   323  }
   324  
   325  func (s *withoutStateServerSuite) TestSetStatus(c *gc.C) {
   326  	err := s.machines[0].SetStatus(state.StatusStarted, "blah", nil)
   327  	c.Assert(err, jc.ErrorIsNil)
   328  	err = s.machines[1].SetStatus(state.StatusStopped, "foo", nil)
   329  	c.Assert(err, jc.ErrorIsNil)
   330  	err = s.machines[2].SetStatus(state.StatusError, "not really", nil)
   331  	c.Assert(err, jc.ErrorIsNil)
   332  
   333  	args := params.SetStatus{
   334  		Entities: []params.EntityStatus{
   335  			{Tag: s.machines[0].Tag().String(), Status: params.StatusError, Info: "not really",
   336  				Data: map[string]interface{}{"foo": "bar"}},
   337  			{Tag: s.machines[1].Tag().String(), Status: params.StatusStopped, Info: "foobar"},
   338  			{Tag: s.machines[2].Tag().String(), Status: params.StatusStarted, Info: "again"},
   339  			{Tag: "machine-42", Status: params.StatusStarted, Info: "blah"},
   340  			{Tag: "unit-foo-0", Status: params.StatusStopped, Info: "foobar"},
   341  			{Tag: "service-bar", Status: params.StatusStopped, Info: "foobar"},
   342  		}}
   343  	result, err := s.provisioner.SetStatus(args)
   344  	c.Assert(err, jc.ErrorIsNil)
   345  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   346  		Results: []params.ErrorResult{
   347  			{nil},
   348  			{nil},
   349  			{nil},
   350  			{apiservertesting.NotFoundError("machine 42")},
   351  			{apiservertesting.ErrUnauthorized},
   352  			{apiservertesting.ErrUnauthorized},
   353  		},
   354  	})
   355  
   356  	// Verify the changes.
   357  	s.assertStatus(c, 0, state.StatusError, "not really", map[string]interface{}{"foo": "bar"})
   358  	s.assertStatus(c, 1, state.StatusStopped, "foobar", map[string]interface{}{})
   359  	s.assertStatus(c, 2, state.StatusStarted, "again", map[string]interface{}{})
   360  }
   361  
   362  func (s *withoutStateServerSuite) TestMachinesWithTransientErrors(c *gc.C) {
   363  	err := s.machines[0].SetStatus(state.StatusStarted, "blah", nil)
   364  	c.Assert(err, jc.ErrorIsNil)
   365  	err = s.machines[1].SetStatus(state.StatusError, "transient error",
   366  		map[string]interface{}{"transient": true, "foo": "bar"})
   367  	c.Assert(err, jc.ErrorIsNil)
   368  	err = s.machines[2].SetStatus(state.StatusError, "error", map[string]interface{}{"transient": false})
   369  	c.Assert(err, jc.ErrorIsNil)
   370  	err = s.machines[3].SetStatus(state.StatusError, "error", nil)
   371  	c.Assert(err, jc.ErrorIsNil)
   372  	// Machine 4 is provisioned but error not reset yet.
   373  	err = s.machines[4].SetStatus(state.StatusError, "transient error",
   374  		map[string]interface{}{"transient": true, "foo": "bar"})
   375  	c.Assert(err, jc.ErrorIsNil)
   376  	hwChars := instance.MustParseHardware("arch=i386", "mem=4G")
   377  	err = s.machines[4].SetProvisioned("i-am", "fake_nonce", &hwChars)
   378  	c.Assert(err, jc.ErrorIsNil)
   379  
   380  	result, err := s.provisioner.MachinesWithTransientErrors()
   381  	c.Assert(err, jc.ErrorIsNil)
   382  	c.Assert(result, gc.DeepEquals, params.StatusResults{
   383  		Results: []params.StatusResult{
   384  			{Id: "1", Life: "alive", Status: "error", Info: "transient error",
   385  				Data: map[string]interface{}{"transient": true, "foo": "bar"}},
   386  		},
   387  	})
   388  }
   389  
   390  func (s *withoutStateServerSuite) TestMachinesWithTransientErrorsPermission(c *gc.C) {
   391  	// Machines where there's permission issues are omitted.
   392  	anAuthorizer := s.authorizer
   393  	anAuthorizer.EnvironManager = false
   394  	anAuthorizer.Tag = names.NewMachineTag("1")
   395  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources,
   396  		anAuthorizer)
   397  	err = s.machines[0].SetStatus(state.StatusStarted, "blah", nil)
   398  	c.Assert(err, jc.ErrorIsNil)
   399  	err = s.machines[1].SetStatus(state.StatusError, "transient error",
   400  		map[string]interface{}{"transient": true, "foo": "bar"})
   401  	c.Assert(err, jc.ErrorIsNil)
   402  	err = s.machines[2].SetStatus(state.StatusError, "error", map[string]interface{}{"transient": false})
   403  	c.Assert(err, jc.ErrorIsNil)
   404  	err = s.machines[3].SetStatus(state.StatusError, "error", nil)
   405  	c.Assert(err, jc.ErrorIsNil)
   406  
   407  	result, err := aProvisioner.MachinesWithTransientErrors()
   408  	c.Assert(err, jc.ErrorIsNil)
   409  	c.Assert(result, gc.DeepEquals, params.StatusResults{
   410  		Results: []params.StatusResult{
   411  			{Id: "1", Life: "alive", Status: "error", Info: "transient error",
   412  				Data: map[string]interface{}{"transient": true, "foo": "bar"}},
   413  		},
   414  	})
   415  }
   416  
   417  func (s *withoutStateServerSuite) TestEnsureDead(c *gc.C) {
   418  	err := s.machines[1].EnsureDead()
   419  	c.Assert(err, jc.ErrorIsNil)
   420  	s.assertLife(c, 0, state.Alive)
   421  	s.assertLife(c, 1, state.Dead)
   422  	s.assertLife(c, 2, state.Alive)
   423  
   424  	args := params.Entities{Entities: []params.Entity{
   425  		{Tag: s.machines[0].Tag().String()},
   426  		{Tag: s.machines[1].Tag().String()},
   427  		{Tag: s.machines[2].Tag().String()},
   428  		{Tag: "machine-42"},
   429  		{Tag: "unit-foo-0"},
   430  		{Tag: "service-bar"},
   431  	}}
   432  	result, err := s.provisioner.EnsureDead(args)
   433  	c.Assert(err, jc.ErrorIsNil)
   434  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   435  		Results: []params.ErrorResult{
   436  			{nil},
   437  			{nil},
   438  			{nil},
   439  			{apiservertesting.NotFoundError("machine 42")},
   440  			{apiservertesting.ErrUnauthorized},
   441  			{apiservertesting.ErrUnauthorized},
   442  		},
   443  	})
   444  
   445  	// Verify the changes.
   446  	s.assertLife(c, 0, state.Dead)
   447  	s.assertLife(c, 1, state.Dead)
   448  	s.assertLife(c, 2, state.Dead)
   449  }
   450  
   451  func (s *withoutStateServerSuite) assertLife(c *gc.C, index int, expectLife state.Life) {
   452  	err := s.machines[index].Refresh()
   453  	c.Assert(err, jc.ErrorIsNil)
   454  	c.Assert(s.machines[index].Life(), gc.Equals, expectLife)
   455  }
   456  
   457  func (s *withoutStateServerSuite) assertStatus(c *gc.C, index int, expectStatus state.Status, expectInfo string,
   458  	expectData map[string]interface{}) {
   459  
   460  	statusInfo, err := s.machines[index].Status()
   461  	c.Assert(err, jc.ErrorIsNil)
   462  	c.Assert(statusInfo.Status, gc.Equals, expectStatus)
   463  	c.Assert(statusInfo.Message, gc.Equals, expectInfo)
   464  	c.Assert(statusInfo.Data, gc.DeepEquals, expectData)
   465  }
   466  
   467  func (s *withoutStateServerSuite) TestWatchContainers(c *gc.C) {
   468  	c.Assert(s.resources.Count(), gc.Equals, 0)
   469  
   470  	args := params.WatchContainers{Params: []params.WatchContainer{
   471  		{MachineTag: s.machines[0].Tag().String(), ContainerType: string(instance.LXC)},
   472  		{MachineTag: s.machines[1].Tag().String(), ContainerType: string(instance.KVM)},
   473  		{MachineTag: "machine-42", ContainerType: ""},
   474  		{MachineTag: "unit-foo-0", ContainerType: ""},
   475  		{MachineTag: "service-bar", ContainerType: ""},
   476  	}}
   477  	result, err := s.provisioner.WatchContainers(args)
   478  	c.Assert(err, jc.ErrorIsNil)
   479  	c.Assert(result, gc.DeepEquals, params.StringsWatchResults{
   480  		Results: []params.StringsWatchResult{
   481  			{StringsWatcherId: "1", Changes: []string{}},
   482  			{StringsWatcherId: "2", Changes: []string{}},
   483  			{Error: apiservertesting.NotFoundError("machine 42")},
   484  			{Error: apiservertesting.ErrUnauthorized},
   485  			{Error: apiservertesting.ErrUnauthorized},
   486  		},
   487  	})
   488  
   489  	// Verify the resources were registered and stop them when done.
   490  	c.Assert(s.resources.Count(), gc.Equals, 2)
   491  	m0Watcher := s.resources.Get("1")
   492  	defer statetesting.AssertStop(c, m0Watcher)
   493  	m1Watcher := s.resources.Get("2")
   494  	defer statetesting.AssertStop(c, m1Watcher)
   495  
   496  	// Check that the Watch has consumed the initial event ("returned"
   497  	// in the Watch call)
   498  	wc0 := statetesting.NewStringsWatcherC(c, s.State, m0Watcher.(state.StringsWatcher))
   499  	wc0.AssertNoChange()
   500  	wc1 := statetesting.NewStringsWatcherC(c, s.State, m1Watcher.(state.StringsWatcher))
   501  	wc1.AssertNoChange()
   502  }
   503  
   504  func (s *withoutStateServerSuite) TestWatchAllContainers(c *gc.C) {
   505  	c.Assert(s.resources.Count(), gc.Equals, 0)
   506  
   507  	args := params.WatchContainers{Params: []params.WatchContainer{
   508  		{MachineTag: s.machines[0].Tag().String()},
   509  		{MachineTag: s.machines[1].Tag().String()},
   510  		{MachineTag: "machine-42"},
   511  		{MachineTag: "unit-foo-0"},
   512  		{MachineTag: "service-bar"},
   513  	}}
   514  	result, err := s.provisioner.WatchAllContainers(args)
   515  	c.Assert(err, jc.ErrorIsNil)
   516  	c.Assert(result, gc.DeepEquals, params.StringsWatchResults{
   517  		Results: []params.StringsWatchResult{
   518  			{StringsWatcherId: "1", Changes: []string{}},
   519  			{StringsWatcherId: "2", Changes: []string{}},
   520  			{Error: apiservertesting.NotFoundError("machine 42")},
   521  			{Error: apiservertesting.ErrUnauthorized},
   522  			{Error: apiservertesting.ErrUnauthorized},
   523  		},
   524  	})
   525  
   526  	// Verify the resources were registered and stop them when done.
   527  	c.Assert(s.resources.Count(), gc.Equals, 2)
   528  	m0Watcher := s.resources.Get("1")
   529  	defer statetesting.AssertStop(c, m0Watcher)
   530  	m1Watcher := s.resources.Get("2")
   531  	defer statetesting.AssertStop(c, m1Watcher)
   532  
   533  	// Check that the Watch has consumed the initial event ("returned"
   534  	// in the Watch call)
   535  	wc0 := statetesting.NewStringsWatcherC(c, s.State, m0Watcher.(state.StringsWatcher))
   536  	wc0.AssertNoChange()
   537  	wc1 := statetesting.NewStringsWatcherC(c, s.State, m1Watcher.(state.StringsWatcher))
   538  	wc1.AssertNoChange()
   539  }
   540  
   541  func (s *withoutStateServerSuite) TestEnvironConfigNonManager(c *gc.C) {
   542  	// Now test it with a non-environment manager and make sure
   543  	// the secret attributes are masked.
   544  	anAuthorizer := s.authorizer
   545  	anAuthorizer.Tag = names.NewMachineTag("1")
   546  	anAuthorizer.EnvironManager = false
   547  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources,
   548  		anAuthorizer)
   549  	c.Assert(err, jc.ErrorIsNil)
   550  	s.AssertEnvironConfig(c, aProvisioner, commontesting.NoSecrets)
   551  }
   552  
   553  func (s *withoutStateServerSuite) TestStatus(c *gc.C) {
   554  	err := s.machines[0].SetStatus(state.StatusStarted, "blah", nil)
   555  	c.Assert(err, jc.ErrorIsNil)
   556  	err = s.machines[1].SetStatus(state.StatusStopped, "foo", nil)
   557  	c.Assert(err, jc.ErrorIsNil)
   558  	err = s.machines[2].SetStatus(state.StatusError, "not really", map[string]interface{}{"foo": "bar"})
   559  	c.Assert(err, jc.ErrorIsNil)
   560  
   561  	args := params.Entities{Entities: []params.Entity{
   562  		{Tag: s.machines[0].Tag().String()},
   563  		{Tag: s.machines[1].Tag().String()},
   564  		{Tag: s.machines[2].Tag().String()},
   565  		{Tag: "machine-42"},
   566  		{Tag: "unit-foo-0"},
   567  		{Tag: "service-bar"},
   568  	}}
   569  	result, err := s.provisioner.Status(args)
   570  	c.Assert(err, jc.ErrorIsNil)
   571  	// Zero out the updated timestamps so we can easily check the results.
   572  	for i, statusResult := range result.Results {
   573  		r := statusResult
   574  		if r.Status != "" {
   575  			c.Assert(r.Since, gc.NotNil)
   576  		}
   577  		r.Since = nil
   578  		result.Results[i] = r
   579  	}
   580  	c.Assert(result, gc.DeepEquals, params.StatusResults{
   581  		Results: []params.StatusResult{
   582  			{Status: params.StatusStarted, Info: "blah", Data: map[string]interface{}{}},
   583  			{Status: params.StatusStopped, Info: "foo", Data: map[string]interface{}{}},
   584  			{Status: params.StatusError, Info: "not really", Data: map[string]interface{}{"foo": "bar"}},
   585  			{Error: apiservertesting.NotFoundError("machine 42")},
   586  			{Error: apiservertesting.ErrUnauthorized},
   587  			{Error: apiservertesting.ErrUnauthorized},
   588  		},
   589  	})
   590  }
   591  
   592  func (s *withoutStateServerSuite) TestSeries(c *gc.C) {
   593  	// Add a machine with different series.
   594  	foobarMachine, err := s.State.AddMachine("foobar", state.JobHostUnits)
   595  	c.Assert(err, jc.ErrorIsNil)
   596  
   597  	args := params.Entities{Entities: []params.Entity{
   598  		{Tag: s.machines[0].Tag().String()},
   599  		{Tag: foobarMachine.Tag().String()},
   600  		{Tag: s.machines[2].Tag().String()},
   601  		{Tag: "machine-42"},
   602  		{Tag: "unit-foo-0"},
   603  		{Tag: "service-bar"},
   604  	}}
   605  	result, err := s.provisioner.Series(args)
   606  	c.Assert(err, jc.ErrorIsNil)
   607  	c.Assert(result, gc.DeepEquals, params.StringResults{
   608  		Results: []params.StringResult{
   609  			{Result: s.machines[0].Series()},
   610  			{Result: foobarMachine.Series()},
   611  			{Result: s.machines[2].Series()},
   612  			{Error: apiservertesting.NotFoundError("machine 42")},
   613  			{Error: apiservertesting.ErrUnauthorized},
   614  			{Error: apiservertesting.ErrUnauthorized},
   615  		},
   616  	})
   617  }
   618  
   619  func (s *withoutStateServerSuite) TestDistributionGroup(c *gc.C) {
   620  	addUnits := func(name string, machines ...*state.Machine) (units []*state.Unit) {
   621  		svc := s.AddTestingService(c, name, s.AddTestingCharm(c, name))
   622  		for _, m := range machines {
   623  			unit, err := svc.AddUnit()
   624  			c.Assert(err, jc.ErrorIsNil)
   625  			err = unit.AssignToMachine(m)
   626  			c.Assert(err, jc.ErrorIsNil)
   627  			units = append(units, unit)
   628  		}
   629  		return units
   630  	}
   631  	setProvisioned := func(id string) {
   632  		m, err := s.State.Machine(id)
   633  		c.Assert(err, jc.ErrorIsNil)
   634  		err = m.SetProvisioned(instance.Id("machine-"+id+"-inst"), "nonce", nil)
   635  		c.Assert(err, jc.ErrorIsNil)
   636  	}
   637  
   638  	mysqlUnit := addUnits("mysql", s.machines[0], s.machines[3])[0]
   639  	wordpressUnits := addUnits("wordpress", s.machines[0], s.machines[1], s.machines[2])
   640  
   641  	// Unassign wordpress/1 from machine-1.
   642  	// The unit should not show up in the results.
   643  	err := wordpressUnits[1].UnassignFromMachine()
   644  	c.Assert(err, jc.ErrorIsNil)
   645  
   646  	// Provision machines 1, 2 and 3. Machine-0 remains
   647  	// unprovisioned, and machine-1 has no units, and so
   648  	// neither will show up in the results.
   649  	setProvisioned("1")
   650  	setProvisioned("2")
   651  	setProvisioned("3")
   652  
   653  	// Add a few state servers, provision two of them.
   654  	_, err = s.State.EnsureAvailability(3, constraints.Value{}, "quantal", nil)
   655  	c.Assert(err, jc.ErrorIsNil)
   656  	setProvisioned("5")
   657  	setProvisioned("7")
   658  
   659  	// Create a logging service, subordinate to mysql.
   660  	s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging"))
   661  	eps, err := s.State.InferEndpoints("mysql", "logging")
   662  	c.Assert(err, jc.ErrorIsNil)
   663  	rel, err := s.State.AddRelation(eps...)
   664  	c.Assert(err, jc.ErrorIsNil)
   665  	ru, err := rel.Unit(mysqlUnit)
   666  	c.Assert(err, jc.ErrorIsNil)
   667  	err = ru.EnterScope(nil)
   668  	c.Assert(err, jc.ErrorIsNil)
   669  
   670  	args := params.Entities{Entities: []params.Entity{
   671  		{Tag: s.machines[0].Tag().String()},
   672  		{Tag: s.machines[1].Tag().String()},
   673  		{Tag: s.machines[2].Tag().String()},
   674  		{Tag: s.machines[3].Tag().String()},
   675  		{Tag: "machine-5"},
   676  	}}
   677  	result, err := s.provisioner.DistributionGroup(args)
   678  	c.Assert(err, jc.ErrorIsNil)
   679  	c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{
   680  		Results: []params.DistributionGroupResult{
   681  			{Result: []instance.Id{"machine-2-inst", "machine-3-inst"}},
   682  			{Result: []instance.Id{}},
   683  			{Result: []instance.Id{"machine-2-inst"}},
   684  			{Result: []instance.Id{"machine-3-inst"}},
   685  			{Result: []instance.Id{"machine-5-inst", "machine-7-inst"}},
   686  		},
   687  	})
   688  }
   689  
   690  func (s *withoutStateServerSuite) TestDistributionGroupEnvironManagerAuth(c *gc.C) {
   691  	args := params.Entities{Entities: []params.Entity{
   692  		{Tag: "machine-0"},
   693  		{Tag: "machine-42"},
   694  		{Tag: "machine-0-lxc-99"},
   695  		{Tag: "unit-foo-0"},
   696  		{Tag: "service-bar"},
   697  	}}
   698  	result, err := s.provisioner.DistributionGroup(args)
   699  	c.Assert(err, jc.ErrorIsNil)
   700  	c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{
   701  		Results: []params.DistributionGroupResult{
   702  			// environ manager may access any top-level machines.
   703  			{Result: []instance.Id{}},
   704  			{Error: apiservertesting.NotFoundError("machine 42")},
   705  			// only a machine agent for the container or its
   706  			// parent may access it.
   707  			{Error: apiservertesting.ErrUnauthorized},
   708  			// non-machines always unauthorized
   709  			{Error: apiservertesting.ErrUnauthorized},
   710  			{Error: apiservertesting.ErrUnauthorized},
   711  		},
   712  	})
   713  }
   714  
   715  func (s *withoutStateServerSuite) TestDistributionGroupMachineAgentAuth(c *gc.C) {
   716  	anAuthorizer := s.authorizer
   717  	anAuthorizer.Tag = names.NewMachineTag("1")
   718  	anAuthorizer.EnvironManager = false
   719  	provisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   720  	c.Check(err, jc.ErrorIsNil)
   721  	args := params.Entities{Entities: []params.Entity{
   722  		{Tag: "machine-0"},
   723  		{Tag: "machine-1"},
   724  		{Tag: "machine-42"},
   725  		{Tag: "machine-0-lxc-99"},
   726  		{Tag: "machine-1-lxc-99"},
   727  		{Tag: "machine-1-lxc-99-lxc-100"},
   728  	}}
   729  	result, err := provisioner.DistributionGroup(args)
   730  	c.Assert(err, jc.ErrorIsNil)
   731  	c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{
   732  		Results: []params.DistributionGroupResult{
   733  			{Error: apiservertesting.ErrUnauthorized},
   734  			{Result: []instance.Id{}},
   735  			{Error: apiservertesting.ErrUnauthorized},
   736  			// only a machine agent for the container or its
   737  			// parent may access it.
   738  			{Error: apiservertesting.ErrUnauthorized},
   739  			{Error: apiservertesting.NotFoundError("machine 1/lxc/99")},
   740  			{Error: apiservertesting.ErrUnauthorized},
   741  		},
   742  	})
   743  }
   744  
   745  func (s *withoutStateServerSuite) TestProvisioningInfo(c *gc.C) {
   746  	registry.RegisterProvider("static", &storagedummy.StorageProvider{IsDynamic: false})
   747  	defer registry.RegisterProvider("static", nil)
   748  	registry.RegisterEnvironStorageProviders("dummy", "static")
   749  
   750  	pm := poolmanager.New(state.NewStateSettings(s.State))
   751  	_, err := pm.Create("static-pool", "static", map[string]interface{}{"foo": "bar"})
   752  	c.Assert(err, jc.ErrorIsNil)
   753  
   754  	cons := constraints.MustParse("cpu-cores=123 mem=8G networks=^net3,^net4")
   755  	template := state.MachineTemplate{
   756  		Series:            "quantal",
   757  		Jobs:              []state.MachineJob{state.JobHostUnits},
   758  		Constraints:       cons,
   759  		Placement:         "valid",
   760  		RequestedNetworks: []string{"net1", "net2"},
   761  		Volumes: []state.MachineVolumeParams{
   762  			{Volume: state.VolumeParams{Size: 1000, Pool: "static-pool"}},
   763  			{Volume: state.VolumeParams{Size: 2000, Pool: "static-pool"}},
   764  		},
   765  	}
   766  	placementMachine, err := s.State.AddOneMachine(template)
   767  	c.Assert(err, jc.ErrorIsNil)
   768  
   769  	args := params.Entities{Entities: []params.Entity{
   770  		{Tag: s.machines[0].Tag().String()},
   771  		{Tag: placementMachine.Tag().String()},
   772  		{Tag: "machine-42"},
   773  		{Tag: "unit-foo-0"},
   774  		{Tag: "service-bar"},
   775  	}}
   776  	result, err := s.provisioner.ProvisioningInfo(args)
   777  	c.Assert(err, jc.ErrorIsNil)
   778  
   779  	expected := params.ProvisioningInfoResults{
   780  		Results: []params.ProvisioningInfoResult{
   781  			{Result: &params.ProvisioningInfo{
   782  				Series:   "quantal",
   783  				Networks: []string{},
   784  				Jobs:     []multiwatcher.MachineJob{multiwatcher.JobHostUnits},
   785  				Tags: map[string]string{
   786  					tags.JujuEnv: coretesting.EnvironmentTag.Id(),
   787  				},
   788  			}},
   789  			{Result: &params.ProvisioningInfo{
   790  				Series:      "quantal",
   791  				Constraints: template.Constraints,
   792  				Placement:   template.Placement,
   793  				Networks:    template.RequestedNetworks,
   794  				Jobs:        []multiwatcher.MachineJob{multiwatcher.JobHostUnits},
   795  				Tags: map[string]string{
   796  					tags.JujuEnv: coretesting.EnvironmentTag.Id(),
   797  				},
   798  				Volumes: []params.VolumeParams{{
   799  					VolumeTag:  "volume-0",
   800  					Size:       1000,
   801  					Provider:   "static",
   802  					Attributes: map[string]interface{}{"foo": "bar"},
   803  					Tags: map[string]string{
   804  						tags.JujuEnv: coretesting.EnvironmentTag.Id(),
   805  					},
   806  					Attachment: &params.VolumeAttachmentParams{
   807  						MachineTag: placementMachine.Tag().String(),
   808  						VolumeTag:  "volume-0",
   809  						Provider:   "static",
   810  					},
   811  				}, {
   812  					VolumeTag:  "volume-1",
   813  					Size:       2000,
   814  					Provider:   "static",
   815  					Attributes: map[string]interface{}{"foo": "bar"},
   816  					Tags: map[string]string{
   817  						tags.JujuEnv: coretesting.EnvironmentTag.Id(),
   818  					},
   819  					Attachment: &params.VolumeAttachmentParams{
   820  						MachineTag: placementMachine.Tag().String(),
   821  						VolumeTag:  "volume-1",
   822  						Provider:   "static",
   823  					},
   824  				}},
   825  			}},
   826  			{Error: apiservertesting.NotFoundError("machine 42")},
   827  			{Error: apiservertesting.ErrUnauthorized},
   828  			{Error: apiservertesting.ErrUnauthorized},
   829  		},
   830  	}
   831  	// The order of volumes is not predictable, so we make sure we compare the right ones. This only
   832  	// applies to Results[1] since it is the only result to contain volumes.
   833  	if expected.Results[1].Result.Volumes[0].VolumeTag != result.Results[1].Result.Volumes[0].VolumeTag {
   834  		vols := expected.Results[1].Result.Volumes
   835  		vols[0], vols[1] = vols[1], vols[0]
   836  	}
   837  	c.Assert(result, jc.DeepEquals, expected)
   838  }
   839  
   840  func (s *withoutStateServerSuite) TestStorageProviderFallbackToType(c *gc.C) {
   841  	registry.RegisterProvider("dynamic", &storagedummy.StorageProvider{IsDynamic: true})
   842  	defer registry.RegisterProvider("dynamic", nil)
   843  	registry.RegisterProvider("static", &storagedummy.StorageProvider{IsDynamic: false})
   844  	defer registry.RegisterProvider("static", nil)
   845  	registry.RegisterEnvironStorageProviders("dummy", "dynamic", "static")
   846  
   847  	template := state.MachineTemplate{
   848  		Series:            "quantal",
   849  		Jobs:              []state.MachineJob{state.JobHostUnits},
   850  		Placement:         "valid",
   851  		RequestedNetworks: []string{"net1", "net2"},
   852  		Volumes: []state.MachineVolumeParams{
   853  			{Volume: state.VolumeParams{Size: 1000, Pool: "dynamic"}},
   854  			{Volume: state.VolumeParams{Size: 1000, Pool: "static"}},
   855  		},
   856  	}
   857  	placementMachine, err := s.State.AddOneMachine(template)
   858  	c.Assert(err, jc.ErrorIsNil)
   859  
   860  	args := params.Entities{Entities: []params.Entity{
   861  		{Tag: placementMachine.Tag().String()},
   862  	}}
   863  	result, err := s.provisioner.ProvisioningInfo(args)
   864  	c.Assert(err, jc.ErrorIsNil)
   865  
   866  	c.Assert(result, jc.DeepEquals, params.ProvisioningInfoResults{
   867  		Results: []params.ProvisioningInfoResult{
   868  			{Result: &params.ProvisioningInfo{
   869  				Series:      "quantal",
   870  				Constraints: template.Constraints,
   871  				Placement:   template.Placement,
   872  				Networks:    template.RequestedNetworks,
   873  				Jobs:        []multiwatcher.MachineJob{multiwatcher.JobHostUnits},
   874  				Tags: map[string]string{
   875  					tags.JujuEnv: coretesting.EnvironmentTag.Id(),
   876  				},
   877  				Volumes: []params.VolumeParams{{
   878  					VolumeTag:  "volume-1",
   879  					Size:       1000,
   880  					Provider:   "static",
   881  					Attributes: nil,
   882  					Tags: map[string]string{
   883  						tags.JujuEnv: coretesting.EnvironmentTag.Id(),
   884  					},
   885  					Attachment: &params.VolumeAttachmentParams{
   886  						MachineTag: placementMachine.Tag().String(),
   887  						VolumeTag:  "volume-1",
   888  						Provider:   "static",
   889  					},
   890  				}},
   891  			}},
   892  		},
   893  	})
   894  }
   895  
   896  func (s *withoutStateServerSuite) TestProvisioningInfoPermissions(c *gc.C) {
   897  	// Login as a machine agent for machine 0.
   898  	anAuthorizer := s.authorizer
   899  	anAuthorizer.EnvironManager = false
   900  	anAuthorizer.Tag = s.machines[0].Tag()
   901  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   902  	c.Assert(err, jc.ErrorIsNil)
   903  	c.Assert(aProvisioner, gc.NotNil)
   904  
   905  	args := params.Entities{Entities: []params.Entity{
   906  		{Tag: s.machines[0].Tag().String()},
   907  		{Tag: s.machines[0].Tag().String() + "-lxc-0"},
   908  		{Tag: "machine-42"},
   909  		{Tag: s.machines[1].Tag().String()},
   910  		{Tag: "service-bar"},
   911  	}}
   912  
   913  	// Only machine 0 and containers therein can be accessed.
   914  	results, err := aProvisioner.ProvisioningInfo(args)
   915  	c.Assert(results, jc.DeepEquals, params.ProvisioningInfoResults{
   916  		Results: []params.ProvisioningInfoResult{
   917  			{Result: &params.ProvisioningInfo{
   918  				Series:   "quantal",
   919  				Networks: []string{},
   920  				Jobs:     []multiwatcher.MachineJob{multiwatcher.JobHostUnits},
   921  				Tags: map[string]string{
   922  					tags.JujuEnv: coretesting.EnvironmentTag.Id(),
   923  				},
   924  			}},
   925  			{Error: apiservertesting.NotFoundError("machine 0/lxc/0")},
   926  			{Error: apiservertesting.ErrUnauthorized},
   927  			{Error: apiservertesting.ErrUnauthorized},
   928  			{Error: apiservertesting.ErrUnauthorized},
   929  		},
   930  	})
   931  }
   932  
   933  func (s *withoutStateServerSuite) TestConstraints(c *gc.C) {
   934  	// Add a machine with some constraints.
   935  	cons := constraints.MustParse("cpu-cores=123", "mem=8G", "networks=net3,^net4")
   936  	template := state.MachineTemplate{
   937  		Series:      "quantal",
   938  		Jobs:        []state.MachineJob{state.JobHostUnits},
   939  		Constraints: cons,
   940  	}
   941  	consMachine, err := s.State.AddOneMachine(template)
   942  	c.Assert(err, jc.ErrorIsNil)
   943  
   944  	machine0Constraints, err := s.machines[0].Constraints()
   945  	c.Assert(err, jc.ErrorIsNil)
   946  
   947  	args := params.Entities{Entities: []params.Entity{
   948  		{Tag: s.machines[0].Tag().String()},
   949  		{Tag: consMachine.Tag().String()},
   950  		{Tag: "machine-42"},
   951  		{Tag: "unit-foo-0"},
   952  		{Tag: "service-bar"},
   953  	}}
   954  	result, err := s.provisioner.Constraints(args)
   955  	c.Assert(err, jc.ErrorIsNil)
   956  	c.Assert(result, gc.DeepEquals, params.ConstraintsResults{
   957  		Results: []params.ConstraintsResult{
   958  			{Constraints: machine0Constraints},
   959  			{Constraints: template.Constraints},
   960  			{Error: apiservertesting.NotFoundError("machine 42")},
   961  			{Error: apiservertesting.ErrUnauthorized},
   962  			{Error: apiservertesting.ErrUnauthorized},
   963  		},
   964  	})
   965  }
   966  
   967  func (s *withoutStateServerSuite) TestRequestedNetworks(c *gc.C) {
   968  	// Add a machine with some requested networks.
   969  	template := state.MachineTemplate{
   970  		Series:            "quantal",
   971  		Jobs:              []state.MachineJob{state.JobHostUnits},
   972  		RequestedNetworks: []string{"net1", "net2"},
   973  	}
   974  	netsMachine, err := s.State.AddOneMachine(template)
   975  	c.Assert(err, jc.ErrorIsNil)
   976  
   977  	networksMachine0, err := s.machines[0].RequestedNetworks()
   978  	c.Assert(err, jc.ErrorIsNil)
   979  
   980  	args := params.Entities{Entities: []params.Entity{
   981  		{Tag: s.machines[0].Tag().String()},
   982  		{Tag: netsMachine.Tag().String()},
   983  		{Tag: "machine-42"},
   984  		{Tag: "unit-foo-0"},
   985  		{Tag: "service-bar"},
   986  	}}
   987  	result, err := s.provisioner.RequestedNetworks(args)
   988  	c.Assert(err, jc.ErrorIsNil)
   989  	c.Assert(result, gc.DeepEquals, params.RequestedNetworksResults{
   990  		Results: []params.RequestedNetworkResult{
   991  			{
   992  				Networks: networksMachine0,
   993  			},
   994  			{
   995  				Networks: template.RequestedNetworks,
   996  			},
   997  			{Error: apiservertesting.NotFoundError("machine 42")},
   998  			{Error: apiservertesting.ErrUnauthorized},
   999  			{Error: apiservertesting.ErrUnauthorized},
  1000  		},
  1001  	})
  1002  }
  1003  
  1004  func (s *withoutStateServerSuite) TestSetProvisioned(c *gc.C) {
  1005  	// Provision machine 0 first.
  1006  	hwChars := instance.MustParseHardware("arch=i386", "mem=4G")
  1007  	err := s.machines[0].SetProvisioned("i-am", "fake_nonce", &hwChars)
  1008  	c.Assert(err, jc.ErrorIsNil)
  1009  
  1010  	args := params.SetProvisioned{Machines: []params.MachineSetProvisioned{
  1011  		{Tag: s.machines[0].Tag().String(), InstanceId: "i-was", Nonce: "fake_nonce", Characteristics: nil},
  1012  		{Tag: s.machines[1].Tag().String(), InstanceId: "i-will", Nonce: "fake_nonce", Characteristics: &hwChars},
  1013  		{Tag: s.machines[2].Tag().String(), InstanceId: "i-am-too", Nonce: "fake", Characteristics: nil},
  1014  		{Tag: "machine-42", InstanceId: "", Nonce: "", Characteristics: nil},
  1015  		{Tag: "unit-foo-0", InstanceId: "", Nonce: "", Characteristics: nil},
  1016  		{Tag: "service-bar", InstanceId: "", Nonce: "", Characteristics: nil},
  1017  	}}
  1018  	result, err := s.provisioner.SetProvisioned(args)
  1019  	c.Assert(err, jc.ErrorIsNil)
  1020  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
  1021  		Results: []params.ErrorResult{
  1022  			{&params.Error{
  1023  				Message: `cannot set instance data for machine "0": already set`,
  1024  			}},
  1025  			{nil},
  1026  			{nil},
  1027  			{apiservertesting.NotFoundError("machine 42")},
  1028  			{apiservertesting.ErrUnauthorized},
  1029  			{apiservertesting.ErrUnauthorized},
  1030  		},
  1031  	})
  1032  
  1033  	// Verify machine 1 and 2 were provisioned.
  1034  	c.Assert(s.machines[1].Refresh(), gc.IsNil)
  1035  	c.Assert(s.machines[2].Refresh(), gc.IsNil)
  1036  
  1037  	instanceId, err := s.machines[1].InstanceId()
  1038  	c.Assert(err, jc.ErrorIsNil)
  1039  	c.Check(instanceId, gc.Equals, instance.Id("i-will"))
  1040  	instanceId, err = s.machines[2].InstanceId()
  1041  	c.Assert(err, jc.ErrorIsNil)
  1042  	c.Check(instanceId, gc.Equals, instance.Id("i-am-too"))
  1043  	c.Check(s.machines[1].CheckProvisioned("fake_nonce"), jc.IsTrue)
  1044  	c.Check(s.machines[2].CheckProvisioned("fake"), jc.IsTrue)
  1045  	gotHardware, err := s.machines[1].HardwareCharacteristics()
  1046  	c.Assert(err, jc.ErrorIsNil)
  1047  	c.Check(gotHardware, gc.DeepEquals, &hwChars)
  1048  }
  1049  
  1050  func (s *withoutStateServerSuite) TestSetInstanceInfo(c *gc.C) {
  1051  	registry.RegisterProvider("static", &storagedummy.StorageProvider{IsDynamic: false})
  1052  	defer registry.RegisterProvider("static", nil)
  1053  	registry.RegisterEnvironStorageProviders("dummy", "static")
  1054  
  1055  	pm := poolmanager.New(state.NewStateSettings(s.State))
  1056  	_, err := pm.Create("static-pool", "static", map[string]interface{}{"foo": "bar"})
  1057  	c.Assert(err, jc.ErrorIsNil)
  1058  	err = s.State.UpdateEnvironConfig(map[string]interface{}{
  1059  		"storage-default-block-source": "static-pool",
  1060  	}, nil, nil)
  1061  	c.Assert(err, jc.ErrorIsNil)
  1062  
  1063  	// Provision machine 0 first.
  1064  	hwChars := instance.MustParseHardware("arch=i386", "mem=4G")
  1065  	err = s.machines[0].SetInstanceInfo("i-am", "fake_nonce", &hwChars, nil, nil, nil, nil)
  1066  	c.Assert(err, jc.ErrorIsNil)
  1067  
  1068  	volumesMachine, err := s.State.AddOneMachine(state.MachineTemplate{
  1069  		Series: "quantal",
  1070  		Jobs:   []state.MachineJob{state.JobHostUnits},
  1071  		Volumes: []state.MachineVolumeParams{{
  1072  			Volume: state.VolumeParams{Size: 1000},
  1073  		}},
  1074  	})
  1075  	c.Assert(err, jc.ErrorIsNil)
  1076  
  1077  	networks := []params.Network{{
  1078  		Tag:        "network-net1",
  1079  		ProviderId: "net1",
  1080  		CIDR:       "0.1.2.0/24",
  1081  		VLANTag:    0,
  1082  	}, {
  1083  		Tag:        "network-vlan42",
  1084  		ProviderId: "vlan42",
  1085  		CIDR:       "0.2.2.0/24",
  1086  		VLANTag:    42,
  1087  	}, {
  1088  		Tag:        "network-vlan69",
  1089  		ProviderId: "vlan69",
  1090  		CIDR:       "0.3.2.0/24",
  1091  		VLANTag:    69,
  1092  	}, {
  1093  		Tag:        "network-vlan42", // duplicated; ignored
  1094  		ProviderId: "vlan42",
  1095  		CIDR:       "0.2.2.0/24",
  1096  		VLANTag:    42,
  1097  	}}
  1098  	ifaces := []params.NetworkInterface{{
  1099  		MACAddress:    "aa:bb:cc:dd:ee:f0",
  1100  		NetworkTag:    "network-net1",
  1101  		InterfaceName: "eth0",
  1102  		IsVirtual:     false,
  1103  	}, {
  1104  		MACAddress:    "aa:bb:cc:dd:ee:f1",
  1105  		NetworkTag:    "network-net1",
  1106  		InterfaceName: "eth1",
  1107  		IsVirtual:     false,
  1108  	}, {
  1109  		MACAddress:    "aa:bb:cc:dd:ee:f1",
  1110  		NetworkTag:    "network-vlan42",
  1111  		InterfaceName: "eth1.42",
  1112  		IsVirtual:     true,
  1113  	}, {
  1114  		MACAddress:    "aa:bb:cc:dd:ee:f0",
  1115  		NetworkTag:    "network-vlan69",
  1116  		InterfaceName: "eth0.69",
  1117  		IsVirtual:     true,
  1118  		Disabled:      true,
  1119  	}, {
  1120  		MACAddress:    "aa:bb:cc:dd:ee:f1", // duplicated mac+net; ignored
  1121  		NetworkTag:    "network-vlan42",
  1122  		InterfaceName: "eth2",
  1123  		IsVirtual:     true,
  1124  	}, {
  1125  		MACAddress:    "aa:bb:cc:dd:ee:f2",
  1126  		NetworkTag:    "network-net1",
  1127  		InterfaceName: "eth1", // duplicated name+machine id; ignored for machine 1.
  1128  		IsVirtual:     false,
  1129  	}}
  1130  	args := params.InstancesInfo{Machines: []params.InstanceInfo{{
  1131  		Tag:        s.machines[0].Tag().String(),
  1132  		InstanceId: "i-was",
  1133  		Nonce:      "fake_nonce",
  1134  	}, {
  1135  		Tag:             s.machines[1].Tag().String(),
  1136  		InstanceId:      "i-will",
  1137  		Nonce:           "fake_nonce",
  1138  		Characteristics: &hwChars,
  1139  		Networks:        networks,
  1140  		Interfaces:      ifaces,
  1141  	}, {
  1142  		Tag:             s.machines[2].Tag().String(),
  1143  		InstanceId:      "i-am-too",
  1144  		Nonce:           "fake",
  1145  		Characteristics: nil,
  1146  		Networks:        networks,
  1147  		Interfaces:      ifaces,
  1148  	}, {
  1149  		Tag:        volumesMachine.Tag().String(),
  1150  		InstanceId: "i-am-also",
  1151  		Nonce:      "fake",
  1152  		Volumes: []params.Volume{{
  1153  			VolumeTag: "volume-0",
  1154  			Info: params.VolumeInfo{
  1155  				VolumeId: "vol-0",
  1156  				Size:     1234,
  1157  			},
  1158  		}},
  1159  		VolumeAttachments: map[string]params.VolumeAttachmentInfo{
  1160  			"volume-0": {
  1161  				DeviceName: "sda",
  1162  			},
  1163  		},
  1164  	},
  1165  		{Tag: "machine-42"},
  1166  		{Tag: "unit-foo-0"},
  1167  		{Tag: "service-bar"},
  1168  	}}
  1169  	result, err := s.provisioner.SetInstanceInfo(args)
  1170  	c.Assert(err, jc.ErrorIsNil)
  1171  	c.Assert(result, jc.DeepEquals, params.ErrorResults{
  1172  		Results: []params.ErrorResult{
  1173  			{&params.Error{
  1174  				Message: `cannot record provisioning info for "i-was": cannot set instance data for machine "0": already set`,
  1175  			}},
  1176  			{nil},
  1177  			{nil},
  1178  			{nil},
  1179  			{apiservertesting.NotFoundError("machine 42")},
  1180  			{apiservertesting.ErrUnauthorized},
  1181  			{apiservertesting.ErrUnauthorized},
  1182  		},
  1183  	})
  1184  
  1185  	// Verify machine 1 and 2 were provisioned.
  1186  	c.Assert(s.machines[1].Refresh(), gc.IsNil)
  1187  	c.Assert(s.machines[2].Refresh(), gc.IsNil)
  1188  
  1189  	instanceId, err := s.machines[1].InstanceId()
  1190  	c.Assert(err, jc.ErrorIsNil)
  1191  	c.Check(instanceId, gc.Equals, instance.Id("i-will"))
  1192  	instanceId, err = s.machines[2].InstanceId()
  1193  	c.Assert(err, jc.ErrorIsNil)
  1194  	c.Check(instanceId, gc.Equals, instance.Id("i-am-too"))
  1195  	c.Check(s.machines[1].CheckProvisioned("fake_nonce"), jc.IsTrue)
  1196  	c.Check(s.machines[2].CheckProvisioned("fake"), jc.IsTrue)
  1197  	gotHardware, err := s.machines[1].HardwareCharacteristics()
  1198  	c.Assert(err, jc.ErrorIsNil)
  1199  	c.Check(gotHardware, gc.DeepEquals, &hwChars)
  1200  	ifacesMachine1, err := s.machines[1].NetworkInterfaces()
  1201  	c.Assert(err, jc.ErrorIsNil)
  1202  	c.Assert(ifacesMachine1, gc.HasLen, 4)
  1203  	actual := make([]params.NetworkInterface, len(ifacesMachine1))
  1204  	for i, iface := range ifacesMachine1 {
  1205  		actual[i].InterfaceName = iface.InterfaceName()
  1206  		actual[i].NetworkTag = iface.NetworkTag().String()
  1207  		actual[i].MACAddress = iface.MACAddress()
  1208  		actual[i].IsVirtual = iface.IsVirtual()
  1209  		actual[i].Disabled = iface.IsDisabled()
  1210  		c.Check(iface.MachineId(), gc.Equals, s.machines[1].Id())
  1211  		c.Check(iface.MachineTag(), gc.Equals, s.machines[1].Tag())
  1212  	}
  1213  	c.Assert(actual, jc.SameContents, ifaces[:4])
  1214  	ifacesMachine2, err := s.machines[2].NetworkInterfaces()
  1215  	c.Assert(err, jc.ErrorIsNil)
  1216  	c.Assert(ifacesMachine2, gc.HasLen, 1)
  1217  	c.Assert(ifacesMachine2[0].InterfaceName(), gc.Equals, ifaces[5].InterfaceName)
  1218  	c.Assert(ifacesMachine2[0].MACAddress(), gc.Equals, ifaces[5].MACAddress)
  1219  	c.Assert(ifacesMachine2[0].NetworkTag().String(), gc.Equals, ifaces[5].NetworkTag)
  1220  	c.Assert(ifacesMachine2[0].MachineId(), gc.Equals, s.machines[2].Id())
  1221  	for i := range networks {
  1222  		if i == 3 {
  1223  			// Last one was ignored, so don't check.
  1224  			break
  1225  		}
  1226  		tag, err := names.ParseNetworkTag(networks[i].Tag)
  1227  		c.Assert(err, jc.ErrorIsNil)
  1228  		networkName := tag.Id()
  1229  		nw, err := s.State.Network(networkName)
  1230  		c.Assert(err, jc.ErrorIsNil)
  1231  		c.Check(nw.Name(), gc.Equals, networkName)
  1232  		c.Check(nw.ProviderId(), gc.Equals, network.Id(networks[i].ProviderId))
  1233  		c.Check(nw.Tag().String(), gc.Equals, networks[i].Tag)
  1234  		c.Check(nw.VLANTag(), gc.Equals, networks[i].VLANTag)
  1235  		c.Check(nw.CIDR(), gc.Equals, networks[i].CIDR)
  1236  	}
  1237  
  1238  	// Verify the machine with requested volumes was provisioned, and the
  1239  	// volume information recorded in state.
  1240  	volumeAttachments, err := s.State.MachineVolumeAttachments(volumesMachine.MachineTag())
  1241  	c.Assert(err, jc.ErrorIsNil)
  1242  	c.Assert(volumeAttachments, gc.HasLen, 1)
  1243  	volumeAttachmentInfo, err := volumeAttachments[0].Info()
  1244  	c.Assert(err, jc.ErrorIsNil)
  1245  	c.Assert(volumeAttachmentInfo, gc.Equals, state.VolumeAttachmentInfo{DeviceName: "sda"})
  1246  	volume, err := s.State.Volume(volumeAttachments[0].Volume())
  1247  	c.Assert(err, jc.ErrorIsNil)
  1248  	volumeInfo, err := volume.Info()
  1249  	c.Assert(err, jc.ErrorIsNil)
  1250  	c.Assert(volumeInfo, gc.Equals, state.VolumeInfo{VolumeId: "vol-0", Pool: "static-pool", Size: 1234})
  1251  
  1252  	// Verify the machine without requested volumes still has no volume
  1253  	// attachments recorded in state.
  1254  	volumeAttachments, err = s.State.MachineVolumeAttachments(s.machines[1].MachineTag())
  1255  	c.Assert(err, jc.ErrorIsNil)
  1256  	c.Assert(volumeAttachments, gc.HasLen, 0)
  1257  }
  1258  
  1259  func (s *withoutStateServerSuite) TestInstanceId(c *gc.C) {
  1260  	// Provision 2 machines first.
  1261  	err := s.machines[0].SetProvisioned("i-am", "fake_nonce", nil)
  1262  	c.Assert(err, jc.ErrorIsNil)
  1263  	hwChars := instance.MustParseHardware("arch=i386", "mem=4G")
  1264  	err = s.machines[1].SetProvisioned("i-am-not", "fake_nonce", &hwChars)
  1265  	c.Assert(err, jc.ErrorIsNil)
  1266  
  1267  	args := params.Entities{Entities: []params.Entity{
  1268  		{Tag: s.machines[0].Tag().String()},
  1269  		{Tag: s.machines[1].Tag().String()},
  1270  		{Tag: s.machines[2].Tag().String()},
  1271  		{Tag: "machine-42"},
  1272  		{Tag: "unit-foo-0"},
  1273  		{Tag: "service-bar"},
  1274  	}}
  1275  	result, err := s.provisioner.InstanceId(args)
  1276  	c.Assert(err, jc.ErrorIsNil)
  1277  	c.Assert(result, gc.DeepEquals, params.StringResults{
  1278  		Results: []params.StringResult{
  1279  			{Result: "i-am"},
  1280  			{Result: "i-am-not"},
  1281  			{Error: apiservertesting.NotProvisionedError("2")},
  1282  			{Error: apiservertesting.NotFoundError("machine 42")},
  1283  			{Error: apiservertesting.ErrUnauthorized},
  1284  			{Error: apiservertesting.ErrUnauthorized},
  1285  		},
  1286  	})
  1287  }
  1288  
  1289  func (s *withoutStateServerSuite) TestWatchEnvironMachines(c *gc.C) {
  1290  	c.Assert(s.resources.Count(), gc.Equals, 0)
  1291  
  1292  	got, err := s.provisioner.WatchEnvironMachines()
  1293  	c.Assert(err, jc.ErrorIsNil)
  1294  	want := params.StringsWatchResult{
  1295  		StringsWatcherId: "1",
  1296  		Changes:          []string{"0", "1", "2", "3", "4"},
  1297  	}
  1298  	c.Assert(got.StringsWatcherId, gc.Equals, want.StringsWatcherId)
  1299  	c.Assert(got.Changes, jc.SameContents, want.Changes)
  1300  
  1301  	// Verify the resources were registered and stop them when done.
  1302  	c.Assert(s.resources.Count(), gc.Equals, 1)
  1303  	resource := s.resources.Get("1")
  1304  	defer statetesting.AssertStop(c, resource)
  1305  
  1306  	// Check that the Watch has consumed the initial event ("returned"
  1307  	// in the Watch call)
  1308  	wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher))
  1309  	wc.AssertNoChange()
  1310  
  1311  	// Make sure WatchEnvironMachines fails with a machine agent login.
  1312  	anAuthorizer := s.authorizer
  1313  	anAuthorizer.Tag = names.NewMachineTag("1")
  1314  	anAuthorizer.EnvironManager = false
  1315  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
  1316  	c.Assert(err, jc.ErrorIsNil)
  1317  
  1318  	result, err := aProvisioner.WatchEnvironMachines()
  1319  	c.Assert(err, gc.ErrorMatches, "permission denied")
  1320  	c.Assert(result, gc.DeepEquals, params.StringsWatchResult{})
  1321  }
  1322  
  1323  func (s *provisionerSuite) getManagerConfig(c *gc.C, typ instance.ContainerType) map[string]string {
  1324  	args := params.ContainerManagerConfigParams{Type: typ}
  1325  	results, err := s.provisioner.ContainerManagerConfig(args)
  1326  	c.Assert(err, jc.ErrorIsNil)
  1327  	return results.ManagerConfig
  1328  }
  1329  
  1330  func (s *withoutStateServerSuite) TestContainerManagerConfig(c *gc.C) {
  1331  	cfg := s.getManagerConfig(c, instance.KVM)
  1332  	c.Assert(cfg, jc.DeepEquals, map[string]string{
  1333  		container.ConfigName: "juju",
  1334  
  1335  		// dummy provider supports both networking and address
  1336  		// allocation by default, so IP forwarding should be enabled.
  1337  		container.ConfigIPForwarding: "true",
  1338  	})
  1339  }
  1340  
  1341  func (s *withoutStateServerSuite) TestContainerManagerConfigNoFeatureFlagNoIPForwarding(c *gc.C) {
  1342  	s.SetFeatureFlags() // clear the flags.
  1343  
  1344  	cfg := s.getManagerConfig(c, instance.KVM)
  1345  	c.Assert(cfg, jc.DeepEquals, map[string]string{
  1346  		container.ConfigName: "juju",
  1347  		// ConfigIPForwarding should be missing.
  1348  	})
  1349  }
  1350  
  1351  func (s *withoutStateServerSuite) TestContainerManagerConfigNoIPForwarding(c *gc.C) {
  1352  	// Break dummy provider's SupportsAddressAllocation method to
  1353  	// ensure ConfigIPForwarding is not set below.
  1354  	s.AssertConfigParameterUpdated(c, "broken", "SupportsAddressAllocation")
  1355  
  1356  	cfg := s.getManagerConfig(c, instance.KVM)
  1357  	c.Assert(cfg, jc.DeepEquals, map[string]string{
  1358  		container.ConfigName: "juju",
  1359  	})
  1360  }
  1361  
  1362  func (s *withoutStateServerSuite) TestContainerConfig(c *gc.C) {
  1363  	attrs := map[string]interface{}{
  1364  		"http-proxy":            "http://proxy.example.com:9000",
  1365  		"allow-lxc-loop-mounts": true,
  1366  	}
  1367  	err := s.State.UpdateEnvironConfig(attrs, nil, nil)
  1368  	c.Assert(err, jc.ErrorIsNil)
  1369  	expectedProxy := proxy.Settings{
  1370  		Http: "http://proxy.example.com:9000",
  1371  	}
  1372  
  1373  	results, err := s.provisioner.ContainerConfig()
  1374  	c.Check(err, jc.ErrorIsNil)
  1375  	c.Check(results.UpdateBehavior, gc.Not(gc.IsNil))
  1376  	c.Check(results.ProviderType, gc.Equals, "dummy")
  1377  	c.Check(results.AuthorizedKeys, gc.Equals, s.Environ.Config().AuthorizedKeys())
  1378  	c.Check(results.SSLHostnameVerification, jc.IsTrue)
  1379  	c.Check(results.Proxy, gc.DeepEquals, expectedProxy)
  1380  	c.Check(results.AptProxy, gc.DeepEquals, expectedProxy)
  1381  	c.Check(results.PreferIPv6, jc.IsTrue)
  1382  	c.Check(results.AllowLXCLoopMounts, jc.IsTrue)
  1383  }
  1384  
  1385  func (s *withoutStateServerSuite) TestSetSupportedContainers(c *gc.C) {
  1386  	args := params.MachineContainersParams{Params: []params.MachineContainers{{
  1387  		MachineTag:     "machine-0",
  1388  		ContainerTypes: []instance.ContainerType{instance.LXC},
  1389  	}, {
  1390  		MachineTag:     "machine-1",
  1391  		ContainerTypes: []instance.ContainerType{instance.LXC, instance.KVM},
  1392  	}}}
  1393  	results, err := s.provisioner.SetSupportedContainers(args)
  1394  	c.Assert(err, jc.ErrorIsNil)
  1395  	c.Assert(results.Results, gc.HasLen, 2)
  1396  	for _, result := range results.Results {
  1397  		c.Assert(result.Error, gc.IsNil)
  1398  	}
  1399  	m0, err := s.State.Machine("0")
  1400  	c.Assert(err, jc.ErrorIsNil)
  1401  	containers, ok := m0.SupportedContainers()
  1402  	c.Assert(ok, jc.IsTrue)
  1403  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC})
  1404  	m1, err := s.State.Machine("1")
  1405  	c.Assert(err, jc.ErrorIsNil)
  1406  	containers, ok = m1.SupportedContainers()
  1407  	c.Assert(ok, jc.IsTrue)
  1408  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC, instance.KVM})
  1409  }
  1410  
  1411  func (s *withoutStateServerSuite) TestSetSupportedContainersPermissions(c *gc.C) {
  1412  	// Login as a machine agent for machine 0.
  1413  	anAuthorizer := s.authorizer
  1414  	anAuthorizer.EnvironManager = false
  1415  	anAuthorizer.Tag = s.machines[0].Tag()
  1416  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
  1417  	c.Assert(err, jc.ErrorIsNil)
  1418  	c.Assert(aProvisioner, gc.NotNil)
  1419  
  1420  	args := params.MachineContainersParams{
  1421  		Params: []params.MachineContainers{{
  1422  			MachineTag:     "machine-0",
  1423  			ContainerTypes: []instance.ContainerType{instance.LXC},
  1424  		}, {
  1425  			MachineTag:     "machine-1",
  1426  			ContainerTypes: []instance.ContainerType{instance.LXC},
  1427  		}, {
  1428  			MachineTag:     "machine-42",
  1429  			ContainerTypes: []instance.ContainerType{instance.LXC},
  1430  		},
  1431  		},
  1432  	}
  1433  	// Only machine 0 can have it's containers updated.
  1434  	results, err := aProvisioner.SetSupportedContainers(args)
  1435  	c.Assert(results, gc.DeepEquals, params.ErrorResults{
  1436  		Results: []params.ErrorResult{
  1437  			{Error: nil},
  1438  			{Error: apiservertesting.ErrUnauthorized},
  1439  			{Error: apiservertesting.ErrUnauthorized},
  1440  		},
  1441  	})
  1442  }
  1443  
  1444  func (s *withoutStateServerSuite) TestSupportsNoContainers(c *gc.C) {
  1445  	args := params.MachineContainersParams{
  1446  		Params: []params.MachineContainers{
  1447  			{
  1448  				MachineTag: "machine-0",
  1449  			},
  1450  		},
  1451  	}
  1452  	results, err := s.provisioner.SetSupportedContainers(args)
  1453  	c.Assert(err, jc.ErrorIsNil)
  1454  	c.Assert(results.Results, gc.HasLen, 1)
  1455  	c.Assert(results.Results[0].Error, gc.IsNil)
  1456  	m0, err := s.State.Machine("0")
  1457  	c.Assert(err, jc.ErrorIsNil)
  1458  	containers, ok := m0.SupportedContainers()
  1459  	c.Assert(ok, jc.IsTrue)
  1460  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{})
  1461  }
  1462  
  1463  var _ = gc.Suite(&withStateServerSuite{})
  1464  
  1465  type withStateServerSuite struct {
  1466  	provisionerSuite
  1467  }
  1468  
  1469  func (s *withStateServerSuite) SetUpTest(c *gc.C) {
  1470  	s.provisionerSuite.setUpTest(c, true)
  1471  }
  1472  
  1473  func (s *withStateServerSuite) TestAPIAddresses(c *gc.C) {
  1474  	hostPorts := [][]network.HostPort{
  1475  		network.NewHostPorts(1234, "0.1.2.3"),
  1476  	}
  1477  	err := s.State.SetAPIHostPorts(hostPorts)
  1478  	c.Assert(err, jc.ErrorIsNil)
  1479  
  1480  	result, err := s.provisioner.APIAddresses()
  1481  	c.Assert(err, jc.ErrorIsNil)
  1482  	c.Assert(result, gc.DeepEquals, params.StringsResult{
  1483  		Result: []string{"0.1.2.3:1234"},
  1484  	})
  1485  }
  1486  
  1487  func (s *withStateServerSuite) TestStateAddresses(c *gc.C) {
  1488  	addresses, err := s.State.Addresses()
  1489  	c.Assert(err, jc.ErrorIsNil)
  1490  
  1491  	result, err := s.provisioner.StateAddresses()
  1492  	c.Assert(err, jc.ErrorIsNil)
  1493  	c.Assert(result, gc.DeepEquals, params.StringsResult{
  1494  		Result: addresses,
  1495  	})
  1496  }
  1497  
  1498  func (s *withStateServerSuite) TestCACert(c *gc.C) {
  1499  	result := s.provisioner.CACert()
  1500  	c.Assert(result, gc.DeepEquals, params.BytesResult{
  1501  		Result: []byte(s.State.CACert()),
  1502  	})
  1503  }
  1504  
  1505  func (s *withoutStateServerSuite) TestWatchMachineErrorRetry(c *gc.C) {
  1506  	coretesting.SkipIfI386(c, "lp:1425569")
  1507  
  1508  	s.PatchValue(&provisioner.ErrorRetryWaitDelay, 2*coretesting.ShortWait)
  1509  	c.Assert(s.resources.Count(), gc.Equals, 0)
  1510  
  1511  	_, err := s.provisioner.WatchMachineErrorRetry()
  1512  	c.Assert(err, jc.ErrorIsNil)
  1513  
  1514  	// Verify the resources were registered and stop them when done.
  1515  	c.Assert(s.resources.Count(), gc.Equals, 1)
  1516  	resource := s.resources.Get("1")
  1517  	defer statetesting.AssertStop(c, resource)
  1518  
  1519  	// Check that the Watch has consumed the initial event ("returned"
  1520  	// in the Watch call)
  1521  	wc := statetesting.NewNotifyWatcherC(c, s.State, resource.(state.NotifyWatcher))
  1522  	wc.AssertNoChange()
  1523  
  1524  	// We should now get a time triggered change.
  1525  	wc.AssertOneChange()
  1526  
  1527  	// Make sure WatchMachineErrorRetry fails with a machine agent login.
  1528  	anAuthorizer := s.authorizer
  1529  	anAuthorizer.Tag = names.NewMachineTag("1")
  1530  	anAuthorizer.EnvironManager = false
  1531  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
  1532  	c.Assert(err, jc.ErrorIsNil)
  1533  
  1534  	result, err := aProvisioner.WatchMachineErrorRetry()
  1535  	c.Assert(err, gc.ErrorMatches, "permission denied")
  1536  	c.Assert(result, gc.DeepEquals, params.NotifyWatchResult{})
  1537  }
  1538  
  1539  func (s *withoutStateServerSuite) TestFindTools(c *gc.C) {
  1540  	args := params.FindToolsParams{
  1541  		MajorVersion: -1,
  1542  		MinorVersion: -1,
  1543  	}
  1544  	result, err := s.provisioner.FindTools(args)
  1545  	c.Assert(err, jc.ErrorIsNil)
  1546  	c.Assert(result.Error, gc.IsNil)
  1547  	c.Assert(result.List, gc.Not(gc.HasLen), 0)
  1548  	for _, tools := range result.List {
  1549  		url := fmt.Sprintf("https://%s/environment/%s/tools/%s",
  1550  			s.APIState.Addr(), coretesting.EnvironmentTag.Id(), tools.Version)
  1551  		c.Assert(tools.URL, gc.Equals, url)
  1552  	}
  1553  }
  1554  
  1555  type lxcDefaultMTUSuite struct {
  1556  	provisionerSuite
  1557  }
  1558  
  1559  var _ = gc.Suite(&lxcDefaultMTUSuite{})
  1560  
  1561  func (s *lxcDefaultMTUSuite) SetUpTest(c *gc.C) {
  1562  	// Because lxc-default-mtu is an immutable setting, we need to set
  1563  	// it in the default config JujuConnSuite uses, before the
  1564  	// environment is "created".
  1565  	s.DummyConfig = dummy.SampleConfig()
  1566  	s.DummyConfig["lxc-default-mtu"] = 9000
  1567  	s.provisionerSuite.SetUpTest(c)
  1568  
  1569  	stateConfig, err := s.State.EnvironConfig()
  1570  	c.Assert(err, jc.ErrorIsNil)
  1571  	value, ok := stateConfig.LXCDefaultMTU()
  1572  	c.Assert(ok, jc.IsTrue)
  1573  	c.Assert(value, gc.Equals, 9000)
  1574  	c.Logf("environ config lxc-default-mtu set to %v", value)
  1575  }
  1576  
  1577  func (s *lxcDefaultMTUSuite) TestContainerManagerConfigLXCDefaultMTU(c *gc.C) {
  1578  	managerConfig := s.getManagerConfig(c, instance.LXC)
  1579  	c.Assert(managerConfig, jc.DeepEquals, map[string]string{
  1580  		container.ConfigName:          "juju",
  1581  		container.ConfigLXCDefaultMTU: "9000",
  1582  
  1583  		"use-aufs":                   "false",
  1584  		container.ConfigIPForwarding: "true",
  1585  	})
  1586  
  1587  	// KVM instances are not affected.
  1588  	managerConfig = s.getManagerConfig(c, instance.KVM)
  1589  	c.Assert(managerConfig, jc.DeepEquals, map[string]string{
  1590  		container.ConfigName:         "juju",
  1591  		container.ConfigIPForwarding: "true",
  1592  	})
  1593  }