fix(apiserver): propagate submit user as job execuser (bug-1780)
modelJobToSubmit() never set job_startinfo_t.execuser when converting a submitted job to the C struct sent to the controller/worker, so every job ran as the worker's 'nobody' default and failed to exec (exit 126). Default execuser to the submitting user via a new resolveExecUser() pure helper, and free the newly allocated C string. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hb6Edtj4KbS8CrgEWYdA2E
This commit is contained in:
parent
37ea6dfd9f
commit
5ab344e1ae
4 changed files with 61 additions and 0 deletions
|
|
@ -273,6 +273,9 @@ func cClusterConfToClusterInfo(conf *C.cluster_config_t) *models.ClusterInfo {
|
|||
func modelJobToSubmit(job *models.JobInfo) (*C.xce_job_submit_t, *C.job_submit_data_t, *C.job_startinfo_t) {
|
||||
si := (*C.job_startinfo_t)(C.calloc(1, C.sizeof_job_startinfo_t))
|
||||
si.cmdline = C.CString(job.Command)
|
||||
if execUser := resolveExecUser(job.ExecUser, job.SubmitUser); execUser != "" {
|
||||
si.execuser = C.CString(execUser)
|
||||
}
|
||||
if job.LaunchType != "" {
|
||||
si.launch_type = C.CString(job.LaunchType)
|
||||
}
|
||||
|
|
@ -324,6 +327,7 @@ func modelJobToSubmit(job *models.JobInfo) (*C.xce_job_submit_t, *C.job_submit_d
|
|||
func freeJobSubmit(js *C.xce_job_submit_t, sd *C.job_submit_data_t, si *C.job_startinfo_t) {
|
||||
if si != nil {
|
||||
C.free(unsafe.Pointer(si.cmdline))
|
||||
C.free(unsafe.Pointer(si.execuser))
|
||||
C.free(unsafe.Pointer(si.launch_type))
|
||||
C.free(unsafe.Pointer(si.job_pre_exec))
|
||||
C.free(unsafe.Pointer(si.job_post_exec))
|
||||
|
|
|
|||
|
|
@ -104,6 +104,18 @@ func WorkerDefaultOutputPath(uniqueJobID int64, taskIdx int) string {
|
|||
return fmt.Sprintf("/tmp/job_%s_task%d.out", FormatJobID(uniqueJobID), taskIdx)
|
||||
}
|
||||
|
||||
// resolveExecUser returns the effective exec user for a job submission: the
|
||||
// caller-specified ExecUser if present, otherwise the submitting user
|
||||
// (bug-1780: an unset execuser in the startjob request reaches xcecd as
|
||||
// empty, which controller_connector.c defaults to the literal Linux user
|
||||
// 'nobody' -- a user with no home/shell that then fails to exec the job).
|
||||
func resolveExecUser(execUser, submitUser string) string {
|
||||
if execUser != "" {
|
||||
return execUser
|
||||
}
|
||||
return submitUser
|
||||
}
|
||||
|
||||
// rawStartInfo mirrors the C job_startinfo_t fields used by the Go model.
|
||||
type rawStartInfo struct {
|
||||
cmdline string
|
||||
|
|
|
|||
|
|
@ -6,6 +6,28 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
// bug-1780: modelJobToSubmit must default a job's exec user to its
|
||||
// submitting user when the caller didn't specify one explicitly, so
|
||||
// xcecd never falls back to running the job as the literal Linux user
|
||||
// 'nobody' (which has no home/shell and fails to exec the command).
|
||||
func TestResolveExecUser_DefaultsToSubmitUserWhenEmpty(t *testing.T) {
|
||||
if got, want := resolveExecUser("", "alice"), "alice"; got != want {
|
||||
t.Errorf("resolveExecUser(\"\", %q): got %q, want %q", "alice", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveExecUser_PrefersExplicitExecUser(t *testing.T) {
|
||||
if got, want := resolveExecUser("bob", "alice"), "bob"; got != want {
|
||||
t.Errorf("resolveExecUser(%q, %q): got %q, want %q", "bob", "alice", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveExecUser_EmptyWhenBothEmpty(t *testing.T) {
|
||||
if got, want := resolveExecUser("", ""), ""; got != want {
|
||||
t.Errorf("resolveExecUser(\"\", \"\"): got %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRawJobToModel_BasicFields(t *testing.T) {
|
||||
r := rawJobData{
|
||||
jobID: 123,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue