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 }