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

Delta Between Two Patch Sets: provider/local/environ.go

Issue 77820044: Add EnvironCapability to state.Policy
Left Patch Set: Add EnvironCapability to state.Policy Created 10 years ago
Right Patch Set: Add EnvironCapability to state.Policy Created 9 years, 12 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:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « provider/joyent/environ.go ('k') | provider/maas/environ.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2013, 2014 Canonical Ltd. 1 // Copyright 2013, 2014 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 local 4 package local
5 5
6 import ( 6 import (
7 "fmt" 7 "fmt"
8 "net" 8 "net"
9 "os" 9 "os"
10 "os/exec" 10 "os/exec"
(...skipping 21 matching lines...) Expand all
32 "launchpad.net/juju-core/environs/simplestreams" 32 "launchpad.net/juju-core/environs/simplestreams"
33 "launchpad.net/juju-core/environs/storage" 33 "launchpad.net/juju-core/environs/storage"
34 envtools "launchpad.net/juju-core/environs/tools" 34 envtools "launchpad.net/juju-core/environs/tools"
35 "launchpad.net/juju-core/instance" 35 "launchpad.net/juju-core/instance"
36 "launchpad.net/juju-core/juju/arch" 36 "launchpad.net/juju-core/juju/arch"
37 "launchpad.net/juju-core/juju/osenv" 37 "launchpad.net/juju-core/juju/osenv"
38 "launchpad.net/juju-core/provider/common" 38 "launchpad.net/juju-core/provider/common"
39 "launchpad.net/juju-core/state" 39 "launchpad.net/juju-core/state"
40 "launchpad.net/juju-core/state/api" 40 "launchpad.net/juju-core/state/api"
41 "launchpad.net/juju-core/state/api/params" 41 "launchpad.net/juju-core/state/api/params"
42 "launchpad.net/juju-core/upstart"
42 "launchpad.net/juju-core/utils/shell" 43 "launchpad.net/juju-core/utils/shell"
43 "launchpad.net/juju-core/version" 44 "launchpad.net/juju-core/version"
44 "launchpad.net/juju-core/worker/terminationworker" 45 "launchpad.net/juju-core/worker/terminationworker"
45 ) 46 )
46 47
47 // boostrapInstanceId is just the name we give to the bootstrap machine. 48 // boostrapInstanceId is just the name we give to the bootstrap machine.
48 // Using "localhost" because it is, and it makes sense. 49 // Using "localhost" because it is, and it makes sense.
49 const bootstrapInstanceId instance.Id = "localhost" 50 const bootstrapInstanceId instance.Id = "localhost"
50 51
51 // localEnviron implements Environ. 52 // localEnviron implements Environ.
52 var _ environs.Environ = (*localEnviron)(nil) 53 var _ environs.Environ = (*localEnviron)(nil)
53 54
54 // localEnviron implements SupportsCustomSources. 55 // localEnviron implements SupportsCustomSources.
55 var _ envtools.SupportsCustomSources = (*localEnviron)(nil) 56 var _ envtools.SupportsCustomSources = (*localEnviron)(nil)
56 57
57 type localEnviron struct { 58 type localEnviron struct {
58 » common.NopPrechecker 59 » common.NopPrecheckerPolicy
59 » common.DoesSupportUnitPlacement 60 » common.SupportsUnitPlacementPolicy
60 61
61 localMutex sync.Mutex 62 localMutex sync.Mutex
62 config *environConfig 63 config *environConfig
63 name string 64 name string
64 bridgeAddress string 65 bridgeAddress string
65 localStorage storage.Storage 66 localStorage storage.Storage
66 storageListener net.Listener 67 storageListener net.Listener
67 containerManager container.Manager 68 containerManager container.Manager
68 } 69 }
69 70
70 // GetToolsSources returns a list of sources which are used to search for simple streams tools metadata. 71 // GetToolsSources returns a list of sources which are used to search for simple streams tools metadata.
71 func (e *localEnviron) GetToolsSources() ([]simplestreams.DataSource, error) { 72 func (e *localEnviron) GetToolsSources() ([]simplestreams.DataSource, error) {
72 // Add the simplestreams source off the control bucket. 73 // Add the simplestreams source off the control bucket.
73 return []simplestreams.DataSource{ 74 return []simplestreams.DataSource{
74 storage.NewStorageSimpleStreamsDataSource("cloud storage", e.Sto rage(), storage.BaseToolsPath)}, nil 75 storage.NewStorageSimpleStreamsDataSource("cloud storage", e.Sto rage(), storage.BaseToolsPath)}, nil
75 } 76 }
76 77
77 // SupportedArchitectures is specified on the EnvironCapability interface. 78 // SupportedArchitectures is specified on the EnvironCapability interface.
78 func (*localEnviron) SupportedArchitectures() ([]string, error) { 79 func (*localEnviron) SupportedArchitectures() ([]string, error) {
79 localArch := arch.HostArch() 80 localArch := arch.HostArch()
80 return []string{localArch}, nil 81 return []string{localArch}, nil
81 } 82 }
82 83
84 // SupportNetworks is specified on the EnvironCapability interface.
85 func (*localEnviron) SupportNetworks() bool {
86 return false
87 }
88
83 // Name is specified in the Environ interface. 89 // Name is specified in the Environ interface.
84 func (env *localEnviron) Name() string { 90 func (env *localEnviron) Name() string {
85 return env.name 91 return env.name
86 } 92 }
87 93
88 func (env *localEnviron) mongoServiceName() string { 94 func (env *localEnviron) mongoServiceName() string {
89 return "juju-db-" + env.config.namespace() 95 return "juju-db-" + env.config.namespace()
90 } 96 }
91 97
92 func (env *localEnviron) machineAgentServiceName() string { 98 func (env *localEnviron) machineAgentServiceName() string {
(...skipping 12 matching lines...) Expand all
105 if err := ensureNotRoot(); err != nil { 111 if err := ensureNotRoot(); err != nil {
106 return err 112 return err
107 } 113 }
108 privateKey, err := common.GenerateSystemSSHKey(env) 114 privateKey, err := common.GenerateSystemSSHKey(env)
109 if err != nil { 115 if err != nil {
110 return err 116 return err
111 } 117 }
112 118
113 // Before we write the agent config file, we need to make sure the 119 // Before we write the agent config file, we need to make sure the
114 // instance is saved in the StateInfo. 120 // instance is saved in the StateInfo.
115 stateFileURL, err := bootstrap.CreateStateFile(env.Storage())
116 if err != nil {
117 return err
118 }
119 if err := bootstrap.SaveState(env.Storage(), &bootstrap.BootstrapState{ 121 if err := bootstrap.SaveState(env.Storage(), &bootstrap.BootstrapState{
120 StateInstances: []instance.Id{bootstrapInstanceId}, 122 StateInstances: []instance.Id{bootstrapInstanceId},
121 }); err != nil { 123 }); err != nil {
122 logger.Errorf("failed to save state instances: %v", err) 124 logger.Errorf("failed to save state instances: %v", err)
123 return err 125 return err
124 } 126 }
125 127
126 vers := version.Current 128 vers := version.Current
127 » selectedTools, err := common.EnsureBootstrapTools(env, vers.Series, &ver s.Arch) 129 » selectedTools, err := common.EnsureBootstrapTools(ctx, env, vers.Series, &vers.Arch)
128 if err != nil { 130 if err != nil {
129 return err 131 return err
130 } 132 }
131 133
132 // Record the bootstrap IP, so the containers know where to go for stora ge. 134 // Record the bootstrap IP, so the containers know where to go for stora ge.
133 cfg, err := env.Config().Apply(map[string]interface{}{ 135 cfg, err := env.Config().Apply(map[string]interface{}{
134 "bootstrap-ip": env.bridgeAddress, 136 "bootstrap-ip": env.bridgeAddress,
135 }) 137 })
136 if err == nil { 138 if err == nil {
137 err = env.SetConfig(cfg) 139 err = env.SetConfig(cfg)
138 } 140 }
139 if err != nil { 141 if err != nil {
140 logger.Errorf("failed to apply bootstrap-ip to config: %v", err) 142 logger.Errorf("failed to apply bootstrap-ip to config: %v", err)
141 return err 143 return err
142 } 144 }
143 145
144 » mcfg := environs.NewBootstrapMachineConfig(stateFileURL, privateKey) 146 » mcfg := environs.NewBootstrapMachineConfig(privateKey)
147 » mcfg.InstanceId = bootstrapInstanceId
145 mcfg.Tools = selectedTools[0] 148 mcfg.Tools = selectedTools[0]
146 mcfg.DataDir = env.config.rootDir() 149 mcfg.DataDir = env.config.rootDir()
147 mcfg.LogDir = fmt.Sprintf("/var/log/juju-%s", env.config.namespace()) 150 mcfg.LogDir = fmt.Sprintf("/var/log/juju-%s", env.config.namespace())
148 mcfg.Jobs = []params.MachineJob{params.JobManageEnviron} 151 mcfg.Jobs = []params.MachineJob{params.JobManageEnviron}
149 » mcfg.CloudInitOutputLog = filepath.Join(env.config.logDir(), "cloud-init -output.log") 152 » mcfg.CloudInitOutputLog = filepath.Join(mcfg.DataDir, "cloud-init-output .log")
150 mcfg.DisablePackageCommands = true 153 mcfg.DisablePackageCommands = true
151 mcfg.MachineAgentServiceName = env.machineAgentServiceName() 154 mcfg.MachineAgentServiceName = env.machineAgentServiceName()
152 mcfg.MongoServiceName = env.mongoServiceName() 155 mcfg.MongoServiceName = env.mongoServiceName()
153 mcfg.AgentEnvironment = map[string]string{ 156 mcfg.AgentEnvironment = map[string]string{
154 agent.Namespace: env.config.namespace(), 157 agent.Namespace: env.config.namespace(),
155 agent.StorageDir: env.config.storageDir(), 158 agent.StorageDir: env.config.storageDir(),
156 agent.StorageAddr: env.config.storageAddr(), 159 agent.StorageAddr: env.config.storageAddr(),
157 } 160 }
158 if err := environs.FinishMachineConfig(mcfg, cfg, cons); err != nil { 161 if err := environs.FinishMachineConfig(mcfg, cfg, cons); err != nil {
159 return err 162 return err
160 } 163 }
161 // don't write proxy settings for local machine 164 // don't write proxy settings for local machine
162 mcfg.AptProxySettings = osenv.ProxySettings{} 165 mcfg.AptProxySettings = osenv.ProxySettings{}
163 mcfg.ProxySettings = osenv.ProxySettings{} 166 mcfg.ProxySettings = osenv.ProxySettings{}
164 cloudcfg := coreCloudinit.New() 167 cloudcfg := coreCloudinit.New()
165 // Since rsyslogd is restricted by apparmor to only write to /var/log/** 168 // Since rsyslogd is restricted by apparmor to only write to /var/log/**
166 // we now provide a symlink to the written file in the local log dir. 169 // we now provide a symlink to the written file in the local log dir.
167 // Also, we leave the old all-machines.log file in 170 // Also, we leave the old all-machines.log file in
168 // /var/log/juju-{{namespace}} until we start the environment again. So 171 // /var/log/juju-{{namespace}} until we start the environment again. So
169 // potentially remove it at the start of the cloud-init. 172 // potentially remove it at the start of the cloud-init.
170 » os.RemoveAll(env.config.logDir()) 173 » localLogDir := filepath.Join(mcfg.DataDir, "log")
171 » os.MkdirAll(env.config.logDir(), 0755) 174 » if err := os.RemoveAll(localLogDir); err != nil {
175 » » return err
176 » }
177 » if err := os.Symlink(mcfg.LogDir, localLogDir); err != nil {
178 » » return err
179 » }
180 » if err := os.Remove(mcfg.CloudInitOutputLog); err != nil && !os.IsNotExi st(err) {
181 » » return err
182 » }
172 cloudcfg.AddScripts( 183 cloudcfg.AddScripts(
173 fmt.Sprintf("rm -fr %s", mcfg.LogDir), 184 fmt.Sprintf("rm -fr %s", mcfg.LogDir),
174 fmt.Sprintf("mkdir -p %s", mcfg.LogDir),
175 fmt.Sprintf("chown syslog:adm %s", mcfg.LogDir),
176 fmt.Sprintf("rm -f /var/spool/rsyslog/machine-0-%s", env.config. namespace()), 185 fmt.Sprintf("rm -f /var/spool/rsyslog/machine-0-%s", env.config. namespace()),
177 » » fmt.Sprintf("ln -s %s/all-machines.log %s/", mcfg.LogDir, env.co nfig.logDir()), 186 » )
178 » » fmt.Sprintf("ln -s %s/machine-0.log %s/", env.config.logDir(), m cfg.LogDir))
179 if err := cloudinit.ConfigureJuju(mcfg, cloudcfg); err != nil { 187 if err := cloudinit.ConfigureJuju(mcfg, cloudcfg); err != nil {
180 return err 188 return err
181 } 189 }
182 return finishBootstrap(mcfg, cloudcfg, ctx) 190 return finishBootstrap(mcfg, cloudcfg, ctx)
183 } 191 }
184 192
185 // finishBootstrap converts the machine config to cloud-config, 193 // finishBootstrap converts the machine config to cloud-config,
186 // converts that to a script, and then executes it locally. 194 // converts that to a script, and then executes it locally.
187 // 195 //
188 // mcfg is supplied for testing purposes. 196 // mcfg is supplied for testing purposes.
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 storage, err := filestorage.NewFileStorageWriter(env.config.storageDir() ) 299 storage, err := filestorage.NewFileStorageWriter(env.config.storageDir() )
292 if err != nil { 300 if err != nil {
293 return err 301 return err
294 } 302 }
295 env.localStorage = storage 303 env.localStorage = storage
296 return nil 304 return nil
297 } 305 }
298 306
299 // StartInstance is specified in the InstanceBroker interface. 307 // StartInstance is specified in the InstanceBroker interface.
300 func (env *localEnviron) StartInstance(args environs.StartInstanceParams) (insta nce.Instance, *instance.HardwareCharacteristics, error) { 308 func (env *localEnviron) StartInstance(args environs.StartInstanceParams) (insta nce.Instance, *instance.HardwareCharacteristics, error) {
301 309 » if args.MachineConfig.HasNetworks() {
310 » » return nil, nil, fmt.Errorf("starting instances with networks is not supported yet.")
311 » }
302 series := args.Tools.OneSeries() 312 series := args.Tools.OneSeries()
303 logger.Debugf("StartInstance: %q, %s", args.MachineConfig.MachineId, ser ies) 313 logger.Debugf("StartInstance: %q, %s", args.MachineConfig.MachineId, ser ies)
304 args.MachineConfig.Tools = args.Tools[0] 314 args.MachineConfig.Tools = args.Tools[0]
305 args.MachineConfig.MachineContainerType = env.config.container() 315 args.MachineConfig.MachineContainerType = env.config.container()
306 logger.Debugf("tools: %#v", args.MachineConfig.Tools) 316 logger.Debugf("tools: %#v", args.MachineConfig.Tools)
307 network := container.BridgeNetworkConfig(env.config.networkBridge()) 317 network := container.BridgeNetworkConfig(env.config.networkBridge())
308 if err := environs.FinishMachineConfig(args.MachineConfig, env.config.Co nfig, args.Constraints); err != nil { 318 if err := environs.FinishMachineConfig(args.MachineConfig, env.config.Co nfig, args.Constraints); err != nil {
309 return nil, nil, err 319 return nil, nil, err
310 } 320 }
311 // TODO: evaluate the impact of setting the contstraints on the 321 // TODO: evaluate the impact of setting the contstraints on the
312 // machineConfig for all machines rather than just state server nodes. 322 // machineConfig for all machines rather than just state server nodes.
313 // This limiation is why the constraints are assigned directly here. 323 // This limiation is why the constraints are assigned directly here.
314 args.MachineConfig.Constraints = args.Constraints 324 args.MachineConfig.Constraints = args.Constraints
315 args.MachineConfig.AgentEnvironment[agent.Namespace] = env.config.namesp ace() 325 args.MachineConfig.AgentEnvironment[agent.Namespace] = env.config.namesp ace()
316 » inst, hardware, err := env.containerManager.StartContainer(args.MachineC onfig, series, network) 326 » inst, hardware, err := env.containerManager.CreateContainer(args.Machine Config, series, network)
317 if err != nil { 327 if err != nil {
318 return nil, nil, err 328 return nil, nil, err
319 } 329 }
320 return inst, hardware, nil 330 return inst, hardware, nil
321 } 331 }
322 332
323 // StartInstance is specified in the InstanceBroker interface. 333 // StartInstance is specified in the InstanceBroker interface.
324 func (env *localEnviron) StopInstances(instances []instance.Instance) error { 334 func (env *localEnviron) StopInstances(instances []instance.Instance) error {
325 for _, inst := range instances { 335 for _, inst := range instances {
326 if inst.Id() == bootstrapInstanceId { 336 if inst.Id() == bootstrapInstanceId {
327 return fmt.Errorf("cannot stop the bootstrap instance") 337 return fmt.Errorf("cannot stop the bootstrap instance")
328 } 338 }
329 » » if err := env.containerManager.StopContainer(inst); err != nil { 339 » » if err := env.containerManager.DestroyContainer(inst); err != ni l {
330 return err 340 return err
331 } 341 }
332 } 342 }
333 return nil 343 return nil
334 } 344 }
335 345
336 // Instances is specified in the Environ interface. 346 // Instances is specified in the Environ interface.
337 func (env *localEnviron) Instances(ids []instance.Id) ([]instance.Instance, erro r) { 347 func (env *localEnviron) Instances(ids []instance.Id) ([]instance.Instance, erro r) {
338 if len(ids) == 0 { 348 if len(ids) == 0 {
339 return nil, nil 349 return nil, nil
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 if os.RemoveAll(env.config.rootDir()) == nil { 410 if os.RemoveAll(env.config.rootDir()) == nil {
401 return nil 411 return nil
402 } 412 }
403 } 413 }
404 if !checkIfRoot() { 414 if !checkIfRoot() {
405 juju, err := exec.LookPath(os.Args[0]) 415 juju, err := exec.LookPath(os.Args[0])
406 if err != nil { 416 if err != nil {
407 return err 417 return err
408 } 418 }
409 args := []string{ 419 args := []string{
410 » » » osenv.JujuHomeEnvKey + "=" + osenv.JujuHome(), 420 » » » "env", osenv.JujuHomeEnvKey + "=" + osenv.JujuHome(),
411 juju, "destroy-environment", "-y", "--force", env.Name() , 421 juju, "destroy-environment", "-y", "--force", env.Name() ,
412 } 422 }
413 cmd := exec.Command("sudo", args...) 423 cmd := exec.Command("sudo", args...)
414 cmd.Stdout = os.Stdout 424 cmd.Stdout = os.Stdout
415 cmd.Stderr = os.Stderr 425 cmd.Stderr = os.Stderr
416 return cmd.Run() 426 return cmd.Run()
417 } 427 }
418 // Kill all running instances. This must be done as 428 // Kill all running instances. This must be done as
419 // root, or listing/stopping containers will fail. 429 // root, or listing/stopping containers will fail.
420 containers, err := env.containerManager.ListContainers() 430 containers, err := env.containerManager.ListContainers()
421 if err != nil { 431 if err != nil {
422 return err 432 return err
423 } 433 }
424 for _, inst := range containers { 434 for _, inst := range containers {
425 » » if err := env.containerManager.StopContainer(inst); err != nil { 435 » » if err := env.containerManager.DestroyContainer(inst); err != ni l {
426 return err 436 return err
427 } 437 }
428 } 438 }
429 cmd := exec.Command( 439 cmd := exec.Command(
430 "pkill", 440 "pkill",
431 fmt.Sprintf("-%d", terminationworker.TerminationSignal), 441 fmt.Sprintf("-%d", terminationworker.TerminationSignal),
432 "-f", filepath.Join(regexp.QuoteMeta(env.config.rootDir()), ".*" , "jujud"), 442 "-f", filepath.Join(regexp.QuoteMeta(env.config.rootDir()), ".*" , "jujud"),
433 ) 443 )
434 if err := cmd.Run(); err != nil { 444 if err := cmd.Run(); err != nil {
435 if err, ok := err.(*exec.ExitError); ok { 445 if err, ok := err.(*exec.ExitError); ok {
436 // Exit status 1 means no processes were matched: 446 // Exit status 1 means no processes were matched:
437 // we don't consider this an error here. 447 // we don't consider this an error here.
438 if err.ProcessState.Sys().(syscall.WaitStatus).ExitStatu s() != 1 { 448 if err.ProcessState.Sys().(syscall.WaitStatus).ExitStatu s() != 1 {
439 return errgo.Annotate(err, "failed to kill jujud ") 449 return errgo.Annotate(err, "failed to kill jujud ")
440 } 450 }
441 } 451 }
442 } 452 }
453 // Stop the mongo database and machine agent. It's possible that the
454 // service doesn't exist or is not running, so don't check the error.
455 upstart.NewService(env.mongoServiceName()).StopAndRemove()
456 upstart.NewService(env.machineAgentServiceName()).StopAndRemove()
457
458 // Finally, remove the data-dir.
443 if err := os.RemoveAll(env.config.rootDir()); err != nil && !os.IsNotExi st(err) { 459 if err := os.RemoveAll(env.config.rootDir()); err != nil && !os.IsNotExi st(err) {
444 return err 460 return err
445 } 461 }
446 return nil 462 return nil
447 } 463 }
448 464
449 // OpenPorts is specified in the Environ interface. 465 // OpenPorts is specified in the Environ interface.
450 func (env *localEnviron) OpenPorts(ports []instance.Port) error { 466 func (env *localEnviron) OpenPorts(ports []instance.Port) error {
451 return fmt.Errorf("open ports not implemented") 467 return fmt.Errorf("open ports not implemented")
452 } 468 }
453 469
454 // ClosePorts is specified in the Environ interface. 470 // ClosePorts is specified in the Environ interface.
455 func (env *localEnviron) ClosePorts(ports []instance.Port) error { 471 func (env *localEnviron) ClosePorts(ports []instance.Port) error {
456 return fmt.Errorf("close ports not implemented") 472 return fmt.Errorf("close ports not implemented")
457 } 473 }
458 474
459 // Ports is specified in the Environ interface. 475 // Ports is specified in the Environ interface.
460 func (env *localEnviron) Ports() ([]instance.Port, error) { 476 func (env *localEnviron) Ports() ([]instance.Port, error) {
461 return nil, nil 477 return nil, nil
462 } 478 }
463 479
464 // Provider is specified in the Environ interface. 480 // Provider is specified in the Environ interface.
465 func (env *localEnviron) Provider() environs.EnvironProvider { 481 func (env *localEnviron) Provider() environs.EnvironProvider {
466 return providerInstance 482 return providerInstance
467 } 483 }
LEFTRIGHT

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