Browse Source

Merge branch 'develop' into NET-792-remove-freebsd

Christopher Blaha 1 năm trước cách đây
mục cha
commit
b3a838f047

+ 1 - 1
auth/host_session.go

@@ -253,7 +253,7 @@ func CheckNetRegAndHostUpdate(networks []string, h *models.Host, relayNodeId uui
 			Action: models.RequestAck,
 			Action: models.RequestAck,
 			Host:   *h,
 			Host:   *h,
 		})
 		})
-		if err := mq.PublishPeerUpdate(); err != nil {
+		if err := mq.PublishPeerUpdate(false); err != nil {
 			logger.Log(0, "failed to publish peer update during registration -", err.Error())
 			logger.Log(0, "failed to publish peer update during registration -", err.Error())
 		}
 		}
 	}
 	}

+ 1 - 1
config/config.go

@@ -91,7 +91,7 @@ type ServerConfig struct {
 	Environment                string        `yaml:"environment"`
 	Environment                string        `yaml:"environment"`
 	JwtValidityDuration        time.Duration `yaml:"jwt_validity_duration"`
 	JwtValidityDuration        time.Duration `yaml:"jwt_validity_duration"`
 	RacAutoDisable             bool          `yaml:"rac_auto_disable"`
 	RacAutoDisable             bool          `yaml:"rac_auto_disable"`
-	CacheEnabled               bool          `yaml:"caching_enabled"`
+	CacheEnabled               string        `yaml:"caching_enabled"`
 }
 }
 
 
 // SQLConfig - Generic SQL Config
 // SQLConfig - Generic SQL Config

+ 29 - 14
controllers/ext_client.go

@@ -422,7 +422,7 @@ func createExtClient(w http.ResponseWriter, r *http.Request) {
 	slog.Info("created extclient", "user", r.Header.Get("user"), "network", node.Network, "clientid", extclient.ClientID)
 	slog.Info("created extclient", "user", r.Header.Get("user"), "network", node.Network, "clientid", extclient.ClientID)
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 	go func() {
 	go func() {
-		if err := mq.PublishPeerUpdate(); err != nil {
+		if err := mq.PublishPeerUpdate(false); err != nil {
 			logger.Log(1, "error setting ext peers on "+nodeid+": "+err.Error())
 			logger.Log(1, "error setting ext peers on "+nodeid+": "+err.Error())
 		}
 		}
 		if servercfg.IsDNSMode() {
 		if servercfg.IsDNSMode() {
@@ -510,22 +510,37 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) {
 		return
 		return
 	}
 	}
 	logger.Log(0, r.Header.Get("user"), "updated ext client", update.ClientID)
 	logger.Log(0, r.Header.Get("user"), "updated ext client", update.ClientID)
-	if sendPeerUpdate { // need to send a peer update to the ingress node as enablement of one of it's clients has changed
-		if ingressNode, err := logic.GetNodeByID(newclient.IngressGatewayID); err == nil {
-			if err = mq.PublishPeerUpdate(); err != nil {
-				logger.Log(1, "error setting ext peers on", ingressNode.ID.String(), ":", err.Error())
-			}
-		}
-	}
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(newclient)
 	json.NewEncoder(w).Encode(newclient)
-	if changedID {
-		go func() {
-			if servercfg.IsDNSMode() {
-				logic.SetDNS()
+
+	go func() {
+		if changedID && servercfg.IsDNSMode() {
+			logic.SetDNS()
+		}
+		if sendPeerUpdate { // need to send a peer update to the ingress node as enablement of one of it's clients has changed
+			ingressNode, err := logic.GetNodeByID(newclient.IngressGatewayID)
+			if err == nil {
+				if err = mq.PublishPeerUpdate(false); err != nil {
+					logger.Log(1, "error setting ext peers on", ingressNode.ID.String(), ":", err.Error())
+				}
 			}
 			}
-		}()
-	}
+			if !update.Enabled {
+				ingressHost, err := logic.GetHost(ingressNode.HostID.String())
+				if err != nil {
+					slog.Error("Failed to get ingress host", "node", ingressNode.ID.String(), "error", err)
+					return
+				}
+				nodes, err := logic.GetAllNodes()
+				if err != nil {
+					slog.Error("Failed to get nodes", "error", err)
+					return
+				}
+				go mq.PublishSingleHostPeerUpdate(ingressHost, nodes, nil, []models.ExtClient{oldExtClient}, false)
+			}
+		}
+
+	}()
+
 }
 }
 
 
 // swagger:route DELETE /api/extclients/{network}/{clientid} ext_client deleteExtClient
 // swagger:route DELETE /api/extclients/{network}/{clientid} ext_client deleteExtClient

+ 7 - 3
controllers/hosts.go

@@ -195,7 +195,7 @@ func updateHost(w http.ResponseWriter, r *http.Request) {
 		logger.Log(0, r.Header.Get("user"), "failed to send host update: ", currHost.ID.String(), err.Error())
 		logger.Log(0, r.Header.Get("user"), "failed to send host update: ", currHost.ID.String(), err.Error())
 	}
 	}
 	go func() {
 	go func() {
-		if err := mq.PublishPeerUpdate(); err != nil {
+		if err := mq.PublishPeerUpdate(false); err != nil {
 			logger.Log(0, "fail to publish peer update: ", err.Error())
 			logger.Log(0, "fail to publish peer update: ", err.Error())
 		}
 		}
 		if newHost.Name != currHost.Name {
 		if newHost.Name != currHost.Name {
@@ -228,6 +228,7 @@ func hostUpdateFallback(w http.ResponseWriter, r *http.Request) {
 	currentHost, err := logic.GetHost(hostid)
 	currentHost, err := logic.GetHost(hostid)
 	if err != nil {
 	if err != nil {
 		slog.Error("error getting host", "id", hostid, "error", err)
 		slog.Error("error getting host", "id", hostid, "error", err)
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 		return
 	}
 	}
 
 
@@ -249,10 +250,13 @@ func hostUpdateFallback(w http.ResponseWriter, r *http.Request) {
 		err := logic.UpsertHost(currentHost)
 		err := logic.UpsertHost(currentHost)
 		if err != nil {
 		if err != nil {
 			slog.Error("failed to update host", "id", currentHost.ID, "error", err)
 			slog.Error("failed to update host", "id", currentHost.ID, "error", err)
+			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 			return
 			return
 		}
 		}
-
+	case models.UpdateMetrics:
+		mq.UpdateMetricsFallBack(hostUpdate.Node.ID.String(), hostUpdate.NewMetrics)
 	}
 	}
+	logic.ReturnSuccessResponse(w, r, "updated host data")
 
 
 }
 }
 
 
@@ -356,7 +360,7 @@ func addHostToNetwork(w http.ResponseWriter, r *http.Request) {
 			Host:   *currHost,
 			Host:   *currHost,
 			Node:   *newNode,
 			Node:   *newNode,
 		})
 		})
-		mq.PublishPeerUpdate()
+		mq.PublishPeerUpdate(false)
 		if servercfg.IsDNSMode() {
 		if servercfg.IsDNSMode() {
 			logic.SetDNS()
 			logic.SetDNS()
 		}
 		}

+ 1 - 1
controllers/migrate.go

@@ -95,7 +95,7 @@ func migrate(w http.ResponseWriter, r *http.Request) {
 	if err := logic.UpsertHost(&host); err != nil {
 	if err := logic.UpsertHost(&host); err != nil {
 		slog.Error("save host", "error", err)
 		slog.Error("save host", "error", err)
 	}
 	}
-	go mq.PublishPeerUpdate()
+	go mq.PublishPeerUpdate(false)
 	response := models.HostPull{
 	response := models.HostPull{
 		Host:         host,
 		Host:         host,
 		Nodes:        nodes,
 		Nodes:        nodes,

+ 4 - 4
controllers/network.go

@@ -17,7 +17,6 @@ import (
 	"github.com/gravitl/netmaker/logic/acls"
 	"github.com/gravitl/netmaker/logic/acls"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/mq"
 	"github.com/gravitl/netmaker/mq"
-	"github.com/gravitl/netmaker/servercfg"
 )
 )
 
 
 func networkHandlers(r *mux.Router) {
 func networkHandlers(r *mux.Router) {
@@ -128,11 +127,12 @@ func updateNetworkACL(w http.ResponseWriter, r *http.Request) {
 	logger.Log(1, r.Header.Get("user"), "updated ACLs for network", netname)
 	logger.Log(1, r.Header.Get("user"), "updated ACLs for network", netname)
 
 
 	// send peer updates
 	// send peer updates
-	if servercfg.IsMessageQueueBackend() {
-		if err = mq.PublishPeerUpdate(); err != nil {
+	go func() {
+		if err = mq.PublishPeerUpdate(false); err != nil {
 			logger.Log(0, "failed to publish peer update after ACL update on", netname)
 			logger.Log(0, "failed to publish peer update after ACL update on", netname)
 		}
 		}
-	}
+	}()
+
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(newNetACL)
 	json.NewEncoder(w).Encode(newNetACL)
 }
 }

+ 4 - 4
controllers/node.go

@@ -436,7 +436,7 @@ func createEgressGateway(w http.ResponseWriter, r *http.Request) {
 		if err := mq.NodeUpdate(&node); err != nil {
 		if err := mq.NodeUpdate(&node); err != nil {
 			slog.Error("error publishing node update to node", "node", node.ID, "error", err)
 			slog.Error("error publishing node update to node", "node", node.ID, "error", err)
 		}
 		}
-		mq.PublishPeerUpdate()
+		mq.PublishPeerUpdate(false)
 	}()
 	}()
 }
 }
 
 
@@ -479,7 +479,7 @@ func deleteEgressGateway(w http.ResponseWriter, r *http.Request) {
 		if err := mq.NodeUpdate(&node); err != nil {
 		if err := mq.NodeUpdate(&node); err != nil {
 			slog.Error("error publishing node update to node", "node", node.ID, "error", err)
 			slog.Error("error publishing node update to node", "node", node.ID, "error", err)
 		}
 		}
-		mq.PublishPeerUpdate()
+		mq.PublishPeerUpdate(false)
 	}()
 	}()
 }
 }
 
 
@@ -590,7 +590,7 @@ func deleteIngressGateway(w http.ResponseWriter, r *http.Request) {
 				return
 				return
 			}
 			}
 			go func() {
 			go func() {
-				if err := mq.PublishSingleHostPeerUpdate(host, allNodes, nil, removedClients[:]); err != nil {
+				if err := mq.PublishSingleHostPeerUpdate(host, allNodes, nil, removedClients[:], false); err != nil {
 					slog.Error("publishSingleHostUpdate", "host", host.Name, "error", err)
 					slog.Error("publishSingleHostUpdate", "host", host.Name, "error", err)
 				}
 				}
 				if err := mq.NodeUpdate(&node); err != nil {
 				if err := mq.NodeUpdate(&node); err != nil {
@@ -667,7 +667,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
 			slog.Error("error publishing node update to node", "node", newNode.ID, "error", err)
 			slog.Error("error publishing node update to node", "node", newNode.ID, "error", err)
 		}
 		}
 		if aclUpdate || relayupdate || ifaceDelta {
 		if aclUpdate || relayupdate || ifaceDelta {
-			if err := mq.PublishPeerUpdate(); err != nil {
+			if err := mq.PublishPeerUpdate(false); err != nil {
 				logger.Log(0, "error during node ACL update for node", newNode.ID.String())
 				logger.Log(0, "error during node ACL update for node", newNode.ID.String())
 			}
 			}
 		}
 		}

+ 3 - 2
controllers/user.go

@@ -138,7 +138,7 @@ func authenticateUser(response http.ResponseWriter, request *http.Request) {
 					} else {
 					} else {
 						// publish peer update to ingress gateway
 						// publish peer update to ingress gateway
 						if ingressNode, err := logic.GetNodeByID(newClient.IngressGatewayID); err == nil {
 						if ingressNode, err := logic.GetNodeByID(newClient.IngressGatewayID); err == nil {
-							if err = mq.PublishPeerUpdate(); err != nil {
+							if err = mq.PublishPeerUpdate(false); err != nil {
 								slog.Error("error updating ext clients on", "ingress", ingressNode.ID.String(), "err", err.Error())
 								slog.Error("error updating ext clients on", "ingress", ingressNode.ID.String(), "err", err.Error())
 							}
 							}
 						}
 						}
@@ -343,6 +343,7 @@ func createUser(w http.ResponseWriter, r *http.Request) {
 	caller, err := logic.GetUser(r.Header.Get("user"))
 	caller, err := logic.GetUser(r.Header.Get("user"))
 	if err != nil {
 	if err != nil {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+		return
 	}
 	}
 	var user models.User
 	var user models.User
 	err = json.NewDecoder(r.Body).Decode(&user)
 	err = json.NewDecoder(r.Body).Decode(&user)
@@ -365,7 +366,7 @@ func createUser(w http.ResponseWriter, r *http.Request) {
 		return
 		return
 	}
 	}
 	if !servercfg.IsPro && !user.IsAdmin {
 	if !servercfg.IsPro && !user.IsAdmin {
-		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
+		logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("non-admins users can only be created on Pro version"), "forbidden"))
 		return
 		return
 	}
 	}
 
 

+ 1 - 6
logic/nodes.go

@@ -475,13 +475,8 @@ func DeleteExpiredNodes(ctx context.Context, peerUpdate chan *models.Node) {
 				return
 				return
 			}
 			}
 			for _, node := range allnodes {
 			for _, node := range allnodes {
+				node := node
 				if time.Now().After(node.ExpirationDateTime) {
 				if time.Now().After(node.ExpirationDateTime) {
-					if err := DeleteNode(&node, false); err != nil {
-						slog.Error("error deleting expired node", "nodeid", node.ID.String(), "error", err.Error())
-						continue
-					}
-					node.Action = models.NODE_DELETE
-					node.PendingDelete = true
 					peerUpdate <- &node
 					peerUpdate <- &node
 					slog.Info("deleting expired node", "nodeid", node.ID.String())
 					slog.Info("deleting expired node", "nodeid", node.ID.String())
 				}
 				}

+ 1 - 1
logic/peers.go

@@ -210,7 +210,7 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
 				nodePeer = hostPeerUpdate.Peers[peerIndexMap[peerHost.PublicKey.String()]]
 				nodePeer = hostPeerUpdate.Peers[peerIndexMap[peerHost.PublicKey.String()]]
 			}
 			}
 
 
-			if node.Network == network && !peerConfig.Remove { // add to peers map for metrics
+			if node.Network == network && !peerConfig.Remove && len(peerConfig.AllowedIPs) > 0 { // add to peers map for metrics
 				hostPeerUpdate.PeerIDs[peerHost.PublicKey.String()] = models.IDandAddr{
 				hostPeerUpdate.PeerIDs[peerHost.PublicKey.String()] = models.IDandAddr{
 					ID:         peer.ID.String(),
 					ID:         peer.ID.String(),
 					HostID:     peerHost.ID.String(),
 					HostID:     peerHost.ID.String(),

+ 12 - 2
main.go

@@ -168,9 +168,19 @@ func runMessageQueue(wg *sync.WaitGroup, ctx context.Context) {
 		go logic.ManageZombies(ctx, peerUpdate)
 		go logic.ManageZombies(ctx, peerUpdate)
 		go logic.DeleteExpiredNodes(ctx, peerUpdate)
 		go logic.DeleteExpiredNodes(ctx, peerUpdate)
 		for nodeUpdate := range peerUpdate {
 		for nodeUpdate := range peerUpdate {
-			if err := mq.NodeUpdate(nodeUpdate); err != nil {
-				logger.Log(0, "failed to send peer update for deleted node: ", nodeUpdate.ID.String(), err.Error())
+			if nodeUpdate == nil {
+				continue
 			}
 			}
+			node := nodeUpdate
+			node.Action = models.NODE_DELETE
+			node.PendingDelete = true
+			if err := mq.NodeUpdate(node); err != nil {
+				logger.Log(0, "failed to send peer update for deleted node: ", node.ID.String(), err.Error())
+			}
+			if err := logic.DeleteNode(node, true); err != nil {
+				slog.Error("error deleting expired node", "nodeid", node.ID.String(), "error", err.Error())
+			}
+			go mq.PublishDeletedNodePeerUpdate(node)
 		}
 		}
 	}()
 	}()
 	<-ctx.Done()
 	<-ctx.Done()

+ 7 - 4
models/host.go

@@ -114,6 +114,8 @@ const (
 	UpdateKeys HostMqAction = "UPDATE_KEYS"
 	UpdateKeys HostMqAction = "UPDATE_KEYS"
 	// RequestPull - request a pull from a host
 	// RequestPull - request a pull from a host
 	RequestPull HostMqAction = "REQ_PULL"
 	RequestPull HostMqAction = "REQ_PULL"
+	// UpdateMetrics - updates metrics data
+	UpdateMetrics HostMqAction = "UPDATE_METRICS"
 )
 )
 
 
 // SignalAction - turn peer signal action
 // SignalAction - turn peer signal action
@@ -128,10 +130,11 @@ const (
 
 
 // HostUpdate - struct for host update
 // HostUpdate - struct for host update
 type HostUpdate struct {
 type HostUpdate struct {
-	Action HostMqAction
-	Host   Host
-	Node   Node
-	Signal Signal
+	Action     HostMqAction
+	Host       Host
+	Node       Node
+	Signal     Signal
+	NewMetrics Metrics
 }
 }
 
 
 // HostTurnRegister - struct for host turn registration
 // HostTurnRegister - struct for host turn registration

+ 4 - 5
models/metrics.go

@@ -6,11 +6,10 @@ import (
 
 
 // Metrics - metrics struct
 // Metrics - metrics struct
 type Metrics struct {
 type Metrics struct {
-	Network       string            `json:"network" bson:"network" yaml:"network"`
-	NodeID        string            `json:"node_id" bson:"node_id" yaml:"node_id"`
-	NodeName      string            `json:"node_name" bson:"node_name" yaml:"node_name"`
-	Connectivity  map[string]Metric `json:"connectivity" bson:"connectivity" yaml:"connectivity"`
-	FailoverPeers map[string]string `json:"needsfailover" bson:"needsfailover" yaml:"needsfailover"`
+	Network      string            `json:"network" bson:"network" yaml:"network"`
+	NodeID       string            `json:"node_id" bson:"node_id" yaml:"node_id"`
+	NodeName     string            `json:"node_name" bson:"node_name" yaml:"node_name"`
+	Connectivity map[string]Metric `json:"connectivity" bson:"connectivity" yaml:"connectivity"`
 }
 }
 
 
 // Metric - holds a metric for data between nodes
 // Metric - holds a metric for data between nodes

+ 1 - 0
models/mqtt.go

@@ -19,6 +19,7 @@ type HostPeerUpdate struct {
 	HostNetworkInfo HostInfoMap           `json:"host_network_info,omitempty" bson:"host_network_info,omitempty" yaml:"host_network_info,omitempty"`
 	HostNetworkInfo HostInfoMap           `json:"host_network_info,omitempty" bson:"host_network_info,omitempty" yaml:"host_network_info,omitempty"`
 	EgressRoutes    []EgressNetworkRoutes `json:"egress_network_routes"`
 	EgressRoutes    []EgressNetworkRoutes `json:"egress_network_routes"`
 	FwUpdate        FwUpdate              `json:"fw_update"`
 	FwUpdate        FwUpdate              `json:"fw_update"`
+	ReplacePeers    bool                  `json:"replace_peers"`
 }
 }
 
 
 // IngressInfo - struct for ingress info
 // IngressInfo - struct for ingress info

+ 1 - 3
models/node.go

@@ -14,8 +14,6 @@ import (
 const (
 const (
 	// NODE_SERVER_NAME - the default server name
 	// NODE_SERVER_NAME - the default server name
 	NODE_SERVER_NAME = "netmaker"
 	NODE_SERVER_NAME = "netmaker"
-	// TEN_YEARS_IN_SECONDS - ten years in seconds
-	TEN_YEARS_IN_SECONDS = 315670000000000000
 	// MAX_NAME_LENGTH - max name length of node
 	// MAX_NAME_LENGTH - max name length of node
 	MAX_NAME_LENGTH = 62
 	MAX_NAME_LENGTH = 62
 	// == ACTIONS == (can only be set by server)
 	// == ACTIONS == (can only be set by server)
@@ -354,7 +352,7 @@ func (node *Node) SetLastPeerUpdate() {
 // Node.SetExpirationDateTime - sets node expiry time
 // Node.SetExpirationDateTime - sets node expiry time
 func (node *Node) SetExpirationDateTime() {
 func (node *Node) SetExpirationDateTime() {
 	if node.ExpirationDateTime.IsZero() {
 	if node.ExpirationDateTime.IsZero() {
-		node.ExpirationDateTime = time.Now().Add(TEN_YEARS_IN_SECONDS)
+		node.ExpirationDateTime = time.Now().AddDate(100, 1, 0)
 	}
 	}
 }
 }
 
 

+ 9 - 26
mq/handlers.go

@@ -2,7 +2,6 @@ package mq
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"
-	"fmt"
 
 
 	mqtt "github.com/eclipse/paho.mqtt.golang"
 	mqtt "github.com/eclipse/paho.mqtt.golang"
 	"github.com/google/uuid"
 	"github.com/google/uuid"
@@ -14,13 +13,14 @@ import (
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/servercfg"
 	"golang.org/x/exp/slog"
 	"golang.org/x/exp/slog"
-	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 )
 )
 
 
 // UpdateMetrics  message Handler -- handles updates from client nodes for metrics
 // UpdateMetrics  message Handler -- handles updates from client nodes for metrics
 var UpdateMetrics = func(client mqtt.Client, msg mqtt.Message) {
 var UpdateMetrics = func(client mqtt.Client, msg mqtt.Message) {
 }
 }
 
 
+var UpdateMetricsFallBack = func(nodeid string, newMetrics models.Metrics) {}
+
 // DefaultHandler default message queue handler  -- NOT USED
 // DefaultHandler default message queue handler  -- NOT USED
 func DefaultHandler(client mqtt.Client, msg mqtt.Message) {
 func DefaultHandler(client mqtt.Client, msg mqtt.Message) {
 	slog.Info("mqtt default handler", "topic", msg.Topic(), "message", msg.Payload())
 	slog.Info("mqtt default handler", "topic", msg.Topic(), "message", msg.Payload())
@@ -65,10 +65,10 @@ func UpdateNode(client mqtt.Client, msg mqtt.Message) {
 			}
 			}
 			allNodes, err := logic.GetAllNodes()
 			allNodes, err := logic.GetAllNodes()
 			if err == nil {
 			if err == nil {
-				PublishSingleHostPeerUpdate(host, allNodes, nil, nil)
+				PublishSingleHostPeerUpdate(host, allNodes, nil, nil, false)
 			}
 			}
 		} else {
 		} else {
-			err = PublishPeerUpdate()
+			err = PublishPeerUpdate(false)
 		}
 		}
 		if err != nil {
 		if err != nil {
 			slog.Warn("error updating peers when node informed the server of an interface change", "nodeid", currentNode.ID, "error", err)
 			slog.Warn("error updating peers when node informed the server of an interface change", "nodeid", currentNode.ID, "error", err)
@@ -102,6 +102,7 @@ func UpdateHost(client mqtt.Client, msg mqtt.Message) {
 	}
 	}
 	slog.Info("recieved host update", "name", hostUpdate.Host.Name, "id", hostUpdate.Host.ID)
 	slog.Info("recieved host update", "name", hostUpdate.Host.Name, "id", hostUpdate.Host.ID)
 	var sendPeerUpdate bool
 	var sendPeerUpdate bool
+	var replacePeers bool
 	switch hostUpdate.Action {
 	switch hostUpdate.Action {
 	case models.CheckIn:
 	case models.CheckIn:
 		sendPeerUpdate = HandleHostCheckin(&hostUpdate.Host, currentHost)
 		sendPeerUpdate = HandleHostCheckin(&hostUpdate.Host, currentHost)
@@ -122,7 +123,7 @@ func UpdateHost(client mqtt.Client, msg mqtt.Message) {
 				if err != nil {
 				if err != nil {
 					return
 					return
 				}
 				}
-				if err = PublishSingleHostPeerUpdate(currentHost, nodes, nil, nil); err != nil {
+				if err = PublishSingleHostPeerUpdate(currentHost, nodes, nil, nil, false); err != nil {
 					slog.Error("failed peers publish after join acknowledged", "name", hostUpdate.Host.Name, "id", currentHost.ID, "error", err)
 					slog.Error("failed peers publish after join acknowledged", "name", hostUpdate.Host.Name, "id", currentHost.ID, "error", err)
 					return
 					return
 				}
 				}
@@ -131,25 +132,7 @@ func UpdateHost(client mqtt.Client, msg mqtt.Message) {
 	case models.UpdateHost:
 	case models.UpdateHost:
 		if hostUpdate.Host.PublicKey != currentHost.PublicKey {
 		if hostUpdate.Host.PublicKey != currentHost.PublicKey {
 			//remove old peer entry
 			//remove old peer entry
-			peerUpdate := models.HostPeerUpdate{
-				ServerVersion: servercfg.GetVersion(),
-				Peers: []wgtypes.PeerConfig{
-					{
-						PublicKey: currentHost.PublicKey,
-						Remove:    true,
-					},
-				},
-			}
-			data, err := json.Marshal(&peerUpdate)
-			if err != nil {
-				slog.Error("failed to marshal peer update", "error", err)
-			}
-			hosts := logic.GetRelatedHosts(hostUpdate.Host.ID.String())
-			server := servercfg.GetServer()
-			for _, host := range hosts {
-				publish(&host, fmt.Sprintf("peers/host/%s/%s", host.ID.String(), server), data)
-			}
-
+			replacePeers = true
 		}
 		}
 		sendPeerUpdate = logic.UpdateHostFromClient(&hostUpdate.Host, currentHost)
 		sendPeerUpdate = logic.UpdateHostFromClient(&hostUpdate.Host, currentHost)
 		err := logic.UpsertHost(currentHost)
 		err := logic.UpsertHost(currentHost)
@@ -198,7 +181,7 @@ func UpdateHost(client mqtt.Client, msg mqtt.Message) {
 	}
 	}
 
 
 	if sendPeerUpdate {
 	if sendPeerUpdate {
-		err := PublishPeerUpdate()
+		err := PublishPeerUpdate(replacePeers)
 		if err != nil {
 		if err != nil {
 			slog.Error("failed to publish peer update", "error", err)
 			slog.Error("failed to publish peer update", "error", err)
 		}
 		}
@@ -249,7 +232,7 @@ func ClientPeerUpdate(client mqtt.Client, msg mqtt.Message) {
 	case ncutils.ACK:
 	case ncutils.ACK:
 		// do we still need this
 		// do we still need this
 	case ncutils.DONE:
 	case ncutils.DONE:
-		if err = PublishPeerUpdate(); err != nil {
+		if err = PublishPeerUpdate(false); err != nil {
 			slog.Error("error publishing peer update for node", "id", currentNode.ID, "error", err)
 			slog.Error("error publishing peer update for node", "id", currentNode.ID, "error", err)
 			return
 			return
 		}
 		}

+ 12 - 8
mq/publishers.go

@@ -14,7 +14,7 @@ import (
 )
 )
 
 
 // PublishPeerUpdate --- determines and publishes a peer update to all the hosts
 // PublishPeerUpdate --- determines and publishes a peer update to all the hosts
-func PublishPeerUpdate() error {
+func PublishPeerUpdate(replacePeers bool) error {
 	if !servercfg.IsMessageQueueBackend() {
 	if !servercfg.IsMessageQueueBackend() {
 		return nil
 		return nil
 	}
 	}
@@ -30,9 +30,12 @@ func PublishPeerUpdate() error {
 	}
 	}
 	for _, host := range hosts {
 	for _, host := range hosts {
 		host := host
 		host := host
-		if err = PublishSingleHostPeerUpdate(&host, allNodes, nil, nil); err != nil {
-			logger.Log(1, "failed to publish peer update to host", host.ID.String(), ": ", err.Error())
-		}
+		go func(host models.Host) {
+			if err = PublishSingleHostPeerUpdate(&host, allNodes, nil, nil, replacePeers); err != nil {
+				logger.Log(1, "failed to publish peer update to host", host.ID.String(), ": ", err.Error())
+			}
+		}(host)
+
 	}
 	}
 	return err
 	return err
 }
 }
@@ -55,7 +58,7 @@ func PublishDeletedNodePeerUpdate(delNode *models.Node) error {
 	}
 	}
 	for _, host := range hosts {
 	for _, host := range hosts {
 		host := host
 		host := host
-		if err = PublishSingleHostPeerUpdate(&host, allNodes, delNode, nil); err != nil {
+		if err = PublishSingleHostPeerUpdate(&host, allNodes, delNode, nil, false); err != nil {
 			logger.Log(1, "failed to publish peer update to host", host.ID.String(), ": ", err.Error())
 			logger.Log(1, "failed to publish peer update to host", host.ID.String(), ": ", err.Error())
 		}
 		}
 	}
 	}
@@ -81,7 +84,7 @@ func PublishDeletedClientPeerUpdate(delClient *models.ExtClient) error {
 	for _, host := range hosts {
 	for _, host := range hosts {
 		host := host
 		host := host
 		if host.OS != models.OS_Types.IoT {
 		if host.OS != models.OS_Types.IoT {
-			if err = PublishSingleHostPeerUpdate(&host, nodes, nil, []models.ExtClient{*delClient}); err != nil {
+			if err = PublishSingleHostPeerUpdate(&host, nodes, nil, []models.ExtClient{*delClient}, false); err != nil {
 				logger.Log(1, "failed to publish peer update to host", host.ID.String(), ": ", err.Error())
 				logger.Log(1, "failed to publish peer update to host", host.ID.String(), ": ", err.Error())
 			}
 			}
 		}
 		}
@@ -90,12 +93,13 @@ func PublishDeletedClientPeerUpdate(delClient *models.ExtClient) error {
 }
 }
 
 
 // PublishSingleHostPeerUpdate --- determines and publishes a peer update to one host
 // PublishSingleHostPeerUpdate --- determines and publishes a peer update to one host
-func PublishSingleHostPeerUpdate(host *models.Host, allNodes []models.Node, deletedNode *models.Node, deletedClients []models.ExtClient) error {
+func PublishSingleHostPeerUpdate(host *models.Host, allNodes []models.Node, deletedNode *models.Node, deletedClients []models.ExtClient, replacePeers bool) error {
 
 
 	peerUpdate, err := logic.GetPeerUpdateForHost("", host, allNodes, deletedNode, deletedClients)
 	peerUpdate, err := logic.GetPeerUpdateForHost("", host, allNodes, deletedNode, deletedClients)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
+	peerUpdate.ReplacePeers = replacePeers
 	data, err := json.Marshal(&peerUpdate)
 	data, err := json.Marshal(&peerUpdate)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
@@ -231,7 +235,7 @@ func sendPeers() {
 		for _, host := range hosts {
 		for _, host := range hosts {
 			host := host
 			host := host
 			logger.Log(2, "sending scheduled peer update (5 min)")
 			logger.Log(2, "sending scheduled peer update (5 min)")
-			if err = PublishSingleHostPeerUpdate(&host, nodes, nil, nil); err != nil {
+			if err = PublishSingleHostPeerUpdate(&host, nodes, nil, nil, false); err != nil {
 				logger.Log(1, "error publishing peer updates for host: ", host.ID.String(), " Err: ", err.Error())
 				logger.Log(1, "error publishing peer updates for host: ", host.ID.String(), " Err: ", err.Error())
 			}
 			}
 		}
 		}

+ 4 - 4
pro/controllers/failover.go

@@ -70,7 +70,7 @@ func createfailOver(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 		return
 	}
 	}
-	go mq.PublishPeerUpdate()
+	go mq.PublishPeerUpdate(false)
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Content-Type", "application/json")
 	logic.ReturnSuccessResponseWithJson(w, r, node, "created failover successfully")
 	logic.ReturnSuccessResponseWithJson(w, r, node, "created failover successfully")
 }
 }
@@ -90,7 +90,7 @@ func resetFailOver(w http.ResponseWriter, r *http.Request) {
 			logic.UpsertNode(&node)
 			logic.UpsertNode(&node)
 		}
 		}
 	}
 	}
-	go mq.PublishPeerUpdate()
+	go mq.PublishPeerUpdate(false)
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Content-Type", "application/json")
 	logic.ReturnSuccessResponse(w, r, "failover has been reset successfully")
 	logic.ReturnSuccessResponse(w, r, "failover has been reset successfully")
 }
 }
@@ -126,7 +126,7 @@ func deletefailOver(w http.ResponseWriter, r *http.Request) {
 	}
 	}
 	go func() {
 	go func() {
 		proLogic.ResetFailOver(&node)
 		proLogic.ResetFailOver(&node)
-		mq.PublishPeerUpdate()
+		mq.PublishPeerUpdate(false)
 	}()
 	}()
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Content-Type", "application/json")
 	logic.ReturnSuccessResponseWithJson(w, r, node, "deleted failover successfully")
 	logic.ReturnSuccessResponseWithJson(w, r, node, "deleted failover successfully")
@@ -193,7 +193,7 @@ func failOverME(w http.ResponseWriter, r *http.Request) {
 	sendPeerUpdate = true
 	sendPeerUpdate = true
 
 
 	if sendPeerUpdate {
 	if sendPeerUpdate {
-		go mq.PublishPeerUpdate()
+		go mq.PublishPeerUpdate(false)
 	}
 	}
 
 
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Content-Type", "application/json")

+ 3 - 3
pro/controllers/relay.go

@@ -63,7 +63,7 @@ func createRelay(w http.ResponseWriter, r *http.Request) {
 
 
 		}
 		}
 	}
 	}
-	go mq.PublishPeerUpdate()
+	go mq.PublishPeerUpdate(false)
 	logger.Log(1, r.Header.Get("user"), "created relay on node", relayRequest.NodeID, "on network", relayRequest.NetID)
 	logger.Log(1, r.Header.Get("user"), "created relay on node", relayRequest.NodeID, "on network", relayRequest.NetID)
 	apiNode := relayNode.ConvertToAPINode()
 	apiNode := relayNode.ConvertToAPINode()
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
@@ -108,13 +108,13 @@ func deleteRelay(w http.ResponseWriter, r *http.Request) {
 						return
 						return
 					}
 					}
 					node.IsRelay = true // for iot update to recognise that it has to delete relay peer
 					node.IsRelay = true // for iot update to recognise that it has to delete relay peer
-					if err = mq.PublishSingleHostPeerUpdate(h, nodes, &node, nil); err != nil {
+					if err = mq.PublishSingleHostPeerUpdate(h, nodes, &node, nil, false); err != nil {
 						logger.Log(1, "failed to publish peer update to host", h.ID.String(), ": ", err.Error())
 						logger.Log(1, "failed to publish peer update to host", h.ID.String(), ": ", err.Error())
 					}
 					}
 				}
 				}
 			}
 			}
 		}
 		}
-		mq.PublishPeerUpdate()
+		mq.PublishPeerUpdate(false)
 	}()
 	}()
 	logger.Log(1, r.Header.Get("user"), "deleted relay on node", node.ID.String(), "on network", node.Network)
 	logger.Log(1, r.Header.Get("user"), "deleted relay on node", node.ID.String(), "on network", node.Network)
 	apiNode := node.ConvertToAPINode()
 	apiNode := node.ConvertToAPINode()

+ 10 - 0
pro/controllers/users.go

@@ -162,6 +162,7 @@ func getUserRemoteAccessGws(w http.ResponseWriter, r *http.Request) {
 			return
 			return
 		}
 		}
 	}
 	}
+	reqFromMobile := r.URL.Query().Get("from_mobile") == "true"
 	if req.RemoteAccessClientID == "" && remoteAccessClientID == "" {
 	if req.RemoteAccessClientID == "" && remoteAccessClientID == "" {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("remote access client id cannot be empty"), "badrequest"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("remote access client id cannot be empty"), "badrequest"))
 		return
 		return
@@ -288,6 +289,15 @@ func getUserRemoteAccessGws(w http.ResponseWriter, r *http.Request) {
 			}
 			}
 		}
 		}
 	}
 	}
+	if reqFromMobile {
+		// send resp in array format
+		userGwsArr := []models.UserRemoteGws{}
+		for _, userGwI := range userGws {
+			userGwsArr = append(userGwsArr, userGwI...)
+		}
+		logic.ReturnSuccessResponseWithJson(w, r, userGwsArr, "fetched gateways for user"+username)
+		return
+	}
 	slog.Debug("returned user gws", "user", username, "gws", userGws)
 	slog.Debug("returned user gws", "user", username, "gws", userGws)
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(userGws)
 	json.NewEncoder(w).Encode(userGws)

+ 1 - 0
pro/initialize.go

@@ -64,6 +64,7 @@ func InitPro() {
 	logic.IsInternetGw = proLogic.IsInternetGw
 	logic.IsInternetGw = proLogic.IsInternetGw
 	logic.SetInternetGw = proLogic.SetInternetGw
 	logic.SetInternetGw = proLogic.SetInternetGw
 	mq.UpdateMetrics = proLogic.MQUpdateMetrics
 	mq.UpdateMetrics = proLogic.MQUpdateMetrics
+	mq.UpdateMetricsFallBack = proLogic.MQUpdateMetricsFallBack
 }
 }
 
 
 func retrieveProLogo() string {
 func retrieveProLogo() string {

+ 26 - 37
pro/logic/metrics.go

@@ -46,6 +46,28 @@ func DeleteMetrics(nodeid string) error {
 	return database.DeleteRecord(database.METRICS_TABLE_NAME, nodeid)
 	return database.DeleteRecord(database.METRICS_TABLE_NAME, nodeid)
 }
 }
 
 
+// MQUpdateMetricsFallBack - called when mq fallback thread is triggered on client
+func MQUpdateMetricsFallBack(nodeid string, newMetrics models.Metrics) {
+
+	currentNode, err := logic.GetNodeByID(nodeid)
+	if err != nil {
+		slog.Error("error getting node", "id", nodeid, "error", err)
+		return
+	}
+
+	updateNodeMetrics(&currentNode, &newMetrics)
+	if err = logic.UpdateMetrics(nodeid, &newMetrics); err != nil {
+		slog.Error("failed to update node metrics", "id", nodeid, "error", err)
+		return
+	}
+	if servercfg.IsMetricsExporter() {
+		if err := mq.PushMetricsToExporter(newMetrics); err != nil {
+			slog.Error("failed to push node metrics to exporter", "id", currentNode.ID, "error", err)
+		}
+	}
+	slog.Debug("updated node metrics", "id", nodeid)
+}
+
 func MQUpdateMetrics(client mqtt.Client, msg mqtt.Message) {
 func MQUpdateMetrics(client mqtt.Client, msg mqtt.Message) {
 	id, err := mq.GetID(msg.Topic())
 	id, err := mq.GetID(msg.Topic())
 	if err != nil {
 	if err != nil {
@@ -68,9 +90,7 @@ func MQUpdateMetrics(client mqtt.Client, msg mqtt.Message) {
 		slog.Error("error unmarshaling payload", "error", err)
 		slog.Error("error unmarshaling payload", "error", err)
 		return
 		return
 	}
 	}
-
-	shouldUpdate := updateNodeMetrics(&currentNode, &newMetrics)
-
+	updateNodeMetrics(&currentNode, &newMetrics)
 	if err = logic.UpdateMetrics(id, &newMetrics); err != nil {
 	if err = logic.UpdateMetrics(id, &newMetrics); err != nil {
 		slog.Error("failed to update node metrics", "id", id, "error", err)
 		slog.Error("failed to update node metrics", "id", id, "error", err)
 		return
 		return
@@ -80,34 +100,15 @@ func MQUpdateMetrics(client mqtt.Client, msg mqtt.Message) {
 			slog.Error("failed to push node metrics to exporter", "id", currentNode.ID, "error", err)
 			slog.Error("failed to push node metrics to exporter", "id", currentNode.ID, "error", err)
 		}
 		}
 	}
 	}
-
-	if shouldUpdate {
-		slog.Info("updating peers after node detected connectivity issues", "id", currentNode.ID, "network", currentNode.Network)
-		host, err := logic.GetHost(currentNode.HostID.String())
-		if err == nil {
-			nodes, err := logic.GetAllNodes()
-			if err != nil {
-				return
-			}
-			if err = mq.PublishSingleHostPeerUpdate(host, nodes, nil, nil); err != nil {
-				slog.Warn("failed to publish update after failover peer change for node", "id", currentNode.ID, "network", currentNode.Network, "error", err)
-			}
-		}
-	}
 	slog.Debug("updated node metrics", "id", id)
 	slog.Debug("updated node metrics", "id", id)
 }
 }
 
 
-func updateNodeMetrics(currentNode *models.Node, newMetrics *models.Metrics) bool {
-	if newMetrics.FailoverPeers == nil {
-		newMetrics.FailoverPeers = make(map[string]string)
-	}
+func updateNodeMetrics(currentNode *models.Node, newMetrics *models.Metrics) {
+
 	oldMetrics, err := logic.GetMetrics(currentNode.ID.String())
 	oldMetrics, err := logic.GetMetrics(currentNode.ID.String())
 	if err != nil {
 	if err != nil {
 		slog.Error("error finding old metrics for node", "id", currentNode.ID, "error", err)
 		slog.Error("error finding old metrics for node", "id", currentNode.ID, "error", err)
-		return false
-	}
-	if oldMetrics.FailoverPeers == nil {
-		oldMetrics.FailoverPeers = make(map[string]string)
+		return
 	}
 	}
 
 
 	var attachedClients []models.ExtClient
 	var attachedClients []models.ExtClient
@@ -164,19 +165,7 @@ func updateNodeMetrics(currentNode *models.Node, newMetrics *models.Metrics) boo
 
 
 	}
 	}
 
 
-	shouldUpdate := len(oldMetrics.FailoverPeers) == 0 && len(newMetrics.FailoverPeers) > 0
-	for k, v := range oldMetrics.FailoverPeers {
-		if len(newMetrics.FailoverPeers[k]) > 0 && len(v) == 0 {
-			shouldUpdate = true
-		}
-
-		if len(v) > 0 && len(newMetrics.FailoverPeers[k]) == 0 {
-			newMetrics.FailoverPeers[k] = v
-		}
-	}
-
 	for k := range oldMetrics.Connectivity { // cleanup any left over data, self healing
 	for k := range oldMetrics.Connectivity { // cleanup any left over data, self healing
 		delete(newMetrics.Connectivity, k)
 		delete(newMetrics.Connectivity, k)
 	}
 	}
-	return shouldUpdate
 }
 }

+ 10 - 1
pro/remote_access_client.go

@@ -64,9 +64,18 @@ func disableExtClient(client *models.ExtClient) error {
 	} else {
 	} else {
 		// publish peer update to ingress gateway
 		// publish peer update to ingress gateway
 		if ingressNode, err := logic.GetNodeByID(newClient.IngressGatewayID); err == nil {
 		if ingressNode, err := logic.GetNodeByID(newClient.IngressGatewayID); err == nil {
-			if err = mq.PublishPeerUpdate(); err != nil {
+			if err = mq.PublishPeerUpdate(false); err != nil {
 				slog.Error("error updating ext clients on", "ingress", ingressNode.ID.String(), "err", err.Error())
 				slog.Error("error updating ext clients on", "ingress", ingressNode.ID.String(), "err", err.Error())
 			}
 			}
+			ingressHost, err := logic.GetHost(ingressNode.HostID.String())
+			if err != nil {
+				return err
+			}
+			nodes, err := logic.GetAllNodes()
+			if err != nil {
+				return err
+			}
+			go mq.PublishSingleHostPeerUpdate(ingressHost, nodes, nil, []models.ExtClient{*client}, false)
 		} else {
 		} else {
 			return err
 			return err
 		}
 		}

+ 12 - 13
release.md

@@ -2,18 +2,17 @@
 # Netmaker v0.22.0
 # Netmaker v0.22.0
 
 
 ## Whats New
 ## Whats New
-- Auto Relay via Enrollment key
-- Local Routing Improvements
-## What's Fixed
-- Inconsistency in DNS Entries for Network has been fixed
-- Unique network CIDR validation
-- Fixed extclient caching decrepancies
-- Deleted node peer update fixes when disconnected from network
-- Force Deletion of Daemon Nodes that are stuck in removing state
-## known issues
-- Windows installer does not install WireGuard
-- netclient-gui will continously display error dialog if netmaker server is offline
-- Mac IPv6 addresses/route issues
-- netclient-gui network tab blank after disconnect
+- Revamped Internet Gateways
+- MQ fallback
+- Deprecating TURN in favour of failover hosts on Pro
+- Switch to CoreDNS for DNS resolution
+- Add support for RAC on mobile
 
 
+## What's Fixed
+- Expired nodes not getting deleted
+- NMCTL acl subcommand leading to dirty state
+- Enforce private network ranges
+- Minor bugs and enhacements with user management
+- Scalability issues
 
 
+## Known issues

+ 2 - 2
scripts/netmaker.default.env

@@ -68,6 +68,6 @@ OIDC_ISSUER=
 # Duration of JWT token validity in seconds
 # Duration of JWT token validity in seconds
 JWT_VALIDITY_DURATION=43200
 JWT_VALIDITY_DURATION=43200
 # Auto disable a user's connecteds clients bassed on JWT token expiration
 # Auto disable a user's connecteds clients bassed on JWT token expiration
-RAC_AUTO_DISABLE="true"
+RAC_AUTO_DISABLE=true
 # if turned on data will be cached on to improve performance significantly (IMPORTANT: If HA set to `false` )
 # if turned on data will be cached on to improve performance significantly (IMPORTANT: If HA set to `false` )
-CACHING_ENABLED="true
+CACHING_ENABLED=true

+ 5 - 5
servercfg/serverconf.go

@@ -173,11 +173,11 @@ func GetDB() string {
 
 
 // CacheEnabled - checks if cache is enabled
 // CacheEnabled - checks if cache is enabled
 func CacheEnabled() bool {
 func CacheEnabled() bool {
-	caching := false
-	if os.Getenv("CACHING_ENABLED") != "" {
-		caching = os.Getenv("CACHING_ENABLED") == "true"
-	} else if config.Config.Server.Database != "" {
-		caching = config.Config.Server.CacheEnabled
+	caching := true
+	if os.Getenv("CACHING_ENABLED") == "false" {
+		caching = false
+	} else if config.Config.Server.CacheEnabled == "false" {
+		caching = false
 	}
 	}
 	return caching
 	return caching
 }
 }