blob: e65c3967840440442f3aa044616470accadf59eb [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 */
npujar1d86a522019-11-14 17:11:16 +053016
Kent Hagerman6031aad2020-07-29 16:36:33 -040017package state
khenaidoob9203542018-09-17 22:56:37 -040018
19import (
npujar467fe752020-01-16 20:17:45 +053020 "context"
Maninderdfadc982020-10-28 14:04:33 +053021 "github.com/opencord/voltha-lib-go/v4/pkg/log"
22 "github.com/opencord/voltha-protos/v4/go/voltha"
Himani Chawla2ba1c9c2020-10-07 13:19:03 +053023 "reflect"
24 "runtime"
khenaidoob9203542018-09-17 22:56:37 -040025)
26
Kent Hagerman2b216042020-04-03 18:28:56 -040027// deviceType mentions type of device like parent, child
28type deviceType int32
khenaidoob9203542018-09-17 22:56:37 -040029
30const (
Kent Hagerman2b216042020-04-03 18:28:56 -040031 parent deviceType = 0
32 child deviceType = 1
33 any deviceType = 2
khenaidoob9203542018-09-17 22:56:37 -040034)
35
Himani Chawla2ba1c9c2020-10-07 13:19:03 +053036type matchResult uint16
khenaidoo442e7c72020-03-10 16:13:48 -040037
38const (
Kent Hagerman2b216042020-04-03 18:28:56 -040039 noMatch matchResult = iota // current state has not match in the transition table
khenaidoo442e7c72020-03-10 16:13:48 -040040 currWildcardMatch // current state matches the wildcard *_UNKNOWN state in the transition table
41 currStateOnlyMatch // current state matches the current state and previous state matches the wildcard in the transition table
42 currPrevStateMatch // both current and previous states match in the transition table
43)
44
45// match is used to keep the current match states
46type match struct {
Himani Chawla2ba1c9c2020-10-07 13:19:03 +053047 admin, oper, conn, transient matchResult
khenaidoo442e7c72020-03-10 16:13:48 -040048}
49
50// toInt returns an integer representing the matching level of the match (the larger the number the better)
51func (m *match) toInt() int {
Himani Chawla2ba1c9c2020-10-07 13:19:03 +053052 return int(m.transient<<8 | m.admin<<4 | m.oper<<2 | m.conn)
khenaidoo442e7c72020-03-10 16:13:48 -040053}
54
55// isExactMatch returns true if match is an exact match
56func (m *match) isExactMatch() bool {
Himani Chawla2ba1c9c2020-10-07 13:19:03 +053057 return m.admin == currPrevStateMatch && m.oper == currPrevStateMatch && m.conn == currPrevStateMatch &&
58 m.transient == currPrevStateMatch
khenaidoo442e7c72020-03-10 16:13:48 -040059}
60
61// isBetterMatch returns true if newMatch is a worse match
62func (m *match) isBetterMatch(newMatch *match) bool {
63 return m.toInt() > newMatch.toInt()
64}
65
Kent Hagerman2b216042020-04-03 18:28:56 -040066// deviceState has admin, operational and connection status of device
67type deviceState struct {
serkant.uluderya2ae470f2020-01-21 11:13:09 -080068 Admin voltha.AdminState_Types
69 Connection voltha.ConnectStatus_Types
70 Operational voltha.OperStatus_Types
Himani Chawla2ba1c9c2020-10-07 13:19:03 +053071 Transient voltha.DeviceTransientState_Types
khenaidoob9203542018-09-17 22:56:37 -040072}
73
Kent Hagerman6031aad2020-07-29 16:36:33 -040074// transitionHandler function type which takes the current and previous device info as input parameter
75type transitionHandler func(context.Context, *voltha.Device) error
khenaidoob9203542018-09-17 22:56:37 -040076
Kent Hagerman6031aad2020-07-29 16:36:33 -040077// transition represent transition related attributes
78type transition struct {
Kent Hagerman2b216042020-04-03 18:28:56 -040079 deviceType deviceType
80 previousState deviceState
81 currentState deviceState
Kent Hagerman6031aad2020-07-29 16:36:33 -040082 handlers []transitionHandler
khenaidoob9203542018-09-17 22:56:37 -040083}
84
npujar1d86a522019-11-14 17:11:16 +053085// TransitionMap represent map of transitions and device manager
khenaidoob9203542018-09-17 22:56:37 -040086type TransitionMap struct {
Kent Hagerman6031aad2020-07-29 16:36:33 -040087 transitions []transition
88 dMgr DeviceManager
89}
90
91// DeviceManager represents a generic device manager
92type DeviceManager interface {
93 NotifyInvalidTransition(ctx context.Context, curr *voltha.Device) error
94 CreateLogicalDevice(ctx context.Context, curr *voltha.Device) error
95 SetupUNILogicalPorts(ctx context.Context, curr *voltha.Device) error
96 DeleteLogicalDevice(ctx context.Context, curr *voltha.Device) error
97 DeleteLogicalPorts(ctx context.Context, curr *voltha.Device) error
98 DeleteAllChildDevices(ctx context.Context, curr *voltha.Device) error
99 RunPostDeviceDelete(ctx context.Context, curr *voltha.Device) error
100 ChildDeviceLost(ctx context.Context, curr *voltha.Device) error
101 DeleteAllLogicalPorts(ctx context.Context, curr *voltha.Device) error
102 DeleteAllDeviceFlows(ctx context.Context, curr *voltha.Device) error
khenaidoob9203542018-09-17 22:56:37 -0400103}
104
npujar1d86a522019-11-14 17:11:16 +0530105// NewTransitionMap creates transition map
Kent Hagerman6031aad2020-07-29 16:36:33 -0400106func NewTransitionMap(dMgr DeviceManager) *TransitionMap {
khenaidoob9203542018-09-17 22:56:37 -0400107 var transitionMap TransitionMap
khenaidoo0a822f92019-05-08 15:15:57 -0400108 transitionMap.dMgr = dMgr
Kent Hagerman6031aad2020-07-29 16:36:33 -0400109 transitionMap.transitions = make([]transition, 0)
khenaidoo442e7c72020-03-10 16:13:48 -0400110 transitionMap.transitions = append(
111 transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400112 transition{
khenaidoob9203542018-09-17 22:56:37 -0400113 deviceType: parent,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530114 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
115 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400116 handlers: []transitionHandler{dMgr.CreateLogicalDevice}})
khenaidoo0a822f92019-05-08 15:15:57 -0400117 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400118 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400119 deviceType: child,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530120 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED, Transient: voltha.DeviceTransientState_NONE},
121 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400122 handlers: []transitionHandler{}})
khenaidoo442e7c72020-03-10 16:13:48 -0400123 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400124 transition{
khenaidoo442e7c72020-03-10 16:13:48 -0400125 deviceType: child,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530126 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED, Transient: voltha.DeviceTransientState_NONE},
127 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400128 handlers: []transitionHandler{dMgr.SetupUNILogicalPorts}})
khenaidoob9203542018-09-17 22:56:37 -0400129 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400130 transition{
khenaidoob9203542018-09-17 22:56:37 -0400131 deviceType: child,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530132 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
133 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400134 handlers: []transitionHandler{}})
khenaidoo442e7c72020-03-10 16:13:48 -0400135 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400136 transition{
khenaidoo442e7c72020-03-10 16:13:48 -0400137 deviceType: child,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530138 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
139 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400140 handlers: []transitionHandler{dMgr.SetupUNILogicalPorts}})
khenaidoob9203542018-09-17 22:56:37 -0400141 transitionMap.transitions = append(transitionMap.transitions,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530142 transition{ //DELETE PRE PROVISIONED State device forcefully
khenaidoo4554f7c2019-05-29 22:13:15 -0400143 deviceType: any,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530144 previousState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
145 currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_FORCE_DELETING},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400146 handlers: []transitionHandler{dMgr.RunPostDeviceDelete}})
khenaidoo4554f7c2019-05-29 22:13:15 -0400147 transitionMap.transitions = append(transitionMap.transitions,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530148 transition{ // DELETE PRE PROVISIONED State device no force option set
149 deviceType: any,
150 previousState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
151 currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE},
152 handlers: []transitionHandler{dMgr.RunPostDeviceDelete}})
153 transitionMap.transitions = append(transitionMap.transitions,
154 transition{ //DELETE device forcefully
khenaidoo4d4802d2018-10-04 21:59:49 -0400155 deviceType: parent,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530156 previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
157 currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_FORCE_DELETING},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400158 handlers: []transitionHandler{dMgr.DeleteAllLogicalPorts, dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.RunPostDeviceDelete}})
khenaidoo0a822f92019-05-08 15:15:57 -0400159 transitionMap.transitions = append(transitionMap.transitions,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530160 transition{ //DELETE device after adapter response
161 deviceType: parent,
162 previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
163 currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE},
164 handlers: []transitionHandler{dMgr.DeleteAllLogicalPorts, dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.RunPostDeviceDelete}})
165 transitionMap.transitions = append(transitionMap.transitions,
166 transition{ //DELETE no operation transition
167 deviceType: parent,
168 previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
169 currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_DELETING_FROM_ADAPTER},
170 handlers: []transitionHandler{}})
171 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400172 transition{
Girish Gowdra408cd962020-03-11 14:31:31 -0700173 deviceType: parent,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530174 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_NONE},
175 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400176 handlers: []transitionHandler{dMgr.DeleteAllLogicalPorts, dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.DeleteAllDeviceFlows}})
Girish Gowdra408cd962020-03-11 14:31:31 -0700177 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400178 transition{
Girish Gowdra408cd962020-03-11 14:31:31 -0700179 deviceType: parent,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530180 previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
181 currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400182 handlers: []transitionHandler{dMgr.DeleteAllLogicalPorts, dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.DeleteAllDeviceFlows}})
Chaitrashree G S7849b322020-03-29 19:25:49 -0400183 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400184 transition{
Chaitrashree G S7849b322020-03-29 19:25:49 -0400185 deviceType: parent,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530186 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
187 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400188 handlers: []transitionHandler{dMgr.CreateLogicalDevice}})
Girish Gowdra408cd962020-03-11 14:31:31 -0700189 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400190 transition{
Chaitrashree G S7849b322020-03-29 19:25:49 -0400191 deviceType: parent,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530192 previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
193 currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400194 handlers: []transitionHandler{dMgr.CreateLogicalDevice}})
Chaitrashree G S7849b322020-03-29 19:25:49 -0400195 transitionMap.transitions = append(transitionMap.transitions,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530196 transition{ //DELETE force case
khenaidoo0a822f92019-05-08 15:15:57 -0400197 deviceType: child,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530198 previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
199 currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_FORCE_DELETING},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400200 handlers: []transitionHandler{dMgr.ChildDeviceLost, dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
Chaitrashree G S543df3e2020-02-24 22:36:54 -0500201 transitionMap.transitions = append(transitionMap.transitions,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530202 transition{ //DELETE after adapter response case
Chaitrashree G S543df3e2020-02-24 22:36:54 -0500203 deviceType: child,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530204 previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
205 currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_DELETING_POST_ADAPTER_RESPONSE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400206 handlers: []transitionHandler{dMgr.ChildDeviceLost, dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
khenaidoob9203542018-09-17 22:56:37 -0400207 transitionMap.transitions = append(transitionMap.transitions,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530208 transition{ //DELETE wait for adapter response(no operation)
209 deviceType: child,
210 previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_ANY},
211 currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_DELETING_FROM_ADAPTER},
212 handlers: []transitionHandler{}})
213 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400214 transition{
khenaidoob9203542018-09-17 22:56:37 -0400215 deviceType: any,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530216 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_NONE},
217 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400218 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400219 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400220 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400221 deviceType: any,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530222 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
223 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400224 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400225 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400226 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400227 deviceType: any,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530228 previousState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
229 currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400230 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400231 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400232 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400233 deviceType: any,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530234 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
235 currentState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400236 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400237 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400238 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400239 deviceType: any,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530240 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
241 currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400242 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400243 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400244 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400245 deviceType: parent,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530246 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE, Transient: voltha.DeviceTransientState_NONE},
247 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400248 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400249 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400250 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400251 deviceType: any,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530252 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING, Transient: voltha.DeviceTransientState_NONE},
253 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400254 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400255 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400256 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400257 deviceType: any,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530258 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
259 currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400260 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400261 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400262 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400263 deviceType: child,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530264 previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
265 currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400266 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400267 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400268 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400269 deviceType: any,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530270 previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
271 currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400272 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400273 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400274 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400275 deviceType: any,
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530276 previousState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
277 currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN, Transient: voltha.DeviceTransientState_NONE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400278 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoob9203542018-09-17 22:56:37 -0400279
280 return &transitionMap
281}
282
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530283func getDeviceStates(device *voltha.Device, transientState voltha.DeviceTransientState_Types) deviceState {
284 return deviceState{Admin: device.AdminState, Connection: device.ConnectStatus, Operational: device.OperStatus,
285 Transient: transientState}
khenaidoob9203542018-09-17 22:56:37 -0400286}
287
288// isMatched matches a state transition. It returns whether there is a match and if there is whether it is an exact match
Kent Hagerman6031aad2020-07-29 16:36:33 -0400289func getHandler(previous deviceState, current deviceState, transition *transition) ([]transitionHandler, *match) {
khenaidoo442e7c72020-03-10 16:13:48 -0400290 m := &match{}
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530291 var waitForOtherStatesMatch bool
khenaidoob9203542018-09-17 22:56:37 -0400292 // Do we have an exact match?
Kent Hagerman6031aad2020-07-29 16:36:33 -0400293 if previous == transition.previousState && current == transition.currentState {
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530294 return transition.handlers, &match{admin: currPrevStateMatch, oper: currPrevStateMatch, conn: currPrevStateMatch,
295 transient: currPrevStateMatch}
296 }
297 // Do we have transient state match?
298 if current.Transient == transition.currentState.Transient && transition.currentState.Transient != voltha.DeviceTransientState_ANY {
299 if previous.Transient == transition.previousState.Transient || transition.previousState.Transient == voltha.DeviceTransientState_ANY {
300 m.transient = currPrevStateMatch
301 } else {
302 m.transient = currStateOnlyMatch
303 }
304 } else if current.Transient == transition.currentState.Transient && transition.currentState.Transient == voltha.DeviceTransientState_ANY {
305 if previous.Transient == transition.previousState.Transient || transition.previousState.Transient == voltha.DeviceTransientState_ANY {
306 m.transient = currWildcardMatch
307 }
308 }
309 if m.transient == noMatch {
310 return nil, m
khenaidoob9203542018-09-17 22:56:37 -0400311 }
khenaidoo0a822f92019-05-08 15:15:57 -0400312
khenaidoo442e7c72020-03-10 16:13:48 -0400313 // Do we have Admin state match?
314 if current.Admin == transition.currentState.Admin && transition.currentState.Admin != voltha.AdminState_UNKNOWN {
315 if previous.Admin == transition.previousState.Admin {
316 m.admin = currPrevStateMatch
317 } else if transition.previousState.Admin == voltha.AdminState_UNKNOWN {
318 m.admin = currStateOnlyMatch
319 }
320 } else if current.Admin == transition.currentState.Admin && transition.currentState.Admin == voltha.AdminState_UNKNOWN {
321 if previous.Admin == transition.previousState.Admin || transition.previousState.Admin == voltha.AdminState_UNKNOWN {
322 m.admin = currWildcardMatch
323 }
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530324 } else if transition.previousState.Admin == voltha.AdminState_UNKNOWN && transition.currentState.Admin == voltha.AdminState_UNKNOWN {
325 // Will only be the case of DELETION currently.(to allow only transient match, we can avoid this check if
326 // we can allow wild card in admin state)
327 waitForOtherStatesMatch = true
khenaidoo442e7c72020-03-10 16:13:48 -0400328 }
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530329 if !waitForOtherStatesMatch && m.admin == noMatch {
khenaidoo442e7c72020-03-10 16:13:48 -0400330 return nil, m
khenaidoo0a822f92019-05-08 15:15:57 -0400331 }
khenaidoo442e7c72020-03-10 16:13:48 -0400332 // Do we have an operational state match?
333 if current.Operational == transition.currentState.Operational && transition.previousState.Operational != voltha.OperStatus_UNKNOWN {
334 if previous.Operational == transition.previousState.Operational || transition.previousState.Operational == voltha.OperStatus_UNKNOWN {
335 m.oper = currPrevStateMatch
336 } else {
337 m.oper = currStateOnlyMatch
338 }
339 } else if current.Operational == transition.currentState.Operational && transition.previousState.Operational == voltha.OperStatus_UNKNOWN {
340 if previous.Operational == transition.previousState.Operational || transition.previousState.Operational == voltha.OperStatus_UNKNOWN {
341 m.oper = currWildcardMatch
khenaidoob9203542018-09-17 22:56:37 -0400342 }
343 }
khenaidoo442e7c72020-03-10 16:13:48 -0400344
345 // Do we have an connection state match?
346 if current.Connection == transition.currentState.Connection && transition.previousState.Connection != voltha.ConnectStatus_UNKNOWN {
347 if previous.Connection == transition.previousState.Connection || transition.previousState.Connection == voltha.ConnectStatus_UNKNOWN {
348 m.conn = currPrevStateMatch
349 } else {
350 m.conn = currStateOnlyMatch
351 }
352 } else if current.Connection == transition.currentState.Connection && transition.previousState.Connection == voltha.ConnectStatus_UNKNOWN {
353 if previous.Connection == transition.previousState.Connection || transition.previousState.Connection == voltha.ConnectStatus_UNKNOWN {
354 m.conn = currWildcardMatch
khenaidoob9203542018-09-17 22:56:37 -0400355 }
356 }
khenaidoo442e7c72020-03-10 16:13:48 -0400357 return transition.handlers, m
khenaidoob9203542018-09-17 22:56:37 -0400358}
359
Kent Hagerman6031aad2020-07-29 16:36:33 -0400360// getTransitionHandler returns transition handler & a flag that's set if the transition is invalid
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530361func (tMap *TransitionMap) getTransitionHandler(ctx context.Context, cDevice, pDevice *voltha.Device,
362 cTransientState, pTransientState voltha.DeviceTransientState_Types) []transitionHandler {
khenaidoob9203542018-09-17 22:56:37 -0400363 //1. Get the previous and current set of states
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530364 cState := getDeviceStates(cDevice, cTransientState)
365 pState := getDeviceStates(pDevice, pTransientState)
khenaidoo442e7c72020-03-10 16:13:48 -0400366
367 // Do nothing is there are no states change
Kent Hagerman6031aad2020-07-29 16:36:33 -0400368 if pState == cState {
khenaidoo442e7c72020-03-10 16:13:48 -0400369 return nil
370 }
371
Rohan Agrawal31f21802020-06-12 05:38:46 +0000372 //logger.Infow(ctx, "deviceType", log.Fields{"device": pDevice})
khenaidoob9203542018-09-17 22:56:37 -0400373 deviceType := parent
Kent Hagerman6031aad2020-07-29 16:36:33 -0400374 if !cDevice.Root {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000375 logger.Info(ctx, "device is child")
khenaidoob9203542018-09-17 22:56:37 -0400376 deviceType = child
377 }
Kent Hagerman6031aad2020-07-29 16:36:33 -0400378 logger.Infof(ctx, "deviceType:%d-deviceId:%s-previous:%v-current:%v", deviceType, cDevice.Id, pState, cState)
khenaidoob9203542018-09-17 22:56:37 -0400379
380 //2. Go over transition array to get the right transition
Kent Hagerman6031aad2020-07-29 16:36:33 -0400381 var currentMatch []transitionHandler
382 var tempHandler []transitionHandler
khenaidoo442e7c72020-03-10 16:13:48 -0400383 var m *match
384 bestMatch := &match{}
khenaidoob9203542018-09-17 22:56:37 -0400385 for _, aTransition := range tMap.transitions {
386 // consider transition only if it matches deviceType or is a wild card - any
387 if aTransition.deviceType != deviceType && aTransition.deviceType != any {
388 continue
389 }
khenaidoo442e7c72020-03-10 16:13:48 -0400390 tempHandler, m = getHandler(pState, cState, &aTransition)
khenaidoob9203542018-09-17 22:56:37 -0400391 if tempHandler != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400392 if m.isExactMatch() && aTransition.deviceType == deviceType {
khenaidoob9203542018-09-17 22:56:37 -0400393 return tempHandler
khenaidoo442e7c72020-03-10 16:13:48 -0400394 } else if m.isExactMatch() || m.isBetterMatch(bestMatch) {
khenaidoo0a822f92019-05-08 15:15:57 -0400395 currentMatch = tempHandler
khenaidoo442e7c72020-03-10 16:13:48 -0400396 bestMatch = m
khenaidoob9203542018-09-17 22:56:37 -0400397 }
398 }
399 }
400 return currentMatch
401}
Kent Hagerman6031aad2020-07-29 16:36:33 -0400402
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530403func (tMap *TransitionMap) ProcessTransition(ctx context.Context, device, prevDevice *voltha.Device,
404 deviceTransientState, prevDeviceTransientState voltha.DeviceTransientState_Types) error {
Kent Hagerman6031aad2020-07-29 16:36:33 -0400405 // This will be triggered on every state update
406 logger.Debugw(ctx, "state-transition", log.Fields{
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530407 "device": device.Id,
408 "prev-admin-state": prevDevice.AdminState,
409 "prev-oper-state": prevDevice.OperStatus,
410 "prev-conn-state": prevDevice.ConnectStatus,
411 "curr-admin-state": device.AdminState,
412 "curr-oper-state": device.OperStatus,
413 "curr-conn-state": device.ConnectStatus,
414 "curr-transient-state": deviceTransientState,
415 "prev-transient-state": prevDeviceTransientState,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400416 })
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530417 handlers := tMap.getTransitionHandler(ctx, device, prevDevice, deviceTransientState, prevDeviceTransientState)
Kent Hagerman6031aad2020-07-29 16:36:33 -0400418 if handlers == nil {
419 logger.Debugw(ctx, "no-op-transition", log.Fields{"deviceId": device.Id})
420 return nil
421 }
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530422 logger.Debugw(ctx, "handler-found", log.Fields{"num-expectedHandlers": len(handlers), "isParent": device.Root,
423 "current-data": device, "previous-data": prevDevice})
Kent Hagerman6031aad2020-07-29 16:36:33 -0400424 for _, handler := range handlers {
425 logger.Debugw(ctx, "running-handler", log.Fields{"handler": funcName(handler)})
426 if err := handler(ctx, device); err != nil {
427 logger.Warnw(ctx, "handler-failed", log.Fields{"handler": funcName(handler), "error": err})
428 return err
429 }
430 }
431 return nil
432}
433
434func funcName(f interface{}) string {
435 return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
436}