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  }