forked from gravitl/netmaker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
207 lines (178 loc) · 5.53 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
//TODO: Harden. Add failover for every method and agent calls
//TODO: Figure out why mongodb keeps failing (log rotation?)
package main
import (
"fmt"
"log"
"net"
"os"
"os/signal"
"runtime/debug"
"strconv"
"sync"
"time"
"github.com/gravitl/netmaker/auth"
controller "github.com/gravitl/netmaker/controllers"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/functions"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/ncutils"
"github.com/gravitl/netmaker/servercfg"
"github.com/gravitl/netmaker/serverctl"
"google.golang.org/grpc"
)
// Start DB Connection and start API Request Handler
func main() {
fmt.Println(models.RetrieveLogo()) // print the logo
initialize() // initial db and grpc server
setGarbageCollection()
defer database.CloseDB()
startControllers() // start the grpc or rest endpoints
}
func initialize() { // Client Mode Prereq Check
var err error
if err = database.InitializeDatabase(); err != nil {
logic.Log("Error connecting to database", 0)
log.Fatal(err)
}
logic.Log("database successfully connected", 0)
var authProvider = auth.InitializeAuthProvider()
if authProvider != "" {
logic.Log("OAuth provider, "+authProvider+", initialized", 0)
} else {
logic.Log("no OAuth provider found or not configured, continuing without OAuth", 0)
}
if servercfg.IsClientMode() != "off" {
output, err := ncutils.RunCmd("id -u", true)
if err != nil {
logic.Log("Error running 'id -u' for prereq check. Please investigate or disable client mode.", 0)
log.Fatal(output, err)
}
uid, err := strconv.Atoi(string(output[:len(output)-1]))
if err != nil {
logic.Log("Error retrieving uid from 'id -u' for prereq check. Please investigate or disable client mode.", 0)
log.Fatal(err)
}
if uid != 0 {
log.Fatal("To run in client mode requires root privileges. Either disable client mode or run with sudo.")
}
if err := serverctl.InitServerNetclient(); err != nil {
log.Fatal("Did not find netclient to use CLIENT_MODE")
}
}
if servercfg.IsDNSMode() {
err := functions.SetDNSDir()
if err != nil {
log.Fatal(err)
}
}
}
func startControllers() {
var waitnetwork sync.WaitGroup
//Run Agent Server
if servercfg.IsAgentBackend() {
if !(servercfg.DisableRemoteIPCheck()) && servercfg.GetGRPCHost() == "127.0.0.1" {
err := servercfg.SetHost()
if err != nil {
logic.Log("Unable to Set host. Exiting...", 0)
log.Fatal(err)
}
}
waitnetwork.Add(1)
go runGRPC(&waitnetwork)
}
if servercfg.IsClientMode() == "on" {
waitnetwork.Add(1)
go runClient(&waitnetwork)
}
if servercfg.IsDNSMode() {
err := logic.SetDNS()
if err != nil {
logic.Log("error occurred initializing DNS: "+err.Error(), 0)
}
}
//Run Rest Server
if servercfg.IsRestBackend() {
if !servercfg.DisableRemoteIPCheck() && servercfg.GetAPIHost() == "127.0.0.1" {
err := servercfg.SetHost()
if err != nil {
logic.Log("Unable to Set host. Exiting...", 0)
log.Fatal(err)
}
}
waitnetwork.Add(1)
controller.HandleRESTRequests(&waitnetwork)
}
if !servercfg.IsAgentBackend() && !servercfg.IsRestBackend() {
logic.Log("No Server Mode selected, so nothing is being served! Set either Agent mode (AGENT_BACKEND) or Rest mode (REST_BACKEND) to 'true'.", 0)
}
waitnetwork.Wait()
logic.Log("exiting", 0)
}
func runClient(wg *sync.WaitGroup) {
defer wg.Done()
go func() {
for {
if err := serverctl.HandleContainedClient(); err != nil {
// PASS
}
var checkintime = time.Duration(servercfg.GetServerCheckinInterval()) * time.Second
time.Sleep(checkintime)
}
}()
}
func runGRPC(wg *sync.WaitGroup) {
defer wg.Done()
// Configure 'log' package to give file name and line number on eg. log.Fatal
// Pipe flags to one another (log.LstdFLags = log.Ldate | log.Ltime)
log.SetFlags(log.LstdFlags | log.Lshortfile)
grpcport := servercfg.GetGRPCPort()
listener, err := net.Listen("tcp", ":"+grpcport)
// Handle errors if any
if err != nil {
log.Fatalf("[netmaker] Unable to listen on port "+grpcport+", error: %v", err)
}
s := grpc.NewServer(
authServerUnaryInterceptor(),
)
// Create NodeService type
srv := &controller.NodeServiceServer{}
// Register the service with the server
nodepb.RegisterNodeServiceServer(s, srv)
// Start the server in a child routine
go func() {
if err := s.Serve(listener); err != nil {
log.Fatalf("Failed to serve: %v", err)
}
}()
logic.Log("Agent Server successfully started on port "+grpcport+" (gRPC)", 0)
// Right way to stop the server using a SHUTDOWN HOOK
// Create a channel to receive OS signals
c := make(chan os.Signal)
// Relay os.Interrupt to our channel (os.Interrupt = CTRL+C)
// Ignore other incoming signals
signal.Notify(c, os.Interrupt)
// Block main routine until a signal is received
// As long as user doesn't press CTRL+C a message is not passed and our main routine keeps running
<-c
// After receiving CTRL+C Properly stop the server
logic.Log("Stopping the Agent server...", 0)
s.Stop()
listener.Close()
logic.Log("Agent server closed..", 0)
logic.Log("Closed DB connection.", 0)
}
func authServerUnaryInterceptor() grpc.ServerOption {
return grpc.UnaryInterceptor(controller.AuthServerUnaryInterceptor)
}
func setGarbageCollection() {
_, gcset := os.LookupEnv("GOGC")
if !gcset {
debug.SetGCPercent(ncutils.DEFAULT_GC_PERCENT)
}
}
// func authServerStreamInterceptor() grpc.ServerOption {
// return grpc.StreamInterceptor(controller.AuthServerStreamInterceptor)
// }