github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/state/api/provisioner/provisioner_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package provisioner_test
     5  
     6  import (
     7  	stdtesting "testing"
     8  
     9  	gc "launchpad.net/gocheck"
    10  
    11  	"launchpad.net/juju-core/constraints"
    12  	"launchpad.net/juju-core/errors"
    13  	"launchpad.net/juju-core/instance"
    14  	"launchpad.net/juju-core/juju/testing"
    15  	"launchpad.net/juju-core/state"
    16  	"launchpad.net/juju-core/state/api"
    17  	commontesting "launchpad.net/juju-core/state/api/common/testing"
    18  	"launchpad.net/juju-core/state/api/params"
    19  	"launchpad.net/juju-core/state/api/provisioner"
    20  	statetesting "launchpad.net/juju-core/state/testing"
    21  	coretesting "launchpad.net/juju-core/testing"
    22  	jc "launchpad.net/juju-core/testing/checkers"
    23  	"launchpad.net/juju-core/tools"
    24  	"launchpad.net/juju-core/utils"
    25  	"launchpad.net/juju-core/version"
    26  )
    27  
    28  func TestAll(t *stdtesting.T) {
    29  	coretesting.MgoTestPackage(t)
    30  }
    31  
    32  type provisionerSuite struct {
    33  	testing.JujuConnSuite
    34  	*commontesting.EnvironWatcherTest
    35  
    36  	st      *api.State
    37  	machine *state.Machine
    38  
    39  	provisioner *provisioner.State
    40  }
    41  
    42  var _ = gc.Suite(&provisionerSuite{})
    43  
    44  func (s *provisionerSuite) SetUpTest(c *gc.C) {
    45  	s.JujuConnSuite.SetUpTest(c)
    46  
    47  	var err error
    48  	s.machine, err = s.State.AddMachine("quantal", state.JobManageEnviron)
    49  	c.Assert(err, gc.IsNil)
    50  	password, err := utils.RandomPassword()
    51  	c.Assert(err, gc.IsNil)
    52  	err = s.machine.SetPassword(password)
    53  	c.Assert(err, gc.IsNil)
    54  	err = s.machine.SetProvisioned("i-manager", "fake_nonce", nil)
    55  	c.Assert(err, gc.IsNil)
    56  	s.st = s.OpenAPIAsMachine(c, s.machine.Tag(), password, "fake_nonce")
    57  	c.Assert(s.st, gc.NotNil)
    58  
    59  	// Create the provisioner API facade.
    60  	s.provisioner = s.st.Provisioner()
    61  	c.Assert(s.provisioner, gc.NotNil)
    62  
    63  	s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest(s.provisioner, s.State, s.BackingState, commontesting.HasSecrets)
    64  }
    65  
    66  func (s *provisionerSuite) TestMachineTagAndId(c *gc.C) {
    67  	apiMachine, err := s.provisioner.Machine("machine-42")
    68  	c.Assert(err, gc.ErrorMatches, "machine 42 not found")
    69  	c.Assert(err, jc.Satisfies, params.IsCodeNotFound)
    70  	c.Assert(apiMachine, gc.IsNil)
    71  
    72  	apiMachine, err = s.provisioner.Machine(s.machine.Tag())
    73  	c.Assert(err, gc.IsNil)
    74  	c.Assert(apiMachine.Tag(), gc.Equals, s.machine.Tag())
    75  	c.Assert(apiMachine.Id(), gc.Equals, s.machine.Id())
    76  }
    77  
    78  func (s *provisionerSuite) TestGetSetStatus(c *gc.C) {
    79  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
    80  	c.Assert(err, gc.IsNil)
    81  
    82  	status, info, err := apiMachine.Status()
    83  	c.Assert(err, gc.IsNil)
    84  	c.Assert(status, gc.Equals, params.StatusPending)
    85  	c.Assert(info, gc.Equals, "")
    86  
    87  	err = apiMachine.SetStatus(params.StatusStarted, "blah")
    88  	c.Assert(err, gc.IsNil)
    89  
    90  	status, info, err = apiMachine.Status()
    91  	c.Assert(err, gc.IsNil)
    92  	c.Assert(status, gc.Equals, params.StatusStarted)
    93  	c.Assert(info, gc.Equals, "blah")
    94  }
    95  
    96  func (s *provisionerSuite) TestEnsureDeadAndRemove(c *gc.C) {
    97  	// Create a fresh machine to test the complete scenario.
    98  	otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
    99  	c.Assert(err, gc.IsNil)
   100  	c.Assert(otherMachine.Life(), gc.Equals, state.Alive)
   101  
   102  	apiMachine, err := s.provisioner.Machine(otherMachine.Tag())
   103  	c.Assert(err, gc.IsNil)
   104  
   105  	err = apiMachine.Remove()
   106  	c.Assert(err, gc.ErrorMatches, `cannot remove entity "machine-1": still alive`)
   107  	err = apiMachine.EnsureDead()
   108  	c.Assert(err, gc.IsNil)
   109  
   110  	err = otherMachine.Refresh()
   111  	c.Assert(err, gc.IsNil)
   112  	c.Assert(otherMachine.Life(), gc.Equals, state.Dead)
   113  
   114  	err = apiMachine.EnsureDead()
   115  	c.Assert(err, gc.IsNil)
   116  	err = otherMachine.Refresh()
   117  	c.Assert(err, gc.IsNil)
   118  	c.Assert(otherMachine.Life(), gc.Equals, state.Dead)
   119  
   120  	err = apiMachine.Remove()
   121  	c.Assert(err, gc.IsNil)
   122  	err = otherMachine.Refresh()
   123  	c.Assert(err, jc.Satisfies, errors.IsNotFoundError)
   124  
   125  	err = apiMachine.EnsureDead()
   126  	c.Assert(err, gc.ErrorMatches, "machine 1 not found")
   127  	c.Assert(err, jc.Satisfies, params.IsCodeNotFound)
   128  
   129  	// Now try to EnsureDead machine 0 - should fail.
   130  	apiMachine, err = s.provisioner.Machine(s.machine.Tag())
   131  	c.Assert(err, gc.IsNil)
   132  	err = apiMachine.EnsureDead()
   133  	c.Assert(err, gc.ErrorMatches, "machine 0 is required by the environment")
   134  }
   135  
   136  func (s *provisionerSuite) TestRefreshAndLife(c *gc.C) {
   137  	// Create a fresh machine to test the complete scenario.
   138  	otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   139  	c.Assert(err, gc.IsNil)
   140  	c.Assert(otherMachine.Life(), gc.Equals, state.Alive)
   141  
   142  	apiMachine, err := s.provisioner.Machine(otherMachine.Tag())
   143  	c.Assert(err, gc.IsNil)
   144  	c.Assert(apiMachine.Life(), gc.Equals, params.Alive)
   145  
   146  	err = apiMachine.EnsureDead()
   147  	c.Assert(err, gc.IsNil)
   148  	c.Assert(apiMachine.Life(), gc.Equals, params.Alive)
   149  
   150  	err = apiMachine.Refresh()
   151  	c.Assert(err, gc.IsNil)
   152  	c.Assert(apiMachine.Life(), gc.Equals, params.Dead)
   153  }
   154  
   155  func (s *provisionerSuite) TestSetProvisionedAndInstanceId(c *gc.C) {
   156  	// Create a fresh machine, since machine 0 is already provisioned.
   157  	notProvisionedMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   158  	c.Assert(err, gc.IsNil)
   159  
   160  	apiMachine, err := s.provisioner.Machine(notProvisionedMachine.Tag())
   161  	c.Assert(err, gc.IsNil)
   162  
   163  	instanceId, err := apiMachine.InstanceId()
   164  	c.Assert(err, jc.Satisfies, params.IsCodeNotProvisioned)
   165  	c.Assert(err, gc.ErrorMatches, "machine 1 is not provisioned")
   166  	c.Assert(instanceId, gc.Equals, instance.Id(""))
   167  
   168  	hwChars := instance.MustParseHardware("cpu-cores=123", "mem=4G")
   169  	err = apiMachine.SetProvisioned("i-will", "fake_nonce", &hwChars)
   170  	c.Assert(err, gc.IsNil)
   171  
   172  	instanceId, err = apiMachine.InstanceId()
   173  	c.Assert(err, gc.IsNil)
   174  	c.Assert(instanceId, gc.Equals, instance.Id("i-will"))
   175  
   176  	// Try it again - should fail.
   177  	err = apiMachine.SetProvisioned("i-wont", "fake", nil)
   178  	c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": already set`)
   179  
   180  	// Now try to get machine 0's instance id.
   181  	apiMachine, err = s.provisioner.Machine(s.machine.Tag())
   182  	c.Assert(err, gc.IsNil)
   183  	instanceId, err = apiMachine.InstanceId()
   184  	c.Assert(err, gc.IsNil)
   185  	c.Assert(instanceId, gc.Equals, instance.Id("i-manager"))
   186  }
   187  
   188  func (s *provisionerSuite) TestSeries(c *gc.C) {
   189  	// Create a fresh machine with different series.
   190  	foobarMachine, err := s.State.AddMachine("foobar", state.JobHostUnits)
   191  	c.Assert(err, gc.IsNil)
   192  
   193  	apiMachine, err := s.provisioner.Machine(foobarMachine.Tag())
   194  	c.Assert(err, gc.IsNil)
   195  	series, err := apiMachine.Series()
   196  	c.Assert(err, gc.IsNil)
   197  	c.Assert(series, gc.Equals, "foobar")
   198  
   199  	// Now try machine 0.
   200  	apiMachine, err = s.provisioner.Machine(s.machine.Tag())
   201  	c.Assert(err, gc.IsNil)
   202  	series, err = apiMachine.Series()
   203  	c.Assert(err, gc.IsNil)
   204  	c.Assert(series, gc.Equals, "quantal")
   205  }
   206  
   207  func (s *provisionerSuite) TestConstraints(c *gc.C) {
   208  	// Create a fresh machine with some constraints.
   209  	template := state.MachineTemplate{
   210  		Series:      "quantal",
   211  		Jobs:        []state.MachineJob{state.JobHostUnits},
   212  		Constraints: constraints.MustParse("cpu-cores=12", "mem=8G"),
   213  	}
   214  	consMachine, err := s.State.AddOneMachine(template)
   215  	c.Assert(err, gc.IsNil)
   216  
   217  	apiMachine, err := s.provisioner.Machine(consMachine.Tag())
   218  	c.Assert(err, gc.IsNil)
   219  	cons, err := apiMachine.Constraints()
   220  	c.Assert(err, gc.IsNil)
   221  	c.Assert(cons, gc.DeepEquals, template.Constraints)
   222  
   223  	// Now try machine 0.
   224  	apiMachine, err = s.provisioner.Machine(s.machine.Tag())
   225  	c.Assert(err, gc.IsNil)
   226  	cons, err = apiMachine.Constraints()
   227  	c.Assert(err, gc.IsNil)
   228  	c.Assert(cons, gc.DeepEquals, constraints.Value{})
   229  }
   230  
   231  func (s *provisionerSuite) TestWatchContainers(c *gc.C) {
   232  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   233  	c.Assert(err, gc.IsNil)
   234  
   235  	// Add one LXC container.
   236  	template := state.MachineTemplate{
   237  		Series: "quantal",
   238  		Jobs:   []state.MachineJob{state.JobHostUnits},
   239  	}
   240  	container, err := s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC)
   241  	c.Assert(err, gc.IsNil)
   242  
   243  	w, err := apiMachine.WatchContainers(instance.LXC)
   244  	c.Assert(err, gc.IsNil)
   245  	defer statetesting.AssertStop(c, w)
   246  	wc := statetesting.NewStringsWatcherC(c, s.BackingState, w)
   247  
   248  	// Initial event.
   249  	wc.AssertChange(container.Id())
   250  
   251  	// Change something other than the containers and make sure it's
   252  	// not detected.
   253  	err = apiMachine.SetStatus(params.StatusStarted, "not really")
   254  	c.Assert(err, gc.IsNil)
   255  	wc.AssertNoChange()
   256  
   257  	// Add a KVM container and make sure it's not detected.
   258  	container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.KVM)
   259  	c.Assert(err, gc.IsNil)
   260  	wc.AssertNoChange()
   261  
   262  	// Add another LXC container and make sure it's detected.
   263  	container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC)
   264  	c.Assert(err, gc.IsNil)
   265  	wc.AssertChange(container.Id())
   266  
   267  	statetesting.AssertStop(c, w)
   268  	wc.AssertClosed()
   269  }
   270  
   271  func (s *provisionerSuite) TestWatchContainersAcceptsSupportedContainers(c *gc.C) {
   272  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   273  	c.Assert(err, gc.IsNil)
   274  
   275  	for _, ctype := range instance.ContainerTypes {
   276  		w, err := apiMachine.WatchContainers(ctype)
   277  		c.Assert(w, gc.NotNil)
   278  		c.Assert(err, gc.IsNil)
   279  	}
   280  }
   281  
   282  func (s *provisionerSuite) TestWatchContainersErrors(c *gc.C) {
   283  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   284  	c.Assert(err, gc.IsNil)
   285  
   286  	_, err = apiMachine.WatchContainers(instance.NONE)
   287  	c.Assert(err, gc.ErrorMatches, `unsupported container type "none"`)
   288  
   289  	_, err = apiMachine.WatchContainers("")
   290  	c.Assert(err, gc.ErrorMatches, "container type must be specified")
   291  }
   292  
   293  func (s *provisionerSuite) TestWatchEnvironMachines(c *gc.C) {
   294  	w, err := s.provisioner.WatchEnvironMachines()
   295  	c.Assert(err, gc.IsNil)
   296  	defer statetesting.AssertStop(c, w)
   297  	wc := statetesting.NewStringsWatcherC(c, s.BackingState, w)
   298  
   299  	// Initial event.
   300  	wc.AssertChange(s.machine.Id())
   301  
   302  	// Add another 2 machines make sure they are detected.
   303  	otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   304  	c.Assert(err, gc.IsNil)
   305  	otherMachine, err = s.State.AddMachine("quantal", state.JobHostUnits)
   306  	c.Assert(err, gc.IsNil)
   307  	wc.AssertChange("1", "2")
   308  
   309  	// Change the lifecycle of last machine.
   310  	err = otherMachine.EnsureDead()
   311  	c.Assert(err, gc.IsNil)
   312  	wc.AssertChange("2")
   313  
   314  	// Add a container and make sure it's not detected.
   315  	template := state.MachineTemplate{
   316  		Series: "quantal",
   317  		Jobs:   []state.MachineJob{state.JobHostUnits},
   318  	}
   319  	_, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC)
   320  	c.Assert(err, gc.IsNil)
   321  	wc.AssertNoChange()
   322  
   323  	statetesting.AssertStop(c, w)
   324  	wc.AssertClosed()
   325  }
   326  
   327  func (s *provisionerSuite) TestStateAddresses(c *gc.C) {
   328  	err := s.machine.SetAddresses([]instance.Address{
   329  		instance.NewAddress("0.1.2.3"),
   330  	})
   331  	c.Assert(err, gc.IsNil)
   332  
   333  	stateAddresses, err := s.State.Addresses()
   334  	c.Assert(err, gc.IsNil)
   335  
   336  	addresses, err := s.provisioner.StateAddresses()
   337  	c.Assert(err, gc.IsNil)
   338  	c.Assert(addresses, gc.DeepEquals, stateAddresses)
   339  }
   340  
   341  func (s *provisionerSuite) TestAPIAddresses(c *gc.C) {
   342  	err := s.machine.SetAddresses([]instance.Address{
   343  		instance.NewAddress("0.1.2.3"),
   344  	})
   345  	c.Assert(err, gc.IsNil)
   346  
   347  	apiAddresses, err := s.State.APIAddresses()
   348  	c.Assert(err, gc.IsNil)
   349  
   350  	addresses, err := s.provisioner.APIAddresses()
   351  	c.Assert(err, gc.IsNil)
   352  	c.Assert(addresses, gc.DeepEquals, apiAddresses)
   353  }
   354  
   355  func (s *provisionerSuite) TestContainerConfig(c *gc.C) {
   356  	result, err := s.provisioner.ContainerConfig()
   357  	c.Assert(err, gc.IsNil)
   358  	c.Assert(result.ProviderType, gc.Equals, "dummy")
   359  	c.Assert(result.AuthorizedKeys, gc.Equals, coretesting.FakeAuthKeys)
   360  	c.Assert(result.SSLHostnameVerification, jc.IsTrue)
   361  }
   362  
   363  func (s *provisionerSuite) TestCACert(c *gc.C) {
   364  	caCert, err := s.provisioner.CACert()
   365  	c.Assert(err, gc.IsNil)
   366  	c.Assert(caCert, gc.DeepEquals, s.State.CACert())
   367  }
   368  
   369  func (s *provisionerSuite) TestToolsWrongMachine(c *gc.C) {
   370  	tools, err := s.provisioner.Tools("42")
   371  	c.Assert(err, gc.ErrorMatches, "permission denied")
   372  	c.Assert(err, jc.Satisfies, params.IsCodeUnauthorized)
   373  	c.Assert(tools, gc.IsNil)
   374  }
   375  
   376  func (s *provisionerSuite) TestTools(c *gc.C) {
   377  	cur := version.Current
   378  	curTools := &tools.Tools{Version: cur, URL: ""}
   379  	curTools.Version.Minor++
   380  	s.machine.SetAgentVersion(cur)
   381  	// Provisioner.Tools returns the *desired* set of tools, not the
   382  	// currently running set. We want to be upgraded to cur.Version
   383  	stateTools, err := s.provisioner.Tools(s.machine.Tag())
   384  	c.Assert(err, gc.IsNil)
   385  	c.Assert(stateTools.Version, gc.Equals, cur)
   386  	c.Assert(stateTools.URL, gc.Not(gc.Equals), "")
   387  }
   388  
   389  func (s *provisionerSuite) TestSetSupportedContainers(c *gc.C) {
   390  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   391  	c.Assert(err, gc.IsNil)
   392  	err = apiMachine.SetSupportedContainers(instance.LXC, instance.KVM)
   393  	c.Assert(err, gc.IsNil)
   394  
   395  	err = s.machine.Refresh()
   396  	c.Assert(err, gc.IsNil)
   397  	containers, ok := s.machine.SupportedContainers()
   398  	c.Assert(ok, jc.IsTrue)
   399  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC, instance.KVM})
   400  }
   401  
   402  func (s *provisionerSuite) TestSupportsNoContainers(c *gc.C) {
   403  	apiMachine, err := s.provisioner.Machine(s.machine.Tag())
   404  	c.Assert(err, gc.IsNil)
   405  	err = apiMachine.SupportsNoContainers()
   406  	c.Assert(err, gc.IsNil)
   407  
   408  	err = s.machine.Refresh()
   409  	c.Assert(err, gc.IsNil)
   410  	containers, ok := s.machine.SupportedContainers()
   411  	c.Assert(ok, jc.IsTrue)
   412  	c.Assert(containers, gc.DeepEquals, []instance.ContainerType{})
   413  }