~rogpeppe/juju-core/438-local-instance-Addresses

« back to all changes in this revision

Viewing changes to worker/uniter/uniter.go

  • Committer: John Arbash Meinel
  • Date: 2013-09-15 07:36:52 UTC
  • mfrom: (1817 juju-core)
  • mto: This revision was merged to the branch mainline in revision 1882.
  • Revision ID: john@arbash-meinel.com-20130915073652-80jnupeguvr1klea
Merge trunk, resolve conflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
        corecharm "launchpad.net/juju-core/charm"
20
20
        "launchpad.net/juju-core/charm/hooks"
21
21
        "launchpad.net/juju-core/cmd"
22
 
        "launchpad.net/juju-core/errors"
23
 
        "launchpad.net/juju-core/state"
 
22
        "launchpad.net/juju-core/state/api/params"
 
23
        "launchpad.net/juju-core/state/api/uniter"
24
24
        "launchpad.net/juju-core/state/watcher"
25
25
        "launchpad.net/juju-core/utils"
26
26
        "launchpad.net/juju-core/utils/fslock"
38
38
// the uniter's responses to them.
39
39
type Uniter struct {
40
40
        tomb          tomb.Tomb
41
 
        st            *state.State
 
41
        st            *uniter.State
42
42
        f             *filter
43
 
        unit          *state.Unit
44
 
        service       *state.Service
 
43
        unit          *uniter.Unit
 
44
        service       *uniter.Service
45
45
        relationers   map[int]*Relationer
46
46
        relationHooks chan hook.Info
47
47
        uuid          string
61
61
        ranConfigChanged bool
62
62
}
63
63
 
64
 
// NewUniter creates a new Uniter which will install, run, and upgrade a
65
 
// charm on behalf of the named unit, by executing hooks and operations
66
 
// provoked by changes in st.
67
 
func NewUniter(st *state.State, name string, dataDir string) *Uniter {
 
64
// NewUniter creates a new Uniter which will install, run, and upgrade
 
65
// a charm on behalf of the unit with the given unitTag, by executing
 
66
// hooks and operations provoked by changes in st.
 
67
func NewUniter(st *uniter.State, unitTag string, dataDir string) *Uniter {
68
68
        u := &Uniter{
69
69
                st:      st,
70
70
                dataDir: dataDir,
71
71
        }
72
72
        go func() {
73
73
                defer u.tomb.Done()
74
 
                u.tomb.Kill(u.loop(name))
 
74
                u.tomb.Kill(u.loop(unitTag))
75
75
        }()
76
76
        return u
77
77
}
78
78
 
79
 
func (u *Uniter) loop(name string) (err error) {
80
 
        if err = u.init(name); err != nil {
 
79
func (u *Uniter) loop(unitTag string) (err error) {
 
80
        if err = u.init(unitTag); err != nil {
81
81
                return err
82
82
        }
83
83
        logger.Infof("unit %q started", u.unit)
84
84
 
85
85
        // Start filtering state change events for consumption by modes.
86
 
        u.f, err = newFilter(u.st, name)
 
86
        u.f, err = newFilter(u.st, unitTag)
87
87
        if err != nil {
88
88
                return err
89
89
        }
92
92
                u.tomb.Kill(u.f.Wait())
93
93
        }()
94
94
 
95
 
        // Announce our presence to the world.
96
 
        pinger, err := u.unit.SetAgentAlive()
97
 
        if err != nil {
98
 
                return err
99
 
        }
100
 
        defer watcher.Stop(pinger, &u.tomb)
101
 
 
102
95
        // Run modes until we encounter an error.
103
96
        mode := ModeInit
104
97
        for err == nil {
133
126
        return nil
134
127
}
135
128
 
136
 
func (u *Uniter) init(name string) (err error) {
137
 
        defer utils.ErrorContextf(&err, "failed to initialize uniter for unit %q", name)
138
 
        u.unit, err = u.st.Unit(name)
 
129
func (u *Uniter) init(unitTag string) (err error) {
 
130
        defer utils.ErrorContextf(&err, "failed to initialize uniter for %q", unitTag)
 
131
        u.unit, err = u.st.Unit(unitTag)
139
132
        if err != nil {
140
133
                return err
141
134
        }
142
135
        if err = u.setupLocks(); err != nil {
143
136
                return err
144
137
        }
145
 
        ename := u.unit.Tag()
146
 
        u.toolsDir = tools.ToolsDir(u.dataDir, ename)
 
138
        u.toolsDir = tools.ToolsDir(u.dataDir, unitTag)
147
139
        if err := EnsureJujucSymlinks(u.toolsDir); err != nil {
148
140
                return err
149
141
        }
150
 
        u.baseDir = filepath.Join(u.dataDir, "agents", ename)
 
142
        u.baseDir = filepath.Join(u.dataDir, "agents", unitTag)
151
143
        u.relationsDir = filepath.Join(u.baseDir, "state", "relations")
152
144
        if err := os.MkdirAll(u.relationsDir, 0755); err != nil {
153
145
                return err
154
146
        }
155
 
        u.service, err = u.st.Service(u.unit.ServiceName())
 
147
        u.service, err = u.st.Service(u.unit.ServiceTag())
156
148
        if err != nil {
157
149
                return err
158
150
        }
159
 
        var env *state.Environment
 
151
        var env *uniter.Environment
160
152
        env, err = u.st.Environment()
161
153
        if err != nil {
162
154
                return err
163
155
        }
164
 
        u.uuid = env.UUID()
 
156
        u.uuid, err = env.UUID()
 
157
        if err != nil {
 
158
                return err
 
159
        }
165
160
        u.relationers = map[int]*Relationer{}
166
161
        u.relationHooks = make(chan hook.Info)
167
162
        u.charm = charm.NewGitDir(filepath.Join(u.baseDir, "charm"))
185
180
        return u.Wait()
186
181
}
187
182
 
188
 
func (u *Uniter) String() string {
189
 
        return "uniter for " + u.unit.Name()
190
 
}
191
 
 
192
183
func (u *Uniter) Dead() <-chan struct{} {
193
184
        return u.tomb.Dead()
194
185
}
325
316
        if err != nil {
326
317
                return err
327
318
        }
328
 
        hctx := NewHookContext(u.unit, hctxId, u.uuid, relationId, hi.RemoteUnit,
 
319
        hctx, err := NewHookContext(u.unit, hctxId, u.uuid, relationId, hi.RemoteUnit,
329
320
                ctxRelations, apiAddrs)
 
321
        if err != nil {
 
322
                return err
 
323
        }
330
324
 
331
325
        // Prepare server.
332
326
        getCmd := func(ctxId, cmdName string) (cmd.Command, error) {
398
392
        }
399
393
        for id, dir := range dirs {
400
394
                remove := false
401
 
                rel, err := u.st.Relation(id)
402
 
                if errors.IsNotFoundError(err) {
 
395
                rel, err := u.st.RelationById(id)
 
396
                if params.IsCodeNotFound(err) {
403
397
                        remove = true
404
398
                } else if err != nil {
405
399
                        return err
406
400
                }
407
 
                if err = u.addRelation(rel, dir); err == state.ErrCannotEnterScope {
 
401
                err = u.addRelation(rel, dir)
 
402
                if params.IsCodeCannotEnterScope(err) {
408
403
                        remove = true
409
404
                } else if err != nil {
410
405
                        return err
432
427
                        if err := rel.Refresh(); err != nil {
433
428
                                return nil, fmt.Errorf("cannot update relation %q: %v", rel, err)
434
429
                        }
435
 
                        if rel.Life() == state.Dying {
 
430
                        if rel.Life() == params.Dying {
436
431
                                if err := r.SetDying(); err != nil {
437
432
                                        return nil, err
438
433
                                } else if r.IsImplicit() {
443
438
                }
444
439
                // Relations that are not alive are simply skipped, because they
445
440
                // were not previously known anyway.
446
 
                rel, err := u.st.Relation(id)
 
441
                rel, err := u.st.RelationById(id)
447
442
                if err != nil {
448
 
                        if errors.IsNotFoundError(err) {
 
443
                        if params.IsCodeNotFound(err) {
449
444
                                continue
450
445
                        }
451
446
                        return nil, err
452
447
                }
453
 
                if rel.Life() != state.Alive {
 
448
                if rel.Life() != params.Alive {
454
449
                        continue
455
450
                }
456
451
                // Make sure we ignore relations not implemented by the unit's charm
458
453
                if err != nil {
459
454
                        return nil, err
460
455
                }
461
 
                if ep, err := rel.Endpoint(u.unit.ServiceName()); err != nil {
 
456
                if ep, err := rel.Endpoint(); err != nil {
462
457
                        return nil, err
463
458
                } else if !ep.ImplementedBy(ch) {
464
459
                        logger.Warningf("skipping relation with unknown endpoint %q", ep)
474
469
                        continue
475
470
                }
476
471
                e := dir.Remove()
477
 
                if err != state.ErrCannotEnterScope {
 
472
                if !params.IsCodeCannotEnterScope(err) {
478
473
                        return nil, err
479
474
                }
480
475
                if e != nil {
481
476
                        return nil, e
482
477
                }
483
478
        }
484
 
        if u.unit.IsPrincipal() {
 
479
        if ok, err := u.unit.IsPrincipal(); err != nil {
 
480
                return nil, err
 
481
        } else if ok {
485
482
                return added, nil
486
483
        }
487
484
        // If no Alive relations remain between a subordinate unit's service
504
501
 
505
502
// addRelation causes the unit agent to join the supplied relation, and to
506
503
// store persistent state in the supplied dir.
507
 
func (u *Uniter) addRelation(rel *state.Relation, dir *relation.StateDir) error {
 
504
func (u *Uniter) addRelation(rel *uniter.Relation, dir *relation.StateDir) error {
508
505
        logger.Infof("joining relation %q", rel)
509
506
        ru, err := rel.Unit(u.unit)
510
507
        if err != nil {
511
508
                return err
512
509
        }
513
510
        r := NewRelationer(ru, dir, u.relationHooks)
514
 
        w := u.unit.Watch()
 
511
        w, err := u.unit.Watch()
 
512
        if err != nil {
 
513
                return err
 
514
        }
515
515
        defer watcher.Stop(w, &u.tomb)
516
516
        for {
517
517
                select {
521
521
                        if !ok {
522
522
                                return watcher.MustErr(w)
523
523
                        }
524
 
                        if err := r.Join(); err == state.ErrCannotEnterScopeYet {
 
524
                        err := r.Join()
 
525
                        if params.IsCodeCannotEnterScopeYet(err) {
525
526
                                logger.Infof("cannot enter scope for relation %q; waiting for subordinate to be removed", rel)
526
527
                                continue
527
528
                        } else if err != nil {