| package main |
| |
| import ( |
| "bytes" |
| "encoding/json" |
| "fmt" |
| "io/ioutil" |
| "net/http" |
| "os" |
| "strconv" |
| "time" |
| |
| "gerrit.o-ran-sc.org/r/ric-plt/alarm-go/alarm" |
| "github.com/jedib0t/go-pretty/table" |
| "github.com/thatisuday/commando" |
| "sync" |
| ) |
| |
| type CliAlarmDefinitions struct { |
| AlarmDefinitions []*alarm.AlarmDefinition `json:"alarmdefinitions"` |
| } |
| |
| type AlarmClient struct { |
| alarmer *alarm.RICAlarm |
| } |
| |
| type RicPerfAlarmObjects struct { |
| AlarmObjects []*alarm.Alarm `json:"alarmobjects"` |
| } |
| |
| var CLIPerfAlarmObjects map[int]*alarm.Alarm |
| |
| var wg sync.WaitGroup |
| |
| var CliPerfAlarmDefinitions CliAlarmDefinitions |
| |
| const ( |
| Raise string = "RAISE" |
| Clear string = "CLEAR" |
| End string = "END" |
| PeakTestDuration int = 60 |
| OneSecondDuration int = 1 |
| ) |
| |
| func main() { |
| |
| // configure commando |
| commando. |
| SetExecutableName("alarm-cli"). |
| SetVersion("1.0.0"). |
| SetDescription("This CLI tool provides management interface to SEP alarm system") |
| |
| // Get active alarms |
| commando. |
| Register("active"). |
| SetShortDescription("Displays the SEP active alarms"). |
| SetDescription("This command displays more information about the SEP active alarms"). |
| AddFlag("host", "Alarm manager host address", commando.String, "localhost"). |
| AddFlag("port", "Alarm manager host address", commando.String, "8080"). |
| SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) { |
| displayAlarms(getAlarms(flags, "active"), false) |
| }) |
| |
| // Get alarm history |
| commando. |
| Register("history"). |
| SetShortDescription("Displays the SEP alarm history"). |
| SetDescription("This command displays more information about the SEP alarm history"). |
| AddFlag("host", "Alarm manager host address", commando.String, "localhost"). |
| AddFlag("port", "Alarm manager host address", commando.String, "8080"). |
| SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) { |
| displayAlarms(getAlarms(flags, "history"), true) |
| }) |
| |
| // Raise an alarm |
| commando. |
| Register("raise"). |
| SetShortDescription("Raises alarm with given parameters"). |
| AddFlag("moid", "Managed object Id", commando.String, nil). |
| AddFlag("apid", "Application Id", commando.String, nil). |
| AddFlag("sp", "Specific problem Id", commando.Int, nil). |
| AddFlag("severity", "Perceived severity", commando.String, nil). |
| AddFlag("iinfo", "Application identifying info", commando.String, nil). |
| AddFlag("aai", "Application additional info", commando.String, "-"). |
| AddFlag("host", "Alarm manager host address", commando.String, "localhost"). |
| AddFlag("port", "Alarm manager host address", commando.String, "8080"). |
| AddFlag("if", "http or rmr used as interface", commando.String, "http"). |
| SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) { |
| postAlarm(flags, readAlarmParams(flags, false), alarm.AlarmActionRaise, nil) |
| }) |
| |
| // Clear an alarm |
| commando. |
| Register("clear"). |
| SetShortDescription("Raises alarm with given parameters"). |
| AddFlag("moid", "Managed object Id", commando.String, nil). |
| AddFlag("apid", "Application Id", commando.String, nil). |
| AddFlag("sp", "Specific problem Id", commando.Int, nil). |
| AddFlag("iinfo", "Application identifying info", commando.String, nil). |
| AddFlag("host", "Alarm manager host address", commando.String, "localhost"). |
| AddFlag("port", "Alarm manager host address", commando.String, "8080"). |
| AddFlag("if", "http or rmr used as interface", commando.String, "http"). |
| SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) { |
| postAlarm(flags, readAlarmParams(flags, true), alarm.AlarmActionClear, nil) |
| }) |
| |
| // Configure an alarm manager |
| commando. |
| Register("configure"). |
| SetShortDescription("Configure alarm manager with given parameters"). |
| AddFlag("mal", "max active alarms", commando.Int, nil). |
| AddFlag("mah", "max alarm history", commando.Int, nil). |
| AddFlag("host", "Alarm manager host address", commando.String, "localhost"). |
| AddFlag("port", "Alarm manager host address", commando.String, "8080"). |
| SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) { |
| postAlarmConfig(flags) |
| }) |
| // Create alarm definition |
| commando. |
| Register("define"). |
| SetShortDescription("Define alarm with given parameters"). |
| AddFlag("aid", "alarm identifier", commando.Int, nil). |
| AddFlag("atx", "alarm text", commando.String, nil). |
| AddFlag("ety", "event type", commando.String, nil). |
| AddFlag("oin", "operation instructions", commando.String, nil). |
| AddFlag("host", "Alarm manager host address", commando.String, "localhost"). |
| AddFlag("port", "Alarm manager host address", commando.String, "8080"). |
| SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) { |
| postAlarmDefinition(flags) |
| }) |
| // Delete alarm definition |
| commando. |
| Register("undefine"). |
| SetShortDescription("Define alarm with given parameters"). |
| AddFlag("aid", "alarm identifier", commando.Int, nil). |
| AddFlag("host", "Alarm manager host address", commando.String, "localhost"). |
| AddFlag("port", "Alarm manager host address", commando.String, "8080"). |
| SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) { |
| deleteAlarmDefinition(flags) |
| }) |
| // Conduct performance test for alarm-go |
| commando. |
| Register("perf"). |
| SetShortDescription("Conduct performance test with given parameters"). |
| AddFlag("prf", "performance profile id", commando.Int, nil). |
| AddFlag("nal", "number of alarms", commando.Int, nil). |
| AddFlag("aps", "alarms per sec", commando.Int, nil). |
| AddFlag("tim", "total time of test", commando.Int, nil). |
| AddFlag("host", "Alarm manager host address", commando.String, "localhost"). |
| AddFlag("port", "Alarm manager host address", commando.String, "8080"). |
| AddFlag("if", "http or rmr used as interface", commando.String, "http"). |
| SetAction(func(args map[string]commando.ArgValue, flags map[string]commando.FlagValue) { |
| conductperformancetest(flags) |
| }) |
| |
| // parse command-line arguments |
| commando.Parse(nil) |
| } |
| |
| func readAlarmParams(flags map[string]commando.FlagValue, clear bool) (a alarm.Alarm) { |
| a.ManagedObjectId, _ = flags["moid"].GetString() |
| a.ApplicationId, _ = flags["apid"].GetString() |
| a.SpecificProblem, _ = flags["sp"].GetInt() |
| a.IdentifyingInfo, _ = flags["iinfo"].GetString() |
| |
| if !clear { |
| s, _ := flags["severity"].GetString() |
| a.PerceivedSeverity = alarm.Severity(s) |
| } |
| |
| if !clear { |
| a.AdditionalInfo, _ = flags["aai"].GetString() |
| } |
| return |
| } |
| |
| func getAlarms(flags map[string]commando.FlagValue, action alarm.AlarmAction) (alarms []alarm.AlarmMessage) { |
| host, _ := flags["host"].GetString() |
| port, _ := flags["port"].GetString() |
| targetUrl := fmt.Sprintf("http://%s:%s/ric/v1/alarms/%s", host, port, action) |
| resp, err := http.Get(targetUrl) |
| if err != nil || resp == nil || resp.Body == nil { |
| fmt.Println("Couldn't fetch active alarm list due to error: ", err) |
| return alarms |
| } |
| |
| defer resp.Body.Close() |
| |
| body, err := ioutil.ReadAll(resp.Body) |
| if err != nil { |
| fmt.Println("ioutil.ReadAll failed: ", err) |
| return alarms |
| } |
| |
| json.Unmarshal([]byte(body), &alarms) |
| return alarms |
| } |
| |
| func postAlarmWithRmrIf(a alarm.Alarm, action alarm.AlarmAction, alarmClient *AlarmClient) { |
| if alarmClient == nil { |
| alarmClient = NewAlarmClient("my-pod", "my-app") |
| } |
| if alarmClient == nil { |
| return |
| } |
| |
| // Wait until RMR is up-and-running |
| for !alarmClient.alarmer.IsRMRReady() { |
| time.Sleep(100 * time.Millisecond) |
| } |
| |
| if action == alarm.AlarmActionRaise { |
| alarmClient.alarmer.Raise(a) |
| } |
| |
| if action == alarm.AlarmActionClear { |
| alarmClient.alarmer.Clear(a) |
| } |
| return |
| } |
| |
| func postAlarmWithHttpIf(targetUrl string, a alarm.Alarm, action alarm.AlarmAction) { |
| m := alarm.AlarmMessage{Alarm: a, AlarmAction: action} |
| jsonData, err := json.Marshal(m) |
| if err != nil { |
| fmt.Println("json.Marshal failed: ", err) |
| return |
| } |
| |
| resp, err := http.Post(targetUrl, "application/json", bytes.NewBuffer(jsonData)) |
| if err != nil || resp == nil { |
| fmt.Println("Couldn't fetch active alarm list due to error: ", err) |
| return |
| } |
| } |
| |
| func postAlarm(flags map[string]commando.FlagValue, a alarm.Alarm, action alarm.AlarmAction, alarmClient *AlarmClient) { |
| // Check the interface to be used for raise or clear the alarm |
| rmr_or_http, _ := flags["if"].GetString() |
| if rmr_or_http == "rmr" { |
| postAlarmWithRmrIf(a, action, alarmClient) |
| } else { |
| |
| host, _ := flags["host"].GetString() |
| port, _ := flags["port"].GetString() |
| targetUrl := fmt.Sprintf("http://%s:%s/ric/v1/alarms", host, port) |
| postAlarmWithHttpIf(targetUrl, a, action) |
| } |
| } |
| |
| func displayAlarms(alarms []alarm.AlarmMessage, isHistory bool) { |
| t := table.NewWriter() |
| t.SetOutputMirror(os.Stdout) |
| if isHistory { |
| t.AppendHeader(table.Row{"SP", "MOID", "APPID", "IINFO", "SEVERITY", "AAI", "ACTION", "TIME"}) |
| } else { |
| t.AppendHeader(table.Row{"SP", "MOID", "APPID", "IINFO", "SEVERITY", "AAI", "TIME"}) |
| } |
| |
| for _, a := range alarms { |
| alarmTime := time.Unix(0, a.AlarmTime).Format("02/01/2006, 15:04:05") |
| if isHistory { |
| t.AppendRows([]table.Row{ |
| {a.SpecificProblem, a.ManagedObjectId, a.ApplicationId, a.IdentifyingInfo, a.PerceivedSeverity, a.AdditionalInfo, a.AlarmAction, alarmTime}, |
| }) |
| } else { |
| t.AppendRows([]table.Row{ |
| {a.SpecificProblem, a.ManagedObjectId, a.ApplicationId, a.IdentifyingInfo, a.PerceivedSeverity, a.AdditionalInfo, alarmTime}, |
| }) |
| } |
| } |
| |
| t.SetStyle(table.StyleColoredBright) |
| t.Render() |
| } |
| |
| func postAlarmConfig(flags map[string]commando.FlagValue) { |
| host, _ := flags["host"].GetString() |
| port, _ := flags["port"].GetString() |
| maxactivealarms, _ := flags["mal"].GetInt() |
| maxalarmhistory, _ := flags["mah"].GetInt() |
| targetUrl := fmt.Sprintf("http://%s:%s/ric/v1/alarms/config", host, port) |
| |
| m := alarm.AlarmConfigParams{MaxActiveAlarms: maxactivealarms, MaxAlarmHistory: maxalarmhistory} |
| jsonData, err := json.Marshal(m) |
| if err != nil { |
| fmt.Println("json.Marshal failed: ", err) |
| return |
| } |
| |
| resp, err := http.Post(targetUrl, "application/json", bytes.NewBuffer(jsonData)) |
| if err != nil || resp == nil { |
| fmt.Println("Couldn't fetch post alarm configuration due to error: ", err) |
| return |
| } |
| } |
| |
| func postAlarmDefinition(flags map[string]commando.FlagValue) { |
| host, _ := flags["host"].GetString() |
| port, _ := flags["port"].GetString() |
| alarmid, _ := flags["aid"].GetInt() |
| alarmtxt, _ := flags["atx"].GetString() |
| etype, _ := flags["ety"].GetString() |
| operation, _ := flags["oin"].GetString() |
| targetUrl := fmt.Sprintf("http://%s:%s/ric/v1/alarms/define", host, port) |
| |
| var alarmdefinition alarm.AlarmDefinition |
| alarmdefinition.AlarmId = alarmid |
| alarmdefinition.AlarmText = alarmtxt |
| alarmdefinition.EventType = etype |
| alarmdefinition.OperationInstructions = operation |
| |
| m := CliAlarmDefinitions{AlarmDefinitions: []*alarm.AlarmDefinition{&alarmdefinition}} |
| jsonData, err := json.Marshal(m) |
| if err != nil { |
| fmt.Println("json.Marshal failed: ", err) |
| return |
| } |
| |
| resp, err := http.Post(targetUrl, "application/json", bytes.NewBuffer(jsonData)) |
| if err != nil || resp == nil { |
| fmt.Println("Couldn't post alarm definition due to error: ", err) |
| return |
| } |
| } |
| |
| func deleteAlarmDefinition(flags map[string]commando.FlagValue) { |
| host, _ := flags["host"].GetString() |
| port, _ := flags["port"].GetString() |
| alarmid, _ := flags["aid"].GetInt() |
| salarmid := strconv.FormatUint(uint64(alarmid), 10) |
| targetUrl := fmt.Sprintf("http://%s:%s/ric/v1/alarms/define/%s", host, port, salarmid) |
| |
| client := &http.Client{} |
| req, err := http.NewRequest("DELETE", targetUrl, nil) |
| if err != nil || req == nil { |
| fmt.Println("Couldn't make delete request due to error: ", err) |
| return |
| } |
| resp, errr := client.Do(req) |
| if errr != nil || resp == nil { |
| fmt.Println("Couldn't send delete request due to error: ", err) |
| return |
| } |
| } |
| |
| // NewAlarmClient returns a new AlarmClient. |
| func NewAlarmClient(moId, appId string) *AlarmClient { |
| alarmInstance, err := alarm.InitAlarm(moId, appId) |
| if err == nil { |
| return &AlarmClient{ |
| alarmer: alarmInstance, |
| } |
| } |
| fmt.Println("Failed to create alarmInstance", err) |
| return nil |
| } |
| |
| // Conduct performance testing |
| func conductperformancetest(flags map[string]commando.FlagValue) { |
| var readerror error |
| var senderror error |
| var readobjerror error |
| host, _ := flags["host"].GetString() |
| port, _ := flags["port"].GetString() |
| targetUrl := fmt.Sprintf("http://%s:%s/ric/v1/alarms/define", host, port) |
| readerror = readPerfAlarmDefinitionFromJson() |
| if readerror == nil { |
| senderror = sendPerfAlarmDefinitionToAlarmManager(targetUrl) |
| if senderror == nil { |
| fmt.Println("sent performance alarm definitions to alarm manager") |
| CLIPerfAlarmObjects = make(map[int]*alarm.Alarm) |
| readobjerror = readPerfAlarmObjectFromJson() |
| if readobjerror == nil { |
| profile, _ := flags["prf"].GetInt() |
| if profile == 1 { |
| fmt.Println("starting peak performance test") |
| peakPerformanceTest(flags) |
| } else if profile == 2 { |
| fmt.Println("starting endurance test") |
| enduranceTest(flags) |
| } else { |
| fmt.Println("Unknown profile, received profile = ", profile) |
| } |
| } else { |
| fmt.Println("reading performance alarm objects from json file failed ") |
| } |
| } else { |
| fmt.Println("sending performance alarm definitions to alarm manager failed ") |
| } |
| |
| } else { |
| fmt.Println("reading performance alarm definitions from json file failed ") |
| } |
| |
| } |
| |
| func peakPerformanceTest(flags map[string]commando.FlagValue) { |
| nalarms, _ := flags["nal"].GetInt() |
| var count int = 0 |
| for aid, obj := range CLIPerfAlarmObjects { |
| count = count + 1 |
| if count <= nalarms { |
| fmt.Println("peakPerformanceTest: invoking worker routine ", count, aid, *obj) |
| wg.Add(1) |
| go raiseClearAlarmOnce(obj, flags) |
| } else { |
| break |
| } |
| } |
| fmt.Println("peakPerformanceTest: Waiting for workers to finish") |
| wg.Wait() |
| fmt.Println("peakPerformanceTest: Wait completed") |
| } |
| |
| func enduranceTest(flags map[string]commando.FlagValue) { |
| alarmspersec, _ := flags["aps"].GetInt() |
| var count int = 0 |
| for aid, obj := range CLIPerfAlarmObjects { |
| count = count + 1 |
| if count <= alarmspersec { |
| fmt.Println("enduranceTest: invoking worker routine ", count, aid, *obj) |
| wg.Add(1) |
| go raiseClearAlarmOverPeriod(obj, flags) |
| } else { |
| break |
| } |
| } |
| fmt.Println("enduranceTest: Waiting for workers to finish") |
| wg.Wait() |
| fmt.Println("enduranceTest: Wait completed") |
| } |
| |
| func readPerfAlarmObjectFromJson() error { |
| filename := os.Getenv("PERF_OBJ_FILE") |
| file, err := ioutil.ReadFile(filename) |
| if err == nil { |
| data := RicPerfAlarmObjects{} |
| err = json.Unmarshal([]byte(file), &data) |
| if err == nil { |
| for _, alarmObject := range data.AlarmObjects { |
| ricAlarmObject := new(alarm.Alarm) |
| ricAlarmObject.ManagedObjectId = alarmObject.ManagedObjectId |
| ricAlarmObject.ApplicationId = alarmObject.ApplicationId |
| ricAlarmObject.SpecificProblem = alarmObject.SpecificProblem |
| ricAlarmObject.PerceivedSeverity = alarmObject.PerceivedSeverity |
| ricAlarmObject.AdditionalInfo = alarmObject.AdditionalInfo |
| ricAlarmObject.IdentifyingInfo = alarmObject.IdentifyingInfo |
| CLIPerfAlarmObjects[alarmObject.SpecificProblem] = ricAlarmObject |
| } |
| } else { |
| fmt.Println("readPerfAlarmObjectFromJson: json.Unmarshal failed with error ", err) |
| return err |
| } |
| } else { |
| fmt.Println("readPerfAlarmObjectFromJson: ioutil.ReadFile failed with error ", err) |
| return err |
| } |
| return nil |
| } |
| |
| func readPerfAlarmDefinitionFromJson() error { |
| filename := os.Getenv("PERF_DEF_FILE") |
| file, err := ioutil.ReadFile(filename) |
| if err == nil { |
| data := CliAlarmDefinitions{} |
| err = json.Unmarshal([]byte(file), &data) |
| if err == nil { |
| for _, alarmDefinition := range data.AlarmDefinitions { |
| _, exists := alarm.RICAlarmDefinitions[alarmDefinition.AlarmId] |
| if exists { |
| fmt.Println("ReadPerfAlarmDefinitionFromJson: alarm definition already exists for ", alarmDefinition.AlarmId) |
| } else { |
| fmt.Println("ReadPerfAlarmDefinitionFromJson: alarm ", alarmDefinition.AlarmId) |
| ricAlarmDefintion := new(alarm.AlarmDefinition) |
| ricAlarmDefintion.AlarmId = alarmDefinition.AlarmId |
| ricAlarmDefintion.AlarmText = alarmDefinition.AlarmText |
| ricAlarmDefintion.EventType = alarmDefinition.EventType |
| ricAlarmDefintion.OperationInstructions = alarmDefinition.OperationInstructions |
| CliPerfAlarmDefinitions.AlarmDefinitions = append(CliPerfAlarmDefinitions.AlarmDefinitions, ricAlarmDefintion) |
| } |
| } |
| } else { |
| fmt.Println("ReadPerfAlarmDefinitionFromJson: json.Unmarshal failed with error: ", err) |
| return err |
| } |
| } else { |
| fmt.Println("ReadPerfAlarmDefinitionFromJson: ioutil.ReadFile failed with error: ", err) |
| return err |
| } |
| return nil |
| } |
| |
| func sendPerfAlarmDefinitionToAlarmManager(targetUrl string) error { |
| |
| jsonData, err := json.Marshal(CliPerfAlarmDefinitions) |
| if err != nil { |
| fmt.Println("sendPerfAlarmDefinitionToAlarmManager: json.Marshal failed: ", err) |
| return err |
| } |
| |
| resp, err := http.Post(targetUrl, "application/json", bytes.NewBuffer(jsonData)) |
| if err != nil || resp == nil { |
| fmt.Println("sendPerfAlarmDefinitionToAlarmManager: Couldn't post alarm definition to targeturl due to error: ", targetUrl, err) |
| return err |
| } |
| return nil |
| } |
| |
| func wakeUpAfterTime(timeinseconds int, chn chan string, action string) { |
| time.Sleep(time.Second * time.Duration(timeinseconds)) |
| chn <- action |
| } |
| |
| func raiseClearAlarmOnce(alarmobject *alarm.Alarm, flags map[string]commando.FlagValue) { |
| var alarmClient *AlarmClient = nil |
| defer wg.Done() |
| chn := make(chan string, 1) |
| rmr_or_http, _ := flags["if"].GetString() |
| if rmr_or_http == "rmr" { |
| alarmClient = NewAlarmClient("my-pod", "my-app") |
| } |
| postAlarm(flags, *alarmobject, alarm.AlarmActionRaise, alarmClient) |
| go wakeUpAfterTime(PeakTestDuration, chn, Clear) |
| select { |
| case res := <-chn: |
| if res == Clear { |
| postAlarm(flags, *alarmobject, alarm.AlarmActionClear, alarmClient) |
| go wakeUpAfterTime(PeakTestDuration, chn, End) |
| } else if res == End { |
| return |
| } |
| } |
| } |
| |
| func raiseClearAlarmOverPeriod(alarmobject *alarm.Alarm, flags map[string]commando.FlagValue) { |
| var alarmClient *AlarmClient = nil |
| defer wg.Done() |
| timeinminutes, _ := flags["tim"].GetInt() |
| timeinseconds := timeinminutes * 60 |
| chn := make(chan string, 1) |
| rmr_or_http, _ := flags["if"].GetString() |
| if rmr_or_http == "rmr" { |
| alarmClient = NewAlarmClient("my-pod", "my-app") |
| } |
| postAlarm(flags, *alarmobject, alarm.AlarmActionRaise, alarmClient) |
| go wakeUpAfterTime(OneSecondDuration, chn, Clear) |
| go wakeUpAfterTime(timeinseconds, chn, End) |
| for { |
| select { |
| case res := <-chn: |
| if res == Raise { |
| postAlarm(flags, *alarmobject, alarm.AlarmActionRaise, alarmClient) |
| go wakeUpAfterTime(OneSecondDuration, chn, Clear) |
| } else if res == Clear { |
| postAlarm(flags, *alarmobject, alarm.AlarmActionClear, alarmClient) |
| go wakeUpAfterTime(OneSecondDuration, chn, Raise) |
| } else if res == End { |
| return |
| } |
| } |
| } |
| } |