github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/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.EntityStatusArgs{
   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  	// Add a couple of spaces.
   747  	_, err := s.State.AddSpace("space1", nil, true)
   748  	c.Assert(err, jc.ErrorIsNil)
   749  	_, err = s.State.AddSpace("space2", nil, false)
   750  	c.Assert(err, jc.ErrorIsNil)
   751  	// Add 1 subnet into space1, and 2 into space2.
   752  	// Only the first subnet of space2 has AllocatableIPLow|High set.
   753  	// Each subnet is in a matching zone (e.g "subnet-#" in "zone#").
   754  	testing.AddSubnetsWithTemplate(c, s.State, 3, state.SubnetInfo{
   755  		CIDR:              "10.10.{{.}}.0/24",
   756  		ProviderId:        "subnet-{{.}}",
   757  		AllocatableIPLow:  "{{if (eq . 1)}}10.10.{{.}}.5{{end}}",
   758  		AllocatableIPHigh: "{{if (eq . 1)}}10.10.{{.}}.254{{end}}",
   759  		AvailabilityZone:  "zone{{.}}",
   760  		SpaceName:         "{{if (eq . 0)}}space1{{else}}space2{{end}}",
   761  		VLANTag:           42,
   762  	})
   763  
   764  	registry.RegisterProvider("static", &storagedummy.StorageProvider{IsDynamic: false})
   765  	defer registry.RegisterProvider("static", nil)
   766  	registry.RegisterEnvironStorageProviders("dummy", "static")
   767  
   768  	pm := poolmanager.New(state.NewStateSettings(s.State))
   769  	_, err = pm.Create("static-pool", "static", map[string]interface{}{"foo": "bar"})
   770  	c.Assert(err, jc.ErrorIsNil)
   771  
   772  	cons := constraints.MustParse("cpu-cores=123 mem=8G spaces=^space1,space2")
   773  	template := state.MachineTemplate{
   774  		Series:      "quantal",
   775  		Jobs:        []state.MachineJob{state.JobHostUnits},
   776  		Constraints: cons,
   777  		Placement:   "valid",
   778  		Volumes: []state.MachineVolumeParams{
   779  			{Volume: state.VolumeParams{Size: 1000, Pool: "static-pool"}},
   780  			{Volume: state.VolumeParams{Size: 2000, Pool: "static-pool"}},
   781  		},
   782  	}
   783  	placementMachine, err := s.State.AddOneMachine(template)
   784  	c.Assert(err, jc.ErrorIsNil)
   785  
   786  	args := params.Entities{Entities: []params.Entity{
   787  		{Tag: s.machines[0].Tag().String()},
   788  		{Tag: placementMachine.Tag().String()},
   789  		{Tag: "machine-42"},
   790  		{Tag: "unit-foo-0"},
   791  		{Tag: "service-bar"},
   792  	}}
   793  	result, err := s.provisioner.ProvisioningInfo(args)
   794  	c.Assert(err, jc.ErrorIsNil)
   795  
   796  	expected := params.ProvisioningInfoResults{
   797  		Results: []params.ProvisioningInfoResult{
   798  			{Result: &params.ProvisioningInfo{
   799  				Series:   "quantal",
   800  				Networks: []string{},
   801  				Jobs:     []multiwatcher.MachineJob{multiwatcher.JobHostUnits},
   802  				Tags: map[string]string{
   803  					tags.JujuEnv: coretesting.EnvironmentTag.Id(),
   804  				},
   805  			}},
   806  			{Result: &params.ProvisioningInfo{
   807  				Series:      "quantal",
   808  				Constraints: template.Constraints,
   809  				Placement:   template.Placement,
   810  				Networks:    template.RequestedNetworks,
   811  				Jobs:        []multiwatcher.MachineJob{multiwatcher.JobHostUnits},
   812  				Tags: map[string]string{
   813  					tags.JujuEnv: coretesting.EnvironmentTag.Id(),
   814  				},
   815  				SubnetsToZones: map[string][]string{
   816  					"subnet-1": []string{"zone1"},
   817  					"subnet-2": []string{"zone2"},
   818  				},
   819  				Volumes: []params.VolumeParams{{
   820  					VolumeTag:  "volume-0",
   821  					Size:       1000,
   822  					Provider:   "static",
   823  					Attributes: map[string]interface{}{"foo": "bar"},
   824  					Tags: map[string]string{
   825  						tags.JujuEnv: coretesting.EnvironmentTag.Id(),
   826  					},
   827  					Attachment: &params.VolumeAttachmentParams{
   828  						MachineTag: placementMachine.Tag().String(),
   829  						VolumeTag:  "volume-0",
   830  						Provider:   "static",
   831  					},
   832  				}, {
   833  					VolumeTag:  "volume-1",
   834  					Size:       2000,
   835  					Provider:   "static",
   836  					Attributes: map[string]interface{}{"foo": "bar"},
   837  					Tags: map[string]string{
   838  						tags.JujuEnv: coretesting.EnvironmentTag.Id(),
   839  					},
   840  					Attachment: &params.VolumeAttachmentParams{
   841  						MachineTag: placementMachine.Tag().String(),
   842  						VolumeTag:  "volume-1",
   843  						Provider:   "static",
   844  					},
   845  				}},
   846  			}},
   847  			{Error: apiservertesting.NotFoundError("machine 42")},
   848  			{Error: apiservertesting.ErrUnauthorized},
   849  			{Error: apiservertesting.ErrUnauthorized},
   850  		},
   851  	}
   852  	// The order of volumes is not predictable, so we make sure we
   853  	// compare the right ones. This only applies to Results[1] since
   854  	// it is the only result to contain volumes.
   855  	if expected.Results[1].Result.Volumes[0].VolumeTag != result.Results[1].Result.Volumes[0].VolumeTag {
   856  		vols := expected.Results[1].Result.Volumes
   857  		vols[0], vols[1] = vols[1], vols[0]
   858  	}
   859  	c.Assert(result, jc.DeepEquals, expected)
   860  }
   861  
   862  func (s *withoutStateServerSuite) TestStorageProviderFallbackToType(c *gc.C) {
   863  	registry.RegisterProvider("dynamic", &storagedummy.StorageProvider{IsDynamic: true})
   864  	defer registry.RegisterProvider("dynamic", nil)
   865  	registry.RegisterProvider("static", &storagedummy.StorageProvider{IsDynamic: false})
   866  	defer registry.RegisterProvider("static", nil)
   867  	registry.RegisterEnvironStorageProviders("dummy", "dynamic", "static")
   868  
   869  	template := state.MachineTemplate{
   870  		Series:            "quantal",
   871  		Jobs:              []state.MachineJob{state.JobHostUnits},
   872  		Placement:         "valid",
   873  		RequestedNetworks: []string{"net1", "net2"},
   874  		Volumes: []state.MachineVolumeParams{
   875  			{Volume: state.VolumeParams{Size: 1000, Pool: "dynamic"}},
   876  			{Volume: state.VolumeParams{Size: 1000, Pool: "static"}},
   877  		},
   878  	}
   879  	placementMachine, err := s.State.AddOneMachine(template)
   880  	c.Assert(err, jc.ErrorIsNil)
   881  
   882  	args := params.Entities{Entities: []params.Entity{
   883  		{Tag: placementMachine.Tag().String()},
   884  	}}
   885  	result, err := s.provisioner.ProvisioningInfo(args)
   886  	c.Assert(err, jc.ErrorIsNil)
   887  
   888  	c.Assert(result, jc.DeepEquals, params.ProvisioningInfoResults{
   889  		Results: []params.ProvisioningInfoResult{
   890  			{Result: &params.ProvisioningInfo{
   891  				Series:      "quantal",
   892  				Constraints: template.Constraints,
   893  				Placement:   template.Placement,
   894  				Networks:    template.RequestedNetworks,
   895  				Jobs:        []multiwatcher.MachineJob{multiwatcher.JobHostUnits},
   896  				Tags: map[string]string{
   897  					tags.JujuEnv: coretesting.EnvironmentTag.Id(),
   898  				},
   899  				Volumes: []params.VolumeParams{{
   900  					VolumeTag:  "volume-1",
   901  					Size:       1000,
   902  					Provider:   "static",
   903  					Attributes: nil,
   904  					Tags: map[string]string{
   905  						tags.JujuEnv: coretesting.EnvironmentTag.Id(),
   906  					},
   907  					Attachment: &params.VolumeAttachmentParams{
   908  						MachineTag: placementMachine.Tag().String(),
   909  						VolumeTag:  "volume-1",
   910  						Provider:   "static",
   911  					},
   912  				}},
   913  			}},
   914  		},
   915  	})
   916  }
   917  
   918  func (s *withoutStateServerSuite) TestProvisioningInfoPermissions(c *gc.C) {
   919  	// Login as a machine agent for machine 0.
   920  	anAuthorizer := s.authorizer
   921  	anAuthorizer.EnvironManager = false
   922  	anAuthorizer.Tag = s.machines[0].Tag()
   923  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   924  	c.Assert(err, jc.ErrorIsNil)
   925  	c.Assert(aProvisioner, gc.NotNil)
   926  
   927  	args := params.Entities{Entities: []params.Entity{
   928  		{Tag: s.machines[0].Tag().String()},
   929  		{Tag: s.machines[0].Tag().String() + "-lxc-0"},
   930  		{Tag: "machine-42"},
   931  		{Tag: s.machines[1].Tag().String()},
   932  		{Tag: "service-bar"},
   933  	}}
   934  
   935  	// Only machine 0 and containers therein can be accessed.
   936  	results, err := aProvisioner.ProvisioningInfo(args)
   937  	c.Assert(results, jc.DeepEquals, params.ProvisioningInfoResults{
   938  		Results: []params.ProvisioningInfoResult{
   939  			{Result: &params.ProvisioningInfo{
   940  				Series:   "quantal",
   941  				Networks: []string{},
   942  				Jobs:     []multiwatcher.MachineJob{multiwatcher.JobHostUnits},
   943  				Tags: map[string]string{
   944  					tags.JujuEnv: coretesting.EnvironmentTag.Id(),
   945  				},
   946  			}},
   947  			{Error: apiservertesting.NotFoundError("machine 0/lxc/0")},
   948  			{Error: apiservertesting.ErrUnauthorized},
   949  			{Error: apiservertesting.ErrUnauthorized},
   950  			{Error: apiservertesting.ErrUnauthorized},
   951  		},
   952  	})
   953  }
   954  
   955  func (s *withoutStateServerSuite) TestConstraints(c *gc.C) {
   956  	// Add a machine with some constraints.
   957  	cons := constraints.MustParse("cpu-cores=123", "mem=8G", "networks=net3,^net4")
   958  	template := state.MachineTemplate{
   959  		Series:      "quantal",
   960  		Jobs:        []state.MachineJob{state.JobHostUnits},
   961  		Constraints: cons,
   962  	}
   963  	consMachine, err := s.State.AddOneMachine(template)
   964  	c.Assert(err, jc.ErrorIsNil)
   965  
   966  	machine0Constraints, err := s.machines[0].Constraints()
   967  	c.Assert(err, jc.ErrorIsNil)
   968  
   969  	args := params.Entities{Entities: []params.Entity{
   970  		{Tag: s.machines[0].Tag().String()},
   971  		{Tag: consMachine.Tag().String()},
   972  		{Tag: "machine-42"},
   973  		{Tag: "unit-foo-0"},
   974  		{Tag: "service-bar"},
   975  	}}
   976  	result, err := s.provisioner.Constraints(args)
   977  	c.Assert(err, jc.ErrorIsNil)
   978  	c.Assert(result, gc.DeepEquals, params.ConstraintsResults{
   979  		Results: []params.ConstraintsResult{
   980  			{Constraints: machine0Constraints},
   981  			{Constraints: template.Constraints},
   982  			{Error: apiservertesting.NotFoundError("machine 42")},
   983  			{Error: apiservertesting.ErrUnauthorized},
   984  			{Error: apiservertesting.ErrUnauthorized},
   985  		},
   986  	})
   987  }
   988  
   989  func (s *withoutStateServerSuite) TestRequestedNetworks(c *gc.C) {
   990  	// Add a machine with some requested networks.
   991  	template := state.MachineTemplate{
   992  		Series:            "quantal",
   993  		Jobs:              []state.MachineJob{state.JobHostUnits},
   994  		RequestedNetworks: []string{"net1", "net2"},
   995  	}
   996  	netsMachine, err := s.State.AddOneMachine(template)
   997  	c.Assert(err, jc.ErrorIsNil)
   998  
   999  	networksMachine0, err := s.machines[0].RequestedNetworks()
  1000  	c.Assert(err, jc.ErrorIsNil)
  1001  
  1002  	args := params.Entities{Entities: []params.Entity{
  1003  		{Tag: s.machines[0].Tag().String()},
  1004  		{Tag: netsMachine.Tag().String()},
  1005  		{Tag: "machine-42"},
  1006  		{Tag: "unit-foo-0"},
  1007  		{Tag: "service-bar"},
  1008  	}}
  1009  	result, err := s.provisioner.RequestedNetworks(args)
  1010  	c.Assert(err, jc.ErrorIsNil)
  1011  	c.Assert(result, gc.DeepEquals, params.RequestedNetworksResults{
  1012  		Results: []params.RequestedNetworkResult{
  1013  			{
  1014  				Networks: networksMachine0,
  1015  			},
  1016  			{
  1017  				Networks: template.RequestedNetworks,
  1018  			},
  1019  			{Error: apiservertesting.NotFoundError("machine 42")},
  1020  			{Error: apiservertesting.ErrUnauthorized},
  1021  			{Error: apiservertesting.ErrUnauthorized},
  1022  		},
  1023  	})
  1024  }
  1025  
  1026  func (s *withoutStateServerSuite) TestSetProvisioned(c *gc.C) {
  1027  	// Provision machine 0 first.
  1028  	hwChars := instance.MustParseHardware("arch=i386", "mem=4G")
  1029  	err := s.machines[0].SetProvisioned("i-am", "fake_nonce", &hwChars)
  1030  	c.Assert(err, jc.ErrorIsNil)
  1031  
  1032  	args := params.SetProvisioned{Machines: []params.MachineSetProvisioned{
  1033  		{Tag: s.machines[0].Tag().String(), InstanceId: "i-was", Nonce: "fake_nonce", Characteristics: nil},
  1034  		{Tag: s.machines[1].Tag().String(), InstanceId: "i-will", Nonce: "fake_nonce", Characteristics: &hwChars},
  1035  		{Tag: s.machines[2].Tag().String(), InstanceId: "i-am-too", Nonce: "fake", Characteristics: nil},
  1036  		{Tag: "machine-42", InstanceId: "", Nonce: "", Characteristics: nil},
  1037  		{Tag: "unit-foo-0", InstanceId: "", Nonce: "", Characteristics: nil},
  1038  		{Tag: "service-bar", InstanceId: "", Nonce: "", Characteristics: nil},
  1039  	}}
  1040  	result, err := s.provisioner.SetProvisioned(args)
  1041  	c.Assert(err, jc.ErrorIsNil)
  1042  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
  1043  		Results: []params.ErrorResult{
  1044  			{&params.Error{
  1045  				Message: `cannot set instance data for machine "0": already set`,
  1046  			}},
  1047  			{nil},
  1048  			{nil},
  1049  			{apiservertesting.NotFoundError("machine 42")},
  1050  			{apiservertesting.ErrUnauthorized},
  1051  			{apiservertesting.ErrUnauthorized},
  1052  		},
  1053  	})
  1054  
  1055  	// Verify machine 1 and 2 were provisioned.
  1056  	c.Assert(s.machines[1].Refresh(), gc.IsNil)
  1057  	c.Assert(s.machines[2].Refresh(), gc.IsNil)
  1058  
  1059  	instanceId, err := s.machines[1].InstanceId()
  1060  	c.Assert(err, jc.ErrorIsNil)
  1061  	c.Check(instanceId, gc.Equals, instance.Id("i-will"))
  1062  	instanceId, err = s.machines[2].InstanceId()
  1063  	c.Assert(err, jc.ErrorIsNil)
  1064  	c.Check(instanceId, gc.Equals, instance.Id("i-am-too"))
  1065  	c.Check(s.machines[1].CheckProvisioned("fake_nonce"), jc.IsTrue)
  1066  	c.Check(s.machines[2].CheckProvisioned("fake"), jc.IsTrue)
  1067  	gotHardware, err := s.machines[1].HardwareCharacteristics()
  1068  	c.Assert(err, jc.ErrorIsNil)
  1069  	c.Check(gotHardware, gc.DeepEquals, &hwChars)
  1070  }
  1071  
  1072  func (s *withoutStateServerSuite) TestSetInstanceInfo(c *gc.C) {
  1073  	registry.RegisterProvider("static", &storagedummy.StorageProvider{IsDynamic: false})
  1074  	defer registry.RegisterProvider("static", nil)
  1075  	registry.RegisterEnvironStorageProviders("dummy", "static")
  1076  
  1077  	pm := poolmanager.New(state.NewStateSettings(s.State))
  1078  	_, err := pm.Create("static-pool", "static", map[string]interface{}{"foo": "bar"})
  1079  	c.Assert(err, jc.ErrorIsNil)
  1080  	err = s.State.UpdateEnvironConfig(map[string]interface{}{
  1081  		"storage-default-block-source": "static-pool",
  1082  	}, nil, nil)
  1083  	c.Assert(err, jc.ErrorIsNil)
  1084  
  1085  	// Provision machine 0 first.
  1086  	hwChars := instance.MustParseHardware("arch=i386", "mem=4G")
  1087  	err = s.machines[0].SetInstanceInfo("i-am", "fake_nonce", &hwChars, nil, nil, nil, nil)
  1088  	c.Assert(err, jc.ErrorIsNil)
  1089  
  1090  	volumesMachine, err := s.State.AddOneMachine(state.MachineTemplate{
  1091  		Series: "quantal",
  1092  		Jobs:   []state.MachineJob{state.JobHostUnits},
  1093  		Volumes: []state.MachineVolumeParams{{
  1094  			Volume: state.VolumeParams{Size: 1000},
  1095  		}},
  1096  	})
  1097  	c.Assert(err, jc.ErrorIsNil)
  1098  
  1099  	networks := []params.Network{{
  1100  		Tag:        "network-net1",
  1101  		ProviderId: "net1",
  1102  		CIDR:       "0.1.2.0/24",
  1103  		VLANTag:    0,
  1104  	}, {
  1105  		Tag:        "network-vlan42",
  1106  		ProviderId: "vlan42",
  1107  		CIDR:       "0.2.2.0/24",
  1108  		VLANTag:    42,
  1109  	}, {
  1110  		Tag:        "network-vlan69",
  1111  		ProviderId: "vlan69",
  1112  		CIDR:       "0.3.2.0/24",
  1113  		VLANTag:    69,
  1114  	}, {
  1115  		Tag:        "network-vlan42", // duplicated; ignored
  1116  		ProviderId: "vlan42",
  1117  		CIDR:       "0.2.2.0/24",
  1118  		VLANTag:    42,
  1119  	}}
  1120  	ifaces := []params.NetworkInterface{{
  1121  		MACAddress:    "aa:bb:cc:dd:ee:f0",
  1122  		NetworkTag:    "network-net1",
  1123  		InterfaceName: "eth0",
  1124  		IsVirtual:     false,
  1125  	}, {
  1126  		MACAddress:    "aa:bb:cc:dd:ee:f1",
  1127  		NetworkTag:    "network-net1",
  1128  		InterfaceName: "eth1",
  1129  		IsVirtual:     false,
  1130  	}, {
  1131  		MACAddress:    "aa:bb:cc:dd:ee:f1",
  1132  		NetworkTag:    "network-vlan42",
  1133  		InterfaceName: "eth1.42",
  1134  		IsVirtual:     true,
  1135  	}, {
  1136  		MACAddress:    "aa:bb:cc:dd:ee:f0",
  1137  		NetworkTag:    "network-vlan69",
  1138  		InterfaceName: "eth0.69",
  1139  		IsVirtual:     true,
  1140  		Disabled:      true,
  1141  	}, {
  1142  		MACAddress:    "aa:bb:cc:dd:ee:f1", // duplicated mac+net; ignored
  1143  		NetworkTag:    "network-vlan42",
  1144  		InterfaceName: "eth2",
  1145  		IsVirtual:     true,
  1146  	}, {
  1147  		MACAddress:    "aa:bb:cc:dd:ee:f2",
  1148  		NetworkTag:    "network-net1",
  1149  		InterfaceName: "eth1", // duplicated name+machine id; ignored for machine 1.
  1150  		IsVirtual:     false,
  1151  	}}
  1152  	args := params.InstancesInfo{Machines: []params.InstanceInfo{{
  1153  		Tag:        s.machines[0].Tag().String(),
  1154  		InstanceId: "i-was",
  1155  		Nonce:      "fake_nonce",
  1156  	}, {
  1157  		Tag:             s.machines[1].Tag().String(),
  1158  		InstanceId:      "i-will",
  1159  		Nonce:           "fake_nonce",
  1160  		Characteristics: &hwChars,
  1161  		Networks:        networks,
  1162  		Interfaces:      ifaces,
  1163  	}, {
  1164  		Tag:             s.machines[2].Tag().String(),
  1165  		InstanceId:      "i-am-too",
  1166  		Nonce:           "fake",
  1167  		Characteristics: nil,
  1168  		Networks:        networks,
  1169  		Interfaces:      ifaces,
  1170  	}, {
  1171  		Tag:        volumesMachine.Tag().String(),
  1172  		InstanceId: "i-am-also",
  1173  		Nonce:      "fake",
  1174  		Volumes: []params.Volume{{
  1175  			VolumeTag: "volume-0",
  1176  			Info: params.VolumeInfo{
  1177  				VolumeId: "vol-0",
  1178  				Size:     1234,
  1179  			},
  1180  		}},
  1181  		VolumeAttachments: map[string]params.VolumeAttachmentInfo{
  1182  			"volume-0": {
  1183  				DeviceName: "sda",
  1184  			},
  1185  		},
  1186  	},
  1187  		{Tag: "machine-42"},
  1188  		{Tag: "unit-foo-0"},
  1189  		{Tag: "service-bar"},
  1190  	}}
  1191  	result, err := s.provisioner.SetInstanceInfo(args)
  1192  	c.Assert(err, jc.ErrorIsNil)
  1193  	c.Assert(result, jc.DeepEquals, params.ErrorResults{
  1194  		Results: []params.ErrorResult{
  1195  			{&params.Error{
  1196  				Message: `cannot record provisioning info for "i-was": cannot set instance data for machine "0": already set`,
  1197  			}},
  1198  			{nil},
  1199  			{nil},
  1200  			{nil},
  1201  			{apiservertesting.NotFoundError("machine 42")},
  1202  			{apiservertesting.ErrUnauthorized},
  1203  			{apiservertesting.ErrUnauthorized},
  1204  		},
  1205  	})
  1206  
  1207  	// Verify machine 1 and 2 were provisioned.
  1208  	c.Assert(s.machines[1].Refresh(), gc.IsNil)
  1209  	c.Assert(s.machines[2].Refresh(), gc.IsNil)
  1210  
  1211  	instanceId, err := s.machines[1].InstanceId()
  1212  	c.Assert(err, jc.ErrorIsNil)
  1213  	c.Check(instanceId, gc.Equals, instance.Id("i-will"))
  1214  	instanceId, err = s.machines[2].InstanceId()
  1215  	c.Assert(err, jc.ErrorIsNil)
  1216  	c.Check(instanceId, gc.Equals, instance.Id("i-am-too"))
  1217  	c.Check(s.machines[1].CheckProvisioned("fake_nonce"), jc.IsTrue)
  1218  	c.Check(s.machines[2].CheckProvisioned("fake"), jc.IsTrue)
  1219  	gotHardware, err := s.machines[1].HardwareCharacteristics()
  1220  	c.Assert(err, jc.ErrorIsNil)
  1221  	c.Check(gotHardware, gc.DeepEquals, &hwChars)
  1222  	ifacesMachine1, err := s.machines[1].NetworkInterfaces()
  1223  	c.Assert(err, jc.ErrorIsNil)
  1224  	c.Assert(ifacesMachine1, gc.HasLen, 4)
  1225  	actual := make([]params.NetworkInterface, len(ifacesMachine1))
  1226  	for i, iface := range ifacesMachine1 {
  1227  		actual[i].InterfaceName = iface.InterfaceName()
  1228  		actual[i].NetworkTag = iface.NetworkTag().String()
  1229  		actual[i].MACAddress = iface.MACAddress()
  1230  		actual[i].IsVirtual = iface.IsVirtual()
  1231  		actual[i].Disabled = iface.IsDisabled()
  1232  		c.Check(iface.MachineId(), gc.Equals, s.machines[1].Id())
  1233  		c.Check(iface.MachineTag(), gc.Equals, s.machines[1].Tag())
  1234  	}
  1235  	c.Assert(actual, jc.SameContents, ifaces[:4])
  1236  	ifacesMachine2, err := s.machines[2].NetworkInterfaces()
  1237  	c.Assert(err, jc.ErrorIsNil)
  1238  	c.Assert(ifacesMachine2, gc.HasLen, 1)
  1239  	c.Assert(ifacesMachine2[0].InterfaceName(), gc.Equals, ifaces[5].InterfaceName)
  1240  	c.Assert(ifacesMachine2[0].MACAddress(), gc.Equals, ifaces[5].MACAddress)
  1241  	c.Assert(ifacesMachine2[0].NetworkTag().String(), gc.Equals, ifaces[5].NetworkTag)
  1242  	c.Assert(ifacesMachine2[0].MachineId(), gc.Equals, s.machines[2].Id())
  1243  	for i := range networks {
  1244  		if i == 3 {
  1245  			// Last one was ignored, so don't check.
  1246  			break
  1247  		}
  1248  		tag, err := names.ParseNetworkTag(networks[i].Tag)
  1249  		c.Assert(err, jc.ErrorIsNil)
  1250  		networkName := tag.Id()
  1251  		nw, err := s.State.Network(networkName)
  1252  		c.Assert(err, jc.ErrorIsNil)
  1253  		c.Check(nw.Name(), gc.Equals, networkName)
  1254  		c.Check(nw.ProviderId(), gc.Equals, network.Id(networks[i].ProviderId))
  1255  		c.Check(nw.Tag().String(), gc.Equals, networks[i].Tag)
  1256  		c.Check(nw.VLANTag(), gc.Equals, networks[i].VLANTag)
  1257  		c.Check(nw.CIDR(), gc.Equals, networks[i].CIDR)
  1258  	}
  1259  
  1260  	// Verify the machine with requested volumes was provisioned, and the
  1261  	// volume information recorded in state.
  1262  	volumeAttachments, err := s.State.MachineVolumeAttachments(volumesMachine.MachineTag())
  1263  	c.Assert(err, jc.ErrorIsNil)
  1264  	c.Assert(volumeAttachments, gc.HasLen, 1)
  1265  	volumeAttachmentInfo, err := volumeAttachments[0].Info()
  1266  	c.Assert(err, jc.ErrorIsNil)
  1267  	c.Assert(volumeAttachmentInfo, gc.Equals, state.VolumeAttachmentInfo{DeviceName: "sda"})
  1268  	volume, err := s.State.Volume(volumeAttachments[0].Volume())
  1269  	c.Assert(err, jc.ErrorIsNil)
  1270  	volumeInfo, err := volume.Info()
  1271  	c.Assert(err, jc.ErrorIsNil)
  1272  	c.Assert(volumeInfo, gc.Equals, state.VolumeInfo{VolumeId: "vol-0", Pool: "static-pool", Size: 1234})
  1273  
  1274  	// Verify the machine without requested volumes still has no volume
  1275  	// attachments recorded in state.
  1276  	volumeAttachments, err = s.State.MachineVolumeAttachments(s.machines[1].MachineTag())
  1277  	c.Assert(err, jc.ErrorIsNil)
  1278  	c.Assert(volumeAttachments, gc.HasLen, 0)
  1279  }
  1280  
  1281  func (s *withoutStateServerSuite) TestInstanceId(c *gc.C) {
  1282  	// Provision 2 machines first.
  1283  	err := s.machines[0].SetProvisioned("i-am", "fake_nonce", nil)
  1284  	c.Assert(err, jc.ErrorIsNil)
  1285  	hwChars := instance.MustParseHardware("arch=i386", "mem=4G")
  1286  	err = s.machines[1].SetProvisioned("i-am-not", "fake_nonce", &hwChars)
  1287  	c.Assert(err, jc.ErrorIsNil)
  1288  
  1289  	args := params.Entities{Entities: []params.Entity{
  1290  		{Tag: s.machines[0].Tag().String()},
  1291  		{Tag: s.machines[1].Tag().String()},
  1292  		{Tag: s.machines[2].Tag().String()},
  1293  		{Tag: "machine-42"},
  1294  		{Tag: "unit-foo-0"},
  1295  		{Tag: "service-bar"},
  1296  	}}
  1297  	result, err := s.provisioner.InstanceId(args)
  1298  	c.Assert(err, jc.ErrorIsNil)
  1299  	c.Assert(result, gc.DeepEquals, params.StringResults{
  1300  		Results: []params.StringResult{
  1301  			{Result: "i-am"},
  1302  			{Result: "i-am-not"},
  1303  			{Error: apiservertesting.NotProvisionedError("2")},
  1304  			{Error: apiservertesting.NotFoundError("machine 42")},
  1305  			{Error: apiservertesting.ErrUnauthorized},
  1306  			{Error: apiservertesting.ErrUnauthorized},
  1307  		},
  1308  	})
  1309  }
  1310  
  1311  func (s *withoutStateServerSuite) TestWatchEnvironMachines(c *gc.C) {
  1312  	c.Assert(s.resources.Count(), gc.Equals, 0)
  1313  
  1314  	got, err := s.provisioner.WatchEnvironMachines()
  1315  	c.Assert(err, jc.ErrorIsNil)
  1316  	want := params.StringsWatchResult{
  1317  		StringsWatcherId: "1",
  1318  		Changes:          []string{"0", "1", "2", "3", "4"},
  1319  	}
  1320  	c.Assert(got.StringsWatcherId, gc.Equals, want.StringsWatcherId)
  1321  	c.Assert(got.Changes, jc.SameContents, want.Changes)
  1322  
  1323  	// Verify the resources were registered and stop them when done.
  1324  	c.Assert(s.resources.Count(), gc.Equals, 1)
  1325  	resource := s.resources.Get("1")
  1326  	defer statetesting.AssertStop(c, resource)
  1327  
  1328  	// Check that the Watch has consumed the initial event ("returned"
  1329  	// in the Watch call)
  1330  	wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher))
  1331  	wc.AssertNoChange()
  1332  
  1333  	// Make sure WatchEnvironMachines fails with a machine agent login.
  1334  	anAuthorizer := s.authorizer
  1335  	anAuthorizer.Tag = names.NewMachineTag("1")
  1336  	anAuthorizer.EnvironManager = false
  1337  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
  1338  	c.Assert(err, jc.ErrorIsNil)
  1339  
  1340  	result, err := aProvisioner.WatchEnvironMachines()
  1341  	c.Assert(err, gc.ErrorMatches, "permission denied")
  1342  	c.Assert(result, gc.DeepEquals, params.StringsWatchResult{})
  1343  }
  1344  
  1345  func (s *provisionerSuite) getManagerConfig(c *gc.C, typ instance.ContainerType) map[string]string {
  1346  	args := params.ContainerManagerConfigParams{Type: typ}
  1347  	results, err := s.provisioner.ContainerManagerConfig(args)
  1348  	c.Assert(err, jc.ErrorIsNil)
  1349  	return results.ManagerConfig
  1350  }
  1351  
  1352  func (s *withoutStateServerSuite) TestContainerManagerConfig(c *gc.C) {
  1353  	cfg := s.getManagerConfig(c, instance.KVM)
  1354  	c.Assert(cfg, jc.DeepEquals, map[string]string{
  1355  		container.ConfigName: "juju",
  1356  
  1357  		// dummy provider supports both networking and address
  1358  		// allocation by default, so IP forwarding should be enabled.
  1359  		container.ConfigIPForwarding: "true",
  1360  	})
  1361  }
  1362  
  1363  func (s *withoutStateServerSuite) TestContainerManagerConfigNoFeatureFlagNoIPForwarding(c *gc.C) {
  1364  	s.SetFeatureFlags() // clear the flags.
  1365  
  1366  	cfg := s.getManagerConfig(c, instance.KVM)
  1367  	c.Assert(cfg, jc.DeepEquals, map[string]string{
  1368  		container.ConfigName: "juju",
  1369  		// ConfigIPForwarding should be missing.
  1370  	})
  1371  }
  1372  
  1373  func (s *withoutStateServerSuite) TestContainerManagerConfigNoIPForwarding(c *gc.C) {
  1374  	// Break dummy provider's SupportsAddressAllocation method to
  1375  	// ensure ConfigIPForwarding is not set below.
  1376  	s.AssertConfigParameterUpdated(c, "broken", "SupportsAddressAllocation")
  1377  
  1378  	cfg := s.getManagerConfig(c, instance.KVM)
  1379  	c.Assert(cfg, jc.DeepEquals, map[string]string{
  1380  		container.ConfigName: "juju",
  1381  	})
  1382  }
  1383  
  1384  func (s *withoutStateServerSuite) TestContainerConfig(c *gc.C) {
  1385  	attrs := map[string]interface{}{
  1386  		"http-proxy":            "http://proxy.example.com:9000",
  1387  		"allow-lxc-loop-mounts": true,
  1388  	}
  1389  	err := s.State.UpdateEnvironConfig(attrs, nil, nil)
  1390  	c.Assert(err, jc.ErrorIsNil)
  1391  	expectedProxy := proxy.Settings{
  1392  		Http: "http://proxy.example.com:9000",
  1393  	}
  1394  
  1395  	results, err := s.provisioner.ContainerConfig()
  1396  	c.Check(err, jc.ErrorIsNil)
  1397  	c.Check(results.UpdateBehavior, gc.Not(gc.IsNil))
  1398  	c.Check(results.ProviderType, gc.Equals, "dummy")
  1399  	c.Check(results.AuthorizedKeys, gc.Equals, s.Environ.Config().AuthorizedKeys())
  1400  	c.Check(results.SSLHostnameVerification, jc.IsTrue)
  1401  	c.Check(results.Proxy, gc.DeepEquals, expectedProxy)
  1402  	c.Check(results.AptProxy, gc.DeepEquals, expectedProxy)
  1403  	c.Check(results.PreferIPv6, jc.IsTrue)
  1404  	c.Check(results.AllowLXCLoopMounts, jc.IsTrue)
  1405  }
  1406  
  1407  func (s *withoutStateServerSuite) TestSetSupportedContainers(c *gc.C) {
  1408  	args := params.MachineContainersParams{Params: []params.MachineContainers{{
  1409  		MachineTag:     "machine-0",
  1410  		ContainerTypes: []instance.ContainerType{instance.LXC},
  1411  	}, {
  1412  		MachineTag:     "machine-1",
  1413  		ContainerTypes: []instance.ContainerType{instance.LXC, instance.KVM},
  1414  	}}}
  1415  	results, err := s.provisioner.SetSupportedContainers(args)
  1416  	c.Assert(err, jc.ErrorIsNil)
  1417  	c.Assert(results.Results, gc.HasLen, 2)
  1418  	for _, result := range results.Results {
  1419  		c.Assert(result.Error, gc.IsNil)
  1420  	}
  1421  	m0, err := s.State.Machine("0")
  1422  	c.Assert(err, jc.ErrorIsNil)
  1423  	containers, ok := m0.SupportedContainers()
  1424  	c.Assert(ok, jc.IsTrue)
  1425  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC})
  1426  	m1, err := s.State.Machine("1")
  1427  	c.Assert(err, jc.ErrorIsNil)
  1428  	containers, ok = m1.SupportedContainers()
  1429  	c.Assert(ok, jc.IsTrue)
  1430  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC, instance.KVM})
  1431  }
  1432  
  1433  func (s *withoutStateServerSuite) TestSetSupportedContainersPermissions(c *gc.C) {
  1434  	// Login as a machine agent for machine 0.
  1435  	anAuthorizer := s.authorizer
  1436  	anAuthorizer.EnvironManager = false
  1437  	anAuthorizer.Tag = s.machines[0].Tag()
  1438  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
  1439  	c.Assert(err, jc.ErrorIsNil)
  1440  	c.Assert(aProvisioner, gc.NotNil)
  1441  
  1442  	args := params.MachineContainersParams{
  1443  		Params: []params.MachineContainers{{
  1444  			MachineTag:     "machine-0",
  1445  			ContainerTypes: []instance.ContainerType{instance.LXC},
  1446  		}, {
  1447  			MachineTag:     "machine-1",
  1448  			ContainerTypes: []instance.ContainerType{instance.LXC},
  1449  		}, {
  1450  			MachineTag:     "machine-42",
  1451  			ContainerTypes: []instance.ContainerType{instance.LXC},
  1452  		},
  1453  		},
  1454  	}
  1455  	// Only machine 0 can have it's containers updated.
  1456  	results, err := aProvisioner.SetSupportedContainers(args)
  1457  	c.Assert(results, gc.DeepEquals, params.ErrorResults{
  1458  		Results: []params.ErrorResult{
  1459  			{Error: nil},
  1460  			{Error: apiservertesting.ErrUnauthorized},
  1461  			{Error: apiservertesting.ErrUnauthorized},
  1462  		},
  1463  	})
  1464  }
  1465  
  1466  func (s *withoutStateServerSuite) TestSupportsNoContainers(c *gc.C) {
  1467  	args := params.MachineContainersParams{
  1468  		Params: []params.MachineContainers{
  1469  			{
  1470  				MachineTag: "machine-0",
  1471  			},
  1472  		},
  1473  	}
  1474  	results, err := s.provisioner.SetSupportedContainers(args)
  1475  	c.Assert(err, jc.ErrorIsNil)
  1476  	c.Assert(results.Results, gc.HasLen, 1)
  1477  	c.Assert(results.Results[0].Error, gc.IsNil)
  1478  	m0, err := s.State.Machine("0")
  1479  	c.Assert(err, jc.ErrorIsNil)
  1480  	containers, ok := m0.SupportedContainers()
  1481  	c.Assert(ok, jc.IsTrue)
  1482  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{})
  1483  }
  1484  
  1485  var _ = gc.Suite(&withStateServerSuite{})
  1486  
  1487  type withStateServerSuite struct {
  1488  	provisionerSuite
  1489  }
  1490  
  1491  func (s *withStateServerSuite) SetUpTest(c *gc.C) {
  1492  	s.provisionerSuite.setUpTest(c, true)
  1493  }
  1494  
  1495  func (s *withStateServerSuite) TestAPIAddresses(c *gc.C) {
  1496  	hostPorts := [][]network.HostPort{
  1497  		network.NewHostPorts(1234, "0.1.2.3"),
  1498  	}
  1499  	err := s.State.SetAPIHostPorts(hostPorts)
  1500  	c.Assert(err, jc.ErrorIsNil)
  1501  
  1502  	result, err := s.provisioner.APIAddresses()
  1503  	c.Assert(err, jc.ErrorIsNil)
  1504  	c.Assert(result, gc.DeepEquals, params.StringsResult{
  1505  		Result: []string{"0.1.2.3:1234"},
  1506  	})
  1507  }
  1508  
  1509  func (s *withStateServerSuite) TestStateAddresses(c *gc.C) {
  1510  	addresses, err := s.State.Addresses()
  1511  	c.Assert(err, jc.ErrorIsNil)
  1512  
  1513  	result, err := s.provisioner.StateAddresses()
  1514  	c.Assert(err, jc.ErrorIsNil)
  1515  	c.Assert(result, gc.DeepEquals, params.StringsResult{
  1516  		Result: addresses,
  1517  	})
  1518  }
  1519  
  1520  func (s *withStateServerSuite) TestCACert(c *gc.C) {
  1521  	result := s.provisioner.CACert()
  1522  	c.Assert(result, gc.DeepEquals, params.BytesResult{
  1523  		Result: []byte(s.State.CACert()),
  1524  	})
  1525  }
  1526  
  1527  func (s *withoutStateServerSuite) TestWatchMachineErrorRetry(c *gc.C) {
  1528  	coretesting.SkipIfI386(c, "lp:1425569")
  1529  
  1530  	s.PatchValue(&provisioner.ErrorRetryWaitDelay, 2*coretesting.ShortWait)
  1531  	c.Assert(s.resources.Count(), gc.Equals, 0)
  1532  
  1533  	_, err := s.provisioner.WatchMachineErrorRetry()
  1534  	c.Assert(err, jc.ErrorIsNil)
  1535  
  1536  	// Verify the resources were registered and stop them when done.
  1537  	c.Assert(s.resources.Count(), gc.Equals, 1)
  1538  	resource := s.resources.Get("1")
  1539  	defer statetesting.AssertStop(c, resource)
  1540  
  1541  	// Check that the Watch has consumed the initial event ("returned"
  1542  	// in the Watch call)
  1543  	wc := statetesting.NewNotifyWatcherC(c, s.State, resource.(state.NotifyWatcher))
  1544  	wc.AssertNoChange()
  1545  
  1546  	// We should now get a time triggered change.
  1547  	wc.AssertOneChange()
  1548  
  1549  	// Make sure WatchMachineErrorRetry fails with a machine agent login.
  1550  	anAuthorizer := s.authorizer
  1551  	anAuthorizer.Tag = names.NewMachineTag("1")
  1552  	anAuthorizer.EnvironManager = false
  1553  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
  1554  	c.Assert(err, jc.ErrorIsNil)
  1555  
  1556  	result, err := aProvisioner.WatchMachineErrorRetry()
  1557  	c.Assert(err, gc.ErrorMatches, "permission denied")
  1558  	c.Assert(result, gc.DeepEquals, params.NotifyWatchResult{})
  1559  }
  1560  
  1561  func (s *withoutStateServerSuite) TestFindTools(c *gc.C) {
  1562  	args := params.FindToolsParams{
  1563  		MajorVersion: -1,
  1564  		MinorVersion: -1,
  1565  	}
  1566  	result, err := s.provisioner.FindTools(args)
  1567  	c.Assert(err, jc.ErrorIsNil)
  1568  	c.Assert(result.Error, gc.IsNil)
  1569  	c.Assert(result.List, gc.Not(gc.HasLen), 0)
  1570  	for _, tools := range result.List {
  1571  		url := fmt.Sprintf("https://%s/environment/%s/tools/%s",
  1572  			s.APIState.Addr(), coretesting.EnvironmentTag.Id(), tools.Version)
  1573  		c.Assert(tools.URL, gc.Equals, url)
  1574  	}
  1575  }
  1576  
  1577  type lxcDefaultMTUSuite struct {
  1578  	provisionerSuite
  1579  }
  1580  
  1581  var _ = gc.Suite(&lxcDefaultMTUSuite{})
  1582  
  1583  func (s *lxcDefaultMTUSuite) SetUpTest(c *gc.C) {
  1584  	// Because lxc-default-mtu is an immutable setting, we need to set
  1585  	// it in the default config JujuConnSuite uses, before the
  1586  	// environment is "created".
  1587  	s.DummyConfig = dummy.SampleConfig()
  1588  	s.DummyConfig["lxc-default-mtu"] = 9000
  1589  	s.provisionerSuite.SetUpTest(c)
  1590  
  1591  	stateConfig, err := s.State.EnvironConfig()
  1592  	c.Assert(err, jc.ErrorIsNil)
  1593  	value, ok := stateConfig.LXCDefaultMTU()
  1594  	c.Assert(ok, jc.IsTrue)
  1595  	c.Assert(value, gc.Equals, 9000)
  1596  	c.Logf("environ config lxc-default-mtu set to %v", value)
  1597  }
  1598  
  1599  func (s *lxcDefaultMTUSuite) TestContainerManagerConfigLXCDefaultMTU(c *gc.C) {
  1600  	managerConfig := s.getManagerConfig(c, instance.LXC)
  1601  	c.Assert(managerConfig, jc.DeepEquals, map[string]string{
  1602  		container.ConfigName:          "juju",
  1603  		container.ConfigLXCDefaultMTU: "9000",
  1604  
  1605  		"use-aufs":                   "false",
  1606  		container.ConfigIPForwarding: "true",
  1607  	})
  1608  
  1609  	// KVM instances are not affected.
  1610  	managerConfig = s.getManagerConfig(c, instance.KVM)
  1611  	c.Assert(managerConfig, jc.DeepEquals, map[string]string{
  1612  		container.ConfigName:         "juju",
  1613  		container.ConfigIPForwarding: "true",
  1614  	})
  1615  }