failover.go 5.0 KB

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