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