Initial alarm library implementation
[ric-plt/alarm-go.git] / alarm / alarm.go
diff --git a/alarm/alarm.go b/alarm/alarm.go
new file mode 100755 (executable)
index 0000000..2246abe
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ *  Copyright (c) 2020 AT&T Intellectual Property.
+ *  Copyright (c) 2020 Nokia.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ * This source code is part of the near-RT RIC (RAN Intelligent Controller)
+ * platform project (RICP).
+ */
+
+package alarm
+
+import (
+       "encoding/json"
+       "errors"
+       "fmt"
+       "log"
+       "sync"
+       "time"
+       "unsafe"
+)
+
+/*
+#cgo CFLAGS: -I../
+#cgo LDFLAGS: -lrmr_nng -lnng
+
+#include "utils.h"
+*/
+import "C"
+
+// Severity for alarms
+type Severity string
+
+// Possible values for Severity
+const (
+       SeverityUnspecified Severity = "UNSPECIFIED"
+       SeverityCritical    Severity = "CRITICAL"
+       SeverityMajor       Severity = "MAJOR"
+       SeverityMinor       Severity = "MINOR"
+       SeverityWarning     Severity = "WARNING"
+       SeverityNormal      Severity = "CLEARED"
+       SeverityDefault     Severity = "DEFAULT"
+)
+
+// Alarm object - see README for more information
+type Alarm struct {
+       ManagedObjectId   string   `json:"managedObjectId"`
+       ApplicationId     string   `json:"applicationId"`
+       SpecificProblem   int      `json:"specificProblem"`
+       PerceivedSeverity Severity `json:"perceivedSeverity"`
+       AdditionalInfo    string   `json:"additionalInfo"`
+       IdentifyingInfo   string   `json:"identifyingInfo"`
+}
+
+// Alarm actions
+type AlarmAction string
+
+// Possible values for alarm actions
+const (
+       AlarmActionRaise    AlarmAction = "RAISE"
+       AlarmActionClear    AlarmAction = "CLEAR"
+       AlarmActionReraise  AlarmAction = "RERAISE"
+       AlarmActionClearAll AlarmAction = "CLEARALL"
+)
+
+type AlarmMessage struct {
+       Alarm
+       AlarmAction
+       AlarmTime int64
+}
+
+// RICAlarm is an alarm instance
+type RICAlarm struct {
+       moId   string
+       appId  string
+       rmrCtx unsafe.Pointer
+       mutex  sync.Mutex
+}
+
+// InitAlarm is the init routine which returns a new alarm instance.
+// The MO and APP identities are given as a parameters.
+// The identities are used when raising/clearing alarms, unless provided by the applications.
+func InitAlarm(mo, id string) (*RICAlarm, error) {
+       if ctx := C.rmrInit(); ctx != nil {
+               r := &RICAlarm{
+                       moId:   mo,
+                       appId:  id,
+                       rmrCtx: ctx,
+               }
+
+               return r, nil
+       }
+
+       return nil, errors.New("rmrInit failed!")
+}
+
+// Create a new Alarm instance
+func (r *RICAlarm) NewAlarm(sp int, severity Severity, ainfo, iinfo string) Alarm {
+       return Alarm{
+               ManagedObjectId:   r.moId,
+               ApplicationId:     r.appId,
+               SpecificProblem:   sp,
+               PerceivedSeverity: severity,
+               AdditionalInfo:    ainfo,
+               IdentifyingInfo:   iinfo,
+       }
+}
+
+// Create a new AlarmMessage instance
+func (r *RICAlarm) NewAlarmMessage(a Alarm, alarmAction AlarmAction) AlarmMessage {
+       alarmTime := time.Now().UnixNano() / 1000
+       return AlarmMessage{a, alarmAction, alarmTime}
+}
+
+// Raise a RIC alarm
+func (r *RICAlarm) Raise(a Alarm) error {
+       r.mutex.Lock()
+       defer r.mutex.Unlock()
+
+       m := r.NewAlarmMessage(a, AlarmActionRaise)
+       return r.SendMessage(m)
+}
+
+// Clear a RIC alarm
+func (r *RICAlarm) Clear(a Alarm) error {
+       r.mutex.Lock()
+       defer r.mutex.Unlock()
+
+       m := r.NewAlarmMessage(a, AlarmActionClear)
+       return r.SendMessage(m)
+}
+
+// Re-raise a RIC alarm
+func (r *RICAlarm) Reraise(a Alarm) error {
+       r.mutex.Lock()
+       defer r.mutex.Unlock()
+
+       m := r.NewAlarmMessage(a, AlarmActionReraise)
+       return r.SendMessage(m)
+}
+
+// Clear all alarms raised by the application
+func (r *RICAlarm) ClearAll() error {
+       r.mutex.Lock()
+       defer r.mutex.Unlock()
+
+       a := r.NewAlarm(0, SeverityDefault, "", "")
+       m := r.NewAlarmMessage(a, AlarmActionClearAll)
+
+       return r.SendMessage(m)
+}
+
+// Internal functions
+func (r *RICAlarm) AlarmString(a AlarmMessage) string {
+       s := "MOId=%s AppId=%s SP=%d severity=%s IA=%s"
+       return fmt.Sprintf(s, a.ManagedObjectId, a.ApplicationId, a.SpecificProblem, a.PerceivedSeverity, a.IdentifyingInfo)
+}
+
+func (r *RICAlarm) SendMessage(a AlarmMessage) error {
+       log.Println("Sending alarm:", r.AlarmString(a))
+
+       payload, err := json.Marshal(a)
+       if err != nil {
+               return err
+       }
+
+       datap := C.CBytes(payload)
+       defer C.free(datap)
+       meid := C.CString("ric")
+       defer C.free(unsafe.Pointer(meid))
+
+       if state := C.rmrSend(r.rmrCtx, 1234, datap, C.int(len(payload)), meid); state != C.RMR_OK {
+               return errors.New(fmt.Sprintf("rmrSend failed with error: %d", state))
+       }
+       return nil
+}
+
+func (r *RICAlarm) ReceiveMessage(cb func(AlarmMessage)) error {
+       if rbuf := C.rmrRcv(r.rmrCtx); rbuf != nil {
+               payload := C.GoBytes(unsafe.Pointer(rbuf.payload), C.int(rbuf.len))
+               a := AlarmMessage{}
+               if err := json.Unmarshal(payload, &a); err == nil {
+                       cb(a)
+               }
+       }
+       return errors.New("rmrRcv failed!")
+}