blob: 0bfd82f6435130d522fea41f875354fc29ec5b4e [file] [log] [blame]
/*
* Copyright 2020-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 nbi holds rpc server apis implemented
package nbi
import (
"context"
"errors"
"fmt"
"github.com/jinzhu/copier"
"github.com/opencord/device-management-interface/go/dmi"
"github.com/opencord/opendevice-manager/pkg/config"
"github.com/opencord/voltha-lib-go/v4/pkg/log"
dev "github.com/opencord/opendevice-manager/pkg/models/device"
hw "github.com/opencord/opendevice-manager/pkg/models/hwcomponents"
empty "github.com/golang/protobuf/ptypes/empty"
)
// StartManagingDevice refers to the RPC method invoked for start Managing Device.
// Initializes context for a device and sets up required states
func (c *NativeHwManagementService) StartManagingDevice(req *dmi.ModifiableComponent, streamResp dmi.NativeHWManagementService_StartManagingDeviceServer) error {
ctx := config.GetNewContextFromGlobalContxt("StartManagingDevice")
logger.Infow(ctx, "StartManagingDevice-invoked-on-grpc-server", log.Fields{"req": req})
defer logger.Infow(ctx, "StartManagingDevice-on-grpc-server-completed", log.Fields{"req": req})
if errorResp, ok := validateStartManagingDeviceReq(ctx, req); !ok {
streamResp.Send(errorResp)
return errors.New("failed at validateStartManagingDeviceReq")
}
devRec, err := dev.NewDeviceRecord(ctx, req)
if err != nil {
streamResp.Send(errRespStartManagingDevice(ctx, req, dmi.StartManagingDeviceResponse_INVALID_PARAMS, err))
return err
}
adapter, err := connections.getConnection(ctx, devRec)
if adapter == nil {
streamResp.Send(errRespStartManagingDevice(ctx, req, dmi.StartManagingDeviceResponse_INVALID_PARAMS, err))
return err
}
devRec.DBAddByName(ctx)
err, connMade := adapter.StartManagingDevice(ctx, devRec, req, streamResp)
if !connMade {
devRec.DBDelRecord(ctx)
adapter.Disconnect(ctx)
connections.delConn(ctx, devRec.Name)
streamResp.Send(errRespStartManagingDevice(ctx, req, dmi.StartManagingDeviceResponse_UNDEFINED_REASON, err))
}
return err
}
// StopManagingDevice - Stops management of a device and clean up any context and caches for that device
// This rpc can be called at any time, even before the StartManagingDevice operation
// has completed, and should be able to cleanup.
func (c *NativeHwManagementService) StopManagingDevice(ctx context.Context, req *dmi.StopManagingDeviceRequest) (*dmi.StopManagingDeviceResponse, error) {
var devRec *dev.DeviceRecord
resp := new(dmi.StopManagingDeviceResponse)
var err error
ctx = config.GetNewContextFromContxt(ctx, "StopManagingDevice")
logger.Infow(ctx, "StopManagingDevice-invoked-on-grpc-server", log.Fields{"req": req})
defer logger.Infow(ctx, "StopManagingDevice-on-grpc-server-completed", log.Fields{"req": req})
if recTmp, err := dev.DBGetByName(ctx, req.Name); recTmp == nil {
return errRespStopManagingDevice(ctx, req, dmi.StopManagingDeviceResponse_UNKNOWN_DEVICE, err), err
} else {
devRec = recTmp
}
defer devRec.DBDelRecord(ctx)
defer hw.DBDelAllHwComponents(ctx, devRec.Uuid)
adapter, err := connections.getConnection(ctx, devRec)
if adapter != nil {
resp, err = adapter.StopManagingDevice(ctx, devRec, req)
adapter.Disconnect(ctx)
connections.delConn(ctx, devRec.Name)
}
if err != nil {
logger.Errorw(ctx, "Errors-at-StopManagingDevice", log.Fields{"req": req, "error": err})
}
return resp, err
}
// GetManagedDevices - Returns an object containing a list of devices managed by this entity
func (c *NativeHwManagementService) GetManagedDevices(ctx context.Context, req *empty.Empty) (*dmi.ManagedDevicesResponse, error) {
ctx = config.GetNewContextFromContxt(ctx, "GetManagedDevices")
resp := new(dmi.ManagedDevicesResponse)
logger.Infow(ctx, "GetManagedDevices-invoked-on-grpc-server", log.Fields{"req": req})
defer logger.Infow(ctx, "GetManagedDevices-on-grpc-server-completed", log.Fields{"req": req})
listDevRecs, err := dev.DBGetAll(ctx)
for _, devRec := range listDevRecs {
modComp := new(dmi.ModifiableComponent)
err2 := copier.Copy(&modComp, &devRec)
if err2 != nil {
logger.Errorw(ctx, "Copy-failed-at-GetManagedDevices", log.Fields{"req": req, "rec": devRec, "error": err})
} else {
modComp.Uri.Uri = devRec.Uri
resp.Devices = append(resp.Devices, modComp)
}
}
logger.Infow(ctx, "GetManagedDevices-completed", log.Fields{"req": req, "resp": resp, "error": err})
return resp, err
}
// GetPhysicalInventory - Place Holder for implementation in future
func (c *NativeHwManagementService) GetPhysicalInventory(req *dmi.PhysicalInventoryRequest, streamResp dmi.NativeHWManagementService_GetPhysicalInventoryServer) error {
ctx := config.GetNewContextFromGlobalContxt("GetPhysicalInventory")
logger.Infow(ctx, "GetPhysicalInventory-invoked-on-grpc-server", log.Fields{"req": req})
defer logger.Infow(ctx, "GetPhysicalInventory-on-grpc-server-completed", log.Fields{"req": req})
var devRec *dev.DeviceRecord
if recTmp, err := dev.DBGetByUuid(ctx, req.DeviceUuid.Uuid); recTmp == nil {
streamResp.Send(errRespGetPhysicatInventory(ctx, req, dmi.PhysicalInventoryResponse_UNKNOWN_DEVICE, err))
return err
} else {
devRec = recTmp
}
adapter, err := connections.getConnection(ctx, devRec)
if adapter == nil {
streamResp.Send(errRespGetPhysicatInventory(ctx, req, dmi.PhysicalInventoryResponse_DEVICE_UNREACHABLE, err))
return err
}
err = adapter.GetPhysicalInventory(ctx, devRec, req, streamResp)
if err != nil {
logger.Errorw(ctx, "Errors-at-GetPhysicalInventory", log.Fields{"req": req, "error": err})
}
return err
}
// GetHWComponentInfo - refers to the RPC method invoked for get the details of a particular HW component
func (c *NativeHwManagementService) GetHWComponentInfo(req *dmi.HWComponentInfoGetRequest, streamResp dmi.NativeHWManagementService_GetHWComponentInfoServer) error {
ctx := config.GetNewContextFromGlobalContxt("GetHWComponentInfo")
logger.Infow(ctx, "GetHWComponentInfo-invoked-on-grpc-server", log.Fields{"req": req})
defer logger.Infow(ctx, "GetHWComponentInfo-on-grpc-server-completed", log.Fields{"req": req})
devRec, err := dev.DBGetByUuid(ctx, req.DeviceUuid.Uuid)
if devRec == nil {
streamResp.Send(errRespGetHWComponentInfo(ctx, req, dmi.HWComponentInfoGetResponse_UNKNOWN_DEVICE, err))
return err
}
hwCompRec, err := hw.DBGetRecByUuid(ctx, req.DeviceUuid.Uuid, req.ComponentUuid.Uuid)
if hwCompRec == nil {
streamResp.Send(errRespGetHWComponentInfo(ctx, req, dmi.HWComponentInfoGetResponse_UNKNOWN_DEVICE, err))
return err
}
adapter, err := connections.getConnection(ctx, devRec)
if adapter == nil {
streamResp.Send(errRespGetHWComponentInfo(ctx, req, dmi.HWComponentInfoGetResponse_DEVICE_UNREACHABLE, err))
return err
}
err = adapter.GetHWComponentInfo(ctx, devRec.Uuid, hwCompRec, req, streamResp)
if err != nil {
logger.Errorw(ctx, "Errors-at-GetHWComponentInfo", log.Fields{"req": req, "error": err})
}
return err
}
// SetHWComponentInfo is the nb api exposed for receiving SetHWComponentInfo from NEM
func (c *NativeHwManagementService) SetHWComponentInfo(ctx context.Context, req *dmi.HWComponentInfoSetRequest) (*dmi.HWComponentInfoSetResponse, error) {
ctx = config.GetNewContextFromContxt(ctx, "SetHWComponentInfo")
logger.Infow(ctx, "SetHWComponentInfo-invoked-on-grpc-server", log.Fields{"req": req})
defer logger.Infow(ctx, "SetHWComponentInfo-on-grpc-server-completed", log.Fields{"req": req})
var devRec *dev.DeviceRecord
var hwCompRec *hw.HwCompRecord
var err error
if devRec, err = dev.DBGetByUuid(ctx, req.DeviceUuid.Uuid); devRec == nil {
return errRespSetHWComponentInfo(ctx, req, dmi.HWComponentInfoSetResponse_UNKNOWN_DEVICE, err), err
}
if hwCompRec, err = hw.DBGetRecByUuid(ctx, req.DeviceUuid.Uuid, req.ComponentUuid.Uuid); hwCompRec == nil {
return errRespSetHWComponentInfo(ctx, req, dmi.HWComponentInfoSetResponse_UNKNOWN_DEVICE, err), err
}
adapter, err := connections.getConnection(ctx, devRec)
if adapter == nil {
return errRespSetHWComponentInfo(ctx, req, dmi.HWComponentInfoSetResponse_DEVICE_UNREACHABLE, err), err
}
resp, err := adapter.SetHWComponentInfo(ctx, devRec.Uuid, hwCompRec, req)
if err != nil {
logger.Errorw(ctx, "Errors-at-SetHWComponentInfo", log.Fields{"req": req, "error": err})
}
return resp, err
}
// SetLoggingEndpoint - refers to the RPC method invoked for set the location to which logs need to be shipped
func (c *NativeHwManagementService) SetLoggingEndpoint(ctx context.Context, req *dmi.SetLoggingEndpointRequest) (*dmi.SetRemoteEndpointResponse, error) {
ctx = config.GetNewContextFromGlobalContxt("SetLoggingEndpoint")
logger.Infow(ctx, "SetLoggingEndpoint-invoked-on-grpc-server", log.Fields{"req": req})
defer logger.Infow(ctx, "SetLoggingEndpoint-on-grpc-server-completed", log.Fields{"req": req})
// Check device is there or not by Uuid
devRec, err := dev.DBGetByUuid(ctx, req.DeviceUuid.Uuid)
if err != nil {
return errRespSetLoggingEndpoint(ctx, req, dmi.SetRemoteEndpointResponse_UNKNOWN_DEVICE, err), err
}
adapter, err2 := connections.getConnection(ctx, devRec)
if adapter == nil {
return errRespSetLoggingEndpoint(ctx, req, dmi.SetRemoteEndpointResponse_DEVICE_UNREACHABLE, err2), err2
}
resp, err := adapter.SetLoggingEndpoint(ctx, devRec, req)
if err != nil {
logger.Errorw(ctx, "Errors-at-SetLoggingEndpoint", log.Fields{"req": req, "error": err})
}
return resp, err
}
// GetLoggingEndpoint - refers to the RPC method invoked for get the location to which logs need to be shipped
func (c *NativeHwManagementService) GetLoggingEndpoint(ctx context.Context, req *dmi.HardwareID) (*dmi.GetLoggingEndpointResponse, error) {
ctx = config.GetNewContextFromGlobalContxt("GetLoggingEndpoint")
logger.Infow(ctx, "GetLoggingEndpoint-invoked-on-grpc-server", log.Fields{"req": req})
defer logger.Infow(ctx, "GetLoggingEndpoint-on-grpc-server-completed", log.Fields{"req": req})
// Check device is there or not by Uuid
devRec, err := dev.DBGetByUuid(ctx, req.Uuid.Uuid)
if err != nil {
return errRespGetLoggingEndpoint(ctx, req, dmi.GetLoggingEndpointResponse_UNKNOWN_DEVICE, err), err
}
adapter, err := connections.getConnection(ctx, devRec)
if adapter == nil {
return errRespGetLoggingEndpoint(ctx, req, dmi.GetLoggingEndpointResponse_DEVICE_UNREACHABLE, err), err
}
resp, err := adapter.GetLoggingEndpoint(ctx, devRec, req)
if err != nil {
logger.Errorw(ctx, "Errors-at-GetLoggingEndpoint", log.Fields{"req": req, "error": err})
}
return resp, err
}
// SetMsgBusEndpoint - Place Holder for implementation in future
func (c *NativeHwManagementService) SetMsgBusEndpoint(ctx context.Context, req *dmi.SetMsgBusEndpointRequest) (*dmi.SetRemoteEndpointResponse, error) {
errMsg := "SetMsgBusEndpoint not yet implemented"
fmt.Println(errMsg)
return nil, errors.New(errMsg)
}
// GetMsgBusEndpoint - Place Holder for implementation in future
func (c *NativeHwManagementService) GetMsgBusEndpoint(ctx context.Context, req *empty.Empty) (*dmi.GetMsgBusEndpointResponse, error) {
errMsg := "GetMsgBusEndpoint not yet implemented"
fmt.Println(errMsg)
return nil, errors.New(errMsg)
}
// GetLoggableEntities refers to the grpc northbound interface exposed for getting loggable entities from device
func (c *NativeHwManagementService) GetLoggableEntities(ctx context.Context, req *dmi.GetLoggableEntitiesRequest) (*dmi.GetLogLevelResponse, error) {
ctx = config.GetNewContextFromContxt(ctx, "GetLoggableEntities")
resp := new(dmi.GetLogLevelResponse)
resp.DeviceUuid = req.DeviceUuid
logger.Infow(ctx, "GetLoggableEntities-invoked-on-grpc-server", log.Fields{"req": req})
defer logger.Infow(ctx, "GetLoggableEntities-on-grpc-server-completed", log.Fields{"req": req})
devRec, err := dev.DBGetByUuid(ctx, req.DeviceUuid.Uuid)
if err != nil {
return errRespGetLoggableEntities(ctx, req, dmi.GetLogLevelResponse_UNKNOWN_DEVICE, err), err
}
if devRec.Logging.LoggableEntities != nil {
resp.Status = dmi.Status_OK_STATUS
resp.LogLevels, _ = devRec.GetLoggableEntitiesFromDevRec(ctx, nil)
return resp, nil
}
adapter, err := connections.getConnection(ctx, devRec)
if adapter == nil {
return errRespGetLoggableEntities(ctx, req, dmi.GetLogLevelResponse_DEVICE_UNREACHABLE, err), err
}
return adapter.GetLoggableEntities(ctx, devRec, req)
}
// SetLogLevel refers to the grpc northbound interface exposed for setting log level for entities
func (c *NativeHwManagementService) SetLogLevel(ctx context.Context, req *dmi.SetLogLevelRequest) (*dmi.SetLogLevelResponse, error) {
ctx = config.GetNewContextFromContxt(ctx, "SetLogLevel")
resp := new(dmi.SetLogLevelResponse)
resp.DeviceUuid = req.DeviceUuid
logger.Infow(ctx, "SetLogLevel-invoked-on-grpc-server", log.Fields{"req": req})
defer logger.Infow(ctx, "SetLogLevel-on-grpc-server-completed", log.Fields{"req": req})
// validate request
if ok, err := isValidSetLogLevel(ctx, req.Loglevels); ok {
return errRespSetLogLevel(ctx, req, dmi.SetLogLevelResponse_UNKNOWN_LOG_ENTITY, err), err
}
devRec, err := dev.DBGetByUuid(ctx, req.DeviceUuid.Uuid)
if err != nil {
return errRespSetLogLevel(ctx, req, dmi.SetLogLevelResponse_UNKNOWN_DEVICE, err), err
}
adapter, err := connections.getConnection(ctx, devRec)
if adapter == nil {
return errRespSetLogLevel(ctx, req, dmi.SetLogLevelResponse_DEVICE_UNREACHABLE, err), err
}
return adapter.SetLogLevel(ctx, devRec, req)
}
// GetLogLevel refers to the grpc northbound interface exposed for getting log level of entities
func (c *NativeHwManagementService) GetLogLevel(ctx context.Context, req *dmi.GetLogLevelRequest) (*dmi.GetLogLevelResponse, error) {
ctx = config.GetNewContextFromContxt(ctx, "GetLogLevel")
resp := new(dmi.GetLogLevelResponse)
resp.DeviceUuid = req.DeviceUuid
logger.Infow(ctx, "GetLogLevel-invoked-on-grpc-server", log.Fields{"req": req})
defer logger.Infow(ctx, "GetLogLevel-on-grpc-server-completed", log.Fields{"req": req})
devRec, err := dev.DBGetByUuid(ctx, req.DeviceUuid.Uuid)
if err != nil {
return errRespGetLogLevel(ctx, req, dmi.GetLogLevelResponse_UNKNOWN_DEVICE, err), err
}
if devRec.Logging.LoggableEntities != nil {
if output, ok := devRec.GetLoggableEntitiesFromDevRec(ctx, req.Entities); ok {
resp.Status = dmi.Status_OK_STATUS
resp.LogLevels = output
return resp, nil
}
}
adapter, err := connections.getConnection(ctx, devRec)
if adapter == nil {
return errRespGetLogLevel(ctx, req, dmi.GetLogLevelResponse_DEVICE_UNREACHABLE, err), err
}
return adapter.GetLogLevel(ctx, devRec, req)
}