github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/upgrades/agentconfig.go (about) 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 "path/filepath" 10 11 "github.com/juju/errors" 12 "github.com/juju/utils" 13 "github.com/juju/utils/symlink" 14 15 "github.com/juju/juju/agent" 16 "github.com/juju/juju/environs/config" 17 "github.com/juju/juju/state/multiwatcher" 18 ) 19 20 var ( 21 rootLogDir = "/var/log" 22 rootSpoolDir = "/var/spool/rsyslog" 23 ) 24 25 var chownPath = utils.ChownPath 26 27 var isLocalEnviron = func(envConfig *config.Config) bool { 28 return envConfig.Type() == "local" 29 } 30 31 func migrateLocalProviderAgentConfig(context Context) error { 32 st := context.State() 33 if st == nil { 34 logger.Debugf("no state connection, no migration required") 35 // We're running on a different node than the state server. 36 return nil 37 } 38 envConfig, err := st.EnvironConfig() 39 if err != nil { 40 return fmt.Errorf("failed to read current config: %v", err) 41 } 42 if !isLocalEnviron(envConfig) { 43 logger.Debugf("not a local environment, no migration required") 44 return nil 45 } 46 attrs := envConfig.AllAttrs() 47 rootDir, _ := attrs["root-dir"].(string) 48 sharedStorageDir := filepath.Join(rootDir, "shared-storage") 49 // In case these two are empty we need to set them and update the 50 // environment config. 51 namespace, _ := attrs["namespace"].(string) 52 container, _ := attrs["container"].(string) 53 54 if namespace == "" { 55 username := os.Getenv("USER") 56 if username == "root" { 57 // sudo was probably called, get the original user. 58 username = os.Getenv("SUDO_USER") 59 } 60 if username == "" { 61 return fmt.Errorf("cannot get current user from the environment: %v", os.Environ()) 62 } 63 namespace = username + "-" + envConfig.Name() 64 } 65 if container == "" { 66 container = "lxc" 67 } 68 69 dataDir := rootDir 70 localLogDir := filepath.Join(rootDir, "log") 71 metricSpoolDir := filepath.Join(rootDir, "metricspool") 72 uniterStateDir := filepath.Join(rootDir, "uniter", "state") 73 // rsyslogd is restricted to write to /var/log 74 logDir := fmt.Sprintf("%s/juju-%s", rootLogDir, namespace) 75 jobs := []multiwatcher.MachineJob{multiwatcher.JobManageEnviron} 76 values := map[string]string{ 77 agent.Namespace: namespace, 78 // ContainerType is empty on the bootstrap node. 79 agent.ContainerType: "", 80 agent.AgentServiceName: "juju-agent-" + namespace, 81 } 82 deprecatedValues := []string{ 83 "SHARED_STORAGE_ADDR", 84 "SHARED_STORAGE_DIR", 85 } 86 87 // Remove shared-storage dir if there. 88 if err := os.RemoveAll(sharedStorageDir); err != nil { 89 return fmt.Errorf("cannot remove deprecated %q: %v", sharedStorageDir, err) 90 } 91 92 // We need to create the dirs if they don't exist. 93 if err := os.MkdirAll(dataDir, 0755); err != nil { 94 return fmt.Errorf("cannot create dataDir %q: %v", dataDir, err) 95 } 96 // We always recreate the logDir to make sure it's empty. 97 if err := os.RemoveAll(logDir); err != nil { 98 return fmt.Errorf("cannot remove logDir %q: %v", logDir, err) 99 } 100 if err := os.MkdirAll(logDir, 0755); err != nil { 101 return fmt.Errorf("cannot create logDir %q: %v", logDir, err) 102 } 103 if err := os.MkdirAll(metricSpoolDir, 0755); err != nil { 104 return fmt.Errorf("cannot create metricSpoolDir %q: %v", metricSpoolDir, err) 105 } 106 if err := os.MkdirAll(uniterStateDir, 0755); err != nil { 107 return fmt.Errorf("cannot create uniterStateDir %q: %v", uniterStateDir, err) 108 } 109 // Reconfigure rsyslog as needed: 110 // 1. logDir must be owned by syslog:adm 111 // 2. Remove old rsyslog spool config 112 // 3. Relink logs to the new logDir 113 if err := chownPath(logDir, "syslog"); err != nil { 114 return err 115 } 116 spoolConfig := fmt.Sprintf("%s/machine-0-%s", rootSpoolDir, namespace) 117 if err := os.RemoveAll(spoolConfig); err != nil { 118 return fmt.Errorf("cannot remove %q: %v", spoolConfig, err) 119 } 120 allMachinesLog := filepath.Join(logDir, "all-machines.log") 121 if err := symlink.New(allMachinesLog, localLogDir+"/"); err != nil && !os.IsExist(err) { 122 return fmt.Errorf("cannot symlink %q to %q: %v", allMachinesLog, localLogDir, err) 123 } 124 machine0Log := filepath.Join(localLogDir, "machine-0.log") 125 if err := symlink.New(machine0Log, logDir+"/"); err != nil && !os.IsExist(err) { 126 return fmt.Errorf("cannot symlink %q to %q: %v", machine0Log, logDir, err) 127 } 128 129 newCfg := map[string]interface{}{ 130 "namespace": namespace, 131 "container": container, 132 } 133 if err := st.UpdateEnvironConfig(newCfg, nil, nil); err != nil { 134 return fmt.Errorf("cannot update environment config: %v", err) 135 } 136 137 return context.AgentConfig().Migrate(agent.MigrateParams{ 138 Paths: agent.Paths{ 139 DataDir: dataDir, 140 LogDir: logDir, 141 MetricsSpoolDir: metricSpoolDir, 142 }, 143 Jobs: jobs, 144 Values: values, 145 DeleteValues: deprecatedValues, 146 }) 147 } 148 149 func addEnvironmentUUIDToAgentConfig(context Context) error { 150 if context.AgentConfig().Environment().Id() != "" { 151 logger.Infof("environment uuid already set in agent config") 152 return nil 153 } 154 155 environTag, err := context.APIState().EnvironTag() 156 if err != nil { 157 return errors.Annotate(err, "no environment uuid set on api") 158 } 159 160 return context.AgentConfig().Migrate(agent.MigrateParams{ 161 Environment: environTag, 162 }) 163 }