blob: 0f0239c4a414af2bf2f1a2dc6ad482e66215583d [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
37type TransitionHandler func(*voltha.Device, *voltha.Device) error
38
39type Transition struct {
40 deviceType DeviceType
41 previousState DeviceState
42 currentState DeviceState
43 handler TransitionHandler
44}
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},
58 handler: dMgr.activateDevice})
59 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},
64 handler: dMgr.notAllowed})
65 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},
70 handler: dMgr.activateDevice})
71 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},
76 handler: dMgr.notAllowed})
77 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},
82 handler: dMgr.notAllowed})
83 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},
88 handler: dMgr.createLogicalDevice})
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_ACTIVATING},
93 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
94 handler: dMgr.addUNILogicalPort})
95 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_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
100 handler: dMgr.disableDevice})
101
102 transitionMap.transitions = append(transitionMap.transitions,
103 Transition{
104 deviceType: any,
105 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
106 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
107 handler: dMgr.abandonDevice})
108 transitionMap.transitions = append(transitionMap.transitions,
109 Transition{
110 deviceType: any,
111 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
112 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
113 handler: dMgr.notAllowed})
114 transitionMap.transitions = append(transitionMap.transitions,
115 Transition{
116 deviceType: any,
117 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
118 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
119 handler: dMgr.abandonDevice})
120 transitionMap.transitions = append(transitionMap.transitions,
121 Transition{
122 deviceType: any,
123 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
124 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
125 handler: dMgr.reEnableDevice})
126
127 transitionMap.transitions = append(transitionMap.transitions,
128 Transition{
129 deviceType: any,
130 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
131 currentState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
132 handler: dMgr.notAllowed})
133
134 transitionMap.transitions = append(transitionMap.transitions,
135 Transition{
136 deviceType: any,
137 previousState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
138 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
139 handler: dMgr.notAllowed})
140
141 return &transitionMap
142}
143
144func getDeviceStates(device *voltha.Device) *DeviceState {
145 return &DeviceState{Admin: device.AdminState, Connection: device.ConnectStatus, Operational: device.OperStatus}
146}
147
148// isMatched matches a state transition. It returns whether there is a match and if there is whether it is an exact match
149func getHandler(previous *DeviceState, current *DeviceState, transition *Transition) (TransitionHandler, bool) {
150
151 // Do we have an exact match?
152 if *previous == transition.previousState && *current == transition.currentState {
153 return transition.handler, true
154 }
155 // If the admin state changed then prioritize it first
156 if previous.Admin != current.Admin {
157 if previous.Admin == transition.previousState.Admin && current.Admin == transition.currentState.Admin {
158 return transition.handler, false
159 }
160 }
161 // If the operational state changed then prioritize it in second position
162 if previous.Operational != current.Operational {
163 if previous.Operational == transition.previousState.Operational && current.Operational == transition.currentState.Operational {
164 return transition.handler, false
165 }
166 }
167 // If the connection state changed then prioritize it in third position
168 if previous.Connection != current.Connection {
169 if previous.Connection == transition.previousState.Connection && current.Connection == transition.currentState.Connection {
170 return transition.handler, false
171 }
172 }
173 return nil, false
174}
175
176func (tMap *TransitionMap) GetTransitionHandler(pDevice *voltha.Device, cDevice *voltha.Device) TransitionHandler {
177 //1. Get the previous and current set of states
178 pState := getDeviceStates(pDevice)
179 cState := getDeviceStates(cDevice)
180 log.Infow("DeviceType", log.Fields{"device": pDevice})
181 deviceType := parent
182 if !pDevice.Root {
183 log.Info("device is child")
184 deviceType = child
185 }
186 log.Infof("deviceType:%d-deviceId:%s-previous:%v-current:%v", deviceType, pDevice.Id, pState, cState)
187
188 //2. Go over transition array to get the right transition
189 var currentMatch TransitionHandler
190 var tempHandler TransitionHandler
191 var exactMatch bool
192 var deviceTypeMatch bool
193 for _, aTransition := range tMap.transitions {
194 // consider transition only if it matches deviceType or is a wild card - any
195 if aTransition.deviceType != deviceType && aTransition.deviceType != any {
196 continue
197 }
198 tempHandler, exactMatch = getHandler(pState, cState, &aTransition)
199 if tempHandler != nil {
200 if exactMatch {
201 return tempHandler
202 } else {
203 if currentMatch == nil {
204 currentMatch = tempHandler
205 } else if aTransition.deviceType == deviceType {
206 currentMatch = tempHandler
207 deviceTypeMatch = true
208 } else if !deviceTypeMatch {
209 currentMatch = tempHandler
210 }
211 }
212 }
213 }
214 return currentMatch
215}