blob: 44eb484db1684c4a5a38ee553708c0cac135dfc5 [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{
khenaidoob9203542018-09-17 22:56:37 -040058 deviceType: parent,
khenaidoo59ef7be2019-06-21 12:40:28 -040059 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
60 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
khenaidoo0a822f92019-05-08 15:15:57 -040061 handlers: []TransitionHandler{dMgr.CreateLogicalDevice}})
62 transitionMap.transitions = append(transitionMap.transitions,
63 Transition{
khenaidoo59ef7be2019-06-21 12:40:28 -040064 deviceType: child,
65 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED},
66 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
67 handlers: []TransitionHandler{dMgr.SetupUNILogicalPorts}})
khenaidoob9203542018-09-17 22:56:37 -040068 transitionMap.transitions = append(transitionMap.transitions,
69 Transition{
70 deviceType: child,
khenaidoo59ef7be2019-06-21 12:40:28 -040071 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
72 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
khenaidoo0a822f92019-05-08 15:15:57 -040073 handlers: []TransitionHandler{dMgr.SetupUNILogicalPorts}})
khenaidoob9203542018-09-17 22:56:37 -040074 transitionMap.transitions = append(transitionMap.transitions,
75 Transition{
khenaidoo92e62c52018-10-03 14:02:54 -040076 deviceType: parent,
khenaidoob9203542018-09-17 22:56:37 -040077 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
78 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo59ef7be2019-06-21 12:40:28 -040079 handlers: []TransitionHandler{dMgr.MarkChildDevicesAsUnReachable}})
khenaidoob9203542018-09-17 22:56:37 -040080 transitionMap.transitions = append(transitionMap.transitions,
81 Transition{
khenaidoo4554f7c2019-05-29 22:13:15 -040082 deviceType: any,
83 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
84 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
85 handlers: []TransitionHandler{dMgr.RunPostDeviceDelete}})
86 transitionMap.transitions = append(transitionMap.transitions,
87 Transition{
khenaidoo4d4802d2018-10-04 21:59:49 -040088 deviceType: parent,
khenaidoob9203542018-09-17 22:56:37 -040089 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo4d4802d2018-10-04 21:59:49 -040090 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -040091 handlers: []TransitionHandler{dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.RunPostDeviceDelete}})
92 transitionMap.transitions = append(transitionMap.transitions,
93 Transition{
94 deviceType: child,
95 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
96 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
97 handlers: []TransitionHandler{dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
khenaidoob9203542018-09-17 22:56:37 -040098 transitionMap.transitions = append(transitionMap.transitions,
99 Transition{
100 deviceType: any,
khenaidoo59ef7be2019-06-21 12:40:28 -0400101 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
102 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
103 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
104 transitionMap.transitions = append(transitionMap.transitions,
105 Transition{
106 deviceType: any,
107 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
108 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
109 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
110 transitionMap.transitions = append(transitionMap.transitions,
111 Transition{
112 deviceType: any,
113 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
114 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
115 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
116 transitionMap.transitions = append(transitionMap.transitions,
117 Transition{
118 deviceType: any,
119 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
120 currentState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
121 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
122 transitionMap.transitions = append(transitionMap.transitions,
123 Transition{
124 deviceType: any,
125 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
126 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
127 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
128 transitionMap.transitions = append(transitionMap.transitions,
129 Transition{
130 deviceType: parent,
131 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
132 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
133 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
134 transitionMap.transitions = append(transitionMap.transitions,
135 Transition{
136 deviceType: any,
137 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
138 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
139 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
140 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},
145 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
146 transitionMap.transitions = append(transitionMap.transitions,
147 Transition{
148 deviceType: child,
149 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
150 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
151 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
152 transitionMap.transitions = append(transitionMap.transitions,
153 Transition{
154 deviceType: any,
155 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
156 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
157 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
158 transitionMap.transitions = append(transitionMap.transitions,
159 Transition{
160 deviceType: any,
khenaidoob9203542018-09-17 22:56:37 -0400161 previousState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
162 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, 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
165 return &transitionMap
166}
167
168func getDeviceStates(device *voltha.Device) *DeviceState {
169 return &DeviceState{Admin: device.AdminState, Connection: device.ConnectStatus, Operational: device.OperStatus}
170}
171
172// 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 -0400173func getHandler(previous *DeviceState, current *DeviceState, transition *Transition) ([]TransitionHandler, bool) {
khenaidoob9203542018-09-17 22:56:37 -0400174
175 // Do we have an exact match?
176 if *previous == transition.previousState && *current == transition.currentState {
khenaidoo92e62c52018-10-03 14:02:54 -0400177 return transition.handlers, true
khenaidoob9203542018-09-17 22:56:37 -0400178 }
khenaidoo0a822f92019-05-08 15:15:57 -0400179
180 // Admin states must match
181 if previous.Admin != transition.previousState.Admin || current.Admin != transition.currentState.Admin {
182 return nil, false
183 }
184
khenaidoob9203542018-09-17 22:56:37 -0400185 // If the admin state changed then prioritize it first
186 if previous.Admin != current.Admin {
187 if previous.Admin == transition.previousState.Admin && current.Admin == transition.currentState.Admin {
khenaidoo92e62c52018-10-03 14:02:54 -0400188 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400189 }
190 }
191 // If the operational state changed then prioritize it in second position
192 if previous.Operational != current.Operational {
193 if previous.Operational == transition.previousState.Operational && current.Operational == transition.currentState.Operational {
khenaidoo92e62c52018-10-03 14:02:54 -0400194 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400195 }
196 }
197 // If the connection state changed then prioritize it in third position
198 if previous.Connection != current.Connection {
199 if previous.Connection == transition.previousState.Connection && current.Connection == transition.currentState.Connection {
khenaidoo92e62c52018-10-03 14:02:54 -0400200 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400201 }
202 }
203 return nil, false
204}
205
khenaidoo92e62c52018-10-03 14:02:54 -0400206func (tMap *TransitionMap) GetTransitionHandler(pDevice *voltha.Device, cDevice *voltha.Device) []TransitionHandler {
khenaidoob9203542018-09-17 22:56:37 -0400207 //1. Get the previous and current set of states
208 pState := getDeviceStates(pDevice)
209 cState := getDeviceStates(cDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400210 //log.Infow("DeviceType", log.Fields{"device": pDevice})
khenaidoob9203542018-09-17 22:56:37 -0400211 deviceType := parent
212 if !pDevice.Root {
213 log.Info("device is child")
214 deviceType = child
215 }
216 log.Infof("deviceType:%d-deviceId:%s-previous:%v-current:%v", deviceType, pDevice.Id, pState, cState)
217
218 //2. Go over transition array to get the right transition
khenaidoo92e62c52018-10-03 14:02:54 -0400219 var currentMatch []TransitionHandler
220 var tempHandler []TransitionHandler
khenaidoo0a822f92019-05-08 15:15:57 -0400221 var exactStateMatch bool
222 var stateMatchFound bool
khenaidoob9203542018-09-17 22:56:37 -0400223 for _, aTransition := range tMap.transitions {
224 // consider transition only if it matches deviceType or is a wild card - any
225 if aTransition.deviceType != deviceType && aTransition.deviceType != any {
226 continue
227 }
khenaidoo0a822f92019-05-08 15:15:57 -0400228 tempHandler, exactStateMatch = getHandler(pState, cState, &aTransition)
khenaidoob9203542018-09-17 22:56:37 -0400229 if tempHandler != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400230 if exactStateMatch && aTransition.deviceType == deviceType {
khenaidoob9203542018-09-17 22:56:37 -0400231 return tempHandler
khenaidoo0a822f92019-05-08 15:15:57 -0400232 } else if exactStateMatch {
233 currentMatch = tempHandler
234 stateMatchFound = true
235 } else if currentMatch == nil && !stateMatchFound {
236 currentMatch = tempHandler
khenaidoob9203542018-09-17 22:56:37 -0400237 }
238 }
239 }
240 return currentMatch
241}