failover.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package logic
  2. import (
  3. "errors"
  4. "net"
  5. "github.com/google/uuid"
  6. "github.com/gravitl/netmaker/logic"
  7. "github.com/gravitl/netmaker/models"
  8. "golang.org/x/exp/slog"
  9. )
  10. func SetFailOverCtx(failOverNode, victimNode, peerNode models.Node) error {
  11. if victimNode.IsIngressGateway || peerNode.IsIngressGateway || victimNode.IsInternetGateway || peerNode.IsInternetGateway {
  12. return nil
  13. }
  14. if peerNode.FailOverPeers == nil {
  15. peerNode.FailOverPeers = make(map[string]struct{})
  16. }
  17. if victimNode.FailOverPeers == nil {
  18. victimNode.FailOverPeers = make(map[string]struct{})
  19. }
  20. peerNode.FailOverPeers[victimNode.ID.String()] = struct{}{}
  21. victimNode.FailOverPeers[peerNode.ID.String()] = struct{}{}
  22. victimNode.FailedOverBy = failOverNode.ID
  23. peerNode.FailedOverBy = failOverNode.ID
  24. if err := logic.UpsertNode(&failOverNode); err != nil {
  25. return err
  26. }
  27. if err := logic.UpsertNode(&victimNode); err != nil {
  28. return err
  29. }
  30. if err := logic.UpsertNode(&peerNode); err != nil {
  31. return err
  32. }
  33. return nil
  34. }
  35. // GetFailOverNode - gets the host acting as failOver
  36. func GetFailOverNode(network string, allNodes []models.Node) (models.Node, error) {
  37. nodes := logic.GetNetworkNodesMemory(allNodes, network)
  38. for _, node := range nodes {
  39. if node.IsFailOver {
  40. return node, nil
  41. }
  42. }
  43. return models.Node{}, errors.New("auto relay not found")
  44. }
  45. // FailOverExists - checks if failOver exists already in the network
  46. func FailOverExists(network string) (failOverNode models.Node, exists bool) {
  47. nodes, err := logic.GetNetworkNodes(network)
  48. if err != nil {
  49. return
  50. }
  51. for _, node := range nodes {
  52. if node.IsFailOver {
  53. exists = true
  54. failOverNode = node
  55. return
  56. }
  57. }
  58. return
  59. }
  60. // ResetFailedOverPeer - removes failed over node from network peers
  61. func ResetFailedOverPeer(failedOveredNode *models.Node) error {
  62. nodes, err := logic.GetNetworkNodes(failedOveredNode.Network)
  63. if err != nil {
  64. return err
  65. }
  66. failedOveredNode.FailedOverBy = uuid.Nil
  67. failedOveredNode.FailOverPeers = make(map[string]struct{})
  68. err = logic.UpsertNode(failedOveredNode)
  69. if err != nil {
  70. return err
  71. }
  72. for _, node := range nodes {
  73. if node.FailOverPeers == nil || node.ID == failedOveredNode.ID {
  74. continue
  75. }
  76. delete(node.FailOverPeers, failedOveredNode.ID.String())
  77. logic.UpsertNode(&node)
  78. }
  79. return nil
  80. }
  81. // ResetFailOver - reset failovered peers
  82. func ResetFailOver(failOverNode *models.Node) error {
  83. // Unset FailedOverPeers
  84. nodes, err := logic.GetNetworkNodes(failOverNode.Network)
  85. if err != nil {
  86. return err
  87. }
  88. for _, node := range nodes {
  89. if node.FailedOverBy == failOverNode.ID {
  90. node.FailedOverBy = uuid.Nil
  91. node.FailOverPeers = make(map[string]struct{})
  92. logic.UpsertNode(&node)
  93. }
  94. }
  95. return nil
  96. }
  97. // GetFailOverPeerIps - adds the failedOvered peerIps by the peer
  98. func GetFailOverPeerIps(peer, node *models.Node) []net.IPNet {
  99. allowedips := []net.IPNet{}
  100. for failOverpeerID := range node.FailOverPeers {
  101. failOverpeer, err := logic.GetNodeByID(failOverpeerID)
  102. if err == nil && failOverpeer.FailedOverBy == peer.ID {
  103. if failOverpeer.Address.IP != nil {
  104. allowed := net.IPNet{
  105. IP: failOverpeer.Address.IP,
  106. Mask: net.CIDRMask(32, 32),
  107. }
  108. allowedips = append(allowedips, allowed)
  109. }
  110. if failOverpeer.Address6.IP != nil {
  111. allowed := net.IPNet{
  112. IP: failOverpeer.Address6.IP,
  113. Mask: net.CIDRMask(128, 128),
  114. }
  115. allowedips = append(allowedips, allowed)
  116. }
  117. if failOverpeer.IsEgressGateway {
  118. allowedips = append(allowedips, logic.GetEgressIPs(&failOverpeer)...)
  119. }
  120. }
  121. }
  122. return allowedips
  123. }
  124. func CreateFailOver(node models.Node) error {
  125. if _, exists := FailOverExists(node.Network); exists {
  126. return errors.New("failover already exists in the network")
  127. }
  128. host, err := logic.GetHost(node.HostID.String())
  129. if err != nil {
  130. return err
  131. }
  132. if host.OS != models.OS_Types.Linux {
  133. return err
  134. }
  135. if node.IsRelayed {
  136. return err
  137. }
  138. node.IsFailOver = true
  139. err = logic.UpsertNode(&node)
  140. if err != nil {
  141. slog.Error("failed to upsert node", "node", node.ID.String(), "error", err)
  142. return err
  143. }
  144. return nil
  145. }