github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/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 "strings" 9 "time" 10 11 "github.com/juju/clock" 12 "github.com/juju/errors" 13 "github.com/juju/loggo" 14 "github.com/juju/mgo/v3" 15 "github.com/juju/mgo/v3/bson" 16 "github.com/juju/mgo/v3/txn" 17 "github.com/juju/names/v5" 18 jc "github.com/juju/testing/checkers" 19 jujutxn "github.com/juju/txn/v3" 20 "github.com/juju/version/v2" 21 gc "gopkg.in/check.v1" 22 23 "github.com/juju/juju/core/arch" 24 "github.com/juju/juju/core/constraints" 25 corecontainer "github.com/juju/juju/core/container" 26 "github.com/juju/juju/core/instance" 27 "github.com/juju/juju/core/network" 28 "github.com/juju/juju/core/status" 29 "github.com/juju/juju/mongo" 30 "github.com/juju/juju/mongo/mongotest" 31 "github.com/juju/juju/state" 32 stateerrors "github.com/juju/juju/state/errors" 33 "github.com/juju/juju/state/testing" 34 "github.com/juju/juju/storage" 35 "github.com/juju/juju/storage/poolmanager" 36 "github.com/juju/juju/storage/provider" 37 dummystorage "github.com/juju/juju/storage/provider/dummy" 38 coretesting "github.com/juju/juju/testing" 39 "github.com/juju/juju/testing/factory" 40 ) 41 42 type MachineSuite struct { 43 ConnSuite 44 machine0 *state.Machine 45 machine *state.Machine 46 } 47 48 var _ = gc.Suite(&MachineSuite{}) 49 50 func (s *MachineSuite) SetUpTest(c *gc.C) { 51 s.ConnSuite.SetUpTest(c) 52 s.policy.GetConstraintsValidator = func() (constraints.Validator, error) { 53 validator := constraints.NewValidator() 54 validator.RegisterConflicts([]string{constraints.InstanceType}, []string{constraints.Mem}) 55 validator.RegisterUnsupported([]string{constraints.CpuPower}) 56 return validator, nil 57 } 58 var err error 59 s.machine0, err = s.State.AddMachine(state.UbuntuBase("12.10"), state.JobManageModel) 60 c.Assert(err, jc.ErrorIsNil) 61 controllerNode, err := s.State.ControllerNode(s.machine0.Id()) 62 c.Assert(err, jc.ErrorIsNil) 63 c.Assert(controllerNode.HasVote(), jc.IsFalse) 64 c.Assert(controllerNode.SetHasVote(true), jc.ErrorIsNil) 65 s.machine, err = s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 66 c.Assert(err, jc.ErrorIsNil) 67 _, err = s.State.ControllerNode(s.machine.Id()) 68 c.Assert(err, jc.Satisfies, errors.IsNotFound) 69 } 70 71 func (s *MachineSuite) TestSetRebootFlagDeadMachine(c *gc.C) { 72 err := s.machine.EnsureDead() 73 c.Assert(err, jc.ErrorIsNil) 74 75 err = s.machine.SetRebootFlag(true) 76 c.Assert(err, gc.Equals, mgo.ErrNotFound) 77 78 rFlag, err := s.machine.GetRebootFlag() 79 c.Assert(err, jc.ErrorIsNil) 80 c.Assert(rFlag, jc.IsFalse) 81 82 err = s.machine.SetRebootFlag(false) 83 c.Assert(err, jc.ErrorIsNil) 84 85 action, err := s.machine.ShouldRebootOrShutdown() 86 c.Assert(err, jc.ErrorIsNil) 87 c.Assert(action, gc.Equals, state.ShouldDoNothing) 88 } 89 90 func (s *MachineSuite) TestSetRebootFlagDeadMachineRace(c *gc.C) { 91 setFlag := jujutxn.TestHook{ 92 Before: func() { 93 err := s.machine.EnsureDead() 94 c.Assert(err, jc.ErrorIsNil) 95 }, 96 } 97 defer state.SetTestHooks(c, s.State, setFlag).Check() 98 99 err := s.machine.SetRebootFlag(true) 100 c.Assert(err, gc.Equals, mgo.ErrNotFound) 101 } 102 103 func (s *MachineSuite) TestSetRebootFlag(c *gc.C) { 104 err := s.machine.SetRebootFlag(true) 105 c.Assert(err, jc.ErrorIsNil) 106 107 rebootFlag, err := s.machine.GetRebootFlag() 108 c.Assert(err, jc.ErrorIsNil) 109 c.Assert(rebootFlag, jc.IsTrue) 110 } 111 112 func (s *MachineSuite) TestSetUnsetRebootFlag(c *gc.C) { 113 err := s.machine.SetRebootFlag(true) 114 c.Assert(err, jc.ErrorIsNil) 115 116 rebootFlag, err := s.machine.GetRebootFlag() 117 c.Assert(err, jc.ErrorIsNil) 118 c.Assert(rebootFlag, jc.IsTrue) 119 120 err = s.machine.SetRebootFlag(false) 121 c.Assert(err, jc.ErrorIsNil) 122 123 rebootFlag, err = s.machine.GetRebootFlag() 124 c.Assert(err, jc.ErrorIsNil) 125 c.Assert(rebootFlag, jc.IsFalse) 126 } 127 128 func (s *MachineSuite) TestRecordAgentStartInformation(c *gc.C) { 129 now := s.Clock.Now().Truncate(time.Minute) 130 err := s.machine.RecordAgentStartInformation("thundering-herds") 131 c.Assert(err, jc.ErrorIsNil) 132 133 err = s.machine.Refresh() 134 c.Assert(err, jc.ErrorIsNil) 135 c.Assert(s.machine.AgentStartTime().Truncate(time.Minute), gc.Equals, now) 136 c.Assert(s.machine.Hostname(), gc.Equals, "thundering-herds") 137 138 // Passing an empty hostname should be ignored 139 err = s.machine.RecordAgentStartInformation("") 140 c.Assert(err, jc.ErrorIsNil) 141 err = s.machine.Refresh() 142 c.Assert(err, jc.ErrorIsNil) 143 c.Assert(s.machine.AgentStartTime().Truncate(time.Minute), gc.Equals, now) 144 c.Assert(s.machine.Hostname(), gc.Equals, "thundering-herds", gc.Commentf("expected the host name not be changed")) 145 } 146 147 func (s *MachineSuite) TestSetKeepInstance(c *gc.C) { 148 err := s.machine.SetProvisioned("1234", "", "nonce", nil) 149 c.Assert(err, jc.ErrorIsNil) 150 err = s.machine.SetKeepInstance(true) 151 c.Assert(err, jc.ErrorIsNil) 152 153 m, err := s.State.Machine(s.machine.Id()) 154 c.Assert(err, jc.ErrorIsNil) 155 keep, err := m.KeepInstance() 156 c.Assert(err, jc.ErrorIsNil) 157 c.Assert(keep, jc.IsTrue) 158 } 159 160 func (s *MachineSuite) TestAddMachineInsideMachineModelDying(c *gc.C) { 161 model, err := s.State.Model() 162 c.Assert(err, jc.ErrorIsNil) 163 c.Assert(model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil) 164 165 _, err = s.State.AddMachineInsideMachine(state.MachineTemplate{ 166 Base: state.UbuntuBase("12.10"), 167 Jobs: []state.MachineJob{state.JobHostUnits}, 168 }, s.machine.Id(), instance.LXD) 169 c.Assert(err, gc.ErrorMatches, `model "testmodel" is dying`) 170 } 171 172 func (s *MachineSuite) TestAddMachineInsideMachineModelMigrating(c *gc.C) { 173 model, err := s.State.Model() 174 c.Assert(err, jc.ErrorIsNil) 175 c.Assert(model.SetMigrationMode(state.MigrationModeExporting), jc.ErrorIsNil) 176 177 _, err = s.State.AddMachineInsideMachine(state.MachineTemplate{ 178 Base: state.UbuntuBase("12.10"), 179 Jobs: []state.MachineJob{state.JobHostUnits}, 180 }, s.machine.Id(), instance.LXD) 181 c.Assert(err, gc.ErrorMatches, `model "testmodel" is being migrated`) 182 } 183 184 func (s *MachineSuite) TestShouldShutdownOrReboot(c *gc.C) { 185 // Add first container. 186 c1, err := s.State.AddMachineInsideMachine(state.MachineTemplate{ 187 Base: state.UbuntuBase("12.10"), 188 Jobs: []state.MachineJob{state.JobHostUnits}, 189 }, s.machine.Id(), instance.LXD) 190 c.Assert(err, jc.ErrorIsNil) 191 192 // Add second container. 193 c2, err := s.State.AddMachineInsideMachine(state.MachineTemplate{ 194 Base: state.UbuntuBase("12.10"), 195 Jobs: []state.MachineJob{state.JobHostUnits}, 196 }, c1.Id(), instance.LXD) 197 c.Assert(err, jc.ErrorIsNil) 198 199 err = c2.SetRebootFlag(true) 200 c.Assert(err, jc.ErrorIsNil) 201 202 rAction, err := s.machine.ShouldRebootOrShutdown() 203 c.Assert(err, jc.ErrorIsNil) 204 c.Assert(rAction, gc.Equals, state.ShouldDoNothing) 205 206 rAction, err = c1.ShouldRebootOrShutdown() 207 c.Assert(err, jc.ErrorIsNil) 208 c.Assert(rAction, gc.Equals, state.ShouldDoNothing) 209 210 rAction, err = c2.ShouldRebootOrShutdown() 211 c.Assert(err, jc.ErrorIsNil) 212 c.Assert(rAction, gc.Equals, state.ShouldReboot) 213 214 // // Reboot happens on the root node 215 err = c2.SetRebootFlag(false) 216 c.Assert(err, jc.ErrorIsNil) 217 218 err = s.machine.SetRebootFlag(true) 219 c.Assert(err, jc.ErrorIsNil) 220 221 rAction, err = s.machine.ShouldRebootOrShutdown() 222 c.Assert(err, jc.ErrorIsNil) 223 c.Assert(rAction, gc.Equals, state.ShouldReboot) 224 225 rAction, err = c1.ShouldRebootOrShutdown() 226 c.Assert(err, jc.ErrorIsNil) 227 c.Assert(rAction, gc.Equals, state.ShouldShutdown) 228 229 rAction, err = c2.ShouldRebootOrShutdown() 230 c.Assert(err, jc.ErrorIsNil) 231 c.Assert(rAction, gc.Equals, state.ShouldShutdown) 232 } 233 234 func (s *MachineSuite) TestContainerDefaults(c *gc.C) { 235 c.Assert(string(s.machine.ContainerType()), gc.Equals, "") 236 containers, err := s.machine.Containers() 237 c.Assert(err, jc.ErrorIsNil) 238 c.Assert(containers, gc.DeepEquals, []string(nil)) 239 } 240 241 func (s *MachineSuite) TestParentId(c *gc.C) { 242 parentId, ok := s.machine.ParentId() 243 c.Assert(parentId, gc.Equals, "") 244 c.Assert(ok, jc.IsFalse) 245 container, err := s.State.AddMachineInsideMachine(state.MachineTemplate{ 246 Base: state.UbuntuBase("12.10"), 247 Jobs: []state.MachineJob{state.JobHostUnits}, 248 }, s.machine.Id(), instance.LXD) 249 c.Assert(err, jc.ErrorIsNil) 250 parentId, ok = container.ParentId() 251 c.Assert(parentId, gc.Equals, s.machine.Id()) 252 c.Assert(ok, jc.IsTrue) 253 } 254 255 func (s *MachineSuite) TestMachineIsManager(c *gc.C) { 256 c.Assert(s.machine0.IsManager(), jc.IsTrue) 257 c.Assert(s.machine.IsManager(), jc.IsFalse) 258 } 259 260 func (s *MachineSuite) TestMachineIsManualBootstrap(c *gc.C) { 261 cfg, err := s.Model.ModelConfig() 262 c.Assert(err, jc.ErrorIsNil) 263 c.Assert(cfg.Type(), gc.Not(gc.Equals), "null") 264 c.Assert(s.machine.Id(), gc.Equals, "1") 265 manual, err := s.machine0.IsManual() 266 c.Assert(err, jc.ErrorIsNil) 267 c.Assert(manual, jc.IsFalse) 268 attrs := map[string]interface{}{"type": "null"} 269 err = s.Model.UpdateModelConfig(attrs, nil) 270 c.Assert(err, jc.ErrorIsNil) 271 manual, err = s.machine0.IsManual() 272 c.Assert(err, jc.ErrorIsNil) 273 c.Assert(manual, jc.IsTrue) 274 } 275 276 func (s *MachineSuite) TestMachineIsManual(c *gc.C) { 277 tests := []struct { 278 instanceId instance.Id 279 nonce string 280 isManual bool 281 }{ 282 {instanceId: "x", nonce: "y", isManual: false}, 283 {instanceId: "manual:", nonce: "y", isManual: false}, 284 {instanceId: "x", nonce: "manual:", isManual: true}, 285 {instanceId: "x", nonce: "manual:y", isManual: true}, 286 {instanceId: "x", nonce: "manual", isManual: false}, 287 } 288 for _, test := range tests { 289 m, err := s.State.AddOneMachine(state.MachineTemplate{ 290 Base: state.UbuntuBase("12.10"), 291 Jobs: []state.MachineJob{state.JobHostUnits}, 292 InstanceId: test.instanceId, 293 Nonce: test.nonce, 294 }) 295 c.Assert(err, jc.ErrorIsNil) 296 isManual, err := m.IsManual() 297 c.Assert(err, jc.ErrorIsNil) 298 c.Assert(isManual, gc.Equals, test.isManual) 299 } 300 } 301 302 func (s *MachineSuite) TestMachineIsContainer(c *gc.C) { 303 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 304 c.Assert(err, jc.ErrorIsNil) 305 306 template := state.MachineTemplate{ 307 Base: state.UbuntuBase("12.10"), 308 Jobs: []state.MachineJob{state.JobHostUnits}, 309 } 310 container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXD) 311 c.Assert(err, jc.ErrorIsNil) 312 313 c.Assert(machine.IsContainer(), jc.IsFalse) 314 c.Assert(container.IsContainer(), jc.IsTrue) 315 } 316 317 func (s *MachineSuite) TestLifeJobController(c *gc.C) { 318 m := s.machine0 319 err := m.Destroy() 320 c.Assert(err, gc.ErrorMatches, "controller 0 is the only controller") 321 controllerNode, err := s.State.ControllerNode(m.Id()) 322 c.Assert(err, jc.ErrorIsNil) 323 c.Assert(controllerNode.HasVote(), jc.IsTrue) 324 err = m.EnsureDead() 325 c.Assert(err, gc.ErrorMatches, "machine 0 is still a voting controller member") 326 controllerNode, err = s.State.ControllerNode(m.Id()) 327 c.Assert(err, jc.ErrorIsNil) 328 c.Assert(controllerNode.HasVote(), jc.IsTrue) 329 330 // Since this is the only controller machine, we cannot even force destroy it 331 err = m.ForceDestroy(dontWait) 332 c.Assert(err, gc.ErrorMatches, "controller 0 is the only controller") 333 err = m.EnsureDead() 334 c.Assert(err, gc.ErrorMatches, "machine 0 is still a voting controller member") 335 } 336 337 func (s *MachineSuite) TestLifeJobManageModelWithControllerCharm(c *gc.C) { 338 cons := constraints.Value{ 339 Mem: newUint64(100), 340 } 341 changes, err := s.State.EnableHA(3, cons, state.UbuntuBase("12.10"), nil) 342 c.Assert(err, jc.ErrorIsNil) 343 c.Assert(changes.Added, gc.HasLen, 2) 344 345 m2, err := s.State.Machine("2") 346 c.Assert(err, jc.ErrorIsNil) 347 c.Assert(m2.Jobs(), gc.DeepEquals, []state.MachineJob{ 348 state.JobHostUnits, 349 state.JobManageModel, 350 }) 351 352 ch := s.AddTestingCharmWithSeries(c, "juju-controller", "") 353 app := s.AddTestingApplicationForBase(c, state.UbuntuBase("12.10"), "controller", ch) 354 unit, err := app.AddUnit(state.AddUnitParams{}) 355 c.Assert(err, jc.ErrorIsNil) 356 err = unit.SetCharmURL(ch.URL()) 357 c.Assert(err, jc.ErrorIsNil) 358 err = unit.AssignToMachine(m2) 359 c.Assert(err, jc.ErrorIsNil) 360 err = m2.Destroy() 361 c.Assert(err, jc.ErrorIsNil) 362 363 c.Assert(m2.Life(), gc.Equals, state.Alive) 364 c.Assert(err, jc.ErrorIsNil) 365 366 for i := 0; i < 3; i++ { 367 needsCleanup, err := s.State.NeedsCleanup() 368 c.Assert(err, jc.ErrorIsNil) 369 c.Assert(needsCleanup, jc.IsTrue) 370 err = s.State.Cleanup() 371 c.Assert(err, jc.ErrorIsNil) 372 } 373 needsCleanup, err := s.State.NeedsCleanup() 374 c.Assert(err, jc.ErrorIsNil) 375 c.Assert(needsCleanup, jc.IsFalse) 376 377 err = m2.Refresh() 378 c.Assert(err, jc.ErrorIsNil) 379 c.Assert(m2.Life(), gc.Equals, state.Dying) 380 381 cn2, err := s.State.ControllerNode(m2.Id()) 382 c.Assert(err, jc.ErrorIsNil) 383 err = s.State.RemoveControllerReference(cn2) 384 c.Assert(err, jc.ErrorIsNil) 385 386 err = m2.EnsureDead() 387 c.Assert(err, jc.ErrorIsNil) 388 c.Assert(m2.Life(), gc.Equals, state.Dead) 389 } 390 391 func (s *MachineSuite) TestLifeMachineWithContainer(c *gc.C) { 392 // A machine hosting a container must not advance lifecycle. 393 _, err := s.State.AddMachineInsideMachine(state.MachineTemplate{ 394 Base: state.UbuntuBase("12.10"), 395 Jobs: []state.MachineJob{state.JobHostUnits}, 396 }, s.machine.Id(), instance.LXD) 397 c.Assert(err, jc.ErrorIsNil) 398 399 err = s.machine.Destroy() 400 c.Assert(errors.Is(err, stateerrors.HasContainersError), jc.IsTrue) 401 c.Assert(err, gc.ErrorMatches, `machine 1 is hosting containers "1/lxd/0"`) 402 403 err = s.machine.EnsureDead() 404 c.Assert(errors.Is(err, stateerrors.HasContainersError), jc.IsTrue) 405 c.Assert(err, gc.ErrorMatches, `machine 1 is hosting containers "1/lxd/0"`) 406 407 c.Assert(s.machine.Life(), gc.Equals, state.Alive) 408 } 409 410 func (s *MachineSuite) TestLifeMachineLockedForSeriesUpgrade(c *gc.C) { 411 err := s.machine.CreateUpgradeSeriesLock(nil, state.UbuntuBase("16.04")) 412 c.Assert(err, jc.ErrorIsNil) 413 414 err = s.machine.Destroy() 415 c.Assert(err, gc.ErrorMatches, `machine 1 is locked for series upgrade`) 416 417 err = s.machine.EnsureDead() 418 c.Assert(err, gc.ErrorMatches, `machine 1 is locked for series upgrade`) 419 c.Assert(s.machine.Life(), gc.Equals, state.Alive) 420 } 421 422 func (s *MachineSuite) TestLifeJobHostUnits(c *gc.C) { 423 // A machine with an assigned unit must not advance lifecycle. 424 app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 425 unit, err := app.AddUnit(state.AddUnitParams{}) 426 c.Assert(err, jc.ErrorIsNil) 427 err = unit.AssignToMachine(s.machine) 428 c.Assert(err, jc.ErrorIsNil) 429 err = s.machine.Destroy() 430 c.Assert(errors.Is(err, stateerrors.HasAssignedUnitsError), jc.IsTrue) 431 c.Assert(err, gc.ErrorMatches, `machine 1 has unit "wordpress/0" assigned`) 432 433 err = s.machine.EnsureDead() 434 c.Assert(errors.Is(err, stateerrors.HasAssignedUnitsError), jc.IsTrue) 435 c.Assert(err, gc.ErrorMatches, `machine 1 has unit "wordpress/0" assigned`) 436 437 c.Assert(s.machine.Life(), gc.Equals, state.Alive) 438 439 // Once no unit is assigned, lifecycle can advance. 440 err = unit.UnassignFromMachine() 441 c.Assert(err, jc.ErrorIsNil) 442 err = s.machine.Destroy() 443 c.Assert(s.machine.Life(), gc.Equals, state.Dying) 444 c.Assert(err, jc.ErrorIsNil) 445 err = s.machine.EnsureDead() 446 c.Assert(err, jc.ErrorIsNil) 447 c.Assert(s.machine.Life(), gc.Equals, state.Dead) 448 449 // A machine that has never had units assigned can advance lifecycle. 450 m, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 451 c.Assert(err, jc.ErrorIsNil) 452 err = m.Destroy() 453 c.Assert(err, jc.ErrorIsNil) 454 c.Assert(m.Life(), gc.Equals, state.Dying) 455 err = m.EnsureDead() 456 c.Assert(err, jc.ErrorIsNil) 457 c.Assert(m.Life(), gc.Equals, state.Dead) 458 } 459 460 func (s *MachineSuite) TestDestroyRemovePorts(c *gc.C) { 461 app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 462 unit, err := app.AddUnit(state.AddUnitParams{}) 463 c.Assert(err, jc.ErrorIsNil) 464 err = unit.AssignToMachine(s.machine) 465 c.Assert(err, jc.ErrorIsNil) 466 467 state.MustOpenUnitPortRange(c, s.State, s.machine, unit.Name(), allEndpoints, network.MustParsePortRange("8080/tcp")) 468 469 machPortRanges, err := s.machine.OpenedPortRanges() 470 c.Assert(err, jc.ErrorIsNil) 471 c.Assert(machPortRanges.UniquePortRanges(), gc.HasLen, 1) 472 473 err = unit.UnassignFromMachine() 474 c.Assert(err, jc.ErrorIsNil) 475 err = s.machine.Destroy() 476 c.Assert(err, jc.ErrorIsNil) 477 err = s.machine.EnsureDead() 478 c.Assert(err, jc.ErrorIsNil) 479 err = s.machine.Remove() 480 c.Assert(err, jc.ErrorIsNil) 481 482 // once the machine is destroyed, there should be no ports documents present for it 483 machPortRanges, err = s.machine.OpenedPortRanges() 484 c.Assert(err, jc.ErrorIsNil) 485 assertMachinePortsPersisted(c, machPortRanges, false) // we should get back a blank fresh doc 486 } 487 488 func (s *MachineSuite) TestDestroyOps(c *gc.C) { 489 m := s.Factory.MakeMachine(c, nil) 490 ops, err := state.ForceDestroyMachineOps(m) 491 c.Assert(err, jc.ErrorIsNil) 492 c.Assert(ops, gc.NotNil) 493 } 494 495 func (s *MachineSuite) TestDestroyOpsForManagerFails(c *gc.C) { 496 // s.Factory does not allow us to make a manager machine, so we grab one 497 // from State ... 498 machines, err := s.State.AllMachines() 499 c.Assert(err, jc.ErrorIsNil) 500 c.Assert(len(machines), jc.GreaterThan, 0) 501 m := machines[0] 502 c.Assert(m.IsManager(), jc.IsTrue) 503 504 // ... and assert that we cannot get the destroy ops for it. 505 ops, err := state.ForceDestroyMachineOps(m) 506 c.Assert(err, gc.ErrorMatches, `controller 0 is the only controller`) 507 c.Assert(ops, gc.IsNil) 508 } 509 510 func (s *MachineSuite) TestDestroyAbort(c *gc.C) { 511 defer state.SetBeforeHooks(c, s.State, func() { 512 c.Assert(s.machine.Destroy(), gc.IsNil) 513 }).Check() 514 err := s.machine.Destroy() 515 c.Assert(err, jc.ErrorIsNil) 516 } 517 518 func (s *MachineSuite) TestDestroyCancel(c *gc.C) { 519 app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 520 unit, err := app.AddUnit(state.AddUnitParams{}) 521 c.Assert(err, jc.ErrorIsNil) 522 523 defer state.SetBeforeHooks(c, s.State, func() { 524 c.Assert(unit.AssignToMachine(s.machine), gc.IsNil) 525 }).Check() 526 err = s.machine.Destroy() 527 c.Assert(errors.Is(err, stateerrors.HasAssignedUnitsError), jc.IsTrue) 528 } 529 530 func (s *MachineSuite) TestDestroyContention(c *gc.C) { 531 app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 532 unit, err := app.AddUnit(state.AddUnitParams{}) 533 c.Assert(err, jc.ErrorIsNil) 534 535 perturb := jujutxn.TestHook{ 536 Before: func() { c.Assert(unit.AssignToMachine(s.machine), gc.IsNil) }, 537 After: func() { c.Assert(unit.UnassignFromMachine(), gc.IsNil) }, 538 } 539 state.SetMaxTxnAttempts(c, s.State, 3) 540 defer state.SetTestHooks(c, s.State, perturb, perturb, perturb).Check() 541 542 err = s.machine.Destroy() 543 c.Assert(err, gc.ErrorMatches, "machine 1 cannot advance lifecycle: state changing too quickly; try again soon") 544 } 545 546 func (s *MachineSuite) TestDestroyWithApplicationDestroyPending(c *gc.C) { 547 app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 548 unit, err := app.AddUnit(state.AddUnitParams{}) 549 c.Assert(err, jc.ErrorIsNil) 550 err = unit.AssignToMachine(s.machine) 551 c.Assert(err, jc.ErrorIsNil) 552 553 err = app.Destroy() 554 c.Assert(err, jc.ErrorIsNil) 555 err = s.machine.Destroy() 556 c.Assert(err, jc.ErrorIsNil) 557 // Machine is still advanced to Dying. 558 life := s.machine.Life() 559 c.Assert(life, gc.Equals, state.Dying) 560 } 561 562 func (s *MachineSuite) TestDestroyFailsWhenNewUnitAdded(c *gc.C) { 563 app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 564 unit, err := app.AddUnit(state.AddUnitParams{}) 565 c.Assert(err, jc.ErrorIsNil) 566 err = unit.AssignToMachine(s.machine) 567 c.Assert(err, jc.ErrorIsNil) 568 569 err = app.Destroy() 570 c.Assert(err, jc.ErrorIsNil) 571 572 defer state.SetBeforeHooks(c, s.State, func() { 573 anotherApp := s.AddTestingApplication(c, "mysql", s.AddTestingCharm(c, "mysql")) 574 anotherUnit, err := anotherApp.AddUnit(state.AddUnitParams{}) 575 c.Assert(err, jc.ErrorIsNil) 576 err = anotherUnit.AssignToMachine(s.machine) 577 c.Assert(err, jc.ErrorIsNil) 578 }).Check() 579 580 err = s.machine.Destroy() 581 c.Assert(errors.Is(err, stateerrors.HasAssignedUnitsError), jc.IsTrue) 582 life := s.machine.Life() 583 c.Assert(life, gc.Equals, state.Alive) 584 } 585 586 func (s *MachineSuite) TestDestroyWithUnitDestroyPending(c *gc.C) { 587 app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 588 unit, err := app.AddUnit(state.AddUnitParams{}) 589 c.Assert(err, jc.ErrorIsNil) 590 err = unit.AssignToMachine(s.machine) 591 c.Assert(err, jc.ErrorIsNil) 592 593 err = unit.Destroy() 594 c.Assert(err, jc.ErrorIsNil) 595 err = s.machine.Destroy() 596 c.Assert(err, jc.ErrorIsNil) 597 // Machine is still advanced to Dying. 598 life := s.machine.Life() 599 c.Assert(life, gc.Equals, state.Dying) 600 } 601 602 func (s *MachineSuite) TestDestroyFailsWhenNewContainerAdded(c *gc.C) { 603 app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 604 unit, err := app.AddUnit(state.AddUnitParams{}) 605 c.Assert(err, jc.ErrorIsNil) 606 err = unit.AssignToMachine(s.machine) 607 c.Assert(err, jc.ErrorIsNil) 608 609 err = app.Destroy() 610 c.Assert(err, jc.ErrorIsNil) 611 612 defer state.SetBeforeHooks(c, s.State, func() { 613 _, err := s.State.AddMachineInsideMachine(state.MachineTemplate{ 614 Base: state.UbuntuBase("12.10"), 615 Jobs: []state.MachineJob{state.JobHostUnits}, 616 }, s.machine.Id(), instance.LXD) 617 c.Assert(err, jc.ErrorIsNil) 618 }).Check() 619 620 err = s.machine.Destroy() 621 c.Assert(errors.Is(err, stateerrors.HasAssignedUnitsError), jc.IsTrue) 622 life := s.machine.Life() 623 c.Assert(life, gc.Equals, state.Alive) 624 } 625 626 func (s *MachineSuite) TestRemove(c *gc.C) { 627 arch := arch.DefaultArchitecture 628 char := &instance.HardwareCharacteristics{ 629 Arch: &arch, 630 } 631 err := s.machine.SetProvisioned("umbrella/0", "snowflake", "fake_nonce", char) 632 c.Assert(err, jc.ErrorIsNil) 633 634 err = s.State.SetSSHHostKeys(s.machine.MachineTag(), state.SSHHostKeys{"rsa", "dsa"}) 635 c.Assert(err, jc.ErrorIsNil) 636 637 err = s.machine.Remove() 638 c.Assert(err, gc.ErrorMatches, "cannot remove machine 1: machine is not dead") 639 640 err = s.machine.EnsureDead() 641 c.Assert(err, jc.ErrorIsNil) 642 643 err = s.machine.Remove() 644 c.Assert(err, jc.ErrorIsNil) 645 646 err = s.machine.Refresh() 647 c.Assert(err, jc.Satisfies, errors.IsNotFound) 648 649 _, err = s.machine.HardwareCharacteristics() 650 c.Assert(err, jc.Satisfies, errors.IsNotFound) 651 652 _, err = s.machine.Containers() 653 c.Assert(err, jc.Satisfies, errors.IsNotFound) 654 655 _, err = s.State.GetSSHHostKeys(s.machine.MachineTag()) 656 c.Assert(errors.IsNotFound(err), jc.IsTrue) 657 658 // Removing an already removed machine is OK. 659 err = s.machine.Remove() 660 c.Assert(err, jc.ErrorIsNil) 661 } 662 663 func (s *MachineSuite) TestRemoveAbort(c *gc.C) { 664 err := s.machine.EnsureDead() 665 c.Assert(err, jc.ErrorIsNil) 666 667 defer state.SetBeforeHooks(c, s.State, func() { 668 c.Assert(s.machine.Remove(), gc.IsNil) 669 }).Check() 670 err = s.machine.Remove() 671 c.Assert(err, jc.ErrorIsNil) 672 } 673 674 func (s *MachineSuite) TestTag(c *gc.C) { 675 tag := s.machine.MachineTag() 676 c.Assert(tag.Kind(), gc.Equals, names.MachineTagKind) 677 c.Assert(tag.Id(), gc.Equals, "1") 678 679 // To keep gccgo happy, don't compare an interface with a struct. 680 var asTag names.Tag = tag 681 c.Assert(s.machine.Tag(), gc.Equals, asTag) 682 } 683 684 func (s *MachineSuite) TestSetMongoPassword(c *gc.C) { 685 testSetMongoPassword(c, func(st *state.State, id string) (mongoPasswordSetter, error) { 686 return st.Machine("0") 687 }, s.State.ControllerTag(), s.modelTag, s.Session) 688 } 689 690 type mongoPasswordSetter interface { 691 SetMongoPassword(password string) error 692 Tag() names.Tag 693 } 694 695 type mongoPasswordSetterGetter func(st *state.State, id string) (mongoPasswordSetter, error) 696 697 func testSetMongoPassword( 698 c *gc.C, entityFunc mongoPasswordSetterGetter, 699 controllerTag names.ControllerTag, modelTag names.ModelTag, mgoSession *mgo.Session, 700 ) { 701 pool, err := state.OpenStatePool(state.OpenParams{ 702 Clock: clock.WallClock, 703 ControllerTag: controllerTag, 704 ControllerModelTag: modelTag, 705 MongoSession: mgoSession, 706 }) 707 c.Assert(err, jc.ErrorIsNil) 708 st, err := pool.SystemState() 709 c.Assert(err, jc.ErrorIsNil) 710 defer func() { 711 // Remove the admin password so that the test harness can reset the state. 712 err := st.SetAdminMongoPassword("") 713 c.Check(err, jc.ErrorIsNil) 714 err = pool.Close() 715 c.Check(err, jc.ErrorIsNil) 716 }() 717 718 // Turn on fully-authenticated mode. 719 err = st.SetAdminMongoPassword("admin-secret") 720 c.Assert(err, jc.ErrorIsNil) 721 err = st.MongoSession().DB("admin").Login("admin", "admin-secret") 722 c.Assert(err, jc.ErrorIsNil) 723 724 // Set the password for the entity 725 ent, err := entityFunc(st, "0") 726 c.Assert(err, jc.ErrorIsNil) 727 err = ent.SetMongoPassword("foo") 728 c.Assert(err, jc.ErrorIsNil) 729 730 // Check that we cannot log in with the wrong password. 731 info := testing.NewMongoInfo() 732 info.Tag = ent.Tag() 733 info.Password = "bar" 734 err = tryOpenState(modelTag, controllerTag, info) 735 c.Check(errors.Cause(err), jc.Satisfies, errors.IsUnauthorized) 736 c.Check(err, gc.ErrorMatches, `cannot log in to admin database as "(machine|controller)-0": unauthorized mongo access: .*`) 737 738 // Check that we can log in with the correct password. 739 info.Password = "foo" 740 session, err := mongo.DialWithInfo(*info, mongotest.DialOpts()) 741 c.Assert(err, jc.ErrorIsNil) 742 defer session.Close() 743 744 pool1, err := state.OpenStatePool(state.OpenParams{ 745 Clock: clock.WallClock, 746 ControllerTag: controllerTag, 747 ControllerModelTag: modelTag, 748 MongoSession: session, 749 }) 750 c.Assert(err, jc.ErrorIsNil) 751 defer pool1.Close() 752 st1, err := pool1.SystemState() 753 c.Assert(err, jc.ErrorIsNil) 754 755 // Change the password with an entity derived from the newly 756 // opened and authenticated state. 757 ent, err = entityFunc(st1, "0") 758 c.Assert(err, jc.ErrorIsNil) 759 err = ent.SetMongoPassword("bar") 760 c.Assert(err, jc.ErrorIsNil) 761 762 // Check that we cannot log in with the old password. 763 info.Password = "foo" 764 err = tryOpenState(modelTag, controllerTag, info) 765 c.Check(errors.Cause(err), jc.Satisfies, errors.IsUnauthorized) 766 c.Check(err, gc.ErrorMatches, `cannot log in to admin database as "(machine|controller)-0": unauthorized mongo access: .*`) 767 768 // Check that we can log in with the correct password. 769 info.Password = "bar" 770 err = tryOpenState(modelTag, controllerTag, info) 771 c.Assert(err, jc.ErrorIsNil) 772 773 // Check that the administrator can still log in. 774 info.Tag, info.Password = nil, "admin-secret" 775 err = tryOpenState(modelTag, controllerTag, info) 776 c.Assert(err, jc.ErrorIsNil) 777 } 778 779 func (s *MachineSuite) TestSetPassword(c *gc.C) { 780 testSetPassword(c, func() (state.Authenticator, error) { 781 return s.State.Machine(s.machine.Id()) 782 }) 783 } 784 785 func (s *MachineSuite) TestMachineInstanceIdCorrupt(c *gc.C) { 786 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 787 c.Assert(err, jc.ErrorIsNil) 788 err = s.machines.Update( 789 bson.D{{"_id", state.DocID(s.State, machine.Id())}}, 790 bson.D{{"$set", bson.D{{"instanceid", bson.D{{"foo", "bar"}}}}}}, 791 ) 792 c.Assert(err, jc.ErrorIsNil) 793 794 err = machine.Refresh() 795 c.Assert(err, jc.ErrorIsNil) 796 iid, err := machine.InstanceId() 797 c.Assert(err, jc.Satisfies, errors.IsNotProvisioned) 798 c.Assert(iid, gc.Equals, instance.Id("")) 799 } 800 801 func (s *MachineSuite) TestMachineInstanceIdMissing(c *gc.C) { 802 iid, err := s.machine.InstanceId() 803 c.Assert(err, jc.Satisfies, errors.IsNotProvisioned) 804 c.Assert(string(iid), gc.Equals, "") 805 } 806 807 func (s *MachineSuite) TestMachineInstanceIdBlank(c *gc.C) { 808 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 809 c.Assert(err, jc.ErrorIsNil) 810 err = s.machines.Update( 811 bson.D{{"_id", state.DocID(s.State, machine.Id())}}, 812 bson.D{{"$set", bson.D{{"instanceid", ""}}}}, 813 ) 814 c.Assert(err, jc.ErrorIsNil) 815 816 err = machine.Refresh() 817 c.Assert(err, jc.ErrorIsNil) 818 iid, err := machine.InstanceId() 819 c.Assert(err, jc.Satisfies, errors.IsNotProvisioned) 820 c.Assert(string(iid), gc.Equals, "") 821 } 822 823 func (s *MachineSuite) TestMachineSetProvisionedStoresAndInstanceNamesReturnsDisplayName(c *gc.C) { 824 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse) 825 err := s.machine.SetProvisioned("umbrella/0", "snowflake", "fake_nonce", nil) 826 c.Assert(err, jc.ErrorIsNil) 827 828 iid, iname, err := s.machine.InstanceNames() 829 c.Assert(err, jc.ErrorIsNil) 830 c.Assert(string(iid), gc.Equals, "umbrella/0") 831 c.Assert(iname, gc.Equals, "snowflake") 832 833 all, err := s.Model.AllInstanceData() 834 c.Assert(err, jc.ErrorIsNil) 835 iid, iname = all.InstanceNames(s.machine.Id()) 836 c.Assert(string(iid), gc.Equals, "umbrella/0") 837 c.Assert(iname, gc.Equals, "snowflake") 838 } 839 840 func (s *MachineSuite) TestMachineInstanceNamesReturnsIsNotProvisionedWhenNotProvisioned(c *gc.C) { 841 iid, iname, err := s.machine.InstanceNames() 842 c.Assert(err, jc.Satisfies, errors.IsNotProvisioned) 843 c.Assert(string(iid), gc.Equals, "") 844 c.Assert(iname, gc.Equals, "") 845 } 846 847 func (s *MachineSuite) TestMachineSetProvisionedUpdatesCharacteristics(c *gc.C) { 848 // Before provisioning, there is no hardware characteristics. 849 _, err := s.machine.HardwareCharacteristics() 850 c.Assert(err, jc.Satisfies, errors.IsNotFound) 851 arch := arch.DefaultArchitecture 852 mem := uint64(4096) 853 expected := &instance.HardwareCharacteristics{ 854 Arch: &arch, 855 Mem: &mem, 856 } 857 err = s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", expected) 858 c.Assert(err, jc.ErrorIsNil) 859 md, err := s.machine.HardwareCharacteristics() 860 c.Assert(err, jc.ErrorIsNil) 861 c.Assert(*md, gc.DeepEquals, *expected) 862 863 // Reload machine and check again. 864 err = s.machine.Refresh() 865 c.Assert(err, jc.ErrorIsNil) 866 md, err = s.machine.HardwareCharacteristics() 867 c.Assert(err, jc.ErrorIsNil) 868 c.Assert(*md, gc.DeepEquals, *expected) 869 870 all, err := s.Model.AllInstanceData() 871 c.Assert(err, jc.ErrorIsNil) 872 md = all.HardwareCharacteristics(s.machine.Id()) 873 c.Assert(*md, gc.DeepEquals, *expected) 874 } 875 876 func (s *MachineSuite) TestMachineCharmProfiles(c *gc.C) { 877 hwc := &instance.HardwareCharacteristics{} 878 err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", hwc) 879 c.Assert(err, jc.ErrorIsNil) 880 881 profiles := []string{"secure", "magic"} 882 err = s.machine.SetCharmProfiles(profiles) 883 c.Assert(err, jc.ErrorIsNil) 884 885 saved, err := s.machine.CharmProfiles() 886 c.Assert(err, jc.ErrorIsNil) 887 c.Assert(saved, jc.SameContents, profiles) 888 889 all, err := s.Model.AllInstanceData() 890 c.Assert(err, jc.ErrorIsNil) 891 saved = all.CharmProfiles(s.machine.Id()) 892 c.Assert(saved, jc.SameContents, profiles) 893 } 894 895 func (s *MachineSuite) TestMachineAvailabilityZone(c *gc.C) { 896 zone := "a_zone" 897 hwc := &instance.HardwareCharacteristics{ 898 AvailabilityZone: &zone, 899 } 900 err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", hwc) 901 c.Assert(err, jc.ErrorIsNil) 902 903 zone, err = s.machine.AvailabilityZone() 904 c.Assert(err, jc.ErrorIsNil) 905 c.Check(zone, gc.Equals, "a_zone") 906 } 907 908 func (s *MachineSuite) TestContainerAvailabilityZone(c *gc.C) { 909 zone := "a_zone" 910 hwc := &instance.HardwareCharacteristics{ 911 AvailabilityZone: &zone, 912 } 913 err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", hwc) 914 c.Assert(err, jc.ErrorIsNil) 915 916 zone, err = s.machine.AvailabilityZone() 917 c.Assert(err, jc.ErrorIsNil) 918 c.Check(zone, gc.Equals, "a_zone") 919 920 // now add a container to that machine 921 container := s.Factory.MakeMachineNested(c, s.machine.Id(), nil) 922 c.Assert(err, jc.ErrorIsNil) 923 924 containerAvailabilityZone, err := container.AvailabilityZone() 925 c.Assert(err, jc.ErrorIsNil) 926 c.Assert(containerAvailabilityZone, gc.Equals, "") 927 } 928 929 func (s *MachineSuite) TestMachineAvailabilityZoneEmpty(c *gc.C) { 930 zone := "" 931 hwc := &instance.HardwareCharacteristics{ 932 AvailabilityZone: &zone, 933 } 934 err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", hwc) 935 c.Assert(err, jc.ErrorIsNil) 936 937 zone, err = s.machine.AvailabilityZone() 938 c.Assert(err, jc.ErrorIsNil) 939 c.Check(zone, gc.Equals, "") 940 } 941 942 func (s *MachineSuite) TestMachineAvailabilityZoneMissing(c *gc.C) { 943 hwc := &instance.HardwareCharacteristics{} 944 err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", hwc) 945 c.Assert(err, jc.ErrorIsNil) 946 947 zone, err := s.machine.AvailabilityZone() 948 c.Assert(err, jc.ErrorIsNil) 949 c.Check(zone, gc.Equals, "") 950 } 951 952 func (s *MachineSuite) TestMachineSetCheckProvisioned(c *gc.C) { 953 // Check before provisioning. 954 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse) 955 956 // Either one should not be empty. 957 err := s.machine.SetProvisioned("umbrella/0", "", "", nil) 958 c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`) 959 err = s.machine.SetProvisioned(instance.Id(""), "", "fake_nonce", nil) 960 c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`) 961 err = s.machine.SetProvisioned(instance.Id(""), "", "", nil) 962 c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`) 963 964 err = s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", nil) 965 c.Assert(err, jc.ErrorIsNil) 966 967 m, err := s.State.Machine(s.machine.Id()) 968 c.Assert(err, jc.ErrorIsNil) 969 id, err := m.InstanceId() 970 c.Assert(err, jc.ErrorIsNil) 971 c.Assert(string(id), gc.Equals, "umbrella/0") 972 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue) 973 id, err = s.machine.InstanceId() 974 c.Assert(err, jc.ErrorIsNil) 975 c.Assert(string(id), gc.Equals, "umbrella/0") 976 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue) 977 978 // Try it twice, it should fail. 979 err = s.machine.SetProvisioned(instance.Id("doesn't-matter"), "", "phony", nil) 980 c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": already set`) 981 982 // Check it with invalid nonce. 983 c.Assert(s.machine.CheckProvisioned("not-really"), jc.IsFalse) 984 } 985 986 func (s *MachineSuite) TestSetProvisionedDupInstanceId(c *gc.C) { 987 var logWriter loggo.TestWriter 988 c.Assert(loggo.RegisterWriter("dupe-test", &logWriter), gc.IsNil) 989 s.AddCleanup(func(*gc.C) { 990 _, _ = loggo.RemoveWriter("dupe-test") 991 }) 992 993 err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", nil) 994 c.Assert(err, jc.ErrorIsNil) 995 996 anotherMachine, _ := s.Factory.MakeUnprovisionedMachineReturningPassword(c, &factory.MachineParams{}) 997 err = anotherMachine.SetProvisioned("umbrella/0", "", "another_nonce", nil) 998 c.Assert(err, jc.ErrorIsNil) 999 found := false 1000 for _, le := range logWriter.Log() { 1001 if found = strings.Contains(le.Message, "duplicate instance id"); found == true { 1002 break 1003 } 1004 } 1005 c.Assert(found, jc.IsTrue) 1006 } 1007 1008 func (s *MachineSuite) TestMachineSetInstanceInfoFailureDoesNotProvision(c *gc.C) { 1009 assertNotProvisioned := func() { 1010 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse) 1011 } 1012 1013 assertNotProvisioned() 1014 1015 invalidVolumes := map[names.VolumeTag]state.VolumeInfo{ 1016 names.NewVolumeTag("1065"): {VolumeId: "vol-ume"}, 1017 } 1018 err := s.machine.SetInstanceInfo("umbrella/0", "", "fake_nonce", nil, nil, nil, invalidVolumes, nil, nil) 1019 c.Assert(err, gc.ErrorMatches, `cannot set info for volume \"1065\": volume \"1065\" not found`) 1020 assertNotProvisioned() 1021 1022 invalidVolumes = map[names.VolumeTag]state.VolumeInfo{ 1023 names.NewVolumeTag("1065"): {}, 1024 } 1025 err = s.machine.SetInstanceInfo("umbrella/0", "", "fake_nonce", nil, nil, nil, invalidVolumes, nil, nil) 1026 c.Assert(err, gc.ErrorMatches, `cannot set info for volume \"1065\": volume ID not set`) 1027 assertNotProvisioned() 1028 1029 // TODO(axw) test invalid volume attachment 1030 } 1031 1032 func (s *MachineSuite) addVolume(c *gc.C, params state.VolumeParams, machineId string) names.VolumeTag { 1033 ops, tag, err := state.AddVolumeOps(s.State, params, machineId) 1034 c.Assert(err, jc.ErrorIsNil) 1035 state.RunTransaction(c, s.State, ops) 1036 return tag 1037 } 1038 1039 func (s *MachineSuite) TestMachineSetInstanceInfoSuccess(c *gc.C) { 1040 pm := poolmanager.New(state.NewStateSettings(s.State), storage.ChainedProviderRegistry{ 1041 dummystorage.StorageProviders(), 1042 provider.CommonStorageProviders(), 1043 }) 1044 _, err := pm.Create("loop-pool", provider.LoopProviderType, map[string]interface{}{}) 1045 c.Assert(err, jc.ErrorIsNil) 1046 1047 // Must create the requested block device prior to SetInstanceInfo. 1048 volumeTag := s.addVolume(c, state.VolumeParams{Size: 1000, Pool: "loop-pool"}, "123") 1049 c.Assert(volumeTag, gc.Equals, names.NewVolumeTag("123/0")) 1050 1051 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse) 1052 volumeInfo := state.VolumeInfo{ 1053 VolumeId: "storage-123", 1054 Size: 1234, 1055 } 1056 volumes := map[names.VolumeTag]state.VolumeInfo{volumeTag: volumeInfo} 1057 err = s.machine.SetInstanceInfo("umbrella/0", "", "fake_nonce", nil, nil, nil, volumes, nil, nil) 1058 c.Assert(err, jc.ErrorIsNil) 1059 c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue) 1060 1061 sb, err := state.NewStorageBackend(s.State) 1062 c.Assert(err, jc.ErrorIsNil) 1063 volume, err := sb.Volume(volumeTag) 1064 c.Assert(err, jc.ErrorIsNil) 1065 info, err := volume.Info() 1066 c.Assert(err, jc.ErrorIsNil) 1067 volumeInfo.Pool = "loop-pool" // taken from params 1068 c.Assert(info, gc.Equals, volumeInfo) 1069 volumeStatus, err := volume.Status() 1070 c.Assert(err, jc.ErrorIsNil) 1071 c.Assert(volumeStatus.Status, gc.Equals, status.Attaching) 1072 } 1073 1074 func (s *MachineSuite) TestMachineSetProvisionedWhenNotAlive(c *gc.C) { 1075 testWhenDying(c, s.machine, notAliveErr, notAliveErr, func() error { 1076 return s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", nil) 1077 }) 1078 } 1079 1080 func (s *MachineSuite) TestMachineSetInstanceStatus(c *gc.C) { 1081 // Machine needs to be provisioned first. 1082 err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", nil) 1083 c.Assert(err, jc.ErrorIsNil) 1084 1085 now := coretesting.ZeroTime() 1086 sInfo := status.StatusInfo{ 1087 Status: status.Running, 1088 Message: "alive", 1089 Since: &now, 1090 } 1091 err = s.machine.SetInstanceStatus(sInfo) 1092 c.Assert(err, jc.ErrorIsNil) 1093 1094 // Reload machine and check result. 1095 err = s.machine.Refresh() 1096 c.Assert(err, jc.ErrorIsNil) 1097 machineStatus, err := s.machine.InstanceStatus() 1098 c.Assert(err, jc.ErrorIsNil) 1099 c.Assert(machineStatus.Status, gc.DeepEquals, status.Running) 1100 c.Assert(machineStatus.Message, gc.DeepEquals, "alive") 1101 } 1102 1103 func (s *MachineSuite) TestMachineSetModificationStatus(c *gc.C) { 1104 // Machine needs to be provisioned first. 1105 err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", nil) 1106 c.Assert(err, jc.ErrorIsNil) 1107 1108 now := coretesting.ZeroTime() 1109 sInfo := status.StatusInfo{ 1110 Status: status.Applied, 1111 Message: "applied", 1112 Since: &now, 1113 } 1114 err = s.machine.SetModificationStatus(sInfo) 1115 c.Assert(err, jc.ErrorIsNil) 1116 1117 // Reload machine and check result. 1118 err = s.machine.Refresh() 1119 c.Assert(err, jc.ErrorIsNil) 1120 machineStatus, err := s.machine.ModificationStatus() 1121 c.Assert(err, jc.ErrorIsNil) 1122 c.Assert(machineStatus.Status, gc.DeepEquals, status.Applied) 1123 c.Assert(machineStatus.Message, gc.DeepEquals, "applied") 1124 } 1125 1126 func (s *MachineSuite) TestMachineRefresh(c *gc.C) { 1127 m0, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1128 c.Assert(err, jc.ErrorIsNil) 1129 oldTools, _ := m0.AgentTools() 1130 m1, err := s.State.Machine(m0.Id()) 1131 c.Assert(err, jc.ErrorIsNil) 1132 err = m0.SetAgentVersion(version.MustParseBinary("0.0.3-ubuntu-amd64")) 1133 c.Assert(err, jc.ErrorIsNil) 1134 newTools, _ := m0.AgentTools() 1135 1136 m1Tools, _ := m1.AgentTools() 1137 c.Assert(m1Tools, gc.DeepEquals, oldTools) 1138 err = m1.Refresh() 1139 c.Assert(err, jc.ErrorIsNil) 1140 m1Tools, _ = m1.AgentTools() 1141 c.Assert(*m1Tools, gc.Equals, *newTools) 1142 1143 err = m0.EnsureDead() 1144 c.Assert(err, jc.ErrorIsNil) 1145 err = m0.Remove() 1146 c.Assert(err, jc.ErrorIsNil) 1147 err = m0.Refresh() 1148 c.Assert(err, jc.Satisfies, errors.IsNotFound) 1149 } 1150 1151 func (s *MachineSuite) TestRefreshWhenNotAlive(c *gc.C) { 1152 // Refresh should work regardless of liveness status. 1153 testWhenDying(c, s.machine, noErr, noErr, func() error { 1154 return s.machine.Refresh() 1155 }) 1156 } 1157 1158 func (s *MachineSuite) TestMachinePrincipalUnits(c *gc.C) { 1159 // Check that Machine.Units and st.UnitsFor work correctly. 1160 1161 // Make three machines, three applications and three units for each application; 1162 // variously assign units to machines and check that Machine.Units 1163 // tells us the right thing. 1164 1165 m1 := s.machine 1166 m2, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1167 c.Assert(err, jc.ErrorIsNil) 1168 m3, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1169 c.Assert(err, jc.ErrorIsNil) 1170 1171 dummy := s.AddTestingCharm(c, "dummy") 1172 logging := s.AddTestingCharm(c, "logging") 1173 s0 := s.AddTestingApplication(c, "s0", dummy) 1174 s1 := s.AddTestingApplication(c, "s1", dummy) 1175 s2 := s.AddTestingApplication(c, "s2", dummy) 1176 s3 := s.AddTestingApplication(c, "s3", logging) 1177 1178 units := make([][]*state.Unit, 4) 1179 for i, app := range []*state.Application{s0, s1, s2} { 1180 units[i] = make([]*state.Unit, 3) 1181 for j := range units[i] { 1182 units[i][j], err = app.AddUnit(state.AddUnitParams{}) 1183 c.Assert(err, jc.ErrorIsNil) 1184 } 1185 } 1186 1187 // Principals must be assigned to a machine before then 1188 // enter scope to create subordinates. 1189 assignments := []struct { 1190 machine *state.Machine 1191 units []*state.Unit 1192 subordinates []*state.Unit 1193 }{ 1194 {m1, []*state.Unit{units[0][0]}, nil}, 1195 {m2, []*state.Unit{units[0][1], units[1][0], units[1][1], units[2][0]}, nil}, 1196 {m3, []*state.Unit{units[2][2]}, nil}, 1197 } 1198 1199 for _, a := range assignments { 1200 for _, u := range a.units { 1201 err := u.AssignToMachine(a.machine) 1202 c.Assert(err, jc.ErrorIsNil) 1203 } 1204 } 1205 1206 // Add the logging units subordinate to the s2 units. 1207 eps, err := s.State.InferEndpoints("s2", "s3") 1208 c.Assert(err, jc.ErrorIsNil) 1209 rel, err := s.State.AddRelation(eps...) 1210 c.Assert(err, jc.ErrorIsNil) 1211 for _, u := range units[2] { 1212 ru, err := rel.Unit(u) 1213 c.Assert(err, jc.ErrorIsNil) 1214 err = ru.EnterScope(nil) 1215 c.Assert(err, jc.ErrorIsNil) 1216 } 1217 units[3], err = s3.AllUnits() 1218 c.Assert(err, jc.ErrorIsNil) 1219 c.Assert(sortedUnitNames(units[3]), jc.DeepEquals, []string{"s3/0", "s3/1", "s3/2"}) 1220 assignments[1].subordinates = []*state.Unit{units[3][0]} 1221 assignments[2].subordinates = []*state.Unit{units[3][2]} 1222 1223 for i, a := range assignments { 1224 c.Logf("test %d", i) 1225 expect := sortedUnitNames(append(a.units, a.subordinates...)) 1226 1227 // The units can be retrieved from the machine model. 1228 got, err := a.machine.Units() 1229 c.Assert(err, jc.ErrorIsNil) 1230 c.Assert(sortedUnitNames(got), jc.DeepEquals, expect) 1231 1232 // The units can be retrieved from the machine id. 1233 got, err = s.State.UnitsFor(a.machine.Id()) 1234 c.Assert(err, jc.ErrorIsNil) 1235 c.Assert(sortedUnitNames(got), jc.DeepEquals, expect) 1236 } 1237 } 1238 1239 func sortedUnitNames(units []*state.Unit) []string { 1240 names := make([]string, len(units)) 1241 for i, u := range units { 1242 names[i] = u.Name() 1243 } 1244 sort.Strings(names) 1245 return names 1246 } 1247 1248 func (s *MachineSuite) assertMachineDirtyAfterAddingUnit(c *gc.C) (*state.Machine, *state.Application, *state.Unit) { 1249 m, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1250 c.Assert(err, jc.ErrorIsNil) 1251 c.Assert(m.Clean(), jc.IsTrue) 1252 1253 app := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 1254 unit, err := app.AddUnit(state.AddUnitParams{}) 1255 c.Assert(err, jc.ErrorIsNil) 1256 err = unit.AssignToMachine(m) 1257 c.Assert(err, jc.ErrorIsNil) 1258 c.Assert(m.Clean(), jc.IsFalse) 1259 return m, app, unit 1260 } 1261 1262 func (s *MachineSuite) TestMachineDirtyAfterAddingUnit(c *gc.C) { 1263 s.assertMachineDirtyAfterAddingUnit(c) 1264 } 1265 1266 func (s *MachineSuite) TestMachineDirtyAfterUnassigningUnit(c *gc.C) { 1267 m, _, unit := s.assertMachineDirtyAfterAddingUnit(c) 1268 err := unit.UnassignFromMachine() 1269 c.Assert(err, jc.ErrorIsNil) 1270 c.Assert(m.Clean(), jc.IsFalse) 1271 } 1272 1273 func (s *MachineSuite) TestMachineDirtyAfterRemovingUnit(c *gc.C) { 1274 m, app, unit := s.assertMachineDirtyAfterAddingUnit(c) 1275 err := unit.EnsureDead() 1276 c.Assert(err, jc.ErrorIsNil) 1277 err = unit.Remove() 1278 c.Assert(err, jc.ErrorIsNil) 1279 err = app.Destroy() 1280 c.Assert(err, jc.ErrorIsNil) 1281 c.Assert(m.Clean(), jc.IsFalse) 1282 } 1283 1284 func (s *MachineSuite) TestWatchMachine(c *gc.C) { 1285 s.WaitForModelWatchersIdle(c, s.Model.UUID()) 1286 w := s.machine.Watch() 1287 defer testing.AssertStop(c, w) 1288 1289 // Initial event. 1290 wc := testing.NewNotifyWatcherC(c, w) 1291 wc.AssertOneChange() 1292 1293 // Make one change (to a separate instance), check one event. 1294 machine, err := s.State.Machine(s.machine.Id()) 1295 c.Assert(err, jc.ErrorIsNil) 1296 err = machine.SetProvisioned(instance.Id("m-foo"), "", "fake_nonce", nil) 1297 c.Assert(err, jc.ErrorIsNil) 1298 wc.AssertOneChange() 1299 1300 // Make two changes, check one event. 1301 err = machine.SetAgentVersion(version.MustParseBinary("0.0.3-ubuntu-amd64")) 1302 c.Assert(err, jc.ErrorIsNil) 1303 // TODO(quiescence): these two changes should be one event. 1304 wc.AssertOneChange() 1305 err = machine.Destroy() 1306 c.Assert(err, jc.ErrorIsNil) 1307 wc.AssertOneChange() 1308 1309 // Stop, check closed. 1310 testing.AssertStop(c, w) 1311 wc.AssertClosed() 1312 1313 // Remove machine, start new watch, check single event. 1314 err = machine.EnsureDead() 1315 c.Assert(err, jc.ErrorIsNil) 1316 err = machine.Remove() 1317 c.Assert(err, jc.ErrorIsNil) 1318 s.WaitForModelWatchersIdle(c, s.Model.UUID()) 1319 w = s.machine.Watch() 1320 defer testing.AssertStop(c, w) 1321 testing.NewNotifyWatcherC(c, w).AssertOneChange() 1322 } 1323 1324 func (s *MachineSuite) TestWatchDiesOnStateClose(c *gc.C) { 1325 // This test is testing logic in watcher.entityWatcher, which 1326 // is also used by: 1327 // Machine.WatchInstanceData 1328 // Application.Watch 1329 // Unit.Watch 1330 // State.WatchForModelConfigChanges 1331 // Unit.WatchConfigSettings 1332 testWatcherDiesWhenStateCloses(c, s.Session, s.modelTag, s.State.ControllerTag(), func(c *gc.C, st *state.State) waiter { 1333 m, err := st.Machine(s.machine.Id()) 1334 c.Assert(err, jc.ErrorIsNil) 1335 w := m.Watch() 1336 select { 1337 case <-w.Changes(): 1338 case <-time.After(coretesting.LongWait): 1339 c.Errorf("timeout waiting for Changes() to trigger") 1340 } 1341 return w 1342 }) 1343 } 1344 1345 func (s *MachineSuite) TestWatchPrincipalUnits(c *gc.C) { 1346 // TODO(mjs) - MODELUUID - test with multiple models with 1347 // identically named units and ensure there's no leakage. 1348 1349 s.WaitForModelWatchersIdle(c, s.Model.UUID()) 1350 // Start a watch on an empty machine; check no units reported. 1351 w := s.machine.WatchPrincipalUnits() 1352 defer testing.AssertStop(c, w) 1353 wc := testing.NewStringsWatcherC(c, w) 1354 wc.AssertChange() 1355 wc.AssertNoChange() 1356 1357 // Change machine, and create a unit independently; no change. 1358 err := s.machine.SetProvisioned("cheese", "", "fake_nonce", nil) 1359 c.Assert(err, jc.ErrorIsNil) 1360 wc.AssertNoChange() 1361 mysql := s.AddTestingApplication(c, "mysql", s.AddTestingCharm(c, "mysql")) 1362 mysql0, err := mysql.AddUnit(state.AddUnitParams{}) 1363 c.Assert(err, jc.ErrorIsNil) 1364 wc.AssertNoChange() 1365 1366 // Assign that unit (to a separate machine instance); change detected. 1367 machine, err := s.State.Machine(s.machine.Id()) 1368 c.Assert(err, jc.ErrorIsNil) 1369 err = mysql0.AssignToMachine(machine) 1370 c.Assert(err, jc.ErrorIsNil) 1371 wc.AssertChange("mysql/0") 1372 wc.AssertNoChange() 1373 1374 // Change the unit; no change. 1375 now := coretesting.ZeroTime() 1376 sInfo := status.StatusInfo{ 1377 Status: status.Idle, 1378 Message: "", 1379 Since: &now, 1380 } 1381 err = mysql0.SetAgentStatus(sInfo) 1382 c.Assert(err, jc.ErrorIsNil) 1383 wc.AssertNoChange() 1384 1385 // Assign another unit and make the first Dying; check both changes detected. 1386 c.Logf("assigning unit and destroying other") 1387 mysql1, err := mysql.AddUnit(state.AddUnitParams{}) 1388 c.Assert(err, jc.ErrorIsNil) 1389 err = mysql1.AssignToMachine(machine) 1390 c.Assert(err, jc.ErrorIsNil) 1391 err = mysql0.Destroy() 1392 c.Assert(err, jc.ErrorIsNil) 1393 wc.AssertChange("mysql/0", "mysql/1") 1394 wc.AssertNoChange() 1395 1396 // Add a subordinate to the Alive unit; no change. 1397 s.AddTestingApplication(c, "logging", s.AddTestingCharm(c, "logging")) 1398 eps, err := s.State.InferEndpoints("mysql", "logging") 1399 c.Assert(err, jc.ErrorIsNil) 1400 rel, err := s.State.AddRelation(eps...) 1401 c.Assert(err, jc.ErrorIsNil) 1402 mysqlru1, err := rel.Unit(mysql1) 1403 c.Assert(err, jc.ErrorIsNil) 1404 err = mysqlru1.EnterScope(nil) 1405 c.Assert(err, jc.ErrorIsNil) 1406 logging0, err := s.State.Unit("logging/0") 1407 c.Assert(err, jc.ErrorIsNil) 1408 wc.AssertNoChange() 1409 1410 // Change the subordinate; no change. 1411 sInfo = status.StatusInfo{ 1412 Status: status.Idle, 1413 Message: "", 1414 Since: &now, 1415 } 1416 err = logging0.SetAgentStatus(sInfo) 1417 c.Assert(err, jc.ErrorIsNil) 1418 wc.AssertNoChange() 1419 1420 // Make the Dying unit Dead; change detected. 1421 err = mysql0.EnsureDead() 1422 c.Assert(err, jc.ErrorIsNil) 1423 wc.AssertChange("mysql/0") 1424 wc.AssertNoChange() 1425 1426 // Stop watcher; check Changes chan closed. 1427 testing.AssertStop(c, w) 1428 wc.AssertClosed() 1429 1430 s.WaitForModelWatchersIdle(c, s.Model.UUID()) 1431 // Start a fresh watcher; check both principals reported. 1432 w = s.machine.WatchPrincipalUnits() 1433 defer testing.AssertStop(c, w) 1434 wc = testing.NewStringsWatcherC(c, w) 1435 wc.AssertChange("mysql/0", "mysql/1") 1436 wc.AssertNoChange() 1437 1438 // Remove the Dead unit; no change. 1439 err = mysql0.Remove() 1440 c.Assert(err, jc.ErrorIsNil) 1441 wc.AssertNoChange() 1442 1443 // Destroy the subordinate; no change. 1444 err = logging0.Destroy() 1445 c.Assert(err, jc.ErrorIsNil) 1446 wc.AssertNoChange() 1447 1448 // Unassign the unit; check change. 1449 err = mysql1.UnassignFromMachine() 1450 c.Assert(err, jc.ErrorIsNil) 1451 wc.AssertChange("mysql/1") 1452 wc.AssertNoChange() 1453 } 1454 1455 func (s *MachineSuite) TestWatchPrincipalUnitsDiesOnStateClose(c *gc.C) { 1456 // This test is testing logic in watcher.unitsWatcher, which 1457 // is also used by Unit.WatchSubordinateUnits. 1458 testWatcherDiesWhenStateCloses(c, s.Session, s.modelTag, s.State.ControllerTag(), func(c *gc.C, st *state.State) waiter { 1459 m, err := st.Machine(s.machine.Id()) 1460 c.Assert(err, jc.ErrorIsNil) 1461 w := m.WatchPrincipalUnits() 1462 <-w.Changes() 1463 return w 1464 }) 1465 } 1466 1467 func (s *MachineSuite) TestWatchUnits(c *gc.C) { 1468 s.WaitForModelWatchersIdle(c, s.Model.UUID()) 1469 // Start a watch on an empty machine; check no units reported. 1470 w := s.machine.WatchUnits() 1471 defer testing.AssertStop(c, w) 1472 wc := testing.NewStringsWatcherC(c, w) 1473 wc.AssertChange() 1474 wc.AssertNoChange() 1475 1476 // Change machine; no change. 1477 err := s.machine.SetProvisioned("cheese", "", "fake_nonce", nil) 1478 c.Assert(err, jc.ErrorIsNil) 1479 wc.AssertNoChange() 1480 1481 // Assign a unit (to a separate instance); change detected. 1482 c.Logf("assigning mysql to machine %s", s.machine.Id()) 1483 mysql := s.AddTestingApplication(c, "mysql", s.AddTestingCharm(c, "mysql")) 1484 mysql0, err := mysql.AddUnit(state.AddUnitParams{}) 1485 c.Assert(err, jc.ErrorIsNil) 1486 machine, err := s.State.Machine(s.machine.Id()) 1487 c.Assert(err, jc.ErrorIsNil) 1488 err = mysql0.AssignToMachine(machine) 1489 c.Assert(err, jc.ErrorIsNil) 1490 wc.AssertChange("mysql/0") 1491 wc.AssertNoChange() 1492 1493 // Change the unit; no change. 1494 c.Logf("changing unit mysql/0") 1495 now := coretesting.ZeroTime() 1496 sInfo := status.StatusInfo{ 1497 Status: status.Idle, 1498 Message: "", 1499 Since: &now, 1500 } 1501 err = mysql0.SetAgentStatus(sInfo) 1502 c.Assert(err, jc.ErrorIsNil) 1503 wc.AssertNoChange() 1504 1505 // Assign another unit and make the first Dying; check both changes detected. 1506 c.Logf("assigning mysql/1, destroying mysql/0") 1507 mysql1, err := mysql.AddUnit(state.AddUnitParams{}) 1508 c.Assert(err, jc.ErrorIsNil) 1509 err = mysql1.AssignToMachine(machine) 1510 c.Assert(err, jc.ErrorIsNil) 1511 err = mysql0.Destroy() 1512 c.Assert(err, jc.ErrorIsNil) 1513 wc.AssertChange("mysql/0", "mysql/1") 1514 wc.AssertNoChange() 1515 1516 // Add a subordinate to the Alive unit; change detected. 1517 c.Logf("adding subordinate logging/0") 1518 s.AddTestingApplication(c, "logging", s.AddTestingCharm(c, "logging")) 1519 eps, err := s.State.InferEndpoints("mysql", "logging") 1520 c.Assert(err, jc.ErrorIsNil) 1521 rel, err := s.State.AddRelation(eps...) 1522 c.Assert(err, jc.ErrorIsNil) 1523 mysqlru1, err := rel.Unit(mysql1) 1524 c.Assert(err, jc.ErrorIsNil) 1525 err = mysqlru1.EnterScope(nil) 1526 c.Assert(err, jc.ErrorIsNil) 1527 logging0, err := s.State.Unit("logging/0") 1528 c.Assert(err, jc.ErrorIsNil) 1529 wc.AssertChange("logging/0") 1530 wc.AssertNoChange() 1531 1532 // Change the subordinate; no change. 1533 c.Logf("changing subordinate") 1534 sInfo = status.StatusInfo{ 1535 Status: status.Idle, 1536 Message: "", 1537 Since: &now, 1538 } 1539 err = logging0.SetAgentStatus(sInfo) 1540 c.Assert(err, jc.ErrorIsNil) 1541 wc.AssertNoChange() 1542 1543 // Make the Dying unit Dead; change detected. 1544 c.Logf("ensuring mysql/0 is Dead") 1545 err = mysql0.EnsureDead() 1546 c.Assert(err, jc.ErrorIsNil) 1547 wc.AssertChange("mysql/0") 1548 wc.AssertNoChange() 1549 1550 // Stop watcher; check Changes chan closed. 1551 testing.AssertStop(c, w) 1552 wc.AssertClosed() 1553 1554 // Start a fresh watcher; check all units reported. 1555 c.Logf("starting new watcher") 1556 w = s.machine.WatchUnits() 1557 defer testing.AssertStop(c, w) 1558 wc = testing.NewStringsWatcherC(c, w) 1559 wc.AssertChange("mysql/0", "mysql/1", "logging/0") 1560 wc.AssertNoChange() 1561 1562 // Remove the Dead unit; no change. 1563 c.Logf("removing Dead unit mysql/0") 1564 err = mysql0.Remove() 1565 c.Assert(err, jc.ErrorIsNil) 1566 wc.AssertNoChange() 1567 1568 // Destroy the subordinate; change detected. 1569 c.Logf("destroying subordinate logging/0") 1570 err = logging0.Destroy() 1571 c.Assert(err, jc.ErrorIsNil) 1572 wc.AssertChange("logging/0") 1573 wc.AssertNoChange() 1574 1575 // Unassign the principal; check subordinate departure also reported. 1576 c.Logf("unassigning mysql/1") 1577 err = mysql1.UnassignFromMachine() 1578 c.Assert(err, jc.ErrorIsNil) 1579 wc.AssertChange("mysql/1", "logging/0") 1580 wc.AssertNoChange() 1581 } 1582 1583 func (s *MachineSuite) TestWatchUnitsHandlesDeletedEntries(c *gc.C) { 1584 s.WaitForModelWatchersIdle(c, s.Model.UUID()) 1585 w := s.machine.WatchUnits() 1586 defer testing.AssertStop(c, w) 1587 wc := testing.NewStringsWatcherC(c, w) 1588 wc.AssertChange() 1589 wc.AssertNoChange() 1590 1591 // Change machine; no change. 1592 err := s.machine.SetProvisioned("cheese", "", "fake_nonce", nil) 1593 c.Assert(err, jc.ErrorIsNil) 1594 wc.AssertNoChange() 1595 1596 // Assign a unit (to a separate instance); change detected. 1597 c.Logf("assigning mysql to machine %s", s.machine.Id()) 1598 mysql := s.AddTestingApplication(c, "mysql", s.AddTestingCharm(c, "mysql")) 1599 mysql0, err := mysql.AddUnit(state.AddUnitParams{}) 1600 c.Assert(err, jc.ErrorIsNil) 1601 machine, err := s.State.Machine(s.machine.Id()) 1602 c.Assert(err, jc.ErrorIsNil) 1603 err = mysql0.AssignToMachine(machine) 1604 c.Assert(err, jc.ErrorIsNil) 1605 wc.AssertChange("mysql/0") 1606 wc.AssertNoChange() 1607 1608 // Destroy the instance before checking the change 1609 err = mysql0.EnsureDead() 1610 c.Assert(err, jc.ErrorIsNil) 1611 err = mysql0.Remove() 1612 c.Assert(err, jc.ErrorIsNil) 1613 wc.AssertChange("mysql/0") 1614 wc.AssertNoChange() 1615 } 1616 1617 func (s *MachineSuite) TestApplicationNames(c *gc.C) { 1618 mysql := s.AddTestingApplication(c, "mysql", s.AddTestingCharm(c, "mysql")) 1619 wordpress := s.AddTestingApplication(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 1620 1621 mysql0, err := mysql.AddUnit(state.AddUnitParams{}) 1622 c.Assert(err, jc.ErrorIsNil) 1623 mysql1, err := mysql.AddUnit(state.AddUnitParams{}) 1624 c.Assert(err, jc.ErrorIsNil) 1625 worpress0, err := wordpress.AddUnit(state.AddUnitParams{}) 1626 c.Assert(err, jc.ErrorIsNil) 1627 1628 machine, err := s.State.Machine(s.machine.Id()) 1629 c.Assert(err, jc.ErrorIsNil) 1630 err = mysql0.AssignToMachine(machine) 1631 c.Assert(err, jc.ErrorIsNil) 1632 err = mysql1.AssignToMachine(machine) 1633 c.Assert(err, jc.ErrorIsNil) 1634 err = worpress0.AssignToMachine(machine) 1635 c.Assert(err, jc.ErrorIsNil) 1636 1637 apps, err := machine.ApplicationNames() 1638 c.Assert(err, jc.ErrorIsNil) 1639 c.Check(apps, jc.DeepEquals, []string{"mysql", "wordpress"}) 1640 } 1641 1642 func (s *MachineSuite) TestWatchUnitsDiesOnStateClose(c *gc.C) { 1643 testWatcherDiesWhenStateCloses(c, s.Session, s.modelTag, s.State.ControllerTag(), func(c *gc.C, st *state.State) waiter { 1644 m, err := st.Machine(s.machine.Id()) 1645 c.Assert(err, jc.ErrorIsNil) 1646 w := m.WatchUnits() 1647 <-w.Changes() 1648 return w 1649 }) 1650 } 1651 1652 func (s *MachineSuite) TestWatchMachineStartTimes(c *gc.C) { 1653 // Machine needs to be provisioned first. 1654 err := s.machine.SetProvisioned("umbrella/0", "", "fake_nonce", nil) 1655 c.Assert(err, jc.ErrorIsNil) 1656 1657 quiesceInterval := 10 * time.Second 1658 s.WaitForModelWatchersIdle(c, s.Model.UUID()) 1659 w := s.State.WatchModelMachineStartTimes(quiesceInterval) 1660 1661 defer testing.AssertStop(c, w) 1662 wc := testing.NewStringsWatcherC(c, w) 1663 1664 // Get initial set of changes 1665 s.WaitForModelWatchersIdle(c, s.Model.UUID()) 1666 s.Clock.Advance(quiesceInterval) 1667 wc.AssertChange("0", "1") 1668 wc.AssertNoChange() 1669 1670 // Update the agent start time for the new machine and wait for quiesceInterval 1671 // so the change gets processed and added to a new changeset. 1672 err = s.machine.RecordAgentStartInformation("machine-1") 1673 c.Assert(err, jc.ErrorIsNil) 1674 s.WaitForModelWatchersIdle(c, s.Model.UUID()) 1675 s.Clock.Advance(quiesceInterval) 1676 1677 // Update the agent start time for machine 0 and wait for quiesceInterval 1678 // so the change gets processed and appended to the current changeset. 1679 err = s.machine0.RecordAgentStartInformation("machine-0") 1680 c.Assert(err, jc.ErrorIsNil) 1681 s.WaitForModelWatchersIdle(c, s.Model.UUID()) 1682 s.Clock.Advance(quiesceInterval) 1683 1684 // Fetch the pending changes 1685 wc.AssertChange("1", "0") 1686 wc.AssertNoChange() 1687 1688 // Kill the machine, remove it from state and check ensure that we 1689 // still get back a change event. 1690 err = s.machine.Destroy() 1691 c.Assert(err, jc.ErrorIsNil) 1692 s.WaitForModelWatchersIdle(c, s.Model.UUID()) 1693 err = s.machine.EnsureDead() 1694 c.Assert(err, jc.ErrorIsNil) 1695 err = s.machine.Remove() 1696 c.Assert(err, jc.ErrorIsNil) 1697 s.Clock.Advance(quiesceInterval) 1698 wc.AssertChange("1") 1699 wc.AssertNoChange() 1700 } 1701 1702 func (s *MachineSuite) TestConstraintsFromModel(c *gc.C) { 1703 econs1 := constraints.MustParse("mem=1G") 1704 econs2 := constraints.MustParse("mem=2G") 1705 1706 // A newly-created machine gets a copy of the model constraints. 1707 err := s.State.SetModelConstraints(econs1) 1708 c.Assert(err, jc.ErrorIsNil) 1709 machine1, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1710 c.Assert(err, jc.ErrorIsNil) 1711 mcons1, err := machine1.Constraints() 1712 c.Assert(err, jc.ErrorIsNil) 1713 c.Assert(mcons1, gc.DeepEquals, econs1) 1714 1715 // Change model constraints and add a new machine. 1716 err = s.State.SetModelConstraints(econs2) 1717 c.Assert(err, jc.ErrorIsNil) 1718 machine2, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1719 c.Assert(err, jc.ErrorIsNil) 1720 mcons2, err := machine2.Constraints() 1721 c.Assert(err, jc.ErrorIsNil) 1722 c.Assert(mcons2, gc.DeepEquals, econs2) 1723 1724 // Check the original machine has its original constraints. 1725 mcons1, err = machine1.Constraints() 1726 c.Assert(err, jc.ErrorIsNil) 1727 c.Assert(mcons1, gc.DeepEquals, econs1) 1728 } 1729 1730 func (s *MachineSuite) TestSetConstraints(c *gc.C) { 1731 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1732 c.Assert(err, jc.ErrorIsNil) 1733 1734 // Constraints can be set... 1735 cons1 := constraints.MustParse("mem=1G") 1736 err = machine.SetConstraints(cons1) 1737 c.Assert(err, jc.ErrorIsNil) 1738 mcons, err := machine.Constraints() 1739 c.Assert(err, jc.ErrorIsNil) 1740 c.Assert(mcons, gc.DeepEquals, cons1) 1741 1742 // ...until the machine is provisioned, at which point they stick. 1743 err = machine.SetProvisioned("i-mstuck", "", "fake_nonce", nil) 1744 c.Assert(err, jc.ErrorIsNil) 1745 cons2 := constraints.MustParse("mem=2G") 1746 err = machine.SetConstraints(cons2) 1747 c.Assert(err, gc.ErrorMatches, `updating machine "2": cannot set constraints: machine is already provisioned`) 1748 1749 // Check the failed set had no effect. 1750 mcons, err = machine.Constraints() 1751 c.Assert(err, jc.ErrorIsNil) 1752 c.Assert(mcons, gc.DeepEquals, cons1) 1753 1754 all, err := s.Model.AllConstraints() 1755 c.Assert(err, jc.ErrorIsNil) 1756 cons := all.Machine(machine.Id()) 1757 c.Assert(cons, gc.DeepEquals, cons1) 1758 } 1759 1760 func (s *MachineSuite) TestSetAmbiguousConstraints(c *gc.C) { 1761 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1762 c.Assert(err, jc.ErrorIsNil) 1763 cons := constraints.MustParse("mem=4G instance-type=foo") 1764 err = machine.SetConstraints(cons) 1765 c.Assert(err, gc.ErrorMatches, `updating machine "2": cannot set constraints: ambiguous constraints: "instance-type" overlaps with "mem"`) 1766 } 1767 1768 func (s *MachineSuite) TestSetUnsupportedConstraintsWarning(c *gc.C) { 1769 defer loggo.ResetWriters() 1770 logger := loggo.GetLogger("test") 1771 logger.SetLogLevel(loggo.DEBUG) 1772 var tw loggo.TestWriter 1773 c.Assert(loggo.RegisterWriter("constraints-tester", &tw), gc.IsNil) 1774 1775 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1776 c.Assert(err, jc.ErrorIsNil) 1777 cons := constraints.MustParse("mem=4G cpu-power=10") 1778 err = machine.SetConstraints(cons) 1779 c.Assert(err, jc.ErrorIsNil) 1780 c.Assert(tw.Log(), jc.LogMatches, jc.SimpleMessages{{ 1781 loggo.WARNING, 1782 `setting constraints on machine "2": unsupported constraints: cpu-power`}, 1783 }) 1784 mcons, err := machine.Constraints() 1785 c.Assert(err, jc.ErrorIsNil) 1786 c.Assert(mcons, gc.DeepEquals, cons) 1787 } 1788 1789 func (s *MachineSuite) TestConstraintsLifecycle(c *gc.C) { 1790 cons := constraints.MustParse("mem=1G") 1791 cannotSet := `updating machine "1": cannot set constraints: machine is not found or not alive` 1792 testWhenDying(c, s.machine, cannotSet, cannotSet, func() error { 1793 err := s.machine.SetConstraints(cons) 1794 mcons, err1 := s.machine.Constraints() 1795 c.Assert(err1, gc.IsNil) 1796 c.Assert(&mcons, jc.Satisfies, constraints.IsEmpty) 1797 return err 1798 }) 1799 1800 err := s.machine.Remove() 1801 c.Assert(err, jc.ErrorIsNil) 1802 err = s.machine.SetConstraints(cons) 1803 c.Assert(err, gc.ErrorMatches, cannotSet) 1804 _, err = s.machine.Constraints() 1805 c.Assert(err, gc.ErrorMatches, `constraints not found`) 1806 } 1807 1808 func (s *MachineSuite) TestSetProviderAddresses(c *gc.C) { 1809 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1810 c.Assert(err, jc.ErrorIsNil) 1811 c.Assert(machine.Addresses(), gc.HasLen, 0) 1812 1813 addresses := network.SpaceAddresses{ 1814 network.NewSpaceAddress("127.0.0.1"), 1815 { 1816 MachineAddress: network.MachineAddress{ 1817 Value: "8.8.8.8", 1818 Type: network.IPv4Address, 1819 Scope: network.ScopeCloudLocal, 1820 }, 1821 SpaceID: "1", 1822 }, 1823 } 1824 err = machine.SetProviderAddresses(addresses...) 1825 c.Assert(err, jc.ErrorIsNil) 1826 err = machine.Refresh() 1827 c.Assert(err, jc.ErrorIsNil) 1828 1829 sort.Sort(addresses) 1830 c.Assert(machine.Addresses(), jc.DeepEquals, addresses) 1831 } 1832 1833 func (s *MachineSuite) TestSetProviderAddressesWithContainers(c *gc.C) { 1834 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1835 c.Assert(err, jc.ErrorIsNil) 1836 c.Assert(machine.Addresses(), gc.HasLen, 0) 1837 1838 // When setting all addresses the subnet addresses have to be 1839 // filtered out. 1840 addresses := network.NewSpaceAddresses( 1841 "127.0.0.1", 1842 "8.8.8.8", 1843 ) 1844 err = machine.SetProviderAddresses(addresses...) 1845 c.Assert(err, jc.ErrorIsNil) 1846 err = machine.Refresh() 1847 c.Assert(err, jc.ErrorIsNil) 1848 1849 expectedAddresses := network.NewSpaceAddresses("8.8.8.8", "127.0.0.1") 1850 c.Assert(machine.Addresses(), jc.DeepEquals, expectedAddresses) 1851 } 1852 1853 func (s *MachineSuite) TestSetProviderAddressesOnContainer(c *gc.C) { 1854 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1855 c.Assert(err, jc.ErrorIsNil) 1856 c.Assert(machine.Addresses(), gc.HasLen, 0) 1857 1858 // Create an LXC container inside the machine. 1859 template := state.MachineTemplate{ 1860 Base: state.UbuntuBase("12.10"), 1861 Jobs: []state.MachineJob{state.JobHostUnits}, 1862 } 1863 container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXD) 1864 c.Assert(err, jc.ErrorIsNil) 1865 1866 // When setting all addresses the subnet address has to accepted. 1867 addresses := network.NewSpaceAddresses("127.0.0.1") 1868 err = container.SetProviderAddresses(addresses...) 1869 c.Assert(err, jc.ErrorIsNil) 1870 err = container.Refresh() 1871 c.Assert(err, jc.ErrorIsNil) 1872 1873 expectedAddresses := network.NewSpaceAddresses("127.0.0.1") 1874 c.Assert(container.Addresses(), jc.DeepEquals, expectedAddresses) 1875 } 1876 1877 func (s *MachineSuite) TestSetMachineAddresses(c *gc.C) { 1878 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1879 c.Assert(err, jc.ErrorIsNil) 1880 c.Assert(machine.Addresses(), gc.HasLen, 0) 1881 1882 addresses := network.NewSpaceAddresses("127.0.0.1", "8.8.8.8") 1883 err = machine.SetMachineAddresses(addresses...) 1884 c.Assert(err, jc.ErrorIsNil) 1885 err = machine.Refresh() 1886 c.Assert(err, jc.ErrorIsNil) 1887 1888 expectedAddresses := network.NewSpaceAddresses("8.8.8.8", "127.0.0.1") 1889 c.Assert(machine.MachineAddresses(), jc.DeepEquals, expectedAddresses) 1890 } 1891 1892 func (s *MachineSuite) TestSetEmptyMachineAddresses(c *gc.C) { 1893 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1894 c.Assert(err, jc.ErrorIsNil) 1895 c.Assert(machine.Addresses(), gc.HasLen, 0) 1896 1897 // Add some machine addresses initially to make sure they're removed. 1898 addresses := network.NewSpaceAddresses("127.0.0.1", "8.8.8.8") 1899 err = machine.SetMachineAddresses(addresses...) 1900 c.Assert(err, jc.ErrorIsNil) 1901 err = machine.Refresh() 1902 c.Assert(err, jc.ErrorIsNil) 1903 c.Assert(machine.MachineAddresses(), gc.HasLen, 2) 1904 1905 // Make call with empty address list. 1906 err = machine.SetMachineAddresses() 1907 c.Assert(err, jc.ErrorIsNil) 1908 err = machine.Refresh() 1909 c.Assert(err, jc.ErrorIsNil) 1910 1911 c.Assert(machine.MachineAddresses(), gc.HasLen, 0) 1912 } 1913 1914 func (s *MachineSuite) TestMergedAddresses(c *gc.C) { 1915 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1916 c.Assert(err, jc.ErrorIsNil) 1917 c.Assert(machine.Addresses(), gc.HasLen, 0) 1918 1919 providerAddresses := network.NewSpaceAddresses( 1920 "127.0.0.2", 1921 "8.8.8.8", 1922 "fc00::1", 1923 "::1", 1924 "", 1925 "2001:db8::1", 1926 "127.0.0.2", 1927 "example.org", 1928 ) 1929 err = machine.SetProviderAddresses(providerAddresses...) 1930 c.Assert(err, jc.ErrorIsNil) 1931 1932 machineAddresses := network.NewSpaceAddresses( 1933 "127.0.0.1", 1934 "localhost", 1935 "2001:db8::1", 1936 "192.168.0.1", 1937 "fe80::1", 1938 "::1", 1939 "fd00::1", 1940 ) 1941 err = machine.SetMachineAddresses(machineAddresses...) 1942 c.Assert(err, jc.ErrorIsNil) 1943 err = machine.Refresh() 1944 c.Assert(err, jc.ErrorIsNil) 1945 1946 // Before setting the addresses coming from either the provider or 1947 // the machine itself, they are sorted to prefer public IPs on 1948 // top, then hostnames, cloud-local, machine-local, link-local. 1949 // Duplicates are removed, then when calling Addresses() both 1950 // sources are merged while preservig the provider addresses 1951 // order. 1952 c.Assert(machine.Addresses(), jc.DeepEquals, network.NewSpaceAddresses( 1953 "8.8.8.8", 1954 "2001:db8::1", 1955 "example.org", 1956 "fc00::1", 1957 "127.0.0.2", 1958 "::1", 1959 "localhost", 1960 "192.168.0.1", 1961 "fd00::1", 1962 "127.0.0.1", 1963 "fe80::1", 1964 )) 1965 } 1966 1967 func (s *MachineSuite) TestSetProviderAddressesConcurrentChangeDifferent(c *gc.C) { 1968 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1969 c.Assert(err, jc.ErrorIsNil) 1970 c.Assert(machine.Addresses(), gc.HasLen, 0) 1971 1972 addr0 := network.NewSpaceAddress("127.0.0.1") 1973 addr1 := network.NewSpaceAddress("8.8.8.8") 1974 1975 defer state.SetBeforeHooks(c, s.State, func() { 1976 machine, err := s.State.Machine(machine.Id()) 1977 c.Assert(err, jc.ErrorIsNil) 1978 err = machine.SetProviderAddresses(addr1, addr0) 1979 c.Assert(err, jc.ErrorIsNil) 1980 }).Check() 1981 1982 err = machine.SetProviderAddresses(addr0, addr1) 1983 c.Assert(err, jc.ErrorIsNil) 1984 c.Assert(machine.Addresses(), jc.SameContents, network.SpaceAddresses{addr0, addr1}) 1985 } 1986 1987 func (s *MachineSuite) TestSetProviderAddressesConcurrentChangeEqual(c *gc.C) { 1988 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 1989 c.Assert(err, jc.ErrorIsNil) 1990 c.Assert(machine.Addresses(), gc.HasLen, 0) 1991 machineDocID := state.DocID(s.State, machine.Id()) 1992 revno0, err := state.TxnRevno(s.State, "machines", machineDocID) 1993 c.Assert(err, jc.ErrorIsNil) 1994 1995 addr0 := network.NewSpaceAddress("127.0.0.1") 1996 addr1 := network.NewSpaceAddress("8.8.8.8") 1997 1998 var revno1 int64 1999 defer state.SetBeforeHooks(c, s.State, func() { 2000 machine, err := s.State.Machine(machine.Id()) 2001 c.Assert(err, jc.ErrorIsNil) 2002 err = machine.SetProviderAddresses(addr0, addr1) 2003 c.Assert(err, jc.ErrorIsNil) 2004 revno1, err = state.TxnRevno(s.State, "machines", machineDocID) 2005 c.Assert(err, jc.ErrorIsNil) 2006 c.Assert(revno1, jc.GreaterThan, revno0) 2007 }).Check() 2008 2009 err = machine.SetProviderAddresses(addr0, addr1) 2010 c.Assert(err, jc.ErrorIsNil) 2011 2012 // Doc will be updated; concurrent changes are explicitly ignored. 2013 revno2, err := state.TxnRevno(s.State, "machines", machineDocID) 2014 c.Assert(err, jc.ErrorIsNil) 2015 c.Assert(revno2, jc.GreaterThan, revno1) 2016 c.Assert(machine.Addresses(), jc.SameContents, network.SpaceAddresses{addr0, addr1}) 2017 } 2018 2019 func (s *MachineSuite) TestSetProviderAddressesInvalidateMemory(c *gc.C) { 2020 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2021 c.Assert(err, jc.ErrorIsNil) 2022 c.Assert(machine.Addresses(), gc.HasLen, 0) 2023 machineDocID := state.DocID(s.State, machine.Id()) 2024 2025 addr0 := network.NewSpaceAddress("127.0.0.1") 2026 addr1 := network.NewSpaceAddress("8.8.8.8") 2027 2028 // Set addresses to [addr0] initially. We'll get a separate Machine 2029 // object to update addresses, to ensure that the in-memory cache of 2030 // addresses does not prevent the initial Machine from updating 2031 // addresses back to the original value. 2032 err = machine.SetProviderAddresses(addr0) 2033 c.Assert(err, jc.ErrorIsNil) 2034 revno0, err := state.TxnRevno(s.State, "machines", machineDocID) 2035 c.Assert(err, jc.ErrorIsNil) 2036 2037 machine2, err := s.State.Machine(machine.Id()) 2038 c.Assert(err, jc.ErrorIsNil) 2039 err = machine2.SetProviderAddresses(addr1) 2040 c.Assert(err, jc.ErrorIsNil) 2041 revno1, err := state.TxnRevno(s.State, "machines", machineDocID) 2042 c.Assert(err, jc.ErrorIsNil) 2043 c.Assert(revno1, jc.GreaterThan, revno0) 2044 c.Assert(machine.Addresses(), jc.SameContents, network.SpaceAddresses{addr0}) 2045 c.Assert(machine2.Addresses(), jc.SameContents, network.SpaceAddresses{addr1}) 2046 2047 err = machine.SetProviderAddresses(addr0) 2048 c.Assert(err, jc.ErrorIsNil) 2049 revno2, err := state.TxnRevno(s.State, "machines", machineDocID) 2050 c.Assert(err, jc.ErrorIsNil) 2051 c.Assert(revno2, jc.GreaterThan, revno1) 2052 c.Assert(machine.Addresses(), jc.SameContents, network.SpaceAddresses{addr0}) 2053 } 2054 2055 func (s *MachineSuite) TestPublicAddressSetOnNewMachine(c *gc.C) { 2056 m, err := s.State.AddOneMachine(state.MachineTemplate{ 2057 Base: state.UbuntuBase("12.10"), 2058 Jobs: []state.MachineJob{state.JobHostUnits}, 2059 Addresses: network.NewSpaceAddresses("10.0.0.1", "8.8.8.8"), 2060 }) 2061 c.Assert(err, jc.ErrorIsNil) 2062 addr, err := m.PublicAddress() 2063 c.Assert(err, jc.ErrorIsNil) 2064 c.Assert(addr, jc.DeepEquals, network.NewSpaceAddress("8.8.8.8")) 2065 } 2066 2067 func (s *MachineSuite) TestPrivateAddressSetOnNewMachine(c *gc.C) { 2068 m, err := s.State.AddOneMachine(state.MachineTemplate{ 2069 Base: state.UbuntuBase("12.10"), 2070 Jobs: []state.MachineJob{state.JobHostUnits}, 2071 Addresses: network.NewSpaceAddresses("10.0.0.1", "8.8.8.8"), 2072 }) 2073 c.Assert(err, jc.ErrorIsNil) 2074 addr, err := m.PrivateAddress() 2075 c.Assert(err, jc.ErrorIsNil) 2076 c.Assert(addr, jc.DeepEquals, network.NewSpaceAddress("10.0.0.1")) 2077 } 2078 2079 func (s *MachineSuite) TestPublicAddressEmptyAddresses(c *gc.C) { 2080 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2081 c.Assert(err, jc.ErrorIsNil) 2082 c.Assert(machine.Addresses(), gc.HasLen, 0) 2083 2084 addr, err := machine.PublicAddress() 2085 c.Assert(err, jc.Satisfies, network.IsNoAddressError) 2086 c.Assert(addr.Value, gc.Equals, "") 2087 } 2088 2089 func (s *MachineSuite) TestPrivateAddressEmptyAddresses(c *gc.C) { 2090 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2091 c.Assert(err, jc.ErrorIsNil) 2092 c.Assert(machine.Addresses(), gc.HasLen, 0) 2093 2094 addr, err := machine.PrivateAddress() 2095 c.Assert(err, jc.Satisfies, network.IsNoAddressError) 2096 c.Assert(addr.Value, gc.Equals, "") 2097 } 2098 2099 func (s *MachineSuite) TestPublicAddress(c *gc.C) { 2100 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2101 c.Assert(err, jc.ErrorIsNil) 2102 2103 err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.8.8")) 2104 c.Assert(err, jc.ErrorIsNil) 2105 2106 addr, err := machine.PublicAddress() 2107 c.Assert(err, jc.ErrorIsNil) 2108 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2109 } 2110 2111 func (s *MachineSuite) TestPrivateAddress(c *gc.C) { 2112 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2113 c.Assert(err, jc.ErrorIsNil) 2114 2115 err = machine.SetMachineAddresses(network.NewSpaceAddress("10.0.0.1")) 2116 c.Assert(err, jc.ErrorIsNil) 2117 2118 addr, err := machine.PrivateAddress() 2119 c.Assert(err, jc.ErrorIsNil) 2120 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 2121 } 2122 2123 func (s *MachineSuite) TestPublicAddressBetterMatch(c *gc.C) { 2124 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2125 c.Assert(err, jc.ErrorIsNil) 2126 2127 err = machine.SetMachineAddresses(network.NewSpaceAddress("10.0.0.1")) 2128 c.Assert(err, jc.ErrorIsNil) 2129 2130 addr, err := machine.PublicAddress() 2131 c.Assert(err, jc.ErrorIsNil) 2132 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 2133 2134 err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.8.8")) 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 } 2141 2142 func (s *MachineSuite) TestPrivateAddressBetterMatch(c *gc.C) { 2143 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2144 c.Assert(err, jc.ErrorIsNil) 2145 2146 err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.8.8")) 2147 c.Assert(err, jc.ErrorIsNil) 2148 2149 addr, err := machine.PrivateAddress() 2150 c.Assert(err, jc.ErrorIsNil) 2151 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2152 2153 err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.8.8"), network.NewSpaceAddress("10.0.0.1")) 2154 c.Assert(err, jc.ErrorIsNil) 2155 2156 addr, err = machine.PrivateAddress() 2157 c.Assert(err, jc.ErrorIsNil) 2158 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 2159 } 2160 2161 func (s *MachineSuite) TestPublicAddressChanges(c *gc.C) { 2162 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2163 c.Assert(err, jc.ErrorIsNil) 2164 2165 err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.8.8")) 2166 c.Assert(err, jc.ErrorIsNil) 2167 2168 addr, err := machine.PublicAddress() 2169 c.Assert(err, jc.ErrorIsNil) 2170 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2171 2172 err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.4.4")) 2173 c.Assert(err, jc.ErrorIsNil) 2174 2175 addr, err = machine.PublicAddress() 2176 c.Assert(err, jc.ErrorIsNil) 2177 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 2178 } 2179 2180 func (s *MachineSuite) TestPrivateAddressChanges(c *gc.C) { 2181 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2182 c.Assert(err, jc.ErrorIsNil) 2183 2184 err = machine.SetMachineAddresses(network.NewSpaceAddress("10.0.0.2")) 2185 c.Assert(err, jc.ErrorIsNil) 2186 2187 addr, err := machine.PrivateAddress() 2188 c.Assert(err, jc.ErrorIsNil) 2189 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 2190 2191 err = machine.SetMachineAddresses(network.NewSpaceAddress("10.0.0.1")) 2192 c.Assert(err, jc.ErrorIsNil) 2193 2194 addr, err = machine.PrivateAddress() 2195 c.Assert(err, jc.ErrorIsNil) 2196 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 2197 } 2198 2199 func (s *MachineSuite) TestAddressesDeadMachine(c *gc.C) { 2200 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2201 c.Assert(err, jc.ErrorIsNil) 2202 2203 err = machine.SetProviderAddresses(network.NewSpaceAddress("10.0.0.2"), network.NewSpaceAddress("8.8.4.4")) 2204 c.Assert(err, jc.ErrorIsNil) 2205 2206 addr, err := machine.PrivateAddress() 2207 c.Assert(err, jc.ErrorIsNil) 2208 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 2209 2210 addr, err = machine.PublicAddress() 2211 c.Assert(err, jc.ErrorIsNil) 2212 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 2213 2214 err = machine.EnsureDead() 2215 c.Assert(err, jc.ErrorIsNil) 2216 2217 // A dead machine should still report the last known addresses. 2218 addr, err = machine.PrivateAddress() 2219 c.Assert(err, jc.ErrorIsNil) 2220 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 2221 2222 addr, err = machine.PublicAddress() 2223 c.Assert(err, jc.ErrorIsNil) 2224 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 2225 } 2226 2227 func (s *MachineSuite) TestStablePrivateAddress(c *gc.C) { 2228 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2229 c.Assert(err, jc.ErrorIsNil) 2230 2231 err = machine.SetMachineAddresses(network.NewSpaceAddress("10.0.0.2")) 2232 c.Assert(err, jc.ErrorIsNil) 2233 2234 addr, err := machine.PrivateAddress() 2235 c.Assert(err, jc.ErrorIsNil) 2236 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 2237 2238 // Now add an address that would previously have sorted before the 2239 // default. 2240 err = machine.SetMachineAddresses(network.NewSpaceAddress("10.0.0.1"), network.NewSpaceAddress("10.0.0.2")) 2241 c.Assert(err, jc.ErrorIsNil) 2242 2243 // Assert the address is unchanged. 2244 addr, err = machine.PrivateAddress() 2245 c.Assert(err, jc.ErrorIsNil) 2246 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 2247 } 2248 2249 func (s *MachineSuite) TestStablePublicAddress(c *gc.C) { 2250 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2251 c.Assert(err, jc.ErrorIsNil) 2252 2253 err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.8.8")) 2254 c.Assert(err, jc.ErrorIsNil) 2255 2256 addr, err := machine.PublicAddress() 2257 c.Assert(err, jc.ErrorIsNil) 2258 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2259 2260 // Now add an address that would previously have sorted before the 2261 // default. 2262 err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.4.4"), network.NewSpaceAddress("8.8.8.8")) 2263 c.Assert(err, jc.ErrorIsNil) 2264 2265 // Assert the address is unchanged. 2266 addr, err = machine.PublicAddress() 2267 c.Assert(err, jc.ErrorIsNil) 2268 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2269 } 2270 2271 func (s *MachineSuite) TestAddressesRaceMachineFirst(c *gc.C) { 2272 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2273 c.Assert(err, jc.ErrorIsNil) 2274 2275 changeAddresses := jujutxn.TestHook{ 2276 Before: func() { 2277 err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.8.8")) 2278 c.Assert(err, jc.ErrorIsNil) 2279 address, err := machine.PublicAddress() 2280 c.Assert(err, jc.ErrorIsNil) 2281 c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("8.8.8.8")) 2282 address, err = machine.PrivateAddress() 2283 c.Assert(err, jc.ErrorIsNil) 2284 c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("8.8.8.8")) 2285 }, 2286 } 2287 defer state.SetTestHooks(c, s.State, changeAddresses).Check() 2288 2289 err = machine.SetMachineAddresses(network.NewSpaceAddress("8.8.4.4")) 2290 c.Assert(err, jc.ErrorIsNil) 2291 2292 machine, err = s.State.Machine(machine.Id()) 2293 c.Assert(err, jc.ErrorIsNil) 2294 address, err := machine.PublicAddress() 2295 c.Assert(err, jc.ErrorIsNil) 2296 c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("8.8.8.8")) 2297 address, err = machine.PrivateAddress() 2298 c.Assert(err, jc.ErrorIsNil) 2299 c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("8.8.8.8")) 2300 } 2301 2302 func (s *MachineSuite) TestAddressesRaceProviderFirst(c *gc.C) { 2303 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2304 c.Assert(err, jc.ErrorIsNil) 2305 2306 changeAddresses := jujutxn.TestHook{ 2307 Before: func() { 2308 err = machine.SetMachineAddresses(network.NewSpaceAddress("10.0.0.1")) 2309 c.Assert(err, jc.ErrorIsNil) 2310 address, err := machine.PublicAddress() 2311 c.Assert(err, jc.ErrorIsNil) 2312 c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("10.0.0.1")) 2313 address, err = machine.PrivateAddress() 2314 c.Assert(err, jc.ErrorIsNil) 2315 c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("10.0.0.1")) 2316 }, 2317 } 2318 defer state.SetTestHooks(c, s.State, changeAddresses).Check() 2319 2320 err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.4.4")) 2321 c.Assert(err, jc.ErrorIsNil) 2322 2323 machine, err = s.State.Machine(machine.Id()) 2324 c.Assert(err, jc.ErrorIsNil) 2325 address, err := machine.PublicAddress() 2326 c.Assert(err, jc.ErrorIsNil) 2327 c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("8.8.4.4")) 2328 address, err = machine.PrivateAddress() 2329 c.Assert(err, jc.ErrorIsNil) 2330 c.Assert(address, jc.DeepEquals, network.NewSpaceAddress("8.8.4.4")) 2331 } 2332 2333 func (s *MachineSuite) TestPrivateAddressPrefersProvider(c *gc.C) { 2334 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2335 c.Assert(err, jc.ErrorIsNil) 2336 2337 err = machine.SetMachineAddresses(network.NewSpaceAddress("8.8.8.8"), network.NewSpaceAddress("10.0.0.2")) 2338 c.Assert(err, jc.ErrorIsNil) 2339 2340 addr, err := machine.PublicAddress() 2341 c.Assert(err, jc.ErrorIsNil) 2342 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2343 addr, err = machine.PrivateAddress() 2344 c.Assert(err, jc.ErrorIsNil) 2345 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 2346 2347 err = machine.SetProviderAddresses(network.NewSpaceAddress("10.0.0.1")) 2348 c.Assert(err, jc.ErrorIsNil) 2349 2350 addr, err = machine.PublicAddress() 2351 c.Assert(err, jc.ErrorIsNil) 2352 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 2353 addr, err = machine.PrivateAddress() 2354 c.Assert(err, jc.ErrorIsNil) 2355 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 2356 } 2357 2358 func (s *MachineSuite) TestPublicAddressPrefersProvider(c *gc.C) { 2359 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2360 c.Assert(err, jc.ErrorIsNil) 2361 2362 err = machine.SetMachineAddresses(network.NewSpaceAddress("8.8.8.8"), network.NewSpaceAddress("10.0.0.2")) 2363 c.Assert(err, jc.ErrorIsNil) 2364 2365 addr, err := machine.PublicAddress() 2366 c.Assert(err, jc.ErrorIsNil) 2367 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2368 addr, err = machine.PrivateAddress() 2369 c.Assert(err, jc.ErrorIsNil) 2370 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 2371 2372 err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.4.4")) 2373 c.Assert(err, jc.ErrorIsNil) 2374 2375 addr, err = machine.PublicAddress() 2376 c.Assert(err, jc.ErrorIsNil) 2377 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 2378 addr, err = machine.PrivateAddress() 2379 c.Assert(err, jc.ErrorIsNil) 2380 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 2381 } 2382 2383 func (s *MachineSuite) TestAddressesPrefersProviderBoth(c *gc.C) { 2384 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2385 c.Assert(err, jc.ErrorIsNil) 2386 2387 err = machine.SetMachineAddresses(network.NewSpaceAddress("8.8.8.8"), network.NewSpaceAddress("10.0.0.1")) 2388 c.Assert(err, jc.ErrorIsNil) 2389 2390 addr, err := machine.PublicAddress() 2391 c.Assert(err, jc.ErrorIsNil) 2392 c.Assert(addr.Value, gc.Equals, "8.8.8.8") 2393 addr, err = machine.PrivateAddress() 2394 c.Assert(err, jc.ErrorIsNil) 2395 c.Assert(addr.Value, gc.Equals, "10.0.0.1") 2396 2397 err = machine.SetProviderAddresses(network.NewSpaceAddress("8.8.4.4"), network.NewSpaceAddress("10.0.0.2")) 2398 c.Assert(err, jc.ErrorIsNil) 2399 2400 addr, err = machine.PublicAddress() 2401 c.Assert(err, jc.ErrorIsNil) 2402 c.Assert(addr.Value, gc.Equals, "8.8.4.4") 2403 addr, err = machine.PrivateAddress() 2404 c.Assert(err, jc.ErrorIsNil) 2405 c.Assert(addr.Value, gc.Equals, "10.0.0.2") 2406 } 2407 2408 func (s *MachineSuite) addMachineWithSupportedContainer(c *gc.C, container instance.ContainerType) *state.Machine { 2409 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2410 c.Assert(err, jc.ErrorIsNil) 2411 containers := []instance.ContainerType{container} 2412 err = machine.SetSupportedContainers(containers) 2413 c.Assert(err, jc.ErrorIsNil) 2414 assertSupportedContainers(c, machine, containers) 2415 return machine 2416 } 2417 2418 // assertSupportedContainers checks the document in memory has the specified 2419 // containers and then reloads the document from the database to assert saved 2420 // values match also. 2421 func assertSupportedContainers(c *gc.C, machine *state.Machine, containers []instance.ContainerType) { 2422 supportedContainers, known := machine.SupportedContainers() 2423 c.Assert(known, jc.IsTrue) 2424 c.Assert(supportedContainers, gc.DeepEquals, containers) 2425 // Reload so we can check the saved values. 2426 err := machine.Refresh() 2427 c.Assert(err, jc.ErrorIsNil) 2428 supportedContainers, known = machine.SupportedContainers() 2429 c.Assert(known, jc.IsTrue) 2430 c.Assert(supportedContainers, gc.DeepEquals, containers) 2431 } 2432 2433 func assertSupportedContainersUnknown(c *gc.C, machine *state.Machine) { 2434 containers, known := machine.SupportedContainers() 2435 c.Assert(known, jc.IsFalse) 2436 c.Assert(containers, gc.HasLen, 0) 2437 } 2438 2439 func (s *MachineSuite) TestSupportedContainersInitiallyUnknown(c *gc.C) { 2440 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2441 c.Assert(err, jc.ErrorIsNil) 2442 assertSupportedContainersUnknown(c, machine) 2443 } 2444 2445 func (s *MachineSuite) TestSupportsNoContainers(c *gc.C) { 2446 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2447 c.Assert(err, jc.ErrorIsNil) 2448 2449 err = machine.SupportsNoContainers() 2450 c.Assert(err, jc.ErrorIsNil) 2451 assertSupportedContainers(c, machine, []instance.ContainerType{}) 2452 } 2453 2454 func (s *MachineSuite) TestSetSupportedContainerTypeNoneIsError(c *gc.C) { 2455 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2456 c.Assert(err, jc.ErrorIsNil) 2457 2458 err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.NONE}) 2459 c.Assert(err, gc.ErrorMatches, `"none" is not a valid container type`) 2460 assertSupportedContainersUnknown(c, machine) 2461 err = machine.Refresh() 2462 c.Assert(err, jc.ErrorIsNil) 2463 assertSupportedContainersUnknown(c, machine) 2464 } 2465 2466 func (s *MachineSuite) TestSupportsNoContainersOverwritesExisting(c *gc.C) { 2467 machine := s.addMachineWithSupportedContainer(c, instance.LXD) 2468 2469 err := machine.SupportsNoContainers() 2470 c.Assert(err, jc.ErrorIsNil) 2471 assertSupportedContainers(c, machine, []instance.ContainerType{}) 2472 // Calling it a second time should not invoke a db transaction 2473 defer state.SetFailIfTransaction(c, s.State).Check() 2474 err = machine.SupportsNoContainers() 2475 c.Assert(err, jc.ErrorIsNil) 2476 assertSupportedContainers(c, machine, []instance.ContainerType{}) 2477 } 2478 2479 func (s *MachineSuite) TestSetSupportedContainersSingle(c *gc.C) { 2480 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2481 c.Assert(err, jc.ErrorIsNil) 2482 2483 err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD}) 2484 c.Assert(err, jc.ErrorIsNil) 2485 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD}) 2486 } 2487 2488 func (s *MachineSuite) TestSetSupportedContainersSame(c *gc.C) { 2489 machine := s.addMachineWithSupportedContainer(c, instance.LXD) 2490 2491 defer state.SetFailIfTransaction(c, s.State).Check() 2492 err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXD}) 2493 c.Assert(err, jc.ErrorIsNil) 2494 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD}) 2495 } 2496 2497 func (s *MachineSuite) TestSetSupportedContainersNew(c *gc.C) { 2498 machine := s.addMachineWithSupportedContainer(c, instance.LXD) 2499 2500 err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM}) 2501 c.Assert(err, jc.ErrorIsNil) 2502 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM}) 2503 } 2504 2505 func (s *MachineSuite) TestSetSupportedContainersMultipeNew(c *gc.C) { 2506 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2507 c.Assert(err, jc.ErrorIsNil) 2508 2509 err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM}) 2510 c.Assert(err, jc.ErrorIsNil) 2511 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM}) 2512 } 2513 2514 func (s *MachineSuite) TestSetSupportedContainersMultipleExisting(c *gc.C) { 2515 machine := s.addMachineWithSupportedContainer(c, instance.LXD) 2516 2517 err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM}) 2518 c.Assert(err, jc.ErrorIsNil) 2519 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM}) 2520 // Setting it again will be a no-op 2521 defer state.SetFailIfTransaction(c, s.State).Check() 2522 err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM}) 2523 c.Assert(err, jc.ErrorIsNil) 2524 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM}) 2525 } 2526 2527 func (s *MachineSuite) TestSetSupportedContainersMultipleExistingInvertedOrder(c *gc.C) { 2528 machine := s.addMachineWithSupportedContainer(c, instance.LXD) 2529 2530 err := machine.SetSupportedContainers([]instance.ContainerType{instance.KVM, instance.LXD}) 2531 c.Assert(err, jc.ErrorIsNil) 2532 assertSupportedContainers(c, machine, []instance.ContainerType{instance.KVM, instance.LXD}) 2533 // Setting it again will be a no-op 2534 defer state.SetFailIfTransaction(c, s.State).Check() 2535 err = machine.SetSupportedContainers([]instance.ContainerType{instance.KVM, instance.LXD}) 2536 c.Assert(err, jc.ErrorIsNil) 2537 assertSupportedContainers(c, machine, []instance.ContainerType{instance.KVM, instance.LXD}) 2538 } 2539 2540 func (s *MachineSuite) TestSetSupportedContainersMultipleExistingWithDifferentInstanceType(c *gc.C) { 2541 machine := s.addMachineWithSupportedContainer(c, instance.LXD) 2542 2543 err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM}) 2544 c.Assert(err, jc.ErrorIsNil) 2545 assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM}) 2546 // Setting it again will be a no-op 2547 err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.ContainerType("FOO")}) 2548 c.Assert(err, jc.ErrorIsNil) 2549 } 2550 2551 func (s *MachineSuite) TestSetSupportedContainersSetsUnknownToError(c *gc.C) { 2552 // Create a machine and add lxd and kvm containers prior to calling SetSupportedContainers 2553 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2554 c.Assert(err, jc.ErrorIsNil) 2555 template := state.MachineTemplate{ 2556 Base: state.UbuntuBase("12.10"), 2557 Jobs: []state.MachineJob{state.JobHostUnits}, 2558 } 2559 container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXD) 2560 c.Assert(err, jc.ErrorIsNil) 2561 supportedContainer, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.KVM) 2562 c.Assert(err, jc.ErrorIsNil) 2563 err = machine.SetSupportedContainers([]instance.ContainerType{instance.KVM}) 2564 c.Assert(err, jc.ErrorIsNil) 2565 2566 // A supported (kvm) container will have a pending status. 2567 err = supportedContainer.Refresh() 2568 c.Assert(err, jc.ErrorIsNil) 2569 statusInfo, err := supportedContainer.Status() 2570 c.Assert(err, jc.ErrorIsNil) 2571 c.Assert(statusInfo.Status, gc.Equals, status.Pending) 2572 2573 // An unsupported (lxd) container will have an error status. 2574 err = container.Refresh() 2575 c.Assert(err, jc.ErrorIsNil) 2576 statusInfo, err = container.Status() 2577 c.Assert(err, jc.ErrorIsNil) 2578 c.Assert(statusInfo.Status, gc.Equals, status.Error) 2579 c.Assert(statusInfo.Message, gc.Equals, "unsupported container") 2580 c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{"type": "lxd"}) 2581 } 2582 2583 func (s *MachineSuite) TestSupportsNoContainersSetsAllToError(c *gc.C) { 2584 // Create a machine and add all container types prior to calling SupportsNoContainers 2585 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2586 c.Assert(err, jc.ErrorIsNil) 2587 var containers []*state.Machine 2588 template := state.MachineTemplate{ 2589 Base: state.UbuntuBase("12.10"), 2590 Jobs: []state.MachineJob{state.JobHostUnits}, 2591 } 2592 for _, containerType := range instance.ContainerTypes { 2593 container, err := s.State.AddMachineInsideMachine(template, machine.Id(), containerType) 2594 c.Assert(err, jc.ErrorIsNil) 2595 containers = append(containers, container) 2596 } 2597 2598 err = machine.SupportsNoContainers() 2599 c.Assert(err, jc.ErrorIsNil) 2600 2601 // All containers should be in error state. 2602 for _, container := range containers { 2603 err = container.Refresh() 2604 c.Assert(err, jc.ErrorIsNil) 2605 statusInfo, err := container.Status() 2606 c.Assert(err, jc.ErrorIsNil) 2607 c.Assert(statusInfo.Status, gc.Equals, status.Error) 2608 c.Assert(statusInfo.Message, gc.Equals, "unsupported container") 2609 containerType := corecontainer.ContainerTypeFromId(container.Id()) 2610 c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{"type": string(containerType)}) 2611 } 2612 } 2613 2614 func (s *MachineSuite) TestMachineAgentTools(c *gc.C) { 2615 m, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2616 c.Assert(err, jc.ErrorIsNil) 2617 testAgentTools(c, m, "machine "+m.Id()) 2618 } 2619 2620 func (s *MachineSuite) TestMachineValidActions(c *gc.C) { 2621 m, err := s.State.AddMachine(state.UbuntuBase("22.04"), state.JobHostUnits) 2622 c.Assert(err, jc.ErrorIsNil) 2623 2624 var tests = []struct { 2625 actionName string 2626 errString string 2627 givenPayload map[string]interface{} 2628 expectedPayload map[string]interface{} 2629 }{ 2630 { 2631 actionName: "juju-exec", 2632 errString: `validation failed: (root) : "command" property is missing and required, given {}; (root) : "timeout" property is missing and required, given {}`, 2633 }, 2634 { 2635 actionName: "juju-exec", 2636 givenPayload: map[string]interface{}{"command": "allyourbasearebelongtous", "timeout": 5.0}, 2637 expectedPayload: map[string]interface{}{"command": "allyourbasearebelongtous", "timeout": 5.0}, 2638 }, 2639 { 2640 actionName: "baiku", 2641 errString: `cannot add action "baiku" to a machine; only predefined actions allowed`, 2642 }, 2643 } 2644 2645 for i, t := range tests { 2646 c.Logf("running test %d", i) 2647 operationID, err := s.Model.EnqueueOperation("a test", 1) 2648 c.Assert(err, jc.ErrorIsNil) 2649 action, err := s.Model.AddAction(m, operationID, t.actionName, t.givenPayload, nil, nil) 2650 if t.errString != "" { 2651 c.Assert(err.Error(), gc.Equals, t.errString) 2652 continue 2653 } else { 2654 c.Assert(err, jc.ErrorIsNil) 2655 c.Assert(action.Parameters(), jc.DeepEquals, t.expectedPayload) 2656 } 2657 } 2658 } 2659 2660 func (s *MachineSuite) TestAddActionWithError(c *gc.C) { 2661 m, err := s.State.AddMachine(state.UbuntuBase("22.04"), state.JobHostUnits) 2662 c.Assert(err, jc.ErrorIsNil) 2663 2664 operationID, err := s.Model.EnqueueOperation("a test", 1) 2665 c.Assert(err, jc.ErrorIsNil) 2666 _, err = s.Model.AddAction(m, operationID, "benchmark", nil, nil, nil) 2667 c.Assert(err, gc.ErrorMatches, `cannot add action "benchmark" to a machine; only predefined actions allowed`) 2668 op, err := s.Model.Operation(operationID) 2669 c.Assert(err, jc.ErrorIsNil) 2670 c.Assert(op.Status(), gc.Equals, state.ActionError) 2671 } 2672 2673 func (s *MachineSuite) setupTestUpdateMachineSeries(c *gc.C) *state.Machine { 2674 mach, err := s.State.AddMachine(state.UbuntuBase("12.04"), state.JobHostUnits) 2675 c.Assert(err, jc.ErrorIsNil) 2676 2677 ch := state.AddTestingCharmMultiSeries(c, s.State, "multi-series") 2678 app := state.AddTestingApplicationForBase(c, s.State, state.UbuntuBase("12.04"), "multi-series", ch) 2679 subCh := state.AddTestingCharmMultiSeries(c, s.State, "multi-series-subordinate") 2680 _ = state.AddTestingApplicationForBase(c, s.State, state.UbuntuBase("12.04"), "multi-series-subordinate", subCh) 2681 2682 eps, err := s.State.InferEndpoints("multi-series", "multi-series-subordinate") 2683 c.Assert(err, jc.ErrorIsNil) 2684 rel, err := s.State.AddRelation(eps...) 2685 c.Assert(err, jc.ErrorIsNil) 2686 2687 unit, err := app.AddUnit(state.AddUnitParams{}) 2688 c.Assert(err, jc.ErrorIsNil) 2689 err = unit.AssignToMachine(mach) 2690 c.Assert(err, jc.ErrorIsNil) 2691 2692 ru, err := rel.Unit(unit) 2693 c.Assert(err, jc.ErrorIsNil) 2694 err = ru.EnterScope(nil) 2695 c.Assert(err, jc.ErrorIsNil) 2696 2697 return mach 2698 } 2699 2700 func (s *MachineSuite) assertMachineAndUnitSeriesChanged(c *gc.C, mach *state.Machine, base state.Base) { 2701 err := mach.Refresh() 2702 c.Assert(err, jc.ErrorIsNil) 2703 c.Assert(mach.Base().String(), gc.Equals, base.String()) 2704 principals := mach.Principals() 2705 for _, p := range principals { 2706 u, err := s.State.Unit(p) 2707 c.Assert(err, jc.ErrorIsNil) 2708 c.Assert(u.Base().String(), jc.DeepEquals, base.String()) 2709 subs := u.SubordinateNames() 2710 for _, sn := range subs { 2711 u, err := s.State.Unit(sn) 2712 c.Assert(err, jc.ErrorIsNil) 2713 c.Assert(u.Base().String(), jc.DeepEquals, base.String()) 2714 } 2715 } 2716 } 2717 2718 func (s *MachineSuite) TestUpdateMachineSeries(c *gc.C) { 2719 mach := s.setupTestUpdateMachineSeries(c) 2720 err := mach.UpdateMachineSeries(state.UbuntuBase("22.04")) 2721 c.Assert(err, jc.ErrorIsNil) 2722 s.assertMachineAndUnitSeriesChanged(c, mach, state.UbuntuBase("22.04")) 2723 } 2724 2725 func (s *MachineSuite) TestUpdateMachineSeriesSameSeriesToStart(c *gc.C) { 2726 mach := s.setupTestUpdateMachineSeries(c) 2727 err := mach.UpdateMachineSeries(state.UbuntuBase("22.04")) 2728 c.Assert(err, jc.ErrorIsNil) 2729 s.assertMachineAndUnitSeriesChanged(c, mach, state.UbuntuBase("22.04")) 2730 } 2731 2732 func (s *MachineSuite) TestUpdateMachineSeriesSameSeriesAfterStart(c *gc.C) { 2733 mach := s.setupTestUpdateMachineSeries(c) 2734 2735 defer state.SetTestHooks(c, s.State, 2736 jujutxn.TestHook{ 2737 Before: func() { 2738 ops := []txn.Op{{ 2739 C: state.MachinesC, 2740 Id: state.DocID(s.State, mach.Id()), 2741 Update: bson.D{{"$set", bson.D{{"series", state.UbuntuBase("22.04")}}}}, 2742 }} 2743 state.RunTransaction(c, s.State, ops) 2744 }, 2745 After: func() { 2746 err := mach.Refresh() 2747 c.Assert(err, jc.ErrorIsNil) 2748 c.Assert(mach.Base().String(), gc.Equals, "ubuntu@22.04/stable") 2749 }, 2750 }, 2751 ).Check() 2752 2753 err := mach.UpdateMachineSeries(state.UbuntuBase("22.04")) 2754 c.Assert(err, jc.ErrorIsNil) 2755 err = mach.Refresh() 2756 c.Assert(err, jc.ErrorIsNil) 2757 c.Assert(mach.Base().DisplayString(), gc.Equals, "ubuntu@22.04") 2758 } 2759 2760 func (s *MachineSuite) TestUpdateMachineSeriesPrincipalsListChange(c *gc.C) { 2761 mach := s.setupTestUpdateMachineSeries(c) 2762 err := mach.Refresh() 2763 c.Assert(err, jc.ErrorIsNil) 2764 c.Assert(len(mach.Principals()), gc.Equals, 1) 2765 2766 defer state.SetTestHooks(c, s.State, 2767 jujutxn.TestHook{ 2768 Before: func() { 2769 app, err := s.State.Application("multi-series") 2770 c.Assert(err, jc.ErrorIsNil) 2771 unit, err := app.AddUnit(state.AddUnitParams{}) 2772 c.Assert(err, jc.ErrorIsNil) 2773 err = unit.AssignToMachine(mach) 2774 c.Assert(err, jc.ErrorIsNil) 2775 }, 2776 }, 2777 ).Check() 2778 2779 err = mach.UpdateMachineSeries(state.UbuntuBase("22.04")) 2780 c.Assert(err, jc.ErrorIsNil) 2781 s.assertMachineAndUnitSeriesChanged(c, mach, state.UbuntuBase("22.04")) 2782 c.Assert(len(mach.Principals()), gc.Equals, 2) 2783 } 2784 2785 func (s *MachineSuite) addMachineUnit(c *gc.C, mach *state.Machine) *state.Unit { 2786 units, err := mach.Units() 2787 c.Assert(err, jc.ErrorIsNil) 2788 2789 var app *state.Application 2790 if len(units) == 0 { 2791 ch := state.AddTestingCharmMultiSeries(c, s.State, "multi-series") 2792 app = state.AddTestingApplicationForBase(c, s.State, mach.Base(), "multi-series", ch) 2793 subCh := state.AddTestingCharmMultiSeries(c, s.State, "multi-series-subordinate") 2794 _ = state.AddTestingApplicationForBase(c, s.State, mach.Base(), "multi-series-subordinate", subCh) 2795 } else { 2796 app, err = units[0].Application() 2797 c.Assert(err, jc.ErrorIsNil) 2798 } 2799 2800 unit, err := app.AddUnit(state.AddUnitParams{}) 2801 c.Assert(err, jc.ErrorIsNil) 2802 err = unit.AssignToMachine(mach) 2803 c.Assert(err, jc.ErrorIsNil) 2804 return unit 2805 } 2806 2807 func (s *MachineSuite) TestWatchAddresses(c *gc.C) { 2808 // Add a machine: reported. 2809 machine, err := s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits) 2810 c.Assert(err, jc.ErrorIsNil) 2811 2812 s.WaitForModelWatchersIdle(c, s.Model.UUID()) 2813 w := machine.WatchAddresses() 2814 defer w.Stop() 2815 wc := testing.NewNotifyWatcherC(c, w) 2816 wc.AssertOneChange() 2817 2818 // Change the machine: not reported. 2819 err = machine.SetProvisioned("i-blah", "", "fake-nonce", nil) 2820 c.Assert(err, jc.ErrorIsNil) 2821 wc.AssertNoChange() 2822 2823 // Set machine addresses: reported. 2824 err = machine.SetMachineAddresses(network.NewSpaceAddress("abc")) 2825 c.Assert(err, jc.ErrorIsNil) 2826 wc.AssertOneChange() 2827 2828 // Set provider addresses eclipsing machine addresses: reported. 2829 err = machine.SetProviderAddresses(network.NewSpaceAddress("abc", network.WithScope(network.ScopePublic))) 2830 c.Assert(err, jc.ErrorIsNil) 2831 wc.AssertOneChange() 2832 2833 // Set same machine eclipsed by provider addresses: not reported. 2834 err = machine.SetMachineAddresses(network.NewSpaceAddress("abc", network.WithScope(network.ScopeCloudLocal))) 2835 c.Assert(err, jc.ErrorIsNil) 2836 wc.AssertNoChange() 2837 2838 // Set different machine addresses: reported. 2839 err = machine.SetMachineAddresses(network.NewSpaceAddress("def")) 2840 c.Assert(err, jc.ErrorIsNil) 2841 wc.AssertOneChange() 2842 2843 // Set different provider addresses: reported. 2844 err = machine.SetMachineAddresses(network.NewSpaceAddress("def", network.WithScope(network.ScopePublic))) 2845 c.Assert(err, jc.ErrorIsNil) 2846 wc.AssertOneChange() 2847 2848 // Make it Dying: not reported. 2849 err = machine.Destroy() 2850 c.Assert(err, jc.ErrorIsNil) 2851 wc.AssertNoChange() 2852 2853 // Make it Dead: not reported. 2854 err = machine.EnsureDead() 2855 c.Assert(err, jc.ErrorIsNil) 2856 wc.AssertNoChange() 2857 2858 // Remove it: watcher eventually closed and Err 2859 // returns an IsNotFound error. 2860 err = machine.Remove() 2861 c.Assert(err, jc.ErrorIsNil) 2862 select { 2863 case _, ok := <-w.Changes(): 2864 c.Assert(ok, jc.IsFalse) 2865 case <-time.After(coretesting.LongWait): 2866 c.Fatalf("watcher not closed") 2867 } 2868 c.Assert(w.Err(), jc.Satisfies, errors.IsNotFound) 2869 } 2870 2871 func (s *MachineSuite) TestGetManualMachineArches(c *gc.C) { 2872 _, err := s.State.AddOneMachine(state.MachineTemplate{ 2873 Base: state.UbuntuBase("12.10"), 2874 Jobs: []state.MachineJob{state.JobHostUnits}, 2875 InstanceId: "manual:foo", 2876 Nonce: "manual:foo-nonce", 2877 HardwareCharacteristics: instance.MustParseHardware("arch=amd64"), 2878 }) 2879 c.Assert(err, jc.ErrorIsNil) 2880 2881 _, err = s.State.AddOneMachine(state.MachineTemplate{ 2882 Base: state.UbuntuBase("12.10"), 2883 Jobs: []state.MachineJob{state.JobHostUnits}, 2884 InstanceId: "manual:bar", 2885 Nonce: "manual:bar-nonce", 2886 HardwareCharacteristics: instance.MustParseHardware("arch=s390x"), 2887 }) 2888 c.Assert(err, jc.ErrorIsNil) 2889 2890 _, err = s.State.AddOneMachine(state.MachineTemplate{ 2891 Base: state.UbuntuBase("12.10"), 2892 Jobs: []state.MachineJob{state.JobHostUnits}, 2893 InstanceId: "lorem", 2894 Nonce: "lorem:nonce", 2895 HardwareCharacteristics: instance.MustParseHardware("arch=ppc64el"), 2896 }) 2897 c.Assert(err, jc.ErrorIsNil) 2898 2899 manualArchSet, err := s.State.GetManualMachineArches() 2900 c.Assert(err, jc.ErrorIsNil) 2901 c.Assert(manualArchSet.SortedValues(), gc.DeepEquals, []string{"amd64", "s390x"}) 2902 }