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  }