From efa9cc3abcb71d68d0ec14a791c80728b2a594ff Mon Sep 17 00:00:00 2001
From: Morris Jette <jette@schedmd.com>
Date: Thu, 4 Sep 2014 15:48:14 -0700
Subject: [PATCH] added ability to update jobs by name

 Added ability for "scontrol update" to references jobs by JobName.
bug 725
---
 NEWS                      |  1 +
 RELEASE_NOTES             |  1 +
 doc/man/man1/scontrol.1   |  5 ++--
 src/api/job_info.c        |  2 +-
 src/scontrol/scontrol.c   |  9 +++----
 src/scontrol/update_job.c | 49 ++++++++++++++++++++++++++++++++++++++-
 6 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/NEWS b/NEWS
index 165e142178a..164269f61f9 100644
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,7 @@ documents those changes that are of interest to users and administrators.
     updated without restarting the slurmctld daemon.
  -- Allow users to specify --resv_ports to have value 0.
  -- Cray MPMD (Multiple-Program Multiple-Data) support completed.
+ -- Added ability for "scontrol update" to references jobs by JobName.
 
 * Changes in Slurm 14.11.0pre4
 ==============================
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index e769c107078..d810d668cf9 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -138,6 +138,7 @@ COMMAND CHANGES (see man pages for details)
  -- Modify scontrol job operations to accept comma delimited list of job IDs.
     Applies to job update, hold, release, suspend, resume, requeue, and
     requeuehold operations.
+ -- Added ability for "scontrol update" to references jobs by JobName.
 
 OTHER CHANGES
 =============
diff --git a/doc/man/man1/scontrol.1 b/doc/man/man1/scontrol.1
index 08cd190cac6..1331f6b2d45 100644
--- a/doc/man/man1/scontrol.1
+++ b/doc/man/man1/scontrol.1
@@ -560,7 +560,7 @@ Examples of use include "Gres=gpus:2*cpu,disk=40G" and "Gres=help".
 \fIJobId\fP=<job_list>
 Identify the job(s) to be updated.
 The job_list may be a comma separated list of job IDs.
-This specification is required.
+Either \fIJobId\fP or \fIJobName\fP is required.
 .TP
 \fILicenses\fP=<name>
 Specification of licenses (or other resources available on all nodes
@@ -584,8 +584,9 @@ Only the Slurm administrator or root can change this parameter.
 Set the job's minimum temporary disk space required per node to the specified value.
 Only the Slurm administrator or root can change this parameter.
 .TP
-\fIName\fP=<name>
+\fIJobName\fP=<name>
 Set the job's name to the specified value.
+Either \fIJobId\fP or \fIJobName\fP is required.
 .TP
 \fINice\fP[=delta]
 Adjust job's priority by the specified value. Default value is 100.
diff --git a/src/api/job_info.c b/src/api/job_info.c
index fca9ec2b28d..a23e3d206be 100644
--- a/src/api/job_info.c
+++ b/src/api/job_info.c
@@ -380,7 +380,7 @@ slurm_sprint_job_info ( job_info_t * job_ptr, int one_liner )
 		}
 		xstrcat(out, tmp_line);
 	}
-	snprintf(tmp_line, sizeof(tmp_line), "Name=%s", job_ptr->name);
+	snprintf(tmp_line, sizeof(tmp_line), "JobName=%s", job_ptr->name);
 	xstrcat(out, tmp_line);
 	if (one_liner)
 		xstrcat(out, " ");
diff --git a/src/scontrol/scontrol.c b/src/scontrol/scontrol.c
index 016d385a1f6..a852d7960e7 100644
--- a/src/scontrol/scontrol.c
+++ b/src/scontrol/scontrol.c
@@ -1491,14 +1491,15 @@ _update_it (int argc, char *argv[])
 		} else if (!strncasecmp(tag, "PartitionName",
 					MAX(tag_len, 3))) {
 			part_tag = 1;
-		} else if (!strncasecmp(tag, "JobId", MAX(tag_len, 3))) {
+		} else if (!strncasecmp(tag, "JobId", MAX(tag_len, 3)) ||
+			   !strncasecmp(tag, "JobNAME", MAX(tag_len, 3))) {
 			job_tag = 1;
 		} else if (!strncasecmp(tag, "StepId", MAX(tag_len, 4))) {
 			step_tag = 1;
 		} else if (!strncasecmp(tag, "BlockName", MAX(tag_len, 3))) {
 			block_tag = 1;
-		} else if (!strncasecmp(tag, "SubBPName", MAX(tag_len, 3))
-			   || !strncasecmp(tag, "SubMPName", MAX(tag_len, 3))) {
+		} else if (!strncasecmp(tag, "SubBPName", MAX(tag_len, 3)) ||
+			   !strncasecmp(tag, "SubMPName", MAX(tag_len, 3))) {
 			sub_tag = 1;
 		} else if (!strncasecmp(tag, "FrontendName",
 					MAX(tag_len, 2))) {
@@ -1508,7 +1509,7 @@ _update_it (int argc, char *argv[])
 			res_tag = 1;
 		} else if (!strncasecmp(tag, "SlurmctldDebug",
 					MAX(tag_len, 2))) {
-			debug_tag= 1;
+			debug_tag = 1;
 		}
 	}
 
diff --git a/src/scontrol/update_job.c b/src/scontrol/update_job.c
index 3fb59da63d3..d4c8b654c4d 100644
--- a/src/scontrol/update_job.c
+++ b/src/scontrol/update_job.c
@@ -52,6 +52,7 @@ typedef struct job_ids {
 static uint32_t	_get_job_time(const char *job_id_str);
 static bool	_is_job_id(char *job_str);
 static bool	_is_single_job(char *job_id_str);
+static char *	_job_name2id(char *job_name);
 static char *	_next_job_id(void);
 static int	_parse_checkpoint_args(int argc, char **argv,
 				       uint16_t *max_wait, char **image_dir);
@@ -964,7 +965,8 @@ scontrol_update_job (int argc, char *argv[])
 			job_msg.reservation = val;
 			update_cnt++;
 		}
-		else if (strncasecmp(tag, "Name", MAX(taglen, 2)) == 0) {
+		else if (!strncasecmp(tag, "Name", MAX(taglen, 2)) ||
+			 !strncasecmp(tag, "JobName", MAX(taglen, 4))) {
 			job_msg.name = val;
 			update_cnt++;
 		}
@@ -1161,6 +1163,11 @@ scontrol_update_job (int argc, char *argv[])
 		return 0;
 	}
 
+	if (!job_msg.job_id_str && job_msg.name) {
+		/* Translate name to job ID string */
+		job_msg.job_id_str = _job_name2id(job_msg.name);
+	}
+
 	if (!job_msg.job_id_str) {
 		error("No job ID specified");
 		exit_code = 1;
@@ -1480,3 +1487,43 @@ static bool _is_single_job(char *job_id_str)
 
 	return is_single;
 }
+
+/* Translate a job name to relevant job IDs
+ * NOTE: xfree the return value to avoid memory leak */
+static char * _job_name2id(char *job_name)
+{
+	int i, rc;
+	job_info_msg_t *resp;
+	slurm_job_info_t *job_ptr;
+	char *job_id_str = NULL, *sep = "";
+
+	xassert(job_name);
+
+	rc = scontrol_load_job(&resp, 0);
+	if (rc == SLURM_SUCCESS) {
+		if (resp->record_count == 0) {
+			error("JobName %s not found", job_name);
+			slurm_free_job_info_msg(resp);
+			return job_id_str;
+		}
+		for (i = 0, job_ptr = resp->job_array; i < resp->record_count;
+		     i++, job_ptr++) {
+			if (!job_ptr->name || strcmp(job_name, job_ptr->name))
+				continue;
+			if (job_ptr->array_task_id != NO_VAL) {
+				xstrfmtcat(job_id_str, "%s%u_%u", sep,
+					   job_ptr->array_job_id,
+					   job_ptr->array_task_id);
+			} else {
+				xstrfmtcat(job_id_str, "%s%u", sep,
+					   job_ptr->job_id);
+			}
+			sep = ",";
+		}
+	} else {
+		error("Could not load state information for JobName %s: %m",
+		      job_name);
+	}
+
+	return job_id_str;
+}
-- 
GitLab