blob: cf1301f69f8be8aa41809159855439cc54875d1c [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
khenaidoo8b4abbf2020-04-24 17:04:30 -0400337 logger.Debugw("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
khenaidoo0db4c812020-05-27 15:27:30 -0400728func (dMgr *Manager) addPeerPort(ctx context.Context, deviceID string, port *voltha.Port) error {
729 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
730 for _, peerPort := range port.Peers {
731 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
732 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
733 return err
734 }
735 }
736 }
737 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
738 // then a logical port will be added to the logical device and the device route generated. If the port is a
739 // PON port then only the device graph will be generated.
740 device, err := dMgr.getDevice(ctx, deviceID)
741 if err != nil {
742 return err
743 }
744 if err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, port); err != nil {
745 return err
746 }
747 return nil
748}
749
Kent Hagerman2b216042020-04-03 18:28:56 -0400750func (dMgr *Manager) AddPort(ctx context.Context, deviceID string, port *voltha.Port) error {
npujar467fe752020-01-16 20:17:45 +0530751 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530752 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530753 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400754 return err
755 }
khenaidoo0db4c812020-05-27 15:27:30 -0400756 // Setup peer ports in its own routine
757 go func() {
758 if err := dMgr.addPeerPort(ctx, deviceID, port); err != nil {
759 logger.Errorw("unable-to-add-peer-port", log.Fields{"error": err, "device-id": deviceID})
khenaidoo92e62c52018-10-03 14:02:54 -0400760 }
khenaidoo0db4c812020-05-27 15:27:30 -0400761 }()
khenaidoo92e62c52018-10-03 14:02:54 -0400762 return nil
khenaidoob9203542018-09-17 22:56:37 -0400763 }
npujar1d86a522019-11-14 17:11:16 +0530764 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400765}
766
Kent Hagerman2b216042020-04-03 18:28:56 -0400767func (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 +0000768 logger.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530769 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
770 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400771 }
npujar1d86a522019-11-14 17:11:16 +0530772 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400773}
774
khenaidoo787224a2020-04-16 18:08:47 -0400775// deleteParentFlows removes flows from the parent device based on specific attributes
776func (dMgr *Manager) deleteParentFlows(ctx context.Context, deviceID string, uniPort uint32, metadata *voltha.FlowMetadata) error {
777 logger.Debugw("deleteParentFlows", log.Fields{"device-id": deviceID, "uni-port": uniPort, "metadata": metadata})
778 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
779 if !agent.isRootdevice {
780 return status.Errorf(codes.FailedPrecondition, "not-a-parent-device-%s", deviceID)
781 }
782 return agent.filterOutFlows(ctx, uniPort, metadata)
783 }
784 return status.Errorf(codes.NotFound, "%s", deviceID)
785}
786
Kent Hagerman2b216042020-04-03 18:28:56 -0400787func (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 +0000788 logger.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530789 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
790 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400791 }
npujar1d86a522019-11-14 17:11:16 +0530792 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400793}
794
Kent Hagerman2b216042020-04-03 18:28:56 -0400795func (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 +0000796 logger.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530797 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
798 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400799 }
npujar1d86a522019-11-14 17:11:16 +0530800 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400801}
802
Kent Hagerman45a13e42020-04-13 12:23:50 -0400803// UpdateDevicePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
khenaidoob3127472019-07-24 21:04:55 -0400804// following a user action
Kent Hagerman45a13e42020-04-13 12:23:50 -0400805func (dMgr *Manager) UpdateDevicePmConfigs(ctx context.Context, configs *voltha.PmConfigs) (*empty.Empty, error) {
806 if configs.Id == "" {
807 return nil, status.Error(codes.FailedPrecondition, "invalid-device-Id")
khenaidoob3127472019-07-24 21:04:55 -0400808 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400809 agent := dMgr.getDeviceAgent(ctx, configs.Id)
810 if agent == nil {
811 return nil, status.Errorf(codes.NotFound, "%s", configs.Id)
812 }
813 return &empty.Empty{}, agent.updatePmConfigs(ctx, configs)
khenaidoob3127472019-07-24 21:04:55 -0400814}
815
Kent Hagerman2b216042020-04-03 18:28:56 -0400816// InitPmConfigs initialize the pm configs as defined by the adapter.
817func (dMgr *Manager) InitPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400818 if pmConfigs.Id == "" {
819 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
820 }
npujar467fe752020-01-16 20:17:45 +0530821 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
822 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400823 }
npujar1d86a522019-11-14 17:11:16 +0530824 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400825}
826
Kent Hagerman45a13e42020-04-13 12:23:50 -0400827// ListDevicePmConfigs returns pm configs of device
828func (dMgr *Manager) ListDevicePmConfigs(ctx context.Context, id *voltha.ID) (*voltha.PmConfigs, error) {
829 agent := dMgr.getDeviceAgent(ctx, id.Id)
830 if agent == nil {
831 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob3127472019-07-24 21:04:55 -0400832 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400833 return agent.listPmConfigs(ctx)
khenaidoob3127472019-07-24 21:04:55 -0400834}
835
Kent Hagerman2b216042020-04-03 18:28:56 -0400836func (dMgr *Manager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000837 logger.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530838 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400839 return agent.getSwitchCapability(ctx)
840 }
npujar1d86a522019-11-14 17:11:16 +0530841 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400842}
843
Kent Hagerman2b216042020-04-03 18:28:56 -0400844func (dMgr *Manager) GetPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
845 logger.Debugw("GetPorts", log.Fields{"deviceid": deviceID, "portType": portType})
npujar467fe752020-01-16 20:17:45 +0530846 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400847 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400848 }
npujar1d86a522019-11-14 17:11:16 +0530849 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400850}
851
Kent Hagerman2b216042020-04-03 18:28:56 -0400852func (dMgr *Manager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000853 logger.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530854 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400855 return agent.getPortCapability(ctx, portNo)
856 }
npujar1d86a522019-11-14 17:11:16 +0530857 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400858}
859
Kent Hagerman2b216042020-04-03 18:28:56 -0400860func (dMgr *Manager) UpdateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
861 logger.Debugw("UpdateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530862 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
863 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400864 }
npujar1d86a522019-11-14 17:11:16 +0530865 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400866}
867
Kent Hagerman2b216042020-04-03 18:28:56 -0400868func (dMgr *Manager) UpdateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
869 logger.Debugw("UpdateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400870 var parentDevice *voltha.Device
871 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -0400872 if parentDevice, err = dMgr.getDevice(ctx, deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400873 return status.Errorf(codes.Aborted, "%s", err.Error())
874 }
875 var childDeviceIds []string
876 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
877 return status.Errorf(codes.Aborted, "%s", err.Error())
878 }
879 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000880 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400881 }
npujar1d86a522019-11-14 17:11:16 +0530882 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530883 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
884 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530885 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400886 }
887 }
888 }
889 return nil
890}
891
Kent Hagerman2b216042020-04-03 18:28:56 -0400892func (dMgr *Manager) UpdatePortState(ctx context.Context, deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
893 logger.Debugw("UpdatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530894 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
895 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000896 logger.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400897 return err
898 }
899 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800900 // Do this for NNI and UNIs only. PON ports are not known by logical device
901 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
902 go func() {
903 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
904 if err != nil {
905 // While we want to handle (catch) and log when
906 // an update to a port was not able to be
907 // propagated to the logical port, we can report
908 // it as a warning and not an error because it
909 // doesn't stop or modify processing.
910 // TODO: VOL-2707
Girish Kumarf56a4682020-03-20 20:07:46 +0000911 logger.Warnw("unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800912 }
913 }()
914 }
khenaidoo442e7c72020-03-10 16:13:48 -0400915 return nil
khenaidoob9203542018-09-17 22:56:37 -0400916 }
npujar1d86a522019-11-14 17:11:16 +0530917 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400918}
919
Kent Hagerman2b216042020-04-03 18:28:56 -0400920func (dMgr *Manager) DeleteAllPorts(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000921 logger.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530922 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
923 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400924 return err
925 }
926 // Notify the logical device manager to remove all logical ports, if needed.
Kent Hagerman2b216042020-04-03 18:28:56 -0400927 // At this stage the device itself may gave been deleted already at a DeleteAllPorts
khenaidoo0a822f92019-05-08 15:15:57 -0400928 // typically is part of a device deletion phase.
Kent Hagerman45a13e42020-04-13 12:23:50 -0400929 if device, err := dMgr.getDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530930 go func() {
npujar467fe752020-01-16 20:17:45 +0530931 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530932 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000933 logger.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530934 }
935 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400936 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000937 logger.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400938 return err
939 }
940 return nil
941 }
npujar1d86a522019-11-14 17:11:16 +0530942 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400943}
944
Kent Hagerman2b216042020-04-03 18:28:56 -0400945//UpdatePortsState updates all ports on the device
946func (dMgr *Manager) UpdatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
947 logger.Debugw("UpdatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400948
npujar467fe752020-01-16 20:17:45 +0530949 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400950 switch state {
951 case voltha.OperStatus_ACTIVE:
kesavandbc2d1622020-01-21 00:42:01 -0500952 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000953 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400954 return err
955 }
956 case voltha.OperStatus_UNKNOWN:
kesavandbc2d1622020-01-21 00:42:01 -0500957 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000958 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400959 return err
960 }
961 default:
962 return status.Error(codes.Unimplemented, "state-change-not-implemented")
963 }
964 // Notify the logical device about the state change
Kent Hagerman45a13e42020-04-13 12:23:50 -0400965 device, err := dMgr.getDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530966 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000967 logger.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400968 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400969 }
kesavandbc2d1622020-01-21 00:42:01 -0500970 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000971 logger.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
npujar1d86a522019-11-14 17:11:16 +0530972 return err
973 }
974 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400975 }
npujar1d86a522019-11-14 17:11:16 +0530976 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400977}
978
Kent Hagerman2b216042020-04-03 18:28:56 -0400979func (dMgr *Manager) ChildDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530980 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
Kent Hagerman2b216042020-04-03 18:28:56 -0400981 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 -0700982
npujar1d86a522019-11-14 17:11:16 +0530983 if deviceType == "" && vendorID != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000984 logger.Debug("device-type-is-nil-fetching-device-type")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400985 deviceTypes, err := dMgr.adapterMgr.ListDeviceTypes(ctx, nil)
986 if err != nil {
987 return nil, err
988 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400989 OLoop:
Kent Hagerman45a13e42020-04-13 12:23:50 -0400990 for _, dType := range deviceTypes.Items {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400991 for _, v := range dType.VendorIds {
992 if v == vendorID {
993 deviceType = dType.Adapter
994 break OLoop
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700995 }
996 }
997 }
998 }
999 //if no match found for the vendorid,report adapter with the custom error message
1000 if deviceType == "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001001 logger.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
npujar1d86a522019-11-14 17:11:16 +05301002 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -07001003 }
khenaidoob9203542018-09-17 22:56:37 -04001004
1005 // Create the ONU device
1006 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -04001007 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +05301008 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -04001009 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +05301010 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -05001011 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -04001012 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001013
khenaidoo442e7c72020-03-10 16:13:48 -04001014 // Get parent device type
1015 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
1016 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +05301017 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001018 }
khenaidoo442e7c72020-03-10 16:13:48 -04001019 if pAgent.deviceType == "" {
1020 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
1021 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001022
npujar467fe752020-01-16 20:17:45 +05301023 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001024 logger.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001025 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001026 }
1027
khenaidoo442e7c72020-03-10 16:13:48 -04001028 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001029
1030 // Create and start a device agent for that device
Kent Hagerman2b216042020-04-03 18:28:56 -04001031 agent := newAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy, dMgr.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -04001032 childDevice, err := agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001033 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001034 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 -08001035 return nil, err
1036 }
khenaidoo442e7c72020-03-10 16:13:48 -04001037 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -04001038
1039 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301040 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301041 go func() {
npujar467fe752020-01-16 20:17:45 +05301042 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301043 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001044 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301045 }
1046 }()
khenaidoob9203542018-09-17 22:56:37 -04001047 }
1048
khenaidoo79232702018-12-04 11:00:41 -05001049 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301050 go func() {
1051 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1052 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001053 logger.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301054 }
1055 }()
khenaidoo79232702018-12-04 11:00:41 -05001056
Scott Baker80678602019-11-14 16:57:36 -08001057 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001058}
1059
Kent Hagerman2b216042020-04-03 18:28:56 -04001060func (dMgr *Manager) processTransition(ctx context.Context, device *voltha.Device, previousState *deviceState) error {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001061 // This will be triggered on every state update
1062 logger.Debugw("state-transition", log.Fields{
1063 "device": device.Id,
1064 "prev-admin-state": previousState.Admin,
1065 "prev-oper-state": previousState.Operational,
1066 "prev-conn-state": previousState.Connection,
1067 "curr-admin-state": device.AdminState,
1068 "curr-oper-state": device.OperStatus,
1069 "curr-conn-state": device.ConnectStatus,
1070 })
1071 handlers := dMgr.stateTransitions.GetTransitionHandler(device, previousState)
khenaidoo92e62c52018-10-03 14:02:54 -04001072 if handlers == nil {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001073 logger.Debugw("no-op-transition", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001074 return nil
khenaidoob9203542018-09-17 22:56:37 -04001075 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001076 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 -04001077 for _, handler := range handlers {
Girish Kumarf56a4682020-03-20 20:07:46 +00001078 logger.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001079 if err := handler(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001080 logger.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001081 return err
1082 }
1083 }
khenaidoob9203542018-09-17 22:56:37 -04001084 return nil
1085}
1086
Kent Hagerman2b216042020-04-03 18:28:56 -04001087func (dMgr *Manager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001088 logger.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301089 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1090 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001091 }
npujar1d86a522019-11-14 17:11:16 +05301092 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001093}
1094
npujar1d86a522019-11-14 17:11:16 +05301095// PacketIn receives packet from adapter
Kent Hagerman2b216042020-04-03 18:28:56 -04001096func (dMgr *Manager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001097 logger.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001098 // Get the logical device Id based on the deviceId
1099 var device *voltha.Device
1100 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -04001101 if device, err = dMgr.getDevice(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001102 logger.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001103 return err
1104 }
khenaidoo43c82122018-11-22 18:38:28 -05001105 if !device.Root {
Girish Kumarf56a4682020-03-20 20:07:46 +00001106 logger.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301107 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001108 }
1109
npujar467fe752020-01-16 20:17:45 +05301110 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001111 return err
1112 }
1113 return nil
1114}
1115
Kent Hagerman2b216042020-04-03 18:28:56 -04001116func (dMgr *Manager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001117 logger.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301118 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1119 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001120 }
1121 return status.Errorf(codes.NotFound, "%s", device.Id)
1122}
1123
npujar1d86a522019-11-14 17:11:16 +05301124// CreateLogicalDevice creates logical device in core
Kent Hagerman2b216042020-04-03 18:28:56 -04001125func (dMgr *Manager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001126 logger.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001127 // Verify whether the logical device has already been created
1128 if cDevice.ParentId != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001129 logger.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001130 return nil
1131 }
khenaidoob9203542018-09-17 22:56:37 -04001132 var err error
npujar467fe752020-01-16 20:17:45 +05301133 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001134 logger.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001135 return err
1136 }
khenaidoob9203542018-09-17 22:56:37 -04001137 return nil
1138}
1139
npujar1d86a522019-11-14 17:11:16 +05301140// DeleteLogicalDevice deletes logical device from core
Kent Hagerman2b216042020-04-03 18:28:56 -04001141func (dMgr *Manager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001142 logger.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001143 var err error
npujar467fe752020-01-16 20:17:45 +05301144 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001145 logger.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001146 return err
1147 }
1148 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301149 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301150 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001151 return nil
1152}
1153
npujar1d86a522019-11-14 17:11:16 +05301154// DeleteLogicalPort removes the logical port associated with a device
Kent Hagerman2b216042020-04-03 18:28:56 -04001155func (dMgr *Manager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001156 logger.Info("deleteLogicalPort")
khenaidoo92e62c52018-10-03 14:02:54 -04001157 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001158 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301159 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301160 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001161 logger.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001162 return err
1163 }
npujar467fe752020-01-16 20:17:45 +05301164 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001165 logger.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001166 return err
1167 }
khenaidoo92e62c52018-10-03 14:02:54 -04001168 return nil
1169}
1170
npujar1d86a522019-11-14 17:11:16 +05301171// DeleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagerman2b216042020-04-03 18:28:56 -04001172func (dMgr *Manager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001173 logger.Debugw("delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001174 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001175 // 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 +00001176 logger.Warnw("deleteLogical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001177 }
1178 return nil
1179}
1180
Kent Hagerman2b216042020-04-03 18:28:56 -04001181func (dMgr *Manager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001182 // Sanity check
1183 if childDevice.Root {
1184 // childDevice is the parent device
1185 return childDevice
1186 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001187 parentDevice, _ := dMgr.getDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001188 return parentDevice
1189}
1190
Kent Hagerman2b216042020-04-03 18:28:56 -04001191//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 -04001192//cannot manage the child devices. This will trigger the Core to disable all the child devices.
Kent Hagerman2b216042020-04-03 18:28:56 -04001193func (dMgr *Manager) ChildDevicesLost(ctx context.Context, parentDeviceID string) error {
1194 logger.Debug("ChildDevicesLost")
khenaidoo0a822f92019-05-08 15:15:57 -04001195 var err error
1196 var parentDevice *voltha.Device
Kent Hagerman45a13e42020-04-13 12:23:50 -04001197 if parentDevice, err = dMgr.getDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001198 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001199 return err
1200 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001201 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001202}
1203
Kent Hagerman2b216042020-04-03 18:28:56 -04001204//ChildDevicesDetected is invoked by an adapter when child devices are found, typically after after a
khenaidoo0a822f92019-05-08 15:15:57 -04001205// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
Kent Hagerman2b216042020-04-03 18:28:56 -04001206func (dMgr *Manager) ChildDevicesDetected(ctx context.Context, parentDeviceID string) error {
1207 logger.Debug("ChildDevicesDetected")
khenaidoo0a822f92019-05-08 15:15:57 -04001208 var err error
1209 var parentDevice *voltha.Device
1210 var childDeviceIds []string
1211
Kent Hagerman45a13e42020-04-13 12:23:50 -04001212 if parentDevice, err = dMgr.getDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001213 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001214 return err
1215 }
1216
1217 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1218 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1219 }
1220 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001221 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo0a822f92019-05-08 15:15:57 -04001222 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001223 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301224 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301225 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001226 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301227 go func() {
npujar467fe752020-01-16 20:17:45 +05301228 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301229 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001230 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301231 }
1232 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001233 } else {
npujar1d86a522019-11-14 17:11:16 +05301234 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
Girish Kumarf56a4682020-03-20 20:07:46 +00001235 logger.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001236 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001237 }
1238 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001239 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001240 return err
1241 }
1242 return nil
1243}
1244
khenaidoo4d4802d2018-10-04 21:59:49 -04001245/*
1246All the functions below are callback functions where they are invoked with the latest and previous data. We can
1247therefore use the data as is without trying to get the latest from the model.
1248*/
1249
khenaidoo0a822f92019-05-08 15:15:57 -04001250//DisableAllChildDevices is invoked as a callback when the parent device is disabled
Kent Hagerman2b216042020-04-03 18:28:56 -04001251func (dMgr *Manager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001252 logger.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001253 var childDeviceIds []string
1254 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001255 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1256 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001257 }
1258 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001259 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001260 }
npujar1d86a522019-11-14 17:11:16 +05301261 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301262 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1263 if err = agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001264 // Just log the error - this error happens only if the child device was already in deleted state.
Girish Kumarf56a4682020-03-20 20:07:46 +00001265 logger.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001266 }
1267 }
1268 }
1269 return nil
1270}
1271
khenaidoo0a822f92019-05-08 15:15:57 -04001272//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
Kent Hagerman2b216042020-04-03 18:28:56 -04001273func (dMgr *Manager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001274 logger.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001275 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001276 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001277 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1278 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001279 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001280 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001281 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -04001282 }
npujar1d86a522019-11-14 17:11:16 +05301283 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301284 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1285 if err = agent.deleteDevice(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001286 logger.Warnw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001287 }
khenaidoo49085352020-01-13 19:15:43 -05001288 // No further action is required here. The deleteDevice will change the device state where the resulting
1289 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001290 }
1291 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001292 return nil
1293}
1294
Girish Gowdra408cd962020-03-11 14:31:31 -07001295//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001296func (dMgr *Manager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001297 logger.Debugw("delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001298 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001299 // Just log error as logical device may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001300 logger.Warnw("delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001301 }
1302 return nil
1303}
1304
1305//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001306func (dMgr *Manager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001307 logger.Debugw("delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001308 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1309 if err := agent.deleteAllFlows(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001310 logger.Errorw("error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001311 return err
1312 }
1313 return nil
1314 }
1315 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1316}
1317
khenaidoo4d4802d2018-10-04 21:59:49 -04001318//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 -04001319func (dMgr *Manager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001320 logger.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001321 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001322 if parentDevice != nil {
1323 for _, port := range parentDevice.Ports {
1324 for _, peer := range port.Peers {
1325 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1326 }
khenaidoo92e62c52018-10-03 14:02:54 -04001327 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001328 logger.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001329 }
1330 return childDeviceIds, nil
1331}
1332
Kent Hagerman2b216042020-04-03 18:28:56 -04001333//GetAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1334func (dMgr *Manager) GetAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
1335 logger.Debugw("GetAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001336 if parentDevice, err := dMgr.getDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001337 childDevices := make([]*voltha.Device, 0)
1338 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301339 for _, deviceID := range childDeviceIds {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001340 if d, e := dMgr.getDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001341 childDevices = append(childDevices, d)
1342 }
1343 }
1344 }
1345 return &voltha.Devices{Items: childDevices}, nil
1346 }
npujar1d86a522019-11-14 17:11:16 +05301347 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001348}
1349
npujar1d86a522019-11-14 17:11:16 +05301350// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
Kent Hagerman2b216042020-04-03 18:28:56 -04001351func (dMgr *Manager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001352 logger.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301353 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001354 logger.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001355 return err
1356 }
1357 return nil
1358}
1359
Kent Hagerman45a13e42020-04-13 12:23:50 -04001360// convenience to avoid redefining
1361var operationFailureResp = &common.OperationResp{Code: voltha.OperationResp_OPERATION_FAILURE}
1362
1363// DownloadImage execute an image download request
1364func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1365 logger.Debugw("DownloadImage", log.Fields{"device-id": img.Id, "imageName": img.Name})
1366 agent := dMgr.getDeviceAgent(ctx, img.Id)
1367 if agent == nil {
1368 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001369 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001370 resp, err := agent.downloadImage(ctx, img)
1371 if err != nil {
1372 return operationFailureResp, err
1373 }
1374 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001375}
1376
Kent Hagerman45a13e42020-04-13 12:23:50 -04001377// CancelImageDownload cancels image download request
1378func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1379 logger.Debugw("CancelImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
1380 agent := dMgr.getDeviceAgent(ctx, img.Id)
1381 if agent == nil {
1382 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001383 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001384 resp, err := agent.cancelImageDownload(ctx, img)
1385 if err != nil {
1386 return operationFailureResp, err
1387 }
1388 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001389}
1390
Kent Hagerman45a13e42020-04-13 12:23:50 -04001391// ActivateImageUpdate activates image update request
1392func (dMgr *Manager) ActivateImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1393 logger.Debugw("ActivateImageUpdate", log.Fields{"device-id": img.Id, "imageName": img.Name})
1394 agent := dMgr.getDeviceAgent(ctx, img.Id)
1395 if agent == nil {
1396 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001397 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001398 resp, err := agent.activateImage(ctx, img)
1399 if err != nil {
1400 return operationFailureResp, err
1401 }
1402 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001403}
1404
Kent Hagerman45a13e42020-04-13 12:23:50 -04001405// RevertImageUpdate reverts image update
1406func (dMgr *Manager) RevertImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1407 logger.Debugw("RevertImageUpdate", log.Fields{"device-id": img.Id, "imageName": img.Name})
1408 agent := dMgr.getDeviceAgent(ctx, img.Id)
1409 if agent == nil {
1410 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001411 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001412 resp, err := agent.revertImage(ctx, img)
1413 if err != nil {
1414 return operationFailureResp, err
1415 }
1416 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001417}
1418
Kent Hagerman45a13e42020-04-13 12:23:50 -04001419// convenience to avoid redefining
1420var imageDownloadFailureResp = &voltha.ImageDownload{DownloadState: voltha.ImageDownload_DOWNLOAD_UNKNOWN}
1421
1422// GetImageDownloadStatus returns status of image download
1423func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1424 logger.Debugw("GetImageDownloadStatus", log.Fields{"device-id": img.Id, "imageName": img.Name})
1425 agent := dMgr.getDeviceAgent(ctx, img.Id)
1426 if agent == nil {
1427 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001428 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001429 resp, err := agent.getImageDownloadStatus(ctx, img)
1430 if err != nil {
1431 return imageDownloadFailureResp, err
1432 }
1433 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001434}
1435
Kent Hagerman2b216042020-04-03 18:28:56 -04001436func (dMgr *Manager) UpdateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001437 logger.Debugw("UpdateImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301438 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1439 if err := agent.updateImageDownload(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001440 logger.Debugw("UpdateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001441 return err
1442 }
1443 } else {
1444 return status.Errorf(codes.NotFound, "%s", img.Id)
1445 }
1446 return nil
1447}
1448
Kent Hagerman45a13e42020-04-13 12:23:50 -04001449// GetImageDownload returns image download
Kent Hagerman2b216042020-04-03 18:28:56 -04001450func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001451 logger.Debugw("GetImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
1452 agent := dMgr.getDeviceAgent(ctx, img.Id)
1453 if agent == nil {
1454 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001455 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001456 resp, err := agent.getImageDownload(ctx, img)
1457 if err != nil {
1458 return imageDownloadFailureResp, err
1459 }
1460 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001461}
1462
Kent Hagerman45a13e42020-04-13 12:23:50 -04001463// ListImageDownloads returns image downloads
1464func (dMgr *Manager) ListImageDownloads(ctx context.Context, id *voltha.ID) (*voltha.ImageDownloads, error) {
1465 logger.Debugw("ListImageDownloads", log.Fields{"device-id": id.Id})
1466 agent := dMgr.getDeviceAgent(ctx, id.Id)
1467 if agent == nil {
1468 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001469 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001470 resp, err := agent.listImageDownloads(ctx, id.Id)
1471 if err != nil {
1472 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, err
1473 }
1474 return resp, nil
1475}
1476
1477// GetImages returns all images for a specific device entry
1478func (dMgr *Manager) GetImages(ctx context.Context, id *voltha.ID) (*voltha.Images, error) {
1479 logger.Debugw("GetImages", log.Fields{"device-id": id.Id})
1480 device, err := dMgr.getDevice(ctx, id.Id)
1481 if err != nil {
1482 return nil, err
1483 }
1484 return device.GetImages(), nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001485}
1486
Kent Hagerman2b216042020-04-03 18:28:56 -04001487func (dMgr *Manager) NotifyInvalidTransition(_ context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001488 logger.Errorw("NotifyInvalidTransition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001489 "device": device.Id,
1490 "curr-admin-state": device.AdminState,
1491 "curr-oper-state": device.OperStatus,
1492 "curr-conn-state": device.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001493 })
khenaidoo0a822f92019-05-08 15:15:57 -04001494 //TODO: notify over kafka?
1495 return nil
1496}
1497
khenaidoob9203542018-09-17 22:56:37 -04001498func funcName(f interface{}) string {
1499 p := reflect.ValueOf(f).Pointer()
1500 rf := runtime.FuncForPC(p)
1501 return rf.Name()
1502}
1503
npujar1d86a522019-11-14 17:11:16 +05301504// UpdateDeviceAttribute updates value of particular device attribute
Kent Hagerman2b216042020-04-03 18:28:56 -04001505func (dMgr *Manager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301506 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -04001507 agent.(*Agent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001508 }
1509}
1510
npujar1d86a522019-11-14 17:11:16 +05301511// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -04001512func (dMgr *Manager) GetParentDeviceID(ctx context.Context, deviceID string) string {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001513 if device, _ := dMgr.getDevice(ctx, deviceID); device != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001514 logger.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001515 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001516 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001517 return ""
khenaidoob9203542018-09-17 22:56:37 -04001518}
serkant.uluderya334479d2019-04-10 08:26:15 -07001519
Kent Hagerman45a13e42020-04-13 12:23:50 -04001520func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulateReq *voltha.SimulateAlarmRequest) (*common.OperationResp, error) {
1521 logger.Debugw("SimulateAlarm", log.Fields{"id": simulateReq.Id, "Indicator": simulateReq.Indicator, "IntfId": simulateReq.IntfId,
1522 "PortTypeName": simulateReq.PortTypeName, "OnuDeviceId": simulateReq.OnuDeviceId, "InverseBitErrorRate": simulateReq.InverseBitErrorRate,
1523 "Drift": simulateReq.Drift, "NewEqd": simulateReq.NewEqd, "OnuSerialNumber": simulateReq.OnuSerialNumber, "Operation": simulateReq.Operation})
1524 agent := dMgr.getDeviceAgent(ctx, simulateReq.Id)
1525 if agent == nil {
1526 return nil, status.Errorf(codes.NotFound, "%s", simulateReq.Id)
serkant.uluderya334479d2019-04-10 08:26:15 -07001527 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001528 if err := agent.simulateAlarm(ctx, simulateReq); err != nil {
1529 return nil, err
1530 }
1531 return &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}, nil
serkant.uluderya334479d2019-04-10 08:26:15 -07001532}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001533
Kent Hagerman2b216042020-04-03 18:28:56 -04001534func (dMgr *Manager) UpdateDeviceReason(ctx context.Context, deviceID string, reason string) error {
1535 logger.Debugw("UpdateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301536 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1537 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001538 }
npujar1d86a522019-11-14 17:11:16 +05301539 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001540}
kesavandbc2d1622020-01-21 00:42:01 -05001541
Kent Hagerman45a13e42020-04-13 12:23:50 -04001542func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Kent Hagerman2b216042020-04-03 18:28:56 -04001543 logger.Debugw("EnablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001544 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1545 if agent == nil {
1546 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001547 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001548 return &empty.Empty{}, agent.enablePort(ctx, port)
kesavandbc2d1622020-01-21 00:42:01 -05001549}
1550
Kent Hagerman45a13e42020-04-13 12:23:50 -04001551func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Kent Hagerman2b216042020-04-03 18:28:56 -04001552 logger.Debugw("DisablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001553 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1554 if agent == nil {
1555 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001556 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001557 return &empty.Empty{}, agent.disablePort(ctx, port)
kesavandbc2d1622020-01-21 00:42:01 -05001558}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001559
Kent Hagerman2b216042020-04-03 18:28:56 -04001560// ChildDeviceLost calls parent adapter to delete child device and all its references
1561func (dMgr *Manager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001562 logger.Debugw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001563 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001564 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1565 // Just log the message and let the remaining pipeline proceed.
Girish Kumarf56a4682020-03-20 20:07:46 +00001566 logger.Warnw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001567 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001568 }
khenaidooe132f522020-03-20 15:23:15 -04001569 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1570 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001571}
onkarkundargi87285252020-01-27 11:34:52 +05301572
Kent Hagerman45a13e42020-04-13 12:23:50 -04001573func (dMgr *Manager) StartOmciTestAction(ctx context.Context, request *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
1574 logger.Debugw("StartOmciTestAction", log.Fields{"device-id": request.Id, "uuid": request.Uuid})
1575 agent := dMgr.getDeviceAgent(ctx, request.Id)
1576 if agent == nil {
1577 return nil, status.Errorf(codes.NotFound, "%s", request.Id)
onkarkundargi87285252020-01-27 11:34:52 +05301578 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001579 return agent.startOmciTest(ctx, request)
onkarkundargi87285252020-01-27 11:34:52 +05301580}
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001581
1582func (dMgr *Manager) GetExtValue(ctx context.Context, value *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
1583 log.Debugw("getExtValue", log.Fields{"onu-id": value.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001584 cDevice, err := dMgr.getDevice(ctx, value.Id)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001585 if err != nil {
1586 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1587 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001588 pDevice, err := dMgr.getDevice(ctx, cDevice.ParentId)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001589 if err != nil {
1590 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1591 }
1592 if agent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); agent != nil {
1593 resp, err := agent.getExtValue(ctx, pDevice, cDevice, value)
1594 if err != nil {
1595 return nil, err
1596 }
1597 log.Debugw("getExtValue-result", log.Fields{"result": resp})
1598 return resp, nil
1599 }
1600 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
1601
1602}