1
// Copyright 2014 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
9
jc "github.com/juju/testing/checkers"
10
"github.com/juju/utils"
11
"github.com/juju/utils/clock"
12
"github.com/juju/utils/series"
13
gc "gopkg.in/check.v1"
15
"github.com/juju/juju/api"
16
apireboot "github.com/juju/juju/api/reboot"
17
"github.com/juju/juju/instance"
18
jujutesting "github.com/juju/juju/juju/testing"
19
"github.com/juju/juju/state"
20
"github.com/juju/juju/worker"
21
"github.com/juju/juju/worker/reboot"
24
type rebootSuite struct {
25
jujutesting.JujuConnSuite
27
machine *state.Machine
28
stateAPI api.Connection
29
rebootState apireboot.State
32
ctRebootState apireboot.State
37
var _ = gc.Suite(&rebootSuite{})
39
func (s *rebootSuite) SetUpTest(c *gc.C) {
41
template := state.MachineTemplate{
42
Series: series.LatestLts(),
43
Jobs: []state.MachineJob{state.JobHostUnits},
45
s.JujuConnSuite.SetUpTest(c)
47
s.stateAPI, s.machine = s.OpenAPIAsNewMachine(c)
48
s.rebootState, err = s.stateAPI.Reboot()
49
c.Assert(err, jc.ErrorIsNil)
50
c.Assert(s.rebootState, gc.NotNil)
53
s.ct, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.KVM)
54
c.Assert(err, jc.ErrorIsNil)
55
password, err := utils.RandomPassword()
56
c.Assert(err, jc.ErrorIsNil)
57
err = s.ct.SetPassword(password)
58
c.Assert(err, jc.ErrorIsNil)
59
err = s.ct.SetProvisioned("foo", "fake_nonce", nil)
60
c.Assert(err, jc.ErrorIsNil)
62
// Open api as container
63
ctState := s.OpenAPIAsMachine(c, s.ct.Tag(), password, "fake_nonce")
64
s.ctRebootState, err = ctState.Reboot()
65
c.Assert(err, jc.ErrorIsNil)
66
c.Assert(s.ctRebootState, gc.NotNil)
68
s.clock = &fakeClock{delay: time.Millisecond}
71
func (s *rebootSuite) TearDownTest(c *gc.C) {
72
s.JujuConnSuite.TearDownTest(c)
75
// NOTE: the various reboot tests use a different lock name for each test.
76
// This is due to the behaviour of the reboot worker. What it does is acquires
77
// the named process lock and never releases it. This is fine(ish) on linux as the
78
// garbage collector will eventually clean up the old lock which will release the
79
// domain socket, but on windows, the actual lock is a system level semaphore wich
80
// isn't cleaned up by the golang garbage collector, but instead relies on the process
81
// dying to release the semaphore handle.
83
// If more tests are added here, they each need their own lock name to avoid blocking
84
// forever on windows.
86
func (s *rebootSuite) TestStartStop(c *gc.C) {
87
worker, err := reboot.NewReboot(s.rebootState, s.AgentConfigForTag(c, s.machine.Tag()), "test-reboot-start-stop", s.clock)
88
c.Assert(err, jc.ErrorIsNil)
90
c.Assert(worker.Wait(), gc.IsNil)
93
func (s *rebootSuite) TestWorkerCatchesRebootEvent(c *gc.C) {
94
wrk, err := reboot.NewReboot(s.rebootState, s.AgentConfigForTag(c, s.machine.Tag()), "test-reboot-event", s.clock)
95
c.Assert(err, jc.ErrorIsNil)
96
err = s.rebootState.RequestReboot()
97
c.Assert(err, jc.ErrorIsNil)
98
c.Assert(wrk.Wait(), gc.Equals, worker.ErrRebootMachine)
101
func (s *rebootSuite) TestContainerCatchesParentFlag(c *gc.C) {
102
wrk, err := reboot.NewReboot(s.ctRebootState, s.AgentConfigForTag(c, s.ct.Tag()), "test-reboot-container", s.clock)
103
c.Assert(err, jc.ErrorIsNil)
104
err = s.rebootState.RequestReboot()
105
c.Assert(err, jc.ErrorIsNil)
106
c.Assert(wrk.Wait(), gc.Equals, worker.ErrShutdownMachine)
109
type fakeClock struct {
114
func (f *fakeClock) After(time.Duration) <-chan time.Time {
115
return time.After(f.delay)