| /* |
| * Copyright 2018-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 dmiserver |
| |
| import ( |
| "context" |
| "fmt" |
| |
| "github.com/Shopify/sarama" |
| |
| "github.com/golang/protobuf/ptypes/empty" |
| "github.com/golang/protobuf/ptypes/timestamp" |
| "github.com/opencord/bbsim/internal/bbsim/devices" |
| "github.com/opencord/bbsim/internal/common" |
| dmi "github.com/opencord/device-management-interface/go/dmi" |
| |
| guuid "github.com/google/uuid" |
| "google.golang.org/grpc/codes" |
| "google.golang.org/grpc/status" |
| ) |
| |
| const ( |
| kafkaChannelSize = 100 |
| ) |
| |
| func getUUID(seed string) string { |
| return guuid.NewMD5(guuid.Nil, []byte(seed)).String() |
| } |
| |
| //StartManagingDevice establishes connection with the device and does checks to ascertain if the device with passed identity can be managed |
| func (dms *DmiAPIServer) StartManagingDevice(req *dmi.ModifiableComponent, stream dmi.NativeHWManagementService_StartManagingDeviceServer) error { |
| //Get serial number and generate the UUID based on this serial number. Store this UUID in local cache |
| logger.Debugf("StartManagingDevice() invoked with request %+v", req) |
| if req == nil { |
| return status.Errorf(codes.FailedPrecondition, "request is empty") |
| } |
| |
| if req.Name == "" { |
| return status.Errorf(codes.InvalidArgument, "'Name' can not be empty in the request") |
| } |
| |
| olt := devices.GetOLT() |
| |
| // Uri is the IP address |
| dms.ipAddress = req.GetUri().GetUri() |
| dms.deviceSerial = olt.SerialNumber |
| dms.deviceName = fmt.Sprintf("%s-%s", common.Config.Olt.Vendor, dms.deviceSerial) |
| |
| dms.uuid = getUUID(dms.deviceSerial) |
| |
| dms.ponTransceiverUuids = make([]string, olt.NumPon) |
| dms.ponTransceiverCageUuids = make([]string, olt.NumPon) |
| |
| // Start device metrics generator |
| dms.metricChannel = make(chan interface{}, kafkaChannelSize) |
| StartMetricGenerator(dms) |
| |
| // Start device event generator |
| dms.eventChannel = make(chan interface{}, kafkaChannelSize) |
| StartEventsGenerator(dms) |
| |
| var components []*dmi.Component |
| |
| // Create and store the component for transceivers and transceiver cages |
| for i := 0; i < olt.NumPon; i++ { |
| label := fmt.Sprintf("pon-%d", olt.Pons[i].ID) |
| dms.ponTransceiverUuids[i] = getUUID(dms.deviceSerial + label) |
| dms.ponTransceiverCageUuids[i] = getUUID(dms.deviceSerial + "cage" + label) |
| |
| transName := fmt.Sprintf("sfp-%d", i) |
| cageName := fmt.Sprintf("sfp-plus-transceiver-cage-pon-%d", i) |
| |
| trans := dmi.Component{ |
| Name: transName, |
| Class: dmi.ComponentType_COMPONENT_TYPE_TRANSCEIVER, |
| Description: "XGS-PON", |
| Uuid: &dmi.Uuid{ |
| Uuid: dms.ponTransceiverUuids[i], |
| }, |
| Parent: cageName, |
| } |
| |
| cage := dmi.Component{ |
| Name: cageName, |
| Class: dmi.ComponentType_COMPONENT_TYPE_CONTAINER, |
| Description: "cage", |
| Uuid: &dmi.Uuid{ |
| Uuid: dms.ponTransceiverCageUuids[i], |
| }, |
| Parent: dms.deviceName, |
| Children: []*dmi.Component{&trans}, |
| } |
| |
| components = append(components, &cage) |
| } |
| |
| // create the fans |
| numFans := 2 |
| fans := make([]*dmi.Component, numFans) |
| |
| for i := 0; i < numFans; i++ { |
| fans[i] = createFanComponent(i + 1) |
| } |
| components = append(components, fans...) |
| |
| // Create 1 disk, 1 processor, 1 ram, 1 temperature sensor and power supply unit |
| components = append(components, createDiskComponent(0)) |
| components = append(components, createProcessorComponent(0)) |
| components = append(components, createMemoryComponent(0)) |
| components = append(components, createInnerSurroundingTempComponentSensor(0)) |
| components = append(components, createPowerSupplyComponent(0)) |
| |
| // create the root component |
| dms.root = &dmi.Component{ |
| Name: dms.deviceName, |
| Class: 0, |
| Description: "", |
| Parent: "", |
| ParentRelPos: 0, |
| Children: components, |
| SerialNum: dms.deviceSerial, |
| MfgName: common.Config.Olt.Vendor, |
| IsFru: false, |
| Uri: &dmi.Uri{ |
| Uri: dms.ipAddress, |
| }, |
| Uuid: &dmi.Uuid{ |
| Uuid: dms.uuid, |
| }, |
| State: &dmi.ComponentState{}, |
| } |
| |
| logger.Debugf("Generated UUID for the uri %s is %s", dms.ipAddress, dms.uuid) |
| response := &dmi.StartManagingDeviceResponse{ |
| Status: dmi.Status_OK_STATUS, |
| DeviceUuid: &dmi.Uuid{ |
| Uuid: dms.uuid, |
| }, |
| } |
| |
| err := stream.Send(response) |
| if err != nil { |
| logger.Errorf("Error while sending response to client %v", err.Error()) |
| return status.Errorf(codes.Unknown, err.Error()) |
| } |
| |
| return nil |
| } |
| |
| func createFanComponent(fanIdx int) *dmi.Component { |
| fanName := fmt.Sprintf("Thermal/Fans/System Fan/%d", fanIdx) |
| fanSerial := fmt.Sprintf("bbsim-fan-serial-%d", fanIdx) |
| return &dmi.Component{ |
| Name: fanName, |
| Class: dmi.ComponentType_COMPONENT_TYPE_FAN, |
| Description: "bbsim-fan", |
| Parent: "", |
| ParentRelPos: 0, |
| SerialNum: fanSerial, |
| MfgName: "bbsim-fan", |
| IsFru: false, |
| Uuid: &dmi.Uuid{ |
| Uuid: getUUID(fanName), |
| }, |
| State: &dmi.ComponentState{}, |
| } |
| } |
| |
| func createProcessorComponent(cpuIdx int) *dmi.Component { |
| cpuName := fmt.Sprintf("Systems/1/Processors/%d", cpuIdx) |
| cpuSerial := fmt.Sprintf("bbsim-cpu-serial-%d", cpuIdx) |
| return &dmi.Component{ |
| Name: cpuName, |
| Class: dmi.ComponentType_COMPONENT_TYPE_CPU, |
| Description: "bbsim-cpu", |
| Parent: "", |
| ParentRelPos: 0, |
| SerialNum: cpuSerial, |
| MfgName: "bbsim-cpu", |
| IsFru: false, |
| Uuid: &dmi.Uuid{ |
| Uuid: getUUID(cpuName), |
| }, |
| State: &dmi.ComponentState{}, |
| } |
| } |
| |
| func createMemoryComponent(memIdx int) *dmi.Component { |
| memName := fmt.Sprintf("Systems/1/Memory/%d", memIdx) |
| memSerial := fmt.Sprintf("bbsim-ram-serial-%d", memIdx) |
| return &dmi.Component{ |
| Name: memName, |
| Class: dmi.ComponentType_COMPONENT_TYPE_MEMORY, |
| Description: "bbsim-ram", |
| Parent: "", |
| ParentRelPos: 0, |
| SerialNum: memSerial, |
| MfgName: "bbsim-ram", |
| IsFru: false, |
| Uuid: &dmi.Uuid{ |
| Uuid: getUUID(memName), |
| }, |
| State: &dmi.ComponentState{}, |
| } |
| } |
| |
| func createDiskComponent(diskIdx int) *dmi.Component { |
| diskName := fmt.Sprintf("Systems/1/Disk/%d", diskIdx) |
| diskSerial := fmt.Sprintf("bbsim-disk-serial-%d", diskIdx) |
| return &dmi.Component{ |
| Name: diskName, |
| Class: dmi.ComponentType_COMPONENT_TYPE_STORAGE, |
| Description: "bbsim-disk", |
| Parent: "", |
| ParentRelPos: 0, |
| SerialNum: diskSerial, |
| MfgName: "bbsim-disk", |
| IsFru: false, |
| Uuid: &dmi.Uuid{ |
| Uuid: getUUID(diskName), |
| }, |
| State: &dmi.ComponentState{}, |
| } |
| } |
| |
| func createInnerSurroundingTempComponentSensor(sensorIdx int) *dmi.Component { |
| sensorName := fmt.Sprintf("Systems/1/Sensor/%d", sensorIdx) |
| sensorSerial := fmt.Sprintf("bbsim-sensor-istemp-serial-%d", sensorIdx) |
| return &dmi.Component{ |
| Name: sensorName, |
| Class: dmi.ComponentType_COMPONENT_TYPE_SENSOR, |
| Description: "bbsim-istemp", |
| Parent: "", |
| ParentRelPos: 0, |
| SerialNum: sensorSerial, |
| MfgName: "bbsim-istemp", |
| IsFru: false, |
| Uuid: &dmi.Uuid{ |
| Uuid: getUUID(sensorName), |
| }, |
| State: &dmi.ComponentState{}, |
| } |
| } |
| |
| func createPowerSupplyComponent(psuIdx int) *dmi.Component { |
| psuName := fmt.Sprintf("Thermal/PSU/SystemPSU/%d", psuIdx) |
| psuSerial := fmt.Sprintf("bbsim-psu-serial-%d", psuIdx) |
| return &dmi.Component{ |
| Name: psuName, |
| Class: dmi.ComponentType_COMPONENT_TYPE_POWER_SUPPLY, |
| Description: "bbsim-psu", |
| Parent: "", |
| ParentRelPos: 0, |
| SerialNum: psuSerial, |
| MfgName: "bbsim-psu", |
| IsFru: false, |
| Uuid: &dmi.Uuid{ |
| Uuid: getUUID(psuName), |
| }, |
| State: &dmi.ComponentState{}, |
| } |
| } |
| |
| //StopManagingDevice stops management of a device and cleans up any context and caches for that device |
| func (dms *DmiAPIServer) StopManagingDevice(ctx context.Context, req *dmi.StopManagingDeviceRequest) (*dmi.StopManagingDeviceResponse, error) { |
| logger.Debugf("StopManagingDevice API invoked") |
| if req == nil { |
| return &dmi.StopManagingDeviceResponse{Status: dmi.Status_ERROR_STATUS, Reason: dmi.StopManagingDeviceResponse_UNDEFINED_REASON}, status.Errorf(codes.FailedPrecondition, "request is empty") |
| } |
| |
| if req.Name == "" { |
| return &dmi.StopManagingDeviceResponse{Status: dmi.Status_ERROR_STATUS, Reason: dmi.StopManagingDeviceResponse_UNKNOWN_DEVICE}, |
| status.Errorf(codes.InvalidArgument, "'Name' can not be empty in the request") |
| } |
| |
| // Stop the components/go routines created |
| StopMetricGenerator() |
| |
| if dms.mPublisherCancelFunc != nil { |
| dms.mPublisherCancelFunc() |
| } |
| |
| dms.deviceName = "" |
| dms.kafkaEndpoint = "" |
| dms.ipAddress = "" |
| dms.deviceSerial = "" |
| dms.ponTransceiverUuids = nil |
| dms.ponTransceiverCageUuids = nil |
| dms.uuid = "" |
| dms.root = nil |
| dms.metricChannel = nil |
| |
| logger.Infof("Stopped managing the device") |
| return &dmi.StopManagingDeviceResponse{Status: dmi.Status_OK_STATUS}, nil |
| } |
| |
| //GetPhysicalInventory gets the HW inventory details of the Device |
| func (dms *DmiAPIServer) GetPhysicalInventory(req *dmi.PhysicalInventoryRequest, stream dmi.NativeHWManagementService_GetPhysicalInventoryServer) error { |
| if req == nil || req.DeviceUuid == nil || req.DeviceUuid.Uuid == "" { |
| return status.Errorf(codes.InvalidArgument, "device-UUID missing in the request") |
| } |
| |
| // Function to send the response back on the stream |
| sendResponseBackOnStream := func(stream dmi.NativeHWManagementService_GetPhysicalInventoryServer, msg *dmi.PhysicalInventoryResponse) error { |
| err := stream.Send(msg) |
| if err != nil { |
| logger.Errorf("Error sending response to client, error: %v", err) |
| return status.Errorf(codes.Internal, "Error sending response to client "+err.Error()) |
| } |
| return nil |
| } |
| |
| if req.DeviceUuid.Uuid != dms.uuid { |
| logger.Errorf("Requested uuid =%s, uuid of existing device = %s", req.DeviceUuid.Uuid, dms.uuid) |
| // Wrong uuid, return error |
| errResponse := &dmi.PhysicalInventoryResponse{ |
| Status: dmi.Status_ERROR_STATUS, |
| Reason: dmi.PhysicalInventoryResponse_UNKNOWN_DEVICE, |
| Inventory: &dmi.Hardware{}, |
| } |
| |
| return sendResponseBackOnStream(stream, errResponse) |
| } |
| |
| response := &dmi.PhysicalInventoryResponse{ |
| Status: dmi.Status_OK_STATUS, |
| Inventory: &dmi.Hardware{ |
| LastChange: ×tamp.Timestamp{ |
| Seconds: 0, |
| Nanos: 0, |
| }, |
| Root: dms.root, |
| }, |
| } |
| return sendResponseBackOnStream(stream, response) |
| } |
| |
| //Contains tells whether arr contains element. |
| func Contains(arr []string, element string) bool { |
| for _, item := range arr { |
| if element == item { |
| return true |
| } |
| } |
| return false |
| } |
| |
| func findComponent(l []*dmi.Component, compUUID string) *dmi.Component { |
| var foundComp *dmi.Component |
| |
| for _, comp := range l { |
| logger.Debugf("findComponent slice comp = %v compUUID = %s", comp, compUUID) |
| if comp.Uuid.Uuid == compUUID { |
| return comp |
| } |
| |
| foundComp = findComponent(comp.GetChildren(), compUUID) |
| if foundComp != nil { |
| return foundComp |
| } |
| } |
| |
| return nil |
| } |
| |
| func findComponentsOfType(l []*dmi.Component, compType dmi.ComponentType) []*dmi.Component { |
| var comps []*dmi.Component |
| findComponents(l, compType, &comps) |
| return comps |
| } |
| |
| func findComponents(l []*dmi.Component, compType dmi.ComponentType, collector *[]*dmi.Component) { |
| |
| for _, comp := range l { |
| if comp.Class == compType { |
| *collector = append(*collector, comp) |
| //logger.Debugf("Added collector = %v", *collector) |
| } |
| |
| findComponents(comp.GetChildren(), compType, collector) |
| } |
| } |
| |
| func sendGetHWComponentResponse(c *dmi.Component, stream dmi.NativeHWManagementService_GetHWComponentInfoServer) error { |
| apiStatus := dmi.Status_OK_STATUS |
| reason := dmi.HWComponentInfoGetResponse_UNDEFINED_REASON |
| |
| if c == nil { |
| apiStatus = dmi.Status_ERROR_STATUS |
| reason = dmi.HWComponentInfoGetResponse_UNKNOWN_DEVICE |
| } |
| |
| response := &dmi.HWComponentInfoGetResponse{ |
| Status: apiStatus, |
| Reason: reason, |
| Component: c, |
| } |
| |
| err := stream.Send(response) |
| if err != nil { |
| logger.Errorf("Error sending response to client, error: %v", err) |
| return status.Errorf(codes.Internal, "Error sending response to client "+err.Error()) |
| } |
| return nil |
| } |
| |
| //GetHWComponentInfo gets the details of a particular HW component |
| func (dms *DmiAPIServer) GetHWComponentInfo(req *dmi.HWComponentInfoGetRequest, stream dmi.NativeHWManagementService_GetHWComponentInfoServer) error { |
| logger.Debugf("GetHWComponentInfo() invoked with request %+v", req) |
| |
| if req == nil { |
| return status.Errorf(codes.FailedPrecondition, "can not entertain nil request") |
| } |
| if stream == nil { |
| logger.Errorf("stream to send is nil, not sending response from gRPC server ") |
| return status.Errorf(codes.Internal, "stream to send is nil, can not send response from gRPC server") |
| } |
| |
| //if component list is empty, return error |
| if dms.root == nil { |
| logger.Errorf("Error occurred, device is not managed") |
| return status.Errorf(codes.Internal, "Error occurred, device is not managed, please start managing device") |
| } |
| // Search for the component and return it |
| c := findComponent(dms.root.Children, req.ComponentUuid.Uuid) |
| |
| return sendGetHWComponentResponse(c, stream) |
| } |
| |
| //SetHWComponentInfo sets the permissible attributes of a HW component |
| func (dms *DmiAPIServer) SetHWComponentInfo(context.Context, *dmi.HWComponentInfoSetRequest) (*dmi.HWComponentInfoSetResponse, error) { |
| return nil, status.Errorf(codes.Unimplemented, "rpc SetHWComponentInfo not implemented") |
| } |
| |
| //SetLoggingEndpoint sets the location to which logs need to be shipped |
| func (dms *DmiAPIServer) SetLoggingEndpoint(_ context.Context, request *dmi.SetLoggingEndpointRequest) (*dmi.SetRemoteEndpointResponse, error) { |
| logger.Debugf("SetLoggingEndpoint called with request %+v", request) |
| errRetFunc := func(stat dmi.Status, reason dmi.SetRemoteEndpointResponse_Reason) (*dmi.SetRemoteEndpointResponse, error) { |
| return &dmi.SetRemoteEndpointResponse{ |
| Status: stat, |
| Reason: reason, |
| }, status.Errorf(codes.InvalidArgument, "invalid request") |
| } |
| |
| //check the validity of the request |
| if request == nil { |
| return errRetFunc(dmi.Status_ERROR_STATUS, dmi.SetRemoteEndpointResponse_UNKNOWN_DEVICE) |
| } |
| if request.LoggingEndpoint == "" { |
| return errRetFunc(dmi.Status_ERROR_STATUS, dmi.SetRemoteEndpointResponse_LOGGING_ENDPOINT_ERROR) |
| } |
| if request.LoggingProtocol == "" { |
| return errRetFunc(dmi.Status_ERROR_STATUS, dmi.SetRemoteEndpointResponse_LOGGING_ENDPOINT_PROTOCOL_ERROR) |
| } |
| if request.DeviceUuid == nil || request.DeviceUuid.Uuid != dms.uuid { |
| return errRetFunc(dmi.Status_ERROR_STATUS, dmi.SetRemoteEndpointResponse_UNKNOWN_DEVICE) |
| } |
| |
| dms.loggingEndpoint = request.LoggingEndpoint |
| dms.loggingProtocol = request.LoggingProtocol |
| |
| return &dmi.SetRemoteEndpointResponse{ |
| Status: dmi.Status_OK_STATUS, |
| }, nil |
| } |
| |
| //GetLoggingEndpoint gets the configured location to which the logs are being shipped |
| func (dms *DmiAPIServer) GetLoggingEndpoint(_ context.Context, request *dmi.HardwareID) (*dmi.GetLoggingEndpointResponse, error) { |
| logger.Debugf("GetLoggingEndpoint called with request %+v", request) |
| if request == nil || request.Uuid == nil || request.Uuid.Uuid == "" { |
| return &dmi.GetLoggingEndpointResponse{ |
| Status: dmi.Status_ERROR_STATUS, |
| Reason: dmi.GetLoggingEndpointResponse_UNKNOWN_DEVICE, |
| }, status.Errorf(codes.InvalidArgument, "invalid request") |
| } |
| if request.Uuid.Uuid != dms.uuid { |
| return &dmi.GetLoggingEndpointResponse{ |
| Status: dmi.Status_ERROR_STATUS, |
| Reason: dmi.GetLoggingEndpointResponse_UNKNOWN_DEVICE, |
| }, nil |
| } |
| |
| return &dmi.GetLoggingEndpointResponse{ |
| Status: dmi.Status_OK_STATUS, |
| LoggingEndpoint: dms.loggingEndpoint, |
| LoggingProtocol: dms.loggingProtocol, |
| }, nil |
| } |
| |
| //SetMsgBusEndpoint sets the location of the Message Bus to which events and metrics are shipped |
| func (dms *DmiAPIServer) SetMsgBusEndpoint(ctx context.Context, request *dmi.SetMsgBusEndpointRequest) (*dmi.SetRemoteEndpointResponse, error) { |
| logger.Debugf("SetMsgBusEndpoint() invoked with request: %+v and context: %v", request, ctx) |
| if request == nil || request.MsgbusEndpoint == "" { |
| return &dmi.SetRemoteEndpointResponse{Status: dmi.Status_ERROR_STATUS, Reason: dmi.SetRemoteEndpointResponse_MSGBUS_ENDPOINT_ERROR}, |
| status.Errorf(codes.FailedPrecondition, "request is nil") |
| } |
| olt := devices.GetOLT() |
| dms.kafkaEndpoint = request.MsgbusEndpoint |
| |
| // close the old publisher |
| if dms.mPublisherCancelFunc != nil { |
| dms.mPublisherCancelFunc() |
| } |
| |
| // initialize a new publisher |
| var nCtx context.Context |
| nCtx, dms.mPublisherCancelFunc = context.WithCancel(context.Background()) |
| // initialize a publisher |
| if err := InitializeDMKafkaPublishers(sarama.NewAsyncProducer, olt.ID, dms.kafkaEndpoint); err == nil { |
| // start a go routine which will read from channel and publish on kafka topic dm.metrics |
| go DMKafkaPublisher(nCtx, dms.metricChannel, "dm.metrics") |
| // start a go routine which will read from channel and publish on kafka topic dm.events |
| go DMKafkaPublisher(nCtx, dms.eventChannel, "dm.events") |
| } else { |
| logger.Errorf("Failed to start metric kafka publisher: %v", err) |
| return &dmi.SetRemoteEndpointResponse{Status: dmi.Status_ERROR_STATUS, Reason: dmi.SetRemoteEndpointResponse_MSGBUS_ENDPOINT_ERROR}, err |
| } |
| |
| return &dmi.SetRemoteEndpointResponse{Status: dmi.Status_OK_STATUS, Reason: dmi.SetRemoteEndpointResponse_UNDEFINED_REASON}, nil |
| } |
| |
| //GetMsgBusEndpoint gets the configured location to which the events and metrics are being shipped |
| func (dms *DmiAPIServer) GetMsgBusEndpoint(context.Context, *empty.Empty) (*dmi.GetMsgBusEndpointResponse, error) { |
| logger.Debugf("GetMsgBusEndpoint() invoked") |
| if dms.kafkaEndpoint != "" { |
| return &dmi.GetMsgBusEndpointResponse{ |
| Status: dmi.Status_OK_STATUS, |
| Reason: dmi.GetMsgBusEndpointResponse_UNDEFINED_REASON, |
| MsgbusEndpoint: dms.kafkaEndpoint, |
| }, nil |
| } |
| return &dmi.GetMsgBusEndpointResponse{ |
| Status: dmi.Status_ERROR_STATUS, |
| Reason: dmi.GetMsgBusEndpointResponse_INTERNAL_ERROR, |
| MsgbusEndpoint: "", |
| }, nil |
| } |
| |
| //GetManagedDevices returns an object containing a list of devices managed by this entity |
| func (dms *DmiAPIServer) GetManagedDevices(context.Context, *empty.Empty) (*dmi.ManagedDevicesResponse, error) { |
| retResponse := dmi.ManagedDevicesResponse{} |
| //If our uuid is empty, we return empty list; else we fill details and return |
| if dms.uuid != "" { |
| root := dmi.ModifiableComponent{ |
| Name: dms.deviceName, |
| Uri: &dmi.Uri{ |
| Uri: dms.ipAddress, |
| }, |
| } |
| |
| retResponse.Devices = append(retResponse.Devices, &root) |
| } |
| |
| return &retResponse, nil |
| } |
| |
| //GetLogLevel Gets the configured log level for a certain entity on a certain device. |
| func (dms *DmiAPIServer) GetLogLevel(context.Context, *dmi.GetLogLevelRequest) (*dmi.GetLogLevelResponse, error) { |
| return &dmi.GetLogLevelResponse{ |
| Status: dmi.Status_OK_STATUS, |
| DeviceUuid: &dmi.Uuid{ |
| Uuid: dms.uuid, |
| }, |
| LogLevels: []*dmi.EntitiesLogLevel{}, |
| }, nil |
| } |
| |
| // SetLogLevel Sets the log level of the device, for each given entity to a certain level. |
| func (dms *DmiAPIServer) SetLogLevel(context.Context, *dmi.SetLogLevelRequest) (*dmi.SetLogLevelResponse, error) { |
| return &dmi.SetLogLevelResponse{ |
| Status: dmi.Status_OK_STATUS, |
| DeviceUuid: &dmi.Uuid{ |
| Uuid: dms.uuid, |
| }, |
| }, nil |
| } |
| |
| // GetLoggableEntities Gets the entities of a device on which log can be configured. |
| func (dms *DmiAPIServer) GetLoggableEntities(context.Context, *dmi.GetLoggableEntitiesRequest) (*dmi.GetLogLevelResponse, error) { |
| return &dmi.GetLogLevelResponse{ |
| Status: dmi.Status_OK_STATUS, |
| DeviceUuid: &dmi.Uuid{ |
| Uuid: dms.uuid, |
| }, |
| LogLevels: []*dmi.EntitiesLogLevel{}, |
| }, nil |
| } |