failover.go 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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. // SetFailover - finds a suitable failover candidate and sets it
  8. func SetFailover(node *models.Node) error {
  9. failoverNode := determineFailoverCandidate(node)
  10. if failoverNode != nil {
  11. return setFailoverNode(failoverNode, node)
  12. }
  13. return nil
  14. }
  15. // ResetFailover - sets the failover node and wipes disconnected status
  16. func ResetFailover(network string) error {
  17. nodes, err := logic.GetNetworkNodes(network)
  18. if err != nil {
  19. return err
  20. }
  21. for _, node := range nodes {
  22. err = SetFailover(&node)
  23. if err != nil {
  24. logger.Log(2, "error setting failover for node", node.Name, ":", err.Error())
  25. }
  26. err = WipeFailover(node.ID)
  27. if err != nil {
  28. logger.Log(2, "error wiping failover for node", node.Name, ":", err.Error())
  29. }
  30. }
  31. return nil
  32. }
  33. // determineFailoverCandidate - returns a list of nodes that
  34. // are suitable for relaying a given node
  35. func determineFailoverCandidate(nodeToBeRelayed *models.Node) *models.Node {
  36. currentNetworkNodes, err := logic.GetNetworkNodes(nodeToBeRelayed.Network)
  37. if err != nil {
  38. return nil
  39. }
  40. currentMetrics, err := logic.GetMetrics(nodeToBeRelayed.ID)
  41. if err != nil || currentMetrics == nil || currentMetrics.Connectivity == nil {
  42. return nil
  43. }
  44. minLatency := int64(9223372036854775807) // max signed int64 value
  45. var fastestCandidate *models.Node
  46. for i := range currentNetworkNodes {
  47. if currentNetworkNodes[i].ID == nodeToBeRelayed.ID {
  48. continue
  49. }
  50. if currentMetrics.Connectivity[currentNetworkNodes[i].ID].Connected && (currentNetworkNodes[i].Failover == "yes") {
  51. if currentMetrics.Connectivity[currentNetworkNodes[i].ID].Latency < int64(minLatency) {
  52. fastestCandidate = &currentNetworkNodes[i]
  53. minLatency = currentMetrics.Connectivity[currentNetworkNodes[i].ID].Latency
  54. }
  55. }
  56. }
  57. if fastestCandidate == nil {
  58. leader, err := logic.GetNetworkServerLeader(nodeToBeRelayed.Network)
  59. if err != nil {
  60. return nil
  61. }
  62. return &leader
  63. }
  64. return fastestCandidate
  65. }
  66. // setFailoverNode - changes node's failover node
  67. func setFailoverNode(failoverNode, node *models.Node) error {
  68. node.FailoverNode = failoverNode.ID
  69. nodeToUpdate, err := logic.GetNodeByID(node.ID)
  70. if err != nil {
  71. return err
  72. }
  73. return logic.UpdateNode(&nodeToUpdate, node)
  74. }
  75. func WipeFailover(nodeid string) error {
  76. metrics, err := logic.GetMetrics(nodeid)
  77. if err != nil {
  78. return err
  79. }
  80. metrics.NeedsFailover = make(map[string]string)
  81. return logic.UpdateMetrics(nodeid, metrics)
  82. }