2018-01-11 23:58:59 +00:00
|
|
|
package nomad
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
metrics "github.com/armon/go-metrics"
|
2018-09-15 23:23:13 +00:00
|
|
|
log "github.com/hashicorp/go-hclog"
|
2018-01-11 23:58:59 +00:00
|
|
|
nstructs "github.com/hashicorp/nomad/nomad/structs"
|
2018-09-15 23:23:13 +00:00
|
|
|
|
|
|
|
"github.com/hashicorp/nomad/client/structs"
|
2018-01-11 23:58:59 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// ClientStats is used to forward RPC requests to the targed Nomad client's
|
|
|
|
// ClientStats endpoint.
|
|
|
|
type ClientStats struct {
|
2018-09-15 23:23:13 +00:00
|
|
|
srv *Server
|
|
|
|
logger log.Logger
|
2018-01-11 23:58:59 +00:00
|
|
|
}
|
|
|
|
|
2018-02-06 01:20:42 +00:00
|
|
|
func (s *ClientStats) Stats(args *nstructs.NodeSpecificRequest, reply *structs.ClientStatsResponse) error {
|
2018-01-11 23:58:59 +00:00
|
|
|
// We only allow stale reads since the only potentially stale information is
|
|
|
|
// the Node registration and the cost is fairly high for adding another hope
|
|
|
|
// in the forwarding chain.
|
|
|
|
args.QueryOptions.AllowStale = true
|
|
|
|
|
|
|
|
// Potentially forward to a different region.
|
|
|
|
if done, err := s.srv.forward("ClientStats.Stats", args, args, reply); done {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer metrics.MeasureSince([]string{"nomad", "client_stats", "stats"}, time.Now())
|
|
|
|
|
|
|
|
// Check node read permissions
|
|
|
|
if aclObj, err := s.srv.ResolveToken(args.AuthToken); err != nil {
|
|
|
|
return err
|
|
|
|
} else if aclObj != nil && !aclObj.AllowNodeRead() {
|
|
|
|
return nstructs.ErrPermissionDenied
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify the arguments.
|
|
|
|
if args.NodeID == "" {
|
|
|
|
return errors.New("missing NodeID")
|
|
|
|
}
|
|
|
|
|
2018-04-06 18:33:08 +00:00
|
|
|
// Check if the node even exists and is compatible with NodeRpc
|
|
|
|
snap, err := s.srv.State().Snapshot()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure Node is new enough to support RPC
|
2018-04-09 17:17:39 +00:00
|
|
|
_, err = getNodeForRpc(snap, args.NodeID)
|
|
|
|
if err != nil {
|
2018-04-06 18:33:08 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-01-11 23:58:59 +00:00
|
|
|
// Get the connection to the client
|
2018-01-12 23:57:07 +00:00
|
|
|
state, ok := s.srv.getNodeConn(args.NodeID)
|
2018-01-11 23:58:59 +00:00
|
|
|
if !ok {
|
|
|
|
|
2018-01-15 22:48:53 +00:00
|
|
|
// Determine the Server that has a connection to the node.
|
2018-01-30 06:01:42 +00:00
|
|
|
srv, err := s.srv.serverWithNodeConn(args.NodeID, s.srv.Region())
|
2018-01-15 22:48:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-01-23 22:14:31 +00:00
|
|
|
if srv == nil {
|
2018-01-27 01:05:38 +00:00
|
|
|
return nstructs.ErrNoNodeConn
|
2018-01-23 22:14:31 +00:00
|
|
|
}
|
|
|
|
|
2018-01-15 22:48:53 +00:00
|
|
|
return s.srv.forwardServer(srv, "ClientStats.Stats", args, reply)
|
2018-01-11 23:58:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Make the RPC
|
2018-01-27 01:05:38 +00:00
|
|
|
return NodeRpc(state.Session, "ClientStats.Stats", args, reply)
|
2018-01-11 23:58:59 +00:00
|
|
|
}
|