server.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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. r.HandleFunc("/api/server/mem_profile", logic.SecurityCheck(false, http.HandlerFunc(memProfile))).
  47. Methods(http.MethodPost)
  48. }
  49. func cpuProfile(w http.ResponseWriter, r *http.Request) {
  50. start := r.URL.Query().Get("action") == "start"
  51. if start {
  52. os.Remove("/root/data/cpu.prof")
  53. cpuProfileLog = logic.StartCPUProfiling()
  54. } else {
  55. if cpuProfileLog != nil {
  56. logic.StopCPUProfiling(cpuProfileLog)
  57. cpuProfileLog = nil
  58. }
  59. }
  60. }
  61. func memProfile(w http.ResponseWriter, r *http.Request) {
  62. os.Remove("/root/data/mem.prof")
  63. logic.StartMemProfiling()
  64. }
  65. func getUsage(w http.ResponseWriter, _ *http.Request) {
  66. type usage struct {
  67. Hosts int `json:"hosts"`
  68. Clients int `json:"clients"`
  69. Networks int `json:"networks"`
  70. Users int `json:"users"`
  71. Ingresses int `json:"ingresses"`
  72. Egresses int `json:"egresses"`
  73. Relays int `json:"relays"`
  74. InternetGateways int `json:"internet_gateways"`
  75. FailOvers int `json:"fail_overs"`
  76. }
  77. var serverUsage usage
  78. hosts, err := logic.GetAllHosts()
  79. if err == nil {
  80. serverUsage.Hosts = len(hosts)
  81. }
  82. clients, err := logic.GetAllExtClients()
  83. if err == nil {
  84. serverUsage.Clients = len(clients)
  85. }
  86. users, err := logic.GetUsers()
  87. if err == nil {
  88. serverUsage.Users = len(users)
  89. }
  90. networks, err := logic.GetNetworks()
  91. if err == nil {
  92. serverUsage.Networks = len(networks)
  93. }
  94. // TODO this part bellow can be optimized to get nodes just once
  95. ingresses, err := logic.GetAllIngresses()
  96. if err == nil {
  97. serverUsage.Ingresses = len(ingresses)
  98. }
  99. egresses, err := logic.GetAllEgresses()
  100. if err == nil {
  101. serverUsage.Egresses = len(egresses)
  102. }
  103. relays, err := logic.GetRelays()
  104. if err == nil {
  105. serverUsage.Relays = len(relays)
  106. }
  107. gateways, err := logic.GetInternetGateways()
  108. if err == nil {
  109. serverUsage.InternetGateways = len(gateways)
  110. }
  111. failOvers, err := logic.GetAllFailOvers()
  112. if err == nil {
  113. serverUsage.FailOvers = len(failOvers)
  114. }
  115. w.Header().Set("Content-Type", "application/json")
  116. json.NewEncoder(w).Encode(models.SuccessResponse{
  117. Code: http.StatusOK,
  118. Response: serverUsage,
  119. })
  120. }
  121. // @Summary Get the server status
  122. // @Router /api/server/status [get]
  123. // @Tags Server
  124. // @Security oauth2
  125. func getStatus(w http.ResponseWriter, r *http.Request) {
  126. // @Success 200 {object} status
  127. type status struct {
  128. DB bool `json:"db_connected"`
  129. Broker bool `json:"broker_connected"`
  130. IsBrokerConnOpen bool `json:"is_broker_conn_open"`
  131. LicenseError string `json:"license_error"`
  132. IsPro bool `json:"is_pro"`
  133. TrialEndDate time.Time `json:"trial_end_date"`
  134. IsOnTrialLicense bool `json:"is_on_trial_license"`
  135. }
  136. licenseErr := ""
  137. if servercfg.ErrLicenseValidation != nil {
  138. licenseErr = servercfg.ErrLicenseValidation.Error()
  139. }
  140. //var trialEndDate time.Time
  141. //var err error
  142. // isOnTrial := false
  143. // if servercfg.IsPro &&
  144. // (servercfg.GetLicenseKey() == "" || servercfg.GetNetmakerTenantID() == "") {
  145. // trialEndDate, err = logic.GetTrialEndDate()
  146. // if err != nil {
  147. // slog.Error("failed to get trial end date", "error", err)
  148. // } else {
  149. // isOnTrial = true
  150. // }
  151. // }
  152. currentServerStatus := status{
  153. DB: database.IsConnected(),
  154. Broker: mq.IsConnected(),
  155. IsBrokerConnOpen: mq.IsConnectionOpen(),
  156. LicenseError: licenseErr,
  157. IsPro: servercfg.IsPro,
  158. //TrialEndDate: trialEndDate,
  159. //IsOnTrialLicense: isOnTrial,
  160. }
  161. w.Header().Set("Content-Type", "application/json")
  162. json.NewEncoder(w).Encode(&currentServerStatus)
  163. }
  164. // allowUsers - allow all authenticated (valid) users - only used by getConfig, may be able to remove during refactor
  165. func allowUsers(next http.Handler) http.HandlerFunc {
  166. return func(w http.ResponseWriter, r *http.Request) {
  167. errorResponse := models.ErrorResponse{
  168. Code: http.StatusUnauthorized, Message: logic.Unauthorized_Msg,
  169. }
  170. bearerToken := r.Header.Get("Authorization")
  171. tokenSplit := strings.Split(bearerToken, " ")
  172. authToken := ""
  173. if len(tokenSplit) < 2 {
  174. logic.ReturnErrorResponse(w, r, errorResponse)
  175. return
  176. } else {
  177. authToken = tokenSplit[1]
  178. }
  179. user, _, _, err := logic.VerifyUserToken(authToken)
  180. if err != nil || user == "" {
  181. logic.ReturnErrorResponse(w, r, errorResponse)
  182. return
  183. }
  184. next.ServeHTTP(w, r)
  185. }
  186. }
  187. // @Summary Get the server information
  188. // @Router /api/server/getserverinfo [get]
  189. // @Tags Server
  190. // @Security oauth2
  191. // @Success 200 {object} models.ServerConfig
  192. func getServerInfo(w http.ResponseWriter, r *http.Request) {
  193. // Set header
  194. w.Header().Set("Content-Type", "application/json")
  195. // get params
  196. json.NewEncoder(w).Encode(servercfg.GetServerInfo())
  197. // w.WriteHeader(http.StatusOK)
  198. }
  199. // @Summary Get the server configuration
  200. // @Router /api/server/getconfig [get]
  201. // @Tags Server
  202. // @Security oauth2
  203. // @Success 200 {object} config.ServerConfig
  204. func getConfig(w http.ResponseWriter, r *http.Request) {
  205. // Set header
  206. w.Header().Set("Content-Type", "application/json")
  207. // get params
  208. scfg := servercfg.GetServerConfig()
  209. scfg.IsPro = "no"
  210. if servercfg.IsPro {
  211. scfg.IsPro = "yes"
  212. }
  213. json.NewEncoder(w).Encode(scfg)
  214. // w.WriteHeader(http.StatusOK)
  215. }