Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(767)

Side by Side Diff: mstate/unit.go

Issue 6494073: mstate: added unit status (Closed)
Patch Set: mstate: added unit status Created 5 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mstate/state_test.go ('k') | mstate/unit_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 package mstate 1 package mstate
2 2
3 import ( 3 import (
4 "errors" 4 "errors"
5 "fmt" 5 "fmt"
6 "labix.org/v2/mgo" 6 "labix.org/v2/mgo"
7 "labix.org/v2/mgo/txn" 7 "labix.org/v2/mgo/txn"
8 "launchpad.net/juju-core/mstate/presence"
8 "launchpad.net/juju-core/trivial" 9 "launchpad.net/juju-core/trivial"
10 "time"
9 ) 11 )
10 12
11 // ResolvedMode describes the way state transition errors· 13 // ResolvedMode describes the way state transition errors·
12 // are resolved.· 14 // are resolved.·
13 type ResolvedMode int 15 type ResolvedMode int
14 16
15 const ( 17 const (
16 ResolvedNone ResolvedMode = iota 18 ResolvedNone ResolvedMode = iota
17 ResolvedRetryHooks 19 ResolvedRetryHooks
18 ResolvedNoHooks 20 ResolvedNoHooks
19 nResolvedModes 21 nResolvedModes
20 ) 22 )
21 23
22 // AssignmentPolicy controls what machine a unit will be assigned to. 24 // AssignmentPolicy controls what machine a unit will be assigned to.
23 type AssignmentPolicy string 25 type AssignmentPolicy string
24 26
25 const ( 27 const (
26 // AssignLocal indicates that all service units should be assigned· 28 // AssignLocal indicates that all service units should be assigned·
27 // to machine 0. 29 // to machine 0.
28 AssignLocal AssignmentPolicy = "local" 30 AssignLocal AssignmentPolicy = "local"
29 // AssignUnused indicates that every service unit should be assigned 31 // AssignUnused indicates that every service unit should be assigned
30 // to a dedicated machine, and that new machines should be launched 32 // to a dedicated machine, and that new machines should be launched
31 // if required. 33 // if required.
32 AssignUnused AssignmentPolicy = "unused" 34 AssignUnused AssignmentPolicy = "unused"
33 ) 35 )
34 36
37 // UnitStatus represents the status of the unit agent.
38 type UnitStatus string
39
40 const (
41 UnitPending UnitStatus = "pending" // Agent hasn't started
42 UnitInstalled UnitStatus = "installed" // Agent has run the installed ho ok
43 UnitStarted UnitStatus = "started" // Agent is running properly
44 UnitStopped UnitStatus = "stopped" // Agent has stopped running on r equest
45 UnitError UnitStatus = "error" // Agent is waiting in an error s tate
46 UnitDown UnitStatus = "down" // Agent is down or not communica ting
47 )
48
35 // NeedsUpgrade describes if a unit needs an 49 // NeedsUpgrade describes if a unit needs an
36 // upgrade and if this is forced. 50 // upgrade and if this is forced.
37 type NeedsUpgrade struct { 51 type NeedsUpgrade struct {
38 Upgrade bool 52 Upgrade bool
39 Force bool 53 Force bool
40 } 54 }
41 55
42 // Port identifies a network port number for a particular protocol. 56 // Port identifies a network port number for a particular protocol.
43 type Port struct { 57 type Port struct {
44 Protocol string `yaml:"proto"` 58 Protocol string `yaml:"proto"`
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 // String returns the unit as string. 100 // String returns the unit as string.
87 func (u *Unit) String() string { 101 func (u *Unit) String() string {
88 return u.doc.Name 102 return u.doc.Name
89 } 103 }
90 104
91 // Name returns the unit name. 105 // Name returns the unit name.
92 func (u *Unit) Name() string { 106 func (u *Unit) Name() string {
93 return u.doc.Name 107 return u.doc.Name
94 } 108 }
95 109
110 // globalKey returns the global database key for the unit.
111 func (u *Unit) globalKey() string {
112 return "u#" + u.doc.Name
113 }
114
96 // Life returns whether the unit is Alive, Dying or Dead. 115 // Life returns whether the unit is Alive, Dying or Dead.
97 func (u *Unit) Life() Life { 116 func (u *Unit) Life() Life {
98 return u.doc.Life 117 return u.doc.Life
99 } 118 }
100 119
101 // Kill sets the unit lifecycle to Dying if it is Alive. 120 // Kill sets the unit lifecycle to Dying if it is Alive.
102 // It does nothing otherwise. 121 // It does nothing otherwise.
103 func (u *Unit) Kill() error { 122 func (u *Unit) Kill() error {
104 err := ensureLife(u.st, u.st.units, u.doc.Name, Dying, "unit") 123 err := ensureLife(u.st, u.st.units, u.doc.Name, Dying, "unit")
105 if err != nil { 124 if err != nil {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 } 167 }
149 168
150 func (u *Unit) Refresh() error { 169 func (u *Unit) Refresh() error {
151 err := u.st.units.FindId(u.doc.Name).One(&u.doc) 170 err := u.st.units.FindId(u.doc.Name).One(&u.doc)
152 if err != nil { 171 if err != nil {
153 return fmt.Errorf("cannot refresh unit %q: %v", u, err) 172 return fmt.Errorf("cannot refresh unit %q: %v", u, err)
154 } 173 }
155 return nil 174 return nil
156 } 175 }
157 176
177 // Status returns the status of the unit's agent.
178 func (u *Unit) Status() (s UnitStatus, info string, err error) {
179 config, err := u.Config()
180 if err != nil {
181 return "", "", fmt.Errorf("cannot read status of unit %q: %v", u , err)
182 }
183 raw, found := config.Get("status")
184 if !found {
185 return UnitPending, "", nil
186 }
187 s = UnitStatus(raw.(string))
188 switch s {
189 case UnitError:
190 // We always expect an info if status is 'error'.
191 raw, found = config.Get("status-info")
192 if !found {
193 panic("no status-info found for unit error")
194 }
195 return s, raw.(string), nil
196 case UnitStopped:
197 return UnitStopped, "", nil
198 }
199 alive := u.AgentAlive()
200 if !alive {
201 s = UnitDown
202 }
203 return s, "", nil
204 }
205
206 // SetStatus sets the status of the unit.
207 func (u *Unit) SetStatus(status UnitStatus, info string) error {
208 if status == UnitPending {
209 panic("unit status must not be set to pending")
210 }
211 config, err := u.Config()
212 if err != nil {
213 return err
214 }
215 config.Set("status", status)
216 config.Set("status-info", info)
217 _, err = config.Write()
218 if err != nil {
219 return fmt.Errorf("cannot set status of unit %q: %v", u, err)
220 }
221 return nil
222 }
223
224 // AgentAlive returns whether the respective remote agent is alive.
225 func (u *Unit) AgentAlive() bool {
226 return u.st.presencew.Alive(u.globalKey())
227 }
228
229 // WaitAgentAlive blocks until the respective agent is alive.
230 func (u *Unit) WaitAgentAlive(timeout time.Duration) error {
231 ch := make(chan presence.Change)
232 u.st.presencew.Add(u.globalKey(), ch)
233 defer u.st.presencew.Remove(u.globalKey(), ch)
234 // Initial check.
235 select {
236 case change := <-ch:
237 if change.Alive {
238 return nil
239 }
240 case <-time.After(timeout):
241 return fmt.Errorf("waiting for agent of unit %q: still not alive after timeout", u)
242 }
243 // Hasn't been alive, so now wait for change.
244 select {
245 case change := <-ch:
246 if change.Alive {
247 return nil
248 }
249 panic(fmt.Sprintf("presence reported dead status twice in a row for unit %q", u))
250 case <-time.After(timeout):
251 return fmt.Errorf("waiting for agent of unit %q: still not alive after timeout", u)
252 }
253 panic("unreachable")
254 }
255
256 // SetAgentAlive signals that the agent for unit u is alive.·
257 // It returns the started pinger.
258 func (u *Unit) SetAgentAlive() (*presence.Pinger, error) {
259 p := presence.NewPinger(u.st.presence, u.globalKey())
260 err := p.Start()
261 if err != nil {
262 return nil, err
263 }
264 return p, nil
265 }
266
158 // AssignedMachineId returns the id of the assigned machine. 267 // AssignedMachineId returns the id of the assigned machine.
159 func (u *Unit) AssignedMachineId() (id int, err error) { 268 func (u *Unit) AssignedMachineId() (id int, err error) {
160 defer trivial.ErrorContextf(&err, "cannot get machine id of unit %q", u) 269 defer trivial.ErrorContextf(&err, "cannot get machine id of unit %q", u)
161 if u.IsPrincipal() { 270 if u.IsPrincipal() {
162 if u.doc.MachineId == nil { 271 if u.doc.MachineId == nil {
163 return 0, errors.New("unit not assigned to machine") 272 return 0, errors.New("unit not assigned to machine")
164 } 273 }
165 return *u.doc.MachineId, nil 274 return *u.doc.MachineId, nil
166 } 275 }
167 pudoc := unitDoc{} 276 pudoc := unitDoc{}
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 func (u *Unit) ClearNeedsUpgrade() error { 461 func (u *Unit) ClearNeedsUpgrade() error {
353 change := D{{"$set", D{{"needsupgrade", nil}}}} 462 change := D{{"$set", D{{"needsupgrade", nil}}}}
354 sel := D{{"_id", u.doc.Name}} 463 sel := D{{"_id", u.doc.Name}}
355 err := u.st.units.Update(sel, change) 464 err := u.st.units.Update(sel, change)
356 if err != nil { 465 if err != nil {
357 return fmt.Errorf("upgrade notification for unit %q cannot be re set: %v", u, err) 466 return fmt.Errorf("upgrade notification for unit %q cannot be re set: %v", u, err)
358 } 467 }
359 u.doc.NeedsUpgrade = nil 468 u.doc.NeedsUpgrade = nil
360 return nil 469 return nil
361 } 470 }
471
472 // Config returns the configuration node for the unit.
473 func (u *Unit) Config() (config *ConfigNode, err error) {
474 config, err = readConfigNode(u.st, u.globalKey())
475 if err != nil {
476 return nil, fmt.Errorf("cannot get configuration of unit %q: %v" , u, err)
477 }
478 return config, nil
479 }
OLDNEW
« no previous file with comments | « mstate/state_test.go ('k') | mstate/unit_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld 204d58d