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