2015-06-07 19:14:41 +00:00
|
|
|
package nomad
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/armon/go-metrics"
|
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Client endpoint is used for client interactions
|
|
|
|
type Client struct {
|
|
|
|
srv *Server
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register is used to upsert a client that is available for scheduling
|
2015-07-07 16:51:42 +00:00
|
|
|
func (c *Client) Register(args *structs.NodeRegisterRequest, reply *structs.GenericResponse) error {
|
2015-06-07 19:14:41 +00:00
|
|
|
if done, err := c.srv.forward("Client.Register", args, args, reply); done {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer metrics.MeasureSince([]string{"nomad", "client", "register"}, time.Now())
|
|
|
|
|
|
|
|
// Validate the arguments
|
2015-07-04 00:47:55 +00:00
|
|
|
if args.Node == nil {
|
|
|
|
return fmt.Errorf("missing node for client registration")
|
|
|
|
}
|
|
|
|
if args.Node.ID == "" {
|
|
|
|
return fmt.Errorf("missing node ID for client registration")
|
|
|
|
}
|
|
|
|
if args.Node.Datacenter == "" {
|
2015-06-07 19:14:41 +00:00
|
|
|
return fmt.Errorf("missing datacenter for client registration")
|
|
|
|
}
|
2015-07-04 00:47:55 +00:00
|
|
|
if args.Node.Name == "" {
|
2015-06-07 19:14:41 +00:00
|
|
|
return fmt.Errorf("missing node name for client registration")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Default the status if none is given
|
2015-07-04 00:47:55 +00:00
|
|
|
if args.Node.Status == "" {
|
|
|
|
args.Node.Status = structs.NodeStatusInit
|
2015-06-07 19:14:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Commit this update via Raft
|
2015-07-07 16:51:42 +00:00
|
|
|
_, index, err := c.srv.raftApply(structs.NodeRegisterRequestType, args)
|
2015-06-07 19:14:41 +00:00
|
|
|
if err != nil {
|
|
|
|
c.srv.logger.Printf("[ERR] nomad.client: Register failed: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
2015-07-06 20:34:32 +00:00
|
|
|
|
|
|
|
// Set the reply index
|
|
|
|
reply.Index = index
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-07-06 20:42:33 +00:00
|
|
|
// Deregister is used to remove a client from the client. If a client should
|
|
|
|
// just be made unavailable for scheduling, a status update is prefered.
|
2015-07-07 16:51:42 +00:00
|
|
|
func (c *Client) Deregister(args *structs.NodeDeregisterRequest, reply *structs.GenericResponse) error {
|
2015-07-06 20:42:33 +00:00
|
|
|
if done, err := c.srv.forward("Client.Deregister", args, args, reply); done {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer metrics.MeasureSince([]string{"nomad", "client", "deregister"}, time.Now())
|
|
|
|
|
|
|
|
// Verify the arguments
|
|
|
|
if args.NodeID == "" {
|
|
|
|
return fmt.Errorf("missing node ID for client deregistration")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Commit this update via Raft
|
2015-07-07 16:51:42 +00:00
|
|
|
_, index, err := c.srv.raftApply(structs.NodeDeregisterRequestType, args)
|
2015-07-06 20:42:33 +00:00
|
|
|
if err != nil {
|
|
|
|
c.srv.logger.Printf("[ERR] nomad.client: Deregister failed: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the reply index
|
|
|
|
reply.Index = index
|
2015-06-07 19:14:41 +00:00
|
|
|
return nil
|
|
|
|
}
|
2015-07-06 20:50:40 +00:00
|
|
|
|
|
|
|
// UpdateStatus is used to update the status of a client node
|
2015-07-07 16:51:42 +00:00
|
|
|
func (c *Client) UpdateStatus(args *structs.NodeUpdateStatusRequest, reply *structs.GenericResponse) error {
|
2015-07-06 20:50:40 +00:00
|
|
|
if done, err := c.srv.forward("Client.UpdateStatus", args, args, reply); done {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer metrics.MeasureSince([]string{"nomad", "client", "update_status"}, time.Now())
|
|
|
|
|
|
|
|
// Verify the arguments
|
|
|
|
if args.NodeID == "" {
|
|
|
|
return fmt.Errorf("missing node ID for client deregistration")
|
|
|
|
}
|
|
|
|
switch args.Status {
|
|
|
|
case structs.NodeStatusInit, structs.NodeStatusReady,
|
|
|
|
structs.NodeStatusMaint, structs.NodeStatusDown:
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("invalid status for node")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Commit this update via Raft
|
|
|
|
_, index, err := c.srv.raftApply(structs.NodeUpdateStatusRequestType, args)
|
|
|
|
if err != nil {
|
|
|
|
c.srv.logger.Printf("[ERR] nomad.client: status update failed: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the reply index
|
|
|
|
reply.Index = index
|
|
|
|
return nil
|
|
|
|
}
|
2015-07-06 21:23:15 +00:00
|
|
|
|
|
|
|
// GetNode is used to request information about a specific ndoe
|
|
|
|
func (c *Client) GetNode(args *structs.NodeSpecificRequest,
|
|
|
|
reply *structs.SingleNodeResponse) error {
|
|
|
|
if done, err := c.srv.forward("Client.GetNode", args, args, reply); done {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer metrics.MeasureSince([]string{"nomad", "client", "get_node"}, time.Now())
|
|
|
|
|
|
|
|
// Verify the arguments
|
|
|
|
if args.NodeID == "" {
|
|
|
|
return fmt.Errorf("missing node ID")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look for the node
|
2015-07-06 21:38:57 +00:00
|
|
|
snap, err := c.srv.fsm.State().Snapshot()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
out, err := snap.GetNodeByID(args.NodeID)
|
2015-07-06 21:23:15 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup the output
|
|
|
|
if out != nil {
|
|
|
|
reply.Node = out
|
|
|
|
reply.Index = out.ModifyIndex
|
|
|
|
} else {
|
2015-07-06 21:38:57 +00:00
|
|
|
// Use the last index that affected the nodes table
|
|
|
|
index, err := snap.GetIndex("nodes")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
reply.Index = index
|
2015-07-06 21:23:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set the query response
|
|
|
|
c.srv.setQueryMeta(&reply.QueryMeta)
|
|
|
|
return nil
|
|
|
|
}
|