blob: 5c52a8f6bf4bb431235bc3d0a468beb7a9922e15 [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{
khenaidoo4d4802d2018-10-04 21:59:49 -0400166 deviceType: parent,
khenaidoob9203542018-09-17 22:56:37 -0400167 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo4d4802d2018-10-04 21:59:49 -0400168 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -0400169 handlers: []TransitionHandler{dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.RunPostDeviceDelete}})
170 transitionMap.transitions = append(transitionMap.transitions,
171 Transition{
172 deviceType: child,
173 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
174 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
175 handlers: []TransitionHandler{dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
khenaidoob9203542018-09-17 22:56:37 -0400176 transitionMap.transitions = append(transitionMap.transitions,
177 Transition{
178 deviceType: any,
179 previousState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
180 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -0400181 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoob9203542018-09-17 22:56:37 -0400182
183 return &transitionMap
184}
185
186func getDeviceStates(device *voltha.Device) *DeviceState {
187 return &DeviceState{Admin: device.AdminState, Connection: device.ConnectStatus, Operational: device.OperStatus}
188}
189
190// 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 -0400191func getHandler(previous *DeviceState, current *DeviceState, transition *Transition) ([]TransitionHandler, bool) {
khenaidoob9203542018-09-17 22:56:37 -0400192
193 // Do we have an exact match?
194 if *previous == transition.previousState && *current == transition.currentState {
khenaidoo92e62c52018-10-03 14:02:54 -0400195 return transition.handlers, true
khenaidoob9203542018-09-17 22:56:37 -0400196 }
khenaidoo0a822f92019-05-08 15:15:57 -0400197
198 // Admin states must match
199 if previous.Admin != transition.previousState.Admin || current.Admin != transition.currentState.Admin {
200 return nil, false
201 }
202
khenaidoob9203542018-09-17 22:56:37 -0400203 // If the admin state changed then prioritize it first
204 if previous.Admin != current.Admin {
205 if previous.Admin == transition.previousState.Admin && current.Admin == transition.currentState.Admin {
khenaidoo92e62c52018-10-03 14:02:54 -0400206 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400207 }
208 }
209 // If the operational state changed then prioritize it in second position
210 if previous.Operational != current.Operational {
211 if previous.Operational == transition.previousState.Operational && current.Operational == transition.currentState.Operational {
khenaidoo92e62c52018-10-03 14:02:54 -0400212 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400213 }
214 }
215 // If the connection state changed then prioritize it in third position
216 if previous.Connection != current.Connection {
217 if previous.Connection == transition.previousState.Connection && current.Connection == transition.currentState.Connection {
khenaidoo92e62c52018-10-03 14:02:54 -0400218 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400219 }
220 }
221 return nil, false
222}
223
khenaidoo92e62c52018-10-03 14:02:54 -0400224func (tMap *TransitionMap) GetTransitionHandler(pDevice *voltha.Device, cDevice *voltha.Device) []TransitionHandler {
khenaidoob9203542018-09-17 22:56:37 -0400225 //1. Get the previous and current set of states
226 pState := getDeviceStates(pDevice)
227 cState := getDeviceStates(cDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400228 //log.Infow("DeviceType", log.Fields{"device": pDevice})
khenaidoob9203542018-09-17 22:56:37 -0400229 deviceType := parent
230 if !pDevice.Root {
231 log.Info("device is child")
232 deviceType = child
233 }
234 log.Infof("deviceType:%d-deviceId:%s-previous:%v-current:%v", deviceType, pDevice.Id, pState, cState)
235
236 //2. Go over transition array to get the right transition
khenaidoo92e62c52018-10-03 14:02:54 -0400237 var currentMatch []TransitionHandler
238 var tempHandler []TransitionHandler
khenaidoo0a822f92019-05-08 15:15:57 -0400239 var exactStateMatch bool
240 var stateMatchFound bool
khenaidoob9203542018-09-17 22:56:37 -0400241 for _, aTransition := range tMap.transitions {
242 // consider transition only if it matches deviceType or is a wild card - any
243 if aTransition.deviceType != deviceType && aTransition.deviceType != any {
244 continue
245 }
khenaidoo0a822f92019-05-08 15:15:57 -0400246 tempHandler, exactStateMatch = getHandler(pState, cState, &aTransition)
khenaidoob9203542018-09-17 22:56:37 -0400247 if tempHandler != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400248 if exactStateMatch && aTransition.deviceType == deviceType {
khenaidoob9203542018-09-17 22:56:37 -0400249 return tempHandler
khenaidoo0a822f92019-05-08 15:15:57 -0400250 } else if exactStateMatch {
251 currentMatch = tempHandler
252 stateMatchFound = true
253 } else if currentMatch == nil && !stateMatchFound {
254 currentMatch = tempHandler
khenaidoob9203542018-09-17 22:56:37 -0400255 }
256 }
257 }
258 return currentMatch
259}