Skip to content

Commit

Permalink
NET-1782: Fetch Node Connection Status from metrics (#3237)
Browse files Browse the repository at this point in the history
* add live status of node

* handle static node status

* add public IP field to server configuration

* get public Ip from config

* improve node status logic

* improvise status check

* use only checkin status on old nodes

---------

Co-authored-by: the_aceix <[email protected]>
  • Loading branch information
abhishek9686 and Aceix authored Dec 10, 2024
1 parent 496d541 commit 31c2311
Show file tree
Hide file tree
Showing 12 changed files with 293 additions and 34 deletions.
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ type ServerConfig struct {
Stun bool `yaml:"stun"`
StunServers string `yaml:"stun_servers"`
DefaultDomain string `yaml:"default_domain"`
PublicIp string `yaml:"public_ip"`
}

// SQLConfig - Generic SQL Config
Expand Down
4 changes: 3 additions & 1 deletion controllers/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,9 @@ func getNetworkNodes(w http.ResponseWriter, r *http.Request) {
if len(filteredNodes) > 0 {
nodes = filteredNodes
}
nodes = logic.AddStaticNodestoList(nodes)

nodes = logic.AddStaticNodestoList(nodes)
nodes = logic.AddStatusToNodes(nodes)
// returns all the nodes in JSON/API format
apiNodes := logic.GetAllNodesAPI(nodes[:])
logger.Log(2, r.Header.Get("user"), "fetched nodes on network", networkName)
Expand Down Expand Up @@ -367,6 +368,7 @@ func getAllNodes(w http.ResponseWriter, r *http.Request) {

}
nodes = logic.AddStaticNodestoList(nodes)
nodes = logic.AddStatusToNodes(nodes)
// return all the nodes in JSON/API format
apiNodes := logic.GetAllNodesAPI(nodes[:])
logger.Log(3, r.Header.Get("user"), "fetched all nodes they have access to")
Expand Down
14 changes: 14 additions & 0 deletions logic/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,20 @@ func AddStaticNodestoList(nodes []models.Node) []models.Node {
return nodes
}

func AddStatusToNodes(nodes []models.Node) (nodesWithStatus []models.Node) {
aclDefaultPolicyStatusMap := make(map[string]bool)
for _, node := range nodes {
if _, ok := aclDefaultPolicyStatusMap[node.Network]; !ok {
// check default policy if all allowed return true
defaultPolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
aclDefaultPolicyStatusMap[node.Network] = defaultPolicy.Enabled
}
GetNodeStatus(&node, aclDefaultPolicyStatusMap[node.Network])
nodesWithStatus = append(nodesWithStatus, node)
}
return
}

// GetNetworkByNode - gets the network model from a node
func GetNetworkByNode(node *models.Node) (models.Network, error) {

Expand Down
26 changes: 26 additions & 0 deletions logic/status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package logic

import (
"time"

"github.com/gravitl/netmaker/models"
)

var GetNodeStatus = getNodeStatus

func getNodeStatus(node *models.Node, t bool) {
// On CE check only last check-in time
if node.IsStatic {
if !node.StaticNode.Enabled {
node.Status = models.OfflineSt
return
}
node.Status = models.OnlineSt
return
}
if time.Since(node.LastCheckIn) > time.Minute*10 {
node.Status = models.OfflineSt
return
}
node.Status = models.OnlineSt
}
29 changes: 28 additions & 1 deletion logic/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import (
"encoding/base32"
"encoding/base64"
"encoding/json"
"fmt"
"net"
"os"
"strings"
"time"
"unicode"

"github.com/blang/semver"
"github.com/c-robinson/iplib"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logger"
Expand Down Expand Up @@ -148,4 +151,28 @@ func IsSlicesEqual(a, b []string) bool {
return true
}

// == private ==
// VersionLessThan checks if v1 < v2 semantically
// dev is the latest version
func VersionLessThan(v1, v2 string) (bool, error) {
if v1 == "dev" {
return false, nil
}
if v2 == "dev" {
return true, nil
}
semVer1 := strings.TrimFunc(v1, func(r rune) bool {
return !unicode.IsNumber(r)
})
semVer2 := strings.TrimFunc(v2, func(r rune) bool {
return !unicode.IsNumber(r)
})
sv1, err := semver.Parse(semVer1)
if err != nil {
return false, fmt.Errorf("failed to parse semver1 (%s): %w", semVer1, err)
}
sv2, err := semver.Parse(semVer2)
if err != nil {
return false, fmt.Errorf("failed to parse semver2 (%s): %w", semVer2, err)
}
return sv1.LT(sv2), nil
}
2 changes: 2 additions & 0 deletions models/api_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ type ApiNode struct {
IsStatic bool `json:"is_static"`
IsUserNode bool `json:"is_user_node"`
StaticNode ExtClient `json:"static_node"`
Status NodeStatus `json:"status"`
}

// ApiNode.ConvertToServerNode - converts an api node to a server node
Expand Down Expand Up @@ -192,6 +193,7 @@ func (nm *Node) ConvertToAPINode() *ApiNode {
apiNode.IsStatic = nm.IsStatic
apiNode.IsUserNode = nm.IsUserNode
apiNode.StaticNode = nm.StaticNode
apiNode.Status = nm.Status
return &apiNode
}

Expand Down
14 changes: 14 additions & 0 deletions models/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@ import (
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)

type NodeStatus string

const (
OnlineSt NodeStatus = "online"
OfflineSt NodeStatus = "offline"
WarningSt NodeStatus = "warning"
ErrorSt NodeStatus = "error"
UnKnown NodeStatus = "unknown"
)

// LastCheckInThreshold - if node's checkin more than this threshold,then node is declared as offline
const LastCheckInThreshold = time.Minute * 10

const (
// NODE_SERVER_NAME - the default server name
NODE_SERVER_NAME = "netmaker"
Expand Down Expand Up @@ -103,6 +116,7 @@ type Node struct {
IsStatic bool `json:"is_static"`
IsUserNode bool `json:"is_user_node"`
StaticNode ExtClient `json:"static_node"`
Status NodeStatus `json:"node_status"`
}

// LegacyNode - legacy struct for node model
Expand Down
3 changes: 0 additions & 3 deletions mq/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,6 @@ func SendPullSYN() error {
return err
}
encrypted, encryptErr := encryptAESGCM(host.TrafficKeyPublic[0:32], zipped)
if encryptErr != nil {
return encryptErr
}

if encryptErr != nil {
continue
Expand Down
30 changes: 1 addition & 29 deletions mq/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import (
"math"
"strings"
"time"
"unicode"

"github.com/blang/semver"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/ncutils"
Expand Down Expand Up @@ -139,7 +137,7 @@ func publish(host *models.Host, dest string, msg []byte) error {

var encrypted []byte
var encryptErr error
vlt, err := versionLessThan(host.Version, "v0.30.0")
vlt, err := logic.VersionLessThan(host.Version, "v0.30.0")
if err != nil {
slog.Warn("error checking version less than", "error", err)
return err
Expand Down Expand Up @@ -187,29 +185,3 @@ func GetID(topic string) (string, error) {
//the last part of the topic will be the node.ID
return parts[count-1], nil
}

// versionLessThan checks if v1 < v2 semantically
// dev is the latest version
func versionLessThan(v1, v2 string) (bool, error) {
if v1 == "dev" {
return false, nil
}
if v2 == "dev" {
return true, nil
}
semVer1 := strings.TrimFunc(v1, func(r rune) bool {
return !unicode.IsNumber(r)
})
semVer2 := strings.TrimFunc(v2, func(r rune) bool {
return !unicode.IsNumber(r)
})
sv1, err := semver.Parse(semVer1)
if err != nil {
return false, fmt.Errorf("failed to parse semver1 (%s): %w", semVer1, err)
}
sv2, err := semver.Parse(semVer2)
if err != nil {
return false, fmt.Errorf("failed to parse semver2 (%s): %w", semVer2, err)
}
return sv1.LT(sv2), nil
}
1 change: 1 addition & 0 deletions pro/initialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ func InitPro() {
logic.IntialiseGroups = proLogic.UserGroupsInit
logic.AddGlobalNetRolesToAdmins = proLogic.AddGlobalNetRolesToAdmins
logic.GetUserGroupsInNetwork = proLogic.GetUserGroupsInNetwork
logic.GetNodeStatus = proLogic.GetNodeStatus
}

func retrieveProLogo() string {
Expand Down
Loading

0 comments on commit 31c2311

Please sign in to comment.