github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/machine_test.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "sort" 8 9 "github.com/juju/errors" 10 "github.com/juju/loggo" 11 jc "github.com/juju/testing/checkers" 12 jujutxn "github.com/juju/txn" 13 "github.com/juju/version" 14 gc "gopkg.in/check.v1" 15 "gopkg.in/juju/names.v2" 16 "gopkg.in/mgo.v2" 17 "gopkg.in/mgo.v2/bson" 18 19 "github.com/juju/juju/constraints" 20 "github.com/juju/juju/instance" 21 "github.com/juju/juju/mongo/mongotest" 22 "github.com/juju/juju/network" 23 "github.com/juju/juju/provider/dummy" 24 "github.com/juju/juju/state" 25 "github.com/juju/juju/state/testing" 26 "github.com/juju/juju/status" 27 "github.com/juju/juju/storage/poolmanager" 28 "github.com/juju/juju/storage/provider" 29 coretesting "github.com/juju/juju/testing" 30 "github.com/juju/juju/worker" 31 ) 32 33 type MachineSuite struct { 34 ConnSuite 35 machine0 *state.Machine 36 machine *state.Machine 37 } 38 39 var _ = gc.Suite(&MachineSuite{}) 40 41 func (s *MachineSuite) SetUpTest(c *gc.C) { 42 s.ConnSuite.SetUpTest(c) 43 s.policy.GetConstraintsValidator = func() (constraints.Validator, error) { 44 validator := constraints.NewValidator() 45 validator.RegisterConflicts([]string{constraints.InstanceType}, []string{constraints.Mem}) 46 validator.RegisterUnsupported([]string{constraints.CpuPower}) 47 return validator, nil 48 } 49 var err error 50 s.machine0, err = s.State.AddMachine("quantal", state.JobManageModel) 51 c.Assert(err, jc.ErrorIsNil) 52 s.machine, err = s.State.AddMachine("quantal", state.JobHostUnits) 53 c.Assert(err, jc.ErrorIsNil) 54 } 55 56 func (s *MachineSuite) TestSetRebootFlagDeadMachine(c *gc.C) { 57 err := s.machine.EnsureDead() 58 c.Assert(err, jc.ErrorIsNil) 59 60 err = s.machine.SetRebootFlag(true) 61 c.Assert(err, gc.Equals, mgo.ErrNotFound) 62 63 rFlag, err := s.machine.GetRebootFlag() 64 c.Assert(err, jc.ErrorIsNil) 65 c.Assert(rFlag, jc.IsFalse) 66 67 err = s.machine.SetRebootFlag(false) 68 c.Assert(err, jc.ErrorIsNil) 69 70 action, err := s.machine.ShouldRebootOrShutdown() 71 c.Assert(err, jc.ErrorIsNil) 72 c.Assert(action, gc.Equals, state.ShouldDoNothing) 73 } 74 75 func (s *MachineSuite) TestSetRebootFlagDeadMachineRace(c *gc.C) { 76 setFlag := jujutxn.TestHook{ 77 Before: func() { 78 err := s.machine.EnsureDead() 79 c.Assert(err, jc.ErrorIsNil) 80 }, 81 } 82 defer state.SetTestHooks(c, s.State, setFlag).Check() 83 84 err := s.machine.SetRebootFlag(true) 85 c.Assert(err, gc.Equals, mgo.ErrNotFound) 86 } 87 88 func (s *MachineSuite) TestSetRebootFlag(c *gc.C) { 89 err := s.machine.SetRebootFlag(true) 90 c.Assert(err, jc.ErrorIsNil) 91 92 rebootFlag, err := s.machine.GetRebootFlag() 93 c.Assert(err, jc.ErrorIsNil) 94 c.Assert(rebootFlag, jc.IsTrue) 95 } 96 97 func (s *MachineSuite) TestSetUnsetRebootFlag(c *gc.C) { 98 err := s.machine.SetRebootFlag(true) 99 c.Assert(err, jc.ErrorIsNil) 100 101 rebootFlag, err := s.machine.GetRebootFlag() 102 c.Assert(err, jc.ErrorIsNil) 103 c.Assert(rebootFlag, jc.IsTrue) 104 105 err = s.machine.SetRebootFlag(false) 106 c.Assert(err, jc.ErrorIsNil) 107 108 rebootFlag, err = s.machine.GetRebootFlag() 109 c.Assert(err, jc.ErrorIsNil) 110 c.Assert(rebootFlag, jc.IsFalse) 111 } 112 113 func (s *MachineSuite) TestAddMachineInsideMachineModelDying(c *gc.C) { 114 model, err := s.State.Model() 115 c.Assert(err, jc.ErrorIsNil) 116 c.Assert(model.Destroy(), jc.ErrorIsNil) 117 118 _, err = s.State.AddMachineInsideMachine(state.MachineTemplate{ 119 Series: "quantal", 120 Jobs: []state.MachineJob{state.JobHostUnits}, 121 }, s.machine.Id(), instance.LXD) 122 c.Assert(err, gc.ErrorMatches, `model "testenv" is no longer alive`) 123 } 124 125 func (s *MachineSuite) TestAddMachineInsideMachineModelMigrating(c *gc.C) { 126 model, err := s.State.Model() 127 c.Assert(err, jc.ErrorIsNil) 128 c.Assert(model.SetMigrationMode(state.MigrationModeExporting), jc.ErrorIsNil) 129 130 _, err = s.State.AddMachineInsideMachine(state.MachineTemplate{ 131 Series: "quantal", 132 Jobs: []state.MachineJob{state.JobHostUnits}, 133 }, s.machine.Id(), instance.LXD) 134 c.Assert(err, gc.ErrorMatches, `model "testenv" is being migrated`) 135 } 136 137 func (s *MachineSuite) TestShouldShutdownOrReboot(c *gc.C) { 138 // Add first container. 139 c1, err := s.State.AddMachineInsideMachine(state.MachineTemplate{ 140 Series: "quantal", 141 Jobs: []state.MachineJob{state.JobHostUnits}, 142 }, s.machine.Id(), instance.LXD) 143 c.Assert(err, jc.ErrorIsNil) 144 145 // Add second container. 146 c2, err := s.State.AddMachineInsideMachine(state.MachineTemplate{ 147 Series: "quantal", 148 Jobs: []state.MachineJob{state.JobHostUnits}, 149 }, c1.Id(), instance.LXD) 150 c.Assert(err, jc.ErrorIsNil) 151 152 err = c2.SetRebootFlag(true) 153 c.Assert(err, jc.ErrorIsNil) 154 155 rAction, err := s.machine.ShouldRebootOrShutdown() 156 c.Assert(err, jc.ErrorIsNil) 157 c.Assert(rAction, gc.Equals, state.ShouldDoNothing) 158 159 rAction, err = c1.ShouldRebootOrShutdown() 160 c.Assert(err, jc.ErrorIsNil) 161 c.Assert(rAction, gc.Equals, state.ShouldDoNothing) 162 163 rAction, err = c2.ShouldRebootOrShutdown() 164 c.Assert(err, jc.ErrorIsNil) 165 c.Assert(rAction, gc.Equals, state.ShouldReboot) 166 167 // // Reboot happens on the root node 168 err = c2.SetRebootFlag(false) 169 c.Assert(err, jc.ErrorIsNil) 170 171 err = s.machine.SetRebootFlag(true) 172 c.Assert(err, jc.ErrorIsNil) 173 174 rAction, err = s.machine.ShouldRebootOrShutdown() 175 c.Assert(err, jc.ErrorIsNil) 176 c.Assert(rAction, gc.Equals, state.ShouldReboot) 177 178 rAction, err = c1.ShouldRebootOrShutdown() 179 c.Assert(err, jc.ErrorIsNil) 180 c.Assert(rAction, gc.Equals, state.ShouldShutdown) 181 182 rAction, err = c2.ShouldRebootOrShutdown() 183 c.Assert(err, jc.ErrorIsNil) 184 c.Assert(rAction, gc.Equals, state.ShouldShutdown) 185 } 186 187 func (s *MachineSuite) TestContainerDefaults(c *gc.C) { 188 c.Assert(string(s.machine.ContainerType()), gc.Equals, "") 189 containers, err := s.machine.Containers() 190 c.Assert(err, jc.ErrorIsNil) 191 c.Assert(containers, gc.DeepEquals, []string(nil)) 192 } 193 194 func (s *MachineSuite) TestParentId(c *gc.C) { 195 parentId, ok := s.machine.ParentId() 196 c.Assert(parentId, gc.Equals, "") 197 c.Assert(ok, jc.IsFalse) 198 container, err := s.State.AddMachineInsideMachine(state.MachineTemplate{ 199 Series: "quantal", 200 Jobs: []state.MachineJob{state.JobHostUnits}, 201 }, s.machine.Id(), instance.LXD) 202 c.Assert(err, jc.ErrorIsNil) 203 parentId, ok = container.ParentId() 204 c.Assert(parentId, gc.Equals, s.machine.Id()) 205 c.Assert(ok, jc.IsTrue) 206 } 207 208 func (s *MachineSuite) TestMachineIsManager(c *gc.C) { 209 c.Assert(s.machine0.IsManager(), jc.IsTrue) 210 c.Assert(s.machine.IsManager(), jc.IsFalse) 211 } 212 213 func (s *MachineSuite) TestMachineIsManualBootstrap(c *gc.C) { 214 cfg, err := s.State.ModelConfig() 215 c.Assert(err, jc.ErrorIsNil) 216 c.Assert(cfg.Type(), gc.Not(gc.Equals), "null") 217 c.Assert(s.machine.Id(), gc.Equals, "1") 218 manual, err := s.machine0.IsManual() 219 c.Assert(err, jc.ErrorIsNil) 220 c.Assert(manual, jc.IsFalse) 221 attrs := map[string]interface{}{"type": "null"} 222 err = s.State.UpdateModelConfig(attrs, nil, nil) 223 c.Assert(err, jc.ErrorIsNil) 224 manual, err = s.machine0.IsManual() 225 c.Assert(err, jc.ErrorIsNil) 226 c.Assert(manual, jc.IsTrue) 227 } 228 229 func (s *MachineSuite) TestMachineIsManual(c *gc.C) { 230 tests := []struct { 231 instanceId instance.Id 232 nonce string 233 isManual bool 234 }{ 235 {instanceId: "x", nonce: "y", isManual: false}, 236 {instanceId: "manual:", nonce: "y", isManual: false}, 237 {instanceId: "x", nonce: "manual:", isManual: true}, 238 {instanceId: "x", nonce: "manual:y", isManual: true}, 239 {instanceId: "x", nonce: "manual", isManual: false}, 240 } 241 for _, test := range tests { 242 m, err := s.State.AddOneMachine(state.MachineTemplate{ 243 Series: "quantal", 244 Jobs: []state.MachineJob{state.JobHostUnits}, 245 InstanceId: test.instanceId, 246 Nonce: test.nonce, 247 }) 248 c.Assert(err, jc.ErrorIsNil) 249 isManual, err := m.IsManual() 250 c.Assert(isManual, gc.Equals, test.isManual) 251 } 252 } 253 254 func (s *MachineSuite) TestMachineIsContainer(c *gc.C) { 255 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 256 c.Assert(err, jc.ErrorIsNil) 257 258 template := state.MachineTemplate{ 259 Series: "quantal", 260 Jobs: []state.MachineJob{state.JobHostUnits}, 261 } 262 container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXD) 263 c.Assert(err, jc.ErrorIsNil) 264 265 c.Assert(machine.IsContainer(), jc.IsFalse) 266 c.Assert(container.IsContainer(), jc.IsTrue) 267 } 268 269 func (s *MachineSuite) TestLifeJobManageModel(c *gc.C) { 270 // A JobManageModel machine must never advance lifecycle. 271 m := s.machine0 272 err := m.Destroy() 273 c.Assert(err, gc.ErrorMatches, "machine 0 is required by the model") 274 err = m.ForceDestroy() 275 c.Assert(err, gc.ErrorMatches, "machine is required by the model") 276 err = m.EnsureDead() 277 c.Assert(err, gc.ErrorMatches, "machine 0 is required by the model") 278 } 279 280 func (s *MachineSuite) TestLifeMachineWithContainer(c *gc.C) { 281 // A machine hosting a container must not advance lifecycle. 282 _, err := s.State.AddMachineInsideMachine(state.MachineTemplate{ 283 Series: "quantal", 284 Jobs: []state.MachineJob{state.JobHostUnits}, 285 }, s.machine.Id(), instance.LXD) 286 c.Assert(err, jc.ErrorIsNil) 287 err = s.machine.Destroy() 288 c.Assert(err, gc.FitsTypeOf, &state.HasContainersError{}) 289 c.Assert(err, gc.ErrorMatches, `machine 1 is hosting containers "1/lxd/0"`) 290 err1 := s.machine.EnsureDead() 291 c.Assert(err1, gc.DeepEquals, err) 292 c.Assert(s.machine.Life(), gc.Equals, state.Alive) 293 } 294 295 func (s *MachineSuite) TestLifeJobHostUnits(c *gc.C) { 296 // A machine with an assigned unit must not advance lifecycle. 297 svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 298 unit, err := svc.AddUnit() 299 c.Assert(err, jc.ErrorIsNil) 300 err = unit.AssignToMachine(s.machine) 301 c.Assert(err, jc.ErrorIsNil) 302 err = s.machine.Destroy() 303 c.Assert(err, jc.Satisfies, state.IsHasAssignedUnitsError) 304 c.Assert(err, gc.ErrorMatches, `machine 1 has unit "wordpress/0" assigned`) 305 err1 := s.machine.EnsureDead() 306 c.Assert(err1, gc.DeepEquals, err) 307 c.Assert(s.machine.Life(), gc.Equals, state.Alive) 308 309 // Once no unit is assigned, lifecycle can advance. 310 err = unit.UnassignFromMachine() 311 c.Assert(err, jc.ErrorIsNil) 312 err = s.machine.Destroy() 313 c.Assert(s.machine.Life(), gc.Equals, state.Dying) 314 c.Assert(err, jc.ErrorIsNil) 315 err = s.machine.EnsureDead() 316 c.Assert(err, jc.ErrorIsNil) 317 c.Assert(s.machine.Life(), gc.Equals, state.Dead) 318 319 // A machine that has never had units assigned can advance lifecycle. 320 m, err := s.State.AddMachine("quantal", state.JobHostUnits) 321 c.Assert(err, jc.ErrorIsNil) 322 err = m.Destroy() 323 c.Assert(err, jc.ErrorIsNil) 324 c.Assert(m.Life(), gc.Equals, state.Dying) 325 err = m.EnsureDead() 326 c.Assert(err, jc.ErrorIsNil) 327 c.Assert(m.Life(), gc.Equals, state.Dead) 328 } 329 330 func (s *MachineSuite) TestDestroyRemovePorts(c *gc.C) { 331 svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 332 unit, err := svc.AddUnit() 333 c.Assert(err, jc.ErrorIsNil) 334 err = unit.AssignToMachine(s.machine) 335 c.Assert(err, jc.ErrorIsNil) 336 err = unit.OpenPort("tcp", 8080) 337 c.Assert(err, jc.ErrorIsNil) 338 ports, err := state.GetPorts(s.State, s.machine.Id(), "") 339 c.Assert(ports, gc.NotNil) 340 c.Assert(err, jc.ErrorIsNil) 341 err = unit.UnassignFromMachine() 342 c.Assert(err, jc.ErrorIsNil) 343 err = s.machine.Destroy() 344 c.Assert(err, jc.ErrorIsNil) 345 err = s.machine.EnsureDead() 346 c.Assert(err, jc.ErrorIsNil) 347 err = s.machine.Remove() 348 c.Assert(err, jc.ErrorIsNil) 349 // once the machine is destroyed, there should be no ports documents present for it 350 ports, err = state.GetPorts(s.State, s.machine.Id(), "") 351 c.Assert(ports, gc.IsNil) 352 c.Assert(err, jc.Satisfies, errors.IsNotFound) 353 } 354 355 func (s *MachineSuite) TestDestroyOps(c *gc.C) { 356 m := s.Factory.MakeMachine(c, nil) 357 ops, err := state.ForceDestroyMachineOps(m) 358 c.Assert(err, jc.ErrorIsNil) 359 c.Assert(ops, gc.NotNil) 360 } 361 362 func (s *MachineSuite) TestDestroyOpsForManagerFails(c *gc.C) { 363 // s.Factory does not allow us to make a manager machine, so we grab one 364 // from State ... 365 machines, err := s.State.AllMachines() 366 c.Assert(err, jc.ErrorIsNil) 367 c.Assert(len(machines), jc.GreaterThan, 0) 368 m := machines[0] 369 c.Assert(m.IsManager(), jc.IsTrue) 370 371 // ... and assert that we cannot get the destroy ops for it. 372 ops, err := state.ForceDestroyMachineOps(m) 373 c.Assert(err, jc.Satisfies, state.IsManagerMachineError) 374 c.Assert(ops, gc.IsNil) 375 } 376 377 func (s *MachineSuite) TestDestroyAbort(c *gc.C) { 378 defer state.SetBeforeHooks(c, s.State, func() { 379 c.Assert(s.machine.Destroy(), gc.IsNil) 380 }).Check() 381 err := s.machine.Destroy() 382 c.Assert(err, jc.ErrorIsNil) 383 } 384 385 func (s *MachineSuite) TestDestroyCancel(c *gc.C) { 386 svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 387 unit, err := svc.AddUnit() 388 c.Assert(err, jc.ErrorIsNil) 389 390 defer state.SetBeforeHooks(c, s.State, func() { 391 c.Assert(unit.AssignToMachine(s.machine), gc.IsNil) 392 }).Check() 393 err = s.machine.Destroy() 394 c.Assert(err, jc.Satisfies, state.IsHasAssignedUnitsError) 395 } 396 397 func (s *MachineSuite) TestDestroyContention(c *gc.C) { 398 svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 399 unit, err := svc.AddUnit() 400 c.Assert(err, jc.ErrorIsNil) 401 402 perturb := jujutxn.TestHook{ 403 Before: func() { c.Assert(unit.AssignToMachine(s.machine), gc.IsNil) }, 404 After: func() { c.Assert(unit.UnassignFromMachine(), gc.IsNil) }, 405 } 406 defer state.SetTestHooks(c, s.State, perturb, perturb, perturb).Check() 407 408 err = s.machine.Destroy() 409 c.Assert(err, gc.ErrorMatches, "machine 1 cannot advance lifecycle: state changing too quickly; try again soon") 410 } 411 412 func (s *MachineSuite) TestDestroyWithServiceDestroyPending(c *gc.C) { 413 svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 414 unit, err := svc.AddUnit() 415 c.Assert(err, jc.ErrorIsNil) 416 err = unit.AssignToMachine(s.machine) 417 c.Assert(err, jc.ErrorIsNil) 418 419 err = svc.Destroy() 420 c.Assert(err, jc.ErrorIsNil) 421 err = s.machine.Destroy() 422 c.Assert(err, jc.ErrorIsNil) 423 // Machine is still advanced to Dying. 424 life := s.machine.Life() 425 c.Assert(life, gc.Equals, state.Dying) 426 } 427 428 func (s *MachineSuite) TestDestroyFailsWhenNewUnitAdded(c *gc.C) { 429 svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 430 unit, err := svc.AddUnit() 431 c.Assert(err, jc.ErrorIsNil) 432 err = unit.AssignToMachine(s.machine) 433 c.Assert(err, jc.ErrorIsNil) 434 435 err = svc.Destroy() 436 c.Assert(err, jc.ErrorIsNil) 437 438 defer state.SetBeforeHooks(c, s.State, func() { 439 anotherSvc := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) 440 anotherUnit, err := anotherSvc.AddUnit() 441 c.Assert(err, jc.ErrorIsNil) 442 err = anotherUnit.AssignToMachine(s.machine) 443 c.Assert(err, jc.ErrorIsNil) 444 }).Check() 445 446 err = s.machine.Destroy() 447 c.Assert(err, jc.Satisfies, state.IsHasAssignedUnitsError) 448 life := s.machine.Life() 449 c.Assert(life, gc.Equals, state.Alive) 450 } 451 452 func (s *MachineSuite) TestDestroyWithUnitDestroyPending(c *gc.C) { 453 svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 454 unit, err := svc.AddUnit() 455 c.Assert(err, jc.ErrorIsNil) 456 err = unit.AssignToMachine(s.machine) 457 c.Assert(err, jc.ErrorIsNil) 458 459 err = unit.Destroy() 460 c.Assert(err, jc.ErrorIsNil) 461 err = s.machine.Destroy() 462 c.Assert(err, jc.ErrorIsNil) 463 // Machine is still advanced to Dying. 464 life := s.machine.Life() 465 c.Assert(life, gc.Equals, state.Dying) 466 } 467 468 func (s *MachineSuite) TestDestroyFailsWhenNewContainerAdded(c *gc.C) { 469 svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 470 unit, err := svc.AddUnit() 471 c.Assert(err, jc.ErrorIsNil) 472 err = unit.AssignToMachine(s.machine) 473 c.Assert(err, jc.ErrorIsNil) 474 475 err = svc.Destroy() 476 c.Assert(err, jc.ErrorIsNil) 477 478 defer state.SetBeforeHooks(c, s.State, func() { 479 _, err := s.State.AddMachineInsideMachine(state.MachineTemplate{ 480 Series: "quantal", 481 Jobs: []state.MachineJob{state.JobHostUnits}, 482 }, s.machine.Id(), instance.LXD) 483 c.Assert(err, jc.ErrorIsNil) 484 }).Check() 485 486 err = s.machine.Destroy() 487 c.Assert(err, jc.Satisfies, state.IsHasAssignedUnitsError) 488 life := s.machine.Life() 489 c.Assert(life, gc.Equals, state.Alive) 490 } 491 492 func (s *MachineSuite) TestRemove(c *gc.C) { 493 err := s.State.SetSSHHostKeys(s.machine.MachineTag(), state.SSHHostKeys{"rsa", "dsa"}) 494 c.Assert(err, jc.ErrorIsNil) 495 496 err = s.machine.Remove() 497 c.Assert(err, gc.ErrorMatches, "cannot remove machine 1: machine is not dead") 498 499 err = s.machine.EnsureDead() 500 c.Assert(err, jc.ErrorIsNil) 501 502 err = s.machine.Remove() 503 c.Assert(err, jc.ErrorIsNil) 504 505 err = s.machine.Refresh() 506 c.Assert(err, jc.Satisfies, errors.IsNotFound) 507 508 _, err = s.machine.HardwareCharacteristics() 509 c.Assert(err, jc.Satisfies, errors.IsNotFound) 510 511 _, err = s.machine.Containers() 512 c.Assert(err, jc.Satisfies, errors.IsNotFound) 513 514 _, err = s.State.GetSSHHostKeys(s.machine.MachineTag()) 515 c.Assert(errors.IsNotFound(err), jc.IsTrue) 516 517 // Removing an already removed machine is OK. 518 err = s.machine.Remove() 519 c.Assert(err, jc.ErrorIsNil) 520 } 521 522 func (s *MachineSuite) TestHasVote(c *gc.C) { 523 c.Assert(s.machine.HasVote(), jc.IsFalse) 524 525 // Make another machine value so that 526 // it won't have the cached HasVote value. 527 m, err := s.State.Machine(s.machine.Id()) 528 c.Assert(err, jc.ErrorIsNil) 529 530 err = s.machine.SetHasVote(true) 531 c.Assert(err, jc.ErrorIsNil) 532 c.Assert(s.machine.HasVote(), jc.IsTrue) 533 c.Assert(m.HasVote(), jc.IsFalse) 534 535 err = m.Refresh() 536 c.Assert(err, jc.ErrorIsNil) 537 c.Assert(m.HasVote(), jc.IsTrue) 538 539 err = m.SetHasVote(false) 540 c.Assert(err, jc.ErrorIsNil) 541 c.Assert(m.HasVote(), jc.IsFalse) 542 543 c.Assert(s.machine.HasVote(), jc.IsTrue) 544 err = s.machine.Refresh() 545 c.Assert(err, jc.ErrorIsNil) 546 c.Assert(s.machine.HasVote(), jc.IsFalse) 547 } 548 549 func (s *MachineSuite) TestCannotDestroyMachineWithVote(c *gc.C) { 550 err := s.machine.SetHasVote(true) 551 c.Assert(err, jc.ErrorIsNil) 552 553 // Make another machine value so that 554 // it won't have the cached HasVote value. 555 m, err := s.State.Machine(s.machine.Id()) 556 c.Assert(err, jc.ErrorIsNil) 557 558 err = s.machine.Destroy() 559 c.Assert(err, gc.ErrorMatches, "machine "+s.machine.Id()+" is a voting replica set member") 560 561 err = m.Destroy() 562 c.Assert(err, gc.ErrorMatches, "machine "+s.machine.Id()+" is a voting replica set member") 563 } 564 565 func (s *MachineSuite) TestRemoveAbort(c *gc.C) { 566 err := s.machine.EnsureDead() 567 c.Assert(err, jc.ErrorIsNil) 568 569 defer state.SetBeforeHooks(c, s.State, func() { 570 c.Assert(s.machine.Remove(), gc.IsNil) 571 }).Check() 572 err = s.machine.Remove() 573 c.Assert(err, jc.ErrorIsNil) 574 } 575 576 func (s *MachineSuite) TestMachineSetAgentPresence(c *gc.C) { 577 alive, err := s.machine.AgentPresence() 578 c.Assert(err, jc.ErrorIsNil) 579 c.Assert(alive, jc.IsFalse) 580 581 pinger, err := s.machine.SetAgentPresence() 582 c.Assert(err, jc.ErrorIsNil) 583 c.Assert(pinger, gc.NotNil) 584 defer func() { 585 c.Assert(worker.Stop(pinger), jc.ErrorIsNil) 586 }() 587 588 s.State.StartSync() 589 alive, err = s.machine.AgentPresence() 590 c.Assert(err, jc.ErrorIsNil) 591 c.Assert(alive, jc.IsTrue) 592 } 593 594 func (s *MachineSuite) TestTag(c *gc.C) { 595 tag := s.machine.MachineTag() 596 c.Assert(tag.Kind(), gc.Equals, names.MachineTagKind) 597 c.Assert(tag.Id(), gc.Equals, "1") 598 599 // To keep gccgo happy, don't compare an interface with a struct. 600 var asTag names.Tag = tag 601 c.Assert(s.machine.Tag(), gc.Equals, asTag) 602 } 603 604 func (s *MachineSuite) TestSetMongoPassword(c *gc.C) { 605 info := testing.NewMongoInfo() 606 st, err := state.Open(s.modelTag, s.State.ControllerTag(), info, mongotest.DialOpts(), state.NewPolicyFunc(nil)) 607 c.Assert(err, jc.ErrorIsNil) 608 defer func() { 609 // Remove the admin password so that the test harness can reset the state. 610 err := st.SetAdminMongoPassword("") 611 c.Check(err, jc.ErrorIsNil) 612 err = st.Close() 613 c.Check(err, jc.ErrorIsNil) 614 }() 615 616 // Turn on fully-authenticated mode. 617 err = st.SetAdminMongoPassword("admin-secret") 618 c.Assert(err, jc.ErrorIsNil) 619 err = st.MongoSession().DB("admin").Login("admin", "admin-secret") 620 c.Assert(err, jc.ErrorIsNil) 621 622 // Set the password for the entity 623 ent, err := st.Machine("0") 624 c.Assert(err, jc.ErrorIsNil) 625 err = ent.SetMongoPassword("foo") 626 c.Assert(err, jc.ErrorIsNil) 627 628 // Check that we cannot log in with the wrong password. 629 info.Tag = ent.Tag() 630 info.Password = "bar" 631 err = tryOpenState(s.modelTag, s.State.ControllerTag(), info) 632 c.Check(errors.Cause(err), jc.Satisfies, errors.IsUnauthorized) 633 c.Check(err, gc.ErrorMatches, `cannot log in to admin database as "machine-0": unauthorized mongo access: .*`) 634 635 // Check that we can log in with the correct password. 636 info.Password = "foo" 637 st1, err := state.Open(s.modelTag, s.State.ControllerTag(), info, mongotest.DialOpts(), state.NewPolicyFunc(nil)) 638 c.Assert(err, jc.ErrorIsNil) 639 defer st1.Close() 640 641 // Change the password with an entity derived from the newly 642 // opened and authenticated state. 643 ent, err = st.Machine("0") 644 c.Assert(err, jc.ErrorIsNil) 645 err = ent.SetMongoPassword("bar") 646 c.Assert(err, jc.ErrorIsNil) 647 648 // Check that we cannot log in with the old password. 649 info.Password = "foo" 650 err = tryOpenState(s.modelTag, s.State.ControllerTag(), info) 651 c.Check(errors.Cause(err), jc.Satisfies, errors.IsUnauthorized) 652 c.Check(err, gc.ErrorMatches, `cannot log in to admin database as "machine-0": unauthorized mongo access: .*`) 653 654 // Check that we can log in with the correct password. 655 info.Password = "bar" 656 err = tryOpenState(s.modelTag, s.State.ControllerTag(), info) 657 c.Assert(err, jc.ErrorIsNil) 658 659 // Check that the administrator can still log in. 660 info.Tag, info.Password = nil, "admin-secret" 661 err = tryOpenState(s.modelTag, s.State.ControllerTag(), info) 662 c.Assert(err, jc.ErrorIsNil) 663 } 664 665 func (s *MachineSuite) TestSetPassword(c *gc.C) { 666 testSetPassword(c, func() (state.Authenticator, error) { 667 return s.State.Machine(s.machine.Id()) 668 }) 669 } 670 671 func (s *MachineSuite) TestMachineWaitAgentPresence(c *gc.C) { 672 alive, err := s.machine.AgentPresence() 673 c.Assert(err, jc.ErrorIsNil) 674 c.Assert(alive, jc.IsFalse) 675 676 s.State.StartSync() 677 err = s.machine.WaitAgentPresence(coretesting.ShortWait) 678 c.Assert(err, gc.ErrorMatches, `waiting for agent of machine 1: still not alive after timeout`) 679 680 pinger, err := s.machine.SetAgentPresence() 681 c.Assert(err, jc.ErrorIsNil) 682 683 s.State.StartSync() 684 err = s.machine.WaitAgentPresence(coretesting.LongWait) 685 c.Assert(err, jc.ErrorIsNil) 686 687 alive, err = s.machine.AgentPresence() 688 c.Assert(err, jc.ErrorIsNil) 689 c.Assert(alive, jc.IsTrue) 690 691 err = pinger.KillForTesting() 692 c.Assert(err, jc.ErrorIsNil) 693 694 s.State.StartSync() 695 alive, err = s.machine.AgentPresence() 696 c.Assert(err, jc.ErrorIsNil) 697 c.Assert(alive, jc.IsFalse) 698 } 699 700 func (s *MachineSuite) TestMachineInstanceIdCorrupt(c *gc.C) { 701 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 702 c.Assert(err, jc.ErrorIsNil) 703 err = s.machines.Update( 704 bson.D{{"_id", state.DocID(s.State, machine.Id())}}, 705 bson.D{{"$set", bson.D{{"instanceid", bson.D{{"foo", "bar"}}}}}}, 706 ) 707 c.Assert(err, jc.ErrorIsNil) 708 709 err = machine.Refresh() 710 c.Assert(err, jc.ErrorIsNil) 711 iid, err := machine.InstanceId() 712 c.Assert(err, jc.Satisfies, errors.IsNotProvisioned) 713 c.Assert(iid, gc.Equals, instance.Id("")) 714 } 715 716 func (s *MachineSuite) TestMachineInstanceIdMissing(c *gc.C) { 717 iid, err := s.machine.InstanceId() 718 c.Assert(err, jc.Satisfies, errors.IsNotProvisioned) 719 c.Assert(string(iid), gc.Equals, "") 720 } 721 722 func (s *MachineSuite) TestMachineInstanceIdBlank(c *gc.C) { 723 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 724 c.Assert(err, jc.ErrorIsNil) 725 err = s.machines.Update( 726 bson.D{{"_id", state.DocID(s.State, machine.Id())}}, 727 bson.D{{"$set", bson.D{{"instanceid", ""}}}}, 728 ) 729 c.Assert(err, jc.ErrorIsNil) 730 731 err = machine.Refresh() 732 c.Assert(err, jc.ErrorIsNil) 733 iid, err := machine.InstanceId() 734 c.Assert(err, jc.Satisfies, errors.IsNotProvisioned) 735 c.Assert(string(iid), gc.Equals, "") 736 } 737 738 func (s *MachineSuite) TestMachineSetProvisionedUpdatesCharacteristics(c *gc.C) { 739 // Before provisioning, there is no hardware characteristics. 740 _, err := s.machine.HardwareCharacteristics() 741 c.Assert(err, jc.Satisfies, errors.IsNotFound) 742 arch := "amd64" 743 mem := uint64(4096) 744 expected := &instance.HardwareCharacteristics{ 745 Arch: &arch, 746 Mem: &mem, 747 } 748 err = s.machine.SetProvisioned("umbrella/0", "fake_nonce", expected) 749 c.Assert(err, jc.ErrorIsNil) 750 md, err := s.machine.HardwareCharacteristics() 751 c.Assert(err, jc.ErrorIsNil) 752 c.Assert(*md, gc.DeepEquals, *expected) 753 754 // Reload machine and check again. 755 err = s.machine.Refresh() 756 c.Assert(err, jc.ErrorIsNil) 757 md, err = s.machine.HardwareCharacteristics() 758 c.Assert(err, jc.ErrorIsNil) 759 c.Assert(*md, gc.DeepEquals, *expected) 760 } 761 762 func (s *MachineSuite) TestMachineAvailabilityZone(c *gc.C) { 763 zone := "a_zone" 764 hwc := &instance.HardwareCharacteristics{ 765 AvailabilityZone: &zone, 766 } 767 err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", hwc) 768 c.Assert(err, jc.ErrorIsNil) 769 770 zone, err = s.machine.AvailabilityZone() 771 c.Assert(err, jc.ErrorIsNil) 772 c.Check(zone, gc.Equals, "a_zone") 773 } 774 775 func (s *MachineSuite) TestMachineAvailabilityZoneEmpty(c *gc.C) { 776 zone := "" 777 hwc := &instance.HardwareCharacteristics{ 778 AvailabilityZone: &zone, 779 } 780 err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", hwc) 781 c.Assert(err, jc.ErrorIsNil) 782 783 zone, err = s.machine.AvailabilityZone() 784 c.Assert(err, jc.ErrorIsNil) 785 c.Check(zone, gc.Equals, "") 786 } 787 788 func (s *MachineSuite) TestMachineAvailabilityZoneMissing(c *gc.C) { 789 zone := "a_zone" 790 hwc := &instance.HardwareCharacteristics{} 791 err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", hwc) 792 c.Assert(err, jc.ErrorIsNil) 793 794 zone, err = s.machine.AvailabilityZone() 795 c.Assert(err, jc.ErrorIsNil) 796 c.Check(zone, gc.Equals, "") 797 } 798 799 func (s *MachineSuite) TestMachineSetCheckProvisioned(c *gc.C) { 800 // Check before provisioning. 801 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse) 802 803 // Either one should not be empty. 804 err := s.machine.SetProvisioned("umbrella/0", "", nil) 805 c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`) 806 err = s.machine.SetProvisioned("", "fake_nonce", nil) 807 c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`) 808 err = s.machine.SetProvisioned("", "", nil) 809 c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`) 810 811 err = s.machine.SetProvisioned("umbrella/0", "fake_nonce", nil) 812 c.Assert(err, jc.ErrorIsNil) 813 814 m, err := s.State.Machine(s.machine.Id()) 815 c.Assert(err, jc.ErrorIsNil) 816 id, err := m.InstanceId() 817 c.Assert(err, jc.ErrorIsNil) 818 c.Assert(string(id), gc.Equals, "umbrella/0") 819 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue) 820 id, err = s.machine.InstanceId() 821 c.Assert(err, jc.ErrorIsNil) 822 c.Assert(string(id), gc.Equals, "umbrella/0") 823 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue) 824 825 // Try it twice, it should fail. 826 err = s.machine.SetProvisioned("doesn't-matter", "phony", nil) 827 c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": already set`) 828 829 // Check it with invalid nonce. 830 c.Assert(s.machine.CheckProvisioned("not-really"), jc.IsFalse) 831 } 832 833 func (s *MachineSuite) TestMachineSetInstanceInfoFailureDoesNotProvision(c *gc.C) { 834 assertNotProvisioned := func() { 835 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse) 836 } 837 838 assertNotProvisioned() 839 840 invalidVolumes := map[names.VolumeTag]state.VolumeInfo{ 841 names.NewVolumeTag("1065"): state.VolumeInfo{VolumeId: "vol-ume"}, 842 } 843 err := s.machine.SetInstanceInfo("umbrella/0", "fake_nonce", nil, nil, nil, invalidVolumes, nil) 844 c.Assert(err, gc.ErrorMatches, `cannot set info for volume \"1065\": volume \"1065\" not found`) 845 assertNotProvisioned() 846 847 invalidVolumes = map[names.VolumeTag]state.VolumeInfo{ 848 names.NewVolumeTag("1065"): state.VolumeInfo{}, 849 } 850 err = s.machine.SetInstanceInfo("umbrella/0", "fake_nonce", nil, nil, nil, invalidVolumes, nil) 851 c.Assert(err, gc.ErrorMatches, `cannot set info for volume \"1065\": volume ID not set`) 852 assertNotProvisioned() 853 854 // TODO(axw) test invalid volume attachment 855 } 856 857 func (s *MachineSuite) addVolume(c *gc.C, params state.VolumeParams, machineId string) names.VolumeTag { 858 ops, tag, err := state.AddVolumeOps(s.State, params, machineId) 859 c.Assert(err, jc.ErrorIsNil) 860 err = state.RunTransaction(s.State, ops) 861 c.Assert(err, jc.ErrorIsNil) 862 return tag 863 } 864 865 func (s *MachineSuite) TestMachineSetInstanceInfoSuccess(c *gc.C) { 866 pm := poolmanager.New(state.NewStateSettings(s.State), dummy.StorageProviders()) 867 _, err := pm.Create("loop-pool", provider.LoopProviderType, map[string]interface{}{}) 868 c.Assert(err, jc.ErrorIsNil) 869 870 // Must create the requested block device prior to SetInstanceInfo. 871 volumeTag := s.addVolume(c, state.VolumeParams{Size: 1000, Pool: "loop-pool"}, "123") 872 c.Assert(volumeTag, gc.Equals, names.NewVolumeTag("123/0")) 873 874 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse) 875 volumeInfo := state.VolumeInfo{ 876 VolumeId: "storage-123", 877 Size: 1234, 878 } 879 volumes := map[names.VolumeTag]state.VolumeInfo{volumeTag: volumeInfo} 880 err = s.machine.SetInstanceInfo("umbrella/0", "fake_nonce", nil, nil, nil, volumes, nil) 881 c.Assert(err, jc.ErrorIsNil) 882 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue) 883 884 volume, err := s.State.Volume(volumeTag) 885 c.Assert(err, jc.ErrorIsNil) 886 info, err := volume.Info() 887 c.Assert(err, jc.ErrorIsNil) 888 volumeInfo.Pool = "loop-pool" // taken from params 889 c.Assert(info, gc.Equals, volumeInfo) 890 } 891 892 func (s *MachineSuite) TestMachineSetProvisionedWhenNotAlive(c *gc.C) { 893 testWhenDying(c, s.machine, notAliveErr, notAliveErr, func() error { 894 return s.machine.SetProvisioned("umbrella/0", "fake_nonce", nil) 895 }) 896 } 897 898 func (s *MachineSuite) TestMachineSetInstanceStatus(c *gc.C) { 899 // Machine needs to be provisioned first. 900 err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", nil) 901 c.Assert(err, jc.ErrorIsNil) 902 903 now := coretesting.ZeroTime() 904 sInfo := status.StatusInfo{ 905 Status: status.Running, 906 Message: "alive", 907 Since: &now, 908 } 909 err = s.machine.SetInstanceStatus(sInfo) 910 c.Assert(err, jc.ErrorIsNil) 911 912 // Reload machine and check result. 913 err = s.machine.Refresh() 914 c.Assert(err, jc.ErrorIsNil) 915 machineStatus, err := s.machine.InstanceStatus() 916 c.Assert(err, jc.ErrorIsNil) 917 c.Assert(machineStatus.Status, gc.DeepEquals, status.Running) 918 c.Assert(machineStatus.Message, gc.DeepEquals, "alive") 919 } 920 921 func (s *MachineSuite) TestMachineRefresh(c *gc.C) { 922 m0, err := s.State.AddMachine("quantal", state.JobHostUnits) 923 c.Assert(err, jc.ErrorIsNil) 924 oldTools, _ := m0.AgentTools() 925 m1, err := s.State.Machine(m0.Id()) 926 c.Assert(err, jc.ErrorIsNil) 927 err = m0.SetAgentVersion(version.MustParseBinary("0.0.3-quantal-amd64")) 928 c.Assert(err, jc.ErrorIsNil) 929 newTools, _ := m0.AgentTools() 930 931 m1Tools, _ := m1.AgentTools() 932 c.Assert(m1Tools, gc.DeepEquals, oldTools) 933 err = m1.Refresh() 934 c.Assert(err, jc.ErrorIsNil) 935 m1Tools, _ = m1.AgentTools() 936 c.Assert(*m1Tools, gc.Equals, *newTools) 937 938 err = m0.EnsureDead() 939 c.Assert(err, jc.ErrorIsNil) 940 err = m0.Remove() 941 c.Assert(err, jc.ErrorIsNil) 942 err = m0.Refresh() 943 c.Assert(err, jc.Satisfies, errors.IsNotFound) 944 } 945 946 func (s *MachineSuite) TestRefreshWhenNotAlive(c *gc.C) { 947 // Refresh should work regardless of liveness status. 948 testWhenDying(c, s.machine, noErr, noErr, func() error { 949 return s.machine.Refresh() 950 }) 951 } 952 953 func (s *MachineSuite) TestMachinePrincipalUnits(c *gc.C) { 954 // Check that Machine.Units and st.UnitsFor work correctly. 955 956 // Make three machines, three services and three units for each service; 957 // variously assign units to machines and check that Machine.Units 958 // tells us the right thing. 959 960 m1 := s.machine 961 m2, err := s.State.AddMachine("quantal", state.JobHostUnits) 962 c.Assert(err, jc.ErrorIsNil) 963 m3, err := s.State.AddMachine("quantal", state.JobHostUnits) 964 c.Assert(err, jc.ErrorIsNil) 965 966 dummy := s.AddTestingCharm(c, "dummy") 967 logging := s.AddTestingCharm(c, "logging") 968 s0 := s.AddTestingService(c, "s0", dummy) 969 s1 := s.AddTestingService(c, "s1", dummy) 970 s2 := s.AddTestingService(c, "s2", dummy) 971 s3 := s.AddTestingService(c, "s3", logging) 972 973 units := make([][]*state.Unit, 4) 974 for i, svc := range []*state.Application{s0, s1, s2} { 975 units[i] = make([]*state.Unit, 3) 976 for j := range units[i] { 977 units[i][j], err = svc.AddUnit() 978 c.Assert(err, jc.ErrorIsNil) 979 } 980 } 981 // Add the logging units subordinate to the s2 units. 982 eps, err := s.State.InferEndpoints("s2", "s3") 983 c.Assert(err, jc.ErrorIsNil) 984 rel, err := s.State.AddRelation(eps...) 985 c.Assert(err, jc.ErrorIsNil) 986 for _, u := range units[2] { 987 ru, err := rel.Unit(u) 988 c.Assert(err, jc.ErrorIsNil) 989 err = ru.EnterScope(nil) 990 c.Assert(err, jc.ErrorIsNil) 991 } 992 units[3], err = s3.AllUnits() 993 c.Assert(err, jc.ErrorIsNil) 994 c.Assert(sortedUnitNames(units[3]), jc.DeepEquals, []string{"s3/0", "s3/1", "s3/2"}) 995 996 assignments := []struct { 997 machine *state.Machine 998 units []*state.Unit 999 subordinates []*state.Unit 1000 }{ 1001 {m1, []*state.Unit{units[0][0]}, nil}, 1002 {m2, []*state.Unit{units[0][1], units[1][0], units[1][1], units[2][0]}, []*state.Unit{units[3][0]}}, 1003 {m3, []*state.Unit{units[2][2]}, []*state.Unit{units[3][2]}}, 1004 } 1005 1006 for _, a := range assignments { 1007 for _, u := range a.units { 1008 err := u.AssignToMachine(a.machine) 1009 c.Assert(err, jc.ErrorIsNil) 1010 } 1011 } 1012 1013 for i, a := range assignments { 1014 c.Logf("test %d", i) 1015 expect := sortedUnitNames(append(a.units, a.subordinates...)) 1016 1017 // The units can be retrieved from the machine model. 1018 got, err := a.machine.Units() 1019 c.Assert(err, jc.ErrorIsNil) 1020 c.Assert(sortedUnitNames(got), jc.DeepEquals, expect) 1021 1022 // The units can be retrieved from the machine id. 1023 got, err = s.State.UnitsFor(a.machine.Id()) 1024 c.Assert(err, jc.ErrorIsNil) 1025 c.Assert(sortedUnitNames(got), jc.DeepEquals, expect) 1026 } 1027 } 1028 1029 func sortedUnitNames(units []*state.Unit) []string { 1030 names := make([]string, len(units)) 1031 for i, u := range units { 1032 names[i] = u.Name() 1033 } 1034 sort.Strings(names) 1035 return names 1036 } 1037 1038 func (s *MachineSuite) assertMachineDirtyAfterAddingUnit(c *gc.C) (*state.Machine, *state.Application, *state.Unit) { 1039 m, err := s.State.AddMachine("quantal", state.JobHostUnits) 1040 c.Assert(err, jc.ErrorIsNil) 1041 c.Assert(m.Clean(), jc.IsTrue) 1042 1043 svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 1044 unit, err := svc.AddUnit() 1045 c.Assert(err, jc.ErrorIsNil) 1046 err = unit.AssignToMachine(m) 1047 c.Assert(err, jc.ErrorIsNil) 1048 c.Assert(m.Clean(), jc.IsFalse) 1049 return m, svc, unit 1050 } 1051 1052 func (s *MachineSuite) TestMachineDirtyAfterAddingUnit(c *gc.C) { 1053 s.assertMachineDirtyAfterAddingUnit(c) 1054 } 1055 1056 func (s *MachineSuite) TestMachineDirtyAfterUnassigningUnit(c *gc.C) { 1057 m, _, unit := s.assertMachineDirtyAfterAddingUnit(c) 1058 err := unit.UnassignFromMachine() 1059 c.Assert(err, jc.ErrorIsNil) 1060 c.Assert(m.Clean(), jc.IsFalse) 1061 } 1062 1063 func (s *MachineSuite) TestMachineDirtyAfterRemovingUnit(c *gc.C) { 1064 m, svc, unit := s.assertMachineDirtyAfterAddingUnit(c) 1065 err := unit.EnsureDead() 1066 c.Assert(err, jc.ErrorIsNil) 1067 err = unit.Remove() 1068 c.Assert(err, jc.ErrorIsNil) 1069 err = svc.Destroy() 1070 c.Assert(err, jc.ErrorIsNil) 1071 c.Assert(m.Clean(), jc.IsFalse) 1072 } 1073 1074 func (s *MachineSuite) TestWatchMachine(c *gc.C) { 1075 w := s.machine.Watch() 1076 defer testing.AssertStop(c, w) 1077 1078 // Initial event. 1079 wc := testing.NewNotifyWatcherC(c, s.State, w) 1080 wc.AssertOneChange() 1081 1082 // Make one change (to a separate instance), check one event. 1083 machine, err := s.State.Machine(s.machine.Id()) 1084 c.Assert(err, jc.ErrorIsNil) 1085 err = machine.SetProvisioned("m-foo", "fake_nonce", nil) 1086 c.Assert(err, jc.ErrorIsNil) 1087 wc.AssertOneChange() 1088 1089 // Make two changes, check one event. 1090 err = machine.SetAgentVersion(version.MustParseBinary("0.0.3-quantal-amd64")) 1091 c.Assert(err, jc.ErrorIsNil) 1092 err = machine.Destroy() 1093 c.Assert(err, jc.ErrorIsNil) 1094 wc.AssertOneChange() 1095 1096 // Stop, check closed. 1097 testing.AssertStop(c, w) 1098 wc.AssertClosed() 1099 1100 // Remove machine, start new watch, check single event. 1101 err = machine.EnsureDead() 1102 c.Assert(err, jc.ErrorIsNil) 1103 err = machine.Remove() 1104 c.Assert(err, jc.ErrorIsNil) 1105 w = s.machine.Watch() 1106 defer testing.AssertStop(c, w) 1107 testing.NewNotifyWatcherC(c, s.State, w).AssertOneChange() 1108 } 1109 1110 func (s *MachineSuite) TestWatchDiesOnStateClose(c *gc.C) { 1111 // This test is testing logic in watcher.entityWatcher, which 1112 // is also used by: 1113 // Machine.WatchHardwareCharacteristics 1114 // Service.Watch 1115 // Unit.Watch 1116 // State.WatchForModelConfigChanges 1117 // Unit.WatchConfigSettings 1118 testWatcherDiesWhenStateCloses(c, s.modelTag, s.State.ControllerTag(), func(c *gc.C, st *state.State) waiter { 1119 m, err := st.Machine(s.machine.Id()) 1120 c.Assert(err, jc.ErrorIsNil) 1121 w := m.Watch() 1122 <-w.Changes() 1123 return w 1124 }) 1125 } 1126 1127 func (s *MachineSuite) TestWatchPrincipalUnits(c *gc.C) { 1128 // TODO(mjs) - MODELUUID - test with multiple models with 1129 // identically named units and ensure there's no leakage. 1130 1131 // Start a watch on an empty machine; check no units reported. 1132 w := s.machine.WatchPrincipalUnits() 1133 defer testing.AssertStop(c, w) 1134 wc := testing.NewStringsWatcherC(c, s.State, w) 1135 wc.AssertChange() 1136 wc.AssertNoChange() 1137 1138 // Change machine, and create a unit independently; no change. 1139 err := s.machine.SetProvisioned("cheese", "fake_nonce", nil) 1140 c.Assert(err, jc.ErrorIsNil) 1141 wc.AssertNoChange() 1142 mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) 1143 mysql0, err := mysql.AddUnit() 1144 c.Assert(err, jc.ErrorIsNil) 1145 wc.AssertNoChange() 1146 1147 // Assign that unit (to a separate machine instance); change detected. 1148 machine, err := s.State.Machine(s.machine.Id()) 1149 c.Assert(err, jc.ErrorIsNil) 1150 err = mysql0.AssignToMachine(machine) 1151 c.Assert(err, jc.ErrorIsNil) 1152 wc.AssertChange("mysql/0") 1153 wc.AssertNoChange() 1154 1155 // Change the unit; no change. 1156 now := coretesting.ZeroTime() 1157 sInfo := status.StatusInfo{ 1158 Status: status.Idle, 1159 Message: "", 1160 Since: &now, 1161 } 1162 err = mysql0.SetAgentStatus(sInfo) 1163 c.Assert(err, jc.ErrorIsNil) 1164 wc.AssertNoChange() 1165 1166 // Assign another unit and make the first Dying; check both changes detected. 1167 mysql1, err := mysql.AddUnit() 1168 c.Assert(err, jc.ErrorIsNil) 1169 err = mysql1.AssignToMachine(machine) 1170 c.Assert(err, jc.ErrorIsNil) 1171 err = mysql0.Destroy() 1172 c.Assert(err, jc.ErrorIsNil) 1173 wc.AssertChange("mysql/0", "mysql/1") 1174 wc.AssertNoChange() 1175 1176 // Add a subordinate to the Alive unit; no change. 1177 s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging")) 1178 eps, err := s.State.InferEndpoints("mysql", "logging") 1179 c.Assert(err, jc.ErrorIsNil) 1180 rel, err := s.State.AddRelation(eps...) 1181 c.Assert(err, jc.ErrorIsNil) 1182 mysqlru1, err := rel.Unit(mysql1) 1183 c.Assert(err, jc.ErrorIsNil) 1184 err = mysqlru1.EnterScope(nil) 1185 c.Assert(err, jc.ErrorIsNil) 1186 logging0, err := s.State.Unit("logging/0") 1187 c.Assert(err, jc.ErrorIsNil) 1188 wc.AssertNoChange() 1189 1190 // Change the subordinate; no change. 1191 sInfo = status.StatusInfo{ 1192 Status: status.Idle, 1193 Message: "", 1194 Since: &now, 1195 } 1196 err = logging0.SetAgentStatus(sInfo) 1197 c.Assert(err, jc.ErrorIsNil) 1198 wc.AssertNoChange() 1199 1200 // Make the Dying unit Dead; change detected. 1201 err = mysql0.EnsureDead() 1202 c.Assert(err, jc.ErrorIsNil) 1203 wc.AssertChange("mysql/0") 1204 wc.AssertNoChange() 1205 1206 // Stop watcher; check Changes chan closed. 1207 testing.AssertStop(c, w) 1208 wc.AssertClosed() 1209 1210 // Start a fresh watcher; check both principals reported. 1211 w = s.machine.WatchPrincipalUnits() 1212 defer testing.AssertStop(c, w) 1213 wc = testing.NewStringsWatcherC(c, s.State, w) 1214 wc.AssertChange("mysql/0", "mysql/1") 1215 wc.AssertNoChange() 1216 1217 // Remove the Dead unit; no change. 1218 err = mysql0.Remove() 1219 c.Assert(err, jc.ErrorIsNil) 1220 wc.AssertNoChange() 1221 1222 // Destroy the subordinate; no change. 1223 err = logging0.Destroy() 1224 c.Assert(err, jc.ErrorIsNil) 1225 wc.AssertNoChange() 1226 1227 // Unassign the unit; check change. 1228 err = mysql1.UnassignFromMachine() 1229 c.Assert(err, jc.ErrorIsNil) 1230 wc.AssertChange("mysql/1") 1231 wc.AssertNoChange() 1232 } 1233 1234 func (s *MachineSuite) TestWatchPrincipalUnitsDiesOnStateClose(c *gc.C) { 1235 // This test is testing logic in watcher.unitsWatcher, which 1236 // is also used by Unit.WatchSubordinateUnits. 1237 testWatcherDiesWhenStateCloses(c, s.modelTag, s.State.ControllerTag(), func(c *gc.C, st *state.State) waiter { 1238 m, err := st.Machine(s.machine.Id()) 1239 c.Assert(err, jc.ErrorIsNil) 1240 w := m.WatchPrincipalUnits() 1241 <-w.Changes() 1242 return w 1243 }) 1244 } 1245 1246 func (s *MachineSuite) TestWatchUnits(c *gc.C) { 1247 // Start a watch on an empty machine; check no units reported. 1248 w := s.machine.WatchUnits() 1249 defer testing.AssertStop(c, w) 1250 wc := testing.NewStringsWatcherC(c, s.State, w) 1251 wc.AssertChange() 1252 wc.AssertNoChange() 1253 1254 // Change machine; no change. 1255 err := s.machine.SetProvisioned("cheese", "fake_nonce", nil) 1256 c.Assert(err, jc.ErrorIsNil) 1257 wc.AssertNoChange() 1258 1259 // Assign a unit (to a separate instance); change detected. 1260 mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) 1261 mysql0, err := mysql.AddUnit() 1262 c.Assert(err, jc.ErrorIsNil) 1263 machine, err := s.State.Machine(s.machine.Id()) 1264 c.Assert(err, jc.ErrorIsNil) 1265 err = mysql0.AssignToMachine(machine) 1266 c.Assert(err, jc.ErrorIsNil) 1267 wc.AssertChange("mysql/0") 1268 wc.AssertNoChange() 1269 1270 // Change the unit; no change. 1271 now := coretesting.ZeroTime() 1272 sInfo := status.StatusInfo{ 1273 Status: status.Idle, 1274 Message: "", 1275 Since: &now, 1276 } 1277 err = mysql0.SetAgentStatus(sInfo) 1278 c.Assert(err, jc.ErrorIsNil) 1279 wc.AssertNoChange() 1280 1281 // Assign another unit and make the first Dying; check both changes detected. 1282 mysql1, err := mysql.AddUnit() 1283 c.Assert(err, jc.ErrorIsNil) 1284 err = mysql1.AssignToMachine(machine) 1285 c.Assert(err, jc.ErrorIsNil) 1286 err = mysql0.Destroy() 1287 c.Assert(err, jc.ErrorIsNil) 1288 wc.AssertChange("mysql/0", "mysql/1") 1289 wc.AssertNoChange() 1290 1291 // Add a subordinate to the Alive unit; change detected. 1292 s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging")) 1293 eps, err := s.State.InferEndpoints("mysql", "logging") 1294 c.Assert(err, jc.ErrorIsNil) 1295 rel, err := s.State.AddRelation(eps...) 1296 c.Assert(err, jc.ErrorIsNil) 1297 mysqlru1, err := rel.Unit(mysql1) 1298 c.Assert(err, jc.ErrorIsNil) 1299 err = mysqlru1.EnterScope(nil) 1300 c.Assert(err, jc.ErrorIsNil) 1301 logging0, err := s.State.Unit("logging/0") 1302 c.Assert(err, jc.ErrorIsNil) 1303 wc.AssertChange("logging/0") 1304 wc.AssertNoChange() 1305 1306 // Change the subordinate; no change. 1307 sInfo = status.StatusInfo{ 1308 Status: status.Idle, 1309 Message: "", 1310 Since: &now, 1311 } 1312 err = logging0.SetAgentStatus(sInfo) 1313 c.Assert(err, jc.ErrorIsNil) 1314 wc.AssertNoChange() 1315 1316 // Make the Dying unit Dead; change detected. 1317 err = mysql0.EnsureDead() 1318 c.Assert(err, jc.ErrorIsNil) 1319 wc.AssertChange("mysql/0") 1320 wc.AssertNoChange() 1321 1322 // Stop watcher; check Changes chan closed. 1323 testing.AssertStop(c, w) 1324 wc.AssertClosed() 1325 1326 // Start a fresh watcher; check all units reported. 1327 w = s.machine.WatchUnits() 1328 defer testing.AssertStop(c, w) 1329 wc = testing.NewStringsWatcherC(c, s.State, w) 1330 wc.AssertChange("mysql/0", "mysql/1", "logging/0") 1331 wc.AssertNoChange() 1332 1333 // Remove the Dead unit; no change. 1334 err = mysql0.Remove() 1335 c.Assert(err, jc.ErrorIsNil) 1336 wc.AssertNoChange() 1337 1338 // Destroy the subordinate; change detected. 1339 err = logging0.Destroy() 1340 c.Assert(err, jc.ErrorIsNil) 1341 wc.AssertChange("logging/0") 1342 wc.AssertNoChange() 1343 1344 // Unassign the principal; check subordinate departure also reported. 1345 err = mysql1.UnassignFromMachine() 1346 c.Assert(err, jc.ErrorIsNil) 1347 wc.AssertChange("mysql/1", "logging/0") 1348 wc.AssertNoChange() 1349 } 1350 1351 func (s *MachineSuite) TestWatchUnitsDiesOnStateClose(c *gc.C) { 1352 testWatcherDiesWhenStateCloses(c, s.modelTag, s.State.ControllerTag(), func(c *gc.C, st *state.State) waiter { 1353 m, err := st.Machine(s.machine.Id()) 1354 c.Assert(err, jc.ErrorIsNil) 1355 w := m.WatchUnits() 1356 <-w.Changes() 1357 return w 1358 }) 1359 } 1360 1361 func (s *MachineSuite) TestConstraintsFromModel(c *gc.C) { 1362 econs1 := constraints.MustParse("mem=1G") 1363 econs2 := constraints.MustParse("mem=2G") 1364 1365 // A newly-created machine gets a copy of the model constraints. 1366 err := s.State.SetModelConstraints(econs1) 1367 c.Assert(err, jc.ErrorIsNil) 1368 machine1, err := s.State.AddMachine("quantal", state.JobHostUnits) 1369 c.Assert(err, jc.ErrorIsNil) 1370 mcons1, err := machine1.Constraints() 1371 c.Assert(err, jc.ErrorIsNil) 1372 c.Assert(mcons1, gc.DeepEquals, econs1) 1373 1374 // Change model constraints and add a new machine. 1375 err = s.State.SetModelConstraints(econs2) 1376 c.Assert(err, jc.ErrorIsNil) 1377 machine2, err := s.State.AddMachine("quantal", state.JobHostUnits) 1378 c.Assert(err, jc.ErrorIsNil) 1379 mcons2, err := machine2.Constraints() 1380 c.Assert(err, jc.ErrorIsNil) 1381 c.Assert(mcons2, gc.DeepEquals, econs2) 1382 1383 // Check the original machine has its original constraints. 1384 mcons1, err = machine1.Constraints() 1385 c.Assert(err, jc.ErrorIsNil) 1386 c.Assert(mcons1, gc.DeepEquals, econs1) 1387 } 1388 1389 func (s *MachineSuite) TestSetConstraints(c *gc.C) { 1390 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1391 c.Assert(err, jc.ErrorIsNil) 1392 1393 // Constraints can be set... 1394 cons1 := constraints.MustParse("mem=1G") 1395 err = machine.SetConstraints(cons1) 1396 c.Assert(err, jc.ErrorIsNil) 1397 mcons, err := machine.Constraints() 1398 c.Assert(err, jc.ErrorIsNil) 1399 c.Assert(mcons, gc.DeepEquals, cons1) 1400 1401 // ...until the machine is provisioned, at which point they stick. 1402 err = machine.SetProvisioned("i-mstuck", "fake_nonce", nil) 1403 c.Assert(err, jc.ErrorIsNil) 1404 cons2 := constraints.MustParse("mem=2G") 1405 err = machine.SetConstraints(cons2) 1406 c.Assert(err, gc.ErrorMatches, "cannot set constraints: machine is already provisioned") 1407 1408 // Check the failed set had no effect. 1409 mcons, err = machine.Constraints() 1410 c.Assert(err, jc.ErrorIsNil) 1411 c.Assert(mcons, gc.DeepEquals, cons1) 1412 } 1413 1414 func (s *MachineSuite) TestSetAmbiguousConstraints(c *gc.C) { 1415 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1416 c.Assert(err, jc.ErrorIsNil) 1417 cons := constraints.MustParse("mem=4G instance-type=foo") 1418 err = machine.SetConstraints(cons) 1419 c.Assert(err, gc.ErrorMatches, `cannot set constraints: ambiguous constraints: "instance-type" overlaps with "mem"`) 1420 } 1421 1422 func (s *MachineSuite) TestSetUnsupportedConstraintsWarning(c *gc.C) { 1423 defer loggo.ResetWriters() 1424 logger := loggo.GetLogger("test") 1425 logger.SetLogLevel(loggo.DEBUG) 1426 var tw loggo.TestWriter 1427 c.Assert(loggo.RegisterWriter("constraints-tester", &tw), gc.IsNil) 1428 1429 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1430 c.Assert(err, jc.ErrorIsNil) 1431 cons := constraints.MustParse("mem=4G cpu-power=10") 1432 err = machine.SetConstraints(cons) 1433 c.Assert(err, jc.ErrorIsNil) 1434 c.Assert(tw.Log(), jc.LogMatches, jc.SimpleMessages{{ 1435 loggo.WARNING, 1436 `setting constraints on machine "2": unsupported constraints: cpu-power`}, 1437 }) 1438 mcons, err := machine.Constraints() 1439 c.Assert(err, jc.ErrorIsNil) 1440 c.Assert(mcons, gc.DeepEquals, cons) 1441 } 1442 1443 func (s *MachineSuite) TestConstraintsLifecycle(c *gc.C) { 1444 cons := constraints.MustParse("mem=1G") 1445 cannotSet := `cannot set constraints: not found or not alive` 1446 testWhenDying(c, s.machine, cannotSet, cannotSet, func() error { 1447 err := s.machine.SetConstraints(cons) 1448 mcons, err1 := s.machine.Constraints() 1449 c.Assert(err1, gc.IsNil) 1450 c.Assert(&mcons, jc.Satisfies, constraints.IsEmpty) 1451 return err 1452 }) 1453 1454 err := s.machine.Remove() 1455 c.Assert(err, jc.ErrorIsNil) 1456 err = s.machine.SetConstraints(cons) 1457 c.Assert(err, gc.ErrorMatches, cannotSet) 1458 _, err = s.machine.Constraints() 1459 c.Assert(err, gc.ErrorMatches, `constraints not found`) 1460 } 1461 1462 func (s *MachineSuite) TestSetProviderAddresses(c *gc.C) { 1463 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1464 c.Assert(err, jc.ErrorIsNil) 1465 c.Assert(machine.Addresses(), gc.HasLen, 0) 1466 1467 addresses := network.NewAddresses("127.0.0.1", "8.8.8.8") 1468 err = machine.SetProviderAddresses(addresses...) 1469 c.Assert(err, jc.ErrorIsNil) 1470 err = machine.Refresh() 1471 c.Assert(err, jc.ErrorIsNil) 1472 1473 expectedAddresses := network.NewAddresses("8.8.8.8", "127.0.0.1") 1474 c.Assert(machine.Addresses(), jc.DeepEquals, expectedAddresses) 1475 } 1476 1477 func (s *MachineSuite) TestSetProviderAddressesWithContainers(c *gc.C) { 1478 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1479 c.Assert(err, jc.ErrorIsNil) 1480 c.Assert(machine.Addresses(), gc.HasLen, 0) 1481 1482 // When setting all addresses the subnet addresses have to be 1483 // filtered out. 1484 addresses := network.NewAddresses( 1485 "127.0.0.1", 1486 "8.8.8.8", 1487 ) 1488 err = machine.SetProviderAddresses(addresses...) 1489 c.Assert(err, jc.ErrorIsNil) 1490 err = machine.Refresh() 1491 c.Assert(err, jc.ErrorIsNil) 1492 1493 expectedAddresses := network.NewAddresses("8.8.8.8", "127.0.0.1") 1494 c.Assert(machine.Addresses(), jc.DeepEquals, expectedAddresses) 1495 } 1496 1497 func (s *MachineSuite) TestSetProviderAddressesOnContainer(c *gc.C) { 1498 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1499 c.Assert(err, jc.ErrorIsNil) 1500 c.Assert(machine.Addresses(), gc.HasLen, 0) 1501 1502 // Create an LXC container inside the machine. 1503 template := state.MachineTemplate{ 1504 Series: "quantal", 1505 Jobs: []state.MachineJob{state.JobHostUnits}, 1506 } 1507 container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXD) 1508 c.Assert(err, jc.ErrorIsNil) 1509 1510 // When setting all addresses the subnet address has to accepted. 1511 addresses := network.NewAddresses("127.0.0.1") 1512 err = container.SetProviderAddresses(addresses...) 1513 c.Assert(err, jc.ErrorIsNil) 1514 err = container.Refresh() 1515 c.Assert(err, jc.ErrorIsNil) 1516 1517 expectedAddresses := network.NewAddresses("127.0.0.1") 1518 c.Assert(container.Addresses(), jc.DeepEquals, expectedAddresses) 1519 } 1520 1521 func (s *MachineSuite) TestSetMachineAddresses(c *gc.C) { 1522 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1523 c.Assert(err, jc.ErrorIsNil) 1524 c.Assert(machine.Addresses(), gc.HasLen, 0) 1525 1526 addresses := network.NewAddresses("127.0.0.1", "8.8.8.8") 1527 err = machine.SetMachineAddresses(addresses...) 1528 c.Assert(err, jc.ErrorIsNil) 1529 err = machine.Refresh() 1530 c.Assert(err, jc.ErrorIsNil) 1531 1532 expectedAddresses := network.NewAddresses("8.8.8.8", "127.0.0.1") 1533 c.Assert(machine.MachineAddresses(), jc.DeepEquals, expectedAddresses) 1534 } 1535 1536 func (s *MachineSuite) TestSetEmptyMachineAddresses(c *gc.C) { 1537 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1538 c.Assert(err, jc.ErrorIsNil) 1539 c.Assert(machine.Addresses(), gc.HasLen, 0) 1540 1541 // Add some machine addresses initially to make sure they're removed. 1542 addresses := network.NewAddresses("127.0.0.1", "8.8.8.8") 1543 err = machine.SetMachineAddresses(addresses...) 1544 c.Assert(err, jc.ErrorIsNil) 1545 err = machine.Refresh() 1546 c.Assert(err, jc.ErrorIsNil) 1547 c.Assert(machine.MachineAddresses(), gc.HasLen, 2) 1548 1549 // Make call with empty address list. 1550 err = machine.SetMachineAddresses() 1551 c.Assert(err, jc.ErrorIsNil) 1552 err = machine.Refresh() 1553 c.Assert(err, jc.ErrorIsNil) 1554 1555 c.Assert(machine.MachineAddresses(), gc.HasLen, 0) 1556 } 1557 1558 func (s *MachineSuite) TestMergedAddresses(c *gc.C) { 1559 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1560 c.Assert(err, jc.ErrorIsNil) 1561 c.Assert(machine.Addresses(), gc.HasLen, 0) 1562 1563 providerAddresses := network.NewAddresses( 1564 "127.0.0.2", 1565 "8.8.8.8", 1566 "fc00::1", 1567 "::1", 1568 "", 1569 "2001:db8::1", 1570 "127.0.0.2", 1571 "example.org", 1572 ) 1573 err = machine.SetProviderAddresses(providerAddresses...) 1574 c.Assert(err, jc.ErrorIsNil) 1575 1576 machineAddresses := network.NewAddresses( 1577 "127.0.0.1", 1578 "localhost", 1579 "2001:db8::1", 1580 "192.168.0.1", 1581 "fe80::1", 1582 "::1", 1583 "fd00::1", 1584 ) 1585 err = machine.SetMachineAddresses(machineAddresses...) 1586 c.Assert(err, jc.ErrorIsNil) 1587 err = machine.Refresh() 1588 c.Assert(err, jc.ErrorIsNil) 1589 1590 // Before setting the addresses coming from either the provider or 1591 // the machine itself, they are sorted to prefer public IPs on 1592 // top, then hostnames, cloud-local, machine-local, link-local. 1593 // Duplicates are removed, then when calling Addresses() both 1594 // sources are merged while preservig the provider addresses 1595 // order. 1596 c.Assert(machine.Addresses(), jc.DeepEquals, network.NewAddresses( 1597 "8.8.8.8", 1598 "2001:db8::1", 1599 "example.org", 1600 "fc00::1", 1601 "127.0.0.2", 1602 "::1", 1603 "localhost", 1604 "192.168.0.1", 1605 "fd00::1", 1606 "127.0.0.1", 1607 "fe80::1", 1608 )) 1609 } 1610 1611 func (s *MachineSuite) TestSetProviderAddressesConcurrentChangeDifferent(c *gc.C) { 1612 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1613 c.Assert(err, jc.ErrorIsNil) 1614 c.Assert(machine.Addresses(), gc.HasLen, 0) 1615 1616 addr0 := network.NewAddress("127.0.0.1") 1617 addr1 := network.NewAddress("8.8.8.8") 1618 1619 defer state.SetBeforeHooks(c, s.State, func() { 1620 machine, err := s.State.Machine(machine.Id()) 1621 c.Assert(err, jc.ErrorIsNil) 1622 err = machine.SetProviderAddresses(addr1, addr0) 1623 c.Assert(err, jc.ErrorIsNil) 1624 }).Check() 1625 1626 err = machine.SetProviderAddresses(addr0, addr1) 1627 c.Assert(err, jc.ErrorIsNil) 1628 c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0, addr1}) 1629 } 1630 1631 func (s *MachineSuite) TestSetProviderAddressesConcurrentChangeEqual(c *gc.C) { 1632 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1633 c.Assert(err, jc.ErrorIsNil) 1634 c.Assert(machine.Addresses(), gc.HasLen, 0) 1635 machineDocID := state.DocID(s.State, machine.Id()) 1636 revno0, err := state.TxnRevno(s.State, "machines", machineDocID) 1637 c.Assert(err, jc.ErrorIsNil) 1638 1639 addr0 := network.NewAddress("127.0.0.1") 1640 addr1 := network.NewAddress("8.8.8.8") 1641 1642 var revno1 int64 1643 defer state.SetBeforeHooks(c, s.State, func() { 1644 machine, err := s.State.Machine(machine.Id()) 1645 c.Assert(err, jc.ErrorIsNil) 1646 err = machine.SetProviderAddresses(addr0, addr1) 1647 c.Assert(err, jc.ErrorIsNil) 1648 revno1, err = state.TxnRevno(s.State, "machines", machineDocID) 1649 c.Assert(err, jc.ErrorIsNil) 1650 c.Assert(revno1, jc.GreaterThan, revno0) 1651 }).Check() 1652 1653 err = machine.SetProviderAddresses(addr0, addr1) 1654 c.Assert(err, jc.ErrorIsNil) 1655 1656 // Doc will be updated; concurrent changes are explicitly ignored. 1657 revno2, err := state.TxnRevno(s.State, "machines", machineDocID) 1658 c.Assert(err, jc.ErrorIsNil) 1659 c.Assert(revno2, jc.GreaterThan, revno1) 1660 c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0, addr1}) 1661 } 1662 1663 func (s *MachineSuite) TestSetProviderAddressesInvalidateMemory(c *gc.C) { 1664 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1665 c.Assert(err, jc.ErrorIsNil) 1666 c.Assert(machine.Addresses(), gc.HasLen, 0) 1667 machineDocID := state.DocID(s.State, machine.Id()) 1668 1669 addr0 := network.NewAddress("127.0.0.1") 1670 addr1 := network.NewAddress("8.8.8.8") 1671 1672 // Set addresses to [addr0] initially. We'll get a separate Machine 1673 // object to update addresses, to ensure that the in-memory cache of 1674 // addresses does not prevent the initial Machine from updating 1675 // addresses back to the original value. 1676 err = machine.SetProviderAddresses(addr0) 1677 c.Assert(err, jc.ErrorIsNil) 1678 revno0, err := state.TxnRevno(s.State, "machines", machineDocID) 1679 c.Assert(err, jc.ErrorIsNil) 1680 1681 machine2, err := s.State.Machine(machine.Id()) 1682 c.Assert(err, jc.ErrorIsNil) 1683 err = machine2.SetProviderAddresses(addr1) 1684 c.Assert(err, jc.ErrorIsNil) 1685 revno1, err := state.TxnRevno(s.State, "machines", machineDocID) 1686 c.Assert(err, jc.ErrorIsNil) 1687 c.Assert(revno1, jc.GreaterThan, revno0) 1688 c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0}) 1689 c.Assert(machine2.Addresses(), jc.SameContents, []network.Address{addr1}) 1690 1691 err = machine.SetProviderAddresses(addr0) 1692 c.Assert(err, jc.ErrorIsNil) 1693 revno2, err := state.TxnRevno(s.State, "machines", machineDocID) 1694 c.Assert(err, jc.ErrorIsNil) 1695 c.Assert(revno2, jc.GreaterThan, revno1) 1696 c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0}) 1697 } 1698 1699 func (s *MachineSuite) TestPublicAddressSetOnNewMachine(c *gc.C) { 1700 m, err := s.State.AddOneMachine(state.MachineTemplate{ 1701 Series: "quantal", 1702 Jobs: []state.MachineJob{state.JobHostUnits}, 1703 Addresses: network.NewAddresses("10.0.0.1", "8.8.8.8"), 1704 }) 1705 c.Assert(err, jc.ErrorIsNil) 1706 addr, err := m.PublicAddress() 1707 c.Assert(err, jc.ErrorIsNil) 1708 c.Assert(addr, jc.DeepEquals, network.NewAddress("8.8.8.8")) 1709 } 1710 1711 func (s *MachineSuite) TestPrivateAddressSetOnNewMachine(c *gc.C) { 1712 m, err := s.State.AddOneMachine(state.MachineTemplate{ 1713 Series: "quantal", 1714 Jobs: []state.MachineJob{state.JobHostUnits}, 1715 Addresses: network.NewAddresses("10.0.0.1", "8.8.8.8"), 1716 }) 1717 c.Assert(err, jc.ErrorIsNil) 1718 addr, err := m.PrivateAddress() 1719 c.Assert(err, jc.ErrorIsNil) 1720 c.Assert(addr, jc.DeepEquals, network.NewAddress("10.0.0.1")) 1721 } 1722 1723 func (s *MachineSuite) TestPublicAddressEmptyAddresses(c *gc.C) { 1724 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1725 c.Assert(err, jc.ErrorIsNil) 1726 c.Assert(machine.Addresses(), gc.HasLen, 0) 1727 1728 addr, err := machine.PublicAddress() 1729 c.Assert(err, jc.Satisfies, network.IsNoAddressError) 1730 c.Assert(addr.Value, gc.Equals, "") 1731 } 1732 1733 func (s *MachineSuite) TestPrivateAddressEmptyAddresses(c *gc.C) { 1734 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1735 c.Assert(err, jc.ErrorIsNil) 1736 c.Assert(machine.Addresses(), gc.HasLen, 0) 1737 1738 addr, err := machine.PrivateAddress() 1739 c.Assert(err, jc.Satisfies, network.IsNoAddressError) 1740 c.Assert(addr.Value, gc.Equals, "") 1741 } 1742 1743 func (s *MachineSuite) TestPublicAddress(c *gc.C) { 1744 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1745 c.Assert(err, jc.ErrorIsNil) 1746 1747 err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8")) 1748 c.Assert(err, jc.ErrorIsNil) 1749 1750 addr, err := machine.PublicAddress() 1751 c.Assert(err, jc.ErrorIsNil) 1752 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 1753 } 1754 1755 func (s *MachineSuite) TestPrivateAddress(c *gc.C) { 1756 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1757 c.Assert(err, jc.ErrorIsNil) 1758 1759 err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1")) 1760 c.Assert(err, jc.ErrorIsNil) 1761 1762 addr, err := machine.PrivateAddress() 1763 c.Assert(err, jc.ErrorIsNil) 1764 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 1765 } 1766 1767 func (s *MachineSuite) TestPublicAddressBetterMatch(c *gc.C) { 1768 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1769 c.Assert(err, jc.ErrorIsNil) 1770 1771 err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1")) 1772 c.Assert(err, jc.ErrorIsNil) 1773 1774 addr, err := machine.PublicAddress() 1775 c.Assert(err, jc.ErrorIsNil) 1776 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 1777 1778 err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8")) 1779 c.Assert(err, jc.ErrorIsNil) 1780 1781 addr, err = machine.PublicAddress() 1782 c.Assert(err, jc.ErrorIsNil) 1783 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 1784 } 1785 1786 func (s *MachineSuite) TestPrivateAddressBetterMatch(c *gc.C) { 1787 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1788 c.Assert(err, jc.ErrorIsNil) 1789 1790 err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8")) 1791 c.Assert(err, jc.ErrorIsNil) 1792 1793 addr, err := machine.PrivateAddress() 1794 c.Assert(err, jc.ErrorIsNil) 1795 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 1796 1797 err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.1")) 1798 c.Assert(err, jc.ErrorIsNil) 1799 1800 addr, err = machine.PrivateAddress() 1801 c.Assert(err, jc.ErrorIsNil) 1802 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 1803 } 1804 1805 func (s *MachineSuite) TestPublicAddressChanges(c *gc.C) { 1806 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1807 c.Assert(err, jc.ErrorIsNil) 1808 1809 err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8")) 1810 c.Assert(err, jc.ErrorIsNil) 1811 1812 addr, err := machine.PublicAddress() 1813 c.Assert(err, jc.ErrorIsNil) 1814 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 1815 1816 err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4")) 1817 c.Assert(err, jc.ErrorIsNil) 1818 1819 addr, err = machine.PublicAddress() 1820 c.Assert(err, jc.ErrorIsNil) 1821 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 1822 } 1823 1824 func (s *MachineSuite) TestPrivateAddressChanges(c *gc.C) { 1825 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1826 c.Assert(err, jc.ErrorIsNil) 1827 1828 err = machine.SetMachineAddresses(network.NewAddress("10.0.0.2")) 1829 c.Assert(err, jc.ErrorIsNil) 1830 1831 addr, err := machine.PrivateAddress() 1832 c.Assert(err, jc.ErrorIsNil) 1833 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 1834 1835 err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1")) 1836 c.Assert(err, jc.ErrorIsNil) 1837 1838 addr, err = machine.PrivateAddress() 1839 c.Assert(err, jc.ErrorIsNil) 1840 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 1841 } 1842 1843 func (s *MachineSuite) TestAddressesDeadMachine(c *gc.C) { 1844 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1845 c.Assert(err, jc.ErrorIsNil) 1846 1847 err = machine.SetProviderAddresses(network.NewAddress("10.0.0.2"), network.NewAddress("8.8.4.4")) 1848 c.Assert(err, jc.ErrorIsNil) 1849 1850 addr, err := machine.PrivateAddress() 1851 c.Assert(err, jc.ErrorIsNil) 1852 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 1853 1854 addr, err = machine.PublicAddress() 1855 c.Assert(err, jc.ErrorIsNil) 1856 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 1857 1858 err = machine.EnsureDead() 1859 c.Assert(err, jc.ErrorIsNil) 1860 1861 // A dead machine should still report the last known addresses. 1862 addr, err = machine.PrivateAddress() 1863 c.Assert(err, jc.ErrorIsNil) 1864 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 1865 1866 addr, err = machine.PublicAddress() 1867 c.Assert(err, jc.ErrorIsNil) 1868 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 1869 } 1870 1871 func (s *MachineSuite) TestStablePrivateAddress(c *gc.C) { 1872 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1873 c.Assert(err, jc.ErrorIsNil) 1874 1875 err = machine.SetMachineAddresses(network.NewAddress("10.0.0.2")) 1876 c.Assert(err, jc.ErrorIsNil) 1877 1878 addr, err := machine.PrivateAddress() 1879 c.Assert(err, jc.ErrorIsNil) 1880 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 1881 1882 // Now add an address that would previously have sorted before the 1883 // default. 1884 err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1"), network.NewAddress("10.0.0.2")) 1885 c.Assert(err, jc.ErrorIsNil) 1886 1887 // Assert the address is unchanged. 1888 addr, err = machine.PrivateAddress() 1889 c.Assert(err, jc.ErrorIsNil) 1890 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 1891 } 1892 1893 func (s *MachineSuite) TestStablePublicAddress(c *gc.C) { 1894 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1895 c.Assert(err, jc.ErrorIsNil) 1896 1897 err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8")) 1898 c.Assert(err, jc.ErrorIsNil) 1899 1900 addr, err := machine.PublicAddress() 1901 c.Assert(err, jc.ErrorIsNil) 1902 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 1903 1904 // Now add an address that would previously have sorted before the 1905 // default. 1906 err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4"), network.NewAddress("8.8.8.8")) 1907 c.Assert(err, jc.ErrorIsNil) 1908 1909 // Assert the address is unchanged. 1910 addr, err = machine.PublicAddress() 1911 c.Assert(err, jc.ErrorIsNil) 1912 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 1913 } 1914 1915 func (s *MachineSuite) TestAddressesRaceMachineFirst(c *gc.C) { 1916 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1917 c.Assert(err, jc.ErrorIsNil) 1918 1919 changeAddresses := jujutxn.TestHook{ 1920 Before: func() { 1921 err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8")) 1922 c.Assert(err, jc.ErrorIsNil) 1923 address, err := machine.PublicAddress() 1924 c.Assert(err, jc.ErrorIsNil) 1925 c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8")) 1926 address, err = machine.PrivateAddress() 1927 c.Assert(err, jc.ErrorIsNil) 1928 c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8")) 1929 }, 1930 } 1931 defer state.SetTestHooks(c, s.State, changeAddresses).Check() 1932 1933 err = machine.SetMachineAddresses(network.NewAddress("8.8.4.4")) 1934 c.Assert(err, jc.ErrorIsNil) 1935 1936 machine, err = s.State.Machine(machine.Id()) 1937 c.Assert(err, jc.ErrorIsNil) 1938 address, err := machine.PublicAddress() 1939 c.Assert(err, jc.ErrorIsNil) 1940 c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8")) 1941 address, err = machine.PrivateAddress() 1942 c.Assert(err, jc.ErrorIsNil) 1943 c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8")) 1944 } 1945 1946 func (s *MachineSuite) TestAddressesRaceProviderFirst(c *gc.C) { 1947 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1948 c.Assert(err, jc.ErrorIsNil) 1949 1950 changeAddresses := jujutxn.TestHook{ 1951 Before: func() { 1952 err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1")) 1953 c.Assert(err, jc.ErrorIsNil) 1954 address, err := machine.PublicAddress() 1955 c.Assert(err, jc.ErrorIsNil) 1956 c.Assert(address, jc.DeepEquals, network.NewAddress("10.0.0.1")) 1957 address, err = machine.PrivateAddress() 1958 c.Assert(err, jc.ErrorIsNil) 1959 c.Assert(address, jc.DeepEquals, network.NewAddress("10.0.0.1")) 1960 }, 1961 } 1962 defer state.SetTestHooks(c, s.State, changeAddresses).Check() 1963 1964 err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4")) 1965 c.Assert(err, jc.ErrorIsNil) 1966 1967 machine, err = s.State.Machine(machine.Id()) 1968 c.Assert(err, jc.ErrorIsNil) 1969 address, err := machine.PublicAddress() 1970 c.Assert(err, jc.ErrorIsNil) 1971 c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.4.4")) 1972 address, err = machine.PrivateAddress() 1973 c.Assert(err, jc.ErrorIsNil) 1974 c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.4.4")) 1975 } 1976 1977 func (s *MachineSuite) TestPrivateAddressPrefersProvider(c *gc.C) { 1978 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1979 c.Assert(err, jc.ErrorIsNil) 1980 1981 err = machine.SetMachineAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.2")) 1982 c.Assert(err, jc.ErrorIsNil) 1983 1984 addr, err := machine.PublicAddress() 1985 c.Assert(err, jc.ErrorIsNil) 1986 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 1987 addr, err = machine.PrivateAddress() 1988 c.Assert(err, jc.ErrorIsNil) 1989 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 1990 1991 err = machine.SetProviderAddresses(network.NewAddress("10.0.0.1")) 1992 c.Assert(err, jc.ErrorIsNil) 1993 1994 addr, err = machine.PublicAddress() 1995 c.Assert(err, jc.ErrorIsNil) 1996 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 1997 addr, err = machine.PrivateAddress() 1998 c.Assert(err, jc.ErrorIsNil) 1999 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 2000 } 2001 2002 func (s *MachineSuite) TestPublicAddressPrefersProvider(c *gc.C) { 2003 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2004 c.Assert(err, jc.ErrorIsNil) 2005 2006 err = machine.SetMachineAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.2")) 2007 c.Assert(err, jc.ErrorIsNil) 2008 2009 addr, err := machine.PublicAddress() 2010 c.Assert(err, jc.ErrorIsNil) 2011 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2012 addr, err = machine.PrivateAddress() 2013 c.Assert(err, jc.ErrorIsNil) 2014 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 2015 2016 err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4")) 2017 c.Assert(err, jc.ErrorIsNil) 2018 2019 addr, err = machine.PublicAddress() 2020 c.Assert(err, jc.ErrorIsNil) 2021 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 2022 addr, err = machine.PrivateAddress() 2023 c.Assert(err, jc.ErrorIsNil) 2024 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 2025 } 2026 2027 func (s *MachineSuite) TestAddressesPrefersProviderBoth(c *gc.C) { 2028 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2029 c.Assert(err, jc.ErrorIsNil) 2030 2031 err = machine.SetMachineAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.1")) 2032 c.Assert(err, jc.ErrorIsNil) 2033 2034 addr, err := machine.PublicAddress() 2035 c.Assert(err, jc.ErrorIsNil) 2036 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2037 addr, err = machine.PrivateAddress() 2038 c.Assert(err, jc.ErrorIsNil) 2039 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 2040 2041 err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4"), network.NewAddress("10.0.0.2")) 2042 c.Assert(err, jc.ErrorIsNil) 2043 2044 addr, err = machine.PublicAddress() 2045 c.Assert(err, jc.ErrorIsNil) 2046 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 2047 addr, err = machine.PrivateAddress() 2048 c.Assert(err, jc.ErrorIsNil) 2049 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 2050 } 2051 2052 func (s *MachineSuite) addMachineWithSupportedContainer(c *gc.C, container instance.ContainerType) *state.Machine { 2053 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2054 c.Assert(err, jc.ErrorIsNil) 2055 containers := []instance.ContainerType{container} 2056 err = machine.SetSupportedContainers(containers) 2057 c.Assert(err, jc.ErrorIsNil) 2058 assertSupportedContainers(c, machine, containers) 2059 return machine 2060 } 2061 2062 // assertSupportedContainers checks the document in memory has the specified 2063 // containers and then reloads the document from the database to assert saved 2064 // values match also. 2065 func assertSupportedContainers(c *gc.C, machine *state.Machine, containers []instance.ContainerType) { 2066 supportedContainers, known := machine.SupportedContainers() 2067 c.Assert(known, jc.IsTrue) 2068 c.Assert(supportedContainers, gc.DeepEquals, containers) 2069 // Reload so we can check the saved values. 2070 err := machine.Refresh() 2071 c.Assert(err, jc.ErrorIsNil) 2072 supportedContainers, known = machine.SupportedContainers() 2073 c.Assert(known, jc.IsTrue) 2074 c.Assert(supportedContainers, gc.DeepEquals, containers) 2075 } 2076 2077 func assertSupportedContainersUnknown(c *gc.C, machine *state.Machine) { 2078 containers, known := machine.SupportedContainers() 2079 c.Assert(known, jc.IsFalse) 2080 c.Assert(containers, gc.HasLen, 0) 2081 } 2082 2083 func (s *MachineSuite) TestSupportedContainersInitiallyUnknown(c *gc.C) { 2084 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2085 c.Assert(err, jc.ErrorIsNil) 2086 assertSupportedContainersUnknown(c, machine) 2087 } 2088 2089 func (s *MachineSuite) TestSupportsNoContainers(c *gc.C) { 2090 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2091 c.Assert(err, jc.ErrorIsNil) 2092 2093 err = machine.SupportsNoContainers() 2094 c.Assert(err, jc.ErrorIsNil) 2095 assertSupportedContainers(c, machine, []instance.ContainerType{}) 2096 } 2097 2098 func (s *MachineSuite) TestSetSupportedContainerTypeNoneIsError(c *gc.C) { 2099 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2100 c.Assert(err, jc.ErrorIsNil) 2101 2102 err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.NONE}) 2103 c.Assert(err, gc.ErrorMatches, `"none" is not a valid container type`) 2104 assertSupportedContainersUnknown(c, machine) 2105 err = machine.Refresh() 2106 c.Assert(err, jc.ErrorIsNil) 2107 assertSupportedContainersUnknown(c, machine) 2108 } 2109 2110 func (s *MachineSuite) TestSupportsNoContainersOverwritesExisting(c *gc.C) { 2111 machine := s.addMachineWithSupportedContainer(c, instance.LXD) 2112 2113 err := machine.SupportsNoContainers() 2114 c.Assert(err, jc.ErrorIsNil) 2115 assertSupportedContainers(c, machine, []instance.ContainerType{}) 2116 } 2117 2118 func (s *MachineSuite) TestSetSupportedContainersSingle(c *gc.C) { 2119 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2120 c.Assert(err, jc.ErrorIsNil) 2121 2122 err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD}) 2123 c.Assert(err, jc.ErrorIsNil) 2124 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD}) 2125 } 2126 2127 func (s *MachineSuite) TestSetSupportedContainersSame(c *gc.C) { 2128 machine := s.addMachineWithSupportedContainer(c, instance.LXD) 2129 2130 err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXD}) 2131 c.Assert(err, jc.ErrorIsNil) 2132 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD}) 2133 } 2134 2135 func (s *MachineSuite) TestSetSupportedContainersNew(c *gc.C) { 2136 machine := s.addMachineWithSupportedContainer(c, instance.LXD) 2137 2138 err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM}) 2139 c.Assert(err, jc.ErrorIsNil) 2140 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM}) 2141 } 2142 2143 func (s *MachineSuite) TestSetSupportedContainersMultipeNew(c *gc.C) { 2144 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2145 c.Assert(err, jc.ErrorIsNil) 2146 2147 err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM}) 2148 c.Assert(err, jc.ErrorIsNil) 2149 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM}) 2150 } 2151 2152 func (s *MachineSuite) TestSetSupportedContainersMultipleExisting(c *gc.C) { 2153 machine := s.addMachineWithSupportedContainer(c, instance.LXD) 2154 2155 err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM}) 2156 c.Assert(err, jc.ErrorIsNil) 2157 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM}) 2158 } 2159 2160 func (s *MachineSuite) TestSetSupportedContainersSetsUnknownToError(c *gc.C) { 2161 // Create a machine and add lxd and kvm containers prior to calling SetSupportedContainers 2162 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2163 template := state.MachineTemplate{ 2164 Series: "quantal", 2165 Jobs: []state.MachineJob{state.JobHostUnits}, 2166 } 2167 container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXD) 2168 c.Assert(err, jc.ErrorIsNil) 2169 supportedContainer, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.KVM) 2170 c.Assert(err, jc.ErrorIsNil) 2171 err = machine.SetSupportedContainers([]instance.ContainerType{instance.KVM}) 2172 c.Assert(err, jc.ErrorIsNil) 2173 2174 // A supported (kvm) container will have a pending status. 2175 err = supportedContainer.Refresh() 2176 c.Assert(err, jc.ErrorIsNil) 2177 statusInfo, err := supportedContainer.Status() 2178 c.Assert(err, jc.ErrorIsNil) 2179 c.Assert(statusInfo.Status, gc.Equals, status.Pending) 2180 2181 // An unsupported (lxd) container will have an error status. 2182 err = container.Refresh() 2183 c.Assert(err, jc.ErrorIsNil) 2184 statusInfo, err = container.Status() 2185 c.Assert(err, jc.ErrorIsNil) 2186 c.Assert(statusInfo.Status, gc.Equals, status.Error) 2187 c.Assert(statusInfo.Message, gc.Equals, "unsupported container") 2188 c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{"type": "lxd"}) 2189 } 2190 2191 func (s *MachineSuite) TestSupportsNoContainersSetsAllToError(c *gc.C) { 2192 // Create a machine and add all container types prior to calling SupportsNoContainers 2193 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2194 var containers []*state.Machine 2195 template := state.MachineTemplate{ 2196 Series: "quantal", 2197 Jobs: []state.MachineJob{state.JobHostUnits}, 2198 } 2199 for _, containerType := range instance.ContainerTypes { 2200 container, err := s.State.AddMachineInsideMachine(template, machine.Id(), containerType) 2201 c.Assert(err, jc.ErrorIsNil) 2202 containers = append(containers, container) 2203 } 2204 2205 err = machine.SupportsNoContainers() 2206 c.Assert(err, jc.ErrorIsNil) 2207 2208 // All containers should be in error state. 2209 for _, container := range containers { 2210 err = container.Refresh() 2211 c.Assert(err, jc.ErrorIsNil) 2212 statusInfo, err := container.Status() 2213 c.Assert(err, jc.ErrorIsNil) 2214 c.Assert(statusInfo.Status, gc.Equals, status.Error) 2215 c.Assert(statusInfo.Message, gc.Equals, "unsupported container") 2216 containerType := state.ContainerTypeFromId(container.Id()) 2217 c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{"type": string(containerType)}) 2218 } 2219 } 2220 2221 func (s *MachineSuite) TestMachineAgentTools(c *gc.C) { 2222 m, err := s.State.AddMachine("quantal", state.JobHostUnits) 2223 c.Assert(err, jc.ErrorIsNil) 2224 testAgentTools(c, m, "machine "+m.Id()) 2225 } 2226 2227 func (s *MachineSuite) TestMachineValidActions(c *gc.C) { 2228 m, err := s.State.AddMachine("trusty", state.JobHostUnits) 2229 c.Assert(err, jc.ErrorIsNil) 2230 2231 var tests = []struct { 2232 actionName string 2233 errString string 2234 givenPayload map[string]interface{} 2235 expectedPayload map[string]interface{} 2236 }{ 2237 { 2238 actionName: "juju-run", 2239 errString: `validation failed: (root) : "command" property is missing and required, given {}; (root) : "timeout" property is missing and required, given {}`, 2240 }, 2241 { 2242 actionName: "juju-run", 2243 givenPayload: map[string]interface{}{"command": "allyourbasearebelongtous", "timeout": 5.0}, 2244 expectedPayload: map[string]interface{}{"command": "allyourbasearebelongtous", "timeout": 5.0}, 2245 }, 2246 { 2247 actionName: "baiku", 2248 errString: `cannot add action "baiku" to a machine; only predefined actions allowed`, 2249 }, 2250 } 2251 2252 for i, t := range tests { 2253 c.Logf("running test %d", i) 2254 action, err := m.AddAction(t.actionName, t.givenPayload) 2255 if t.errString != "" { 2256 c.Assert(err.Error(), gc.Equals, t.errString) 2257 continue 2258 } else { 2259 c.Assert(err, jc.ErrorIsNil) 2260 c.Assert(action.Parameters(), jc.DeepEquals, t.expectedPayload) 2261 } 2262 } 2263 } 2264 2265 func (s *MachineSuite) TestMachineAddDifferentAction(c *gc.C) { 2266 m, err := s.State.AddMachine("trusty", state.JobHostUnits) 2267 c.Assert(err, jc.ErrorIsNil) 2268 2269 _, err = m.AddAction("benchmark", nil) 2270 c.Assert(err, gc.ErrorMatches, `cannot add action "benchmark" to a machine; only predefined actions allowed`) 2271 }