2022-02-17 04:40:51 +08:00
package mq
import (
2023-03-07 01:21:51 +08:00
"context"
2022-02-17 04:40:51 +08:00
"encoding/json"
2022-09-14 03:25:56 +08:00
"errors"
2022-02-17 04:40:51 +08:00
"fmt"
2022-09-14 03:25:56 +08:00
"time"
2022-02-17 04:40:51 +08:00
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg"
)
2023-01-06 23:57:40 +08:00
// PublishPeerUpdate --- determines and publishes a peer update to all the hosts
2023-01-10 13:19:15 +08:00
func PublishPeerUpdate ( ) error {
2022-02-17 04:40:51 +08:00
if ! servercfg . IsMessageQueueBackend ( ) {
return nil
}
2023-01-04 12:35:05 +08:00
2023-01-06 19:28:41 +08:00
hosts , err := logic . GetAllHosts ( )
2022-02-17 04:40:51 +08:00
if err != nil {
2023-01-04 12:35:05 +08:00
logger . Log ( 1 , "err getting all hosts" , err . Error ( ) )
2022-02-17 04:40:51 +08:00
return err
}
2023-03-07 01:21:51 +08:00
logic . ResetPeerUpdateContext ( )
2023-01-04 12:35:05 +08:00
for _ , host := range hosts {
2023-01-26 02:21:18 +08:00
host := host
2023-03-14 03:06:07 +08:00
if err = PublishSingleHostPeerUpdate ( logic . PeerUpdateCtx , & host , nil , nil ) ; err != nil {
2023-01-04 12:35:05 +08:00
logger . Log ( 1 , "failed to publish peer update to host" , host . ID . String ( ) , ": " , err . Error ( ) )
2022-02-17 04:40:51 +08:00
}
}
2022-09-30 02:49:44 +08:00
return err
}
2023-02-24 23:37:11 +08:00
// PublishDeletedNodePeerUpdate --- determines and publishes a peer update
// to all the hosts with a deleted node to account for
func PublishDeletedNodePeerUpdate ( delNode * models . Node ) error {
if ! servercfg . IsMessageQueueBackend ( ) {
return nil
}
2022-11-20 12:05:29 +08:00
2023-02-24 23:37:11 +08:00
hosts , err := logic . GetAllHosts ( )
if err != nil {
logger . Log ( 1 , "err getting all hosts" , err . Error ( ) )
return err
}
2023-03-07 01:21:51 +08:00
logic . ResetPeerUpdateContext ( )
2023-02-24 23:37:11 +08:00
for _ , host := range hosts {
host := host
2023-03-14 03:06:07 +08:00
if err = PublishSingleHostPeerUpdate ( logic . PeerUpdateCtx , & host , delNode , nil ) ; err != nil {
logger . Log ( 1 , "failed to publish peer update to host" , host . ID . String ( ) , ": " , err . Error ( ) )
}
}
return err
}
// PublishDeletedClientPeerUpdate --- determines and publishes a peer update
// to all the hosts with a deleted ext client to account for
func PublishDeletedClientPeerUpdate ( delClient * models . ExtClient ) error {
if ! servercfg . IsMessageQueueBackend ( ) {
return nil
}
hosts , err := logic . GetAllHosts ( )
if err != nil {
logger . Log ( 1 , "err getting all hosts" , err . Error ( ) )
return err
}
logic . ResetPeerUpdateContext ( )
for _ , host := range hosts {
host := host
2023-04-07 00:27:33 +08:00
if err = PublishSingleHostPeerUpdate ( logic . PeerUpdateCtx , & host , nil , [ ] models . ExtClient { * delClient } ) ; err != nil {
2023-02-24 23:37:11 +08:00
logger . Log ( 1 , "failed to publish peer update to host" , host . ID . String ( ) , ": " , err . Error ( ) )
}
}
return err
}
2023-02-23 23:55:42 +08:00
// PublishSingleHostPeerUpdate --- determines and publishes a peer update to one host
2023-04-07 00:27:33 +08:00
func PublishSingleHostPeerUpdate ( ctx context . Context , host * models . Host , deletedNode * models . Node , deletedClients [ ] models . ExtClient ) error {
2022-11-20 12:05:29 +08:00
2023-04-07 00:27:33 +08:00
peerUpdate , err := logic . GetPeerUpdateForHost ( ctx , "" , host , deletedNode , deletedClients )
2022-09-30 02:49:44 +08:00
if err != nil {
return err
}
2023-02-18 00:32:02 +08:00
if len ( peerUpdate . Peers ) == 0 { // no peers to send
return nil
}
2023-03-28 18:04:27 +08:00
proxyUpdate , err := logic . GetProxyUpdateForHost ( ctx , host )
if err != nil {
return err
2022-11-07 03:55:04 +08:00
}
2023-03-28 18:04:27 +08:00
proxyUpdate . Server = servercfg . GetServer ( )
2023-03-29 14:39:18 +08:00
if host . ProxyEnabled {
proxyUpdate . Action = models . ProxyUpdate
} else {
proxyUpdate . Action = models . NoProxy
}
2023-03-28 18:04:27 +08:00
peerUpdate . ProxyUpdate = proxyUpdate
2022-11-20 12:05:29 +08:00
2022-09-30 02:49:44 +08:00
data , err := json . Marshal ( & peerUpdate )
if err != nil {
return err
}
2023-01-04 13:33:13 +08:00
return publish ( host , fmt . Sprintf ( "peers/host/%s/%s" , host . ID . String ( ) , servercfg . GetServer ( ) ) , data )
2022-02-17 04:40:51 +08:00
}
// NodeUpdate -- publishes a node update
2022-12-21 04:29:09 +08:00
func NodeUpdate ( node * models . Node ) error {
2022-12-24 02:41:17 +08:00
host , err := logic . GetHost ( node . HostID . String ( ) )
2022-12-22 19:42:33 +08:00
if err != nil {
return nil
}
2022-12-21 04:29:09 +08:00
if ! servercfg . IsMessageQueueBackend ( ) {
2022-02-17 04:40:51 +08:00
return nil
}
2022-12-21 04:29:09 +08:00
logger . Log ( 3 , "publishing node update to " + node . ID . String ( ) )
2022-09-02 16:52:28 +08:00
2022-12-21 04:29:09 +08:00
//if len(node.NetworkSettings.AccessKeys) > 0 {
//node.NetworkSettings.AccessKeys = []models.AccessKey{} // not to be sent (don't need to spread access keys around the network; we need to know how to reach other nodes, not become them)
//}
2022-09-02 16:52:28 +08:00
2022-12-02 20:05:41 +08:00
data , err := json . Marshal ( node )
if err != nil {
logger . Log ( 2 , "error marshalling node update " , err . Error ( ) )
return err
}
2023-02-15 02:00:08 +08:00
if err = publish ( host , fmt . Sprintf ( "node/update/%s/%s" , node . Network , node . ID ) , data ) ; err != nil {
2022-12-21 04:29:09 +08:00
logger . Log ( 2 , "error publishing node update to peer " , node . ID . String ( ) , err . Error ( ) )
2022-12-02 20:05:41 +08:00
return err
}
2022-11-20 12:05:29 +08:00
2022-02-17 04:40:51 +08:00
return nil
}
2023-01-17 13:47:13 +08:00
// HostUpdate -- publishes a host update to clients
func HostUpdate ( hostUpdate * models . HostUpdate ) error {
2023-01-11 23:33:43 +08:00
if ! servercfg . IsMessageQueueBackend ( ) {
return nil
}
2023-01-17 13:47:13 +08:00
logger . Log ( 3 , "publishing host update to " + hostUpdate . Host . ID . String ( ) )
2023-01-11 23:33:43 +08:00
2023-01-17 13:47:13 +08:00
data , err := json . Marshal ( hostUpdate )
2023-01-11 23:33:43 +08:00
if err != nil {
logger . Log ( 2 , "error marshalling node update " , err . Error ( ) )
return err
}
2023-01-17 13:47:13 +08:00
if err = publish ( & hostUpdate . Host , fmt . Sprintf ( "host/update/%s/%s" , hostUpdate . Host . ID . String ( ) , servercfg . GetServer ( ) ) , data ) ; err != nil {
logger . Log ( 2 , "error publishing host update to" , hostUpdate . Host . ID . String ( ) , err . Error ( ) )
2023-01-11 23:33:43 +08:00
return err
}
return nil
}
2022-04-25 23:12:49 +08:00
// ServerStartNotify - notifies all non server nodes to pull changes after a restart
func ServerStartNotify ( ) error {
nodes , err := logic . GetAllNodes ( )
2022-09-14 03:25:56 +08:00
if err != nil {
2022-04-25 23:12:49 +08:00
return err
}
for i := range nodes {
nodes [ i ] . Action = models . NODE_FORCE_UPDATE
if err = NodeUpdate ( & nodes [ i ] ) ; err != nil {
2022-12-21 04:29:09 +08:00
logger . Log ( 1 , "error when notifying node" , nodes [ i ] . ID . String ( ) , "of a server startup" )
2022-04-25 23:12:49 +08:00
}
2022-09-14 03:25:56 +08:00
}
2022-04-25 23:12:49 +08:00
return nil
}
2022-09-14 03:25:56 +08:00
2023-02-07 04:38:42 +08:00
// PublishDNSUpdate publishes a dns update to all nodes on a network
2023-02-06 20:32:37 +08:00
func PublishDNSUpdate ( network string , dns models . DNSUpdate ) error {
nodes , err := logic . GetNetworkNodes ( network )
if err != nil {
return err
}
for _ , node := range nodes {
host , err := logic . GetHost ( node . HostID . String ( ) )
2022-02-23 03:53:40 +08:00
if err != nil {
2023-02-06 20:32:37 +08:00
logger . Log ( 0 , "error retrieving host for dns update" , host . ID . String ( ) , err . Error ( ) )
continue
}
data , err := json . Marshal ( dns )
if err != nil {
logger . Log ( 0 , "failed to encode dns data for node" , node . ID . String ( ) , err . Error ( ) )
2022-02-23 03:53:40 +08:00
}
2023-02-08 21:35:36 +08:00
if err := publish ( host , "dns/update/" + host . ID . String ( ) + "/" + servercfg . GetServer ( ) , data ) ; err != nil {
2023-02-06 20:32:37 +08:00
logger . Log ( 0 , "error publishing dns update to host" , host . ID . String ( ) , err . Error ( ) )
continue
}
logger . Log ( 3 , "published dns update to host" , host . ID . String ( ) )
}
return nil
}
2022-09-14 03:25:56 +08:00
2023-02-07 04:38:42 +08:00
// PublishAllDNS publishes an array of dns updates (ip / host.network) for each peer to a node joining a network
2023-02-06 20:32:37 +08:00
func PublishAllDNS ( newnode * models . Node ) error {
alldns := [ ] models . DNSUpdate { }
newnodeHost , err := logic . GetHost ( newnode . HostID . String ( ) )
if err != nil {
return fmt . Errorf ( "error retrieving host for dns update %w" , err )
}
2023-02-15 02:29:20 +08:00
alldns = append ( alldns , getNodeDNS ( newnode . Network ) ... )
alldns = append ( alldns , getExtClientDNS ( newnode . Network ) ... )
alldns = append ( alldns , getCustomDNS ( newnode . Network ) ... )
2023-02-06 20:32:37 +08:00
data , err := json . Marshal ( alldns )
if err != nil {
2023-02-11 00:03:08 +08:00
return fmt . Errorf ( "error encoding dns data %w" , err )
2023-02-06 20:32:37 +08:00
}
2023-02-08 21:35:36 +08:00
if err := publish ( newnodeHost , "dns/all/" + newnodeHost . ID . String ( ) + "/" + servercfg . GetServer ( ) , data ) ; err != nil {
2023-02-09 23:49:56 +08:00
return fmt . Errorf ( "error publishing full dns update to %s, %w" , newnodeHost . ID . String ( ) , err )
2022-02-17 04:40:51 +08:00
}
2023-02-10 23:58:06 +08:00
logger . Log ( 3 , "published full dns update to %s" , newnodeHost . ID . String ( ) )
2023-02-06 20:32:37 +08:00
return nil
}
2022-02-23 03:53:40 +08:00
2023-02-07 04:38:42 +08:00
// PublishDNSDelete publish a dns update deleting a node to all hosts on a network
2023-02-06 21:37:42 +08:00
func PublishDNSDelete ( node * models . Node , host * models . Host ) error {
dns := models . DNSUpdate {
2023-02-07 03:50:29 +08:00
Action : models . DNSDeleteByIP ,
2023-02-06 21:37:42 +08:00
Name : host . Name + "." + node . Network ,
}
if node . Address . IP != nil {
dns . Address = node . Address . IP . String ( )
if err := PublishDNSUpdate ( node . Network , dns ) ; err != nil {
return fmt . Errorf ( "dns update node deletion %w" , err )
}
}
if node . Address6 . IP != nil {
dns . Address = node . Address6 . IP . String ( )
if err := PublishDNSUpdate ( node . Network , dns ) ; err != nil {
return fmt . Errorf ( "dns update node deletion %w" , err )
2022-02-17 04:40:51 +08:00
}
}
2023-02-06 21:37:42 +08:00
return nil
2022-02-17 04:40:51 +08:00
}
2022-04-25 23:12:49 +08:00
2023-02-15 02:29:20 +08:00
// PublishReplaceDNS publish a dns update to replace a dns entry on all hosts in network
2023-02-06 22:01:45 +08:00
func PublishReplaceDNS ( oldNode , newNode * models . Node , host * models . Host ) error {
dns := models . DNSUpdate {
2023-02-07 04:38:42 +08:00
Action : models . DNSReplaceIP ,
2023-02-06 22:01:45 +08:00
Name : host . Name + "." + oldNode . Network ,
2022-04-25 23:12:49 +08:00
}
2023-02-06 22:01:45 +08:00
if ! oldNode . Address . IP . Equal ( newNode . Address . IP ) {
2023-02-08 23:33:27 +08:00
dns . Address = oldNode . Address . IP . String ( )
dns . NewAddress = newNode . Address . IP . String ( )
2023-02-06 22:01:45 +08:00
if err := PublishDNSUpdate ( oldNode . Network , dns ) ; err != nil {
return err
}
}
if ! oldNode . Address6 . IP . Equal ( newNode . Address6 . IP ) {
2023-02-08 23:33:27 +08:00
dns . Address = oldNode . Address6 . IP . String ( )
dns . NewAddress = newNode . Address6 . IP . String ( )
2023-02-06 22:01:45 +08:00
if err := PublishDNSUpdate ( oldNode . Network , dns ) ; err != nil {
return err
2022-04-25 23:12:49 +08:00
}
}
return nil
}
2022-09-14 03:25:56 +08:00
2023-02-07 04:38:42 +08:00
// PublishExtClientDNS publish dns update for new extclient
2023-02-06 23:48:33 +08:00
func PublishExtCLientDNS ( client * models . ExtClient ) error {
2023-02-10 19:58:00 +08:00
errMsgs := models . DNSError { }
2023-02-06 23:48:33 +08:00
dns := models . DNSUpdate {
Action : models . DNSInsert ,
Name : client . ClientID + "." + client . Network ,
Address : client . Address ,
}
if client . Address != "" {
dns . Address = client . Address
2023-02-10 19:58:00 +08:00
if err := PublishDNSUpdate ( client . Network , dns ) ; err != nil {
errMsgs . ErrorStrings = append ( errMsgs . ErrorStrings , err . Error ( ) )
}
2023-02-06 23:48:33 +08:00
}
if client . Address6 != "" {
dns . Address = client . Address6
2023-02-10 19:58:00 +08:00
if err := PublishDNSUpdate ( client . Network , dns ) ; err != nil {
errMsgs . ErrorStrings = append ( errMsgs . ErrorStrings , err . Error ( ) )
}
2023-02-06 23:48:33 +08:00
}
2023-02-10 19:58:00 +08:00
if len ( errMsgs . ErrorStrings ) > 0 {
return errMsgs
2023-02-06 23:48:33 +08:00
}
return nil
}
2023-02-15 02:29:20 +08:00
// PublishExtClientDNSUpdate update for extclient name change
2023-02-09 00:32:28 +08:00
func PublishExtClientDNSUpdate ( old , new models . ExtClient , network string ) error {
dns := models . DNSUpdate {
Action : models . DNSReplaceName ,
2023-02-09 03:02:01 +08:00
Name : old . ClientID + "." + network ,
NewName : new . ClientID + "." + network ,
2023-02-09 00:32:28 +08:00
}
if err := PublishDNSUpdate ( network , dns ) ; err != nil {
return err
}
return nil
}
2023-02-15 02:29:20 +08:00
// PublishDeleteExtClientDNS publish dns update to delete extclient entry
2023-02-06 23:48:33 +08:00
func PublishDeleteExtClientDNS ( client * models . ExtClient ) error {
dns := models . DNSUpdate {
Action : models . DNSDeleteByName ,
2023-02-09 03:02:01 +08:00
Name : client . ClientID + "." + client . Network ,
2023-02-06 23:48:33 +08:00
}
if err := PublishDNSUpdate ( client . Network , dns ) ; err != nil {
return err
}
return nil
}
2023-02-07 04:38:42 +08:00
// PublishCustomDNS publish dns update for new custom dns entry
2023-02-07 00:19:19 +08:00
func PublishCustomDNS ( entry * models . DNSEntry ) error {
dns := models . DNSUpdate {
Action : models . DNSInsert ,
2023-02-08 23:11:36 +08:00
Name : entry . Name + "." + entry . Network ,
2023-02-07 00:19:19 +08:00
//entry.Address6 is never used
Address : entry . Address ,
}
if err := PublishDNSUpdate ( entry . Network , dns ) ; err != nil {
return err
}
2023-02-07 00:27:50 +08:00
return nil
2023-02-07 00:19:19 +08:00
}
2023-02-07 04:38:42 +08:00
// PublishHostDNSUpdate publishes dns update on host name change
2023-02-07 03:50:29 +08:00
func PublishHostDNSUpdate ( old , new * models . Host , networks [ ] string ) error {
2023-02-10 19:58:00 +08:00
errMsgs := models . DNSError { }
2023-02-07 03:50:29 +08:00
for _ , network := range networks {
dns := models . DNSUpdate {
Action : models . DNSReplaceName ,
Name : old . Name + "." + network ,
NewName : new . Name + "." + network ,
}
if err := PublishDNSUpdate ( network , dns ) ; err != nil {
2023-02-10 19:58:00 +08:00
errMsgs . ErrorStrings = append ( errMsgs . ErrorStrings , err . Error ( ) )
2023-02-07 03:50:29 +08:00
}
}
2023-02-10 19:58:00 +08:00
if len ( errMsgs . ErrorStrings ) > 0 {
return errMsgs
2023-02-07 03:50:29 +08:00
}
return nil
}
2022-09-14 03:25:56 +08:00
func pushMetricsToExporter ( metrics models . Metrics ) error {
logger . Log ( 2 , "----> Pushing metrics to exporter" )
data , err := json . Marshal ( metrics )
if err != nil {
return errors . New ( "failed to marshal metrics: " + err . Error ( ) )
}
2022-09-30 21:01:57 +08:00
if token := mqclient . Publish ( "metrics_exporter" , 2 , true , data ) ; ! token . WaitTimeout ( MQ_TIMEOUT * time . Second ) || token . Error ( ) != nil {
2022-09-14 03:25:56 +08:00
var err error
if token . Error ( ) == nil {
err = errors . New ( "connection timeout" )
} else {
err = token . Error ( )
}
return err
}
return nil
}
2023-02-15 02:29:20 +08:00
func getNodeDNS ( network string ) [ ] models . DNSUpdate {
alldns := [ ] models . DNSUpdate { }
dns := models . DNSUpdate { }
nodes , err := logic . GetNetworkNodes ( network )
if err != nil {
logger . Log ( 0 , "error retreiving network nodes for network" , network , err . Error ( ) )
}
for _ , node := range nodes {
host , err := logic . GetHost ( node . HostID . String ( ) )
if err != nil {
logger . Log ( 0 , "error retrieving host for dns update" , host . ID . String ( ) , err . Error ( ) )
continue
}
dns . Action = models . DNSInsert
dns . Name = host . Name + "." + node . Network
if node . Address . IP != nil {
dns . Address = node . Address . IP . String ( )
alldns = append ( alldns , dns )
}
if node . Address6 . IP != nil {
dns . Address = node . Address6 . IP . String ( )
alldns = append ( alldns , dns )
}
}
return alldns
}
func getExtClientDNS ( network string ) [ ] models . DNSUpdate {
alldns := [ ] models . DNSUpdate { }
dns := models . DNSUpdate { }
clients , err := logic . GetNetworkExtClients ( network )
if err != nil {
logger . Log ( 0 , "error retrieving extclients" , err . Error ( ) )
}
for _ , client := range clients {
dns . Action = models . DNSInsert
dns . Name = client . ClientID + "." + client . Network
if client . Address != "" {
dns . Address = client . Address
alldns = append ( alldns , dns )
}
if client . Address6 != "" {
dns . Address = client . Address
alldns = append ( alldns , dns )
}
}
return alldns
}
func getCustomDNS ( network string ) [ ] models . DNSUpdate {
alldns := [ ] models . DNSUpdate { }
dns := models . DNSUpdate { }
customdns , err := logic . GetCustomDNS ( network )
if err != nil {
logger . Log ( 0 , "error retrieving custom dns entries" , err . Error ( ) )
}
for _ , custom := range customdns {
dns . Action = models . DNSInsert
dns . Address = custom . Address
dns . Name = custom . Name + "." + custom . Network
alldns = append ( alldns , dns )
}
return alldns
}
// sendPeers - retrieve networks, send peer ports to all peers
func sendPeers ( ) {
hosts , err := logic . GetAllHosts ( )
2023-02-28 03:52:50 +08:00
if err != nil && len ( hosts ) > 0 {
2023-02-15 02:29:20 +08:00
logger . Log ( 1 , "error retrieving networks for keepalive" , err . Error ( ) )
}
var force bool
peer_force_send ++
if peer_force_send == 5 {
servercfg . SetHost ( )
force = true
peer_force_send = 0
err := logic . TimerCheckpoint ( ) // run telemetry & log dumps if 24 hours has passed..
if err != nil {
logger . Log ( 3 , "error occurred on timer," , err . Error ( ) )
}
//collectServerMetrics(networks[:])
}
2023-03-07 01:21:51 +08:00
if force {
logic . ResetPeerUpdateContext ( )
for _ , host := range hosts {
2023-02-15 02:29:20 +08:00
host := host
logger . Log ( 2 , "sending scheduled peer update (5 min)" )
2023-03-14 03:06:07 +08:00
if err = PublishSingleHostPeerUpdate ( logic . PeerUpdateCtx , & host , nil , nil ) ; err != nil {
2023-02-15 02:29:20 +08:00
logger . Log ( 1 , "error publishing peer updates for host: " , host . ID . String ( ) , " Err: " , err . Error ( ) )
}
}
}
}