mirror of
https://github.com/kemko/nomad.git
synced 2026-01-06 10:25:42 +03:00
Allow per_alloc to be used with host volumes (#15780)
Disallowing per_alloc for host volumes in some cases makes life of a nomad user much harder. When we rely on the NOMAD_ALLOC_INDEX for any configuration that needs to be re-used across restarts we need to make sure allocation placement is consistent. With CSI volumes we can use the `per_alloc` feature but for some reason this is explicitly disabled for host volumes. Ensure host volumes understand the concept of per_alloc
This commit is contained in:
@@ -208,6 +208,8 @@ func (tr *TaskRunner) prestart() error {
|
||||
joinedCtx, joinedCancel := joincontext.Join(tr.killCtx, tr.shutdownCtx)
|
||||
defer joinedCancel()
|
||||
|
||||
alloc := tr.Alloc()
|
||||
|
||||
for _, hook := range tr.runnerHooks {
|
||||
pre, ok := hook.(interfaces.TaskPrestartHook)
|
||||
if !ok {
|
||||
@@ -218,6 +220,7 @@ func (tr *TaskRunner) prestart() error {
|
||||
|
||||
// Build the request
|
||||
req := interfaces.TaskPrestartRequest{
|
||||
Alloc: alloc,
|
||||
Task: tr.Task(),
|
||||
TaskDir: tr.taskDir,
|
||||
TaskEnv: tr.envBuilder.Build(),
|
||||
|
||||
@@ -32,7 +32,7 @@ func (*volumeHook) Name() string {
|
||||
return "volumes"
|
||||
}
|
||||
|
||||
func validateHostVolumes(requestedByAlias map[string]*structs.VolumeRequest, clientVolumesByName map[string]*structs.ClientHostVolumeConfig) error {
|
||||
func validateHostVolumes(requestedByAlias map[string]*structs.VolumeRequest, clientVolumesByName map[string]*structs.ClientHostVolumeConfig, allocName string) error {
|
||||
var result error
|
||||
|
||||
for _, req := range requestedByAlias {
|
||||
@@ -42,9 +42,14 @@ func validateHostVolumes(requestedByAlias map[string]*structs.VolumeRequest, cli
|
||||
continue
|
||||
}
|
||||
|
||||
_, ok := clientVolumesByName[req.Source]
|
||||
source := req.Source
|
||||
if req.PerAlloc {
|
||||
source = source + structs.AllocSuffix(allocName)
|
||||
}
|
||||
|
||||
_, ok := clientVolumesByName[source]
|
||||
if !ok {
|
||||
result = multierror.Append(result, fmt.Errorf("missing %s", req.Source))
|
||||
result = multierror.Append(result, fmt.Errorf("missing %s", source))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +59,7 @@ func validateHostVolumes(requestedByAlias map[string]*structs.VolumeRequest, cli
|
||||
// hostVolumeMountConfigurations takes the users requested volume mounts,
|
||||
// volumes, and the client host volume configuration and converts them into a
|
||||
// format that can be used by drivers.
|
||||
func (h *volumeHook) hostVolumeMountConfigurations(taskMounts []*structs.VolumeMount, taskVolumesByAlias map[string]*structs.VolumeRequest, clientVolumesByName map[string]*structs.ClientHostVolumeConfig) ([]*drivers.MountConfig, error) {
|
||||
func (h *volumeHook) hostVolumeMountConfigurations(taskMounts []*structs.VolumeMount, taskVolumesByAlias map[string]*structs.VolumeRequest, clientVolumesByName map[string]*structs.ClientHostVolumeConfig, allocName string) ([]*drivers.MountConfig, error) {
|
||||
var mounts []*drivers.MountConfig
|
||||
for _, m := range taskMounts {
|
||||
req, ok := taskVolumesByAlias[m.Volume]
|
||||
@@ -71,11 +76,15 @@ func (h *volumeHook) hostVolumeMountConfigurations(taskMounts []*structs.VolumeM
|
||||
continue
|
||||
}
|
||||
|
||||
hostVolume, ok := clientVolumesByName[req.Source]
|
||||
source := req.Source
|
||||
if req.PerAlloc {
|
||||
source = source + structs.AllocSuffix(allocName)
|
||||
}
|
||||
hostVolume, ok := clientVolumesByName[source]
|
||||
if !ok {
|
||||
// Should never happen, but unless the client volumes were mutated during
|
||||
// the execution of this hook.
|
||||
return nil, fmt.Errorf("No host volume named: %s", req.Source)
|
||||
return nil, fmt.Errorf("no host volume named: %s", source)
|
||||
}
|
||||
|
||||
mcfg := &drivers.MountConfig{
|
||||
@@ -110,12 +119,12 @@ func (h *volumeHook) prepareHostVolumes(req *interfaces.TaskPrestartRequest, vol
|
||||
|
||||
// Always validate volumes to ensure that we do not allow volumes to be used
|
||||
// if a host is restarted and loses the host volume configuration.
|
||||
if err := validateHostVolumes(volumes, hostVolumes); err != nil {
|
||||
if err := validateHostVolumes(volumes, hostVolumes, req.Alloc.Name); err != nil {
|
||||
h.logger.Error("Requested Host Volume does not exist", "existing", hostVolumes, "requested", volumes)
|
||||
return nil, fmt.Errorf("host volume validation error: %v", err)
|
||||
}
|
||||
|
||||
hostVolumeMounts, err := h.hostVolumeMountConfigurations(req.Task.VolumeMounts, volumes, hostVolumes)
|
||||
hostVolumeMounts, err := h.hostVolumeMountConfigurations(req.Task.VolumeMounts, volumes, hostVolumes, req.Alloc.Name)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to generate host volume mounts", "error", err)
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user