blob: 2a9073e8231945b29f3ae3c2a0f5e9be3b3e5e1b [file] [log] [blame]
hkouser24361d42020-12-14 19:21:47 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
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
31//DmiEventsGenerator has the attributes for generating events
32type 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 }
60
61 eventGenMap[dmi.EventIds_EVENT_PSU_FAILURE] = eventGenerationUtil{
62 componentType: dmi.ComponentType_COMPONENT_TYPE_POWER_SUPPLY,
63 genFunc: noThresholdEventGenerationFunc,
64 }
65 eventGenMap[dmi.EventIds_EVENT_PSU_FAILURE_RECOVERED] = eventGenerationUtil{
66 componentType: dmi.ComponentType_COMPONENT_TYPE_POWER_SUPPLY,
67 genFunc: noThresholdEventGenerationFunc,
68 }
69
70 eventGenMap[dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL] = eventGenerationUtil{
71 componentType: dmi.ComponentType_COMPONENT_TYPE_SENSOR,
72 genFunc: thresholdEventGenerationFunc,
73 }
74 eventGenMap[dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL_RECOVERED] = eventGenerationUtil{
75 componentType: dmi.ComponentType_COMPONENT_TYPE_SENSOR,
76 genFunc: thresholdEventGenerationFunc,
77 }
78}
79
80//StartEventsGenerator initializes the event generator
81func StartEventsGenerator(apiSrv *DmiAPIServer) {
82 log.Debugf("StartEventsGenerator invoked")
83
84 dmiEG = DmiEventsGenerator{
85 apiSrv: apiSrv,
86 }
87 dmiEG.configuredEvents = make(map[dmi.EventIds]dmi.EventCfg)
88
89 // Add Fan Failure event configuration
90 dmiEG.configuredEvents[dmi.EventIds_EVENT_FAN_FAILURE] = dmi.EventCfg{
91 EventId: dmi.EventIds_EVENT_FAN_FAILURE,
92 IsConfigured: true,
93 }
94
95 // Add hardware device temp above critical event configuration
96 dmiEG.configuredEvents[dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL] = dmi.EventCfg{
97 EventId: dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL,
98 IsConfigured: true,
99 Thresholds: &dmi.Thresholds{
100 Threshold: &dmi.Thresholds_Upper{Upper: &dmi.WaterMarks{
101 High: &dmi.ValueType{
102 Val: &dmi.ValueType_IntVal{IntVal: 95},
103 },
104 Low: &dmi.ValueType{
105 Val: &dmi.ValueType_IntVal{IntVal: 90},
106 },
107 }},
108 },
109 }
110
111 // Add Power Supply Unit failure event configuration
112 dmiEG.configuredEvents[dmi.EventIds_EVENT_PSU_FAILURE] = dmi.EventCfg{
113 EventId: dmi.EventIds_EVENT_PSU_FAILURE,
114 IsConfigured: true,
115 }
116}
117
118// get the events list
119func getEventsList() []*dmi.EventCfg {
120 events := make(map[dmi.EventIds]dmi.EventCfg)
121 dmiEG.access.Lock()
122
123 for key, value := range dmiEG.configuredEvents {
124 events[key] = value
125 }
126
127 dmiEG.access.Unlock()
128
129 var toRet []*dmi.EventCfg
130 for _, v := range events {
131 eventConfig := v
132 toRet = append(toRet, &eventConfig)
133 }
134 logger.Debugf("Events list supported by device %+v", toRet)
135 return toRet
136}
137
138//UpdateEventConfig Adds/Updates the passed event configuration
139func UpdateEventConfig(newEventCfg *dmi.EventCfg) {
140 dmiEG.access.Lock()
141 dmiEG.configuredEvents[newEventCfg.GetEventId()] = *newEventCfg
142 dmiEG.access.Unlock()
143 logger.Infof("Events updated %v", newEventCfg)
144}
145
146// update Event MetaData
147func updateEventMetaData(c *dmi.Component, apiSrv *DmiAPIServer, evt *dmi.Event) *dmi.Event {
148 evt.EventMetadata = &dmi.EventMetaData{
149 DeviceUuid: &dmi.Uuid{
150 Uuid: apiSrv.uuid,
151 },
152 ComponentUuid: c.Uuid,
153 ComponentName: c.Name,
154 }
155 return evt
156}
157
158func sendOutEventOnKafka(event interface{}, apiSrv *DmiAPIServer) {
159 select {
160 case apiSrv.eventChannel <- event:
161 default:
162 logger.Debugf("Channel not ready dropping event")
163 }
164}
165
166func noThresholdEventGenerationFunc(eventID dmi.EventIds, cType dmi.ComponentType) {
167 for _, comp := range findComponentsOfType(dmiEG.apiSrv.root.Children, cType) {
168 var evnt dmi.Event
169 evnt.EventId = eventID
170 evnt = *updateEventMetaData(comp, dmiEG.apiSrv, &evnt)
David K. Bainbridgec415efe2021-08-19 13:05:21 +0000171 evnt.RaisedTs = timestamppb.Now()
hkouser24361d42020-12-14 19:21:47 +0530172 logger.Debugf("Got a No Threshold event %+v", evnt)
173 sendOutEventOnKafka(evnt, dmiEG.apiSrv)
174 break
175 }
176}
177
178func thresholdEventGenerationFunc(eventID dmi.EventIds, cType dmi.ComponentType) {
179 eventGenerated := false
180 for _, comp := range findComponentsOfType(dmiEG.apiSrv.root.Children, cType) {
181 var evnt dmi.Event
182 evnt.EventId = eventID
183 evnt = *updateEventMetaData(comp, dmiEG.apiSrv, &evnt)
David K. Bainbridgec415efe2021-08-19 13:05:21 +0000184 evnt.RaisedTs = timestamppb.Now()
hkouser24361d42020-12-14 19:21:47 +0530185 configuredEvents := make(map[dmi.EventIds]dmi.EventCfg)
186
187 dmiEG.access.Lock()
188 for key, value := range dmiEG.configuredEvents {
189 configuredEvents[key] = value
190 }
191 dmiEG.access.Unlock()
192
193 for k, v := range configuredEvents {
194 if k == eventID {
195 evnt.ThresholdInfo = &dmi.ThresholdInformation{
196 ObservedValue: &dmi.ValueType{
197 Val: &dmi.ValueType_IntVal{IntVal: int64(generateRand(int32(v.Thresholds.GetUpper().GetLow().GetIntVal()), int32(v.Thresholds.GetUpper().GetHigh().GetIntVal())))},
198 },
199 Thresholds: v.GetThresholds(),
200 }
201 }
202 }
203
204 logger.Debugf("Got Threshold event %v", evnt)
205 sendOutEventOnKafka(evnt, dmiEG.apiSrv)
206 eventGenerated = true
207 if eventGenerated {
208 break
209 }
210
211 }
212}
213
214// CreateEvent creates and the passed event if it's valid and sends it to the msg bus
ssiddiqui6ca40702021-03-08 18:20:21 +0530215func (dms *DmiAPIServer) CreateEvent(ctx context.Context, evt *bbsim.DmiEvent) (*bbsim.DmiCreateEventResponse, error) {
hkouser24361d42020-12-14 19:21:47 +0530216 retFunc := func(code codes.Code, msg string) (*bbsim.DmiCreateEventResponse, error) {
217 res := &bbsim.DmiCreateEventResponse{}
218 res.StatusCode = int32(code)
219 res.Message = msg
220 return res, nil
221 }
222
223 if dmiEG.apiSrv == nil || dmiEG.apiSrv.root == nil || dmiEG.apiSrv.root.Children == nil {
224 // inventory might not yet be created
225 return retFunc(codes.Internal, "inventory do no exist")
226 }
227
228 eventID, exists := dmi.EventIds_value[evt.EventName]
229 if !exists {
230 return retFunc(codes.NotFound,
231 fmt.Sprintf("DMI Alarm not supported. Permissible values are %s", getValidEventNames()))
232 }
233
234 genUtil, exists := eventGenMap[dmi.EventIds(eventID)]
235 if !exists {
236 return retFunc(codes.Unimplemented, "Generation of this event not yet implemented")
237 }
238
239 genUtil.genFunc(dmi.EventIds(eventID), genUtil.componentType)
240
241 return retFunc(codes.OK, "DMI Event Indication Sent.")
242
243}
244
245func getValidEventNames() string {
246 s := ""
247 //keys := make([]string, len(dmi.EventIds_value)-1)
248 for k, v := range dmi.EventIds_value {
249 if v != 0 {
250 s = s + "\n" + k
251 }
252 }
253 return s
254}