blob: cd662aca580023cc2fb7acf15caa4cfb5822d377 [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 "context"
20 "errors"
21 "github.com/opencord/voltha-go/common/log"
22 "github.com/opencord/voltha-go/db/model"
23 "github.com/opencord/voltha-go/kafka"
khenaidoo79232702018-12-04 11:00:41 -050024 ic "github.com/opencord/voltha-go/protos/inter_container"
khenaidoo19d7b632018-10-30 10:49:50 -040025 ofp "github.com/opencord/voltha-go/protos/openflow_13"
khenaidoob9203542018-09-17 22:56:37 -040026 "github.com/opencord/voltha-go/protos/voltha"
27 "google.golang.org/grpc/codes"
28 "google.golang.org/grpc/status"
29 "reflect"
30 "runtime"
31 "sync"
32)
33
34type DeviceManager struct {
35 deviceAgents map[string]*DeviceAgent
36 adapterProxy *AdapterProxy
khenaidoo21d51152019-02-01 13:48:37 -050037 adapterMgr *AdapterManager
khenaidoob9203542018-09-17 22:56:37 -040038 logicalDeviceMgr *LogicalDeviceManager
khenaidoo43c82122018-11-22 18:38:28 -050039 kafkaICProxy *kafka.InterContainerProxy
khenaidoob9203542018-09-17 22:56:37 -040040 stateTransitions *TransitionMap
khenaidoo9a468962018-09-19 15:33:13 -040041 clusterDataProxy *model.Proxy
khenaidood2b6df92018-12-13 16:37:20 -050042 coreInstanceId string
khenaidoob9203542018-09-17 22:56:37 -040043 exitChannel chan int
44 lockDeviceAgentsMap sync.RWMutex
45}
46
khenaidoo21d51152019-02-01 13:48:37 -050047func newDeviceManager(kafkaICProxy *kafka.InterContainerProxy, cdProxy *model.Proxy, adapterMgr *AdapterManager, coreInstanceId string) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040048 var deviceMgr DeviceManager
49 deviceMgr.exitChannel = make(chan int, 1)
50 deviceMgr.deviceAgents = make(map[string]*DeviceAgent)
khenaidoo43c82122018-11-22 18:38:28 -050051 deviceMgr.adapterProxy = NewAdapterProxy(kafkaICProxy)
52 deviceMgr.kafkaICProxy = kafkaICProxy
khenaidoo19374072018-12-11 11:05:15 -050053 deviceMgr.coreInstanceId = coreInstanceId
khenaidoo9a468962018-09-19 15:33:13 -040054 deviceMgr.clusterDataProxy = cdProxy
khenaidoo21d51152019-02-01 13:48:37 -050055 deviceMgr.adapterMgr= adapterMgr
khenaidoob9203542018-09-17 22:56:37 -040056 deviceMgr.lockDeviceAgentsMap = sync.RWMutex{}
57 return &deviceMgr
58}
59
khenaidoo4d4802d2018-10-04 21:59:49 -040060func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040061 log.Info("starting-device-manager")
62 dMgr.logicalDeviceMgr = logicalDeviceMgr
63 dMgr.stateTransitions = NewTransitionMap(dMgr)
64 log.Info("device-manager-started")
65}
66
khenaidoo4d4802d2018-10-04 21:59:49 -040067func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040068 log.Info("stopping-device-manager")
69 dMgr.exitChannel <- 1
70 log.Info("device-manager-stopped")
71}
72
73func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
74 if ctx.Err() == nil {
75 // Returned response only of the ctx has not been cancelled/timeout/etc
76 // Channel is automatically closed when a context is Done
77 ch <- result
78 log.Debugw("sendResponse", log.Fields{"result": result})
79 } else {
80 // Should the transaction be reverted back?
81 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
82 }
83}
84
85func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
86 dMgr.lockDeviceAgentsMap.Lock()
87 defer dMgr.lockDeviceAgentsMap.Unlock()
88 if _, exist := dMgr.deviceAgents[agent.deviceId]; !exist {
89 dMgr.deviceAgents[agent.deviceId] = agent
90 }
91}
92
khenaidoo4d4802d2018-10-04 21:59:49 -040093func (dMgr *DeviceManager) deleteDeviceAgentToMap(agent *DeviceAgent) {
94 dMgr.lockDeviceAgentsMap.Lock()
95 defer dMgr.lockDeviceAgentsMap.Unlock()
96 delete(dMgr.deviceAgents, agent.deviceId)
97}
98
khenaidoob9203542018-09-17 22:56:37 -040099func (dMgr *DeviceManager) getDeviceAgent(deviceId string) *DeviceAgent {
khenaidoo4d4802d2018-10-04 21:59:49 -0400100 // TODO If the device is not in memory it needs to be loaded first
khenaidoob9203542018-09-17 22:56:37 -0400101 dMgr.lockDeviceAgentsMap.Lock()
102 defer dMgr.lockDeviceAgentsMap.Unlock()
103 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
104 return agent
105 }
106 return nil
107}
108
khenaidoo7ccedd52018-12-14 16:48:54 -0500109func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
110 dMgr.lockDeviceAgentsMap.Lock()
111 defer dMgr.lockDeviceAgentsMap.Unlock()
112 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
113 for key, _ := range dMgr.deviceAgents {
114 result.Items = append(result.Items, &voltha.ID{Id: key})
115 }
116 return result
117}
118
khenaidoob9203542018-09-17 22:56:37 -0400119func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400120 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400121
122 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400123 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400124 dMgr.addDeviceAgentToMap(agent)
125 agent.start(ctx)
126
khenaidoo92e62c52018-10-03 14:02:54 -0400127 sendResponse(ctx, ch, agent.lastData)
khenaidoob9203542018-09-17 22:56:37 -0400128}
129
130func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400131 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400132 var res interface{}
133 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
134 res = agent.enableDevice(ctx)
135 log.Debugw("EnableDevice-result", log.Fields{"result": res})
136 } else {
137 res = status.Errorf(codes.NotFound, "%s", id.Id)
138 }
139
140 sendResponse(ctx, ch, res)
141}
142
khenaidoo92e62c52018-10-03 14:02:54 -0400143func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
144 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400145 var res interface{}
146 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
147 res = agent.disableDevice(ctx)
148 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400149 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400150 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400151 }
khenaidoo92e62c52018-10-03 14:02:54 -0400152
153 sendResponse(ctx, ch, res)
154}
155
khenaidoo4d4802d2018-10-04 21:59:49 -0400156func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
157 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
158 var res interface{}
159 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
160 res = agent.rebootDevice(ctx)
161 log.Debugw("rebootDevice-result", log.Fields{"result": res})
162 } else {
163 res = status.Errorf(codes.NotFound, "%s", id.Id)
164 }
165 sendResponse(ctx, ch, res)
166}
167
168func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
169 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
170 var res interface{}
171 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
172 res = agent.deleteDevice(ctx)
173 if res == nil { //Success
174 agent.stop(ctx)
175 dMgr.deleteDeviceAgentToMap(agent)
176 }
177 log.Debugw("deleteDevice-result", log.Fields{"result": res})
178 } else {
179 res = status.Errorf(codes.NotFound, "%s", id.Id)
180 }
181 sendResponse(ctx, ch, res)
182}
183
khenaidoo19d7b632018-10-30 10:49:50 -0400184func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
185 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400186 if agent := dMgr.getDeviceAgent(id); agent != nil {
187 return agent.getDevice()
188 }
189 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400190}
191
khenaidoo19d7b632018-10-30 10:49:50 -0400192func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
193 device, err := dMgr.GetDevice(id)
194 if err != nil {
195 return false, err
196 }
197 return device.Root, nil
198}
199
Stephane Barbarieaa467942019-02-06 14:09:44 -0500200// ListDevices retrieves the latest devices from the data model
khenaidoob9203542018-09-17 22:56:37 -0400201func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400202 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400203 result := &voltha.Devices{}
Stephane Barbarieaa467942019-02-06 14:09:44 -0500204 if devices := dMgr.clusterDataProxy.List("/devices", 0, false, ""); devices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500205 for _, device := range devices.([]interface{}) {
206 if agent := dMgr.getDeviceAgent(device.(*voltha.Device).Id); agent == nil {
207 agent = newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy)
208 dMgr.addDeviceAgentToMap(agent)
209 agent.start(nil)
210 }
211 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400212 }
213 }
214 return result, nil
215}
216
khenaidoo7ccedd52018-12-14 16:48:54 -0500217// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
218func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
219 log.Debug("ListDeviceIDs")
220 // Report only device IDs that are in the device agent map
221 return dMgr.listDeviceIdsFromMap(), nil
222}
223
224//ReconcileDevices is a request to a voltha core to managed a list of devices based on their IDs
225func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
226 log.Debug("ReconcileDevices")
227 var res interface{}
228 if ids != nil {
229 toReconcile := len(ids.Items)
230 reconciled := 0
231 for _, id := range ids.Items {
232 // Act on the device only if its not present in the agent map
233 if agent := dMgr.getDeviceAgent(id.Id); agent == nil {
234 // Device Id not in memory
235 log.Debugw("reconciling-device", log.Fields{"id": id.Id})
236 // Load device from model
237 if device := dMgr.clusterDataProxy.Get("/devices/"+id.Id, 0, false, ""); device != nil {
238 agent = newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy)
239 dMgr.addDeviceAgentToMap(agent)
240 agent.start(nil)
241 reconciled += 1
242 } else {
243 log.Warnw("device-inexistent", log.Fields{"id": id.Id})
244 }
245 } else {
246 reconciled += 1
247 }
248 }
249 if toReconcile != reconciled {
250 res = status.Errorf(codes.DataLoss, "less-device-reconciled:%d/%d", reconciled, toReconcile)
251 }
252 } else {
253 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
254 }
255 sendResponse(ctx, ch, res)
256}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500257
khenaidoob9203542018-09-17 22:56:37 -0400258func (dMgr *DeviceManager) updateDevice(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400259 log.Debugw("updateDevice", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400260 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
261 return agent.updateDevice(device)
262 }
263 return status.Errorf(codes.NotFound, "%s", device.Id)
264}
265
266func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
267 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400268 if err := agent.addPort(port); err != nil {
269 return err
270 }
271 // Setup peer ports
272 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
273 for _, peerPort := range port.Peers {
274 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
275 if err := agent.addPeerPort(meAsPeer); err != nil {
276 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
277 return err
278 }
279 }
280 }
281 return nil
282 } else {
283 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400284 }
khenaidoob9203542018-09-17 22:56:37 -0400285}
286
khenaidoo19d7b632018-10-30 10:49:50 -0400287func (dMgr *DeviceManager) updateFlows(deviceId string, flows []*ofp.OfpFlowStats) error {
288 log.Debugw("updateFlows", log.Fields{"deviceid": deviceId})
289 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
290 return agent.updateFlows(flows)
291 }
292 return status.Errorf(codes.NotFound, "%s", deviceId)
293}
294
295func (dMgr *DeviceManager) updateGroups(deviceId string, groups []*ofp.OfpGroupEntry) error {
296 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
297 return agent.updateGroups(groups)
298 }
299 return status.Errorf(codes.NotFound, "%s", deviceId)
300}
301
khenaidoob9203542018-09-17 22:56:37 -0400302func (dMgr *DeviceManager) updatePmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
303 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
304 return agent.updatePmConfigs(pmConfigs)
305 }
306 return status.Errorf(codes.NotFound, "%s", deviceId)
307}
308
khenaidoo79232702018-12-04 11:00:41 -0500309func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400310 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400311 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
312 return agent.getSwitchCapability(ctx)
313 }
314 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
315}
316
khenaidoo92e62c52018-10-03 14:02:54 -0400317func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
318 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400319 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400320 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400321 }
322 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoo92e62c52018-10-03 14:02:54 -0400323
khenaidoob9203542018-09-17 22:56:37 -0400324}
325
khenaidoo79232702018-12-04 11:00:41 -0500326func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400327 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400328 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
329 return agent.getPortCapability(ctx, portNo)
330 }
331 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
332}
333
khenaidoo92e62c52018-10-03 14:02:54 -0400334func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
335 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400336 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400337 return agent.updateDeviceStatus(operStatus, connStatus)
338 }
339 return status.Errorf(codes.NotFound, "%s", deviceId)
340}
341
khenaidoo4d4802d2018-10-04 21:59:49 -0400342func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
343 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
344 var parentDevice *voltha.Device
345 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400346 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400347 return status.Errorf(codes.Aborted, "%s", err.Error())
348 }
349 var childDeviceIds []string
350 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
351 return status.Errorf(codes.Aborted, "%s", err.Error())
352 }
353 if len(childDeviceIds) == 0 {
354 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
355 }
356 for _, childDeviceId := range childDeviceIds {
357 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
358 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
359 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
360 }
361 }
362 }
363 return nil
364}
365
khenaidoo92e62c52018-10-03 14:02:54 -0400366func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
367 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
368 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
369 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400370 }
371 return status.Errorf(codes.NotFound, "%s", deviceId)
372}
373
374func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string, channelId int64) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400375 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400376
377 // Create the ONU device
378 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400379 childDevice.Type = deviceType
380 childDevice.ParentId = parentDeviceId
381 childDevice.ParentPortNo = uint32(parentPortNo)
382 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400383
384 //Get parent device type
385 parent, err := dMgr.GetDevice(parentDeviceId)
386 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500387 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400388 return status.Errorf(codes.NotFound, "%s", parentDeviceId)
389 }
390
391 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId)}
khenaidoob9203542018-09-17 22:56:37 -0400392
393 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400394 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400395 dMgr.addDeviceAgentToMap(agent)
396 agent.start(nil)
397
398 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400399 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500400 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400401 }
402
khenaidoo79232702018-12-04 11:00:41 -0500403 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500404 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500405
khenaidoob9203542018-09-17 22:56:37 -0400406 return nil
407}
408
409func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
410 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400411 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
412 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500413 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400414 return nil
khenaidoob9203542018-09-17 22:56:37 -0400415 }
khenaidoo92e62c52018-10-03 14:02:54 -0400416 for _, handler := range handlers {
417 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
418 if err := handler(current); err != nil {
419 return err
420 }
421 }
khenaidoob9203542018-09-17 22:56:37 -0400422 return nil
423}
424
khenaidoofdbad6e2018-11-06 22:26:38 -0500425func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
426 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
427 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
428 return agent.packetOut(outPort, packet)
429 }
430 return status.Errorf(codes.NotFound, "%s", deviceId)
431}
432
433func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, packet []byte) error {
434 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
435 // Get the logical device Id based on the deviceId
436 var device *voltha.Device
437 var err error
438 if device, err = dMgr.GetDevice(deviceId); err != nil {
439 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
440 return err
441 }
khenaidoo43c82122018-11-22 18:38:28 -0500442 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500443 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
444 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
445 }
446
447 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, packet); err != nil {
448 return err
449 }
450 return nil
451}
452
khenaidoo92e62c52018-10-03 14:02:54 -0400453func (dMgr *DeviceManager) createLogicalDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400454 log.Info("createLogicalDevice")
455 var logicalId *string
456 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400457 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400458 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
459 return err
460 }
461 // Update the parent device with the logical id
462 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
463 return nil
464}
465
khenaidoo92e62c52018-10-03 14:02:54 -0400466func (dMgr *DeviceManager) deleteLogicalDevice(cDevice *voltha.Device) error {
467 log.Info("deleteLogicalDevice")
468 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400469 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400470 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
471 return err
472 }
473 // Remove the logical device Id from the parent device
474 logicalId := ""
475 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
476 return nil
477}
478
khenaidoo19d7b632018-10-30 10:49:50 -0400479func (dMgr *DeviceManager) deleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400480 log.Info("deleteLogicalPort")
481 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400482 // Get the logical port associated with this device
483 var lPortId *voltha.LogicalPortId
484 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400485 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400486 return err
487 }
488 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
489 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400490 return err
491 }
khenaidoo92e62c52018-10-03 14:02:54 -0400492 return nil
493}
494
495func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
496 // Sanity check
497 if childDevice.Root {
498 // childDevice is the parent device
499 return childDevice
500 }
khenaidoo19d7b632018-10-30 10:49:50 -0400501 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400502 return parentDevice
503}
504
khenaidoo4d4802d2018-10-04 21:59:49 -0400505/*
506All the functions below are callback functions where they are invoked with the latest and previous data. We can
507therefore use the data as is without trying to get the latest from the model.
508*/
509
510//disableAllChildDevices is invoked as a callback when the parent device is disabled
511func (dMgr *DeviceManager) disableAllChildDevices(parentDevice *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400512 log.Debug("disableAllChildDevices")
513 var childDeviceIds []string
514 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400515 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
516 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400517 }
518 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400519 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400520 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400521 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400522 for _, childDeviceId := range childDeviceIds {
523 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
524 if err = agent.disableDevice(nil); err != nil {
525 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400526 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400527 }
528 }
529 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400530 if !allChildDisable {
531 return err
532 }
khenaidoo92e62c52018-10-03 14:02:54 -0400533 return nil
534}
535
khenaidoo4d4802d2018-10-04 21:59:49 -0400536//deleteAllChildDevices is invoked as a callback when the parent device is deleted
537func (dMgr *DeviceManager) deleteAllChildDevices(parentDevice *voltha.Device) error {
538 log.Debug("deleteAllChildDevices")
539 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400540 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400541 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
542 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400543 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400544 if len(childDeviceIds) == 0 {
545 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
546 }
547 allChildDeleted := true
548 for _, childDeviceId := range childDeviceIds {
549 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
550 if err = agent.deleteDevice(nil); err != nil {
551 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
552 allChildDeleted = false
553 } else {
554 agent.stop(nil)
555 dMgr.deleteDeviceAgentToMap(agent)
556 }
557 }
558 }
559 if !allChildDeleted {
560 return err
561 }
562 return nil
563}
564
565//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
566func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
567 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400568 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -0400569 if parentDevice != nil {
570 for _, port := range parentDevice.Ports {
571 for _, peer := range port.Peers {
572 childDeviceIds = append(childDeviceIds, peer.DeviceId)
573 }
khenaidoo92e62c52018-10-03 14:02:54 -0400574 }
575 }
576 return childDeviceIds, nil
577}
578
579func (dMgr *DeviceManager) addUNILogicalPort(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400580 log.Info("addUNILogicalPort")
khenaidoo4d4802d2018-10-04 21:59:49 -0400581 if err := dMgr.logicalDeviceMgr.addUNILogicalPort(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400582 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
583 return err
584 }
585 return nil
586}
587
khenaidoof5a5bfa2019-01-23 22:20:29 -0500588
589func (dMgr *DeviceManager) downloadImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
590 log.Debugw("downloadImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
591 var res interface{}
592 var err error
593 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
594 if res, err = agent.downloadImage(ctx, img); err != nil {
595 log.Debugw("downloadImage-failed", log.Fields{"err": err, "imageName": img.Name})
596 res = err
597 }
598 } else {
599 res = status.Errorf(codes.NotFound, "%s", img.Id)
600 }
601 sendResponse(ctx, ch, res)
602}
603
604func (dMgr *DeviceManager) cancelImageDownload(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
605 log.Debugw("cancelImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
606 var res interface{}
607 var err error
608 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
609 if res, err = agent.cancelImageDownload(ctx, img); err != nil {
610 log.Debugw("cancelImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
611 res = err
612 }
613 } else {
614 res = status.Errorf(codes.NotFound, "%s", img.Id)
615 }
616 sendResponse(ctx, ch, res)
617}
618
619func (dMgr *DeviceManager) activateImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
620 log.Debugw("activateImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
621 var res interface{}
622 var err error
623 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
624 if res, err = agent.activateImage(ctx, img); err != nil {
625 log.Debugw("activateImage-failed", log.Fields{"err": err, "imageName": img.Name})
626 res = err
627 }
628 } else {
629 res = status.Errorf(codes.NotFound, "%s", img.Id)
630 }
631 sendResponse(ctx, ch, res)
632}
633
634func (dMgr *DeviceManager) revertImage(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
635 log.Debugw("revertImage", log.Fields{"deviceid": img.Id, "imageName": img.Name})
636 var res interface{}
637 var err error
638 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
639 if res, err = agent.revertImage(ctx, img); err != nil {
640 log.Debugw("revertImage-failed", log.Fields{"err": err, "imageName": img.Name})
641 res = err
642 }
643 } else {
644 res = status.Errorf(codes.NotFound, "%s", img.Id)
645 }
646 sendResponse(ctx, ch, res)
647}
648
649func (dMgr *DeviceManager) getImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload, ch chan interface{}) {
650 log.Debugw("getImageDownloadStatus", log.Fields{"deviceid": img.Id, "imageName": img.Name})
651 var res interface{}
652 var err error
653 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
654 if res, err = agent.getImageDownloadStatus(ctx, img); err != nil {
655 log.Debugw("getImageDownloadStatus-failed", log.Fields{"err": err, "imageName": img.Name})
656 res = err
657 }
658 } else {
659 res = status.Errorf(codes.NotFound, "%s", img.Id)
660 }
661 sendResponse(ctx, ch, res)
662}
663
664
665func (dMgr *DeviceManager) updateImageDownload(deviceId string, img *voltha.ImageDownload) error {
666 log.Debugw("updateImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
667 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
668 if err := agent.updateImageDownload(img); err != nil {
669 log.Debugw("updateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
670 return err
671 }
672 } else {
673 return status.Errorf(codes.NotFound, "%s", img.Id)
674 }
675 return nil
676}
677
678func (dMgr *DeviceManager) getImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
679 log.Debugw("getImageDownload", log.Fields{"deviceid": img.Id, "imageName": img.Name})
680 if agent := dMgr.getDeviceAgent(img.Id); agent != nil {
681 return agent.getImageDownload(ctx, img)
682 }
683 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
684}
685
686func (dMgr *DeviceManager) listImageDownloads(ctx context.Context, deviceId string) (*voltha.ImageDownloads, error) {
687 log.Debugw("listImageDownloads", log.Fields{"deviceId": deviceId})
688 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
689 return agent.listImageDownloads(ctx, deviceId)
690 }
691 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
692}
693
694
khenaidoo92e62c52018-10-03 14:02:54 -0400695func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400696 log.Info("activateDevice")
697 return nil
698}
699
khenaidoo92e62c52018-10-03 14:02:54 -0400700func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
701 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -0400702 return nil
703}
704
khenaidoo92e62c52018-10-03 14:02:54 -0400705func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400706 log.Info("abandonDevice")
707 return nil
708}
709
khenaidoo92e62c52018-10-03 14:02:54 -0400710func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400711 log.Info("reEnableDevice")
712 return nil
713}
714
khenaidoo92e62c52018-10-03 14:02:54 -0400715func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400716 log.Info("noOp")
717 return nil
718}
719
khenaidoo92e62c52018-10-03 14:02:54 -0400720func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400721 log.Info("notAllowed")
722 return errors.New("Transition-not-allowed")
723}
724
725func funcName(f interface{}) string {
726 p := reflect.ValueOf(f).Pointer()
727 rf := runtime.FuncForPC(p)
728 return rf.Name()
729}
730
731func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
732 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
733 agent.updateDeviceAttribute(attribute, value)
734 }
735}
736
737func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -0400738 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400739 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -0400740 return &device.ParentId
741 }
742 return nil
743}