[VOL-3695]: Support to create some of the OLT device events over the Device Management Interface
1. Following events and its corresponding recovered event creation is supported :
EVENT_FAN_FAILURE
EVENT_PSU_FAILURE
EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL
2. Following DMI Native Events Management Service APIs are implemented:
ListEvents
UpdateEventsConfiguration
3. Updated docs/source/DMI_Server_README.md
Change-Id: Ibc48302b61fd52a2f83bd888731f611eaf6c4c37
diff --git a/internal/bbsim/dmiserver/dmi_api_server.go b/internal/bbsim/dmiserver/dmi_api_server.go
index f64f801..272f3c9 100755
--- a/internal/bbsim/dmiserver/dmi_api_server.go
+++ b/internal/bbsim/dmiserver/dmi_api_server.go
@@ -20,6 +20,7 @@
"context"
"net"
+ "github.com/opencord/bbsim/api/bbsim"
"github.com/opencord/bbsim/internal/common"
dmi "github.com/opencord/device-management-interface/go/dmi"
log "github.com/sirupsen/logrus"
@@ -42,6 +43,7 @@
ponTransceiverCageUuids []string
root *dmi.Component
metricChannel chan interface{}
+ eventChannel chan interface{}
kafkaEndpoint string
mPublisherCancelFunc context.CancelFunc
}
@@ -69,6 +71,7 @@
dmi.RegisterNativeSoftwareManagementServiceServer(grpcServer, dms)
dmi.RegisterNativeEventsManagementServiceServer(grpcServer, dms)
dmi.RegisterNativeMetricsManagementServiceServer(grpcServer, dms)
+ bbsim.RegisterBBsimDmiServer(grpcServer, dms)
reflection.Register(grpcServer)
diff --git a/internal/bbsim/dmiserver/dmi_event_generator.go b/internal/bbsim/dmiserver/dmi_event_generator.go
new file mode 100644
index 0000000..b25cb59
--- /dev/null
+++ b/internal/bbsim/dmiserver/dmi_event_generator.go
@@ -0,0 +1,254 @@
+/*
+ * 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"
+ "sync"
+
+ "github.com/golang/protobuf/ptypes"
+ "github.com/opencord/bbsim/api/bbsim"
+ "github.com/opencord/device-management-interface/go/dmi"
+ log "github.com/sirupsen/logrus"
+ "google.golang.org/grpc/codes"
+)
+
+//DmiEventsGenerator has the attributes for generating events
+type DmiEventsGenerator struct {
+ apiSrv *DmiAPIServer
+ configuredEvents map[dmi.EventIds]dmi.EventCfg
+ access sync.Mutex
+}
+
+// func to generate the different types of events, there are two types one with thresholds and one without
+type eventGenerationFunc func(dmi.EventIds, dmi.ComponentType)
+
+// eventGenerationUtil contains the component and the func for a specific eventId
+type eventGenerationUtil struct {
+ componentType dmi.ComponentType
+ genFunc eventGenerationFunc
+}
+
+var dmiEG DmiEventsGenerator
+var eventGenMap map[dmi.EventIds]eventGenerationUtil
+
+func init() {
+ eventGenMap = make(map[dmi.EventIds]eventGenerationUtil)
+ eventGenMap[dmi.EventIds_EVENT_FAN_FAILURE] = eventGenerationUtil{
+ componentType: dmi.ComponentType_COMPONENT_TYPE_FAN,
+ genFunc: noThresholdEventGenerationFunc,
+ }
+ eventGenMap[dmi.EventIds_EVENT_FAN_FAILURE_RECOVERED] = eventGenerationUtil{
+ componentType: dmi.ComponentType_COMPONENT_TYPE_FAN,
+ genFunc: noThresholdEventGenerationFunc,
+ }
+
+ eventGenMap[dmi.EventIds_EVENT_PSU_FAILURE] = eventGenerationUtil{
+ componentType: dmi.ComponentType_COMPONENT_TYPE_POWER_SUPPLY,
+ genFunc: noThresholdEventGenerationFunc,
+ }
+ eventGenMap[dmi.EventIds_EVENT_PSU_FAILURE_RECOVERED] = eventGenerationUtil{
+ componentType: dmi.ComponentType_COMPONENT_TYPE_POWER_SUPPLY,
+ genFunc: noThresholdEventGenerationFunc,
+ }
+
+ eventGenMap[dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL] = eventGenerationUtil{
+ componentType: dmi.ComponentType_COMPONENT_TYPE_SENSOR,
+ genFunc: thresholdEventGenerationFunc,
+ }
+ eventGenMap[dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL_RECOVERED] = eventGenerationUtil{
+ componentType: dmi.ComponentType_COMPONENT_TYPE_SENSOR,
+ genFunc: thresholdEventGenerationFunc,
+ }
+}
+
+//StartEventsGenerator initializes the event generator
+func StartEventsGenerator(apiSrv *DmiAPIServer) {
+ log.Debugf("StartEventsGenerator invoked")
+
+ dmiEG = DmiEventsGenerator{
+ apiSrv: apiSrv,
+ }
+ dmiEG.configuredEvents = make(map[dmi.EventIds]dmi.EventCfg)
+
+ // Add Fan Failure event configuration
+ dmiEG.configuredEvents[dmi.EventIds_EVENT_FAN_FAILURE] = dmi.EventCfg{
+ EventId: dmi.EventIds_EVENT_FAN_FAILURE,
+ IsConfigured: true,
+ }
+
+ // Add hardware device temp above critical event configuration
+ dmiEG.configuredEvents[dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL] = dmi.EventCfg{
+ EventId: dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL,
+ IsConfigured: true,
+ Thresholds: &dmi.Thresholds{
+ Threshold: &dmi.Thresholds_Upper{Upper: &dmi.WaterMarks{
+ High: &dmi.ValueType{
+ Val: &dmi.ValueType_IntVal{IntVal: 95},
+ },
+ Low: &dmi.ValueType{
+ Val: &dmi.ValueType_IntVal{IntVal: 90},
+ },
+ }},
+ },
+ }
+
+ // Add Power Supply Unit failure event configuration
+ dmiEG.configuredEvents[dmi.EventIds_EVENT_PSU_FAILURE] = dmi.EventCfg{
+ EventId: dmi.EventIds_EVENT_PSU_FAILURE,
+ IsConfigured: true,
+ }
+}
+
+// get the events list
+func getEventsList() []*dmi.EventCfg {
+ events := make(map[dmi.EventIds]dmi.EventCfg)
+ dmiEG.access.Lock()
+
+ for key, value := range dmiEG.configuredEvents {
+ events[key] = value
+ }
+
+ dmiEG.access.Unlock()
+
+ var toRet []*dmi.EventCfg
+ for _, v := range events {
+ eventConfig := v
+ toRet = append(toRet, &eventConfig)
+ }
+ logger.Debugf("Events list supported by device %+v", toRet)
+ return toRet
+}
+
+//UpdateEventConfig Adds/Updates the passed event configuration
+func UpdateEventConfig(newEventCfg *dmi.EventCfg) {
+ dmiEG.access.Lock()
+ dmiEG.configuredEvents[newEventCfg.GetEventId()] = *newEventCfg
+ dmiEG.access.Unlock()
+ logger.Infof("Events updated %v", newEventCfg)
+}
+
+// update Event MetaData
+func updateEventMetaData(c *dmi.Component, apiSrv *DmiAPIServer, evt *dmi.Event) *dmi.Event {
+ evt.EventMetadata = &dmi.EventMetaData{
+ DeviceUuid: &dmi.Uuid{
+ Uuid: apiSrv.uuid,
+ },
+ ComponentUuid: c.Uuid,
+ ComponentName: c.Name,
+ }
+ return evt
+}
+
+func sendOutEventOnKafka(event interface{}, apiSrv *DmiAPIServer) {
+ select {
+ case apiSrv.eventChannel <- event:
+ default:
+ logger.Debugf("Channel not ready dropping event")
+ }
+}
+
+func noThresholdEventGenerationFunc(eventID dmi.EventIds, cType dmi.ComponentType) {
+ for _, comp := range findComponentsOfType(dmiEG.apiSrv.root.Children, cType) {
+ var evnt dmi.Event
+ evnt.EventId = eventID
+ evnt = *updateEventMetaData(comp, dmiEG.apiSrv, &evnt)
+ evnt.RaisedTs = ptypes.TimestampNow()
+ logger.Debugf("Got a No Threshold event %+v", evnt)
+ sendOutEventOnKafka(evnt, dmiEG.apiSrv)
+ break
+ }
+}
+
+func thresholdEventGenerationFunc(eventID dmi.EventIds, cType dmi.ComponentType) {
+ eventGenerated := false
+ for _, comp := range findComponentsOfType(dmiEG.apiSrv.root.Children, cType) {
+ var evnt dmi.Event
+ evnt.EventId = eventID
+ evnt = *updateEventMetaData(comp, dmiEG.apiSrv, &evnt)
+ evnt.RaisedTs = ptypes.TimestampNow()
+ configuredEvents := make(map[dmi.EventIds]dmi.EventCfg)
+
+ dmiEG.access.Lock()
+ for key, value := range dmiEG.configuredEvents {
+ configuredEvents[key] = value
+ }
+ dmiEG.access.Unlock()
+
+ for k, v := range configuredEvents {
+ if k == eventID {
+ evnt.ThresholdInfo = &dmi.ThresholdInformation{
+ ObservedValue: &dmi.ValueType{
+ Val: &dmi.ValueType_IntVal{IntVal: int64(generateRand(int32(v.Thresholds.GetUpper().GetLow().GetIntVal()), int32(v.Thresholds.GetUpper().GetHigh().GetIntVal())))},
+ },
+ Thresholds: v.GetThresholds(),
+ }
+ }
+ }
+
+ logger.Debugf("Got Threshold event %v", evnt)
+ sendOutEventOnKafka(evnt, dmiEG.apiSrv)
+ eventGenerated = true
+ if eventGenerated {
+ break
+ }
+
+ }
+}
+
+// CreateEvent creates and the passed event if it's valid and sends it to the msg bus
+func (das *DmiAPIServer) CreateEvent(ctx context.Context, evt *bbsim.DmiEvent) (*bbsim.DmiCreateEventResponse, error) {
+ retFunc := func(code codes.Code, msg string) (*bbsim.DmiCreateEventResponse, error) {
+ res := &bbsim.DmiCreateEventResponse{}
+ res.StatusCode = int32(code)
+ res.Message = msg
+ return res, nil
+ }
+
+ if dmiEG.apiSrv == nil || dmiEG.apiSrv.root == nil || dmiEG.apiSrv.root.Children == nil {
+ // inventory might not yet be created
+ return retFunc(codes.Internal, "inventory do no exist")
+ }
+
+ eventID, exists := dmi.EventIds_value[evt.EventName]
+ if !exists {
+ return retFunc(codes.NotFound,
+ fmt.Sprintf("DMI Alarm not supported. Permissible values are %s", getValidEventNames()))
+ }
+
+ genUtil, exists := eventGenMap[dmi.EventIds(eventID)]
+ if !exists {
+ return retFunc(codes.Unimplemented, "Generation of this event not yet implemented")
+ }
+
+ genUtil.genFunc(dmi.EventIds(eventID), genUtil.componentType)
+
+ return retFunc(codes.OK, "DMI Event Indication Sent.")
+
+}
+
+func getValidEventNames() string {
+ s := ""
+ //keys := make([]string, len(dmi.EventIds_value)-1)
+ for k, v := range dmi.EventIds_value {
+ if v != 0 {
+ s = s + "\n" + k
+ }
+ }
+ return s
+}
diff --git a/internal/bbsim/dmiserver/dmi_events_mgmt.go b/internal/bbsim/dmiserver/dmi_events_mgmt.go
index 3fc3416..da1e8ae 100755
--- a/internal/bbsim/dmiserver/dmi_events_mgmt.go
+++ b/internal/bbsim/dmiserver/dmi_events_mgmt.go
@@ -18,6 +18,8 @@
import (
"context"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
dmi "github.com/opencord/device-management-interface/go/dmi"
)
@@ -25,11 +27,10 @@
//ListEvents lists the supported events for the passed device
func (dms *DmiAPIServer) ListEvents(ctx context.Context, req *dmi.HardwareID) (*dmi.ListEventsResponse, error) {
logger.Debugf("ListEvents called with request %+v", req)
- //empty events
- events := []*dmi.EventCfg{{}}
+ events := getEventsList()
+
return &dmi.ListEventsResponse{
Status: dmi.Status_OK_STATUS,
- Reason: dmi.Reason_UNDEFINED_REASON,
Events: &dmi.EventsCfg{
Items: events,
},
@@ -39,6 +40,31 @@
//UpdateEventsConfiguration updates the configuration of the list of events in the request
func (dms *DmiAPIServer) UpdateEventsConfiguration(ctx context.Context, req *dmi.EventsConfigurationRequest) (*dmi.EventsConfigurationResponse, error) {
logger.Debugf("UpdateEventsConfiguration called with request %+v", req)
+
+ if req == nil || req.Operation == nil {
+ return &dmi.EventsConfigurationResponse{
+ Status: dmi.Status_ERROR_STATUS,
+ //TODO reason must be INVALID_PARAMS, currently this is not available in Device Management interface (DMI),
+ // change below reason with type INVALID_PARAMS once DMI is updated
+ Reason: dmi.Reason_UNDEFINED_REASON,
+ }, status.Errorf(codes.FailedPrecondition, "request is nil")
+ }
+
+ switch x := req.Operation.(type) {
+ case *dmi.EventsConfigurationRequest_Changes:
+ for _, eventConfig := range x.Changes.Items {
+ UpdateEventConfig(eventConfig)
+ }
+ case *dmi.EventsConfigurationRequest_ResetToDefault:
+ logger.Debugf("To be implemented later")
+ case nil:
+ // The field is not set.
+ logger.Debugf("Update request operation type is nil")
+ return &dmi.EventsConfigurationResponse{
+ Status: dmi.Status_UNDEFINED_STATUS,
+ }, nil
+ }
+
return &dmi.EventsConfigurationResponse{
Status: dmi.Status_OK_STATUS,
}, nil
diff --git a/internal/bbsim/dmiserver/dmi_hw_mgmt.go b/internal/bbsim/dmiserver/dmi_hw_mgmt.go
index cf6410d..cd0b0e9 100755
--- a/internal/bbsim/dmiserver/dmi_hw_mgmt.go
+++ b/internal/bbsim/dmiserver/dmi_hw_mgmt.go
@@ -34,7 +34,7 @@
)
const (
- metricChannelSize = 100
+ kafkaChannelSize = 100
)
func getUUID(seed string) string {
@@ -66,9 +66,13 @@
dms.ponTransceiverCageUuids = make([]string, olt.NumPon)
// Start device metrics generator
- dms.metricChannel = make(chan interface{}, metricChannelSize)
+ 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
@@ -113,11 +117,12 @@
}
components = append(components, fans...)
- // Create 1 disk, 1 Processor and 1 ram
+ // 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{
@@ -251,6 +256,25 @@
}
}
+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")
@@ -452,10 +476,12 @@
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
+ // 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 kafka publisher: %v", err)
+ logger.Errorf("Failed to start metric kafka publisher: %v", err)
return &dmi.SetRemoteEndpointResponse{Status: dmi.Status_ERROR_STATUS, Reason: dmi.Reason_KAFKA_ENDPOINT_ERROR}, err
}
diff --git a/internal/bbsim/dmiserver/dmi_kafka_producer.go b/internal/bbsim/dmiserver/dmi_kafka_producer.go
index 9ee0172..8955dfa 100755
--- a/internal/bbsim/dmiserver/dmi_kafka_producer.go
+++ b/internal/bbsim/dmiserver/dmi_kafka_producer.go
@@ -26,7 +26,7 @@
log "github.com/sirupsen/logrus"
)
-var metricsProducer sarama.AsyncProducer
+var producer sarama.AsyncProducer
// InitializeDMKafkaPublishers initializes metrics kafka publisher
func InitializeDMKafkaPublishers(NewAsyncProducer func([]string, *sarama.Config) (sarama.AsyncProducer, error), oltID int, msgBusEndPoint string) error {
@@ -37,9 +37,9 @@
config.Producer.Retry.Max = 5
config.Metadata.Retry.Max = 10
config.Metadata.Retry.Backoff = 10 * time.Second
- config.ClientID = "BBSim-OLT-Metrics-" + strconv.Itoa(oltID)
+ config.ClientID = "BBSim-OLT-DMIServer-" + strconv.Itoa(oltID)
- metricsProducer, err = NewAsyncProducer([]string{msgBusEndPoint}, config)
+ producer, err = NewAsyncProducer([]string{msgBusEndPoint}, config)
return err
}
@@ -49,16 +49,16 @@
loop:
for {
select {
- case metric := <-ch:
- log.Tracef("Writing to kafka topic(%s): %v", topic, metric)
- jsonMet, err := json.Marshal(metric)
+ case data := <-ch:
+ log.Tracef("Writing to kafka topic(%s): %v", topic, data)
+ jsonData, err := json.Marshal(data)
if err != nil {
- log.Errorf("Failed to get json metric %v", err)
+ log.Errorf("Failed to get json %v", err)
continue
}
- metricsProducer.Input() <- &sarama.ProducerMessage{
+ producer.Input() <- &sarama.ProducerMessage{
Topic: topic,
- Value: sarama.ByteEncoder(jsonMet),
+ Value: sarama.ByteEncoder(jsonData),
}
case <-ctx.Done():
log.Infof("Stopping DM Kafka Publisher for topic %s", topic)
diff --git a/internal/bbsim/dmiserver/dmi_metrics_mgmt.go b/internal/bbsim/dmiserver/dmi_metrics_mgmt.go
index cb88cc7..e23786f 100755
--- a/internal/bbsim/dmiserver/dmi_metrics_mgmt.go
+++ b/internal/bbsim/dmiserver/dmi_metrics_mgmt.go
@@ -79,7 +79,7 @@
if req == nil || req.GetMetricId() < 0 {
return &dmi.GetMetricResponse{
Status: dmi.Status_ERROR_STATUS,
- //TODO reason must be INVALID_PARAMS, currently this is available in Device Management interface (DMI),
+ //TODO reason must be INVALID_PARAMS, currently this is not available in Device Management interface (DMI),
// change below reason with type INVALID_PARAMS once DMI is updated
Reason: dmi.Reason_UNDEFINED_REASON,
Metric: &dmi.Metric{},
diff --git a/internal/bbsimctl/commands/dmi_events.go b/internal/bbsimctl/commands/dmi_events.go
new file mode 100644
index 0000000..1608965
--- /dev/null
+++ b/internal/bbsimctl/commands/dmi_events.go
@@ -0,0 +1,74 @@
+/*
+ * 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 commands
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/jessevdk/go-flags"
+ "github.com/opencord/bbsim/api/bbsim"
+ "github.com/opencord/bbsim/internal/bbsimctl/config"
+ log "github.com/sirupsen/logrus"
+ "google.golang.org/grpc"
+)
+
+type DMIOptions struct {
+ Events DmiEventOptions `command:"events"`
+}
+
+type DmiEventCreate struct {
+ Args struct {
+ Name string
+ } `positional-args:"yes" required:"yes"`
+}
+
+type DmiEventOptions struct {
+ Create DmiEventCreate `command:"create"`
+}
+
+func RegisterDMICommands(parser *flags.Parser) {
+ _, _ = parser.AddCommand("dmi", "DMI Commands", "Commands to create events", &DMIOptions{})
+}
+
+func dmiEventGrpcClient() (bbsim.BBsimDmiClient, *grpc.ClientConn) {
+ conn, err := grpc.Dial(config.DmiConfig.Server, grpc.WithInsecure())
+ if err != nil {
+ log.Errorf("BBsimDmiClient connection failed : %v", err)
+ return nil, conn
+ }
+ return bbsim.NewBBsimDmiClient(conn), conn
+}
+
+// Execute create event
+func (o *DmiEventCreate) Execute(args []string) error {
+ client, conn := dmiEventGrpcClient()
+ defer conn.Close()
+
+ ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+ defer cancel()
+
+ req := bbsim.DmiEvent{EventName: o.Args.Name}
+ res, err := client.CreateEvent(ctx, &req)
+ if err != nil {
+ log.Errorf("Cannot create DMI event: %v", err)
+ return err
+ }
+
+ fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
+ return nil
+}
diff --git a/internal/bbsimctl/commands/onualarms.go b/internal/bbsimctl/commands/onualarms.go
index fb1d00e..669c173 100755
--- a/internal/bbsimctl/commands/onualarms.go
+++ b/internal/bbsimctl/commands/onualarms.go
@@ -20,10 +20,11 @@
import (
"context"
"fmt"
- "github.com/opencord/bbsim/internal/common"
"os"
"strings"
+ "github.com/opencord/bbsim/internal/common"
+
"github.com/jessevdk/go-flags"
"github.com/olekukonko/tablewriter"
pb "github.com/opencord/bbsim/api/bbsim"
diff --git a/internal/bbsimctl/config/config.go b/internal/bbsimctl/config/config.go
index 7d11122..4bf762a 100644
--- a/internal/bbsimctl/config/config.go
+++ b/internal/bbsimctl/config/config.go
@@ -57,6 +57,13 @@
},
}
+var DmiConfig = GlobalConfigSpec{
+ Server: "localhost:50075",
+ Grpc: GrpcConfigSpec{
+ Timeout: time.Second * 10,
+ },
+}
+
func ProcessGlobalOptions() {
if len(GlobalOptions.Config) == 0 {
home, err := os.UserHomeDir()