1
// Copyright 2012, 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
10
"github.com/juju/errors"
11
"github.com/juju/loggo"
12
jc "github.com/juju/testing/checkers"
13
jujutxn "github.com/juju/txn"
14
"github.com/juju/version"
15
gc "gopkg.in/check.v1"
16
"gopkg.in/juju/names.v2"
18
"gopkg.in/mgo.v2/bson"
20
"github.com/juju/juju/constraints"
21
"github.com/juju/juju/instance"
22
"github.com/juju/juju/mongo/mongotest"
23
"github.com/juju/juju/network"
24
"github.com/juju/juju/provider/dummy"
25
"github.com/juju/juju/state"
26
"github.com/juju/juju/state/testing"
27
"github.com/juju/juju/status"
28
"github.com/juju/juju/storage/poolmanager"
29
"github.com/juju/juju/storage/provider"
30
coretesting "github.com/juju/juju/testing"
31
"github.com/juju/juju/worker"
34
type MachineSuite struct {
36
machine0 *state.Machine
37
machine *state.Machine
40
var _ = gc.Suite(&MachineSuite{})
42
func (s *MachineSuite) SetUpTest(c *gc.C) {
43
s.ConnSuite.SetUpTest(c)
44
s.policy.GetConstraintsValidator = func() (constraints.Validator, error) {
45
validator := constraints.NewValidator()
46
validator.RegisterConflicts([]string{constraints.InstanceType}, []string{constraints.Mem})
47
validator.RegisterUnsupported([]string{constraints.CpuPower})
51
s.machine0, err = s.State.AddMachine("quantal", state.JobManageModel)
52
c.Assert(err, jc.ErrorIsNil)
53
s.machine, err = s.State.AddMachine("quantal", state.JobHostUnits)
54
c.Assert(err, jc.ErrorIsNil)
57
func (s *MachineSuite) TestSetRebootFlagDeadMachine(c *gc.C) {
58
err := s.machine.EnsureDead()
59
c.Assert(err, jc.ErrorIsNil)
61
err = s.machine.SetRebootFlag(true)
62
c.Assert(err, gc.Equals, mgo.ErrNotFound)
64
rFlag, err := s.machine.GetRebootFlag()
65
c.Assert(err, jc.ErrorIsNil)
66
c.Assert(rFlag, jc.IsFalse)
68
err = s.machine.SetRebootFlag(false)
69
c.Assert(err, jc.ErrorIsNil)
71
action, err := s.machine.ShouldRebootOrShutdown()
72
c.Assert(err, jc.ErrorIsNil)
73
c.Assert(action, gc.Equals, state.ShouldDoNothing)
76
func (s *MachineSuite) TestSetRebootFlagDeadMachineRace(c *gc.C) {
77
setFlag := jujutxn.TestHook{
79
err := s.machine.EnsureDead()
80
c.Assert(err, jc.ErrorIsNil)
83
defer state.SetTestHooks(c, s.State, setFlag).Check()
85
err := s.machine.SetRebootFlag(true)
86
c.Assert(err, gc.Equals, mgo.ErrNotFound)
89
func (s *MachineSuite) TestSetRebootFlag(c *gc.C) {
90
err := s.machine.SetRebootFlag(true)
91
c.Assert(err, jc.ErrorIsNil)
93
rebootFlag, err := s.machine.GetRebootFlag()
94
c.Assert(err, jc.ErrorIsNil)
95
c.Assert(rebootFlag, jc.IsTrue)
98
func (s *MachineSuite) TestSetUnsetRebootFlag(c *gc.C) {
99
err := s.machine.SetRebootFlag(true)
100
c.Assert(err, jc.ErrorIsNil)
102
rebootFlag, err := s.machine.GetRebootFlag()
103
c.Assert(err, jc.ErrorIsNil)
104
c.Assert(rebootFlag, jc.IsTrue)
106
err = s.machine.SetRebootFlag(false)
107
c.Assert(err, jc.ErrorIsNil)
109
rebootFlag, err = s.machine.GetRebootFlag()
110
c.Assert(err, jc.ErrorIsNil)
111
c.Assert(rebootFlag, jc.IsFalse)
114
func (s *MachineSuite) TestAddMachineInsideMachineModelDying(c *gc.C) {
115
model, err := s.State.Model()
116
c.Assert(err, jc.ErrorIsNil)
117
c.Assert(model.Destroy(), jc.ErrorIsNil)
119
_, err = s.State.AddMachineInsideMachine(state.MachineTemplate{
121
Jobs: []state.MachineJob{state.JobHostUnits},
122
}, s.machine.Id(), instance.LXD)
123
c.Assert(err, gc.ErrorMatches, `model "testenv" is no longer alive`)
126
func (s *MachineSuite) TestAddMachineInsideMachineModelMigrating(c *gc.C) {
127
model, err := s.State.Model()
128
c.Assert(err, jc.ErrorIsNil)
129
c.Assert(model.SetMigrationMode(state.MigrationModeExporting), jc.ErrorIsNil)
131
_, err = s.State.AddMachineInsideMachine(state.MachineTemplate{
133
Jobs: []state.MachineJob{state.JobHostUnits},
134
}, s.machine.Id(), instance.LXD)
135
c.Assert(err, gc.ErrorMatches, `model "testenv" is being migrated`)
138
func (s *MachineSuite) TestShouldShutdownOrReboot(c *gc.C) {
139
// Add first container.
140
c1, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
142
Jobs: []state.MachineJob{state.JobHostUnits},
143
}, s.machine.Id(), instance.LXD)
144
c.Assert(err, jc.ErrorIsNil)
146
// Add second container.
147
c2, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
149
Jobs: []state.MachineJob{state.JobHostUnits},
150
}, c1.Id(), instance.LXD)
151
c.Assert(err, jc.ErrorIsNil)
153
err = c2.SetRebootFlag(true)
154
c.Assert(err, jc.ErrorIsNil)
156
rAction, err := s.machine.ShouldRebootOrShutdown()
157
c.Assert(err, jc.ErrorIsNil)
158
c.Assert(rAction, gc.Equals, state.ShouldDoNothing)
160
rAction, err = c1.ShouldRebootOrShutdown()
161
c.Assert(err, jc.ErrorIsNil)
162
c.Assert(rAction, gc.Equals, state.ShouldDoNothing)
164
rAction, err = c2.ShouldRebootOrShutdown()
165
c.Assert(err, jc.ErrorIsNil)
166
c.Assert(rAction, gc.Equals, state.ShouldReboot)
168
// // Reboot happens on the root node
169
err = c2.SetRebootFlag(false)
170
c.Assert(err, jc.ErrorIsNil)
172
err = s.machine.SetRebootFlag(true)
173
c.Assert(err, jc.ErrorIsNil)
175
rAction, err = s.machine.ShouldRebootOrShutdown()
176
c.Assert(err, jc.ErrorIsNil)
177
c.Assert(rAction, gc.Equals, state.ShouldReboot)
179
rAction, err = c1.ShouldRebootOrShutdown()
180
c.Assert(err, jc.ErrorIsNil)
181
c.Assert(rAction, gc.Equals, state.ShouldShutdown)
183
rAction, err = c2.ShouldRebootOrShutdown()
184
c.Assert(err, jc.ErrorIsNil)
185
c.Assert(rAction, gc.Equals, state.ShouldShutdown)
188
func (s *MachineSuite) TestContainerDefaults(c *gc.C) {
189
c.Assert(string(s.machine.ContainerType()), gc.Equals, "")
190
containers, err := s.machine.Containers()
191
c.Assert(err, jc.ErrorIsNil)
192
c.Assert(containers, gc.DeepEquals, []string(nil))
195
func (s *MachineSuite) TestParentId(c *gc.C) {
196
parentId, ok := s.machine.ParentId()
197
c.Assert(parentId, gc.Equals, "")
198
c.Assert(ok, jc.IsFalse)
199
container, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
201
Jobs: []state.MachineJob{state.JobHostUnits},
202
}, s.machine.Id(), instance.LXD)
203
c.Assert(err, jc.ErrorIsNil)
204
parentId, ok = container.ParentId()
205
c.Assert(parentId, gc.Equals, s.machine.Id())
206
c.Assert(ok, jc.IsTrue)
209
func (s *MachineSuite) TestMachineIsManager(c *gc.C) {
210
c.Assert(s.machine0.IsManager(), jc.IsTrue)
211
c.Assert(s.machine.IsManager(), jc.IsFalse)
214
func (s *MachineSuite) TestMachineIsManualBootstrap(c *gc.C) {
215
cfg, err := s.State.ModelConfig()
216
c.Assert(err, jc.ErrorIsNil)
217
c.Assert(cfg.Type(), gc.Not(gc.Equals), "null")
218
c.Assert(s.machine.Id(), gc.Equals, "1")
219
manual, err := s.machine0.IsManual()
220
c.Assert(err, jc.ErrorIsNil)
221
c.Assert(manual, jc.IsFalse)
222
attrs := map[string]interface{}{"type": "null"}
223
err = s.State.UpdateModelConfig(attrs, nil, nil)
224
c.Assert(err, jc.ErrorIsNil)
225
manual, err = s.machine0.IsManual()
226
c.Assert(err, jc.ErrorIsNil)
227
c.Assert(manual, jc.IsTrue)
230
func (s *MachineSuite) TestMachineIsManual(c *gc.C) {
232
instanceId instance.Id
236
{instanceId: "x", nonce: "y", isManual: false},
237
{instanceId: "manual:", nonce: "y", isManual: false},
238
{instanceId: "x", nonce: "manual:", isManual: true},
239
{instanceId: "x", nonce: "manual:y", isManual: true},
240
{instanceId: "x", nonce: "manual", isManual: false},
242
for _, test := range tests {
243
m, err := s.State.AddOneMachine(state.MachineTemplate{
245
Jobs: []state.MachineJob{state.JobHostUnits},
246
InstanceId: test.instanceId,
249
c.Assert(err, jc.ErrorIsNil)
250
isManual, err := m.IsManual()
251
c.Assert(isManual, gc.Equals, test.isManual)
255
func (s *MachineSuite) TestMachineIsContainer(c *gc.C) {
256
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
257
c.Assert(err, jc.ErrorIsNil)
259
template := state.MachineTemplate{
261
Jobs: []state.MachineJob{state.JobHostUnits},
263
container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXD)
264
c.Assert(err, jc.ErrorIsNil)
266
c.Assert(machine.IsContainer(), jc.IsFalse)
267
c.Assert(container.IsContainer(), jc.IsTrue)
270
func (s *MachineSuite) TestLifeJobManageModel(c *gc.C) {
271
// A JobManageModel machine must never advance lifecycle.
274
c.Assert(err, gc.ErrorMatches, "machine 0 is required by the model")
275
err = m.ForceDestroy()
276
c.Assert(err, gc.ErrorMatches, "machine is required by the model")
278
c.Assert(err, gc.ErrorMatches, "machine 0 is required by the model")
281
func (s *MachineSuite) TestLifeMachineWithContainer(c *gc.C) {
282
// A machine hosting a container must not advance lifecycle.
283
_, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
285
Jobs: []state.MachineJob{state.JobHostUnits},
286
}, s.machine.Id(), instance.LXD)
287
c.Assert(err, jc.ErrorIsNil)
288
err = s.machine.Destroy()
289
c.Assert(err, gc.FitsTypeOf, &state.HasContainersError{})
290
c.Assert(err, gc.ErrorMatches, `machine 1 is hosting containers "1/lxd/0"`)
291
err1 := s.machine.EnsureDead()
292
c.Assert(err1, gc.DeepEquals, err)
293
c.Assert(s.machine.Life(), gc.Equals, state.Alive)
296
func (s *MachineSuite) TestLifeJobHostUnits(c *gc.C) {
297
// A machine with an assigned unit must not advance lifecycle.
298
svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
299
unit, err := svc.AddUnit()
300
c.Assert(err, jc.ErrorIsNil)
301
err = unit.AssignToMachine(s.machine)
302
c.Assert(err, jc.ErrorIsNil)
303
err = s.machine.Destroy()
304
c.Assert(err, jc.Satisfies, state.IsHasAssignedUnitsError)
305
c.Assert(err, gc.ErrorMatches, `machine 1 has unit "wordpress/0" assigned`)
306
err1 := s.machine.EnsureDead()
307
c.Assert(err1, gc.DeepEquals, err)
308
c.Assert(s.machine.Life(), gc.Equals, state.Alive)
310
// Once no unit is assigned, lifecycle can advance.
311
err = unit.UnassignFromMachine()
312
c.Assert(err, jc.ErrorIsNil)
313
err = s.machine.Destroy()
314
c.Assert(s.machine.Life(), gc.Equals, state.Dying)
315
c.Assert(err, jc.ErrorIsNil)
316
err = s.machine.EnsureDead()
317
c.Assert(err, jc.ErrorIsNil)
318
c.Assert(s.machine.Life(), gc.Equals, state.Dead)
320
// A machine that has never had units assigned can advance lifecycle.
321
m, err := s.State.AddMachine("quantal", state.JobHostUnits)
322
c.Assert(err, jc.ErrorIsNil)
324
c.Assert(err, jc.ErrorIsNil)
325
c.Assert(m.Life(), gc.Equals, state.Dying)
327
c.Assert(err, jc.ErrorIsNil)
328
c.Assert(m.Life(), gc.Equals, state.Dead)
331
func (s *MachineSuite) TestDestroyRemovePorts(c *gc.C) {
332
svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
333
unit, err := svc.AddUnit()
334
c.Assert(err, jc.ErrorIsNil)
335
err = unit.AssignToMachine(s.machine)
336
c.Assert(err, jc.ErrorIsNil)
337
err = unit.OpenPort("tcp", 8080)
338
c.Assert(err, jc.ErrorIsNil)
339
ports, err := state.GetPorts(s.State, s.machine.Id(), "")
340
c.Assert(ports, gc.NotNil)
341
c.Assert(err, jc.ErrorIsNil)
342
err = unit.UnassignFromMachine()
343
c.Assert(err, jc.ErrorIsNil)
344
err = s.machine.Destroy()
345
c.Assert(err, jc.ErrorIsNil)
346
err = s.machine.EnsureDead()
347
c.Assert(err, jc.ErrorIsNil)
348
err = s.machine.Remove()
349
c.Assert(err, jc.ErrorIsNil)
350
// once the machine is destroyed, there should be no ports documents present for it
351
ports, err = state.GetPorts(s.State, s.machine.Id(), "")
352
c.Assert(ports, gc.IsNil)
353
c.Assert(err, jc.Satisfies, errors.IsNotFound)
356
func (s *MachineSuite) TestDestroyOps(c *gc.C) {
357
m := s.Factory.MakeMachine(c, nil)
358
ops, err := state.ForceDestroyMachineOps(m)
359
c.Assert(err, jc.ErrorIsNil)
360
c.Assert(ops, gc.NotNil)
363
func (s *MachineSuite) TestDestroyOpsForManagerFails(c *gc.C) {
364
// s.Factory does not allow us to make a manager machine, so we grab one
366
machines, err := s.State.AllMachines()
367
c.Assert(err, jc.ErrorIsNil)
368
c.Assert(len(machines), jc.GreaterThan, 0)
370
c.Assert(m.IsManager(), jc.IsTrue)
372
// ... and assert that we cannot get the destroy ops for it.
373
ops, err := state.ForceDestroyMachineOps(m)
374
c.Assert(err, jc.Satisfies, state.IsManagerMachineError)
375
c.Assert(ops, gc.IsNil)
378
func (s *MachineSuite) TestDestroyAbort(c *gc.C) {
379
defer state.SetBeforeHooks(c, s.State, func() {
380
c.Assert(s.machine.Destroy(), gc.IsNil)
382
err := s.machine.Destroy()
383
c.Assert(err, jc.ErrorIsNil)
386
func (s *MachineSuite) TestDestroyCancel(c *gc.C) {
387
svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
388
unit, err := svc.AddUnit()
389
c.Assert(err, jc.ErrorIsNil)
391
defer state.SetBeforeHooks(c, s.State, func() {
392
c.Assert(unit.AssignToMachine(s.machine), gc.IsNil)
394
err = s.machine.Destroy()
395
c.Assert(err, jc.Satisfies, state.IsHasAssignedUnitsError)
398
func (s *MachineSuite) TestDestroyContention(c *gc.C) {
399
svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
400
unit, err := svc.AddUnit()
401
c.Assert(err, jc.ErrorIsNil)
403
perturb := jujutxn.TestHook{
404
Before: func() { c.Assert(unit.AssignToMachine(s.machine), gc.IsNil) },
405
After: func() { c.Assert(unit.UnassignFromMachine(), gc.IsNil) },
407
defer state.SetTestHooks(c, s.State, perturb, perturb, perturb).Check()
409
err = s.machine.Destroy()
410
c.Assert(err, gc.ErrorMatches, "machine 1 cannot advance lifecycle: state changing too quickly; try again soon")
413
func (s *MachineSuite) TestDestroyWithServiceDestroyPending(c *gc.C) {
414
svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
415
unit, err := svc.AddUnit()
416
c.Assert(err, jc.ErrorIsNil)
417
err = unit.AssignToMachine(s.machine)
418
c.Assert(err, jc.ErrorIsNil)
421
c.Assert(err, jc.ErrorIsNil)
422
err = s.machine.Destroy()
423
c.Assert(err, jc.ErrorIsNil)
424
// Machine is still advanced to Dying.
425
life := s.machine.Life()
426
c.Assert(life, gc.Equals, state.Dying)
429
func (s *MachineSuite) TestDestroyFailsWhenNewUnitAdded(c *gc.C) {
430
svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
431
unit, err := svc.AddUnit()
432
c.Assert(err, jc.ErrorIsNil)
433
err = unit.AssignToMachine(s.machine)
434
c.Assert(err, jc.ErrorIsNil)
437
c.Assert(err, jc.ErrorIsNil)
439
defer state.SetBeforeHooks(c, s.State, func() {
440
anotherSvc := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql"))
441
anotherUnit, err := anotherSvc.AddUnit()
442
c.Assert(err, jc.ErrorIsNil)
443
err = anotherUnit.AssignToMachine(s.machine)
444
c.Assert(err, jc.ErrorIsNil)
447
err = s.machine.Destroy()
448
c.Assert(err, jc.Satisfies, state.IsHasAssignedUnitsError)
449
life := s.machine.Life()
450
c.Assert(life, gc.Equals, state.Alive)
453
func (s *MachineSuite) TestDestroyWithUnitDestroyPending(c *gc.C) {
454
svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
455
unit, err := svc.AddUnit()
456
c.Assert(err, jc.ErrorIsNil)
457
err = unit.AssignToMachine(s.machine)
458
c.Assert(err, jc.ErrorIsNil)
461
c.Assert(err, jc.ErrorIsNil)
462
err = s.machine.Destroy()
463
c.Assert(err, jc.ErrorIsNil)
464
// Machine is still advanced to Dying.
465
life := s.machine.Life()
466
c.Assert(life, gc.Equals, state.Dying)
469
func (s *MachineSuite) TestDestroyFailsWhenNewContainerAdded(c *gc.C) {
470
svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
471
unit, err := svc.AddUnit()
472
c.Assert(err, jc.ErrorIsNil)
473
err = unit.AssignToMachine(s.machine)
474
c.Assert(err, jc.ErrorIsNil)
477
c.Assert(err, jc.ErrorIsNil)
479
defer state.SetBeforeHooks(c, s.State, func() {
480
_, err := s.State.AddMachineInsideMachine(state.MachineTemplate{
482
Jobs: []state.MachineJob{state.JobHostUnits},
483
}, s.machine.Id(), instance.LXD)
484
c.Assert(err, jc.ErrorIsNil)
487
err = s.machine.Destroy()
488
c.Assert(err, jc.Satisfies, state.IsHasAssignedUnitsError)
489
life := s.machine.Life()
490
c.Assert(life, gc.Equals, state.Alive)
493
func (s *MachineSuite) TestRemove(c *gc.C) {
494
err := s.State.SetSSHHostKeys(s.machine.MachineTag(), state.SSHHostKeys{"rsa", "dsa"})
495
c.Assert(err, jc.ErrorIsNil)
497
err = s.machine.Remove()
498
c.Assert(err, gc.ErrorMatches, "cannot remove machine 1: machine is not dead")
500
err = s.machine.EnsureDead()
501
c.Assert(err, jc.ErrorIsNil)
503
err = s.machine.Remove()
504
c.Assert(err, jc.ErrorIsNil)
506
err = s.machine.Refresh()
507
c.Assert(err, jc.Satisfies, errors.IsNotFound)
509
_, err = s.machine.HardwareCharacteristics()
510
c.Assert(err, jc.Satisfies, errors.IsNotFound)
512
_, err = s.machine.Containers()
513
c.Assert(err, jc.Satisfies, errors.IsNotFound)
515
_, err = s.State.GetSSHHostKeys(s.machine.MachineTag())
516
c.Assert(errors.IsNotFound(err), jc.IsTrue)
518
// Removing an already removed machine is OK.
519
err = s.machine.Remove()
520
c.Assert(err, jc.ErrorIsNil)
523
func (s *MachineSuite) TestHasVote(c *gc.C) {
524
c.Assert(s.machine.HasVote(), jc.IsFalse)
526
// Make another machine value so that
527
// it won't have the cached HasVote value.
528
m, err := s.State.Machine(s.machine.Id())
529
c.Assert(err, jc.ErrorIsNil)
531
err = s.machine.SetHasVote(true)
532
c.Assert(err, jc.ErrorIsNil)
533
c.Assert(s.machine.HasVote(), jc.IsTrue)
534
c.Assert(m.HasVote(), jc.IsFalse)
537
c.Assert(err, jc.ErrorIsNil)
538
c.Assert(m.HasVote(), jc.IsTrue)
540
err = m.SetHasVote(false)
541
c.Assert(err, jc.ErrorIsNil)
542
c.Assert(m.HasVote(), jc.IsFalse)
544
c.Assert(s.machine.HasVote(), jc.IsTrue)
545
err = s.machine.Refresh()
546
c.Assert(err, jc.ErrorIsNil)
547
c.Assert(s.machine.HasVote(), jc.IsFalse)
550
func (s *MachineSuite) TestCannotDestroyMachineWithVote(c *gc.C) {
551
err := s.machine.SetHasVote(true)
552
c.Assert(err, jc.ErrorIsNil)
554
// Make another machine value so that
555
// it won't have the cached HasVote value.
556
m, err := s.State.Machine(s.machine.Id())
557
c.Assert(err, jc.ErrorIsNil)
559
err = s.machine.Destroy()
560
c.Assert(err, gc.ErrorMatches, "machine "+s.machine.Id()+" is a voting replica set member")
563
c.Assert(err, gc.ErrorMatches, "machine "+s.machine.Id()+" is a voting replica set member")
566
func (s *MachineSuite) TestRemoveAbort(c *gc.C) {
567
err := s.machine.EnsureDead()
568
c.Assert(err, jc.ErrorIsNil)
570
defer state.SetBeforeHooks(c, s.State, func() {
571
c.Assert(s.machine.Remove(), gc.IsNil)
573
err = s.machine.Remove()
574
c.Assert(err, jc.ErrorIsNil)
577
func (s *MachineSuite) TestMachineSetAgentPresence(c *gc.C) {
578
alive, err := s.machine.AgentPresence()
579
c.Assert(err, jc.ErrorIsNil)
580
c.Assert(alive, jc.IsFalse)
582
pinger, err := s.machine.SetAgentPresence()
583
c.Assert(err, jc.ErrorIsNil)
584
c.Assert(pinger, gc.NotNil)
586
c.Assert(worker.Stop(pinger), jc.ErrorIsNil)
590
alive, err = s.machine.AgentPresence()
591
c.Assert(err, jc.ErrorIsNil)
592
c.Assert(alive, jc.IsTrue)
595
func (s *MachineSuite) TestTag(c *gc.C) {
596
tag := s.machine.MachineTag()
597
c.Assert(tag.Kind(), gc.Equals, names.MachineTagKind)
598
c.Assert(tag.Id(), gc.Equals, "1")
600
// To keep gccgo happy, don't compare an interface with a struct.
601
var asTag names.Tag = tag
602
c.Assert(s.machine.Tag(), gc.Equals, asTag)
605
func (s *MachineSuite) TestSetMongoPassword(c *gc.C) {
606
info := testing.NewMongoInfo()
607
st, err := state.Open(s.modelTag, info, mongotest.DialOpts(), state.NewPolicyFunc(nil))
608
c.Assert(err, jc.ErrorIsNil)
610
// Remove the admin password so that the test harness can reset the state.
611
err := st.SetAdminMongoPassword("")
612
c.Check(err, jc.ErrorIsNil)
614
c.Check(err, jc.ErrorIsNil)
617
// Turn on fully-authenticated mode.
618
err = st.SetAdminMongoPassword("admin-secret")
619
c.Assert(err, jc.ErrorIsNil)
620
err = st.MongoSession().DB("admin").Login("admin", "admin-secret")
621
c.Assert(err, jc.ErrorIsNil)
623
// Set the password for the entity
624
ent, err := st.Machine("0")
625
c.Assert(err, jc.ErrorIsNil)
626
err = ent.SetMongoPassword("foo")
627
c.Assert(err, jc.ErrorIsNil)
629
// Check that we cannot log in with the wrong password.
631
info.Password = "bar"
632
err = tryOpenState(s.modelTag, info)
633
c.Check(errors.Cause(err), jc.Satisfies, errors.IsUnauthorized)
634
c.Check(err, gc.ErrorMatches, `cannot log in to admin database as "machine-0": unauthorized mongo access: .*`)
636
// Check that we can log in with the correct password.
637
info.Password = "foo"
638
st1, err := state.Open(s.modelTag, info, mongotest.DialOpts(), state.NewPolicyFunc(nil))
639
c.Assert(err, jc.ErrorIsNil)
642
// Change the password with an entity derived from the newly
643
// opened and authenticated state.
644
ent, err = st.Machine("0")
645
c.Assert(err, jc.ErrorIsNil)
646
err = ent.SetMongoPassword("bar")
647
c.Assert(err, jc.ErrorIsNil)
649
// Check that we cannot log in with the old password.
650
info.Password = "foo"
651
err = tryOpenState(s.modelTag, info)
652
c.Check(errors.Cause(err), jc.Satisfies, errors.IsUnauthorized)
653
c.Check(err, gc.ErrorMatches, `cannot log in to admin database as "machine-0": unauthorized mongo access: .*`)
655
// Check that we can log in with the correct password.
656
info.Password = "bar"
657
err = tryOpenState(s.modelTag, info)
658
c.Assert(err, jc.ErrorIsNil)
660
// Check that the administrator can still log in.
661
info.Tag, info.Password = nil, "admin-secret"
662
err = tryOpenState(s.modelTag, info)
663
c.Assert(err, jc.ErrorIsNil)
666
func (s *MachineSuite) TestSetPassword(c *gc.C) {
667
testSetPassword(c, func() (state.Authenticator, error) {
668
return s.State.Machine(s.machine.Id())
672
func (s *MachineSuite) TestMachineWaitAgentPresence(c *gc.C) {
673
alive, err := s.machine.AgentPresence()
674
c.Assert(err, jc.ErrorIsNil)
675
c.Assert(alive, jc.IsFalse)
678
err = s.machine.WaitAgentPresence(coretesting.ShortWait)
679
c.Assert(err, gc.ErrorMatches, `waiting for agent of machine 1: still not alive after timeout`)
681
pinger, err := s.machine.SetAgentPresence()
682
c.Assert(err, jc.ErrorIsNil)
685
err = s.machine.WaitAgentPresence(coretesting.LongWait)
686
c.Assert(err, jc.ErrorIsNil)
688
alive, err = s.machine.AgentPresence()
689
c.Assert(err, jc.ErrorIsNil)
690
c.Assert(alive, jc.IsTrue)
692
err = pinger.KillForTesting()
693
c.Assert(err, jc.ErrorIsNil)
696
alive, err = s.machine.AgentPresence()
697
c.Assert(err, jc.ErrorIsNil)
698
c.Assert(alive, jc.IsFalse)
701
func (s *MachineSuite) TestMachineInstanceIdCorrupt(c *gc.C) {
702
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
703
c.Assert(err, jc.ErrorIsNil)
704
err = s.machines.Update(
705
bson.D{{"_id", state.DocID(s.State, machine.Id())}},
706
bson.D{{"$set", bson.D{{"instanceid", bson.D{{"foo", "bar"}}}}}},
708
c.Assert(err, jc.ErrorIsNil)
710
err = machine.Refresh()
711
c.Assert(err, jc.ErrorIsNil)
712
iid, err := machine.InstanceId()
713
c.Assert(err, jc.Satisfies, errors.IsNotProvisioned)
714
c.Assert(iid, gc.Equals, instance.Id(""))
717
func (s *MachineSuite) TestMachineInstanceIdMissing(c *gc.C) {
718
iid, err := s.machine.InstanceId()
719
c.Assert(err, jc.Satisfies, errors.IsNotProvisioned)
720
c.Assert(string(iid), gc.Equals, "")
723
func (s *MachineSuite) TestMachineInstanceIdBlank(c *gc.C) {
724
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
725
c.Assert(err, jc.ErrorIsNil)
726
err = s.machines.Update(
727
bson.D{{"_id", state.DocID(s.State, machine.Id())}},
728
bson.D{{"$set", bson.D{{"instanceid", ""}}}},
730
c.Assert(err, jc.ErrorIsNil)
732
err = machine.Refresh()
733
c.Assert(err, jc.ErrorIsNil)
734
iid, err := machine.InstanceId()
735
c.Assert(err, jc.Satisfies, errors.IsNotProvisioned)
736
c.Assert(string(iid), gc.Equals, "")
739
func (s *MachineSuite) TestMachineSetProvisionedUpdatesCharacteristics(c *gc.C) {
740
// Before provisioning, there is no hardware characteristics.
741
_, err := s.machine.HardwareCharacteristics()
742
c.Assert(err, jc.Satisfies, errors.IsNotFound)
745
expected := &instance.HardwareCharacteristics{
749
err = s.machine.SetProvisioned("umbrella/0", "fake_nonce", expected)
750
c.Assert(err, jc.ErrorIsNil)
751
md, err := s.machine.HardwareCharacteristics()
752
c.Assert(err, jc.ErrorIsNil)
753
c.Assert(*md, gc.DeepEquals, *expected)
755
// Reload machine and check again.
756
err = s.machine.Refresh()
757
c.Assert(err, jc.ErrorIsNil)
758
md, err = s.machine.HardwareCharacteristics()
759
c.Assert(err, jc.ErrorIsNil)
760
c.Assert(*md, gc.DeepEquals, *expected)
763
func (s *MachineSuite) TestMachineAvailabilityZone(c *gc.C) {
765
hwc := &instance.HardwareCharacteristics{
766
AvailabilityZone: &zone,
768
err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", hwc)
769
c.Assert(err, jc.ErrorIsNil)
771
zone, err = s.machine.AvailabilityZone()
772
c.Assert(err, jc.ErrorIsNil)
773
c.Check(zone, gc.Equals, "a_zone")
776
func (s *MachineSuite) TestMachineAvailabilityZoneEmpty(c *gc.C) {
778
hwc := &instance.HardwareCharacteristics{
779
AvailabilityZone: &zone,
781
err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", hwc)
782
c.Assert(err, jc.ErrorIsNil)
784
zone, err = s.machine.AvailabilityZone()
785
c.Assert(err, jc.ErrorIsNil)
786
c.Check(zone, gc.Equals, "")
789
func (s *MachineSuite) TestMachineAvailabilityZoneMissing(c *gc.C) {
791
hwc := &instance.HardwareCharacteristics{}
792
err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", hwc)
793
c.Assert(err, jc.ErrorIsNil)
795
zone, err = s.machine.AvailabilityZone()
796
c.Assert(err, jc.ErrorIsNil)
797
c.Check(zone, gc.Equals, "")
800
func (s *MachineSuite) TestMachineSetCheckProvisioned(c *gc.C) {
801
// Check before provisioning.
802
c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse)
804
// Either one should not be empty.
805
err := s.machine.SetProvisioned("umbrella/0", "", nil)
806
c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`)
807
err = s.machine.SetProvisioned("", "fake_nonce", nil)
808
c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`)
809
err = s.machine.SetProvisioned("", "", nil)
810
c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": instance id and nonce cannot be empty`)
812
err = s.machine.SetProvisioned("umbrella/0", "fake_nonce", nil)
813
c.Assert(err, jc.ErrorIsNil)
815
m, err := s.State.Machine(s.machine.Id())
816
c.Assert(err, jc.ErrorIsNil)
817
id, err := m.InstanceId()
818
c.Assert(err, jc.ErrorIsNil)
819
c.Assert(string(id), gc.Equals, "umbrella/0")
820
c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue)
821
id, err = s.machine.InstanceId()
822
c.Assert(err, jc.ErrorIsNil)
823
c.Assert(string(id), gc.Equals, "umbrella/0")
824
c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue)
826
// Try it twice, it should fail.
827
err = s.machine.SetProvisioned("doesn't-matter", "phony", nil)
828
c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": already set`)
830
// Check it with invalid nonce.
831
c.Assert(s.machine.CheckProvisioned("not-really"), jc.IsFalse)
834
func (s *MachineSuite) TestMachineSetInstanceInfoFailureDoesNotProvision(c *gc.C) {
835
assertNotProvisioned := func() {
836
c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse)
839
assertNotProvisioned()
841
invalidVolumes := map[names.VolumeTag]state.VolumeInfo{
842
names.NewVolumeTag("1065"): state.VolumeInfo{VolumeId: "vol-ume"},
844
err := s.machine.SetInstanceInfo("umbrella/0", "fake_nonce", nil, nil, nil, invalidVolumes, nil)
845
c.Assert(err, gc.ErrorMatches, `cannot set info for volume \"1065\": volume \"1065\" not found`)
846
assertNotProvisioned()
848
invalidVolumes = map[names.VolumeTag]state.VolumeInfo{
849
names.NewVolumeTag("1065"): state.VolumeInfo{},
851
err = s.machine.SetInstanceInfo("umbrella/0", "fake_nonce", nil, nil, nil, invalidVolumes, nil)
852
c.Assert(err, gc.ErrorMatches, `cannot set info for volume \"1065\": volume ID not set`)
853
assertNotProvisioned()
855
// TODO(axw) test invalid volume attachment
858
func (s *MachineSuite) addVolume(c *gc.C, params state.VolumeParams, machineId string) names.VolumeTag {
859
ops, tag, err := state.AddVolumeOps(s.State, params, machineId)
860
c.Assert(err, jc.ErrorIsNil)
861
err = state.RunTransaction(s.State, ops)
862
c.Assert(err, jc.ErrorIsNil)
866
func (s *MachineSuite) TestMachineSetInstanceInfoSuccess(c *gc.C) {
867
pm := poolmanager.New(state.NewStateSettings(s.State), dummy.StorageProviders())
868
_, err := pm.Create("loop-pool", provider.LoopProviderType, map[string]interface{}{})
869
c.Assert(err, jc.ErrorIsNil)
871
// Must create the requested block device prior to SetInstanceInfo.
872
volumeTag := s.addVolume(c, state.VolumeParams{Size: 1000, Pool: "loop-pool"}, "123")
873
c.Assert(volumeTag, gc.Equals, names.NewVolumeTag("123/0"))
875
c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsFalse)
876
volumeInfo := state.VolumeInfo{
877
VolumeId: "storage-123",
880
volumes := map[names.VolumeTag]state.VolumeInfo{volumeTag: volumeInfo}
881
err = s.machine.SetInstanceInfo("umbrella/0", "fake_nonce", nil, nil, nil, volumes, nil)
882
c.Assert(err, jc.ErrorIsNil)
883
c.Assert(s.machine.CheckProvisioned("fake_nonce"), jc.IsTrue)
885
volume, err := s.State.Volume(volumeTag)
886
c.Assert(err, jc.ErrorIsNil)
887
info, err := volume.Info()
888
c.Assert(err, jc.ErrorIsNil)
889
volumeInfo.Pool = "loop-pool" // taken from params
890
c.Assert(info, gc.Equals, volumeInfo)
893
func (s *MachineSuite) TestMachineSetProvisionedWhenNotAlive(c *gc.C) {
894
testWhenDying(c, s.machine, notAliveErr, notAliveErr, func() error {
895
return s.machine.SetProvisioned("umbrella/0", "fake_nonce", nil)
899
func (s *MachineSuite) TestMachineSetInstanceStatus(c *gc.C) {
900
// Machine needs to be provisioned first.
901
err := s.machine.SetProvisioned("umbrella/0", "fake_nonce", nil)
902
c.Assert(err, jc.ErrorIsNil)
905
sInfo := status.StatusInfo{
906
Status: status.StatusRunning,
910
err = s.machine.SetInstanceStatus(sInfo)
911
c.Assert(err, jc.ErrorIsNil)
913
// Reload machine and check result.
914
err = s.machine.Refresh()
915
c.Assert(err, jc.ErrorIsNil)
916
machineStatus, err := s.machine.InstanceStatus()
917
c.Assert(err, jc.ErrorIsNil)
918
c.Assert(machineStatus.Status, gc.DeepEquals, status.StatusRunning)
919
c.Assert(machineStatus.Message, gc.DeepEquals, "alive")
922
func (s *MachineSuite) TestMachineRefresh(c *gc.C) {
923
m0, err := s.State.AddMachine("quantal", state.JobHostUnits)
924
c.Assert(err, jc.ErrorIsNil)
925
oldTools, _ := m0.AgentTools()
926
m1, err := s.State.Machine(m0.Id())
927
c.Assert(err, jc.ErrorIsNil)
928
err = m0.SetAgentVersion(version.MustParseBinary("0.0.3-quantal-amd64"))
929
c.Assert(err, jc.ErrorIsNil)
930
newTools, _ := m0.AgentTools()
932
m1Tools, _ := m1.AgentTools()
933
c.Assert(m1Tools, gc.DeepEquals, oldTools)
935
c.Assert(err, jc.ErrorIsNil)
936
m1Tools, _ = m1.AgentTools()
937
c.Assert(*m1Tools, gc.Equals, *newTools)
939
err = m0.EnsureDead()
940
c.Assert(err, jc.ErrorIsNil)
942
c.Assert(err, jc.ErrorIsNil)
944
c.Assert(err, jc.Satisfies, errors.IsNotFound)
947
func (s *MachineSuite) TestRefreshWhenNotAlive(c *gc.C) {
948
// Refresh should work regardless of liveness status.
949
testWhenDying(c, s.machine, noErr, noErr, func() error {
950
return s.machine.Refresh()
954
func (s *MachineSuite) TestMachinePrincipalUnits(c *gc.C) {
955
// Check that Machine.Units and st.UnitsFor work correctly.
957
// Make three machines, three services and three units for each service;
958
// variously assign units to machines and check that Machine.Units
959
// tells us the right thing.
962
m2, err := s.State.AddMachine("quantal", state.JobHostUnits)
963
c.Assert(err, jc.ErrorIsNil)
964
m3, err := s.State.AddMachine("quantal", state.JobHostUnits)
965
c.Assert(err, jc.ErrorIsNil)
967
dummy := s.AddTestingCharm(c, "dummy")
968
logging := s.AddTestingCharm(c, "logging")
969
s0 := s.AddTestingService(c, "s0", dummy)
970
s1 := s.AddTestingService(c, "s1", dummy)
971
s2 := s.AddTestingService(c, "s2", dummy)
972
s3 := s.AddTestingService(c, "s3", logging)
974
units := make([][]*state.Unit, 4)
975
for i, svc := range []*state.Application{s0, s1, s2} {
976
units[i] = make([]*state.Unit, 3)
977
for j := range units[i] {
978
units[i][j], err = svc.AddUnit()
979
c.Assert(err, jc.ErrorIsNil)
982
// Add the logging units subordinate to the s2 units.
983
eps, err := s.State.InferEndpoints("s2", "s3")
984
c.Assert(err, jc.ErrorIsNil)
985
rel, err := s.State.AddRelation(eps...)
986
c.Assert(err, jc.ErrorIsNil)
987
for _, u := range units[2] {
988
ru, err := rel.Unit(u)
989
c.Assert(err, jc.ErrorIsNil)
990
err = ru.EnterScope(nil)
991
c.Assert(err, jc.ErrorIsNil)
993
units[3], err = s3.AllUnits()
994
c.Assert(err, jc.ErrorIsNil)
995
c.Assert(sortedUnitNames(units[3]), jc.DeepEquals, []string{"s3/0", "s3/1", "s3/2"})
997
assignments := []struct {
998
machine *state.Machine
1000
subordinates []*state.Unit
1002
{m1, []*state.Unit{units[0][0]}, nil},
1003
{m2, []*state.Unit{units[0][1], units[1][0], units[1][1], units[2][0]}, []*state.Unit{units[3][0]}},
1004
{m3, []*state.Unit{units[2][2]}, []*state.Unit{units[3][2]}},
1007
for _, a := range assignments {
1008
for _, u := range a.units {
1009
err := u.AssignToMachine(a.machine)
1010
c.Assert(err, jc.ErrorIsNil)
1014
for i, a := range assignments {
1015
c.Logf("test %d", i)
1016
expect := sortedUnitNames(append(a.units, a.subordinates...))
1018
// The units can be retrieved from the machine model.
1019
got, err := a.machine.Units()
1020
c.Assert(err, jc.ErrorIsNil)
1021
c.Assert(sortedUnitNames(got), jc.DeepEquals, expect)
1023
// The units can be retrieved from the machine id.
1024
got, err = s.State.UnitsFor(a.machine.Id())
1025
c.Assert(err, jc.ErrorIsNil)
1026
c.Assert(sortedUnitNames(got), jc.DeepEquals, expect)
1030
func sortedUnitNames(units []*state.Unit) []string {
1031
names := make([]string, len(units))
1032
for i, u := range units {
1039
func (s *MachineSuite) assertMachineDirtyAfterAddingUnit(c *gc.C) (*state.Machine, *state.Application, *state.Unit) {
1040
m, err := s.State.AddMachine("quantal", state.JobHostUnits)
1041
c.Assert(err, jc.ErrorIsNil)
1042
c.Assert(m.Clean(), jc.IsTrue)
1044
svc := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
1045
unit, err := svc.AddUnit()
1046
c.Assert(err, jc.ErrorIsNil)
1047
err = unit.AssignToMachine(m)
1048
c.Assert(err, jc.ErrorIsNil)
1049
c.Assert(m.Clean(), jc.IsFalse)
1053
func (s *MachineSuite) TestMachineDirtyAfterAddingUnit(c *gc.C) {
1054
s.assertMachineDirtyAfterAddingUnit(c)
1057
func (s *MachineSuite) TestMachineDirtyAfterUnassigningUnit(c *gc.C) {
1058
m, _, unit := s.assertMachineDirtyAfterAddingUnit(c)
1059
err := unit.UnassignFromMachine()
1060
c.Assert(err, jc.ErrorIsNil)
1061
c.Assert(m.Clean(), jc.IsFalse)
1064
func (s *MachineSuite) TestMachineDirtyAfterRemovingUnit(c *gc.C) {
1065
m, svc, unit := s.assertMachineDirtyAfterAddingUnit(c)
1066
err := unit.EnsureDead()
1067
c.Assert(err, jc.ErrorIsNil)
1069
c.Assert(err, jc.ErrorIsNil)
1071
c.Assert(err, jc.ErrorIsNil)
1072
c.Assert(m.Clean(), jc.IsFalse)
1075
func (s *MachineSuite) TestWatchMachine(c *gc.C) {
1076
w := s.machine.Watch()
1077
defer testing.AssertStop(c, w)
1080
wc := testing.NewNotifyWatcherC(c, s.State, w)
1081
wc.AssertOneChange()
1083
// Make one change (to a separate instance), check one event.
1084
machine, err := s.State.Machine(s.machine.Id())
1085
c.Assert(err, jc.ErrorIsNil)
1086
err = machine.SetProvisioned("m-foo", "fake_nonce", nil)
1087
c.Assert(err, jc.ErrorIsNil)
1088
wc.AssertOneChange()
1090
// Make two changes, check one event.
1091
err = machine.SetAgentVersion(version.MustParseBinary("0.0.3-quantal-amd64"))
1092
c.Assert(err, jc.ErrorIsNil)
1093
err = machine.Destroy()
1094
c.Assert(err, jc.ErrorIsNil)
1095
wc.AssertOneChange()
1097
// Stop, check closed.
1098
testing.AssertStop(c, w)
1101
// Remove machine, start new watch, check single event.
1102
err = machine.EnsureDead()
1103
c.Assert(err, jc.ErrorIsNil)
1104
err = machine.Remove()
1105
c.Assert(err, jc.ErrorIsNil)
1106
w = s.machine.Watch()
1107
defer testing.AssertStop(c, w)
1108
testing.NewNotifyWatcherC(c, s.State, w).AssertOneChange()
1111
func (s *MachineSuite) TestWatchDiesOnStateClose(c *gc.C) {
1112
// This test is testing logic in watcher.entityWatcher, which
1114
// Machine.WatchHardwareCharacteristics
1117
// State.WatchForModelConfigChanges
1118
// Unit.WatchConfigSettings
1119
testWatcherDiesWhenStateCloses(c, s.modelTag, func(c *gc.C, st *state.State) waiter {
1120
m, err := st.Machine(s.machine.Id())
1121
c.Assert(err, jc.ErrorIsNil)
1128
func (s *MachineSuite) TestWatchPrincipalUnits(c *gc.C) {
1129
// TODO(mjs) - MODELUUID - test with multiple models with
1130
// identically named units and ensure there's no leakage.
1132
// Start a watch on an empty machine; check no units reported.
1133
w := s.machine.WatchPrincipalUnits()
1134
defer testing.AssertStop(c, w)
1135
wc := testing.NewStringsWatcherC(c, s.State, w)
1139
// Change machine, and create a unit independently; no change.
1140
err := s.machine.SetProvisioned("cheese", "fake_nonce", nil)
1141
c.Assert(err, jc.ErrorIsNil)
1143
mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql"))
1144
mysql0, err := mysql.AddUnit()
1145
c.Assert(err, jc.ErrorIsNil)
1148
// Assign that unit (to a separate machine instance); change detected.
1149
machine, err := s.State.Machine(s.machine.Id())
1150
c.Assert(err, jc.ErrorIsNil)
1151
err = mysql0.AssignToMachine(machine)
1152
c.Assert(err, jc.ErrorIsNil)
1153
wc.AssertChange("mysql/0")
1156
// Change the unit; no change.
1158
sInfo := status.StatusInfo{
1159
Status: status.StatusIdle,
1163
err = mysql0.SetAgentStatus(sInfo)
1164
c.Assert(err, jc.ErrorIsNil)
1167
// Assign another unit and make the first Dying; check both changes detected.
1168
mysql1, err := mysql.AddUnit()
1169
c.Assert(err, jc.ErrorIsNil)
1170
err = mysql1.AssignToMachine(machine)
1171
c.Assert(err, jc.ErrorIsNil)
1172
err = mysql0.Destroy()
1173
c.Assert(err, jc.ErrorIsNil)
1174
wc.AssertChange("mysql/0", "mysql/1")
1177
// Add a subordinate to the Alive unit; no change.
1178
s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging"))
1179
eps, err := s.State.InferEndpoints("mysql", "logging")
1180
c.Assert(err, jc.ErrorIsNil)
1181
rel, err := s.State.AddRelation(eps...)
1182
c.Assert(err, jc.ErrorIsNil)
1183
mysqlru1, err := rel.Unit(mysql1)
1184
c.Assert(err, jc.ErrorIsNil)
1185
err = mysqlru1.EnterScope(nil)
1186
c.Assert(err, jc.ErrorIsNil)
1187
logging0, err := s.State.Unit("logging/0")
1188
c.Assert(err, jc.ErrorIsNil)
1191
// Change the subordinate; no change.
1192
sInfo = status.StatusInfo{
1193
Status: status.StatusIdle,
1197
err = logging0.SetAgentStatus(sInfo)
1198
c.Assert(err, jc.ErrorIsNil)
1201
// Make the Dying unit Dead; change detected.
1202
err = mysql0.EnsureDead()
1203
c.Assert(err, jc.ErrorIsNil)
1204
wc.AssertChange("mysql/0")
1207
// Stop watcher; check Changes chan closed.
1208
testing.AssertStop(c, w)
1211
// Start a fresh watcher; check both principals reported.
1212
w = s.machine.WatchPrincipalUnits()
1213
defer testing.AssertStop(c, w)
1214
wc = testing.NewStringsWatcherC(c, s.State, w)
1215
wc.AssertChange("mysql/0", "mysql/1")
1218
// Remove the Dead unit; no change.
1219
err = mysql0.Remove()
1220
c.Assert(err, jc.ErrorIsNil)
1223
// Destroy the subordinate; no change.
1224
err = logging0.Destroy()
1225
c.Assert(err, jc.ErrorIsNil)
1228
// Unassign the unit; check change.
1229
err = mysql1.UnassignFromMachine()
1230
c.Assert(err, jc.ErrorIsNil)
1231
wc.AssertChange("mysql/1")
1235
func (s *MachineSuite) TestWatchPrincipalUnitsDiesOnStateClose(c *gc.C) {
1236
// This test is testing logic in watcher.unitsWatcher, which
1237
// is also used by Unit.WatchSubordinateUnits.
1238
testWatcherDiesWhenStateCloses(c, s.modelTag, func(c *gc.C, st *state.State) waiter {
1239
m, err := st.Machine(s.machine.Id())
1240
c.Assert(err, jc.ErrorIsNil)
1241
w := m.WatchPrincipalUnits()
1247
func (s *MachineSuite) TestWatchUnits(c *gc.C) {
1248
// Start a watch on an empty machine; check no units reported.
1249
w := s.machine.WatchUnits()
1250
defer testing.AssertStop(c, w)
1251
wc := testing.NewStringsWatcherC(c, s.State, w)
1255
// Change machine; no change.
1256
err := s.machine.SetProvisioned("cheese", "fake_nonce", nil)
1257
c.Assert(err, jc.ErrorIsNil)
1260
// Assign a unit (to a separate instance); change detected.
1261
mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql"))
1262
mysql0, err := mysql.AddUnit()
1263
c.Assert(err, jc.ErrorIsNil)
1264
machine, err := s.State.Machine(s.machine.Id())
1265
c.Assert(err, jc.ErrorIsNil)
1266
err = mysql0.AssignToMachine(machine)
1267
c.Assert(err, jc.ErrorIsNil)
1268
wc.AssertChange("mysql/0")
1271
// Change the unit; no change.
1273
sInfo := status.StatusInfo{
1274
Status: status.StatusIdle,
1278
err = mysql0.SetAgentStatus(sInfo)
1279
c.Assert(err, jc.ErrorIsNil)
1282
// Assign another unit and make the first Dying; check both changes detected.
1283
mysql1, err := mysql.AddUnit()
1284
c.Assert(err, jc.ErrorIsNil)
1285
err = mysql1.AssignToMachine(machine)
1286
c.Assert(err, jc.ErrorIsNil)
1287
err = mysql0.Destroy()
1288
c.Assert(err, jc.ErrorIsNil)
1289
wc.AssertChange("mysql/0", "mysql/1")
1292
// Add a subordinate to the Alive unit; change detected.
1293
s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging"))
1294
eps, err := s.State.InferEndpoints("mysql", "logging")
1295
c.Assert(err, jc.ErrorIsNil)
1296
rel, err := s.State.AddRelation(eps...)
1297
c.Assert(err, jc.ErrorIsNil)
1298
mysqlru1, err := rel.Unit(mysql1)
1299
c.Assert(err, jc.ErrorIsNil)
1300
err = mysqlru1.EnterScope(nil)
1301
c.Assert(err, jc.ErrorIsNil)
1302
logging0, err := s.State.Unit("logging/0")
1303
c.Assert(err, jc.ErrorIsNil)
1304
wc.AssertChange("logging/0")
1307
// Change the subordinate; no change.
1308
sInfo = status.StatusInfo{
1309
Status: status.StatusIdle,
1313
err = logging0.SetAgentStatus(sInfo)
1314
c.Assert(err, jc.ErrorIsNil)
1317
// Make the Dying unit Dead; change detected.
1318
err = mysql0.EnsureDead()
1319
c.Assert(err, jc.ErrorIsNil)
1320
wc.AssertChange("mysql/0")
1323
// Stop watcher; check Changes chan closed.
1324
testing.AssertStop(c, w)
1327
// Start a fresh watcher; check all units reported.
1328
w = s.machine.WatchUnits()
1329
defer testing.AssertStop(c, w)
1330
wc = testing.NewStringsWatcherC(c, s.State, w)
1331
wc.AssertChange("mysql/0", "mysql/1", "logging/0")
1334
// Remove the Dead unit; no change.
1335
err = mysql0.Remove()
1336
c.Assert(err, jc.ErrorIsNil)
1339
// Destroy the subordinate; change detected.
1340
err = logging0.Destroy()
1341
c.Assert(err, jc.ErrorIsNil)
1342
wc.AssertChange("logging/0")
1345
// Unassign the principal; check subordinate departure also reported.
1346
err = mysql1.UnassignFromMachine()
1347
c.Assert(err, jc.ErrorIsNil)
1348
wc.AssertChange("mysql/1", "logging/0")
1352
func (s *MachineSuite) TestWatchUnitsDiesOnStateClose(c *gc.C) {
1353
testWatcherDiesWhenStateCloses(c, s.modelTag, func(c *gc.C, st *state.State) waiter {
1354
m, err := st.Machine(s.machine.Id())
1355
c.Assert(err, jc.ErrorIsNil)
1362
func (s *MachineSuite) TestConstraintsFromModel(c *gc.C) {
1363
econs1 := constraints.MustParse("mem=1G")
1364
econs2 := constraints.MustParse("mem=2G")
1366
// A newly-created machine gets a copy of the model constraints.
1367
err := s.State.SetModelConstraints(econs1)
1368
c.Assert(err, jc.ErrorIsNil)
1369
machine1, err := s.State.AddMachine("quantal", state.JobHostUnits)
1370
c.Assert(err, jc.ErrorIsNil)
1371
mcons1, err := machine1.Constraints()
1372
c.Assert(err, jc.ErrorIsNil)
1373
c.Assert(mcons1, gc.DeepEquals, econs1)
1375
// Change model constraints and add a new machine.
1376
err = s.State.SetModelConstraints(econs2)
1377
c.Assert(err, jc.ErrorIsNil)
1378
machine2, err := s.State.AddMachine("quantal", state.JobHostUnits)
1379
c.Assert(err, jc.ErrorIsNil)
1380
mcons2, err := machine2.Constraints()
1381
c.Assert(err, jc.ErrorIsNil)
1382
c.Assert(mcons2, gc.DeepEquals, econs2)
1384
// Check the original machine has its original constraints.
1385
mcons1, err = machine1.Constraints()
1386
c.Assert(err, jc.ErrorIsNil)
1387
c.Assert(mcons1, gc.DeepEquals, econs1)
1390
func (s *MachineSuite) TestSetConstraints(c *gc.C) {
1391
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1392
c.Assert(err, jc.ErrorIsNil)
1394
// Constraints can be set...
1395
cons1 := constraints.MustParse("mem=1G")
1396
err = machine.SetConstraints(cons1)
1397
c.Assert(err, jc.ErrorIsNil)
1398
mcons, err := machine.Constraints()
1399
c.Assert(err, jc.ErrorIsNil)
1400
c.Assert(mcons, gc.DeepEquals, cons1)
1402
// ...until the machine is provisioned, at which point they stick.
1403
err = machine.SetProvisioned("i-mstuck", "fake_nonce", nil)
1404
c.Assert(err, jc.ErrorIsNil)
1405
cons2 := constraints.MustParse("mem=2G")
1406
err = machine.SetConstraints(cons2)
1407
c.Assert(err, gc.ErrorMatches, "cannot set constraints: machine is already provisioned")
1409
// Check the failed set had no effect.
1410
mcons, err = machine.Constraints()
1411
c.Assert(err, jc.ErrorIsNil)
1412
c.Assert(mcons, gc.DeepEquals, cons1)
1415
func (s *MachineSuite) TestSetAmbiguousConstraints(c *gc.C) {
1416
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1417
c.Assert(err, jc.ErrorIsNil)
1418
cons := constraints.MustParse("mem=4G instance-type=foo")
1419
err = machine.SetConstraints(cons)
1420
c.Assert(err, gc.ErrorMatches, `cannot set constraints: ambiguous constraints: "instance-type" overlaps with "mem"`)
1423
func (s *MachineSuite) TestSetUnsupportedConstraintsWarning(c *gc.C) {
1424
defer loggo.ResetWriters()
1425
logger := loggo.GetLogger("test")
1426
logger.SetLogLevel(loggo.DEBUG)
1427
var tw loggo.TestWriter
1428
c.Assert(loggo.RegisterWriter("constraints-tester", &tw), gc.IsNil)
1430
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1431
c.Assert(err, jc.ErrorIsNil)
1432
cons := constraints.MustParse("mem=4G cpu-power=10")
1433
err = machine.SetConstraints(cons)
1434
c.Assert(err, jc.ErrorIsNil)
1435
c.Assert(tw.Log(), jc.LogMatches, jc.SimpleMessages{{
1437
`setting constraints on machine "2": unsupported constraints: cpu-power`},
1439
mcons, err := machine.Constraints()
1440
c.Assert(err, jc.ErrorIsNil)
1441
c.Assert(mcons, gc.DeepEquals, cons)
1444
func (s *MachineSuite) TestConstraintsLifecycle(c *gc.C) {
1445
cons := constraints.MustParse("mem=1G")
1446
cannotSet := `cannot set constraints: not found or not alive`
1447
testWhenDying(c, s.machine, cannotSet, cannotSet, func() error {
1448
err := s.machine.SetConstraints(cons)
1449
mcons, err1 := s.machine.Constraints()
1450
c.Assert(err1, gc.IsNil)
1451
c.Assert(&mcons, jc.Satisfies, constraints.IsEmpty)
1455
err := s.machine.Remove()
1456
c.Assert(err, jc.ErrorIsNil)
1457
err = s.machine.SetConstraints(cons)
1458
c.Assert(err, gc.ErrorMatches, cannotSet)
1459
_, err = s.machine.Constraints()
1460
c.Assert(err, gc.ErrorMatches, `constraints not found`)
1463
func (s *MachineSuite) TestSetProviderAddresses(c *gc.C) {
1464
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1465
c.Assert(err, jc.ErrorIsNil)
1466
c.Assert(machine.Addresses(), gc.HasLen, 0)
1468
addresses := network.NewAddresses("127.0.0.1", "8.8.8.8")
1469
err = machine.SetProviderAddresses(addresses...)
1470
c.Assert(err, jc.ErrorIsNil)
1471
err = machine.Refresh()
1472
c.Assert(err, jc.ErrorIsNil)
1474
expectedAddresses := network.NewAddresses("8.8.8.8", "127.0.0.1")
1475
c.Assert(machine.Addresses(), jc.DeepEquals, expectedAddresses)
1478
func (s *MachineSuite) TestSetProviderAddressesWithContainers(c *gc.C) {
1479
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1480
c.Assert(err, jc.ErrorIsNil)
1481
c.Assert(machine.Addresses(), gc.HasLen, 0)
1483
// When setting all addresses the subnet addresses have to be
1485
addresses := network.NewAddresses(
1489
err = machine.SetProviderAddresses(addresses...)
1490
c.Assert(err, jc.ErrorIsNil)
1491
err = machine.Refresh()
1492
c.Assert(err, jc.ErrorIsNil)
1494
expectedAddresses := network.NewAddresses("8.8.8.8", "127.0.0.1")
1495
c.Assert(machine.Addresses(), jc.DeepEquals, expectedAddresses)
1498
func (s *MachineSuite) TestSetProviderAddressesOnContainer(c *gc.C) {
1499
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1500
c.Assert(err, jc.ErrorIsNil)
1501
c.Assert(machine.Addresses(), gc.HasLen, 0)
1503
// Create an LXC container inside the machine.
1504
template := state.MachineTemplate{
1506
Jobs: []state.MachineJob{state.JobHostUnits},
1508
container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXD)
1509
c.Assert(err, jc.ErrorIsNil)
1511
// When setting all addresses the subnet address has to accepted.
1512
addresses := network.NewAddresses("127.0.0.1")
1513
err = container.SetProviderAddresses(addresses...)
1514
c.Assert(err, jc.ErrorIsNil)
1515
err = container.Refresh()
1516
c.Assert(err, jc.ErrorIsNil)
1518
expectedAddresses := network.NewAddresses("127.0.0.1")
1519
c.Assert(container.Addresses(), jc.DeepEquals, expectedAddresses)
1522
func (s *MachineSuite) TestSetMachineAddresses(c *gc.C) {
1523
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1524
c.Assert(err, jc.ErrorIsNil)
1525
c.Assert(machine.Addresses(), gc.HasLen, 0)
1527
addresses := network.NewAddresses("127.0.0.1", "8.8.8.8")
1528
err = machine.SetMachineAddresses(addresses...)
1529
c.Assert(err, jc.ErrorIsNil)
1530
err = machine.Refresh()
1531
c.Assert(err, jc.ErrorIsNil)
1533
expectedAddresses := network.NewAddresses("8.8.8.8", "127.0.0.1")
1534
c.Assert(machine.MachineAddresses(), jc.DeepEquals, expectedAddresses)
1537
func (s *MachineSuite) TestSetEmptyMachineAddresses(c *gc.C) {
1538
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1539
c.Assert(err, jc.ErrorIsNil)
1540
c.Assert(machine.Addresses(), gc.HasLen, 0)
1542
// Add some machine addresses initially to make sure they're removed.
1543
addresses := network.NewAddresses("127.0.0.1", "8.8.8.8")
1544
err = machine.SetMachineAddresses(addresses...)
1545
c.Assert(err, jc.ErrorIsNil)
1546
err = machine.Refresh()
1547
c.Assert(err, jc.ErrorIsNil)
1548
c.Assert(machine.MachineAddresses(), gc.HasLen, 2)
1550
// Make call with empty address list.
1551
err = machine.SetMachineAddresses()
1552
c.Assert(err, jc.ErrorIsNil)
1553
err = machine.Refresh()
1554
c.Assert(err, jc.ErrorIsNil)
1556
c.Assert(machine.MachineAddresses(), gc.HasLen, 0)
1559
func (s *MachineSuite) TestMergedAddresses(c *gc.C) {
1560
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1561
c.Assert(err, jc.ErrorIsNil)
1562
c.Assert(machine.Addresses(), gc.HasLen, 0)
1564
providerAddresses := network.NewAddresses(
1574
err = machine.SetProviderAddresses(providerAddresses...)
1575
c.Assert(err, jc.ErrorIsNil)
1577
machineAddresses := network.NewAddresses(
1586
err = machine.SetMachineAddresses(machineAddresses...)
1587
c.Assert(err, jc.ErrorIsNil)
1588
err = machine.Refresh()
1589
c.Assert(err, jc.ErrorIsNil)
1591
// Before setting the addresses coming from either the provider or
1592
// the machine itself, they are sorted to prefer public IPs on
1593
// top, then hostnames, cloud-local, machine-local, link-local.
1594
// Duplicates are removed, then when calling Addresses() both
1595
// sources are merged while preservig the provider addresses
1597
c.Assert(machine.Addresses(), jc.DeepEquals, network.NewAddresses(
1612
func (s *MachineSuite) TestSetProviderAddressesConcurrentChangeDifferent(c *gc.C) {
1613
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1614
c.Assert(err, jc.ErrorIsNil)
1615
c.Assert(machine.Addresses(), gc.HasLen, 0)
1617
addr0 := network.NewAddress("127.0.0.1")
1618
addr1 := network.NewAddress("8.8.8.8")
1620
defer state.SetBeforeHooks(c, s.State, func() {
1621
machine, err := s.State.Machine(machine.Id())
1622
c.Assert(err, jc.ErrorIsNil)
1623
err = machine.SetProviderAddresses(addr1, addr0)
1624
c.Assert(err, jc.ErrorIsNil)
1627
err = machine.SetProviderAddresses(addr0, addr1)
1628
c.Assert(err, jc.ErrorIsNil)
1629
c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0, addr1})
1632
func (s *MachineSuite) TestSetProviderAddressesConcurrentChangeEqual(c *gc.C) {
1633
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1634
c.Assert(err, jc.ErrorIsNil)
1635
c.Assert(machine.Addresses(), gc.HasLen, 0)
1636
machineDocID := state.DocID(s.State, machine.Id())
1637
revno0, err := state.TxnRevno(s.State, "machines", machineDocID)
1638
c.Assert(err, jc.ErrorIsNil)
1640
addr0 := network.NewAddress("127.0.0.1")
1641
addr1 := network.NewAddress("8.8.8.8")
1644
defer state.SetBeforeHooks(c, s.State, func() {
1645
machine, err := s.State.Machine(machine.Id())
1646
c.Assert(err, jc.ErrorIsNil)
1647
err = machine.SetProviderAddresses(addr0, addr1)
1648
c.Assert(err, jc.ErrorIsNil)
1649
revno1, err = state.TxnRevno(s.State, "machines", machineDocID)
1650
c.Assert(err, jc.ErrorIsNil)
1651
c.Assert(revno1, jc.GreaterThan, revno0)
1654
err = machine.SetProviderAddresses(addr0, addr1)
1655
c.Assert(err, jc.ErrorIsNil)
1657
// Doc will be updated; concurrent changes are explicitly ignored.
1658
revno2, err := state.TxnRevno(s.State, "machines", machineDocID)
1659
c.Assert(err, jc.ErrorIsNil)
1660
c.Assert(revno2, jc.GreaterThan, revno1)
1661
c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0, addr1})
1664
func (s *MachineSuite) TestSetProviderAddressesInvalidateMemory(c *gc.C) {
1665
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1666
c.Assert(err, jc.ErrorIsNil)
1667
c.Assert(machine.Addresses(), gc.HasLen, 0)
1668
machineDocID := state.DocID(s.State, machine.Id())
1670
addr0 := network.NewAddress("127.0.0.1")
1671
addr1 := network.NewAddress("8.8.8.8")
1673
// Set addresses to [addr0] initially. We'll get a separate Machine
1674
// object to update addresses, to ensure that the in-memory cache of
1675
// addresses does not prevent the initial Machine from updating
1676
// addresses back to the original value.
1677
err = machine.SetProviderAddresses(addr0)
1678
c.Assert(err, jc.ErrorIsNil)
1679
revno0, err := state.TxnRevno(s.State, "machines", machineDocID)
1680
c.Assert(err, jc.ErrorIsNil)
1682
machine2, err := s.State.Machine(machine.Id())
1683
c.Assert(err, jc.ErrorIsNil)
1684
err = machine2.SetProviderAddresses(addr1)
1685
c.Assert(err, jc.ErrorIsNil)
1686
revno1, err := state.TxnRevno(s.State, "machines", machineDocID)
1687
c.Assert(err, jc.ErrorIsNil)
1688
c.Assert(revno1, jc.GreaterThan, revno0)
1689
c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0})
1690
c.Assert(machine2.Addresses(), jc.SameContents, []network.Address{addr1})
1692
err = machine.SetProviderAddresses(addr0)
1693
c.Assert(err, jc.ErrorIsNil)
1694
revno2, err := state.TxnRevno(s.State, "machines", machineDocID)
1695
c.Assert(err, jc.ErrorIsNil)
1696
c.Assert(revno2, jc.GreaterThan, revno1)
1697
c.Assert(machine.Addresses(), jc.SameContents, []network.Address{addr0})
1700
func (s *MachineSuite) TestPublicAddressSetOnNewMachine(c *gc.C) {
1701
m, err := s.State.AddOneMachine(state.MachineTemplate{
1703
Jobs: []state.MachineJob{state.JobHostUnits},
1704
Addresses: network.NewAddresses("10.0.0.1", "8.8.8.8"),
1706
c.Assert(err, jc.ErrorIsNil)
1707
addr, err := m.PublicAddress()
1708
c.Assert(err, jc.ErrorIsNil)
1709
c.Assert(addr, jc.DeepEquals, network.NewAddress("8.8.8.8"))
1712
func (s *MachineSuite) TestPrivateAddressSetOnNewMachine(c *gc.C) {
1713
m, err := s.State.AddOneMachine(state.MachineTemplate{
1715
Jobs: []state.MachineJob{state.JobHostUnits},
1716
Addresses: network.NewAddresses("10.0.0.1", "8.8.8.8"),
1718
c.Assert(err, jc.ErrorIsNil)
1719
addr, err := m.PrivateAddress()
1720
c.Assert(err, jc.ErrorIsNil)
1721
c.Assert(addr, jc.DeepEquals, network.NewAddress("10.0.0.1"))
1724
func (s *MachineSuite) TestPublicAddressEmptyAddresses(c *gc.C) {
1725
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1726
c.Assert(err, jc.ErrorIsNil)
1727
c.Assert(machine.Addresses(), gc.HasLen, 0)
1729
addr, err := machine.PublicAddress()
1730
c.Assert(err, jc.Satisfies, network.IsNoAddressError)
1731
c.Assert(addr.Value, gc.Equals, "")
1734
func (s *MachineSuite) TestPrivateAddressEmptyAddresses(c *gc.C) {
1735
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1736
c.Assert(err, jc.ErrorIsNil)
1737
c.Assert(machine.Addresses(), gc.HasLen, 0)
1739
addr, err := machine.PrivateAddress()
1740
c.Assert(err, jc.Satisfies, network.IsNoAddressError)
1741
c.Assert(addr.Value, gc.Equals, "")
1744
func (s *MachineSuite) TestPublicAddress(c *gc.C) {
1745
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1746
c.Assert(err, jc.ErrorIsNil)
1748
err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"))
1749
c.Assert(err, jc.ErrorIsNil)
1751
addr, err := machine.PublicAddress()
1752
c.Assert(err, jc.ErrorIsNil)
1753
c.Assert(addr.Value, gc.Equals, "8.8.8.8")
1756
func (s *MachineSuite) TestPrivateAddress(c *gc.C) {
1757
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1758
c.Assert(err, jc.ErrorIsNil)
1760
err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1"))
1761
c.Assert(err, jc.ErrorIsNil)
1763
addr, err := machine.PrivateAddress()
1764
c.Assert(err, jc.ErrorIsNil)
1765
c.Assert(addr.Value, gc.Equals, "10.0.0.1")
1768
func (s *MachineSuite) TestPublicAddressBetterMatch(c *gc.C) {
1769
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1770
c.Assert(err, jc.ErrorIsNil)
1772
err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1"))
1773
c.Assert(err, jc.ErrorIsNil)
1775
addr, err := machine.PublicAddress()
1776
c.Assert(err, jc.ErrorIsNil)
1777
c.Assert(addr.Value, gc.Equals, "10.0.0.1")
1779
err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"))
1780
c.Assert(err, jc.ErrorIsNil)
1782
addr, err = machine.PublicAddress()
1783
c.Assert(err, jc.ErrorIsNil)
1784
c.Assert(addr.Value, gc.Equals, "8.8.8.8")
1787
func (s *MachineSuite) TestPrivateAddressBetterMatch(c *gc.C) {
1788
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1789
c.Assert(err, jc.ErrorIsNil)
1791
err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"))
1792
c.Assert(err, jc.ErrorIsNil)
1794
addr, err := machine.PrivateAddress()
1795
c.Assert(err, jc.ErrorIsNil)
1796
c.Assert(addr.Value, gc.Equals, "8.8.8.8")
1798
err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.1"))
1799
c.Assert(err, jc.ErrorIsNil)
1801
addr, err = machine.PrivateAddress()
1802
c.Assert(err, jc.ErrorIsNil)
1803
c.Assert(addr.Value, gc.Equals, "10.0.0.1")
1806
func (s *MachineSuite) TestPublicAddressChanges(c *gc.C) {
1807
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1808
c.Assert(err, jc.ErrorIsNil)
1810
err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"))
1811
c.Assert(err, jc.ErrorIsNil)
1813
addr, err := machine.PublicAddress()
1814
c.Assert(err, jc.ErrorIsNil)
1815
c.Assert(addr.Value, gc.Equals, "8.8.8.8")
1817
err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4"))
1818
c.Assert(err, jc.ErrorIsNil)
1820
addr, err = machine.PublicAddress()
1821
c.Assert(err, jc.ErrorIsNil)
1822
c.Assert(addr.Value, gc.Equals, "8.8.4.4")
1825
func (s *MachineSuite) TestPrivateAddressChanges(c *gc.C) {
1826
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1827
c.Assert(err, jc.ErrorIsNil)
1829
err = machine.SetMachineAddresses(network.NewAddress("10.0.0.2"))
1830
c.Assert(err, jc.ErrorIsNil)
1832
addr, err := machine.PrivateAddress()
1833
c.Assert(err, jc.ErrorIsNil)
1834
c.Assert(addr.Value, gc.Equals, "10.0.0.2")
1836
err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1"))
1837
c.Assert(err, jc.ErrorIsNil)
1839
addr, err = machine.PrivateAddress()
1840
c.Assert(err, jc.ErrorIsNil)
1841
c.Assert(addr.Value, gc.Equals, "10.0.0.1")
1844
func (s *MachineSuite) TestAddressesDeadMachine(c *gc.C) {
1845
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1846
c.Assert(err, jc.ErrorIsNil)
1848
err = machine.SetProviderAddresses(network.NewAddress("10.0.0.2"), network.NewAddress("8.8.4.4"))
1849
c.Assert(err, jc.ErrorIsNil)
1851
addr, err := machine.PrivateAddress()
1852
c.Assert(err, jc.ErrorIsNil)
1853
c.Assert(addr.Value, gc.Equals, "10.0.0.2")
1855
addr, err = machine.PublicAddress()
1856
c.Assert(err, jc.ErrorIsNil)
1857
c.Assert(addr.Value, gc.Equals, "8.8.4.4")
1859
err = machine.EnsureDead()
1860
c.Assert(err, jc.ErrorIsNil)
1862
// A dead machine should still report the last known addresses.
1863
addr, err = machine.PrivateAddress()
1864
c.Assert(err, jc.ErrorIsNil)
1865
c.Assert(addr.Value, gc.Equals, "10.0.0.2")
1867
addr, err = machine.PublicAddress()
1868
c.Assert(err, jc.ErrorIsNil)
1869
c.Assert(addr.Value, gc.Equals, "8.8.4.4")
1872
func (s *MachineSuite) TestStablePrivateAddress(c *gc.C) {
1873
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1874
c.Assert(err, jc.ErrorIsNil)
1876
err = machine.SetMachineAddresses(network.NewAddress("10.0.0.2"))
1877
c.Assert(err, jc.ErrorIsNil)
1879
addr, err := machine.PrivateAddress()
1880
c.Assert(err, jc.ErrorIsNil)
1881
c.Assert(addr.Value, gc.Equals, "10.0.0.2")
1883
// Now add an address that would previously have sorted before the
1885
err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1"), network.NewAddress("10.0.0.2"))
1886
c.Assert(err, jc.ErrorIsNil)
1888
// Assert the address is unchanged.
1889
addr, err = machine.PrivateAddress()
1890
c.Assert(err, jc.ErrorIsNil)
1891
c.Assert(addr.Value, gc.Equals, "10.0.0.2")
1894
func (s *MachineSuite) TestStablePublicAddress(c *gc.C) {
1895
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1896
c.Assert(err, jc.ErrorIsNil)
1898
err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"))
1899
c.Assert(err, jc.ErrorIsNil)
1901
addr, err := machine.PublicAddress()
1902
c.Assert(err, jc.ErrorIsNil)
1903
c.Assert(addr.Value, gc.Equals, "8.8.8.8")
1905
// Now add an address that would previously have sorted before the
1907
err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4"), network.NewAddress("8.8.8.8"))
1908
c.Assert(err, jc.ErrorIsNil)
1910
// Assert the address is unchanged.
1911
addr, err = machine.PublicAddress()
1912
c.Assert(err, jc.ErrorIsNil)
1913
c.Assert(addr.Value, gc.Equals, "8.8.8.8")
1916
func (s *MachineSuite) TestAddressesRaceMachineFirst(c *gc.C) {
1917
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1918
c.Assert(err, jc.ErrorIsNil)
1920
changeAddresses := jujutxn.TestHook{
1922
err = machine.SetProviderAddresses(network.NewAddress("8.8.8.8"))
1923
c.Assert(err, jc.ErrorIsNil)
1924
address, err := machine.PublicAddress()
1925
c.Assert(err, jc.ErrorIsNil)
1926
c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8"))
1927
address, err = machine.PrivateAddress()
1928
c.Assert(err, jc.ErrorIsNil)
1929
c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8"))
1932
defer state.SetTestHooks(c, s.State, changeAddresses).Check()
1934
err = machine.SetMachineAddresses(network.NewAddress("8.8.4.4"))
1935
c.Assert(err, jc.ErrorIsNil)
1937
machine, err = s.State.Machine(machine.Id())
1938
c.Assert(err, jc.ErrorIsNil)
1939
address, err := machine.PublicAddress()
1940
c.Assert(err, jc.ErrorIsNil)
1941
c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8"))
1942
address, err = machine.PrivateAddress()
1943
c.Assert(err, jc.ErrorIsNil)
1944
c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.8.8"))
1947
func (s *MachineSuite) TestAddressesRaceProviderFirst(c *gc.C) {
1948
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1949
c.Assert(err, jc.ErrorIsNil)
1951
changeAddresses := jujutxn.TestHook{
1953
err = machine.SetMachineAddresses(network.NewAddress("10.0.0.1"))
1954
c.Assert(err, jc.ErrorIsNil)
1955
address, err := machine.PublicAddress()
1956
c.Assert(err, jc.ErrorIsNil)
1957
c.Assert(address, jc.DeepEquals, network.NewAddress("10.0.0.1"))
1958
address, err = machine.PrivateAddress()
1959
c.Assert(err, jc.ErrorIsNil)
1960
c.Assert(address, jc.DeepEquals, network.NewAddress("10.0.0.1"))
1963
defer state.SetTestHooks(c, s.State, changeAddresses).Check()
1965
err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4"))
1966
c.Assert(err, jc.ErrorIsNil)
1968
machine, err = s.State.Machine(machine.Id())
1969
c.Assert(err, jc.ErrorIsNil)
1970
address, err := machine.PublicAddress()
1971
c.Assert(err, jc.ErrorIsNil)
1972
c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.4.4"))
1973
address, err = machine.PrivateAddress()
1974
c.Assert(err, jc.ErrorIsNil)
1975
c.Assert(address, jc.DeepEquals, network.NewAddress("8.8.4.4"))
1978
func (s *MachineSuite) TestPrivateAddressPrefersProvider(c *gc.C) {
1979
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
1980
c.Assert(err, jc.ErrorIsNil)
1982
err = machine.SetMachineAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.2"))
1983
c.Assert(err, jc.ErrorIsNil)
1985
addr, err := machine.PublicAddress()
1986
c.Assert(err, jc.ErrorIsNil)
1987
c.Assert(addr.Value, gc.Equals, "8.8.8.8")
1988
addr, err = machine.PrivateAddress()
1989
c.Assert(err, jc.ErrorIsNil)
1990
c.Assert(addr.Value, gc.Equals, "10.0.0.2")
1992
err = machine.SetProviderAddresses(network.NewAddress("10.0.0.1"))
1993
c.Assert(err, jc.ErrorIsNil)
1995
addr, err = machine.PublicAddress()
1996
c.Assert(err, jc.ErrorIsNil)
1997
c.Assert(addr.Value, gc.Equals, "10.0.0.1")
1998
addr, err = machine.PrivateAddress()
1999
c.Assert(err, jc.ErrorIsNil)
2000
c.Assert(addr.Value, gc.Equals, "10.0.0.1")
2003
func (s *MachineSuite) TestPublicAddressPrefersProvider(c *gc.C) {
2004
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
2005
c.Assert(err, jc.ErrorIsNil)
2007
err = machine.SetMachineAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.2"))
2008
c.Assert(err, jc.ErrorIsNil)
2010
addr, err := machine.PublicAddress()
2011
c.Assert(err, jc.ErrorIsNil)
2012
c.Assert(addr.Value, gc.Equals, "8.8.8.8")
2013
addr, err = machine.PrivateAddress()
2014
c.Assert(err, jc.ErrorIsNil)
2015
c.Assert(addr.Value, gc.Equals, "10.0.0.2")
2017
err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4"))
2018
c.Assert(err, jc.ErrorIsNil)
2020
addr, err = machine.PublicAddress()
2021
c.Assert(err, jc.ErrorIsNil)
2022
c.Assert(addr.Value, gc.Equals, "8.8.4.4")
2023
addr, err = machine.PrivateAddress()
2024
c.Assert(err, jc.ErrorIsNil)
2025
c.Assert(addr.Value, gc.Equals, "8.8.4.4")
2028
func (s *MachineSuite) TestAddressesPrefersProviderBoth(c *gc.C) {
2029
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
2030
c.Assert(err, jc.ErrorIsNil)
2032
err = machine.SetMachineAddresses(network.NewAddress("8.8.8.8"), network.NewAddress("10.0.0.1"))
2033
c.Assert(err, jc.ErrorIsNil)
2035
addr, err := machine.PublicAddress()
2036
c.Assert(err, jc.ErrorIsNil)
2037
c.Assert(addr.Value, gc.Equals, "8.8.8.8")
2038
addr, err = machine.PrivateAddress()
2039
c.Assert(err, jc.ErrorIsNil)
2040
c.Assert(addr.Value, gc.Equals, "10.0.0.1")
2042
err = machine.SetProviderAddresses(network.NewAddress("8.8.4.4"), network.NewAddress("10.0.0.2"))
2043
c.Assert(err, jc.ErrorIsNil)
2045
addr, err = machine.PublicAddress()
2046
c.Assert(err, jc.ErrorIsNil)
2047
c.Assert(addr.Value, gc.Equals, "8.8.4.4")
2048
addr, err = machine.PrivateAddress()
2049
c.Assert(err, jc.ErrorIsNil)
2050
c.Assert(addr.Value, gc.Equals, "10.0.0.2")
2053
func (s *MachineSuite) addMachineWithSupportedContainer(c *gc.C, container instance.ContainerType) *state.Machine {
2054
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
2055
c.Assert(err, jc.ErrorIsNil)
2056
containers := []instance.ContainerType{container}
2057
err = machine.SetSupportedContainers(containers)
2058
c.Assert(err, jc.ErrorIsNil)
2059
assertSupportedContainers(c, machine, containers)
2063
// assertSupportedContainers checks the document in memory has the specified
2064
// containers and then reloads the document from the database to assert saved
2065
// values match also.
2066
func assertSupportedContainers(c *gc.C, machine *state.Machine, containers []instance.ContainerType) {
2067
supportedContainers, known := machine.SupportedContainers()
2068
c.Assert(known, jc.IsTrue)
2069
c.Assert(supportedContainers, gc.DeepEquals, containers)
2070
// Reload so we can check the saved values.
2071
err := machine.Refresh()
2072
c.Assert(err, jc.ErrorIsNil)
2073
supportedContainers, known = machine.SupportedContainers()
2074
c.Assert(known, jc.IsTrue)
2075
c.Assert(supportedContainers, gc.DeepEquals, containers)
2078
func assertSupportedContainersUnknown(c *gc.C, machine *state.Machine) {
2079
containers, known := machine.SupportedContainers()
2080
c.Assert(known, jc.IsFalse)
2081
c.Assert(containers, gc.HasLen, 0)
2084
func (s *MachineSuite) TestSupportedContainersInitiallyUnknown(c *gc.C) {
2085
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
2086
c.Assert(err, jc.ErrorIsNil)
2087
assertSupportedContainersUnknown(c, machine)
2090
func (s *MachineSuite) TestSupportsNoContainers(c *gc.C) {
2091
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
2092
c.Assert(err, jc.ErrorIsNil)
2094
err = machine.SupportsNoContainers()
2095
c.Assert(err, jc.ErrorIsNil)
2096
assertSupportedContainers(c, machine, []instance.ContainerType{})
2099
func (s *MachineSuite) TestSetSupportedContainerTypeNoneIsError(c *gc.C) {
2100
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
2101
c.Assert(err, jc.ErrorIsNil)
2103
err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.NONE})
2104
c.Assert(err, gc.ErrorMatches, `"none" is not a valid container type`)
2105
assertSupportedContainersUnknown(c, machine)
2106
err = machine.Refresh()
2107
c.Assert(err, jc.ErrorIsNil)
2108
assertSupportedContainersUnknown(c, machine)
2111
func (s *MachineSuite) TestSupportsNoContainersOverwritesExisting(c *gc.C) {
2112
machine := s.addMachineWithSupportedContainer(c, instance.LXD)
2114
err := machine.SupportsNoContainers()
2115
c.Assert(err, jc.ErrorIsNil)
2116
assertSupportedContainers(c, machine, []instance.ContainerType{})
2119
func (s *MachineSuite) TestSetSupportedContainersSingle(c *gc.C) {
2120
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
2121
c.Assert(err, jc.ErrorIsNil)
2123
err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD})
2124
c.Assert(err, jc.ErrorIsNil)
2125
assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD})
2128
func (s *MachineSuite) TestSetSupportedContainersSame(c *gc.C) {
2129
machine := s.addMachineWithSupportedContainer(c, instance.LXD)
2131
err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXD})
2132
c.Assert(err, jc.ErrorIsNil)
2133
assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD})
2136
func (s *MachineSuite) TestSetSupportedContainersNew(c *gc.C) {
2137
machine := s.addMachineWithSupportedContainer(c, instance.LXD)
2139
err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM})
2140
c.Assert(err, jc.ErrorIsNil)
2141
assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM})
2144
func (s *MachineSuite) TestSetSupportedContainersMultipeNew(c *gc.C) {
2145
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
2146
c.Assert(err, jc.ErrorIsNil)
2148
err = machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM})
2149
c.Assert(err, jc.ErrorIsNil)
2150
assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM})
2153
func (s *MachineSuite) TestSetSupportedContainersMultipleExisting(c *gc.C) {
2154
machine := s.addMachineWithSupportedContainer(c, instance.LXD)
2156
err := machine.SetSupportedContainers([]instance.ContainerType{instance.LXD, instance.KVM})
2157
c.Assert(err, jc.ErrorIsNil)
2158
assertSupportedContainers(c, machine, []instance.ContainerType{instance.LXD, instance.KVM})
2161
func (s *MachineSuite) TestSetSupportedContainersSetsUnknownToError(c *gc.C) {
2162
// Create a machine and add lxd and kvm containers prior to calling SetSupportedContainers
2163
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
2164
template := state.MachineTemplate{
2166
Jobs: []state.MachineJob{state.JobHostUnits},
2168
container, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.LXD)
2169
c.Assert(err, jc.ErrorIsNil)
2170
supportedContainer, err := s.State.AddMachineInsideMachine(template, machine.Id(), instance.KVM)
2171
c.Assert(err, jc.ErrorIsNil)
2172
err = machine.SetSupportedContainers([]instance.ContainerType{instance.KVM})
2173
c.Assert(err, jc.ErrorIsNil)
2175
// A supported (kvm) container will have a pending status.
2176
err = supportedContainer.Refresh()
2177
c.Assert(err, jc.ErrorIsNil)
2178
statusInfo, err := supportedContainer.Status()
2179
c.Assert(err, jc.ErrorIsNil)
2180
c.Assert(statusInfo.Status, gc.Equals, status.StatusPending)
2182
// An unsupported (lxd) container will have an error status.
2183
err = container.Refresh()
2184
c.Assert(err, jc.ErrorIsNil)
2185
statusInfo, err = container.Status()
2186
c.Assert(err, jc.ErrorIsNil)
2187
c.Assert(statusInfo.Status, gc.Equals, status.StatusError)
2188
c.Assert(statusInfo.Message, gc.Equals, "unsupported container")
2189
c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{"type": "lxd"})
2192
func (s *MachineSuite) TestSupportsNoContainersSetsAllToError(c *gc.C) {
2193
// Create a machine and add all container types prior to calling SupportsNoContainers
2194
machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
2195
var containers []*state.Machine
2196
template := state.MachineTemplate{
2198
Jobs: []state.MachineJob{state.JobHostUnits},
2200
for _, containerType := range instance.ContainerTypes {
2201
container, err := s.State.AddMachineInsideMachine(template, machine.Id(), containerType)
2202
c.Assert(err, jc.ErrorIsNil)
2203
containers = append(containers, container)
2206
err = machine.SupportsNoContainers()
2207
c.Assert(err, jc.ErrorIsNil)
2209
// All containers should be in error state.
2210
for _, container := range containers {
2211
err = container.Refresh()
2212
c.Assert(err, jc.ErrorIsNil)
2213
statusInfo, err := container.Status()
2214
c.Assert(err, jc.ErrorIsNil)
2215
c.Assert(statusInfo.Status, gc.Equals, status.StatusError)
2216
c.Assert(statusInfo.Message, gc.Equals, "unsupported container")
2217
containerType := state.ContainerTypeFromId(container.Id())
2218
c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{"type": string(containerType)})
2222
func (s *MachineSuite) TestMachineAgentTools(c *gc.C) {
2223
m, err := s.State.AddMachine("quantal", state.JobHostUnits)
2224
c.Assert(err, jc.ErrorIsNil)
2225
testAgentTools(c, m, "machine "+m.Id())
2228
func (s *MachineSuite) TestMachineValidActions(c *gc.C) {
2229
m, err := s.State.AddMachine("trusty", state.JobHostUnits)
2230
c.Assert(err, jc.ErrorIsNil)
2232
var tests = []struct {
2235
givenPayload map[string]interface{}
2236
expectedPayload map[string]interface{}
2239
actionName: "juju-run",
2240
errString: `validation failed: (root) : "command" property is missing and required, given {}; (root) : "timeout" property is missing and required, given {}`,
2243
actionName: "juju-run",
2244
givenPayload: map[string]interface{}{"command": "allyourbasearebelongtous", "timeout": 5.0},
2245
expectedPayload: map[string]interface{}{"command": "allyourbasearebelongtous", "timeout": 5.0},
2248
actionName: "baiku",
2249
errString: `cannot add action "baiku" to a machine; only predefined actions allowed`,
2253
for i, t := range tests {
2254
c.Logf("running test %d", i)
2255
action, err := m.AddAction(t.actionName, t.givenPayload)
2256
if t.errString != "" {
2257
c.Assert(err.Error(), gc.Equals, t.errString)
2260
c.Assert(err, jc.ErrorIsNil)
2261
c.Assert(action.Parameters(), jc.DeepEquals, t.expectedPayload)
2266
func (s *MachineSuite) TestMachineAddDifferentAction(c *gc.C) {
2267
m, err := s.State.AddMachine("trusty", state.JobHostUnits)
2268
c.Assert(err, jc.ErrorIsNil)
2270
_, err = m.AddAction("benchmark", nil)
2271
c.Assert(err, gc.ErrorMatches, `cannot add action "benchmark" to a machine; only predefined actions allowed`)