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