X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=test%2Fusecases%2Foruclosedlooprecovery%2Fgoversion%2Fmain.go;h=b7d689549db8a1b7f40f66b9ef24344a61ad4cd0;hb=46a0fd717e5f49ebae6cb2c4fbcf54f0e329dc86;hp=5574f8ccd5e9a5af12ecb697b913bbba5286a411;hpb=856d55d6413fe66c05b42a3c5e98d0b0f20743e3;p=nonrtric.git diff --git a/test/usecases/oruclosedlooprecovery/goversion/main.go b/test/usecases/oruclosedlooprecovery/goversion/main.go index 5574f8cc..b7d68954 100644 --- a/test/usecases/oruclosedlooprecovery/goversion/main.go +++ b/test/usecases/oruclosedlooprecovery/goversion/main.go @@ -21,9 +21,13 @@ package main import ( + "crypto/tls" "encoding/json" "fmt" "net/http" + "os" + "os/signal" + "syscall" "github.com/gorilla/mux" log "github.com/sirupsen/logrus" @@ -33,63 +37,134 @@ import ( "oransc.org/usecase/oruclosedloop/internal/restclient" ) -var consumerConfig linkfailure.Configuration -var lookupService repository.LookupService -var host string -var port string +type Server interface { + ListenAndServe() error +} const jobId = "14e7bb84-a44d-44c1-90b7-6995a92ad43c" +var jobRegistrationInfo = struct { + InfoTypeId string `json:"info_type_id"` + JobResultUri string `json:"job_result_uri"` + JobOwner string `json:"job_owner"` + JobDefinition interface{} `json:"job_definition"` +}{ + InfoTypeId: "STD_Fault_Messages", + JobResultUri: "", + JobOwner: "O-RU Closed Loop Usecase", + JobDefinition: "{}", +} + +var client restclient.HTTPClient +var configuration *config.Config +var linkfailureConfig linkfailure.Configuration +var lookupService repository.LookupService +var consumerPort string + func init() { - configuration := config.New() + doInit() +} + +func doInit() { + configuration = config.New() log.SetLevel(configuration.LogLevel) + log.Debug("Using configuration: ", configuration) - if configuration.ConsumerHost == "" || configuration.ConsumerPort == 0 { - log.Fatal("Consumer host and port must be provided!") + consumerPort = fmt.Sprint(configuration.ConsumerPort) + jobRegistrationInfo.JobResultUri = configuration.ConsumerHost + ":" + consumerPort + + linkfailureConfig = linkfailure.Configuration{ + SDNRAddress: configuration.SDNRAddress, + SDNRUser: configuration.SDNRUser, + SDNRPassword: configuration.SDNPassword, } - host = configuration.ConsumerHost - port = fmt.Sprint(configuration.ConsumerPort) +} - csvFileHelper := repository.NewCsvFileHelper() - lookupService = repository.NewLookupServiceImpl(&csvFileHelper, configuration.ORUToODUMapFile) - if initErr := lookupService.Init(); initErr != nil { +func main() { + if err := validateConfiguration(configuration); err != nil { + log.Fatalf("Unable to start consumer due to configuration error: %v", err) + } + + csvFileHelper := repository.NewCsvFileHelperImpl() + if initErr := initializeLookupService(csvFileHelper, configuration.ORUToODUMapFile); initErr != nil { log.Fatalf("Unable to create LookupService due to inability to get O-RU-ID to O-DU-ID map. Cause: %v", initErr) } - consumerConfig = linkfailure.Configuration{ - InfoCoordAddress: configuration.InfoCoordinatorAddress, - SDNRAddress: configuration.SDNRHost + ":" + fmt.Sprint(configuration.SDNRPort), - SDNRUser: configuration.SDNRUser, - SDNRPassword: configuration.SDNPassword, + + var cert tls.Certificate + if c, err := restclient.CreateClientCertificate(configuration.ConsumerCertPath, configuration.ConsumerKeyPath); err == nil { + cert = c + } else { + log.Fatalf("Stopping producer due to error: %v", err) } + client = restclient.CreateRetryClient(cert) + + go func() { + startServer() + os.Exit(1) // If the startServer function exits, it is because there has been a failure in the server, so we exit. + }() + + go func() { + deleteOnShutdown(make(chan os.Signal, 1)) + os.Exit(0) + }() + + keepConsumerAlive() } -func main() { - defer deleteJob() - messageHandler := linkfailure.NewLinkFailureHandler(lookupService, consumerConfig) +func validateConfiguration(configuration *config.Config) error { + if configuration.ConsumerHost == "" || configuration.ConsumerPort == 0 { + return fmt.Errorf("consumer host and port must be provided") + } + + if configuration.ConsumerCertPath == "" || configuration.ConsumerKeyPath == "" { + return fmt.Errorf("missing CONSUMER_CERT and/or CONSUMER_KEY") + } + + return nil +} + +func initializeLookupService(csvFileHelper repository.CsvFileHelper, csvFile string) error { + lookupService = repository.NewLookupServiceImpl(csvFileHelper, csvFile) + return lookupService.Init() +} + +func getRouter() *mux.Router { + messageHandler := linkfailure.NewLinkFailureHandler(lookupService, linkfailureConfig, client) + r := mux.NewRouter() - r.HandleFunc("/", messageHandler.MessagesHandler).Methods(http.MethodPost) - r.HandleFunc("/admin/start", startHandler).Methods(http.MethodPost) - r.HandleFunc("/admin/stop", stopHandler).Methods(http.MethodPost) - log.Error(http.ListenAndServe(":"+port, r)) + r.HandleFunc("/", messageHandler.MessagesHandler).Methods(http.MethodPost).Name("messageHandler") + r.HandleFunc("/admin/start", startHandler).Methods(http.MethodPost).Name("start") + r.HandleFunc("/admin/stop", stopHandler).Methods(http.MethodPost).Name("stop") + + return r } -func startHandler(w http.ResponseWriter, r *http.Request) { - jobRegistrationInfo := struct { - InfoTypeId string `json:"info_type_id"` - JobResultUri string `json:"job_result_uri"` - JobOwner string `json:"job_owner"` - JobDefinition interface{} `json:"job_definition"` - }{ - InfoTypeId: "STD_Fault_Messages", - JobResultUri: host + ":" + port, - JobOwner: "O-RU Closed Loop Usecase", - JobDefinition: "{}", +func startServer() { + var err error + if restclient.IsUrlSecure(configuration.ConsumerHost) { + err = http.ListenAndServeTLS(fmt.Sprintf(":%v", configuration.ConsumerPort), configuration.ConsumerCertPath, configuration.ConsumerKeyPath, getRouter()) + } else { + err = http.ListenAndServe(fmt.Sprintf(":%v", configuration.ConsumerPort), getRouter()) + } + if err != nil { + log.Errorf("Server stopped unintentionally due to: %v. Deleteing job.", err) + if deleteErr := deleteJob(); deleteErr != nil { + log.Error(fmt.Sprintf("Unable to delete consumer job due to: %v. Please remove job %v manually.", deleteErr, jobId)) + } } +} + +func keepConsumerAlive() { + forever := make(chan int) + <-forever +} + +func startHandler(w http.ResponseWriter, r *http.Request) { body, _ := json.Marshal(jobRegistrationInfo) - putErr := restclient.PutWithoutAuth(consumerConfig.InfoCoordAddress+"/data-consumer/v1/info-jobs/"+jobId, body) + putErr := restclient.PutWithoutAuth(configuration.InfoCoordinatorAddress+"/data-consumer/v1/info-jobs/"+jobId, body, client) if putErr != nil { - http.Error(w, fmt.Sprintf("Unable to register consumer job: %v", putErr), http.StatusBadRequest) + http.Error(w, fmt.Sprintf("Unable to register consumer job due to: %v.", putErr), http.StatusBadRequest) return } log.Debug("Registered job.") @@ -98,12 +173,22 @@ func startHandler(w http.ResponseWriter, r *http.Request) { func stopHandler(w http.ResponseWriter, r *http.Request) { deleteErr := deleteJob() if deleteErr != nil { - http.Error(w, fmt.Sprintf("Unable to delete consumer job: %v", deleteErr), http.StatusBadRequest) + http.Error(w, fmt.Sprintf("Unable to delete consumer job due to: %v. Please remove job %v manually.", deleteErr, jobId), http.StatusBadRequest) return } log.Debug("Deleted job.") } +func deleteOnShutdown(s chan os.Signal) { + signal.Notify(s, os.Interrupt) + signal.Notify(s, syscall.SIGTERM) + <-s + log.Info("Shutting down gracefully.") + if err := deleteJob(); err != nil { + log.Error(fmt.Sprintf("Unable to delete job on shutdown due to: %v. Please remove job %v manually.", err, jobId)) + } +} + func deleteJob() error { - return restclient.Delete(consumerConfig.InfoCoordAddress + "/data-consumer/v1/info-jobs/" + jobId) + return restclient.Delete(configuration.InfoCoordinatorAddress+"/data-consumer/v1/info-jobs/"+jobId, client) }