blob: f7ad81e7e5cdaa8b683dbe11a58d2e903e25ea95 [file] [log] [blame]
Mohamed Abukar3e038152020-03-04 10:01:45 +02001/*
2 * Copyright (c) 2020 AT&T Intellectual Property.
3 * Copyright (c) 2020 Nokia.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * This source code is part of the near-RT RIC (RAN Intelligent Controller)
18 * platform project (RICP).
19 */
Mohamed Abukar4e7e7122020-03-04 10:01:45 +020020
Mohamed Abukar3e038152020-03-04 10:01:45 +020021package main
22
23import (
Mohamed Abukar105030f2020-10-22 18:08:34 +030024 "bytes"
Mohamed Abukar4e7e7122020-03-04 10:01:45 +020025 "encoding/json"
26 "fmt"
Anssi Mannila18fd03c2020-10-29 10:01:00 +020027 "io/ioutil"
28 "net/http"
29 "os"
30 "time"
31
vipin14323a92020-09-25 10:03:43 +000032 "gerrit.o-ran-sc.org/r/ric-plt/alarm-go/alarm"
33 app "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
Mohamed Abukar4e7e7122020-03-04 10:01:45 +020034 clientruntime "github.com/go-openapi/runtime/client"
35 "github.com/go-openapi/strfmt"
36 "github.com/prometheus/alertmanager/api/v2/client"
37 "github.com/prometheus/alertmanager/api/v2/client/alert"
38 "github.com/prometheus/alertmanager/api/v2/models"
39 "github.com/spf13/viper"
Mohamed Abukar3e038152020-03-04 10:01:45 +020040)
41
Abukar Mohamed121e8b62020-09-18 11:41:33 +000042func (a *AlarmManager) StartAlertTimer() {
Mohamed Abukar4e7e7122020-03-04 10:01:45 +020043 tick := time.Tick(time.Duration(a.alertInterval) * time.Millisecond)
44 for range tick {
Mohamed Abukaraf0c5702020-03-11 10:29:40 +020045 a.mutex.Lock()
Mohamed Abukar4e7e7122020-03-04 10:01:45 +020046 for _, m := range a.activeAlarms {
47 app.Logger.Info("Re-raising alarm: %v", m)
Anssi Mannila2be5ac52020-09-22 12:17:05 +030048 a.PostAlert(a.GenerateAlertLabels(m.Alarm, AlertStatusActive, m.AlarmTime))
Mohamed Abukar4e7e7122020-03-04 10:01:45 +020049 }
Mohamed Abukaraf0c5702020-03-11 10:29:40 +020050 a.mutex.Unlock()
Mohamed Abukar4e7e7122020-03-04 10:01:45 +020051 }
52}
53
Abukar Mohamed121e8b62020-09-18 11:41:33 +000054func (a *AlarmManager) Consume(rp *app.RMRParams) (err error) {
Mohamed Abukar4e7e7122020-03-04 10:01:45 +020055 app.Logger.Info("Message received!")
56
57 defer app.Rmr.Free(rp.Mbuf)
58 switch rp.Mtype {
59 case alarm.RIC_ALARM_UPDATE:
60 a.HandleAlarms(rp)
61 default:
62 app.Logger.Info("Unknown Message Type '%d', discarding", rp.Mtype)
63 }
64
65 return nil
66}
67
Abukar Mohamed121e8b62020-09-18 11:41:33 +000068func (a *AlarmManager) HandleAlarms(rp *app.RMRParams) (*alert.PostAlertsOK, error) {
Mohamed Abukar4e7e7122020-03-04 10:01:45 +020069 var m alarm.AlarmMessage
Lott, Christopher (cl778h)3e8e2aa2020-06-03 08:52:14 -040070 app.Logger.Info("Received JSON: %s", rp.Payload)
Mohamed Abukar4e7e7122020-03-04 10:01:45 +020071 if err := json.Unmarshal(rp.Payload, &m); err != nil {
72 app.Logger.Error("json.Unmarshal failed: %v", err)
73 return nil, err
74 }
75 app.Logger.Info("newAlarm: %v", m)
76
Mohamed Abukar105030f2020-10-22 18:08:34 +030077 return a.ProcessAlarm(&AlarmNotification{m, alarm.AlarmDefinition{}})
Mohamed Abukar540ceee2020-09-09 08:07:40 +030078}
79
Mohamed Abukar105030f2020-10-22 18:08:34 +030080func (a *AlarmManager) ProcessAlarm(m *AlarmNotification) (*alert.PostAlertsOK, error) {
vipin6f73fa32020-10-06 06:51:53 +000081 a.mutex.Lock()
Anssi Mannila18fd03c2020-10-29 10:01:00 +020082 alarmDef := &alarm.AlarmDefinition{}
83 var ok bool
84 if alarmDef, ok = alarm.RICAlarmDefinitions[m.Alarm.SpecificProblem]; !ok {
Mohamed Abukar540ceee2020-09-09 08:07:40 +030085 app.Logger.Warn("Alarm (SP='%d') not recognized, suppressing ...", m.Alarm.SpecificProblem)
vipin6f73fa32020-10-06 06:51:53 +000086 a.mutex.Unlock()
Mohamed Abukar4e7e7122020-03-04 10:01:45 +020087 return nil, nil
88 }
89
Mohamed Abukar4e7e7122020-03-04 10:01:45 +020090 idx, found := a.IsMatchFound(m.Alarm)
Anssi Mannila18fd03c2020-10-29 10:01:00 +020091 // Suppress duplicate alarms
vipin4cedd502020-09-25 05:58:31 +000092 if found && m.AlarmAction == alarm.AlarmActionRaise {
Mohamed Abukar540ceee2020-09-09 08:07:40 +030093 app.Logger.Info("Duplicate alarm found, suppressing ...")
Anssi Mannilafe07bd12020-09-24 14:02:57 +030094 if m.PerceivedSeverity == a.activeAlarms[idx].PerceivedSeverity {
95 // Duplicate with same severity found
vipin6f73fa32020-10-06 06:51:53 +000096 a.mutex.Unlock()
Anssi Mannilafe07bd12020-09-24 14:02:57 +030097 return nil, nil
98 } else {
99 // Remove duplicate with different severity
100 a.activeAlarms = a.RemoveAlarm(a.activeAlarms, idx, "active")
101 }
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200102 }
103
104 // Clear alarm if found from active alarm list
105 if m.AlarmAction == alarm.AlarmActionClear {
106 if found {
Anssi Mannila18fd03c2020-10-29 10:01:00 +0200107 if a.ProcessClearAlarm(m, alarmDef, idx) == false {
108 return nil, nil
vipin887efa32020-09-28 13:26:28 +0000109 }
Mohamed Abukarb2f29a82020-03-17 09:31:55 +0200110 if a.postClear {
vipin6f73fa32020-10-06 06:51:53 +0000111 a.mutex.Unlock()
Mohamed Abukar105030f2020-10-22 18:08:34 +0300112
113 // Send alarm notification to NOMA, if enabled
114 if app.Config.GetBool("controls.noma.enabled") {
115 m.PerceivedSeverity = alarm.SeverityCleared
116 return a.PostAlarm(m)
117 }
Anssi Mannila2be5ac52020-09-22 12:17:05 +0300118 return a.PostAlert(a.GenerateAlertLabels(m.Alarm, AlertStatusResolved, m.AlarmTime))
Mohamed Abukarb2f29a82020-03-17 09:31:55 +0200119 }
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200120 }
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300121 app.Logger.Info("No matching active alarm found, suppressing ...")
vipin6f73fa32020-10-06 06:51:53 +0000122 a.mutex.Unlock()
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200123 return nil, nil
124 }
125
126 // New alarm -> update active alarms and post to Alert Manager
127 if m.AlarmAction == alarm.AlarmActionRaise {
Anssi Mannila18fd03c2020-10-29 10:01:00 +0200128 if a.ProcessRaiseAlarm(m, alarmDef) == false {
129 return nil, nil
130 }
Mohamed Abukar105030f2020-10-22 18:08:34 +0300131 // Send alarm notification to NOMA, if enabled
132 if app.Config.GetBool("controls.noma.enabled") {
133 return a.PostAlarm(m)
134 }
Anssi Mannila2be5ac52020-09-22 12:17:05 +0300135 return a.PostAlert(a.GenerateAlertLabels(m.Alarm, AlertStatusActive, m.AlarmTime))
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200136 }
137
vipin6f73fa32020-10-06 06:51:53 +0000138 a.mutex.Unlock()
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200139 return nil, nil
140}
141
Anssi Mannila18fd03c2020-10-29 10:01:00 +0200142func (a *AlarmManager)ProcessRaiseAlarm(m *AlarmNotification, alarmDef *alarm.AlarmDefinition) bool {
143 app.Logger.Debug("Raise alarmDef.RaiseDelay = %v, AlarmNotification = %v", alarmDef.RaiseDelay, *m)
144 // RaiseDelay > 0 in an alarm object in active alarm table indicates that raise delay is still ongoing for the alarm
145 m.AlarmDefinition.RaiseDelay = alarmDef.RaiseDelay
146 a.UpdateAlarmFields(a.GenerateAlarmId(), m)
147 a.UpdateActiveAlarmList(m)
148 a.mutex.Unlock()
149 if alarmDef.RaiseDelay > 0 {
150 timerDelay(alarmDef.RaiseDelay)
151 a.mutex.Lock()
152 // Alarm may have been deleted from active alarms table during delay or table index may have changed
153 idx, found := a.IsMatchFound(m.Alarm)
154 if found {
155 // Alarm is not showed in active alarms or alarm history via CLI before RaiseDelay has elapsed, i.e the value is 0
156 a.activeAlarms[idx].AlarmDefinition.RaiseDelay = 0
157 app.Logger.Debug("Raise after delay alarmDef.RaiseDelay = %v, AlarmNotification = %v", alarmDef.RaiseDelay, *m)
158 a.mutex.Unlock()
159 } else {
160 app.Logger.Debug("Alarm deleted during raise delay. AlarmNotification = %v", *m)
161 a.mutex.Unlock()
162 return false
163 }
164 }
165 m.AlarmDefinition.RaiseDelay = 0
166 a.UpdateAlarmHistoryList(m)
167 a.WriteAlarmInfoToPersistentVolume()
168 return true
169}
170
171func (a *AlarmManager)ProcessClearAlarm(m *AlarmNotification, alarmDef *alarm.AlarmDefinition, idx int) bool {
172 app.Logger.Debug("Clear alarmDef.ClearDelay = %v, AlarmNotification = %v", alarmDef.ClearDelay, *m)
173 if alarmDef.ClearDelay > 0 {
174 a.mutex.Unlock()
175 timerDelay(alarmDef.ClearDelay)
176 app.Logger.Debug("Clear after delay alarmDef.ClearDelay = %v, AlarmNotification = %v", alarmDef.ClearDelay, *m)
177 a.mutex.Lock()
178 // Another alarm clear may have happened during delay and active alarms table index changed
179 var found bool
180 idx, found = a.IsMatchFound(m.Alarm)
181 if !found {
182 app.Logger.Debug("Alarm not anymore in the active alarms table. AlarmNotification = %v", *m)
183 a.mutex.Unlock()
184 return false
185 }
186 }
187 a.UpdateAlarmFields(a.activeAlarms[idx].AlarmId, m)
188 a.alarmHistory = append(a.alarmHistory, *m)
189 a.activeAlarms = a.RemoveAlarm(a.activeAlarms, idx, "active")
190 if (len(a.alarmHistory) >= a.maxAlarmHistory) && (a.exceededAlarmHistoryOn == false) {
191 app.Logger.Warn("alarm history count exceeded maxAlarmHistory threshold")
192 a.GenerateThresholdAlarm(alarm.ALARM_HISTORY_EXCEED_MAX_THRESHOLD, "history")
193 }
194
195 if a.exceededActiveAlarmOn && m.Alarm.SpecificProblem == alarm.ACTIVE_ALARM_EXCEED_MAX_THRESHOLD {
196 a.exceededActiveAlarmOn = false
197 }
198
199 if a.exceededAlarmHistoryOn && m.Alarm.SpecificProblem == alarm.ALARM_HISTORY_EXCEED_MAX_THRESHOLD {
200 a.exceededAlarmHistoryOn = false
201 }
202 a.WriteAlarmInfoToPersistentVolume()
203 return true
204}
205
206func timerDelay(delay int) {
207 timer := time.NewTimer(time.Duration(delay) * time.Second)
208 <-timer.C
209}
210
Abukar Mohamed121e8b62020-09-18 11:41:33 +0000211func (a *AlarmManager) IsMatchFound(newAlarm alarm.Alarm) (int, bool) {
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200212 for i, m := range a.activeAlarms {
213 if m.ManagedObjectId == newAlarm.ManagedObjectId && m.ApplicationId == newAlarm.ApplicationId &&
Mohamed Abukar0c389732020-09-17 14:47:50 +0300214 m.SpecificProblem == newAlarm.SpecificProblem && m.IdentifyingInfo == newAlarm.IdentifyingInfo {
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200215 return i, true
216 }
217 }
218 return -1, false
219}
220
Mohamed Abukar105030f2020-10-22 18:08:34 +0300221func (a *AlarmManager) RemoveAlarm(alarms []AlarmNotification, i int, listName string) []AlarmNotification {
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300222 app.Logger.Info("Alarm '%+v' deleted from the '%s' list", alarms[i], listName)
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200223 copy(alarms[i:], alarms[i+1:])
224 return alarms[:len(alarms)-1]
225}
226
Mohamed Abukar105030f2020-10-22 18:08:34 +0300227func (a *AlarmManager) GenerateAlarmId() int {
Mohamed Abukarf5a8e712020-10-19 16:58:17 +0300228 a.uniqueAlarmId++ // @todo: generate a unique ID
Mohamed Abukar105030f2020-10-22 18:08:34 +0300229 return a.uniqueAlarmId
230}
231
232func (a *AlarmManager) UpdateAlarmFields(alarmId int, newAlarm *AlarmNotification) {
233 alarmDef := alarm.RICAlarmDefinitions[newAlarm.SpecificProblem]
234 newAlarm.AlarmId = alarmId
Mohamed Abukarf5a8e712020-10-19 16:58:17 +0300235 newAlarm.AlarmText = alarmDef.AlarmText
236 newAlarm.EventType = alarmDef.EventType
237}
238
Mohamed Abukar105030f2020-10-22 18:08:34 +0300239func (a *AlarmManager) GenerateThresholdAlarm(sp int, data string) bool {
240 thresholdAlarm := a.alarmClient.NewAlarm(sp, alarm.SeverityWarning, "threshold", data)
241 thresholdMessage := alarm.AlarmMessage{
242 Alarm: thresholdAlarm,
243 AlarmAction: alarm.AlarmActionRaise,
244 AlarmTime: (time.Now().UnixNano()),
245 }
vipin78b2b0a2020-10-28 10:10:18 +0000246 alarmDef := alarm.RICAlarmDefinitions[sp]
247 alarmId := a.GenerateAlarmId()
248 alarmDef.AlarmId = alarmId
249 a.activeAlarms = append(a.activeAlarms, AlarmNotification{thresholdMessage, *alarmDef})
250 a.alarmHistory = append(a.alarmHistory, AlarmNotification{thresholdMessage, *alarmDef})
Mohamed Abukar105030f2020-10-22 18:08:34 +0300251
252 return true
253}
254
Anssi Mannila18fd03c2020-10-29 10:01:00 +0200255func (a *AlarmManager) UpdateActiveAlarmList(newAlarm *AlarmNotification) {
vipin541eb502020-09-22 12:04:59 +0000256 /* If maximum number of active alarms is reached, an error log writing is made, and new alarm indicating the problem is raised.
Anssi Mannila18fd03c2020-10-29 10:01:00 +0200257 The attempt to raise the alarm next time will be suppressed when found as duplicate. */
Mohamed Abukarf5a8e712020-10-19 16:58:17 +0300258 if (len(a.activeAlarms) >= a.maxActiveAlarms) && (a.exceededActiveAlarmOn == false) {
Mohamed Abukar105030f2020-10-22 18:08:34 +0300259 app.Logger.Warn("active alarm count exceeded maxActiveAlarms threshold")
260 a.exceededActiveAlarmOn = a.GenerateThresholdAlarm(alarm.ACTIVE_ALARM_EXCEED_MAX_THRESHOLD, "active")
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300261 }
262
Anssi Mannila18fd03c2020-10-29 10:01:00 +0200263 // @todo: For now just keep the active alarms in-memory. Use SDL later for persistence
264 a.activeAlarms = append(a.activeAlarms, *newAlarm)
265}
266
267func (a *AlarmManager) UpdateAlarmHistoryList(newAlarm *AlarmNotification) {
268 /* If maximum number of events in alarm history is reached, an error log writing is made,
269 and new alarm indicating the problem is raised. The attempt to add new event time will
270 be suppressed */
271
Mohamed Abukarf5a8e712020-10-19 16:58:17 +0300272 if (len(a.alarmHistory) >= a.maxAlarmHistory) && (a.exceededAlarmHistoryOn == false) {
Mohamed Abukar105030f2020-10-22 18:08:34 +0300273 app.Logger.Warn("alarm history count exceeded maxAlarmHistory threshold")
274 a.exceededAlarmHistoryOn = a.GenerateThresholdAlarm(alarm.ALARM_HISTORY_EXCEED_MAX_THRESHOLD, "history")
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300275 }
276
Anssi Mannila18fd03c2020-10-29 10:01:00 +0200277 // @todo: For now just keep the alarms history in-memory. Use SDL later for persistence
Mohamed Abukar0c389732020-09-17 14:47:50 +0300278 a.alarmHistory = append(a.alarmHistory, *newAlarm)
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200279}
280
Mohamed Abukar105030f2020-10-22 18:08:34 +0300281func (a *AlarmManager) PostAlarm(m *AlarmNotification) (*alert.PostAlertsOK, error) {
282 result, err := json.Marshal(m)
283 if err != nil {
284 app.Logger.Info("json.Marshal failed: %v", err)
285 return nil, err
286 }
287
288 fullUrl := fmt.Sprintf("%s/%s", app.Config.GetString("controls.noma.host"), app.Config.GetString("controls.noma.alarmUrl"))
289 app.Logger.Info("Posting alarm to '%s'", fullUrl)
290
291 resp, err := http.Post(fullUrl, "application/json", bytes.NewReader(result))
292 if err != nil || resp == nil {
293 app.Logger.Info("Unable to post alarm to '%s': %v", fullUrl, err)
294 }
295
296 return nil, err
297}
298
Anssi Mannila2be5ac52020-09-22 12:17:05 +0300299func (a *AlarmManager) GenerateAlertLabels(newAlarm alarm.Alarm, status AlertStatus, alarmTime int64) (models.LabelSet, models.LabelSet) {
Mohamed Abukaraf0c5702020-03-11 10:29:40 +0200300 alarmDef := alarm.RICAlarmDefinitions[newAlarm.SpecificProblem]
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200301 amLabels := models.LabelSet{
Mohamed Abukarb2f29a82020-03-17 09:31:55 +0200302 "status": string(status),
Mohamed Abukaraf0c5702020-03-11 10:29:40 +0200303 "alertname": alarmDef.AlarmText,
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200304 "severity": string(newAlarm.PerceivedSeverity),
Mohamed Abukar105030f2020-10-22 18:08:34 +0300305 "service": fmt.Sprintf("%s/%s", newAlarm.ManagedObjectId, newAlarm.ApplicationId),
306 "system_name": "RIC",
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200307 }
308 amAnnotations := models.LabelSet{
Mohamed Abukar105030f2020-10-22 18:08:34 +0300309 "alarm_id": fmt.Sprintf("%d", alarmDef.AlarmId),
310 "specific_problem": fmt.Sprintf("%d", newAlarm.SpecificProblem),
311 "event_type": alarmDef.EventType,
312 "identifying_info": newAlarm.IdentifyingInfo,
313 "additional_info": newAlarm.AdditionalInfo,
314 "description": fmt.Sprintf("%s:%s", newAlarm.IdentifyingInfo, newAlarm.AdditionalInfo),
315 "instructions": alarmDef.OperationInstructions,
316 "timestamp": fmt.Sprintf("%s", time.Unix(0, alarmTime).Format("02/01/2006, 15:04:05")),
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200317 }
318
319 return amLabels, amAnnotations
320}
321
Abukar Mohamed121e8b62020-09-18 11:41:33 +0000322func (a *AlarmManager) NewAlertmanagerClient() *client.Alertmanager {
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200323 cr := clientruntime.New(a.amHost, a.amBaseUrl, a.amSchemes)
324 return client.New(cr, strfmt.Default)
325}
326
Abukar Mohamed121e8b62020-09-18 11:41:33 +0000327func (a *AlarmManager) PostAlert(amLabels, amAnnotations models.LabelSet) (*alert.PostAlertsOK, error) {
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200328 pa := &models.PostableAlert{
329 Alert: models.Alert{
330 GeneratorURL: strfmt.URI(""),
331 Labels: amLabels,
332 },
333 Annotations: amAnnotations,
334 }
335 alertParams := alert.NewPostAlertsParams().WithAlerts(models.PostableAlerts{pa})
336
Mohamed Abukar643241f2020-06-09 15:26:00 +0300337 app.Logger.Info("Posting alerts: labels: %+v, annotations: %+v", amLabels, amAnnotations)
Mohamed Abukaraf0c5702020-03-11 10:29:40 +0200338 ok, err := a.NewAlertmanagerClient().Alert.PostAlerts(alertParams)
339 if err != nil {
340 app.Logger.Error("Posting alerts to '%s/%s' failed with error: %v", a.amHost, a.amBaseUrl, err)
341 }
342 return ok, err
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200343}
344
Abukar Mohamed121e8b62020-09-18 11:41:33 +0000345func (a *AlarmManager) StatusCB() bool {
Mohamed Abukar4e7e7122020-03-04 10:01:45 +0200346 if !a.rmrReady {
347 app.Logger.Info("RMR not ready yet!")
348 }
349
350 return a.rmrReady
Mohamed Abukar3e038152020-03-04 10:01:45 +0200351}
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300352
vipin541eb502020-09-22 12:04:59 +0000353func (a *AlarmManager) ConfigChangeCB(configparam string) {
354
355 a.maxActiveAlarms = app.Config.GetInt("controls.maxActiveAlarms")
356 a.maxAlarmHistory = app.Config.GetInt("controls.maxAlarmHistory")
Anssi Mannila4450a892020-09-25 10:24:29 +0300357 a.alertInterval = viper.GetInt("controls.promAlertManager.alertInterval")
358 a.amHost = viper.GetString("controls.promAlertManager.address")
vipin541eb502020-09-22 12:04:59 +0000359
360 app.Logger.Debug("ConfigChangeCB: maxActiveAlarms %v", a.maxActiveAlarms)
361 app.Logger.Debug("ConfigChangeCB: maxAlarmHistory = %v", a.maxAlarmHistory)
Anssi Mannila4450a892020-09-25 10:24:29 +0300362 app.Logger.Debug("ConfigChangeCB: alertInterval %v", a.alertInterval)
363 app.Logger.Debug("ConfigChangeCB: amHost = %v", a.amHost)
vipin541eb502020-09-22 12:04:59 +0000364
365 return
366}
367
vipin14323a92020-09-25 10:03:43 +0000368func (a *AlarmManager) ReadAlarmDefinitionFromJson() {
369
370 filename := os.Getenv("DEF_FILE")
371 file, err := ioutil.ReadFile(filename)
372 if err == nil {
373 data := RicAlarmDefinitions{}
374 err = json.Unmarshal([]byte(file), &data)
375 if err == nil {
376 for _, alarmDefinition := range data.AlarmDefinitions {
377 _, exists := alarm.RICAlarmDefinitions[alarmDefinition.AlarmId]
378 if exists {
379 app.Logger.Error("ReadAlarmDefinitionFromJson: alarm definition already exists for %v", alarmDefinition.AlarmId)
380 } else {
381 app.Logger.Debug("ReadAlarmDefinitionFromJson: alarm %v", alarmDefinition.AlarmId)
382 ricAlarmDefintion := new(alarm.AlarmDefinition)
383 ricAlarmDefintion.AlarmId = alarmDefinition.AlarmId
384 ricAlarmDefintion.AlarmText = alarmDefinition.AlarmText
385 ricAlarmDefintion.EventType = alarmDefinition.EventType
386 ricAlarmDefintion.OperationInstructions = alarmDefinition.OperationInstructions
Anssi Mannila18fd03c2020-10-29 10:01:00 +0200387 ricAlarmDefintion.RaiseDelay = alarmDefinition.RaiseDelay
388 ricAlarmDefintion.ClearDelay = alarmDefinition.ClearDelay
vipin14323a92020-09-25 10:03:43 +0000389 alarm.RICAlarmDefinitions[alarmDefinition.AlarmId] = ricAlarmDefintion
390 }
391 }
392 } else {
vipin6f73fa32020-10-06 06:51:53 +0000393 app.Logger.Error("ReadAlarmDefinitionFromJson: json.Unmarshal failed with error %v", err)
vipin14323a92020-09-25 10:03:43 +0000394 }
395 } else {
vipin6f73fa32020-10-06 06:51:53 +0000396 app.Logger.Error("ReadAlarmDefinitionFromJson: ioutil.ReadFile failed with error %v", err)
vipin14323a92020-09-25 10:03:43 +0000397 }
398}
399
vipin78b2b0a2020-10-28 10:10:18 +0000400func (a *AlarmManager) ReadAlarmInfoFromPersistentVolume() {
401 var alarmpersistentinfo AlarmPersistentInfo
402 byteValue, rerr := ioutil.ReadFile(a.alarmInfoPvFile)
403 if rerr != nil {
404 app.Logger.Error("ararminfo.json file read error %v", rerr)
405 } else {
406 err := json.Unmarshal(byteValue, &alarmpersistentinfo)
407 if err != nil {
408 app.Logger.Error("alarmpersistentinfo json unmarshal error %v", err)
409 } else {
410 a.uniqueAlarmId = alarmpersistentinfo.UniqueAlarmId
411 a.activeAlarms = make([]AlarmNotification, len(alarmpersistentinfo.ActiveAlarms))
412 a.alarmHistory = make([]AlarmNotification, len(alarmpersistentinfo.AlarmHistory))
413 copy(a.activeAlarms, alarmpersistentinfo.ActiveAlarms)
414 copy(a.alarmHistory, alarmpersistentinfo.AlarmHistory)
415 }
416 }
417}
418
419func (a *AlarmManager) WriteAlarmInfoToPersistentVolume() {
420 var alarmpersistentinfo AlarmPersistentInfo
421 alarmpersistentinfo.UniqueAlarmId = a.uniqueAlarmId
422 alarmpersistentinfo.ActiveAlarms = make([]AlarmNotification, len(a.activeAlarms))
423 alarmpersistentinfo.AlarmHistory = make([]AlarmNotification, len(a.alarmHistory))
424 copy(alarmpersistentinfo.ActiveAlarms, a.activeAlarms)
425 copy(alarmpersistentinfo.AlarmHistory, a.alarmHistory)
426 wdata, err := json.MarshalIndent(alarmpersistentinfo, "", " ")
427 if err != nil {
428 app.Logger.Error("alarmpersistentinfo json marshal error %v", err)
429 } else {
430 werr := ioutil.WriteFile(a.alarmInfoPvFile, wdata, 0777)
431 if werr != nil {
432 app.Logger.Error("alarminfo.json file write error %v", werr)
433 }
434 }
435}
436
Abukar Mohamed121e8b62020-09-18 11:41:33 +0000437func (a *AlarmManager) Run(sdlcheck bool) {
438 app.Logger.SetMdc("alarmManager", fmt.Sprintf("%s:%s", Version, Hash))
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300439 app.SetReadyCB(func(d interface{}) { a.rmrReady = true }, true)
440 app.Resource.InjectStatusCb(a.StatusCB)
vipin541eb502020-09-22 12:04:59 +0000441 app.AddConfigChangeListener(a.ConfigChangeCB)
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300442
vipin54a3a4f2020-09-23 12:19:58 +0000443 alarm.RICAlarmDefinitions = make(map[int]*alarm.AlarmDefinition)
vipin14323a92020-09-25 10:03:43 +0000444 a.ReadAlarmDefinitionFromJson()
vipin54a3a4f2020-09-23 12:19:58 +0000445
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300446 app.Resource.InjectRoute("/ric/v1/alarms", a.RaiseAlarm, "POST")
447 app.Resource.InjectRoute("/ric/v1/alarms", a.ClearAlarm, "DELETE")
448 app.Resource.InjectRoute("/ric/v1/alarms/active", a.GetActiveAlarms, "GET")
449 app.Resource.InjectRoute("/ric/v1/alarms/history", a.GetAlarmHistory, "GET")
vipin541eb502020-09-22 12:04:59 +0000450 app.Resource.InjectRoute("/ric/v1/alarms/config", a.SetAlarmConfig, "POST")
451 app.Resource.InjectRoute("/ric/v1/alarms/config", a.GetAlarmConfig, "GET")
vipin54a3a4f2020-09-23 12:19:58 +0000452 app.Resource.InjectRoute("/ric/v1/alarms/define", a.SetAlarmDefinition, "POST")
453 app.Resource.InjectRoute("/ric/v1/alarms/define/{alarmId}", a.DeleteAlarmDefinition, "DELETE")
454 app.Resource.InjectRoute("/ric/v1/alarms/define", a.GetAlarmDefinition, "GET")
vipin4cedd502020-09-25 05:58:31 +0000455 app.Resource.InjectRoute("/ric/v1/alarms/define/{alarmId}", a.GetAlarmDefinition, "GET")
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300456
457 // Start background timer for re-raising alerts
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300458 go a.StartAlertTimer()
vipin541eb502020-09-22 12:04:59 +0000459 a.alarmClient, _ = alarm.InitAlarm("SEP", "ALARMMANAGER")
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300460
vipin78b2b0a2020-10-28 10:10:18 +0000461 a.ReadAlarmInfoFromPersistentVolume()
462
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300463 app.RunWithParams(a, sdlcheck)
464}
465
Mohamed Abukar105030f2020-10-22 18:08:34 +0300466func NewAlarmManager(amHost string, alertInterval int, clearAlarm bool) *AlarmManager {
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300467 if alertInterval == 0 {
468 alertInterval = viper.GetInt("controls.promAlertManager.alertInterval")
469 }
470
471 if amHost == "" {
472 amHost = viper.GetString("controls.promAlertManager.address")
473 }
474
Abukar Mohamed121e8b62020-09-18 11:41:33 +0000475 return &AlarmManager{
Mohamed Abukarf5a8e712020-10-19 16:58:17 +0300476 rmrReady: false,
Mohamed Abukar105030f2020-10-22 18:08:34 +0300477 postClear: clearAlarm,
Mohamed Abukarf5a8e712020-10-19 16:58:17 +0300478 amHost: amHost,
Mohamed Abukar105030f2020-10-22 18:08:34 +0300479 amBaseUrl: app.Config.GetString("controls.promAlertManager.baseUrl"),
480 amSchemes: []string{app.Config.GetString("controls.promAlertManager.schemes")},
Mohamed Abukarf5a8e712020-10-19 16:58:17 +0300481 alertInterval: alertInterval,
Mohamed Abukar105030f2020-10-22 18:08:34 +0300482 activeAlarms: make([]AlarmNotification, 0),
483 alarmHistory: make([]AlarmNotification, 0),
484 uniqueAlarmId: 0,
Mohamed Abukarf5a8e712020-10-19 16:58:17 +0300485 maxActiveAlarms: app.Config.GetInt("controls.maxActiveAlarms"),
486 maxAlarmHistory: app.Config.GetInt("controls.maxAlarmHistory"),
vipin6f73fa32020-10-06 06:51:53 +0000487 exceededActiveAlarmOn: false,
488 exceededAlarmHistoryOn: false,
vipin78b2b0a2020-10-28 10:10:18 +0000489 alarmInfoPvFile: app.Config.GetString("controls.alarmInfoPvFile"),
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300490 }
491}
492
493// Main function
494func main() {
Mohamed Abukar105030f2020-10-22 18:08:34 +0300495 NewAlarmManager("", 0, true).Run(true)
Mohamed Abukar540ceee2020-09-09 08:07:40 +0300496}