From b5bba34c526b08a5d3839dda2104669a736a6ace Mon Sep 17 00:00:00 2001 From: Don Lipari <lipari1@llnl.gov> Date: Tue, 26 Oct 2010 00:10:22 +0000 Subject: [PATCH] -- Add the functionality to modify the Derived Exit Code/String fields of a database's job record. --- slurm/slurmdb.h | 10 +- src/common/slurm_accounting_storage.c | 14 + src/common/slurm_accounting_storage.h | 10 + src/common/slurmdb_defs.c | 12 + src/common/slurmdb_defs.h | 1 + src/common/slurmdb_pack.c | 38 +++ src/common/slurmdb_pack.h | 4 + src/common/slurmdbd_defs.c | 22 ++ src/common/slurmdbd_defs.h | 3 +- .../filetxt/accounting_storage_filetxt.c | 7 + .../mysql/accounting_storage_mysql.c | 12 +- .../accounting_storage/mysql/as_mysql_job.c | 104 ++++++++ .../accounting_storage/mysql/as_mysql_job.h | 4 + .../none/accounting_storage_none.c | 7 + .../pgsql/accounting_storage_pgsql.c | 7 + .../pgsql/accounting_storage_pgsql.h | 3 + .../slurmdbd/accounting_storage_slurmdbd.c | 43 +++ src/sacctmgr/Makefile.am | 1 + src/sacctmgr/job_functions.c | 245 ++++++++++++++++++ src/sacctmgr/sacctmgr.c | 2 + src/sacctmgr/sacctmgr.h | 1 + src/slurmdbd/proc_req.c | 102 +++++++- 22 files changed, 635 insertions(+), 17 deletions(-) create mode 100644 src/sacctmgr/job_functions.c diff --git a/slurm/slurmdb.h b/slurm/slurmdb.h index 0ee28b23bf8..817f0145cab 100644 --- a/slurm/slurmdb.h +++ b/slurm/slurmdb.h @@ -502,6 +502,12 @@ typedef struct { /* slurmdb_job_cond_t is defined above alphabetical */ + +typedef struct { + char *cluster; + uint32_t job_id; +} slurmdb_job_modify_cond_t; + typedef struct { uint32_t alloc_cpus; uint32_t alloc_nodes; @@ -509,12 +515,12 @@ typedef struct { uint32_t associd; char *blockid; char *cluster; - int32_t derived_ec; + uint32_t derived_ec; char *derived_es; uint32_t elapsed; time_t eligible; time_t end; - int32_t exitcode; + uint32_t exitcode; void *first_step_ptr; uint32_t gid; uint32_t jobid; diff --git a/src/common/slurm_accounting_storage.c b/src/common/slurm_accounting_storage.c index 8a7cf4f7d65..37cc143ba4d 100644 --- a/src/common/slurm_accounting_storage.c +++ b/src/common/slurm_accounting_storage.c @@ -100,6 +100,9 @@ typedef struct slurm_acct_storage_ops { List (*modify_associations)(void *db_conn, uint32_t uid, slurmdb_association_cond_t *assoc_cond, slurmdb_association_rec_t *assoc); + List (*modify_job) (void *db_conn, uint32_t uid, + slurmdb_job_modify_cond_t *job_cond, + slurmdb_job_rec_t *job); List (*modify_qos) (void *db_conn, uint32_t uid, slurmdb_qos_cond_t *qos_cond, slurmdb_qos_rec_t *qos); @@ -231,6 +234,7 @@ static slurm_acct_storage_ops_t * _acct_storage_get_ops( "acct_storage_p_modify_accts", "acct_storage_p_modify_clusters", "acct_storage_p_modify_associations", + "acct_storage_p_modify_job", "acct_storage_p_modify_qos", "acct_storage_p_modify_wckeys", "acct_storage_p_modify_reservation", @@ -564,6 +568,16 @@ extern List acct_storage_g_modify_associations( (db_conn, uid, assoc_cond, assoc); } +extern List acct_storage_g_modify_job(void *db_conn, uint32_t uid, + slurmdb_job_modify_cond_t *job_cond, + slurmdb_job_rec_t *job) +{ + if (slurm_acct_storage_init(NULL) < 0) + return NULL; + return (*(g_acct_storage_context->ops.modify_job)) + (db_conn, uid, job_cond, job); +} + extern List acct_storage_g_modify_qos(void *db_conn, uint32_t uid, slurmdb_qos_cond_t *qos_cond, slurmdb_qos_rec_t *qos) diff --git a/src/common/slurm_accounting_storage.h b/src/common/slurm_accounting_storage.h index ca4613fe3fc..ca573b4e1a7 100644 --- a/src/common/slurm_accounting_storage.h +++ b/src/common/slurm_accounting_storage.h @@ -190,6 +190,16 @@ extern List acct_storage_g_modify_associations( slurmdb_association_cond_t *assoc_cond, slurmdb_association_rec_t *assoc); +/* + * modify existing job in the accounting system + * IN: slurmdb_job_modify_cond_t *job_cond + * IN: slurmdb_job_rec_t *job + * RET: List containing (char *'s) else NULL on error + */ +extern List acct_storage_g_modify_job(void *db_conn, uint32_t uid, + slurmdb_job_modify_cond_t *job_cond, + slurmdb_job_rec_t *job); + /* * modify existing qos in the accounting system * IN: slurmdb_qos_cond_t *qos_cond diff --git a/src/common/slurmdb_defs.c b/src/common/slurmdb_defs.c index e17c2ecc930..c3b48051095 100644 --- a/src/common/slurmdb_defs.c +++ b/src/common/slurmdb_defs.c @@ -288,6 +288,7 @@ extern slurmdb_job_rec_t *slurmdb_create_job_rec() { slurmdb_job_rec_t *job = xmalloc(sizeof(slurmdb_job_rec_t)); memset(&job->stats, 0, sizeof(slurmdb_stats_t)); + job->derived_ec = NO_VAL; job->stats.cpu_min = NO_VAL; job->state = JOB_PENDING; job->steps = list_create(slurmdb_destroy_step_rec); @@ -709,6 +710,17 @@ extern void slurmdb_destroy_job_cond(void *object) } } +extern void slurmdb_destroy_job_modify_cond(void *object) +{ + slurmdb_job_modify_cond_t *job_cond = + (slurmdb_job_modify_cond_t *)object; + + if(job_cond) { + xfree(job_cond->cluster); + xfree(job_cond); + } +} + extern void slurmdb_destroy_qos_cond(void *object) { slurmdb_qos_cond_t *slurmdb_qos = (slurmdb_qos_cond_t *)object; diff --git a/src/common/slurmdb_defs.h b/src/common/slurmdb_defs.h index 901db7d5d37..5c8f627a630 100644 --- a/src/common/slurmdb_defs.h +++ b/src/common/slurmdb_defs.h @@ -81,6 +81,7 @@ extern void slurmdb_destroy_cluster_cond(void *object); extern void slurmdb_destroy_association_cond(void *object); extern void slurmdb_destroy_event_cond(void *object); extern void slurmdb_destroy_job_cond(void *object); +extern void slurmdb_destroy_job_modify_cond(void *object); extern void slurmdb_destroy_qos_cond(void *object); extern void slurmdb_destroy_reservation_cond(void *object); extern void slurmdb_destroy_txn_cond(void *object); diff --git a/src/common/slurmdb_pack.c b/src/common/slurmdb_pack.c index 71ba9622f6c..68b9aa6a90d 100644 --- a/src/common/slurmdb_pack.c +++ b/src/common/slurmdb_pack.c @@ -4369,6 +4369,44 @@ unpack_error: return SLURM_ERROR; } +extern void slurmdb_pack_job_modify_cond(void *in, uint16_t rpc_version, + Buf buffer) +{ + slurmdb_job_modify_cond_t *cond = (slurmdb_job_modify_cond_t *)in; + + if(rpc_version >= 8) { + if(!cond) { + packnull(buffer); + pack32(NO_VAL, buffer); + return; + } + packstr(cond->cluster, buffer); + pack32(cond->job_id, buffer); + } +} + +extern int slurmdb_unpack_job_modify_cond(void **object, uint16_t rpc_version, + Buf buffer) +{ + uint32_t uint32_tmp; + slurmdb_job_modify_cond_t *object_ptr = xmalloc(sizeof( + slurmdb_job_modify_cond_t)); + + *object = object_ptr; + + if(rpc_version >= 8) { + safe_unpackstr_xmalloc(&object_ptr->cluster, &uint32_tmp, + buffer); + safe_unpack32(&object_ptr->job_id, buffer); + } + return SLURM_SUCCESS; + +unpack_error: + slurmdb_destroy_job_modify_cond(object_ptr); + *object = NULL; + return SLURM_ERROR; +} + extern void slurmdb_pack_job_rec(void *object, uint16_t rpc_version, Buf buffer) { slurmdb_job_rec_t *job = (slurmdb_job_rec_t *)object; diff --git a/src/common/slurmdb_pack.h b/src/common/slurmdb_pack.h index c39f6c6c3c4..7b4e6d1f67f 100644 --- a/src/common/slurmdb_pack.h +++ b/src/common/slurmdb_pack.h @@ -128,6 +128,10 @@ extern void slurmdb_pack_job_cond(void *in, uint16_t rpc_version, Buf buffer); extern int slurmdb_unpack_job_cond(void **object, uint16_t rpc_version, Buf buffer); +extern void slurmdb_pack_job_modify_cond(void *in, + uint16_t rpc_version, Buf buffer); +extern int slurmdb_unpack_job_modify_cond(void **object, uint16_t rpc_version, + Buf buffer); extern void slurmdb_pack_job_rec(void *object, uint16_t rpc_version, Buf buffer); extern int slurmdb_unpack_job_rec(void **job, uint16_t rpc_version, Buf buffer); diff --git a/src/common/slurmdbd_defs.c b/src/common/slurmdbd_defs.c index 5db3246c339..45ed69540d7 100644 --- a/src/common/slurmdbd_defs.c +++ b/src/common/slurmdbd_defs.c @@ -572,6 +572,7 @@ extern Buf pack_slurmdbd_msg(slurmdbd_msg_t *req, uint16_t rpc_version) case DBD_MODIFY_ACCOUNTS: case DBD_MODIFY_ASSOCS: case DBD_MODIFY_CLUSTERS: + case DBD_MODIFY_JOB: case DBD_MODIFY_QOS: case DBD_MODIFY_USERS: slurmdbd_pack_modify_msg( @@ -747,6 +748,7 @@ extern int unpack_slurmdbd_msg(slurmdbd_msg_t *resp, case DBD_MODIFY_ACCOUNTS: case DBD_MODIFY_ASSOCS: case DBD_MODIFY_CLUSTERS: + case DBD_MODIFY_JOB: case DBD_MODIFY_QOS: case DBD_MODIFY_USERS: rc = slurmdbd_unpack_modify_msg( @@ -881,6 +883,8 @@ extern slurmdbd_msg_type_t str_2_slurmdbd_msg_type(char *msg_type) return DBD_MODIFY_ASSOCS; } else if(!strcasecmp(msg_type, "Modify Clusters")) { return DBD_MODIFY_CLUSTERS; + } else if(!strcasecmp(msg_type, "Modify Job")) { + return DBD_MODIFY_JOB; } else if(!strcasecmp(msg_type, "Modify QOS")) { return DBD_MODIFY_QOS; } else if(!strcasecmp(msg_type, "Modify Users")) { @@ -1179,6 +1183,12 @@ extern char *slurmdbd_msg_type_2_str(slurmdbd_msg_type_t msg_type, int get_enum) } else return "Modify Clusters"; break; + case DBD_MODIFY_JOB: + if(get_enum) { + return "DBD_MODIFY_JOB"; + } else + return "Modify Job"; + break; case DBD_MODIFY_QOS: if(get_enum) { return "DBD_MODIFY_QOS"; @@ -2477,6 +2487,10 @@ inline void slurmdbd_free_modify_msg(dbd_modify_msg_t *msg, destroy_cond = slurmdb_destroy_cluster_cond; destroy_rec = slurmdb_destroy_cluster_rec; break; + case DBD_MODIFY_JOB: + destroy_cond = slurmdb_destroy_job_modify_cond; + destroy_rec = slurmdb_destroy_job_rec; + break; case DBD_MODIFY_QOS: destroy_cond = slurmdb_destroy_qos_cond; destroy_rec = slurmdb_destroy_qos_rec; @@ -3535,6 +3549,10 @@ inline void slurmdbd_pack_modify_msg(dbd_modify_msg_t *msg, my_cond = slurmdb_pack_cluster_cond; my_rec = slurmdb_pack_cluster_rec; break; + case DBD_MODIFY_JOB: + my_cond = slurmdb_pack_job_modify_cond; + my_rec = slurmdb_pack_job_rec; + break; case DBD_MODIFY_QOS: my_cond = slurmdb_pack_qos_cond; my_rec = slurmdb_pack_qos_rec; @@ -3576,6 +3594,10 @@ inline int slurmdbd_unpack_modify_msg(dbd_modify_msg_t **msg, my_cond = slurmdb_unpack_cluster_cond; my_rec = slurmdb_unpack_cluster_rec; break; + case DBD_MODIFY_JOB: + my_cond = slurmdb_unpack_job_modify_cond; + my_rec = slurmdb_unpack_job_rec; + break; case DBD_MODIFY_QOS: my_cond = slurmdb_unpack_qos_cond; my_rec = slurmdb_unpack_qos_rec; diff --git a/src/common/slurmdbd_defs.h b/src/common/slurmdbd_defs.h index a0ef4a47a4e..d6d910be963 100644 --- a/src/common/slurmdbd_defs.h +++ b/src/common/slurmdbd_defs.h @@ -164,7 +164,8 @@ typedef enum { DBD_SEND_MULT_JOB_START,/* Send multiple job starts */ DBD_GOT_MULT_JOB_START, /* Get response to DBD_SEND_MULT_JOB_START */ DBD_SEND_MULT_MSG, /* Send multiple message */ - DBD_GOT_MULT_MSG /* Get response to DBD_SEND_MULT_MSG */ + DBD_GOT_MULT_MSG, /* Get response to DBD_SEND_MULT_MSG */ + DBD_MODIFY_JOB /* Modify existing Job(s) */ } slurmdbd_msg_type_t; /*****************************************************************************\ diff --git a/src/plugins/accounting_storage/filetxt/accounting_storage_filetxt.c b/src/plugins/accounting_storage/filetxt/accounting_storage_filetxt.c index 6d271fa2d01..65d95c93d05 100644 --- a/src/plugins/accounting_storage/filetxt/accounting_storage_filetxt.c +++ b/src/plugins/accounting_storage/filetxt/accounting_storage_filetxt.c @@ -335,6 +335,13 @@ extern List acct_storage_p_modify_associations(void *db_conn, uint32_t uid, return SLURM_SUCCESS; } +extern List acct_storage_p_modify_job(void *db_conn, uint32_t uid, + slurmdb_job_modify_cond_t *job_cond, + slurmdb_job_rec_t *job) +{ + return SLURM_SUCCESS; +} + extern List acct_storage_p_modify_qos(void *db_conn, uint32_t uid, slurmdb_qos_cond_t *qos_cond, slurmdb_qos_rec_t *qos) diff --git a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c index 062c667304a..8385e016290 100644 --- a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c +++ b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c @@ -905,13 +905,14 @@ extern int create_cluster_tables(MYSQL *db_conn, char *cluster_name) storage_field_t job_table_fields[] = { { "job_db_inx", "int not null auto_increment" }, + { "mod_time", "int unsigned default 0 not null" }, { "deleted", "tinyint default 0 not null" }, { "account", "tinytext" }, { "cpus_req", "int unsigned not null" }, { "cpus_alloc", "int unsigned not null" }, - { "derived_ec", "int default 0 not null" }, + { "derived_ec", "int unsigned default 0 not null" }, { "derived_es", "text" }, - { "exit_code", "int default 0 not null" }, + { "exit_code", "int unsigned default 0 not null" }, { "job_name", "tinytext not null" }, { "id_assoc", "int unsigned not null" }, { "id_block", "tinytext" }, @@ -2289,6 +2290,13 @@ extern List acct_storage_p_modify_associations( return as_mysql_modify_assocs(mysql_conn, uid, assoc_cond, assoc); } +extern List acct_storage_p_modify_job(mysql_conn_t *mysql_conn, uint32_t uid, + slurmdb_job_modify_cond_t *job_cond, + slurmdb_job_rec_t *job) +{ + return as_mysql_modify_job(mysql_conn, uid, job_cond, job); +} + extern List acct_storage_p_modify_qos(mysql_conn_t *mysql_conn, uint32_t uid, slurmdb_qos_cond_t *qos_cond, slurmdb_qos_rec_t *qos) diff --git a/src/plugins/accounting_storage/mysql/as_mysql_job.c b/src/plugins/accounting_storage/mysql/as_mysql_job.c index d8f7176294f..5bb147ec3da 100644 --- a/src/plugins/accounting_storage/mysql/as_mysql_job.c +++ b/src/plugins/accounting_storage/mysql/as_mysql_job.c @@ -545,6 +545,110 @@ no_rollup_change: return rc; } +extern List as_mysql_modify_job(mysql_conn_t *mysql_conn, uint32_t uid, + slurmdb_job_modify_cond_t *job_cond, + slurmdb_job_rec_t *job) +{ + List ret_list = NULL; + int rc = SLURM_SUCCESS; + char *object = NULL; + char *vals = NULL, *extra = NULL, *query = NULL, *cond_char = NULL; + time_t now = time(NULL); + time_t submit_time = 0; + time_t most_recent = 0; + char *user_name = NULL; + MYSQL_RES *result = NULL; + MYSQL_ROW row; + + if(!job_cond || !job) { + error("we need something to change"); + return NULL; + } + + if(check_connection(mysql_conn) != SLURM_SUCCESS) + return NULL; + + if(job_cond->job_id == NO_VAL) { + errno = SLURM_NO_CHANGE_IN_DATA; + error("Job ID was not specified for job modification\n"); + return NULL; + } else + xstrfmtcat(extra, " && id_job=%u", job_cond->job_id); + + xstrfmtcat(extra, " && id_user=%u", uid); + + if(job->derived_ec != NO_VAL) + xstrfmtcat(vals, ", derived_ec=%u", job->derived_ec); + + if(job->derived_es) + xstrfmtcat(vals, ", derived_es='%s'", job->derived_es); + + if (!vals) { + errno = SLURM_NO_CHANGE_IN_DATA; + error("No change specified for job modification"); + xfree(extra); + return NULL; + } + + if (job_cond->cluster) { + query = xstrdup_printf("select id_job,time_submit from " + "\"%s_%s\" where deleted=0 %s;", + job_cond->cluster, job_table, extra); + } else { + errno = SLURM_NO_CHANGE_IN_DATA; + error("Cluster was not specified for job modification\n"); + xfree(extra); + xfree(vals); + return NULL; + } + + xfree(extra); + if(!(result = mysql_db_query_ret(mysql_conn->db_conn, query, 0))) { + xfree(vals); + xfree(query); + return NULL; + } + + ret_list = list_create(slurm_destroy_char); + while((row = mysql_fetch_row(result))) { + submit_time = (time_t)atol(row[1]); + if (submit_time > most_recent) { + most_recent = submit_time; + xfree(object); + object = xstrdup(row[0]); + } + } + mysql_free_result(result); + + if (object) { + xstrfmtcat(cond_char, "id_job=%s and time_submit=%ld", object, + most_recent); + list_append(ret_list, object); + } else { + errno = SLURM_NO_CHANGE_IN_DATA; + debug3("didn't effect anything\n%s", query); + xfree(vals); + xfree(query); + list_destroy(ret_list); + return NULL; + } + xfree(query); + + user_name = uid_to_string((uid_t) uid); + rc = modify_common(mysql_conn, DBD_MODIFY_JOB, now, user_name, + job_table, cond_char, vals, job_cond->cluster); + xfree(user_name); + xfree(cond_char); + xfree(vals); + if (rc == SLURM_ERROR) { + error("Couldn't modify job"); + list_destroy(ret_list); + ret_list = NULL; + } + + return ret_list; +} + extern int as_mysql_job_complete(mysql_conn_t *mysql_conn, struct job_record *job_ptr) { diff --git a/src/plugins/accounting_storage/mysql/as_mysql_job.h b/src/plugins/accounting_storage/mysql/as_mysql_job.h index 2a589595372..6267478af1e 100644 --- a/src/plugins/accounting_storage/mysql/as_mysql_job.h +++ b/src/plugins/accounting_storage/mysql/as_mysql_job.h @@ -45,6 +45,10 @@ extern int as_mysql_job_start(mysql_conn_t *mysql_conn, struct job_record *job_ptr); +extern List as_mysql_modify_job(mysql_conn_t *mysql_conn, uint32_t uid, + slurmdb_job_modify_cond_t *job_cond, + slurmdb_job_rec_t *job); + extern int as_mysql_job_complete(mysql_conn_t *mysql_conn, struct job_record *job_ptr); diff --git a/src/plugins/accounting_storage/none/accounting_storage_none.c b/src/plugins/accounting_storage/none/accounting_storage_none.c index 5bd7a4d22f5..3d0e7e12442 100644 --- a/src/plugins/accounting_storage/none/accounting_storage_none.c +++ b/src/plugins/accounting_storage/none/accounting_storage_none.c @@ -181,6 +181,13 @@ extern List acct_storage_p_modify_associations(void *db_conn, uint32_t uid, return SLURM_SUCCESS; } +extern List acct_storage_p_modify_job(void *db_conn, uint32_t uid, + slurmdb_job_modify_cond_t *job_cond, + slurmdb_job_rec_t *job) +{ + return SLURM_SUCCESS; +} + extern List acct_storage_p_modify_qos(void *db_conn, uint32_t uid, slurmdb_qos_cond_t *qos_cond, slurmdb_qos_rec_t *qos) diff --git a/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.c b/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.c index 54085e1184e..a05e97e66b2 100644 --- a/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.c +++ b/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.c @@ -403,6 +403,13 @@ extern List acct_storage_p_modify_associations( return as_pg_modify_associations(pg_conn, uid, assoc_cond, assoc); } +extern List acct_storage_p_modify_job(pgsql_conn_t *pg_conn, uint32_t uid, + slurmdb_job_modify_cond_t *job_cond, + slurmdb_job_rec_t *job) +{ + return SLURM_SUCCESS; +} + extern List acct_storage_p_modify_qos(pgsql_conn_t *pg_conn, uint32_t uid, slurmdb_qos_cond_t *qos_cond, slurmdb_qos_rec_t *qos) diff --git a/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.h b/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.h index 23efe435e23..448e4c7cd63 100644 --- a/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.h +++ b/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.h @@ -85,6 +85,9 @@ extern List acct_storage_p_modify_associations( pgsql_conn_t *pg_conn, uint32_t uid, slurmdb_association_cond_t *assoc_cond, slurmdb_association_rec_t *assoc); +extern List acct_storage_p_modify_job(pgsql_conn_t *pg_conn, uint32_t uid, + slurmdb_job_modify_cond_t *job_cond, + slurmdb_job_rec_t *job); extern List acct_storage_p_modify_qos(pgsql_conn_t *pg_conn, uint32_t uid, slurmdb_qos_cond_t *qos_cond, slurmdb_qos_rec_t *qos); diff --git a/src/plugins/accounting_storage/slurmdbd/accounting_storage_slurmdbd.c b/src/plugins/accounting_storage/slurmdbd/accounting_storage_slurmdbd.c index 1e7c11dd13a..6216389a18f 100644 --- a/src/plugins/accounting_storage/slurmdbd/accounting_storage_slurmdbd.c +++ b/src/plugins/accounting_storage/slurmdbd/accounting_storage_slurmdbd.c @@ -771,6 +771,49 @@ extern List acct_storage_p_modify_associations( return ret_list; } +extern List acct_storage_p_modify_job(void *db_conn, uint32_t uid, + slurmdb_job_modify_cond_t *job_cond, + slurmdb_job_rec_t *job) +{ + slurmdbd_msg_t req, resp; + dbd_modify_msg_t get_msg; + dbd_list_msg_t *got_msg; + List ret_list = NULL; + int rc; + + memset(&get_msg, 0, sizeof(dbd_modify_msg_t)); + get_msg.cond = job_cond; + get_msg.rec = job; + + req.msg_type = DBD_MODIFY_JOB; + req.data = &get_msg; + rc = slurm_send_recv_slurmdbd_msg(SLURMDBD_VERSION, &req, &resp); + + if (rc != SLURM_SUCCESS) + error("slurmdbd: DBD_MODIFY_JOB failure: %m"); + else if (resp.msg_type == DBD_RC) { + dbd_rc_msg_t *msg = resp.data; + if(msg->return_code == SLURM_SUCCESS) { + info("%s", msg->comment); + ret_list = list_create(NULL); + } else { + slurm_seterrno(msg->return_code); + error("%s", msg->comment); + } + slurmdbd_free_rc_msg(msg); + } else if (resp.msg_type != DBD_GOT_LIST) { + error("slurmdbd: response type not DBD_GOT_LIST: %u", + resp.msg_type); + } else { + got_msg = (dbd_list_msg_t *) resp.data; + ret_list = got_msg->my_list; + got_msg->my_list = NULL; + slurmdbd_free_list_msg(got_msg); + } + + return ret_list; +} + extern List acct_storage_p_modify_qos(void *db_conn, uint32_t uid, slurmdb_qos_cond_t *qos_cond, slurmdb_qos_rec_t *qos) diff --git a/src/sacctmgr/Makefile.am b/src/sacctmgr/Makefile.am index da0da765345..76a9a32a944 100644 --- a/src/sacctmgr/Makefile.am +++ b/src/sacctmgr/Makefile.am @@ -19,6 +19,7 @@ sacctmgr_SOURCES = \ common.c \ event_functions.c \ file_functions.c \ + job_functions.c \ sacctmgr.c sacctmgr.h \ qos_functions.c \ txn_functions.c \ diff --git a/src/sacctmgr/job_functions.c b/src/sacctmgr/job_functions.c new file mode 100644 index 00000000000..3b35656c6ff --- /dev/null +++ b/src/sacctmgr/job_functions.c @@ -0,0 +1,245 @@ +/*****************************************************************************\ + * job_functions.c - functions dealing with jobs in the accounting system. + ***************************************************************************** + * Copyright (C) 2008-2010 Lawrence Livermore National Security. + * Copyright (C) 2002-2008 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Danny Auble <da@llnl.gov> + * CODE-OCEC-09-009. All rights reserved. + * + * This file is part of SLURM, a resource management program. + * For details, see <https://computing.llnl.gov/linux/slurm/>. + * Please also read the included file: DISCLAIMER. + * + * SLURM is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * In addition, as a special exception, the copyright holders give permission + * to link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. You must obey the GNU + * General Public License in all respects for all of the code used other than + * OpenSSL. If you modify file(s) with this exception, you may extend this + * exception to your version of the file(s), but you are not obligated to do + * so. If you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files in + * the program, then also delete it here. + * + * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with SLURM; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +\*****************************************************************************/ + +#include "src/sacctmgr/sacctmgr.h" + +static int _set_cond(int *start, int argc, char *argv[], + slurmdb_job_modify_cond_t *job_cond) +{ + char *next_str; + int i; + int set = 0; + int end = 0; + int command_len = 0; + + if (!job_cond) { + error("No job_cond given"); + return -1; + } + + job_cond->job_id = NO_VAL; + for (i=(*start); i<argc; i++) { + end = parse_option_end(argv[i]); + if (!end) + command_len=strlen(argv[i]); + else { + command_len=end-1; + if (argv[i][end] == '=') { +/* option = (int)argv[i][end-1]; */ + end++; + } + } + + if (!strncasecmp (argv[i], "Set", MAX(command_len, 3))) { + i--; + break; + } else if (!end && !strncasecmp(argv[i], "where", + MAX(command_len, 5))) { + continue; + } else if (!strncasecmp (argv[i], "Cluster", + MAX(command_len, 1))) { + job_cond->cluster = xstrdup(argv[i]+end); + } else if (!strncasecmp (argv[i], "JobID", + MAX(command_len, 1))) { + job_cond->job_id = (uint32_t) strtol(argv[i]+end, + &next_str, 10); + if ((job_cond->job_id == 0) || + ((next_str[0] != '\0') && (next_str[0] != ' '))) { + fprintf(stderr, "Invalid job id %s specified\n", + argv[i]+end); + exit_code = 1; + } else + set = 1; + } else { + exit_code = 1; + fprintf(stderr, " Unknown condition: %s\n" + " Use keyword 'set' to modify value\n", + argv[i]); + } + } + + if (!job_cond->cluster) + job_cond->cluster = slurm_get_cluster_name(); + + return set; +} + +static int _set_rec(int *start, int argc, char *argv[], + slurmdb_job_rec_t *job) +{ + int i; + int set = 0; + int end = 0; + int command_len = 0; + int option = 0; + + for (i=(*start); i<argc; i++) { + end = parse_option_end(argv[i]); + if(!end) + command_len=strlen(argv[i]); + else { + command_len=end-1; + if(argv[i][end] == '=') { + option = (int)argv[i][end-1]; + end++; + } + } + + if (!strncasecmp (argv[i], "Where", MAX(command_len, 5))) { + i--; + break; + } else if(!end && !strncasecmp(argv[i], "set", + MAX(command_len, 3))) { + continue; + } else if(!end) { + exit_code=1; + fprintf(stderr, + " Bad format on %s: End your option with " + "an '=' sign\n", argv[i]); + } else if ((!strncasecmp(argv[i], "DerivedExitCode", + MAX(command_len, 12))) || + (!strncasecmp(argv[i], "DerivedEC", + MAX(command_len, 9)))) { + if (get_uint(argv[i]+end, &job->derived_ec, + "DerivedExitCode") == SLURM_SUCCESS) { + set = 1; + } + } else if ((!strncasecmp(argv[i], "DerivedExitString", + MAX(command_len, 12))) || + (!strncasecmp(argv[i], "DerivedES", + MAX(command_len, 9)))) { + if(job->derived_es) + xfree(job->derived_es); + job->derived_es = strip_quotes(argv[i]+end, NULL, 1); + set = 1; + } else { + printf(" Unknown option: %s\n" + " Use keyword 'where' to modify condition\n", + argv[i]); + } + } + + return set; +} + +extern int sacctmgr_modify_job(int argc, char *argv[]) +{ + int rc = SLURM_SUCCESS; + slurmdb_job_modify_cond_t *job_cond = xmalloc(sizeof( + slurmdb_job_modify_cond_t)); + slurmdb_job_rec_t *job = slurmdb_create_job_rec(); + int i=0; + int cond_set = 0, rec_set = 0, set = 0; + List ret_list = NULL; + + for (i=0; i<argc; i++) { + int command_len = strlen(argv[i]); + if (!strncasecmp(argv[i], "Where", MAX(command_len, 5))) { + i++; + cond_set += _set_cond(&i, argc, argv, job_cond); + + } else if (!strncasecmp(argv[i], "Set", MAX(command_len, 3))) { + i++; + rec_set += _set_rec(&i, argc, argv, job); + } else { + cond_set += _set_cond(&i, argc, argv, job_cond); + } + } + + if (exit_code) { + slurmdb_destroy_job_modify_cond(job_cond); + slurmdb_destroy_job_rec(job); + return SLURM_ERROR; + } else if (!rec_set) { + exit_code=1; + fprintf(stderr, " You didn't give me anything to set\n"); + slurmdb_destroy_job_modify_cond(job_cond); + slurmdb_destroy_job_rec(job); + return SLURM_ERROR; + } else if (!cond_set) { + if (!commit_check("You didn't set any conditions with 'WHERE'." + "\nAre you sure you want to continue?")) { + printf("Aborted\n"); + slurmdb_destroy_job_modify_cond(job_cond); + slurmdb_destroy_job_rec(job); + return SLURM_SUCCESS; + } + } + + notice_thread_init(); + + ret_list = acct_storage_g_modify_job(db_conn, my_uid, job_cond, job); + if (ret_list && list_count(ret_list)) { + char *object = NULL; + ListIterator itr = list_iterator_create(ret_list); + printf(" Modified jobs...\n"); + while((object = list_next(itr))) { + printf(" %s\n", object); + } + list_iterator_destroy(itr); + set = 1; + } else if (ret_list) { + printf(" Nothing modified\n"); + rc = SLURM_ERROR; + } else { + exit_code=1; + fprintf(stderr, " Error with request: %s\n", + slurm_strerror(errno)); + rc = SLURM_ERROR; + } + + if (ret_list) + list_destroy(ret_list); + + notice_thread_fini(); + + if (set) { + if (commit_check("Would you like to commit changes?")) + acct_storage_g_commit(db_conn, 1); + else { + printf(" Changes Discarded\n"); + acct_storage_g_commit(db_conn, 0); + } + } + + slurmdb_destroy_job_modify_cond(job_cond); + slurmdb_destroy_job_rec(job); + + return rc; +} diff --git a/src/sacctmgr/sacctmgr.c b/src/sacctmgr/sacctmgr.c index c626ce496b3..f4dadde6b63 100644 --- a/src/sacctmgr/sacctmgr.c +++ b/src/sacctmgr/sacctmgr.c @@ -677,6 +677,8 @@ static void _modify_it (int argc, char *argv[]) } else if (strncasecmp (argv[0], "Clusters", MAX(command_len, 1)) == 0) { error_code = sacctmgr_modify_cluster((argc - 1), &argv[1]); + } else if (strncasecmp (argv[0], "Job", MAX(command_len, 1)) == 0) { + error_code = sacctmgr_modify_job((argc - 1), &argv[1]); } else if (strncasecmp (argv[0], "QOSs", MAX(command_len, 1)) == 0) { error_code = sacctmgr_modify_qos((argc - 1), &argv[1]); } else if (strncasecmp (argv[0], "Users", MAX(command_len, 1)) == 0) { diff --git a/src/sacctmgr/sacctmgr.h b/src/sacctmgr/sacctmgr.h index c13f7b40b25..614d6bf3d57 100644 --- a/src/sacctmgr/sacctmgr.h +++ b/src/sacctmgr/sacctmgr.h @@ -220,6 +220,7 @@ extern int sacctmgr_modify_association(int argc, char *argv[]); extern int sacctmgr_modify_user(int argc, char *argv[]); extern int sacctmgr_modify_account(int argc, char *argv[]); extern int sacctmgr_modify_cluster(int argc, char *argv[]); +extern int sacctmgr_modify_job(int argc, char *argv[]); extern int sacctmgr_modify_qos(int argc, char *argv[]); extern int sacctmgr_delete_association(int argc, char *argv[]); diff --git a/src/slurmdbd/proc_req.c b/src/slurmdbd/proc_req.c index b1c31f5382f..3c90be95567 100644 --- a/src/slurmdbd/proc_req.c +++ b/src/slurmdbd/proc_req.c @@ -118,6 +118,8 @@ static int _modify_assocs(slurmdbd_conn_t *slurmdbd_conn, Buf in_buffer, Buf *out_buffer, uint32_t *uid); static int _modify_clusters(slurmdbd_conn_t *slurmdbd_conn, Buf in_buffer, Buf *out_buffer, uint32_t *uid); +static int _modify_job(slurmdbd_conn_t *slurmdbd_conn, + Buf in_buffer, Buf *out_buffer, uint32_t *uid); static int _modify_qos(slurmdbd_conn_t *slurmdbd_conn, Buf in_buffer, Buf *out_buffer, uint32_t *uid); static int _modify_users(slurmdbd_conn_t *slurmdbd_conn, @@ -340,6 +342,10 @@ proc_req(slurmdbd_conn_t *slurmdbd_conn, rc = _modify_clusters(slurmdbd_conn, in_buffer, out_buffer, uid); break; + case DBD_MODIFY_JOB: + rc = _modify_job(slurmdbd_conn, + in_buffer, out_buffer, uid); + break; case DBD_MODIFY_QOS: rc = _modify_qos(slurmdbd_conn, in_buffer, out_buffer, uid); @@ -1962,12 +1968,13 @@ end_it: static int _modify_accounts(slurmdbd_conn_t *slurmdbd_conn, Buf in_buffer, Buf *out_buffer, uint32_t *uid) { + dbd_list_msg_t list_msg; int rc = SLURM_SUCCESS; dbd_modify_msg_t *get_msg = NULL; - dbd_list_msg_t list_msg; char *comment = NULL; debug2("DBD_MODIFY_ACCOUNTS: called"); + if((*uid != slurmdbd_conf->slurm_user_id && *uid != 0) && assoc_mgr_get_admin_level(slurmdbd_conn->db_conn, *uid) < SLURMDB_ADMIN_OPERATOR) { @@ -1991,7 +1998,6 @@ static int _modify_accounts(slurmdbd_conn_t *slurmdbd_conn, return SLURM_ERROR; } - if(!(list_msg.my_list = acct_storage_g_modify_accounts( slurmdbd_conn->db_conn, *uid, get_msg->cond, get_msg->rec))) { @@ -2018,24 +2024,25 @@ static int _modify_accounts(slurmdbd_conn_t *slurmdbd_conn, rc, comment, DBD_MODIFY_ACCOUNTS); return rc; } - slurmdbd_free_modify_msg(get_msg, DBD_MODIFY_ACCOUNTS); + slurmdbd_free_modify_msg(get_msg, DBD_MODIFY_ACCOUNTS); *out_buffer = init_buf(1024); pack16((uint16_t) DBD_GOT_LIST, *out_buffer); slurmdbd_pack_list_msg(&list_msg, slurmdbd_conn->rpc_version, DBD_GOT_LIST, *out_buffer); if(list_msg.my_list) list_destroy(list_msg.my_list); + return rc; } static int _modify_assocs(slurmdbd_conn_t *slurmdbd_conn, Buf in_buffer, Buf *out_buffer, uint32_t *uid) { + dbd_list_msg_t list_msg; int rc = SLURM_SUCCESS; dbd_modify_msg_t *get_msg = NULL; char *comment = NULL; - dbd_list_msg_t list_msg; debug2("DBD_MODIFY_ASSOCS: called"); @@ -2102,6 +2109,8 @@ static int _modify_clusters(slurmdbd_conn_t *slurmdbd_conn, dbd_modify_msg_t *get_msg = NULL; char *comment = NULL; + debug2("DBD_MODIFY_CLUSTERS: called"); + if((*uid != slurmdbd_conf->slurm_user_id && *uid != 0) && assoc_mgr_get_admin_level(slurmdbd_conn->db_conn, *uid) < SLURMDB_ADMIN_SUPER_USER) { @@ -2125,8 +2134,6 @@ static int _modify_clusters(slurmdbd_conn_t *slurmdbd_conn, return SLURM_ERROR; } - debug2("DBD_MODIFY_CLUSTERS: called"); - if(!(list_msg.my_list = acct_storage_g_modify_clusters( slurmdbd_conn->db_conn, *uid, get_msg->cond, get_msg->rec))) { @@ -2165,6 +2172,77 @@ static int _modify_clusters(slurmdbd_conn_t *slurmdbd_conn, return rc; } +static int _modify_job(slurmdbd_conn_t *slurmdbd_conn, + Buf in_buffer, Buf *out_buffer, uint32_t *uid) +{ + dbd_list_msg_t list_msg; + int rc = SLURM_SUCCESS; + dbd_modify_msg_t *get_msg = NULL; + char *comment = NULL; + + debug2("DBD_MODIFY_JOB: called"); + + if((*uid != slurmdbd_conf->slurm_user_id && *uid != 0) + && assoc_mgr_get_admin_level(slurmdbd_conn->db_conn, *uid) + < SLURMDB_ADMIN_SUPER_USER) { + comment = "Your user doesn't have privilege to preform this action"; + error("%s", comment); + *out_buffer = make_dbd_rc_msg(slurmdbd_conn->rpc_version, + ESLURM_ACCESS_DENIED, + comment, DBD_MODIFY_JOB); + + return ESLURM_ACCESS_DENIED; + } + + if (slurmdbd_unpack_modify_msg(&get_msg, slurmdbd_conn->rpc_version, + DBD_MODIFY_JOB, + in_buffer) != SLURM_SUCCESS) { + comment = "Failed to unpack DBD_MODIFY_JOB message"; + error("%s", comment); + *out_buffer = make_dbd_rc_msg(slurmdbd_conn->rpc_version, + SLURM_ERROR, + comment, DBD_MODIFY_JOB); + return SLURM_ERROR; + } + + if(!(list_msg.my_list = acct_storage_g_modify_job( + slurmdbd_conn->db_conn, *uid, get_msg->cond, + get_msg->rec))) { + if(errno == ESLURM_ACCESS_DENIED) { + comment = "Your user doesn't have privilege to preform this action"; + rc = ESLURM_ACCESS_DENIED; + } else if(errno == SLURM_ERROR) { + comment = "Something was wrong with your query"; + rc = SLURM_ERROR; + } else if(errno == SLURM_NO_CHANGE_IN_DATA) { + comment = "Request didn't affect anything"; + rc = SLURM_SUCCESS; + } else if(errno == ESLURM_DB_CONNECTION) { + comment = slurm_strerror(errno); + rc = errno; + } else { + rc = errno; + if(!(comment = slurm_strerror(errno))) + comment = "Unknown issue"; + } + error("%s", comment); + slurmdbd_free_modify_msg(get_msg, DBD_MODIFY_JOB); + *out_buffer = make_dbd_rc_msg(slurmdbd_conn->rpc_version, + rc, comment, DBD_MODIFY_JOB); + return rc; + } + + slurmdbd_free_modify_msg(get_msg, DBD_MODIFY_JOB); + *out_buffer = init_buf(1024); + pack16((uint16_t) DBD_GOT_LIST, *out_buffer); + slurmdbd_pack_list_msg(&list_msg, slurmdbd_conn->rpc_version, + DBD_GOT_LIST, *out_buffer); + if(list_msg.my_list) + list_destroy(list_msg.my_list); + + return rc; +} + static int _modify_qos(slurmdbd_conn_t *slurmdbd_conn, Buf in_buffer, Buf *out_buffer, uint32_t *uid) { @@ -2173,6 +2251,8 @@ static int _modify_qos(slurmdbd_conn_t *slurmdbd_conn, dbd_modify_msg_t *get_msg = NULL; char *comment = NULL; + debug2("DBD_MODIFY_QOS: called"); + if((*uid != slurmdbd_conf->slurm_user_id && *uid != 0) && assoc_mgr_get_admin_level(slurmdbd_conn->db_conn, *uid) < SLURMDB_ADMIN_SUPER_USER) { @@ -2196,8 +2276,6 @@ static int _modify_qos(slurmdbd_conn_t *slurmdbd_conn, return SLURM_ERROR; } - debug2("DBD_MODIFY_QOS: called"); - if(!(list_msg.my_list = acct_storage_g_modify_qos( slurmdbd_conn->db_conn, *uid, get_msg->cond, get_msg->rec))) { @@ -2255,8 +2333,8 @@ static int _modify_users(slurmdbd_conn_t *slurmdbd_conn, debug2("DBD_MODIFY_USERS: called"); if (slurmdbd_unpack_modify_msg(&get_msg, slurmdbd_conn->rpc_version, - DBD_MODIFY_USERS, in_buffer) != - SLURM_SUCCESS) { + DBD_MODIFY_USERS, + in_buffer) != SLURM_SUCCESS) { comment = "Failed to unpack DBD_MODIFY_USERS message"; error("%s", comment); *out_buffer = make_dbd_rc_msg(slurmdbd_conn->rpc_version, @@ -2363,6 +2441,8 @@ static int _modify_wckeys(slurmdbd_conn_t *slurmdbd_conn, dbd_modify_msg_t *get_msg = NULL; char *comment = NULL; + debug2("DBD_MODIFY_WCKEYS: called"); + if((*uid != slurmdbd_conf->slurm_user_id && *uid != 0) && assoc_mgr_get_admin_level(slurmdbd_conn->db_conn, *uid) < SLURMDB_ADMIN_SUPER_USER) { @@ -2386,8 +2466,6 @@ static int _modify_wckeys(slurmdbd_conn_t *slurmdbd_conn, return SLURM_ERROR; } - debug2("DBD_MODIFY_WCKEYS: called"); - if(!(list_msg.my_list = acct_storage_g_modify_wckeys( slurmdbd_conn->db_conn, *uid, get_msg->cond, get_msg->rec))) { -- GitLab