github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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  	jujutesting "github.com/juju/testing"
    13  	jc "github.com/juju/testing/checkers"
    14  	"github.com/juju/utils/proxy"
    15  	gc "gopkg.in/check.v1"
    16  
    17  	"github.com/juju/juju/apiserver/common"
    18  	commontesting "github.com/juju/juju/apiserver/common/testing"
    19  	"github.com/juju/juju/apiserver/params"
    20  	"github.com/juju/juju/apiserver/provisioner"
    21  	apiservertesting "github.com/juju/juju/apiserver/testing"
    22  	"github.com/juju/juju/constraints"
    23  	"github.com/juju/juju/container"
    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  	statetesting "github.com/juju/juju/state/testing"
    31  	"github.com/juju/juju/status"
    32  	"github.com/juju/juju/storage/poolmanager"
    33  	coretesting "github.com/juju/juju/testing"
    34  )
    35  
    36  func TestPackage(t *stdtesting.T) {
    37  	if jujutesting.RaceEnabled {
    38  		t.Skip("skipping package under -race, see LP 1517632")
    39  	}
    40  	coretesting.MgoTestPackage(t)
    41  }
    42  
    43  type provisionerSuite struct {
    44  	testing.JujuConnSuite
    45  
    46  	machines []*state.Machine
    47  
    48  	authorizer  apiservertesting.FakeAuthorizer
    49  	resources   *common.Resources
    50  	provisioner *provisioner.ProvisionerAPI
    51  }
    52  
    53  var _ = gc.Suite(&provisionerSuite{})
    54  
    55  func (s *provisionerSuite) SetUpTest(c *gc.C) {
    56  	s.setUpTest(c, false)
    57  }
    58  
    59  func (s *provisionerSuite) setUpTest(c *gc.C, withController bool) {
    60  	s.JujuConnSuite.ConfigAttrs = map[string]interface{}{
    61  		"image-stream": "daily",
    62  	}
    63  	s.JujuConnSuite.SetUpTest(c)
    64  	// We're testing with address allocation on by default. There are
    65  	// separate tests to check the behavior when the flag is not
    66  	// enabled.
    67  	s.SetFeatureFlags(feature.AddressAllocation)
    68  
    69  	// Reset previous machines (if any) and create 3 machines
    70  	// for the tests, plus an optional controller machine.
    71  	s.machines = nil
    72  	// Note that the specific machine ids allocated are assumed
    73  	// to be numerically consecutive from zero.
    74  	if withController {
    75  		s.machines = append(s.machines, testing.AddControllerMachine(c, s.State))
    76  	}
    77  	for i := 0; i < 5; i++ {
    78  		machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
    79  		c.Check(err, jc.ErrorIsNil)
    80  		s.machines = append(s.machines, machine)
    81  	}
    82  
    83  	// Create a FakeAuthorizer so we can check permissions,
    84  	// set up assuming we logged in as the environment manager.
    85  	s.authorizer = apiservertesting.FakeAuthorizer{
    86  		EnvironManager: true,
    87  	}
    88  
    89  	// Create the resource registry separately to track invocations to
    90  	// Register, and to register the root for tools URLs.
    91  	s.resources = common.NewResources()
    92  
    93  	// Create a provisioner API for the machine.
    94  	provisionerAPI, err := provisioner.NewProvisionerAPI(
    95  		s.State,
    96  		s.resources,
    97  		s.authorizer,
    98  	)
    99  	c.Assert(err, jc.ErrorIsNil)
   100  	s.provisioner = provisionerAPI
   101  }
   102  
   103  type withoutControllerSuite struct {
   104  	provisionerSuite
   105  	*commontesting.ModelWatcherTest
   106  }
   107  
   108  var _ = gc.Suite(&withoutControllerSuite{})
   109  
   110  func (s *withoutControllerSuite) SetUpTest(c *gc.C) {
   111  	s.setUpTest(c, false)
   112  	s.ModelWatcherTest = commontesting.NewModelWatcherTest(s.provisioner, s.State, s.resources, commontesting.HasSecrets)
   113  }
   114  
   115  func (s *withoutControllerSuite) TestProvisionerFailsWithNonMachineAgentNonManagerUser(c *gc.C) {
   116  	anAuthorizer := s.authorizer
   117  	anAuthorizer.EnvironManager = true
   118  	// Works with an environment manager, which is not a machine agent.
   119  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   120  	c.Assert(err, jc.ErrorIsNil)
   121  	c.Assert(aProvisioner, gc.NotNil)
   122  
   123  	// But fails with neither a machine agent or an environment manager.
   124  	anAuthorizer.EnvironManager = false
   125  	aProvisioner, err = provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   126  	c.Assert(err, gc.NotNil)
   127  	c.Assert(aProvisioner, gc.IsNil)
   128  	c.Assert(err, gc.ErrorMatches, "permission denied")
   129  }
   130  
   131  func (s *withoutControllerSuite) TestSetPasswords(c *gc.C) {
   132  	args := params.EntityPasswords{
   133  		Changes: []params.EntityPassword{
   134  			{Tag: s.machines[0].Tag().String(), Password: "xxx0-1234567890123457890"},
   135  			{Tag: s.machines[1].Tag().String(), Password: "xxx1-1234567890123457890"},
   136  			{Tag: s.machines[2].Tag().String(), Password: "xxx2-1234567890123457890"},
   137  			{Tag: s.machines[3].Tag().String(), Password: "xxx3-1234567890123457890"},
   138  			{Tag: s.machines[4].Tag().String(), Password: "xxx4-1234567890123457890"},
   139  			{Tag: "machine-42", Password: "foo"},
   140  			{Tag: "unit-foo-0", Password: "zzz"},
   141  			{Tag: "service-bar", Password: "abc"},
   142  		},
   143  	}
   144  	results, err := s.provisioner.SetPasswords(args)
   145  	c.Assert(err, jc.ErrorIsNil)
   146  	c.Assert(results, gc.DeepEquals, params.ErrorResults{
   147  		Results: []params.ErrorResult{
   148  			{nil},
   149  			{nil},
   150  			{nil},
   151  			{nil},
   152  			{nil},
   153  			{apiservertesting.NotFoundError("machine 42")},
   154  			{apiservertesting.ErrUnauthorized},
   155  			{apiservertesting.ErrUnauthorized},
   156  		},
   157  	})
   158  
   159  	// Verify the changes to both machines succeeded.
   160  	for i, machine := range s.machines {
   161  		c.Logf("trying %q password", machine.Tag())
   162  		err = machine.Refresh()
   163  		c.Assert(err, jc.ErrorIsNil)
   164  		changed := machine.PasswordValid(fmt.Sprintf("xxx%d-1234567890123457890", i))
   165  		c.Assert(changed, jc.IsTrue)
   166  	}
   167  }
   168  
   169  func (s *withoutControllerSuite) TestShortSetPasswords(c *gc.C) {
   170  	args := params.EntityPasswords{
   171  		Changes: []params.EntityPassword{
   172  			{Tag: s.machines[1].Tag().String(), Password: "xxx1"},
   173  		},
   174  	}
   175  	results, err := s.provisioner.SetPasswords(args)
   176  	c.Assert(err, jc.ErrorIsNil)
   177  	c.Assert(results.Results, gc.HasLen, 1)
   178  	c.Assert(results.Results[0].Error, gc.ErrorMatches,
   179  		"password is only 4 bytes long, and is not a valid Agent password")
   180  }
   181  
   182  func (s *withoutControllerSuite) TestLifeAsMachineAgent(c *gc.C) {
   183  	// NOTE: This and the next call serve to test the two
   184  	// different authorization schemes:
   185  	// 1. Machine agents can access their own machine and
   186  	// any container that has their own machine as parent;
   187  	// 2. Environment managers can access any machine without
   188  	// a parent.
   189  	// There's no need to repeat this test for each method,
   190  	// because the authorization logic is common.
   191  
   192  	// Login as a machine agent for machine 0.
   193  	anAuthorizer := s.authorizer
   194  	anAuthorizer.EnvironManager = false
   195  	anAuthorizer.Tag = s.machines[0].Tag()
   196  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   197  	c.Assert(err, jc.ErrorIsNil)
   198  	c.Assert(aProvisioner, gc.NotNil)
   199  
   200  	// Make the machine dead before trying to add containers.
   201  	err = s.machines[0].EnsureDead()
   202  	c.Assert(err, jc.ErrorIsNil)
   203  
   204  	// Create some containers to work on.
   205  	template := state.MachineTemplate{
   206  		Series: "quantal",
   207  		Jobs:   []state.MachineJob{state.JobHostUnits},
   208  	}
   209  	var containers []*state.Machine
   210  	for i := 0; i < 3; i++ {
   211  		container, err := s.State.AddMachineInsideMachine(template, s.machines[0].Id(), instance.LXC)
   212  		c.Check(err, jc.ErrorIsNil)
   213  		containers = append(containers, container)
   214  	}
   215  	// Make one container dead.
   216  	err = containers[1].EnsureDead()
   217  	c.Assert(err, jc.ErrorIsNil)
   218  
   219  	args := params.Entities{Entities: []params.Entity{
   220  		{Tag: s.machines[0].Tag().String()},
   221  		{Tag: s.machines[1].Tag().String()},
   222  		{Tag: containers[0].Tag().String()},
   223  		{Tag: containers[1].Tag().String()},
   224  		{Tag: containers[2].Tag().String()},
   225  		{Tag: "machine-42"},
   226  		{Tag: "unit-foo-0"},
   227  		{Tag: "service-bar"},
   228  	}}
   229  	result, err := aProvisioner.Life(args)
   230  	c.Assert(err, jc.ErrorIsNil)
   231  	c.Assert(result, gc.DeepEquals, params.LifeResults{
   232  		Results: []params.LifeResult{
   233  			{Life: "dead"},
   234  			{Error: apiservertesting.ErrUnauthorized},
   235  			{Life: "alive"},
   236  			{Life: "dead"},
   237  			{Life: "alive"},
   238  			{Error: apiservertesting.ErrUnauthorized},
   239  			{Error: apiservertesting.ErrUnauthorized},
   240  			{Error: apiservertesting.ErrUnauthorized},
   241  		},
   242  	})
   243  }
   244  
   245  func (s *withoutControllerSuite) TestLifeAsEnvironManager(c *gc.C) {
   246  	err := s.machines[1].EnsureDead()
   247  	c.Assert(err, jc.ErrorIsNil)
   248  	err = s.machines[1].Refresh()
   249  	c.Assert(err, jc.ErrorIsNil)
   250  	c.Assert(s.machines[0].Life(), gc.Equals, state.Alive)
   251  	c.Assert(s.machines[1].Life(), gc.Equals, state.Dead)
   252  	c.Assert(s.machines[2].Life(), gc.Equals, state.Alive)
   253  
   254  	args := params.Entities{Entities: []params.Entity{
   255  		{Tag: s.machines[0].Tag().String()},
   256  		{Tag: s.machines[1].Tag().String()},
   257  		{Tag: s.machines[2].Tag().String()},
   258  		{Tag: "machine-42"},
   259  		{Tag: "unit-foo-0"},
   260  		{Tag: "service-bar"},
   261  	}}
   262  	result, err := s.provisioner.Life(args)
   263  	c.Assert(err, jc.ErrorIsNil)
   264  	c.Assert(result, gc.DeepEquals, params.LifeResults{
   265  		Results: []params.LifeResult{
   266  			{Life: "alive"},
   267  			{Life: "dead"},
   268  			{Life: "alive"},
   269  			{Error: apiservertesting.NotFoundError("machine 42")},
   270  			{Error: apiservertesting.ErrUnauthorized},
   271  			{Error: apiservertesting.ErrUnauthorized},
   272  		},
   273  	})
   274  
   275  	// Remove the subordinate and make sure it's detected.
   276  	err = s.machines[1].Remove()
   277  	c.Assert(err, jc.ErrorIsNil)
   278  	err = s.machines[1].Refresh()
   279  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   280  
   281  	result, err = s.provisioner.Life(params.Entities{
   282  		Entities: []params.Entity{
   283  			{Tag: s.machines[1].Tag().String()},
   284  		},
   285  	})
   286  	c.Assert(err, jc.ErrorIsNil)
   287  	c.Assert(result, gc.DeepEquals, params.LifeResults{
   288  		Results: []params.LifeResult{
   289  			{Error: apiservertesting.NotFoundError("machine 1")},
   290  		},
   291  	})
   292  }
   293  
   294  func (s *withoutControllerSuite) TestRemove(c *gc.C) {
   295  	err := s.machines[1].EnsureDead()
   296  	c.Assert(err, jc.ErrorIsNil)
   297  	s.assertLife(c, 0, state.Alive)
   298  	s.assertLife(c, 1, state.Dead)
   299  	s.assertLife(c, 2, state.Alive)
   300  
   301  	args := params.Entities{Entities: []params.Entity{
   302  		{Tag: s.machines[0].Tag().String()},
   303  		{Tag: s.machines[1].Tag().String()},
   304  		{Tag: s.machines[2].Tag().String()},
   305  		{Tag: "machine-42"},
   306  		{Tag: "unit-foo-0"},
   307  		{Tag: "service-bar"},
   308  	}}
   309  	result, err := s.provisioner.Remove(args)
   310  	c.Assert(err, jc.ErrorIsNil)
   311  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   312  		Results: []params.ErrorResult{
   313  			{&params.Error{Message: `cannot remove entity "machine-0": still alive`}},
   314  			{nil},
   315  			{&params.Error{Message: `cannot remove entity "machine-2": still alive`}},
   316  			{apiservertesting.NotFoundError("machine 42")},
   317  			{apiservertesting.ErrUnauthorized},
   318  			{apiservertesting.ErrUnauthorized},
   319  		},
   320  	})
   321  
   322  	// Verify the changes.
   323  	s.assertLife(c, 0, state.Alive)
   324  	err = s.machines[2].Refresh()
   325  	c.Assert(err, jc.ErrorIsNil)
   326  	s.assertLife(c, 2, state.Alive)
   327  }
   328  
   329  func (s *withoutControllerSuite) TestSetStatus(c *gc.C) {
   330  	err := s.machines[0].SetStatus(status.StatusStarted, "blah", nil)
   331  	c.Assert(err, jc.ErrorIsNil)
   332  	err = s.machines[1].SetStatus(status.StatusStopped, "foo", nil)
   333  	c.Assert(err, jc.ErrorIsNil)
   334  	err = s.machines[2].SetStatus(status.StatusError, "not really", nil)
   335  	c.Assert(err, jc.ErrorIsNil)
   336  
   337  	args := params.SetStatus{
   338  		Entities: []params.EntityStatusArgs{
   339  			{Tag: s.machines[0].Tag().String(), Status: status.StatusError, Info: "not really",
   340  				Data: map[string]interface{}{"foo": "bar"}},
   341  			{Tag: s.machines[1].Tag().String(), Status: status.StatusStopped, Info: "foobar"},
   342  			{Tag: s.machines[2].Tag().String(), Status: status.StatusStarted, Info: "again"},
   343  			{Tag: "machine-42", Status: status.StatusStarted, Info: "blah"},
   344  			{Tag: "unit-foo-0", Status: status.StatusStopped, Info: "foobar"},
   345  			{Tag: "service-bar", Status: status.StatusStopped, Info: "foobar"},
   346  		}}
   347  	result, err := s.provisioner.SetStatus(args)
   348  	c.Assert(err, jc.ErrorIsNil)
   349  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   350  		Results: []params.ErrorResult{
   351  			{nil},
   352  			{nil},
   353  			{nil},
   354  			{apiservertesting.NotFoundError("machine 42")},
   355  			{apiservertesting.ErrUnauthorized},
   356  			{apiservertesting.ErrUnauthorized},
   357  		},
   358  	})
   359  
   360  	// Verify the changes.
   361  	s.assertStatus(c, 0, status.StatusError, "not really", map[string]interface{}{"foo": "bar"})
   362  	s.assertStatus(c, 1, status.StatusStopped, "foobar", map[string]interface{}{})
   363  	s.assertStatus(c, 2, status.StatusStarted, "again", map[string]interface{}{})
   364  }
   365  
   366  func (s *withoutControllerSuite) TestMachinesWithTransientErrors(c *gc.C) {
   367  	err := s.machines[0].SetStatus(status.StatusStarted, "blah", nil)
   368  	c.Assert(err, jc.ErrorIsNil)
   369  	err = s.machines[1].SetStatus(status.StatusError, "transient error",
   370  		map[string]interface{}{"transient": true, "foo": "bar"})
   371  	c.Assert(err, jc.ErrorIsNil)
   372  	err = s.machines[2].SetStatus(status.StatusError, "error", map[string]interface{}{"transient": false})
   373  	c.Assert(err, jc.ErrorIsNil)
   374  	err = s.machines[3].SetStatus(status.StatusError, "error", nil)
   375  	c.Assert(err, jc.ErrorIsNil)
   376  	// Machine 4 is provisioned but error not reset yet.
   377  	err = s.machines[4].SetStatus(status.StatusError, "transient error",
   378  		map[string]interface{}{"transient": true, "foo": "bar"})
   379  	c.Assert(err, jc.ErrorIsNil)
   380  	hwChars := instance.MustParseHardware("arch=i386", "mem=4G")
   381  	err = s.machines[4].SetProvisioned("i-am", "fake_nonce", &hwChars)
   382  	c.Assert(err, jc.ErrorIsNil)
   383  
   384  	result, err := s.provisioner.MachinesWithTransientErrors()
   385  	c.Assert(err, jc.ErrorIsNil)
   386  	c.Assert(result, gc.DeepEquals, params.StatusResults{
   387  		Results: []params.StatusResult{
   388  			{Id: "1", Life: "alive", Status: "error", Info: "transient error",
   389  				Data: map[string]interface{}{"transient": true, "foo": "bar"}},
   390  		},
   391  	})
   392  }
   393  
   394  func (s *withoutControllerSuite) TestMachinesWithTransientErrorsPermission(c *gc.C) {
   395  	// Machines where there's permission issues are omitted.
   396  	anAuthorizer := s.authorizer
   397  	anAuthorizer.EnvironManager = false
   398  	anAuthorizer.Tag = names.NewMachineTag("1")
   399  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources,
   400  		anAuthorizer)
   401  	err = s.machines[0].SetStatus(status.StatusStarted, "blah", nil)
   402  	c.Assert(err, jc.ErrorIsNil)
   403  	err = s.machines[1].SetStatus(status.StatusError, "transient error",
   404  		map[string]interface{}{"transient": true, "foo": "bar"})
   405  	c.Assert(err, jc.ErrorIsNil)
   406  	err = s.machines[2].SetStatus(status.StatusError, "error", map[string]interface{}{"transient": false})
   407  	c.Assert(err, jc.ErrorIsNil)
   408  	err = s.machines[3].SetStatus(status.StatusError, "error", nil)
   409  	c.Assert(err, jc.ErrorIsNil)
   410  
   411  	result, err := aProvisioner.MachinesWithTransientErrors()
   412  	c.Assert(err, jc.ErrorIsNil)
   413  	c.Assert(result, gc.DeepEquals, params.StatusResults{
   414  		Results: []params.StatusResult{
   415  			{Id: "1", Life: "alive", Status: "error", Info: "transient error",
   416  				Data: map[string]interface{}{"transient": true, "foo": "bar"}},
   417  		},
   418  	})
   419  }
   420  
   421  func (s *withoutControllerSuite) TestEnsureDead(c *gc.C) {
   422  	err := s.machines[1].EnsureDead()
   423  	c.Assert(err, jc.ErrorIsNil)
   424  	s.assertLife(c, 0, state.Alive)
   425  	s.assertLife(c, 1, state.Dead)
   426  	s.assertLife(c, 2, state.Alive)
   427  
   428  	args := params.Entities{Entities: []params.Entity{
   429  		{Tag: s.machines[0].Tag().String()},
   430  		{Tag: s.machines[1].Tag().String()},
   431  		{Tag: s.machines[2].Tag().String()},
   432  		{Tag: "machine-42"},
   433  		{Tag: "unit-foo-0"},
   434  		{Tag: "service-bar"},
   435  	}}
   436  	result, err := s.provisioner.EnsureDead(args)
   437  	c.Assert(err, jc.ErrorIsNil)
   438  	c.Assert(result, gc.DeepEquals, params.ErrorResults{
   439  		Results: []params.ErrorResult{
   440  			{nil},
   441  			{nil},
   442  			{nil},
   443  			{apiservertesting.NotFoundError("machine 42")},
   444  			{apiservertesting.ErrUnauthorized},
   445  			{apiservertesting.ErrUnauthorized},
   446  		},
   447  	})
   448  
   449  	// Verify the changes.
   450  	s.assertLife(c, 0, state.Dead)
   451  	s.assertLife(c, 1, state.Dead)
   452  	s.assertLife(c, 2, state.Dead)
   453  }
   454  
   455  func (s *withoutControllerSuite) assertLife(c *gc.C, index int, expectLife state.Life) {
   456  	err := s.machines[index].Refresh()
   457  	c.Assert(err, jc.ErrorIsNil)
   458  	c.Assert(s.machines[index].Life(), gc.Equals, expectLife)
   459  }
   460  
   461  func (s *withoutControllerSuite) assertStatus(c *gc.C, index int, expectStatus status.Status, expectInfo string,
   462  	expectData map[string]interface{}) {
   463  
   464  	statusInfo, err := s.machines[index].Status()
   465  	c.Assert(err, jc.ErrorIsNil)
   466  	c.Assert(statusInfo.Status, gc.Equals, expectStatus)
   467  	c.Assert(statusInfo.Message, gc.Equals, expectInfo)
   468  	c.Assert(statusInfo.Data, gc.DeepEquals, expectData)
   469  }
   470  
   471  func (s *withoutControllerSuite) TestWatchContainers(c *gc.C) {
   472  	c.Assert(s.resources.Count(), gc.Equals, 0)
   473  
   474  	args := params.WatchContainers{Params: []params.WatchContainer{
   475  		{MachineTag: s.machines[0].Tag().String(), ContainerType: string(instance.LXC)},
   476  		{MachineTag: s.machines[1].Tag().String(), ContainerType: string(instance.KVM)},
   477  		{MachineTag: "machine-42", ContainerType: ""},
   478  		{MachineTag: "unit-foo-0", ContainerType: ""},
   479  		{MachineTag: "service-bar", ContainerType: ""},
   480  	}}
   481  	result, err := s.provisioner.WatchContainers(args)
   482  	c.Assert(err, jc.ErrorIsNil)
   483  	c.Assert(result, gc.DeepEquals, params.StringsWatchResults{
   484  		Results: []params.StringsWatchResult{
   485  			{StringsWatcherId: "1", Changes: []string{}},
   486  			{StringsWatcherId: "2", Changes: []string{}},
   487  			{Error: apiservertesting.NotFoundError("machine 42")},
   488  			{Error: apiservertesting.ErrUnauthorized},
   489  			{Error: apiservertesting.ErrUnauthorized},
   490  		},
   491  	})
   492  
   493  	// Verify the resources were registered and stop them when done.
   494  	c.Assert(s.resources.Count(), gc.Equals, 2)
   495  	m0Watcher := s.resources.Get("1")
   496  	defer statetesting.AssertStop(c, m0Watcher)
   497  	m1Watcher := s.resources.Get("2")
   498  	defer statetesting.AssertStop(c, m1Watcher)
   499  
   500  	// Check that the Watch has consumed the initial event ("returned"
   501  	// in the Watch call)
   502  	wc0 := statetesting.NewStringsWatcherC(c, s.State, m0Watcher.(state.StringsWatcher))
   503  	wc0.AssertNoChange()
   504  	wc1 := statetesting.NewStringsWatcherC(c, s.State, m1Watcher.(state.StringsWatcher))
   505  	wc1.AssertNoChange()
   506  }
   507  
   508  func (s *withoutControllerSuite) TestWatchAllContainers(c *gc.C) {
   509  	c.Assert(s.resources.Count(), gc.Equals, 0)
   510  
   511  	args := params.WatchContainers{Params: []params.WatchContainer{
   512  		{MachineTag: s.machines[0].Tag().String()},
   513  		{MachineTag: s.machines[1].Tag().String()},
   514  		{MachineTag: "machine-42"},
   515  		{MachineTag: "unit-foo-0"},
   516  		{MachineTag: "service-bar"},
   517  	}}
   518  	result, err := s.provisioner.WatchAllContainers(args)
   519  	c.Assert(err, jc.ErrorIsNil)
   520  	c.Assert(result, gc.DeepEquals, params.StringsWatchResults{
   521  		Results: []params.StringsWatchResult{
   522  			{StringsWatcherId: "1", Changes: []string{}},
   523  			{StringsWatcherId: "2", Changes: []string{}},
   524  			{Error: apiservertesting.NotFoundError("machine 42")},
   525  			{Error: apiservertesting.ErrUnauthorized},
   526  			{Error: apiservertesting.ErrUnauthorized},
   527  		},
   528  	})
   529  
   530  	// Verify the resources were registered and stop them when done.
   531  	c.Assert(s.resources.Count(), gc.Equals, 2)
   532  	m0Watcher := s.resources.Get("1")
   533  	defer statetesting.AssertStop(c, m0Watcher)
   534  	m1Watcher := s.resources.Get("2")
   535  	defer statetesting.AssertStop(c, m1Watcher)
   536  
   537  	// Check that the Watch has consumed the initial event ("returned"
   538  	// in the Watch call)
   539  	wc0 := statetesting.NewStringsWatcherC(c, s.State, m0Watcher.(state.StringsWatcher))
   540  	wc0.AssertNoChange()
   541  	wc1 := statetesting.NewStringsWatcherC(c, s.State, m1Watcher.(state.StringsWatcher))
   542  	wc1.AssertNoChange()
   543  }
   544  
   545  func (s *withoutControllerSuite) TestModelConfigNonManager(c *gc.C) {
   546  	// Now test it with a non-environment manager and make sure
   547  	// the secret attributes are masked.
   548  	anAuthorizer := s.authorizer
   549  	anAuthorizer.Tag = names.NewMachineTag("1")
   550  	anAuthorizer.EnvironManager = false
   551  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources,
   552  		anAuthorizer)
   553  	c.Assert(err, jc.ErrorIsNil)
   554  	s.AssertModelConfig(c, aProvisioner, commontesting.NoSecrets)
   555  }
   556  
   557  func (s *withoutControllerSuite) TestStatus(c *gc.C) {
   558  	err := s.machines[0].SetStatus(status.StatusStarted, "blah", nil)
   559  	c.Assert(err, jc.ErrorIsNil)
   560  	err = s.machines[1].SetStatus(status.StatusStopped, "foo", nil)
   561  	c.Assert(err, jc.ErrorIsNil)
   562  	err = s.machines[2].SetStatus(status.StatusError, "not really", map[string]interface{}{"foo": "bar"})
   563  	c.Assert(err, jc.ErrorIsNil)
   564  
   565  	args := params.Entities{Entities: []params.Entity{
   566  		{Tag: s.machines[0].Tag().String()},
   567  		{Tag: s.machines[1].Tag().String()},
   568  		{Tag: s.machines[2].Tag().String()},
   569  		{Tag: "machine-42"},
   570  		{Tag: "unit-foo-0"},
   571  		{Tag: "service-bar"},
   572  	}}
   573  	result, err := s.provisioner.Status(args)
   574  	c.Assert(err, jc.ErrorIsNil)
   575  	// Zero out the updated timestamps so we can easily check the results.
   576  	for i, statusResult := range result.Results {
   577  		r := statusResult
   578  		if r.Status != "" {
   579  			c.Assert(r.Since, gc.NotNil)
   580  		}
   581  		r.Since = nil
   582  		result.Results[i] = r
   583  	}
   584  	c.Assert(result, gc.DeepEquals, params.StatusResults{
   585  		Results: []params.StatusResult{
   586  			{Status: status.StatusStarted, Info: "blah", Data: map[string]interface{}{}},
   587  			{Status: status.StatusStopped, Info: "foo", Data: map[string]interface{}{}},
   588  			{Status: status.StatusError, Info: "not really", Data: map[string]interface{}{"foo": "bar"}},
   589  			{Error: apiservertesting.NotFoundError("machine 42")},
   590  			{Error: apiservertesting.ErrUnauthorized},
   591  			{Error: apiservertesting.ErrUnauthorized},
   592  		},
   593  	})
   594  }
   595  
   596  func (s *withoutControllerSuite) TestSeries(c *gc.C) {
   597  	// Add a machine with different series.
   598  	foobarMachine, err := s.State.AddMachine("foobar", state.JobHostUnits)
   599  	c.Assert(err, jc.ErrorIsNil)
   600  
   601  	args := params.Entities{Entities: []params.Entity{
   602  		{Tag: s.machines[0].Tag().String()},
   603  		{Tag: foobarMachine.Tag().String()},
   604  		{Tag: s.machines[2].Tag().String()},
   605  		{Tag: "machine-42"},
   606  		{Tag: "unit-foo-0"},
   607  		{Tag: "service-bar"},
   608  	}}
   609  	result, err := s.provisioner.Series(args)
   610  	c.Assert(err, jc.ErrorIsNil)
   611  	c.Assert(result, gc.DeepEquals, params.StringResults{
   612  		Results: []params.StringResult{
   613  			{Result: s.machines[0].Series()},
   614  			{Result: foobarMachine.Series()},
   615  			{Result: s.machines[2].Series()},
   616  			{Error: apiservertesting.NotFoundError("machine 42")},
   617  			{Error: apiservertesting.ErrUnauthorized},
   618  			{Error: apiservertesting.ErrUnauthorized},
   619  		},
   620  	})
   621  }
   622  
   623  func (s *withoutControllerSuite) TestDistributionGroup(c *gc.C) {
   624  	addUnits := func(name string, machines ...*state.Machine) (units []*state.Unit) {
   625  		svc := s.AddTestingService(c, name, s.AddTestingCharm(c, name))
   626  		for _, m := range machines {
   627  			unit, err := svc.AddUnit()
   628  			c.Assert(err, jc.ErrorIsNil)
   629  			err = unit.AssignToMachine(m)
   630  			c.Assert(err, jc.ErrorIsNil)
   631  			units = append(units, unit)
   632  		}
   633  		return units
   634  	}
   635  	setProvisioned := func(id string) {
   636  		m, err := s.State.Machine(id)
   637  		c.Assert(err, jc.ErrorIsNil)
   638  		err = m.SetProvisioned(instance.Id("machine-"+id+"-inst"), "nonce", nil)
   639  		c.Assert(err, jc.ErrorIsNil)
   640  	}
   641  
   642  	mysqlUnit := addUnits("mysql", s.machines[0], s.machines[3])[0]
   643  	wordpressUnits := addUnits("wordpress", s.machines[0], s.machines[1], s.machines[2])
   644  
   645  	// Unassign wordpress/1 from machine-1.
   646  	// The unit should not show up in the results.
   647  	err := wordpressUnits[1].UnassignFromMachine()
   648  	c.Assert(err, jc.ErrorIsNil)
   649  
   650  	// Provision machines 1, 2 and 3. Machine-0 remains
   651  	// unprovisioned, and machine-1 has no units, and so
   652  	// neither will show up in the results.
   653  	setProvisioned("1")
   654  	setProvisioned("2")
   655  	setProvisioned("3")
   656  
   657  	// Add a few controllers, provision two of them.
   658  	_, err = s.State.EnableHA(3, constraints.Value{}, "quantal", nil)
   659  	c.Assert(err, jc.ErrorIsNil)
   660  	setProvisioned("5")
   661  	setProvisioned("7")
   662  
   663  	// Create a logging service, subordinate to mysql.
   664  	s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging"))
   665  	eps, err := s.State.InferEndpoints("mysql", "logging")
   666  	c.Assert(err, jc.ErrorIsNil)
   667  	rel, err := s.State.AddRelation(eps...)
   668  	c.Assert(err, jc.ErrorIsNil)
   669  	ru, err := rel.Unit(mysqlUnit)
   670  	c.Assert(err, jc.ErrorIsNil)
   671  	err = ru.EnterScope(nil)
   672  	c.Assert(err, jc.ErrorIsNil)
   673  
   674  	args := params.Entities{Entities: []params.Entity{
   675  		{Tag: s.machines[0].Tag().String()},
   676  		{Tag: s.machines[1].Tag().String()},
   677  		{Tag: s.machines[2].Tag().String()},
   678  		{Tag: s.machines[3].Tag().String()},
   679  		{Tag: "machine-5"},
   680  	}}
   681  	result, err := s.provisioner.DistributionGroup(args)
   682  	c.Assert(err, jc.ErrorIsNil)
   683  	c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{
   684  		Results: []params.DistributionGroupResult{
   685  			{Result: []instance.Id{"machine-2-inst", "machine-3-inst"}},
   686  			{Result: []instance.Id{}},
   687  			{Result: []instance.Id{"machine-2-inst"}},
   688  			{Result: []instance.Id{"machine-3-inst"}},
   689  			{Result: []instance.Id{"machine-5-inst", "machine-7-inst"}},
   690  		},
   691  	})
   692  }
   693  
   694  func (s *withoutControllerSuite) TestDistributionGroupEnvironManagerAuth(c *gc.C) {
   695  	args := params.Entities{Entities: []params.Entity{
   696  		{Tag: "machine-0"},
   697  		{Tag: "machine-42"},
   698  		{Tag: "machine-0-lxc-99"},
   699  		{Tag: "unit-foo-0"},
   700  		{Tag: "service-bar"},
   701  	}}
   702  	result, err := s.provisioner.DistributionGroup(args)
   703  	c.Assert(err, jc.ErrorIsNil)
   704  	c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{
   705  		Results: []params.DistributionGroupResult{
   706  			// environ manager may access any top-level machines.
   707  			{Result: []instance.Id{}},
   708  			{Error: apiservertesting.NotFoundError("machine 42")},
   709  			// only a machine agent for the container or its
   710  			// parent may access it.
   711  			{Error: apiservertesting.ErrUnauthorized},
   712  			// non-machines always unauthorized
   713  			{Error: apiservertesting.ErrUnauthorized},
   714  			{Error: apiservertesting.ErrUnauthorized},
   715  		},
   716  	})
   717  }
   718  
   719  func (s *withoutControllerSuite) TestDistributionGroupMachineAgentAuth(c *gc.C) {
   720  	anAuthorizer := s.authorizer
   721  	anAuthorizer.Tag = names.NewMachineTag("1")
   722  	anAuthorizer.EnvironManager = false
   723  	provisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   724  	c.Check(err, jc.ErrorIsNil)
   725  	args := params.Entities{Entities: []params.Entity{
   726  		{Tag: "machine-0"},
   727  		{Tag: "machine-1"},
   728  		{Tag: "machine-42"},
   729  		{Tag: "machine-0-lxc-99"},
   730  		{Tag: "machine-1-lxc-99"},
   731  		{Tag: "machine-1-lxc-99-lxc-100"},
   732  	}}
   733  	result, err := provisioner.DistributionGroup(args)
   734  	c.Assert(err, jc.ErrorIsNil)
   735  	c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{
   736  		Results: []params.DistributionGroupResult{
   737  			{Error: apiservertesting.ErrUnauthorized},
   738  			{Result: []instance.Id{}},
   739  			{Error: apiservertesting.ErrUnauthorized},
   740  			// only a machine agent for the container or its
   741  			// parent may access it.
   742  			{Error: apiservertesting.ErrUnauthorized},
   743  			{Error: apiservertesting.NotFoundError("machine 1/lxc/99")},
   744  			{Error: apiservertesting.ErrUnauthorized},
   745  		},
   746  	})
   747  }
   748  
   749  func (s *withoutControllerSuite) TestConstraints(c *gc.C) {
   750  	// Add a machine with some constraints.
   751  	cons := constraints.MustParse("cpu-cores=123", "mem=8G")
   752  	template := state.MachineTemplate{
   753  		Series:      "quantal",
   754  		Jobs:        []state.MachineJob{state.JobHostUnits},
   755  		Constraints: cons,
   756  	}
   757  	consMachine, err := s.State.AddOneMachine(template)
   758  	c.Assert(err, jc.ErrorIsNil)
   759  
   760  	machine0Constraints, err := s.machines[0].Constraints()
   761  	c.Assert(err, jc.ErrorIsNil)
   762  
   763  	args := params.Entities{Entities: []params.Entity{
   764  		{Tag: s.machines[0].Tag().String()},
   765  		{Tag: consMachine.Tag().String()},
   766  		{Tag: "machine-42"},
   767  		{Tag: "unit-foo-0"},
   768  		{Tag: "service-bar"},
   769  	}}
   770  	result, err := s.provisioner.Constraints(args)
   771  	c.Assert(err, jc.ErrorIsNil)
   772  	c.Assert(result, gc.DeepEquals, params.ConstraintsResults{
   773  		Results: []params.ConstraintsResult{
   774  			{Constraints: machine0Constraints},
   775  			{Constraints: template.Constraints},
   776  			{Error: apiservertesting.NotFoundError("machine 42")},
   777  			{Error: apiservertesting.ErrUnauthorized},
   778  			{Error: apiservertesting.ErrUnauthorized},
   779  		},
   780  	})
   781  }
   782  
   783  func (s *withoutControllerSuite) TestSetInstanceInfo(c *gc.C) {
   784  	s.registerStorageProviders(c, "static")
   785  
   786  	pm := poolmanager.New(state.NewStateSettings(s.State))
   787  	_, err := pm.Create("static-pool", "static", map[string]interface{}{"foo": "bar"})
   788  	c.Assert(err, jc.ErrorIsNil)
   789  	err = s.State.UpdateModelConfig(map[string]interface{}{
   790  		"storage-default-block-source": "static-pool",
   791  	}, nil, nil)
   792  	c.Assert(err, jc.ErrorIsNil)
   793  
   794  	// Provision machine 0 first.
   795  	hwChars := instance.MustParseHardware("arch=i386", "mem=4G")
   796  	err = s.machines[0].SetInstanceInfo("i-am", "fake_nonce", &hwChars, nil, nil, nil, nil)
   797  	c.Assert(err, jc.ErrorIsNil)
   798  
   799  	volumesMachine, err := s.State.AddOneMachine(state.MachineTemplate{
   800  		Series: "quantal",
   801  		Jobs:   []state.MachineJob{state.JobHostUnits},
   802  		Volumes: []state.MachineVolumeParams{{
   803  			Volume: state.VolumeParams{Size: 1000},
   804  		}},
   805  	})
   806  	c.Assert(err, jc.ErrorIsNil)
   807  
   808  	args := params.InstancesInfo{Machines: []params.InstanceInfo{{
   809  		Tag:        s.machines[0].Tag().String(),
   810  		InstanceId: "i-was",
   811  		Nonce:      "fake_nonce",
   812  	}, {
   813  		Tag:             s.machines[1].Tag().String(),
   814  		InstanceId:      "i-will",
   815  		Nonce:           "fake_nonce",
   816  		Characteristics: &hwChars,
   817  	}, {
   818  		Tag:             s.machines[2].Tag().String(),
   819  		InstanceId:      "i-am-too",
   820  		Nonce:           "fake",
   821  		Characteristics: nil,
   822  	}, {
   823  		Tag:        volumesMachine.Tag().String(),
   824  		InstanceId: "i-am-also",
   825  		Nonce:      "fake",
   826  		Volumes: []params.Volume{{
   827  			VolumeTag: "volume-0",
   828  			Info: params.VolumeInfo{
   829  				VolumeId: "vol-0",
   830  				Size:     1234,
   831  			},
   832  		}},
   833  		VolumeAttachments: map[string]params.VolumeAttachmentInfo{
   834  			"volume-0": {
   835  				DeviceName: "sda",
   836  			},
   837  		},
   838  	},
   839  		{Tag: "machine-42"},
   840  		{Tag: "unit-foo-0"},
   841  		{Tag: "service-bar"},
   842  	}}
   843  	result, err := s.provisioner.SetInstanceInfo(args)
   844  	c.Assert(err, jc.ErrorIsNil)
   845  	c.Assert(result, jc.DeepEquals, params.ErrorResults{
   846  		Results: []params.ErrorResult{
   847  			{&params.Error{
   848  				Message: `cannot record provisioning info for "i-was": cannot set instance data for machine "0": already set`,
   849  			}},
   850  			{nil},
   851  			{nil},
   852  			{nil},
   853  			{apiservertesting.NotFoundError("machine 42")},
   854  			{apiservertesting.ErrUnauthorized},
   855  			{apiservertesting.ErrUnauthorized},
   856  		},
   857  	})
   858  
   859  	// Verify machine 1 and 2 were provisioned.
   860  	c.Assert(s.machines[1].Refresh(), gc.IsNil)
   861  	c.Assert(s.machines[2].Refresh(), gc.IsNil)
   862  
   863  	instanceId, err := s.machines[1].InstanceId()
   864  	c.Assert(err, jc.ErrorIsNil)
   865  	c.Check(instanceId, gc.Equals, instance.Id("i-will"))
   866  	instanceId, err = s.machines[2].InstanceId()
   867  	c.Assert(err, jc.ErrorIsNil)
   868  	c.Check(instanceId, gc.Equals, instance.Id("i-am-too"))
   869  	c.Check(s.machines[1].CheckProvisioned("fake_nonce"), jc.IsTrue)
   870  	c.Check(s.machines[2].CheckProvisioned("fake"), jc.IsTrue)
   871  	gotHardware, err := s.machines[1].HardwareCharacteristics()
   872  	c.Assert(err, jc.ErrorIsNil)
   873  	c.Check(gotHardware, gc.DeepEquals, &hwChars)
   874  
   875  	// Verify the machine with requested volumes was provisioned, and the
   876  	// volume information recorded in state.
   877  	volumeAttachments, err := s.State.MachineVolumeAttachments(volumesMachine.MachineTag())
   878  	c.Assert(err, jc.ErrorIsNil)
   879  	c.Assert(volumeAttachments, gc.HasLen, 1)
   880  	volumeAttachmentInfo, err := volumeAttachments[0].Info()
   881  	c.Assert(err, jc.ErrorIsNil)
   882  	c.Assert(volumeAttachmentInfo, gc.Equals, state.VolumeAttachmentInfo{DeviceName: "sda"})
   883  	volume, err := s.State.Volume(volumeAttachments[0].Volume())
   884  	c.Assert(err, jc.ErrorIsNil)
   885  	volumeInfo, err := volume.Info()
   886  	c.Assert(err, jc.ErrorIsNil)
   887  	c.Assert(volumeInfo, gc.Equals, state.VolumeInfo{VolumeId: "vol-0", Pool: "static-pool", Size: 1234})
   888  
   889  	// Verify the machine without requested volumes still has no volume
   890  	// attachments recorded in state.
   891  	volumeAttachments, err = s.State.MachineVolumeAttachments(s.machines[1].MachineTag())
   892  	c.Assert(err, jc.ErrorIsNil)
   893  	c.Assert(volumeAttachments, gc.HasLen, 0)
   894  }
   895  
   896  func (s *withoutControllerSuite) TestInstanceId(c *gc.C) {
   897  	// Provision 2 machines first.
   898  	err := s.machines[0].SetProvisioned("i-am", "fake_nonce", nil)
   899  	c.Assert(err, jc.ErrorIsNil)
   900  	hwChars := instance.MustParseHardware("arch=i386", "mem=4G")
   901  	err = s.machines[1].SetProvisioned("i-am-not", "fake_nonce", &hwChars)
   902  	c.Assert(err, jc.ErrorIsNil)
   903  
   904  	args := params.Entities{Entities: []params.Entity{
   905  		{Tag: s.machines[0].Tag().String()},
   906  		{Tag: s.machines[1].Tag().String()},
   907  		{Tag: s.machines[2].Tag().String()},
   908  		{Tag: "machine-42"},
   909  		{Tag: "unit-foo-0"},
   910  		{Tag: "service-bar"},
   911  	}}
   912  	result, err := s.provisioner.InstanceId(args)
   913  	c.Assert(err, jc.ErrorIsNil)
   914  	c.Assert(result, gc.DeepEquals, params.StringResults{
   915  		Results: []params.StringResult{
   916  			{Result: "i-am"},
   917  			{Result: "i-am-not"},
   918  			{Error: apiservertesting.NotProvisionedError("2")},
   919  			{Error: apiservertesting.NotFoundError("machine 42")},
   920  			{Error: apiservertesting.ErrUnauthorized},
   921  			{Error: apiservertesting.ErrUnauthorized},
   922  		},
   923  	})
   924  }
   925  
   926  func (s *withoutControllerSuite) TestWatchModelMachines(c *gc.C) {
   927  	c.Assert(s.resources.Count(), gc.Equals, 0)
   928  
   929  	got, err := s.provisioner.WatchModelMachines()
   930  	c.Assert(err, jc.ErrorIsNil)
   931  	want := params.StringsWatchResult{
   932  		StringsWatcherId: "1",
   933  		Changes:          []string{"0", "1", "2", "3", "4"},
   934  	}
   935  	c.Assert(got.StringsWatcherId, gc.Equals, want.StringsWatcherId)
   936  	c.Assert(got.Changes, jc.SameContents, want.Changes)
   937  
   938  	// Verify the resources were registered and stop them when done.
   939  	c.Assert(s.resources.Count(), gc.Equals, 1)
   940  	resource := s.resources.Get("1")
   941  	defer statetesting.AssertStop(c, resource)
   942  
   943  	// Check that the Watch has consumed the initial event ("returned"
   944  	// in the Watch call)
   945  	wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher))
   946  	wc.AssertNoChange()
   947  
   948  	// Make sure WatchModelMachines fails with a machine agent login.
   949  	anAuthorizer := s.authorizer
   950  	anAuthorizer.Tag = names.NewMachineTag("1")
   951  	anAuthorizer.EnvironManager = false
   952  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
   953  	c.Assert(err, jc.ErrorIsNil)
   954  
   955  	result, err := aProvisioner.WatchModelMachines()
   956  	c.Assert(err, gc.ErrorMatches, "permission denied")
   957  	c.Assert(result, gc.DeepEquals, params.StringsWatchResult{})
   958  }
   959  
   960  func (s *provisionerSuite) getManagerConfig(c *gc.C, typ instance.ContainerType) map[string]string {
   961  	args := params.ContainerManagerConfigParams{Type: typ}
   962  	results, err := s.provisioner.ContainerManagerConfig(args)
   963  	c.Assert(err, jc.ErrorIsNil)
   964  	return results.ManagerConfig
   965  }
   966  
   967  func (s *withoutControllerSuite) TestContainerManagerConfig(c *gc.C) {
   968  	cfg := s.getManagerConfig(c, instance.KVM)
   969  	c.Assert(cfg, jc.DeepEquals, map[string]string{
   970  		container.ConfigName: "juju",
   971  
   972  		// dummy provider supports both networking and address
   973  		// allocation by default, so IP forwarding should be enabled.
   974  		container.ConfigIPForwarding: "true",
   975  	})
   976  }
   977  
   978  func (s *withoutControllerSuite) TestContainerManagerConfigNoFeatureFlagNoIPForwarding(c *gc.C) {
   979  	s.SetFeatureFlags() // clear the flags.
   980  
   981  	cfg := s.getManagerConfig(c, instance.KVM)
   982  	c.Assert(cfg, jc.DeepEquals, map[string]string{
   983  		container.ConfigName: "juju",
   984  		// ConfigIPForwarding should be missing.
   985  	})
   986  }
   987  
   988  func (s *withoutControllerSuite) TestContainerManagerConfigNoIPForwarding(c *gc.C) {
   989  	// Break dummy provider's SupportsAddressAllocation method to
   990  	// ensure ConfigIPForwarding is not set below.
   991  	s.AssertConfigParameterUpdated(c, "broken", "SupportsAddressAllocation")
   992  
   993  	cfg := s.getManagerConfig(c, instance.KVM)
   994  	c.Assert(cfg, jc.DeepEquals, map[string]string{
   995  		container.ConfigName: "juju",
   996  	})
   997  }
   998  
   999  func (s *withoutControllerSuite) TestContainerConfig(c *gc.C) {
  1000  	attrs := map[string]interface{}{
  1001  		"http-proxy":            "http://proxy.example.com:9000",
  1002  		"allow-lxc-loop-mounts": true,
  1003  		"apt-mirror":            "http://example.mirror.com",
  1004  	}
  1005  	err := s.State.UpdateModelConfig(attrs, nil, nil)
  1006  	c.Assert(err, jc.ErrorIsNil)
  1007  	expectedProxy := proxy.Settings{
  1008  		Http: "http://proxy.example.com:9000",
  1009  	}
  1010  
  1011  	results, err := s.provisioner.ContainerConfig()
  1012  	c.Check(err, jc.ErrorIsNil)
  1013  	c.Check(results.UpdateBehavior, gc.Not(gc.IsNil))
  1014  	c.Check(results.ProviderType, gc.Equals, "dummy")
  1015  	c.Check(results.AuthorizedKeys, gc.Equals, s.Environ.Config().AuthorizedKeys())
  1016  	c.Check(results.SSLHostnameVerification, jc.IsTrue)
  1017  	c.Check(results.Proxy, gc.DeepEquals, expectedProxy)
  1018  	c.Check(results.AptProxy, gc.DeepEquals, expectedProxy)
  1019  	c.Check(results.AptMirror, gc.DeepEquals, "http://example.mirror.com")
  1020  	c.Check(results.PreferIPv6, jc.IsFalse)
  1021  	c.Check(results.AllowLXCLoopMounts, jc.IsTrue)
  1022  }
  1023  
  1024  func (s *withoutControllerSuite) TestSetSupportedContainers(c *gc.C) {
  1025  	args := params.MachineContainersParams{Params: []params.MachineContainers{{
  1026  		MachineTag:     "machine-0",
  1027  		ContainerTypes: []instance.ContainerType{instance.LXC},
  1028  	}, {
  1029  		MachineTag:     "machine-1",
  1030  		ContainerTypes: []instance.ContainerType{instance.LXC, instance.KVM},
  1031  	}}}
  1032  	results, err := s.provisioner.SetSupportedContainers(args)
  1033  	c.Assert(err, jc.ErrorIsNil)
  1034  	c.Assert(results.Results, gc.HasLen, 2)
  1035  	for _, result := range results.Results {
  1036  		c.Assert(result.Error, gc.IsNil)
  1037  	}
  1038  	m0, err := s.State.Machine("0")
  1039  	c.Assert(err, jc.ErrorIsNil)
  1040  	containers, ok := m0.SupportedContainers()
  1041  	c.Assert(ok, jc.IsTrue)
  1042  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC})
  1043  	m1, err := s.State.Machine("1")
  1044  	c.Assert(err, jc.ErrorIsNil)
  1045  	containers, ok = m1.SupportedContainers()
  1046  	c.Assert(ok, jc.IsTrue)
  1047  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC, instance.KVM})
  1048  }
  1049  
  1050  func (s *withoutControllerSuite) TestSetSupportedContainersPermissions(c *gc.C) {
  1051  	// Login as a machine agent for machine 0.
  1052  	anAuthorizer := s.authorizer
  1053  	anAuthorizer.EnvironManager = false
  1054  	anAuthorizer.Tag = s.machines[0].Tag()
  1055  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
  1056  	c.Assert(err, jc.ErrorIsNil)
  1057  	c.Assert(aProvisioner, gc.NotNil)
  1058  
  1059  	args := params.MachineContainersParams{
  1060  		Params: []params.MachineContainers{{
  1061  			MachineTag:     "machine-0",
  1062  			ContainerTypes: []instance.ContainerType{instance.LXC},
  1063  		}, {
  1064  			MachineTag:     "machine-1",
  1065  			ContainerTypes: []instance.ContainerType{instance.LXC},
  1066  		}, {
  1067  			MachineTag:     "machine-42",
  1068  			ContainerTypes: []instance.ContainerType{instance.LXC},
  1069  		},
  1070  		},
  1071  	}
  1072  	// Only machine 0 can have it's containers updated.
  1073  	results, err := aProvisioner.SetSupportedContainers(args)
  1074  	c.Assert(results, gc.DeepEquals, params.ErrorResults{
  1075  		Results: []params.ErrorResult{
  1076  			{Error: nil},
  1077  			{Error: apiservertesting.ErrUnauthorized},
  1078  			{Error: apiservertesting.ErrUnauthorized},
  1079  		},
  1080  	})
  1081  }
  1082  
  1083  func (s *withoutControllerSuite) TestSupportsNoContainers(c *gc.C) {
  1084  	args := params.MachineContainersParams{
  1085  		Params: []params.MachineContainers{
  1086  			{
  1087  				MachineTag: "machine-0",
  1088  			},
  1089  		},
  1090  	}
  1091  	results, err := s.provisioner.SetSupportedContainers(args)
  1092  	c.Assert(err, jc.ErrorIsNil)
  1093  	c.Assert(results.Results, gc.HasLen, 1)
  1094  	c.Assert(results.Results[0].Error, gc.IsNil)
  1095  	m0, err := s.State.Machine("0")
  1096  	c.Assert(err, jc.ErrorIsNil)
  1097  	containers, ok := m0.SupportedContainers()
  1098  	c.Assert(ok, jc.IsTrue)
  1099  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{})
  1100  }
  1101  
  1102  var _ = gc.Suite(&withControllerSuite{})
  1103  
  1104  type withControllerSuite struct {
  1105  	provisionerSuite
  1106  }
  1107  
  1108  func (s *withControllerSuite) SetUpTest(c *gc.C) {
  1109  	s.provisionerSuite.setUpTest(c, true)
  1110  }
  1111  
  1112  func (s *withControllerSuite) TestAPIAddresses(c *gc.C) {
  1113  	hostPorts := [][]network.HostPort{
  1114  		network.NewHostPorts(1234, "0.1.2.3"),
  1115  	}
  1116  	err := s.State.SetAPIHostPorts(hostPorts)
  1117  	c.Assert(err, jc.ErrorIsNil)
  1118  
  1119  	result, err := s.provisioner.APIAddresses()
  1120  	c.Assert(err, jc.ErrorIsNil)
  1121  	c.Assert(result, gc.DeepEquals, params.StringsResult{
  1122  		Result: []string{"0.1.2.3:1234"},
  1123  	})
  1124  }
  1125  
  1126  func (s *withControllerSuite) TestStateAddresses(c *gc.C) {
  1127  	addresses, err := s.State.Addresses()
  1128  	c.Assert(err, jc.ErrorIsNil)
  1129  
  1130  	result, err := s.provisioner.StateAddresses()
  1131  	c.Assert(err, jc.ErrorIsNil)
  1132  	c.Assert(result, gc.DeepEquals, params.StringsResult{
  1133  		Result: addresses,
  1134  	})
  1135  }
  1136  
  1137  func (s *withControllerSuite) TestCACert(c *gc.C) {
  1138  	result := s.provisioner.CACert()
  1139  	c.Assert(result, gc.DeepEquals, params.BytesResult{
  1140  		Result: []byte(s.State.CACert()),
  1141  	})
  1142  }
  1143  
  1144  func (s *withoutControllerSuite) TestWatchMachineErrorRetry(c *gc.C) {
  1145  	coretesting.SkipIfI386(c, "lp:1425569")
  1146  
  1147  	s.PatchValue(&provisioner.ErrorRetryWaitDelay, 2*coretesting.ShortWait)
  1148  	c.Assert(s.resources.Count(), gc.Equals, 0)
  1149  
  1150  	_, err := s.provisioner.WatchMachineErrorRetry()
  1151  	c.Assert(err, jc.ErrorIsNil)
  1152  
  1153  	// Verify the resources were registered and stop them when done.
  1154  	c.Assert(s.resources.Count(), gc.Equals, 1)
  1155  	resource := s.resources.Get("1")
  1156  	defer statetesting.AssertStop(c, resource)
  1157  
  1158  	// Check that the Watch has consumed the initial event ("returned"
  1159  	// in the Watch call)
  1160  	wc := statetesting.NewNotifyWatcherC(c, s.State, resource.(state.NotifyWatcher))
  1161  	wc.AssertNoChange()
  1162  
  1163  	// We should now get a time triggered change.
  1164  	wc.AssertOneChange()
  1165  
  1166  	// Make sure WatchMachineErrorRetry fails with a machine agent login.
  1167  	anAuthorizer := s.authorizer
  1168  	anAuthorizer.Tag = names.NewMachineTag("1")
  1169  	anAuthorizer.EnvironManager = false
  1170  	aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer)
  1171  	c.Assert(err, jc.ErrorIsNil)
  1172  
  1173  	result, err := aProvisioner.WatchMachineErrorRetry()
  1174  	c.Assert(err, gc.ErrorMatches, "permission denied")
  1175  	c.Assert(result, gc.DeepEquals, params.NotifyWatchResult{})
  1176  }
  1177  
  1178  func (s *withoutControllerSuite) TestFindTools(c *gc.C) {
  1179  	args := params.FindToolsParams{
  1180  		MajorVersion: -1,
  1181  		MinorVersion: -1,
  1182  	}
  1183  	result, err := s.provisioner.FindTools(args)
  1184  	c.Assert(err, jc.ErrorIsNil)
  1185  	c.Assert(result.Error, gc.IsNil)
  1186  	c.Assert(result.List, gc.Not(gc.HasLen), 0)
  1187  	for _, tools := range result.List {
  1188  		url := fmt.Sprintf("https://%s/model/%s/tools/%s",
  1189  			s.APIState.Addr(), coretesting.ModelTag.Id(), tools.Version)
  1190  		c.Assert(tools.URL, gc.Equals, url)
  1191  	}
  1192  }
  1193  
  1194  type lxcDefaultMTUSuite struct {
  1195  	provisionerSuite
  1196  }
  1197  
  1198  var _ = gc.Suite(&lxcDefaultMTUSuite{})
  1199  
  1200  func (s *lxcDefaultMTUSuite) SetUpTest(c *gc.C) {
  1201  	// Because lxc-default-mtu is an immutable setting, we need to set
  1202  	// it in the default config JujuConnSuite uses, before the
  1203  	// environment is "created".
  1204  	s.DummyConfig = dummy.SampleConfig()
  1205  	s.DummyConfig["lxc-default-mtu"] = 9000
  1206  	s.provisionerSuite.SetUpTest(c)
  1207  
  1208  	stateConfig, err := s.State.ModelConfig()
  1209  	c.Assert(err, jc.ErrorIsNil)
  1210  	value, ok := stateConfig.LXCDefaultMTU()
  1211  	c.Assert(ok, jc.IsTrue)
  1212  	c.Assert(value, gc.Equals, 9000)
  1213  	c.Logf("environ config lxc-default-mtu set to %v", value)
  1214  }
  1215  
  1216  func (s *lxcDefaultMTUSuite) TestContainerManagerConfigLXCDefaultMTU(c *gc.C) {
  1217  	managerConfig := s.getManagerConfig(c, instance.LXC)
  1218  	c.Assert(managerConfig, jc.DeepEquals, map[string]string{
  1219  		container.ConfigName:          "juju",
  1220  		container.ConfigLXCDefaultMTU: "9000",
  1221  
  1222  		"use-aufs":                   "false",
  1223  		container.ConfigIPForwarding: "true",
  1224  	})
  1225  
  1226  	// KVM instances are not affected.
  1227  	managerConfig = s.getManagerConfig(c, instance.KVM)
  1228  	c.Assert(managerConfig, jc.DeepEquals, map[string]string{
  1229  		container.ConfigName:         "juju",
  1230  		container.ConfigIPForwarding: "true",
  1231  	})
  1232  }