blob: 906c4e762c6d38752933a114b7de1a538ff95ac3 [file] [log] [blame]
khenaidoob9203542018-09-17 22:56:37 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package core
17
18import (
19 "github.com/opencord/voltha-go/common/log"
khenaidoo0a822f92019-05-08 15:15:57 -040020 "github.com/opencord/voltha-go/rw_core/coreIf"
William Kurkiandaa6bb22019-03-07 12:26:28 -050021 "github.com/opencord/voltha-protos/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040022)
23
24type DeviceType int32
25
26const (
27 parent DeviceType = 0
28 child DeviceType = 1
29 any DeviceType = 2
30)
31
32type DeviceState struct {
33 Admin voltha.AdminState_AdminState
34 Connection voltha.ConnectStatus_ConnectStatus
35 Operational voltha.OperStatus_OperStatus
36}
37
khenaidoo92e62c52018-10-03 14:02:54 -040038type TransitionHandler func(*voltha.Device) error
khenaidoob9203542018-09-17 22:56:37 -040039
40type Transition struct {
41 deviceType DeviceType
42 previousState DeviceState
43 currentState DeviceState
khenaidoo92e62c52018-10-03 14:02:54 -040044 handlers []TransitionHandler
khenaidoob9203542018-09-17 22:56:37 -040045}
46
47type TransitionMap struct {
48 transitions []Transition
khenaidoo0a822f92019-05-08 15:15:57 -040049 dMgr coreIf.DeviceManager
khenaidoob9203542018-09-17 22:56:37 -040050}
51
khenaidoo0a822f92019-05-08 15:15:57 -040052func NewTransitionMap(dMgr coreIf.DeviceManager) *TransitionMap {
khenaidoob9203542018-09-17 22:56:37 -040053 var transitionMap TransitionMap
khenaidoo0a822f92019-05-08 15:15:57 -040054 transitionMap.dMgr = dMgr
khenaidoob9203542018-09-17 22:56:37 -040055 transitionMap.transitions = make([]Transition, 0)
khenaidoob9203542018-09-17 22:56:37 -040056 transitionMap.transitions = append(transitionMap.transitions,
57 Transition{
58 deviceType: any,
59 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
60 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -040061 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoob9203542018-09-17 22:56:37 -040062 transitionMap.transitions = append(transitionMap.transitions,
63 Transition{
64 deviceType: any,
65 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
66 currentState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -040067 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoob9203542018-09-17 22:56:37 -040068 transitionMap.transitions = append(transitionMap.transitions,
69 Transition{
70 deviceType: any,
71 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
72 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -040073 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoob9203542018-09-17 22:56:37 -040074 transitionMap.transitions = append(transitionMap.transitions,
75 Transition{
76 deviceType: parent,
khenaidoo0a822f92019-05-08 15:15:57 -040077 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
78 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE},
79 handlers: []TransitionHandler{dMgr.SetAdminStateToEnable}})
80 transitionMap.transitions = append(transitionMap.transitions,
81 Transition{
82 deviceType: parent,
83 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE},
84 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE},
85 handlers: []TransitionHandler{dMgr.CreateLogicalDevice}})
86 transitionMap.transitions = append(transitionMap.transitions,
87 Transition{
88 deviceType: parent,
89 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
90 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
91 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
92 transitionMap.transitions = append(transitionMap.transitions,
93 Transition{
94 deviceType: any,
95 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
96 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
97 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoob9203542018-09-17 22:56:37 -040098 transitionMap.transitions = append(transitionMap.transitions,
99 Transition{
100 deviceType: child,
khenaidoo0a822f92019-05-08 15:15:57 -0400101 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
102 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE},
103 handlers: []TransitionHandler{dMgr.SetAdminStateToEnable}})
104 transitionMap.transitions = append(transitionMap.transitions,
105 Transition{
106 deviceType: child,
107 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
108 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_DISCOVERED},
109 handlers: []TransitionHandler{}})
110 transitionMap.transitions = append(transitionMap.transitions,
111 Transition{
112 deviceType: child,
113 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_DISCOVERED},
114 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVATING},
115 handlers: []TransitionHandler{}})
116 transitionMap.transitions = append(transitionMap.transitions,
117 Transition{
118 deviceType: child,
119 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVATING},
120 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE},
121 handlers: []TransitionHandler{dMgr.SetAdminStateToEnable}})
122 transitionMap.transitions = append(transitionMap.transitions,
123 Transition{
124 deviceType: child,
125 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE},
126 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE},
127 handlers: []TransitionHandler{dMgr.SetupUNILogicalPorts}})
khenaidoob9203542018-09-17 22:56:37 -0400128 transitionMap.transitions = append(transitionMap.transitions,
129 Transition{
khenaidoo92e62c52018-10-03 14:02:54 -0400130 deviceType: parent,
khenaidoob9203542018-09-17 22:56:37 -0400131 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
132 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -0400133 handlers: []TransitionHandler{dMgr.DisableAllChildDevices}})
khenaidoo92e62c52018-10-03 14:02:54 -0400134 transitionMap.transitions = append(transitionMap.transitions,
135 Transition{
136 deviceType: child,
137 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
138 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -0400139 handlers: []TransitionHandler{}})
khenaidoob9203542018-09-17 22:56:37 -0400140 transitionMap.transitions = append(transitionMap.transitions,
141 Transition{
142 deviceType: any,
143 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
144 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -0400145 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
146 transitionMap.transitions = append(transitionMap.transitions,
147 Transition{
148 deviceType: any,
149 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
150 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
151 handlers: []TransitionHandler{dMgr.SetAdminStateToEnable}})
khenaidoob9203542018-09-17 22:56:37 -0400152 transitionMap.transitions = append(transitionMap.transitions,
153 Transition{
khenaidoo4d4802d2018-10-04 21:59:49 -0400154 deviceType: child,
khenaidoob9203542018-09-17 22:56:37 -0400155 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
156 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -0400157 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoob9203542018-09-17 22:56:37 -0400158 transitionMap.transitions = append(transitionMap.transitions,
159 Transition{
160 deviceType: any,
161 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
162 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -0400163 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoob9203542018-09-17 22:56:37 -0400164 transitionMap.transitions = append(transitionMap.transitions,
165 Transition{
khenaidoo4554f7c2019-05-29 22:13:15 -0400166 deviceType: any,
167 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
168 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
169 handlers: []TransitionHandler{dMgr.RunPostDeviceDelete}})
170 transitionMap.transitions = append(transitionMap.transitions,
171 Transition{
khenaidoo4d4802d2018-10-04 21:59:49 -0400172 deviceType: parent,
khenaidoob9203542018-09-17 22:56:37 -0400173 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo4d4802d2018-10-04 21:59:49 -0400174 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -0400175 handlers: []TransitionHandler{dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.RunPostDeviceDelete}})
176 transitionMap.transitions = append(transitionMap.transitions,
177 Transition{
178 deviceType: child,
179 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
180 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
181 handlers: []TransitionHandler{dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
khenaidoob9203542018-09-17 22:56:37 -0400182 transitionMap.transitions = append(transitionMap.transitions,
183 Transition{
184 deviceType: any,
185 previousState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
186 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -0400187 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoob9203542018-09-17 22:56:37 -0400188
189 return &transitionMap
190}
191
192func getDeviceStates(device *voltha.Device) *DeviceState {
193 return &DeviceState{Admin: device.AdminState, Connection: device.ConnectStatus, Operational: device.OperStatus}
194}
195
196// isMatched matches a state transition. It returns whether there is a match and if there is whether it is an exact match
khenaidoo92e62c52018-10-03 14:02:54 -0400197func getHandler(previous *DeviceState, current *DeviceState, transition *Transition) ([]TransitionHandler, bool) {
khenaidoob9203542018-09-17 22:56:37 -0400198
199 // Do we have an exact match?
200 if *previous == transition.previousState && *current == transition.currentState {
khenaidoo92e62c52018-10-03 14:02:54 -0400201 return transition.handlers, true
khenaidoob9203542018-09-17 22:56:37 -0400202 }
khenaidoo0a822f92019-05-08 15:15:57 -0400203
204 // Admin states must match
205 if previous.Admin != transition.previousState.Admin || current.Admin != transition.currentState.Admin {
206 return nil, false
207 }
208
khenaidoob9203542018-09-17 22:56:37 -0400209 // If the admin state changed then prioritize it first
210 if previous.Admin != current.Admin {
211 if previous.Admin == transition.previousState.Admin && current.Admin == transition.currentState.Admin {
khenaidoo92e62c52018-10-03 14:02:54 -0400212 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400213 }
214 }
215 // If the operational state changed then prioritize it in second position
216 if previous.Operational != current.Operational {
217 if previous.Operational == transition.previousState.Operational && current.Operational == transition.currentState.Operational {
khenaidoo92e62c52018-10-03 14:02:54 -0400218 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400219 }
220 }
221 // If the connection state changed then prioritize it in third position
222 if previous.Connection != current.Connection {
223 if previous.Connection == transition.previousState.Connection && current.Connection == transition.currentState.Connection {
khenaidoo92e62c52018-10-03 14:02:54 -0400224 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400225 }
226 }
227 return nil, false
228}
229
khenaidoo92e62c52018-10-03 14:02:54 -0400230func (tMap *TransitionMap) GetTransitionHandler(pDevice *voltha.Device, cDevice *voltha.Device) []TransitionHandler {
khenaidoob9203542018-09-17 22:56:37 -0400231 //1. Get the previous and current set of states
232 pState := getDeviceStates(pDevice)
233 cState := getDeviceStates(cDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400234 //log.Infow("DeviceType", log.Fields{"device": pDevice})
khenaidoob9203542018-09-17 22:56:37 -0400235 deviceType := parent
236 if !pDevice.Root {
237 log.Info("device is child")
238 deviceType = child
239 }
240 log.Infof("deviceType:%d-deviceId:%s-previous:%v-current:%v", deviceType, pDevice.Id, pState, cState)
241
242 //2. Go over transition array to get the right transition
khenaidoo92e62c52018-10-03 14:02:54 -0400243 var currentMatch []TransitionHandler
244 var tempHandler []TransitionHandler
khenaidoo0a822f92019-05-08 15:15:57 -0400245 var exactStateMatch bool
246 var stateMatchFound bool
khenaidoob9203542018-09-17 22:56:37 -0400247 for _, aTransition := range tMap.transitions {
248 // consider transition only if it matches deviceType or is a wild card - any
249 if aTransition.deviceType != deviceType && aTransition.deviceType != any {
250 continue
251 }
khenaidoo0a822f92019-05-08 15:15:57 -0400252 tempHandler, exactStateMatch = getHandler(pState, cState, &aTransition)
khenaidoob9203542018-09-17 22:56:37 -0400253 if tempHandler != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400254 if exactStateMatch && aTransition.deviceType == deviceType {
khenaidoob9203542018-09-17 22:56:37 -0400255 return tempHandler
khenaidoo0a822f92019-05-08 15:15:57 -0400256 } else if exactStateMatch {
257 currentMatch = tempHandler
258 stateMatchFound = true
259 } else if currentMatch == nil && !stateMatchFound {
260 currentMatch = tempHandler
khenaidoob9203542018-09-17 22:56:37 -0400261 }
262 }
263 }
264 return currentMatch
265}