main.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. //TODO: Harden. Add failover for every method and agent calls
  2. //TODO: Figure out why mongodb keeps failing (log rotation?)
  3. package main
  4. import (
  5. "log"
  6. "github.com/gravitl/netmaker/models"
  7. "github.com/gravitl/netmaker/controllers"
  8. //"github.com/gravitl/netmaker/serverctl"
  9. "github.com/gravitl/netmaker/functions"
  10. "github.com/gravitl/netmaker/mongoconn"
  11. "github.com/gravitl/netmaker/config"
  12. "go.mongodb.org/mongo-driver/bson"
  13. "fmt"
  14. "time"
  15. "net/http"
  16. "errors"
  17. "io/ioutil"
  18. "os"
  19. "net"
  20. "context"
  21. "sync"
  22. "os/signal"
  23. service "github.com/gravitl/netmaker/controllers"
  24. nodepb "github.com/gravitl/netmaker/grpc"
  25. "google.golang.org/grpc"
  26. )
  27. var ServerGRPC string
  28. var PortGRPC string
  29. //Start MongoDB Connection and start API Request Handler
  30. func main() {
  31. log.Println("Server starting...")
  32. mongoconn.ConnectDatabase()
  33. if config.Config.Server.CreateDefault {
  34. err := createDefaultNetwork()
  35. if err != nil {
  36. fmt.Printf("Error creating default network: %v", err)
  37. } else {
  38. /*
  39. err = serverctl.NetworkAdd(config.Config.Server.DefaultNetName)
  40. if err != nil {
  41. fmt.Printf("Error adding to default network: %v", err)
  42. }
  43. */
  44. }
  45. }
  46. var waitgroup sync.WaitGroup
  47. if config.Config.Server.AgentBackend {
  48. waitgroup.Add(1)
  49. go runGRPC(&waitgroup)
  50. }
  51. if config.Config.Server.RestBackend {
  52. waitgroup.Add(1)
  53. controller.HandleRESTRequests(&waitgroup)
  54. }
  55. if !config.Config.Server.RestBackend && !config.Config.Server.AgentBackend {
  56. fmt.Println("Oops! No Server Mode selected. Nothing being served.")
  57. }
  58. waitgroup.Wait()
  59. fmt.Println("Exiting now.")
  60. }
  61. func runGRPC(wg *sync.WaitGroup) {
  62. defer wg.Done()
  63. // Configure 'log' package to give file name and line number on eg. log.Fatal
  64. // Pipe flags to one another (log.LstdFLags = log.Ldate | log.Ltime)
  65. log.SetFlags(log.LstdFlags | log.Lshortfile)
  66. // Start our listener, 50051 is the default gRPC port
  67. grpcport := ":50051"
  68. if config.Config.Server.GrpcPort != "" {
  69. grpcport = ":" + config.Config.Server.GrpcPort
  70. }
  71. if os.Getenv("GRPC_PORT") != "" {
  72. grpcport = ":" + os.Getenv("GRPC_PORT")
  73. }
  74. PortGRPC = grpcport
  75. if os.Getenv("BACKEND_URL") == "" {
  76. if config.Config.Server.Host == "" {
  77. ServerGRPC, _ = getPublicIP()
  78. } else {
  79. ServerGRPC = config.Config.Server.Host
  80. }
  81. } else {
  82. ServerGRPC = os.Getenv("BACKEND_URL")
  83. }
  84. fmt.Println("GRPC Server set to: " + ServerGRPC)
  85. fmt.Println("GRPC Port set to: " + PortGRPC)
  86. var gconf models.GlobalConfig
  87. gconf.ServerGRPC = ServerGRPC
  88. gconf.PortGRPC = PortGRPC
  89. gconf.Name = "netmaker"
  90. err := setGlobalConfig(gconf)
  91. if err != nil {
  92. log.Fatalf("Unable to set global config: %v", err)
  93. }
  94. listener, err := net.Listen("tcp", grpcport)
  95. // Handle errors if any
  96. if err != nil {
  97. log.Fatalf("Unable to listen on port" + grpcport + ": %v", err)
  98. }
  99. s := grpc.NewServer(
  100. authServerUnaryInterceptor(),
  101. authServerStreamInterceptor(),
  102. )
  103. // Create NodeService type
  104. srv := &service.NodeServiceServer{}
  105. // Register the service with the server
  106. nodepb.RegisterNodeServiceServer(s, srv)
  107. srv.NodeDB = mongoconn.NodeDB
  108. // Start the server in a child routine
  109. go func() {
  110. if err := s.Serve(listener); err != nil {
  111. log.Fatalf("Failed to serve: %v", err)
  112. }
  113. }()
  114. fmt.Println("Agent Server succesfully started on port " + grpcport + " (gRPC)")
  115. // Right way to stop the server using a SHUTDOWN HOOK
  116. // Create a channel to receive OS signals
  117. c := make(chan os.Signal)
  118. // Relay os.Interrupt to our channel (os.Interrupt = CTRL+C)
  119. // Ignore other incoming signals
  120. signal.Notify(c, os.Interrupt)
  121. // Block main routine until a signal is received
  122. // As long as user doesn't press CTRL+C a message is not passed and our main routine keeps running
  123. <-c
  124. // After receiving CTRL+C Properly stop the server
  125. fmt.Println("Stopping the Agent server...")
  126. s.Stop()
  127. listener.Close()
  128. fmt.Println("Agent server closed..")
  129. fmt.Println("Closing MongoDB connection")
  130. mongoconn.Client.Disconnect(context.TODO())
  131. fmt.Println("MongoDB connection closed.")
  132. }
  133. func setGlobalConfig(globalconf models.GlobalConfig) (error) {
  134. collection := mongoconn.Client.Database("netmaker").Collection("config")
  135. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  136. _, err := functions.GetGlobalConfig()
  137. if err != nil {
  138. _, err := collection.InsertOne(ctx, globalconf)
  139. defer cancel()
  140. if err != nil {
  141. return err
  142. }
  143. } else {
  144. filter := bson.M{"name": "netmaker"}
  145. update := bson.D{
  146. {"$set", bson.D{
  147. {"servergrpc", globalconf.ServerGRPC},
  148. {"portgrpc", globalconf.PortGRPC},
  149. }},
  150. }
  151. err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&globalconf)
  152. }
  153. return nil
  154. }
  155. func createDefaultNetwork() error {
  156. exists, err := functions.GroupExists(config.Config.Server.DefaultNetName)
  157. if exists || err != nil {
  158. fmt.Println("Default group already exists")
  159. fmt.Println("Skipping default group create")
  160. return err
  161. } else {
  162. var group models.Group
  163. group.NameID = config.Config.Server.DefaultNetName
  164. group.AddressRange = config.Config.Server.DefaultNetRange
  165. group.DisplayName = config.Config.Server.DefaultNetName
  166. group.SetDefaults()
  167. group.SetNodesLastModified()
  168. group.SetGroupLastModified()
  169. group.KeyUpdateTimeStamp = time.Now().Unix()
  170. allow := true
  171. group.AllowManualSignUp = &allow
  172. fmt.Println("Creating default group.")
  173. collection := mongoconn.Client.Database("netmaker").Collection("groups")
  174. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  175. // insert our group into the group table
  176. _, err = collection.InsertOne(ctx, group)
  177. defer cancel()
  178. }
  179. return err
  180. }
  181. func getPublicIP() (string, error) {
  182. iplist := []string{"https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
  183. endpoint := ""
  184. var err error
  185. for _, ipserver := range iplist {
  186. resp, err := http.Get(ipserver)
  187. if err != nil {
  188. continue
  189. }
  190. defer resp.Body.Close()
  191. if resp.StatusCode == http.StatusOK {
  192. bodyBytes, err := ioutil.ReadAll(resp.Body)
  193. if err != nil {
  194. continue
  195. }
  196. endpoint = string(bodyBytes)
  197. break
  198. }
  199. }
  200. if err == nil && endpoint == "" {
  201. err = errors.New("Public Address Not Found.")
  202. }
  203. return endpoint, err
  204. }
  205. func authServerUnaryInterceptor() grpc.ServerOption {
  206. return grpc.UnaryInterceptor(controller.AuthServerUnaryInterceptor)
  207. }
  208. func authServerStreamInterceptor() grpc.ServerOption {
  209. return grpc.StreamInterceptor(controller.AuthServerStreamInterceptor)
  210. }