Release image 0.4.4
[ric-plt/alarm-go.git] / adapter / cmd / adapter.go
index bd491a5..7fa1f3b 100755 (executable)
@@ -23,6 +23,7 @@ package main
 import (
        "encoding/json"
        "fmt"
+       "sync"
        "time"
 
        clientruntime "github.com/go-openapi/runtime/client"
@@ -36,28 +37,22 @@ import (
        app "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
 )
 
+type AlertStatus string
+
+const (
+       AlertStatusActive   = "active"
+       AlertStatusResolved = "resolved"
+)
+
 type AlarmAdapter struct {
        amHost        string
        amBaseUrl     string
        amSchemes     []string
        alertInterval int
        activeAlarms  []alarm.Alarm
+       mutex         sync.Mutex
        rmrReady      bool
-}
-
-// Temp alarm constants & definitions
-const (
-       RIC_RT_DISTRIBUTION_FAILED     int = 8004
-       CONNECTIVITY_LOST_TO_DBAAS     int = 8005
-       E2_CONNECTIVITY_LOST_TO_GNODEB int = 8006
-       E2_CONNECTIVITY_LOST_TO_ENODEB int = 8007
-)
-
-var alarmDefinitions = map[int]string{
-       RIC_RT_DISTRIBUTION_FAILED:     "RIC ROUTING TABLE DISTRIBUTION FAILED",
-       CONNECTIVITY_LOST_TO_DBAAS:     "CONNECTIVITY LOST TO DBAAS",
-       E2_CONNECTIVITY_LOST_TO_GNODEB: "E2 CONNECTIVITY LOST TO G-NODEB",
-       E2_CONNECTIVITY_LOST_TO_ENODEB: "E2 CONNECTIVITY LOST TO E-NODEB",
+       postClear     bool
 }
 
 var Version string
@@ -92,10 +87,12 @@ func (a *AlarmAdapter) Run(sdlcheck bool) {
        app.SetReadyCB(func(d interface{}) { a.rmrReady = true }, true)
        app.Resource.InjectStatusCb(a.StatusCB)
 
-       app.Resource.InjectRoute("/ric/v1/alarm", a.GetActiveAlarms, "GET")
-       app.Resource.InjectRoute("/ric/v1/alarm", a.GenerateAlarm, "POST")
+       app.Resource.InjectRoute("/ric/v1/alarms", a.GetActiveAlarms, "GET")
+       app.Resource.InjectRoute("/ric/v1/alarms", a.RaiseAlarm, "POST")
+       app.Resource.InjectRoute("/ric/v1/alarms", a.ClearAlarm, "DELETE")
 
        // Start background timer for re-raising alerts
+       a.postClear = sdlcheck
        go a.StartAlertTimer()
 
        app.RunWithParams(a, sdlcheck)
@@ -104,10 +101,12 @@ func (a *AlarmAdapter) Run(sdlcheck bool) {
 func (a *AlarmAdapter) StartAlertTimer() {
        tick := time.Tick(time.Duration(a.alertInterval) * time.Millisecond)
        for range tick {
+               a.mutex.Lock()
                for _, m := range a.activeAlarms {
                        app.Logger.Info("Re-raising alarm: %v", m)
-                       a.PostAlert(a.GenerateAlertLabels(m))
+                       a.PostAlert(a.GenerateAlertLabels(m, AlertStatusActive))
                }
+               a.mutex.Unlock()
        }
 }
 
@@ -133,7 +132,7 @@ func (a *AlarmAdapter) HandleAlarms(rp *app.RMRParams) (*alert.PostAlertsOK, err
        }
        app.Logger.Info("newAlarm: %v", m)
 
-       if _, ok := alarmDefinitions[m.Alarm.SpecificProblem]; !ok {
+       if _, ok := alarm.RICAlarmDefinitions[m.Alarm.SpecificProblem]; !ok {
                app.Logger.Warn("Alarm (SP='%d') not recognized, ignoring ...", m.Alarm.SpecificProblem)
                return nil, nil
        }
@@ -150,16 +149,19 @@ func (a *AlarmAdapter) HandleAlarms(rp *app.RMRParams) (*alert.PostAlertsOK, err
                if found {
                        a.activeAlarms = a.RemoveAlarm(a.activeAlarms, idx)
                        app.Logger.Info("Active alarm cleared!")
-               } else {
-                       app.Logger.Info("No matching alarm found, ignoring!")
+
+                       if a.postClear {
+                               return a.PostAlert(a.GenerateAlertLabels(m.Alarm, AlertStatusResolved))
+                       }
                }
+               app.Logger.Info("No matching alarm found, ignoring!")
                return nil, nil
        }
 
        // New alarm -> update active alarms and post to Alert Manager
        if m.AlarmAction == alarm.AlarmActionRaise {
                a.UpdateActiveAlarms(m.Alarm)
-               return a.PostAlert(a.GenerateAlertLabels(m.Alarm))
+               return a.PostAlert(a.GenerateAlertLabels(m.Alarm, AlertStatusActive))
        }
 
        return nil, nil
@@ -176,25 +178,36 @@ func (a *AlarmAdapter) IsMatchFound(newAlarm alarm.Alarm) (int, bool) {
 }
 
 func (a *AlarmAdapter) RemoveAlarm(alarms []alarm.Alarm, i int) []alarm.Alarm {
+       a.mutex.Lock()
+       defer a.mutex.Unlock()
+
        copy(alarms[i:], alarms[i+1:])
        return alarms[:len(alarms)-1]
 }
 
 func (a *AlarmAdapter) UpdateActiveAlarms(newAlarm alarm.Alarm) {
+       a.mutex.Lock()
+       defer a.mutex.Unlock()
+
        // For now just keep the active alarms in-memory. Use SDL later
        a.activeAlarms = append(a.activeAlarms, newAlarm)
 }
 
-func (a *AlarmAdapter) GenerateAlertLabels(newAlarm alarm.Alarm) (models.LabelSet, models.LabelSet) {
+func (a *AlarmAdapter) GenerateAlertLabels(newAlarm alarm.Alarm, status AlertStatus) (models.LabelSet, models.LabelSet) {
+       alarmDef := alarm.RICAlarmDefinitions[newAlarm.SpecificProblem]
        amLabels := models.LabelSet{
-               "alertname":   alarmDefinitions[newAlarm.SpecificProblem],
+               "status":      string(status),
+               "alertname":   alarmDef.AlarmText,
                "severity":    string(newAlarm.PerceivedSeverity),
                "service":     fmt.Sprintf("%s:%s", newAlarm.ManagedObjectId, newAlarm.ApplicationId),
                "system_name": "RIC",
        }
        amAnnotations := models.LabelSet{
+               "alarm_id":        string(alarmDef.AlarmId),
                "description":     newAlarm.IdentifyingInfo,
                "additional_info": newAlarm.AdditionalInfo,
+               "summary":         alarmDef.EventType,
+               "instructions":    alarmDef.OperationInstructions,
        }
 
        return amLabels, amAnnotations
@@ -216,7 +229,11 @@ func (a *AlarmAdapter) PostAlert(amLabels, amAnnotations models.LabelSet) (*aler
        alertParams := alert.NewPostAlertsParams().WithAlerts(models.PostableAlerts{pa})
 
        app.Logger.Info("Posting alerts: labels: %v, annotations: %v", amLabels, amAnnotations)
-       return a.NewAlertmanagerClient().Alert.PostAlerts(alertParams)
+       ok, err := a.NewAlertmanagerClient().Alert.PostAlerts(alertParams)
+       if err != nil {
+               app.Logger.Error("Posting alerts to '%s/%s' failed with error: %v", a.amHost, a.amBaseUrl, err)
+       }
+       return ok, err
 }
 
 func (a *AlarmAdapter) StatusCB() bool {