func (n *Node) UpdateStatus(args *structs.NodeUpdateStatusRequest, reply *structs.NodeUpdateResponse) error {
	if done, err := n.srv.forward("Node.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 status update")
	}
	if !structs.ValidNodeStatus(args.Status) {
		return fmt.Errorf("invalid status for node")
	}

	// Look for the node
	snap, err := n.srv.fsm.State().Snapshot()
	if err != nil {
		return err
	}

	ws := memdb.NewWatchSet()
	node, err := snap.NodeByID(ws, args.NodeID)
	if err != nil {
		return err
	}
	if node == nil {
		return fmt.Errorf("node not found")
	}

	// XXX: Could use the SecretID here but have to update the heartbeat system
	// to track SecretIDs.

	// Update the timestamp of when the node status was updated
	node.StatusUpdatedAt = time.Now().Unix()

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

	// Check if we should trigger evaluations
	transitionToReady := transitionedToReady(args.Status, node.Status)
	if structs.ShouldDrainNode(args.Status) || transitionToReady {
		evalIDs, evalIndex, err := n.createNodeEvals(args.NodeID, 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
	switch args.Status {
	case structs.NodeStatusDown:
		// Determine if there are any Vault accessors on the node
		accessors, err := n.srv.State().VaultAccessorsByNode(ws, args.NodeID)
		if err != nil {
			n.srv.logger.Printf("[ERR] nomad.client: looking up accessors for node %q failed: %v", args.NodeID, err)
			return err
		}

		if l := len(accessors); l != 0 {
			n.srv.logger.Printf("[DEBUG] nomad.client: revoking %d accessors on node %q due to down state", l, args.NodeID)
			if err := n.srv.vault.RevokeTokens(context.Background(), accessors, true); err != nil {
				n.srv.logger.Printf("[ERR] nomad.client: revoking accessors for node %q failed: %v", args.NodeID, err)
				return err
			}
		}
	default:
		ttl, err := n.srv.resetHeartbeatTimer(args.NodeID)
		if err != nil {
			n.srv.logger.Printf("[ERR] nomad.client: heartbeat reset failed: %v", err)
			return err
		}
		reply.HeartbeatTTL = ttl
	}

	// Set the reply index and leader
	reply.Index = index
	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
}
// UpdateStatus is used to update the status of a client node
UpdateStatus is used to update the status of a client node
// UpdateStatus is used to update the status of a client node
func (n *Node) UpdateStatus(args *structs.NodeUpdateStatusRequest, reply *structs.NodeUpdateResponse) error {
	if done, err := n.srv.forward("Node.UpdateStatus", args, args, reply); done {
		return err
	}
	defer metrics.MeasureSince([]string{"nomad", "client", "update_status"}, time.Now())
	if args.NodeID == "" {
		return fmt.Errorf("missing node ID for client status update")
	}
	if !structs.ValidNodeStatus(args.Status) {
		return fmt.Errorf("invalid status for node")
	}
	snap, err := n.srv.fsm.State().Snapshot()
	if err != nil {
		return err
	}
	ws := memdb.NewWatchSet()
	node, err := snap.NodeByID(ws, args.NodeID)
	if err != nil {
		return err
	}
	if node == nil {
		return fmt.Errorf("node not found")
	}
	node.StatusUpdatedAt = time.Now().Unix()
	var index uint64
	if node.Status != args.Status {
		_, index, err = n.srv.raftApply(structs.NodeUpdateStatusRequestType, args)
		if err != nil {
			n.srv.logger.Printf("[ERR] nomad.client: status update failed: %v", err)
			return err
		}
		reply.NodeModifyIndex = index
	}
	transitionToReady := transitionedToReady(args.Status, node.Status)
	if structs.ShouldDrainNode(args.Status) || transitionToReady {
		evalIDs, evalIndex, err := n.createNodeEvals(args.NodeID, index)
		if err != nil {
			n.srv.logger.Printf("[ERR] nomad.client: eval creation failed: %v", err)
			return err
		}
		reply.EvalIDs = evalIDs
		reply.EvalCreateIndex = evalIndex
	}
	switch args.Status {
	case structs.NodeStatusDown:
		accessors, err := n.srv.State().VaultAccessorsByNode(ws, args.NodeID)
		if err != nil {
			n.srv.logger.Printf("[ERR] nomad.client: looking up accessors for node %q failed: %v", args.NodeID, err)
			return err
		}
		if l := len(accessors); l != 0 {
			n.srv.logger.Printf("[DEBUG] nomad.client: revoking %d accessors on node %q due to down state", l, args.NodeID)
			if err := n.srv.vault.RevokeTokens(context.Background(), accessors, true); err != nil {
				n.srv.logger.Printf("[ERR] nomad.client: revoking accessors for node %q failed: %v", args.NodeID, err)
				return err
			}
		}
	default:
		ttl, err := n.srv.resetHeartbeatTimer(args.NodeID)
		if err != nil {
			n.srv.logger.Printf("[ERR] nomad.client: heartbeat reset failed: %v", err)
			return err
		}
		reply.HeartbeatTTL = ttl
	}
	reply.Index = index
	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 ) UpdateStatus ( args * structs . NodeUpdateStatusRequest , reply * structs . NodeUpdateResponse ) error { if done , err := n . srv . forward ( " " , args , args , reply ) ; done { return err } defer metrics . MeasureSince ( [ ] string { " " , " " , " " } , time . Now ( ) ) if args . NodeID == " " { return fmt . Errorf ( " " ) } if ! structs . ValidNodeStatus ( args . Status ) { return fmt . Errorf ( " " ) } snap , err := n . srv . fsm . State ( ) . Snapshot ( ) if err != nil { return err } ws := memdb . NewWatchSet ( ) node , err := snap . NodeByID ( ws , args . NodeID ) if err != nil { return err } if node == nil { return fmt . Errorf ( " " ) } node . StatusUpdatedAt = time . Now ( ) . Unix ( ) var index uint64 if node . Status != args . Status { _ , index , err = n . srv . raftApply ( structs . NodeUpdateStatusRequestType , args ) if err != nil { n . srv . logger . Printf ( " " , err ) return err } reply . NodeModifyIndex = index } transitionToReady := transitionedToReady ( args . Status , node . Status ) if structs . ShouldDrainNode ( args . Status ) || transitionToReady { evalIDs , evalIndex , err := n . createNodeEvals ( args . NodeID , index ) if err != nil { n . srv . logger . Printf ( " " , err ) return err } reply . EvalIDs = evalIDs reply . EvalCreateIndex = evalIndex } switch args . Status { case structs . NodeStatusDown : accessors , err := n . srv . State ( ) . VaultAccessorsByNode ( ws , args . NodeID ) if err != nil { n . srv . logger . Printf ( " " , args . NodeID , err ) return err } if l := len ( accessors ) ; l != 0 { n . srv . logger . Printf ( " " , l , args . NodeID ) if err := n . srv . vault . RevokeTokens ( context . Background ( ) , accessors , true ) ; err != nil { n . srv . logger . Printf ( " " , args . NodeID , err ) return err } } default : ttl , err := n . srv . resetHeartbeatTimer ( args . NodeID ) if err != nil { n . srv . logger . Printf ( " " , err ) return err } reply . HeartbeatTTL = ttl } reply . Index = index 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 }
UpdateStatus is used to update the status of a client node
UpdateStatus is used to update the status of a client node
// Verify the arguments // Look for the node // XXX: Could use the SecretID here but have to update the heartbeat system // to track SecretIDs. // Update the timestamp of when the node status was updated // Commit this update via Raft // Check if we should trigger evaluations // Check if we need to setup a heartbeat // Determine if there are any Vault accessors on the node // Set the reply index and leader