LEFT | RIGHT |
1 // Copyright 2013 Canonical Ltd. | 1 // Copyright 2013 Canonical Ltd. |
2 // Licensed under the AGPLv3, see LICENCE file for details. | 2 // Licensed under the AGPLv3, see LICENCE file for details. |
3 | 3 |
4 package manual | 4 package manual |
5 | 5 |
6 import ( | 6 import ( |
7 "bytes" | 7 "bytes" |
8 "errors" | 8 "errors" |
9 "fmt" | 9 "fmt" |
10 "net" | 10 "net" |
11 "path" | 11 "path" |
12 "strings" | 12 "strings" |
13 "sync" | 13 "sync" |
14 | 14 |
15 "github.com/juju/loggo" | 15 "github.com/juju/loggo" |
16 | 16 |
17 "launchpad.net/juju-core/agent" | 17 "launchpad.net/juju-core/agent" |
18 "launchpad.net/juju-core/constraints" | 18 "launchpad.net/juju-core/constraints" |
19 "launchpad.net/juju-core/environs" | 19 "launchpad.net/juju-core/environs" |
20 "launchpad.net/juju-core/environs/config" | 20 "launchpad.net/juju-core/environs/config" |
21 "launchpad.net/juju-core/environs/httpstorage" | 21 "launchpad.net/juju-core/environs/httpstorage" |
22 "launchpad.net/juju-core/environs/manual" | 22 "launchpad.net/juju-core/environs/manual" |
23 "launchpad.net/juju-core/environs/simplestreams" | 23 "launchpad.net/juju-core/environs/simplestreams" |
24 "launchpad.net/juju-core/environs/sshstorage" | 24 "launchpad.net/juju-core/environs/sshstorage" |
25 "launchpad.net/juju-core/environs/storage" | 25 "launchpad.net/juju-core/environs/storage" |
26 envtools "launchpad.net/juju-core/environs/tools" | 26 envtools "launchpad.net/juju-core/environs/tools" |
27 "launchpad.net/juju-core/instance" | 27 "launchpad.net/juju-core/instance" |
| 28 "launchpad.net/juju-core/juju/arch" |
28 "launchpad.net/juju-core/provider/common" | 29 "launchpad.net/juju-core/provider/common" |
29 "launchpad.net/juju-core/state" | 30 "launchpad.net/juju-core/state" |
30 "launchpad.net/juju-core/state/api" | 31 "launchpad.net/juju-core/state/api" |
| 32 "launchpad.net/juju-core/utils" |
31 "launchpad.net/juju-core/utils/ssh" | 33 "launchpad.net/juju-core/utils/ssh" |
32 "launchpad.net/juju-core/worker/localstorage" | 34 "launchpad.net/juju-core/worker/localstorage" |
33 "launchpad.net/juju-core/worker/terminationworker" | 35 "launchpad.net/juju-core/worker/terminationworker" |
34 ) | 36 ) |
35 | 37 |
36 const ( | 38 const ( |
37 // TODO(axw) make this configurable? | |
38 dataDir = agent.DefaultDataDir | |
39 | |
40 // storageSubdir is the subdirectory of | 39 // storageSubdir is the subdirectory of |
41 // dataDir in which storage will be located. | 40 // dataDir in which storage will be located. |
42 storageSubdir = "storage" | 41 storageSubdir = "storage" |
43 | 42 |
44 // storageTmpSubdir is the subdirectory of | 43 // storageTmpSubdir is the subdirectory of |
45 // dataDir in which temporary storage will | 44 // dataDir in which temporary storage will |
46 // be located. | 45 // be located. |
47 storageTmpSubdir = "storage-tmp" | 46 storageTmpSubdir = "storage-tmp" |
48 ) | 47 ) |
49 | 48 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 } | 82 } |
84 | 83 |
85 func (e *manualEnviron) Config() *config.Config { | 84 func (e *manualEnviron) Config() *config.Config { |
86 return e.envConfig().Config | 85 return e.envConfig().Config |
87 } | 86 } |
88 | 87 |
89 func (e *manualEnviron) Name() string { | 88 func (e *manualEnviron) Name() string { |
90 return e.envConfig().Name() | 89 return e.envConfig().Name() |
91 } | 90 } |
92 | 91 |
| 92 // SupportedArchitectures is specified on the EnvironCapability interface. |
| 93 func (e *manualEnviron) SupportedArchitectures() ([]string, error) { |
| 94 return arch.AllSupportedArches, nil |
| 95 } |
| 96 |
| 97 // SupportNetworks is specified on the EnvironCapability interface. |
| 98 func (e *manualEnviron) SupportNetworks() bool { |
| 99 return false |
| 100 } |
| 101 |
93 func (e *manualEnviron) Bootstrap(ctx environs.BootstrapContext, cons constraint
s.Value) error { | 102 func (e *manualEnviron) Bootstrap(ctx environs.BootstrapContext, cons constraint
s.Value) error { |
94 // Set "use-sshstorage" to false, so agents know not to use sshstorage. | 103 // Set "use-sshstorage" to false, so agents know not to use sshstorage. |
95 cfg, err := e.Config().Apply(map[string]interface{}{"use-sshstorage": fa
lse}) | 104 cfg, err := e.Config().Apply(map[string]interface{}{"use-sshstorage": fa
lse}) |
96 if err != nil { | 105 if err != nil { |
97 return err | 106 return err |
98 } | 107 } |
99 if err := e.SetConfig(cfg); err != nil { | 108 if err := e.SetConfig(cfg); err != nil { |
100 return err | 109 return err |
101 } | 110 } |
102 envConfig := e.envConfig() | 111 envConfig := e.envConfig() |
103 host := envConfig.bootstrapHost() | 112 host := envConfig.bootstrapHost() |
104 hc, series, err := manual.DetectSeriesAndHardwareCharacteristics(host) | 113 hc, series, err := manual.DetectSeriesAndHardwareCharacteristics(host) |
105 if err != nil { | 114 if err != nil { |
106 return err | 115 return err |
107 } | 116 } |
108 » selectedTools, err := common.EnsureBootstrapTools(e, series, hc.Arch) | 117 » selectedTools, err := common.EnsureBootstrapTools(ctx, e, series, hc.Arc
h) |
109 if err != nil { | 118 if err != nil { |
110 return err | 119 return err |
111 } | 120 } |
112 return manual.Bootstrap(manual.BootstrapArgs{ | 121 return manual.Bootstrap(manual.BootstrapArgs{ |
113 Context: ctx, | 122 Context: ctx, |
114 Host: host, | 123 Host: host, |
115 » » DataDir: dataDir, | 124 » » DataDir: agent.DefaultDataDir, |
116 Environ: e, | 125 Environ: e, |
117 PossibleTools: selectedTools, | 126 PossibleTools: selectedTools, |
118 Series: series, | 127 Series: series, |
119 HardwareCharacteristics: &hc, | 128 HardwareCharacteristics: &hc, |
120 }) | 129 }) |
121 } | 130 } |
122 | 131 |
123 func (e *manualEnviron) StateInfo() (*state.Info, *api.Info, error) { | 132 func (e *manualEnviron) StateInfo() (*state.Info, *api.Info, error) { |
124 return common.StateInfo(e) | 133 return common.StateInfo(e) |
125 } | 134 } |
126 | 135 |
127 func (e *manualEnviron) SetConfig(cfg *config.Config) error { | 136 func (e *manualEnviron) SetConfig(cfg *config.Config) error { |
128 e.cfgmutex.Lock() | 137 e.cfgmutex.Lock() |
129 defer e.cfgmutex.Unlock() | 138 defer e.cfgmutex.Unlock() |
130 envConfig, err := manualProvider{}.validate(cfg, e.cfg.Config) | 139 envConfig, err := manualProvider{}.validate(cfg, e.cfg.Config) |
131 if err != nil { | 140 if err != nil { |
132 return err | 141 return err |
133 } | 142 } |
134 // Set storage. If "use-sshstorage" is true then use the SSH storage. | 143 // Set storage. If "use-sshstorage" is true then use the SSH storage. |
135 // Otherwise, use HTTP storage. | 144 // Otherwise, use HTTP storage. |
136 // | 145 // |
137 // We don't change storage once it's been set. Storage parameters | 146 // We don't change storage once it's been set. Storage parameters |
138 // are fixed at bootstrap time, and it is not possible to change | 147 // are fixed at bootstrap time, and it is not possible to change |
139 // them. | 148 // them. |
140 if e.storage == nil { | 149 if e.storage == nil { |
141 var stor storage.Storage | 150 var stor storage.Storage |
142 if envConfig.useSSHStorage() { | 151 if envConfig.useSSHStorage() { |
143 storageDir := e.StorageDir() | 152 storageDir := e.StorageDir() |
144 » » » storageTmpdir := path.Join(dataDir, storageTmpSubdir) | 153 » » » storageTmpdir := path.Join(agent.DefaultDataDir, storage
TmpSubdir) |
145 stor, err = newSSHStorage("ubuntu@"+e.cfg.bootstrapHost(
), storageDir, storageTmpdir) | 154 stor, err = newSSHStorage("ubuntu@"+e.cfg.bootstrapHost(
), storageDir, storageTmpdir) |
146 if err != nil { | 155 if err != nil { |
147 return fmt.Errorf("initialising SSH storage fail
ed: %v", err) | 156 return fmt.Errorf("initialising SSH storage fail
ed: %v", err) |
148 } | 157 } |
149 } else { | 158 } else { |
150 caCertPEM, ok := envConfig.CACert() | 159 caCertPEM, ok := envConfig.CACert() |
151 if !ok { | 160 if !ok { |
152 // should not be possible to validate base confi
g | 161 // should not be possible to validate base confi
g |
153 return fmt.Errorf("ca-cert not set") | 162 return fmt.Errorf("ca-cert not set") |
154 } | 163 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 storage.NewStorageSimpleStreamsDataSource("cloud storage", e.Sto
rage(), storage.BaseToolsPath), | 213 storage.NewStorageSimpleStreamsDataSource("cloud storage", e.Sto
rage(), storage.BaseToolsPath), |
205 }, nil | 214 }, nil |
206 } | 215 } |
207 | 216 |
208 func (e *manualEnviron) Storage() storage.Storage { | 217 func (e *manualEnviron) Storage() storage.Storage { |
209 e.cfgmutex.Lock() | 218 e.cfgmutex.Lock() |
210 defer e.cfgmutex.Unlock() | 219 defer e.cfgmutex.Unlock() |
211 return e.storage | 220 return e.storage |
212 } | 221 } |
213 | 222 |
214 var runSSHCommand = func(host string, command []string) (stderr string, err erro
r) { | 223 var runSSHCommand = func(host string, command []string, stdin string) (stderr st
ring, err error) { |
215 cmd := ssh.Command(host, command, nil) | 224 cmd := ssh.Command(host, command, nil) |
216 var stderrBuf bytes.Buffer | 225 var stderrBuf bytes.Buffer |
| 226 cmd.Stdin = strings.NewReader(stdin) |
217 cmd.Stderr = &stderrBuf | 227 cmd.Stderr = &stderrBuf |
218 err = cmd.Run() | 228 err = cmd.Run() |
219 return stderrBuf.String(), err | 229 return stderrBuf.String(), err |
220 } | 230 } |
221 | 231 |
222 func (e *manualEnviron) Destroy() error { | 232 func (e *manualEnviron) Destroy() error { |
| 233 script := ` |
| 234 set -x |
| 235 pkill -%d jujud && exit |
| 236 stop juju-db |
| 237 rm -f /etc/init/juju* |
| 238 rm -f /etc/rsyslog.d/*juju* |
| 239 rm -fr %s %s |
| 240 exit 0 |
| 241 ` |
| 242 script = fmt.Sprintf( |
| 243 script, |
| 244 terminationworker.TerminationSignal, |
| 245 utils.ShQuote(agent.DefaultDataDir), |
| 246 utils.ShQuote(agent.DefaultLogDir), |
| 247 ) |
223 stderr, err := runSSHCommand( | 248 stderr, err := runSSHCommand( |
224 "ubuntu@"+e.envConfig().bootstrapHost(), | 249 "ubuntu@"+e.envConfig().bootstrapHost(), |
225 » » []string{"sudo", "pkill", fmt.Sprintf("-%d", terminationworker.T
erminationSignal), "jujud"}, | 250 » » []string{"sudo", "/bin/bash"}, script, |
226 ) | 251 ) |
227 if err != nil { | 252 if err != nil { |
228 if stderr := strings.TrimSpace(stderr); len(stderr) > 0 { | 253 if stderr := strings.TrimSpace(stderr); len(stderr) > 0 { |
229 err = fmt.Errorf("%v (%v)", err, stderr) | 254 err = fmt.Errorf("%v (%v)", err, stderr) |
230 } | 255 } |
231 } | 256 } |
232 return err | 257 return err |
233 } | 258 } |
234 | 259 |
235 func (*manualEnviron) PrecheckInstance(series string, cons constraints.Value) er
ror { | 260 func (*manualEnviron) PrecheckInstance(series string, cons constraints.Value) er
ror { |
(...skipping 14 matching lines...) Expand all Loading... |
250 | 275 |
251 func (*manualEnviron) Provider() environs.EnvironProvider { | 276 func (*manualEnviron) Provider() environs.EnvironProvider { |
252 return manualProvider{} | 277 return manualProvider{} |
253 } | 278 } |
254 | 279 |
255 func (e *manualEnviron) StorageAddr() string { | 280 func (e *manualEnviron) StorageAddr() string { |
256 return e.envConfig().storageListenAddr() | 281 return e.envConfig().storageListenAddr() |
257 } | 282 } |
258 | 283 |
259 func (e *manualEnviron) StorageDir() string { | 284 func (e *manualEnviron) StorageDir() string { |
260 » return path.Join(dataDir, storageSubdir) | 285 » return path.Join(agent.DefaultDataDir, storageSubdir) |
261 } | 286 } |
262 | 287 |
263 func (e *manualEnviron) SharedStorageAddr() string { | 288 func (e *manualEnviron) SharedStorageAddr() string { |
264 return "" | 289 return "" |
265 } | 290 } |
266 | 291 |
267 func (e *manualEnviron) SharedStorageDir() string { | 292 func (e *manualEnviron) SharedStorageDir() string { |
268 return "" | 293 return "" |
269 } | 294 } |
270 | 295 |
(...skipping 20 matching lines...) Expand all Loading... |
291 } | 316 } |
292 } | 317 } |
293 return hostnames | 318 return hostnames |
294 } | 319 } |
295 | 320 |
296 func (e *manualEnviron) StorageAuthKey() string { | 321 func (e *manualEnviron) StorageAuthKey() string { |
297 return e.envConfig().storageAuthKey() | 322 return e.envConfig().storageAuthKey() |
298 } | 323 } |
299 | 324 |
300 var _ localstorage.LocalTLSStorageConfig = (*manualEnviron)(nil) | 325 var _ localstorage.LocalTLSStorageConfig = (*manualEnviron)(nil) |
LEFT | RIGHT |