github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/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 "github.com/juju/names" 12 jc "github.com/juju/testing/checkers" 13 jujutxn "github.com/juju/txn" 14 "github.com/juju/version" 15 gc "gopkg.in/check.v1" 16 "gopkg.in/mgo.v2" 17 "gopkg.in/mgo.v2/bson" 18 19 "github.com/juju/juju/constraints" 20 "github.com/juju/juju/environs/config" 21 "github.com/juju/juju/instance" 22 "github.com/juju/juju/mongo/mongotest" 23 "github.com/juju/juju/network" 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 "github.com/juju/juju/storage/provider/registry" 30 coretesting "github.com/juju/juju/testing" 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(*config.Config, state.SupportedArchitecturesQuerier) (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.LXC) 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.LXC) 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.LXC) 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.LXC) 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.LXC) 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.LXC) 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.LXC) 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/lxc/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.LXC) 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) TestRemoveMarksAddressesAsDead(c *gc.C) { 523 err := s.machine.SetProvisioned("fake", "totally-fake", nil) 524 c.Assert(err, jc.ErrorIsNil) 525 526 addr1, err := s.State.AddIPAddress(network.NewAddress("10.0.0.1"), "foo") 527 c.Assert(err, jc.ErrorIsNil) 528 err = addr1.AllocateTo(s.machine.Id(), "bar", "01:23:45:67:89:ab") 529 c.Assert(err, jc.ErrorIsNil) 530 531 addr2, err := s.State.AddIPAddress(network.NewAddress("10.0.0.2"), "foo") 532 c.Assert(err, jc.ErrorIsNil) 533 err = addr2.AllocateTo(s.machine.Id(), "bar", "01:23:45:67:89:ab") 534 c.Assert(err, jc.ErrorIsNil) 535 536 addr3, err := s.State.AddIPAddress(network.NewAddress("10.0.0.3"), "bar") 537 c.Assert(err, jc.ErrorIsNil) 538 err = addr3.AllocateTo(s.machine0.Id(), "bar", "01:23:45:67:89:ab") 539 c.Assert(err, jc.ErrorIsNil) 540 541 addr4, err := s.State.AddIPAddress(network.NewAddress("10.0.0.4"), "foo") 542 c.Assert(err, jc.ErrorIsNil) 543 err = addr4.AllocateTo(s.machine.Id(), "bar", "01:23:45:67:89:ab") 544 c.Assert(err, jc.ErrorIsNil) 545 err = addr4.EnsureDead() 546 c.Assert(err, jc.ErrorIsNil) 547 548 err = s.machine.EnsureDead() 549 c.Assert(err, jc.ErrorIsNil) 550 err = s.machine.Remove() 551 c.Assert(err, jc.ErrorIsNil) 552 553 err = addr1.Refresh() 554 c.Assert(err, jc.ErrorIsNil) 555 c.Assert(addr1.Life(), gc.Equals, state.Dead) 556 err = addr2.Refresh() 557 c.Assert(err, jc.ErrorIsNil) 558 c.Assert(addr2.Life(), gc.Equals, state.Dead) 559 err = addr3.Refresh() 560 c.Assert(err, jc.ErrorIsNil) 561 c.Assert(addr3.Life(), gc.Equals, state.Alive) 562 err = addr4.Refresh() 563 c.Assert(err, jc.ErrorIsNil) 564 c.Assert(addr4.Life(), gc.Equals, state.Dead) 565 } 566 567 func (s *MachineSuite) TestHasVote(c *gc.C) { 568 c.Assert(s.machine.HasVote(), jc.IsFalse) 569 570 // Make another machine value so that 571 // it won't have the cached HasVote value. 572 m, err := s.State.Machine(s.machine.Id()) 573 c.Assert(err, jc.ErrorIsNil) 574 575 err = s.machine.SetHasVote(true) 576 c.Assert(err, jc.ErrorIsNil) 577 c.Assert(s.machine.HasVote(), jc.IsTrue) 578 c.Assert(m.HasVote(), jc.IsFalse) 579 580 err = m.Refresh() 581 c.Assert(err, jc.ErrorIsNil) 582 c.Assert(m.HasVote(), jc.IsTrue) 583 584 err = m.SetHasVote(false) 585 c.Assert(err, jc.ErrorIsNil) 586 c.Assert(m.HasVote(), jc.IsFalse) 587 588 c.Assert(s.machine.HasVote(), jc.IsTrue) 589 err = s.machine.Refresh() 590 c.Assert(err, jc.ErrorIsNil) 591 c.Assert(s.machine.HasVote(), jc.IsFalse) 592 } 593 594 func (s *MachineSuite) TestCannotDestroyMachineWithVote(c *gc.C) { 595 err := s.machine.SetHasVote(true) 596 c.Assert(err, jc.ErrorIsNil) 597 598 // Make another machine value so that 599 // it won't have the cached HasVote value. 600 m, err := s.State.Machine(s.machine.Id()) 601 c.Assert(err, jc.ErrorIsNil) 602 603 err = s.machine.Destroy() 604 c.Assert(err, gc.ErrorMatches, "machine "+s.machine.Id()+" is a voting replica set member") 605 606 err = m.Destroy() 607 c.Assert(err, gc.ErrorMatches, "machine "+s.machine.Id()+" is a voting replica set member") 608 } 609 610 func (s *MachineSuite) TestRemoveAbort(c *gc.C) { 611 err := s.machine.EnsureDead() 612 c.Assert(err, jc.ErrorIsNil) 613 614 defer state.SetBeforeHooks(c, s.State, func() { 615 c.Assert(s.machine.Remove(), gc.IsNil) 616 }).Check() 617 err = s.machine.Remove() 618 c.Assert(err, jc.ErrorIsNil) 619 } 620 621 func (s *MachineSuite) TestMachineSetAgentPresence(c *gc.C) { 622 alive, err := s.machine.AgentPresence() 623 c.Assert(err, jc.ErrorIsNil) 624 c.Assert(alive, jc.IsFalse) 625 626 pinger, err := s.machine.SetAgentPresence() 627 c.Assert(err, jc.ErrorIsNil) 628 c.Assert(pinger, gc.NotNil) 629 defer pinger.Stop() 630 631 s.State.StartSync() 632 alive, err = s.machine.AgentPresence() 633 c.Assert(err, jc.ErrorIsNil) 634 c.Assert(alive, jc.IsTrue) 635 } 636 637 func (s *MachineSuite) TestTag(c *gc.C) { 638 tag := s.machine.MachineTag() 639 c.Assert(tag.Kind(), gc.Equals, names.MachineTagKind) 640 c.Assert(tag.Id(), gc.Equals, "1") 641 642 // To keep gccgo happy, don't compare an interface with a struct. 643 var asTag names.Tag = tag 644 c.Assert(s.machine.Tag(), gc.Equals, asTag) 645 } 646 647 func (s *MachineSuite) TestSetMongoPassword(c *gc.C) { 648 info := testing.NewMongoInfo() 649 st, err := state.Open(s.modelTag, info, mongotest.DialOpts(), state.Policy(nil)) 650 c.Assert(err, jc.ErrorIsNil) 651 defer func() { 652 // Remove the admin password so that the test harness can reset the state. 653 err := st.SetAdminMongoPassword("") 654 c.Check(err, jc.ErrorIsNil) 655 err = st.Close() 656 c.Check(err, jc.ErrorIsNil) 657 }() 658 659 // Turn on fully-authenticated mode. 660 err = st.SetAdminMongoPassword("admin-secret") 661 c.Assert(err, jc.ErrorIsNil) 662 err = st.MongoSession().DB("admin").Login("admin", "admin-secret") 663 c.Assert(err, jc.ErrorIsNil) 664 665 // Set the password for the entity 666 ent, err := st.Machine("0") 667 c.Assert(err, jc.ErrorIsNil) 668 err = ent.SetMongoPassword("foo") 669 c.Assert(err, jc.ErrorIsNil) 670 671 // Check that we cannot log in with the wrong password. 672 info.Tag = ent.Tag() 673 info.Password = "bar" 674 err = tryOpenState(s.modelTag, info) 675 c.Check(errors.Cause(err), jc.Satisfies, errors.IsUnauthorized) 676 c.Check(err, gc.ErrorMatches, `cannot log in to admin database as "machine-0": unauthorized mongo access: .*`) 677 678 // Check that we can log in with the correct password. 679 info.Password = "foo" 680 st1, err := state.Open(s.modelTag, info, mongotest.DialOpts(), state.Policy(nil)) 681 c.Assert(err, jc.ErrorIsNil) 682 defer st1.Close() 683 684 // Change the password with an entity derived from the newly 685 // opened and authenticated state. 686 ent, err = st.Machine("0") 687 c.Assert(err, jc.ErrorIsNil) 688 err = ent.SetMongoPassword("bar") 689 c.Assert(err, jc.ErrorIsNil) 690 691 // Check that we cannot log in with the old password. 692 info.Password = "foo" 693 err = tryOpenState(s.modelTag, info) 694 c.Check(errors.Cause(err), jc.Satisfies, errors.IsUnauthorized) 695 c.Check(err, gc.ErrorMatches, `cannot log in to admin database as "machine-0": unauthorized mongo access: .*`) 696 697 // Check that we can log in with the correct password. 698 info.Password = "bar" 699 err = tryOpenState(s.modelTag, info) 700 c.Assert(err, jc.ErrorIsNil) 701 702 // Check that the administrator can still log in. 703 info.Tag, info.Password = nil, "admin-secret" 704 err = tryOpenState(s.modelTag, info) 705 c.Assert(err, jc.ErrorIsNil) 706 } 707 708 func (s *MachineSuite) TestSetPassword(c *gc.C) { 709 testSetPassword(c, func() (state.Authenticator, error) { 710 return s.State.Machine(s.machine.Id()) 711 }) 712 } 713 714 func (s *MachineSuite) TestSetPasswordPreModelUUID(c *gc.C) { 715 // Ensure that SetPassword works for machines even when the env 716 // UUID upgrade migrations haven't run yet. 717 type oldMachineDoc struct { 718 Id string `bson:"_id"` 719 Series string 720 } 721 s.machines.Insert(&oldMachineDoc{"99", "quantal"}) 722 723 m, err := s.State.Machine("99") 724 c.Assert(err, jc.ErrorIsNil) 725 726 // Set the password and make sure it sticks. 727 c.Assert(m.PasswordValid(goodPassword), jc.IsFalse) 728 err = m.SetPassword(goodPassword) 729 c.Assert(err, jc.ErrorIsNil) 730 c.Assert(m.PasswordValid(goodPassword), jc.IsTrue) 731 732 // Check a newly-fetched entity has the same password. 733 err = m.Refresh() 734 c.Assert(err, jc.ErrorIsNil) 735 c.Assert(m.PasswordValid(goodPassword), jc.IsTrue) 736 } 737 738 func (s *MachineSuite) TestMachineWaitAgentPresence(c *gc.C) { 739 alive, err := s.machine.AgentPresence() 740 c.Assert(err, jc.ErrorIsNil) 741 c.Assert(alive, jc.IsFalse) 742 743 s.State.StartSync() 744 err = s.machine.WaitAgentPresence(coretesting.ShortWait) 745 c.Assert(err, gc.ErrorMatches, `waiting for agent of machine 1: still not alive after timeout`) 746 747 pinger, err := s.machine.SetAgentPresence() 748 c.Assert(err, jc.ErrorIsNil) 749 750 s.State.StartSync() 751 err = s.machine.WaitAgentPresence(coretesting.LongWait) 752 c.Assert(err, jc.ErrorIsNil) 753 754 alive, err = s.machine.AgentPresence() 755 c.Assert(err, jc.ErrorIsNil) 756 c.Assert(alive, jc.IsTrue) 757 758 err = pinger.KillForTesting() 759 c.Assert(err, jc.ErrorIsNil) 760 761 s.State.StartSync() 762 alive, err = s.machine.AgentPresence() 763 c.Assert(err, jc.ErrorIsNil) 764 c.Assert(alive, jc.IsFalse) 765 } 766 767 func (s *MachineSuite) TestMachineInstanceIdCorrupt(c *gc.C) { 768 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 769 c.Assert(err, jc.ErrorIsNil) 770 err = s.machines.Update( 771 bson.D{{"_id", state.DocID(s.State, machine.Id())}}, 772 bson.D{{"$set", bson.D{{"instanceid", bson.D{{"foo", "bar"}}}}}}, 773 ) 774 c.Assert(err, jc.ErrorIsNil) 775 776 err = machine.Refresh() 777 c.Assert(err, jc.ErrorIsNil) 778 iid, err := machine.InstanceId() 779 c.Assert(err, jc.Satisfies, errors.IsNotProvisioned) 780 c.Assert(iid, gc.Equals, instance.Id("")) 781 } 782 783 func (s *MachineSuite) TestMachineInstanceIdMissing(c *gc.C) { 784 iid, err := s.machine.InstanceId() 785 c.Assert(err, jc.Satisfies, errors.IsNotProvisioned) 786 c.Assert(string(iid), gc.Equals, "") 787 } 788 789 func (s *MachineSuite) TestMachineInstanceIdBlank(c *gc.C) { 790 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 791 c.Assert(err, jc.ErrorIsNil) 792 err = s.machines.Update( 793 bson.D{{"_id", state.DocID(s.State, machine.Id())}}, 794 bson.D{{"$set", bson.D{{"instanceid", ""}}}}, 795 ) 796 c.Assert(err, jc.ErrorIsNil) 797 798 err = machine.Refresh() 799 c.Assert(err, jc.ErrorIsNil) 800 iid, err := machine.InstanceId() 801 c.Assert(err, jc.Satisfies, errors.IsNotProvisioned) 802 c.Assert(string(iid), gc.Equals, "") 803 } 804 805 func (s *MachineSuite) TestMachineSetProvisionedUpdatesCharacteristics(c *gc.C) { 806 // Before provisioning, there is no hardware characteristics. 807 _, err := s.machine.HardwareCharacteristics() 808 c.Assert(err, jc.Satisfies, errors.IsNotFound) 809 arch := "amd64" 810 mem := uint64(4096) 811 expected := &instance.HardwareCharacteristics{ 812 Arch: &arch, 813 Mem: &mem, 814 } 815 err = s.machine.SetProvisioned("umbrella/0", "fake_nonce", expected) 816 c.Assert(err, jc.ErrorIsNil) 817 md, err := s.machine.HardwareCharacteristics() 818 c.Assert(err, jc.ErrorIsNil) 819 c.Assert(*md, gc.DeepEquals, *expected) 820 821 // Reload machine and check again. 822 err = s.machine.Refresh() 823 c.Assert(err, jc.ErrorIsNil) 824 md, err = s.machine.HardwareCharacteristics() 825 c.Assert(err, jc.ErrorIsNil) 826 c.Assert(*md, gc.DeepEquals, *expected) 827 } 828 829 func (s *MachineSuite) TestMachineAvailabilityZone(c *gc.C) { 830 zone := "a_zone" 831 hwc := &instance.HardwareCharacteristics{ 832 AvailabilityZone: &zone, 833 } 834 err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", hwc) 835 c.Assert(err, jc.ErrorIsNil) 836 837 zone, err = s.machine.AvailabilityZone() 838 c.Assert(err, jc.ErrorIsNil) 839 c.Check(zone, gc.Equals, "a_zone") 840 } 841 842 func (s *MachineSuite) TestMachineAvailabilityZoneEmpty(c *gc.C) { 843 zone := "" 844 hwc := &instance.HardwareCharacteristics{ 845 AvailabilityZone: &zone, 846 } 847 err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", hwc) 848 c.Assert(err, jc.ErrorIsNil) 849 850 zone, err = s.machine.AvailabilityZone() 851 c.Assert(err, jc.ErrorIsNil) 852 c.Check(zone, gc.Equals, "") 853 } 854 855 func (s *MachineSuite) TestMachineAvailabilityZoneMissing(c *gc.C) { 856 zone := "a_zone" 857 hwc := &instance.HardwareCharacteristics{} 858 err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", hwc) 859 c.Assert(err, jc.ErrorIsNil) 860 861 zone, err = s.machine.AvailabilityZone() 862 c.Assert(err, jc.ErrorIsNil) 863 c.Check(zone, gc.Equals, "") 864 } 865 866 func (s *MachineSuite) TestMachineSetCheckProvisioned(c *gc.C) { 867 // Check before provisioning. 868 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse) 869 870 // Either one should not be empty. 871 err := s.machine.SetProvisioned("umbrella/0", "", nil) 872 c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`) 873 err = s.machine.SetProvisioned("", "fake_nonce", nil) 874 c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`) 875 err = s.machine.SetProvisioned("", "", nil) 876 c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`) 877 878 err = s.machine.SetProvisioned("umbrella/0", "fake_nonce", nil) 879 c.Assert(err, jc.ErrorIsNil) 880 881 m, err := s.State.Machine(s.machine.Id()) 882 c.Assert(err, jc.ErrorIsNil) 883 id, err := m.InstanceId() 884 c.Assert(err, jc.ErrorIsNil) 885 c.Assert(string(id), gc.Equals, "umbrella/0") 886 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue) 887 id, err = s.machine.InstanceId() 888 c.Assert(err, jc.ErrorIsNil) 889 c.Assert(string(id), gc.Equals, "umbrella/0") 890 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue) 891 892 // Try it twice, it should fail. 893 err = s.machine.SetProvisioned("doesn't-matter", "phony", nil) 894 c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": already set`) 895 896 // Check it with invalid nonce. 897 c.Assert(s.machine.CheckProvisioned("not-really"), jc.IsFalse) 898 } 899 900 func (s *MachineSuite) TestMachineSetInstanceInfoFailureDoesNotProvision(c *gc.C) { 901 assertNotProvisioned := func() { 902 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse) 903 } 904 905 assertNotProvisioned() 906 907 invalidVolumes := map[names.VolumeTag]state.VolumeInfo{ 908 names.NewVolumeTag("1065"): state.VolumeInfo{VolumeId: "vol-ume"}, 909 } 910 err := s.machine.SetInstanceInfo("umbrella/0", "fake_nonce", nil, nil, nil, invalidVolumes, nil) 911 c.Assert(err, gc.ErrorMatches, `cannot set info for volume \"1065\": volume \"1065\" not found`) 912 assertNotProvisioned() 913 914 invalidVolumes = map[names.VolumeTag]state.VolumeInfo{ 915 names.NewVolumeTag("1065"): state.VolumeInfo{}, 916 } 917 err = s.machine.SetInstanceInfo("umbrella/0", "fake_nonce", nil, nil, nil, invalidVolumes, nil) 918 c.Assert(err, gc.ErrorMatches, `cannot set info for volume \"1065\": volume ID not set`) 919 assertNotProvisioned() 920 921 // TODO(axw) test invalid volume attachment 922 } 923 924 func (s *MachineSuite) addVolume(c *gc.C, params state.VolumeParams, machineId string) names.VolumeTag { 925 ops, tag, err := state.AddVolumeOps(s.State, params, machineId) 926 c.Assert(err, jc.ErrorIsNil) 927 err = state.RunTransaction(s.State, ops) 928 c.Assert(err, jc.ErrorIsNil) 929 return tag 930 } 931 932 func (s *MachineSuite) TestMachineSetInstanceInfoSuccess(c *gc.C) { 933 pm := poolmanager.New(state.NewStateSettings(s.State)) 934 _, err := pm.Create("loop-pool", provider.LoopProviderType, map[string]interface{}{}) 935 c.Assert(err, jc.ErrorIsNil) 936 registry.RegisterEnvironStorageProviders("someprovider", provider.LoopProviderType) 937 938 // Must create the requested block device prior to SetInstanceInfo. 939 volumeTag := s.addVolume(c, state.VolumeParams{Size: 1000, Pool: "loop-pool"}, "123") 940 c.Assert(volumeTag, gc.Equals, names.NewVolumeTag("123/0")) 941 942 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse) 943 volumeInfo := state.VolumeInfo{ 944 VolumeId: "storage-123", 945 Size: 1234, 946 } 947 volumes := map[names.VolumeTag]state.VolumeInfo{volumeTag: volumeInfo} 948 err = s.machine.SetInstanceInfo("umbrella/0", "fake_nonce", nil, nil, nil, volumes, nil) 949 c.Assert(err, jc.ErrorIsNil) 950 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue) 951 952 volume, err := s.State.Volume(volumeTag) 953 c.Assert(err, jc.ErrorIsNil) 954 info, err := volume.Info() 955 c.Assert(err, jc.ErrorIsNil) 956 volumeInfo.Pool = "loop-pool" // taken from params 957 c.Assert(info, gc.Equals, volumeInfo) 958 } 959 960 func (s *MachineSuite) TestMachineSetProvisionedWhenNotAlive(c *gc.C) { 961 testWhenDying(c, s.machine, notAliveErr, notAliveErr, func() error { 962 return s.machine.SetProvisioned("umbrella/0", "fake_nonce", nil) 963 }) 964 } 965 966 func (s *MachineSuite) TestMachineSetInstanceStatus(c *gc.C) { 967 // Machine needs to be provisioned first. 968 err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", nil) 969 c.Assert(err, jc.ErrorIsNil) 970 971 err = s.machine.SetInstanceStatus(status.StatusRunning, "alive", map[string]interface{}{}) 972 c.Assert(err, jc.ErrorIsNil) 973 974 // Reload machine and check result. 975 err = s.machine.Refresh() 976 c.Assert(err, jc.ErrorIsNil) 977 machineStatus, err := s.machine.InstanceStatus() 978 c.Assert(err, jc.ErrorIsNil) 979 c.Assert(machineStatus.Status, gc.DeepEquals, status.StatusRunning) 980 c.Assert(machineStatus.Message, gc.DeepEquals, "alive") 981 } 982 983 func (s *MachineSuite) TestMachineRefresh(c *gc.C) { 984 m0, err := s.State.AddMachine("quantal", state.JobHostUnits) 985 c.Assert(err, jc.ErrorIsNil) 986 oldTools, _ := m0.AgentTools() 987 m1, err := s.State.Machine(m0.Id()) 988 c.Assert(err, jc.ErrorIsNil) 989 err = m0.SetAgentVersion(version.MustParseBinary("0.0.3-quantal-amd64")) 990 c.Assert(err, jc.ErrorIsNil) 991 newTools, _ := m0.AgentTools() 992 993 m1Tools, _ := m1.AgentTools() 994 c.Assert(m1Tools, gc.DeepEquals, oldTools) 995 err = m1.Refresh() 996 c.Assert(err, jc.ErrorIsNil) 997 m1Tools, _ = m1.AgentTools() 998 c.Assert(*m1Tools, gc.Equals, *newTools) 999 1000 err = m0.EnsureDead() 1001 c.Assert(err, jc.ErrorIsNil) 1002 err = m0.Remove() 1003 c.Assert(err, jc.ErrorIsNil) 1004 err = m0.Refresh() 1005 c.Assert(err, jc.Satisfies, errors.IsNotFound) 1006 } 1007 1008 func (s *MachineSuite) TestRefreshWhenNotAlive(c *gc.C) { 1009 // Refresh should work regardless of liveness status. 1010 testWhenDying(c, s.machine, noErr, noErr, func() error { 1011 return s.machine.Refresh() 1012 }) 1013 } 1014 1015 func (s *MachineSuite) TestMachinePrincipalUnits(c *gc.C) { 1016 // Check that Machine.Units and st.UnitsFor work correctly. 1017 1018 // Make three machines, three services and three units for each service; 1019 // variously assign units to machines and check that Machine.Units 1020 // tells us the right thing. 1021 1022 m1 := s.machine 1023 m2, err := s.State.AddMachine("quantal", state.JobHostUnits) 1024 c.Assert(err, jc.ErrorIsNil) 1025 m3, err := s.State.AddMachine("quantal", state.JobHostUnits) 1026 c.Assert(err, jc.ErrorIsNil) 1027 1028 dummy := s.AddTestingCharm(c, "dummy") 1029 logging := s.AddTestingCharm(c, "logging") 1030 s0 := s.AddTestingService(c, "s0", dummy) 1031 s1 := s.AddTestingService(c, "s1", dummy) 1032 s2 := s.AddTestingService(c, "s2", dummy) 1033 s3 := s.AddTestingService(c, "s3", logging) 1034 1035 units := make([][]*state.Unit, 4) 1036 for i, svc := range []*state.Service{s0, s1, s2} { 1037 units[i] = make([]*state.Unit, 3) 1038 for j := range units[i] { 1039 units[i][j], err = svc.AddUnit() 1040 c.Assert(err, jc.ErrorIsNil) 1041 } 1042 } 1043 // Add the logging units subordinate to the s2 units. 1044 eps, err := s.State.InferEndpoints("s2", "s3") 1045 c.Assert(err, jc.ErrorIsNil) 1046 rel, err := s.State.AddRelation(eps...) 1047 c.Assert(err, jc.ErrorIsNil) 1048 for _, u := range units[2] { 1049 ru, err := rel.Unit(u) 1050 c.Assert(err, jc.ErrorIsNil) 1051 err = ru.EnterScope(nil) 1052 c.Assert(err, jc.ErrorIsNil) 1053 } 1054 units[3], err = s3.AllUnits() 1055 c.Assert(err, jc.ErrorIsNil) 1056 c.Assert(sortedUnitNames(units[3]), jc.DeepEquals, []string{"s3/0", "s3/1", "s3/2"}) 1057 1058 assignments := []struct { 1059 machine *state.Machine 1060 units []*state.Unit 1061 subordinates []*state.Unit 1062 }{ 1063 {m1, []*state.Unit{units[0][0]}, nil}, 1064 {m2, []*state.Unit{units[0][1], units[1][0], units[1][1], units[2][0]}, []*state.Unit{units[3][0]}}, 1065 {m3, []*state.Unit{units[2][2]}, []*state.Unit{units[3][2]}}, 1066 } 1067 1068 for _, a := range assignments { 1069 for _, u := range a.units { 1070 err := u.AssignToMachine(a.machine) 1071 c.Assert(err, jc.ErrorIsNil) 1072 } 1073 } 1074 1075 for i, a := range assignments { 1076 c.Logf("test %d", i) 1077 expect := sortedUnitNames(append(a.units, a.subordinates...)) 1078 1079 // The units can be retrieved from the machine model. 1080 got, err := a.machine.Units() 1081 c.Assert(err, jc.ErrorIsNil) 1082 c.Assert(sortedUnitNames(got), jc.DeepEquals, expect) 1083 1084 // The units can be retrieved from the machine id. 1085 got, err = s.State.UnitsFor(a.machine.Id()) 1086 c.Assert(err, jc.ErrorIsNil) 1087 c.Assert(sortedUnitNames(got), jc.DeepEquals, expect) 1088 } 1089 } 1090 1091 func sortedUnitNames(units []*state.Unit) []string { 1092 names := make([]string, len(units)) 1093 for i, u := range units { 1094 names[i] = u.Name() 1095 } 1096 sort.Strings(names) 1097 return names 1098 } 1099 1100 func (s *MachineSuite) assertMachineDirtyAfterAddingUnit(c *gc.C) (*state.Machine, *state.Service, *state.Unit) { 1101 m, err := s.State.AddMachine("quantal", state.JobHostUnits) 1102 c.Assert(err, jc.ErrorIsNil) 1103 c.Assert(m.Clean(), jc.IsTrue) 1104 1105 svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 1106 unit, err := svc.AddUnit() 1107 c.Assert(err, jc.ErrorIsNil) 1108 err = unit.AssignToMachine(m) 1109 c.Assert(err, jc.ErrorIsNil) 1110 c.Assert(m.Clean(), jc.IsFalse) 1111 return m, svc, unit 1112 } 1113 1114 func (s *MachineSuite) TestMachineDirtyAfterAddingUnit(c *gc.C) { 1115 s.assertMachineDirtyAfterAddingUnit(c) 1116 } 1117 1118 func (s *MachineSuite) TestMachineDirtyAfterUnassigningUnit(c *gc.C) { 1119 m, _, unit := s.assertMachineDirtyAfterAddingUnit(c) 1120 err := unit.UnassignFromMachine() 1121 c.Assert(err, jc.ErrorIsNil) 1122 c.Assert(m.Clean(), jc.IsFalse) 1123 } 1124 1125 func (s *MachineSuite) TestMachineDirtyAfterRemovingUnit(c *gc.C) { 1126 m, svc, unit := s.assertMachineDirtyAfterAddingUnit(c) 1127 err := unit.EnsureDead() 1128 c.Assert(err, jc.ErrorIsNil) 1129 err = unit.Remove() 1130 c.Assert(err, jc.ErrorIsNil) 1131 err = svc.Destroy() 1132 c.Assert(err, jc.ErrorIsNil) 1133 c.Assert(m.Clean(), jc.IsFalse) 1134 } 1135 1136 func (s *MachineSuite) TestWatchMachine(c *gc.C) { 1137 w := s.machine.Watch() 1138 defer testing.AssertStop(c, w) 1139 1140 // Initial event. 1141 wc := testing.NewNotifyWatcherC(c, s.State, w) 1142 wc.AssertOneChange() 1143 1144 // Make one change (to a separate instance), check one event. 1145 machine, err := s.State.Machine(s.machine.Id()) 1146 c.Assert(err, jc.ErrorIsNil) 1147 err = machine.SetProvisioned("m-foo", "fake_nonce", nil) 1148 c.Assert(err, jc.ErrorIsNil) 1149 wc.AssertOneChange() 1150 1151 // Make two changes, check one event. 1152 err = machine.SetAgentVersion(version.MustParseBinary("0.0.3-quantal-amd64")) 1153 c.Assert(err, jc.ErrorIsNil) 1154 err = machine.Destroy() 1155 c.Assert(err, jc.ErrorIsNil) 1156 wc.AssertOneChange() 1157 1158 // Stop, check closed. 1159 testing.AssertStop(c, w) 1160 wc.AssertClosed() 1161 1162 // Remove machine, start new watch, check single event. 1163 err = machine.EnsureDead() 1164 c.Assert(err, jc.ErrorIsNil) 1165 err = machine.Remove() 1166 c.Assert(err, jc.ErrorIsNil) 1167 w = s.machine.Watch() 1168 defer testing.AssertStop(c, w) 1169 testing.NewNotifyWatcherC(c, s.State, w).AssertOneChange() 1170 } 1171 1172 func (s *MachineSuite) TestWatchDiesOnStateClose(c *gc.C) { 1173 // This test is testing logic in watcher.entityWatcher, which 1174 // is also used by: 1175 // Machine.WatchHardwareCharacteristics 1176 // Service.Watch 1177 // Unit.Watch 1178 // State.WatchForModelConfigChanges 1179 // Unit.WatchConfigSettings 1180 testWatcherDiesWhenStateCloses(c, s.modelTag, func(c *gc.C, st *state.State) waiter { 1181 m, err := st.Machine(s.machine.Id()) 1182 c.Assert(err, jc.ErrorIsNil) 1183 w := m.Watch() 1184 <-w.Changes() 1185 return w 1186 }) 1187 } 1188 1189 func (s *MachineSuite) TestWatchPrincipalUnits(c *gc.C) { 1190 // TODO(mjs) - MODELUUID - test with multiple models with 1191 // identically named units and ensure there's no leakage. 1192 1193 // Start a watch on an empty machine; check no units reported. 1194 w := s.machine.WatchPrincipalUnits() 1195 defer testing.AssertStop(c, w) 1196 wc := testing.NewStringsWatcherC(c, s.State, w) 1197 wc.AssertChange() 1198 wc.AssertNoChange() 1199 1200 // Change machine, and create a unit independently; no change. 1201 err := s.machine.SetProvisioned("cheese", "fake_nonce", nil) 1202 c.Assert(err, jc.ErrorIsNil) 1203 wc.AssertNoChange() 1204 mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) 1205 mysql0, err := mysql.AddUnit() 1206 c.Assert(err, jc.ErrorIsNil) 1207 wc.AssertNoChange() 1208 1209 // Assign that unit (to a separate machine instance); change detected. 1210 machine, err := s.State.Machine(s.machine.Id()) 1211 c.Assert(err, jc.ErrorIsNil) 1212 err = mysql0.AssignToMachine(machine) 1213 c.Assert(err, jc.ErrorIsNil) 1214 wc.AssertChange("mysql/0") 1215 wc.AssertNoChange() 1216 1217 // Change the unit; no change. 1218 err = mysql0.SetAgentStatus(status.StatusIdle, "", nil) 1219 c.Assert(err, jc.ErrorIsNil) 1220 wc.AssertNoChange() 1221 1222 // Assign another unit and make the first Dying; check both changes detected. 1223 mysql1, err := mysql.AddUnit() 1224 c.Assert(err, jc.ErrorIsNil) 1225 err = mysql1.AssignToMachine(machine) 1226 c.Assert(err, jc.ErrorIsNil) 1227 err = mysql0.Destroy() 1228 c.Assert(err, jc.ErrorIsNil) 1229 wc.AssertChange("mysql/0", "mysql/1") 1230 wc.AssertNoChange() 1231 1232 // Add a subordinate to the Alive unit; no change. 1233 s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging")) 1234 eps, err := s.State.InferEndpoints("mysql", "logging") 1235 c.Assert(err, jc.ErrorIsNil) 1236 rel, err := s.State.AddRelation(eps...) 1237 c.Assert(err, jc.ErrorIsNil) 1238 mysqlru1, err := rel.Unit(mysql1) 1239 c.Assert(err, jc.ErrorIsNil) 1240 err = mysqlru1.EnterScope(nil) 1241 c.Assert(err, jc.ErrorIsNil) 1242 logging0, err := s.State.Unit("logging/0") 1243 c.Assert(err, jc.ErrorIsNil) 1244 wc.AssertNoChange() 1245 1246 // Change the subordinate; no change. 1247 err = logging0.SetAgentStatus(status.StatusIdle, "", nil) 1248 c.Assert(err, jc.ErrorIsNil) 1249 wc.AssertNoChange() 1250 1251 // Make the Dying unit Dead; change detected. 1252 err = mysql0.EnsureDead() 1253 c.Assert(err, jc.ErrorIsNil) 1254 wc.AssertChange("mysql/0") 1255 wc.AssertNoChange() 1256 1257 // Stop watcher; check Changes chan closed. 1258 testing.AssertStop(c, w) 1259 wc.AssertClosed() 1260 1261 // Start a fresh watcher; check both principals reported. 1262 w = s.machine.WatchPrincipalUnits() 1263 defer testing.AssertStop(c, w) 1264 wc = testing.NewStringsWatcherC(c, s.State, w) 1265 wc.AssertChange("mysql/0", "mysql/1") 1266 wc.AssertNoChange() 1267 1268 // Remove the Dead unit; no change. 1269 err = mysql0.Remove() 1270 c.Assert(err, jc.ErrorIsNil) 1271 wc.AssertNoChange() 1272 1273 // Destroy the subordinate; no change. 1274 err = logging0.Destroy() 1275 c.Assert(err, jc.ErrorIsNil) 1276 wc.AssertNoChange() 1277 1278 // Unassign the unit; check change. 1279 err = mysql1.UnassignFromMachine() 1280 c.Assert(err, jc.ErrorIsNil) 1281 wc.AssertChange("mysql/1") 1282 wc.AssertNoChange() 1283 } 1284 1285 func (s *MachineSuite) TestWatchPrincipalUnitsDiesOnStateClose(c *gc.C) { 1286 // This test is testing logic in watcher.unitsWatcher, which 1287 // is also used by Unit.WatchSubordinateUnits. 1288 testWatcherDiesWhenStateCloses(c, s.modelTag, func(c *gc.C, st *state.State) waiter { 1289 m, err := st.Machine(s.machine.Id()) 1290 c.Assert(err, jc.ErrorIsNil) 1291 w := m.WatchPrincipalUnits() 1292 <-w.Changes() 1293 return w 1294 }) 1295 } 1296 1297 func (s *MachineSuite) TestWatchUnits(c *gc.C) { 1298 // Start a watch on an empty machine; check no units reported. 1299 w := s.machine.WatchUnits() 1300 defer testing.AssertStop(c, w) 1301 wc := testing.NewStringsWatcherC(c, s.State, w) 1302 wc.AssertChange() 1303 wc.AssertNoChange() 1304 1305 // Change machine; no change. 1306 err := s.machine.SetProvisioned("cheese", "fake_nonce", nil) 1307 c.Assert(err, jc.ErrorIsNil) 1308 wc.AssertNoChange() 1309 1310 // Assign a unit (to a separate instance); change detected. 1311 mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) 1312 mysql0, err := mysql.AddUnit() 1313 c.Assert(err, jc.ErrorIsNil) 1314 machine, err := s.State.Machine(s.machine.Id()) 1315 c.Assert(err, jc.ErrorIsNil) 1316 err = mysql0.AssignToMachine(machine) 1317 c.Assert(err, jc.ErrorIsNil) 1318 wc.AssertChange("mysql/0") 1319 wc.AssertNoChange() 1320 1321 // Change the unit; no change. 1322 err = mysql0.SetAgentStatus(status.StatusIdle, "", nil) 1323 c.Assert(err, jc.ErrorIsNil) 1324 wc.AssertNoChange() 1325 1326 // Assign another unit and make the first Dying; check both changes detected. 1327 mysql1, err := mysql.AddUnit() 1328 c.Assert(err, jc.ErrorIsNil) 1329 err = mysql1.AssignToMachine(machine) 1330 c.Assert(err, jc.ErrorIsNil) 1331 err = mysql0.Destroy() 1332 c.Assert(err, jc.ErrorIsNil) 1333 wc.AssertChange("mysql/0", "mysql/1") 1334 wc.AssertNoChange() 1335 1336 // Add a subordinate to the Alive unit; change detected. 1337 s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging")) 1338 eps, err := s.State.InferEndpoints("mysql", "logging") 1339 c.Assert(err, jc.ErrorIsNil) 1340 rel, err := s.State.AddRelation(eps...) 1341 c.Assert(err, jc.ErrorIsNil) 1342 mysqlru1, err := rel.Unit(mysql1) 1343 c.Assert(err, jc.ErrorIsNil) 1344 err = mysqlru1.EnterScope(nil) 1345 c.Assert(err, jc.ErrorIsNil) 1346 logging0, err := s.State.Unit("logging/0") 1347 c.Assert(err, jc.ErrorIsNil) 1348 wc.AssertChange("logging/0") 1349 wc.AssertNoChange() 1350 1351 // Change the subordinate; no change. 1352 err = logging0.SetAgentStatus(status.StatusIdle, "", nil) 1353 c.Assert(err, jc.ErrorIsNil) 1354 wc.AssertNoChange() 1355 1356 // Make the Dying unit Dead; change detected. 1357 err = mysql0.EnsureDead() 1358 c.Assert(err, jc.ErrorIsNil) 1359 wc.AssertChange("mysql/0") 1360 wc.AssertNoChange() 1361 1362 // Stop watcher; check Changes chan closed. 1363 testing.AssertStop(c, w) 1364 wc.AssertClosed() 1365 1366 // Start a fresh watcher; check all units reported. 1367 w = s.machine.WatchUnits() 1368 defer testing.AssertStop(c, w) 1369 wc = testing.NewStringsWatcherC(c, s.State, w) 1370 wc.AssertChange("mysql/0", "mysql/1", "logging/0") 1371 wc.AssertNoChange() 1372 1373 // Remove the Dead unit; no change. 1374 err = mysql0.Remove() 1375 c.Assert(err, jc.ErrorIsNil) 1376 wc.AssertNoChange() 1377 1378 // Destroy the subordinate; change detected. 1379 err = logging0.Destroy() 1380 c.Assert(err, jc.ErrorIsNil) 1381 wc.AssertChange("logging/0") 1382 wc.AssertNoChange() 1383 1384 // Unassign the principal; check subordinate departure also reported. 1385 err = mysql1.UnassignFromMachine() 1386 c.Assert(err, jc.ErrorIsNil) 1387 wc.AssertChange("mysql/1", "logging/0") 1388 wc.AssertNoChange() 1389 } 1390 1391 func (s *MachineSuite) TestWatchUnitsDiesOnStateClose(c *gc.C) { 1392 testWatcherDiesWhenStateCloses(c, s.modelTag, func(c *gc.C, st *state.State) waiter { 1393 m, err := st.Machine(s.machine.Id()) 1394 c.Assert(err, jc.ErrorIsNil) 1395 w := m.WatchUnits() 1396 <-w.Changes() 1397 return w 1398 }) 1399 } 1400 1401 func (s *MachineSuite) TestConstraintsFromModel(c *gc.C) { 1402 econs1 := constraints.MustParse("mem=1G") 1403 econs2 := constraints.MustParse("mem=2G") 1404 1405 // A newly-created machine gets a copy of the model constraints. 1406 err := s.State.SetModelConstraints(econs1) 1407 c.Assert(err, jc.ErrorIsNil) 1408 machine1, err := s.State.AddMachine("quantal", state.JobHostUnits) 1409 c.Assert(err, jc.ErrorIsNil) 1410 mcons1, err := machine1.Constraints() 1411 c.Assert(err, jc.ErrorIsNil) 1412 c.Assert(mcons1, gc.DeepEquals, econs1) 1413 1414 // Change model constraints and add a new machine. 1415 err = s.State.SetModelConstraints(econs2) 1416 c.Assert(err, jc.ErrorIsNil) 1417 machine2, err := s.State.AddMachine("quantal", state.JobHostUnits) 1418 c.Assert(err, jc.ErrorIsNil) 1419 mcons2, err := machine2.Constraints() 1420 c.Assert(err, jc.ErrorIsNil) 1421 c.Assert(mcons2, gc.DeepEquals, econs2) 1422 1423 // Check the original machine has its original constraints. 1424 mcons1, err = machine1.Constraints() 1425 c.Assert(err, jc.ErrorIsNil) 1426 c.Assert(mcons1, gc.DeepEquals, econs1) 1427 } 1428 1429 func (s *MachineSuite) TestSetConstraints(c *gc.C) { 1430 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1431 c.Assert(err, jc.ErrorIsNil) 1432 1433 // Constraints can be set... 1434 cons1 := constraints.MustParse("mem=1G") 1435 err = machine.SetConstraints(cons1) 1436 c.Assert(err, jc.ErrorIsNil) 1437 mcons, err := machine.Constraints() 1438 c.Assert(err, jc.ErrorIsNil) 1439 c.Assert(mcons, gc.DeepEquals, cons1) 1440 1441 // ...until the machine is provisioned, at which point they stick. 1442 err = machine.SetProvisioned("i-mstuck", "fake_nonce", nil) 1443 c.Assert(err, jc.ErrorIsNil) 1444 cons2 := constraints.MustParse("mem=2G") 1445 err = machine.SetConstraints(cons2) 1446 c.Assert(err, gc.ErrorMatches, "cannot set constraints: machine is already provisioned") 1447 1448 // Check the failed set had no effect. 1449 mcons, err = machine.Constraints() 1450 c.Assert(err, jc.ErrorIsNil) 1451 c.Assert(mcons, gc.DeepEquals, cons1) 1452 } 1453 1454 func (s *MachineSuite) TestSetAmbiguousConstraints(c *gc.C) { 1455 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1456 c.Assert(err, jc.ErrorIsNil) 1457 cons := constraints.MustParse("mem=4G instance-type=foo") 1458 err = machine.SetConstraints(cons) 1459 c.Assert(err, gc.ErrorMatches, `cannot set constraints: ambiguous constraints: "instance-type" overlaps with "mem"`) 1460 } 1461 1462 func (s *MachineSuite) TestSetUnsupportedConstraintsWarning(c *gc.C) { 1463 defer loggo.ResetWriters() 1464 logger := loggo.GetLogger("test") 1465 logger.SetLogLevel(loggo.DEBUG) 1466 var tw loggo.TestWriter 1467 c.Assert(loggo.RegisterWriter("constraints-tester", &tw, loggo.DEBUG), gc.IsNil) 1468 1469 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1470 c.Assert(err, jc.ErrorIsNil) 1471 cons := constraints.MustParse("mem=4G cpu-power=10") 1472 err = machine.SetConstraints(cons) 1473 c.Assert(err, jc.ErrorIsNil) 1474 c.Assert(tw.Log(), jc.LogMatches, jc.SimpleMessages{{ 1475 loggo.WARNING, 1476 `setting constraints on machine "2": unsupported constraints: cpu-power`}, 1477 }) 1478 mcons, err := machine.Constraints() 1479 c.Assert(err, jc.ErrorIsNil) 1480 c.Assert(mcons, gc.DeepEquals, cons) 1481 } 1482 1483 func (s *MachineSuite) TestConstraintsLifecycle(c *gc.C) { 1484 cons := constraints.MustParse("mem=1G") 1485 cannotSet := `cannot set constraints: not found or not alive` 1486 testWhenDying(c, s.machine, cannotSet, cannotSet, func() error { 1487 err := s.machine.SetConstraints(cons) 1488 mcons, err1 := s.machine.Constraints() 1489 c.Assert(err1, gc.IsNil) 1490 c.Assert(&mcons, jc.Satisfies, constraints.IsEmpty) 1491 return err 1492 }) 1493 1494 err := s.machine.Remove() 1495 c.Assert(err, jc.ErrorIsNil) 1496 err = s.machine.SetConstraints(cons) 1497 c.Assert(err, gc.ErrorMatches, cannotSet) 1498 _, err = s.machine.Constraints() 1499 c.Assert(err, gc.ErrorMatches, `constraints not found`) 1500 } 1501 1502 func (s *MachineSuite) TestSetProviderAddresses(c *gc.C) { 1503 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1504 c.Assert(err, jc.ErrorIsNil) 1505 c.Assert(machine.Addresses(), gc.HasLen, 0) 1506 1507 addresses := network.NewAddresses("127.0.0.1", "8.8.8.8") 1508 err = machine.SetProviderAddresses(addresses...) 1509 c.Assert(err, jc.ErrorIsNil) 1510 err = machine.Refresh() 1511 c.Assert(err, jc.ErrorIsNil) 1512 1513 expectedAddresses := network.NewAddresses("8.8.8.8", "127.0.0.1") 1514 c.Assert(machine.Addresses(), jc.DeepEquals, expectedAddresses) 1515 } 1516 1517 func (s *MachineSuite) TestSetProviderAddressesWithContainers(c *gc.C) { 1518 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1519 c.Assert(err, jc.ErrorIsNil) 1520 c.Assert(machine.Addresses(), gc.HasLen, 0) 1521 1522 // Create subnet and pick two addresses. 1523 subnetInfo := state.SubnetInfo{ 1524 CIDR: "192.168.1.0/24", 1525 AllocatableIPLow: "192.168.1.0", 1526 AllocatableIPHigh: "192.168.1.10", 1527 } 1528 subnet, err := s.State.AddSubnet(subnetInfo) 1529 c.Assert(err, jc.ErrorIsNil) 1530 1531 ipAddr1, err := subnet.PickNewAddress() 1532 c.Assert(err, jc.ErrorIsNil) 1533 err = ipAddr1.SetState(state.AddressStateAllocated) 1534 c.Assert(err, jc.ErrorIsNil) 1535 ipAddr2, err := subnet.PickNewAddress() 1536 c.Assert(err, jc.ErrorIsNil) 1537 err = ipAddr2.SetState(state.AddressStateAllocated) 1538 c.Assert(err, jc.ErrorIsNil) 1539 1540 // When setting all addresses the subnet addresses have to be 1541 // filtered out. 1542 addresses := network.NewAddresses( 1543 "127.0.0.1", 1544 "8.8.8.8", 1545 ipAddr1.Value(), 1546 ipAddr2.Value(), 1547 ) 1548 err = machine.SetProviderAddresses(addresses...) 1549 c.Assert(err, jc.ErrorIsNil) 1550 err = machine.Refresh() 1551 c.Assert(err, jc.ErrorIsNil) 1552 1553 expectedAddresses := network.NewAddresses("8.8.8.8", "127.0.0.1") 1554 c.Assert(machine.Addresses(), jc.DeepEquals, expectedAddresses) 1555 } 1556 1557 func (s *MachineSuite) TestSetProviderAddressesOnContainer(c *gc.C) { 1558 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1559 c.Assert(err, jc.ErrorIsNil) 1560 c.Assert(machine.Addresses(), gc.HasLen, 0) 1561 1562 // Create subnet and pick two addresses. 1563 subnetInfo := state.SubnetInfo{ 1564 CIDR: "192.168.1.0/24", 1565 AllocatableIPLow: "192.168.1.0", 1566 AllocatableIPHigh: "192.168.1.10", 1567 } 1568 subnet, err := s.State.AddSubnet(subnetInfo) 1569 c.Assert(err, jc.ErrorIsNil) 1570 1571 ipAddr, err := subnet.PickNewAddress() 1572 c.Assert(err, jc.ErrorIsNil) 1573 err = ipAddr.SetState(state.AddressStateAllocated) 1574 c.Assert(err, jc.ErrorIsNil) 1575 1576 // Create an LXC container inside the machine. 1577 template := state.MachineTemplate{ 1578 Series: "quantal", 1579 Jobs: []state.MachineJob{state.JobHostUnits}, 1580 } 1581 container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXC) 1582 c.Assert(err, jc.ErrorIsNil) 1583 1584 // When setting all addresses the subnet address has to accepted. 1585 addresses := network.NewAddresses("127.0.0.1", ipAddr.Value()) 1586 err = container.SetProviderAddresses(addresses...) 1587 c.Assert(err, jc.ErrorIsNil) 1588 err = container.Refresh() 1589 c.Assert(err, jc.ErrorIsNil) 1590 1591 expectedAddresses := network.NewAddresses(ipAddr.Value(), "127.0.0.1") 1592 c.Assert(container.Addresses(), jc.DeepEquals, expectedAddresses) 1593 } 1594 1595 func (s *MachineSuite) TestSetMachineAddresses(c *gc.C) { 1596 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1597 c.Assert(err, jc.ErrorIsNil) 1598 c.Assert(machine.Addresses(), gc.HasLen, 0) 1599 1600 addresses := network.NewAddresses("127.0.0.1", "8.8.8.8") 1601 err = machine.SetMachineAddresses(addresses...) 1602 c.Assert(err, jc.ErrorIsNil) 1603 err = machine.Refresh() 1604 c.Assert(err, jc.ErrorIsNil) 1605 1606 expectedAddresses := network.NewAddresses("8.8.8.8", "127.0.0.1") 1607 c.Assert(machine.MachineAddresses(), jc.DeepEquals, expectedAddresses) 1608 } 1609 1610 func (s *MachineSuite) TestSetEmptyMachineAddresses(c *gc.C) { 1611 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1612 c.Assert(err, jc.ErrorIsNil) 1613 c.Assert(machine.Addresses(), gc.HasLen, 0) 1614 1615 // Add some machine addresses initially to make sure they're removed. 1616 addresses := network.NewAddresses("127.0.0.1", "8.8.8.8") 1617 err = machine.SetMachineAddresses(addresses...) 1618 c.Assert(err, jc.ErrorIsNil) 1619 err = machine.Refresh() 1620 c.Assert(err, jc.ErrorIsNil) 1621 c.Assert(machine.MachineAddresses(), gc.HasLen, 2) 1622 1623 // Make call with empty address list. 1624 err = machine.SetMachineAddresses() 1625 c.Assert(err, jc.ErrorIsNil) 1626 err = machine.Refresh() 1627 c.Assert(err, jc.ErrorIsNil) 1628 1629 c.Assert(machine.MachineAddresses(), gc.HasLen, 0) 1630 } 1631 1632 func (s *MachineSuite) TestMergedAddresses(c *gc.C) { 1633 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1634 c.Assert(err, jc.ErrorIsNil) 1635 c.Assert(machine.Addresses(), gc.HasLen, 0) 1636 1637 providerAddresses := network.NewAddresses( 1638 "127.0.0.2", 1639 "8.8.8.8", 1640 "fc00::1", 1641 "::1", 1642 "", 1643 "2001:db8::1", 1644 "127.0.0.2", 1645 "example.org", 1646 ) 1647 err = machine.SetProviderAddresses(providerAddresses...) 1648 c.Assert(err, jc.ErrorIsNil) 1649 1650 machineAddresses := network.NewAddresses( 1651 "127.0.0.1", 1652 "localhost", 1653 "2001:db8::1", 1654 "192.168.0.1", 1655 "fe80::1", 1656 "::1", 1657 "fd00::1", 1658 ) 1659 err = machine.SetMachineAddresses(machineAddresses...) 1660 c.Assert(err, jc.ErrorIsNil) 1661 err = machine.Refresh() 1662 c.Assert(err, jc.ErrorIsNil) 1663 1664 // Before setting the addresses coming from either the provider or 1665 // the machine itself, they are sorted to prefer public IPs on 1666 // top, then hostnames, cloud-local, machine-local, link-local. 1667 // Duplicates are removed, then when calling Addresses() both 1668 // sources are merged while preservig the provider addresses 1669 // order. 1670 c.Assert(machine.Addresses(), jc.DeepEquals, network.NewAddresses( 1671 "8.8.8.8", 1672 "2001:db8::1", 1673 "example.org", 1674 "fc00::1", 1675 "127.0.0.2", 1676 "::1", 1677 "localhost", 1678 "192.168.0.1", 1679 "fd00::1", 1680 "127.0.0.1", 1681 "fe80::1", 1682 )) 1683 1684 // Now simulate prefer-ipv6: true 1685 c.Assert( 1686 s.State.UpdateModelConfig( 1687 map[string]interface{}{"prefer-ipv6": true}, 1688 nil, nil, 1689 ), 1690 gc.IsNil, 1691 ) 1692 1693 err = machine.SetProviderAddresses(providerAddresses...) 1694 c.Assert(err, jc.ErrorIsNil) 1695 err = machine.SetMachineAddresses(machineAddresses...) 1696 c.Assert(err, jc.ErrorIsNil) 1697 err = machine.Refresh() 1698 c.Assert(err, jc.ErrorIsNil) 1699 c.Assert(machine.Addresses(), jc.DeepEquals, network.NewAddresses( 1700 "2001:db8::1", 1701 "8.8.8.8", 1702 "example.org", 1703 "fc00::1", 1704 "::1", 1705 "127.0.0.2", 1706 "localhost", 1707 "fd00::1", 1708 "192.168.0.1", 1709 "127.0.0.1", 1710 "fe80::1", 1711 )) 1712 } 1713 1714 func (s *MachineSuite) TestSetProviderAddressesConcurrentChangeDifferent(c *gc.C) { 1715 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1716 c.Assert(err, jc.ErrorIsNil) 1717 c.Assert(machine.Addresses(), gc.HasLen, 0) 1718 1719 addr0 := network.NewAddress("127.0.0.1") 1720 addr1 := network.NewAddress("8.8.8.8") 1721 1722 defer state.SetBeforeHooks(c, s.State, func() { 1723 machine, err := s.State.Machine(machine.Id()) 1724 c.Assert(err, jc.ErrorIsNil) 1725 err = machine.SetProviderAddresses(addr1, addr0) 1726 c.Assert(err, jc.ErrorIsNil) 1727 }).Check() 1728 1729 err = machine.SetProviderAddresses(addr0, addr1) 1730 c.Assert(err, jc.ErrorIsNil) 1731 c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0, addr1}) 1732 } 1733 1734 func (s *MachineSuite) TestSetProviderAddressesConcurrentChangeEqual(c *gc.C) { 1735 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1736 c.Assert(err, jc.ErrorIsNil) 1737 c.Assert(machine.Addresses(), gc.HasLen, 0) 1738 machineDocID := state.DocID(s.State, machine.Id()) 1739 revno0, err := state.TxnRevno(s.State, "machines", machineDocID) 1740 c.Assert(err, jc.ErrorIsNil) 1741 1742 addr0 := network.NewAddress("127.0.0.1") 1743 addr1 := network.NewAddress("8.8.8.8") 1744 1745 var revno1 int64 1746 defer state.SetBeforeHooks(c, s.State, func() { 1747 machine, err := s.State.Machine(machine.Id()) 1748 c.Assert(err, jc.ErrorIsNil) 1749 err = machine.SetProviderAddresses(addr0, addr1) 1750 c.Assert(err, jc.ErrorIsNil) 1751 revno1, err = state.TxnRevno(s.State, "machines", machineDocID) 1752 c.Assert(err, jc.ErrorIsNil) 1753 c.Assert(revno1, jc.GreaterThan, revno0) 1754 }).Check() 1755 1756 err = machine.SetProviderAddresses(addr0, addr1) 1757 c.Assert(err, jc.ErrorIsNil) 1758 1759 // Doc will be updated; concurrent changes are explicitly ignored. 1760 revno2, err := state.TxnRevno(s.State, "machines", machineDocID) 1761 c.Assert(err, jc.ErrorIsNil) 1762 c.Assert(revno2, jc.GreaterThan, revno1) 1763 c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0, addr1}) 1764 } 1765 1766 func (s *MachineSuite) TestSetProviderAddressesInvalidateMemory(c *gc.C) { 1767 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1768 c.Assert(err, jc.ErrorIsNil) 1769 c.Assert(machine.Addresses(), gc.HasLen, 0) 1770 machineDocID := state.DocID(s.State, machine.Id()) 1771 1772 addr0 := network.NewAddress("127.0.0.1") 1773 addr1 := network.NewAddress("8.8.8.8") 1774 1775 // Set addresses to [addr0] initially. We'll get a separate Machine 1776 // object to update addresses, to ensure that the in-memory cache of 1777 // addresses does not prevent the initial Machine from updating 1778 // addresses back to the original value. 1779 err = machine.SetProviderAddresses(addr0) 1780 c.Assert(err, jc.ErrorIsNil) 1781 revno0, err := state.TxnRevno(s.State, "machines", machineDocID) 1782 c.Assert(err, jc.ErrorIsNil) 1783 1784 machine2, err := s.State.Machine(machine.Id()) 1785 c.Assert(err, jc.ErrorIsNil) 1786 err = machine2.SetProviderAddresses(addr1) 1787 c.Assert(err, jc.ErrorIsNil) 1788 revno1, err := state.TxnRevno(s.State, "machines", machineDocID) 1789 c.Assert(err, jc.ErrorIsNil) 1790 c.Assert(revno1, jc.GreaterThan, revno0) 1791 c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0}) 1792 c.Assert(machine2.Addresses(), jc.SameContents, []network.Address{addr1}) 1793 1794 err = machine.SetProviderAddresses(addr0) 1795 c.Assert(err, jc.ErrorIsNil) 1796 revno2, err := state.TxnRevno(s.State, "machines", machineDocID) 1797 c.Assert(err, jc.ErrorIsNil) 1798 c.Assert(revno2, jc.GreaterThan, revno1) 1799 c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0}) 1800 } 1801 1802 func (s *MachineSuite) TestPublicAddressSetOnNewMachine(c *gc.C) { 1803 m, err := s.State.AddOneMachine(state.MachineTemplate{ 1804 Series: "quantal", 1805 Jobs: []state.MachineJob{state.JobHostUnits}, 1806 Addresses: network.NewAddresses("10.0.0.1", "8.8.8.8"), 1807 }) 1808 c.Assert(err, jc.ErrorIsNil) 1809 addr, err := m.PublicAddress() 1810 c.Assert(err, jc.ErrorIsNil) 1811 c.Assert(addr, jc.DeepEquals, network.NewAddress("8.8.8.8")) 1812 } 1813 1814 func (s *MachineSuite) TestPrivateAddressSetOnNewMachine(c *gc.C) { 1815 m, err := s.State.AddOneMachine(state.MachineTemplate{ 1816 Series: "quantal", 1817 Jobs: []state.MachineJob{state.JobHostUnits}, 1818 Addresses: network.NewAddresses("10.0.0.1", "8.8.8.8"), 1819 }) 1820 c.Assert(err, jc.ErrorIsNil) 1821 addr, err := m.PrivateAddress() 1822 c.Assert(err, jc.ErrorIsNil) 1823 c.Assert(addr, jc.DeepEquals, network.NewAddress("10.0.0.1")) 1824 } 1825 1826 func (s *MachineSuite) TestPublicAddressEmptyAddresses(c *gc.C) { 1827 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1828 c.Assert(err, jc.ErrorIsNil) 1829 c.Assert(machine.Addresses(), gc.HasLen, 0) 1830 1831 addr, err := machine.PublicAddress() 1832 c.Assert(err, jc.Satisfies, network.IsNoAddress) 1833 c.Assert(addr.Value, gc.Equals, "") 1834 } 1835 1836 func (s *MachineSuite) TestPrivateAddressEmptyAddresses(c *gc.C) { 1837 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1838 c.Assert(err, jc.ErrorIsNil) 1839 c.Assert(machine.Addresses(), gc.HasLen, 0) 1840 1841 addr, err := machine.PrivateAddress() 1842 c.Assert(err, jc.Satisfies, network.IsNoAddress) 1843 c.Assert(addr.Value, gc.Equals, "") 1844 } 1845 1846 func (s *MachineSuite) TestPublicAddress(c *gc.C) { 1847 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1848 c.Assert(err, jc.ErrorIsNil) 1849 1850 err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8")) 1851 c.Assert(err, jc.ErrorIsNil) 1852 1853 addr, err := machine.PublicAddress() 1854 c.Assert(err, jc.ErrorIsNil) 1855 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 1856 } 1857 1858 func (s *MachineSuite) TestPrivateAddress(c *gc.C) { 1859 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1860 c.Assert(err, jc.ErrorIsNil) 1861 1862 err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1")) 1863 c.Assert(err, jc.ErrorIsNil) 1864 1865 addr, err := machine.PrivateAddress() 1866 c.Assert(err, jc.ErrorIsNil) 1867 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 1868 } 1869 1870 func (s *MachineSuite) TestPublicAddressBetterMatch(c *gc.C) { 1871 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1872 c.Assert(err, jc.ErrorIsNil) 1873 1874 err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1")) 1875 c.Assert(err, jc.ErrorIsNil) 1876 1877 addr, err := machine.PublicAddress() 1878 c.Assert(err, jc.ErrorIsNil) 1879 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 1880 1881 err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8")) 1882 c.Assert(err, jc.ErrorIsNil) 1883 1884 addr, err = machine.PublicAddress() 1885 c.Assert(err, jc.ErrorIsNil) 1886 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 1887 } 1888 1889 func (s *MachineSuite) TestPrivateAddressBetterMatch(c *gc.C) { 1890 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1891 c.Assert(err, jc.ErrorIsNil) 1892 1893 err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8")) 1894 c.Assert(err, jc.ErrorIsNil) 1895 1896 addr, err := machine.PrivateAddress() 1897 c.Assert(err, jc.ErrorIsNil) 1898 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 1899 1900 err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.1")) 1901 c.Assert(err, jc.ErrorIsNil) 1902 1903 addr, err = machine.PrivateAddress() 1904 c.Assert(err, jc.ErrorIsNil) 1905 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 1906 } 1907 1908 func (s *MachineSuite) TestPublicAddressChanges(c *gc.C) { 1909 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1910 c.Assert(err, jc.ErrorIsNil) 1911 1912 err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8")) 1913 c.Assert(err, jc.ErrorIsNil) 1914 1915 addr, err := machine.PublicAddress() 1916 c.Assert(err, jc.ErrorIsNil) 1917 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 1918 1919 err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4")) 1920 c.Assert(err, jc.ErrorIsNil) 1921 1922 addr, err = machine.PublicAddress() 1923 c.Assert(err, jc.ErrorIsNil) 1924 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 1925 } 1926 1927 func (s *MachineSuite) TestPrivateAddressChanges(c *gc.C) { 1928 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1929 c.Assert(err, jc.ErrorIsNil) 1930 1931 err = machine.SetMachineAddresses(network.NewAddress("10.0.0.2")) 1932 c.Assert(err, jc.ErrorIsNil) 1933 1934 addr, err := machine.PrivateAddress() 1935 c.Assert(err, jc.ErrorIsNil) 1936 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 1937 1938 err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1")) 1939 c.Assert(err, jc.ErrorIsNil) 1940 1941 addr, err = machine.PrivateAddress() 1942 c.Assert(err, jc.ErrorIsNil) 1943 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 1944 } 1945 1946 func (s *MachineSuite) TestAddressesDeadMachine(c *gc.C) { 1947 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1948 c.Assert(err, jc.ErrorIsNil) 1949 1950 err = machine.SetProviderAddresses(network.NewAddress("10.0.0.2"), network.NewAddress("8.8.4.4")) 1951 c.Assert(err, jc.ErrorIsNil) 1952 1953 addr, err := machine.PrivateAddress() 1954 c.Assert(err, jc.ErrorIsNil) 1955 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 1956 1957 addr, err = machine.PublicAddress() 1958 c.Assert(err, jc.ErrorIsNil) 1959 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 1960 1961 err = machine.EnsureDead() 1962 c.Assert(err, jc.ErrorIsNil) 1963 1964 // A dead machine should still report the last known addresses. 1965 addr, err = machine.PrivateAddress() 1966 c.Assert(err, jc.ErrorIsNil) 1967 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 1968 1969 addr, err = machine.PublicAddress() 1970 c.Assert(err, jc.ErrorIsNil) 1971 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 1972 } 1973 1974 func (s *MachineSuite) TestStablePrivateAddress(c *gc.C) { 1975 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1976 c.Assert(err, jc.ErrorIsNil) 1977 1978 err = machine.SetMachineAddresses(network.NewAddress("10.0.0.2")) 1979 c.Assert(err, jc.ErrorIsNil) 1980 1981 addr, err := machine.PrivateAddress() 1982 c.Assert(err, jc.ErrorIsNil) 1983 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 1984 1985 // Now add an address that would previously have sorted before the 1986 // default. 1987 err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1"), network.NewAddress("10.0.0.2")) 1988 c.Assert(err, jc.ErrorIsNil) 1989 1990 // Assert the address is unchanged. 1991 addr, err = machine.PrivateAddress() 1992 c.Assert(err, jc.ErrorIsNil) 1993 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 1994 } 1995 1996 func (s *MachineSuite) TestStablePublicAddress(c *gc.C) { 1997 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 1998 c.Assert(err, jc.ErrorIsNil) 1999 2000 err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8")) 2001 c.Assert(err, jc.ErrorIsNil) 2002 2003 addr, err := machine.PublicAddress() 2004 c.Assert(err, jc.ErrorIsNil) 2005 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2006 2007 // Now add an address that would previously have sorted before the 2008 // default. 2009 err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4"), network.NewAddress("8.8.8.8")) 2010 c.Assert(err, jc.ErrorIsNil) 2011 2012 // Assert the address is unchanged. 2013 addr, err = machine.PublicAddress() 2014 c.Assert(err, jc.ErrorIsNil) 2015 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2016 } 2017 2018 func (s *MachineSuite) TestAddressesRaceMachineFirst(c *gc.C) { 2019 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2020 c.Assert(err, jc.ErrorIsNil) 2021 2022 changeAddresses := jujutxn.TestHook{ 2023 Before: func() { 2024 err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8")) 2025 c.Assert(err, jc.ErrorIsNil) 2026 address, err := machine.PublicAddress() 2027 c.Assert(err, jc.ErrorIsNil) 2028 c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8")) 2029 address, err = machine.PrivateAddress() 2030 c.Assert(err, jc.ErrorIsNil) 2031 c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8")) 2032 }, 2033 } 2034 defer state.SetTestHooks(c, s.State, changeAddresses).Check() 2035 2036 err = machine.SetMachineAddresses(network.NewAddress("8.8.4.4")) 2037 c.Assert(err, jc.ErrorIsNil) 2038 2039 machine, err = s.State.Machine(machine.Id()) 2040 c.Assert(err, jc.ErrorIsNil) 2041 address, err := machine.PublicAddress() 2042 c.Assert(err, jc.ErrorIsNil) 2043 c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8")) 2044 address, err = machine.PrivateAddress() 2045 c.Assert(err, jc.ErrorIsNil) 2046 c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8")) 2047 } 2048 2049 func (s *MachineSuite) TestAddressesRaceProviderFirst(c *gc.C) { 2050 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2051 c.Assert(err, jc.ErrorIsNil) 2052 2053 changeAddresses := jujutxn.TestHook{ 2054 Before: func() { 2055 err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1")) 2056 c.Assert(err, jc.ErrorIsNil) 2057 address, err := machine.PublicAddress() 2058 c.Assert(err, jc.ErrorIsNil) 2059 c.Assert(address, jc.DeepEquals, network.NewAddress("10.0.0.1")) 2060 address, err = machine.PrivateAddress() 2061 c.Assert(err, jc.ErrorIsNil) 2062 c.Assert(address, jc.DeepEquals, network.NewAddress("10.0.0.1")) 2063 }, 2064 } 2065 defer state.SetTestHooks(c, s.State, changeAddresses).Check() 2066 2067 err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4")) 2068 c.Assert(err, jc.ErrorIsNil) 2069 2070 machine, err = s.State.Machine(machine.Id()) 2071 c.Assert(err, jc.ErrorIsNil) 2072 address, err := machine.PublicAddress() 2073 c.Assert(err, jc.ErrorIsNil) 2074 c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.4.4")) 2075 address, err = machine.PrivateAddress() 2076 c.Assert(err, jc.ErrorIsNil) 2077 c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.4.4")) 2078 } 2079 2080 func (s *MachineSuite) TestPrivateAddressPrefersProvider(c *gc.C) { 2081 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2082 c.Assert(err, jc.ErrorIsNil) 2083 2084 err = machine.SetMachineAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.2")) 2085 c.Assert(err, jc.ErrorIsNil) 2086 2087 addr, err := machine.PublicAddress() 2088 c.Assert(err, jc.ErrorIsNil) 2089 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2090 addr, err = machine.PrivateAddress() 2091 c.Assert(err, jc.ErrorIsNil) 2092 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 2093 2094 err = machine.SetProviderAddresses(network.NewAddress("10.0.0.1")) 2095 c.Assert(err, jc.ErrorIsNil) 2096 2097 addr, err = machine.PublicAddress() 2098 c.Assert(err, jc.ErrorIsNil) 2099 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 2100 addr, err = machine.PrivateAddress() 2101 c.Assert(err, jc.ErrorIsNil) 2102 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 2103 } 2104 2105 func (s *MachineSuite) TestPublicAddressPrefersProvider(c *gc.C) { 2106 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2107 c.Assert(err, jc.ErrorIsNil) 2108 2109 err = machine.SetMachineAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.2")) 2110 c.Assert(err, jc.ErrorIsNil) 2111 2112 addr, err := machine.PublicAddress() 2113 c.Assert(err, jc.ErrorIsNil) 2114 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2115 addr, err = machine.PrivateAddress() 2116 c.Assert(err, jc.ErrorIsNil) 2117 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 2118 2119 err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4")) 2120 c.Assert(err, jc.ErrorIsNil) 2121 2122 addr, err = machine.PublicAddress() 2123 c.Assert(err, jc.ErrorIsNil) 2124 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 2125 addr, err = machine.PrivateAddress() 2126 c.Assert(err, jc.ErrorIsNil) 2127 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 2128 } 2129 2130 func (s *MachineSuite) TestAddressesPrefersProviderBoth(c *gc.C) { 2131 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2132 c.Assert(err, jc.ErrorIsNil) 2133 2134 err = machine.SetMachineAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.1")) 2135 c.Assert(err, jc.ErrorIsNil) 2136 2137 addr, err := machine.PublicAddress() 2138 c.Assert(err, jc.ErrorIsNil) 2139 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2140 addr, err = machine.PrivateAddress() 2141 c.Assert(err, jc.ErrorIsNil) 2142 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 2143 2144 err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4"), network.NewAddress("10.0.0.2")) 2145 c.Assert(err, jc.ErrorIsNil) 2146 2147 addr, err = machine.PublicAddress() 2148 c.Assert(err, jc.ErrorIsNil) 2149 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 2150 addr, err = machine.PrivateAddress() 2151 c.Assert(err, jc.ErrorIsNil) 2152 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 2153 } 2154 2155 func (s *MachineSuite) addMachineWithSupportedContainer(c *gc.C, container instance.ContainerType) *state.Machine { 2156 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2157 c.Assert(err, jc.ErrorIsNil) 2158 containers := []instance.ContainerType{container} 2159 err = machine.SetSupportedContainers(containers) 2160 c.Assert(err, jc.ErrorIsNil) 2161 assertSupportedContainers(c, machine, containers) 2162 return machine 2163 } 2164 2165 // assertSupportedContainers checks the document in memory has the specified 2166 // containers and then reloads the document from the database to assert saved 2167 // values match also. 2168 func assertSupportedContainers(c *gc.C, machine *state.Machine, containers []instance.ContainerType) { 2169 supportedContainers, known := machine.SupportedContainers() 2170 c.Assert(known, jc.IsTrue) 2171 c.Assert(supportedContainers, gc.DeepEquals, containers) 2172 // Reload so we can check the saved values. 2173 err := machine.Refresh() 2174 c.Assert(err, jc.ErrorIsNil) 2175 supportedContainers, known = machine.SupportedContainers() 2176 c.Assert(known, jc.IsTrue) 2177 c.Assert(supportedContainers, gc.DeepEquals, containers) 2178 } 2179 2180 func assertSupportedContainersUnknown(c *gc.C, machine *state.Machine) { 2181 containers, known := machine.SupportedContainers() 2182 c.Assert(known, jc.IsFalse) 2183 c.Assert(containers, gc.HasLen, 0) 2184 } 2185 2186 func (s *MachineSuite) TestSupportedContainersInitiallyUnknown(c *gc.C) { 2187 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2188 c.Assert(err, jc.ErrorIsNil) 2189 assertSupportedContainersUnknown(c, machine) 2190 } 2191 2192 func (s *MachineSuite) TestSupportsNoContainers(c *gc.C) { 2193 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2194 c.Assert(err, jc.ErrorIsNil) 2195 2196 err = machine.SupportsNoContainers() 2197 c.Assert(err, jc.ErrorIsNil) 2198 assertSupportedContainers(c, machine, []instance.ContainerType{}) 2199 } 2200 2201 func (s *MachineSuite) TestSetSupportedContainerTypeNoneIsError(c *gc.C) { 2202 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2203 c.Assert(err, jc.ErrorIsNil) 2204 2205 err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXC, instance.NONE}) 2206 c.Assert(err, gc.ErrorMatches, `"none" is not a valid container type`) 2207 assertSupportedContainersUnknown(c, machine) 2208 err = machine.Refresh() 2209 c.Assert(err, jc.ErrorIsNil) 2210 assertSupportedContainersUnknown(c, machine) 2211 } 2212 2213 func (s *MachineSuite) TestSupportsNoContainersOverwritesExisting(c *gc.C) { 2214 machine := s.addMachineWithSupportedContainer(c, instance.LXC) 2215 2216 err := machine.SupportsNoContainers() 2217 c.Assert(err, jc.ErrorIsNil) 2218 assertSupportedContainers(c, machine, []instance.ContainerType{}) 2219 } 2220 2221 func (s *MachineSuite) TestSetSupportedContainersSingle(c *gc.C) { 2222 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2223 c.Assert(err, jc.ErrorIsNil) 2224 2225 err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXC}) 2226 c.Assert(err, jc.ErrorIsNil) 2227 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXC}) 2228 } 2229 2230 func (s *MachineSuite) TestSetSupportedContainersSame(c *gc.C) { 2231 machine := s.addMachineWithSupportedContainer(c, instance.LXC) 2232 2233 err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXC}) 2234 c.Assert(err, jc.ErrorIsNil) 2235 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXC}) 2236 } 2237 2238 func (s *MachineSuite) TestSetSupportedContainersNew(c *gc.C) { 2239 machine := s.addMachineWithSupportedContainer(c, instance.LXC) 2240 2241 err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXC, instance.KVM}) 2242 c.Assert(err, jc.ErrorIsNil) 2243 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXC, instance.KVM}) 2244 } 2245 2246 func (s *MachineSuite) TestSetSupportedContainersMultipeNew(c *gc.C) { 2247 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2248 c.Assert(err, jc.ErrorIsNil) 2249 2250 err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXC, instance.KVM}) 2251 c.Assert(err, jc.ErrorIsNil) 2252 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXC, instance.KVM}) 2253 } 2254 2255 func (s *MachineSuite) TestSetSupportedContainersMultipleExisting(c *gc.C) { 2256 machine := s.addMachineWithSupportedContainer(c, instance.LXC) 2257 2258 err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXC, instance.KVM}) 2259 c.Assert(err, jc.ErrorIsNil) 2260 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXC, instance.KVM}) 2261 } 2262 2263 func (s *MachineSuite) TestSetSupportedContainersSetsUnknownToError(c *gc.C) { 2264 // Create a machine and add lxc and kvm containers prior to calling SetSupportedContainers 2265 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2266 template := state.MachineTemplate{ 2267 Series: "quantal", 2268 Jobs: []state.MachineJob{state.JobHostUnits}, 2269 } 2270 container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXC) 2271 c.Assert(err, jc.ErrorIsNil) 2272 supportedContainer, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.KVM) 2273 c.Assert(err, jc.ErrorIsNil) 2274 err = machine.SetSupportedContainers([]instance.ContainerType{instance.KVM}) 2275 c.Assert(err, jc.ErrorIsNil) 2276 2277 // A supported (kvm) container will have a pending status. 2278 err = supportedContainer.Refresh() 2279 c.Assert(err, jc.ErrorIsNil) 2280 statusInfo, err := supportedContainer.Status() 2281 c.Assert(err, jc.ErrorIsNil) 2282 c.Assert(statusInfo.Status, gc.Equals, status.StatusPending) 2283 2284 // An unsupported (lxc) container will have an error status. 2285 err = container.Refresh() 2286 c.Assert(err, jc.ErrorIsNil) 2287 statusInfo, err = container.Status() 2288 c.Assert(err, jc.ErrorIsNil) 2289 c.Assert(statusInfo.Status, gc.Equals, status.StatusError) 2290 c.Assert(statusInfo.Message, gc.Equals, "unsupported container") 2291 c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{"type": "lxc"}) 2292 } 2293 2294 func (s *MachineSuite) TestSupportsNoContainersSetsAllToError(c *gc.C) { 2295 // Create a machine and add all container types prior to calling SupportsNoContainers 2296 machine, err := s.State.AddMachine("quantal", state.JobHostUnits) 2297 var containers []*state.Machine 2298 template := state.MachineTemplate{ 2299 Series: "quantal", 2300 Jobs: []state.MachineJob{state.JobHostUnits}, 2301 } 2302 for _, containerType := range instance.ContainerTypes { 2303 container, err := s.State.AddMachineInsideMachine(template, machine.Id(), containerType) 2304 c.Assert(err, jc.ErrorIsNil) 2305 containers = append(containers, container) 2306 } 2307 2308 err = machine.SupportsNoContainers() 2309 c.Assert(err, jc.ErrorIsNil) 2310 2311 // All containers should be in error state. 2312 for _, container := range containers { 2313 err = container.Refresh() 2314 c.Assert(err, jc.ErrorIsNil) 2315 statusInfo, err := container.Status() 2316 c.Assert(err, jc.ErrorIsNil) 2317 c.Assert(statusInfo.Status, gc.Equals, status.StatusError) 2318 c.Assert(statusInfo.Message, gc.Equals, "unsupported container") 2319 containerType := state.ContainerTypeFromId(container.Id()) 2320 c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{"type": string(containerType)}) 2321 } 2322 } 2323 2324 func (s *MachineSuite) TestMachineAgentTools(c *gc.C) { 2325 m, err := s.State.AddMachine("quantal", state.JobHostUnits) 2326 c.Assert(err, jc.ErrorIsNil) 2327 testAgentTools(c, m, "machine "+m.Id()) 2328 } 2329 2330 func (s *MachineSuite) TestMachineValidActions(c *gc.C) { 2331 m, err := s.State.AddMachine("trusty", state.JobHostUnits) 2332 c.Assert(err, jc.ErrorIsNil) 2333 2334 var tests = []struct { 2335 actionName string 2336 errString string 2337 givenPayload map[string]interface{} 2338 expectedPayload map[string]interface{} 2339 }{ 2340 { 2341 actionName: "juju-run", 2342 errString: `validation failed: (root) : "command" property is missing and required, given {}; (root) : "timeout" property is missing and required, given {}`, 2343 }, 2344 { 2345 actionName: "juju-run", 2346 givenPayload: map[string]interface{}{"command": "allyourbasearebelongtous", "timeout": 5.0}, 2347 expectedPayload: map[string]interface{}{"command": "allyourbasearebelongtous", "timeout": 5.0}, 2348 }, 2349 { 2350 actionName: "baiku", 2351 errString: `cannot add action "baiku" to a machine; only predefined actions allowed`, 2352 }, 2353 } 2354 2355 for i, t := range tests { 2356 c.Logf("running test %d", i) 2357 action, err := m.AddAction(t.actionName, t.givenPayload) 2358 if t.errString != "" { 2359 c.Assert(err.Error(), gc.Equals, t.errString) 2360 continue 2361 } else { 2362 c.Assert(err, jc.ErrorIsNil) 2363 c.Assert(action.Parameters(), jc.DeepEquals, t.expectedPayload) 2364 } 2365 } 2366 } 2367 2368 func (s *MachineSuite) TestMachineAddDifferentAction(c *gc.C) { 2369 m, err := s.State.AddMachine("trusty", state.JobHostUnits) 2370 c.Assert(err, jc.ErrorIsNil) 2371 2372 _, err = m.AddAction("benchmark", nil) 2373 c.Assert(err, gc.ErrorMatches, `cannot add action "benchmark" to a machine; only predefined actions allowed`) 2374 }