nodeGrpcController.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. package controller
  2. import (
  3. "context"
  4. "fmt"
  5. nodepb "github.com/gravitl/netmaker/grpc"
  6. "github.com/gravitl/netmaker/models"
  7. "github.com/gravitl/netmaker/functions"
  8. "go.mongodb.org/mongo-driver/mongo"
  9. "google.golang.org/grpc/codes"
  10. "google.golang.org/grpc/status"
  11. )
  12. type NodeServiceServer struct {
  13. NodeDB *mongo.Collection
  14. nodepb.UnimplementedNodeServiceServer
  15. }
  16. func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.ReadNodeReq) (*nodepb.ReadNodeRes, error) {
  17. // convert string id (from proto) to mongoDB ObjectId
  18. macaddress := req.GetMacaddress()
  19. groupName := req.GetGroup()
  20. node, err := GetNode(macaddress, groupName)
  21. if err != nil {
  22. return nil, status.Errorf(codes.InvalidArgument, fmt.Sprintf("Something went wrong: %v", err))
  23. }
  24. /*
  25. if node == nil {
  26. return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not find node with Mac Address %s: %v", req.GetMacaddress(), err))
  27. }
  28. */
  29. // Cast to ReadNodeRes type
  30. response := &nodepb.ReadNodeRes{
  31. Node: &nodepb.Node{
  32. Macaddress: node.MacAddress,
  33. Name: node.Name,
  34. Address: node.Address,
  35. Endpoint: node.Endpoint,
  36. Password: node.Password,
  37. Nodegroup: node.Group,
  38. Interface: node.Interface,
  39. Localaddress: node.LocalAddress,
  40. Preup: node.PreUp,
  41. Postup: node.PostUp,
  42. Checkininterval: node.CheckInInterval,
  43. Ispending: node.IsPending,
  44. Publickey: node.PublicKey,
  45. Listenport: node.ListenPort,
  46. Keepalive: node.PersistentKeepalive,
  47. },
  48. }
  49. return response, nil
  50. }
  51. func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNodeReq) (*nodepb.CreateNodeRes, error) {
  52. // Get the protobuf node type from the protobuf request type
  53. // Essentially doing req.Node to access the struct with a nil check
  54. data := req.GetNode()
  55. // Now we have to convert this into a NodeItem type to convert into BSON
  56. node := models.Node{
  57. // ID: primitive.NilObjectID,
  58. MacAddress: data.GetMacaddress(),
  59. LocalAddress: data.GetLocaladdress(),
  60. Name: data.GetName(),
  61. Address: data.GetAddress(),
  62. AccessKey: data.GetAccesskey(),
  63. Endpoint: data.GetEndpoint(),
  64. PersistentKeepalive: data.GetKeepalive(),
  65. Password: data.GetPassword(),
  66. Interface: data.GetInterface(),
  67. Group: data.GetNodegroup(),
  68. IsPending: data.GetIspending(),
  69. PublicKey: data.GetPublickey(),
  70. ListenPort: data.GetListenport(),
  71. }
  72. err := ValidateNode("create", node.Group, node)
  73. if err != nil {
  74. // return internal gRPC error to be handled later
  75. return nil, err
  76. }
  77. //Check to see if key is valid
  78. //TODO: Triple inefficient!!! This is the third call to the DB we make for groups
  79. validKey := functions.IsKeyValid(node.Group, node.AccessKey)
  80. if !validKey {
  81. group, _ := functions.GetParentGroup(node.Group)
  82. //Check to see if group will allow manual sign up
  83. //may want to switch this up with the valid key check and avoid a DB call that way.
  84. if *group.AllowManualSignUp {
  85. node.IsPending = true
  86. } else {
  87. return nil, status.Errorf(
  88. codes.Internal,
  89. fmt.Sprintf("Invalid key, and group does not allow no-key signups"),
  90. )
  91. }
  92. }
  93. node, err = CreateNode(node, node.Group)
  94. if err != nil {
  95. // return internal gRPC error to be handled later
  96. return nil, status.Errorf(
  97. codes.Internal,
  98. fmt.Sprintf("Internal error: %v", err),
  99. )
  100. }
  101. // return the node in a CreateNodeRes type
  102. response := &nodepb.CreateNodeRes{
  103. Node: &nodepb.Node{
  104. Macaddress: node.MacAddress,
  105. Localaddress: node.LocalAddress,
  106. Name: node.Name,
  107. Address: node.Address,
  108. Endpoint: node.Endpoint,
  109. Password: node.Password,
  110. Interface: node.Interface,
  111. Nodegroup: node.Group,
  112. Ispending: node.IsPending,
  113. Publickey: node.PublicKey,
  114. Listenport: node.ListenPort,
  115. Keepalive: node.PersistentKeepalive,
  116. },
  117. }
  118. err = SetGroupNodesLastModified(node.Group)
  119. if err != nil {
  120. return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not update group last modified date: %v", err))
  121. }
  122. return response, nil
  123. }
  124. func (s *NodeServiceServer) CheckIn(ctx context.Context, req *nodepb.CheckInReq) (*nodepb.CheckInRes, error) {
  125. // Get the protobuf node type from the protobuf request type
  126. // Essentially doing req.Node to access the struct with a nil check
  127. data := req.GetNode()
  128. //postchanges := req.GetPostchanges()
  129. // Now we have to convert this into a NodeItem type to convert into BSON
  130. node := models.Node{
  131. // ID: primitive.NilObjectID,
  132. MacAddress: data.GetMacaddress(),
  133. Address: data.GetAddress(),
  134. Endpoint: data.GetEndpoint(),
  135. Group: data.GetNodegroup(),
  136. Password: data.GetPassword(),
  137. LocalAddress: data.GetLocaladdress(),
  138. ListenPort: data.GetListenport(),
  139. PersistentKeepalive: data.GetKeepalive(),
  140. PublicKey: data.GetPublickey(),
  141. }
  142. checkinresponse, err := NodeCheckIn(node, node.Group)
  143. if err != nil {
  144. // return internal gRPC error to be handled later
  145. if checkinresponse == (models.CheckInResponse{}) || !checkinresponse.IsPending {
  146. return nil, status.Errorf(
  147. codes.Internal,
  148. fmt.Sprintf("Internal error: %v", err),
  149. )
  150. }
  151. }
  152. // return the node in a CreateNodeRes type
  153. response := &nodepb.CheckInRes{
  154. Checkinresponse: &nodepb.CheckInResponse{
  155. Success: checkinresponse.Success,
  156. Needpeerupdate: checkinresponse.NeedPeerUpdate,
  157. Needdelete: checkinresponse.NeedDelete,
  158. Needconfigupdate: checkinresponse.NeedConfigUpdate,
  159. Needkeyupdate: checkinresponse.NeedKeyUpdate,
  160. Nodemessage: checkinresponse.NodeMessage,
  161. Ispending: checkinresponse.IsPending,
  162. },
  163. }
  164. return response, nil
  165. }
  166. func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNodeReq) (*nodepb.UpdateNodeRes, error) {
  167. // Get the node data from the request
  168. data := req.GetNode()
  169. // Now we have to convert this into a NodeItem type to convert into BSON
  170. nodechange := models.Node{
  171. // ID: primitive.NilObjectID,
  172. MacAddress: data.GetMacaddress(),
  173. Name: data.GetName(),
  174. Address: data.GetAddress(),
  175. LocalAddress: data.GetLocaladdress(),
  176. Endpoint: data.GetEndpoint(),
  177. Password: data.GetPassword(),
  178. PersistentKeepalive: data.GetKeepalive(),
  179. Group: data.GetNodegroup(),
  180. Interface: data.GetInterface(),
  181. PreUp: data.GetPreup(),
  182. PostUp: data.GetPostup(),
  183. IsPending: data.GetIspending(),
  184. PublicKey: data.GetPublickey(),
  185. ListenPort: data.GetListenport(),
  186. }
  187. // Convert the Id string to a MongoDB ObjectId
  188. macaddress := nodechange.MacAddress
  189. groupName := nodechange.Group
  190. err := ValidateNode("update", groupName, nodechange)
  191. if err != nil {
  192. return nil, err
  193. }
  194. node, err := functions.GetNodeByMacAddress(groupName, macaddress)
  195. if err != nil {
  196. return nil, status.Errorf(
  197. codes.NotFound,
  198. fmt.Sprintf("Could not find node with supplied Mac Address: %v", err),
  199. )
  200. }
  201. newnode, err := UpdateNode(nodechange, node)
  202. if err != nil {
  203. return nil, status.Errorf(
  204. codes.NotFound,
  205. fmt.Sprintf("Could not find node with supplied Mac Address: %v", err),
  206. )
  207. }
  208. return &nodepb.UpdateNodeRes{
  209. Node: &nodepb.Node{
  210. Macaddress: newnode.MacAddress,
  211. Localaddress: newnode.LocalAddress,
  212. Name: newnode.Name,
  213. Address: newnode.Address,
  214. Endpoint: newnode.Endpoint,
  215. Password: newnode.Password,
  216. Interface: newnode.Interface,
  217. Preup: newnode.PreUp,
  218. Postup: newnode.PostUp,
  219. Nodegroup: newnode.Group,
  220. Ispending: newnode.IsPending,
  221. Publickey: newnode.PublicKey,
  222. Listenport: newnode.ListenPort,
  223. Keepalive: newnode.PersistentKeepalive,
  224. },
  225. }, nil
  226. }
  227. func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.DeleteNodeReq) (*nodepb.DeleteNodeRes, error) {
  228. fmt.Println("beginning node delete")
  229. macaddress := req.GetMacaddress()
  230. group := req.GetGroupName()
  231. success, err := DeleteNode(macaddress, group)
  232. if err != nil || !success {
  233. fmt.Println("Error deleting node.")
  234. fmt.Println(err)
  235. return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not find/delete node with mac address %s", macaddress))
  236. }
  237. fmt.Println("updating group last modified of " + req.GetGroupName())
  238. err = SetGroupNodesLastModified(req.GetGroupName())
  239. if err != nil {
  240. fmt.Println("Error updating Group")
  241. fmt.Println(err)
  242. return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not update group last modified date: %v", err))
  243. }
  244. return &nodepb.DeleteNodeRes{
  245. Success: true,
  246. }, nil
  247. }
  248. func (s *NodeServiceServer) GetPeers(req *nodepb.GetPeersReq, stream nodepb.NodeService_GetPeersServer) error {
  249. // Initiate a NodeItem type to write decoded data to
  250. //data := &models.PeersResponse{}
  251. // collection.Find returns a cursor for our (empty) query
  252. //cursor, err := s.NodeDB.Find(context.Background(), bson.M{})
  253. peers, err := GetPeersList(req.GetGroup())
  254. if err != nil {
  255. return status.Errorf(codes.Internal, fmt.Sprintf("Unknown internal error: %v", err))
  256. }
  257. // cursor.Next() returns a boolean, if false there are no more items and loop will break
  258. for i := 0; i < len(peers); i++ {
  259. // If no error is found send node over stream
  260. stream.Send(&nodepb.GetPeersRes{
  261. Peers: &nodepb.PeersResponse{
  262. Address: peers[i].Address,
  263. Endpoint: peers[i].Endpoint,
  264. Publickey: peers[i].PublicKey,
  265. Keepalive: peers[i].KeepAlive,
  266. Listenport: peers[i].ListenPort,
  267. Localaddress: peers[i].LocalAddress,
  268. },
  269. })
  270. }
  271. node, err := functions.GetNodeByMacAddress(req.GetGroup(), req.GetMacaddress())
  272. if err != nil {
  273. return status.Errorf(codes.Internal, fmt.Sprintf("Could not get node: %v", err))
  274. }
  275. err = TimestampNode(node, false, true, false)
  276. if err != nil {
  277. return status.Errorf(codes.Internal, fmt.Sprintf("Internal error occurred: %v", err))
  278. }
  279. return nil
  280. }