blob: 357c49ae31a094c3a4773c139d40d407d2c1c2fb [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"
David Bainbridged1afd662020-03-26 18:27:41 -070022 "reflect"
23 "runtime"
24 "sync"
25 "time"
26
Kent Hagerman45a13e42020-04-13 12:23:50 -040027 "github.com/golang/protobuf/ptypes/empty"
sbarbari17d7e222019-11-05 10:02:29 -050028 "github.com/opencord/voltha-go/db/model"
Kent Hagerman2b216042020-04-03 18:28:56 -040029 "github.com/opencord/voltha-go/rw_core/core/adapter"
Kent Hagermanf5a67352020-04-30 15:15:26 -040030 "github.com/opencord/voltha-go/rw_core/core/device/event"
Kent Hagerman2b216042020-04-03 18:28:56 -040031 "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
Kent Hagermanf5a67352020-04-30 15:15:26 -040053 dProxy *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 Hagermanf5a67352020-04-30 15:15:26 -040060func NewManagers(dbProxy *model.Path, 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,
Kent Hagermanf5a67352020-04-30 15:15:26 -040066 dProxy: dbProxy.Proxy("devices"),
Kent Hagerman2b216042020-04-03 18:28:56 -040067 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,
Kent Hagermanf5a67352020-04-30 15:15:26 -040077 dbProxy: dbProxy,
78 ldProxy: dbProxy.Proxy("logical_devices"),
Kent Hagerman2b216042020-04-03 18:28:56 -040079 defaultTimeout: defaultCoreTimeout,
80 logicalDeviceLoadingInProgress: make(map[string][]chan int),
81 }
82 deviceMgr.logicalDeviceMgr = logicalDeviceMgr
Matteo Scandolod525ae32020-04-02 17:27:29 -070083
Kent Hagerman2b216042020-04-03 18:28:56 -040084 adapterMgr.SetAdapterRestartedCallback(deviceMgr.adapterRestarted)
Matteo Scandolod525ae32020-04-02 17:27:29 -070085
Kent Hagerman2b216042020-04-03 18:28:56 -040086 return deviceMgr, logicalDeviceMgr
khenaidoob9203542018-09-17 22:56:37 -040087}
88
Kent Hagerman2b216042020-04-03 18:28:56 -040089func (dMgr *Manager) addDeviceAgentToMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +053090 if _, exist := dMgr.deviceAgents.Load(agent.deviceID); !exist {
91 dMgr.deviceAgents.Store(agent.deviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -040092 }
khenaidoo2c6a0992019-04-29 13:46:56 -040093 dMgr.lockRootDeviceMap.Lock()
94 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +053095 dMgr.rootDevices[agent.deviceID] = agent.isRootdevice
khenaidoo2c6a0992019-04-29 13:46:56 -040096
khenaidoob9203542018-09-17 22:56:37 -040097}
98
Kent Hagerman2b216042020-04-03 18:28:56 -040099func (dMgr *Manager) deleteDeviceAgentFromMap(agent *Agent) {
npujar1d86a522019-11-14 17:11:16 +0530100 dMgr.deviceAgents.Delete(agent.deviceID)
khenaidoo2c6a0992019-04-29 13:46:56 -0400101 dMgr.lockRootDeviceMap.Lock()
102 defer dMgr.lockRootDeviceMap.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530103 delete(dMgr.rootDevices, agent.deviceID)
khenaidoo4d4802d2018-10-04 21:59:49 -0400104}
105
khenaidoo297cd252019-02-07 22:10:23 -0500106// 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 -0400107func (dMgr *Manager) getDeviceAgent(ctx context.Context, deviceID string) *Agent {
npujar1d86a522019-11-14 17:11:16 +0530108 agent, ok := dMgr.deviceAgents.Load(deviceID)
109 if ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400110 return agent.(*Agent)
khenaidoob9203542018-09-17 22:56:37 -0400111 }
khenaidoo442e7c72020-03-10 16:13:48 -0400112 // Try to load into memory - loading will also create the device agent and set the device ownership
npujar467fe752020-01-16 20:17:45 +0530113 err := dMgr.load(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530114 if err == nil {
115 agent, ok = dMgr.deviceAgents.Load(deviceID)
116 if !ok {
117 return nil
118 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400119 return agent.(*Agent)
npujar1d86a522019-11-14 17:11:16 +0530120 }
121 //TODO: Change the return params to return an error as well
Girish Kumarf56a4682020-03-20 20:07:46 +0000122 logger.Errorw("loading-device-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoob9203542018-09-17 22:56:37 -0400123 return nil
124}
125
khenaidoo297cd252019-02-07 22:10:23 -0500126// listDeviceIdsFromMap returns the list of device IDs that are in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400127func (dMgr *Manager) listDeviceIdsFromMap() *voltha.IDs {
khenaidoo7ccedd52018-12-14 16:48:54 -0500128 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400129
130 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
131 result.Items = append(result.Items, &voltha.ID{Id: key.(string)})
132 return true
133 })
134
khenaidoo7ccedd52018-12-14 16:48:54 -0500135 return result
136}
137
Kent Hagerman45a13e42020-04-13 12:23:50 -0400138// CreateDevice creates a new parent device in the data model
139func (dMgr *Manager) CreateDevice(ctx context.Context, device *voltha.Device) (*voltha.Device, error) {
140 if device.MacAddress == "" && device.GetHostAndPort() == "" {
141 logger.Errorf("No Device Info Present")
142 return &voltha.Device{}, errors.New("no-device-info-present; MAC or HOSTIP&PORT")
143 }
144 logger.Debugw("create-device", log.Fields{"device": *device})
145
npujar467fe752020-01-16 20:17:45 +0530146 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530147 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000148 logger.Errorf("Failed to fetch parent device info")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400149 return nil, err
Thomas Lee Se5a44012019-11-07 20:32:24 +0530150 }
151 if deviceExist {
Girish Kumarf56a4682020-03-20 20:07:46 +0000152 logger.Errorf("Device is Pre-provisioned already with same IP-Port or MAC Address")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400153 return nil, errors.New("device is already pre-provisioned")
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530154 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400155 logger.Debugw("CreateDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400156
khenaidoo5e677ae2019-02-28 17:26:29 -0500157 // Ensure this device is set as root
158 device.Root = true
khenaidoob9203542018-09-17 22:56:37 -0400159 // Create and start a device agent for that device
Kent Hagermanf5a67352020-04-30 15:15:26 -0400160 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dProxy, dMgr.defaultTimeout)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530161 device, err = agent.start(ctx, device)
Scott Baker80678602019-11-14 16:57:36 -0800162 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000163 logger.Errorw("Fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400164 return nil, err
Scott Baker80678602019-11-14 16:57:36 -0800165 }
khenaidoo442e7c72020-03-10 16:13:48 -0400166 dMgr.addDeviceAgentToMap(agent)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400167 return device, nil
khenaidoob9203542018-09-17 22:56:37 -0400168}
169
Kent Hagerman45a13e42020-04-13 12:23:50 -0400170// EnableDevice activates a device by invoking the adopt_device API on the appropriate adapter
171func (dMgr *Manager) EnableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
172 logger.Debugw("EnableDevice", log.Fields{"device-id": id.Id})
173 agent := dMgr.getDeviceAgent(ctx, id.Id)
174 if agent == nil {
175 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400176 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400177 return &empty.Empty{}, agent.enableDevice(ctx)
khenaidoob9203542018-09-17 22:56:37 -0400178}
179
Kent Hagerman45a13e42020-04-13 12:23:50 -0400180// DisableDevice disables a device along with any child device it may have
181func (dMgr *Manager) DisableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
182 logger.Debugw("DisableDevice", log.Fields{"device-id": id.Id})
183 agent := dMgr.getDeviceAgent(ctx, id.Id)
184 if agent == nil {
185 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400186 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400187 return &empty.Empty{}, agent.disableDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400188}
189
Kent Hagerman45a13e42020-04-13 12:23:50 -0400190//RebootDevice invoked the reboot API to the corresponding adapter
191func (dMgr *Manager) RebootDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
192 logger.Debugw("RebootDevice", log.Fields{"device-id": id.Id})
193 agent := dMgr.getDeviceAgent(ctx, id.Id)
194 if agent == nil {
195 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400196 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400197 return &empty.Empty{}, agent.rebootDevice(ctx)
khenaidoo4d4802d2018-10-04 21:59:49 -0400198}
199
Kent Hagerman45a13e42020-04-13 12:23:50 -0400200// DeleteDevice removes a device from the data model
201func (dMgr *Manager) DeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
202 logger.Debugw("DeleteDevice", log.Fields{"device-id": id.Id})
203 agent := dMgr.getDeviceAgent(ctx, id.Id)
204 if agent == nil {
205 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo4d4802d2018-10-04 21:59:49 -0400206 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400207 return &empty.Empty{}, agent.deleteDevice(ctx)
208}
209
210// ListDevicePorts returns the ports details for a specific device entry
211func (dMgr *Manager) ListDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.Ports, error) {
212 logger.Debugw("ListDevicePorts", log.Fields{"device-id": id.Id})
213 device, err := dMgr.getDevice(ctx, id.Id)
214 if err != nil {
215 return &voltha.Ports{}, err
216 }
217 return &voltha.Ports{Items: device.Ports}, nil
218}
219
220// ListDeviceFlows returns the flow details for a specific device entry
221func (dMgr *Manager) ListDeviceFlows(ctx context.Context, id *voltha.ID) (*ofp.Flows, error) {
222 logger.Debugw("ListDeviceFlows", log.Fields{"device-id": id.Id})
223 device, err := dMgr.getDevice(ctx, id.Id)
224 if err != nil {
225 return &ofp.Flows{}, err
226 }
227 return device.Flows, nil
228}
229
230// ListDeviceFlowGroups returns the flow group details for a specific device entry
231func (dMgr *Manager) ListDeviceFlowGroups(ctx context.Context, id *voltha.ID) (*voltha.FlowGroups, error) {
232 logger.Debugw("ListDeviceFlowGroups", log.Fields{"device-id": id.Id})
233
234 device, err := dMgr.getDevice(ctx, id.Id)
235 if err != nil {
236 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
237 }
238 return device.GetFlowGroups(), nil
khenaidoo4d4802d2018-10-04 21:59:49 -0400239}
240
khenaidoo6d62c002019-05-15 21:57:03 -0400241// stopManagingDevice stops the management of the device as well as any of its reference device and logical device.
242// This function is called only in the Core that does not own this device. In the Core that owns this device then a
243// deletion deletion also includes removal of any reference of this device.
Kent Hagerman2b216042020-04-03 18:28:56 -0400244func (dMgr *Manager) stopManagingDevice(ctx context.Context, id string) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000245 logger.Infow("stopManagingDevice", log.Fields{"deviceId": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400246 if dMgr.IsDeviceInCache(id) { // Proceed only if an agent is present for this device
npujar1d86a522019-11-14 17:11:16 +0530247 if root, _ := dMgr.IsRootDevice(id); root {
khenaidoo6d62c002019-05-15 21:57:03 -0400248 // stop managing the logical device
David Bainbridged1afd662020-03-26 18:27:41 -0700249 _ = dMgr.logicalDeviceMgr.stopManagingLogicalDeviceWithDeviceID(ctx, id)
khenaidoo6d62c002019-05-15 21:57:03 -0400250 }
npujar467fe752020-01-16 20:17:45 +0530251 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400252 if err := agent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000253 logger.Warnw("unable-to-stop-device-agent", log.Fields{"device-id": agent.deviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400254 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400255 dMgr.deleteDeviceAgentFromMap(agent)
khenaidoo6d62c002019-05-15 21:57:03 -0400256 }
257 }
258}
259
npujar1d86a522019-11-14 17:11:16 +0530260// RunPostDeviceDelete removes any reference of this device
Kent Hagerman2b216042020-04-03 18:28:56 -0400261func (dMgr *Manager) RunPostDeviceDelete(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000262 logger.Infow("RunPostDeviceDelete", log.Fields{"deviceId": cDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530263 dMgr.stopManagingDevice(ctx, cDevice.Id)
khenaidoo6d62c002019-05-15 21:57:03 -0400264 return nil
khenaidoo0a822f92019-05-08 15:15:57 -0400265}
266
Kent Hagerman45a13e42020-04-13 12:23:50 -0400267func (dMgr *Manager) GetDevice(ctx context.Context, id *voltha.ID) (*voltha.Device, error) {
268 return dMgr.getDevice(ctx, id.Id)
269}
270
271// getDevice will returns a device, either from memory or from the dB, if present
272func (dMgr *Manager) getDevice(ctx context.Context, id string) (*voltha.Device, error) {
273 logger.Debugw("getDevice", log.Fields{"deviceid": id})
npujar467fe752020-01-16 20:17:45 +0530274 if agent := dMgr.getDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400275 return agent.getDevice(ctx)
khenaidoo92e62c52018-10-03 14:02:54 -0400276 }
277 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400278}
279
npujar1d86a522019-11-14 17:11:16 +0530280// GetChildDevice will return a device, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -0400281func (dMgr *Manager) GetChildDevice(ctx context.Context, parentDeviceID string, serialNumber string, onuID int64, parentPortNo int64) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000282 logger.Debugw("GetChildDevice", log.Fields{"parentDeviceid": parentDeviceID, "serialNumber": serialNumber,
npujar1d86a522019-11-14 17:11:16 +0530283 "parentPortNo": parentPortNo, "onuId": onuID})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500284
285 var parentDevice *voltha.Device
286 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -0400287 if parentDevice, err = dMgr.getDevice(ctx, parentDeviceID); err != nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500288 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
289 }
290 var childDeviceIds []string
291 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
292 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
293 }
294 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000295 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530296 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500297 }
298
299 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530300 for _, childDeviceID := range childDeviceIds {
301 var found bool
Kent Hagerman45a13e42020-04-13 12:23:50 -0400302 if searchDevice, err := dMgr.getDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500303
npujar1d86a522019-11-14 17:11:16 +0530304 foundOnuID := false
305 if searchDevice.ProxyAddress.OnuId == uint32(onuID) {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500306 if searchDevice.ParentPortNo == uint32(parentPortNo) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000307 logger.Debugw("found-child-by-onuid", log.Fields{"parentDeviceId": parentDevice.Id, "onuId": onuID})
npujar1d86a522019-11-14 17:11:16 +0530308 foundOnuID = true
Matt Jeanneret4e241952019-02-28 11:16:04 -0500309 }
310 }
311
312 foundSerialNumber := false
313 if searchDevice.SerialNumber == serialNumber {
Girish Kumarf56a4682020-03-20 20:07:46 +0000314 logger.Debugw("found-child-by-serialnumber", log.Fields{"parentDeviceId": parentDevice.Id, "serialNumber": serialNumber})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500315 foundSerialNumber = true
316 }
317
318 // if both onuId and serialNumber are provided both must be true for the device to be found
319 // otherwise whichever one found a match is good enough
npujar1d86a522019-11-14 17:11:16 +0530320 if onuID > 0 && serialNumber != "" {
321 found = foundOnuID && foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500322 } else {
npujar1d86a522019-11-14 17:11:16 +0530323 found = foundOnuID || foundSerialNumber
Matt Jeanneret4e241952019-02-28 11:16:04 -0500324 }
325
npujar1d86a522019-11-14 17:11:16 +0530326 if found {
Matt Jeanneret4e241952019-02-28 11:16:04 -0500327 foundChildDevice = searchDevice
328 break
329 }
330 }
331 }
332
333 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000334 logger.Debugw("child-device-found", log.Fields{"parentDeviceId": parentDevice.Id, "foundChildDevice": foundChildDevice})
Matt Jeanneret4e241952019-02-28 11:16:04 -0500335 return foundChildDevice, nil
336 }
337
khenaidoo8b4abbf2020-04-24 17:04:30 -0400338 logger.Debugw("child-device-not-found", log.Fields{"parentDeviceId": parentDevice.Id,
npujar1d86a522019-11-14 17:11:16 +0530339 "serialNumber": serialNumber, "onuId": onuID, "parentPortNo": parentPortNo})
340 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
Matt Jeanneret4e241952019-02-28 11:16:04 -0500341}
342
npujar1d86a522019-11-14 17:11:16 +0530343// GetChildDeviceWithProxyAddress will return a device based on proxy address
Kent Hagerman2b216042020-04-03 18:28:56 -0400344func (dMgr *Manager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000345 logger.Debugw("GetChildDeviceWithProxyAddress", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500346
347 var parentDevice *voltha.Device
348 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -0400349 if parentDevice, err = dMgr.getDevice(ctx, proxyAddress.DeviceId); err != nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500350 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
351 }
352 var childDeviceIds []string
353 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
354 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
355 }
356 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000357 logger.Debugw("no-child-devices", log.Fields{"parentDeviceId": parentDevice.Id})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500358 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
359 }
360
361 var foundChildDevice *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530362 for _, childDeviceID := range childDeviceIds {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400363 if searchDevice, err := dMgr.getDevice(ctx, childDeviceID); err == nil {
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500364 if searchDevice.ProxyAddress == proxyAddress {
365 foundChildDevice = searchDevice
366 break
367 }
368 }
369 }
370
371 if foundChildDevice != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000372 logger.Debugw("child-device-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500373 return foundChildDevice, nil
374 }
375
Girish Kumarf56a4682020-03-20 20:07:46 +0000376 logger.Warnw("child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
Matt Jeanneret2a20aaa2019-03-05 21:04:02 -0500377 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
378}
379
npujar1d86a522019-11-14 17:11:16 +0530380// IsDeviceInCache returns true if device is found in the map
Kent Hagerman2b216042020-04-03 18:28:56 -0400381func (dMgr *Manager) IsDeviceInCache(id string) bool {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400382 _, exist := dMgr.deviceAgents.Load(id)
khenaidoo297cd252019-02-07 22:10:23 -0500383 return exist
384}
385
npujar1d86a522019-11-14 17:11:16 +0530386// IsRootDevice returns true if root device is found in the map
Kent Hagerman2b216042020-04-03 18:28:56 -0400387func (dMgr *Manager) IsRootDevice(id string) (bool, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -0400388 dMgr.lockRootDeviceMap.RLock()
389 defer dMgr.lockRootDeviceMap.RUnlock()
390 if exist := dMgr.rootDevices[id]; exist {
391 return dMgr.rootDevices[id], nil
khenaidoo19d7b632018-10-30 10:49:50 -0400392 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400393 return false, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400394}
395
Stephane Barbarieaa467942019-02-06 14:09:44 -0500396// ListDevices retrieves the latest devices from the data model
Kent Hagerman45a13e42020-04-13 12:23:50 -0400397func (dMgr *Manager) ListDevices(ctx context.Context, _ *empty.Empty) (*voltha.Devices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000398 logger.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400399 result := &voltha.Devices{}
Kent Hagerman4f355f52020-03-30 16:01:33 -0400400
401 var devices []*voltha.Device
Kent Hagermanf5a67352020-04-30 15:15:26 -0400402 if err := dMgr.dProxy.List(ctx, &devices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000403 logger.Errorw("failed-to-list-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530404 return nil, err
405 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400406
407 for _, device := range devices {
408 // If device is not in memory then set it up
409 if !dMgr.IsDeviceInCache(device.Id) {
410 logger.Debugw("loading-device-from-Model", log.Fields{"id": device.Id})
Kent Hagermanf5a67352020-04-30 15:15:26 -0400411 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dProxy, dMgr.defaultTimeout)
Kent Hagerman4f355f52020-03-30 16:01:33 -0400412 if _, err := agent.start(ctx, nil); err != nil {
413 logger.Warnw("failure-starting-agent", log.Fields{"deviceId": device.Id})
414 } else {
415 dMgr.addDeviceAgentToMap(agent)
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500416 }
khenaidoob9203542018-09-17 22:56:37 -0400417 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400418 result.Items = append(result.Items, device)
khenaidoob9203542018-09-17 22:56:37 -0400419 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000420 logger.Debugw("ListDevices-end", log.Fields{"len": len(result.Items)})
khenaidoob9203542018-09-17 22:56:37 -0400421 return result, nil
422}
423
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530424//isParentDeviceExist checks whether device is already preprovisioned.
Kent Hagerman2b216042020-04-03 18:28:56 -0400425func (dMgr *Manager) isParentDeviceExist(ctx context.Context, newDevice *voltha.Device) (bool, error) {
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530426 hostPort := newDevice.GetHostAndPort()
Kent Hagerman4f355f52020-03-30 16:01:33 -0400427 var devices []*voltha.Device
Kent Hagermanf5a67352020-04-30 15:15:26 -0400428 if err := dMgr.dProxy.List(ctx, &devices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000429 logger.Errorw("Failed to list devices from cluster data proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530430 return false, err
431 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400432 for _, device := range devices {
433 if !device.Root {
434 continue
435 }
436 if hostPort != "" && hostPort == device.GetHostAndPort() && device.AdminState != voltha.AdminState_DELETED {
437 return true, nil
438 }
439 if newDevice.MacAddress != "" && newDevice.MacAddress == device.MacAddress && device.AdminState != voltha.AdminState_DELETED {
440 return true, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530441 }
442 }
Thomas Lee Se5a44012019-11-07 20:32:24 +0530443 return false, nil
Thomas Lee S51b5cb82019-10-14 14:49:34 +0530444}
445
khenaidoo6d62c002019-05-15 21:57:03 -0400446//getDeviceFromModelretrieves the device data from the model.
Kent Hagerman2b216042020-04-03 18:28:56 -0400447func (dMgr *Manager) getDeviceFromModel(ctx context.Context, deviceID string) (*voltha.Device, error) {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400448 device := &voltha.Device{}
Kent Hagermanf5a67352020-04-30 15:15:26 -0400449 if have, err := dMgr.dProxy.Get(ctx, deviceID, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000450 logger.Errorw("failed-to-get-device-info-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530451 return nil, err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400452 } else if !have {
453 return nil, status.Error(codes.NotFound, deviceID)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530454 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400455
456 return device, nil
khenaidoo6d62c002019-05-15 21:57:03 -0400457}
458
npujar1d86a522019-11-14 17:11:16 +0530459// loadDevice loads the deviceID in memory, if not present
Kent Hagerman2b216042020-04-03 18:28:56 -0400460func (dMgr *Manager) loadDevice(ctx context.Context, deviceID string) (*Agent, error) {
npujar1d86a522019-11-14 17:11:16 +0530461 if deviceID == "" {
khenaidoo297cd252019-02-07 22:10:23 -0500462 return nil, status.Error(codes.InvalidArgument, "deviceId empty")
463 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400464 var err error
465 var device *voltha.Device
466 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530467 if _, exist := dMgr.deviceLoadingInProgress[deviceID]; !exist {
468 if !dMgr.IsDeviceInCache(deviceID) {
469 dMgr.deviceLoadingInProgress[deviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400470 dMgr.devicesLoadingLock.Unlock()
471 // Proceed with the loading only if the device exist in the Model (could have been deleted)
npujar467fe752020-01-16 20:17:45 +0530472 if device, err = dMgr.getDeviceFromModel(ctx, deviceID); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000473 logger.Debugw("loading-device", log.Fields{"deviceId": deviceID})
Kent Hagermanf5a67352020-04-30 15:15:26 -0400474 agent := newAgent(dMgr.adapterProxy, device, dMgr, dMgr.dProxy, dMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530475 if _, err = agent.start(ctx, nil); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000476 logger.Warnw("Failure loading device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400477 } else {
478 dMgr.addDeviceAgentToMap(agent)
479 }
480 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000481 logger.Debugw("Device not in model", log.Fields{"deviceId": deviceID})
khenaidoo6d62c002019-05-15 21:57:03 -0400482 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400483 // announce completion of task to any number of waiting channels
484 dMgr.devicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530485 if v, ok := dMgr.deviceLoadingInProgress[deviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400486 for _, ch := range v {
487 close(ch)
488 }
npujar1d86a522019-11-14 17:11:16 +0530489 delete(dMgr.deviceLoadingInProgress, deviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400490 }
491 dMgr.devicesLoadingLock.Unlock()
khenaidoo6d62c002019-05-15 21:57:03 -0400492 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -0400493 dMgr.devicesLoadingLock.Unlock()
khenaidoo297cd252019-02-07 22:10:23 -0500494 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400495 } else {
496 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530497 dMgr.deviceLoadingInProgress[deviceID] = append(dMgr.deviceLoadingInProgress[deviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400498 dMgr.devicesLoadingLock.Unlock()
499 // Wait for the channel to be closed, implying the process loading this device is done.
500 <-ch
khenaidoo297cd252019-02-07 22:10:23 -0500501 }
npujar1d86a522019-11-14 17:11:16 +0530502 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -0400503 return agent.(*Agent), nil
khenaidoo297cd252019-02-07 22:10:23 -0500504 }
npujar1d86a522019-11-14 17:11:16 +0530505 return nil, status.Errorf(codes.Aborted, "Error loading device %s", deviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500506}
507
508// loadRootDeviceParentAndChildren loads the children and parents of a root device in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400509func (dMgr *Manager) loadRootDeviceParentAndChildren(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000510 logger.Debugw("loading-parent-and-children", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500511 if device.Root {
512 // Scenario A
513 if device.ParentId != "" {
514 // Load logical device if needed.
npujar467fe752020-01-16 20:17:45 +0530515 if err := dMgr.logicalDeviceMgr.load(ctx, device.ParentId); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000516 logger.Warnw("failure-loading-logical-device", log.Fields{"lDeviceId": device.ParentId})
khenaidoo297cd252019-02-07 22:10:23 -0500517 }
518 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000519 logger.Debugw("no-parent-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500520 }
521 // Load all child devices, if needed
522 if childDeviceIds, err := dMgr.getAllChildDeviceIds(device); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530523 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530524 if _, err := dMgr.loadDevice(ctx, childDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000525 logger.Warnw("failure-loading-device", log.Fields{"deviceId": childDeviceID, "error": err})
khenaidoo297cd252019-02-07 22:10:23 -0500526 return err
527 }
528 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000529 logger.Debugw("loaded-children", log.Fields{"deviceId": device.Id, "numChildren": len(childDeviceIds)})
khenaidoo297cd252019-02-07 22:10:23 -0500530 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000531 logger.Debugw("no-child-to-load", log.Fields{"deviceId": device.Id})
khenaidoo297cd252019-02-07 22:10:23 -0500532 }
533 }
534 return nil
535}
536
537// load loads the deviceId in memory, if not present, and also loads its accompanying parents and children. Loading
538// in memory is for improved performance. It is not imperative that a device needs to be in memory when a request
539// acting on the device is received by the core. In such a scenario, the Core will load the device in memory first
540// and the proceed with the request.
Kent Hagerman2b216042020-04-03 18:28:56 -0400541func (dMgr *Manager) load(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000542 logger.Debug("load...")
khenaidoo297cd252019-02-07 22:10:23 -0500543 // 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 -0400544 var dAgent *Agent
khenaidoo297cd252019-02-07 22:10:23 -0500545 var err error
npujar467fe752020-01-16 20:17:45 +0530546 if dAgent, err = dMgr.loadDevice(ctx, deviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500547 return err
548 }
549 // Get the loaded device details
khenaidoo442e7c72020-03-10 16:13:48 -0400550 device, err := dAgent.getDevice(ctx)
551 if err != nil {
552 return err
553 }
khenaidoo297cd252019-02-07 22:10:23 -0500554
555 // If the device is in Pre-provisioning or deleted state stop here
556 if device.AdminState == voltha.AdminState_PREPROVISIONED || device.AdminState == voltha.AdminState_DELETED {
557 return nil
558 }
559
560 // Now we face two scenarios
561 if device.Root {
562 // Load all children as well as the parent of this device (logical_device)
npujar467fe752020-01-16 20:17:45 +0530563 if err := dMgr.loadRootDeviceParentAndChildren(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000564 logger.Warnw("failure-loading-device-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500565 return err
566 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000567 logger.Debugw("successfully-loaded-parent-and-children", log.Fields{"deviceId": deviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500568 } else {
569 // Scenario B - use the parentId of that device (root device) to trigger the loading
570 if device.ParentId != "" {
npujar467fe752020-01-16 20:17:45 +0530571 return dMgr.load(ctx, device.ParentId)
khenaidoo297cd252019-02-07 22:10:23 -0500572 }
573 }
574 return nil
575}
576
khenaidoo7ccedd52018-12-14 16:48:54 -0500577// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400578func (dMgr *Manager) ListDeviceIds(_ context.Context, _ *empty.Empty) (*voltha.IDs, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000579 logger.Debug("ListDeviceIDs")
khenaidoo7ccedd52018-12-14 16:48:54 -0500580 // Report only device IDs that are in the device agent map
581 return dMgr.listDeviceIdsFromMap(), nil
582}
583
Kent Hagerman45a13e42020-04-13 12:23:50 -0400584// ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
585// trigger loading the devices along with their children and parent in memory
586func (dMgr *Manager) ReconcileDevices(ctx context.Context, ids *voltha.IDs) (*empty.Empty, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000587 logger.Debugw("ReconcileDevices", log.Fields{"numDevices": len(ids.Items)})
khenaidoo4c9e5592019-09-09 16:20:41 -0400588 if ids != nil && len(ids.Items) != 0 {
khenaidoo7ccedd52018-12-14 16:48:54 -0500589 toReconcile := len(ids.Items)
590 reconciled := 0
khenaidoo4c9e5592019-09-09 16:20:41 -0400591 var err error
khenaidoo7ccedd52018-12-14 16:48:54 -0500592 for _, id := range ids.Items {
npujar467fe752020-01-16 20:17:45 +0530593 if err = dMgr.load(ctx, id.Id); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000594 logger.Warnw("failure-reconciling-device", log.Fields{"deviceId": id.Id, "error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400595 } else {
npujar1d86a522019-11-14 17:11:16 +0530596 reconciled++
khenaidoo7ccedd52018-12-14 16:48:54 -0500597 }
598 }
599 if toReconcile != reconciled {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400600 return nil, status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
khenaidoo7ccedd52018-12-14 16:48:54 -0500601 }
602 } else {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400603 return nil, status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
khenaidoo7ccedd52018-12-14 16:48:54 -0500604 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400605 return &empty.Empty{}, nil
khenaidoo7ccedd52018-12-14 16:48:54 -0500606}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500607
khenaidooba6b6c42019-08-02 09:11:56 -0400608// isOkToReconcile validates whether a device is in the correct status to be reconciled
609func isOkToReconcile(device *voltha.Device) bool {
610 if device == nil {
611 return false
612 }
613 return device.AdminState != voltha.AdminState_PREPROVISIONED && device.AdminState != voltha.AdminState_DELETED
614}
615
616// adapterRestarted is invoked whenever an adapter is restarted
Kent Hagerman2b216042020-04-03 18:28:56 -0400617func (dMgr *Manager) adapterRestarted(ctx context.Context, adapter *voltha.Adapter) error {
Matteo Scandolod525ae32020-04-02 17:27:29 -0700618 logger.Debugw("adapter-restarted", log.Fields{"adapterId": adapter.Id, "vendor": adapter.Vendor,
619 "currentReplica": adapter.CurrentReplica, "totalReplicas": adapter.TotalReplicas, "endpoint": adapter.Endpoint})
khenaidooba6b6c42019-08-02 09:11:56 -0400620
621 // Let's reconcile the device managed by this Core only
David Bainbridged1afd662020-03-26 18:27:41 -0700622 if len(dMgr.rootDevices) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000623 logger.Debugw("nothing-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400624 return nil
625 }
626
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500627 responses := make([]utils.Response, 0)
David Bainbridged1afd662020-03-26 18:27:41 -0700628 for rootDeviceID := range dMgr.rootDevices {
npujar467fe752020-01-16 20:17:45 +0530629 if rootDevice, _ := dMgr.getDeviceFromModel(ctx, rootDeviceID); rootDevice != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -0400630 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(rootDeviceID, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700631 if err != nil {
632 logger.Warnw("is-device-owned-by-service", log.Fields{"error": err, "root-device-id": rootDeviceID, "adapterType": adapter.Type, "replica-number": adapter.CurrentReplica})
633 continue
634 }
635 if isDeviceOwnedByService {
khenaidooba6b6c42019-08-02 09:11:56 -0400636 if isOkToReconcile(rootDevice) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000637 logger.Debugw("reconciling-root-device", log.Fields{"rootId": rootDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530638 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, rootDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400639 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000640 logger.Debugw("not-reconciling-root-device", log.Fields{"rootId": rootDevice.Id, "state": rootDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400641 }
642 } else { // Should we be reconciling the root's children instead?
643 childManagedByAdapter:
644 for _, port := range rootDevice.Ports {
645 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530646 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -0400647 isDeviceOwnedByService, err := dMgr.adapterProxy.IsDeviceOwnedByService(childDevice.Id, adapter.Type, adapter.CurrentReplica)
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700648 if err != nil {
649 logger.Warnw("is-device-owned-by-service", log.Fields{"error": err, "child-device-id": childDevice.Id, "adapterType": adapter.Type, "replica-number": adapter.CurrentReplica})
650 }
651 if isDeviceOwnedByService {
khenaidooba6b6c42019-08-02 09:11:56 -0400652 if isOkToReconcile(childDevice) {
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700653 logger.Debugw("reconciling-child-device", log.Fields{"child-device-id": childDevice.Id})
npujar467fe752020-01-16 20:17:45 +0530654 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400655 } else {
serkant.uluderya7d545aa2020-04-09 13:38:45 -0700656 logger.Debugw("not-reconciling-child-device", log.Fields{"child-device-id": childDevice.Id, "state": childDevice.AdminState})
khenaidooba6b6c42019-08-02 09:11:56 -0400657 }
658 } else {
659 // All child devices under a parent device are typically managed by the same adapter type.
660 // Therefore we only need to check whether the first device we retrieved is managed by that adapter
661 break childManagedByAdapter
662 }
663 }
664 }
665 }
666 }
667 }
668 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500669 if len(responses) > 0 {
khenaidooba6b6c42019-08-02 09:11:56 -0400670 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500671 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400672 return status.Errorf(codes.Aborted, "errors-%s", res)
673 }
674 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000675 logger.Debugw("no-managed-device-to-reconcile", log.Fields{"adapterId": adapter.Id})
khenaidooba6b6c42019-08-02 09:11:56 -0400676 }
677 return nil
678}
679
Kent Hagerman2b216042020-04-03 18:28:56 -0400680func (dMgr *Manager) sendReconcileDeviceRequest(ctx context.Context, device *voltha.Device) utils.Response {
khenaidooba6b6c42019-08-02 09:11:56 -0400681 // Send a reconcile request to the adapter. Since this Core may not be managing this device then there is no
682 // 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 +0530683 // 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 -0400684 // the adapter proxy.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500685 response := utils.NewResponse()
Kent Hagerman2b216042020-04-03 18:28:56 -0400686 ch, err := dMgr.adapterProxy.ReconcileDevice(ctx, device)
khenaidoo442e7c72020-03-10 16:13:48 -0400687 if err != nil {
688 response.Error(err)
689 }
690 // Wait for adapter response in its own routine
691 go func() {
692 resp, ok := <-ch
693 if !ok {
694 response.Error(status.Errorf(codes.Aborted, "channel-closed-device: %s", device.Id))
695 } else if resp.Err != nil {
696 response.Error(resp.Err)
khenaidooba6b6c42019-08-02 09:11:56 -0400697 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500698 response.Done()
khenaidoo442e7c72020-03-10 16:13:48 -0400699 }()
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500700 return response
khenaidooba6b6c42019-08-02 09:11:56 -0400701}
702
Kent Hagerman2b216042020-04-03 18:28:56 -0400703func (dMgr *Manager) ReconcileChildDevices(ctx context.Context, parentDeviceID string) error {
npujar467fe752020-01-16 20:17:45 +0530704 if parentDevice, _ := dMgr.getDeviceFromModel(ctx, parentDeviceID); parentDevice != nil {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500705 responses := make([]utils.Response, 0)
khenaidooba6b6c42019-08-02 09:11:56 -0400706 for _, port := range parentDevice.Ports {
707 for _, peer := range port.Peers {
npujar467fe752020-01-16 20:17:45 +0530708 if childDevice, _ := dMgr.getDeviceFromModel(ctx, peer.DeviceId); childDevice != nil {
709 responses = append(responses, dMgr.sendReconcileDeviceRequest(ctx, childDevice))
khenaidooba6b6c42019-08-02 09:11:56 -0400710 }
711 }
712 }
713 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500714 if res := utils.WaitForNilOrErrorResponses(dMgr.defaultTimeout, responses...); res != nil {
khenaidooba6b6c42019-08-02 09:11:56 -0400715 return status.Errorf(codes.Aborted, "errors-%s", res)
716 }
717 }
718 return nil
719}
720
Kent Hagerman2b216042020-04-03 18:28:56 -0400721func (dMgr *Manager) UpdateDeviceUsingAdapterData(ctx context.Context, device *voltha.Device) error {
722 logger.Debugw("UpdateDeviceUsingAdapterData", log.Fields{"deviceid": device.Id, "device": device})
npujar467fe752020-01-16 20:17:45 +0530723 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
724 return agent.updateDeviceUsingAdapterData(ctx, device)
khenaidoob9203542018-09-17 22:56:37 -0400725 }
726 return status.Errorf(codes.NotFound, "%s", device.Id)
727}
728
khenaidoo0db4c812020-05-27 15:27:30 -0400729func (dMgr *Manager) addPeerPort(ctx context.Context, deviceID string, port *voltha.Port) error {
730 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceID, PortNo: port.PortNo}
731 for _, peerPort := range port.Peers {
732 if agent := dMgr.getDeviceAgent(ctx, peerPort.DeviceId); agent != nil {
733 if err := agent.addPeerPort(ctx, meAsPeer); err != nil {
734 return err
735 }
736 }
737 }
738 // Notify the logical device manager to setup a logical port, if needed. If the added port is an NNI or UNI
739 // then a logical port will be added to the logical device and the device route generated. If the port is a
740 // PON port then only the device graph will be generated.
741 device, err := dMgr.getDevice(ctx, deviceID)
742 if err != nil {
743 return err
744 }
745 if err = dMgr.logicalDeviceMgr.updateLogicalPort(context.Background(), device, port); err != nil {
746 return err
747 }
748 return nil
749}
750
Kent Hagerman2b216042020-04-03 18:28:56 -0400751func (dMgr *Manager) AddPort(ctx context.Context, deviceID string, port *voltha.Port) error {
npujar467fe752020-01-16 20:17:45 +0530752 agent := dMgr.getDeviceAgent(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530753 if agent != nil {
npujar467fe752020-01-16 20:17:45 +0530754 if err := agent.addPort(ctx, port); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400755 return err
756 }
khenaidoo0db4c812020-05-27 15:27:30 -0400757 // Setup peer ports in its own routine
758 go func() {
759 if err := dMgr.addPeerPort(ctx, deviceID, port); err != nil {
760 logger.Errorw("unable-to-add-peer-port", log.Fields{"error": err, "device-id": deviceID})
khenaidoo92e62c52018-10-03 14:02:54 -0400761 }
khenaidoo0db4c812020-05-27 15:27:30 -0400762 }()
khenaidoo92e62c52018-10-03 14:02:54 -0400763 return nil
khenaidoob9203542018-09-17 22:56:37 -0400764 }
npujar1d86a522019-11-14 17:11:16 +0530765 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400766}
767
Kent Hagerman2b216042020-04-03 18:28:56 -0400768func (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 +0000769 logger.Debugw("addFlowsAndGroups", log.Fields{"deviceid": deviceID, "groups:": groups, "flowMetadata": flowMetadata})
npujar467fe752020-01-16 20:17:45 +0530770 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
771 return agent.addFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400772 }
npujar1d86a522019-11-14 17:11:16 +0530773 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400774}
775
khenaidoo787224a2020-04-16 18:08:47 -0400776// deleteParentFlows removes flows from the parent device based on specific attributes
777func (dMgr *Manager) deleteParentFlows(ctx context.Context, deviceID string, uniPort uint32, metadata *voltha.FlowMetadata) error {
778 logger.Debugw("deleteParentFlows", log.Fields{"device-id": deviceID, "uni-port": uniPort, "metadata": metadata})
779 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
780 if !agent.isRootdevice {
781 return status.Errorf(codes.FailedPrecondition, "not-a-parent-device-%s", deviceID)
782 }
783 return agent.filterOutFlows(ctx, uniPort, metadata)
784 }
785 return status.Errorf(codes.NotFound, "%s", deviceID)
786}
787
Kent Hagerman2b216042020-04-03 18:28:56 -0400788func (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 +0000789 logger.Debugw("deleteFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530790 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
791 return agent.deleteFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo0458db62019-06-20 08:50:36 -0400792 }
npujar1d86a522019-11-14 17:11:16 +0530793 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0458db62019-06-20 08:50:36 -0400794}
795
Kent Hagerman2b216042020-04-03 18:28:56 -0400796func (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 +0000797 logger.Debugw("updateFlowsAndGroups", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530798 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
799 return agent.updateFlowsAndGroups(ctx, flows, groups, flowMetadata)
khenaidoo19d7b632018-10-30 10:49:50 -0400800 }
npujar1d86a522019-11-14 17:11:16 +0530801 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400802}
803
Kent Hagerman45a13e42020-04-13 12:23:50 -0400804// UpdateDevicePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
khenaidoob3127472019-07-24 21:04:55 -0400805// following a user action
Kent Hagerman45a13e42020-04-13 12:23:50 -0400806func (dMgr *Manager) UpdateDevicePmConfigs(ctx context.Context, configs *voltha.PmConfigs) (*empty.Empty, error) {
807 if configs.Id == "" {
808 return nil, status.Error(codes.FailedPrecondition, "invalid-device-Id")
khenaidoob3127472019-07-24 21:04:55 -0400809 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400810 agent := dMgr.getDeviceAgent(ctx, configs.Id)
811 if agent == nil {
812 return nil, status.Errorf(codes.NotFound, "%s", configs.Id)
813 }
814 return &empty.Empty{}, agent.updatePmConfigs(ctx, configs)
khenaidoob3127472019-07-24 21:04:55 -0400815}
816
Kent Hagerman2b216042020-04-03 18:28:56 -0400817// InitPmConfigs initialize the pm configs as defined by the adapter.
818func (dMgr *Manager) InitPmConfigs(ctx context.Context, deviceID string, pmConfigs *voltha.PmConfigs) error {
khenaidoob3127472019-07-24 21:04:55 -0400819 if pmConfigs.Id == "" {
820 return status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
821 }
npujar467fe752020-01-16 20:17:45 +0530822 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
823 return agent.initPmConfigs(ctx, pmConfigs)
khenaidoob9203542018-09-17 22:56:37 -0400824 }
npujar1d86a522019-11-14 17:11:16 +0530825 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400826}
827
Kent Hagerman45a13e42020-04-13 12:23:50 -0400828// ListDevicePmConfigs returns pm configs of device
829func (dMgr *Manager) ListDevicePmConfigs(ctx context.Context, id *voltha.ID) (*voltha.PmConfigs, error) {
830 agent := dMgr.getDeviceAgent(ctx, id.Id)
831 if agent == nil {
832 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob3127472019-07-24 21:04:55 -0400833 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400834 return agent.listPmConfigs(ctx)
khenaidoob3127472019-07-24 21:04:55 -0400835}
836
Kent Hagerman2b216042020-04-03 18:28:56 -0400837func (dMgr *Manager) getSwitchCapability(ctx context.Context, deviceID string) (*ic.SwitchCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000838 logger.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530839 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400840 return agent.getSwitchCapability(ctx)
841 }
npujar1d86a522019-11-14 17:11:16 +0530842 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400843}
844
Kent Hagerman2b216042020-04-03 18:28:56 -0400845func (dMgr *Manager) GetPorts(ctx context.Context, deviceID string, portType voltha.Port_PortType) (*voltha.Ports, error) {
846 logger.Debugw("GetPorts", log.Fields{"deviceid": deviceID, "portType": portType})
npujar467fe752020-01-16 20:17:45 +0530847 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400848 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400849 }
npujar1d86a522019-11-14 17:11:16 +0530850 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400851}
852
Kent Hagerman2b216042020-04-03 18:28:56 -0400853func (dMgr *Manager) getPortCapability(ctx context.Context, deviceID string, portNo uint32) (*ic.PortCapability, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000854 logger.Debugw("getPortCapability", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530855 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoob9203542018-09-17 22:56:37 -0400856 return agent.getPortCapability(ctx, portNo)
857 }
npujar1d86a522019-11-14 17:11:16 +0530858 return nil, status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400859}
860
Kent Hagerman2b216042020-04-03 18:28:56 -0400861func (dMgr *Manager) UpdateDeviceStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
862 logger.Debugw("UpdateDeviceStatus", log.Fields{"deviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
npujar467fe752020-01-16 20:17:45 +0530863 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
864 return agent.updateDeviceStatus(ctx, operStatus, connStatus)
khenaidoo92e62c52018-10-03 14:02:54 -0400865 }
npujar1d86a522019-11-14 17:11:16 +0530866 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400867}
868
Kent Hagerman2b216042020-04-03 18:28:56 -0400869func (dMgr *Manager) UpdateChildrenStatus(ctx context.Context, deviceID string, operStatus voltha.OperStatus_Types, connStatus voltha.ConnectStatus_Types) error {
870 logger.Debugw("UpdateChildrenStatus", log.Fields{"parentDeviceid": deviceID, "operStatus": operStatus, "connStatus": connStatus})
khenaidoo4d4802d2018-10-04 21:59:49 -0400871 var parentDevice *voltha.Device
872 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -0400873 if parentDevice, err = dMgr.getDevice(ctx, deviceID); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400874 return status.Errorf(codes.Aborted, "%s", err.Error())
875 }
876 var childDeviceIds []string
877 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
878 return status.Errorf(codes.Aborted, "%s", err.Error())
879 }
880 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000881 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -0400882 }
npujar1d86a522019-11-14 17:11:16 +0530883 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +0530884 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
885 if err = agent.updateDeviceStatus(ctx, operStatus, connStatus); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530886 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
khenaidoo4d4802d2018-10-04 21:59:49 -0400887 }
888 }
889 }
890 return nil
891}
892
Kent Hagerman2b216042020-04-03 18:28:56 -0400893func (dMgr *Manager) UpdatePortState(ctx context.Context, deviceID string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
894 logger.Debugw("UpdatePortState", log.Fields{"deviceid": deviceID, "portType": portType, "portNo": portNo, "operStatus": operStatus})
npujar467fe752020-01-16 20:17:45 +0530895 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
896 if err := agent.updatePortState(ctx, portType, portNo, operStatus); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000897 logger.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceID, "portNo": portNo, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400898 return err
899 }
900 // Notify the logical device manager to change the port state
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800901 // Do this for NNI and UNIs only. PON ports are not known by logical device
902 if portType == voltha.Port_ETHERNET_NNI || portType == voltha.Port_ETHERNET_UNI {
903 go func() {
904 err := dMgr.logicalDeviceMgr.updatePortState(context.Background(), deviceID, portNo, operStatus)
905 if err != nil {
906 // While we want to handle (catch) and log when
907 // an update to a port was not able to be
908 // propagated to the logical port, we can report
909 // it as a warning and not an error because it
910 // doesn't stop or modify processing.
911 // TODO: VOL-2707
Girish Kumarf56a4682020-03-20 20:07:46 +0000912 logger.Warnw("unable-to-update-logical-port-state", log.Fields{"error": err})
Mahir Gunyel18fa0c92020-03-06 13:34:04 -0800913 }
914 }()
915 }
khenaidoo442e7c72020-03-10 16:13:48 -0400916 return nil
khenaidoob9203542018-09-17 22:56:37 -0400917 }
npujar1d86a522019-11-14 17:11:16 +0530918 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoob9203542018-09-17 22:56:37 -0400919}
920
Kent Hagerman2b216042020-04-03 18:28:56 -0400921func (dMgr *Manager) DeleteAllPorts(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000922 logger.Debugw("DeleteAllPorts", log.Fields{"deviceid": deviceID})
npujar467fe752020-01-16 20:17:45 +0530923 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
924 if err := agent.deleteAllPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400925 return err
926 }
927 // Notify the logical device manager to remove all logical ports, if needed.
Kent Hagerman2b216042020-04-03 18:28:56 -0400928 // At this stage the device itself may gave been deleted already at a DeleteAllPorts
khenaidoo0a822f92019-05-08 15:15:57 -0400929 // typically is part of a device deletion phase.
Kent Hagerman45a13e42020-04-13 12:23:50 -0400930 if device, err := dMgr.getDevice(ctx, deviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530931 go func() {
npujar467fe752020-01-16 20:17:45 +0530932 err = dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530933 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000934 logger.Errorw("unable-to-delete-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530935 }
936 }()
khenaidoo0a822f92019-05-08 15:15:57 -0400937 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000938 logger.Warnw("failed-to-retrieve-device", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400939 return err
940 }
941 return nil
942 }
npujar1d86a522019-11-14 17:11:16 +0530943 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo0a822f92019-05-08 15:15:57 -0400944}
945
Kent Hagerman2b216042020-04-03 18:28:56 -0400946//UpdatePortsState updates all ports on the device
947func (dMgr *Manager) UpdatePortsState(ctx context.Context, deviceID string, state voltha.OperStatus_Types) error {
948 logger.Debugw("UpdatePortsState", log.Fields{"deviceid": deviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400949
npujar467fe752020-01-16 20:17:45 +0530950 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400951 switch state {
952 case voltha.OperStatus_ACTIVE:
kesavandbc2d1622020-01-21 00:42:01 -0500953 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000954 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400955 return err
956 }
957 case voltha.OperStatus_UNKNOWN:
kesavandbc2d1622020-01-21 00:42:01 -0500958 if err := agent.updatePortsOperState(ctx, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000959 logger.Warnw("updatePortsOperState-failed", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400960 return err
961 }
962 default:
963 return status.Error(codes.Unimplemented, "state-change-not-implemented")
964 }
965 // Notify the logical device about the state change
Kent Hagerman45a13e42020-04-13 12:23:50 -0400966 device, err := dMgr.getDevice(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530967 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000968 logger.Warnw("non-existent-device", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400969 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400970 }
kesavandbc2d1622020-01-21 00:42:01 -0500971 if err := dMgr.logicalDeviceMgr.updatePortsState(ctx, device, state); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000972 logger.Warnw("failed-updating-ports-state", log.Fields{"deviceId": deviceID, "error": err})
npujar1d86a522019-11-14 17:11:16 +0530973 return err
974 }
975 return nil
khenaidoo3ab34882019-05-02 21:33:30 -0400976 }
npujar1d86a522019-11-14 17:11:16 +0530977 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoo3ab34882019-05-02 21:33:30 -0400978}
979
Kent Hagerman2b216042020-04-03 18:28:56 -0400980func (dMgr *Manager) ChildDeviceDetected(ctx context.Context, parentDeviceID string, parentPortNo int64, deviceType string,
npujar1d86a522019-11-14 17:11:16 +0530981 channelID int64, vendorID string, serialNumber string, onuID int64) (*voltha.Device, error) {
Kent Hagerman2b216042020-04-03 18:28:56 -0400982 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 -0700983
npujar1d86a522019-11-14 17:11:16 +0530984 if deviceType == "" && vendorID != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +0000985 logger.Debug("device-type-is-nil-fetching-device-type")
Kent Hagerman45a13e42020-04-13 12:23:50 -0400986 deviceTypes, err := dMgr.adapterMgr.ListDeviceTypes(ctx, nil)
987 if err != nil {
988 return nil, err
989 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400990 OLoop:
Kent Hagerman45a13e42020-04-13 12:23:50 -0400991 for _, dType := range deviceTypes.Items {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400992 for _, v := range dType.VendorIds {
993 if v == vendorID {
994 deviceType = dType.Adapter
995 break OLoop
Chaitrashree G S4b3fada2019-07-28 23:55:25 -0700996 }
997 }
998 }
999 }
1000 //if no match found for the vendorid,report adapter with the custom error message
1001 if deviceType == "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001002 logger.Errorw("failed-to-fetch-adapter-name ", log.Fields{"vendorId": vendorID})
npujar1d86a522019-11-14 17:11:16 +05301003 return nil, status.Errorf(codes.NotFound, "%s", vendorID)
Chaitrashree G S4b3fada2019-07-28 23:55:25 -07001004 }
khenaidoob9203542018-09-17 22:56:37 -04001005
1006 // Create the ONU device
1007 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -04001008 childDevice.Type = deviceType
npujar1d86a522019-11-14 17:11:16 +05301009 childDevice.ParentId = parentDeviceID
khenaidoob9203542018-09-17 22:56:37 -04001010 childDevice.ParentPortNo = uint32(parentPortNo)
npujar1d86a522019-11-14 17:11:16 +05301011 childDevice.VendorId = vendorID
Matt Jeanneret4e241952019-02-28 11:16:04 -05001012 childDevice.SerialNumber = serialNumber
khenaidoob9203542018-09-17 22:56:37 -04001013 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001014
khenaidoo442e7c72020-03-10 16:13:48 -04001015 // Get parent device type
1016 pAgent := dMgr.getDeviceAgent(ctx, parentDeviceID)
1017 if pAgent == nil {
npujar1d86a522019-11-14 17:11:16 +05301018 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001019 }
khenaidoo442e7c72020-03-10 16:13:48 -04001020 if pAgent.deviceType == "" {
1021 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", parentDeviceID)
1022 }
khenaidoo6fdf0ba2018-11-02 14:38:33 -04001023
npujar467fe752020-01-16 20:17:45 +05301024 if device, err := dMgr.GetChildDevice(ctx, parentDeviceID, serialNumber, onuID, parentPortNo); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001025 logger.Warnw("child-device-exists", log.Fields{"parentId": parentDeviceID, "serialNumber": serialNumber})
Mahir Gunyel6deaa242019-06-27 04:53:33 -07001026 return device, status.Errorf(codes.AlreadyExists, "%s", serialNumber)
Matt Jeanneret4e241952019-02-28 11:16:04 -05001027 }
1028
khenaidoo442e7c72020-03-10 16:13:48 -04001029 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceID, DeviceType: pAgent.deviceType, ChannelId: uint32(channelID), OnuId: uint32(onuID)}
khenaidoob9203542018-09-17 22:56:37 -04001030
1031 // Create and start a device agent for that device
Kent Hagermanf5a67352020-04-30 15:15:26 -04001032 agent := newAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.dProxy, dMgr.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -04001033 childDevice, err := agent.start(ctx, childDevice)
Scott Baker80678602019-11-14 16:57:36 -08001034 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001035 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 -08001036 return nil, err
1037 }
khenaidoo442e7c72020-03-10 16:13:48 -04001038 dMgr.addDeviceAgentToMap(agent)
khenaidoob9203542018-09-17 22:56:37 -04001039
1040 // Activate the child device
npujar467fe752020-01-16 20:17:45 +05301041 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +05301042 go func() {
npujar467fe752020-01-16 20:17:45 +05301043 err := agent.enableDevice(context.Background())
npujar1d86a522019-11-14 17:11:16 +05301044 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001045 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301046 }
1047 }()
khenaidoob9203542018-09-17 22:56:37 -04001048 }
1049
khenaidoo79232702018-12-04 11:00:41 -05001050 // Publish on the messaging bus that we have discovered new devices
npujar1d86a522019-11-14 17:11:16 +05301051 go func() {
1052 err := dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceID, deviceType, parentDeviceID, dMgr.coreInstanceID)
1053 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001054 logger.Errorw("unable-to-discover-the-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301055 }
1056 }()
khenaidoo79232702018-12-04 11:00:41 -05001057
Scott Baker80678602019-11-14 16:57:36 -08001058 return childDevice, nil
khenaidoob9203542018-09-17 22:56:37 -04001059}
1060
Kent Hagerman2b216042020-04-03 18:28:56 -04001061func (dMgr *Manager) processTransition(ctx context.Context, device *voltha.Device, previousState *deviceState) error {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001062 // This will be triggered on every state update
1063 logger.Debugw("state-transition", log.Fields{
1064 "device": device.Id,
1065 "prev-admin-state": previousState.Admin,
1066 "prev-oper-state": previousState.Operational,
1067 "prev-conn-state": previousState.Connection,
1068 "curr-admin-state": device.AdminState,
1069 "curr-oper-state": device.OperStatus,
1070 "curr-conn-state": device.ConnectStatus,
1071 })
1072 handlers := dMgr.stateTransitions.GetTransitionHandler(device, previousState)
khenaidoo92e62c52018-10-03 14:02:54 -04001073 if handlers == nil {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001074 logger.Debugw("no-op-transition", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001075 return nil
khenaidoob9203542018-09-17 22:56:37 -04001076 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001077 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 -04001078 for _, handler := range handlers {
Girish Kumarf56a4682020-03-20 20:07:46 +00001079 logger.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001080 if err := handler(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001081 logger.Warnw("handler-failed", log.Fields{"handler": funcName(handler), "error": err})
khenaidoo92e62c52018-10-03 14:02:54 -04001082 return err
1083 }
1084 }
khenaidoob9203542018-09-17 22:56:37 -04001085 return nil
1086}
1087
Kent Hagerman2b216042020-04-03 18:28:56 -04001088func (dMgr *Manager) packetOut(ctx context.Context, deviceID string, outPort uint32, packet *ofp.OfpPacketOut) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001089 logger.Debugw("packetOut", log.Fields{"deviceId": deviceID, "outPort": outPort})
npujar467fe752020-01-16 20:17:45 +05301090 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1091 return agent.packetOut(ctx, outPort, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001092 }
npujar1d86a522019-11-14 17:11:16 +05301093 return status.Errorf(codes.NotFound, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001094}
1095
npujar1d86a522019-11-14 17:11:16 +05301096// PacketIn receives packet from adapter
Kent Hagerman2b216042020-04-03 18:28:56 -04001097func (dMgr *Manager) PacketIn(ctx context.Context, deviceID string, port uint32, transactionID string, packet []byte) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001098 logger.Debugw("PacketIn", log.Fields{"deviceId": deviceID, "port": port})
khenaidoofdbad6e2018-11-06 22:26:38 -05001099 // Get the logical device Id based on the deviceId
1100 var device *voltha.Device
1101 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -04001102 if device, err = dMgr.getDevice(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001103 logger.Errorw("device-not-found", log.Fields{"deviceId": deviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -05001104 return err
1105 }
khenaidoo43c82122018-11-22 18:38:28 -05001106 if !device.Root {
Girish Kumarf56a4682020-03-20 20:07:46 +00001107 logger.Errorw("device-not-root", log.Fields{"deviceId": deviceID})
npujar1d86a522019-11-14 17:11:16 +05301108 return status.Errorf(codes.FailedPrecondition, "%s", deviceID)
khenaidoofdbad6e2018-11-06 22:26:38 -05001109 }
1110
npujar467fe752020-01-16 20:17:45 +05301111 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, port, transactionID, packet); err != nil {
khenaidoofdbad6e2018-11-06 22:26:38 -05001112 return err
1113 }
1114 return nil
1115}
1116
Kent Hagerman2b216042020-04-03 18:28:56 -04001117func (dMgr *Manager) setParentID(ctx context.Context, device *voltha.Device, parentID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001118 logger.Debugw("setParentId", log.Fields{"deviceId": device.Id, "parentId": parentID})
npujar467fe752020-01-16 20:17:45 +05301119 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
1120 return agent.setParentID(ctx, device, parentID)
khenaidooad06fd72019-10-28 12:26:05 -04001121 }
1122 return status.Errorf(codes.NotFound, "%s", device.Id)
1123}
1124
npujar1d86a522019-11-14 17:11:16 +05301125// CreateLogicalDevice creates logical device in core
Kent Hagerman2b216042020-04-03 18:28:56 -04001126func (dMgr *Manager) CreateLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001127 logger.Info("CreateLogicalDevice")
khenaidoo59ef7be2019-06-21 12:40:28 -04001128 // Verify whether the logical device has already been created
1129 if cDevice.ParentId != "" {
Girish Kumarf56a4682020-03-20 20:07:46 +00001130 logger.Debugw("Parent device already exist.", log.Fields{"deviceId": cDevice.Id, "logicalDeviceId": cDevice.Id})
khenaidoo59ef7be2019-06-21 12:40:28 -04001131 return nil
1132 }
khenaidoob9203542018-09-17 22:56:37 -04001133 var err error
npujar467fe752020-01-16 20:17:45 +05301134 if _, err = dMgr.logicalDeviceMgr.createLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001135 logger.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
khenaidoob9203542018-09-17 22:56:37 -04001136 return err
1137 }
khenaidoob9203542018-09-17 22:56:37 -04001138 return nil
1139}
1140
npujar1d86a522019-11-14 17:11:16 +05301141// DeleteLogicalDevice deletes logical device from core
Kent Hagerman2b216042020-04-03 18:28:56 -04001142func (dMgr *Manager) DeleteLogicalDevice(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001143 logger.Info("DeleteLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -04001144 var err error
npujar467fe752020-01-16 20:17:45 +05301145 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001146 logger.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001147 return err
1148 }
1149 // Remove the logical device Id from the parent device
npujar1d86a522019-11-14 17:11:16 +05301150 logicalID := ""
npujar467fe752020-01-16 20:17:45 +05301151 dMgr.UpdateDeviceAttribute(ctx, cDevice.Id, "ParentId", logicalID)
khenaidoo92e62c52018-10-03 14:02:54 -04001152 return nil
1153}
1154
npujar1d86a522019-11-14 17:11:16 +05301155// DeleteLogicalPort removes the logical port associated with a device
Kent Hagerman2b216042020-04-03 18:28:56 -04001156func (dMgr *Manager) DeleteLogicalPort(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001157 logger.Info("deleteLogicalPort")
khenaidoo92e62c52018-10-03 14:02:54 -04001158 var err error
khenaidoo19d7b632018-10-30 10:49:50 -04001159 // Get the logical port associated with this device
npujar1d86a522019-11-14 17:11:16 +05301160 var lPortID *voltha.LogicalPortId
npujar467fe752020-01-16 20:17:45 +05301161 if lPortID, err = dMgr.logicalDeviceMgr.getLogicalPortID(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001162 logger.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -04001163 return err
1164 }
npujar467fe752020-01-16 20:17:45 +05301165 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(ctx, lPortID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001166 logger.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001167 return err
1168 }
khenaidoo92e62c52018-10-03 14:02:54 -04001169 return nil
1170}
1171
npujar1d86a522019-11-14 17:11:16 +05301172// DeleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagerman2b216042020-04-03 18:28:56 -04001173func (dMgr *Manager) DeleteLogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001174 logger.Debugw("delete-all-logical-ports", log.Fields{"device-id": cDevice.Id})
khenaidoo442e7c72020-03-10 16:13:48 -04001175 if err := dMgr.logicalDeviceMgr.deleteLogicalPorts(ctx, cDevice.Id); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001176 // 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 +00001177 logger.Warnw("deleteLogical-ports-error", log.Fields{"device-id": cDevice.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001178 }
1179 return nil
1180}
1181
Kent Hagerman2b216042020-04-03 18:28:56 -04001182func (dMgr *Manager) getParentDevice(ctx context.Context, childDevice *voltha.Device) *voltha.Device {
khenaidoo92e62c52018-10-03 14:02:54 -04001183 // Sanity check
1184 if childDevice.Root {
1185 // childDevice is the parent device
1186 return childDevice
1187 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001188 parentDevice, _ := dMgr.getDevice(ctx, childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -04001189 return parentDevice
1190}
1191
Kent Hagerman2b216042020-04-03 18:28:56 -04001192//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 -04001193//cannot manage the child devices. This will trigger the Core to disable all the child devices.
Kent Hagerman2b216042020-04-03 18:28:56 -04001194func (dMgr *Manager) ChildDevicesLost(ctx context.Context, parentDeviceID string) error {
1195 logger.Debug("ChildDevicesLost")
khenaidoo0a822f92019-05-08 15:15:57 -04001196 var err error
1197 var parentDevice *voltha.Device
Kent Hagerman45a13e42020-04-13 12:23:50 -04001198 if parentDevice, err = dMgr.getDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001199 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001200 return err
1201 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001202 return dMgr.DisableAllChildDevices(ctx, parentDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001203}
1204
Kent Hagerman2b216042020-04-03 18:28:56 -04001205//ChildDevicesDetected is invoked by an adapter when child devices are found, typically after after a
khenaidoo0a822f92019-05-08 15:15:57 -04001206// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
Kent Hagerman2b216042020-04-03 18:28:56 -04001207func (dMgr *Manager) ChildDevicesDetected(ctx context.Context, parentDeviceID string) error {
1208 logger.Debug("ChildDevicesDetected")
khenaidoo0a822f92019-05-08 15:15:57 -04001209 var err error
1210 var parentDevice *voltha.Device
1211 var childDeviceIds []string
1212
Kent Hagerman45a13e42020-04-13 12:23:50 -04001213 if parentDevice, err = dMgr.getDevice(ctx, parentDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001214 logger.Warnw("failed-getting-device", log.Fields{"deviceId": parentDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001215 return err
1216 }
1217
1218 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
1219 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1220 }
1221 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001222 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo0a822f92019-05-08 15:15:57 -04001223 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001224 allChildEnableRequestSent := true
npujar1d86a522019-11-14 17:11:16 +05301225 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301226 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
khenaidoo59ef7be2019-06-21 12:40:28 -04001227 // Run the children re-registration in its own routine
npujar1d86a522019-11-14 17:11:16 +05301228 go func() {
npujar467fe752020-01-16 20:17:45 +05301229 err = agent.enableDevice(ctx)
npujar1d86a522019-11-14 17:11:16 +05301230 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001231 logger.Errorw("unable-to-enable-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +05301232 }
1233 }()
khenaidoo59ef7be2019-06-21 12:40:28 -04001234 } else {
npujar1d86a522019-11-14 17:11:16 +05301235 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
Girish Kumarf56a4682020-03-20 20:07:46 +00001236 logger.Errorw("no-child-device-agent", log.Fields{"parentDeviceId": parentDevice.Id, "childId": childDeviceID})
khenaidoo59ef7be2019-06-21 12:40:28 -04001237 allChildEnableRequestSent = false
khenaidoo0a822f92019-05-08 15:15:57 -04001238 }
1239 }
khenaidoo59ef7be2019-06-21 12:40:28 -04001240 if !allChildEnableRequestSent {
khenaidoo0a822f92019-05-08 15:15:57 -04001241 return err
1242 }
1243 return nil
1244}
1245
khenaidoo4d4802d2018-10-04 21:59:49 -04001246/*
1247All the functions below are callback functions where they are invoked with the latest and previous data. We can
1248therefore use the data as is without trying to get the latest from the model.
1249*/
1250
khenaidoo0a822f92019-05-08 15:15:57 -04001251//DisableAllChildDevices is invoked as a callback when the parent device is disabled
Kent Hagerman2b216042020-04-03 18:28:56 -04001252func (dMgr *Manager) DisableAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001253 logger.Debug("DisableAllChildDevices")
khenaidoo92e62c52018-10-03 14:02:54 -04001254 var childDeviceIds []string
1255 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001256 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1257 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001258 }
1259 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001260 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001261 }
npujar1d86a522019-11-14 17:11:16 +05301262 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301263 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1264 if err = agent.disableDevice(ctx); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001265 // Just log the error - this error happens only if the child device was already in deleted state.
Girish Kumarf56a4682020-03-20 20:07:46 +00001266 logger.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo92e62c52018-10-03 14:02:54 -04001267 }
1268 }
1269 }
1270 return nil
1271}
1272
khenaidoo0a822f92019-05-08 15:15:57 -04001273//DeleteAllChildDevices is invoked as a callback when the parent device is deleted
Kent Hagerman2b216042020-04-03 18:28:56 -04001274func (dMgr *Manager) DeleteAllChildDevices(ctx context.Context, parentCurrDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001275 logger.Debug("DeleteAllChildDevices")
khenaidoo4d4802d2018-10-04 21:59:49 -04001276 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -04001277 var err error
khenaidoo442e7c72020-03-10 16:13:48 -04001278 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentCurrDevice); err != nil {
1279 return status.Errorf(codes.NotFound, "%s", parentCurrDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -04001280 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001281 if len(childDeviceIds) == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +00001282 logger.Debugw("no-child-device", log.Fields{"parentDeviceId": parentCurrDevice.Id})
khenaidoo4d4802d2018-10-04 21:59:49 -04001283 }
npujar1d86a522019-11-14 17:11:16 +05301284 for _, childDeviceID := range childDeviceIds {
npujar467fe752020-01-16 20:17:45 +05301285 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
1286 if err = agent.deleteDevice(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001287 logger.Warnw("failure-delete-device", log.Fields{"deviceId": childDeviceID, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -04001288 }
khenaidoo49085352020-01-13 19:15:43 -05001289 // No further action is required here. The deleteDevice will change the device state where the resulting
1290 // callback will take care of cleaning the child device agent.
khenaidoo4d4802d2018-10-04 21:59:49 -04001291 }
1292 }
khenaidoo4d4802d2018-10-04 21:59:49 -04001293 return nil
1294}
1295
Girish Gowdra408cd962020-03-11 14:31:31 -07001296//DeleteAllLogicalPorts is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001297func (dMgr *Manager) DeleteAllLogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001298 logger.Debugw("delete-all-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001299 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(ctx, parentDevice); err != nil {
khenaidooe132f522020-03-20 15:23:15 -04001300 // Just log error as logical device may already have been deleted
Girish Kumarf56a4682020-03-20 20:07:46 +00001301 logger.Warnw("delete-all-logical-ports-fail", log.Fields{"parent-device-id": parentDevice.Id, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -07001302 }
1303 return nil
1304}
1305
1306//DeleteAllDeviceFlows is invoked as a callback when the parent device's connection status moves to UNREACHABLE
Kent Hagerman2b216042020-04-03 18:28:56 -04001307func (dMgr *Manager) DeleteAllDeviceFlows(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001308 logger.Debugw("delete-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001309 if agent := dMgr.getDeviceAgent(ctx, parentDevice.Id); agent != nil {
1310 if err := agent.deleteAllFlows(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001311 logger.Errorw("error-deleting-all-device-flows", log.Fields{"parent-device-id": parentDevice.Id})
Girish Gowdra408cd962020-03-11 14:31:31 -07001312 return err
1313 }
1314 return nil
1315 }
1316 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
1317}
1318
khenaidoo4d4802d2018-10-04 21:59:49 -04001319//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 -04001320func (dMgr *Manager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001321 logger.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -04001322 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -04001323 if parentDevice != nil {
1324 for _, port := range parentDevice.Ports {
1325 for _, peer := range port.Peers {
1326 childDeviceIds = append(childDeviceIds, peer.DeviceId)
1327 }
khenaidoo92e62c52018-10-03 14:02:54 -04001328 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001329 logger.Debugw("returning-getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id, "childDeviceIds": childDeviceIds})
khenaidoo92e62c52018-10-03 14:02:54 -04001330 }
1331 return childDeviceIds, nil
1332}
1333
Kent Hagerman2b216042020-04-03 18:28:56 -04001334//GetAllChildDevices is a helper method to get all the child device IDs from the device passed as parameter
1335func (dMgr *Manager) GetAllChildDevices(ctx context.Context, parentDeviceID string) (*voltha.Devices, error) {
1336 logger.Debugw("GetAllChildDevices", log.Fields{"parentDeviceId": parentDeviceID})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001337 if parentDevice, err := dMgr.getDevice(ctx, parentDeviceID); err == nil {
khenaidoo297cd252019-02-07 22:10:23 -05001338 childDevices := make([]*voltha.Device, 0)
1339 if childDeviceIds, er := dMgr.getAllChildDeviceIds(parentDevice); er == nil {
npujar1d86a522019-11-14 17:11:16 +05301340 for _, deviceID := range childDeviceIds {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001341 if d, e := dMgr.getDevice(ctx, deviceID); e == nil && d != nil {
khenaidoo297cd252019-02-07 22:10:23 -05001342 childDevices = append(childDevices, d)
1343 }
1344 }
1345 }
1346 return &voltha.Devices{Items: childDevices}, nil
1347 }
npujar1d86a522019-11-14 17:11:16 +05301348 return nil, status.Errorf(codes.NotFound, "%s", parentDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -05001349}
1350
npujar1d86a522019-11-14 17:11:16 +05301351// SetupUNILogicalPorts creates UNI ports on the logical device that represents a child UNI interface
Kent Hagerman2b216042020-04-03 18:28:56 -04001352func (dMgr *Manager) SetupUNILogicalPorts(ctx context.Context, cDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001353 logger.Info("addUNILogicalPort")
npujar467fe752020-01-16 20:17:45 +05301354 if err := dMgr.logicalDeviceMgr.setupUNILogicalPorts(ctx, cDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001355 logger.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
khenaidoob9203542018-09-17 22:56:37 -04001356 return err
1357 }
1358 return nil
1359}
1360
Kent Hagerman45a13e42020-04-13 12:23:50 -04001361// convenience to avoid redefining
1362var operationFailureResp = &common.OperationResp{Code: voltha.OperationResp_OPERATION_FAILURE}
1363
1364// DownloadImage execute an image download request
1365func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1366 logger.Debugw("DownloadImage", log.Fields{"device-id": img.Id, "imageName": img.Name})
1367 agent := dMgr.getDeviceAgent(ctx, img.Id)
1368 if agent == nil {
1369 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001370 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001371 resp, err := agent.downloadImage(ctx, img)
1372 if err != nil {
1373 return operationFailureResp, err
1374 }
1375 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001376}
1377
Kent Hagerman45a13e42020-04-13 12:23:50 -04001378// CancelImageDownload cancels image download request
1379func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1380 logger.Debugw("CancelImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
1381 agent := dMgr.getDeviceAgent(ctx, img.Id)
1382 if agent == nil {
1383 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001384 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001385 resp, err := agent.cancelImageDownload(ctx, img)
1386 if err != nil {
1387 return operationFailureResp, err
1388 }
1389 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001390}
1391
Kent Hagerman45a13e42020-04-13 12:23:50 -04001392// ActivateImageUpdate activates image update request
1393func (dMgr *Manager) ActivateImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1394 logger.Debugw("ActivateImageUpdate", log.Fields{"device-id": img.Id, "imageName": img.Name})
1395 agent := dMgr.getDeviceAgent(ctx, img.Id)
1396 if agent == nil {
1397 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001398 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001399 resp, err := agent.activateImage(ctx, img)
1400 if err != nil {
1401 return operationFailureResp, err
1402 }
1403 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001404}
1405
Kent Hagerman45a13e42020-04-13 12:23:50 -04001406// RevertImageUpdate reverts image update
1407func (dMgr *Manager) RevertImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
1408 logger.Debugw("RevertImageUpdate", log.Fields{"device-id": img.Id, "imageName": img.Name})
1409 agent := dMgr.getDeviceAgent(ctx, img.Id)
1410 if agent == nil {
1411 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001412 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001413 resp, err := agent.revertImage(ctx, img)
1414 if err != nil {
1415 return operationFailureResp, err
1416 }
1417 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001418}
1419
Kent Hagerman45a13e42020-04-13 12:23:50 -04001420// convenience to avoid redefining
1421var imageDownloadFailureResp = &voltha.ImageDownload{DownloadState: voltha.ImageDownload_DOWNLOAD_UNKNOWN}
1422
1423// GetImageDownloadStatus returns status of image download
1424func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
1425 logger.Debugw("GetImageDownloadStatus", log.Fields{"device-id": img.Id, "imageName": img.Name})
1426 agent := dMgr.getDeviceAgent(ctx, img.Id)
1427 if agent == nil {
1428 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001429 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001430 resp, err := agent.getImageDownloadStatus(ctx, img)
1431 if err != nil {
1432 return imageDownloadFailureResp, err
1433 }
1434 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001435}
1436
Kent Hagerman2b216042020-04-03 18:28:56 -04001437func (dMgr *Manager) UpdateImageDownload(ctx context.Context, deviceID string, img *voltha.ImageDownload) error {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001438 logger.Debugw("UpdateImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
npujar467fe752020-01-16 20:17:45 +05301439 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1440 if err := agent.updateImageDownload(ctx, img); err != nil {
Kent Hagerman2b216042020-04-03 18:28:56 -04001441 logger.Debugw("UpdateImageDownload-failed", log.Fields{"err": err, "imageName": img.Name})
khenaidoof5a5bfa2019-01-23 22:20:29 -05001442 return err
1443 }
1444 } else {
1445 return status.Errorf(codes.NotFound, "%s", img.Id)
1446 }
1447 return nil
1448}
1449
Kent Hagerman45a13e42020-04-13 12:23:50 -04001450// GetImageDownload returns image download
Kent Hagerman2b216042020-04-03 18:28:56 -04001451func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001452 logger.Debugw("GetImageDownload", log.Fields{"device-id": img.Id, "imageName": img.Name})
1453 agent := dMgr.getDeviceAgent(ctx, img.Id)
1454 if agent == nil {
1455 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001456 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001457 resp, err := agent.getImageDownload(ctx, img)
1458 if err != nil {
1459 return imageDownloadFailureResp, err
1460 }
1461 return resp, nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001462}
1463
Kent Hagerman45a13e42020-04-13 12:23:50 -04001464// ListImageDownloads returns image downloads
1465func (dMgr *Manager) ListImageDownloads(ctx context.Context, id *voltha.ID) (*voltha.ImageDownloads, error) {
1466 logger.Debugw("ListImageDownloads", log.Fields{"device-id": id.Id})
1467 agent := dMgr.getDeviceAgent(ctx, id.Id)
1468 if agent == nil {
1469 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoof5a5bfa2019-01-23 22:20:29 -05001470 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001471 resp, err := agent.listImageDownloads(ctx, id.Id)
1472 if err != nil {
1473 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, err
1474 }
1475 return resp, nil
1476}
1477
1478// GetImages returns all images for a specific device entry
1479func (dMgr *Manager) GetImages(ctx context.Context, id *voltha.ID) (*voltha.Images, error) {
1480 logger.Debugw("GetImages", log.Fields{"device-id": id.Id})
1481 device, err := dMgr.getDevice(ctx, id.Id)
1482 if err != nil {
1483 return nil, err
1484 }
1485 return device.GetImages(), nil
khenaidoof5a5bfa2019-01-23 22:20:29 -05001486}
1487
Kent Hagerman2b216042020-04-03 18:28:56 -04001488func (dMgr *Manager) NotifyInvalidTransition(_ context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001489 logger.Errorw("NotifyInvalidTransition", log.Fields{
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001490 "device": device.Id,
1491 "curr-admin-state": device.AdminState,
1492 "curr-oper-state": device.OperStatus,
1493 "curr-conn-state": device.ConnectStatus,
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001494 })
khenaidoo0a822f92019-05-08 15:15:57 -04001495 //TODO: notify over kafka?
1496 return nil
1497}
1498
khenaidoob9203542018-09-17 22:56:37 -04001499func funcName(f interface{}) string {
1500 p := reflect.ValueOf(f).Pointer()
1501 rf := runtime.FuncForPC(p)
1502 return rf.Name()
1503}
1504
npujar1d86a522019-11-14 17:11:16 +05301505// UpdateDeviceAttribute updates value of particular device attribute
Kent Hagerman2b216042020-04-03 18:28:56 -04001506func (dMgr *Manager) UpdateDeviceAttribute(ctx context.Context, deviceID string, attribute string, value interface{}) {
npujar1d86a522019-11-14 17:11:16 +05301507 if agent, ok := dMgr.deviceAgents.Load(deviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -04001508 agent.(*Agent).updateDeviceAttribute(ctx, attribute, value)
khenaidoob9203542018-09-17 22:56:37 -04001509 }
1510}
1511
npujar1d86a522019-11-14 17:11:16 +05301512// GetParentDeviceID returns parent device id, either from memory or from the dB, if present
Kent Hagerman2b216042020-04-03 18:28:56 -04001513func (dMgr *Manager) GetParentDeviceID(ctx context.Context, deviceID string) string {
Kent Hagerman45a13e42020-04-13 12:23:50 -04001514 if device, _ := dMgr.getDevice(ctx, deviceID); device != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001515 logger.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoo4c9e5592019-09-09 16:20:41 -04001516 return device.ParentId
khenaidoob9203542018-09-17 22:56:37 -04001517 }
khenaidoo4c9e5592019-09-09 16:20:41 -04001518 return ""
khenaidoob9203542018-09-17 22:56:37 -04001519}
serkant.uluderya334479d2019-04-10 08:26:15 -07001520
Kent Hagerman45a13e42020-04-13 12:23:50 -04001521func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulateReq *voltha.SimulateAlarmRequest) (*common.OperationResp, error) {
1522 logger.Debugw("SimulateAlarm", log.Fields{"id": simulateReq.Id, "Indicator": simulateReq.Indicator, "IntfId": simulateReq.IntfId,
1523 "PortTypeName": simulateReq.PortTypeName, "OnuDeviceId": simulateReq.OnuDeviceId, "InverseBitErrorRate": simulateReq.InverseBitErrorRate,
1524 "Drift": simulateReq.Drift, "NewEqd": simulateReq.NewEqd, "OnuSerialNumber": simulateReq.OnuSerialNumber, "Operation": simulateReq.Operation})
1525 agent := dMgr.getDeviceAgent(ctx, simulateReq.Id)
1526 if agent == nil {
1527 return nil, status.Errorf(codes.NotFound, "%s", simulateReq.Id)
serkant.uluderya334479d2019-04-10 08:26:15 -07001528 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001529 if err := agent.simulateAlarm(ctx, simulateReq); err != nil {
1530 return nil, err
1531 }
1532 return &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}, nil
serkant.uluderya334479d2019-04-10 08:26:15 -07001533}
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001534
Kent Hagerman2b216042020-04-03 18:28:56 -04001535func (dMgr *Manager) UpdateDeviceReason(ctx context.Context, deviceID string, reason string) error {
1536 logger.Debugw("UpdateDeviceReason", log.Fields{"deviceid": deviceID, "reason": reason})
npujar467fe752020-01-16 20:17:45 +05301537 if agent := dMgr.getDeviceAgent(ctx, deviceID); agent != nil {
1538 return agent.updateDeviceReason(ctx, reason)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001539 }
npujar1d86a522019-11-14 17:11:16 +05301540 return status.Errorf(codes.NotFound, "%s", deviceID)
Mahir Gunyelfdee9212019-10-16 16:52:21 -07001541}
kesavandbc2d1622020-01-21 00:42:01 -05001542
Kent Hagerman45a13e42020-04-13 12:23:50 -04001543func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Kent Hagerman2b216042020-04-03 18:28:56 -04001544 logger.Debugw("EnablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001545 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1546 if agent == nil {
1547 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001548 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001549 return &empty.Empty{}, agent.enablePort(ctx, port)
kesavandbc2d1622020-01-21 00:42:01 -05001550}
1551
Kent Hagerman45a13e42020-04-13 12:23:50 -04001552func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
Kent Hagerman2b216042020-04-03 18:28:56 -04001553 logger.Debugw("DisablePort", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001554 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
1555 if agent == nil {
1556 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
kesavandbc2d1622020-01-21 00:42:01 -05001557 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001558 return &empty.Empty{}, agent.disablePort(ctx, port)
kesavandbc2d1622020-01-21 00:42:01 -05001559}
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001560
Kent Hagerman2b216042020-04-03 18:28:56 -04001561// ChildDeviceLost calls parent adapter to delete child device and all its references
1562func (dMgr *Manager) ChildDeviceLost(ctx context.Context, curr *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001563 logger.Debugw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId})
khenaidoo442e7c72020-03-10 16:13:48 -04001564 if parentAgent := dMgr.getDeviceAgent(ctx, curr.ParentId); parentAgent != nil {
khenaidooe132f522020-03-20 15:23:15 -04001565 if err := parentAgent.ChildDeviceLost(ctx, curr); err != nil {
1566 // Just log the message and let the remaining pipeline proceed.
Girish Kumarf56a4682020-03-20 20:07:46 +00001567 logger.Warnw("childDeviceLost", log.Fields{"child-device-id": curr.Id, "parent-device-id": curr.ParentId, "error": err})
khenaidooe132f522020-03-20 15:23:15 -04001568 }
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001569 }
khenaidooe132f522020-03-20 15:23:15 -04001570 // Do not return an error as parent device may also have been deleted. Let the remaining pipeline proceed.
1571 return nil
Chaitrashree G S543df3e2020-02-24 22:36:54 -05001572}
onkarkundargi87285252020-01-27 11:34:52 +05301573
Kent Hagerman45a13e42020-04-13 12:23:50 -04001574func (dMgr *Manager) StartOmciTestAction(ctx context.Context, request *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
1575 logger.Debugw("StartOmciTestAction", log.Fields{"device-id": request.Id, "uuid": request.Uuid})
1576 agent := dMgr.getDeviceAgent(ctx, request.Id)
1577 if agent == nil {
1578 return nil, status.Errorf(codes.NotFound, "%s", request.Id)
onkarkundargi87285252020-01-27 11:34:52 +05301579 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001580 return agent.startOmciTest(ctx, request)
onkarkundargi87285252020-01-27 11:34:52 +05301581}
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001582
1583func (dMgr *Manager) GetExtValue(ctx context.Context, value *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
1584 log.Debugw("getExtValue", log.Fields{"onu-id": value.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -04001585 cDevice, err := dMgr.getDevice(ctx, value.Id)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001586 if err != nil {
1587 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1588 }
Kent Hagerman45a13e42020-04-13 12:23:50 -04001589 pDevice, err := dMgr.getDevice(ctx, cDevice.ParentId)
Dinesh Belwalkarc1129f12020-02-27 10:41:33 -08001590 if err != nil {
1591 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
1592 }
1593 if agent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); agent != nil {
1594 resp, err := agent.getExtValue(ctx, pDevice, cDevice, value)
1595 if err != nil {
1596 return nil, err
1597 }
1598 log.Debugw("getExtValue-result", log.Fields{"result": resp})
1599 return resp, nil
1600 }
1601 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
1602
1603}