~themue/juju-core/go-state-service-relation-watcher

« back to all changes in this revision

Viewing changes to state/unit.go

  • Committer: Frank Mueller
  • Date: 2012-08-21 09:36:53 UTC
  • mfrom: (360.1.1 juju-core)
  • Revision ID: themue@gmail.com-20120821093653-kuednavb52fcm9z6
state: merged trunk to stay up-to-date

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
        "launchpad.net/gozk/zookeeper"
8
8
        "launchpad.net/juju-core/charm"
9
9
        "launchpad.net/juju-core/state/presence"
 
10
        "launchpad.net/juju-core/trivial"
10
11
        "strconv"
11
12
        "strings"
12
13
        "time"
33
34
        AssignUnused AssignmentPolicy = "unused"
34
35
)
35
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 hook
 
43
        UnitStarted   UnitStatus = "started"   // Agent is running properly
 
44
        UnitStopped   UnitStatus = "stopped"   // Agent has stopped running on request
 
45
        UnitError     UnitStatus = "error"     // Agent is waiting in an error state
 
46
        UnitDown      UnitStatus = "down"      // Agent is down or not communicating
 
47
)
 
48
 
36
49
// NeedsUpgrade describes if a unit needs an
37
50
// upgrade and if this is forced.
38
51
type NeedsUpgrade struct {
118
131
                principalKey: principalKey,
119
132
        }
120
133
        u.agentTools = agentTools{
121
 
                zk:    st.zk,
 
134
                st:    st,
122
135
                path:  u.zkPath(),
123
136
                agent: "unit",
124
137
        }
157
170
                "private address of unit %q", u)
158
171
}
159
172
 
 
173
// Status returns the status of the unit's agent.
 
174
func (u *Unit) Status() (s UnitStatus, info string, err error) {
 
175
        cn, err := readConfigNode(u.st.zk, u.zkPath())
 
176
        if err != nil {
 
177
                return "", "", fmt.Errorf("cannot read status of unit %q: %v", u, err)
 
178
        }
 
179
        raw, found := cn.Get("status")
 
180
        if !found {
 
181
                return UnitPending, "", nil
 
182
        }
 
183
        s = UnitStatus(raw.(string))
 
184
        switch s {
 
185
        case UnitError:
 
186
                // We always expect an info if status is 'error'.
 
187
                raw, found = cn.Get("status-info")
 
188
                if !found {
 
189
                        panic("no status-info found for unit error")
 
190
                }
 
191
                return s, raw.(string), nil
 
192
        case UnitStopped:
 
193
                return UnitStopped, "", nil
 
194
        }
 
195
        alive, err := u.AgentAlive()
 
196
        if err != nil {
 
197
                return "", "", err
 
198
        }
 
199
        if !alive {
 
200
                s = UnitDown
 
201
        }
 
202
        return s, "", nil
 
203
}
 
204
 
 
205
// SetStatus sets the status of the unit.
 
206
func (u *Unit) SetStatus(status UnitStatus, info string) error {
 
207
        if status == UnitPending {
 
208
                panic("unit status must not be set to pending")
 
209
        }
 
210
        cn, err := readConfigNode(u.st.zk, u.zkPath())
 
211
        if err != nil {
 
212
                return err
 
213
        }
 
214
        cn.Set("status", status)
 
215
        cn.Set("status-info", info)
 
216
        _, err = cn.Write()
 
217
        if err != nil {
 
218
                return fmt.Errorf("cannot set status of unit %q: %v", u, err)
 
219
        }
 
220
        return nil
 
221
}
 
222
 
160
223
// CharmURL returns the charm URL this unit is supposed
161
224
// to use.
162
225
func (u *Unit) CharmURL() (url *charm.URL, err error) {
186
249
 
187
250
// AssignedMachineId returns the id of the assigned machine.
188
251
func (u *Unit) AssignedMachineId() (id int, err error) {
189
 
        defer errorContextf(&err, "cannot get machine id of unit %q", u)
 
252
        defer trivial.ErrorContextf(&err, "cannot get machine id of unit %q", u)
190
253
        topology, err := readTopology(u.st.zk)
191
254
        if err != nil {
192
255
                return 0, err
203
266
 
204
267
// AssignToMachine assigns this unit to a given machine.
205
268
func (u *Unit) AssignToMachine(machine *Machine) (err error) {
206
 
        defer errorContextf(&err, "cannot assign unit %q to machine %s", u, machine)
 
269
        defer trivial.ErrorContextf(&err, "cannot assign unit %q to machine %s", u, machine)
207
270
        assignUnit := func(t *topology) error {
208
271
                if !t.HasUnit(u.key) {
209
272
                        return stateChanged
265
328
// UnassignFromMachine removes the assignment between this unit and
266
329
// the machine it's assigned to.
267
330
func (u *Unit) UnassignFromMachine() (err error) {
268
 
        defer errorContextf(&err, "cannot unassign unit %q from machine", u.Name())
 
331
        defer trivial.ErrorContextf(&err, "cannot unassign unit %q from machine", u.Name())
269
332
        unassignUnit := func(t *topology) error {
270
333
                if !t.HasUnit(u.key) {
271
334
                        return stateChanged
285
348
// NeedsUpgrade returns whether the unit needs an upgrade 
286
349
// and if it does, if this is forced.
287
350
func (u *Unit) NeedsUpgrade() (needsUpgrade *NeedsUpgrade, err error) {
288
 
        defer errorContextf(&err, "cannot check if unit %q needs an upgrade", u.Name())
 
351
        defer trivial.ErrorContextf(&err, "cannot check if unit %q needs an upgrade", u.Name())
289
352
        yaml, _, err := u.st.zk.Get(u.zkNeedsUpgradePath())
290
353
        if zookeeper.IsError(err, zookeeper.ZNONODE) {
291
354
                return &NeedsUpgrade{}, nil
303
366
// SetNeedsUpgrade informs the unit that it should perform 
304
367
// a regular or forced upgrade.
305
368
func (u *Unit) SetNeedsUpgrade(force bool) (err error) {
306
 
        defer errorContextf(&err, "cannot inform unit %q about upgrade", u.Name())
 
369
        defer trivial.ErrorContextf(&err, "cannot inform unit %q about upgrade", u.Name())
307
370
        setNeedsUpgrade := func(oldYaml string, stat *zookeeper.Stat) (string, error) {
308
371
                var setting needsUpgradeNode
309
372
                if oldYaml == "" {
328
391
// ClearNeedsUpgrade resets the upgrade notification. It is typically
329
392
// done by the unit agent before beginning the upgrade.
330
393
func (u *Unit) ClearNeedsUpgrade() (err error) {
331
 
        defer errorContextf(&err, "upgrade notification for unit %q cannot be reset", u.Name())
 
394
        defer trivial.ErrorContextf(&err, "upgrade notification for unit %q cannot be reset", u.Name())
332
395
        err = u.st.zk.Delete(u.zkNeedsUpgradePath(), -1)
333
396
        if zookeeper.IsError(err, zookeeper.ZNONODE) {
334
397
                // Node doesn't exist, so same state.
345
408
 
346
409
// Resolved returns the resolved mode for the unit.
347
410
func (u *Unit) Resolved() (mode ResolvedMode, err error) {
348
 
        defer errorContextf(&err, "cannot get resolved mode for unit %q", u)
 
411
        defer trivial.ErrorContextf(&err, "cannot get resolved mode for unit %q", u)
349
412
        yaml, _, err := u.st.zk.Get(u.zkResolvedPath())
350
413
        if zookeeper.IsError(err, zookeeper.ZNONODE) {
351
414
                // Default value.
372
435
// reexecute previous failed hooks or to continue as if they had 
373
436
// succeeded before.
374
437
func (u *Unit) SetResolved(mode ResolvedMode) (err error) {
375
 
        defer errorContextf(&err, "cannot set resolved mode for unit %q", u)
 
438
        defer trivial.ErrorContextf(&err, "cannot set resolved mode for unit %q", u)
376
439
        if err := validResolvedMode(mode, false); err != nil {
377
440
                return err
378
441
        }
390
453
 
391
454
// ClearResolved removes any resolved setting on the unit.
392
455
func (u *Unit) ClearResolved() (err error) {
393
 
        defer errorContextf(&err, "resolved mode for unit %q cannot be cleared", u)
 
456
        defer trivial.ErrorContextf(&err, "resolved mode for unit %q cannot be cleared", u)
394
457
        err = u.st.zk.Delete(u.zkResolvedPath(), -1)
395
458
        if zookeeper.IsError(err, zookeeper.ZNONODE) {
396
459
                // Node doesn't exist, so same state.
408
471
 
409
472
// OpenPort sets the policy of the port with protocol and number to be opened.
410
473
func (u *Unit) OpenPort(protocol string, number int) (err error) {
411
 
        defer errorContextf(&err, "cannot open port %s:%d for unit %q", protocol, number, u)
 
474
        defer trivial.ErrorContextf(&err, "cannot open port %s:%d for unit %q", protocol, number, u)
412
475
        openPort := func(oldYaml string, stat *zookeeper.Stat) (string, error) {
413
476
                var ports openPortsNode
414
477
                if oldYaml != "" {
438
501
 
439
502
// ClosePort sets the policy of the port with protocol and number to be closed.
440
503
func (u *Unit) ClosePort(protocol string, number int) (err error) {
441
 
        defer errorContextf(&err, "cannot close port %s:%d for unit %q", protocol, number, u)
 
504
        defer trivial.ErrorContextf(&err, "cannot close port %s:%d for unit %q", protocol, number, u)
442
505
        closePort := func(oldYaml string, stat *zookeeper.Stat) (string, error) {
443
506
                var ports openPortsNode
444
507
                if oldYaml != "" {
465
528
 
466
529
// OpenPorts returns a slice containing the open ports of the unit.
467
530
func (u *Unit) OpenPorts() (openPorts []Port, err error) {
468
 
        defer errorContextf(&err, "cannot get open ports of unit %q", u)
 
531
        defer trivial.ErrorContextf(&err, "cannot get open ports of unit %q", u)
469
532
        yaml, _, err := u.st.zk.Get(u.zkPortsPath())
470
533
        if zookeeper.IsError(err, zookeeper.ZNONODE) {
471
534
                // Default value.