blob: a48346a244f56cc272e88b908303a55516e0eac0 [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 (
khenaidoo0a822f92019-05-08 15:15:57 -040019 "github.com/opencord/voltha-go/rw_core/coreIf"
Scott Baker807addd2019-10-24 15:16:21 -070020 "github.com/opencord/voltha-lib-go/v2/pkg/log"
Scott Baker555307d2019-11-04 08:58:01 -080021 "github.com/opencord/voltha-protos/v2/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{
khenaidoo4554f7c2019-05-29 22:13:15 -040076 deviceType: any,
77 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
78 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
79 handlers: []TransitionHandler{dMgr.RunPostDeviceDelete}})
80 transitionMap.transitions = append(transitionMap.transitions,
81 Transition{
khenaidoo4d4802d2018-10-04 21:59:49 -040082 deviceType: parent,
khenaidoob9203542018-09-17 22:56:37 -040083 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo4d4802d2018-10-04 21:59:49 -040084 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Devmalya Paul84169b52019-08-27 19:31:44 -040085 handlers: []TransitionHandler{dMgr.DisableAllChildDevices, dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.RunPostDeviceDelete}})
khenaidoo0a822f92019-05-08 15:15:57 -040086 transitionMap.transitions = append(transitionMap.transitions,
87 Transition{
88 deviceType: child,
89 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
90 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
91 handlers: []TransitionHandler{dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
khenaidoob9203542018-09-17 22:56:37 -040092 transitionMap.transitions = append(transitionMap.transitions,
93 Transition{
94 deviceType: any,
khenaidoo59ef7be2019-06-21 12:40:28 -040095 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
96 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
97 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
98 transitionMap.transitions = append(transitionMap.transitions,
99 Transition{
100 deviceType: any,
101 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
102 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
103 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
104 transitionMap.transitions = append(transitionMap.transitions,
105 Transition{
106 deviceType: any,
107 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
108 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, 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_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
114 currentState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, 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_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
121 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
122 transitionMap.transitions = append(transitionMap.transitions,
123 Transition{
124 deviceType: parent,
125 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
126 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
127 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
128 transitionMap.transitions = append(transitionMap.transitions,
129 Transition{
130 deviceType: any,
131 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
132 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
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_UNKNOWN},
138 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
139 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
140 transitionMap.transitions = append(transitionMap.transitions,
141 Transition{
142 deviceType: child,
143 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
144 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
145 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_UNKNOWN},
150 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
151 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
152 transitionMap.transitions = append(transitionMap.transitions,
153 Transition{
154 deviceType: any,
khenaidoob9203542018-09-17 22:56:37 -0400155 previousState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
156 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, 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
159 return &transitionMap
160}
161
162func getDeviceStates(device *voltha.Device) *DeviceState {
163 return &DeviceState{Admin: device.AdminState, Connection: device.ConnectStatus, Operational: device.OperStatus}
164}
165
166// 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 -0400167func getHandler(previous *DeviceState, current *DeviceState, transition *Transition) ([]TransitionHandler, bool) {
khenaidoob9203542018-09-17 22:56:37 -0400168
169 // Do we have an exact match?
170 if *previous == transition.previousState && *current == transition.currentState {
khenaidoo92e62c52018-10-03 14:02:54 -0400171 return transition.handlers, true
khenaidoob9203542018-09-17 22:56:37 -0400172 }
khenaidoo0a822f92019-05-08 15:15:57 -0400173
174 // Admin states must match
175 if previous.Admin != transition.previousState.Admin || current.Admin != transition.currentState.Admin {
176 return nil, false
177 }
178
khenaidoob9203542018-09-17 22:56:37 -0400179 // If the admin state changed then prioritize it first
180 if previous.Admin != current.Admin {
181 if previous.Admin == transition.previousState.Admin && current.Admin == transition.currentState.Admin {
khenaidoo92e62c52018-10-03 14:02:54 -0400182 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400183 }
184 }
185 // If the operational state changed then prioritize it in second position
186 if previous.Operational != current.Operational {
187 if previous.Operational == transition.previousState.Operational && current.Operational == transition.currentState.Operational {
khenaidoo92e62c52018-10-03 14:02:54 -0400188 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400189 }
190 }
191 // If the connection state changed then prioritize it in third position
192 if previous.Connection != current.Connection {
193 if previous.Connection == transition.previousState.Connection && current.Connection == transition.currentState.Connection {
khenaidoo92e62c52018-10-03 14:02:54 -0400194 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400195 }
196 }
197 return nil, false
198}
199
khenaidoo92e62c52018-10-03 14:02:54 -0400200func (tMap *TransitionMap) GetTransitionHandler(pDevice *voltha.Device, cDevice *voltha.Device) []TransitionHandler {
khenaidoob9203542018-09-17 22:56:37 -0400201 //1. Get the previous and current set of states
202 pState := getDeviceStates(pDevice)
203 cState := getDeviceStates(cDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400204 //log.Infow("DeviceType", log.Fields{"device": pDevice})
khenaidoob9203542018-09-17 22:56:37 -0400205 deviceType := parent
206 if !pDevice.Root {
207 log.Info("device is child")
208 deviceType = child
209 }
210 log.Infof("deviceType:%d-deviceId:%s-previous:%v-current:%v", deviceType, pDevice.Id, pState, cState)
211
212 //2. Go over transition array to get the right transition
khenaidoo92e62c52018-10-03 14:02:54 -0400213 var currentMatch []TransitionHandler
214 var tempHandler []TransitionHandler
khenaidoo0a822f92019-05-08 15:15:57 -0400215 var exactStateMatch bool
216 var stateMatchFound bool
khenaidoob9203542018-09-17 22:56:37 -0400217 for _, aTransition := range tMap.transitions {
218 // consider transition only if it matches deviceType or is a wild card - any
219 if aTransition.deviceType != deviceType && aTransition.deviceType != any {
220 continue
221 }
khenaidoo0a822f92019-05-08 15:15:57 -0400222 tempHandler, exactStateMatch = getHandler(pState, cState, &aTransition)
khenaidoob9203542018-09-17 22:56:37 -0400223 if tempHandler != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400224 if exactStateMatch && aTransition.deviceType == deviceType {
khenaidoob9203542018-09-17 22:56:37 -0400225 return tempHandler
khenaidoo0a822f92019-05-08 15:15:57 -0400226 } else if exactStateMatch {
227 currentMatch = tempHandler
228 stateMatchFound = true
229 } else if currentMatch == nil && !stateMatchFound {
230 currentMatch = tempHandler
khenaidoob9203542018-09-17 22:56:37 -0400231 }
232 }
233 }
234 return currentMatch
235}