github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/upgrades/steps124.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package upgrades
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  	"os"
    10  	"path/filepath"
    11  	"strings"
    12  
    13  	"github.com/juju/juju/state"
    14  )
    15  
    16  // stateStepsFor124 returns upgrade steps for Juju 1.24 that manipulate state directly.
    17  func stateStepsFor124() []Step {
    18  	return []Step{
    19  		&upgradeStep{
    20  			description: "add block device documents for existing machines",
    21  			targets:     []Target{DatabaseMaster},
    22  			run: func(context Context) error {
    23  				return state.AddDefaultBlockDevicesDocs(context.State())
    24  			}},
    25  		&upgradeStep{
    26  			description: "move service.UnitSeq to sequence collection",
    27  			targets:     []Target{DatabaseMaster},
    28  			run: func(context Context) error {
    29  				return state.MoveServiceUnitSeqToSequence(context.State())
    30  			}},
    31  		&upgradeStep{
    32  			description: "add instance id field to IP addresses",
    33  			targets:     []Target{DatabaseMaster},
    34  			run: func(context Context) error {
    35  				return state.AddInstanceIdFieldOfIPAddresses(context.State())
    36  			}},
    37  		&upgradeStep{
    38  			description: "add UUID field to IP addresses",
    39  			targets:     []Target{DatabaseMaster},
    40  			run: func(context Context) error {
    41  				return state.AddUUIDToIPAddresses(context.State())
    42  			},
    43  		},
    44  		&upgradeStep{
    45  			description: "migrate charm archives into environment storage",
    46  			targets:     []Target{DatabaseMaster},
    47  			run: func(context Context) error {
    48  				return migrateCharmStorage(context.State(), context.AgentConfig())
    49  			},
    50  		},
    51  		&upgradeStep{
    52  			description: "change entityid field on status history to globalkey",
    53  			targets:     []Target{DatabaseMaster},
    54  			run: func(context Context) error {
    55  				return state.ChangeStatusHistoryEntityId(context.State())
    56  			},
    57  		},
    58  		&upgradeStep{
    59  			description: "change updated field on statushistory from time to int",
    60  			targets:     []Target{DatabaseMaster},
    61  			run: func(context Context) error {
    62  				return state.ChangeStatusHistoryUpdatedType(context.State())
    63  			},
    64  		},
    65  		&upgradeStep{
    66  			description: "change updated field on status from time to int",
    67  			targets:     []Target{DatabaseMaster},
    68  			run: func(context Context) error {
    69  				return state.ChangeStatusUpdatedType(context.State())
    70  			},
    71  		},
    72  	}
    73  }
    74  
    75  // stepsFor124 returns upgrade steps for Juju 1.24 that only need the API.
    76  func stepsFor124() []Step {
    77  	return []Step{
    78  		&upgradeStep{
    79  			description: "move syslog config from LogDir to DataDir",
    80  			targets:     []Target{AllMachines},
    81  			run:         moveSyslogConfig,
    82  		},
    83  	}
    84  }
    85  
    86  // stateStepsFor1244 returns upgrade steps for Juju 1.24.4 that manipulate state directly.
    87  func stateStepsFor1244() []Step {
    88  	return []Step{
    89  		&upgradeStep{
    90  			description: "add missing service statuses",
    91  			targets:     []Target{DatabaseMaster},
    92  			run: func(context Context) error {
    93  				return state.AddMissingServiceStatuses(context.State())
    94  			},
    95  		},
    96  	}
    97  }
    98  
    99  func moveSyslogConfig(context Context) error {
   100  	config := context.AgentConfig()
   101  	logdir := config.LogDir()
   102  	datadir := config.DataDir()
   103  
   104  	// these values were copied from
   105  	// github.com/juju/juju/utils/syslog/config.go
   106  	// Yes this is bad, but it is only needed once every for an
   107  	// upgrade, so it didn't seem worth exporting those values.
   108  	files := []string{
   109  		"ca-cert.pem",
   110  		"rsyslog-cert.pem",
   111  		"rsyslog-key.pem",
   112  		"logrotate.conf",
   113  		"logrotate.run",
   114  	}
   115  	var errs []string
   116  	for _, f := range files {
   117  		oldpath := filepath.Join(logdir, f)
   118  		newpath := filepath.Join(datadir, f)
   119  		if err := copyFile(newpath, oldpath); err != nil {
   120  			errs = append(errs, err.Error())
   121  			continue
   122  		}
   123  		if err := osRemove(oldpath); err != nil {
   124  			// Don't fail the step if we can't get rid of the old files.
   125  			// We don't actually care if they still exist or not.
   126  			logger.Warningf("Can't delete old config file %q: %s", oldpath, err)
   127  		}
   128  	}
   129  	if len(errs) > 0 {
   130  		return fmt.Errorf("error(s) while moving old syslog config files: %s", strings.Join(errs, "\n"))
   131  	}
   132  	return nil
   133  }
   134  
   135  // for testing... of course.
   136  var osRemove = os.Remove
   137  
   138  // copyFile copies a file from one location to another.  It won't overwrite
   139  // existing files and will return nil in this case.  This is used instead of
   140  // os.Rename because os.Rename won't work across partitions.
   141  func copyFile(to, from string) error {
   142  	logger.Debugf("Copying %q to %q", from, to)
   143  	orig, err := os.Open(from)
   144  	if os.IsNotExist(err) {
   145  		logger.Debugf("Old file %q does not exist, skipping.", from)
   146  		// original doesn't exist, that's fine.
   147  		return nil
   148  	}
   149  	if err != nil {
   150  		return err
   151  	}
   152  	defer orig.Close()
   153  	info, err := orig.Stat()
   154  	if err != nil {
   155  		return err
   156  	}
   157  	target, err := os.OpenFile(to, os.O_CREATE|os.O_WRONLY|os.O_EXCL, info.Mode())
   158  	if os.IsExist(err) {
   159  		return nil
   160  	}
   161  	defer target.Close()
   162  	if _, err := io.Copy(target, orig); err != nil {
   163  		return err
   164  	}
   165  	return nil
   166  }