Repository: hashicorp/nomad
File: scheduler/feasible/feasible.go (Go)

Code before:
	storedClaims, _ := h.ctx.State().TaskGroupHostVolumeClaimsByFields(
		nil, state.TgvcSearchableFields{
			Namespace: ns,
			JobID:     jobID,
		})

	// if we have previous claims for sticky volumes, we want to make sure these
	// are getting picked first. But we don't want to count claims that have
	// been met by proposed allocs already
NEXT:
	for raw := storedClaims.Next(); raw != nil; raw = storedClaims.Next() {
		claim := raw.(*structs.TaskGroupHostVolumeClaim)

		alloc, err := h.ctx.State().AllocByID(nil, claim.AllocID)
		if err != nil || alloc == nil {
			continue
		}
		vol, err := h.ctx.State().HostVolumeByID(nil, ns, claim.VolumeID, false)
		if err != nil || vol == nil {
			continue
		}

		// the proposed alloc might be the exact same alloc or it could be an
		// alloc from earlier in this eval that we've successfully placed
		proposed, err := h.ctx.ProposedAllocs(alloc.NodeID)
		if err == nil {
			for _, proposedAlloc := range proposed {
				if proposedAlloc.ID == claim.AllocID ||
					(proposedAlloc.TaskGroup == taskGroupName &&
						vol.NodeID == alloc.NodeID &&
						vol.ID == claim.VolumeID) {
					continue NEXT
				}
			}
			h.unmetClaims = append(h.unmetClaims, claim)
		}
	}

	for _, req := range volumes {
		if req.Type != structs.VolumeTypeHost {
			continue // filter CSI volumes
		}

		if req.PerAlloc {
			// provide a unique volume source per allocation
			copied := req.Copy()
			copied.Source = copied.Source + structs.AllocSuffix(allocName)
			h.volumeReqs = append(h.volumeReqs, copied)
		} else {
			h.volumeReqs = append(h.volumeReqs, req)
		}

Review comment (bug):
Is the error useful to an operator here and could be logged? It looks like it can only be non-nil if we fail to perform the state lookup, so I guess it's not too useful.

Another thought; if we do get an error from state, is it worth considering the claim unmet?

Code after:
	storedClaims, _ := h.ctx.State().TaskGroupHostVolumeClaimsByFields(
		nil, state.TgvcSearchableFields{
			Namespace: ns,
			JobID:     jobID,
		})

	// if we have previous claims for sticky volumes, we want to make sure these
	// are getting picked first. But we don't want to count claims that have
	// been met by proposed allocs already
NEXT:
	for raw := storedClaims.Next(); raw != nil; raw = storedClaims.Next() {
		claim := raw.(*structs.TaskGroupHostVolumeClaim)

		alloc, err := h.ctx.State().AllocByID(nil, claim.AllocID)
		if err != nil || alloc == nil {
			continue
		}
		vol, err := h.ctx.State().HostVolumeByID(nil, ns, claim.VolumeID, false)
		if err != nil || vol == nil {
			continue
		}

		// the proposed alloc might be the exact same alloc or it could be an
		// alloc from earlier in this eval that we've successfully placed
		proposed, err := h.ctx.ProposedAllocs(alloc.NodeID)
		if err == nil {
			for _, proposedAlloc := range proposed {
				if proposedAlloc.ID == claim.AllocID ||
					(proposedAlloc.TaskGroup == taskGroupName &&
						vol.NodeID == alloc.NodeID &&
						vol.ID == claim.VolumeID) {
					continue NEXT
				}
			}
			h.unmetClaims = append(h.unmetClaims, claim)
		} else {
			h.unmetClaims = append(h.unmetClaims, claim)
		}
	}

	for _, req := range volumes {
		if req.Type != structs.VolumeTypeHost {
			continue // filter CSI volumes
		}

		if req.PerAlloc {
			// provide a unique volume source per allocation
			copied := req.Copy()
			copied.Source = copied.Source + structs.AllocSuffix(allocName)
			h.volumeReqs = append(h.volumeReqs, copied)
		} else {