소스 검색

failover handlers, reset failovered peer on deletion

Abhishek Kondur 1 년 전
부모
커밋
b63d590e83
5개의 변경된 파일122개의 추가작업 그리고 14개의 파일을 삭제
  1. 1 1
      logic/peers.go
  2. 1 1
      models/api_node.go
  3. 3 3
      models/node.go
  4. 81 8
      pro/controllers/failover.go
  5. 36 1
      pro/logic/failover.go

+ 1 - 1
logic/peers.go

@@ -471,7 +471,7 @@ func getNodeAllowedIPs(peer, node *models.Node) []net.IPNet {
 	if peer.IsRelay {
 		allowedips = append(allowedips, RelayedAllowedIPs(peer, node)...)
 	}
-	if peer.FailOver {
+	if peer.IsFailOver {
 		allowedips = append(allowedips, GetFailOverPeerIps(peer, node)...)
 	}
 	return allowedips

+ 1 - 1
models/api_node.go

@@ -57,7 +57,7 @@ func (a *ApiNode) ConvertToServerNode(currentNode *Node) *Node {
 	convertedNode.PendingDelete = a.PendingDelete
 	convertedNode.FailedOverBy = currentNode.FailedOverBy
 	convertedNode.FailOverPeers = currentNode.FailOverPeers
-	convertedNode.FailOver = a.FailOver
+	convertedNode.IsFailOver = a.FailOver
 	convertedNode.IsEgressGateway = a.IsEgressGateway
 	convertedNode.IsIngressGateway = a.IsIngressGateway
 	// prevents user from changing ranges, must delete and recreate

+ 3 - 3
models/node.go

@@ -92,7 +92,7 @@ type Node struct {
 	// == PRO ==
 	DefaultACL    string              `json:"defaultacl,omitempty" bson:"defaultacl,omitempty" yaml:"defaultacl,omitempty" validate:"checkyesornoorunset"`
 	OwnerID       string              `json:"ownerid,omitempty" bson:"ownerid,omitempty" yaml:"ownerid,omitempty"`
-	FailOver      bool                `json:"fail_over" yaml:"fail_over"`
+	IsFailOver    bool                `json:"is_fail_over" yaml:"is_fail_over"`
 	FailOverPeers map[string]struct{} `json:"fail_over_peers" yaml:"fail_over_peers"`
 	FailedOverBy  uuid.UUID           `json:"failed_over_by" yaml:"failed_over_by"`
 }
@@ -417,8 +417,8 @@ func (newNode *Node) Fill(currentNode *Node, isPro bool) { // TODO add new field
 	if newNode.DefaultACL == "" {
 		newNode.DefaultACL = currentNode.DefaultACL
 	}
-	if newNode.FailOver != currentNode.FailOver {
-		newNode.FailOver = currentNode.FailOver
+	if newNode.IsFailOver != currentNode.IsFailOver {
+		newNode.IsFailOver = currentNode.IsFailOver
 	}
 }
 

+ 81 - 8
pro/controllers/failover.go

@@ -2,6 +2,7 @@ package controllers
 
 import (
 	"encoding/json"
+	"errors"
 	"net/http"
 
 	"github.com/gorilla/mux"
@@ -18,12 +19,88 @@ type FailOverMeReq struct {
 	PeerPubKey string `json:"peer_pub_key"`
 }
 
-// RelayHandlers - handle Pro Relays
-func FailOverHandler(r *mux.Router) {
-	r.HandleFunc("/api/v1/host/{hostid}/failoverme", controller.Authorize(true, false, "host", http.HandlerFunc(failOverME))).Methods(http.MethodPost)
+// FailOverHandlers - handlers for FailOver
+func FailOverHandlers(r *mux.Router) {
+	r.HandleFunc("/api/v1/node/{nodeid}/failover", logic.SecurityCheck(true, http.HandlerFunc(createfailOver))).Methods(http.MethodPost)
+	r.HandleFunc("/api/v1/node/{nodeid}/failover", logic.SecurityCheck(true, http.HandlerFunc(deletefailOver))).Methods(http.MethodDelete)
+	r.HandleFunc("/api/v1/host/{hostid}/failover_me", controller.Authorize(true, false, "host", http.HandlerFunc(failOverME))).Methods(http.MethodPost)
 }
 
-// swagger:route POST /api/host/failOverME host failOverME
+// swagger:route POST /api/v1/node/failover node createfailOver
+//
+// Create a relay.
+//
+//			Schemes: https
+//
+//			Security:
+//	  		oauth
+//
+//			Responses:
+//				200: nodeResponse
+func createfailOver(w http.ResponseWriter, r *http.Request) {
+	var params = mux.Vars(r)
+	nodeid := params["nodeid"]
+	// confirm host exists
+	node, err := logic.GetNodeByID(nodeid)
+	if err != nil {
+		slog.Error("failed to get node:", "error", err.Error())
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
+		return
+	}
+	if proLogic.FailOverExists(node.Network) {
+		logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("failover exists already in the network"), "badrequest"))
+		return
+	}
+	node.IsFailOver = true
+	err = logic.UpsertNode(&node)
+	if err != nil {
+		slog.Error("failed to upsert node", "node", node.ID.String(), "error", err)
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+		return
+	}
+	go mq.PublishPeerUpdate()
+	w.Header().Set("Content-Type", "application/json")
+	logic.ReturnSuccessResponse(w, r, "relayed successfully")
+}
+
+// swagger:route DELETE /api/v1/node/failover node deletefailOver
+//
+// Create a relay.
+//
+//			Schemes: https
+//
+//			Security:
+//	  		oauth
+//
+//			Responses:
+//				200: nodeResponse
+func deletefailOver(w http.ResponseWriter, r *http.Request) {
+	var params = mux.Vars(r)
+	nodeid := params["nodeid"]
+	// confirm host exists
+	node, err := logic.GetNodeByID(nodeid)
+	if err != nil {
+		slog.Error("failed to get node:", "error", err.Error())
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
+		return
+	}
+	node.IsFailOver = false
+	// Reset FailOvered Peers
+	err = logic.UpsertNode(&node)
+	if err != nil {
+		slog.Error("failed to upsert node", "node", node.ID.String(), "error", err)
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+		return
+	}
+	go func() {
+		proLogic.ResetFailOveredPeers(&node)
+		mq.PublishPeerUpdate()
+	}()
+	w.Header().Set("Content-Type", "application/json")
+	logic.ReturnSuccessResponse(w, r, "relayed successfully")
+}
+
+// swagger:route POST /api/host/failOverME host failOver_me
 //
 // Create a relay.
 //
@@ -44,10 +121,6 @@ func failOverME(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 	}
-	/*
-		1. Set On victimNode that needs failedOver to reach - the FailOver and FailedOverBY
-		2. On the Node that needs to reach Victim Node, add to failovered Peers
-	*/
 	var failOverReq FailOverMeReq
 	err = json.NewDecoder(r.Body).Decode(&failOverReq)
 	if err != nil {

+ 36 - 1
pro/logic/failover.go

@@ -3,13 +3,16 @@ package logic
 import (
 	"errors"
 
+	"github.com/google/uuid"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 )
 
 func SetFailOverCtx(failOverNode, victimNode, peerNode models.Node) error {
 	peerNode.FailOverPeers[victimNode.ID.String()] = struct{}{}
+	victimNode.FailOverPeers[peerNode.ID.String()] = struct{}{}
 	victimNode.FailedOverBy = failOverNode.ID
+	peerNode.FailedOverBy = failOverNode.ID
 	if err := logic.UpsertNode(&failOverNode); err != nil {
 		return err
 	}
@@ -26,9 +29,41 @@ func SetFailOverCtx(failOverNode, victimNode, peerNode models.Node) error {
 func GetFailOverNode(network string, allNodes []models.Node) (models.Node, error) {
 	nodes := logic.GetNetworkNodesMemory(allNodes, network)
 	for _, node := range nodes {
-		if node.FailOver {
+		if node.IsFailOver {
 			return node, nil
 		}
 	}
 	return models.Node{}, errors.New("auto relay not found")
 }
+
+// FailOverExists - checks if failOver exists already in the network
+func FailOverExists(network string) (exists bool) {
+	nodes, err := logic.GetNetworkNodes(network)
+	if err != nil {
+		return
+	}
+	for _, node := range nodes {
+		if node.IsFailOver {
+			exists = true
+			return
+		}
+	}
+	return
+}
+
+// ResetFailOveredPeers - reset failovered peers
+func ResetFailOveredPeers(failOverNode *models.Node) error {
+	// Unset FailedOverPeers
+	nodes, err := logic.GetNetworkNodes(failOverNode.Network)
+	if err != nil {
+		return err
+	}
+	for _, node := range nodes {
+		if node.FailedOverBy == failOverNode.ID {
+			node.FailedOverBy = uuid.Nil
+			node.FailOverPeers = make(map[string]struct{})
+			logic.UpsertNode(&node)
+		}
+	}
+	return nil
+}