failover.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. package logic
  2. import (
  3. "context"
  4. "errors"
  5. "net"
  6. "sync"
  7. "github.com/google/uuid"
  8. "github.com/gravitl/netmaker/db"
  9. "github.com/gravitl/netmaker/logger"
  10. "github.com/gravitl/netmaker/logic"
  11. "github.com/gravitl/netmaker/models"
  12. "github.com/gravitl/netmaker/schema"
  13. )
  14. var failOverCtxMutex = &sync.RWMutex{}
  15. var failOverCacheMutex = &sync.RWMutex{}
  16. var failOverCache = make(map[models.NetworkID]string)
  17. func InitFailOverCache() {
  18. failOverCacheMutex.Lock()
  19. defer failOverCacheMutex.Unlock()
  20. networks, err := logic.GetNetworks()
  21. if err != nil {
  22. return
  23. }
  24. allNodes, err := logic.GetAllNodes()
  25. if err != nil {
  26. return
  27. }
  28. for _, network := range networks {
  29. networkNodes := logic.GetNetworkNodesMemory(allNodes, network.NetID)
  30. for _, node := range networkNodes {
  31. if node.IsFailOver {
  32. failOverCache[models.NetworkID(network.NetID)] = node.ID.String()
  33. break
  34. }
  35. }
  36. }
  37. }
  38. func CheckFailOverCtx(failOverNode, victimNode, peerNode models.Node) error {
  39. failOverCtxMutex.RLock()
  40. defer failOverCtxMutex.RUnlock()
  41. if peerNode.FailOverPeers == nil {
  42. return nil
  43. }
  44. if victimNode.FailOverPeers == nil {
  45. return nil
  46. }
  47. if peerNode.Mutex != nil {
  48. peerNode.Mutex.Lock()
  49. }
  50. _, peerHasFailovered := peerNode.FailOverPeers[victimNode.ID.String()]
  51. if peerNode.Mutex != nil {
  52. peerNode.Mutex.Unlock()
  53. }
  54. if victimNode.Mutex != nil {
  55. victimNode.Mutex.Lock()
  56. }
  57. _, victimHasFailovered := victimNode.FailOverPeers[peerNode.ID.String()]
  58. if victimNode.Mutex != nil {
  59. victimNode.Mutex.Unlock()
  60. }
  61. if peerHasFailovered && victimHasFailovered &&
  62. victimNode.FailedOverBy == failOverNode.ID && peerNode.FailedOverBy == failOverNode.ID {
  63. return errors.New("failover ctx is already set")
  64. }
  65. return nil
  66. }
  67. func SetFailOverCtx(failOverNode, victimNode, peerNode models.Node) error {
  68. failOverCtxMutex.Lock()
  69. defer failOverCtxMutex.Unlock()
  70. if peerNode.FailOverPeers == nil {
  71. peerNode.FailOverPeers = make(map[string]struct{})
  72. }
  73. if victimNode.FailOverPeers == nil {
  74. victimNode.FailOverPeers = make(map[string]struct{})
  75. }
  76. if peerNode.Mutex != nil {
  77. peerNode.Mutex.Lock()
  78. }
  79. _, peerHasFailovered := peerNode.FailOverPeers[victimNode.ID.String()]
  80. if peerNode.Mutex != nil {
  81. peerNode.Mutex.Unlock()
  82. }
  83. if victimNode.Mutex != nil {
  84. victimNode.Mutex.Lock()
  85. }
  86. _, victimHasFailovered := victimNode.FailOverPeers[peerNode.ID.String()]
  87. if victimNode.Mutex != nil {
  88. victimNode.Mutex.Unlock()
  89. }
  90. if peerHasFailovered && victimHasFailovered &&
  91. victimNode.FailedOverBy == failOverNode.ID && peerNode.FailedOverBy == failOverNode.ID {
  92. return errors.New("failover ctx is already set")
  93. }
  94. if peerNode.Mutex != nil {
  95. peerNode.Mutex.Lock()
  96. }
  97. peerNode.FailOverPeers[victimNode.ID.String()] = struct{}{}
  98. if peerNode.Mutex != nil {
  99. peerNode.Mutex.Unlock()
  100. }
  101. if victimNode.Mutex != nil {
  102. victimNode.Mutex.Lock()
  103. }
  104. victimNode.FailOverPeers[peerNode.ID.String()] = struct{}{}
  105. if victimNode.Mutex != nil {
  106. victimNode.Mutex.Unlock()
  107. }
  108. victimNode.FailedOverBy = failOverNode.ID
  109. peerNode.FailedOverBy = failOverNode.ID
  110. if err := logic.UpsertNode(&victimNode); err != nil {
  111. return err
  112. }
  113. if err := logic.UpsertNode(&peerNode); err != nil {
  114. return err
  115. }
  116. return nil
  117. }
  118. // GetFailOverNode - gets the host acting as failOver
  119. func GetFailOverNode(network string, allNodes []models.Node) (models.Node, error) {
  120. nodes := logic.GetNetworkNodesMemory(allNodes, network)
  121. for _, node := range nodes {
  122. if node.IsFailOver {
  123. return node, nil
  124. }
  125. }
  126. return models.Node{}, errors.New("auto relay not found")
  127. }
  128. func RemoveFailOverFromCache(network string) {
  129. failOverCacheMutex.Lock()
  130. defer failOverCacheMutex.Unlock()
  131. delete(failOverCache, models.NetworkID(network))
  132. }
  133. func SetFailOverInCache(node models.Node) {
  134. failOverCacheMutex.Lock()
  135. defer failOverCacheMutex.Unlock()
  136. failOverCache[models.NetworkID(node.Network)] = node.ID.String()
  137. }
  138. // FailOverExists - checks if failOver exists already in the network
  139. func FailOverExists(network string) (failOverNode models.Node, exists bool) {
  140. failOverCacheMutex.RLock()
  141. defer failOverCacheMutex.RUnlock()
  142. if nodeID, ok := failOverCache[models.NetworkID(network)]; ok {
  143. failOverNode, err := logic.GetNodeByID(nodeID)
  144. if err == nil {
  145. return failOverNode, true
  146. }
  147. }
  148. return
  149. }
  150. // ResetFailedOverPeer - removes failed over node from network peers
  151. func ResetFailedOverPeer(failedOveredNode *models.Node) error {
  152. nodes, err := logic.GetNetworkNodes(failedOveredNode.Network)
  153. if err != nil {
  154. return err
  155. }
  156. failedOveredNode.FailedOverBy = uuid.Nil
  157. failedOveredNode.FailOverPeers = make(map[string]struct{})
  158. err = logic.UpsertNode(failedOveredNode)
  159. if err != nil {
  160. return err
  161. }
  162. for _, node := range nodes {
  163. if node.FailOverPeers == nil || node.ID == failedOveredNode.ID {
  164. continue
  165. }
  166. delete(node.FailOverPeers, failedOveredNode.ID.String())
  167. logic.UpsertNode(&node)
  168. }
  169. return nil
  170. }
  171. // ResetFailOver - reset failovered peers
  172. func ResetFailOver(failOverNode *models.Node) error {
  173. // Unset FailedOverPeers
  174. nodes, err := logic.GetNetworkNodes(failOverNode.Network)
  175. if err != nil {
  176. return err
  177. }
  178. for _, node := range nodes {
  179. if node.FailedOverBy == failOverNode.ID {
  180. node.FailedOverBy = uuid.Nil
  181. node.FailOverPeers = make(map[string]struct{})
  182. logic.UpsertNode(&node)
  183. }
  184. }
  185. return nil
  186. }
  187. // GetFailOverPeerIps - adds the failedOvered peerIps by the peer
  188. func GetFailOverPeerIps(peer, node *models.Node) []net.IPNet {
  189. allowedips := []net.IPNet{}
  190. eli, _ := (&schema.Egress{Network: node.Network}).ListByNetwork(db.WithContext(context.TODO()))
  191. acls, _ := logic.ListAclsByNetwork(models.NetworkID(node.Network))
  192. for failOverpeerID := range node.FailOverPeers {
  193. failOverpeer, err := logic.GetNodeByID(failOverpeerID)
  194. if err == nil && failOverpeer.FailedOverBy == peer.ID {
  195. logic.GetNodeEgressInfo(&failOverpeer, eli, acls)
  196. if failOverpeer.Address.IP != nil {
  197. allowed := net.IPNet{
  198. IP: failOverpeer.Address.IP,
  199. Mask: net.CIDRMask(32, 32),
  200. }
  201. allowedips = append(allowedips, allowed)
  202. }
  203. if failOverpeer.Address6.IP != nil {
  204. allowed := net.IPNet{
  205. IP: failOverpeer.Address6.IP,
  206. Mask: net.CIDRMask(128, 128),
  207. }
  208. allowedips = append(allowedips, allowed)
  209. }
  210. if failOverpeer.EgressDetails.IsEgressGateway {
  211. allowedips = append(allowedips, logic.GetEgressIPs(&failOverpeer)...)
  212. }
  213. if failOverpeer.IsRelay {
  214. for _, id := range failOverpeer.RelayedNodes {
  215. rNode, _ := logic.GetNodeByID(id)
  216. logic.GetNodeEgressInfo(&rNode, eli, acls)
  217. if rNode.Address.IP != nil {
  218. allowed := net.IPNet{
  219. IP: rNode.Address.IP,
  220. Mask: net.CIDRMask(32, 32),
  221. }
  222. allowedips = append(allowedips, allowed)
  223. }
  224. if rNode.Address6.IP != nil {
  225. allowed := net.IPNet{
  226. IP: rNode.Address6.IP,
  227. Mask: net.CIDRMask(128, 128),
  228. }
  229. allowedips = append(allowedips, allowed)
  230. }
  231. if rNode.EgressDetails.IsEgressGateway {
  232. allowedips = append(allowedips, logic.GetEgressIPs(&rNode)...)
  233. }
  234. }
  235. }
  236. // handle ingress gateway peers
  237. if failOverpeer.IsIngressGateway {
  238. extPeers, _, _, err := logic.GetExtPeers(&failOverpeer, node)
  239. if err != nil {
  240. logger.Log(2, "could not retrieve ext peers for ", peer.ID.String(), err.Error())
  241. }
  242. for _, extPeer := range extPeers {
  243. allowedips = append(allowedips, extPeer.AllowedIPs...)
  244. }
  245. }
  246. }
  247. }
  248. return allowedips
  249. }
  250. func CreateFailOver(node models.Node) error {
  251. return nil
  252. }