LEFT | RIGHT |
1 package uniter | 1 package uniter |
2 | 2 |
3 import ( | 3 import ( |
4 "errors" | 4 "errors" |
5 "fmt" | 5 "fmt" |
| 6 "launchpad.net/juju-core/environs" |
6 "launchpad.net/juju-core/log" | 7 "launchpad.net/juju-core/log" |
7 "launchpad.net/juju-core/state" | 8 "launchpad.net/juju-core/state" |
8 "launchpad.net/juju-core/state/watcher" | 9 "launchpad.net/juju-core/state/watcher" |
9 "launchpad.net/juju-core/worker/uniter/hook" | 10 "launchpad.net/juju-core/worker/uniter/hook" |
10 "launchpad.net/tomb" | 11 "launchpad.net/tomb" |
11 ) | 12 ) |
12 | 13 |
13 // Mode defines the signature of the functions that implement the possible | 14 // Mode defines the signature of the functions that implement the possible |
14 // states of a running Uniter. | 15 // states of a running Uniter. |
15 type Mode func(u *Uniter) (Mode, error) | 16 type Mode func(u *Uniter) (Mode, error) |
16 | 17 |
17 // ModeInit is the initial Uniter mode. | 18 // ModeInit is the initial Uniter mode. |
18 func ModeInit(u *Uniter) (next Mode, err error) { | 19 func ModeInit(u *Uniter) (next Mode, err error) { |
19 defer errorContextf(&err, "ModeInit") | 20 defer errorContextf(&err, "ModeInit") |
20 » if err := u.charm.Recover(); err != nil { | 21 » log.Printf("updating unit addresses") |
| 22 » cfg, err := u.st.EnvironConfig() |
| 23 » if err != nil { |
| 24 » » return nil, err |
| 25 » } |
| 26 » provider, err := environs.Provider(cfg.Type()) |
| 27 » if err != nil { |
| 28 » » return nil, err |
| 29 » } |
| 30 » if private, err := provider.PrivateAddress(); err != nil { |
| 31 » » return nil, err |
| 32 » } else if err = u.unit.SetPrivateAddress(private); err != nil { |
| 33 » » return nil, err |
| 34 » } |
| 35 » if public, err := provider.PublicAddress(); err != nil { |
| 36 » » return nil, err |
| 37 » } else if err = u.unit.SetPublicAddress(public); err != nil { |
21 return nil, err | 38 return nil, err |
22 } | 39 } |
23 return ModeContinue, nil | 40 return ModeContinue, nil |
24 } | 41 } |
25 | 42 |
26 // ModeContinue determines what action to take based on persistent uniter state. | 43 // ModeContinue determines what action to take based on persistent uniter state. |
27 func ModeContinue(u *Uniter) (next Mode, err error) { | 44 func ModeContinue(u *Uniter) (next Mode, err error) { |
28 defer errorContextf(&err, "ModeContinue") | 45 defer errorContextf(&err, "ModeContinue") |
29 | 46 |
30 // When no charm exists, install it. | 47 // When no charm exists, install it. |
31 » log.Printf("examining persistent state...") | 48 » log.Printf("reading uniter state from disk...") |
32 » op, err := u.op.Read() | 49 » s, err := u.sf.Read() |
33 if err == ErrNoStateFile { | 50 if err == ErrNoStateFile { |
34 log.Printf("charm is not deployed") | 51 log.Printf("charm is not deployed") |
35 sch, _, err := u.service.Charm() | 52 sch, _, err := u.service.Charm() |
36 if err != nil { | 53 if err != nil { |
37 return nil, err | 54 return nil, err |
38 } | 55 } |
39 return ModeInstalling(sch), nil | 56 return ModeInstalling(sch), nil |
40 } else if err != nil { | 57 } else if err != nil { |
41 return nil, err | 58 return nil, err |
42 } | 59 } |
43 | 60 |
44 // Filter out states not related to charm deployment. | 61 // Filter out states not related to charm deployment. |
45 » switch op.Op { | 62 » switch s.Op { |
46 case Abide: | 63 case Abide: |
47 » » log.Printf("continuing after %q hook", op.Hook.Kind) | 64 » » log.Printf("continuing after %q hook", s.Hook.Kind) |
48 » » if op.Hook.Kind == hook.Install { | 65 » » if s.Hook.Kind == hook.Install { |
49 return ModeStarting, nil | 66 return ModeStarting, nil |
50 } | 67 } |
51 return ModeStarted, nil | 68 return ModeStarted, nil |
52 case RunHook: | 69 case RunHook: |
53 » » if op.Status == Queued { | 70 » » if s.OpStep == Queued { |
54 » » » log.Printf("running queued %q hook", op.Hook.Kind) | 71 » » » log.Printf("running queued %q hook", s.Hook.Kind) |
55 » » » if err := u.runHook(*op.Hook); err != nil { | 72 » » » if err := u.runHook(*s.Hook); err != nil { |
56 if err != errHookFailed { | 73 if err != errHookFailed { |
57 return nil, err | 74 return nil, err |
58 } | 75 } |
59 } | 76 } |
60 return ModeContinue, nil | 77 return ModeContinue, nil |
61 } | 78 } |
62 » » if op.Status == Committing { | 79 » » if s.OpStep == Done { |
63 » » » log.Printf("recovering uncommitted %q hook", op.Hook.Kin
d) | 80 » » » log.Printf("recovering uncommitted %q hook", s.Hook.Kind
) |
64 » » » if err = u.commitHook(*op.Hook); err != nil { | 81 » » » if err = u.commitHook(*s.Hook); err != nil { |
65 return nil, err | 82 return nil, err |
66 } | 83 } |
67 return ModeContinue, nil | 84 return ModeContinue, nil |
68 } | 85 } |
69 » » log.Printf("awaiting error resolution for %q hook", op.Hook.Kind
) | 86 » » log.Printf("awaiting error resolution for %q hook", s.Hook.Kind) |
70 return ModeHookError, nil | 87 return ModeHookError, nil |
71 } | 88 } |
72 | 89 |
73 // Resume interrupted deployment operations. | 90 // Resume interrupted deployment operations. |
74 » sch, err := u.st.Charm(op.CharmURL) | 91 » sch, err := u.st.Charm(s.CharmURL) |
75 » if err != nil { | 92 » if err != nil { |
76 » » return nil, err | 93 » » return nil, err |
77 » } | 94 » } |
78 » if op.Op == Install { | 95 » if s.Op == Install { |
79 log.Printf("resuming charm install") | 96 log.Printf("resuming charm install") |
80 return ModeInstalling(sch), nil | 97 return ModeInstalling(sch), nil |
81 } | 98 } |
82 » panic(fmt.Errorf("unhandled operation %q", op.Op)) | 99 » panic(fmt.Errorf("unhandled operation %q", s.Op)) |
83 } | 100 } |
84 | 101 |
85 // ModeInstalling is responsible for creating the charm directory and running | 102 // ModeInstalling is responsible for creating the charm directory and running |
86 // the "install" hook. | 103 // the "install" hook. |
87 func ModeInstalling(sch *state.Charm) Mode { | 104 func ModeInstalling(sch *state.Charm) Mode { |
88 return func(u *Uniter) (next Mode, err error) { | 105 return func(u *Uniter) (next Mode, err error) { |
89 defer errorContextf(&err, "ModeInstalling") | 106 defer errorContextf(&err, "ModeInstalling") |
90 if err = u.deploy(sch, Install); err != nil { | 107 if err = u.deploy(sch, Install); err != nil { |
91 return nil, err | 108 return nil, err |
92 } | 109 } |
(...skipping 14 matching lines...) Expand all Loading... |
107 return ModeContinue, nil | 124 return ModeContinue, nil |
108 } | 125 } |
109 | 126 |
110 // ModeStarted is the Uniter's usual steady state. It watches for and responds t
o: | 127 // ModeStarted is the Uniter's usual steady state. It watches for and responds t
o: |
111 // * service configuration changes | 128 // * service configuration changes |
112 // * charm upgrade requests (not implemented) | 129 // * charm upgrade requests (not implemented) |
113 // * relation changes (not implemented) | 130 // * relation changes (not implemented) |
114 // * unit death (not implemented) | 131 // * unit death (not implemented) |
115 func ModeStarted(u *Uniter) (next Mode, err error) { | 132 func ModeStarted(u *Uniter) (next Mode, err error) { |
116 defer errorContextf(&err, "ModeStarted") | 133 defer errorContextf(&err, "ModeStarted") |
117 » op, err := u.op.Read() | 134 » s, err := u.sf.Read() |
118 » if err != nil { | 135 » if err != nil { |
119 » » return nil, err | 136 » » return nil, err |
120 » } | 137 » } |
121 » if op.Op != Abide { | 138 » if s.Op != Abide { |
122 » » return nil, fmt.Errorf("insane uniter state: %#v", op) | 139 » » return nil, fmt.Errorf("insane uniter state: %#v", s) |
123 } | 140 } |
124 if err = u.unit.SetStatus(state.UnitStarted, ""); err != nil { | 141 if err = u.unit.SetStatus(state.UnitStarted, ""); err != nil { |
125 return nil, err | 142 return nil, err |
126 } | 143 } |
127 configw := u.service.WatchConfig() | 144 configw := u.service.WatchConfig() |
128 defer stop(configw, &next, &err) | 145 defer stop(configw, &next, &err) |
129 for { | 146 for { |
130 select { | 147 select { |
131 case <-u.tomb.Dying(): | 148 case <-u.tomb.Dying(): |
132 return nil, tomb.ErrDying | 149 return nil, tomb.ErrDying |
(...skipping 14 matching lines...) Expand all Loading... |
147 } | 164 } |
148 panic("unreachable") | 165 panic("unreachable") |
149 } | 166 } |
150 | 167 |
151 // ModeHookError is responsible for watching and responding to: | 168 // ModeHookError is responsible for watching and responding to: |
152 // * user resolution of hook errors | 169 // * user resolution of hook errors |
153 // * forced charm upgrade requests (not implemented) | 170 // * forced charm upgrade requests (not implemented) |
154 // * unit death (not implemented) | 171 // * unit death (not implemented) |
155 func ModeHookError(u *Uniter) (next Mode, err error) { | 172 func ModeHookError(u *Uniter) (next Mode, err error) { |
156 defer errorContextf(&err, "ModeHookError") | 173 defer errorContextf(&err, "ModeHookError") |
157 » op, err := u.op.Read() | 174 » s, err := u.sf.Read() |
158 » if err != nil { | 175 » if err != nil { |
159 » » return nil, err | 176 » » return nil, err |
160 » } | 177 » } |
161 » if op.Op != RunHook || op.Status != Pending { | 178 » if s.Op != RunHook || s.OpStep != Pending { |
162 » » return nil, fmt.Errorf("insane uniter state: %#v", op) | 179 » » return nil, fmt.Errorf("insane uniter state: %#v", s) |
163 » } | 180 » } |
164 » msg := fmt.Sprintf("hook failed: %q", op.Hook.Kind) | 181 » msg := fmt.Sprintf("hook failed: %q", s.Hook.Kind) |
165 if err = u.unit.SetStatus(state.UnitError, msg); err != nil { | 182 if err = u.unit.SetStatus(state.UnitError, msg); err != nil { |
166 return nil, err | 183 return nil, err |
167 } | 184 } |
168 // Wait for shutdown, error resolution, or forced charm upgrade. | 185 // Wait for shutdown, error resolution, or forced charm upgrade. |
169 resolvedw := u.unit.WatchResolved() | 186 resolvedw := u.unit.WatchResolved() |
170 defer stop(resolvedw, &next, &err) | 187 defer stop(resolvedw, &next, &err) |
171 for { | 188 for { |
172 select { | 189 select { |
173 case <-u.tomb.Dying(): | 190 case <-u.tomb.Dying(): |
174 return nil, tomb.ErrDying | 191 return nil, tomb.ErrDying |
175 case rm, ok := <-resolvedw.Changes(): | 192 case rm, ok := <-resolvedw.Changes(): |
176 if !ok { | 193 if !ok { |
177 return nil, watcher.MustErr(resolvedw) | 194 return nil, watcher.MustErr(resolvedw) |
178 } | 195 } |
179 switch rm { | 196 switch rm { |
180 case state.ResolvedNone: | 197 case state.ResolvedNone: |
181 continue | 198 continue |
182 case state.ResolvedRetryHooks: | 199 case state.ResolvedRetryHooks: |
183 » » » » err = u.runHook(*op.Hook) | 200 » » » » err = u.runHook(*s.Hook) |
184 case state.ResolvedNoHooks: | 201 case state.ResolvedNoHooks: |
185 » » » » err = u.commitHook(*op.Hook) | 202 » » » » err = u.commitHook(*s.Hook) |
186 default: | 203 default: |
187 panic(fmt.Errorf("unhandled resolved mode %q", r
m)) | 204 panic(fmt.Errorf("unhandled resolved mode %q", r
m)) |
188 } | 205 } |
189 if e := u.unit.ClearResolved(); e != nil { | 206 if e := u.unit.ClearResolved(); e != nil { |
190 err = e | 207 err = e |
191 } | 208 } |
192 if err == errHookFailed { | 209 if err == errHookFailed { |
193 continue | 210 continue |
194 } else if err != nil { | 211 } else if err != nil { |
195 return nil, err | 212 return nil, err |
(...skipping 18 matching lines...) Expand all Loading... |
214 } | 231 } |
215 | 232 |
216 // errorContextf prefixes the error stored in err with text formatted | 233 // errorContextf prefixes the error stored in err with text formatted |
217 // according to the format specifier. If err does not contain an error, | 234 // according to the format specifier. If err does not contain an error, |
218 // or if err is tomb.ErrDying, errorContextf does nothing. | 235 // or if err is tomb.ErrDying, errorContextf does nothing. |
219 func errorContextf(err *error, format string, args ...interface{}) { | 236 func errorContextf(err *error, format string, args ...interface{}) { |
220 if *err != nil && *err != tomb.ErrDying { | 237 if *err != nil && *err != tomb.ErrDying { |
221 *err = errors.New(fmt.Sprintf(format, args...) + ": " + (*err).E
rror()) | 238 *err = errors.New(fmt.Sprintf(format, args...) + ": " + (*err).E
rror()) |
222 } | 239 } |
223 } | 240 } |
LEFT | RIGHT |