func (n *Node) Register(args *structs.NodeRegisterRequest, reply *structs.NodeUpdateResponse) error {
	if done, err := n.srv.forward("Node.Register", args, args, reply); done {
		return err
	}
	defer metrics.MeasureSince([]string{"nomad", "client", "register"}, time.Now())

	// Validate the arguments
	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 == "" {
		return fmt.Errorf("missing datacenter for client registration")
	}
	if args.Node.Name == "" {
		return fmt.Errorf("missing node name for client registration")
	}
	if len(args.Node.Attributes) == 0 {
		return fmt.Errorf("missing attributes for client registration")
	}

	// COMPAT: Remove after 0.6
	// Need to check if this node is <0.4.x since SecretID is new in 0.5
	pre, err := nodePreSecretID(args.Node)
	if err != nil {
		return err
	}
	if args.Node.SecretID == "" && !pre {
		return fmt.Errorf("missing node secret ID for client registration")
	}

	// Default the status if none is given
	if args.Node.Status == "" {
		args.Node.Status = structs.NodeStatusInit
	}
	if !structs.ValidNodeStatus(args.Node.Status) {
		return fmt.Errorf("invalid status for node")
	}

	// Set the timestamp when the node is registered
	args.Node.StatusUpdatedAt = time.Now().Unix()

	// Compute the node class
	if err := args.Node.ComputeClass(); err != nil {
		return fmt.Errorf("failed to computed node class: %v", err)
	}

	// Look for the node so we can detect a state transistion
	snap, err := n.srv.fsm.State().Snapshot()
	if err != nil {
		return err
	}

	ws := memdb.NewWatchSet()
	originalNode, err := snap.NodeByID(ws, args.Node.ID)
	if err != nil {
		return err
	}

	// Check if the SecretID has been tampered with
	if !pre && originalNode != nil {
		if args.Node.SecretID != originalNode.SecretID && originalNode.SecretID != "" {
			return fmt.Errorf("node secret ID does not match. Not registering node.")
		}
	}

	// Commit this update via Raft
	_, index, err := n.srv.raftApply(structs.NodeRegisterRequestType, args)
	if err != nil {
		n.srv.logger.Printf("[ERR] nomad.client: Register failed: %v", err)
		return err
	}
	reply.NodeModifyIndex = index

	// Check if we should trigger evaluations
	originalStatus := structs.NodeStatusInit
	if originalNode != nil {
		originalStatus = originalNode.Status
	}
	transitionToReady := transitionedToReady(args.Node.Status, originalStatus)
	if structs.ShouldDrainNode(args.Node.Status) || transitionToReady {
		evalIDs, evalIndex, err := n.createNodeEvals(args.Node.ID, index)
		if err != nil {
			n.srv.logger.Printf("[ERR] nomad.client: eval creation failed: %v", err)
			return err
		}
		reply.EvalIDs = evalIDs
		reply.EvalCreateIndex = evalIndex
	}

	// Check if we need to setup a heartbeat
	if !args.Node.TerminalStatus() {
		ttl, err := n.srv.resetHeartbeatTimer(args.Node.ID)
		if err != nil {
			n.srv.logger.Printf("[ERR] nomad.client: heartbeat reset failed: %v", err)
			return err
		}
		reply.HeartbeatTTL = ttl
	}

	// Set the reply index
	reply.Index = index
	snap, err = n.srv.fsm.State().Snapshot()
	if err != nil {
		return err
	}

	n.srv.peerLock.RLock()
	defer n.srv.peerLock.RUnlock()
	if err := n.constructNodeServerInfoResponse(snap, reply); err != nil {
		n.srv.logger.Printf("[ERR] nomad.client: failed to populate NodeUpdateResponse: %v", err)
		return err
	}

	return nil
}
// Register is used to upsert a client that is available for scheduling
Register is used to upsert a client that is available for scheduling
// Register is used to upsert a client that is available for scheduling
func (n *Node) Register(args *structs.NodeRegisterRequest, reply *structs.NodeUpdateResponse) error {
	if done, err := n.srv.forward("Node.Register", args, args, reply); done {
		return err
	}
	defer metrics.MeasureSince([]string{"nomad", "client", "register"}, time.Now())
	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 == "" {
		return fmt.Errorf("missing datacenter for client registration")
	}
	if args.Node.Name == "" {
		return fmt.Errorf("missing node name for client registration")
	}
	if len(args.Node.Attributes) == 0 {
		return fmt.Errorf("missing attributes for client registration")
	}
	pre, err := nodePreSecretID(args.Node)
	if err != nil {
		return err
	}
	if args.Node.SecretID == "" && !pre {
		return fmt.Errorf("missing node secret ID for client registration")
	}
	if args.Node.Status == "" {
		args.Node.Status = structs.NodeStatusInit
	}
	if !structs.ValidNodeStatus(args.Node.Status) {
		return fmt.Errorf("invalid status for node")
	}
	args.Node.StatusUpdatedAt = time.Now().Unix()
	if err := args.Node.ComputeClass(); err != nil {
		return fmt.Errorf("failed to computed node class: %v", err)
	}
	snap, err := n.srv.fsm.State().Snapshot()
	if err != nil {
		return err
	}
	ws := memdb.NewWatchSet()
	originalNode, err := snap.NodeByID(ws, args.Node.ID)
	if err != nil {
		return err
	}
	if !pre && originalNode != nil {
		if args.Node.SecretID != originalNode.SecretID && originalNode.SecretID != "" {
			return fmt.Errorf("node secret ID does not match. Not registering node.")
		}
	}
	_, index, err := n.srv.raftApply(structs.NodeRegisterRequestType, args)
	if err != nil {
		n.srv.logger.Printf("[ERR] nomad.client: Register failed: %v", err)
		return err
	}
	reply.NodeModifyIndex = index
	originalStatus := structs.NodeStatusInit
	if originalNode != nil {
		originalStatus = originalNode.Status
	}
	transitionToReady := transitionedToReady(args.Node.Status, originalStatus)
	if structs.ShouldDrainNode(args.Node.Status) || transitionToReady {
		evalIDs, evalIndex, err := n.createNodeEvals(args.Node.ID, index)
		if err != nil {
			n.srv.logger.Printf("[ERR] nomad.client: eval creation failed: %v", err)
			return err
		}
		reply.EvalIDs = evalIDs
		reply.EvalCreateIndex = evalIndex
	}
	if !args.Node.TerminalStatus() {
		ttl, err := n.srv.resetHeartbeatTimer(args.Node.ID)
		if err != nil {
			n.srv.logger.Printf("[ERR] nomad.client: heartbeat reset failed: %v", err)
			return err
		}
		reply.HeartbeatTTL = ttl
	}
	reply.Index = index
	snap, err = n.srv.fsm.State().Snapshot()
	if err != nil {
		return err
	}
	n.srv.peerLock.RLock()
	defer n.srv.peerLock.RUnlock()
	if err := n.constructNodeServerInfoResponse(snap, reply); err != nil {
		n.srv.logger.Printf("[ERR] nomad.client: failed to populate NodeUpdateResponse: %v", err)
		return err
	}
	return nil
}
func ( n * Node ) Register ( args * structs . NodeRegisterRequest , reply * structs . NodeUpdateResponse ) error { if done , err := n . srv . forward ( " " , args , args , reply ) ; done { return err } defer metrics . MeasureSince ( [ ] string { " " , " " , " " } , time . Now ( ) ) if args . Node == nil { return fmt . Errorf ( " " ) } if args . Node . ID == " " { return fmt . Errorf ( " " ) } if args . Node . Datacenter == " " { return fmt . Errorf ( " " ) } if args . Node . Name == " " { return fmt . Errorf ( " " ) } if len ( args . Node . Attributes ) == 0 { return fmt . Errorf ( " " ) } pre , err := nodePreSecretID ( args . Node ) if err != nil { return err } if args . Node . SecretID == " " && ! pre { return fmt . Errorf ( " " ) } if args . Node . Status == " " { args . Node . Status = structs . NodeStatusInit } if ! structs . ValidNodeStatus ( args . Node . Status ) { return fmt . Errorf ( " " ) } args . Node . StatusUpdatedAt = time . Now ( ) . Unix ( ) if err := args . Node . ComputeClass ( ) ; err != nil { return fmt . Errorf ( " " , err ) } snap , err := n . srv . fsm . State ( ) . Snapshot ( ) if err != nil { return err } ws := memdb . NewWatchSet ( ) originalNode , err := snap . NodeByID ( ws , args . Node . ID ) if err != nil { return err } if ! pre && originalNode != nil { if args . Node . SecretID != originalNode . SecretID && originalNode . SecretID != " " { return fmt . Errorf ( " " ) } } _ , index , err := n . srv . raftApply ( structs . NodeRegisterRequestType , args ) if err != nil { n . srv . logger . Printf ( " " , err ) return err } reply . NodeModifyIndex = index originalStatus := structs . NodeStatusInit if originalNode != nil { originalStatus = originalNode . Status } transitionToReady := transitionedToReady ( args . Node . Status , originalStatus ) if structs . ShouldDrainNode ( args . Node . Status ) || transitionToReady { evalIDs , evalIndex , err := n . createNodeEvals ( args . Node . ID , index ) if err != nil { n . srv . logger . Printf ( " " , err ) return err } reply . EvalIDs = evalIDs reply . EvalCreateIndex = evalIndex } if ! args . Node . TerminalStatus ( ) { ttl , err := n . srv . resetHeartbeatTimer ( args . Node . ID ) if err != nil { n . srv . logger . Printf ( " " , err ) return err } reply . HeartbeatTTL = ttl } reply . Index = index snap , err = n . srv . fsm . State ( ) . Snapshot ( ) if err != nil { return err } n . srv . peerLock . RLock ( ) defer n . srv . peerLock . RUnlock ( ) if err := n . constructNodeServerInfoResponse ( snap , reply ) ; err != nil { n . srv . logger . Printf ( " " , err ) return err } return nil }
Register is used to upsert a client that is available for scheduling
Register is used to upsert a client that is available for scheduling
// Validate the arguments // COMPAT: Remove after 0.6 // Need to check if this node is <0.4.x since SecretID is new in 0.5 // Default the status if none is given // Set the timestamp when the node is registered // Compute the node class // Look for the node so we can detect a state transistion // Check if the SecretID has been tampered with // Commit this update via Raft // Check if we should trigger evaluations // Check if we need to setup a heartbeat // Set the reply index