github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/worker/addresser/worker_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package addresser_test
     5  
     6  import (
     7  	"fmt"
     8  	"time"
     9  
    10  	"github.com/juju/errors"
    11  	jc "github.com/juju/testing/checkers"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	"github.com/juju/juju/feature"
    15  	"github.com/juju/juju/instance"
    16  	"github.com/juju/juju/juju/testing"
    17  	"github.com/juju/juju/network"
    18  	"github.com/juju/juju/provider/common"
    19  	"github.com/juju/juju/provider/dummy"
    20  	"github.com/juju/juju/state"
    21  	coretesting "github.com/juju/juju/testing"
    22  	"github.com/juju/juju/worker"
    23  	"github.com/juju/juju/worker/addresser"
    24  )
    25  
    26  var _ = gc.Suite(&workerSuite{})
    27  
    28  type workerSuite struct {
    29  	testing.JujuConnSuite
    30  	machine  *state.Machine
    31  	machine2 *state.Machine
    32  }
    33  
    34  func (s *workerSuite) SetUpTest(c *gc.C) {
    35  	s.JujuConnSuite.SetUpTest(c)
    36  	s.SetFeatureFlags(feature.AddressAllocation)
    37  	// Unbreak dummy provider methods.
    38  	s.AssertConfigParameterUpdated(c, "broken", "")
    39  
    40  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
    41  	s.machine = machine
    42  	c.Assert(err, jc.ErrorIsNil)
    43  	err = s.machine.SetProvisioned("foo", "fake_nonce", nil)
    44  	c.Assert(err, jc.ErrorIsNil)
    45  
    46  	// this machine will be destroyed after address creation to test the
    47  	// handling of addresses for machines that have gone.
    48  	machine2, err := s.State.AddMachine("quantal", state.JobHostUnits)
    49  	s.machine2 = machine2
    50  	c.Assert(err, jc.ErrorIsNil)
    51  
    52  	s.createAddresses(c)
    53  	s.State.StartSync()
    54  }
    55  
    56  func (s *workerSuite) createAddresses(c *gc.C) {
    57  	addresses := []string{
    58  		"0.1.2.3", "0.1.2.4", "0.1.2.5", "0.1.2.6",
    59  	}
    60  	for i, rawAddr := range addresses {
    61  		addr := network.NewAddress(rawAddr)
    62  		ipAddr, err := s.State.AddIPAddress(addr, "foobar")
    63  		c.Assert(err, jc.ErrorIsNil)
    64  		if i%2 == 1 {
    65  			err = ipAddr.AllocateTo(s.machine2.Id(), "wobble")
    66  		} else {
    67  			err = ipAddr.AllocateTo(s.machine.Id(), "wobble")
    68  			c.Assert(err, jc.ErrorIsNil)
    69  		}
    70  
    71  	}
    72  	// Two of the addresses start out allocated to this
    73  	// machine which we destroy to test the handling of
    74  	// addresses allocated to dead machines.
    75  	err := s.machine2.EnsureDead()
    76  	c.Assert(err, jc.ErrorIsNil)
    77  	err = s.machine2.Remove()
    78  	c.Assert(err, jc.ErrorIsNil)
    79  }
    80  
    81  func dummyListen() chan dummy.Operation {
    82  	opsChan := make(chan dummy.Operation, 10)
    83  	dummy.Listen(opsChan)
    84  	return opsChan
    85  }
    86  
    87  func waitForReleaseOp(c *gc.C, opsChan chan dummy.Operation) dummy.OpReleaseAddress {
    88  	var releaseOp dummy.OpReleaseAddress
    89  	var ok bool
    90  	select {
    91  	case op := <-opsChan:
    92  		releaseOp, ok = op.(dummy.OpReleaseAddress)
    93  		c.Assert(ok, jc.IsTrue)
    94  	case <-time.After(coretesting.LongWait):
    95  		c.Fatalf("timeout while expecting operation")
    96  	}
    97  	return releaseOp
    98  }
    99  
   100  func makeReleaseOp(digit int) dummy.OpReleaseAddress {
   101  	return dummy.OpReleaseAddress{
   102  		Env:        "dummyenv",
   103  		InstanceId: "foo",
   104  		SubnetId:   "foobar",
   105  		Address:    network.NewAddress(fmt.Sprintf("0.1.2.%d", digit)),
   106  	}
   107  }
   108  
   109  func (s *workerSuite) assertStop(c *gc.C, w worker.Worker) {
   110  	c.Assert(worker.Stop(w), jc.ErrorIsNil)
   111  }
   112  
   113  func (s *workerSuite) TestWorkerReleasesAlreadyDead(c *gc.C) {
   114  	// we start with two dead addresses
   115  	dead, err := s.State.DeadIPAddresses()
   116  	c.Assert(err, jc.ErrorIsNil)
   117  	c.Assert(dead, gc.HasLen, 2)
   118  
   119  	opsChan := dummyListen()
   120  
   121  	w, err := addresser.NewWorker(s.State)
   122  	c.Assert(err, jc.ErrorIsNil)
   123  	defer s.assertStop(c, w)
   124  	s.waitForInitialDead(c)
   125  
   126  	op1 := waitForReleaseOp(c, opsChan)
   127  	op2 := waitForReleaseOp(c, opsChan)
   128  	expected := []dummy.OpReleaseAddress{makeReleaseOp(4), makeReleaseOp(6)}
   129  
   130  	// The machines are dead, so ReleaseAddress should be called with
   131  	// instance.UnknownId.
   132  	expected[0].InstanceId = instance.UnknownId
   133  	expected[1].InstanceId = instance.UnknownId
   134  	c.Assert([]dummy.OpReleaseAddress{op1, op2}, jc.SameContents, expected)
   135  }
   136  
   137  func (s *workerSuite) waitForInitialDead(c *gc.C) {
   138  	for a := common.ShortAttempt.Start(); a.Next(); {
   139  		dead, err := s.State.DeadIPAddresses()
   140  		c.Assert(err, jc.ErrorIsNil)
   141  		if len(dead) == 0 {
   142  			break
   143  		}
   144  		if !a.HasNext() {
   145  			c.Fatalf("timeout waiting for initial change (dead: %#v)", dead)
   146  		}
   147  	}
   148  }
   149  
   150  func (s *workerSuite) TestWorkerIgnoresAliveAddresses(c *gc.C) {
   151  	w, err := addresser.NewWorker(s.State)
   152  	c.Assert(err, jc.ErrorIsNil)
   153  	defer s.assertStop(c, w)
   154  	s.waitForInitialDead(c)
   155  
   156  	// Add a new alive address.
   157  	addr := network.NewAddress("0.1.2.9")
   158  	ipAddr, err := s.State.AddIPAddress(addr, "foobar")
   159  	c.Assert(err, jc.ErrorIsNil)
   160  	err = ipAddr.AllocateTo(s.machine.Id(), "wobble")
   161  	c.Assert(err, jc.ErrorIsNil)
   162  
   163  	// The worker must not kill this address.
   164  	for a := common.ShortAttempt.Start(); a.Next(); {
   165  		ipAddr, err := s.State.IPAddress("0.1.2.9")
   166  		c.Assert(err, jc.ErrorIsNil)
   167  		c.Assert(ipAddr.Life(), gc.Equals, state.Alive)
   168  	}
   169  }
   170  
   171  func (s *workerSuite) TestWorkerRemovesDeadAddress(c *gc.C) {
   172  	w, err := addresser.NewWorker(s.State)
   173  	c.Assert(err, jc.ErrorIsNil)
   174  	defer s.assertStop(c, w)
   175  	s.waitForInitialDead(c)
   176  	opsChan := dummyListen()
   177  
   178  	addr, err := s.State.IPAddress("0.1.2.3")
   179  	c.Assert(err, jc.ErrorIsNil)
   180  	err = addr.EnsureDead()
   181  	c.Assert(err, jc.ErrorIsNil)
   182  
   183  	// Wait for ReleaseAddress attempt.
   184  	op := waitForReleaseOp(c, opsChan)
   185  	c.Assert(op, jc.DeepEquals, makeReleaseOp(3))
   186  
   187  	// The address should have been removed from state.
   188  	for a := common.ShortAttempt.Start(); a.Next(); {
   189  		_, err := s.State.IPAddress("0.1.2.3")
   190  		if errors.IsNotFound(err) {
   191  			break
   192  		}
   193  		if !a.HasNext() {
   194  			c.Fatalf("IP address not removed")
   195  		}
   196  	}
   197  }
   198  
   199  func (s *workerSuite) TestMachineRemovalTriggersWorker(c *gc.C) {
   200  	w, err := addresser.NewWorker(s.State)
   201  	c.Assert(err, jc.ErrorIsNil)
   202  	defer s.assertStop(c, w)
   203  	s.waitForInitialDead(c)
   204  	opsChan := dummyListen()
   205  
   206  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   207  	c.Assert(err, jc.ErrorIsNil)
   208  	err = machine.SetProvisioned("foo", "really-fake", nil)
   209  	c.Assert(err, jc.ErrorIsNil)
   210  	s.State.StartSync()
   211  
   212  	addr, err := s.State.AddIPAddress(network.NewAddress("0.1.2.9"), "foobar")
   213  	c.Assert(err, jc.ErrorIsNil)
   214  	err = addr.AllocateTo(machine.Id(), "foo")
   215  	c.Assert(err, jc.ErrorIsNil)
   216  	c.Assert(addr.InstanceId(), gc.Equals, instance.Id("foo"))
   217  	s.State.StartSync()
   218  
   219  	err = machine.EnsureDead()
   220  	c.Assert(err, jc.ErrorIsNil)
   221  	err = machine.Remove()
   222  	c.Assert(err, jc.ErrorIsNil)
   223  
   224  	err = addr.Refresh()
   225  	c.Assert(err, jc.ErrorIsNil)
   226  	c.Assert(addr.Life(), gc.Equals, state.Dead)
   227  
   228  	// Wait for ReleaseAddress attempt.
   229  	op := waitForReleaseOp(c, opsChan)
   230  	c.Assert(op, jc.DeepEquals, makeReleaseOp(9))
   231  
   232  	// The address should have been removed from state.
   233  	for a := common.ShortAttempt.Start(); a.Next(); {
   234  		_, err := s.State.IPAddress("0.1.2.9")
   235  		if errors.IsNotFound(err) {
   236  			break
   237  		}
   238  		if !a.HasNext() {
   239  			c.Fatalf("IP address not removed")
   240  		}
   241  	}
   242  }
   243  
   244  func (s *workerSuite) TestErrorKillsWorker(c *gc.C) {
   245  	s.AssertConfigParameterUpdated(c, "broken", "ReleaseAddress")
   246  	w, err := addresser.NewWorker(s.State)
   247  	c.Assert(err, jc.ErrorIsNil)
   248  	defer worker.Stop(w)
   249  
   250  	// The worker should have died with an error.
   251  
   252  	stopErr := make(chan error)
   253  	go func() {
   254  		w.Wait()
   255  		stopErr <- worker.Stop(w)
   256  	}()
   257  
   258  	select {
   259  	case err := <-stopErr:
   260  		msg := "failed to release address .*: dummy.ReleaseAddress is broken"
   261  		c.Assert(err, gc.ErrorMatches, msg)
   262  	case <-time.After(coretesting.LongWait):
   263  		c.Fatalf("worker did not stop as expected")
   264  	}
   265  
   266  	// As we failed to release addresses they should not have been removed
   267  	// from state.
   268  	for _, digit := range []int{3, 4, 5, 6} {
   269  		rawAddr := fmt.Sprintf("0.1.2.%d", digit)
   270  		_, err := s.State.IPAddress(rawAddr)
   271  		c.Assert(err, jc.ErrorIsNil)
   272  	}
   273  }
   274  
   275  func (s *workerSuite) TestAddresserWithNoNetworkingEnviron(c *gc.C) {
   276  	opsChan := dummyListen()
   277  	w := addresser.NewWorkerWithReleaser(s.State, nil)
   278  	defer s.assertStop(c, w)
   279  
   280  	for {
   281  		select {
   282  		case <-opsChan:
   283  			c.Fatalf("unexpected release op")
   284  		case <-time.After(coretesting.ShortWait):
   285  			return
   286  		}
   287  	}
   288  }