2021-03-26 00:17:52 +08:00
package main
import (
2022-01-06 23:57:05 +08:00
"context"
2021-08-10 02:56:27 +08:00
"fmt"
2021-07-21 05:18:45 +08:00
"net"
"os"
"os/signal"
2021-11-17 10:19:13 +08:00
"runtime/debug"
2021-07-21 05:18:45 +08:00
"strconv"
"sync"
2022-01-15 03:30:26 +08:00
"syscall"
2021-08-19 06:12:08 +08:00
2022-01-13 05:23:34 +08:00
mqtt "github.com/eclipse/paho.mqtt.golang"
2021-10-22 03:28:58 +08:00
"github.com/gravitl/netmaker/auth"
2021-07-21 05:18:45 +08:00
controller "github.com/gravitl/netmaker/controllers"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/functions"
nodepb "github.com/gravitl/netmaker/grpc"
2021-12-07 04:31:08 +08:00
"github.com/gravitl/netmaker/logger"
2021-10-22 03:28:58 +08:00
"github.com/gravitl/netmaker/logic"
2021-08-10 02:56:27 +08:00
"github.com/gravitl/netmaker/models"
2022-01-13 05:23:34 +08:00
"github.com/gravitl/netmaker/mq"
2021-09-20 02:03:47 +08:00
"github.com/gravitl/netmaker/netclient/ncutils"
2021-07-21 05:18:45 +08:00
"github.com/gravitl/netmaker/servercfg"
2021-09-28 05:51:20 +08:00
"github.com/gravitl/netmaker/serverctl"
2021-07-21 05:18:45 +08:00
"google.golang.org/grpc"
2021-03-26 00:17:52 +08:00
)
2021-04-06 02:47:07 +08:00
2021-08-31 03:58:23 +08:00
// Start DB Connection and start API Request Handler
2021-03-26 00:17:52 +08:00
func main ( ) {
2021-08-10 02:56:27 +08:00
fmt . Println ( models . RetrieveLogo ( ) ) // print the logo
initialize ( ) // initial db and grpc server
2021-11-17 10:19:13 +08:00
setGarbageCollection ( )
2021-08-19 06:12:08 +08:00
defer database . CloseDB ( )
2021-07-21 05:18:45 +08:00
startControllers ( ) // start the grpc or rest endpoints
}
2021-04-13 12:42:35 +08:00
2021-07-29 04:40:13 +08:00
func initialize ( ) { // Client Mode Prereq Check
2021-07-21 05:18:45 +08:00
var err error
2021-10-22 03:28:58 +08:00
2022-02-01 22:59:23 +08:00
if servercfg . GetNodeID ( ) == "" {
logger . FatalLog ( "error: must set NODE_ID, currently blank" )
}
2021-07-29 04:40:13 +08:00
if err = database . InitializeDatabase ( ) ; err != nil {
2021-12-11 10:09:42 +08:00
logger . FatalLog ( "Error connecting to database" )
2021-07-29 04:40:13 +08:00
}
2021-12-07 04:31:08 +08:00
logger . Log ( 0 , "database successfully connected" )
2021-10-22 03:28:58 +08:00
2022-01-26 00:00:56 +08:00
err = logic . TimerCheckpoint ( )
2022-01-21 06:50:42 +08:00
if err != nil {
2022-01-26 00:00:56 +08:00
logger . Log ( 1 , "Timer error occurred: " , err . Error ( ) )
2022-01-21 06:50:42 +08:00
}
2021-10-22 03:28:58 +08:00
var authProvider = auth . InitializeAuthProvider ( )
if authProvider != "" {
2021-12-29 01:07:50 +08:00
logger . Log ( 0 , "OAuth provider," , authProvider + "," , "initialized" )
2021-10-22 21:47:29 +08:00
} else {
2021-12-07 04:31:08 +08:00
logger . Log ( 0 , "no OAuth provider found or not configured, continuing without OAuth" )
2021-10-22 03:28:58 +08:00
}
2021-09-28 05:51:20 +08:00
if servercfg . IsClientMode ( ) != "off" {
2021-09-20 02:03:47 +08:00
output , err := ncutils . RunCmd ( "id -u" , true )
2021-08-31 03:58:23 +08:00
if err != nil {
2021-12-07 04:31:08 +08:00
logger . FatalLog ( "Error running 'id -u' for prereq check. Please investigate or disable client mode." , output , err . Error ( ) )
2021-08-31 03:58:23 +08:00
}
uid , err := strconv . Atoi ( string ( output [ : len ( output ) - 1 ] ) )
if err != nil {
2021-12-07 04:31:08 +08:00
logger . FatalLog ( "Error retrieving uid from 'id -u' for prereq check. Please investigate or disable client mode." , err . Error ( ) )
2021-08-31 03:58:23 +08:00
}
if uid != 0 {
2021-12-07 04:31:08 +08:00
logger . FatalLog ( "To run in client mode requires root privileges. Either disable client mode or run with sudo." )
2021-08-31 03:58:23 +08:00
}
2021-09-29 02:08:16 +08:00
if err := serverctl . InitServerNetclient ( ) ; err != nil {
2021-12-07 04:31:08 +08:00
logger . FatalLog ( "Did not find netclient to use CLIENT_MODE" )
2021-09-29 02:08:16 +08:00
}
2021-07-21 05:18:45 +08:00
}
2022-01-26 00:58:51 +08:00
// initialize iptables to ensure gateways work correctly and mq is forwarded if containerized
if servercfg . ManageIPTables ( ) != "off" {
if err = serverctl . InitIPTables ( ) ; err != nil {
logger . FatalLog ( "Unable to initialize iptables on host:" , err . Error ( ) )
}
}
2021-04-20 09:50:58 +08:00
2021-07-21 05:18:45 +08:00
if servercfg . IsDNSMode ( ) {
err := functions . SetDNSDir ( )
2021-05-06 04:42:17 +08:00
if err != nil {
2021-12-07 04:31:08 +08:00
logger . FatalLog ( err . Error ( ) )
2021-05-06 04:42:17 +08:00
}
2021-04-13 12:42:35 +08:00
}
2021-07-21 05:18:45 +08:00
}
2021-05-06 04:42:17 +08:00
2021-07-21 05:18:45 +08:00
func startControllers ( ) {
2021-04-13 12:42:35 +08:00
var waitnetwork sync . WaitGroup
2021-05-06 04:42:17 +08:00
//Run Agent Server
2021-05-06 06:03:37 +08:00
if servercfg . IsAgentBackend ( ) {
2021-07-21 05:18:45 +08:00
if ! ( servercfg . DisableRemoteIPCheck ( ) ) && servercfg . GetGRPCHost ( ) == "127.0.0.1" {
2021-05-06 08:41:28 +08:00
err := servercfg . SetHost ( )
if err != nil {
2021-12-07 04:31:08 +08:00
logger . FatalLog ( "Unable to Set host. Exiting..." , err . Error ( ) )
2021-05-06 08:41:28 +08:00
}
}
2021-04-13 12:42:35 +08:00
waitnetwork . Add ( 1 )
2021-07-21 05:18:45 +08:00
go runGRPC ( & waitnetwork )
2021-03-26 00:17:52 +08:00
}
2021-09-28 05:51:20 +08:00
2021-07-21 05:18:45 +08:00
if servercfg . IsDNSMode ( ) {
2021-10-27 00:27:29 +08:00
err := logic . SetDNS ( )
2021-07-21 05:18:45 +08:00
if err != nil {
2021-12-07 04:31:08 +08:00
logger . Log ( 0 , "error occurred initializing DNS: " , err . Error ( ) )
2021-07-21 05:18:45 +08:00
}
}
2021-05-06 04:42:17 +08:00
//Run Rest Server
2021-05-06 06:03:37 +08:00
if servercfg . IsRestBackend ( ) {
2021-07-21 05:18:45 +08:00
if ! servercfg . DisableRemoteIPCheck ( ) && servercfg . GetAPIHost ( ) == "127.0.0.1" {
err := servercfg . SetHost ( )
if err != nil {
2021-12-07 04:31:08 +08:00
logger . FatalLog ( "Unable to Set host. Exiting..." , err . Error ( ) )
2021-07-21 05:18:45 +08:00
}
}
2021-04-13 12:42:35 +08:00
waitnetwork . Add ( 1 )
2021-12-09 05:52:32 +08:00
go controller . HandleRESTRequests ( & waitnetwork )
2021-03-26 00:17:52 +08:00
}
2021-12-09 05:52:32 +08:00
2022-01-13 05:23:34 +08:00
//Run MessageQueue
if servercfg . IsMessageQueueBackend ( ) {
waitnetwork . Add ( 1 )
go runMessageQueue ( & waitnetwork )
}
if ! servercfg . IsAgentBackend ( ) && ! servercfg . IsRestBackend ( ) && ! servercfg . IsMessageQueueBackend ( ) {
logger . Log ( 0 , "No Server Mode selected, so nothing is being served! Set Agent mode (AGENT_BACKEND) or Rest mode (REST_BACKEND) or MessageQueue (MESSAGEQUEUE_BACKEND) to 'true'." )
2021-03-26 00:17:52 +08:00
}
2021-09-28 05:51:20 +08:00
2021-04-13 12:42:35 +08:00
waitnetwork . Wait ( )
2021-09-28 05:51:20 +08:00
}
2021-07-21 05:18:45 +08:00
func runGRPC ( wg * sync . WaitGroup ) {
2021-03-26 00:17:52 +08:00
defer wg . Done ( )
2021-05-06 06:03:37 +08:00
grpcport := servercfg . GetGRPCPort ( )
2021-03-26 00:17:52 +08:00
2021-05-06 06:03:37 +08:00
listener , err := net . Listen ( "tcp" , ":" + grpcport )
2021-07-21 05:18:45 +08:00
// Handle errors if any
if err != nil {
2021-12-11 10:09:42 +08:00
logger . FatalLog ( "[netmaker] Unable to listen on port" , grpcport , ": error:" , err . Error ( ) )
2021-04-07 07:13:34 +08:00
}
2021-07-21 05:18:45 +08:00
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 {
2021-12-11 10:09:42 +08:00
logger . FatalLog ( "Failed to serve:" , err . Error ( ) )
2021-07-21 05:18:45 +08:00
}
} ( )
2021-12-07 04:31:08 +08:00
logger . Log ( 0 , "Agent Server successfully started on port " , grpcport , "(gRPC)" )
2021-07-21 05:18:45 +08:00
// Relay os.Interrupt to our channel (os.Interrupt = CTRL+C)
// Ignore other incoming signals
2022-01-06 23:57:05 +08:00
ctx , stop := signal . NotifyContext ( context . TODO ( ) , os . Interrupt )
defer stop ( )
2021-07-21 05:18:45 +08:00
// 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
2022-01-06 23:57:05 +08:00
<- ctx . Done ( )
2021-07-21 05:18:45 +08:00
// After receiving CTRL+C Properly stop the server
2021-12-07 04:31:08 +08:00
logger . Log ( 0 , "Stopping the Agent server..." )
2022-01-06 23:57:05 +08:00
s . GracefulStop ( )
2021-07-21 05:18:45 +08:00
listener . Close ( )
2021-12-07 04:31:08 +08:00
logger . Log ( 0 , "Agent server closed.." )
logger . Log ( 0 , "Closed DB connection." )
2021-03-26 00:17:52 +08:00
}
2021-04-06 20:24:57 +08:00
2022-01-13 05:23:34 +08:00
// Should we be using a context vice a waitgroup????????????
func runMessageQueue ( wg * sync . WaitGroup ) {
defer wg . Done ( )
//refactor netclient.functions.SetupMQTT so can be called from here
//setupMQTT
opts := mqtt . NewClientOptions ( )
opts . AddBroker ( servercfg . GetMessageQueueEndpoint ( ) )
logger . Log ( 0 , "setting broker " + servercfg . GetMessageQueueEndpoint ( ) )
client := mqtt . NewClient ( opts )
if token := client . Connect ( ) ; token . Wait ( ) && token . Error ( ) != nil {
logger . Log ( 0 , "unable to connect to message queue broker, closing down" )
return
}
//Set up Subscriptions
2022-01-21 18:19:17 +08:00
if servercfg . GetDebug ( ) {
if token := client . Subscribe ( "#" , 2 , mq . DefaultHandler ) ; token . Wait ( ) && token . Error ( ) != nil {
client . Disconnect ( 240 )
logger . Log ( 0 , "default subscription failed" )
}
2022-01-13 05:23:34 +08:00
}
2022-01-15 03:30:26 +08:00
if token := client . Subscribe ( "ping/#" , 2 , mq . Ping ) ; token . Wait ( ) && token . Error ( ) != nil {
2022-01-13 05:23:34 +08:00
client . Disconnect ( 240 )
2022-01-21 18:19:17 +08:00
logger . Log ( 0 , "ping subscription failed" )
2022-01-13 05:23:34 +08:00
}
2022-01-21 18:19:17 +08:00
if token := client . Subscribe ( "update/#" , 0 , mq . UpdateNode ) ; token . Wait ( ) && token . Error ( ) != nil {
2022-01-13 05:23:34 +08:00
client . Disconnect ( 240 )
2022-01-21 18:19:17 +08:00
logger . Log ( 0 , "node update subscription failed" )
2022-01-13 05:23:34 +08:00
}
2022-01-27 02:42:52 +08:00
//Set Up Keepalive message
ctx , cancel := context . WithCancel ( context . Background ( ) )
go mq . Keepalive ( ctx )
2022-01-15 03:30:26 +08:00
quit := make ( chan os . Signal , 1 )
signal . Notify ( quit , syscall . SIGTERM , os . Interrupt )
<- quit
2022-01-27 02:42:52 +08:00
cancel ( )
2022-01-15 03:30:26 +08:00
logger . Log ( 0 , "Message Queue shutting down" )
2022-01-25 04:33:36 +08:00
client . Disconnect ( 250 )
2022-01-13 05:23:34 +08:00
}
2021-03-26 00:17:52 +08:00
func authServerUnaryInterceptor ( ) grpc . ServerOption {
return grpc . UnaryInterceptor ( controller . AuthServerUnaryInterceptor )
}
2021-08-06 03:27:05 +08:00
2021-11-17 10:19:13 +08:00
func setGarbageCollection ( ) {
_ , gcset := os . LookupEnv ( "GOGC" )
if ! gcset {
debug . SetGCPercent ( ncutils . DEFAULT_GC_PERCENT )
}
}