14 "gerrit.o-ran-sc.org/r/ric-plt/alarm-go/alarm"
15 clientruntime "github.com/go-openapi/runtime/client"
16 "github.com/go-openapi/strfmt"
17 "github.com/jedib0t/go-pretty/table"
18 "github.com/prometheus/alertmanager/api/v2/client"
19 "github.com/prometheus/alertmanager/api/v2/client/alert"
20 "github.com/thatisuday/commando"
21 "github.com/spf13/viper"
24 type CliAlarmDefinitions struct {
25 AlarmDefinitions []*alarm.AlarmDefinition `json:"alarmdefinitions"`
28 type AlarmClient struct {
29 alarmer *alarm.RICAlarm
32 type RicPerfAlarmObjects struct {
33 AlarmObjects []*alarm.Alarm `json:"alarmobjects"`
36 var CLIPerfAlarmObjects map[int]*alarm.Alarm
40 var CliPerfAlarmDefinitions CliAlarmDefinitions
43 Raise string = "RAISE"
44 Clear string = "CLEAR"
46 PeakTestDuration int = 60
47 OneSecondDuration int = 1
54 SetExecutableName("alarm-cli").
56 SetDescription("This CLI tool provides management interface to SEP alarm system")
61 SetShortDescription("Displays the SEP active alarms").
62 SetDescription("This command displays more information about the SEP active alarms").
63 AddFlag("host", "Alarm manager host address", commando.String, "localhost").
64 AddFlag("port", "Alarm manager host address", commando.String, "8080").
65 SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) {
66 displayAlarms(getAlarms(flags, "active"), false)
72 SetShortDescription("Displays the SEP alarm history").
73 SetDescription("This command displays more information about the SEP alarm history").
74 AddFlag("host", "Alarm manager host address", commando.String, "localhost").
75 AddFlag("port", "Alarm manager host address", commando.String, "8080").
76 SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) {
77 displayAlarms(getAlarms(flags, "history"), true)
83 SetShortDescription("Raises alarm with given parameters").
84 AddFlag("moid", "Managed object Id", commando.String, nil).
85 AddFlag("apid", "Application Id", commando.String, nil).
86 AddFlag("sp", "Specific problem Id", commando.Int, nil).
87 AddFlag("severity", "Perceived severity", commando.String, nil).
88 AddFlag("iinfo", "Application identifying info", commando.String, nil).
89 AddFlag("aai", "Application additional info", commando.String, "-").
90 AddFlag("host", "Alarm manager host address", commando.String, "localhost").
91 AddFlag("port", "Alarm manager host address", commando.String, "8080").
92 AddFlag("if", "http or rmr used as interface", commando.String, "http").
93 SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) {
94 postAlarm(flags, readAlarmParams(flags, false), alarm.AlarmActionRaise, nil)
100 SetShortDescription("Raises alarm with given parameters").
101 AddFlag("moid", "Managed object Id", commando.String, nil).
102 AddFlag("apid", "Application Id", commando.String, nil).
103 AddFlag("sp", "Specific problem Id", commando.Int, nil).
104 AddFlag("iinfo", "Application identifying info", commando.String, nil).
105 AddFlag("host", "Alarm manager host address", commando.String, "localhost").
106 AddFlag("port", "Alarm manager host address", commando.String, "8080").
107 AddFlag("if", "http or rmr used as interface", commando.String, "http").
108 SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) {
109 postAlarm(flags, readAlarmParams(flags, true), alarm.AlarmActionClear, nil)
112 // Configure an alarm manager
114 Register("configure").
115 SetShortDescription("Configure alarm manager with given parameters").
116 AddFlag("mal", "max active alarms", commando.Int, nil).
117 AddFlag("mah", "max alarm history", commando.Int, nil).
118 AddFlag("host", "Alarm manager host address", commando.String, "localhost").
119 AddFlag("port", "Alarm manager host address", commando.String, "8080").
120 SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) {
121 postAlarmConfig(flags)
123 // Create alarm definition
126 SetShortDescription("Define alarm with given parameters").
127 AddFlag("aid", "alarm identifier", commando.Int, nil).
128 AddFlag("atx", "alarm text", commando.String, nil).
129 AddFlag("ety", "event type", commando.String, nil).
130 AddFlag("oin", "operation instructions", commando.String, nil).
131 AddFlag("host", "Alarm manager host address", commando.String, "localhost").
132 AddFlag("port", "Alarm manager host address", commando.String, "8080").
133 SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) {
134 postAlarmDefinition(flags)
136 // Delete alarm definition
138 Register("undefine").
139 SetShortDescription("Define alarm with given parameters").
140 AddFlag("aid", "alarm identifier", commando.Int, nil).
141 AddFlag("host", "Alarm manager host address", commando.String, "localhost").
142 AddFlag("port", "Alarm manager host address", commando.String, "8080").
143 SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) {
144 deleteAlarmDefinition(flags)
146 // Conduct performance test for alarm-go
149 SetShortDescription("Conduct performance test with given parameters").
150 AddFlag("prf", "performance profile id", commando.Int, nil).
151 AddFlag("nal", "number of alarms", commando.Int, nil).
152 AddFlag("aps", "alarms per sec", commando.Int, nil).
153 AddFlag("tim", "total time of test", commando.Int, nil).
154 AddFlag("host", "Alarm manager host address", commando.String, "localhost").
155 AddFlag("port", "Alarm manager host address", commando.String, "8080").
156 AddFlag("if", "http or rmr used as interface", commando.String, "http").
157 SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) {
158 conductperformancetest(flags)
161 // Get alerts from Prometheus Alert Manager
164 SetShortDescription("Get alerts from Prometheus Alert Manager").
165 AddFlag("active", "Active alerts in Prometheus Alert Manager", commando.Bool, true).
166 AddFlag("inhibited", "Inhibited alerts in Prometheus Alert Manager", commando.Bool, true).
167 AddFlag("silenced", "Silenced alerts in Prometheus Alert Manager", commando.Bool, true).
168 AddFlag("unprocessed", "Unprocessed alerts in Prometheus Alert Manager", commando.Bool, true).
169 AddFlag("host", "Prometheus Alert Manager host address", commando.String, nil).
170 AddFlag("port", "Prometheus Alert Manager port", commando.String, "9093").
171 SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) {
175 // parse command-line arguments
179 func readAlarmParams(flags map[string]commando.FlagValue, clear bool) (a alarm.Alarm) {
180 a.ManagedObjectId, _ = flags["moid"].GetString()
181 a.ApplicationId, _ = flags["apid"].GetString()
182 a.SpecificProblem, _ = flags["sp"].GetInt()
183 a.IdentifyingInfo, _ = flags["iinfo"].GetString()
186 s, _ := flags["severity"].GetString()
187 a.PerceivedSeverity = alarm.Severity(s)
191 a.AdditionalInfo, _ = flags["aai"].GetString()
196 func getAlarms(flags map[string]commando.FlagValue, action alarm.AlarmAction) (alarms []alarm.AlarmMessage) {
197 host, _ := flags["host"].GetString()
198 port, _ := flags["port"].GetString()
199 targetUrl := fmt.Sprintf("http://%s:%s/ric/v1/alarms/%s", host, port, action)
200 resp, err := http.Get(targetUrl)
201 if err != nil || resp == nil || resp.Body == nil {
202 fmt.Println("Couldn't fetch active alarm list due to error: ", err)
206 defer resp.Body.Close()
208 body, err := ioutil.ReadAll(resp.Body)
210 fmt.Println("ioutil.ReadAll failed: ", err)
214 json.Unmarshal([]byte(body), &alarms)
218 func postAlarmWithRmrIf(a alarm.Alarm, action alarm.AlarmAction, alarmClient *AlarmClient) {
219 if alarmClient == nil {
220 alarmClient = NewAlarmClient("my-pod", "my-app")
222 if alarmClient == nil {
226 // Wait until RMR is up-and-running
227 for !alarmClient.alarmer.IsRMRReady() {
228 time.Sleep(100 * time.Millisecond)
231 if action == alarm.AlarmActionRaise {
232 alarmClient.alarmer.Raise(a)
235 if action == alarm.AlarmActionClear {
236 alarmClient.alarmer.Clear(a)
241 func postAlarmWithHttpIf(targetUrl string, a alarm.Alarm, action alarm.AlarmAction) {
242 m := alarm.AlarmMessage{Alarm: a, AlarmAction: action}
243 jsonData, err := json.Marshal(m)
245 fmt.Println("json.Marshal failed: ", err)
249 resp, err := http.Post(targetUrl, "application/json", bytes.NewBuffer(jsonData))
250 if err != nil || resp == nil {
251 fmt.Println("Couldn't fetch active alarm list due to error: ", err)
256 func postAlarm(flags map[string]commando.FlagValue, a alarm.Alarm, action alarm.AlarmAction, alarmClient *AlarmClient) {
257 // Check the interface to be used for raise or clear the alarm
258 rmr_or_http, _ := flags["if"].GetString()
259 if rmr_or_http == "rmr" {
260 postAlarmWithRmrIf(a, action, alarmClient)
263 host, _ := flags["host"].GetString()
264 port, _ := flags["port"].GetString()
265 targetUrl := fmt.Sprintf("http://%s:%s/ric/v1/alarms", host, port)
266 postAlarmWithHttpIf(targetUrl, a, action)
270 func displayAlarms(alarms []alarm.AlarmMessage, isHistory bool) {
271 t := table.NewWriter()
272 t.SetOutputMirror(os.Stdout)
274 t.AppendHeader(table.Row{"SP", "MOID", "APPID", "IINFO", "SEVERITY", "AAI", "ACTION", "TIME"})
276 t.AppendHeader(table.Row{"SP", "MOID", "APPID", "IINFO", "SEVERITY", "AAI", "TIME"})
279 for _, a := range alarms {
280 alarmTime := time.Unix(0, a.AlarmTime).Format("02/01/2006, 15:04:05")
282 t.AppendRows([]table.Row{
283 {a.SpecificProblem, a.ManagedObjectId, a.ApplicationId, a.IdentifyingInfo, a.PerceivedSeverity, a.AdditionalInfo, a.AlarmAction, alarmTime},
286 t.AppendRows([]table.Row{
287 {a.SpecificProblem, a.ManagedObjectId, a.ApplicationId, a.IdentifyingInfo, a.PerceivedSeverity, a.AdditionalInfo, alarmTime},
292 t.SetStyle(table.StyleColoredBright)
296 func postAlarmConfig(flags map[string]commando.FlagValue) {
297 host, _ := flags["host"].GetString()
298 port, _ := flags["port"].GetString()
299 maxactivealarms, _ := flags["mal"].GetInt()
300 maxalarmhistory, _ := flags["mah"].GetInt()
301 targetUrl := fmt.Sprintf("http://%s:%s/ric/v1/alarms/config", host, port)
303 m := alarm.AlarmConfigParams{MaxActiveAlarms: maxactivealarms, MaxAlarmHistory: maxalarmhistory}
304 jsonData, err := json.Marshal(m)
306 fmt.Println("json.Marshal failed: ", err)
310 resp, err := http.Post(targetUrl, "application/json", bytes.NewBuffer(jsonData))
311 if err != nil || resp == nil {
312 fmt.Println("Couldn't fetch post alarm configuration due to error: ", err)
317 func postAlarmDefinition(flags map[string]commando.FlagValue) {
318 host, _ := flags["host"].GetString()
319 port, _ := flags["port"].GetString()
320 alarmid, _ := flags["aid"].GetInt()
321 alarmtxt, _ := flags["atx"].GetString()
322 etype, _ := flags["ety"].GetString()
323 operation, _ := flags["oin"].GetString()
324 targetUrl := fmt.Sprintf("http://%s:%s/ric/v1/alarms/define", host, port)
326 var alarmdefinition alarm.AlarmDefinition
327 alarmdefinition.AlarmId = alarmid
328 alarmdefinition.AlarmText = alarmtxt
329 alarmdefinition.EventType = etype
330 alarmdefinition.OperationInstructions = operation
332 m := CliAlarmDefinitions{AlarmDefinitions: []*alarm.AlarmDefinition{&alarmdefinition}}
333 jsonData, err := json.Marshal(m)
335 fmt.Println("json.Marshal failed: ", err)
339 resp, err := http.Post(targetUrl, "application/json", bytes.NewBuffer(jsonData))
340 if err != nil || resp == nil {
341 fmt.Println("Couldn't post alarm definition due to error: ", err)
346 func deleteAlarmDefinition(flags map[string]commando.FlagValue) {
347 host, _ := flags["host"].GetString()
348 port, _ := flags["port"].GetString()
349 alarmid, _ := flags["aid"].GetInt()
350 salarmid := strconv.FormatUint(uint64(alarmid), 10)
351 targetUrl := fmt.Sprintf("http://%s:%s/ric/v1/alarms/define/%s", host, port, salarmid)
353 client := &http.Client{}
354 req, err := http.NewRequest("DELETE", targetUrl, nil)
355 if err != nil || req == nil {
356 fmt.Println("Couldn't make delete request due to error: ", err)
359 resp, errr := client.Do(req)
360 if errr != nil || resp == nil {
361 fmt.Println("Couldn't send delete request due to error: ", err)
366 // NewAlarmClient returns a new AlarmClient.
367 func NewAlarmClient(moId, appId string) *AlarmClient {
368 alarmInstance, err := alarm.InitAlarm(moId, appId)
371 alarmer: alarmInstance,
374 fmt.Println("Failed to create alarmInstance", err)
378 // Conduct performance testing
379 func conductperformancetest(flags map[string]commando.FlagValue) {
382 var readobjerror error
383 host, _ := flags["host"].GetString()
384 port, _ := flags["port"].GetString()
385 targetUrl := fmt.Sprintf("http://%s:%s/ric/v1/alarms/define", host, port)
386 readerror = readPerfAlarmDefinitionFromJson()
387 if readerror == nil {
388 senderror = sendPerfAlarmDefinitionToAlarmManager(targetUrl)
389 if senderror == nil {
390 fmt.Println("sent performance alarm definitions to alarm manager")
391 CLIPerfAlarmObjects = make(map[int]*alarm.Alarm)
392 readobjerror = readPerfAlarmObjectFromJson()
393 if readobjerror == nil {
394 profile, _ := flags["prf"].GetInt()
396 fmt.Println("starting peak performance test")
397 peakPerformanceTest(flags)
398 } else if profile == 2 {
399 fmt.Println("starting endurance test")
402 fmt.Println("Unknown profile, received profile = ", profile)
405 fmt.Println("reading performance alarm objects from json file failed ")
408 fmt.Println("sending performance alarm definitions to alarm manager failed ")
412 fmt.Println("reading performance alarm definitions from json file failed ")
417 func peakPerformanceTest(flags map[string]commando.FlagValue) {
418 nalarms, _ := flags["nal"].GetInt()
420 for aid, obj := range CLIPerfAlarmObjects {
422 if count <= nalarms {
423 fmt.Println("peakPerformanceTest: invoking worker routine ", count, aid, *obj)
425 go raiseClearAlarmOnce(obj, flags)
430 fmt.Println("peakPerformanceTest: Waiting for workers to finish")
432 fmt.Println("peakPerformanceTest: Wait completed")
435 func enduranceTest(flags map[string]commando.FlagValue) {
436 alarmspersec, _ := flags["aps"].GetInt()
438 for aid, obj := range CLIPerfAlarmObjects {
440 if count <= alarmspersec {
441 fmt.Println("enduranceTest: invoking worker routine ", count, aid, *obj)
443 go raiseClearAlarmOverPeriod(obj, flags)
448 fmt.Println("enduranceTest: Waiting for workers to finish")
450 fmt.Println("enduranceTest: Wait completed")
453 func readPerfAlarmObjectFromJson() error {
454 filename := os.Getenv("PERF_OBJ_FILE")
455 file, err := ioutil.ReadFile(filename)
457 data := RicPerfAlarmObjects{}
458 err = json.Unmarshal([]byte(file), &data)
460 for _, alarmObject := range data.AlarmObjects {
461 ricAlarmObject := new(alarm.Alarm)
462 ricAlarmObject.ManagedObjectId = alarmObject.ManagedObjectId
463 ricAlarmObject.ApplicationId = alarmObject.ApplicationId
464 ricAlarmObject.SpecificProblem = alarmObject.SpecificProblem
465 ricAlarmObject.PerceivedSeverity = alarmObject.PerceivedSeverity
466 ricAlarmObject.AdditionalInfo = alarmObject.AdditionalInfo
467 ricAlarmObject.IdentifyingInfo = alarmObject.IdentifyingInfo
468 CLIPerfAlarmObjects[alarmObject.SpecificProblem] = ricAlarmObject
471 fmt.Println("readPerfAlarmObjectFromJson: json.Unmarshal failed with error ", err)
475 fmt.Println("readPerfAlarmObjectFromJson: ioutil.ReadFile failed with error ", err)
481 func readPerfAlarmDefinitionFromJson() error {
482 filename := os.Getenv("PERF_DEF_FILE")
483 file, err := ioutil.ReadFile(filename)
485 data := CliAlarmDefinitions{}
486 err = json.Unmarshal([]byte(file), &data)
488 for _, alarmDefinition := range data.AlarmDefinitions {
489 _, exists := alarm.RICAlarmDefinitions[alarmDefinition.AlarmId]
491 fmt.Println("ReadPerfAlarmDefinitionFromJson: alarm definition already exists for ", alarmDefinition.AlarmId)
493 fmt.Println("ReadPerfAlarmDefinitionFromJson: alarm ", alarmDefinition.AlarmId)
494 ricAlarmDefintion := new(alarm.AlarmDefinition)
495 ricAlarmDefintion.AlarmId = alarmDefinition.AlarmId
496 ricAlarmDefintion.AlarmText = alarmDefinition.AlarmText
497 ricAlarmDefintion.EventType = alarmDefinition.EventType
498 ricAlarmDefintion.OperationInstructions = alarmDefinition.OperationInstructions
499 CliPerfAlarmDefinitions.AlarmDefinitions = append(CliPerfAlarmDefinitions.AlarmDefinitions, ricAlarmDefintion)
503 fmt.Println("ReadPerfAlarmDefinitionFromJson: json.Unmarshal failed with error: ", err)
507 fmt.Println("ReadPerfAlarmDefinitionFromJson: ioutil.ReadFile failed with error: ", err)
513 func sendPerfAlarmDefinitionToAlarmManager(targetUrl string) error {
515 jsonData, err := json.Marshal(CliPerfAlarmDefinitions)
517 fmt.Println("sendPerfAlarmDefinitionToAlarmManager: json.Marshal failed: ", err)
521 resp, err := http.Post(targetUrl, "application/json", bytes.NewBuffer(jsonData))
522 if err != nil || resp == nil {
523 fmt.Println("sendPerfAlarmDefinitionToAlarmManager: Couldn't post alarm definition to targeturl due to error: ", targetUrl, err)
529 func wakeUpAfterTime(timeinseconds int, chn chan string, action string) {
530 time.Sleep(time.Second * time.Duration(timeinseconds))
534 func raiseClearAlarmOnce(alarmobject *alarm.Alarm, flags map[string]commando.FlagValue) {
535 var alarmClient *AlarmClient = nil
537 chn := make(chan string, 1)
538 rmr_or_http, _ := flags["if"].GetString()
539 if rmr_or_http == "rmr" {
540 alarmClient = NewAlarmClient("my-pod", "my-app")
542 postAlarm(flags, *alarmobject, alarm.AlarmActionRaise, alarmClient)
543 go wakeUpAfterTime(PeakTestDuration, chn, Clear)
547 postAlarm(flags, *alarmobject, alarm.AlarmActionClear, alarmClient)
548 go wakeUpAfterTime(PeakTestDuration, chn, End)
549 } else if res == End {
555 func raiseClearAlarmOverPeriod(alarmobject *alarm.Alarm, flags map[string]commando.FlagValue) {
556 var alarmClient *AlarmClient = nil
558 timeinminutes, _ := flags["tim"].GetInt()
559 timeinseconds := timeinminutes * 60
560 chn := make(chan string, 1)
561 rmr_or_http, _ := flags["if"].GetString()
562 if rmr_or_http == "rmr" {
563 alarmClient = NewAlarmClient("my-pod", "my-app")
565 postAlarm(flags, *alarmobject, alarm.AlarmActionRaise, alarmClient)
566 go wakeUpAfterTime(OneSecondDuration, chn, Clear)
567 go wakeUpAfterTime(timeinseconds, chn, End)
572 postAlarm(flags, *alarmobject, alarm.AlarmActionRaise, alarmClient)
573 go wakeUpAfterTime(OneSecondDuration, chn, Clear)
574 } else if res == Clear {
575 postAlarm(flags, *alarmobject, alarm.AlarmActionClear, alarmClient)
576 go wakeUpAfterTime(OneSecondDuration, chn, Raise)
577 } else if res == End {
584 func displayAlerts(flags map[string]commando.FlagValue) {
585 resp, err := getAlerts(flags)
592 fmt.Println("resp= nil")
596 t := table.NewWriter()
597 t.SetOutputMirror(os.Stdout)
598 t.AppendHeader(table.Row{"Alerts from Prometheus Alert Manager"})
599 for _, gettableAlert := range resp.Payload{
600 t.AppendRow([]interface{}{"------------------------------------"})
601 if gettableAlert != nil {
602 for key, item := range gettableAlert.Annotations {
603 t.AppendRow([]interface{}{key, item})
605 if gettableAlert.EndsAt != nil {
606 t.AppendRow([]interface{}{"EndsAt", *gettableAlert.EndsAt})
608 if gettableAlert.Fingerprint != nil {
609 t.AppendRow([]interface{}{"Fingerprint", *gettableAlert.Fingerprint})
611 for key, item := range gettableAlert.Receivers {
612 if gettableAlert.Receivers != nil {
613 t.AppendRow([]interface{}{key, *item.Name})
616 if gettableAlert.StartsAt != nil {
617 t.AppendRow([]interface{}{"StartsAt", *gettableAlert.StartsAt})
619 if gettableAlert.Status != nil {
620 t.AppendRow([]interface{}{"InhibitedBy", gettableAlert.Status.InhibitedBy})
621 t.AppendRow([]interface{}{"SilencedBy", gettableAlert.Status.SilencedBy})
622 t.AppendRow([]interface{}{"State", *gettableAlert.Status.State})
624 if gettableAlert.UpdatedAt != nil {
625 t.AppendRow([]interface{}{"UpdatedAt", *gettableAlert.UpdatedAt})
627 t.AppendRow([]interface{}{"GeneratorURL", gettableAlert.Alert.GeneratorURL})
628 for key, item := range gettableAlert.Alert.Labels {
629 t.AppendRow([]interface{}{key, item})
633 t.SetStyle(table.StyleColoredBright)
637 func getAlerts(flags map[string]commando.FlagValue) (*alert.GetAlertsOK, error) {
638 active, _ := flags["active"].GetBool()
639 inhibited, _ := flags["inhibited"].GetBool()
640 silenced, _ := flags["silenced"].GetBool()
641 unprocessed, _ := flags["unprocessed"].GetBool()
642 amHost, _ := flags["host"].GetString()
643 amPort, _ := flags["port"].GetString()
646 amAddress = viper.GetString("controls.promAlertManager.address")
648 amAddress = amHost + ":" + amPort
651 alertParams := alert.NewGetAlertsParams()
652 alertParams.Active = &active
653 alertParams.Inhibited = &inhibited
654 alertParams.Silenced = &silenced
655 alertParams.Unprocessed = &unprocessed
656 amBaseUrl := viper.GetString("controls.promAlertManager.baseUrl")
657 amSchemes := []string{viper.GetString("controls.promAlertManager.schemes")}
658 resp, err := newAlertManagerClient(amAddress, amBaseUrl, amSchemes).Alert.GetAlerts(alertParams)
660 err = fmt.Errorf("GetAlerts from '%s%s' failed with error: %v", amAddress, amBaseUrl, err)
665 func newAlertManagerClient(amAddress string, amBaseUrl string, amSchemes []string) *client.Alertmanager {
666 cr := clientruntime.New(amAddress, amBaseUrl, amSchemes)
667 return client.New(cr, strfmt.Default)