blob: b3fecc00fbc6ca581edef4f4845b5f509629f998 [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{
khenaidoo4d4802d2018-10-04 21:59:49 -0400115 deviceType: child,
khenaidoob9203542018-09-17 22:56:37 -0400116 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 transitionMap.transitions = append(transitionMap.transitions,
132 Transition{
khenaidoo4d4802d2018-10-04 21:59:49 -0400133 deviceType: parent,
khenaidoob9203542018-09-17 22:56:37 -0400134 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo4d4802d2018-10-04 21:59:49 -0400135 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
136 handlers: []TransitionHandler{dMgr.deleteAllChildDevices}})
khenaidoob9203542018-09-17 22:56:37 -0400137 transitionMap.transitions = append(transitionMap.transitions,
138 Transition{
139 deviceType: any,
140 previousState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
141 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -0400142 handlers: []TransitionHandler{dMgr.notAllowed}})
khenaidoob9203542018-09-17 22:56:37 -0400143
144 return &transitionMap
145}
146
147func getDeviceStates(device *voltha.Device) *DeviceState {
148 return &DeviceState{Admin: device.AdminState, Connection: device.ConnectStatus, Operational: device.OperStatus}
149}
150
151// 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 -0400152func getHandler(previous *DeviceState, current *DeviceState, transition *Transition) ([]TransitionHandler, bool) {
khenaidoob9203542018-09-17 22:56:37 -0400153
154 // Do we have an exact match?
155 if *previous == transition.previousState && *current == transition.currentState {
khenaidoo92e62c52018-10-03 14:02:54 -0400156 return transition.handlers, true
khenaidoob9203542018-09-17 22:56:37 -0400157 }
158 // If the admin state changed then prioritize it first
159 if previous.Admin != current.Admin {
160 if previous.Admin == transition.previousState.Admin && current.Admin == transition.currentState.Admin {
khenaidoo92e62c52018-10-03 14:02:54 -0400161 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400162 }
163 }
164 // If the operational state changed then prioritize it in second position
165 if previous.Operational != current.Operational {
166 if previous.Operational == transition.previousState.Operational && current.Operational == transition.currentState.Operational {
khenaidoo92e62c52018-10-03 14:02:54 -0400167 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400168 }
169 }
170 // If the connection state changed then prioritize it in third position
171 if previous.Connection != current.Connection {
172 if previous.Connection == transition.previousState.Connection && current.Connection == transition.currentState.Connection {
khenaidoo92e62c52018-10-03 14:02:54 -0400173 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400174 }
175 }
176 return nil, false
177}
178
khenaidoo92e62c52018-10-03 14:02:54 -0400179func (tMap *TransitionMap) GetTransitionHandler(pDevice *voltha.Device, cDevice *voltha.Device) []TransitionHandler {
khenaidoob9203542018-09-17 22:56:37 -0400180 //1. Get the previous and current set of states
181 pState := getDeviceStates(pDevice)
182 cState := getDeviceStates(cDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400183 //log.Infow("DeviceType", log.Fields{"device": pDevice})
khenaidoob9203542018-09-17 22:56:37 -0400184 deviceType := parent
185 if !pDevice.Root {
186 log.Info("device is child")
187 deviceType = child
188 }
189 log.Infof("deviceType:%d-deviceId:%s-previous:%v-current:%v", deviceType, pDevice.Id, pState, cState)
190
191 //2. Go over transition array to get the right transition
khenaidoo92e62c52018-10-03 14:02:54 -0400192 var currentMatch []TransitionHandler
193 var tempHandler []TransitionHandler
khenaidoob9203542018-09-17 22:56:37 -0400194 var exactMatch bool
195 var deviceTypeMatch bool
196 for _, aTransition := range tMap.transitions {
197 // consider transition only if it matches deviceType or is a wild card - any
198 if aTransition.deviceType != deviceType && aTransition.deviceType != any {
199 continue
200 }
201 tempHandler, exactMatch = getHandler(pState, cState, &aTransition)
202 if tempHandler != nil {
203 if exactMatch {
204 return tempHandler
205 } else {
206 if currentMatch == nil {
207 currentMatch = tempHandler
208 } else if aTransition.deviceType == deviceType {
209 currentMatch = tempHandler
210 deviceTypeMatch = true
211 } else if !deviceTypeMatch {
212 currentMatch = tempHandler
213 }
214 }
215 }
216 }
217 return currentMatch
218}