[VOL-4291] Rw-core updates for gRPC migration
Change-Id: I8d5a554409115b29318089671ca4e1ab3fa98810
diff --git a/rw_core/core/device/manager_nbi.go b/rw_core/core/device/manager_nbi.go
new file mode 100644
index 0000000..9a16812
--- /dev/null
+++ b/rw_core/core/device/manager_nbi.go
@@ -0,0 +1,772 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package device
+
+import (
+ "context"
+ "errors"
+
+ "github.com/golang/protobuf/ptypes/empty"
+ "github.com/opencord/voltha-go/rw_core/utils"
+ "github.com/opencord/voltha-lib-go/v7/pkg/log"
+ "github.com/opencord/voltha-protos/v5/go/common"
+ ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
+ "github.com/opencord/voltha-protos/v5/go/voltha"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+// CreateDevice creates a new parent device in the data model
+func (dMgr *Manager) CreateDevice(ctx context.Context, device *voltha.Device) (*voltha.Device, error) {
+ if device.MacAddress == "" && device.GetHostAndPort() == "" {
+ logger.Errorf(ctx, "no-device-info-present")
+ return &voltha.Device{}, errors.New("no-device-info-present; MAC or HOSTIP&PORT")
+ }
+ ctx = utils.WithRPCMetadataContext(ctx, "CreateDevice")
+ logger.Debugw(ctx, "create-device", log.Fields{"device": *device})
+
+ deviceExist, err := dMgr.isParentDeviceExist(ctx, device)
+ if err != nil {
+ logger.Errorf(ctx, "failed-to-fetch-parent-device-info")
+ return nil, err
+ }
+ if deviceExist {
+ logger.Errorf(ctx, "device-is-pre-provisioned-already-with-same-ip-port-or-mac-address")
+ return nil, errors.New("device is already pre-provisioned")
+ }
+ logger.Debugw(ctx, "create-device", log.Fields{"device": device})
+
+ // Ensure this device is set as root
+ device.Root = true
+ // Create and start a device agent for that device
+ agent := newAgent(device, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.internalTimeout, dMgr.rpcTimeout)
+ device, err = agent.start(ctx, false, device)
+ if err != nil {
+ logger.Errorw(ctx, "fail-to-start-device", log.Fields{"device-id": agent.deviceID, "error": err})
+ return nil, err
+ }
+ dMgr.addDeviceAgentToMap(agent)
+ return device, nil
+}
+
+// EnableDevice activates a device by invoking the adopt_device API on the appropriate adapter
+func (dMgr *Manager) EnableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "EnableDevice")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "enable-device", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+ return &empty.Empty{}, agent.enableDevice(ctx)
+}
+
+// DisableDevice disables a device along with any child device it may have
+func (dMgr *Manager) DisableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "DisableDevice")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "disable-device", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+ return &empty.Empty{}, agent.disableDevice(ctx)
+}
+
+//RebootDevice invoked the reboot API to the corresponding adapter
+func (dMgr *Manager) RebootDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "RebootDevice")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "reboot-device", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+ return &empty.Empty{}, agent.rebootDevice(ctx)
+}
+
+// DeleteDevice removes a device from the data model
+func (dMgr *Manager) DeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "DeleteDevice")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "delete-device", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+ return &empty.Empty{}, agent.deleteDevice(ctx)
+}
+
+// ForceDeleteDevice removes a device from the data model forcefully without successfully waiting for the adapters.
+func (dMgr *Manager) ForceDeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ForceDeleteDevice")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "force-delete-device", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+ return &empty.Empty{}, agent.deleteDeviceForce(ctx)
+}
+
+// ListDevices retrieves the latest devices from the data model
+func (dMgr *Manager) ListDevices(ctx context.Context, _ *empty.Empty) (*voltha.Devices, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ListDevices")
+
+ logger.Debug(ctx, "list-devices")
+ result := &voltha.Devices{}
+
+ dMgr.deviceAgents.Range(func(key, value interface{}) bool {
+ result.Items = append(result.Items, value.(*Agent).device)
+ return true
+ })
+
+ logger.Debugw(ctx, "list-devices-end", log.Fields{"len": len(result.Items)})
+ return result, nil
+}
+
+// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
+func (dMgr *Manager) ListDeviceIds(ctx context.Context, _ *empty.Empty) (*voltha.IDs, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceIds")
+
+ logger.Debug(ctx, "list-device-ids")
+ // Report only device IDs that are in the device agent map
+ return dMgr.listDeviceIdsFromMap(), nil
+}
+
+// ReconcileDevices is a request to a voltha core to update its list of managed devices. This will
+// trigger loading the devices along with their children and parent in memory
+func (dMgr *Manager) ReconcileDevices(ctx context.Context, ids *voltha.IDs) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ReconcileDevices")
+
+ numDevices := 0
+ if ids != nil {
+ numDevices = len(ids.Items)
+ }
+
+ logger.Debugw(ctx, "reconcile-devices", log.Fields{"num-devices": numDevices})
+ if ids != nil && len(ids.Items) != 0 {
+ toReconcile := len(ids.Items)
+ reconciled := 0
+ var err error
+ for _, id := range ids.Items {
+ if err = dMgr.load(ctx, id.Id); err != nil {
+ logger.Warnw(ctx, "failure-reconciling-device", log.Fields{"device-id": id.Id, "error": err})
+ } else {
+ reconciled++
+ }
+ }
+ if toReconcile != reconciled {
+ return nil, status.Errorf(codes.DataLoss, "less-device-reconciled-than-requested:%d/%d", reconciled, toReconcile)
+ }
+ } else {
+ return nil, status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
+ }
+ return &empty.Empty{}, nil
+}
+
+// GetDevice exists primarily to implement the gRPC interface.
+// Internal functions should call getDeviceReadOnly instead.
+func (dMgr *Manager) GetDevice(ctx context.Context, id *voltha.ID) (*voltha.Device, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "GetDevice")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ return dMgr.getDeviceReadOnly(ctx, id.Id)
+}
+
+// convenience to avoid redefining
+var operationFailureResp = &common.OperationResp{Code: voltha.OperationResp_OPERATION_FAILURE}
+
+// DownloadImage execute an image download request
+func (dMgr *Manager) DownloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "DownloadImage")
+ log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
+
+ logger.Debugw(ctx, "download-image", log.Fields{"device-id": img.Id, "image-name": img.Name})
+ agent := dMgr.getDeviceAgent(ctx, img.Id)
+ if agent == nil {
+ return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
+ }
+ resp, err := agent.downloadImage(ctx, img)
+ if err != nil {
+ return operationFailureResp, err
+ }
+ return resp, nil
+}
+
+// CancelImageDownload cancels image download request
+func (dMgr *Manager) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "CancelImageDownload")
+ log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
+
+ logger.Debugw(ctx, "cancel-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
+ agent := dMgr.getDeviceAgent(ctx, img.Id)
+ if agent == nil {
+ return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
+ }
+ resp, err := agent.cancelImageDownload(ctx, img)
+ if err != nil {
+ return operationFailureResp, err
+ }
+ return resp, nil
+}
+
+// ActivateImageUpdate activates image update request
+func (dMgr *Manager) ActivateImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ActivateImageUpdate")
+ log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
+
+ logger.Debugw(ctx, "activate-image-update", log.Fields{"device-id": img.Id, "image-name": img.Name})
+ agent := dMgr.getDeviceAgent(ctx, img.Id)
+ if agent == nil {
+ return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
+ }
+ resp, err := agent.activateImage(ctx, img)
+ if err != nil {
+ return operationFailureResp, err
+ }
+ return resp, nil
+}
+
+// RevertImageUpdate reverts image update
+func (dMgr *Manager) RevertImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "RevertImageUpdate")
+ log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
+
+ logger.Debugw(ctx, "rever-image-update", log.Fields{"device-id": img.Id, "image-name": img.Name})
+ agent := dMgr.getDeviceAgent(ctx, img.Id)
+ if agent == nil {
+ return operationFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
+ }
+ resp, err := agent.revertImage(ctx, img)
+ if err != nil {
+ return operationFailureResp, err
+ }
+ return resp, nil
+}
+
+func (dMgr *Manager) DownloadImageToDevice(ctx context.Context, request *voltha.DeviceImageDownloadRequest) (*voltha.DeviceImageResponse, error) {
+ if err := dMgr.validateImageDownloadRequest(request); err != nil {
+ return nil, err
+ }
+
+ ctx = utils.WithRPCMetadataContext(ctx, "DownloadImageToDevice")
+ respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
+
+ for index, deviceID := range request.DeviceId {
+ // Create download request per device
+ downloadReq := &voltha.DeviceImageDownloadRequest{
+ Image: request.Image,
+ ActivateOnSuccess: request.ActivateOnSuccess,
+ CommitOnSuccess: request.CommitOnSuccess,
+ }
+
+ //slice-out only single deviceID from the request
+ downloadReq.DeviceId = request.DeviceId[index : index+1]
+
+ go func(deviceID string, req *voltha.DeviceImageDownloadRequest, ch chan []*voltha.DeviceImageState) {
+ agent := dMgr.getDeviceAgent(ctx, deviceID)
+ if agent == nil {
+ logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
+ ch <- nil
+ return
+ }
+
+ resp, err := agent.downloadImageToDevice(ctx, req)
+ if err != nil {
+ logger.Errorw(ctx, "download-image-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+
+ err = dMgr.validateDeviceImageResponse(resp)
+ if err != nil {
+ logger.Errorw(ctx, "download-image-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+ ch <- resp.GetDeviceImageStates()
+ }(deviceID.GetId(), downloadReq, respCh)
+
+ }
+
+ return dMgr.waitForAllResponses(ctx, "download-image-to-device", respCh, len(request.GetDeviceId()))
+}
+
+func (dMgr *Manager) GetImageStatus(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
+ if err := dMgr.validateImageRequest(request); err != nil {
+ return nil, err
+ }
+
+ ctx = utils.WithRPCMetadataContext(ctx, "GetImageStatus")
+
+ respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
+ for index, deviceID := range request.DeviceId {
+ // Create status request per device
+ imageStatusReq := &voltha.DeviceImageRequest{
+ Version: request.Version,
+ CommitOnSuccess: request.CommitOnSuccess,
+ }
+
+ //slice-out only single deviceID from the request
+ imageStatusReq.DeviceId = request.DeviceId[index : index+1]
+
+ go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
+ agent := dMgr.getDeviceAgent(ctx, deviceID)
+ if agent == nil {
+ logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
+ ch <- nil
+ return
+ }
+
+ resp, err := agent.getImageStatus(ctx, req)
+ if err != nil {
+ logger.Errorw(ctx, "get-image-status-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+
+ err = dMgr.validateDeviceImageResponse(resp)
+ if err != nil {
+ logger.Errorw(ctx, "get-image-status-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+ ch <- resp.GetDeviceImageStates()
+ }(deviceID.GetId(), imageStatusReq, respCh)
+
+ }
+
+ return dMgr.waitForAllResponses(ctx, "get-image-status", respCh, len(request.GetDeviceId()))
+}
+
+func (dMgr *Manager) AbortImageUpgradeToDevice(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
+ if err := dMgr.validateImageRequest(request); err != nil {
+ return nil, err
+ }
+
+ ctx = utils.WithRPCMetadataContext(ctx, "AbortImageUpgradeToDevice")
+ respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
+
+ for index, deviceID := range request.DeviceId {
+ // Create abort request per device
+ abortImageReq := &voltha.DeviceImageRequest{
+ Version: request.Version,
+ CommitOnSuccess: request.CommitOnSuccess,
+ }
+
+ //slice-out only single deviceID from the request
+ abortImageReq.DeviceId = request.DeviceId[index : index+1]
+
+ go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
+ agent := dMgr.getDeviceAgent(ctx, deviceID)
+ if agent == nil {
+ logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
+ ch <- nil
+ return
+ }
+
+ resp, err := agent.abortImageUpgradeToDevice(ctx, req)
+ if err != nil {
+ logger.Errorw(ctx, "abort-image-upgrade-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+
+ err = dMgr.validateDeviceImageResponse(resp)
+ if err != nil {
+ logger.Errorw(ctx, "abort-image-upgrade-to-device-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+ ch <- resp.GetDeviceImageStates()
+ }(deviceID.GetId(), abortImageReq, respCh)
+
+ }
+
+ return dMgr.waitForAllResponses(ctx, "abort-image-upgrade-to-device", respCh, len(request.GetDeviceId()))
+}
+
+func (dMgr *Manager) GetOnuImages(ctx context.Context, id *common.ID) (*voltha.OnuImages, error) {
+ if id == nil || id.Id == "" {
+ return nil, status.Errorf(codes.InvalidArgument, "empty device id")
+ }
+
+ ctx = utils.WithRPCMetadataContext(ctx, "GetOnuImages")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+
+ resp, err := agent.getOnuImages(ctx, id)
+ if err != nil {
+ return nil, err
+ }
+
+ logger.Debugw(ctx, "get-onu-images-result", log.Fields{"onu-image": resp.Items})
+
+ return resp, nil
+}
+
+func (dMgr *Manager) ActivateImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
+ if err := dMgr.validateImageRequest(request); err != nil {
+ return nil, err
+ }
+
+ ctx = utils.WithRPCMetadataContext(ctx, "ActivateImage")
+ respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
+
+ for index, deviceID := range request.DeviceId {
+ // Create activate request per device
+ activateImageReq := &voltha.DeviceImageRequest{
+ Version: request.Version,
+ CommitOnSuccess: request.CommitOnSuccess,
+ }
+
+ //slice-out only single deviceID from the request
+ activateImageReq.DeviceId = request.DeviceId[index : index+1]
+
+ go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
+ agent := dMgr.getDeviceAgent(ctx, deviceID)
+ if agent == nil {
+ logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
+ ch <- nil
+ return
+ }
+
+ resp, err := agent.activateImageOnDevice(ctx, req)
+ if err != nil {
+ logger.Errorw(ctx, "activate-image-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+
+ err = dMgr.validateDeviceImageResponse(resp)
+ if err != nil {
+ logger.Errorw(ctx, "activate-image-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+
+ ch <- resp.GetDeviceImageStates()
+ }(deviceID.GetId(), activateImageReq, respCh)
+
+ }
+
+ return dMgr.waitForAllResponses(ctx, "activate-image", respCh, len(request.GetDeviceId()))
+}
+
+func (dMgr *Manager) CommitImage(ctx context.Context, request *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
+ if err := dMgr.validateImageRequest(request); err != nil {
+ return nil, err
+ }
+
+ ctx = utils.WithRPCMetadataContext(ctx, "CommitImage")
+ respCh := make(chan []*voltha.DeviceImageState, len(request.GetDeviceId()))
+
+ for index, deviceID := range request.DeviceId {
+ // Create commit request per device
+ commitImageReq := &voltha.DeviceImageRequest{
+ Version: request.Version,
+ CommitOnSuccess: request.CommitOnSuccess,
+ }
+ //slice-out only single deviceID from the request
+ commitImageReq.DeviceId = request.DeviceId[index : index+1]
+
+ go func(deviceID string, req *voltha.DeviceImageRequest, ch chan []*voltha.DeviceImageState) {
+ agent := dMgr.getDeviceAgent(ctx, deviceID)
+ if agent == nil {
+ logger.Errorw(ctx, "Not-found", log.Fields{"device-id": deviceID})
+ ch <- nil
+ return
+ }
+
+ resp, err := agent.commitImage(ctx, req)
+ if err != nil {
+ logger.Errorw(ctx, "commit-image-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+
+ err = dMgr.validateDeviceImageResponse(resp)
+ if err != nil {
+ logger.Errorf(ctx, "commit-image-failed", log.Fields{"device-id": deviceID, "error": err})
+ ch <- nil
+ return
+ }
+ ch <- resp.GetDeviceImageStates()
+ }(deviceID.GetId(), commitImageReq, respCh)
+
+ }
+
+ return dMgr.waitForAllResponses(ctx, "commit-image", respCh, len(request.GetDeviceId()))
+}
+
+// convenience to avoid redefining
+var imageDownloadFailureResp = &voltha.ImageDownload{DownloadState: voltha.ImageDownload_DOWNLOAD_UNKNOWN}
+
+// GetImageDownloadStatus returns status of image download
+func (dMgr *Manager) GetImageDownloadStatus(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "GetImageDownloadStatus")
+ log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
+
+ logger.Debugw(ctx, "get-image-download-status", log.Fields{"device-id": img.Id, "image-name": img.Name})
+ agent := dMgr.getDeviceAgent(ctx, img.Id)
+ if agent == nil {
+ return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
+ }
+ resp, err := agent.getImageDownloadStatus(ctx, img)
+ if err != nil {
+ return imageDownloadFailureResp, err
+ }
+ return resp, nil
+}
+
+// GetImageDownload returns image download
+func (dMgr *Manager) GetImageDownload(ctx context.Context, img *voltha.ImageDownload) (*voltha.ImageDownload, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "GetImageDownload")
+ log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
+
+ logger.Debugw(ctx, "get-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
+ agent := dMgr.getDeviceAgent(ctx, img.Id)
+ if agent == nil {
+ return imageDownloadFailureResp, status.Errorf(codes.NotFound, "%s", img.Id)
+ }
+ resp, err := agent.getImageDownload(ctx, img)
+ if err != nil {
+ return imageDownloadFailureResp, err
+ }
+ return resp, nil
+}
+
+// ListImageDownloads returns image downloads
+func (dMgr *Manager) ListImageDownloads(ctx context.Context, id *voltha.ID) (*voltha.ImageDownloads, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ListImageDownloads")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "list-image-downloads", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+ resp, err := agent.listImageDownloads(ctx, id.Id)
+ if err != nil {
+ return &voltha.ImageDownloads{Items: []*voltha.ImageDownload{imageDownloadFailureResp}}, err
+ }
+ return resp, nil
+}
+
+// GetImages returns all images for a specific device entry
+func (dMgr *Manager) GetImages(ctx context.Context, id *voltha.ID) (*voltha.Images, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "GetImages")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "get-images", log.Fields{"device-id": id.Id})
+ device, err := dMgr.getDeviceReadOnly(ctx, id.Id)
+ if err != nil {
+ return nil, err
+ }
+ return device.Images, nil
+}
+
+// ListDevicePorts returns the ports details for a specific device entry
+func (dMgr *Manager) ListDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.Ports, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ListDevicePorts")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ logger.Debugw(ctx, "list-device-ports", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
+ }
+
+ ports := agent.listDevicePorts()
+ ctr, ret := 0, make([]*voltha.Port, len(ports))
+ for _, port := range ports {
+ ret[ctr] = port
+ ctr++
+ }
+ return &voltha.Ports{Items: ret}, nil
+}
+
+// ListDevicePmConfigs returns pm configs of device
+func (dMgr *Manager) ListDevicePmConfigs(ctx context.Context, id *voltha.ID) (*voltha.PmConfigs, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ListDevicePmConfigs")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", id.Id)
+ }
+ return agent.listPmConfigs(ctx)
+}
+
+// UpdateDevicePmConfigs updates the PM configs. This is executed when the northbound gRPC API is invoked, typically
+// following a user action
+func (dMgr *Manager) UpdateDevicePmConfigs(ctx context.Context, configs *voltha.PmConfigs) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "UpdateDevicePmConfigs")
+ log.EnrichSpan(ctx, log.Fields{"device-id": configs.Id})
+
+ if configs.Id == "" {
+ return nil, status.Error(codes.FailedPrecondition, "invalid-device-Id")
+ }
+ agent := dMgr.getDeviceAgent(ctx, configs.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", configs.Id)
+ }
+ return &empty.Empty{}, agent.updatePmConfigs(ctx, configs)
+}
+
+// ListDeviceFlows returns the flow details for a specific device entry
+func (dMgr *Manager) ListDeviceFlows(ctx context.Context, id *voltha.ID) (*ofp.Flows, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceFlows")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+ logger.Debugw(ctx, "list-device-flows", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
+ }
+
+ flows := agent.listDeviceFlows()
+ ctr, ret := 0, make([]*ofp.OfpFlowStats, len(flows))
+ for _, flow := range flows {
+ ret[ctr] = flow
+ ctr++
+ }
+ return &ofp.Flows{Items: ret}, nil
+}
+
+// ListDeviceFlowGroups returns the flow group details for a specific device entry
+func (dMgr *Manager) ListDeviceFlowGroups(ctx context.Context, id *voltha.ID) (*voltha.FlowGroups, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "ListDeviceFlowGroups")
+ log.EnrichSpan(ctx, log.Fields{"device-id": id.Id})
+ logger.Debugw(ctx, "list-device-flow-groups", log.Fields{"device-id": id.Id})
+ agent := dMgr.getDeviceAgent(ctx, id.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "device-%s", id.Id)
+ }
+ groups := agent.listDeviceGroups()
+ ctr, ret := 0, make([]*ofp.OfpGroupEntry, len(groups))
+ for _, group := range groups {
+ ret[ctr] = group
+ ctr++
+ }
+ return &voltha.FlowGroups{Items: ret}, nil
+}
+
+func (dMgr *Manager) EnablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "EnablePort")
+ log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
+
+ logger.Debugw(ctx, "enable-port", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
+ agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
+ }
+ return &empty.Empty{}, agent.enablePort(ctx, port.PortNo)
+}
+
+func (dMgr *Manager) DisablePort(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "DisablePort")
+ log.EnrichSpan(ctx, log.Fields{"device-id": port.DeviceId})
+
+ logger.Debugw(ctx, "disable-port", log.Fields{"device-id": port.DeviceId, "port-no": port.PortNo})
+ agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
+ }
+ return &empty.Empty{}, agent.disablePort(ctx, port.PortNo)
+}
+
+func (dMgr *Manager) GetExtValue(ctx context.Context, value *voltha.ValueSpecifier) (*voltha.ReturnValues, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "GetExtValue")
+ log.EnrichSpan(ctx, log.Fields{"device-id": value.Id})
+
+ logger.Debugw(ctx, "get-ext-value", log.Fields{"onu-id": value.Id})
+ cDevice, err := dMgr.getDeviceReadOnly(ctx, value.Id)
+ if err != nil {
+ return nil, status.Errorf(codes.Aborted, "%s", err.Error())
+ }
+ pDevice, err := dMgr.getDeviceReadOnly(ctx, cDevice.ParentId)
+ if err != nil {
+ return nil, status.Errorf(codes.Aborted, "%s", err.Error())
+ }
+ if agent := dMgr.getDeviceAgent(ctx, cDevice.ParentId); agent != nil {
+ resp, err := agent.getExtValue(ctx, pDevice, cDevice, value)
+ if err != nil {
+ return nil, err
+ }
+ logger.Debugw(ctx, "get-ext-value-result", log.Fields{"result": resp})
+ return resp, nil
+ }
+ return nil, status.Errorf(codes.NotFound, "%s", value.Id)
+
+}
+
+// SetExtValue set some given configs or value
+func (dMgr *Manager) SetExtValue(ctx context.Context, value *voltha.ValueSet) (*empty.Empty, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "SetExtValue")
+ logger.Debugw(ctx, "set-ext-value", log.Fields{"onu-id": value.Id})
+
+ device, err := dMgr.getDeviceReadOnly(ctx, value.Id)
+ if err != nil {
+ return nil, status.Errorf(codes.Aborted, "%s", err.Error())
+ }
+ if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
+ resp, err := agent.setExtValue(ctx, device, value)
+ if err != nil {
+ return nil, err
+ }
+ logger.Debugw(ctx, "set-ext-value-result", log.Fields{"result": resp})
+ return resp, nil
+ }
+ return nil, status.Errorf(codes.NotFound, "%s", value.Id)
+
+}
+
+func (dMgr *Manager) StartOmciTestAction(ctx context.Context, request *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "StartOmciTestAction")
+ log.EnrichSpan(ctx, log.Fields{"device-id": request.Id})
+
+ logger.Debugw(ctx, "start-omci-test-action", log.Fields{"device-id": request.Id, "uuid": request.Uuid})
+ agent := dMgr.getDeviceAgent(ctx, request.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", request.Id)
+ }
+ return agent.startOmciTest(ctx, request)
+}
+
+func (dMgr *Manager) SimulateAlarm(ctx context.Context, simulateReq *voltha.SimulateAlarmRequest) (*common.OperationResp, error) {
+ ctx = utils.WithRPCMetadataContext(ctx, "SimulateAlarm")
+
+ logger.Debugw(ctx, "simulate-alarm", log.Fields{"id": simulateReq.Id, "indicator": simulateReq.Indicator, "intf-id": simulateReq.IntfId,
+ "port-type-name": simulateReq.PortTypeName, "onu-device-id": simulateReq.OnuDeviceId, "inverse-bit-error-rate": simulateReq.InverseBitErrorRate,
+ "drift": simulateReq.Drift, "new-eqd": simulateReq.NewEqd, "onu-serial-number": simulateReq.OnuSerialNumber, "operation": simulateReq.Operation})
+ agent := dMgr.getDeviceAgent(ctx, simulateReq.Id)
+ if agent == nil {
+ return nil, status.Errorf(codes.NotFound, "%s", simulateReq.Id)
+ }
+ if err := agent.simulateAlarm(ctx, simulateReq); err != nil {
+ return nil, err
+ }
+ return &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}, nil
+}