blob: 9990104b17624df0b41a48136e0419a54ca39309 [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 */
npujar1d86a522019-11-14 17:11:16 +053016
Kent Hagerman2b216042020-04-03 18:28:56 -040017package device
khenaidoob9203542018-09-17 22:56:37 -040018
19import (
20 "context"
21 "errors"
Kent Hagerman45a13e42020-04-13 12:23:50 -040022 "github.com/opencord/voltha-go/rw_core/core/device/event"
David Bainbridged1afd662020-03-26 18:27:41 -070023 "reflect"
24 "runtime"
25 "sync"
26 "time"
27
Kent Hagerman45a13e42020-04-13 12:23:50 -040028 "github.com/golang/protobuf/ptypes/empty"
sbarbari17d7e222019-11-05 10:02:29 -050029 "github.com/opencord/voltha-go/db/model"
Kent Hagerman2b216042020-04-03 18:28:56 -040030 "github.com/opencord/voltha-go/rw_core/core/adapter"
31 "github.com/opencord/voltha-go/rw_core/core/device/remote"
khenaidoo3d3b8c22019-05-22 18:10:39 -040032 "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080033 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
34 "github.com/opencord/voltha-lib-go/v3/pkg/log"
Kent Hagerman45a13e42020-04-13 12:23:50 -040035 "github.com/opencord/voltha-protos/v3/go/common"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080036 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
37 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
38 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040039 "google.golang.org/grpc/codes"
40 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040041)
42
Kent Hagerman2b216042020-04-03 18:28:56 -040043// Manager represent device manager attributes
44type Manager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040045 deviceAgents sync.Map
46 rootDevices map[string]bool
47 lockRootDeviceMap sync.RWMutex
Kent Hagerman2b216042020-04-03 18:28:56 -040048 adapterProxy *remote.AdapterProxy
49 adapterMgr *adapter.Manager
50 logicalDeviceMgr *LogicalManager
npujar467fe752020-01-16 20:17:45 +053051 kafkaICProxy kafka.InterContainerProxy
khenaidoo4c9e5592019-09-09 16:20:41 -040052 stateTransitions *TransitionMap
53 clusterDataProxy *model.Proxy
npujar1d86a522019-11-14 17:11:16 +053054 coreInstanceID string
khenaidoo442e7c72020-03-10 16:13:48 -040055 defaultTimeout time.Duration
khenaidoo4c9e5592019-09-09 16:20:41 -040056 devicesLoadingLock sync.RWMutex
57 deviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040058}
59
Kent Hagerman45a13e42020-04-13 12:23:50 -040060func NewManagers(proxy *model.Proxy, adapterMgr *adapter.Manager, kmp kafka.InterContainerProxy, endpointMgr kafka.EndpointManager, corePairTopic, coreInstanceID string, defaultCoreTimeout time.Duration) (*Manager, *LogicalManager) {
Kent Hagerman2b216042020-04-03 18:28:56 -040061 deviceMgr := &Manager{
Kent Hagerman2b216042020-04-03 18:28:56 -040062 rootDevices: make(map[string]bool),
63 kafkaICProxy: kmp,
64 adapterProxy: remote.NewAdapterProxy(kmp, corePairTopic, endpointMgr),
65 coreInstanceID: coreInstanceID,
66 clusterDataProxy: proxy,
67 adapterMgr: adapterMgr,
68 defaultTimeout: defaultCoreTimeout * time.Millisecond,
69 deviceLoadingInProgress: make(map[string][]chan int),
70 }
Kent Hagerman2f0d0552020-04-23 17:28:52 -040071 deviceMgr.stateTransitions = NewTransitionMap(deviceMgr)
72
Kent Hagerman2b216042020-04-03 18:28:56 -040073 logicalDeviceMgr := &LogicalManager{
Kent Hagerman45a13e42020-04-13 12:23:50 -040074 Manager: event.NewManager(),
Kent Hagerman2b216042020-04-03 18:28:56 -040075 deviceMgr: deviceMgr,
76 kafkaICProxy: kmp,
77 clusterDataProxy: proxy,
78 defaultTimeout: defaultCoreTimeout,
79 logicalDeviceLoadingInProgress: make(map[string][]chan int),
80 }
81 deviceMgr.logicalDeviceMgr = logicalDeviceMgr
Matteo Scandolod525ae32020-04-02 17:27:29 -070082
Kent Hagerman2b216042020-04-03 18:28:56 -040083 adapterMgr.SetAdapterRestartedCallback(deviceMgr.adapterRestarted)
Matteo Scandolod525ae32020-04-02 17:27:29 -070084
Kent Hagerman2b216042020-04-03 18:28:56 -040085 return deviceMgr, logicalDeviceMgr
khenaidoob9203542018-09-17 22:56:37 -040086}
87
Kent Hagerman2b216042020-04-03 18:28:56 -040088func (dMgr *Manager) addDeviceAgentToMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +053089 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
90 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -040091 }
khenaidoo2c6a0992019-04-29 13:46:56 -040092 dMgr.lockRootDeviceMap.Lock()
93 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +053094 dMgr.rootDevices[agent.deviceID] = agent.isRootdevice
khenaidoo2c6a0992019-04-29 13:46:56 -040095
khenaidoob9203542018-09-17 22:56:37 -040096}
97
Kent Hagerman2b216042020-04-03 18:28:56 -040098func (dMgr *Manager) deleteDeviceAgentFromMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +053099 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400100 dMgr.lockRootDeviceMap.Lock()
101 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530102 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400103}
104
khenaidoo297cd252019-02-07 22:10:23 -0500105// getDeviceAgent returns the agent managing the device. If the device is not in memory, it will loads it, if it exists
Kent Hagerman2b216042020-04-03 18:28:56 -0400106func (dMgr *Manager) getDeviceAgent(ctx context.Context, deviceID string) *Agent {
npujar1d86a522019-11-14 17:11:16 +0530107 agent, ok := dMgr.deviceAgents.Load(deviceID)
108 if ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400109 return agent.(*Agent)
khenaidoob9203542018-09-17 22:56:37 -0400110 }
khenaidoo442e7c72020-03-10 16:13:48 -0400111 // Try to load into memory - loading will also create the device agent and set the device ownership
npujar467fe752020-01-16 20:17:45 +0530112 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530113 if err == nil {
114 agent, ok = dMgr.deviceAgents.Load(deviceID)
115 if !ok {
116 return nil
117 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400118 return agent.(*Agent)
npujar1d86a522019-11-14 17:11:16 +0530119 }
120 //TODO: Change the return params to return an error as well
Girish Kumarf56a4682020-03-20 20:07:46 +0000121 logger.Errorw("loading-device-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400122 return nil
123}
124
khenaidoo297cd252019-02-07 22:10:23 -0500125// listDeviceIdsFromMap returns the list of device IDs that are in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400126func (dMgr *Manager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500127 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400128
129 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
130 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
131 return true
132 })
133
khenaidoo7ccedd52018-12-14 16:48:54 -0500134 return result
135}
136
Kent Hagerman45a13e42020-04-13 12:23:50 -0400137// CreateDevice creates a new parent device in the data model
138func (dMgr *Manager) CreateDevice(ctx context.Context, device *voltha.Device) (*voltha.Device, error) {
139 if device.MacAddress == "" && device.GetHostAndPort() == "" {
140 logger.Errorf("No Device Info Present")
141 return &voltha.Device{}, errors.New("no-device-info-present; MAC or HOSTIP&PORT")
142 }
143 logger.Debugw("create-device", log.Fields{"device": *device})
144
npujar467fe752020-01-16 20:17:45 +0530145 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530146 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000147 logger.Errorf("Failed to fetch parent device info")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400148 return nil, err
Thomas Lee Se5a44012019-11-07 20:32:24 +0530149 }
150 if deviceExist {
Girish Kumarf56a4682020-03-20 20:07:46 +0000151 logger.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400152 return nil, errors.New("device is already pre-provisioned")
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530153 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400154 logger.Debugw("CreateDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400155
khenaidoo5e677ae2019-02-28 17:26:29 -0500156 // Ensure this device is set as root
157 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400158 // Create and start a device agent for that device
Kent Hagerman2b216042020-04-03 18:28:56 -0400159 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530160 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800161 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000162 logger.Errorw("Fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400163 return nil, err
Scott Baker80678602019-11-14 16:57:36 -0800164 }
khenaidoo442e7c72020-03-10 16:13:48 -0400165 dMgr.addDeviceAgentToMap(agent)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400166 return device, nil
khenaidoob9203542018-09-17 22:56:37 -0400167}
168
Kent Hagerman45a13e42020-04-13 12:23:50 -0400169// EnableDevice activates a device by invoking the adopt_device API on the appropriate adapter
170func (dMgr *Manager) EnableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
171 logger.Debugw("EnableDevice", log.Fields{"device-id": id.Id})
172 agent := dMgr.getDeviceAgent(ctx, id.Id)
173 if agent == nil {
174 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400175 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400176 return &empty.Empty{}, agent.enableDevice(ctx)
khenaidoob9203542018-09-17 22:56:37 -0400177}
178
Kent Hagerman45a13e42020-04-13 12:23:50 -0400179// DisableDevice disables a device along with any child device it may have
180func (dMgr *Manager) DisableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
181 logger.Debugw("DisableDevice", log.Fields{"device-id": id.Id})
182 agent := dMgr.getDeviceAgent(ctx, id.Id)
183 if agent == nil {
184 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400185 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400186 return &empty.Empty{}, agent.disableDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400187}
188
Kent Hagerman45a13e42020-04-13 12:23:50 -0400189//RebootDevice invoked the reboot API to the corresponding adapter
190func (dMgr *Manager) RebootDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
191 logger.Debugw("RebootDevice", log.Fields{"device-id": id.Id})
192 agent := dMgr.getDeviceAgent(ctx, id.Id)
193 if agent == nil {
194 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400195 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400196 return &empty.Empty{}, agent.rebootDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400197}
198
Kent Hagerman45a13e42020-04-13 12:23:50 -0400199// DeleteDevice removes a device from the data model
200func (dMgr *Manager) DeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
201 logger.Debugw("DeleteDevice", log.Fields{"device-id": id.Id})
202 agent := dMgr.getDeviceAgent(ctx, id.Id)
203 if agent == nil {
204 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400205 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400206 return &empty.Empty{}, agent.deleteDevice(ctx)
207}
208
209// ListDevicePorts returns the ports details for a specific device entry
210func (dMgr *Manager) ListDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.Ports, error) {
211 logger.Debugw("ListDevicePorts", log.Fields{"device-id": id.Id})
212 device, err := dMgr.getDevice(ctx, id.Id)
213 if err != nil {
214 return &voltha.Ports{}, err
215 }
216 return &voltha.Ports{Items: device.Ports}, nil
217}
218
219// ListDeviceFlows returns the flow details for a specific device entry
220func (dMgr *Manager) ListDeviceFlows(ctx context.Context, id *voltha.ID) (*ofp.Flows, error) {
221 logger.Debugw("ListDeviceFlows", log.Fields{"device-id": id.Id})
222 device, err := dMgr.getDevice(ctx, id.Id)
223 if err != nil {
224 return &ofp.Flows{}, err
225 }
226 return device.Flows, nil
227}
228
229// ListDeviceFlowGroups returns the flow group details for a specific device entry
230func (dMgr *Manager) ListDeviceFlowGroups(ctx context.Context, id *voltha.ID) (*voltha.FlowGroups, error) {
231 logger.Debugw("ListDeviceFlowGroups", log.Fields{"device-id": id.Id})
232
233 device, err := dMgr.getDevice(ctx, id.Id)
234 if err != nil {
235 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
236 }
237 return device.GetFlowGroups(), nil
khenaidoo4d4802d2018-10-04 21:59:49 -0400238}
239
khenaidoo6d62c002019-05-15 21:57:03 -0400240// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
241// This function is called only in the Core that does not own this device. In the Core that owns this device then a
242// deletion deletion also includes removal of any reference of this device.
Kent Hagerman2b216042020-04-03 18:28:56 -0400243func (dMgr *Manager) stopManagingDevice(ctx context.Context, id string) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000244 logger.Infow("stopManagingDevice", log.Fields{"deviceId": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400245 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
npujar1d86a522019-11-14 17:11:16 +0530246 if root, _ := dMgr.IsRootDevice(id); root {
khenaidoo6d62c002019-05-15 21:57:03 -0400247 // stop managing the logical device
David Bainbridged1afd662020-03-26 18:27:41 -0700248 _ = dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
khenaidoo6d62c002019-05-15 21:57:03 -0400249 }
npujar467fe752020-01-16 20:17:45 +0530250 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400251 if err := agent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000252 logger.Warnw("unable-to-stop-device-agent", log.Fields{"device-id": agent.deviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400253 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400254 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400255 }
256 }
257}
258
npujar1d86a522019-11-14 17:11:16 +0530259// RunPostDeviceDelete removes any reference of this device
Kent Hagerman2b216042020-04-03 18:28:56 -0400260func (dMgr *Manager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000261 logger.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530262 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400263 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400264}
265
Kent Hagerman45a13e42020-04-13 12:23:50 -0400266func (dMgr *Manager) GetDevice(ctx context.Context, id *voltha.ID) (*voltha.Device, error) {
267 return dMgr.getDevice(ctx, id.Id)
268}
269
270// getDevice will returns a device, either from memory or from the dB, if present
271func (dMgr *Manager) getDevice(ctx context.Context, id string) (*voltha.Device, error) {
272 logger.Debugw("getDevice", log.Fields{"deviceid": id})
npujar467fe752020-01-16 20:17:45 +0530273 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400274 return agent.getDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400275 }
276 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400277}
278
npujar1d86a522019-11-14 17:11:16 +0530279// GetChildDevice will return a device, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -0400280func (dMgr *Manager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000281 logger.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
npujar1d86a522019-11-14 17:11:16 +0530282 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500283
284 var parentDevice *voltha.Device
285 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -0400286 if parentDevice, err = dMgr.getDevice(ctx, parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500287 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
288 }
289 var childDeviceIds []string
290 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
291 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
292 }
293 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000294 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530295 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500296 }
297
298 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530299 for _, childDeviceID := range childDeviceIds {
300 var found bool
Kent Hagerman45a13e42020-04-13 12:23:50 -0400301 if searchDevice, err := dMgr.getDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500302
npujar1d86a522019-11-14 17:11:16 +0530303 foundOnuID := false
304 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500305 if searchDevice.ParentPortNo == uint32(parentPortNo) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000306 logger.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530307 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500308 }
309 }
310
311 foundSerialNumber := false
312 if searchDevice.SerialNumber == serialNumber {
Girish Kumarf56a4682020-03-20 20:07:46 +0000313 logger.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500314 foundSerialNumber = true
315 }
316
317 // if both onuId and serialNumber are provided both must be true for the device to be found
318 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530319 if onuID > 0 && serialNumber != "" {
320 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500321 } else {
npujar1d86a522019-11-14 17:11:16 +0530322 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500323 }
324
npujar1d86a522019-11-14 17:11:16 +0530325 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500326 foundChildDevice = searchDevice
327 break
328 }
329 }
330 }
331
332 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000333 logger.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500334 return foundChildDevice, nil
335 }
336
Girish Kumarf56a4682020-03-20 20:07:46 +0000337 logger.Warnw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530338 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
339 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500340}
341
npujar1d86a522019-11-14 17:11:16 +0530342// GetChildDeviceWithProxyAddress will return a device based on proxy address
Kent Hagerman2b216042020-04-03 18:28:56 -0400343func (dMgr *Manager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000344 logger.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500345
346 var parentDevice *voltha.Device
347 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -0400348 if parentDevice, err = dMgr.getDevice(ctx, proxyAddress.DeviceId); err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500349 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
350 }
351 var childDeviceIds []string
352 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
353 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
354 }
355 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000356 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500357 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
358 }
359
360 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530361 for _, childDeviceID := range childDeviceIds {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400362 if searchDevice, err := dMgr.getDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500363 if searchDevice.ProxyAddress == proxyAddress {
364 foundChildDevice = searchDevice
365 break
366 }
367 }
368 }
369
370 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000371 logger.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500372 return foundChildDevice, nil
373 }
374
Girish Kumarf56a4682020-03-20 20:07:46 +0000375 logger.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500376 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
377}
378
npujar1d86a522019-11-14 17:11:16 +0530379// IsDeviceInCache returns true if device is found in the map
Kent Hagerman2b216042020-04-03 18:28:56 -0400380func (dMgr *Manager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400381 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500382 return exist
383}
384
npujar1d86a522019-11-14 17:11:16 +0530385// IsRootDevice returns true if root device is found in the map
Kent Hagerman2b216042020-04-03 18:28:56 -0400386func (dMgr *Manager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400387 dMgr.lockRootDeviceMap.RLock()
388 defer dMgr.lockRootDeviceMap.RUnlock()
389 if exist := dMgr.rootDevices[id]; exist {
390 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400391 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400392 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400393}
394
Stephane Barbarieaa467942019-02-06 14:09:44 -0500395// ListDevices retrieves the latest devices from the data model
Kent Hagerman45a13e42020-04-13 12:23:50 -0400396func (dMgr *Manager) ListDevices(ctx context.Context, _ *empty.Empty) (*voltha.Devices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000397 logger.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400398 result := &voltha.Devices{}
Kent Hagerman4f355f52020-03-30 16:01:33 -0400399
400 var devices []*voltha.Device
401 if err := dMgr.clusterDataProxy.List(ctx, "devices", &devices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000402 logger.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530403 return nil, err
404 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400405
406 for _, device := range devices {
407 // If device is not in memory then set it up
408 if !dMgr.IsDeviceInCache(device.Id) {
409 logger.Debugw("loading-device-from-Model", log.Fields{"id": device.Id})
Kent Hagerman2b216042020-04-03 18:28:56 -0400410 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
Kent Hagerman4f355f52020-03-30 16:01:33 -0400411 if _, err := agent.start(ctx, nil); err != nil {
412 logger.Warnw("failure-starting-agent", log.Fields{"deviceId": device.Id})
413 } else {
414 dMgr.addDeviceAgentToMap(agent)
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500415 }
khenaidoob9203542018-09-17 22:56:37 -0400416 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400417 result.Items = append(result.Items, device)
khenaidoob9203542018-09-17 22:56:37 -0400418 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000419 logger.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400420 return result, nil
421}
422
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530423//isParentDeviceExist checks whether device is already preprovisioned.
Kent Hagerman2b216042020-04-03 18:28:56 -0400424func (dMgr *Manager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530425 hostPort := newDevice.GetHostAndPort()
Kent Hagerman4f355f52020-03-30 16:01:33 -0400426 var devices []*voltha.Device
427 if err := dMgr.clusterDataProxy.List(ctx, "devices", &devices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000428 logger.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530429 return false, err
430 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400431 for _, device := range devices {
432 if !device.Root {
433 continue
434 }
435 if hostPort != "" && hostPort == device.GetHostAndPort() && device.AdminState != voltha.AdminState_DELETED {
436 return true, nil
437 }
438 if newDevice.MacAddress != "" && newDevice.MacAddress == device.MacAddress && device.AdminState != voltha.AdminState_DELETED {
439 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530440 }
441 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530442 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530443}
444
khenaidoo6d62c002019-05-15 21:57:03 -0400445//getDeviceFromModelretrieves the device data from the model.
Kent Hagerman2b216042020-04-03 18:28:56 -0400446func (dMgr *Manager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400447 device := &voltha.Device{}
448 if have, err := dMgr.clusterDataProxy.Get(ctx, "devices/"+deviceID, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000449 logger.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530450 return nil, err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400451 } else if !have {
452 return nil, status.Error(codes.NotFound, deviceID)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530453 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400454
455 return device, nil
khenaidoo6d62c002019-05-15 21:57:03 -0400456}
457
npujar1d86a522019-11-14 17:11:16 +0530458// loadDevice loads the deviceID in memory, if not present
Kent Hagerman2b216042020-04-03 18:28:56 -0400459func (dMgr *Manager) loadDevice(ctx context.Context, deviceID string) (*Agent, error) {
npujar1d86a522019-11-14 17:11:16 +0530460 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500461 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
462 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400463 var err error
464 var device *voltha.Device
465 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530466 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
467 if !dMgr.IsDeviceInCache(deviceID) {
468 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400469 dMgr.devicesLoadingLock.Unlock()
470 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530471 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000472 logger.Debugw("loading-device", log.Fields{"deviceId": deviceID})
Kent Hagerman2b216042020-04-03 18:28:56 -0400473 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530474 if _, err = agent.start(ctx, nil); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000475 logger.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400476 } else {
477 dMgr.addDeviceAgentToMap(agent)
478 }
479 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000480 logger.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400481 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400482 // announce completion of task to any number of waiting channels
483 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530484 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400485 for _, ch := range v {
486 close(ch)
487 }
npujar1d86a522019-11-14 17:11:16 +0530488 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400489 }
490 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400491 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400492 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500493 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400494 } else {
495 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530496 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400497 dMgr.devicesLoadingLock.Unlock()
498 // Wait for the channel to be closed, implying the process loading this device is done.
499 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500500 }
npujar1d86a522019-11-14 17:11:16 +0530501 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400502 return agent.(*Agent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500503 }
npujar1d86a522019-11-14 17:11:16 +0530504 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500505}
506
507// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400508func (dMgr *Manager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000509 logger.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500510 if device.Root {
511 // Scenario A
512 if device.ParentId != "" {
513 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530514 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000515 logger.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
khenaidoo297cd252019-02-07 22:10:23 -0500516 }
517 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000518 logger.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500519 }
520 // Load all child devices, if needed
521 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530522 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530523 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000524 logger.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500525 return err
526 }
527 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000528 logger.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
khenaidoo297cd252019-02-07 22:10:23 -0500529 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000530 logger.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500531 }
532 }
533 return nil
534}
535
536// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
537// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
538// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
539// and the proceed with the request.
Kent Hagerman2b216042020-04-03 18:28:56 -0400540func (dMgr *Manager) load(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000541 logger.Debug("load...")
khenaidoo297cd252019-02-07 22:10:23 -0500542 // First load the device - this may fail in case the device was deleted intentionally by the other core
Kent Hagerman2b216042020-04-03 18:28:56 -0400543 var dAgent *Agent
khenaidoo297cd252019-02-07 22:10:23 -0500544 var err error
npujar467fe752020-01-16 20:17:45 +0530545 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500546 return err
547 }
548 // Get the loaded device details
khenaidoo442e7c72020-03-10 16:13:48 -0400549 device, err := dAgent.getDevice(ctx)
550 if err != nil {
551 return err
552 }
khenaidoo297cd252019-02-07 22:10:23 -0500553
554 // If the device is in Pre-provisioning or deleted state stop here
555 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
556 return nil
557 }
558
559 // Now we face two scenarios
560 if device.Root {
561 // Load all children as well as the parent of this device (logical_device)
npujar467fe752020-01-16 20:17:45 +0530562 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000563 logger.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500564 return err
565 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000566 logger.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500567 } else {
568 // Scenario B - use the parentId of that device (root device) to trigger the loading
569 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530570 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500571 }
572 }
573 return nil
574}
575
khenaidoo7ccedd52018-12-14 16:48:54 -0500576// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400577func (dMgr *Manager) ListDeviceIds(_ context.Context, _ *empty.Empty) (*voltha.IDs, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000578 logger.Debug("ListDeviceIDs")
khenaidoo7ccedd52018-12-14 16:48:54 -0500579 // Report only device IDs that are in the device agent map
580 return dMgr.listDeviceIdsFromMap(), nil
581}
582
Kent Hagerman45a13e42020-04-13 12:23:50 -0400583// ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
584// trigger loading the devices along with their children and parent in memory
585func (dMgr *Manager) ReconcileDevices(ctx context.Context, ids *voltha.IDs) (*empty.Empty, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000586 logger.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo4c9e5592019-09-09 16:20:41 -0400587 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500588 toReconcile := len(ids.Items)
589 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400590 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500591 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530592 if err = dMgr.load(ctx, id.Id); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000593 logger.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400594 } else {
npujar1d86a522019-11-14 17:11:16 +0530595 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500596 }
597 }
598 if toReconcile != reconciled {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400599 return nil, status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500600 }
601 } else {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400602 return nil, status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
khenaidoo7ccedd52018-12-14 16:48:54 -0500603 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400604 return &empty.Empty{}, nil
khenaidoo7ccedd52018-12-14 16:48:54 -0500605}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500606
khenaidooba6b6c42019-08-02 09:11:56 -0400607// isOkToReconcile validates whether a device is in the correct status to be reconciled
608func isOkToReconcile(device *voltha.Device) bool {
609 if device == nil {
610 return false
611 }
612 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
613}
614
615// adapterRestarted is invoked whenever an adapter is restarted
Kent Hagerman2b216042020-04-03 18:28:56 -0400616func (dMgr *Manager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
Matteo Scandolod525ae32020-04-02 17:27:29 -0700617 logger.Debugw("adapter-restarted", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
618 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
khenaidooba6b6c42019-08-02 09:11:56 -0400619
620 // Let's reconcile the device managed by this Core only
David Bainbridged1afd662020-03-26 18:27:41 -0700621 if len(dMgr.rootDevices) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000622 logger.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400623 return nil
624 }
625
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500626 responses := make([]utils.Response, 0)
David Bainbridged1afd662020-03-26 18:27:41 -0700627 for rootDeviceID := range dMgr.rootDevices {
npujar467fe752020-01-16 20:17:45 +0530628 if rootDevice, _ := dMgr.getDeviceFromModel(ctx, rootDeviceID); rootDevice != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -0400629 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(rootDeviceID, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700630 if err != nil {
631 logger.Warnw("is-device-owned-by-service", log.Fields{"error": err, "root-device-id": rootDeviceID, "adapterType": adapter.Type, "replica-number": adapter.CurrentReplica})
632 continue
633 }
634 if isDeviceOwnedByService {
khenaidooba6b6c42019-08-02 09:11:56 -0400635 if isOkToReconcile(rootDevice) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000636 logger.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530637 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400638 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000639 logger.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400640 }
641 } else { // Should we be reconciling the root's children instead?
642 childManagedByAdapter:
643 for _, port := range rootDevice.Ports {
644 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530645 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -0400646 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(childDevice.Id, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700647 if err != nil {
648 logger.Warnw("is-device-owned-by-service", log.Fields{"error": err, "child-device-id": childDevice.Id, "adapterType": adapter.Type, "replica-number": adapter.CurrentReplica})
649 }
650 if isDeviceOwnedByService {
khenaidooba6b6c42019-08-02 09:11:56 -0400651 if isOkToReconcile(childDevice) {
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700652 logger.Debugw("reconciling-child-device", log.Fields{"child-device-id": childDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530653 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400654 } else {
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700655 logger.Debugw("not-reconciling-child-device", log.Fields{"child-device-id": childDevice.Id, "state": childDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400656 }
657 } else {
658 // All child devices under a parent device are typically managed by the same adapter type.
659 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
660 break childManagedByAdapter
661 }
662 }
663 }
664 }
665 }
666 }
667 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500668 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400669 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500670 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400671 return status.Errorf(codes.Aborted, "errors-%s", res)
672 }
673 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000674 logger.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400675 }
676 return nil
677}
678
Kent Hagerman2b216042020-04-03 18:28:56 -0400679func (dMgr *Manager) sendReconcileDeviceRequest(ctx context.Context, device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400680 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
681 // point of creating a device agent (if the device is not being managed by this Core) before sending the request
npujar1d86a522019-11-14 17:11:16 +0530682 // to the adapter. We will therefore bypass the adapter adapter and send the request directly to the adapter via
Kent Hagerman2b216042020-04-03 18:28:56 -0400683 // the adapter proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500684 response := utils.NewResponse()
Kent Hagerman2b216042020-04-03 18:28:56 -0400685 ch, err := dMgr.adapterProxy.ReconcileDevice(ctx, device)
khenaidoo442e7c72020-03-10 16:13:48 -0400686 if err != nil {
687 response.Error(err)
688 }
689 // Wait for adapter response in its own routine
690 go func() {
691 resp, ok := <-ch
692 if !ok {
693 response.Error(status.Errorf(codes.Aborted, "channel-closed-device: %s", device.Id))
694 } else if resp.Err != nil {
695 response.Error(resp.Err)
khenaidooba6b6c42019-08-02 09:11:56 -0400696 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500697 response.Done()
khenaidoo442e7c72020-03-10 16:13:48 -0400698 }()
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500699 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400700}
701
Kent Hagerman2b216042020-04-03 18:28:56 -0400702func (dMgr *Manager) ReconcileChildDevices(ctx context.Context, parentDeviceID string) error {
npujar467fe752020-01-16 20:17:45 +0530703 if parentDevice, _ := dMgr.getDeviceFromModel(ctx, parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500704 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400705 for _, port := range parentDevice.Ports {
706 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530707 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
708 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400709 }
710 }
711 }
712 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500713 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400714 return status.Errorf(codes.Aborted, "errors-%s", res)
715 }
716 }
717 return nil
718}
719
Kent Hagerman2b216042020-04-03 18:28:56 -0400720func (dMgr *Manager) UpdateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
721 logger.Debugw("UpdateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530722 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
723 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400724 }
725 return status.Errorf(codes.NotFound, "%s", device.Id)
726}
727
Kent Hagerman2b216042020-04-03 18:28:56 -0400728func (dMgr *Manager) AddPort(ctx context.Context, deviceID string, port *voltha.Port) error {
npujar467fe752020-01-16 20:17:45 +0530729 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530730 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530731 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400732 return err
733 }
734 // Setup peer ports
npujar1d86a522019-11-14 17:11:16 +0530735 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
khenaidoo92e62c52018-10-03 14:02:54 -0400736 for _, peerPort := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530737 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
738 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000739 logger.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
khenaidoo92e62c52018-10-03 14:02:54 -0400740 return err
741 }
742 }
743 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400744 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
745 // then a logical port will be added to the logical device and the device graph generated. If the port is a
746 // PON port then only the device graph will be generated.
Kent Hagerman45a13e42020-04-13 12:23:50 -0400747 if device, err := dMgr.getDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530748 go func() {
npujar467fe752020-01-16 20:17:45 +0530749 err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, port)
npujar1d86a522019-11-14 17:11:16 +0530750 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000751 logger.Errorw("unable-to-update-logical-port", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530752 }
753 }()
khenaidoo2c6a0992019-04-29 13:46:56 -0400754 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000755 logger.Errorw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -0400756 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400757 }
khenaidoo92e62c52018-10-03 14:02:54 -0400758 return nil
khenaidoob9203542018-09-17 22:56:37 -0400759 }
npujar1d86a522019-11-14 17:11:16 +0530760 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400761}
762
Kent Hagerman2b216042020-04-03 18:28:56 -0400763func (dMgr *Manager) addFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000764 logger.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530765 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
766 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400767 }
npujar1d86a522019-11-14 17:11:16 +0530768 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400769}
770
khenaidoo787224a2020-04-16 18:08:47 -0400771// deleteParentFlows removes flows from the parent device based on specific attributes
772func (dMgr *Manager) deleteParentFlows(ctx context.Context, deviceID string, uniPort uint32, metadata *voltha.FlowMetadata) error {
773 logger.Debugw("deleteParentFlows", log.Fields{"device-id": deviceID, "uni-port": uniPort, "metadata": metadata})
774 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
775 if !agent.isRootdevice {
776 return status.Errorf(codes.FailedPrecondition, "not-a-parent-device-%s", deviceID)
777 }
778 return agent.filterOutFlows(ctx, uniPort, metadata)
779 }
780 return status.Errorf(codes.NotFound, "%s", deviceID)
781}
782
Kent Hagerman2b216042020-04-03 18:28:56 -0400783func (dMgr *Manager) deleteFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000784 logger.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530785 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
786 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400787 }
npujar1d86a522019-11-14 17:11:16 +0530788 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400789}
790
Kent Hagerman2b216042020-04-03 18:28:56 -0400791func (dMgr *Manager) updateFlowsAndGroups(ctx context.Context, deviceID string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry, flowMetadata *voltha.FlowMetadata) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000792 logger.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530793 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
794 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400795 }
npujar1d86a522019-11-14 17:11:16 +0530796 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400797}
798
Kent Hagerman45a13e42020-04-13 12:23:50 -0400799// UpdateDevicePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
khenaidoob3127472019-07-24 21:04:55 -0400800// following a user action
Kent Hagerman45a13e42020-04-13 12:23:50 -0400801func (dMgr *Manager) UpdateDevicePmConfigs(ctx context.Context, configs *voltha.PmConfigs) (*empty.Empty, error) {
802 if configs.Id == "" {
803 return nil, status.Error(codes.FailedPrecondition, "invalid-device-Id")
khenaidoob3127472019-07-24 21:04:55 -0400804 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400805 agent := dMgr.getDeviceAgent(ctx, configs.Id)
806 if agent == nil {
807 return nil, status.Errorf(codes.NotFound, "%s", configs.Id)
808 }
809 return &empty.Empty{}, agent.updatePmConfigs(ctx, configs)
khenaidoob3127472019-07-24 21:04:55 -0400810}
811
Kent Hagerman2b216042020-04-03 18:28:56 -0400812// InitPmConfigs initialize the pm configs as defined by the adapter.
813func (dMgr *Manager) InitPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400814 if pmConfigs.Id == "" {
815 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
816 }
npujar467fe752020-01-16 20:17:45 +0530817 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
818 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400819 }
npujar1d86a522019-11-14 17:11:16 +0530820 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400821}
822
Kent Hagerman45a13e42020-04-13 12:23:50 -0400823// ListDevicePmConfigs returns pm configs of device
824func (dMgr *Manager) ListDevicePmConfigs(ctx context.Context, id *voltha.ID) (*voltha.PmConfigs, error) {
825 agent := dMgr.getDeviceAgent(ctx, id.Id)
826 if agent == nil {
827 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob3127472019-07-24 21:04:55 -0400828 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400829 return agent.listPmConfigs(ctx)
khenaidoob3127472019-07-24 21:04:55 -0400830}
831
Kent Hagerman2b216042020-04-03 18:28:56 -0400832func (dMgr *Manager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000833 logger.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530834 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400835 return agent.getSwitchCapability(ctx)
836 }
npujar1d86a522019-11-14 17:11:16 +0530837 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400838}
839
Kent Hagerman2b216042020-04-03 18:28:56 -0400840func (dMgr *Manager) GetPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
841 logger.Debugw("GetPorts", log.Fields{"deviceid": deviceID, "portType": portType})
npujar467fe752020-01-16 20:17:45 +0530842 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400843 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400844 }
npujar1d86a522019-11-14 17:11:16 +0530845 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400846}
847
Kent Hagerman2b216042020-04-03 18:28:56 -0400848func (dMgr *Manager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000849 logger.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530850 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400851 return agent.getPortCapability(ctx, portNo)
852 }
npujar1d86a522019-11-14 17:11:16 +0530853 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400854}
855
Kent Hagerman2b216042020-04-03 18:28:56 -0400856func (dMgr *Manager) UpdateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
857 logger.Debugw("UpdateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530858 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
859 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400860 }
npujar1d86a522019-11-14 17:11:16 +0530861 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400862}
863
Kent Hagerman2b216042020-04-03 18:28:56 -0400864func (dMgr *Manager) UpdateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
865 logger.Debugw("UpdateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400866 var parentDevice *voltha.Device
867 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -0400868 if parentDevice, err = dMgr.getDevice(ctx, deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400869 return status.Errorf(codes.Aborted, "%s", err.Error())
870 }
871 var childDeviceIds []string
872 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
873 return status.Errorf(codes.Aborted, "%s", err.Error())
874 }
875 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000876 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400877 }
npujar1d86a522019-11-14 17:11:16 +0530878 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530879 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
880 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530881 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400882 }
883 }
884 }
885 return nil
886}
887
Kent Hagerman2b216042020-04-03 18:28:56 -0400888func (dMgr *Manager) UpdatePortState(ctx context.Context, deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
889 logger.Debugw("UpdatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530890 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
891 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000892 logger.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400893 return err
894 }
895 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800896 // Do this for NNI and UNIs only. PON ports are not known by logical device
897 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
898 go func() {
899 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
900 if err != nil {
901 // While we want to handle (catch) and log when
902 // an update to a port was not able to be
903 // propagated to the logical port, we can report
904 // it as a warning and not an error because it
905 // doesn't stop or modify processing.
906 // TODO: VOL-2707
Girish Kumarf56a4682020-03-20 20:07:46 +0000907 logger.Warnw("unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800908 }
909 }()
910 }
khenaidoo442e7c72020-03-10 16:13:48 -0400911 return nil
khenaidoob9203542018-09-17 22:56:37 -0400912 }
npujar1d86a522019-11-14 17:11:16 +0530913 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400914}
915
Kent Hagerman2b216042020-04-03 18:28:56 -0400916func (dMgr *Manager) DeleteAllPorts(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000917 logger.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530918 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
919 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400920 return err
921 }
922 // Notify the logical device manager to remove all logical ports, if needed.
Kent Hagerman2b216042020-04-03 18:28:56 -0400923 // At this stage the device itself may gave been deleted already at a DeleteAllPorts
khenaidoo0a822f92019-05-08 15:15:57 -0400924 // typically is part of a device deletion phase.
Kent Hagerman45a13e42020-04-13 12:23:50 -0400925 if device, err := dMgr.getDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530926 go func() {
npujar467fe752020-01-16 20:17:45 +0530927 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530928 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000929 logger.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530930 }
931 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400932 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000933 logger.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400934 return err
935 }
936 return nil
937 }
npujar1d86a522019-11-14 17:11:16 +0530938 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400939}
940
Kent Hagerman2b216042020-04-03 18:28:56 -0400941//UpdatePortsState updates all ports on the device
942func (dMgr *Manager) UpdatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
943 logger.Debugw("UpdatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400944
npujar467fe752020-01-16 20:17:45 +0530945 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400946 switch state {
947 case voltha.OperStatus_ACTIVE:
kesavandbc2d1622020-01-21 00:42:01 -0500948 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000949 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400950 return err
951 }
952 case voltha.OperStatus_UNKNOWN:
kesavandbc2d1622020-01-21 00:42:01 -0500953 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000954 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400955 return err
956 }
957 default:
958 return status.Error(codes.Unimplemented, "state-change-not-implemented")
959 }
960 // Notify the logical device about the state change
Kent Hagerman45a13e42020-04-13 12:23:50 -0400961 device, err := dMgr.getDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530962 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000963 logger.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400964 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400965 }
kesavandbc2d1622020-01-21 00:42:01 -0500966 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000967 logger.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
npujar1d86a522019-11-14 17:11:16 +0530968 return err
969 }
970 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400971 }
npujar1d86a522019-11-14 17:11:16 +0530972 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400973}
974
Kent Hagerman2b216042020-04-03 18:28:56 -0400975func (dMgr *Manager) ChildDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530976 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
Kent Hagerman2b216042020-04-03 18:28:56 -0400977 logger.Debugw("ChildDeviceDetected", log.Fields{"parentDeviceId": parentDeviceID, "parentPortNo": parentPortNo, "deviceType": deviceType, "channelId": channelID, "vendorId": vendorID, "serialNumber": serialNumber, "onuId": onuID})
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700978
npujar1d86a522019-11-14 17:11:16 +0530979 if deviceType == "" && vendorID != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000980 logger.Debug("device-type-is-nil-fetching-device-type")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400981 deviceTypes, err := dMgr.adapterMgr.ListDeviceTypes(ctx, nil)
982 if err != nil {
983 return nil, err
984 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400985 OLoop:
Kent Hagerman45a13e42020-04-13 12:23:50 -0400986 for _, dType := range deviceTypes.Items {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400987 for _, v := range dType.VendorIds {
988 if v == vendorID {
989 deviceType = dType.Adapter
990 break OLoop
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700991 }
992 }
993 }
994 }
995 //if no match found for the vendorid,report adapter with the custom error message
996 if deviceType == "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000997 logger.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
npujar1d86a522019-11-14 17:11:16 +0530998 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700999 }
khenaidoob9203542018-09-17 22:56:37 -04001000
1001 // Create the ONU device
1002 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -04001003 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +05301004 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -04001005 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +05301006 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -05001007 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -04001008 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001009
khenaidoo442e7c72020-03-10 16:13:48 -04001010 // Get parent device type
1011 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
1012 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +05301013 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001014 }
khenaidoo442e7c72020-03-10 16:13:48 -04001015 if pAgent.deviceType == "" {
1016 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
1017 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001018
npujar467fe752020-01-16 20:17:45 +05301019 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001020 logger.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001021 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001022 }
1023
khenaidoo442e7c72020-03-10 16:13:48 -04001024 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001025
1026 // Create and start a device agent for that device
Kent Hagerman2b216042020-04-03 18:28:56 -04001027 agent := newAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -04001028 childDevice, err := agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001029 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001030 logger.Errorw("error-starting-child-device", log.Fields{"parent-device-id": childDevice.ParentId, "child-device-id": agent.deviceID, "error": err})
Scott Baker80678602019-11-14 16:57:36 -08001031 return nil, err
1032 }
khenaidoo442e7c72020-03-10 16:13:48 -04001033 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -04001034
1035 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301036 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301037 go func() {
npujar467fe752020-01-16 20:17:45 +05301038 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301039 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001040 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301041 }
1042 }()
khenaidoob9203542018-09-17 22:56:37 -04001043 }
1044
khenaidoo79232702018-12-04 11:00:41 -05001045 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301046 go func() {
1047 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1048 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001049 logger.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301050 }
1051 }()
khenaidoo79232702018-12-04 11:00:41 -05001052
Scott Baker80678602019-11-14 16:57:36 -08001053 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001054}
1055
Kent Hagerman2b216042020-04-03 18:28:56 -04001056func (dMgr *Manager) processTransition(ctx context.Context, device *voltha.Device, previousState *deviceState) error {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001057 // This will be triggered on every state update
1058 logger.Debugw("state-transition", log.Fields{
1059 "device": device.Id,
1060 "prev-admin-state": previousState.Admin,
1061 "prev-oper-state": previousState.Operational,
1062 "prev-conn-state": previousState.Connection,
1063 "curr-admin-state": device.AdminState,
1064 "curr-oper-state": device.OperStatus,
1065 "curr-conn-state": device.ConnectStatus,
1066 })
1067 handlers := dMgr.stateTransitions.GetTransitionHandler(device, previousState)
khenaidoo92e62c52018-10-03 14:02:54 -04001068 if handlers == nil {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001069 logger.Debugw("no-op-transition", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001070 return nil
khenaidoob9203542018-09-17 22:56:37 -04001071 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001072 logger.Debugw("handler-found", log.Fields{"num-expectedHandlers": len(handlers), "isParent": device.Root, "current-data": device, "previous-state": previousState})
khenaidoo92e62c52018-10-03 14:02:54 -04001073 for _, handler := range handlers {
Girish Kumarf56a4682020-03-20 20:07:46 +00001074 logger.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001075 if err := handler(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001076 logger.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001077 return err
1078 }
1079 }
khenaidoob9203542018-09-17 22:56:37 -04001080 return nil
1081}
1082
Kent Hagerman2b216042020-04-03 18:28:56 -04001083func (dMgr *Manager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001084 logger.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301085 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1086 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001087 }
npujar1d86a522019-11-14 17:11:16 +05301088 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001089}
1090
npujar1d86a522019-11-14 17:11:16 +05301091// PacketIn receives packet from adapter
Kent Hagerman2b216042020-04-03 18:28:56 -04001092func (dMgr *Manager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001093 logger.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001094 // Get the logical device Id based on the deviceId
1095 var device *voltha.Device
1096 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -04001097 if device, err = dMgr.getDevice(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001098 logger.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001099 return err
1100 }
khenaidoo43c82122018-11-22 18:38:28 -05001101 if !device.Root {
Girish Kumarf56a4682020-03-20 20:07:46 +00001102 logger.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301103 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001104 }
1105
npujar467fe752020-01-16 20:17:45 +05301106 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001107 return err
1108 }
1109 return nil
1110}
1111
Kent Hagerman2b216042020-04-03 18:28:56 -04001112func (dMgr *Manager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001113 logger.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301114 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1115 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001116 }
1117 return status.Errorf(codes.NotFound, "%s", device.Id)
1118}
1119
npujar1d86a522019-11-14 17:11:16 +05301120// CreateLogicalDevice creates logical device in core
Kent Hagerman2b216042020-04-03 18:28:56 -04001121func (dMgr *Manager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001122 logger.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001123 // Verify whether the logical device has already been created
1124 if cDevice.ParentId != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001125 logger.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001126 return nil
1127 }
khenaidoob9203542018-09-17 22:56:37 -04001128 var err error
npujar467fe752020-01-16 20:17:45 +05301129 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001130 logger.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001131 return err
1132 }
khenaidoob9203542018-09-17 22:56:37 -04001133 return nil
1134}
1135
npujar1d86a522019-11-14 17:11:16 +05301136// DeleteLogicalDevice deletes logical device from core
Kent Hagerman2b216042020-04-03 18:28:56 -04001137func (dMgr *Manager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001138 logger.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001139 var err error
npujar467fe752020-01-16 20:17:45 +05301140 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001141 logger.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001142 return err
1143 }
1144 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301145 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301146 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001147 return nil
1148}
1149
npujar1d86a522019-11-14 17:11:16 +05301150// DeleteLogicalPort removes the logical port associated with a device
Kent Hagerman2b216042020-04-03 18:28:56 -04001151func (dMgr *Manager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001152 logger.Info("deleteLogicalPort")
khenaidoo92e62c52018-10-03 14:02:54 -04001153 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001154 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301155 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301156 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001157 logger.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001158 return err
1159 }
npujar467fe752020-01-16 20:17:45 +05301160 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001161 logger.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001162 return err
1163 }
khenaidoo92e62c52018-10-03 14:02:54 -04001164 return nil
1165}
1166
npujar1d86a522019-11-14 17:11:16 +05301167// DeleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagerman2b216042020-04-03 18:28:56 -04001168func (dMgr *Manager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001169 logger.Debugw("delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001170 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001171 // Just log the error. The logical device or port may already have been deleted before this callback is invoked.
Girish Kumarf56a4682020-03-20 20:07:46 +00001172 logger.Warnw("deleteLogical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001173 }
1174 return nil
1175}
1176
Kent Hagerman2b216042020-04-03 18:28:56 -04001177func (dMgr *Manager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001178 // Sanity check
1179 if childDevice.Root {
1180 // childDevice is the parent device
1181 return childDevice
1182 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001183 parentDevice, _ := dMgr.getDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001184 return parentDevice
1185}
1186
Kent Hagerman2b216042020-04-03 18:28:56 -04001187//ChildDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
khenaidoo0a822f92019-05-08 15:15:57 -04001188//cannot manage the child devices. This will trigger the Core to disable all the child devices.
Kent Hagerman2b216042020-04-03 18:28:56 -04001189func (dMgr *Manager) ChildDevicesLost(ctx context.Context, parentDeviceID string) error {
1190 logger.Debug("ChildDevicesLost")
khenaidoo0a822f92019-05-08 15:15:57 -04001191 var err error
1192 var parentDevice *voltha.Device
Kent Hagerman45a13e42020-04-13 12:23:50 -04001193 if parentDevice, err = dMgr.getDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001194 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001195 return err
1196 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001197 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001198}
1199
Kent Hagerman2b216042020-04-03 18:28:56 -04001200//ChildDevicesDetected is invoked by an adapter when child devices are found, typically after after a
khenaidoo0a822f92019-05-08 15:15:57 -04001201// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
Kent Hagerman2b216042020-04-03 18:28:56 -04001202func (dMgr *Manager) ChildDevicesDetected(ctx context.Context, parentDeviceID string) error {
1203 logger.Debug("ChildDevicesDetected")
khenaidoo0a822f92019-05-08 15:15:57 -04001204 var err error
1205 var parentDevice *voltha.Device
1206 var childDeviceIds []string
1207
Kent Hagerman45a13e42020-04-13 12:23:50 -04001208 if parentDevice, err = dMgr.getDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001209 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001210 return err
1211 }
1212
1213 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1214 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1215 }
1216 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001217 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo0a822f92019-05-08 15:15:57 -04001218 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001219 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301220 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301221 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001222 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301223 go func() {
npujar467fe752020-01-16 20:17:45 +05301224 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301225 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001226 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301227 }
1228 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001229 } else {
npujar1d86a522019-11-14 17:11:16 +05301230 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
Girish Kumarf56a4682020-03-20 20:07:46 +00001231 logger.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001232 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001233 }
1234 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001235 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001236 return err
1237 }
1238 return nil
1239}
1240
khenaidoo4d4802d2018-10-04 21:59:49 -04001241/*
1242All the functions below are callback functions where they are invoked with the latest and previous data. We can
1243therefore use the data as is without trying to get the latest from the model.
1244*/
1245
khenaidoo0a822f92019-05-08 15:15:57 -04001246//DisableAllChildDevices is invoked as a callback when the parent device is disabled
Kent Hagerman2b216042020-04-03 18:28:56 -04001247func (dMgr *Manager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001248 logger.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001249 var childDeviceIds []string
1250 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001251 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1252 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001253 }
1254 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001255 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001256 }
npujar1d86a522019-11-14 17:11:16 +05301257 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301258 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1259 if err = agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001260 // Just log the error - this error happens only if the child device was already in deleted state.
Girish Kumarf56a4682020-03-20 20:07:46 +00001261 logger.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001262 }
1263 }
1264 }
1265 return nil
1266}
1267
khenaidoo0a822f92019-05-08 15:15:57 -04001268//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
Kent Hagerman2b216042020-04-03 18:28:56 -04001269func (dMgr *Manager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001270 logger.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001271 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001272 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001273 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1274 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001275 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001276 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001277 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -04001278 }
npujar1d86a522019-11-14 17:11:16 +05301279 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301280 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1281 if err = agent.deleteDevice(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001282 logger.Warnw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001283 }
khenaidoo49085352020-01-13 19:15:43 -05001284 // No further action is required here. The deleteDevice will change the device state where the resulting
1285 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001286 }
1287 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001288 return nil
1289}
1290
Hardik Windlassc704def2020-02-26 18:23:19 +00001291//DeleteAllUNILogicalPorts is invoked as a callback when the parent device is deleted
Kent Hagerman2b216042020-04-03 18:28:56 -04001292func (dMgr *Manager) DeleteAllUNILogicalPorts(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001293 logger.Debugw("delete-all-uni-logical-ports", log.Fields{"parent-device-id": curr.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001294 if err := dMgr.logicalDeviceMgr.deleteAllUNILogicalPorts(ctx, curr); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001295 // Just log the error and let the remaining pipeline proceed - ports may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001296 logger.Warnw("delete-all-uni-logical-ports-failed", log.Fields{"parent-device-id": curr.Id, "error": err})
Hardik Windlassc704def2020-02-26 18:23:19 +00001297 }
1298 return nil
1299}
1300
Girish Gowdra408cd962020-03-11 14:31:31 -07001301//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001302func (dMgr *Manager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001303 logger.Debugw("delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001304 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001305 // Just log error as logical device may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001306 logger.Warnw("delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001307 }
1308 return nil
1309}
1310
1311//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001312func (dMgr *Manager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001313 logger.Debugw("delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001314 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1315 if err := agent.deleteAllFlows(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001316 logger.Errorw("error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001317 return err
1318 }
1319 return nil
1320 }
1321 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1322}
1323
khenaidoo4d4802d2018-10-04 21:59:49 -04001324//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
Kent Hagerman2b216042020-04-03 18:28:56 -04001325func (dMgr *Manager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001326 logger.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001327 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001328 if parentDevice != nil {
1329 for _, port := range parentDevice.Ports {
1330 for _, peer := range port.Peers {
1331 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1332 }
khenaidoo92e62c52018-10-03 14:02:54 -04001333 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001334 logger.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001335 }
1336 return childDeviceIds, nil
1337}
1338
Kent Hagerman2b216042020-04-03 18:28:56 -04001339//GetAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1340func (dMgr *Manager) GetAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
1341 logger.Debugw("GetAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001342 if parentDevice, err := dMgr.getDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001343 childDevices := make([]*voltha.Device, 0)
1344 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301345 for _, deviceID := range childDeviceIds {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001346 if d, e := dMgr.getDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001347 childDevices = append(childDevices, d)
1348 }
1349 }
1350 }
1351 return &voltha.Devices{Items: childDevices}, nil
1352 }
npujar1d86a522019-11-14 17:11:16 +05301353 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001354}
1355
npujar1d86a522019-11-14 17:11:16 +05301356// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
Kent Hagerman2b216042020-04-03 18:28:56 -04001357func (dMgr *Manager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001358 logger.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301359 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001360 logger.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001361 return err
1362 }
1363 return nil
1364}
1365
Kent Hagerman45a13e42020-04-13 12:23:50 -04001366// convenience to avoid redefining
1367var operationFailureResp = &common.OperationResp{Code: voltha.OperationResp_OPERATION_FAILURE}
1368
1369// DownloadImage execute an image download request
1370func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1371 logger.Debugw("DownloadImage", log.Fields{"device-id": img.Id, "imageName": img.Name})
1372 agent := dMgr.getDeviceAgent(ctx, img.Id)
1373 if agent == nil {
1374 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001375 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001376 resp, err := agent.downloadImage(ctx, img)
1377 if err != nil {
1378 return operationFailureResp, err
1379 }
1380 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001381}
1382
Kent Hagerman45a13e42020-04-13 12:23:50 -04001383// CancelImageDownload cancels image download request
1384func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1385 logger.Debugw("CancelImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
1386 agent := dMgr.getDeviceAgent(ctx, img.Id)
1387 if agent == nil {
1388 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001389 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001390 resp, err := agent.cancelImageDownload(ctx, img)
1391 if err != nil {
1392 return operationFailureResp, err
1393 }
1394 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001395}
1396
Kent Hagerman45a13e42020-04-13 12:23:50 -04001397// ActivateImageUpdate activates image update request
1398func (dMgr *Manager) ActivateImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1399 logger.Debugw("ActivateImageUpdate", log.Fields{"device-id": img.Id, "imageName": img.Name})
1400 agent := dMgr.getDeviceAgent(ctx, img.Id)
1401 if agent == nil {
1402 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001403 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001404 resp, err := agent.activateImage(ctx, img)
1405 if err != nil {
1406 return operationFailureResp, err
1407 }
1408 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001409}
1410
Kent Hagerman45a13e42020-04-13 12:23:50 -04001411// RevertImageUpdate reverts image update
1412func (dMgr *Manager) RevertImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1413 logger.Debugw("RevertImageUpdate", log.Fields{"device-id": img.Id, "imageName": img.Name})
1414 agent := dMgr.getDeviceAgent(ctx, img.Id)
1415 if agent == nil {
1416 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001417 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001418 resp, err := agent.revertImage(ctx, img)
1419 if err != nil {
1420 return operationFailureResp, err
1421 }
1422 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001423}
1424
Kent Hagerman45a13e42020-04-13 12:23:50 -04001425// convenience to avoid redefining
1426var imageDownloadFailureResp = &voltha.ImageDownload{DownloadState: voltha.ImageDownload_DOWNLOAD_UNKNOWN}
1427
1428// GetImageDownloadStatus returns status of image download
1429func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1430 logger.Debugw("GetImageDownloadStatus", log.Fields{"device-id": img.Id, "imageName": img.Name})
1431 agent := dMgr.getDeviceAgent(ctx, img.Id)
1432 if agent == nil {
1433 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001434 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001435 resp, err := agent.getImageDownloadStatus(ctx, img)
1436 if err != nil {
1437 return imageDownloadFailureResp, err
1438 }
1439 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001440}
1441
Kent Hagerman2b216042020-04-03 18:28:56 -04001442func (dMgr *Manager) UpdateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001443 logger.Debugw("UpdateImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301444 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1445 if err := agent.updateImageDownload(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001446 logger.Debugw("UpdateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001447 return err
1448 }
1449 } else {
1450 return status.Errorf(codes.NotFound, "%s", img.Id)
1451 }
1452 return nil
1453}
1454
Kent Hagerman45a13e42020-04-13 12:23:50 -04001455// GetImageDownload returns image download
Kent Hagerman2b216042020-04-03 18:28:56 -04001456func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001457 logger.Debugw("GetImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
1458 agent := dMgr.getDeviceAgent(ctx, img.Id)
1459 if agent == nil {
1460 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001461 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001462 resp, err := agent.getImageDownload(ctx, img)
1463 if err != nil {
1464 return imageDownloadFailureResp, err
1465 }
1466 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001467}
1468
Kent Hagerman45a13e42020-04-13 12:23:50 -04001469// ListImageDownloads returns image downloads
1470func (dMgr *Manager) ListImageDownloads(ctx context.Context, id *voltha.ID) (*voltha.ImageDownloads, error) {
1471 logger.Debugw("ListImageDownloads", log.Fields{"device-id": id.Id})
1472 agent := dMgr.getDeviceAgent(ctx, id.Id)
1473 if agent == nil {
1474 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001475 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001476 resp, err := agent.listImageDownloads(ctx, id.Id)
1477 if err != nil {
1478 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, err
1479 }
1480 return resp, nil
1481}
1482
1483// GetImages returns all images for a specific device entry
1484func (dMgr *Manager) GetImages(ctx context.Context, id *voltha.ID) (*voltha.Images, error) {
1485 logger.Debugw("GetImages", log.Fields{"device-id": id.Id})
1486 device, err := dMgr.getDevice(ctx, id.Id)
1487 if err != nil {
1488 return nil, err
1489 }
1490 return device.GetImages(), nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001491}
1492
Kent Hagerman2b216042020-04-03 18:28:56 -04001493func (dMgr *Manager) NotifyInvalidTransition(_ context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001494 logger.Errorw("NotifyInvalidTransition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001495 "device": device.Id,
1496 "curr-admin-state": device.AdminState,
1497 "curr-oper-state": device.OperStatus,
1498 "curr-conn-state": device.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001499 })
khenaidoo0a822f92019-05-08 15:15:57 -04001500 //TODO: notify over kafka?
1501 return nil
1502}
1503
khenaidoob9203542018-09-17 22:56:37 -04001504func funcName(f interface{}) string {
1505 p := reflect.ValueOf(f).Pointer()
1506 rf := runtime.FuncForPC(p)
1507 return rf.Name()
1508}
1509
npujar1d86a522019-11-14 17:11:16 +05301510// UpdateDeviceAttribute updates value of particular device attribute
Kent Hagerman2b216042020-04-03 18:28:56 -04001511func (dMgr *Manager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301512 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -04001513 agent.(*Agent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001514 }
1515}
1516
npujar1d86a522019-11-14 17:11:16 +05301517// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -04001518func (dMgr *Manager) GetParentDeviceID(ctx context.Context, deviceID string) string {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001519 if device, _ := dMgr.getDevice(ctx, deviceID); device != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001520 logger.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001521 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001522 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001523 return ""
khenaidoob9203542018-09-17 22:56:37 -04001524}
serkant.uluderya334479d2019-04-10 08:26:15 -07001525
Kent Hagerman45a13e42020-04-13 12:23:50 -04001526func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulateReq *voltha.SimulateAlarmRequest) (*common.OperationResp, error) {
1527 logger.Debugw("SimulateAlarm", log.Fields{"id": simulateReq.Id, "Indicator": simulateReq.Indicator, "IntfId": simulateReq.IntfId,
1528 "PortTypeName": simulateReq.PortTypeName, "OnuDeviceId": simulateReq.OnuDeviceId, "InverseBitErrorRate": simulateReq.InverseBitErrorRate,
1529 "Drift": simulateReq.Drift, "NewEqd": simulateReq.NewEqd, "OnuSerialNumber": simulateReq.OnuSerialNumber, "Operation": simulateReq.Operation})
1530 agent := dMgr.getDeviceAgent(ctx, simulateReq.Id)
1531 if agent == nil {
1532 return nil, status.Errorf(codes.NotFound, "%s", simulateReq.Id)
serkant.uluderya334479d2019-04-10 08:26:15 -07001533 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001534 if err := agent.simulateAlarm(ctx, simulateReq); err != nil {
1535 return nil, err
1536 }
1537 return &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}, nil
serkant.uluderya334479d2019-04-10 08:26:15 -07001538}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001539
Kent Hagerman2b216042020-04-03 18:28:56 -04001540func (dMgr *Manager) UpdateDeviceReason(ctx context.Context, deviceID string, reason string) error {
1541 logger.Debugw("UpdateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301542 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1543 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001544 }
npujar1d86a522019-11-14 17:11:16 +05301545 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001546}
kesavandbc2d1622020-01-21 00:42:01 -05001547
Kent Hagerman45a13e42020-04-13 12:23:50 -04001548func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Kent Hagerman2b216042020-04-03 18:28:56 -04001549 logger.Debugw("EnablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001550 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1551 if agent == nil {
1552 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001553 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001554 return &empty.Empty{}, agent.enablePort(ctx, port)
kesavandbc2d1622020-01-21 00:42:01 -05001555}
1556
Kent Hagerman45a13e42020-04-13 12:23:50 -04001557func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Kent Hagerman2b216042020-04-03 18:28:56 -04001558 logger.Debugw("DisablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001559 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1560 if agent == nil {
1561 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001562 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001563 return &empty.Empty{}, agent.disablePort(ctx, port)
kesavandbc2d1622020-01-21 00:42:01 -05001564}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001565
Kent Hagerman2b216042020-04-03 18:28:56 -04001566// ChildDeviceLost calls parent adapter to delete child device and all its references
1567func (dMgr *Manager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001568 logger.Debugw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001569 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001570 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1571 // Just log the message and let the remaining pipeline proceed.
Girish Kumarf56a4682020-03-20 20:07:46 +00001572 logger.Warnw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001573 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001574 }
khenaidooe132f522020-03-20 15:23:15 -04001575 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1576 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001577}
onkarkundargi87285252020-01-27 11:34:52 +05301578
Kent Hagerman45a13e42020-04-13 12:23:50 -04001579func (dMgr *Manager) StartOmciTestAction(ctx context.Context, request *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
1580 logger.Debugw("StartOmciTestAction", log.Fields{"device-id": request.Id, "uuid": request.Uuid})
1581 agent := dMgr.getDeviceAgent(ctx, request.Id)
1582 if agent == nil {
1583 return nil, status.Errorf(codes.NotFound, "%s", request.Id)
onkarkundargi87285252020-01-27 11:34:52 +05301584 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001585 return agent.startOmciTest(ctx, request)
onkarkundargi87285252020-01-27 11:34:52 +05301586}
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001587
1588func (dMgr *Manager) GetExtValue(ctx context.Context, value *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
1589 log.Debugw("getExtValue", log.Fields{"onu-id": value.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001590 cDevice, err := dMgr.getDevice(ctx, value.Id)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001591 if err != nil {
1592 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1593 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001594 pDevice, err := dMgr.getDevice(ctx, cDevice.ParentId)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001595 if err != nil {
1596 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1597 }
1598 if agent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); agent != nil {
1599 resp, err := agent.getExtValue(ctx, pDevice, cDevice, value)
1600 if err != nil {
1601 return nil, err
1602 }
1603 log.Debugw("getExtValue-result", log.Fields{"result": resp})
1604 return resp, nil
1605 }
1606 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
1607
1608}