github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/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 IMPORT 15 VALIDATION 16 SUCCESS 17 LOGTRANSFER 18 REAP 19 REAPFAILED 20 DONE 21 ABORT 22 ABORTDONE 23 ) 24 25 var phaseNames = []string{ 26 "UNKNOWN", // To catch uninitialised fields. 27 "NONE", // For watchers to indicate there's never been a migration attempt. 28 "QUIESCE", 29 "IMPORT", 30 "VALIDATION", 31 "SUCCESS", 32 "LOGTRANSFER", 33 "REAP", 34 "REAPFAILED", 35 "DONE", 36 "ABORT", 37 "ABORTDONE", 38 } 39 40 // String returns the name of an model migration phase constant. 41 func (p Phase) String() string { 42 i := int(p) 43 if i >= 0 && i < len(phaseNames) { 44 return phaseNames[i] 45 } 46 return "UNKNOWN" 47 } 48 49 // CanTransitionTo returns true if the given phase is a valid next 50 // model migration phase. 51 func (p Phase) CanTransitionTo(targetPhase Phase) bool { 52 nextPhases, exists := validTransitions[p] 53 if !exists { 54 return false 55 } 56 for _, nextPhase := range nextPhases { 57 if nextPhase == targetPhase { 58 return true 59 } 60 } 61 return false 62 } 63 64 // IsTerminal returns true if the phase is one which signifies the end 65 // of a migration. 66 func (p Phase) IsTerminal() bool { 67 for _, t := range terminalPhases { 68 if p == t { 69 return true 70 } 71 } 72 return false 73 } 74 75 // IsRunning returns true if the phase indicates the migration is 76 // active and up to or at the SUCCESS phase. It returns false if the 77 // phase is one of the final cleanup phases or indicates an failed 78 // migration. 79 func (p Phase) IsRunning() bool { 80 if p.IsTerminal() { 81 return false 82 } 83 switch p { 84 case QUIESCE, IMPORT, VALIDATION, SUCCESS: 85 return true 86 default: 87 return false 88 } 89 } 90 91 // Define all possible phase transitions. 92 // 93 // The keys are the "from" states and the values enumerate the 94 // possible "to" states. 95 var validTransitions = map[Phase][]Phase{ 96 QUIESCE: {IMPORT, ABORT}, 97 IMPORT: {VALIDATION, ABORT}, 98 VALIDATION: {SUCCESS, ABORT}, 99 SUCCESS: {LOGTRANSFER}, 100 LOGTRANSFER: {REAP}, 101 REAP: {DONE, REAPFAILED}, 102 ABORT: {ABORTDONE}, 103 } 104 105 var terminalPhases []Phase 106 107 func init() { 108 // Compute the terminal phases. 109 for p := 0; p <= len(phaseNames); p++ { 110 phase := Phase(p) 111 if _, exists := validTransitions[phase]; !exists { 112 terminalPhases = append(terminalPhases, phase) 113 } 114 } 115 } 116 117 // ParsePhase converts a string model migration phase name 118 // to its constant value. 119 func ParsePhase(target string) (Phase, bool) { 120 for p, name := range phaseNames { 121 if target == name { 122 return Phase(p), true 123 } 124 } 125 return UNKNOWN, false 126 }