blob: 5d83e16f45914551ec648ccf8c2a283639b85212 [file] [log] [blame]
hkouser24361d42020-12-14 19:21:47 +05301/*
Joey Armstrong2c039362024-02-04 18:51:52 -05002 * Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
hkouser24361d42020-12-14 19:21:47 +05303
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 */
16
17package dmiserver
18
19import (
20 "context"
21 "fmt"
22 "sync"
23
hkouser24361d42020-12-14 19:21:47 +053024 "github.com/opencord/bbsim/api/bbsim"
25 "github.com/opencord/device-management-interface/go/dmi"
26 log "github.com/sirupsen/logrus"
27 "google.golang.org/grpc/codes"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000028 "google.golang.org/protobuf/types/known/timestamppb"
hkouser24361d42020-12-14 19:21:47 +053029)
30
Abhay Kumarc5723cc2023-06-08 12:09:30 +053031// DmiEventsGenerator has the attributes for generating events
hkouser24361d42020-12-14 19:21:47 +053032type DmiEventsGenerator struct {
33 apiSrv *DmiAPIServer
34 configuredEvents map[dmi.EventIds]dmi.EventCfg
35 access sync.Mutex
36}
37
38// func to generate the different types of events, there are two types one with thresholds and one without
39type eventGenerationFunc func(dmi.EventIds, dmi.ComponentType)
40
41// eventGenerationUtil contains the component and the func for a specific eventId
42type eventGenerationUtil struct {
43 componentType dmi.ComponentType
44 genFunc eventGenerationFunc
45}
46
47var dmiEG DmiEventsGenerator
48var eventGenMap map[dmi.EventIds]eventGenerationUtil
49
50func init() {
51 eventGenMap = make(map[dmi.EventIds]eventGenerationUtil)
52 eventGenMap[dmi.EventIds_EVENT_FAN_FAILURE] = eventGenerationUtil{
53 componentType: dmi.ComponentType_COMPONENT_TYPE_FAN,
54 genFunc: noThresholdEventGenerationFunc,
55 }
56 eventGenMap[dmi.EventIds_EVENT_FAN_FAILURE_RECOVERED] = eventGenerationUtil{
57 componentType: dmi.ComponentType_COMPONENT_TYPE_FAN,
58 genFunc: noThresholdEventGenerationFunc,
59 }
Elia Battistone8d1fa42022-04-01 10:47:37 +020060 eventGenMap[dmi.EventIds_EVENT_TRANSCEIVER_PLUG_IN] = eventGenerationUtil{
61 componentType: dmi.ComponentType_COMPONENT_TYPE_TRANSCEIVER,
62 genFunc: noThresholdEventGenerationFunc,
63 }
64 eventGenMap[dmi.EventIds_EVENT_TRANSCEIVER_PLUG_OUT] = eventGenerationUtil{
65 componentType: dmi.ComponentType_COMPONENT_TYPE_TRANSCEIVER,
66 genFunc: noThresholdEventGenerationFunc,
67 }
hkouser24361d42020-12-14 19:21:47 +053068
69 eventGenMap[dmi.EventIds_EVENT_PSU_FAILURE] = eventGenerationUtil{
70 componentType: dmi.ComponentType_COMPONENT_TYPE_POWER_SUPPLY,
71 genFunc: noThresholdEventGenerationFunc,
72 }
73 eventGenMap[dmi.EventIds_EVENT_PSU_FAILURE_RECOVERED] = eventGenerationUtil{
74 componentType: dmi.ComponentType_COMPONENT_TYPE_POWER_SUPPLY,
75 genFunc: noThresholdEventGenerationFunc,
76 }
77
78 eventGenMap[dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL] = eventGenerationUtil{
79 componentType: dmi.ComponentType_COMPONENT_TYPE_SENSOR,
80 genFunc: thresholdEventGenerationFunc,
81 }
82 eventGenMap[dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL_RECOVERED] = eventGenerationUtil{
83 componentType: dmi.ComponentType_COMPONENT_TYPE_SENSOR,
84 genFunc: thresholdEventGenerationFunc,
85 }
86}
87
Abhay Kumarc5723cc2023-06-08 12:09:30 +053088// StartEventsGenerator initializes the event generator
hkouser24361d42020-12-14 19:21:47 +053089func StartEventsGenerator(apiSrv *DmiAPIServer) {
90 log.Debugf("StartEventsGenerator invoked")
91
92 dmiEG = DmiEventsGenerator{
93 apiSrv: apiSrv,
94 }
95 dmiEG.configuredEvents = make(map[dmi.EventIds]dmi.EventCfg)
96
97 // Add Fan Failure event configuration
98 dmiEG.configuredEvents[dmi.EventIds_EVENT_FAN_FAILURE] = dmi.EventCfg{
99 EventId: dmi.EventIds_EVENT_FAN_FAILURE,
100 IsConfigured: true,
101 }
102
103 // Add hardware device temp above critical event configuration
104 dmiEG.configuredEvents[dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL] = dmi.EventCfg{
105 EventId: dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL,
106 IsConfigured: true,
107 Thresholds: &dmi.Thresholds{
108 Threshold: &dmi.Thresholds_Upper{Upper: &dmi.WaterMarks{
109 High: &dmi.ValueType{
110 Val: &dmi.ValueType_IntVal{IntVal: 95},
111 },
112 Low: &dmi.ValueType{
113 Val: &dmi.ValueType_IntVal{IntVal: 90},
114 },
115 }},
116 },
117 }
118
119 // Add Power Supply Unit failure event configuration
120 dmiEG.configuredEvents[dmi.EventIds_EVENT_PSU_FAILURE] = dmi.EventCfg{
121 EventId: dmi.EventIds_EVENT_PSU_FAILURE,
122 IsConfigured: true,
123 }
Elia Battistone8d1fa42022-04-01 10:47:37 +0200124
125 // Add Transceiver Plug in and out event configuration
126 dmiEG.configuredEvents[dmi.EventIds_EVENT_TRANSCEIVER_PLUG_IN] = dmi.EventCfg{
127 EventId: dmi.EventIds_EVENT_TRANSCEIVER_PLUG_IN,
128 IsConfigured: true,
129 }
130 dmiEG.configuredEvents[dmi.EventIds_EVENT_TRANSCEIVER_PLUG_OUT] = dmi.EventCfg{
131 EventId: dmi.EventIds_EVENT_TRANSCEIVER_PLUG_OUT,
132 IsConfigured: true,
133 }
hkouser24361d42020-12-14 19:21:47 +0530134}
135
136// get the events list
137func getEventsList() []*dmi.EventCfg {
138 events := make(map[dmi.EventIds]dmi.EventCfg)
139 dmiEG.access.Lock()
140
141 for key, value := range dmiEG.configuredEvents {
142 events[key] = value
143 }
144
145 dmiEG.access.Unlock()
146
147 var toRet []*dmi.EventCfg
148 for _, v := range events {
149 eventConfig := v
150 toRet = append(toRet, &eventConfig)
151 }
152 logger.Debugf("Events list supported by device %+v", toRet)
153 return toRet
154}
155
Abhay Kumarc5723cc2023-06-08 12:09:30 +0530156// UpdateEventConfig Adds/Updates the passed event configuration
hkouser24361d42020-12-14 19:21:47 +0530157func UpdateEventConfig(newEventCfg *dmi.EventCfg) {
158 dmiEG.access.Lock()
159 dmiEG.configuredEvents[newEventCfg.GetEventId()] = *newEventCfg
160 dmiEG.access.Unlock()
161 logger.Infof("Events updated %v", newEventCfg)
162}
163
164// update Event MetaData
165func updateEventMetaData(c *dmi.Component, apiSrv *DmiAPIServer, evt *dmi.Event) *dmi.Event {
166 evt.EventMetadata = &dmi.EventMetaData{
Elia Battistone8d1fa42022-04-01 10:47:37 +0200167 DeviceUuid: apiSrv.uuid,
hkouser24361d42020-12-14 19:21:47 +0530168 ComponentUuid: c.Uuid,
169 ComponentName: c.Name,
170 }
171 return evt
172}
173
174func sendOutEventOnKafka(event interface{}, apiSrv *DmiAPIServer) {
175 select {
176 case apiSrv.eventChannel <- event:
177 default:
178 logger.Debugf("Channel not ready dropping event")
179 }
180}
181
182func noThresholdEventGenerationFunc(eventID dmi.EventIds, cType dmi.ComponentType) {
183 for _, comp := range findComponentsOfType(dmiEG.apiSrv.root.Children, cType) {
184 var evnt dmi.Event
185 evnt.EventId = eventID
186 evnt = *updateEventMetaData(comp, dmiEG.apiSrv, &evnt)
David K. Bainbridgec415efe2021-08-19 13:05:21 +0000187 evnt.RaisedTs = timestamppb.Now()
hkouser24361d42020-12-14 19:21:47 +0530188 logger.Debugf("Got a No Threshold event %+v", evnt)
189 sendOutEventOnKafka(evnt, dmiEG.apiSrv)
190 break
191 }
192}
193
194func thresholdEventGenerationFunc(eventID dmi.EventIds, cType dmi.ComponentType) {
195 eventGenerated := false
196 for _, comp := range findComponentsOfType(dmiEG.apiSrv.root.Children, cType) {
197 var evnt dmi.Event
198 evnt.EventId = eventID
199 evnt = *updateEventMetaData(comp, dmiEG.apiSrv, &evnt)
David K. Bainbridgec415efe2021-08-19 13:05:21 +0000200 evnt.RaisedTs = timestamppb.Now()
hkouser24361d42020-12-14 19:21:47 +0530201 configuredEvents := make(map[dmi.EventIds]dmi.EventCfg)
202
203 dmiEG.access.Lock()
204 for key, value := range dmiEG.configuredEvents {
205 configuredEvents[key] = value
206 }
207 dmiEG.access.Unlock()
208
209 for k, v := range configuredEvents {
210 if k == eventID {
211 evnt.ThresholdInfo = &dmi.ThresholdInformation{
212 ObservedValue: &dmi.ValueType{
213 Val: &dmi.ValueType_IntVal{IntVal: int64(generateRand(int32(v.Thresholds.GetUpper().GetLow().GetIntVal()), int32(v.Thresholds.GetUpper().GetHigh().GetIntVal())))},
214 },
215 Thresholds: v.GetThresholds(),
216 }
217 }
218 }
219
220 logger.Debugf("Got Threshold event %v", evnt)
221 sendOutEventOnKafka(evnt, dmiEG.apiSrv)
222 eventGenerated = true
223 if eventGenerated {
224 break
225 }
226
227 }
228}
229
230// CreateEvent creates and the passed event if it's valid and sends it to the msg bus
Elia Battistone8d1fa42022-04-01 10:47:37 +0200231func (dms *DmiAPIServer) CreateEvent(ctx context.Context, evt *bbsim.DmiEvent) (*bbsim.DmiResponse, error) {
232 retFunc := func(code codes.Code, msg string) (*bbsim.DmiResponse, error) {
233 res := &bbsim.DmiResponse{}
hkouser24361d42020-12-14 19:21:47 +0530234 res.StatusCode = int32(code)
235 res.Message = msg
236 return res, nil
237 }
238
239 if dmiEG.apiSrv == nil || dmiEG.apiSrv.root == nil || dmiEG.apiSrv.root.Children == nil {
240 // inventory might not yet be created
Elia Battistone8d1fa42022-04-01 10:47:37 +0200241 return retFunc(codes.Internal, "Inventory does not exist")
hkouser24361d42020-12-14 19:21:47 +0530242 }
243
244 eventID, exists := dmi.EventIds_value[evt.EventName]
245 if !exists {
246 return retFunc(codes.NotFound,
247 fmt.Sprintf("DMI Alarm not supported. Permissible values are %s", getValidEventNames()))
248 }
249
250 genUtil, exists := eventGenMap[dmi.EventIds(eventID)]
251 if !exists {
252 return retFunc(codes.Unimplemented, "Generation of this event not yet implemented")
253 }
254
255 genUtil.genFunc(dmi.EventIds(eventID), genUtil.componentType)
256
257 return retFunc(codes.OK, "DMI Event Indication Sent.")
258
259}
260
261func getValidEventNames() string {
262 s := ""
263 //keys := make([]string, len(dmi.EventIds_value)-1)
264 for k, v := range dmi.EventIds_value {
265 if v != 0 {
266 s = s + "\n" + k
267 }
268 }
269 return s
270}