failover.go 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. package logic
  2. import (
  3. "github.com/gravitl/netmaker/logger"
  4. "github.com/gravitl/netmaker/logic"
  5. "github.com/gravitl/netmaker/models"
  6. )
  7. // AutoRelay - finds a suitable relay candidate and creates a relay
  8. func AutoRelay(nodeToBeRelayed *models.Node) (updateNodes []models.Node, err error) {
  9. newRelayer := determineFailoverCandidate(nodeToBeRelayed)
  10. if newRelayer != nil {
  11. return changeRelayStatus(newRelayer, nodeToBeRelayed)
  12. }
  13. return
  14. }
  15. // determineFailoverCandidate - returns a list of nodes that
  16. // are suitable for relaying a given node
  17. func determineFailoverCandidate(nodeToBeRelayed *models.Node) *models.Node {
  18. currentNetworkNodes, err := logic.GetNetworkNodes(nodeToBeRelayed.Network)
  19. if err != nil {
  20. return nil
  21. }
  22. currentMetrics, err := logic.GetMetrics(nodeToBeRelayed.ID)
  23. if err != nil || currentMetrics == nil || currentMetrics.Connectivity == nil {
  24. return nil
  25. }
  26. minLatency := int64(9223372036854775807) // max signed int64 value
  27. var fastestCandidate *models.Node
  28. for i := range currentNetworkNodes {
  29. if currentNetworkNodes[i].ID == nodeToBeRelayed.ID {
  30. continue
  31. }
  32. if currentMetrics.Connectivity[currentNetworkNodes[i].ID].Connected && (currentNetworkNodes[i].Failover == "yes" || currentNetworkNodes[i].IsServer == "yes") {
  33. if currentMetrics.Connectivity[currentNetworkNodes[i].ID].Latency < int64(minLatency) {
  34. fastestCandidate = &currentNetworkNodes[i]
  35. minLatency = currentMetrics.Connectivity[currentNetworkNodes[i].ID].Latency
  36. }
  37. }
  38. }
  39. if fastestCandidate == nil {
  40. leader, err := logic.GetNetworkServerLeader(nodeToBeRelayed.Network)
  41. if err != nil {
  42. return nil
  43. }
  44. return &leader
  45. }
  46. return fastestCandidate
  47. }
  48. // changeRelayStatus - changes nodes to relay
  49. func changeRelayStatus(relayer, nodeToBeRelayed *models.Node) ([]models.Node, error) {
  50. var newRelayRequest models.RelayRequest
  51. if relayer.IsRelay == "yes" {
  52. newRelayRequest.RelayAddrs = relayer.RelayAddrs
  53. }
  54. newRelayRequest.NodeID = relayer.ID
  55. newRelayRequest.NetID = relayer.Network
  56. newRelayRequest.RelayAddrs = append(newRelayRequest.RelayAddrs, nodeToBeRelayed.PrimaryAddress())
  57. updatenodes, _, err := logic.CreateRelay(newRelayRequest)
  58. if err != nil {
  59. logger.Log(0, "failed to create relay automatically for node", nodeToBeRelayed.Name, "on network", nodeToBeRelayed.Network)
  60. return nil, err
  61. }
  62. logger.Log(0, "created relay automatically for node", nodeToBeRelayed.Name, "on network", nodeToBeRelayed.Network)
  63. return updatenodes, nil
  64. }