launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/worker/provisioner/kvm-broker_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  	gc "launchpad.net/gocheck"
     9  	"path/filepath"
    10  	"time"
    11  
    12  	"launchpad.net/juju-core/agent"
    13  	"launchpad.net/juju-core/constraints"
    14  	"launchpad.net/juju-core/container/kvm/mock"
    15  	kvmtesting "launchpad.net/juju-core/container/kvm/testing"
    16  	"launchpad.net/juju-core/environs"
    17  	"launchpad.net/juju-core/environs/config"
    18  	"launchpad.net/juju-core/instance"
    19  	instancetest "launchpad.net/juju-core/instance/testing"
    20  	jujutesting "launchpad.net/juju-core/juju/testing"
    21  	"launchpad.net/juju-core/names"
    22  	"launchpad.net/juju-core/state"
    23  	coretesting "launchpad.net/juju-core/testing"
    24  	jc "launchpad.net/juju-core/testing/checkers"
    25  	coretools "launchpad.net/juju-core/tools"
    26  	"launchpad.net/juju-core/version"
    27  	"launchpad.net/juju-core/worker/provisioner"
    28  )
    29  
    30  type kvmSuite struct {
    31  	kvmtesting.TestSuite
    32  	events chan mock.Event
    33  }
    34  
    35  type kvmBrokerSuite struct {
    36  	kvmSuite
    37  	broker      environs.InstanceBroker
    38  	agentConfig agent.Config
    39  }
    40  
    41  var _ = gc.Suite(&kvmBrokerSuite{})
    42  
    43  func (s *kvmSuite) SetUpTest(c *gc.C) {
    44  	s.TestSuite.SetUpTest(c)
    45  	s.events = make(chan mock.Event)
    46  	go func() {
    47  		for event := range s.events {
    48  			c.Output(3, fmt.Sprintf("kvm event: <%s, %s>", event.Action, event.InstanceId))
    49  		}
    50  	}()
    51  	s.TestSuite.Factory.AddListener(s.events)
    52  }
    53  
    54  func (s *kvmSuite) TearDownTest(c *gc.C) {
    55  	close(s.events)
    56  	s.TestSuite.TearDownTest(c)
    57  }
    58  
    59  func (s *kvmBrokerSuite) SetUpTest(c *gc.C) {
    60  	s.kvmSuite.SetUpTest(c)
    61  	tools := &coretools.Tools{
    62  		Version: version.MustParseBinary("2.3.4-foo-bar"),
    63  		URL:     "http://tools.testing.invalid/2.3.4-foo-bar.tgz",
    64  	}
    65  	var err error
    66  	s.agentConfig, err = agent.NewAgentConfig(
    67  		agent.AgentConfigParams{
    68  			DataDir:      "/not/used/here",
    69  			Tag:          "tag",
    70  			Password:     "dummy-secret",
    71  			Nonce:        "nonce",
    72  			APIAddresses: []string{"10.0.0.1:1234"},
    73  			CACert:       []byte(coretesting.CACert),
    74  		})
    75  	c.Assert(err, gc.IsNil)
    76  	s.broker, err = provisioner.NewKvmBroker(&fakeAPI{}, tools, s.agentConfig)
    77  	c.Assert(err, gc.IsNil)
    78  }
    79  
    80  func (s *kvmBrokerSuite) startInstance(c *gc.C, machineId string) instance.Instance {
    81  	machineNonce := "fake-nonce"
    82  	stateInfo := jujutesting.FakeStateInfo(machineId)
    83  	apiInfo := jujutesting.FakeAPIInfo(machineId)
    84  	machineConfig := environs.NewMachineConfig(machineId, machineNonce, stateInfo, apiInfo)
    85  	cons := constraints.Value{}
    86  	possibleTools := s.broker.(coretools.HasTools).Tools()
    87  	kvm, _, err := s.broker.StartInstance(cons, possibleTools, machineConfig)
    88  	c.Assert(err, gc.IsNil)
    89  	return kvm
    90  }
    91  
    92  func (s *kvmBrokerSuite) TestStopInstance(c *gc.C) {
    93  	kvm0 := s.startInstance(c, "1/kvm/0")
    94  	kvm1 := s.startInstance(c, "1/kvm/1")
    95  	kvm2 := s.startInstance(c, "1/kvm/2")
    96  
    97  	err := s.broker.StopInstances([]instance.Instance{kvm0})
    98  	c.Assert(err, gc.IsNil)
    99  	s.assertInstances(c, kvm1, kvm2)
   100  	c.Assert(s.kvmContainerDir(kvm0), jc.DoesNotExist)
   101  	c.Assert(s.kvmRemovedContainerDir(kvm0), jc.IsDirectory)
   102  
   103  	err = s.broker.StopInstances([]instance.Instance{kvm1, kvm2})
   104  	c.Assert(err, gc.IsNil)
   105  	s.assertInstances(c)
   106  }
   107  
   108  func (s *kvmBrokerSuite) TestAllInstances(c *gc.C) {
   109  	kvm0 := s.startInstance(c, "1/kvm/0")
   110  	kvm1 := s.startInstance(c, "1/kvm/1")
   111  	s.assertInstances(c, kvm0, kvm1)
   112  
   113  	err := s.broker.StopInstances([]instance.Instance{kvm1})
   114  	c.Assert(err, gc.IsNil)
   115  	kvm2 := s.startInstance(c, "1/kvm/2")
   116  	s.assertInstances(c, kvm0, kvm2)
   117  }
   118  
   119  func (s *kvmBrokerSuite) assertInstances(c *gc.C, inst ...instance.Instance) {
   120  	results, err := s.broker.AllInstances()
   121  	c.Assert(err, gc.IsNil)
   122  	instancetest.MatchInstances(c, results, inst...)
   123  }
   124  
   125  func (s *kvmBrokerSuite) kvmContainerDir(inst instance.Instance) string {
   126  	return filepath.Join(s.ContainerDir, string(inst.Id()))
   127  }
   128  
   129  func (s *kvmBrokerSuite) kvmRemovedContainerDir(inst instance.Instance) string {
   130  	return filepath.Join(s.RemovedDir, string(inst.Id()))
   131  }
   132  
   133  type kvmProvisionerSuite struct {
   134  	CommonProvisionerSuite
   135  	kvmSuite
   136  	machineId string
   137  	events    chan mock.Event
   138  }
   139  
   140  var _ = gc.Suite(&kvmProvisionerSuite{})
   141  
   142  func (s *kvmProvisionerSuite) SetUpSuite(c *gc.C) {
   143  	s.CommonProvisionerSuite.SetUpSuite(c)
   144  	s.kvmSuite.SetUpSuite(c)
   145  }
   146  
   147  func (s *kvmProvisionerSuite) TearDownSuite(c *gc.C) {
   148  	s.kvmSuite.TearDownSuite(c)
   149  	s.CommonProvisionerSuite.TearDownSuite(c)
   150  }
   151  
   152  func (s *kvmProvisionerSuite) SetUpTest(c *gc.C) {
   153  	s.CommonProvisionerSuite.SetUpTest(c)
   154  	s.kvmSuite.SetUpTest(c)
   155  
   156  	// The kvm provisioner actually needs the machine it is being created on
   157  	// to be in state, in order to get the watcher.
   158  	m, err := s.State.AddMachine(config.DefaultSeries, state.JobHostUnits, state.JobManageEnviron)
   159  	c.Assert(err, gc.IsNil)
   160  	err = m.SetAddresses([]instance.Address{
   161  		instance.NewAddress("0.1.2.3"),
   162  	})
   163  	c.Assert(err, gc.IsNil)
   164  	s.machineId = m.Id()
   165  	s.APILogin(c, m)
   166  	err = m.SetAgentVersion(version.Current)
   167  	c.Assert(err, gc.IsNil)
   168  
   169  	s.events = make(chan mock.Event, 25)
   170  	s.Factory.AddListener(s.events)
   171  }
   172  
   173  func (s *kvmProvisionerSuite) expectStarted(c *gc.C, machine *state.Machine) string {
   174  	s.State.StartSync()
   175  	event := <-s.events
   176  	c.Assert(event.Action, gc.Equals, mock.Started)
   177  	err := machine.Refresh()
   178  	c.Assert(err, gc.IsNil)
   179  	s.waitInstanceId(c, machine, instance.Id(event.InstanceId))
   180  	return event.InstanceId
   181  }
   182  
   183  func (s *kvmProvisionerSuite) expectStopped(c *gc.C, instId string) {
   184  	s.State.StartSync()
   185  	event := <-s.events
   186  	c.Assert(event.Action, gc.Equals, mock.Stopped)
   187  	c.Assert(event.InstanceId, gc.Equals, instId)
   188  }
   189  
   190  func (s *kvmProvisionerSuite) expectNoEvents(c *gc.C) {
   191  	select {
   192  	case event := <-s.events:
   193  		c.Fatalf("unexpected event %#v", event)
   194  	case <-time.After(coretesting.ShortWait):
   195  		return
   196  	}
   197  }
   198  
   199  func (s *kvmProvisionerSuite) TearDownTest(c *gc.C) {
   200  	close(s.events)
   201  	s.kvmSuite.TearDownTest(c)
   202  	s.CommonProvisionerSuite.TearDownTest(c)
   203  }
   204  
   205  func (s *kvmProvisionerSuite) newKvmProvisioner(c *gc.C) provisioner.Provisioner {
   206  	machineTag := names.MachineTag(s.machineId)
   207  	agentConfig := s.AgentConfigForTag(c, machineTag)
   208  	tools, err := s.provisioner.Tools(agentConfig.Tag())
   209  	c.Assert(err, gc.IsNil)
   210  	broker, err := provisioner.NewKvmBroker(s.provisioner, tools, agentConfig)
   211  	c.Assert(err, gc.IsNil)
   212  	return provisioner.NewContainerProvisioner(instance.KVM, s.provisioner, agentConfig, broker)
   213  }
   214  
   215  func (s *kvmProvisionerSuite) TestProvisionerStartStop(c *gc.C) {
   216  	p := s.newKvmProvisioner(c)
   217  	c.Assert(p.Stop(), gc.IsNil)
   218  }
   219  
   220  func (s *kvmProvisionerSuite) TestDoesNotStartEnvironMachines(c *gc.C) {
   221  	p := s.newKvmProvisioner(c)
   222  	defer stop(c, p)
   223  
   224  	// Check that an instance is not provisioned when the machine is created.
   225  	_, err := s.State.AddMachine(config.DefaultSeries, state.JobHostUnits)
   226  	c.Assert(err, gc.IsNil)
   227  
   228  	s.expectNoEvents(c)
   229  }
   230  
   231  func (s *kvmProvisionerSuite) addContainer(c *gc.C) *state.Machine {
   232  	template := state.MachineTemplate{
   233  		Series: config.DefaultSeries,
   234  		Jobs:   []state.MachineJob{state.JobHostUnits},
   235  	}
   236  	container, err := s.State.AddMachineInsideMachine(template, s.machineId, instance.KVM)
   237  	c.Assert(err, gc.IsNil)
   238  	return container
   239  }
   240  
   241  func (s *kvmProvisionerSuite) TestContainerStartedAndStopped(c *gc.C) {
   242  	p := s.newKvmProvisioner(c)
   243  	defer stop(c, p)
   244  
   245  	container := s.addContainer(c)
   246  
   247  	instId := s.expectStarted(c, container)
   248  
   249  	// ...and removed, along with the machine, when the machine is Dead.
   250  	c.Assert(container.EnsureDead(), gc.IsNil)
   251  	s.expectStopped(c, instId)
   252  	s.waitRemoved(c, container)
   253  }