blob: a84f03a801c8bafd31208f99b73c6ab17d2fcd87 [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"
20 "github.com/opencord/voltha-go/protos/voltha"
21)
22
23type DeviceType int32
24
25const (
26 parent DeviceType = 0
27 child DeviceType = 1
28 any DeviceType = 2
29)
30
31type DeviceState struct {
32 Admin voltha.AdminState_AdminState
33 Connection voltha.ConnectStatus_ConnectStatus
34 Operational voltha.OperStatus_OperStatus
35}
36
khenaidoo92e62c52018-10-03 14:02:54 -040037type TransitionHandler func(*voltha.Device) error
khenaidoob9203542018-09-17 22:56:37 -040038
39type Transition struct {
40 deviceType DeviceType
41 previousState DeviceState
42 currentState DeviceState
khenaidoo92e62c52018-10-03 14:02:54 -040043 handlers []TransitionHandler
khenaidoob9203542018-09-17 22:56:37 -040044}
45
46type TransitionMap struct {
47 transitions []Transition
48}
49
50func NewTransitionMap(dMgr *DeviceManager) *TransitionMap {
51 var transitionMap TransitionMap
52 transitionMap.transitions = make([]Transition, 0)
53 transitionMap.transitions = append(transitionMap.transitions,
54 Transition{
55 deviceType: any,
56 previousState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
57 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -040058 handlers: []TransitionHandler{dMgr.activateDevice}})
khenaidoob9203542018-09-17 22:56:37 -040059 transitionMap.transitions = append(transitionMap.transitions,
60 Transition{
61 deviceType: any,
62 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
63 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -040064 handlers: []TransitionHandler{dMgr.notAllowed}})
khenaidoob9203542018-09-17 22:56:37 -040065 transitionMap.transitions = append(transitionMap.transitions,
66 Transition{
67 deviceType: any,
68 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
69 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -040070 handlers: []TransitionHandler{dMgr.activateDevice}})
khenaidoob9203542018-09-17 22:56:37 -040071 transitionMap.transitions = append(transitionMap.transitions,
72 Transition{
73 deviceType: any,
74 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
75 currentState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -040076 handlers: []TransitionHandler{dMgr.notAllowed}})
khenaidoob9203542018-09-17 22:56:37 -040077 transitionMap.transitions = append(transitionMap.transitions,
78 Transition{
79 deviceType: any,
80 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
81 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -040082 handlers: []TransitionHandler{dMgr.notAllowed}})
khenaidoob9203542018-09-17 22:56:37 -040083 transitionMap.transitions = append(transitionMap.transitions,
84 Transition{
85 deviceType: parent,
86 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
87 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
khenaidoo92e62c52018-10-03 14:02:54 -040088 handlers: []TransitionHandler{dMgr.createLogicalDevice}})
khenaidoob9203542018-09-17 22:56:37 -040089 transitionMap.transitions = append(transitionMap.transitions,
90 Transition{
91 deviceType: child,
92 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
93 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
khenaidoo92e62c52018-10-03 14:02:54 -040094 handlers: []TransitionHandler{dMgr.addUNILogicalPort}})
khenaidoob9203542018-09-17 22:56:37 -040095 transitionMap.transitions = append(transitionMap.transitions,
96 Transition{
khenaidoo92e62c52018-10-03 14:02:54 -040097 deviceType: parent,
khenaidoob9203542018-09-17 22:56:37 -040098 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
99 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -0400100 handlers: []TransitionHandler{dMgr.deleteLogicalDevice, dMgr.disableAllChildDevices}})
101 transitionMap.transitions = append(transitionMap.transitions,
102 Transition{
103 deviceType: child,
104 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
105 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
106 handlers: []TransitionHandler{dMgr.deleteLogicalPort}})
khenaidoob9203542018-09-17 22:56:37 -0400107 transitionMap.transitions = append(transitionMap.transitions,
108 Transition{
109 deviceType: any,
110 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
111 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -0400112 handlers: []TransitionHandler{dMgr.abandonDevice}})
khenaidoob9203542018-09-17 22:56:37 -0400113 transitionMap.transitions = append(transitionMap.transitions,
114 Transition{
115 deviceType: any,
116 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
117 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -0400118 handlers: []TransitionHandler{dMgr.notAllowed}})
khenaidoob9203542018-09-17 22:56:37 -0400119 transitionMap.transitions = append(transitionMap.transitions,
120 Transition{
121 deviceType: any,
122 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
123 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -0400124 handlers: []TransitionHandler{dMgr.abandonDevice}})
khenaidoob9203542018-09-17 22:56:37 -0400125 transitionMap.transitions = append(transitionMap.transitions,
126 Transition{
127 deviceType: any,
128 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
129 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -0400130 handlers: []TransitionHandler{dMgr.reEnableDevice}})
khenaidoob9203542018-09-17 22:56:37 -0400131
132 transitionMap.transitions = append(transitionMap.transitions,
133 Transition{
134 deviceType: any,
135 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
136 currentState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -0400137 handlers: []TransitionHandler{dMgr.notAllowed}})
khenaidoob9203542018-09-17 22:56:37 -0400138
139 transitionMap.transitions = append(transitionMap.transitions,
140 Transition{
141 deviceType: any,
142 previousState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
143 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -0400144 handlers: []TransitionHandler{dMgr.notAllowed}})
khenaidoob9203542018-09-17 22:56:37 -0400145
146 return &transitionMap
147}
148
149func getDeviceStates(device *voltha.Device) *DeviceState {
150 return &DeviceState{Admin: device.AdminState, Connection: device.ConnectStatus, Operational: device.OperStatus}
151}
152
153// 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 -0400154func getHandler(previous *DeviceState, current *DeviceState, transition *Transition) ([]TransitionHandler, bool) {
khenaidoob9203542018-09-17 22:56:37 -0400155
156 // Do we have an exact match?
157 if *previous == transition.previousState && *current == transition.currentState {
khenaidoo92e62c52018-10-03 14:02:54 -0400158 return transition.handlers, true
khenaidoob9203542018-09-17 22:56:37 -0400159 }
160 // If the admin state changed then prioritize it first
161 if previous.Admin != current.Admin {
162 if previous.Admin == transition.previousState.Admin && current.Admin == transition.currentState.Admin {
khenaidoo92e62c52018-10-03 14:02:54 -0400163 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400164 }
165 }
166 // If the operational state changed then prioritize it in second position
167 if previous.Operational != current.Operational {
168 if previous.Operational == transition.previousState.Operational && current.Operational == transition.currentState.Operational {
khenaidoo92e62c52018-10-03 14:02:54 -0400169 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400170 }
171 }
172 // If the connection state changed then prioritize it in third position
173 if previous.Connection != current.Connection {
174 if previous.Connection == transition.previousState.Connection && current.Connection == transition.currentState.Connection {
khenaidoo92e62c52018-10-03 14:02:54 -0400175 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400176 }
177 }
178 return nil, false
179}
180
khenaidoo92e62c52018-10-03 14:02:54 -0400181func (tMap *TransitionMap) GetTransitionHandler(pDevice *voltha.Device, cDevice *voltha.Device) []TransitionHandler {
khenaidoob9203542018-09-17 22:56:37 -0400182 //1. Get the previous and current set of states
183 pState := getDeviceStates(pDevice)
184 cState := getDeviceStates(cDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400185 //log.Infow("DeviceType", log.Fields{"device": pDevice})
khenaidoob9203542018-09-17 22:56:37 -0400186 deviceType := parent
187 if !pDevice.Root {
188 log.Info("device is child")
189 deviceType = child
190 }
191 log.Infof("deviceType:%d-deviceId:%s-previous:%v-current:%v", deviceType, pDevice.Id, pState, cState)
192
193 //2. Go over transition array to get the right transition
khenaidoo92e62c52018-10-03 14:02:54 -0400194 var currentMatch []TransitionHandler
195 var tempHandler []TransitionHandler
khenaidoob9203542018-09-17 22:56:37 -0400196 var exactMatch bool
197 var deviceTypeMatch bool
198 for _, aTransition := range tMap.transitions {
199 // consider transition only if it matches deviceType or is a wild card - any
200 if aTransition.deviceType != deviceType && aTransition.deviceType != any {
201 continue
202 }
203 tempHandler, exactMatch = getHandler(pState, cState, &aTransition)
204 if tempHandler != nil {
205 if exactMatch {
206 return tempHandler
207 } else {
208 if currentMatch == nil {
209 currentMatch = tempHandler
210 } else if aTransition.deviceType == deviceType {
211 currentMatch = tempHandler
212 deviceTypeMatch = true
213 } else if !deviceTypeMatch {
214 currentMatch = tempHandler
215 }
216 }
217 }
218 }
219 return currentMatch
220}