github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/core/migration/phase.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package migration
     5  
     6  // Phase values specify model migration phases.
     7  type Phase int
     8  
     9  // Enumerate all possible migration phases.
    10  const (
    11  	UNKNOWN Phase = iota
    12  	NONE
    13  	QUIESCE
    14  	READONLY
    15  	PRECHECK
    16  	IMPORT
    17  	VALIDATION
    18  	SUCCESS
    19  	LOGTRANSFER
    20  	REAP
    21  	REAPFAILED
    22  	DONE
    23  	ABORT
    24  	ABORTDONE
    25  )
    26  
    27  var phaseNames = []string{
    28  	"UNKNOWN", // To catch uninitialised fields.
    29  	"NONE",    // For watchers to indicate there's never been a migration attempt.
    30  	"QUIESCE",
    31  	"READONLY",
    32  	"PRECHECK",
    33  	"VALIDATION",
    34  	"IMPORT",
    35  	"SUCCESS",
    36  	"LOGTRANSFER",
    37  	"REAP",
    38  	"REAPFAILED",
    39  	"DONE",
    40  	"ABORT",
    41  	"ABORTDONE",
    42  }
    43  
    44  // String returns the name of an model migration phase constant.
    45  func (p Phase) String() string {
    46  	i := int(p)
    47  	if i >= 0 && i < len(phaseNames) {
    48  		return phaseNames[i]
    49  	}
    50  	return "UNKNOWN"
    51  }
    52  
    53  // CanTransitionTo returns true if the given phase is a valid next
    54  // model migration phase.
    55  func (p Phase) CanTransitionTo(targetPhase Phase) bool {
    56  	nextPhases, exists := validTransitions[p]
    57  	if !exists {
    58  		return false
    59  	}
    60  	for _, nextPhase := range nextPhases {
    61  		if nextPhase == targetPhase {
    62  			return true
    63  		}
    64  	}
    65  	return false
    66  }
    67  
    68  // IsTerminal returns true if the phase is one which signifies the end
    69  // of a migration.
    70  func (p Phase) IsTerminal() bool {
    71  	for _, t := range terminalPhases {
    72  		if p == t {
    73  			return true
    74  		}
    75  	}
    76  	return false
    77  }
    78  
    79  // Define all possible phase transitions.
    80  //
    81  // The keys are the "from" states and the values enumerate the
    82  // possible "to" states.
    83  var validTransitions = map[Phase][]Phase{
    84  	QUIESCE:     {READONLY, ABORT},
    85  	READONLY:    {PRECHECK, ABORT},
    86  	PRECHECK:    {IMPORT, ABORT},
    87  	IMPORT:      {VALIDATION, ABORT},
    88  	VALIDATION:  {SUCCESS, ABORT},
    89  	SUCCESS:     {LOGTRANSFER},
    90  	LOGTRANSFER: {REAP},
    91  	REAP:        {DONE, REAPFAILED},
    92  	ABORT:       {ABORTDONE},
    93  }
    94  
    95  var terminalPhases []Phase
    96  
    97  func init() {
    98  	// Compute the terminal phases.
    99  	for p := 0; p <= len(phaseNames); p++ {
   100  		phase := Phase(p)
   101  		if _, exists := validTransitions[phase]; !exists {
   102  			terminalPhases = append(terminalPhases, phase)
   103  		}
   104  	}
   105  }
   106  
   107  // ParsePhase converts a string model migration phase name
   108  // to its constant value.
   109  func ParsePhase(target string) (Phase, bool) {
   110  	for p, name := range phaseNames {
   111  		if target == name {
   112  			return Phase(p), true
   113  		}
   114  	}
   115  	return UNKNOWN, false
   116  }