~wallyworld/juju-core/fast-lxc-everywhere

« back to all changes in this revision

Viewing changes to upgrades/agentconfig.go

  • Committer: Bodie Solomon
  • Date: 2014-03-20 01:23:05 UTC
  • mfrom: (2447 juju-core)
  • mto: This revision was merged to the branch mainline in revision 2459.
  • Revision ID: binary132@gmail.com-20140320012305-foerm9in0uqx9jrg
Merged apiAddressesKey change from trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2014 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package upgrades
 
5
 
 
6
import (
 
7
        "fmt"
 
8
        "os"
 
9
        "os/user"
 
10
        "path/filepath"
 
11
        "strconv"
 
12
 
 
13
        "launchpad.net/juju-core/agent"
 
14
        "launchpad.net/juju-core/environs/config"
 
15
        "launchpad.net/juju-core/state/api/params"
 
16
)
 
17
 
 
18
var (
 
19
        rootLogDir   = "/var/log"
 
20
        rootSpoolDir = "/var/spool/rsyslog"
 
21
)
 
22
 
 
23
var chownPath = func(path, username string) error {
 
24
        user, err := user.Lookup(username)
 
25
        if err != nil {
 
26
                return fmt.Errorf("cannot lookup %q user id: %v", username, err)
 
27
        }
 
28
        uid, err := strconv.Atoi(user.Uid)
 
29
        if err != nil {
 
30
                return fmt.Errorf("invalid user id %q: %v", user.Uid, err)
 
31
        }
 
32
        gid, err := strconv.Atoi(user.Gid)
 
33
        if err != nil {
 
34
                return fmt.Errorf("invalid group id %q: %v", user.Gid, err)
 
35
        }
 
36
        return os.Chown(path, uid, gid)
 
37
}
 
38
 
 
39
var isLocalEnviron = func(envConfig *config.Config) bool {
 
40
        return envConfig.Type() == "local"
 
41
}
 
42
 
 
43
func migrateLocalProviderAgentConfig(context Context) error {
 
44
        st := context.State()
 
45
        if st == nil {
 
46
                logger.Debugf("no state connection, no migration required")
 
47
                // We're running on a different node than the state server.
 
48
                return nil
 
49
        }
 
50
        envConfig, err := st.EnvironConfig()
 
51
        if err != nil {
 
52
                return fmt.Errorf("failed to read current config: %v", err)
 
53
        }
 
54
        if !isLocalEnviron(envConfig) {
 
55
                logger.Debugf("not a local environment, no migration required")
 
56
                return nil
 
57
        }
 
58
        attrs := envConfig.AllAttrs()
 
59
        rootDir, _ := attrs["root-dir"].(string)
 
60
        sharedStorageDir := filepath.Join(rootDir, "shared-storage")
 
61
        // In case these two are empty we need to set them and update the
 
62
        // environment config.
 
63
        namespace, _ := attrs["namespace"].(string)
 
64
        container, _ := attrs["container"].(string)
 
65
 
 
66
        if namespace == "" {
 
67
                username := os.Getenv("USER")
 
68
                if username == "root" {
 
69
                        // sudo was probably called, get the original user.
 
70
                        username = os.Getenv("SUDO_USER")
 
71
                }
 
72
                if username == "" {
 
73
                        return fmt.Errorf("cannot get current user from the environment: %v", os.Environ())
 
74
                }
 
75
                namespace = username + "-" + envConfig.Name()
 
76
        }
 
77
        if container == "" {
 
78
                container = "lxc"
 
79
        }
 
80
 
 
81
        dataDir := rootDir
 
82
        localLogDir := filepath.Join(rootDir, "log")
 
83
        // rsyslogd is restricted to write to /var/log
 
84
        logDir := fmt.Sprintf("%s/juju-%s", rootLogDir, namespace)
 
85
        jobs := []params.MachineJob{params.JobManageEnviron}
 
86
        values := map[string]string{
 
87
                agent.Namespace: namespace,
 
88
                // ContainerType is empty on the bootstrap node.
 
89
                agent.ContainerType:    "",
 
90
                agent.AgentServiceName: "juju-agent-" + namespace,
 
91
                agent.MongoServiceName: "juju-db-" + namespace,
 
92
        }
 
93
        deprecatedValues := []string{
 
94
                "SHARED_STORAGE_ADDR",
 
95
                "SHARED_STORAGE_DIR",
 
96
        }
 
97
 
 
98
        // Remove shared-storage dir if there.
 
99
        if err := os.RemoveAll(sharedStorageDir); err != nil {
 
100
                return fmt.Errorf("cannot remove deprecated %q: %v", sharedStorageDir, err)
 
101
        }
 
102
 
 
103
        // We need to create the dirs if they don't exist.
 
104
        if err := os.MkdirAll(dataDir, 0755); err != nil {
 
105
                return fmt.Errorf("cannot create dataDir %q: %v", dataDir, err)
 
106
        }
 
107
        // We always recreate the logDir to make sure it's empty.
 
108
        if err := os.RemoveAll(logDir); err != nil {
 
109
                return fmt.Errorf("cannot remove logDir %q: %v", logDir, err)
 
110
        }
 
111
        if err := os.MkdirAll(logDir, 0755); err != nil {
 
112
                return fmt.Errorf("cannot create logDir %q: %v", logDir, err)
 
113
        }
 
114
        // Reconfigure rsyslog as needed:
 
115
        // 1. logDir must be owned by syslog:adm
 
116
        // 2. Remove old rsyslog spool config
 
117
        // 3. Relink logs to the new logDir
 
118
        if err := chownPath(logDir, "syslog"); err != nil {
 
119
                return err
 
120
        }
 
121
        spoolConfig := fmt.Sprintf("%s/machine-0-%s", rootSpoolDir, namespace)
 
122
        if err := os.RemoveAll(spoolConfig); err != nil {
 
123
                return fmt.Errorf("cannot remove %q: %v", spoolConfig, err)
 
124
        }
 
125
        allMachinesLog := filepath.Join(logDir, "all-machines.log")
 
126
        if err := os.Symlink(allMachinesLog, localLogDir+"/"); err != nil && !os.IsExist(err) {
 
127
                return fmt.Errorf("cannot symlink %q to %q: %v", allMachinesLog, localLogDir, err)
 
128
        }
 
129
        machine0Log := filepath.Join(localLogDir, "machine-0.log")
 
130
        if err := os.Symlink(machine0Log, logDir+"/"); err != nil && !os.IsExist(err) {
 
131
                return fmt.Errorf("cannot symlink %q to %q: %v", machine0Log, logDir, err)
 
132
        }
 
133
 
 
134
        newCfg := map[string]interface{}{
 
135
                "namespace": namespace,
 
136
                "container": container,
 
137
        }
 
138
        if err := st.UpdateEnvironConfig(newCfg, nil, nil); err != nil {
 
139
                return fmt.Errorf("cannot update environment config: %v", err)
 
140
        }
 
141
 
 
142
        migrateParams := agent.MigrateConfigParams{
 
143
                DataDir:      dataDir,
 
144
                LogDir:       logDir,
 
145
                Jobs:         jobs,
 
146
                Values:       values,
 
147
                DeleteValues: deprecatedValues,
 
148
        }
 
149
        return agent.MigrateConfig(context.AgentConfig(), migrateParams)
 
150
}