server.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. package controller
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "os"
  6. "strings"
  7. "syscall"
  8. "time"
  9. "github.com/gorilla/mux"
  10. "golang.org/x/exp/slog"
  11. "github.com/gravitl/netmaker/database"
  12. "github.com/gravitl/netmaker/logic"
  13. "github.com/gravitl/netmaker/models"
  14. "github.com/gravitl/netmaker/mq"
  15. "github.com/gravitl/netmaker/servercfg"
  16. )
  17. var cpuProfileLog *os.File
  18. func serverHandlers(r *mux.Router) {
  19. // r.HandleFunc("/api/server/addnetwork/{network}", securityCheckServer(true, http.HandlerFunc(addNetwork))).Methods(http.MethodPost)
  20. r.HandleFunc(
  21. "/api/server/health",
  22. func(resp http.ResponseWriter, req *http.Request) {
  23. resp.WriteHeader(http.StatusOK)
  24. resp.Write([]byte("Server is up and running!!"))
  25. },
  26. ).Methods(http.MethodGet)
  27. r.HandleFunc(
  28. "/api/server/shutdown",
  29. func(w http.ResponseWriter, _ *http.Request) {
  30. msg := "received api call to shutdown server, sending interruption..."
  31. slog.Warn(msg)
  32. _, _ = w.Write([]byte(msg))
  33. w.WriteHeader(http.StatusOK)
  34. _ = syscall.Kill(syscall.Getpid(), syscall.SIGINT)
  35. },
  36. ).Methods(http.MethodPost)
  37. r.HandleFunc("/api/server/getconfig", allowUsers(http.HandlerFunc(getConfig))).
  38. Methods(http.MethodGet)
  39. r.HandleFunc("/api/server/getserverinfo", logic.SecurityCheck(true, http.HandlerFunc(getServerInfo))).
  40. Methods(http.MethodGet)
  41. r.HandleFunc("/api/server/status", getStatus).Methods(http.MethodGet)
  42. r.HandleFunc("/api/server/usage", logic.SecurityCheck(false, http.HandlerFunc(getUsage))).
  43. Methods(http.MethodGet)
  44. r.HandleFunc("/api/server/cpu_profile", logic.SecurityCheck(false, http.HandlerFunc(cpuProfile))).
  45. Methods(http.MethodPost)
  46. }
  47. func cpuProfile(w http.ResponseWriter, r *http.Request) {
  48. start := r.URL.Query().Get("action") == "start"
  49. if start {
  50. os.Remove("/root/data/cpu.prof")
  51. cpuProfileLog = logic.StartCPUProfiling()
  52. } else {
  53. if cpuProfileLog != nil {
  54. logic.StopCPUProfiling(cpuProfileLog)
  55. cpuProfileLog = nil
  56. }
  57. }
  58. }
  59. func getUsage(w http.ResponseWriter, _ *http.Request) {
  60. type usage struct {
  61. Hosts int `json:"hosts"`
  62. Clients int `json:"clients"`
  63. Networks int `json:"networks"`
  64. Users int `json:"users"`
  65. Ingresses int `json:"ingresses"`
  66. Egresses int `json:"egresses"`
  67. Relays int `json:"relays"`
  68. InternetGateways int `json:"internet_gateways"`
  69. FailOvers int `json:"fail_overs"`
  70. }
  71. var serverUsage usage
  72. hosts, err := logic.GetAllHosts()
  73. if err == nil {
  74. serverUsage.Hosts = len(hosts)
  75. }
  76. clients, err := logic.GetAllExtClients()
  77. if err == nil {
  78. serverUsage.Clients = len(clients)
  79. }
  80. users, err := logic.GetUsers()
  81. if err == nil {
  82. serverUsage.Users = len(users)
  83. }
  84. networks, err := logic.GetNetworks()
  85. if err == nil {
  86. serverUsage.Networks = len(networks)
  87. }
  88. // TODO this part bellow can be optimized to get nodes just once
  89. ingresses, err := logic.GetAllIngresses()
  90. if err == nil {
  91. serverUsage.Ingresses = len(ingresses)
  92. }
  93. egresses, err := logic.GetAllEgresses()
  94. if err == nil {
  95. serverUsage.Egresses = len(egresses)
  96. }
  97. relays, err := logic.GetRelays()
  98. if err == nil {
  99. serverUsage.Relays = len(relays)
  100. }
  101. gateways, err := logic.GetInternetGateways()
  102. if err == nil {
  103. serverUsage.InternetGateways = len(gateways)
  104. }
  105. failOvers, err := logic.GetAllFailOvers()
  106. if err == nil {
  107. serverUsage.FailOvers = len(failOvers)
  108. }
  109. w.Header().Set("Content-Type", "application/json")
  110. json.NewEncoder(w).Encode(models.SuccessResponse{
  111. Code: http.StatusOK,
  112. Response: serverUsage,
  113. })
  114. }
  115. // @Summary Get the server status
  116. // @Router /api/server/status [get]
  117. // @Tags Server
  118. // @Security oauth2
  119. func getStatus(w http.ResponseWriter, r *http.Request) {
  120. // @Success 200 {object} status
  121. type status struct {
  122. DB bool `json:"db_connected"`
  123. Broker bool `json:"broker_connected"`
  124. IsBrokerConnOpen bool `json:"is_broker_conn_open"`
  125. LicenseError string `json:"license_error"`
  126. IsPro bool `json:"is_pro"`
  127. TrialEndDate time.Time `json:"trial_end_date"`
  128. IsOnTrialLicense bool `json:"is_on_trial_license"`
  129. }
  130. licenseErr := ""
  131. if servercfg.ErrLicenseValidation != nil {
  132. licenseErr = servercfg.ErrLicenseValidation.Error()
  133. }
  134. //var trialEndDate time.Time
  135. //var err error
  136. // isOnTrial := false
  137. // if servercfg.IsPro &&
  138. // (servercfg.GetLicenseKey() == "" || servercfg.GetNetmakerTenantID() == "") {
  139. // trialEndDate, err = logic.GetTrialEndDate()
  140. // if err != nil {
  141. // slog.Error("failed to get trial end date", "error", err)
  142. // } else {
  143. // isOnTrial = true
  144. // }
  145. // }
  146. currentServerStatus := status{
  147. DB: database.IsConnected(),
  148. Broker: mq.IsConnected(),
  149. IsBrokerConnOpen: mq.IsConnectionOpen(),
  150. LicenseError: licenseErr,
  151. IsPro: servercfg.IsPro,
  152. //TrialEndDate: trialEndDate,
  153. //IsOnTrialLicense: isOnTrial,
  154. }
  155. w.Header().Set("Content-Type", "application/json")
  156. json.NewEncoder(w).Encode(&currentServerStatus)
  157. }
  158. // allowUsers - allow all authenticated (valid) users - only used by getConfig, may be able to remove during refactor
  159. func allowUsers(next http.Handler) http.HandlerFunc {
  160. return func(w http.ResponseWriter, r *http.Request) {
  161. errorResponse := models.ErrorResponse{
  162. Code: http.StatusUnauthorized, Message: logic.Unauthorized_Msg,
  163. }
  164. bearerToken := r.Header.Get("Authorization")
  165. tokenSplit := strings.Split(bearerToken, " ")
  166. authToken := ""
  167. if len(tokenSplit) < 2 {
  168. logic.ReturnErrorResponse(w, r, errorResponse)
  169. return
  170. } else {
  171. authToken = tokenSplit[1]
  172. }
  173. user, _, _, err := logic.VerifyUserToken(authToken)
  174. if err != nil || user == "" {
  175. logic.ReturnErrorResponse(w, r, errorResponse)
  176. return
  177. }
  178. next.ServeHTTP(w, r)
  179. }
  180. }
  181. // @Summary Get the server information
  182. // @Router /api/server/getserverinfo [get]
  183. // @Tags Server
  184. // @Security oauth2
  185. // @Success 200 {object} models.ServerConfig
  186. func getServerInfo(w http.ResponseWriter, r *http.Request) {
  187. // Set header
  188. w.Header().Set("Content-Type", "application/json")
  189. // get params
  190. json.NewEncoder(w).Encode(servercfg.GetServerInfo())
  191. // w.WriteHeader(http.StatusOK)
  192. }
  193. // @Summary Get the server configuration
  194. // @Router /api/server/getconfig [get]
  195. // @Tags Server
  196. // @Security oauth2
  197. // @Success 200 {object} config.ServerConfig
  198. func getConfig(w http.ResponseWriter, r *http.Request) {
  199. // Set header
  200. w.Header().Set("Content-Type", "application/json")
  201. // get params
  202. scfg := servercfg.GetServerConfig()
  203. scfg.IsPro = "no"
  204. if servercfg.IsPro {
  205. scfg.IsPro = "yes"
  206. }
  207. json.NewEncoder(w).Encode(scfg)
  208. // w.WriteHeader(http.StatusOK)
  209. }