2246abee0c03162330502b37adf7da63f7a7176d
[ric-plt/alarm-go.git] / alarm / alarm.go
1 /*
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  */
20
21 package alarm
22
23 import (
24         "encoding/json"
25         "errors"
26         "fmt"
27         "log"
28         "sync"
29         "time"
30         "unsafe"
31 )
32
33 /*
34 #cgo CFLAGS: -I../
35 #cgo LDFLAGS: -lrmr_nng -lnng
36
37 #include "utils.h"
38 */
39 import "C"
40
41 // Severity for alarms
42 type Severity string
43
44 // Possible values for Severity
45 const (
46         SeverityUnspecified Severity = "UNSPECIFIED"
47         SeverityCritical    Severity = "CRITICAL"
48         SeverityMajor       Severity = "MAJOR"
49         SeverityMinor       Severity = "MINOR"
50         SeverityWarning     Severity = "WARNING"
51         SeverityNormal      Severity = "CLEARED"
52         SeverityDefault     Severity = "DEFAULT"
53 )
54
55 // Alarm object - see README for more information
56 type Alarm struct {
57         ManagedObjectId   string   `json:"managedObjectId"`
58         ApplicationId     string   `json:"applicationId"`
59         SpecificProblem   int      `json:"specificProblem"`
60         PerceivedSeverity Severity `json:"perceivedSeverity"`
61         AdditionalInfo    string   `json:"additionalInfo"`
62         IdentifyingInfo   string   `json:"identifyingInfo"`
63 }
64
65 // Alarm actions
66 type AlarmAction string
67
68 // Possible values for alarm actions
69 const (
70         AlarmActionRaise    AlarmAction = "RAISE"
71         AlarmActionClear    AlarmAction = "CLEAR"
72         AlarmActionReraise  AlarmAction = "RERAISE"
73         AlarmActionClearAll AlarmAction = "CLEARALL"
74 )
75
76 type AlarmMessage struct {
77         Alarm
78         AlarmAction
79         AlarmTime int64
80 }
81
82 // RICAlarm is an alarm instance
83 type RICAlarm struct {
84         moId   string
85         appId  string
86         rmrCtx unsafe.Pointer
87         mutex  sync.Mutex
88 }
89
90 // InitAlarm is the init routine which returns a new alarm instance.
91 // The MO and APP identities are given as a parameters.
92 // The identities are used when raising/clearing alarms, unless provided by the applications.
93 func InitAlarm(mo, id string) (*RICAlarm, error) {
94         if ctx := C.rmrInit(); ctx != nil {
95                 r := &RICAlarm{
96                         moId:   mo,
97                         appId:  id,
98                         rmrCtx: ctx,
99                 }
100
101                 return r, nil
102         }
103
104         return nil, errors.New("rmrInit failed!")
105 }
106
107 // Create a new Alarm instance
108 func (r *RICAlarm) NewAlarm(sp int, severity Severity, ainfo, iinfo string) Alarm {
109         return Alarm{
110                 ManagedObjectId:   r.moId,
111                 ApplicationId:     r.appId,
112                 SpecificProblem:   sp,
113                 PerceivedSeverity: severity,
114                 AdditionalInfo:    ainfo,
115                 IdentifyingInfo:   iinfo,
116         }
117 }
118
119 // Create a new AlarmMessage instance
120 func (r *RICAlarm) NewAlarmMessage(a Alarm, alarmAction AlarmAction) AlarmMessage {
121         alarmTime := time.Now().UnixNano() / 1000
122         return AlarmMessage{a, alarmAction, alarmTime}
123 }
124
125 // Raise a RIC alarm
126 func (r *RICAlarm) Raise(a Alarm) error {
127         r.mutex.Lock()
128         defer r.mutex.Unlock()
129
130         m := r.NewAlarmMessage(a, AlarmActionRaise)
131         return r.SendMessage(m)
132 }
133
134 // Clear a RIC alarm
135 func (r *RICAlarm) Clear(a Alarm) error {
136         r.mutex.Lock()
137         defer r.mutex.Unlock()
138
139         m := r.NewAlarmMessage(a, AlarmActionClear)
140         return r.SendMessage(m)
141 }
142
143 // Re-raise a RIC alarm
144 func (r *RICAlarm) Reraise(a Alarm) error {
145         r.mutex.Lock()
146         defer r.mutex.Unlock()
147
148         m := r.NewAlarmMessage(a, AlarmActionReraise)
149         return r.SendMessage(m)
150 }
151
152 // Clear all alarms raised by the application
153 func (r *RICAlarm) ClearAll() error {
154         r.mutex.Lock()
155         defer r.mutex.Unlock()
156
157         a := r.NewAlarm(0, SeverityDefault, "", "")
158         m := r.NewAlarmMessage(a, AlarmActionClearAll)
159
160         return r.SendMessage(m)
161 }
162
163 // Internal functions
164 func (r *RICAlarm) AlarmString(a AlarmMessage) string {
165         s := "MOId=%s AppId=%s SP=%d severity=%s IA=%s"
166         return fmt.Sprintf(s, a.ManagedObjectId, a.ApplicationId, a.SpecificProblem, a.PerceivedSeverity, a.IdentifyingInfo)
167 }
168
169 func (r *RICAlarm) SendMessage(a AlarmMessage) error {
170         log.Println("Sending alarm:", r.AlarmString(a))
171
172         payload, err := json.Marshal(a)
173         if err != nil {
174                 return err
175         }
176
177         datap := C.CBytes(payload)
178         defer C.free(datap)
179         meid := C.CString("ric")
180         defer C.free(unsafe.Pointer(meid))
181
182         if state := C.rmrSend(r.rmrCtx, 1234, datap, C.int(len(payload)), meid); state != C.RMR_OK {
183                 return errors.New(fmt.Sprintf("rmrSend failed with error: %d", state))
184         }
185         return nil
186 }
187
188 func (r *RICAlarm) ReceiveMessage(cb func(AlarmMessage)) error {
189         if rbuf := C.rmrRcv(r.rmrCtx); rbuf != nil {
190                 payload := C.GoBytes(unsafe.Pointer(rbuf.payload), C.int(rbuf.len))
191                 a := AlarmMessage{}
192                 if err := json.Unmarshal(payload, &a); err == nil {
193                         cb(a)
194                 }
195         }
196         return errors.New("rmrRcv failed!")
197 }