blob: 21f7531906614add638fbd8c98e54ba602778e79 [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"
William Kurkiandaa6bb22019-03-07 12:26:28 -050020 "github.com/opencord/voltha-protos/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040021)
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)
khenaidoob9203542018-09-17 22:56:37 -040053 transitionMap.transitions = append(transitionMap.transitions,
54 Transition{
55 deviceType: any,
56 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
57 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -040058 handlers: []TransitionHandler{dMgr.notAllowed}})
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_DOWNLOADING_IMAGE, 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_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
69 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -040070 handlers: []TransitionHandler{dMgr.notAllowed}})
khenaidoob9203542018-09-17 22:56:37 -040071 transitionMap.transitions = append(transitionMap.transitions,
72 Transition{
73 deviceType: parent,
74 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
75 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
khenaidoo92e62c52018-10-03 14:02:54 -040076 handlers: []TransitionHandler{dMgr.createLogicalDevice}})
khenaidoob9203542018-09-17 22:56:37 -040077 transitionMap.transitions = append(transitionMap.transitions,
78 Transition{
79 deviceType: child,
80 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
81 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
khenaidoofc1314d2019-03-14 09:34:21 -040082 handlers: []TransitionHandler{dMgr.setupUNILogicalPorts}})
khenaidoob9203542018-09-17 22:56:37 -040083 transitionMap.transitions = append(transitionMap.transitions,
84 Transition{
khenaidoo92e62c52018-10-03 14:02:54 -040085 deviceType: parent,
khenaidoob9203542018-09-17 22:56:37 -040086 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
87 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -040088 handlers: []TransitionHandler{dMgr.deleteLogicalDevice, dMgr.disableAllChildDevices}})
89 transitionMap.transitions = append(transitionMap.transitions,
90 Transition{
91 deviceType: child,
92 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
93 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
94 handlers: []TransitionHandler{dMgr.deleteLogicalPort}})
khenaidoob9203542018-09-17 22:56:37 -040095 transitionMap.transitions = append(transitionMap.transitions,
96 Transition{
97 deviceType: any,
98 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
99 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -0400100 handlers: []TransitionHandler{dMgr.abandonDevice}})
khenaidoob9203542018-09-17 22:56:37 -0400101 transitionMap.transitions = append(transitionMap.transitions,
102 Transition{
khenaidoo4d4802d2018-10-04 21:59:49 -0400103 deviceType: child,
khenaidoob9203542018-09-17 22:56:37 -0400104 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
105 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -0400106 handlers: []TransitionHandler{dMgr.notAllowed}})
khenaidoob9203542018-09-17 22:56:37 -0400107 transitionMap.transitions = append(transitionMap.transitions,
108 Transition{
109 deviceType: any,
110 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, 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_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -0400118 handlers: []TransitionHandler{dMgr.reEnableDevice}})
khenaidoob9203542018-09-17 22:56:37 -0400119 transitionMap.transitions = append(transitionMap.transitions,
120 Transition{
khenaidoo4d4802d2018-10-04 21:59:49 -0400121 deviceType: parent,
khenaidoob9203542018-09-17 22:56:37 -0400122 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo4d4802d2018-10-04 21:59:49 -0400123 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
124 handlers: []TransitionHandler{dMgr.deleteAllChildDevices}})
khenaidoob9203542018-09-17 22:56:37 -0400125 transitionMap.transitions = append(transitionMap.transitions,
126 Transition{
127 deviceType: any,
128 previousState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
129 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo92e62c52018-10-03 14:02:54 -0400130 handlers: []TransitionHandler{dMgr.notAllowed}})
khenaidoob9203542018-09-17 22:56:37 -0400131
132 return &transitionMap
133}
134
135func getDeviceStates(device *voltha.Device) *DeviceState {
136 return &DeviceState{Admin: device.AdminState, Connection: device.ConnectStatus, Operational: device.OperStatus}
137}
138
139// 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 -0400140func getHandler(previous *DeviceState, current *DeviceState, transition *Transition) ([]TransitionHandler, bool) {
khenaidoob9203542018-09-17 22:56:37 -0400141
142 // Do we have an exact match?
143 if *previous == transition.previousState && *current == transition.currentState {
khenaidoo92e62c52018-10-03 14:02:54 -0400144 return transition.handlers, true
khenaidoob9203542018-09-17 22:56:37 -0400145 }
146 // If the admin state changed then prioritize it first
147 if previous.Admin != current.Admin {
148 if previous.Admin == transition.previousState.Admin && current.Admin == transition.currentState.Admin {
khenaidoo92e62c52018-10-03 14:02:54 -0400149 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400150 }
151 }
152 // If the operational state changed then prioritize it in second position
153 if previous.Operational != current.Operational {
154 if previous.Operational == transition.previousState.Operational && current.Operational == transition.currentState.Operational {
khenaidoo92e62c52018-10-03 14:02:54 -0400155 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400156 }
157 }
158 // If the connection state changed then prioritize it in third position
159 if previous.Connection != current.Connection {
160 if previous.Connection == transition.previousState.Connection && current.Connection == transition.currentState.Connection {
khenaidoo92e62c52018-10-03 14:02:54 -0400161 return transition.handlers, false
khenaidoob9203542018-09-17 22:56:37 -0400162 }
163 }
164 return nil, false
165}
166
khenaidoo92e62c52018-10-03 14:02:54 -0400167func (tMap *TransitionMap) GetTransitionHandler(pDevice *voltha.Device, cDevice *voltha.Device) []TransitionHandler {
khenaidoob9203542018-09-17 22:56:37 -0400168 //1. Get the previous and current set of states
169 pState := getDeviceStates(pDevice)
170 cState := getDeviceStates(cDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400171 //log.Infow("DeviceType", log.Fields{"device": pDevice})
khenaidoob9203542018-09-17 22:56:37 -0400172 deviceType := parent
173 if !pDevice.Root {
174 log.Info("device is child")
175 deviceType = child
176 }
177 log.Infof("deviceType:%d-deviceId:%s-previous:%v-current:%v", deviceType, pDevice.Id, pState, cState)
178
179 //2. Go over transition array to get the right transition
khenaidoo92e62c52018-10-03 14:02:54 -0400180 var currentMatch []TransitionHandler
181 var tempHandler []TransitionHandler
khenaidoob9203542018-09-17 22:56:37 -0400182 var exactMatch bool
183 var deviceTypeMatch bool
184 for _, aTransition := range tMap.transitions {
185 // consider transition only if it matches deviceType or is a wild card - any
186 if aTransition.deviceType != deviceType && aTransition.deviceType != any {
187 continue
188 }
189 tempHandler, exactMatch = getHandler(pState, cState, &aTransition)
190 if tempHandler != nil {
191 if exactMatch {
192 return tempHandler
193 } else {
194 if currentMatch == nil {
195 currentMatch = tempHandler
196 } else if aTransition.deviceType == deviceType {
197 currentMatch = tempHandler
198 deviceTypeMatch = true
199 } else if !deviceTypeMatch {
200 currentMatch = tempHandler
201 }
202 }
203 }
204 }
205 return currentMatch
206}