blob: 81ac69de5a690f4fdd6456106c70c3f86e5f4738 [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"
Kent Hagerman6031aad2020-07-29 16:36:33 -040021 "reflect"
22 "runtime"
23
Maninderdfadc982020-10-28 14:04:33 +053024 "github.com/opencord/voltha-lib-go/v4/pkg/log"
25 "github.com/opencord/voltha-protos/v4/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040026)
27
Kent Hagerman2b216042020-04-03 18:28:56 -040028// deviceType mentions type of device like parent, child
29type deviceType int32
khenaidoob9203542018-09-17 22:56:37 -040030
31const (
Kent Hagerman2b216042020-04-03 18:28:56 -040032 parent deviceType = 0
33 child deviceType = 1
34 any deviceType = 2
khenaidoob9203542018-09-17 22:56:37 -040035)
36
Kent Hagerman2b216042020-04-03 18:28:56 -040037type matchResult uint8
khenaidoo442e7c72020-03-10 16:13:48 -040038
39const (
Kent Hagerman2b216042020-04-03 18:28:56 -040040 noMatch matchResult = iota // current state has not match in the transition table
khenaidoo442e7c72020-03-10 16:13:48 -040041 currWildcardMatch // current state matches the wildcard *_UNKNOWN state in the transition table
42 currStateOnlyMatch // current state matches the current state and previous state matches the wildcard in the transition table
43 currPrevStateMatch // both current and previous states match in the transition table
44)
45
46// match is used to keep the current match states
47type match struct {
Kent Hagerman2b216042020-04-03 18:28:56 -040048 admin, oper, conn matchResult
khenaidoo442e7c72020-03-10 16:13:48 -040049}
50
51// toInt returns an integer representing the matching level of the match (the larger the number the better)
52func (m *match) toInt() int {
53 return int(m.admin<<4 | m.oper<<2 | m.conn)
54}
55
56// isExactMatch returns true if match is an exact match
57func (m *match) isExactMatch() bool {
58 return m.admin == currPrevStateMatch && m.oper == currPrevStateMatch && m.conn == currPrevStateMatch
59}
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
khenaidoob9203542018-09-17 22:56:37 -040071}
72
Kent Hagerman6031aad2020-07-29 16:36:33 -040073// transitionHandler function type which takes the current and previous device info as input parameter
74type transitionHandler func(context.Context, *voltha.Device) error
khenaidoob9203542018-09-17 22:56:37 -040075
Kent Hagerman6031aad2020-07-29 16:36:33 -040076// transition represent transition related attributes
77type transition struct {
Kent Hagerman2b216042020-04-03 18:28:56 -040078 deviceType deviceType
79 previousState deviceState
80 currentState deviceState
Kent Hagerman6031aad2020-07-29 16:36:33 -040081 handlers []transitionHandler
khenaidoob9203542018-09-17 22:56:37 -040082}
83
npujar1d86a522019-11-14 17:11:16 +053084// TransitionMap represent map of transitions and device manager
khenaidoob9203542018-09-17 22:56:37 -040085type TransitionMap struct {
Kent Hagerman6031aad2020-07-29 16:36:33 -040086 transitions []transition
87 dMgr DeviceManager
88}
89
90// DeviceManager represents a generic device manager
91type DeviceManager interface {
92 NotifyInvalidTransition(ctx context.Context, curr *voltha.Device) error
93 CreateLogicalDevice(ctx context.Context, curr *voltha.Device) error
94 SetupUNILogicalPorts(ctx context.Context, curr *voltha.Device) error
95 DeleteLogicalDevice(ctx context.Context, curr *voltha.Device) error
96 DeleteLogicalPorts(ctx context.Context, curr *voltha.Device) error
97 DeleteAllChildDevices(ctx context.Context, curr *voltha.Device) error
98 RunPostDeviceDelete(ctx context.Context, curr *voltha.Device) error
99 ChildDeviceLost(ctx context.Context, curr *voltha.Device) error
100 DeleteAllLogicalPorts(ctx context.Context, curr *voltha.Device) error
101 DeleteAllDeviceFlows(ctx context.Context, curr *voltha.Device) error
khenaidoob9203542018-09-17 22:56:37 -0400102}
103
npujar1d86a522019-11-14 17:11:16 +0530104// NewTransitionMap creates transition map
Kent Hagerman6031aad2020-07-29 16:36:33 -0400105func NewTransitionMap(dMgr DeviceManager) *TransitionMap {
khenaidoob9203542018-09-17 22:56:37 -0400106 var transitionMap TransitionMap
khenaidoo0a822f92019-05-08 15:15:57 -0400107 transitionMap.dMgr = dMgr
Kent Hagerman6031aad2020-07-29 16:36:33 -0400108 transitionMap.transitions = make([]transition, 0)
khenaidoo442e7c72020-03-10 16:13:48 -0400109 transitionMap.transitions = append(
110 transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400111 transition{
khenaidoob9203542018-09-17 22:56:37 -0400112 deviceType: parent,
Kent Hagerman2b216042020-04-03 18:28:56 -0400113 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
114 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400115 handlers: []transitionHandler{dMgr.CreateLogicalDevice}})
khenaidoo0a822f92019-05-08 15:15:57 -0400116 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400117 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400118 deviceType: child,
Kent Hagerman2b216042020-04-03 18:28:56 -0400119 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED},
120 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400121 handlers: []transitionHandler{}})
khenaidoo442e7c72020-03-10 16:13:48 -0400122 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400123 transition{
khenaidoo442e7c72020-03-10 16:13:48 -0400124 deviceType: child,
Kent Hagerman2b216042020-04-03 18:28:56 -0400125 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED},
126 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400127 handlers: []transitionHandler{dMgr.SetupUNILogicalPorts}})
khenaidoob9203542018-09-17 22:56:37 -0400128 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400129 transition{
khenaidoob9203542018-09-17 22:56:37 -0400130 deviceType: child,
Kent Hagerman2b216042020-04-03 18:28:56 -0400131 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_DISCOVERED},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400133 handlers: []transitionHandler{}})
khenaidoo442e7c72020-03-10 16:13:48 -0400134 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400135 transition{
khenaidoo442e7c72020-03-10 16:13:48 -0400136 deviceType: child,
Kent Hagerman2b216042020-04-03 18:28:56 -0400137 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_ACTIVE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400139 handlers: []transitionHandler{dMgr.SetupUNILogicalPorts}})
khenaidoob9203542018-09-17 22:56:37 -0400140 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400141 transition{
khenaidoo4554f7c2019-05-29 22:13:15 -0400142 deviceType: any,
Kent Hagerman2b216042020-04-03 18:28:56 -0400143 previousState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
144 currentState: deviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400145 handlers: []transitionHandler{dMgr.RunPostDeviceDelete}})
khenaidoo4554f7c2019-05-29 22:13:15 -0400146 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400147 transition{
khenaidoo4d4802d2018-10-04 21:59:49 -0400148 deviceType: parent,
Kent Hagerman2b216042020-04-03 18:28:56 -0400149 previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
150 currentState: deviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400151 handlers: []transitionHandler{dMgr.DeleteAllLogicalPorts, dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.RunPostDeviceDelete}})
khenaidoo0a822f92019-05-08 15:15:57 -0400152 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400153 transition{
Girish Gowdra408cd962020-03-11 14:31:31 -0700154 deviceType: parent,
Kent Hagerman2b216042020-04-03 18:28:56 -0400155 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE},
156 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400157 handlers: []transitionHandler{dMgr.DeleteAllLogicalPorts, dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.DeleteAllDeviceFlows}})
Girish Gowdra408cd962020-03-11 14:31:31 -0700158 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400159 transition{
Girish Gowdra408cd962020-03-11 14:31:31 -0700160 deviceType: parent,
Kent Hagerman2b216042020-04-03 18:28:56 -0400161 previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN},
162 currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400163 handlers: []transitionHandler{dMgr.DeleteAllLogicalPorts, dMgr.DeleteAllChildDevices, dMgr.DeleteLogicalDevice, dMgr.DeleteAllDeviceFlows}})
Chaitrashree G S7849b322020-03-29 19:25:49 -0400164 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400165 transition{
Chaitrashree G S7849b322020-03-29 19:25:49 -0400166 deviceType: parent,
Kent Hagerman2b216042020-04-03 18:28:56 -0400167 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN},
168 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400169 handlers: []transitionHandler{dMgr.CreateLogicalDevice}})
Girish Gowdra408cd962020-03-11 14:31:31 -0700170 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400171 transition{
Chaitrashree G S7849b322020-03-29 19:25:49 -0400172 deviceType: parent,
Kent Hagerman2b216042020-04-03 18:28:56 -0400173 previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN},
174 currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400175 handlers: []transitionHandler{dMgr.CreateLogicalDevice}})
Chaitrashree G S7849b322020-03-29 19:25:49 -0400176 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400177 transition{
khenaidoo0a822f92019-05-08 15:15:57 -0400178 deviceType: child,
Kent Hagerman2b216042020-04-03 18:28:56 -0400179 previousState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
180 currentState: deviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400181 handlers: []transitionHandler{dMgr.ChildDeviceLost, dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
Chaitrashree G S543df3e2020-02-24 22:36:54 -0500182 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400183 transition{
Chaitrashree G S543df3e2020-02-24 22:36:54 -0500184 deviceType: child,
Kent Hagerman2b216042020-04-03 18:28:56 -0400185 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
186 currentState: deviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400187 handlers: []transitionHandler{dMgr.ChildDeviceLost, dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
khenaidoob9203542018-09-17 22:56:37 -0400188 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400189 transition{
khenaidoob9203542018-09-17 22:56:37 -0400190 deviceType: any,
Kent Hagerman2b216042020-04-03 18:28:56 -0400191 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
192 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400193 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400194 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400195 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400196 deviceType: any,
Kent Hagerman2b216042020-04-03 18:28:56 -0400197 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
198 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400199 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400200 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400201 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400202 deviceType: any,
Kent Hagerman2b216042020-04-03 18:28:56 -0400203 previousState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
204 currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400205 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400206 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400207 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400208 deviceType: any,
Kent Hagerman2b216042020-04-03 18:28:56 -0400209 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
210 currentState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400211 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400212 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400213 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400214 deviceType: any,
Kent Hagerman2b216042020-04-03 18:28:56 -0400215 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
216 currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400217 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400218 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400219 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400220 deviceType: parent,
Kent Hagerman2b216042020-04-03 18:28:56 -0400221 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
222 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400223 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400224 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400225 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400226 deviceType: any,
Kent Hagerman2b216042020-04-03 18:28:56 -0400227 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
228 currentState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400229 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400230 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400231 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400232 deviceType: any,
Kent Hagerman2b216042020-04-03 18:28:56 -0400233 previousState: deviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
234 currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400235 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400236 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400237 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400238 deviceType: child,
Kent Hagerman2b216042020-04-03 18:28:56 -0400239 previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
240 currentState: deviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400241 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400242 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400243 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400244 deviceType: any,
Kent Hagerman2b216042020-04-03 18:28:56 -0400245 previousState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
246 currentState: deviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400247 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoo59ef7be2019-06-21 12:40:28 -0400248 transitionMap.transitions = append(transitionMap.transitions,
Kent Hagerman6031aad2020-07-29 16:36:33 -0400249 transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400250 deviceType: any,
Kent Hagerman2b216042020-04-03 18:28:56 -0400251 previousState: deviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
252 currentState: deviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Kent Hagerman6031aad2020-07-29 16:36:33 -0400253 handlers: []transitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoob9203542018-09-17 22:56:37 -0400254
255 return &transitionMap
256}
257
Kent Hagerman6031aad2020-07-29 16:36:33 -0400258func getDeviceStates(device *voltha.Device) deviceState {
259 return deviceState{Admin: device.AdminState, Connection: device.ConnectStatus, Operational: device.OperStatus}
khenaidoob9203542018-09-17 22:56:37 -0400260}
261
262// 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 -0400263func getHandler(previous deviceState, current deviceState, transition *transition) ([]transitionHandler, *match) {
khenaidoo442e7c72020-03-10 16:13:48 -0400264 m := &match{}
khenaidoob9203542018-09-17 22:56:37 -0400265 // Do we have an exact match?
Kent Hagerman6031aad2020-07-29 16:36:33 -0400266 if previous == transition.previousState && current == transition.currentState {
khenaidoo442e7c72020-03-10 16:13:48 -0400267 return transition.handlers, &match{admin: currPrevStateMatch, oper: currPrevStateMatch, conn: currPrevStateMatch}
khenaidoob9203542018-09-17 22:56:37 -0400268 }
khenaidoo0a822f92019-05-08 15:15:57 -0400269
khenaidoo442e7c72020-03-10 16:13:48 -0400270 // Do we have Admin state match?
271 if current.Admin == transition.currentState.Admin && transition.currentState.Admin != voltha.AdminState_UNKNOWN {
272 if previous.Admin == transition.previousState.Admin {
273 m.admin = currPrevStateMatch
274 } else if transition.previousState.Admin == voltha.AdminState_UNKNOWN {
275 m.admin = currStateOnlyMatch
276 }
277 } else if current.Admin == transition.currentState.Admin && transition.currentState.Admin == voltha.AdminState_UNKNOWN {
278 if previous.Admin == transition.previousState.Admin || transition.previousState.Admin == voltha.AdminState_UNKNOWN {
279 m.admin = currWildcardMatch
280 }
281 }
282 if m.admin == noMatch {
283 // invalid transition - need to match on current admin state
284 return nil, m
khenaidoo0a822f92019-05-08 15:15:57 -0400285 }
286
khenaidoo442e7c72020-03-10 16:13:48 -0400287 // Do we have an operational state match?
288 if current.Operational == transition.currentState.Operational && transition.previousState.Operational != voltha.OperStatus_UNKNOWN {
289 if previous.Operational == transition.previousState.Operational || transition.previousState.Operational == voltha.OperStatus_UNKNOWN {
290 m.oper = currPrevStateMatch
291 } else {
292 m.oper = currStateOnlyMatch
293 }
294 } else if current.Operational == transition.currentState.Operational && transition.previousState.Operational == voltha.OperStatus_UNKNOWN {
295 if previous.Operational == transition.previousState.Operational || transition.previousState.Operational == voltha.OperStatus_UNKNOWN {
296 m.oper = currWildcardMatch
khenaidoob9203542018-09-17 22:56:37 -0400297 }
298 }
khenaidoo442e7c72020-03-10 16:13:48 -0400299
300 // Do we have an connection state match?
301 if current.Connection == transition.currentState.Connection && transition.previousState.Connection != voltha.ConnectStatus_UNKNOWN {
302 if previous.Connection == transition.previousState.Connection || transition.previousState.Connection == voltha.ConnectStatus_UNKNOWN {
303 m.conn = currPrevStateMatch
304 } else {
305 m.conn = currStateOnlyMatch
306 }
307 } else if current.Connection == transition.currentState.Connection && transition.previousState.Connection == voltha.ConnectStatus_UNKNOWN {
308 if previous.Connection == transition.previousState.Connection || transition.previousState.Connection == voltha.ConnectStatus_UNKNOWN {
309 m.conn = currWildcardMatch
khenaidoob9203542018-09-17 22:56:37 -0400310 }
311 }
khenaidoo442e7c72020-03-10 16:13:48 -0400312
313 return transition.handlers, m
khenaidoob9203542018-09-17 22:56:37 -0400314}
315
Kent Hagerman6031aad2020-07-29 16:36:33 -0400316// getTransitionHandler returns transition handler & a flag that's set if the transition is invalid
317func (tMap *TransitionMap) getTransitionHandler(ctx context.Context, cDevice, pDevice *voltha.Device) []transitionHandler {
khenaidoob9203542018-09-17 22:56:37 -0400318 //1. Get the previous and current set of states
Kent Hagerman6031aad2020-07-29 16:36:33 -0400319 cState := getDeviceStates(cDevice)
320 pState := getDeviceStates(pDevice)
khenaidoo442e7c72020-03-10 16:13:48 -0400321
322 // Do nothing is there are no states change
Kent Hagerman6031aad2020-07-29 16:36:33 -0400323 if pState == cState {
khenaidoo442e7c72020-03-10 16:13:48 -0400324 return nil
325 }
326
Rohan Agrawal31f21802020-06-12 05:38:46 +0000327 //logger.Infow(ctx, "deviceType", log.Fields{"device": pDevice})
khenaidoob9203542018-09-17 22:56:37 -0400328 deviceType := parent
Kent Hagerman6031aad2020-07-29 16:36:33 -0400329 if !cDevice.Root {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000330 logger.Info(ctx, "device is child")
khenaidoob9203542018-09-17 22:56:37 -0400331 deviceType = child
332 }
Kent Hagerman6031aad2020-07-29 16:36:33 -0400333 logger.Infof(ctx, "deviceType:%d-deviceId:%s-previous:%v-current:%v", deviceType, cDevice.Id, pState, cState)
khenaidoob9203542018-09-17 22:56:37 -0400334
335 //2. Go over transition array to get the right transition
Kent Hagerman6031aad2020-07-29 16:36:33 -0400336 var currentMatch []transitionHandler
337 var tempHandler []transitionHandler
khenaidoo442e7c72020-03-10 16:13:48 -0400338 var m *match
339 bestMatch := &match{}
khenaidoob9203542018-09-17 22:56:37 -0400340 for _, aTransition := range tMap.transitions {
341 // consider transition only if it matches deviceType or is a wild card - any
342 if aTransition.deviceType != deviceType && aTransition.deviceType != any {
343 continue
344 }
khenaidoo442e7c72020-03-10 16:13:48 -0400345 tempHandler, m = getHandler(pState, cState, &aTransition)
khenaidoob9203542018-09-17 22:56:37 -0400346 if tempHandler != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400347 if m.isExactMatch() && aTransition.deviceType == deviceType {
khenaidoob9203542018-09-17 22:56:37 -0400348 return tempHandler
khenaidoo442e7c72020-03-10 16:13:48 -0400349 } else if m.isExactMatch() || m.isBetterMatch(bestMatch) {
khenaidoo0a822f92019-05-08 15:15:57 -0400350 currentMatch = tempHandler
khenaidoo442e7c72020-03-10 16:13:48 -0400351 bestMatch = m
khenaidoob9203542018-09-17 22:56:37 -0400352 }
353 }
354 }
355 return currentMatch
356}
Kent Hagerman6031aad2020-07-29 16:36:33 -0400357
358func (tMap *TransitionMap) ProcessTransition(ctx context.Context, device, prevDevice *voltha.Device) error {
359 // This will be triggered on every state update
360 logger.Debugw(ctx, "state-transition", log.Fields{
361 "device": device.Id,
362 "prev-admin-state": prevDevice.AdminState,
363 "prev-oper-state": prevDevice.OperStatus,
364 "prev-conn-state": prevDevice.ConnectStatus,
365 "curr-admin-state": device.AdminState,
366 "curr-oper-state": device.OperStatus,
367 "curr-conn-state": device.ConnectStatus,
368 })
369 handlers := tMap.getTransitionHandler(ctx, device, prevDevice)
370 if handlers == nil {
371 logger.Debugw(ctx, "no-op-transition", log.Fields{"deviceId": device.Id})
372 return nil
373 }
374 logger.Debugw(ctx, "handler-found", log.Fields{"num-expectedHandlers": len(handlers), "isParent": device.Root, "current-data": device, "previous-data": prevDevice})
375 for _, handler := range handlers {
376 logger.Debugw(ctx, "running-handler", log.Fields{"handler": funcName(handler)})
377 if err := handler(ctx, device); err != nil {
378 logger.Warnw(ctx, "handler-failed", log.Fields{"handler": funcName(handler), "error": err})
379 return err
380 }
381 }
382 return nil
383}
384
385func funcName(f interface{}) string {
386 return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
387}