blob: 9a1681215f70e4244f800a460f40e9943d4c91c1 [file] [log] [blame]
khenaidood948f772021-08-11 17:49:24 -04001/*
2 * Copyright 2021-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package 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"
26 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
27 "github.com/opencord/voltha-protos/v5/go/voltha"
28 "google.golang.org/grpc/codes"
29 "google.golang.org/grpc/status"
30)
31
32// CreateDevice creates a new parent device in the data model
33func (dMgr *Manager) CreateDevice(ctx context.Context, device *voltha.Device) (*voltha.Device, error) {
34 if device.MacAddress == "" && device.GetHostAndPort() == "" {
35 logger.Errorf(ctx, "no-device-info-present")
36 return &voltha.Device{}, errors.New("no-device-info-present; MAC or HOSTIP&PORT")
37 }
38 ctx = utils.WithRPCMetadataContext(ctx, "CreateDevice")
39 logger.Debugw(ctx, "create-device", log.Fields{"device": *device})
40
41 deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
42 if err != nil {
43 logger.Errorf(ctx, "failed-to-fetch-parent-device-info")
44 return nil, err
45 }
46 if deviceExist {
47 logger.Errorf(ctx, "device-is-pre-provisioned-already-with-same-ip-port-or-mac-address")
48 return nil, errors.New("device is already pre-provisioned")
49 }
50 logger.Debugw(ctx, "create-device", log.Fields{"device": device})
51
52 // Ensure this device is set as root
53 device.Root = true
54 // Create and start a device agent for that device
55 agent := newAgent(device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.internalTimeout, dMgr.rpcTimeout)
56 device, err = agent.start(ctx, false, device)
57 if err != nil {
58 logger.Errorw(ctx, "fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
59 return nil, err
60 }
61 dMgr.addDeviceAgentToMap(agent)
62 return device, nil
63}
64
65// EnableDevice activates a device by invoking the adopt_device API on the appropriate adapter
66func (dMgr *Manager) EnableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
67 ctx = utils.WithRPCMetadataContext(ctx, "EnableDevice")
68 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
69
70 logger.Debugw(ctx, "enable-device", log.Fields{"device-id": id.Id})
71 agent := dMgr.getDeviceAgent(ctx, id.Id)
72 if agent == nil {
73 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
74 }
75 return &empty.Empty{}, agent.enableDevice(ctx)
76}
77
78// DisableDevice disables a device along with any child device it may have
79func (dMgr *Manager) DisableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
80 ctx = utils.WithRPCMetadataContext(ctx, "DisableDevice")
81 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
82
83 logger.Debugw(ctx, "disable-device", log.Fields{"device-id": id.Id})
84 agent := dMgr.getDeviceAgent(ctx, id.Id)
85 if agent == nil {
86 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
87 }
88 return &empty.Empty{}, agent.disableDevice(ctx)
89}
90
91//RebootDevice invoked the reboot API to the corresponding adapter
92func (dMgr *Manager) RebootDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
93 ctx = utils.WithRPCMetadataContext(ctx, "RebootDevice")
94 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
95
96 logger.Debugw(ctx, "reboot-device", log.Fields{"device-id": id.Id})
97 agent := dMgr.getDeviceAgent(ctx, id.Id)
98 if agent == nil {
99 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
100 }
101 return &empty.Empty{}, agent.rebootDevice(ctx)
102}
103
104// DeleteDevice removes a device from the data model
105func (dMgr *Manager) DeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
106 ctx = utils.WithRPCMetadataContext(ctx, "DeleteDevice")
107 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
108
109 logger.Debugw(ctx, "delete-device", log.Fields{"device-id": id.Id})
110 agent := dMgr.getDeviceAgent(ctx, id.Id)
111 if agent == nil {
112 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
113 }
114 return &empty.Empty{}, agent.deleteDevice(ctx)
115}
116
117// ForceDeleteDevice removes a device from the data model forcefully without successfully waiting for the adapters.
118func (dMgr *Manager) ForceDeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
119 ctx = utils.WithRPCMetadataContext(ctx, "ForceDeleteDevice")
120 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
121
122 logger.Debugw(ctx, "force-delete-device", log.Fields{"device-id": id.Id})
123 agent := dMgr.getDeviceAgent(ctx, id.Id)
124 if agent == nil {
125 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
126 }
127 return &empty.Empty{}, agent.deleteDeviceForce(ctx)
128}
129
130// ListDevices retrieves the latest devices from the data model
131func (dMgr *Manager) ListDevices(ctx context.Context, _ *empty.Empty) (*voltha.Devices, error) {
132 ctx = utils.WithRPCMetadataContext(ctx, "ListDevices")
133
134 logger.Debug(ctx, "list-devices")
135 result := &voltha.Devices{}
136
137 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
138 result.Items = append(result.Items, value.(*Agent).device)
139 return true
140 })
141
142 logger.Debugw(ctx, "list-devices-end", log.Fields{"len": len(result.Items)})
143 return result, nil
144}
145
146// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
147func (dMgr *Manager) ListDeviceIds(ctx context.Context, _ *empty.Empty) (*voltha.IDs, error) {
148 ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceIds")
149
150 logger.Debug(ctx, "list-device-ids")
151 // Report only device IDs that are in the device agent map
152 return dMgr.listDeviceIdsFromMap(), nil
153}
154
155// ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
156// trigger loading the devices along with their children and parent in memory
157func (dMgr *Manager) ReconcileDevices(ctx context.Context, ids *voltha.IDs) (*empty.Empty, error) {
158 ctx = utils.WithRPCMetadataContext(ctx, "ReconcileDevices")
159
160 numDevices := 0
161 if ids != nil {
162 numDevices = len(ids.Items)
163 }
164
165 logger.Debugw(ctx, "reconcile-devices", log.Fields{"num-devices": numDevices})
166 if ids != nil && len(ids.Items) != 0 {
167 toReconcile := len(ids.Items)
168 reconciled := 0
169 var err error
170 for _, id := range ids.Items {
171 if err = dMgr.load(ctx, id.Id); err != nil {
172 logger.Warnw(ctx, "failure-reconciling-device", log.Fields{"device-id": id.Id, "error": err})
173 } else {
174 reconciled++
175 }
176 }
177 if toReconcile != reconciled {
178 return nil, status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
179 }
180 } else {
181 return nil, status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
182 }
183 return &empty.Empty{}, nil
184}
185
186// GetDevice exists primarily to implement the gRPC interface.
187// Internal functions should call getDeviceReadOnly instead.
188func (dMgr *Manager) GetDevice(ctx context.Context, id *voltha.ID) (*voltha.Device, error) {
189 ctx = utils.WithRPCMetadataContext(ctx, "GetDevice")
190 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
191
192 return dMgr.getDeviceReadOnly(ctx, id.Id)
193}
194
195// convenience to avoid redefining
196var operationFailureResp = &common.OperationResp{Code: voltha.OperationResp_OPERATION_FAILURE}
197
198// DownloadImage execute an image download request
199func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
200 ctx = utils.WithRPCMetadataContext(ctx, "DownloadImage")
201 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
202
203 logger.Debugw(ctx, "download-image", log.Fields{"device-id": img.Id, "image-name": img.Name})
204 agent := dMgr.getDeviceAgent(ctx, img.Id)
205 if agent == nil {
206 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
207 }
208 resp, err := agent.downloadImage(ctx, img)
209 if err != nil {
210 return operationFailureResp, err
211 }
212 return resp, nil
213}
214
215// CancelImageDownload cancels image download request
216func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
217 ctx = utils.WithRPCMetadataContext(ctx, "CancelImageDownload")
218 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
219
220 logger.Debugw(ctx, "cancel-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
221 agent := dMgr.getDeviceAgent(ctx, img.Id)
222 if agent == nil {
223 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
224 }
225 resp, err := agent.cancelImageDownload(ctx, img)
226 if err != nil {
227 return operationFailureResp, err
228 }
229 return resp, nil
230}
231
232// ActivateImageUpdate activates image update request
233func (dMgr *Manager) ActivateImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
234 ctx = utils.WithRPCMetadataContext(ctx, "ActivateImageUpdate")
235 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
236
237 logger.Debugw(ctx, "activate-image-update", log.Fields{"device-id": img.Id, "image-name": img.Name})
238 agent := dMgr.getDeviceAgent(ctx, img.Id)
239 if agent == nil {
240 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
241 }
242 resp, err := agent.activateImage(ctx, img)
243 if err != nil {
244 return operationFailureResp, err
245 }
246 return resp, nil
247}
248
249// RevertImageUpdate reverts image update
250func (dMgr *Manager) RevertImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
251 ctx = utils.WithRPCMetadataContext(ctx, "RevertImageUpdate")
252 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
253
254 logger.Debugw(ctx, "rever-image-update", log.Fields{"device-id": img.Id, "image-name": img.Name})
255 agent := dMgr.getDeviceAgent(ctx, img.Id)
256 if agent == nil {
257 return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
258 }
259 resp, err := agent.revertImage(ctx, img)
260 if err != nil {
261 return operationFailureResp, err
262 }
263 return resp, nil
264}
265
266func (dMgr *Manager) DownloadImageToDevice(ctx context.Context, request *voltha.DeviceImageDownloadRequest) (*voltha.DeviceImageResponse, error) {
267 if err := dMgr.validateImageDownloadRequest(request); err != nil {
268 return nil, err
269 }
270
271 ctx = utils.WithRPCMetadataContext(ctx, "DownloadImageToDevice")
272 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
273
274 for index, deviceID := range request.DeviceId {
275 // Create download request per device
276 downloadReq := &voltha.DeviceImageDownloadRequest{
277 Image: request.Image,
278 ActivateOnSuccess: request.ActivateOnSuccess,
279 CommitOnSuccess: request.CommitOnSuccess,
280 }
281
282 //slice-out only single deviceID from the request
283 downloadReq.DeviceId = request.DeviceId[index : index+1]
284
285 go func(deviceID string, req *voltha.DeviceImageDownloadRequest, ch chan []*voltha.DeviceImageState) {
286 agent := dMgr.getDeviceAgent(ctx, deviceID)
287 if agent == nil {
288 logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
289 ch <- nil
290 return
291 }
292
293 resp, err := agent.downloadImageToDevice(ctx, req)
294 if err != nil {
295 logger.Errorw(ctx, "download-image-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
296 ch <- nil
297 return
298 }
299
300 err = dMgr.validateDeviceImageResponse(resp)
301 if err != nil {
302 logger.Errorw(ctx, "download-image-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
303 ch <- nil
304 return
305 }
306 ch <- resp.GetDeviceImageStates()
307 }(deviceID.GetId(), downloadReq, respCh)
308
309 }
310
311 return dMgr.waitForAllResponses(ctx, "download-image-to-device", respCh, len(request.GetDeviceId()))
312}
313
314func (dMgr *Manager) GetImageStatus(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
315 if err := dMgr.validateImageRequest(request); err != nil {
316 return nil, err
317 }
318
319 ctx = utils.WithRPCMetadataContext(ctx, "GetImageStatus")
320
321 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
322 for index, deviceID := range request.DeviceId {
323 // Create status request per device
324 imageStatusReq := &voltha.DeviceImageRequest{
325 Version: request.Version,
326 CommitOnSuccess: request.CommitOnSuccess,
327 }
328
329 //slice-out only single deviceID from the request
330 imageStatusReq.DeviceId = request.DeviceId[index : index+1]
331
332 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
333 agent := dMgr.getDeviceAgent(ctx, deviceID)
334 if agent == nil {
335 logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
336 ch <- nil
337 return
338 }
339
340 resp, err := agent.getImageStatus(ctx, req)
341 if err != nil {
342 logger.Errorw(ctx, "get-image-status-failed", log.Fields{"device-id": deviceID, "error": err})
343 ch <- nil
344 return
345 }
346
347 err = dMgr.validateDeviceImageResponse(resp)
348 if err != nil {
349 logger.Errorw(ctx, "get-image-status-failed", log.Fields{"device-id": deviceID, "error": err})
350 ch <- nil
351 return
352 }
353 ch <- resp.GetDeviceImageStates()
354 }(deviceID.GetId(), imageStatusReq, respCh)
355
356 }
357
358 return dMgr.waitForAllResponses(ctx, "get-image-status", respCh, len(request.GetDeviceId()))
359}
360
361func (dMgr *Manager) AbortImageUpgradeToDevice(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
362 if err := dMgr.validateImageRequest(request); err != nil {
363 return nil, err
364 }
365
366 ctx = utils.WithRPCMetadataContext(ctx, "AbortImageUpgradeToDevice")
367 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
368
369 for index, deviceID := range request.DeviceId {
370 // Create abort request per device
371 abortImageReq := &voltha.DeviceImageRequest{
372 Version: request.Version,
373 CommitOnSuccess: request.CommitOnSuccess,
374 }
375
376 //slice-out only single deviceID from the request
377 abortImageReq.DeviceId = request.DeviceId[index : index+1]
378
379 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
380 agent := dMgr.getDeviceAgent(ctx, deviceID)
381 if agent == nil {
382 logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
383 ch <- nil
384 return
385 }
386
387 resp, err := agent.abortImageUpgradeToDevice(ctx, req)
388 if err != nil {
389 logger.Errorw(ctx, "abort-image-upgrade-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
390 ch <- nil
391 return
392 }
393
394 err = dMgr.validateDeviceImageResponse(resp)
395 if err != nil {
396 logger.Errorw(ctx, "abort-image-upgrade-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
397 ch <- nil
398 return
399 }
400 ch <- resp.GetDeviceImageStates()
401 }(deviceID.GetId(), abortImageReq, respCh)
402
403 }
404
405 return dMgr.waitForAllResponses(ctx, "abort-image-upgrade-to-device", respCh, len(request.GetDeviceId()))
406}
407
408func (dMgr *Manager) GetOnuImages(ctx context.Context, id *common.ID) (*voltha.OnuImages, error) {
409 if id == nil || id.Id == "" {
410 return nil, status.Errorf(codes.InvalidArgument, "empty device id")
411 }
412
413 ctx = utils.WithRPCMetadataContext(ctx, "GetOnuImages")
414 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
415 agent := dMgr.getDeviceAgent(ctx, id.Id)
416 if agent == nil {
417 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
418 }
419
420 resp, err := agent.getOnuImages(ctx, id)
421 if err != nil {
422 return nil, err
423 }
424
425 logger.Debugw(ctx, "get-onu-images-result", log.Fields{"onu-image": resp.Items})
426
427 return resp, nil
428}
429
430func (dMgr *Manager) ActivateImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
431 if err := dMgr.validateImageRequest(request); err != nil {
432 return nil, err
433 }
434
435 ctx = utils.WithRPCMetadataContext(ctx, "ActivateImage")
436 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
437
438 for index, deviceID := range request.DeviceId {
439 // Create activate request per device
440 activateImageReq := &voltha.DeviceImageRequest{
441 Version: request.Version,
442 CommitOnSuccess: request.CommitOnSuccess,
443 }
444
445 //slice-out only single deviceID from the request
446 activateImageReq.DeviceId = request.DeviceId[index : index+1]
447
448 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
449 agent := dMgr.getDeviceAgent(ctx, deviceID)
450 if agent == nil {
451 logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
452 ch <- nil
453 return
454 }
455
456 resp, err := agent.activateImageOnDevice(ctx, req)
457 if err != nil {
458 logger.Errorw(ctx, "activate-image-failed", log.Fields{"device-id": deviceID, "error": err})
459 ch <- nil
460 return
461 }
462
463 err = dMgr.validateDeviceImageResponse(resp)
464 if err != nil {
465 logger.Errorw(ctx, "activate-image-failed", log.Fields{"device-id": deviceID, "error": err})
466 ch <- nil
467 return
468 }
469
470 ch <- resp.GetDeviceImageStates()
471 }(deviceID.GetId(), activateImageReq, respCh)
472
473 }
474
475 return dMgr.waitForAllResponses(ctx, "activate-image", respCh, len(request.GetDeviceId()))
476}
477
478func (dMgr *Manager) CommitImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
479 if err := dMgr.validateImageRequest(request); err != nil {
480 return nil, err
481 }
482
483 ctx = utils.WithRPCMetadataContext(ctx, "CommitImage")
484 respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
485
486 for index, deviceID := range request.DeviceId {
487 // Create commit request per device
488 commitImageReq := &voltha.DeviceImageRequest{
489 Version: request.Version,
490 CommitOnSuccess: request.CommitOnSuccess,
491 }
492 //slice-out only single deviceID from the request
493 commitImageReq.DeviceId = request.DeviceId[index : index+1]
494
495 go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
496 agent := dMgr.getDeviceAgent(ctx, deviceID)
497 if agent == nil {
498 logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
499 ch <- nil
500 return
501 }
502
503 resp, err := agent.commitImage(ctx, req)
504 if err != nil {
505 logger.Errorw(ctx, "commit-image-failed", log.Fields{"device-id": deviceID, "error": err})
506 ch <- nil
507 return
508 }
509
510 err = dMgr.validateDeviceImageResponse(resp)
511 if err != nil {
512 logger.Errorf(ctx, "commit-image-failed", log.Fields{"device-id": deviceID, "error": err})
513 ch <- nil
514 return
515 }
516 ch <- resp.GetDeviceImageStates()
517 }(deviceID.GetId(), commitImageReq, respCh)
518
519 }
520
521 return dMgr.waitForAllResponses(ctx, "commit-image", respCh, len(request.GetDeviceId()))
522}
523
524// convenience to avoid redefining
525var imageDownloadFailureResp = &voltha.ImageDownload{DownloadState: voltha.ImageDownload_DOWNLOAD_UNKNOWN}
526
527// GetImageDownloadStatus returns status of image download
528func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
529 ctx = utils.WithRPCMetadataContext(ctx, "GetImageDownloadStatus")
530 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
531
532 logger.Debugw(ctx, "get-image-download-status", log.Fields{"device-id": img.Id, "image-name": img.Name})
533 agent := dMgr.getDeviceAgent(ctx, img.Id)
534 if agent == nil {
535 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
536 }
537 resp, err := agent.getImageDownloadStatus(ctx, img)
538 if err != nil {
539 return imageDownloadFailureResp, err
540 }
541 return resp, nil
542}
543
544// GetImageDownload returns image download
545func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
546 ctx = utils.WithRPCMetadataContext(ctx, "GetImageDownload")
547 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
548
549 logger.Debugw(ctx, "get-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
550 agent := dMgr.getDeviceAgent(ctx, img.Id)
551 if agent == nil {
552 return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
553 }
554 resp, err := agent.getImageDownload(ctx, img)
555 if err != nil {
556 return imageDownloadFailureResp, err
557 }
558 return resp, nil
559}
560
561// ListImageDownloads returns image downloads
562func (dMgr *Manager) ListImageDownloads(ctx context.Context, id *voltha.ID) (*voltha.ImageDownloads, error) {
563 ctx = utils.WithRPCMetadataContext(ctx, "ListImageDownloads")
564 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
565
566 logger.Debugw(ctx, "list-image-downloads", log.Fields{"device-id": id.Id})
567 agent := dMgr.getDeviceAgent(ctx, id.Id)
568 if agent == nil {
569 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, status.Errorf(codes.NotFound, "%s", id.Id)
570 }
571 resp, err := agent.listImageDownloads(ctx, id.Id)
572 if err != nil {
573 return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, err
574 }
575 return resp, nil
576}
577
578// GetImages returns all images for a specific device entry
579func (dMgr *Manager) GetImages(ctx context.Context, id *voltha.ID) (*voltha.Images, error) {
580 ctx = utils.WithRPCMetadataContext(ctx, "GetImages")
581 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
582
583 logger.Debugw(ctx, "get-images", log.Fields{"device-id": id.Id})
584 device, err := dMgr.getDeviceReadOnly(ctx, id.Id)
585 if err != nil {
586 return nil, err
587 }
588 return device.Images, nil
589}
590
591// ListDevicePorts returns the ports details for a specific device entry
592func (dMgr *Manager) ListDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.Ports, error) {
593 ctx = utils.WithRPCMetadataContext(ctx, "ListDevicePorts")
594 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
595
596 logger.Debugw(ctx, "list-device-ports", log.Fields{"device-id": id.Id})
597 agent := dMgr.getDeviceAgent(ctx, id.Id)
598 if agent == nil {
599 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
600 }
601
602 ports := agent.listDevicePorts()
603 ctr, ret := 0, make([]*voltha.Port, len(ports))
604 for _, port := range ports {
605 ret[ctr] = port
606 ctr++
607 }
608 return &voltha.Ports{Items: ret}, nil
609}
610
611// ListDevicePmConfigs returns pm configs of device
612func (dMgr *Manager) ListDevicePmConfigs(ctx context.Context, id *voltha.ID) (*voltha.PmConfigs, error) {
613 ctx = utils.WithRPCMetadataContext(ctx, "ListDevicePmConfigs")
614 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
615
616 agent := dMgr.getDeviceAgent(ctx, id.Id)
617 if agent == nil {
618 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
619 }
620 return agent.listPmConfigs(ctx)
621}
622
623// UpdateDevicePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
624// following a user action
625func (dMgr *Manager) UpdateDevicePmConfigs(ctx context.Context, configs *voltha.PmConfigs) (*empty.Empty, error) {
626 ctx = utils.WithRPCMetadataContext(ctx, "UpdateDevicePmConfigs")
627 log.EnrichSpan(ctx, log.Fields{"device-id": configs.Id})
628
629 if configs.Id == "" {
630 return nil, status.Error(codes.FailedPrecondition, "invalid-device-Id")
631 }
632 agent := dMgr.getDeviceAgent(ctx, configs.Id)
633 if agent == nil {
634 return nil, status.Errorf(codes.NotFound, "%s", configs.Id)
635 }
636 return &empty.Empty{}, agent.updatePmConfigs(ctx, configs)
637}
638
639// ListDeviceFlows returns the flow details for a specific device entry
640func (dMgr *Manager) ListDeviceFlows(ctx context.Context, id *voltha.ID) (*ofp.Flows, error) {
641 ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceFlows")
642 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
643 logger.Debugw(ctx, "list-device-flows", log.Fields{"device-id": id.Id})
644 agent := dMgr.getDeviceAgent(ctx, id.Id)
645 if agent == nil {
646 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
647 }
648
649 flows := agent.listDeviceFlows()
650 ctr, ret := 0, make([]*ofp.OfpFlowStats, len(flows))
651 for _, flow := range flows {
652 ret[ctr] = flow
653 ctr++
654 }
655 return &ofp.Flows{Items: ret}, nil
656}
657
658// ListDeviceFlowGroups returns the flow group details for a specific device entry
659func (dMgr *Manager) ListDeviceFlowGroups(ctx context.Context, id *voltha.ID) (*voltha.FlowGroups, error) {
660 ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceFlowGroups")
661 log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
662 logger.Debugw(ctx, "list-device-flow-groups", log.Fields{"device-id": id.Id})
663 agent := dMgr.getDeviceAgent(ctx, id.Id)
664 if agent == nil {
665 return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
666 }
667 groups := agent.listDeviceGroups()
668 ctr, ret := 0, make([]*ofp.OfpGroupEntry, len(groups))
669 for _, group := range groups {
670 ret[ctr] = group
671 ctr++
672 }
673 return &voltha.FlowGroups{Items: ret}, nil
674}
675
676func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
677 ctx = utils.WithRPCMetadataContext(ctx, "EnablePort")
678 log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
679
680 logger.Debugw(ctx, "enable-port", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
681 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
682 if agent == nil {
683 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
684 }
685 return &empty.Empty{}, agent.enablePort(ctx, port.PortNo)
686}
687
688func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
689 ctx = utils.WithRPCMetadataContext(ctx, "DisablePort")
690 log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
691
692 logger.Debugw(ctx, "disable-port", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
693 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
694 if agent == nil {
695 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
696 }
697 return &empty.Empty{}, agent.disablePort(ctx, port.PortNo)
698}
699
700func (dMgr *Manager) GetExtValue(ctx context.Context, value *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
701 ctx = utils.WithRPCMetadataContext(ctx, "GetExtValue")
702 log.EnrichSpan(ctx, log.Fields{"device-id": value.Id})
703
704 logger.Debugw(ctx, "get-ext-value", log.Fields{"onu-id": value.Id})
705 cDevice, err := dMgr.getDeviceReadOnly(ctx, value.Id)
706 if err != nil {
707 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
708 }
709 pDevice, err := dMgr.getDeviceReadOnly(ctx, cDevice.ParentId)
710 if err != nil {
711 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
712 }
713 if agent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); agent != nil {
714 resp, err := agent.getExtValue(ctx, pDevice, cDevice, value)
715 if err != nil {
716 return nil, err
717 }
718 logger.Debugw(ctx, "get-ext-value-result", log.Fields{"result": resp})
719 return resp, nil
720 }
721 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
722
723}
724
725// SetExtValue set some given configs or value
726func (dMgr *Manager) SetExtValue(ctx context.Context, value *voltha.ValueSet) (*empty.Empty, error) {
727 ctx = utils.WithRPCMetadataContext(ctx, "SetExtValue")
728 logger.Debugw(ctx, "set-ext-value", log.Fields{"onu-id": value.Id})
729
730 device, err := dMgr.getDeviceReadOnly(ctx, value.Id)
731 if err != nil {
732 return nil, status.Errorf(codes.Aborted, "%s", err.Error())
733 }
734 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
735 resp, err := agent.setExtValue(ctx, device, value)
736 if err != nil {
737 return nil, err
738 }
739 logger.Debugw(ctx, "set-ext-value-result", log.Fields{"result": resp})
740 return resp, nil
741 }
742 return nil, status.Errorf(codes.NotFound, "%s", value.Id)
743
744}
745
746func (dMgr *Manager) StartOmciTestAction(ctx context.Context, request *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
747 ctx = utils.WithRPCMetadataContext(ctx, "StartOmciTestAction")
748 log.EnrichSpan(ctx, log.Fields{"device-id": request.Id})
749
750 logger.Debugw(ctx, "start-omci-test-action", log.Fields{"device-id": request.Id, "uuid": request.Uuid})
751 agent := dMgr.getDeviceAgent(ctx, request.Id)
752 if agent == nil {
753 return nil, status.Errorf(codes.NotFound, "%s", request.Id)
754 }
755 return agent.startOmciTest(ctx, request)
756}
757
758func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulateReq *voltha.SimulateAlarmRequest) (*common.OperationResp, error) {
759 ctx = utils.WithRPCMetadataContext(ctx, "SimulateAlarm")
760
761 logger.Debugw(ctx, "simulate-alarm", log.Fields{"id": simulateReq.Id, "indicator": simulateReq.Indicator, "intf-id": simulateReq.IntfId,
762 "port-type-name": simulateReq.PortTypeName, "onu-device-id": simulateReq.OnuDeviceId, "inverse-bit-error-rate": simulateReq.InverseBitErrorRate,
763 "drift": simulateReq.Drift, "new-eqd": simulateReq.NewEqd, "onu-serial-number": simulateReq.OnuSerialNumber, "operation": simulateReq.Operation})
764 agent := dMgr.getDeviceAgent(ctx, simulateReq.Id)
765 if agent == nil {
766 return nil, status.Errorf(codes.NotFound, "%s", simulateReq.Id)
767 }
768 if err := agent.simulateAlarm(ctx, simulateReq); err != nil {
769 return nil, err
770 }
771 return &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}, nil
772}