blob: b978823f5c15c048907baab1fbc529629ef42530 [file] [log] [blame]
khenaidood948f772021-08-11 17:49:24 -04001/*
Joey Armstrong811e9542022-12-25 21:45:27 -05002 * Copyright 2021-2023 Open Networking Foundation (ONF) and the ONF Contributors
khenaidood948f772021-08-11 17:49:24 -04003
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package device
17
18import (
19 "context"
20 "errors"
21
22 "github.com/golang/protobuf/ptypes/empty"
23 "github.com/opencord/voltha-go/rw_core/utils"
24 "github.com/opencord/voltha-lib-go/v7/pkg/log"
25 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoo9beaaf12021-10-19 17:32:01 -040026 "github.com/opencord/voltha-protos/v5/go/extension"
27 "github.com/opencord/voltha-protos/v5/go/omci"
khenaidood948f772021-08-11 17:49:24 -040028 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
yasin sapli8fe47e42023-06-09 21:19:00 +000029 "github.com/opencord/voltha-protos/v5/go/voip_system_profile"
30 "github.com/opencord/voltha-protos/v5/go/voip_user_profile"
khenaidood948f772021-08-11 17:49:24 -040031 "github.com/opencord/voltha-protos/v5/go/voltha"
32 "google.golang.org/grpc/codes"
33 "google.golang.org/grpc/status"
34)
35
36// CreateDevice creates a new parent device in the data model
37func (dMgr *Manager) CreateDevice(ctx context.Context, device *voltha.Device) (*voltha.Device, error) {
38 if device.MacAddress == "" && device.GetHostAndPort() == "" {
39 logger.Errorf(ctx, "no-device-info-present")
40 return &voltha.Device{}, errors.New("no-device-info-present; MAC or HOSTIP&PORT")
41 }
42 ctx = utils.WithRPCMetadataContext(ctx, "CreateDevice")
43 logger.Debugw(ctx, "create-device", log.Fields{"device": *device})
44
45 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
46 if err != nil {
47 logger.Errorf(ctx, "failed-to-fetch-parent-device-info")
48 return nil, err
49 }
50 if deviceExist {
51 logger.Errorf(ctx, "device-is-pre-provisioned-already-with-same-ip-port-or-mac-address")
52 return nil, errors.New("device is already pre-provisioned")
53 }
54 logger.Debugw(ctx, "create-device", log.Fields{"device": device})
55
56 // Ensure this device is set as root
57 device.Root = true
58 // Create and start a device agent for that device
Himani Chawla4b4bd252021-11-08 15:59:40 +053059 agent := newAgent(device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.internalTimeout, dMgr.rpcTimeout, dMgr.flowTimeout)
khenaidood948f772021-08-11 17:49:24 -040060 device, err = agent.start(ctx, false, device)
61 if err != nil {
62 logger.Errorw(ctx, "fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
63 return nil, err
64 }
65 dMgr.addDeviceAgentToMap(agent)
66 return device, nil
67}
68
69// EnableDevice activates a device by invoking the adopt_device API on the appropriate adapter
70func (dMgr *Manager) EnableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
71 ctx = utils.WithRPCMetadataContext(ctx, "EnableDevice")
72 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
73
74 logger.Debugw(ctx, "enable-device", log.Fields{"device-id": id.Id})
75 agent := dMgr.getDeviceAgent(ctx, id.Id)
76 if agent == nil {
77 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
78 }
79 return &empty.Empty{}, agent.enableDevice(ctx)
80}
81
82// DisableDevice disables a device along with any child device it may have
83func (dMgr *Manager) DisableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
84 ctx = utils.WithRPCMetadataContext(ctx, "DisableDevice")
85 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
86
87 logger.Debugw(ctx, "disable-device", log.Fields{"device-id": id.Id})
88 agent := dMgr.getDeviceAgent(ctx, id.Id)
89 if agent == nil {
90 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
91 }
92 return &empty.Empty{}, agent.disableDevice(ctx)
93}
94
95//RebootDevice invoked the reboot API to the corresponding adapter
96func (dMgr *Manager) RebootDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
97 ctx = utils.WithRPCMetadataContext(ctx, "RebootDevice")
98 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
99
100 logger.Debugw(ctx, "reboot-device", log.Fields{"device-id": id.Id})
101 agent := dMgr.getDeviceAgent(ctx, id.Id)
102 if agent == nil {
103 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
104 }
105 return &empty.Empty{}, agent.rebootDevice(ctx)
106}
107
108// DeleteDevice removes a device from the data model
109func (dMgr *Manager) DeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
110 ctx = utils.WithRPCMetadataContext(ctx, "DeleteDevice")
111 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
112
113 logger.Debugw(ctx, "delete-device", log.Fields{"device-id": id.Id})
114 agent := dMgr.getDeviceAgent(ctx, id.Id)
115 if agent == nil {
116 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
117 }
118 return &empty.Empty{}, agent.deleteDevice(ctx)
119}
120
121// ForceDeleteDevice removes a device from the data model forcefully without successfully waiting for the adapters.
122func (dMgr *Manager) ForceDeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
123 ctx = utils.WithRPCMetadataContext(ctx, "ForceDeleteDevice")
124 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
125
126 logger.Debugw(ctx, "force-delete-device", log.Fields{"device-id": id.Id})
127 agent := dMgr.getDeviceAgent(ctx, id.Id)
128 if agent == nil {
129 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
130 }
131 return &empty.Empty{}, agent.deleteDeviceForce(ctx)
132}
133
134// ListDevices retrieves the latest devices from the data model
135func (dMgr *Manager) ListDevices(ctx context.Context, _ *empty.Empty) (*voltha.Devices, error) {
136 ctx = utils.WithRPCMetadataContext(ctx, "ListDevices")
137
138 logger.Debug(ctx, "list-devices")
139 result := &voltha.Devices{}
140
141 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
142 result.Items = append(result.Items, value.(*Agent).device)
143 return true
144 })
145
146 logger.Debugw(ctx, "list-devices-end", log.Fields{"len": len(result.Items)})
147 return result, nil
148}
149
150// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
151func (dMgr *Manager) ListDeviceIds(ctx context.Context, _ *empty.Empty) (*voltha.IDs, error) {
152 ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceIds")
153
154 logger.Debug(ctx, "list-device-ids")
155 // Report only device IDs that are in the device agent map
156 return dMgr.listDeviceIdsFromMap(), nil
157}
158
159// ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
160// trigger loading the devices along with their children and parent in memory
161func (dMgr *Manager) ReconcileDevices(ctx context.Context, ids *voltha.IDs) (*empty.Empty, error) {
162 ctx = utils.WithRPCMetadataContext(ctx, "ReconcileDevices")
163
164 numDevices := 0
165 if ids != nil {
166 numDevices = len(ids.Items)
167 }
168
169 logger.Debugw(ctx, "reconcile-devices", log.Fields{"num-devices": numDevices})
170 if ids != nil && len(ids.Items) != 0 {
171 toReconcile := len(ids.Items)
172 reconciled := 0
173 var err error
174 for _, id := range ids.Items {
175 if err = dMgr.load(ctx, id.Id); err != nil {
176 logger.Warnw(ctx, "failure-reconciling-device", log.Fields{"device-id": id.Id, "error": err})
177 } else {
178 reconciled++
179 }
180 }
181 if toReconcile != reconciled {
182 return nil, status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
183 }
184 } else {
185 return nil, status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
186 }
187 return &empty.Empty{}, nil
188}
189
190// GetDevice exists primarily to implement the gRPC interface.
191// Internal functions should call getDeviceReadOnly instead.
192func (dMgr *Manager) GetDevice(ctx context.Context, id *voltha.ID) (*voltha.Device, error) {
193 ctx = utils.WithRPCMetadataContext(ctx, "GetDevice")
194 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
195
196 return dMgr.getDeviceReadOnly(ctx, id.Id)
197}
198
199// convenience to avoid redefining
200var operationFailureResp = &common.OperationResp{Code: voltha.OperationResp_OPERATION_FAILURE}
201
202// DownloadImage execute an image download request
203func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
204 ctx = utils.WithRPCMetadataContext(ctx, "DownloadImage")
205 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
206
207 logger.Debugw(ctx, "download-image", log.Fields{"device-id": img.Id, "image-name": img.Name})
208 agent := dMgr.getDeviceAgent(ctx, img.Id)
209 if agent == nil {
210 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
211 }
212 resp, err := agent.downloadImage(ctx, img)
213 if err != nil {
214 return operationFailureResp, err
215 }
216 return resp, nil
217}
218
219// CancelImageDownload cancels image download request
220func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
221 ctx = utils.WithRPCMetadataContext(ctx, "CancelImageDownload")
222 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
223
224 logger.Debugw(ctx, "cancel-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
225 agent := dMgr.getDeviceAgent(ctx, img.Id)
226 if agent == nil {
227 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
228 }
229 resp, err := agent.cancelImageDownload(ctx, img)
230 if err != nil {
231 return operationFailureResp, err
232 }
233 return resp, nil
234}
235
236// ActivateImageUpdate activates image update request
237func (dMgr *Manager) ActivateImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
238 ctx = utils.WithRPCMetadataContext(ctx, "ActivateImageUpdate")
239 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
240
241 logger.Debugw(ctx, "activate-image-update", log.Fields{"device-id": img.Id, "image-name": img.Name})
242 agent := dMgr.getDeviceAgent(ctx, img.Id)
243 if agent == nil {
244 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
245 }
246 resp, err := agent.activateImage(ctx, img)
247 if err != nil {
248 return operationFailureResp, err
249 }
250 return resp, nil
251}
252
253// RevertImageUpdate reverts image update
254func (dMgr *Manager) RevertImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
255 ctx = utils.WithRPCMetadataContext(ctx, "RevertImageUpdate")
256 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
257
258 logger.Debugw(ctx, "rever-image-update", log.Fields{"device-id": img.Id, "image-name": img.Name})
259 agent := dMgr.getDeviceAgent(ctx, img.Id)
260 if agent == nil {
261 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
262 }
263 resp, err := agent.revertImage(ctx, img)
264 if err != nil {
265 return operationFailureResp, err
266 }
267 return resp, nil
268}
269
270func (dMgr *Manager) DownloadImageToDevice(ctx context.Context, request *voltha.DeviceImageDownloadRequest) (*voltha.DeviceImageResponse, error) {
271 if err := dMgr.validateImageDownloadRequest(request); err != nil {
272 return nil, err
273 }
274
275 ctx = utils.WithRPCMetadataContext(ctx, "DownloadImageToDevice")
276 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
277
278 for index, deviceID := range request.DeviceId {
279 // Create download request per device
280 downloadReq := &voltha.DeviceImageDownloadRequest{
281 Image: request.Image,
282 ActivateOnSuccess: request.ActivateOnSuccess,
283 CommitOnSuccess: request.CommitOnSuccess,
284 }
285
286 //slice-out only single deviceID from the request
287 downloadReq.DeviceId = request.DeviceId[index : index+1]
288
289 go func(deviceID string, req *voltha.DeviceImageDownloadRequest, ch chan []*voltha.DeviceImageState) {
290 agent := dMgr.getDeviceAgent(ctx, deviceID)
291 if agent == nil {
ssiddiqui9e120e92021-10-11 12:33:05 +0530292 logger.Errorw(ctx, "Device-agent-not-found", log.Fields{"device-id": deviceID})
293 ch <- []*voltha.DeviceImageState{{
294 DeviceId: deviceID,
295 ImageState: &voltha.ImageState{
296 Version: req.GetImage().GetVersion(),
297 DownloadState: voltha.ImageState_DOWNLOAD_FAILED,
298 Reason: voltha.ImageState_UNKNOWN_ERROR,
299 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
300 },
301 }}
khenaidood948f772021-08-11 17:49:24 -0400302 return
303 }
304
305 resp, err := agent.downloadImageToDevice(ctx, req)
306 if err != nil {
307 logger.Errorw(ctx, "download-image-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiqui9e120e92021-10-11 12:33:05 +0530308 ch <- []*voltha.DeviceImageState{{
309 DeviceId: deviceID,
310 ImageState: &voltha.ImageState{
311 Version: req.GetImage().GetVersion(),
312 DownloadState: voltha.ImageState_DOWNLOAD_FAILED,
313 Reason: voltha.ImageState_UNKNOWN_ERROR,
314 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
315 },
316 }}
khenaidood948f772021-08-11 17:49:24 -0400317 return
318 }
319
320 err = dMgr.validateDeviceImageResponse(resp)
321 if err != nil {
322 logger.Errorw(ctx, "download-image-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiqui9e120e92021-10-11 12:33:05 +0530323 ch <- []*voltha.DeviceImageState{{
324 DeviceId: deviceID,
325 ImageState: &voltha.ImageState{
326 Version: req.GetImage().GetVersion(),
327 DownloadState: voltha.ImageState_DOWNLOAD_FAILED,
328 Reason: voltha.ImageState_UNKNOWN_ERROR,
329 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
330 },
331 }}
khenaidood948f772021-08-11 17:49:24 -0400332 return
333 }
334 ch <- resp.GetDeviceImageStates()
335 }(deviceID.GetId(), downloadReq, respCh)
336
337 }
338
339 return dMgr.waitForAllResponses(ctx, "download-image-to-device", respCh, len(request.GetDeviceId()))
340}
341
342func (dMgr *Manager) GetImageStatus(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
343 if err := dMgr.validateImageRequest(request); err != nil {
344 return nil, err
345 }
346
347 ctx = utils.WithRPCMetadataContext(ctx, "GetImageStatus")
348
349 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
Elia Battiston58d1c062022-02-08 11:54:27 +0100350
351 if request.DeviceId == nil {
352 //Reply for every ONU
353 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
354 device := value.(*Agent).device
355 if !device.Root {
356 request.DeviceId = append(request.DeviceId, &common.ID{Id: value.(*Agent).device.Id})
357 }
358 return true
359 })
360 }
361
khenaidood948f772021-08-11 17:49:24 -0400362 for index, deviceID := range request.DeviceId {
363 // Create status request per device
364 imageStatusReq := &voltha.DeviceImageRequest{
365 Version: request.Version,
366 CommitOnSuccess: request.CommitOnSuccess,
367 }
368
369 //slice-out only single deviceID from the request
370 imageStatusReq.DeviceId = request.DeviceId[index : index+1]
371
372 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
373 agent := dMgr.getDeviceAgent(ctx, deviceID)
374 if agent == nil {
ssiddiqui9e120e92021-10-11 12:33:05 +0530375 logger.Errorw(ctx, "Device-agent-not-found", log.Fields{"device-id": deviceID})
376 ch <- []*voltha.DeviceImageState{{
377 DeviceId: deviceID,
378 ImageState: &voltha.ImageState{
379 Version: request.GetVersion(),
380 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
381 Reason: voltha.ImageState_UNKNOWN_ERROR,
382 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
383 },
384 }}
khenaidood948f772021-08-11 17:49:24 -0400385 return
386 }
387
388 resp, err := agent.getImageStatus(ctx, req)
389 if err != nil {
390 logger.Errorw(ctx, "get-image-status-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiqui9e120e92021-10-11 12:33:05 +0530391 ch <- []*voltha.DeviceImageState{{
392 DeviceId: deviceID,
393 ImageState: &voltha.ImageState{
394 Version: request.GetVersion(),
395 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
396 Reason: voltha.ImageState_UNKNOWN_ERROR,
397 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
398 },
399 }}
khenaidood948f772021-08-11 17:49:24 -0400400 return
401 }
402
403 err = dMgr.validateDeviceImageResponse(resp)
404 if err != nil {
405 logger.Errorw(ctx, "get-image-status-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiqui9e120e92021-10-11 12:33:05 +0530406 ch <- []*voltha.DeviceImageState{{
407 DeviceId: deviceID,
408 ImageState: &voltha.ImageState{
409 Version: request.GetVersion(),
410 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
411 Reason: voltha.ImageState_UNKNOWN_ERROR,
412 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
413 },
414 }}
khenaidood948f772021-08-11 17:49:24 -0400415 return
416 }
417 ch <- resp.GetDeviceImageStates()
418 }(deviceID.GetId(), imageStatusReq, respCh)
419
420 }
421
422 return dMgr.waitForAllResponses(ctx, "get-image-status", respCh, len(request.GetDeviceId()))
423}
424
425func (dMgr *Manager) AbortImageUpgradeToDevice(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
426 if err := dMgr.validateImageRequest(request); err != nil {
427 return nil, err
428 }
429
430 ctx = utils.WithRPCMetadataContext(ctx, "AbortImageUpgradeToDevice")
431 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
432
433 for index, deviceID := range request.DeviceId {
434 // Create abort request per device
435 abortImageReq := &voltha.DeviceImageRequest{
436 Version: request.Version,
437 CommitOnSuccess: request.CommitOnSuccess,
438 }
439
440 //slice-out only single deviceID from the request
441 abortImageReq.DeviceId = request.DeviceId[index : index+1]
442
443 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
444 agent := dMgr.getDeviceAgent(ctx, deviceID)
445 if agent == nil {
ssiddiqui9e120e92021-10-11 12:33:05 +0530446 logger.Errorw(ctx, "Device-agent-not-found", log.Fields{"device-id": deviceID})
447 ch <- []*voltha.DeviceImageState{{
448 DeviceId: deviceID,
449 ImageState: &voltha.ImageState{
450 Version: request.GetVersion(),
451 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
452 Reason: voltha.ImageState_UNKNOWN_ERROR,
453 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
454 },
455 }}
khenaidood948f772021-08-11 17:49:24 -0400456 return
457 }
458
459 resp, err := agent.abortImageUpgradeToDevice(ctx, req)
460 if err != nil {
461 logger.Errorw(ctx, "abort-image-upgrade-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiqui9e120e92021-10-11 12:33:05 +0530462 ch <- []*voltha.DeviceImageState{{
463 DeviceId: deviceID,
464 ImageState: &voltha.ImageState{
465 Version: request.GetVersion(),
466 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
467 Reason: voltha.ImageState_UNKNOWN_ERROR,
468 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
469 },
470 }}
khenaidood948f772021-08-11 17:49:24 -0400471 return
472 }
473
474 err = dMgr.validateDeviceImageResponse(resp)
475 if err != nil {
476 logger.Errorw(ctx, "abort-image-upgrade-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiqui9e120e92021-10-11 12:33:05 +0530477 ch <- []*voltha.DeviceImageState{{
478 DeviceId: deviceID,
479 ImageState: &voltha.ImageState{
480 Version: request.GetVersion(),
481 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
482 Reason: voltha.ImageState_UNKNOWN_ERROR,
483 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
484 },
485 }}
khenaidood948f772021-08-11 17:49:24 -0400486 return
487 }
488 ch <- resp.GetDeviceImageStates()
489 }(deviceID.GetId(), abortImageReq, respCh)
490
491 }
492
493 return dMgr.waitForAllResponses(ctx, "abort-image-upgrade-to-device", respCh, len(request.GetDeviceId()))
494}
495
496func (dMgr *Manager) GetOnuImages(ctx context.Context, id *common.ID) (*voltha.OnuImages, error) {
497 if id == nil || id.Id == "" {
498 return nil, status.Errorf(codes.InvalidArgument, "empty device id")
499 }
500
501 ctx = utils.WithRPCMetadataContext(ctx, "GetOnuImages")
502 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
503 agent := dMgr.getDeviceAgent(ctx, id.Id)
504 if agent == nil {
505 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
506 }
507
508 resp, err := agent.getOnuImages(ctx, id)
509 if err != nil {
510 return nil, err
511 }
512
513 logger.Debugw(ctx, "get-onu-images-result", log.Fields{"onu-image": resp.Items})
514
515 return resp, nil
516}
517
518func (dMgr *Manager) ActivateImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
519 if err := dMgr.validateImageRequest(request); err != nil {
520 return nil, err
521 }
522
523 ctx = utils.WithRPCMetadataContext(ctx, "ActivateImage")
524 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
525
526 for index, deviceID := range request.DeviceId {
527 // Create activate request per device
528 activateImageReq := &voltha.DeviceImageRequest{
529 Version: request.Version,
530 CommitOnSuccess: request.CommitOnSuccess,
531 }
532
533 //slice-out only single deviceID from the request
534 activateImageReq.DeviceId = request.DeviceId[index : index+1]
535
536 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
537 agent := dMgr.getDeviceAgent(ctx, deviceID)
538 if agent == nil {
ssiddiqui9e120e92021-10-11 12:33:05 +0530539 logger.Errorw(ctx, "Device-agent-not-found", log.Fields{"device-id": deviceID})
540 ch <- []*voltha.DeviceImageState{{
541 DeviceId: deviceID,
542 ImageState: &voltha.ImageState{
543 Version: request.GetVersion(),
544 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
545 Reason: voltha.ImageState_UNKNOWN_ERROR,
546 ImageState: voltha.ImageState_IMAGE_ACTIVATION_ABORTED,
547 },
548 }}
khenaidood948f772021-08-11 17:49:24 -0400549 return
550 }
551
552 resp, err := agent.activateImageOnDevice(ctx, req)
553 if err != nil {
554 logger.Errorw(ctx, "activate-image-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiqui9e120e92021-10-11 12:33:05 +0530555 ch <- []*voltha.DeviceImageState{{
556 DeviceId: deviceID,
557 ImageState: &voltha.ImageState{
558 Version: request.GetVersion(),
559 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
560 Reason: voltha.ImageState_UNKNOWN_ERROR,
561 ImageState: voltha.ImageState_IMAGE_ACTIVATION_ABORTED,
562 },
563 }}
khenaidood948f772021-08-11 17:49:24 -0400564 return
565 }
566
567 err = dMgr.validateDeviceImageResponse(resp)
568 if err != nil {
569 logger.Errorw(ctx, "activate-image-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiqui9e120e92021-10-11 12:33:05 +0530570 ch <- []*voltha.DeviceImageState{{
571 DeviceId: deviceID,
572 ImageState: &voltha.ImageState{
573 Version: request.GetVersion(),
574 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
575 Reason: voltha.ImageState_UNKNOWN_ERROR,
576 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
577 },
578 }}
khenaidood948f772021-08-11 17:49:24 -0400579 return
580 }
581
582 ch <- resp.GetDeviceImageStates()
583 }(deviceID.GetId(), activateImageReq, respCh)
584
585 }
586
587 return dMgr.waitForAllResponses(ctx, "activate-image", respCh, len(request.GetDeviceId()))
588}
589
590func (dMgr *Manager) CommitImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
591 if err := dMgr.validateImageRequest(request); err != nil {
592 return nil, err
593 }
594
595 ctx = utils.WithRPCMetadataContext(ctx, "CommitImage")
596 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
597
598 for index, deviceID := range request.DeviceId {
599 // Create commit request per device
600 commitImageReq := &voltha.DeviceImageRequest{
601 Version: request.Version,
602 CommitOnSuccess: request.CommitOnSuccess,
603 }
604 //slice-out only single deviceID from the request
605 commitImageReq.DeviceId = request.DeviceId[index : index+1]
606
607 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
608 agent := dMgr.getDeviceAgent(ctx, deviceID)
609 if agent == nil {
ssiddiqui9e120e92021-10-11 12:33:05 +0530610 logger.Errorw(ctx, "Device-agent-not-found", log.Fields{"device-id": deviceID})
611 ch <- []*voltha.DeviceImageState{{
612 DeviceId: deviceID,
613 ImageState: &voltha.ImageState{
614 Version: request.GetVersion(),
615 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
616 Reason: voltha.ImageState_UNKNOWN_ERROR,
617 ImageState: voltha.ImageState_IMAGE_COMMIT_ABORTED,
618 },
619 }}
khenaidood948f772021-08-11 17:49:24 -0400620 return
621 }
622
623 resp, err := agent.commitImage(ctx, req)
624 if err != nil {
625 logger.Errorw(ctx, "commit-image-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiqui9e120e92021-10-11 12:33:05 +0530626 ch <- []*voltha.DeviceImageState{{
627 DeviceId: deviceID,
628 ImageState: &voltha.ImageState{
629 Version: request.GetVersion(),
630 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
631 Reason: voltha.ImageState_UNKNOWN_ERROR,
632 ImageState: voltha.ImageState_IMAGE_COMMIT_ABORTED,
633 },
634 }}
khenaidood948f772021-08-11 17:49:24 -0400635 return
636 }
637
638 err = dMgr.validateDeviceImageResponse(resp)
639 if err != nil {
640 logger.Errorf(ctx, "commit-image-failed", log.Fields{"device-id": deviceID, "error": err})
ssiddiqui9e120e92021-10-11 12:33:05 +0530641 ch <- []*voltha.DeviceImageState{{
642 DeviceId: deviceID,
643 ImageState: &voltha.ImageState{
644 Version: request.GetVersion(),
645 DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
646 Reason: voltha.ImageState_UNKNOWN_ERROR,
647 ImageState: voltha.ImageState_IMAGE_UNKNOWN,
648 },
649 }}
khenaidood948f772021-08-11 17:49:24 -0400650 return
651 }
652 ch <- resp.GetDeviceImageStates()
653 }(deviceID.GetId(), commitImageReq, respCh)
654
655 }
656
657 return dMgr.waitForAllResponses(ctx, "commit-image", respCh, len(request.GetDeviceId()))
658}
659
660// convenience to avoid redefining
661var imageDownloadFailureResp = &voltha.ImageDownload{DownloadState: voltha.ImageDownload_DOWNLOAD_UNKNOWN}
662
663// GetImageDownloadStatus returns status of image download
664func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
665 ctx = utils.WithRPCMetadataContext(ctx, "GetImageDownloadStatus")
666 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
667
668 logger.Debugw(ctx, "get-image-download-status", log.Fields{"device-id": img.Id, "image-name": img.Name})
669 agent := dMgr.getDeviceAgent(ctx, img.Id)
670 if agent == nil {
671 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
672 }
673 resp, err := agent.getImageDownloadStatus(ctx, img)
674 if err != nil {
675 return imageDownloadFailureResp, err
676 }
677 return resp, nil
678}
679
680// GetImageDownload returns image download
681func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
682 ctx = utils.WithRPCMetadataContext(ctx, "GetImageDownload")
683 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
684
685 logger.Debugw(ctx, "get-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
686 agent := dMgr.getDeviceAgent(ctx, img.Id)
687 if agent == nil {
688 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
689 }
690 resp, err := agent.getImageDownload(ctx, img)
691 if err != nil {
692 return imageDownloadFailureResp, err
693 }
694 return resp, nil
695}
696
697// ListImageDownloads returns image downloads
698func (dMgr *Manager) ListImageDownloads(ctx context.Context, id *voltha.ID) (*voltha.ImageDownloads, error) {
699 ctx = utils.WithRPCMetadataContext(ctx, "ListImageDownloads")
700 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
701
702 logger.Debugw(ctx, "list-image-downloads", log.Fields{"device-id": id.Id})
703 agent := dMgr.getDeviceAgent(ctx, id.Id)
704 if agent == nil {
705 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, status.Errorf(codes.NotFound, "%s", id.Id)
706 }
707 resp, err := agent.listImageDownloads(ctx, id.Id)
708 if err != nil {
709 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, err
710 }
711 return resp, nil
712}
713
714// GetImages returns all images for a specific device entry
715func (dMgr *Manager) GetImages(ctx context.Context, id *voltha.ID) (*voltha.Images, error) {
716 ctx = utils.WithRPCMetadataContext(ctx, "GetImages")
717 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
718
719 logger.Debugw(ctx, "get-images", log.Fields{"device-id": id.Id})
720 device, err := dMgr.getDeviceReadOnly(ctx, id.Id)
721 if err != nil {
722 return nil, err
723 }
724 return device.Images, nil
725}
726
727// ListDevicePorts returns the ports details for a specific device entry
728func (dMgr *Manager) ListDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.Ports, error) {
729 ctx = utils.WithRPCMetadataContext(ctx, "ListDevicePorts")
730 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
731
732 logger.Debugw(ctx, "list-device-ports", log.Fields{"device-id": id.Id})
733 agent := dMgr.getDeviceAgent(ctx, id.Id)
734 if agent == nil {
735 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
736 }
737
738 ports := agent.listDevicePorts()
739 ctr, ret := 0, make([]*voltha.Port, len(ports))
740 for _, port := range ports {
741 ret[ctr] = port
742 ctr++
743 }
744 return &voltha.Ports{Items: ret}, nil
745}
746
747// ListDevicePmConfigs returns pm configs of device
748func (dMgr *Manager) ListDevicePmConfigs(ctx context.Context, id *voltha.ID) (*voltha.PmConfigs, error) {
749 ctx = utils.WithRPCMetadataContext(ctx, "ListDevicePmConfigs")
750 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
751
752 agent := dMgr.getDeviceAgent(ctx, id.Id)
753 if agent == nil {
754 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
755 }
756 return agent.listPmConfigs(ctx)
757}
758
759// UpdateDevicePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
760// following a user action
761func (dMgr *Manager) UpdateDevicePmConfigs(ctx context.Context, configs *voltha.PmConfigs) (*empty.Empty, error) {
762 ctx = utils.WithRPCMetadataContext(ctx, "UpdateDevicePmConfigs")
763 log.EnrichSpan(ctx, log.Fields{"device-id": configs.Id})
764
765 if configs.Id == "" {
766 return nil, status.Error(codes.FailedPrecondition, "invalid-device-Id")
767 }
768 agent := dMgr.getDeviceAgent(ctx, configs.Id)
769 if agent == nil {
770 return nil, status.Errorf(codes.NotFound, "%s", configs.Id)
771 }
772 return &empty.Empty{}, agent.updatePmConfigs(ctx, configs)
773}
774
775// ListDeviceFlows returns the flow details for a specific device entry
776func (dMgr *Manager) ListDeviceFlows(ctx context.Context, id *voltha.ID) (*ofp.Flows, error) {
777 ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceFlows")
778 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
779 logger.Debugw(ctx, "list-device-flows", log.Fields{"device-id": id.Id})
780 agent := dMgr.getDeviceAgent(ctx, id.Id)
781 if agent == nil {
782 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
783 }
784
785 flows := agent.listDeviceFlows()
786 ctr, ret := 0, make([]*ofp.OfpFlowStats, len(flows))
787 for _, flow := range flows {
788 ret[ctr] = flow
789 ctr++
790 }
791 return &ofp.Flows{Items: ret}, nil
792}
793
794// ListDeviceFlowGroups returns the flow group details for a specific device entry
khenaidoo9beaaf12021-10-19 17:32:01 -0400795func (dMgr *Manager) ListDeviceFlowGroups(ctx context.Context, id *voltha.ID) (*ofp.FlowGroups, error) {
khenaidood948f772021-08-11 17:49:24 -0400796 ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceFlowGroups")
797 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
798 logger.Debugw(ctx, "list-device-flow-groups", log.Fields{"device-id": id.Id})
799 agent := dMgr.getDeviceAgent(ctx, id.Id)
800 if agent == nil {
801 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
802 }
803 groups := agent.listDeviceGroups()
804 ctr, ret := 0, make([]*ofp.OfpGroupEntry, len(groups))
805 for _, group := range groups {
806 ret[ctr] = group
807 ctr++
808 }
khenaidoo9beaaf12021-10-19 17:32:01 -0400809 return &ofp.FlowGroups{Items: ret}, nil
khenaidood948f772021-08-11 17:49:24 -0400810}
811
812func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
813 ctx = utils.WithRPCMetadataContext(ctx, "EnablePort")
814 log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
815
816 logger.Debugw(ctx, "enable-port", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
817 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
818 if agent == nil {
819 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
820 }
821 return &empty.Empty{}, agent.enablePort(ctx, port.PortNo)
822}
823
824func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
825 ctx = utils.WithRPCMetadataContext(ctx, "DisablePort")
826 log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
827
828 logger.Debugw(ctx, "disable-port", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
829 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
830 if agent == nil {
831 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
832 }
833 return &empty.Empty{}, agent.disablePort(ctx, port.PortNo)
834}
835
khenaidoo9beaaf12021-10-19 17:32:01 -0400836func (dMgr *Manager) GetExtValue(ctx context.Context, value *extension.ValueSpecifier) (*extension.ReturnValues, error) {
khenaidood948f772021-08-11 17:49:24 -0400837 ctx = utils.WithRPCMetadataContext(ctx, "GetExtValue")
838 log.EnrichSpan(ctx, log.Fields{"device-id": value.Id})
839
840 logger.Debugw(ctx, "get-ext-value", log.Fields{"onu-id": value.Id})
841 cDevice, err := dMgr.getDeviceReadOnly(ctx, value.Id)
842 if err != nil {
843 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
844 }
845 pDevice, err := dMgr.getDeviceReadOnly(ctx, cDevice.ParentId)
846 if err != nil {
847 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
848 }
849 if agent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); agent != nil {
850 resp, err := agent.getExtValue(ctx, pDevice, cDevice, value)
851 if err != nil {
852 return nil, err
853 }
854 logger.Debugw(ctx, "get-ext-value-result", log.Fields{"result": resp})
855 return resp, nil
856 }
857 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
858
859}
860
861// SetExtValue set some given configs or value
khenaidoo9beaaf12021-10-19 17:32:01 -0400862func (dMgr *Manager) SetExtValue(ctx context.Context, value *extension.ValueSet) (*empty.Empty, error) {
khenaidood948f772021-08-11 17:49:24 -0400863 ctx = utils.WithRPCMetadataContext(ctx, "SetExtValue")
864 logger.Debugw(ctx, "set-ext-value", log.Fields{"onu-id": value.Id})
865
866 device, err := dMgr.getDeviceReadOnly(ctx, value.Id)
867 if err != nil {
868 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
869 }
870 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
871 resp, err := agent.setExtValue(ctx, device, value)
872 if err != nil {
873 return nil, err
874 }
875 logger.Debugw(ctx, "set-ext-value-result", log.Fields{"result": resp})
876 return resp, nil
877 }
878 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
879
880}
881
khenaidoo9beaaf12021-10-19 17:32:01 -0400882func (dMgr *Manager) StartOmciTestAction(ctx context.Context, request *omci.OmciTestRequest) (*omci.TestResponse, error) {
khenaidood948f772021-08-11 17:49:24 -0400883 ctx = utils.WithRPCMetadataContext(ctx, "StartOmciTestAction")
884 log.EnrichSpan(ctx, log.Fields{"device-id": request.Id})
885
886 logger.Debugw(ctx, "start-omci-test-action", log.Fields{"device-id": request.Id, "uuid": request.Uuid})
887 agent := dMgr.getDeviceAgent(ctx, request.Id)
888 if agent == nil {
889 return nil, status.Errorf(codes.NotFound, "%s", request.Id)
890 }
891 return agent.startOmciTest(ctx, request)
892}
893
894func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulateReq *voltha.SimulateAlarmRequest) (*common.OperationResp, error) {
895 ctx = utils.WithRPCMetadataContext(ctx, "SimulateAlarm")
896
897 logger.Debugw(ctx, "simulate-alarm", log.Fields{"id": simulateReq.Id, "indicator": simulateReq.Indicator, "intf-id": simulateReq.IntfId,
898 "port-type-name": simulateReq.PortTypeName, "onu-device-id": simulateReq.OnuDeviceId, "inverse-bit-error-rate": simulateReq.InverseBitErrorRate,
899 "drift": simulateReq.Drift, "new-eqd": simulateReq.NewEqd, "onu-serial-number": simulateReq.OnuSerialNumber, "operation": simulateReq.Operation})
900 agent := dMgr.getDeviceAgent(ctx, simulateReq.Id)
901 if agent == nil {
902 return nil, status.Errorf(codes.NotFound, "%s", simulateReq.Id)
903 }
904 if err := agent.simulateAlarm(ctx, simulateReq); err != nil {
905 return nil, err
906 }
907 return &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}, nil
908}
yasin sapli8fe47e42023-06-09 21:19:00 +0000909
910func (dMgr *Manager) PutVoipUserProfile(ctx context.Context, voipUserProfileRequest *voip_user_profile.VoipUserProfileRequest) (*empty.Empty, error) {
911 return nil, status.Error(codes.Unimplemented, "put-voip-user-profile-not-implemented")
912}
913
914func (dMgr *Manager) DeleteVoipUserProfile(ctx context.Context, key *common.Key) (*empty.Empty, error) {
915 return nil, status.Error(codes.Unimplemented, "delete-voip-user-profile-not-implemented")
916}
917
918func (dMgr *Manager) PutVoipSystemProfile(ctx context.Context, voipSystemProfileRequest *voip_system_profile.VoipSystemProfileRequest) (*empty.Empty, error) {
919 return nil, status.Error(codes.Unimplemented, "put-voip-system-profile-not-implemented")
920}
921
922func (dMgr *Manager) DeleteVoipSystemProfile(ctx context.Context, key *common.Key) (*empty.Empty, error) {
923 return nil, status.Error(codes.Unimplemented, "delete-voip-system-profile-not-implemented")
924}