main.go 7.6 KB

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