| OLD | NEW |
| 1 package main | 1 package main |
| 2 | 2 |
| 3 import ( | 3 import ( |
| 4 "time" |
| 5 |
| 4 . "launchpad.net/gocheck" | 6 . "launchpad.net/gocheck" |
| 5 "launchpad.net/gozk/zookeeper" | 7 "launchpad.net/gozk/zookeeper" |
| 6 "launchpad.net/juju-core/juju/cmd" | 8 "launchpad.net/juju-core/juju/cmd" |
| 7 "launchpad.net/juju-core/juju/environs/dummy" | 9 "launchpad.net/juju-core/juju/environs/dummy" |
| 8 "launchpad.net/juju-core/juju/state" | 10 "launchpad.net/juju-core/juju/state" |
| 9 "launchpad.net/juju-core/juju/testing" | 11 "launchpad.net/juju-core/juju/testing" |
| 10 ) | 12 ) |
| 11 | 13 |
| 12 type ProvisioningSuite struct { | 14 type ProvisioningSuite struct { |
| 13 zkConn *zookeeper.Conn | 15 zkConn *zookeeper.Conn |
| 16 zkInfo *state.Info |
| 14 st *state.State | 17 st *state.State |
| 15 } | 18 } |
| 16 | 19 |
| 17 var _ = Suite(&ProvisioningSuite{}) | 20 var _ = Suite(&ProvisioningSuite{}) |
| 18 | 21 |
| 19 func (s *ProvisioningSuite) SetUpTest(c *C) { | 22 func (s *ProvisioningSuite) SetUpTest(c *C) { |
| 20 zk, session, err := zookeeper.Dial(zkAddr, 15e9) | 23 zk, session, err := zookeeper.Dial(zkAddr, 15e9) |
| 21 c.Assert(err, IsNil) | 24 c.Assert(err, IsNil) |
| 22 event := <-session | 25 event := <-session |
| 23 c.Assert(event.Ok(), Equals, true) | 26 c.Assert(event.Ok(), Equals, true) |
| 24 c.Assert(event.Type, Equals, zookeeper.EVENT_SESSION) | 27 c.Assert(event.Type, Equals, zookeeper.EVENT_SESSION) |
| 25 c.Assert(event.State, Equals, zookeeper.STATE_CONNECTED) | 28 c.Assert(event.State, Equals, zookeeper.STATE_CONNECTED) |
| 26 | 29 |
| 27 s.zkConn = zk | 30 s.zkConn = zk |
| 28 » info := &state.Info{ | 31 » s.zkInfo = &state.Info{ |
| 29 Addrs: []string{zkAddr}, | 32 Addrs: []string{zkAddr}, |
| 30 } | 33 } |
| 31 » testing.ZkRemoveTree(s.zkConn, "/") | 34 » s.st, err = state.Initialize(s.zkInfo) |
| 32 » s.st, err = state.Initialize(info) | |
| 33 c.Assert(err, IsNil) | 35 c.Assert(err, IsNil) |
| 34 | 36 |
| 35 dummy.Reset() | 37 dummy.Reset() |
| 38 |
| 39 // seed /environment to point to dummy |
| 40 env, err := s.st.EnvironConfig() |
| 41 c.Assert(err, IsNil) |
| 42 env.Set("type", "dummy") |
| 43 env.Set("zookeeper", false) |
| 44 env.Set("name", "testing") |
| 45 _, err = env.Write() |
| 46 c.Assert(err, IsNil) |
| 36 } | 47 } |
| 37 | 48 |
| 38 func (s *ProvisioningSuite) TearDownTest(c *C) { | 49 func (s *ProvisioningSuite) TearDownTest(c *C) { |
| 50 testing.ZkRemoveTree(s.zkConn, "/") |
| 39 s.zkConn.Close() | 51 s.zkConn.Close() |
| 40 } | 52 } |
| 41 | 53 |
| 42 func (s *ProvisioningSuite) TestParseSuccess(c *C) { | 54 func (s *ProvisioningSuite) TestParseSuccess(c *C) { |
| 43 create := func() (cmd.Command, *AgentConf) { | 55 create := func() (cmd.Command, *AgentConf) { |
| 44 a := &ProvisioningAgent{} | 56 a := &ProvisioningAgent{} |
| 45 return a, &a.Conf | 57 return a, &a.Conf |
| 46 } | 58 } |
| 47 CheckAgentCommand(c, create, []string{}) | 59 CheckAgentCommand(c, create, []string{}) |
| 48 } | 60 } |
| 49 | 61 |
| 50 func (s *ProvisioningSuite) TestParseUnknown(c *C) { | 62 func (s *ProvisioningSuite) TestParseUnknown(c *C) { |
| 51 a := &ProvisioningAgent{} | 63 a := &ProvisioningAgent{} |
| 52 err := ParseAgentCommand(a, []string{"nincompoops"}) | 64 err := ParseAgentCommand(a, []string{"nincompoops"}) |
| 53 c.Assert(err, ErrorMatches, `unrecognized args: \["nincompoops"\]`) | 65 c.Assert(err, ErrorMatches, `unrecognized args: \["nincompoops"\]`) |
| 54 } | 66 } |
| 55 | 67 |
| 56 func initProvisioningAgent() (*ProvisioningAgent, error) { | 68 func initProvisioningAgent() (*ProvisioningAgent, error) { |
| 57 args := []string{"--zookeeper-servers", zkAddr} | 69 args := []string{"--zookeeper-servers", zkAddr} |
| 58 c := &ProvisioningAgent{} | 70 c := &ProvisioningAgent{} |
| 59 return c, initCmd(c, args) | 71 return c, initCmd(c, args) |
| 60 } | 72 } |
| 61 | 73 |
| 62 func (s *ProvisioningSuite) TestProvisionerStartStop(c *C) { | 74 func (s *ProvisioningSuite) TestProvisionerStartStop(c *C) { |
| 63 » p := NewProvisioner(s.st) | 75 » p := NewProvisioner(s.st, s.zkInfo) |
| 64 c.Assert(p.Stop(), IsNil) | 76 c.Assert(p.Stop(), IsNil) |
| 65 } | 77 } |
| 66 | 78 |
| 67 func (s *ProvisioningSuite) TestProvisionerEnvironmentChange(c *C) { | 79 func (s *ProvisioningSuite) TestProvisionerEnvironmentChange(c *C) { |
| 68 » p := NewProvisioner(s.st) | 80 » p := NewProvisioner(s.st, s.zkInfo) |
| 69 | 81 |
| 70 » // Change environment configuration to point to dummy. | 82 » // twiddle with the environment |
| 71 env, err := s.st.EnvironConfig() | 83 env, err := s.st.EnvironConfig() |
| 72 c.Assert(err, IsNil) | 84 c.Assert(err, IsNil) |
| 73 env.Set("type", "dummy") | |
| 74 env.Set("zookeeper", false) | |
| 75 env.Set("name", "testing") | |
| 76 _, err = env.Write() | |
| 77 c.Assert(err, IsNil) | |
| 78 | |
| 79 // Twiddle with the environment configuration. | |
| 80 env, err = s.st.EnvironConfig() | |
| 81 c.Assert(err, IsNil) | |
| 82 env.Set("name", "testing2") | 85 env.Set("name", "testing2") |
| 83 _, err = env.Write() | 86 _, err = env.Write() |
| 84 c.Assert(err, IsNil) | 87 c.Assert(err, IsNil) |
| 85 env.Set("name", "testing3") | 88 env.Set("name", "testing3") |
| 86 _, err = env.Write() | 89 _, err = env.Write() |
| 87 c.Assert(p.Stop(), IsNil) | 90 c.Assert(p.Stop(), IsNil) |
| 88 } | 91 } |
| 89 | 92 |
| 90 func (s *ProvisioningSuite) TestProvisionerStopOnStateClose(c *C) { | 93 func (s *ProvisioningSuite) TestProvisionerStopOnStateClose(c *C) { |
| 91 » p := NewProvisioner(s.st) | 94 » p := NewProvisioner(s.st, s.zkInfo) |
| 92 | |
| 93 » // Change environment configuration to point to dummy. | |
| 94 » env, err := s.st.EnvironConfig() | |
| 95 » c.Assert(err, IsNil) | |
| 96 » env.Set("type", "dummy") | |
| 97 » env.Set("zookeeper", false) | |
| 98 » env.Set("name", "testing") | |
| 99 » _, err = env.Write() | |
| 100 » c.Assert(err, IsNil) | |
| 101 | 95 |
| 102 s.st.Close() | 96 s.st.Close() |
| 103 | 97 |
| 104 c.Assert(p.Wait(), ErrorMatches, "watcher.*") | 98 c.Assert(p.Wait(), ErrorMatches, "watcher.*") |
| 105 c.Assert(p.Stop(), ErrorMatches, "watcher.*") | 99 c.Assert(p.Stop(), ErrorMatches, "watcher.*") |
| 106 | 100 } |
| 107 } | 101 |
| 102 // Start and stop one machine, watch the PA. |
| 103 func (s *ProvisioningSuite) TestSimple(c *C) { |
| 104 » p := NewProvisioner(s.st, s.zkInfo) |
| 105 |
| 106 » op := make(chan dummy.Operation, 1) |
| 107 » dummy.Listen(op) |
| 108 |
| 109 » // place a new machine into the state |
| 110 » m, err := s.st.AddMachine() |
| 111 » c.Assert(err, IsNil) |
| 112 |
| 113 » // watch the PA create it |
| 114 » select { |
| 115 » case o := <-op: |
| 116 » » c.Assert(o.Kind, Equals, dummy.OpStartInstance) |
| 117 » case <-time.After(3 * time.Second): |
| 118 » » c.Fatalf("ProvisioningAgent did not action AddMachine after 3 se
cond") |
| 119 » } |
| 120 |
| 121 » // now remove it |
| 122 » c.Assert(s.st.RemoveMachine(m.Id()), IsNil) |
| 123 |
| 124 » // watch the PA remove it |
| 125 » select { |
| 126 » case o := <-op: |
| 127 » » c.Assert(o.Kind, Equals, dummy.OpStopInstances) |
| 128 » case <-time.After(3 * time.Second): |
| 129 » » c.Fatalf("ProvisioningAgent did not action RemoveMachine after 3
second") |
| 130 » } |
| 131 |
| 132 » c.Assert(p.Stop(), IsNil) |
| 133 } |
| 134 |
| 135 func (s *ProvisioningSuite) TestProvisioningDoesNotOccurWithAnInvalidEnvironment
(c *C) { |
| 136 » // make the environment unpalitable to the config checker |
| 137 » env, err := s.st.EnvironConfig() |
| 138 » c.Assert(err, IsNil) |
| 139 » env.Set("name", 1) |
| 140 » _, err = env.Write() |
| 141 » c.Assert(err, IsNil) |
| 142 |
| 143 » p := NewProvisioner(s.st, s.zkInfo) |
| 144 |
| 145 » op := make(chan dummy.Operation, 1) |
| 146 » dummy.Listen(op) |
| 147 |
| 148 » // try to create a machine |
| 149 » _, err = s.st.AddMachine() |
| 150 » c.Assert(err, IsNil) |
| 151 |
| 152 » // the PA should not create it |
| 153 » select { |
| 154 » case <-op: |
| 155 » » c.Fatalf("provisioner started an instance") |
| 156 » case <-time.After(1 * time.Second): |
| 157 |
| 158 » } |
| 159 |
| 160 » c.Assert(p.Stop(), IsNil) |
| 161 } |
| 162 |
| 163 func (s *ProvisioningSuite) TestProvisioningOccursWithFixedEnvironment(c *C) { |
| 164 » // make the environment unpalitable to the config checker |
| 165 » env, err := s.st.EnvironConfig() |
| 166 » c.Assert(err, IsNil) |
| 167 » env.Set("name", 1) |
| 168 » _, err = env.Write() |
| 169 » c.Assert(err, IsNil) |
| 170 |
| 171 » p := NewProvisioner(s.st, s.zkInfo) |
| 172 |
| 173 » op := make(chan dummy.Operation, 1) |
| 174 » dummy.Listen(op) |
| 175 |
| 176 » // try to create a machine |
| 177 » _, err = s.st.AddMachine() |
| 178 » c.Assert(err, IsNil) |
| 179 |
| 180 » // the PA should not create it |
| 181 » select { |
| 182 » case <-op: |
| 183 » » c.Fatalf("provisioner started an instance") |
| 184 » case <-time.After(1 * time.Second): |
| 185 |
| 186 » } |
| 187 |
| 188 » // now fix the environment |
| 189 » env.Set("name", "testing") |
| 190 » _, err = env.Write() |
| 191 » c.Assert(err, IsNil) |
| 192 |
| 193 » // watch the PA create it |
| 194 » select { |
| 195 » case o := <-op: |
| 196 » » c.Assert(o.Kind, Equals, dummy.OpStartInstance) |
| 197 » case <-time.After(3 * time.Second): |
| 198 » » c.Fatalf("ProvisioningAgent did not action AddMachine after 3 se
cond") |
| 199 » } |
| 200 |
| 201 » c.Assert(p.Stop(), IsNil) |
| 202 } |
| 203 |
| 204 func (s *ProvisioningSuite) TestProvisioningDoesOccurAfterInvalidEnvironmentPubl
ished(c *C) { |
| 205 » p := NewProvisioner(s.st, s.zkInfo) |
| 206 |
| 207 » op := make(chan dummy.Operation, 1) |
| 208 » dummy.Listen(op) |
| 209 |
| 210 » // place a new machine into the state |
| 211 » _, err := s.st.AddMachine() |
| 212 » c.Assert(err, IsNil) |
| 213 |
| 214 » // watch the PA create it |
| 215 » select { |
| 216 » case o := <-op: |
| 217 » » c.Assert(o.Kind, Equals, dummy.OpStartInstance) |
| 218 » case <-time.After(3 * time.Second): |
| 219 » » c.Fatalf("ProvisioningAgent did not action AddMachine after 3 se
cond") |
| 220 » } |
| 221 |
| 222 » // make the environment unpalitable to the config checker |
| 223 » env, err := s.st.EnvironConfig() |
| 224 » c.Assert(err, IsNil) |
| 225 » env.Set("name", 1) |
| 226 » _, err = env.Write() |
| 227 » c.Assert(err, IsNil) |
| 228 |
| 229 » // create a second machine |
| 230 » _, err = s.st.AddMachine() |
| 231 » c.Assert(err, IsNil) |
| 232 |
| 233 » // the PA should create it using the old environment |
| 234 » // watch the PA create it |
| 235 » select { |
| 236 » case o := <-op: |
| 237 » » c.Assert(o.Kind, Equals, dummy.OpStartInstance) |
| 238 » case <-time.After(3 * time.Second): |
| 239 » » c.Fatalf("ProvisioningAgent did not action AddMachine after 3 se
cond") |
| 240 » } |
| 241 |
| 242 » c.Assert(p.Stop(), IsNil) |
| 243 } |
| 244 |
| 245 func (s *ProvisioningSuite) TestProvisioningDoesNotProvisionTheSameMachineAfterR
estart(c *C) { |
| 246 » p := NewProvisioner(s.st, s.zkInfo) |
| 247 |
| 248 » op := make(chan dummy.Operation, 1) |
| 249 » dummy.Listen(op) |
| 250 |
| 251 » // create a machine |
| 252 » _, err := s.st.AddMachine() |
| 253 » c.Assert(err, IsNil) |
| 254 |
| 255 » // the PA should create it |
| 256 » select { |
| 257 » case o := <-op: |
| 258 » » c.Assert(o.Kind, Equals, dummy.OpStartInstance) |
| 259 » case <-time.After(3 * time.Second): |
| 260 » » c.Fatalf("ProvisioningAgent did not action AddMachine after 3 se
cond") |
| 261 » } |
| 262 |
| 263 » // restart the PA |
| 264 » c.Assert(p.Stop(), IsNil) |
| 265 » p = NewProvisioner(s.st, s.zkInfo) |
| 266 |
| 267 » // the PA should not create it a second time |
| 268 » select { |
| 269 » case <-op: |
| 270 » » c.Fatalf("provisioner started an instance") |
| 271 » case <-time.After(1 * time.Second): |
| 272 » } |
| 273 |
| 274 » c.Assert(p.Stop(), IsNil) |
| 275 } |
| 276 |
| 277 // TODO(dfc) machines removed from the state while the PA isn't watching are not
shut down. |
| 278 func (s *ProvisioningSuite) disabledTestProvisioningRemovesUnknownMachineAfterRe
start(c *C) { |
| 279 » p := NewProvisioner(s.st, s.zkInfo) |
| 280 |
| 281 » op := make(chan dummy.Operation, 1) |
| 282 » dummy.Listen(op) |
| 283 |
| 284 » // create a machine |
| 285 » m, err := s.st.AddMachine() |
| 286 » c.Assert(err, IsNil) |
| 287 |
| 288 » // the PA should create it |
| 289 » select { |
| 290 » case o := <-op: |
| 291 » » c.Assert(o.Kind, Equals, dummy.OpStartInstance) |
| 292 » case <-time.After(3 * time.Second): |
| 293 » » c.Fatalf("ProvisioningAgent did not action AddMachine after 3 se
cond") |
| 294 » } |
| 295 |
| 296 » // stop the PA |
| 297 » c.Assert(p.Stop(), IsNil) |
| 298 |
| 299 » // remove the machine from the topology |
| 300 » err = s.st.RemoveMachine(m.Id()) |
| 301 » c.Assert(err, IsNil) |
| 302 |
| 303 » // start a new PA»······ |
| 304 » p = NewProvisioner(s.st, s.zkInfo) |
| 305 |
| 306 » // the PA should remove this machine |
| 307 » select { |
| 308 » case o := <-op: |
| 309 » » c.Assert(o.Kind, Equals, dummy.OpStopInstances) |
| 310 » case <-time.After(3 * time.Second): |
| 311 » » c.Fatalf("ProvisioningAgent did not action RemoveMachine after 3
second") |
| 312 » } |
| 313 |
| 314 » c.Assert(p.Stop(), IsNil) |
| 315 } |
| 316 |
| 317 func (s *ProvisioningSuite) TestProvisioningRecoversAfterInvalidEnvironmentPubli
shed(c *C) { |
| 318 » p := NewProvisioner(s.st, s.zkInfo) |
| 319 |
| 320 » op := make(chan dummy.Operation, 1) |
| 321 » dummy.Listen(op) |
| 322 |
| 323 » // place a new machine into the state |
| 324 » _, err := s.st.AddMachine() |
| 325 » c.Assert(err, IsNil) |
| 326 |
| 327 » // watch the PA create it |
| 328 » select { |
| 329 » case o := <-op: |
| 330 » » c.Assert(o.Kind, Equals, dummy.OpStartInstance) |
| 331 » case <-time.After(3 * time.Second): |
| 332 » » c.Fatalf("ProvisioningAgent did not action AddMachine after 3 se
cond") |
| 333 » } |
| 334 |
| 335 » // make the environment unpalitable to the config checker |
| 336 » env, err := s.st.EnvironConfig() |
| 337 » c.Assert(err, IsNil) |
| 338 » env.Set("name", 1) |
| 339 » _, err = env.Write() |
| 340 » c.Assert(err, IsNil) |
| 341 |
| 342 » // create a second machine |
| 343 » _, err = s.st.AddMachine() |
| 344 » c.Assert(err, IsNil) |
| 345 |
| 346 » // the PA should create it using the old environment |
| 347 » // watch the PA create it |
| 348 » select { |
| 349 » case o := <-op: |
| 350 » » c.Assert(o.Kind, Equals, dummy.OpStartInstance) |
| 351 » case <-time.After(3 * time.Second): |
| 352 » » c.Fatalf("ProvisioningAgent did not action AddMachine after 3 se
cond") |
| 353 » } |
| 354 |
| 355 » // now fix the environment |
| 356 » env.Set("name", "testing") |
| 357 » _, err = env.Write() |
| 358 » c.Assert(err, IsNil) |
| 359 |
| 360 » // create a third machine |
| 361 » _, err = s.st.AddMachine() |
| 362 » c.Assert(err, IsNil) |
| 363 |
| 364 » // the PA should create it using the new environment |
| 365 » // watch the PA create it |
| 366 » select { |
| 367 » case o := <-op: |
| 368 » » c.Assert(o.Kind, Equals, dummy.OpStartInstance) |
| 369 » case <-time.After(3 * time.Second): |
| 370 » » c.Fatalf("ProvisioningAgent did not action AddMachine after 3 se
cond") |
| 371 » } |
| 372 |
| 373 » c.Assert(p.Stop(), IsNil) |
| 374 } |
| 375 |
| 376 // Start and stop lots of machines, watch the PA. |
| 377 func (s *ProvisioningSuite) TestHard(c *C) { |
| 378 » var N = 200 |
| 379 |
| 380 » p := NewProvisioner(s.st, s.zkInfo) |
| 381 |
| 382 » op := make(chan dummy.Operation, 1) |
| 383 » dummy.Listen(op) |
| 384 |
| 385 » go func() { |
| 386 » » for i := 0; i < N; i++ { |
| 387 » » » m, err := s.st.AddMachine() |
| 388 » » » <-time.After(20 * time.Millisecond) |
| 389 » » » c.Assert(err, IsNil) |
| 390 » » » c.Logf("added machine: %d", m.Id()) |
| 391 » » » go func() { |
| 392 » » » » err := s.st.RemoveMachine(m.Id()) |
| 393 » » » » c.Assert(err, IsNil) |
| 394 » » » » c.Logf("removed machine: %d", m.Id()) |
| 395 » » » }() |
| 396 » » } |
| 397 » }() |
| 398 |
| 399 » var started, stopped int |
| 400 |
| 401 » for stopped < N { |
| 402 » » select { |
| 403 » » case o := <-op: |
| 404 » » » switch o.Kind { |
| 405 » » » case dummy.OpStartInstance: |
| 406 » » » » started++ |
| 407 » » » case dummy.OpStopInstances: |
| 408 » » » » stopped++ |
| 409 » » » default: |
| 410 » » » » c.Fatalf("dummy reported unknown operation: %v",
o) |
| 411 » » » } |
| 412 » » case <-time.After(10 * time.Second): |
| 413 » » » c.Fatalf("PA stalled") |
| 414 » » } |
| 415 » } |
| 416 |
| 417 » c.Assert(started, Equals, N) |
| 418 » c.Assert(stopped, Equals, N) |
| 419 |
| 420 » c.Assert(p.Stop(), IsNil) |
| 421 } |
| OLD | NEW |