mirror of
https://github.com/gravitl/netmaker.git
synced 2025-09-08 06:04:20 +08:00
refactor node deletion
This commit is contained in:
parent
b453897e65
commit
4df672de68
7 changed files with 100 additions and 67 deletions
|
@ -665,7 +665,7 @@ func createNode(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
if !updatedUserNode { // user was found but not updated, so delete node
|
||||
logger.Log(0, "failed to add node to user", keyName)
|
||||
logic.DeleteNodeByID(&node, true)
|
||||
logic.DeleteNode(&node, true)
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
@ -1049,22 +1049,11 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
|
|||
var params = mux.Vars(r)
|
||||
var nodeid = params["nodeid"]
|
||||
fromNode := r.Header.Get("requestfrom") == "node"
|
||||
var node, err = logic.GetNodeByID(nodeid)
|
||||
node, err := logic.GetNodeByID(nodeid)
|
||||
if err != nil {
|
||||
if fromNode {
|
||||
node, err = logic.GetDeletedNodeByID(nodeid)
|
||||
if err != nil {
|
||||
logger.Log(0, r.Header.Get("user"),
|
||||
fmt.Sprintf("error fetching node from deleted nodes [ %s ] info: %v", nodeid, err))
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
logger.Log(0, r.Header.Get("user"),
|
||||
fmt.Sprintf("error fetching node [ %s ] info: %v", nodeid, err))
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
|
||||
return
|
||||
}
|
||||
logger.Log(0, "error retrieving node to delete", err.Error())
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
|
||||
return
|
||||
}
|
||||
if isServer(&node) {
|
||||
err := fmt.Errorf("cannot delete server node")
|
||||
|
@ -1080,34 +1069,35 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
}
|
||||
//send update to node to be deleted before deleting on server otherwise message cannot be sent
|
||||
node.Action = models.NODE_DELETE
|
||||
|
||||
err = logic.DeleteNodeByID(&node, fromNode)
|
||||
if err != nil {
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||
if err := logic.DeleteNode(&node, fromNode); err != nil {
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("failed to delete node"), "internal"))
|
||||
return
|
||||
}
|
||||
if fromNode {
|
||||
// deletes node related role and client
|
||||
event := mq.MqDynsecPayload{
|
||||
Commands: []mq.MqDynSecCmd{
|
||||
{
|
||||
Command: mq.DeleteClientCmd,
|
||||
Username: nodeid,
|
||||
//check if server should be removed from mq
|
||||
found := false
|
||||
// err is irrelevent
|
||||
nodes, _ := logic.GetAllNodes()
|
||||
for _, nodetocheck := range nodes {
|
||||
if nodetocheck.HostID == node.HostID {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
// deletes node related role and client
|
||||
event := mq.MqDynsecPayload{
|
||||
Commands: []mq.MqDynSecCmd{
|
||||
{
|
||||
Command: mq.DeleteClientCmd,
|
||||
Username: node.HostID,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := mq.PublishEventToDynSecTopic(event); err != nil {
|
||||
logger.Log(0, fmt.Sprintf("failed to send DynSec command [%v]: %v",
|
||||
event.Commands, err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
if servercfg.Is_EE {
|
||||
if err = logic.EnterpriseResetAllPeersFailovers(node.ID, node.Network); err != nil {
|
||||
logger.Log(0, "failed to reset failover lists during node delete for node", node.Name, node.Network)
|
||||
}
|
||||
if err := mq.PublishEventToDynSecTopic(event); err != nil {
|
||||
logger.Log(0, fmt.Sprintf("failed to send DynSec command [%v]: %v",
|
||||
event.Commands, err.Error()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ func DeleteNetwork(network string) error {
|
|||
servers, err := GetSortedNetworkServerNodes(network)
|
||||
if err == nil {
|
||||
for _, s := range servers {
|
||||
if err = DeleteNodeByID(&s, true); err != nil {
|
||||
if err = DeleteNode(&s, true); err != nil {
|
||||
logger.Log(2, "could not removed server", s.Name, "before deleting network", network)
|
||||
} else {
|
||||
logger.Log(2, "removed server", s.Name, "before deleting network", network)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -22,8 +23,14 @@ 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"
|
||||
const (
|
||||
// RELAY_NODE_ERR - error to return if relay node is unfound
|
||||
RELAY_NODE_ERR = "could not find relay for node"
|
||||
// NodePurgeTime time to wait for node to response to a NODE_DELETE actions
|
||||
NodePurgeTime = time.Second * 10
|
||||
// NodePurgeCheckTime is how often to check nodes for Pending Delete
|
||||
NodePurgeCheckTime = time.Second * 30
|
||||
)
|
||||
|
||||
// GetNetworkNodes - gets the nodes of a network
|
||||
func GetNetworkNodes(network string) ([]models.Node, error) {
|
||||
|
@ -160,8 +167,31 @@ func UpdateNode(currentNode *models.Node, newNode *models.Node) error {
|
|||
return fmt.Errorf("failed to update node " + currentNode.ID + ", cannot change ID.")
|
||||
}
|
||||
|
||||
// DeleteNodeByID - deletes a node from database or moves into delete nodes table
|
||||
func DeleteNodeByID(node *models.Node, exterminate bool) error {
|
||||
// DeleteNode - marks node for deletion if called by UI or deletes node if called by node
|
||||
func DeleteNode(node *models.Node, purge bool) error {
|
||||
if !purge {
|
||||
newnode := node
|
||||
newnode.PendingDelete = true
|
||||
newnode.Action = models.NODE_DELETE
|
||||
if err := UpdateNode(node, newnode); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err := DeleteNodeByID(node); err != nil {
|
||||
return err
|
||||
}
|
||||
if servercfg.Is_EE {
|
||||
if err := EnterpriseResetAllPeersFailovers(node.ID, node.Network); err != nil {
|
||||
logger.Log(0, "failed to reset failover lists during node delete for node", node.Name, node.Network)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteNodeByID - deletes a node from database
|
||||
func DeleteNodeByID(node *models.Node) error {
|
||||
var err error
|
||||
var key = node.ID
|
||||
//delete any ext clients as required
|
||||
|
@ -170,27 +200,11 @@ func DeleteNodeByID(node *models.Node, exterminate bool) error {
|
|||
logger.Log(0, "failed to deleted ext clients", err.Error())
|
||||
}
|
||||
}
|
||||
if !exterminate {
|
||||
node.Action = models.NODE_DELETE
|
||||
nodedata, err := json.Marshal(&node)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = database.Insert(key, string(nodedata), database.DELETED_NODES_TABLE_NAME)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := database.DeleteRecord(database.DELETED_NODES_TABLE_NAME, key); err != nil {
|
||||
logger.Log(2, err.Error())
|
||||
}
|
||||
}
|
||||
if err = database.DeleteRecord(database.NODES_TABLE_NAME, key); err != nil {
|
||||
if !database.IsEmptyRecord(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if servercfg.IsDNSMode() {
|
||||
SetDNS()
|
||||
}
|
||||
|
@ -200,7 +214,6 @@ func DeleteNodeByID(node *models.Node, exterminate bool) error {
|
|||
logger.Log(0, "failed to dissasociate", node.OwnerID, "from node", node.ID, ":", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
_, err = nodeacls.RemoveNodeACL(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID))
|
||||
if err != nil {
|
||||
// ignoring for now, could hit a nil pointer if delete called twice
|
||||
|
@ -210,11 +223,9 @@ func DeleteNodeByID(node *models.Node, exterminate bool) error {
|
|||
if err = DeleteMetrics(node.ID); err != nil {
|
||||
logger.Log(1, "unable to remove metrics from DB for node", node.ID, err.Error())
|
||||
}
|
||||
|
||||
if node.IsServer == "yes" {
|
||||
return removeLocalServer(node)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -773,4 +784,34 @@ func updateProNodeACLS(node *models.Node) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func PurgePendingNodes(ctx context.Context) {
|
||||
ticker := time.NewTicker(NodePurgeCheckTime)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
nodes, err := GetAllNodes()
|
||||
if err != nil {
|
||||
logger.Log(0, "PurgePendingNodes failed to retrieve nodes", err.Error())
|
||||
continue
|
||||
}
|
||||
for _, node := range nodes {
|
||||
if node.PendingDelete {
|
||||
modified := time.Unix(node.LastModified, 0)
|
||||
if time.Since(modified) > NodePurgeTime {
|
||||
if err := DeleteNode(&node, true); err != nil {
|
||||
logger.Log(0, "failed to purge node", node.ID, err.Error())
|
||||
} else {
|
||||
logger.Log(0, "purged node ", node.ID)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// == END PRO ==
|
||||
|
|
|
@ -193,7 +193,7 @@ func ServerUpdate(serverNode *models.Node, ifaceDelta bool) error {
|
|||
|
||||
var err = ServerPull(serverNode, ifaceDelta)
|
||||
if isDeleteError(err) {
|
||||
return DeleteNodeByID(serverNode, true)
|
||||
return DeleteNode(serverNode, true)
|
||||
} else if err != nil && !ifaceDelta {
|
||||
err = ServerPull(serverNode, true)
|
||||
if err != nil {
|
||||
|
@ -224,7 +224,7 @@ func checkNodeActions(node *models.Node) string {
|
|||
}
|
||||
}
|
||||
if node.Action == models.NODE_DELETE {
|
||||
err := DeleteNodeByID(node, true)
|
||||
err := DeleteNode(node, true)
|
||||
if err != nil {
|
||||
logger.Log(1, "error deleting locally:", err.Error())
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ func ManageZombies(ctx context.Context) {
|
|||
continue
|
||||
}
|
||||
if time.Since(time.Unix(node.LastCheckIn, 0)) > time.Minute*ZOMBIE_DELETE_TIME {
|
||||
if err := DeleteNodeByID(&node, true); err != nil {
|
||||
if err := DeleteNode(&node, true); err != nil {
|
||||
logger.Log(1, "error deleting zombie node", zombies[i], err.Error())
|
||||
continue
|
||||
}
|
||||
|
|
1
main.go
1
main.go
|
@ -184,6 +184,7 @@ func runMessageQueue(wg *sync.WaitGroup) {
|
|||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go mq.Keepalive(ctx)
|
||||
go logic.ManageZombies(ctx)
|
||||
go logic.PurgePendingNodes(ctx)
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGTERM, os.Interrupt)
|
||||
<-quit
|
||||
|
|
|
@ -103,6 +103,7 @@ type Node struct {
|
|||
FirewallInUse string `json:"firewallinuse" bson:"firewallinuse" yaml:"firewallinuse"`
|
||||
InternetGateway string `json:"internetgateway" bson:"internetgateway" yaml:"internetgateway"`
|
||||
Connected string `json:"connected" bson:"connected" yaml:"connected" validate:"checkyesorno"`
|
||||
PendingDelete bool `json:"pendingdelete" bson:"pendingdelete" yaml:"pendingdelete"`
|
||||
// == 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"`
|
||||
|
|
Loading…
Add table
Reference in a new issue