mirror of
https://github.com/gravitl/netmaker.git
synced 2024-09-21 07:46:04 +08:00
Merge pull request #620 from gravitl/feature_v0.10.0_better_server
Feature v0.10.0 better server
This commit is contained in:
commit
de8c4d782d
|
@ -12,7 +12,6 @@ import (
|
|||
"github.com/gravitl/netmaker/logic"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/gravitl/netmaker/servercfg"
|
||||
"github.com/gravitl/netmaker/serverctl"
|
||||
)
|
||||
|
||||
const ALL_NETWORK_ACCESS = "THIS_USER_HAS_ALL"
|
||||
|
@ -226,9 +225,8 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
if servercfg.IsClientMode() != "off" {
|
||||
var success bool
|
||||
success, err = serverctl.AddNetwork(&network)
|
||||
if err != nil || !success {
|
||||
err = logic.ServerJoin(&network)
|
||||
if err != nil {
|
||||
logic.DeleteNetwork(network.NetID)
|
||||
if err == nil {
|
||||
err = errors.New("Failed to add server to network " + network.DisplayName)
|
||||
|
|
|
@ -32,7 +32,6 @@ func nodeHandlers(r *mux.Router) {
|
|||
r.HandleFunc("/api/nodes/{network}", createNode).Methods("POST")
|
||||
r.HandleFunc("/api/nodes/adm/{network}/lastmodified", authorize(true, "network", http.HandlerFunc(getLastModified))).Methods("GET")
|
||||
r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods("POST")
|
||||
|
||||
}
|
||||
|
||||
func authenticate(response http.ResponseWriter, request *http.Request) {
|
||||
|
@ -186,7 +185,7 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha
|
|||
r.Header.Set("ismasterkey", "yes")
|
||||
}
|
||||
if !isadmin && params["network"] != "" {
|
||||
if functions.SliceContains(networks, params["network"]) {
|
||||
if logic.StringSliceContains(networks, params["network"]) {
|
||||
isnetadmin = true
|
||||
}
|
||||
}
|
||||
|
@ -404,6 +403,11 @@ func createNode(w http.ResponseWriter, r *http.Request) {
|
|||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
if err = runServerPeerUpdate(node.Network, true); err != nil {
|
||||
logger.Log(1, "internal error when creating node:", node.ID)
|
||||
}
|
||||
|
||||
logger.Log(1, r.Header.Get("user"), "created new node", node.Name, "on network", node.Network)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(node)
|
||||
|
@ -414,11 +418,15 @@ func createNode(w http.ResponseWriter, r *http.Request) {
|
|||
func uncordonNode(w http.ResponseWriter, r *http.Request) {
|
||||
var params = mux.Vars(r)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
node, err := logic.UncordonNode(params["nodeid"])
|
||||
var nodeid = params["nodeid"]
|
||||
node, err := logic.UncordonNode(nodeid)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
if err = runServerPeerUpdate(node.Network, false); err != nil {
|
||||
logger.Log(1, "internal error when approving node:", nodeid)
|
||||
}
|
||||
logger.Log(1, r.Header.Get("user"), "uncordoned node", node.Name)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode("SUCCESS")
|
||||
|
@ -440,6 +448,9 @@ func createEgressGateway(w http.ResponseWriter, r *http.Request) {
|
|||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
if err = runServerPeerUpdate(gateway.NetID, true); err != nil {
|
||||
logger.Log(1, "internal error when setting peers after creating egress on node:", gateway.NodeID)
|
||||
}
|
||||
logger.Log(1, r.Header.Get("user"), "created egress gateway on node", gateway.NodeID, "on network", gateway.NetID)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(node)
|
||||
|
@ -455,6 +466,9 @@ func deleteEgressGateway(w http.ResponseWriter, r *http.Request) {
|
|||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
if err = runServerPeerUpdate(netid, true); err != nil {
|
||||
logger.Log(1, "internal error when setting peers after removing egress on node:", nodeid)
|
||||
}
|
||||
logger.Log(1, r.Header.Get("user"), "deleted egress gateway", nodeid, "on network", netid)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(node)
|
||||
|
@ -472,6 +486,7 @@ func createIngressGateway(w http.ResponseWriter, r *http.Request) {
|
|||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
logger.Log(1, r.Header.Get("user"), "created ingress gateway on node", nodeid, "on network", netid)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(node)
|
||||
|
@ -486,6 +501,7 @@ func deleteIngressGateway(w http.ResponseWriter, r *http.Request) {
|
|||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
logger.Log(1, r.Header.Get("user"), "deleted ingress gateway", nodeid)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(node)
|
||||
|
@ -530,11 +546,14 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
|
|||
newNode.PostUp = node.PostUp
|
||||
}
|
||||
|
||||
var shouldPeersUpdate = logic.ShouldPeersUpdate(&node, &newNode)
|
||||
|
||||
err = logic.UpdateNode(&node, &newNode)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
if relayupdate {
|
||||
logic.UpdateRelay(node.Network, node.RelayAddrs, newNode.RelayAddrs)
|
||||
if err = logic.NetworkNodesUpdatePullChanges(node.Network); err != nil {
|
||||
|
@ -542,9 +561,11 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
if servercfg.IsDNSMode() {
|
||||
if servercfg.IsDNSMode() { // TODO check when this should be updated..
|
||||
err = logic.SetDNS()
|
||||
}
|
||||
|
||||
err = runServerPeerUpdate(node.Network, shouldPeersUpdate)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
|
@ -572,6 +593,12 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
err = runServerPeerUpdate(node.Network, true)
|
||||
if err != nil {
|
||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
logger.Log(1, r.Header.Get("user"), "Deleted node", nodeid, "from network", params["network"])
|
||||
returnSuccessResponse(w, r, nodeid+" deleted.")
|
||||
}
|
||||
|
|
|
@ -86,6 +86,12 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.Object)
|
|||
return nil, err
|
||||
}
|
||||
|
||||
err = runServerPeerUpdate(node.Network, true)
|
||||
if err != nil {
|
||||
logger.Log(1, "internal error when setting peers after node,", node.ID, "was created (gRPC)")
|
||||
}
|
||||
logger.Log(0, "new node,", node.Name, ", added on network,"+node.Network)
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
|
@ -106,6 +112,7 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.Object)
|
|||
newnode.PostDown = node.PostDown
|
||||
newnode.PostUp = node.PostUp
|
||||
}
|
||||
var shouldPeersUpdate = logic.ShouldPeersUpdate(&node, &newnode)
|
||||
|
||||
err = logic.UpdateNode(&node, &newnode)
|
||||
if err != nil {
|
||||
|
@ -119,6 +126,10 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.Object)
|
|||
if errN != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = runServerPeerUpdate(newnode.Network, shouldPeersUpdate)
|
||||
if err != nil {
|
||||
logger.Log(1, "could not update peers on gRPC after node,", newnode.ID, "updated (gRPC), \nerror:", err.Error())
|
||||
}
|
||||
return &nodepb.Object{
|
||||
Data: string(nodeData),
|
||||
Type: nodepb.NODE_TYPE,
|
||||
|
@ -138,6 +149,11 @@ func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.Object)
|
|||
return nil, err
|
||||
}
|
||||
|
||||
err = runServerPeerUpdate(node.Network, true)
|
||||
if err != nil {
|
||||
logger.Log(1, "internal error when setting peers after deleting node:", node.ID, "over gRPC")
|
||||
}
|
||||
|
||||
return &nodepb.Object{
|
||||
Data: "success",
|
||||
Type: nodepb.STRING_TYPE,
|
||||
|
@ -152,9 +168,6 @@ func (s *NodeServiceServer) GetPeers(ctx context.Context, req *nodepb.Object) (*
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if node.IsServer == "yes" && logic.IsLeader(&node) {
|
||||
logic.SetNetworkServerPeers(&node)
|
||||
}
|
||||
excludeIsRelayed := node.IsRelay != "yes"
|
||||
var relayedNode string
|
||||
if node.IsRelayed == "yes" {
|
||||
|
|
|
@ -26,6 +26,9 @@ func createRelay(w http.ResponseWriter, r *http.Request) {
|
|||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
if err = runServerPeerUpdate(relay.NetID, true); err != nil {
|
||||
logger.Log(1, "internal error when creating relay on node:", relay.NodeID)
|
||||
}
|
||||
logger.Log(1, r.Header.Get("user"), "created relay on node", relay.NodeID, "on network", relay.NetID)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(node)
|
||||
|
@ -41,6 +44,9 @@ func deleteRelay(w http.ResponseWriter, r *http.Request) {
|
|||
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
if err = runServerPeerUpdate(netid, true); err != nil {
|
||||
logger.Log(1, "internal error when deleting relay on node:", nodeid)
|
||||
}
|
||||
logger.Log(1, r.Header.Get("user"), "deleted egress gateway", nodeid, "on network", netid)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(node)
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/gravitl/netmaker/logic"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/gravitl/netmaker/servercfg"
|
||||
"github.com/gravitl/netmaker/serverctl"
|
||||
)
|
||||
|
||||
func serverHandlers(r *mux.Router) {
|
||||
|
@ -70,9 +69,8 @@ func removeNetwork(w http.ResponseWriter, r *http.Request) {
|
|||
// get params
|
||||
var params = mux.Vars(r)
|
||||
|
||||
success, err := serverctl.RemoveNetwork(params["network"])
|
||||
|
||||
if err != nil || !success {
|
||||
err := logic.DeleteNetwork(params["network"])
|
||||
if err != nil {
|
||||
json.NewEncoder(w).Encode("Could not remove server from network " + params["network"])
|
||||
return
|
||||
}
|
||||
|
|
23
controllers/server_util.go
Normal file
23
controllers/server_util.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"github.com/gravitl/netmaker/logger"
|
||||
"github.com/gravitl/netmaker/logic"
|
||||
)
|
||||
|
||||
func runServerPeerUpdate(network string, shouldPeerUpdate bool) error {
|
||||
|
||||
var currentServerNodeID, err = logic.GetNetworkServerNodeID(network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var currentServerNode, currErr = logic.GetNodeByID(currentServerNodeID)
|
||||
if currErr != nil {
|
||||
return currErr
|
||||
}
|
||||
if err = logic.ServerUpdate(¤tServerNode, shouldPeerUpdate); err != nil {
|
||||
logger.Log(1, "server node:", currentServerNode.ID, "failed update")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -31,20 +31,6 @@ func ParseIntClient(value string) (models.IntClient, error) {
|
|||
return intClient, err
|
||||
}
|
||||
|
||||
//Takes in an arbitrary field and value for field and checks to see if any other
|
||||
//node has that value for the same field within the network
|
||||
|
||||
// SliceContains - sees if a slice contains something
|
||||
func SliceContains(slice []string, item string) bool {
|
||||
set := make(map[string]struct{}, len(slice))
|
||||
for _, s := range slice {
|
||||
set[s] = struct{}{}
|
||||
}
|
||||
|
||||
_, ok := set[item]
|
||||
return ok
|
||||
}
|
||||
|
||||
// GetPeersList - gets peers for given network
|
||||
func GetPeersList(networkName string) ([]models.PeersResponse, error) {
|
||||
|
||||
|
|
142
logic/nodes.go
142
logic/nodes.go
|
@ -9,30 +9,22 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/google/uuid"
|
||||
"github.com/gravitl/netmaker/database"
|
||||
"github.com/gravitl/netmaker/logger"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/gravitl/netmaker/servercfg"
|
||||
"github.com/gravitl/netmaker/validation"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// GetNetworkNodes - gets the nodes of a network
|
||||
func GetNetworkNodes(network string) ([]models.Node, error) {
|
||||
var nodes = []models.Node{}
|
||||
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
||||
var nodes, err = GetAllNodes()
|
||||
if err != nil {
|
||||
if database.IsEmptyRecord(err) {
|
||||
return []models.Node{}, nil
|
||||
}
|
||||
return nodes, err
|
||||
return []models.Node{}, err
|
||||
}
|
||||
for _, value := range collection {
|
||||
|
||||
var node models.Node
|
||||
err := json.Unmarshal([]byte(value), &node)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, node := range nodes {
|
||||
if node.Network == network {
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
@ -86,7 +78,7 @@ func UncordonNode(nodeid string) (models.Node, error) {
|
|||
// GetPeers - gets the peers of a given node
|
||||
func GetPeers(node *models.Node) ([]models.Node, error) {
|
||||
if IsLeader(node) {
|
||||
SetNetworkServerPeers(node)
|
||||
setNetworkServerPeers(node)
|
||||
}
|
||||
excludeIsRelayed := node.IsRelay != "yes"
|
||||
var relayedNode string
|
||||
|
@ -166,6 +158,128 @@ func ValidateNode(node *models.Node, isUpdate bool) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// CreateNode - creates a node in database
|
||||
func CreateNode(node *models.Node) error {
|
||||
|
||||
//encrypt that password so we never see it
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(node.Password), 5)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//set password to encrypted password
|
||||
node.Password = string(hash)
|
||||
if node.Name == models.NODE_SERVER_NAME {
|
||||
node.IsServer = "yes"
|
||||
}
|
||||
if node.DNSOn == "" {
|
||||
if servercfg.IsDNSMode() {
|
||||
node.DNSOn = "yes"
|
||||
} else {
|
||||
node.DNSOn = "no"
|
||||
}
|
||||
}
|
||||
SetNodeDefaults(node)
|
||||
node.Address, err = UniqueAddress(node.Network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
node.Address6, err = UniqueAddress6(node.Network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: This covers legacy nodes, eventually want to remove legacy check
|
||||
if node.IsServer == "yes" {
|
||||
node.ID = uuid.NewString()
|
||||
} else if node.IsServer != "yes" || (node.ID == "" || strings.Contains(node.ID, "###")) {
|
||||
node.ID = uuid.NewString()
|
||||
}
|
||||
|
||||
//Create a JWT for the node
|
||||
tokenString, _ := CreateJWT(node.ID, node.MacAddress, node.Network)
|
||||
if tokenString == "" {
|
||||
//returnErrorResponse(w, r, errorResponse)
|
||||
return err
|
||||
}
|
||||
err = ValidateNode(node, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodebytes, err := json.Marshal(&node)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = database.Insert(node.ID, string(nodebytes), database.NODES_TABLE_NAME)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if node.IsPending != "yes" {
|
||||
DecrimentKey(node.Network, node.AccessKey)
|
||||
}
|
||||
SetNetworkNodesLastModified(node.Network)
|
||||
if servercfg.IsDNSMode() {
|
||||
err = SetDNS()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// ShouldPeersUpdate - takes old node and sees if certain fields changing would trigger a peer update
|
||||
func ShouldPeersUpdate(currentNode *models.Node, newNode *models.Node) bool {
|
||||
SetNodeDefaults(newNode)
|
||||
// single comparison statements
|
||||
if newNode.Endpoint != currentNode.Endpoint ||
|
||||
newNode.LocalAddress != currentNode.LocalAddress ||
|
||||
newNode.PublicKey != currentNode.PublicKey ||
|
||||
newNode.Address != currentNode.Address ||
|
||||
newNode.IsEgressGateway != currentNode.IsEgressGateway ||
|
||||
newNode.IsIngressGateway != currentNode.IsIngressGateway ||
|
||||
newNode.IsRelay != currentNode.IsRelay ||
|
||||
newNode.UDPHolePunch != currentNode.UDPHolePunch ||
|
||||
newNode.IsPending != currentNode.IsPending ||
|
||||
len(newNode.ExcludedAddrs) != len(currentNode.ExcludedAddrs) ||
|
||||
len(newNode.AllowedIPs) != len(currentNode.AllowedIPs) {
|
||||
return true
|
||||
}
|
||||
|
||||
// multi-comparison statements
|
||||
if newNode.IsDualStack == "yes" {
|
||||
if newNode.Address6 != currentNode.Address6 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if newNode.IsEgressGateway == "yes" {
|
||||
if len(currentNode.EgressGatewayRanges) != len(newNode.EgressGatewayRanges) {
|
||||
return true
|
||||
}
|
||||
for _, address := range newNode.EgressGatewayRanges {
|
||||
if !StringSliceContains(currentNode.EgressGatewayRanges, address) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if newNode.IsRelay == "yes" {
|
||||
if len(currentNode.RelayAddrs) != len(newNode.RelayAddrs) {
|
||||
return true
|
||||
}
|
||||
for _, address := range newNode.RelayAddrs {
|
||||
if !StringSliceContains(currentNode.RelayAddrs, address) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, address := range newNode.AllowedIPs {
|
||||
if !StringSliceContains(currentNode.AllowedIPs, address) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// GetAllNodes - returns all nodes in the DB
|
||||
func GetAllNodes() ([]models.Node, error) {
|
||||
var nodes []models.Node
|
||||
|
|
152
logic/server.go
152
logic/server.go
|
@ -17,6 +17,7 @@ import (
|
|||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
)
|
||||
|
||||
// == Public ==
|
||||
// == Join, Checkin, and Leave for Server ==
|
||||
|
||||
// KUBERNETES_LISTEN_PORT - starting port for Kubernetes in order to use NodePort range
|
||||
|
@ -26,7 +27,7 @@ const KUBERNETES_LISTEN_PORT = 31821
|
|||
const KUBERNETES_SERVER_MTU = 1024
|
||||
|
||||
// ServerJoin - responsible for joining a server to a network
|
||||
func ServerJoin(networkSettings *models.Network, serverID string) error {
|
||||
func ServerJoin(networkSettings *models.Network) error {
|
||||
|
||||
if networkSettings == nil || networkSettings.NetID == "" {
|
||||
return errors.New("no network provided")
|
||||
|
@ -119,7 +120,7 @@ func ServerJoin(networkSettings *models.Network, serverID string) error {
|
|||
if err = StorePrivKey(node.ID, privateKey); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ServerPush(node); err != nil {
|
||||
if err = serverPush(node); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -137,18 +138,12 @@ func ServerJoin(networkSettings *models.Network, serverID string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ServerCheckin - runs pulls and pushes for server
|
||||
func ServerCheckin(serverID string, mac string, network string) error {
|
||||
var serverNode = &models.Node{}
|
||||
var currentNode, err = GetNodeByIDorMacAddress(serverID, mac, network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
serverNode = ¤tNode
|
||||
|
||||
err = ServerPull(serverNode, false)
|
||||
// ServerUpdate - updates the server
|
||||
// replaces legacy Checkin code
|
||||
func ServerUpdate(serverNode *models.Node, shouldPeerUpdate bool) error {
|
||||
var err = serverPull(serverNode, shouldPeerUpdate)
|
||||
if isDeleteError(err) {
|
||||
return ServerLeave(currentNode.ID)
|
||||
return DeleteNodeByID(serverNode, true)
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -158,66 +153,7 @@ func ServerCheckin(serverID string, mac string, network string) error {
|
|||
return errors.New("node has been removed")
|
||||
}
|
||||
|
||||
return ServerPush(serverNode)
|
||||
}
|
||||
|
||||
// ServerPull - pulls current config/peers for server
|
||||
func ServerPull(serverNode *models.Node, onErr bool) error {
|
||||
|
||||
var err error
|
||||
if serverNode.IPForwarding == "yes" {
|
||||
if err = setIPForwardingLinux(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
serverNode.OS = runtime.GOOS
|
||||
|
||||
if serverNode.PullChanges == "yes" || onErr {
|
||||
// check for interface change
|
||||
// checks if address is in use by another interface
|
||||
var oldIfaceName, isIfacePresent = isInterfacePresent(serverNode.Interface, serverNode.Address)
|
||||
if !isIfacePresent {
|
||||
if err = deleteInterface(oldIfaceName, serverNode.PostDown); err != nil {
|
||||
logger.Log(1, "could not delete old interface", oldIfaceName)
|
||||
}
|
||||
logger.Log(1, "removed old interface", oldIfaceName)
|
||||
}
|
||||
serverNode.PullChanges = "no"
|
||||
if err = setWGConfig(serverNode, false); err != nil {
|
||||
return err
|
||||
}
|
||||
// handle server side update
|
||||
if err = UpdateNode(serverNode, serverNode); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err = setWGConfig(serverNode, true); err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return ServerPull(serverNode, true)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ServerPush - pushes config changes for server checkins/join
|
||||
func ServerPush(serverNode *models.Node) error {
|
||||
serverNode.OS = runtime.GOOS
|
||||
serverNode.SetLastCheckIn()
|
||||
return UpdateNode(serverNode, serverNode)
|
||||
}
|
||||
|
||||
// ServerLeave - removes a server node
|
||||
func ServerLeave(serverID string) error {
|
||||
|
||||
var serverNode, err = GetNodeByID(serverID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return DeleteNodeByID(&serverNode, true)
|
||||
return serverPush(serverNode)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -231,17 +167,14 @@ func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []stri
|
|||
var gateways []string
|
||||
var peers []wgtypes.PeerConfig
|
||||
var nodes []models.Node // fill above fields from server or client
|
||||
var err error
|
||||
|
||||
var nodecfg, err = GetNodeByIDorMacAddress(serverNode.ID, serverNode.MacAddress, serverNode.Network)
|
||||
if err != nil {
|
||||
return nil, hasGateway, gateways, err
|
||||
}
|
||||
nodes, err = GetPeers(&nodecfg)
|
||||
nodes, err = GetPeers(serverNode)
|
||||
if err != nil {
|
||||
return nil, hasGateway, gateways, err
|
||||
}
|
||||
|
||||
keepalive := nodecfg.PersistentKeepalive
|
||||
keepalive := serverNode.PersistentKeepalive
|
||||
keepalivedur, err := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s")
|
||||
if err != nil {
|
||||
logger.Log(1, "Issue with format of keepalive duration value, Please view server config:", err.Error())
|
||||
|
@ -255,11 +188,11 @@ func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []stri
|
|||
return peers, hasGateway, gateways, err
|
||||
}
|
||||
|
||||
if nodecfg.PublicKey == node.PublicKey {
|
||||
if serverNode.PublicKey == node.PublicKey {
|
||||
continue
|
||||
}
|
||||
if nodecfg.Endpoint == node.Endpoint {
|
||||
if nodecfg.LocalAddress != node.LocalAddress && node.LocalAddress != "" {
|
||||
if serverNode.Endpoint == node.Endpoint {
|
||||
if serverNode.LocalAddress != node.LocalAddress && node.LocalAddress != "" {
|
||||
node.Endpoint = node.LocalAddress
|
||||
} else {
|
||||
continue
|
||||
|
@ -304,8 +237,8 @@ func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []stri
|
|||
logger.Log(2, "egress IP range of", iprange, "overlaps with", node.Endpoint, ", omitting")
|
||||
continue // skip adding egress range if overlaps with node's ip
|
||||
}
|
||||
if ipnet.Contains(net.ParseIP(nodecfg.LocalAddress)) { // ensuring egress gateway range does not contain public ip of node
|
||||
logger.Log(2, "egress IP range of", iprange, "overlaps with", nodecfg.LocalAddress, ", omitting")
|
||||
if ipnet.Contains(net.ParseIP(serverNode.LocalAddress)) { // ensuring egress gateway range does not contain public ip of node
|
||||
logger.Log(2, "egress IP range of", iprange, "overlaps with", serverNode.LocalAddress, ", omitting")
|
||||
continue // skip adding egress range if overlaps with node's local ip
|
||||
}
|
||||
gateways = append(gateways, iprange)
|
||||
|
@ -422,7 +355,7 @@ func checkNodeActions(node *models.Node) string {
|
|||
}
|
||||
}
|
||||
if node.Action == models.NODE_DELETE {
|
||||
err := ServerLeave(node.ID)
|
||||
err := DeleteNodeByID(node, true)
|
||||
if err != nil {
|
||||
logger.Log(1, "error deleting locally:", err.Error())
|
||||
}
|
||||
|
@ -431,6 +364,49 @@ func checkNodeActions(node *models.Node) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// == Private ==
|
||||
|
||||
func serverPull(serverNode *models.Node, onErr bool) error {
|
||||
|
||||
var err error
|
||||
if serverNode.IPForwarding == "yes" {
|
||||
if err = setIPForwardingLinux(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
serverNode.OS = runtime.GOOS
|
||||
|
||||
if serverNode.PullChanges == "yes" || onErr {
|
||||
// check for interface change
|
||||
// checks if address is in use by another interface
|
||||
var oldIfaceName, isIfacePresent = isInterfacePresent(serverNode.Interface, serverNode.Address)
|
||||
if !isIfacePresent {
|
||||
if err = deleteInterface(oldIfaceName, serverNode.PostDown); err != nil {
|
||||
logger.Log(1, "could not delete old interface", oldIfaceName)
|
||||
}
|
||||
logger.Log(1, "removed old interface", oldIfaceName)
|
||||
}
|
||||
serverNode.PullChanges = "no"
|
||||
if err = setWGConfig(serverNode, false); err != nil {
|
||||
return err
|
||||
}
|
||||
// handle server side update
|
||||
if err = UpdateNode(serverNode, serverNode); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err = setWGConfig(serverNode, true); err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return serverPull(serverNode, true)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getServerLocalIP(networkSettings *models.Network) (string, error) {
|
||||
|
||||
var networkCIDR = networkSettings.LocalRange
|
||||
|
@ -452,3 +428,9 @@ func getServerLocalIP(networkSettings *models.Network) (string, error) {
|
|||
}
|
||||
return "", errors.New("could not find a local ip for server")
|
||||
}
|
||||
|
||||
func serverPush(serverNode *models.Node) error {
|
||||
serverNode.OS = runtime.GOOS
|
||||
serverNode.SetLastCheckIn()
|
||||
return UpdateNode(serverNode, serverNode)
|
||||
}
|
||||
|
|
|
@ -5,17 +5,16 @@ import (
|
|||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/gravitl/netmaker/database"
|
||||
"github.com/gravitl/netmaker/logger"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||
"github.com/gravitl/netmaker/servercfg"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// IsBase64 - checks if a string is in base64 format
|
||||
|
@ -31,15 +30,13 @@ func CheckEndpoint(endpoint string) bool {
|
|||
return len(endpointarr) == 2
|
||||
}
|
||||
|
||||
// SetNetworkServerPeers - sets the network server peers of a given node
|
||||
func SetNetworkServerPeers(node *models.Node) {
|
||||
if currentPeersList, err := GetSystemPeers(node); err == nil {
|
||||
if database.SetPeers(currentPeersList, node.Network) {
|
||||
logger.Log(1, "set new peers on network", node.Network)
|
||||
}
|
||||
} else {
|
||||
logger.Log(1, "could not set peers on network", node.Network, ":", err.Error())
|
||||
// FileExists - checks if local file exists
|
||||
func FileExists(f string) bool {
|
||||
info, err := os.Stat(f)
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
return !info.IsDir()
|
||||
}
|
||||
|
||||
// DeleteNodeByMacAddress - deletes a node from database or moves into delete nodes table
|
||||
|
@ -75,72 +72,6 @@ func DeleteNodeByMacAddress(node *models.Node, exterminate bool) error {
|
|||
return removeLocalServer(node)
|
||||
}
|
||||
|
||||
// CreateNode - creates a node in database
|
||||
func CreateNode(node *models.Node) error {
|
||||
|
||||
//encrypt that password so we never see it
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(node.Password), 5)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//set password to encrypted password
|
||||
node.Password = string(hash)
|
||||
if node.Name == models.NODE_SERVER_NAME {
|
||||
node.IsServer = "yes"
|
||||
}
|
||||
if node.DNSOn == "" {
|
||||
if servercfg.IsDNSMode() {
|
||||
node.DNSOn = "yes"
|
||||
} else {
|
||||
node.DNSOn = "no"
|
||||
}
|
||||
}
|
||||
SetNodeDefaults(node)
|
||||
node.Address, err = UniqueAddress(node.Network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
node.Address6, err = UniqueAddress6(node.Network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: This covers legacy nodes, eventually want to remove legacy check
|
||||
if node.IsServer == "yes" {
|
||||
node.ID = uuid.NewString()
|
||||
} else if node.IsServer != "yes" || (node.ID == "" || strings.Contains(node.ID, "###")) {
|
||||
node.ID = uuid.NewString()
|
||||
}
|
||||
|
||||
//Create a JWT for the node
|
||||
tokenString, _ := CreateJWT(node.ID, node.MacAddress, node.Network)
|
||||
if tokenString == "" {
|
||||
//returnErrorResponse(w, r, errorResponse)
|
||||
return err
|
||||
}
|
||||
err = ValidateNode(node, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodebytes, err := json.Marshal(&node)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = database.Insert(node.ID, string(nodebytes), database.NODES_TABLE_NAME)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if node.IsPending != "yes" {
|
||||
DecrimentKey(node.Network, node.AccessKey)
|
||||
}
|
||||
SetNetworkNodesLastModified(node.Network)
|
||||
if servercfg.IsDNSMode() {
|
||||
err = SetDNS()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SetNetworkNodesLastModified - sets the network nodes last modified
|
||||
func SetNetworkNodesLastModified(networkName string) error {
|
||||
|
||||
|
@ -402,3 +333,16 @@ func StringSliceContains(slice []string, item string) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// == private ==
|
||||
|
||||
// sets the network server peers of a given node
|
||||
func setNetworkServerPeers(serverNode *models.Node) {
|
||||
if currentPeersList, err := getSystemPeers(serverNode); err == nil {
|
||||
if database.SetPeers(currentPeersList, serverNode.Network) {
|
||||
logger.Log(1, "set new peers on network", serverNode.Network)
|
||||
}
|
||||
} else {
|
||||
logger.Log(1, "could not set peers on network", serverNode.Network, ":", err.Error())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,18 @@ import (
|
|||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
)
|
||||
|
||||
// GetSystemPeers - gets the server peers
|
||||
func GetSystemPeers(node *models.Node) (map[string]string, error) {
|
||||
// RemoveConf - removes a configuration for a given WireGuard interface
|
||||
func RemoveConf(iface string, printlog bool) error {
|
||||
var err error
|
||||
confPath := ncutils.GetNetclientPathSpecific() + iface + ".conf"
|
||||
err = removeWGQuickConf(confPath, printlog)
|
||||
return err
|
||||
}
|
||||
|
||||
// == Private Functions ==
|
||||
|
||||
// gets the server peers locally
|
||||
func getSystemPeers(node *models.Node) (map[string]string, error) {
|
||||
peers := make(map[string]string)
|
||||
|
||||
client, err := wgctrl.New()
|
||||
|
@ -37,16 +47,6 @@ func GetSystemPeers(node *models.Node) (map[string]string, error) {
|
|||
return peers, nil
|
||||
}
|
||||
|
||||
// RemoveConf - removes a configuration for a given WireGuard interface
|
||||
func RemoveConf(iface string, printlog bool) error {
|
||||
var err error
|
||||
confPath := ncutils.GetNetclientPathSpecific() + iface + ".conf"
|
||||
err = removeWGQuickConf(confPath, printlog)
|
||||
return err
|
||||
}
|
||||
|
||||
// == Private Functions ==
|
||||
|
||||
func initWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig, hasGateway bool, gateways []string) error {
|
||||
|
||||
key, err := wgtypes.ParseKey(privkey)
|
||||
|
@ -93,16 +93,6 @@ func initWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
|
|||
logger.Log(1, "error writing wg conf file to", confPath, ":", err.Error())
|
||||
return err
|
||||
}
|
||||
if ncutils.IsWindows() {
|
||||
wgConfPath := ncutils.GetWGPathSpecific() + ifacename + ".conf"
|
||||
logger.Log(1, "writing wg conf file to:", confPath)
|
||||
err = os.WriteFile(wgConfPath, []byte(newConf), 0644)
|
||||
if err != nil {
|
||||
logger.Log(1, "error writing wg conf file to", wgConfPath, ":", err.Error())
|
||||
return err
|
||||
}
|
||||
confPath = wgConfPath
|
||||
}
|
||||
// spin up userspace + apply the conf file
|
||||
var deviceiface = ifacename
|
||||
d, _ := wgclient.Device(deviceiface)
|
||||
|
@ -182,9 +172,10 @@ func setKernelDevice(ifacename string, address string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
_, _ = ncutils.RunCmd("ip link delete dev "+ifacename, false)
|
||||
_, _ = ncutils.RunCmd(ipExec+" link add dev "+ifacename+" type wireguard", true)
|
||||
_, _ = ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+address+"/24", true) // this is a bug waiting to happen
|
||||
// == best effort ==
|
||||
ncutils.RunCmd("ip link delete dev "+ifacename, false)
|
||||
ncutils.RunCmd(ipExec+" link add dev "+ifacename+" type wireguard", true)
|
||||
ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+address+"/24", true) // this is a bug waiting to happen
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
17
main.go
17
main.go
|
@ -9,7 +9,6 @@ import (
|
|||
"runtime/debug"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gravitl/netmaker/auth"
|
||||
controller "github.com/gravitl/netmaker/controllers"
|
||||
|
@ -110,25 +109,9 @@ func startControllers() {
|
|||
logger.Log(0, "No Server Mode selected, so nothing is being served! Set either Agent mode (AGENT_BACKEND) or Rest mode (REST_BACKEND) to 'true'.")
|
||||
}
|
||||
|
||||
if servercfg.IsClientMode() == "on" {
|
||||
var checkintime = time.Duration(servercfg.GetServerCheckinInterval()) * time.Second
|
||||
for { // best effort currently
|
||||
var serverGroup sync.WaitGroup
|
||||
serverGroup.Add(1)
|
||||
go runClient(&serverGroup)
|
||||
serverGroup.Wait()
|
||||
time.Sleep(checkintime)
|
||||
}
|
||||
}
|
||||
|
||||
waitnetwork.Wait()
|
||||
}
|
||||
|
||||
func runClient(wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
go serverctl.HandleContainedClient()
|
||||
}
|
||||
|
||||
func runGRPC(wg *sync.WaitGroup) {
|
||||
|
||||
defer wg.Done()
|
||||
|
|
|
@ -73,6 +73,7 @@ type Node struct {
|
|||
OS string `json:"os" bson:"os" yaml:"os"`
|
||||
MTU int32 `json:"mtu" bson:"mtu" yaml:"mtu"`
|
||||
Version string `json:"version" bson:"version" yaml:"version"`
|
||||
ExcludedAddrs []string `json:"excludedaddrs" bson:"excludedaddrs" yaml:"excludedaddrs"`
|
||||
}
|
||||
|
||||
// NodesArray - used for node sorting
|
||||
|
@ -107,78 +108,91 @@ func (node *Node) SetDefaulIsPending() {
|
|||
}
|
||||
}
|
||||
|
||||
// Node.SetDefaultIsRelayed - set default is relayed
|
||||
func (node *Node) SetDefaultIsRelayed() {
|
||||
if node.IsRelayed == "" {
|
||||
node.IsRelayed = "no"
|
||||
}
|
||||
}
|
||||
|
||||
// Node.SetDefaultIsRelay - set default isrelay
|
||||
func (node *Node) SetDefaultIsRelay() {
|
||||
if node.IsRelay == "" {
|
||||
node.IsRelay = "no"
|
||||
}
|
||||
}
|
||||
|
||||
// Node.SetDefaultEgressGateway - sets default egress gateway status
|
||||
func (node *Node) SetDefaultEgressGateway() {
|
||||
if node.IsEgressGateway == "" {
|
||||
node.IsEgressGateway = "no"
|
||||
}
|
||||
}
|
||||
|
||||
// Node.SetDefaultIngressGateway - sets default ingress gateway status
|
||||
func (node *Node) SetDefaultIngressGateway() {
|
||||
if node.IsIngressGateway == "" {
|
||||
node.IsIngressGateway = "no"
|
||||
}
|
||||
}
|
||||
|
||||
// Node.SetDefaultAction - sets default action status
|
||||
func (node *Node) SetDefaultAction() {
|
||||
if node.Action == "" {
|
||||
node.Action = NODE_NOOP
|
||||
}
|
||||
}
|
||||
|
||||
// Node.SetRoamingDefault - sets default roaming status
|
||||
func (node *Node) SetRoamingDefault() {
|
||||
if node.Roaming == "" {
|
||||
node.Roaming = "yes"
|
||||
}
|
||||
}
|
||||
|
||||
// Node.SetPullChangesDefault - sets default pull changes status
|
||||
func (node *Node) SetPullChangesDefault() {
|
||||
if node.PullChanges == "" {
|
||||
node.PullChanges = "no"
|
||||
}
|
||||
}
|
||||
|
||||
// Node.SetIPForwardingDefault - set ip forwarding default
|
||||
func (node *Node) SetIPForwardingDefault() {
|
||||
if node.IPForwarding == "" {
|
||||
node.IPForwarding = "yes"
|
||||
}
|
||||
}
|
||||
|
||||
// Node.SetIsLocalDefault - set is local default
|
||||
func (node *Node) SetIsLocalDefault() {
|
||||
if node.IsLocal == "" {
|
||||
node.IsLocal = "no"
|
||||
}
|
||||
}
|
||||
|
||||
// Node.SetDNSOnDefault - sets dns on default
|
||||
func (node *Node) SetDNSOnDefault() {
|
||||
if node.DNSOn == "" {
|
||||
node.DNSOn = "yes"
|
||||
}
|
||||
}
|
||||
|
||||
// Node.SetIsDualStackDefault - set is dual stack default status
|
||||
func (node *Node) SetIsDualStackDefault() {
|
||||
if node.IsDualStack == "" {
|
||||
node.IsDualStack = "no"
|
||||
}
|
||||
}
|
||||
|
||||
// Node.SetIsServerDefault - sets node isserver default
|
||||
func (node *Node) SetIsServerDefault() {
|
||||
if node.IsServer != "yes" {
|
||||
node.IsServer = "no"
|
||||
}
|
||||
}
|
||||
|
||||
// Node.SetIsStaticDefault - set is static default
|
||||
func (node *Node) SetIsStaticDefault() {
|
||||
if node.IsServer == "yes" {
|
||||
node.IsStatic = "yes"
|
||||
|
@ -187,28 +201,41 @@ func (node *Node) SetIsStaticDefault() {
|
|||
}
|
||||
}
|
||||
|
||||
// Node.SetLastModified - set last modified initial time
|
||||
func (node *Node) SetLastModified() {
|
||||
node.LastModified = time.Now().Unix()
|
||||
}
|
||||
|
||||
// Node.SetLastCheckIn - time.Now().Unix()
|
||||
func (node *Node) SetLastCheckIn() {
|
||||
node.LastCheckIn = time.Now().Unix()
|
||||
}
|
||||
|
||||
// Node.SetLastPeerUpdate - sets last peer update time
|
||||
func (node *Node) SetLastPeerUpdate() {
|
||||
node.LastPeerUpdate = time.Now().Unix()
|
||||
}
|
||||
|
||||
// Node.SetExpirationDateTime - sets node expiry time
|
||||
func (node *Node) SetExpirationDateTime() {
|
||||
node.ExpirationDateTime = time.Now().Unix() + TEN_YEARS_IN_SECONDS
|
||||
}
|
||||
|
||||
// Node.SetDefaultName - sets a random name to node
|
||||
func (node *Node) SetDefaultName() {
|
||||
if node.Name == "" {
|
||||
node.Name = GenerateNodeName()
|
||||
}
|
||||
}
|
||||
|
||||
// Node.SetDefaultExcludedAddrs - sets ExcludedAddrs to empty array if nil
|
||||
func (node *Node) SetDefaultExcludedAddrs() {
|
||||
if node.ExcludedAddrs == nil {
|
||||
node.ExcludedAddrs = make([]string, 0)
|
||||
}
|
||||
}
|
||||
|
||||
// Node.Fill - fills other node data into calling node data if not set on calling node
|
||||
func (newNode *Node) Fill(currentNode *Node) {
|
||||
newNode.ID = currentNode.ID
|
||||
|
||||
|
@ -354,8 +381,15 @@ func (newNode *Node) Fill(currentNode *Node) {
|
|||
if newNode.IsRelayed == "" {
|
||||
newNode.IsRelayed = currentNode.IsRelayed
|
||||
}
|
||||
if newNode.Version == "" {
|
||||
newNode.Version = currentNode.Version
|
||||
}
|
||||
if newNode.ExcludedAddrs == nil || len(newNode.ExcludedAddrs) != len(currentNode.ExcludedAddrs) {
|
||||
newNode.ExcludedAddrs = currentNode.ExcludedAddrs
|
||||
}
|
||||
}
|
||||
|
||||
// StringWithCharset - returns random string inside defined charset
|
||||
func StringWithCharset(length int, charset string) string {
|
||||
b := make([]byte, length)
|
||||
for i := range b {
|
||||
|
@ -364,13 +398,14 @@ func StringWithCharset(length int, charset string) string {
|
|||
return string(b)
|
||||
}
|
||||
|
||||
//Check for valid IPv4 address
|
||||
//Note: We dont handle IPv6 AT ALL!!!!! This definitely is needed at some point
|
||||
//But for iteration 1, lets just stick to IPv4. Keep it simple stupid.
|
||||
// IsIpv4Net - check for valid IPv4 address
|
||||
// Note: We dont handle IPv6 AT ALL!!!!! This definitely is needed at some point
|
||||
// But for iteration 1, lets just stick to IPv4. Keep it simple stupid.
|
||||
func IsIpv4Net(host string) bool {
|
||||
return net.ParseIP(host) != nil
|
||||
}
|
||||
|
||||
// Node.NameInNodeCharset - returns if name is in charset below or not
|
||||
func (node *Node) NameInNodeCharSet() bool {
|
||||
|
||||
charset := "abcdefghijklmnopqrstuvwxyz1234567890-"
|
||||
|
|
|
@ -156,3 +156,10 @@ type RelayRequest struct {
|
|||
NetID string `json:"netid" bson:"netid"`
|
||||
RelayAddrs []string `json:"relayaddrs" bson:"relayaddrs"`
|
||||
}
|
||||
|
||||
// ServerUpdateData - contains data to configure server
|
||||
// and if it should set peers
|
||||
type ServerUpdateData struct {
|
||||
UpdatePeers bool `json:"updatepeers" bson:"updatepeers"`
|
||||
Node Node `json:"servernode" bson:"servernode"`
|
||||
}
|
||||
|
|
|
@ -1,51 +1,17 @@
|
|||
package serverctl
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/gravitl/netmaker/database"
|
||||
"github.com/gravitl/netmaker/logger"
|
||||
"github.com/gravitl/netmaker/logic"
|
||||
"github.com/gravitl/netmaker/models"
|
||||
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||
"github.com/gravitl/netmaker/servercfg"
|
||||
)
|
||||
|
||||
// GetServerWGConf - gets the server WG configuration
|
||||
func GetServerWGConf() (models.IntClient, error) {
|
||||
var server models.IntClient
|
||||
collection, err := database.FetchRecords(database.INT_CLIENTS_TABLE_NAME)
|
||||
if err != nil {
|
||||
return models.IntClient{}, errors.New("could not find comms server")
|
||||
}
|
||||
for _, value := range collection {
|
||||
json.Unmarshal([]byte(value), &server)
|
||||
if server.Network == "comms" && server.IsServer == "yes" {
|
||||
return server, nil
|
||||
}
|
||||
}
|
||||
return models.IntClient{}, errors.New("could not find comms server")
|
||||
}
|
||||
|
||||
// FileExists - checks if local file exists
|
||||
func FileExists(f string) bool {
|
||||
info, err := os.Stat(f)
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
return !info.IsDir()
|
||||
}
|
||||
|
||||
// RemoveNetwork - removes a network locally on server
|
||||
func RemoveNetwork(network string) (bool, error) {
|
||||
err := logic.ServerLeave(network)
|
||||
return true, err
|
||||
}
|
||||
|
||||
// InitServerNetclient - intializes the server netclient
|
||||
func InitServerNetclient() error {
|
||||
netclientDir := ncutils.GetNetclientPath()
|
||||
|
@ -59,78 +25,42 @@ func InitServerNetclient() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// HandleContainedClient - function for checkins on server
|
||||
func HandleContainedClient() error {
|
||||
servernets, err := logic.GetNetworks()
|
||||
if err != nil && !database.IsEmptyRecord(err) {
|
||||
// SyncServerNetwork - ensures a wg interface and node exists for server
|
||||
func SyncServerNetwork(serverNode *models.Node) error {
|
||||
serverNetworkSettings, err := logic.GetNetwork(serverNode.Network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(servernets) > 0 {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, serverNet := range servernets {
|
||||
var serverID, err = logic.GetNetworkServerNodeID(serverNet.NetID)
|
||||
if err != nil {
|
||||
logger.Log(1, "error occurred during server checkin:", err.Error())
|
||||
continue
|
||||
}
|
||||
err = logic.ServerCheckin(serverID, servercfg.GetNodeID(), serverNet.NetID)
|
||||
if err != nil {
|
||||
logger.Log(1, "error occurred during server checkin:", err.Error())
|
||||
} else {
|
||||
logger.Log(3, "completed peers check of network", serverNet.NetID)
|
||||
}
|
||||
}
|
||||
syncErr := SyncNetworks(servernets[:])
|
||||
if syncErr != nil {
|
||||
logger.Log(1, "error syncing networks:", syncErr.Error())
|
||||
syncErr = nil
|
||||
}
|
||||
// logger.Log("completed a checkin call", 3)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SyncNetworks - syncs the networks for servers
|
||||
func SyncNetworks(servernets []models.Network) error {
|
||||
|
||||
localnets, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// check networks to join
|
||||
for _, servernet := range servernets {
|
||||
exists := false
|
||||
for _, localnet := range localnets {
|
||||
if servernet.DefaultInterface == localnet.Name {
|
||||
exists = true
|
||||
}
|
||||
exists := false
|
||||
for _, localnet := range localnets {
|
||||
if serverNetworkSettings.DefaultInterface == localnet.Name {
|
||||
exists = true
|
||||
}
|
||||
if !exists {
|
||||
success, err := AddNetwork(&servernet)
|
||||
if err != nil || !success {
|
||||
if err == nil {
|
||||
err = errors.New("network add failed for " + servernet.NetID)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "macaddress_unique") { // ignore macaddress unique error throws
|
||||
logger.Log(1, "error adding network", servernet.NetID, "during sync:", err.Error())
|
||||
}
|
||||
}
|
||||
if !exists {
|
||||
err := logic.ServerJoin(&serverNetworkSettings)
|
||||
if err != nil {
|
||||
if err == nil {
|
||||
err = errors.New("network add failed for " + serverNetworkSettings.NetID)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "macaddress_unique") { // ignore macaddress unique error throws
|
||||
logger.Log(1, "error adding network", serverNetworkSettings.NetID, "during sync:", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
// check networks to leave
|
||||
for _, localnet := range localnets {
|
||||
if strings.Contains(localnet.Name, "nm-") {
|
||||
var exists = ""
|
||||
for _, servernet := range servernets {
|
||||
if servernet.DefaultInterface == localnet.Name {
|
||||
exists = servernet.NetID
|
||||
}
|
||||
if serverNetworkSettings.DefaultInterface == localnet.Name {
|
||||
exists = serverNetworkSettings.NetID
|
||||
}
|
||||
if exists == "" {
|
||||
success, err := RemoveNetwork(exists)
|
||||
if err != nil || !success {
|
||||
err := logic.DeleteNodeByID(serverNode, true)
|
||||
if err != nil {
|
||||
if err == nil {
|
||||
err = errors.New("network delete failed for " + exists)
|
||||
}
|
||||
|
@ -139,12 +69,5 @@ func SyncNetworks(servernets []models.Network) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddNetwork - add a network to server in client mode
|
||||
func AddNetwork(networkSettings *models.Network) (bool, error) {
|
||||
var err = logic.ServerJoin(networkSettings, servercfg.GetNodeID())
|
||||
return true, err
|
||||
}
|
||||
|
|
29
serverctl/serverq.go
Normal file
29
serverctl/serverq.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package serverctl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitl/netmaker/models"
|
||||
)
|
||||
|
||||
// ServerQueue - holds data to be updated across the server
|
||||
var ServerQueue chan models.ServerUpdateData
|
||||
|
||||
func init() {
|
||||
ServerQueue = make(chan models.ServerUpdateData, 100)
|
||||
}
|
||||
|
||||
// Push - Pushes ServerUpdateData to be used later
|
||||
func Push(serverData models.ServerUpdateData) {
|
||||
ServerQueue <- serverData
|
||||
}
|
||||
|
||||
// Pop - fetches first available data from queue
|
||||
func Pop() (models.ServerUpdateData, error) {
|
||||
select {
|
||||
case serverData := <-ServerQueue:
|
||||
return serverData, nil
|
||||
default:
|
||||
return models.ServerUpdateData{}, fmt.Errorf("empty server queue")
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue