blob: 13eca83d7d831e5ef6736c13c0cccb97f53798a3 [file] [log] [blame]
khenaidoobf6e7bb2018-08-14 22:27:29 -04001/*
Joey Armstrong7a9af442024-01-03 19:26:36 -05002 * Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
khenaidoobf6e7bb2018-08-14 22:27:29 -04003
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
npujar1d86a522019-11-14 17:11:16 +053016
khenaidoocfee5f42018-07-19 22:47:38 -040017package main
18
19import (
khenaidoo5c11af72018-07-20 17:21:05 -040020 "context"
khenaidoocfee5f42018-07-19 22:47:38 -040021 "fmt"
Akash Reddy Kankanala929cc002025-04-08 15:05:21 +053022 "io"
Abhay Kumar0b343192025-12-09 08:33:36 +000023 "net/http"
khenaidoocfee5f42018-07-19 22:47:38 -040024 "os"
khenaidoo5c11af72018-07-20 17:21:05 -040025 "time"
npujar1d86a522019-11-14 17:11:16 +053026
27 "github.com/opencord/voltha-go/rw_core/config"
28 c "github.com/opencord/voltha-go/rw_core/core"
29 "github.com/opencord/voltha-go/rw_core/utils"
khenaidood948f772021-08-11 17:49:24 -040030 "github.com/opencord/voltha-lib-go/v7/pkg/log"
31 "github.com/opencord/voltha-lib-go/v7/pkg/probe"
32 "github.com/opencord/voltha-lib-go/v7/pkg/version"
Abhay Kumar0b343192025-12-09 08:33:36 +000033 "github.com/prometheus/client_golang/prometheus/promhttp"
khenaidoocfee5f42018-07-19 22:47:38 -040034)
35
khenaidoo5c11af72018-07-20 17:21:05 -040036func printBanner() {
Kent Hagerman2f0d0552020-04-23 17:28:52 -040037 fmt.Println(` `)
38 fmt.Println(` ______ ______ `)
39 fmt.Println(`| _ \ \ / / ___|___ _ __ ___ `)
40 fmt.Println(`| |_) \ \ /\ / / | / _ \| '__/ _ \`)
41 fmt.Println(`| _ < \ V V /| |__| (_) | | | __/`)
42 fmt.Println(`|_| \_\ \_/\_/ \____\___/|_| \___|`)
43 fmt.Println(` `)
khenaidoo5c11af72018-07-20 17:21:05 -040044}
45
David K. Bainbridgef430cd52019-05-28 15:00:35 -070046func printVersion() {
47 fmt.Println("VOLTHA Read-Write Core")
48 fmt.Println(version.VersionInfo.String(" "))
49}
50
khenaidoocfee5f42018-07-19 22:47:38 -040051func main() {
52 start := time.Now()
53
Rohan Agrawal31f21802020-06-12 05:38:46 +000054 ctx := context.Background()
55
David K. Bainbridge6080c172021-07-24 00:22:28 +000056 cf := &config.RWCoreFlags{}
57 cf.ParseCommandArguments(os.Args[1:])
khenaidoocfee5f42018-07-19 22:47:38 -040058
khenaidoo631fe542019-05-31 15:44:43 -040059 // Set the instance ID as the hostname
npujar1d86a522019-11-14 17:11:16 +053060 var instanceID string
khenaidoo631fe542019-05-31 15:44:43 -040061 hostName := utils.GetHostName()
62 if len(hostName) > 0 {
npujar1d86a522019-11-14 17:11:16 +053063 instanceID = hostName
khenaidoo631fe542019-05-31 15:44:43 -040064 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +000065 logger.Fatal(ctx, "HOSTNAME not set")
khenaidoo631fe542019-05-31 15:44:43 -040066 }
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +000067
Don Newton8eca4622020-02-10 16:44:48 -050068 realMain()
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +000069
70 logLevel, err := log.StringToLogLevel(cf.LogLevel)
71 if err != nil {
72 panic(err)
73 }
74
Akash Reddy Kankanala929cc002025-04-08 15:05:21 +053075 // Setup default logger - applies for packages that do not have specific logger set
76 if _, err = log.SetDefaultLogger(log.JSON, logLevel, log.Fields{"instanceId": instanceID}); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +000077 logger.With(log.Fields{"error": err}).Fatal(ctx, "Cannot setup logging")
khenaidoocfee5f42018-07-19 22:47:38 -040078 }
khenaidoob9203542018-09-17 22:56:37 -040079
khenaidoo631fe542019-05-31 15:44:43 -040080 // Update all loggers (provisioned via init) with a common field
Akash Reddy Kankanala929cc002025-04-08 15:05:21 +053081 if err = log.UpdateAllLoggers(log.Fields{"instanceId": instanceID}); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +000082 logger.With(log.Fields{"error": err}).Fatal(ctx, "Cannot setup logging")
khenaidoob9203542018-09-17 22:56:37 -040083 }
84
khenaidoo631fe542019-05-31 15:44:43 -040085 // Update all loggers to log level specified as input parameter
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +000086 log.SetAllLogLevel(logLevel)
khenaidoo2c6a0992019-04-29 13:46:56 -040087
npujar1d86a522019-11-14 17:11:16 +053088 defer func() {
Akash Reddy Kankanala929cc002025-04-08 15:05:21 +053089 err = log.CleanUp()
npujar1d86a522019-11-14 17:11:16 +053090 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +000091 logger.Errorw(ctx, "unable-to-flush-any-buffered-log-entries", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +053092 }
93 }()
khenaidoocfee5f42018-07-19 22:47:38 -040094
khenaidoo631fe542019-05-31 15:44:43 -040095 // Print version / build information and exit
David K. Bainbridgef430cd52019-05-28 15:00:35 -070096 if cf.DisplayVersionOnly {
97 printVersion()
98 return
99 }
100
khenaidoo5c11af72018-07-20 17:21:05 -0400101 // Print banner if specified
102 if cf.Banner {
103 printBanner()
104 }
105
Rohan Agrawal31f21802020-06-12 05:38:46 +0000106 logger.Infow(ctx, "rw-core-config", log.Fields{"config": *cf})
khenaidoo5c11af72018-07-20 17:21:05 -0400107
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -0700108 // Create a context adding the status update channel
khenaidoo5c11af72018-07-20 17:21:05 -0400109 ctx, cancel := context.WithCancel(context.Background())
110 defer cancel()
Abhay Kumar0b343192025-12-09 08:33:36 +0000111 http.Handle("/metrics", promhttp.Handler())
112 go func() {
113 logger.Infof(ctx, "Metrics available at %s/metrics", cf.PrometheusAddress)
114 // Create HTTP server with explicit timeouts to prevent slowloris attacks and resource exhaustion.
115 // Using http.ListenAndServe() directly doesn't allow setting timeouts, which is a security risk.
116 // The server uses http.DefaultServeMux (nil handler) which includes the /metrics endpoint registered above.
117 metricsServer := &http.Server{
118 Addr: cf.PrometheusAddress,
119 Handler: nil,
120 ReadHeaderTimeout: 10 * time.Second,
121 ReadTimeout: 30 * time.Second,
122 WriteTimeout: 30 * time.Second,
123 IdleTimeout: 120 * time.Second,
124 }
125 if err := metricsServer.ListenAndServe(); err != nil {
126 logger.Errorw(ctx, "failed to start metrics HTTP server: ", log.Fields{"error": err})
127 }
128 }()
khenaidoocfee5f42018-07-19 22:47:38 -0400129
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -0700130 /*
131 * Create and start the liveness and readiness container management probes. This
132 * is done in the main function so just in case the main starts multiple other
133 * objects there can be a single probe end point for the process.
134 */
135 p := &probe.Probe{}
Rohan Agrawal31f21802020-06-12 05:38:46 +0000136 go p.ListenAndServe(ctx, cf.ProbeAddress)
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -0700137
138 // Add the probe to the context to pass to all the services started
139 probeCtx := context.WithValue(ctx, probe.ProbeContextKey, p)
140
Akash Reddy Kankanala929cc002025-04-08 15:05:21 +0530141 var closer io.Closer
142 closer, err = log.GetGlobalLFM().InitTracingAndLogCorrelation(cf.TraceEnabled, cf.TraceAgentAddress, cf.LogCorrelationEnabled)
Girish Kumar33470e82020-06-15 13:53:13 +0000143 if err != nil {
144 logger.Warnw(ctx, "unable-to-initialize-tracing-and-log-correlation-module", log.Fields{"error": err})
145 } else {
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300146 defer func() {
147 err = closer.Close()
148 if err != nil {
149 logger.Errorw(ctx, "failed-to-close-trace-closer", log.Fields{"error": err})
150 }
151 }()
Girish Kumar33470e82020-06-15 13:53:13 +0000152 }
153
Kent Hagerman2f0d0552020-04-23 17:28:52 -0400154 // create and start the core
khenaidood948f772021-08-11 17:49:24 -0400155 core, shutdownCtx := c.NewCore(probeCtx, instanceID, cf)
156 go core.Start(shutdownCtx, instanceID, cf)
khenaidoocfee5f42018-07-19 22:47:38 -0400157
khenaidood948f772021-08-11 17:49:24 -0400158 code := utils.WaitForExit(ctx)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000159 logger.Infow(ctx, "received-a-closing-signal", log.Fields{"code": code})
khenaidoocfee5f42018-07-19 22:47:38 -0400160
161 // Cleanup before leaving
khenaidooa46458b2021-12-15 16:50:44 -0500162 core.Stop(shutdownCtx)
khenaidoocfee5f42018-07-19 22:47:38 -0400163
164 elapsed := time.Since(start)
Girish Gowdra11ddb232022-05-26 12:19:59 -0700165
Rohan Agrawal31f21802020-06-12 05:38:46 +0000166 logger.Infow(ctx, "rw-core-run-time", log.Fields{"core": instanceID, "time": elapsed / time.Second})
khenaidoocfee5f42018-07-19 22:47:38 -0400167}