github.com/zoomfoo/nomad@v0.8.5-0.20180907175415-f28fd3a1a056/nomad/status_endpoint.go (about) 1 package nomad 2 3 import ( 4 "fmt" 5 "strconv" 6 7 "errors" 8 9 "github.com/hashicorp/consul/agent/consul/autopilot" 10 11 "github.com/hashicorp/nomad/nomad/structs" 12 ) 13 14 // Status endpoint is used to check on server status 15 type Status struct { 16 srv *Server 17 } 18 19 // Version is used to allow clients to determine the capabilities 20 // of the server 21 func (s *Status) Version(args *structs.GenericRequest, reply *structs.VersionResponse) error { 22 if done, err := s.srv.forward("Status.Version", args, args, reply); done { 23 return err 24 } 25 26 conf := s.srv.config 27 reply.Build = conf.Build 28 reply.Versions = map[string]int{ 29 structs.ProtocolVersion: int(conf.ProtocolVersion), 30 structs.APIMajorVersion: structs.ApiMajorVersion, 31 structs.APIMinorVersion: structs.ApiMinorVersion, 32 } 33 return nil 34 } 35 36 // Ping is used to just check for connectivity 37 func (s *Status) Ping(args struct{}, reply *struct{}) error { 38 return nil 39 } 40 41 // Leader is used to get the address of the leader 42 func (s *Status) Leader(args *structs.GenericRequest, reply *string) error { 43 if args.Region == "" { 44 args.Region = s.srv.config.Region 45 } 46 if done, err := s.srv.forward("Status.Leader", args, args, reply); done { 47 return err 48 } 49 50 leader := string(s.srv.raft.Leader()) 51 if leader != "" { 52 *reply = leader 53 } else { 54 *reply = "" 55 } 56 return nil 57 } 58 59 // Peers is used to get all the Raft peers 60 func (s *Status) Peers(args *structs.GenericRequest, reply *[]string) error { 61 if args.Region == "" { 62 args.Region = s.srv.config.Region 63 } 64 if done, err := s.srv.forward("Status.Peers", args, args, reply); done { 65 return err 66 } 67 68 future := s.srv.raft.GetConfiguration() 69 if err := future.Error(); err != nil { 70 return err 71 } 72 73 for _, server := range future.Configuration().Servers { 74 *reply = append(*reply, string(server.Address)) 75 } 76 return nil 77 } 78 79 // Members return the list of servers in a cluster that a particular server is 80 // aware of 81 func (s *Status) Members(args *structs.GenericRequest, reply *structs.ServerMembersResponse) error { 82 // Check node read permissions 83 if aclObj, err := s.srv.ResolveToken(args.AuthToken); err != nil { 84 return err 85 } else if aclObj != nil && !aclObj.AllowNodeRead() { 86 return structs.ErrPermissionDenied 87 } 88 89 serfMembers := s.srv.Members() 90 members := make([]*structs.ServerMember, len(serfMembers)) 91 for i, mem := range serfMembers { 92 members[i] = &structs.ServerMember{ 93 Name: mem.Name, 94 Addr: mem.Addr, 95 Port: mem.Port, 96 Tags: mem.Tags, 97 Status: mem.Status.String(), 98 ProtocolMin: mem.ProtocolMin, 99 ProtocolMax: mem.ProtocolMax, 100 ProtocolCur: mem.ProtocolCur, 101 DelegateMin: mem.DelegateMin, 102 DelegateMax: mem.DelegateMax, 103 DelegateCur: mem.DelegateCur, 104 } 105 } 106 *reply = structs.ServerMembersResponse{ 107 ServerName: s.srv.config.NodeName, 108 ServerRegion: s.srv.config.Region, 109 ServerDC: s.srv.config.Datacenter, 110 Members: members, 111 } 112 return nil 113 } 114 115 // Used by Autopilot to query the raft stats of the local server. 116 func (s *Status) RaftStats(args struct{}, reply *autopilot.ServerStats) error { 117 stats := s.srv.raft.Stats() 118 119 var err error 120 reply.LastContact = stats["last_contact"] 121 reply.LastIndex, err = strconv.ParseUint(stats["last_log_index"], 10, 64) 122 if err != nil { 123 return fmt.Errorf("error parsing server's last_log_index value: %s", err) 124 } 125 reply.LastTerm, err = strconv.ParseUint(stats["last_log_term"], 10, 64) 126 if err != nil { 127 return fmt.Errorf("error parsing server's last_log_term value: %s", err) 128 } 129 130 return nil 131 } 132 133 // HasNodeConn returns whether the server has a connection to the requested 134 // Node. 135 func (s *Status) HasNodeConn(args *structs.NodeSpecificRequest, reply *structs.NodeConnQueryResponse) error { 136 // Validate the args 137 if args.NodeID == "" { 138 return errors.New("Must provide the NodeID") 139 } 140 141 state, ok := s.srv.getNodeConn(args.NodeID) 142 if ok { 143 reply.Connected = true 144 reply.Established = state.Established 145 } 146 147 return nil 148 }