Browse Source

Merge pull request #692 from gravitl/feature_v0.10.0_relay

backup logic for relay failing, dont allow server to be relayed
Alex Feiszli 3 years ago
parent
commit
6160ec2725
6 changed files with 129 additions and 5 deletions
  1. 23 1
      controllers/ext_client.go
  2. 9 1
      controllers/node_grpc.go
  3. 23 2
      logic/nodes.go
  4. 33 1
      logic/relay.go
  5. 25 0
      mq/mq.go
  6. 16 0
      netclient/local/dns.go

+ 23 - 1
controllers/ext_client.go

@@ -14,6 +14,7 @@ import (
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/mq"
 	"github.com/skip2/go-qrcode"
 )
 
@@ -238,6 +239,10 @@ func createExtClient(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 	w.WriteHeader(http.StatusOK)
+	err = mq.PublishExtPeerUpdate(&node)
+	if err != nil {
+		logger.Log(1, "error setting ext peers on "+nodeid+": "+err.Error())
+	}
 }
 
 func updateExtClient(w http.ResponseWriter, r *http.Request) {
@@ -282,13 +287,30 @@ func deleteExtClient(w http.ResponseWriter, r *http.Request) {
 	// get params
 	var params = mux.Vars(r)
 
-	err := logic.DeleteExtClient(params["network"], params["clientid"])
+	extclient, err := logic.GetExtClient(params["clientid"], params["network"])
+	if err != nil {
+		err = errors.New("Could not delete extclient " + params["clientid"])
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
+	ingressnode, err := logic.GetNodeByID(extclient.IngressGatewayID)
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
+
+	err = logic.DeleteExtClient(params["network"], params["clientid"])
 
 	if err != nil {
 		err = errors.New("Could not delete extclient " + params["clientid"])
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		return
 	}
+
+	err = mq.PublishExtPeerUpdate(&ingressnode)
+	if err != nil {
+		logger.Log(1, "error setting ext peers on "+ingressnode.ID+": "+err.Error())
+	}
 	logger.Log(1, r.Header.Get("user"),
 		"Deleted extclient client", params["clientid"], "from network", params["network"])
 	returnSuccessResponse(w, r, params["clientid"]+" deleted.")

+ 9 - 1
controllers/node_grpc.go

@@ -5,6 +5,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"strings"
 	"time"
 
 	nodepb "github.com/gravitl/netmaker/grpc"
@@ -238,7 +239,14 @@ func (s *NodeServiceServer) GetPeers(ctx context.Context, req *nodepb.Object) (*
 	}
 	peers, err := logic.GetPeersList(node.Network, excludeIsRelayed, relayedNode)
 	if err != nil {
-		return nil, err
+		if strings.Contains(err.Error(), logic.RELAY_NODE_ERR) {
+			peers, err = logic.PeerListUnRelay(node.ID, node.Network)
+			if err != nil {
+				return nil, err
+			}
+		} else {
+			return nil, err
+		}
 	}
 
 	peersData, err := json.Marshal(&peers)

+ 23 - 2
logic/nodes.go

@@ -5,6 +5,7 @@ import (
 	"errors"
 	"fmt"
 	"sort"
+	"strings"
 	"time"
 
 	"github.com/go-playground/validator/v10"
@@ -18,6 +19,9 @@ import (
 	"golang.org/x/crypto/bcrypt"
 )
 
+// RELAY_NODE_ERR - error to return if relay node is unfound
+const RELAY_NODE_ERR = "could not find relay for node"
+
 // GetNetworkNodes - gets the nodes of a network
 func GetNetworkNodes(network string) ([]models.Node, error) {
 	var nodes []models.Node
@@ -103,7 +107,14 @@ func GetPeers(node *models.Node) ([]models.Node, error) {
 	}
 	peers, err := GetPeersList(node.Network, excludeIsRelayed, relayedNode)
 	if err != nil {
-		return nil, err
+		if strings.Contains(err.Error(), RELAY_NODE_ERR) {
+			peers, err = PeerListUnRelay(node.ID, node.Network)
+			if err != nil {
+				return nil, err
+			}
+		} else {
+			return nil, err
+		}
 	}
 	return peers, nil
 }
@@ -498,7 +509,7 @@ func GetNodeRelay(network string, relayedNodeAddr string) (models.Node, error) {
 			}
 		}
 	}
-	return relay, errors.New("could not find relay for node " + relayedNodeAddr)
+	return relay, errors.New(RELAY_NODE_ERR + " " + relayedNodeAddr)
 }
 
 // GetNodeByIDorMacAddress - gets the node, if a mac address exists, but not id, then it should delete it and recreate in DB with new ID
@@ -590,6 +601,16 @@ func GetNetworkServerLocal(network string) (models.Node, error) {
 	return models.Node{}, errors.New("could not find node for local server")
 }
 
+// IsLocalServer - get network server node ID if exists
+func IsLocalServer(node *models.Node) bool {
+	var islocal bool
+	local, err := GetNetworkServerLocal(node.Network)
+	if err != nil {
+		return islocal
+	}
+	return node.ID != "" && local.ID == node.ID
+}
+
 // validateServer - make sure servers dont change port or address
 func validateServer(currentNode, newNode *models.Node) bool {
 	return (newNode.Address == currentNode.Address &&

+ 33 - 1
logic/relay.go

@@ -63,7 +63,7 @@ func SetRelayedNodes(yesOrno string, networkName string, addrs []string) error {
 		if err != nil {
 			return err
 		}
-		if node.Network == networkName {
+		if node.Network == networkName && !(node.IsServer == "yes") {
 			for _, addr := range addrs {
 				if addr == node.Address || addr == node.Address6 {
 					node.IsRelayed = yesOrno
@@ -84,6 +84,38 @@ func SetRelayedNodes(yesOrno string, networkName string, addrs []string) error {
 	return nil
 }
 
+// SetNodeIsRelayed - Sets IsRelayed to on or off for relay
+func SetNodeIsRelayed(yesOrno string, id string) error {
+	node, err := GetNodeByID(id)
+	if err != nil {
+		return err
+	}
+	network, err := GetNetworkByNode(&node)
+	if err != nil {
+		return err
+	}
+	node.IsRelayed = yesOrno
+	if yesOrno == "yes" {
+		node.UDPHolePunch = "no"
+	} else {
+		node.UDPHolePunch = network.DefaultUDPHolePunch
+	}
+	data, err := json.Marshal(&node)
+	if err != nil {
+		return err
+	}
+	return database.Insert(node.ID, string(data), database.NODES_TABLE_NAME)
+}
+
+// PeerListUnRelay - call this function if a relayed node fails to get its relay: unrelays node and gets new peer list
+func PeerListUnRelay(id string, network string) ([]models.Node, error) {
+	err := SetNodeIsRelayed("no", id)
+	if err != nil {
+		return nil, err
+	}
+	return GetPeersList(network, true, "")
+}
+
 // ValidateRelay - checks if relay is valid
 func ValidateRelay(relay models.RelayRequest) error {
 	var err error

+ 25 - 0
mq/mq.go

@@ -133,6 +133,31 @@ func PublishPeerUpdate(newNode *models.Node) error {
 	return nil
 }
 
+// PublishPeerUpdate --- deterines and publishes a peer update to all the peers of a node
+func PublishExtPeerUpdate(node *models.Node) error {
+	var err error
+	if logic.IsLocalServer(node) {
+		if err = logic.ServerUpdate(node, false); err != nil {
+			logger.Log(1, "server node:", node.ID, "failed to update peers with ext clients")
+			return err
+		} else {
+			return nil
+		}
+	}
+	if !servercfg.IsMessageQueueBackend() {
+		return nil
+	}
+	peerUpdate, err := logic.GetPeerUpdate(node)
+	if err != nil {
+		return err
+	}
+	data, err := json.Marshal(&peerUpdate)
+	if err != nil {
+		return err
+	}
+	return publish(node, fmt.Sprintf("peers/%s/%s", node.Network, node.ID), data)
+}
+
 // GetID -- decodes a message queue topic and returns the embedded node.ID
 func GetID(topic string) (string, error) {
 	parts := strings.Split(topic, "/")

+ 16 - 0
netclient/local/dns.go

@@ -91,6 +91,7 @@ func UpdateDNS(ifacename string, network string, nameserver string) error {
 	return err
 }
 
+// IsDNSReachable - checks if nameserver is reachable
 func IsDNSReachable(nameserver string) bool {
 	port := "53"
 	protocols := [2]string{"tcp", "udp"}
@@ -108,3 +109,18 @@ func IsDNSReachable(nameserver string) bool {
 	}
 	return true
 }
+
+// IsDNSWorking - checks if record is returned by correct nameserver
+func IsDNSWorking(network string, nameserver string) bool {
+	var isworking bool
+	servers, err := net.LookupNS("netmaker" + "." + "network")
+	if err != nil {
+		return isworking
+	}
+	for _, ns := range servers {
+		if strings.Contains(ns.Host, nameserver) {
+			isworking = true
+		}
+	}
+	return isworking
+}