Merge lp:~themue/juju-core/go-mstate-machine-agent-alive into lp:~juju/juju-core/trunk

Proposed by Frank Mueller
Status: Merged
Approved by: Gustavo Niemeyer
Approved revision: no longer in the source branch.
Merged at revision: 473
Proposed branch: lp:~themue/juju-core/go-mstate-machine-agent-alive
Merge into: lp:~juju/juju-core/trunk
Prerequisite: lp:~themue/juju-core/go-mstate-unit-status
Diff against target: 140 lines (+96/-0) (has conflicts)
2 files modified
mstate/machine.go (+51/-0)
mstate/machine_test.go (+45/-0)
Text conflict in mstate/state.go
To merge this branch: bzr merge lp:~themue/juju-core/go-mstate-machine-agent-alive
Reviewer Review Type Date Requested Status
The Go Language Gophers Pending
Review via email: mp+122819@code.launchpad.net

Description of the change

mstate: added agent alive methods

Machine provides AgentAlive(), WaitAgentAlive() and
SetAgentAlive() using the presence package.

https://codereview.appspot.com/6498091/

To post a comment you must log in.
Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

Nice, LGTM.

https://codereview.appspot.com/6498091/diff/1/mstate/machine.go
File mstate/machine.go (right):

https://codereview.appspot.com/6498091/diff/1/mstate/machine.go#newcode82
mstate/machine.go:82: func (m *Machine) WaitAgentAlive(timeout
time.Duration) error {
Nice implementation.

https://codereview.appspot.com/6498091/diff/1/mstate/machine.go#newcode101
mstate/machine.go:101: panic(fmt.Sprintf("unexpected alive status of
machine %v", m))
"presence reported dead status twice in a row for machine %v"

https://codereview.appspot.com/6498091/diff/1/mstate/machine.go#newcode109
mstate/machine.go:109: // by starting a pinger on its presence node. It
returns the
Please drop the "by starting a pinger on its presence node" part. This
isn't entirely true anymore, and isn't really necessary given the rest
of the doc.

https://codereview.appspot.com/6498091/diff/1/mstate/machine_test.go
File mstate/machine_test.go (right):

https://codereview.appspot.com/6498091/diff/1/mstate/machine_test.go#newcode31
mstate/machine_test.go:31: defer pinger.Kill()
s/Kill/Stop/

We only care that it's not running after the test is done.

https://codereview.appspot.com/6498091/diff/1/mstate/machine_test.go#newcode50
mstate/machine_test.go:50: c.Assert(pinger, Not(IsNil))
This check isn't necessary. We'd go crazy if we had to check everything
that is *not* nil when err is nil.

https://codereview.appspot.com/6498091/diff/1/mstate/machine_test.go#newcode60
mstate/machine_test.go:60: pinger.Kill()
err := pinger.Kill()
c.Assert(err, IsNil)

https://codereview.appspot.com/6498091/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'mstate/machine.go'
2--- mstate/machine.go 2012-08-29 10:05:26 +0000
3+++ mstate/machine.go 2012-09-05 09:13:24 +0000
4@@ -3,8 +3,10 @@
5 import (
6 "fmt"
7 "labix.org/v2/mgo/txn"
8+ "launchpad.net/juju-core/mstate/presence"
9 "launchpad.net/juju-core/trivial"
10 "strconv"
11+ "time"
12 )
13
14 // Machine represents the state of a machine.
15@@ -29,6 +31,11 @@
16 return m.doc.Id
17 }
18
19+// globalKey returns the global database key for the machine.
20+func (m *Machine) globalKey() string {
21+ return "m#" + m.String()
22+}
23+
24 // Life returns whether the machine is Alive, Dying or Dead.
25 func (m *Machine) Life() Life {
26 return m.doc.Life
27@@ -66,6 +73,50 @@
28 return nil
29 }
30
31+// AgentAlive returns whether the respective remote agent is alive.
32+func (m *Machine) AgentAlive() bool {
33+ return m.st.presencew.Alive(m.globalKey())
34+}
35+
36+// WaitAgentAlive blocks until the respective agent is alive.
37+func (m *Machine) WaitAgentAlive(timeout time.Duration) error {
38+ ch := make(chan presence.Change)
39+ m.st.presencew.Add(m.globalKey(), ch)
40+ defer m.st.presencew.Remove(m.globalKey(), ch)
41+ // Initial check.
42+ select {
43+ case change := <-ch:
44+ if change.Alive {
45+ return nil
46+ }
47+ case <-time.After(timeout):
48+ return fmt.Errorf("waiting for agent of machine %v: still not alive after timeout", m)
49+ }
50+ // Hasn't been alive, so now wait for change.
51+ select {
52+ case change := <-ch:
53+ if change.Alive {
54+ return nil
55+ }
56+ panic(fmt.Sprintf("unexpected alive status of machine %v", m))
57+ case <-time.After(timeout):
58+ return fmt.Errorf("waiting for agent of machine %v: still not alive after timeout", m)
59+ }
60+ panic("unreachable")
61+}
62+
63+// SetAgentAlive signals that the agent for machine m is alive
64+// by starting a pinger on its presence node. It returns the
65+// started pinger.
66+func (m *Machine) SetAgentAlive() (*presence.Pinger, error) {
67+ p := presence.NewPinger(m.st.presence, m.globalKey())
68+ err := p.Start()
69+ if err != nil {
70+ return nil, err
71+ }
72+ return p, nil
73+}
74+
75 // InstanceId returns the provider specific machine id for this machine.
76 func (m *Machine) InstanceId() (string, error) {
77 if m.doc.InstanceId == "" {
78
79=== modified file 'mstate/machine_test.go'
80--- mstate/machine_test.go 2012-08-29 10:05:26 +0000
81+++ mstate/machine_test.go 2012-09-05 09:13:24 +0000
82@@ -4,6 +4,7 @@
83 . "launchpad.net/gocheck"
84 state "launchpad.net/juju-core/mstate"
85 "sort"
86+ "time"
87 )
88
89 type MachineSuite struct {
90@@ -20,6 +21,50 @@
91 c.Assert(err, IsNil)
92 }
93
94+func (s *MachineSuite) TestMachineSetAgentAlive(c *C) {
95+ alive := s.machine.AgentAlive()
96+ c.Assert(alive, Equals, false)
97+
98+ pinger, err := s.machine.SetAgentAlive()
99+ c.Assert(err, IsNil)
100+ c.Assert(pinger, Not(IsNil))
101+ defer pinger.Kill()
102+
103+ s.State.ForcePresenceRefresh()
104+ alive = s.machine.AgentAlive()
105+ c.Assert(alive, Equals, true)
106+}
107+
108+func (s *MachineSuite) TestMachineWaitAgentAlive(c *C) {
109+ // test -gocheck.f TestMachineWaitAgentAlive
110+ timeout := 5 * time.Second
111+ alive := s.machine.AgentAlive()
112+ c.Assert(alive, Equals, false)
113+
114+ s.State.ForcePresenceRefresh()
115+ err := s.machine.WaitAgentAlive(timeout)
116+ c.Assert(err, ErrorMatches, `waiting for agent of machine 0: still not alive after timeout`)
117+
118+ pinger, err := s.machine.SetAgentAlive()
119+ c.Assert(err, IsNil)
120+ c.Assert(pinger, Not(IsNil))
121+
122+ s.State.ForcePresenceRefresh()
123+ err = s.machine.WaitAgentAlive(timeout)
124+ c.Assert(err, IsNil)
125+
126+ alive = s.machine.AgentAlive()
127+ c.Assert(err, IsNil)
128+ c.Assert(alive, Equals, true)
129+
130+ pinger.Kill()
131+
132+ s.State.ForcePresenceRefresh()
133+ alive = s.machine.AgentAlive()
134+ c.Assert(err, IsNil)
135+ c.Assert(alive, Equals, false)
136+}
137+
138 func (s *MachineSuite) TestMachineInstanceId(c *C) {
139 machine, err := s.State.AddMachine()
140 c.Assert(err, IsNil)

Subscribers

People subscribed via source and target branches