/* * as_pg_roll_usage - rollup usage information * * IN pg_conn: database connection * IN sent_start: start time * IN sent_end: end time * IN archive_data: whether to archive usage data * RET: error code */ extern int as_pg_roll_usage(pgsql_conn_t *pg_conn, time_t sent_start, time_t sent_end, uint16_t archive_data) { int rc = SLURM_SUCCESS; if (check_db_connection(pg_conn) != SLURM_SUCCESS) return ESLURM_DB_CONNECTION; slurm_mutex_lock(&usage_rollup_lock); FOR_EACH_CLUSTER(NULL) { rc |= _cluster_rollup_usage(pg_conn, cluster_name, sent_start, sent_end, archive_data); } END_EACH_CLUSTER; slurm_mutex_unlock(&usage_rollup_lock); return rc; }
// Return 1 on success, 0 on failure int add_achievement_progress(int achievement_id, int add_progress_count){ if(achievement_system_disabled){ return ACHIEVEMENT_PUSH_FAILURE; } if(ACHIEVEMENT_DEBUG){pline("DEBUG: add_achievement_progress(%i, %i)", achievement_id, add_progress_count);} if(check_db_connection()){ disable_achievements(); } //Check if user exists if(!user_exists()){ register_user(); } //Calculate user's completion on this achievement int pre_achievement_progress = get_achievement_progress(achievement_id); int max_achievement_progress = get_achievement_max_progress(achievement_id); if(ACHIEVEMENT_DEBUG){pline("DEBUG: get_achievement_max_progress(%i)=%i", achievement_id, max_achievement_progress);} if(pre_achievement_progress < max_achievement_progress){ //user still needs achievement if(pre_achievement_progress + add_progress_count >= max_achievement_progress){ //Achievement fully achieved! if(push_achievement_progress(achievement_id, max_achievement_progress)){ //floor the value to max_progress char * achievement_name = get_achievement_name(achievement_id); pline("Congratulations! You've earned the achievement: %s", achievement_name); free(achievement_name); return ACHIEVEMENT_PUSH_SUCCESS; } else{ pline("Er, oops. You got an achievement, but it can't be recorded."); return ACHIEVEMENT_PUSH_FAILURE; } } else{ //user stills needs achievement, but isn't quite there yet if(push_achievement_progress(achievement_id, pre_achievement_progress+add_progress_count)){ return ACHIEVEMENT_PUSH_SUCCESS; } else{ return ACHIEVEMENT_PUSH_FAILURE; } } } return ACHIEVEMENT_PUSH_SUCCESS; }
/* * as_pg_get_accts - get accounts * * IN pg_conn: database connection * IN uid: user performing the get operation * IN acct_cond: accounts to get * RET: list of accounts */ extern List as_pg_get_accts(pgsql_conn_t *pg_conn, uid_t uid, slurmdb_account_cond_t *acct_cond) { DEF_VARS; char *cond = NULL; List acct_list = NULL; ListIterator itr = NULL; int set=0, is_admin=1; slurmdb_user_rec_t user; /* no need to free lists */ char *ga_fields = "name, description, organization"; enum { F_NAME, F_DESC, F_ORG, F_COUNT }; if (check_db_connection(pg_conn) != SLURM_SUCCESS) return NULL; if (check_user_op(pg_conn, uid, PRIVATE_DATA_ACCOUNTS, &is_admin, &user) != SLURM_SUCCESS) { error("as/pg: user(%u) not found in db", uid); errno = ESLURM_USER_ID_MISSING; return NULL; } if (!is_admin && ! is_user_any_coord(pg_conn, &user)) { errno = ESLURM_ACCESS_DENIED; return NULL; } if(!acct_cond) { xstrcat(cond, "WHERE deleted=0"); goto empty; } if(acct_cond->with_deleted) xstrcat(cond, "WHERE (deleted=0 OR deleted=1)"); else xstrcat(cond, "WHERE deleted=0"); if(acct_cond->assoc_cond) concat_cond_list(acct_cond->assoc_cond->acct_list, NULL, "name", &cond); concat_cond_list(acct_cond->description_list, NULL, "description", &cond); concat_cond_list(acct_cond->organization_list, NULL, "organization", &cond); empty: if(!is_admin) { slurmdb_coord_rec_t *coord = NULL; set = 0; itr = list_iterator_create(user.coord_accts); while((coord = list_next(itr))) { if(set) { xstrfmtcat(cond, " OR name='%s'", coord->name); } else { set = 1; xstrfmtcat(cond, " AND (name='%s'", coord->name); } } list_iterator_destroy(itr); if(set) xstrcat(cond,")"); } query = xstrdup_printf("SELECT %s FROM %s %s", ga_fields, acct_table, cond); xfree(cond); result = DEF_QUERY_RET; if (!result) return NULL; acct_list = list_create(slurmdb_destroy_account_rec); if(acct_cond && acct_cond->with_assocs) { if(!acct_cond->assoc_cond) acct_cond->assoc_cond = xmalloc( sizeof(slurmdb_association_cond_t)); else if(acct_cond->assoc_cond->acct_list) list_destroy(acct_cond->assoc_cond->acct_list); acct_cond->assoc_cond->acct_list = list_create(NULL); } FOR_EACH_ROW { slurmdb_account_rec_t *acct = xmalloc(sizeof(slurmdb_account_rec_t)); list_append(acct_list, acct); acct->name = xstrdup(ROW(F_NAME)); acct->description = xstrdup(ROW(F_DESC)); acct->organization = xstrdup(ROW(F_ORG)); if(acct_cond && acct_cond->with_coords) _get_account_coords(pg_conn, acct); if(acct_cond && acct_cond->with_assocs) { list_append(acct_cond->assoc_cond->acct_list, acct->name); } } END_EACH_ROW; PQclear(result); /* get associations */ if(acct_cond && acct_cond->with_assocs && list_count(acct_cond->assoc_cond->acct_list)) { ListIterator assoc_itr = NULL; slurmdb_account_rec_t *acct = NULL; slurmdb_association_rec_t *assoc = NULL; List assoc_list = acct_storage_p_get_associations( pg_conn, uid, acct_cond->assoc_cond); if(!assoc_list) { error("as/pg: get_accounts: no associations"); return acct_list; } itr = list_iterator_create(acct_list); assoc_itr = list_iterator_create(assoc_list); while((acct = list_next(itr))) { while((assoc = list_next(assoc_itr))) { if(strcmp(assoc->acct, acct->name)) continue; if(!acct->assoc_list) acct->assoc_list = list_create( slurmdb_destroy_association_rec); list_append(acct->assoc_list, assoc); list_remove(assoc_itr); } list_iterator_reset(assoc_itr); if(!acct->assoc_list) /* problem acct */ list_remove(itr); } list_iterator_destroy(itr); list_iterator_destroy(assoc_itr); list_destroy(assoc_list); } return acct_list; }
/* * as_pg_remove_accts - remove accounts * * IN pg_conn: database connection * IN uid: user performing the remove operation * IN acct_cond: accounts to remove * RET: list of accounts removed */ extern List as_pg_remove_accts(pgsql_conn_t *pg_conn, uint32_t uid, slurmdb_account_cond_t *acct_cond) { DEF_VARS; List ret_list = NULL, tmp_list = NULL; char *user_name = NULL, *cond = NULL, *name_char = NULL, *assoc_char = NULL; time_t now = time(NULL); int rc = SLURM_SUCCESS, has_jobs; if(!acct_cond) { error("as/pg: remove_accts: we need something to remove"); return NULL; } if (check_db_connection(pg_conn) != SLURM_SUCCESS) return NULL; if(acct_cond->assoc_cond) concat_cond_list(acct_cond->assoc_cond->acct_list, NULL, "name", &cond); concat_cond_list(acct_cond->description_list, NULL, "description", &cond); concat_cond_list(acct_cond->organization_list, NULL, "organization", &cond); if(!cond) { error("as/pg: remove_accts: nothing to remove"); return NULL; } query = xstrdup_printf( "SELECT name FROM %s WHERE deleted=0 %s;", acct_table, cond); xfree(cond); result = DEF_QUERY_RET; if(!result) return NULL; rc = 0; ret_list = list_create(slurm_destroy_char); FOR_EACH_ROW { char *object = xstrdup(ROW(0)); list_append(ret_list, object); if(!rc) { xstrfmtcat(name_char, "name='%s'", object); xstrfmtcat(assoc_char, "t2.acct='%s'", object); rc = 1; } else { xstrfmtcat(name_char, " OR name='%s'", object); xstrfmtcat(assoc_char, " OR t2.acct='%s'", object); } } END_EACH_ROW; PQclear(result); if(!list_count(ret_list)) { errno = SLURM_NO_CHANGE_IN_DATA; debug3("as/pg: remove_accts: didn't effect anything"); return ret_list; } /* remove these accounts from the coord's that have it */ tmp_list = acct_storage_p_remove_coord(pg_conn, uid, ret_list, NULL); if(tmp_list) list_destroy(tmp_list); /* if there are running jobs of the accounts, return the jobs */ tmp_list = _get_acct_running_jobs(pg_conn, assoc_char); if (tmp_list) { errno = ESLURM_JOBS_RUNNING_ON_ASSOC; list_destroy(ret_list); reset_pgsql_conn(pg_conn); return tmp_list; } /* delete recently added accounts */ has_jobs = _acct_has_jobs(pg_conn, assoc_char); if (! has_jobs ) { query = xstrdup_printf( "DELETE FROM %s WHERE creation_time>%d AND (%s);", acct_table, (int)(now - DELETE_SEC_BACK), name_char); } /* mark others as deleted */ xstrfmtcat(query, "UPDATE %s SET mod_time=%ld, deleted=1 " "WHERE deleted=0 " "AND (%s);", acct_table, (long)now, name_char); user_name = uid_to_string((uid_t) uid); xstrfmtcat(query, "INSERT INTO %s (timestamp, action, name, actor) " "VALUES (%ld, %d, $$%s$$, '%s');", txn_table, (long)now, DBD_REMOVE_ACCOUNTS, name_char, user_name); xfree(user_name); rc = DEF_QUERY_RET_RC; if (rc != SLURM_SUCCESS) { reset_pgsql_conn(pg_conn); list_destroy(ret_list); ret_list = NULL; goto out; } /* TODO: this may leave sub-accts without assoc */ /* handle associations */ FOR_EACH_CLUSTER(NULL) { rc = _cluster_remove_acct_assoc(pg_conn, cluster_name, now, assoc_char, has_jobs); if (rc != SLURM_SUCCESS) break; } END_EACH_CLUSTER; if (rc != SLURM_SUCCESS) { reset_pgsql_conn(pg_conn); list_destroy(ret_list); ret_list = NULL; } out: xfree(name_char); xfree(assoc_char); return ret_list; }
/* * as_pg_modify_accounts - modify accounts * * IN pg_conn: database connection * IN uid: user performing the modify operation * IN acct_cond: accounts to modify * IN acct: attribute of accounts after modification * RET: list of accounts modified */ extern List as_pg_modify_accounts(pgsql_conn_t *pg_conn, uint32_t uid, slurmdb_account_cond_t *acct_cond, slurmdb_account_rec_t *acct) { DEF_VARS; List ret_list = NULL; int rc = SLURM_SUCCESS; char *object = NULL, *user_name = NULL; char *vals = NULL, *cond = NULL, *name_char = NULL; time_t now = time(NULL); if(!acct_cond || !acct) { error("as/pg: modify_accounts: we need something to change"); return NULL; } if (check_db_connection(pg_conn) != SLURM_SUCCESS) return NULL; if(acct_cond->assoc_cond) concat_cond_list(acct_cond->assoc_cond->acct_list, NULL, "name", &cond); concat_cond_list(acct_cond->description_list, NULL, "description", &cond); concat_cond_list(acct_cond->organization_list, NULL, "organization", &cond); if (!cond) { errno = SLURM_NO_CHANGE_IN_DATA; error("as/pg: modify_accounts: no condition given"); return NULL; } if(acct->description) xstrfmtcat(vals, ", description='%s'", acct->description); if(acct->organization) xstrfmtcat(vals, ", organization='%s'", acct->organization); if(!vals) { xfree(cond); errno = SLURM_NO_CHANGE_IN_DATA; error("as/pg: modify_accounts: no new values given"); return NULL; } query = xstrdup_printf("SELECT name FROM %s WHERE deleted=0 %s;", acct_table, cond); xfree(cond); result = DEF_QUERY_RET; if(!result) { xfree(vals); return NULL; } rc = 0; ret_list = list_create(slurm_destroy_char); FOR_EACH_ROW { object = xstrdup(ROW(0)); list_append(ret_list, object); if(!rc) { xstrfmtcat(name_char, "(name='%s'", object); rc = 1; } else { xstrfmtcat(name_char, " OR name='%s'", object); } } END_EACH_ROW; PQclear(result); if(!list_count(ret_list)) { errno = SLURM_NO_CHANGE_IN_DATA; debug3("as/pg: modify_accounts: didn't effect anything"); xfree(vals); return ret_list; } xstrcat(name_char, ")"); user_name = uid_to_string((uid_t) uid); rc = pgsql_modify_common(pg_conn, DBD_MODIFY_ACCOUNTS, now, "", user_name, acct_table, name_char, vals); xfree(user_name); xfree(name_char); xfree(vals); if (rc == SLURM_ERROR) { error("as/pg: couldn't modify accounts"); list_destroy(ret_list); errno = SLURM_ERROR; ret_list = NULL; } return ret_list; }
/* * as_pg_add_accts - add accounts * * IN pg_conn: database connection * IN uid: user performing the add operation * IN acct_list: accounts to add * RET: error code */ extern int as_pg_add_accts(pgsql_conn_t *pg_conn, uint32_t uid, List acct_list) { ListIterator itr = NULL; slurmdb_account_rec_t *object = NULL; List assoc_list = NULL; int rc = SLURM_SUCCESS; char *user_name = NULL, *query = NULL, *txn_query = NULL; char *rec = NULL, *info = NULL; time_t now = time(NULL); if (check_db_connection(pg_conn) != SLURM_SUCCESS) return ESLURM_DB_CONNECTION; assoc_list = list_create(slurmdb_destroy_association_rec); user_name = uid_to_string((uid_t) uid); itr = list_iterator_create(acct_list); while((object = list_next(itr))) { if(!object->name || !object->description || !object->organization) { error("as/pg: add_accts: We need an account name, " "description, and organization to add. %s %s %s", object->name, object->description, object->organization); rc = SLURM_ERROR; continue; } /* order of vals must match structure of acct_table */ rec = xstrdup_printf("(%ld, %ld, 0, '%s', '%s', '%s')", now, now, object->name, object->description, object->organization); query = xstrdup_printf("SELECT public.add_acct(%s);", rec); xfree(rec); rc = DEF_QUERY_RET_RC; if(rc != SLURM_SUCCESS) { error("as/pg: couldn't add acct %s", object->name); continue; } info = xstrdup_printf("description='%s', organization='%s'", object->description, object->organization); if(txn_query) xstrfmtcat(txn_query, ", (%ld, %u, '%s', '%s', $$%s$$)", now, DBD_ADD_ACCOUNTS, object->name, user_name, info); else xstrfmtcat(txn_query, "INSERT INTO %s " "(timestamp, action, name, actor, info) " "VALUES (%ld, %u, '%s', '%s', $$%s$$)", txn_table, now, DBD_ADD_ACCOUNTS, object->name, user_name, info); xfree(info); if(!object->assoc_list) continue; list_transfer(assoc_list, object->assoc_list); } list_iterator_destroy(itr); xfree(user_name); if(rc == SLURM_SUCCESS) { if(txn_query) { xstrcat(txn_query, ";"); rc = pgsql_db_query(pg_conn->db_conn, txn_query); xfree(txn_query); if(rc != SLURM_SUCCESS) { error("as/pg: add_accts: couldn't add txn"); rc = SLURM_SUCCESS; } } } else xfree(txn_query); if(rc == SLURM_SUCCESS && list_count(assoc_list)) { if(acct_storage_p_add_associations(pg_conn, uid, assoc_list) != SLURM_SUCCESS) { error("as/pg: add_accts: problem adding account " "associations"); rc = SLURM_ERROR; } } list_destroy(assoc_list); return rc; }
/* * as_pg_get_clusters - get clusters * * IN pg_conn: database connection * IN uid: user performing the get operation * IN cluster_cond: which clusters to get * RET: the clusters */ extern List as_pg_get_clusters(pgsql_conn_t *pg_conn, uid_t uid, slurmdb_cluster_cond_t *cluster_cond) { DEF_VARS; char *cond = NULL; slurmdb_association_cond_t assoc_cond; slurmdb_cluster_rec_t *cluster = NULL; slurmdb_association_rec_t *assoc = NULL; List cluster_list = NULL, assoc_list = NULL; ListIterator itr = NULL, assoc_itr = NULL; /* if this changes you will need to edit the corresponding enum */ char *gc_fields = "name,classification,control_host,control_port," "rpc_version,dimensions,flags,plugin_id_select"; enum { F_NAME, F_CLASS, F_CH, F_CP, F_VERSION, F_DIMS, F_FLAGS, F_PI_SELECT, F_COUNT }; if (check_db_connection(pg_conn) != SLURM_SUCCESS) return NULL; if(!cluster_cond) { xstrcat(cond, "WHERE deleted=0"); goto empty; } if(cluster_cond->with_deleted) xstrcat(cond, "WHERE (deleted=0 OR deleted=1)"); else xstrcat(cond, "WHERE deleted=0"); concat_cond_list(cluster_cond->cluster_list, NULL, "name", &cond); empty: query = xstrdup_printf("SELECT %s FROM %s %s", gc_fields, cluster_table, cond); xfree(cond); result = DEF_QUERY_RET; if (!result) { error("failed to get clusters"); return NULL; } cluster_list = list_create(slurmdb_destroy_cluster_rec); memset(&assoc_cond, 0, sizeof(slurmdb_association_cond_t)); if(cluster_cond) { /* I don't think we want the with_usage flag here. * We do need the with_deleted though. */ //assoc_cond.with_usage = cluster_cond->with_usage; assoc_cond.with_deleted = cluster_cond->with_deleted; } /* not destroyed, since owned by cluster record */ assoc_cond.cluster_list = list_create(NULL); FOR_EACH_ROW { cluster = xmalloc(sizeof(slurmdb_cluster_rec_t)); list_append(cluster_list, cluster); cluster->name = xstrdup(ROW(F_NAME)); list_append(assoc_cond.cluster_list, cluster->name); /* get the usage if requested */ if(cluster_cond && cluster_cond->with_usage) { as_pg_get_usage(pg_conn, uid, cluster, DBD_GET_CLUSTER_USAGE, cluster_cond->usage_start, cluster_cond->usage_end); } cluster->classification = atoi(ROW(F_CLASS)); cluster->control_host = xstrdup(ROW(F_CH)); cluster->control_port = atoi(ROW(F_CP)); cluster->rpc_version = atoi(ROW(F_VERSION)); cluster->dimensions = atoi(ROW(F_DIMS)); cluster->flags = atoi(ROW(F_FLAGS)); cluster->plugin_id_select = atoi(ROW(F_PI_SELECT)); get_cluster_cpu_nodes(pg_conn, cluster); } END_EACH_ROW; PQclear(result); if(!list_count(assoc_cond.cluster_list)) { list_destroy(assoc_cond.cluster_list); return cluster_list; } /* get root assoc: <cluster, root, '', ''> */ assoc_cond.acct_list = list_create(NULL); list_append(assoc_cond.acct_list, "root"); assoc_cond.user_list = list_create(NULL); list_append(assoc_cond.user_list, ""); assoc_list = acct_storage_p_get_associations(pg_conn, uid, &assoc_cond); list_destroy(assoc_cond.cluster_list); list_destroy(assoc_cond.acct_list); list_destroy(assoc_cond.user_list); if(!assoc_list) return cluster_list; itr = list_iterator_create(cluster_list); assoc_itr = list_iterator_create(assoc_list); while((cluster = list_next(itr))) { while((assoc = list_next(assoc_itr))) { if(strcmp(assoc->cluster, cluster->name)) continue; if(cluster->root_assoc) { debug("This cluster %s already has " "an association.", cluster->name); continue; } cluster->root_assoc = assoc; list_remove(assoc_itr); } list_iterator_reset(assoc_itr); } list_iterator_destroy(itr); list_iterator_destroy(assoc_itr); if(list_count(assoc_list)) error("I have %d left over associations", list_count(assoc_list)); list_destroy(assoc_list); return cluster_list; }
/* * as_pg_remove_clusters - remove clusters * * IN pg_conn: database connection * IN uid: user performing the remove operation * IN cluster_cond: clusters to remove * RET: list of clusters removed */ extern List as_pg_remove_clusters(pgsql_conn_t *pg_conn, uint32_t uid, slurmdb_cluster_cond_t *cluster_cond) { DEF_VARS; List ret_list = NULL, job_list = NULL; int rc = SLURM_SUCCESS, has_jobs; char *cond = NULL, *user_name = NULL; time_t now = time(NULL); if(!cluster_cond) { error("as/pg: remove_clusters: we need something to remove"); return NULL; } if(check_db_connection(pg_conn) != SLURM_SUCCESS) return NULL; concat_cond_list(cluster_cond->cluster_list, NULL, "name", &cond); if(!cond) { error("as/pg: remove_clusters: nothing to remove"); return NULL; } query = xstrdup_printf("SELECT name FROM %s WHERE deleted=0 %s;", cluster_table, cond); xfree(cond); result = DEF_QUERY_RET; if (!result) { error("as/pg: remove_clusters: failed to get cluster names"); return NULL; } ret_list = list_create(slurm_destroy_char); if (PQntuples(result) == 0) { PQclear(result); errno = SLURM_NO_CHANGE_IN_DATA; debug3("didn't effect anything"); /* XXX: if we return NULL, test21.27 will fail to execute */ return ret_list; } user_name = uid_to_string((uid_t)uid); rc = 0; FOR_EACH_ROW { char *cluster = ROW(0); job_list = _get_cluster_running_jobs(pg_conn, cluster); if (job_list) break; has_jobs = _cluster_has_jobs(pg_conn, cluster); if (!has_jobs) query = xstrdup_printf( "DELETE FROM %s WHERE creation_time>%ld AND " "name='%s';", cluster_table, (now - DELETE_SEC_BACK), cluster); xstrfmtcat(query, "UPDATE %s SET mod_time=%ld, deleted=1 WHERE " "deleted=0 AND name='%s';", cluster_table, now, cluster); xstrfmtcat(query, "INSERT INTO %s (timestamp, action, name, actor) " "VALUES (%ld, %d, '%s', '%s');", txn_table, now, (int)DBD_REMOVE_CLUSTERS, cluster, user_name); rc = DEF_QUERY_RET_RC; if (rc != SLURM_SUCCESS) break; rc = _remove_cluster_tables(pg_conn, cluster); if (rc != SLURM_SUCCESS) break; list_append(ret_list, xstrdup(cluster)); addto_update_list(pg_conn->update_list, SLURMDB_REMOVE_CLUSTER, xstrdup(cluster)); pg_conn->cluster_changed = 1; } END_EACH_ROW; PQclear(result); if (job_list) { reset_pgsql_conn(pg_conn); list_destroy(ret_list); error("as/pg: remove_clusters: jobs running on cluster"); errno = ESLURM_JOBS_RUNNING_ON_ASSOC; return job_list; } if (rc != SLURM_SUCCESS) { reset_pgsql_conn(pg_conn); list_destroy(ret_list); ret_list = NULL; } return ret_list; }
/* * as_pg_modify_clusters - modify clusters * This is called by cs_p_register_ctld when ctld registers to dbd. * Also called when modify classification of cluster. * If you need to alter the default values of the cluster, use * modify_associations to change root association of the cluster. * * IN pg_conn: database connection * IN uid: user performing the modify operation * IN cluster_cond: which clusters to modify * IN cluster: attribute of clusters after modification * RET: list of clusters modified */ extern List as_pg_modify_clusters(pgsql_conn_t *pg_conn, uint32_t uid, slurmdb_cluster_cond_t *cluster_cond, slurmdb_cluster_rec_t *cluster) { DEF_VARS; List ret_list = NULL; int rc = SLURM_SUCCESS, set = 0; char *object = NULL, *user_name = NULL, *name_char = NULL; char *vals = NULL, *cond = NULL, *send_char = NULL; time_t now = time(NULL); bool clust_reg = false; if (!cluster_cond || !cluster) { error("as/pg: modify_clusters: we need something to change"); return NULL; } if(check_db_connection(pg_conn) != SLURM_SUCCESS) return NULL; if(!pg_conn->cluster_name && cluster_cond->cluster_list && list_count(cluster_cond->cluster_list)) pg_conn->cluster_name = xstrdup(list_peek(cluster_cond->cluster_list)); concat_cond_list(cluster_cond->cluster_list, NULL, "name", &cond); if(cluster_cond->classification) { xstrfmtcat(cond, " AND (classification & %u)", cluster_cond->classification); } set = 0; if (cluster->control_host) { xstrfmtcat(vals, ", control_host='%s'", cluster->control_host); set++; clust_reg = true; } if (cluster->control_port) { xstrfmtcat(vals, ", control_port=%u", cluster->control_port); set++; clust_reg = true; } if (cluster->rpc_version) { xstrfmtcat(vals, ", rpc_version=%u", cluster->rpc_version); set++; clust_reg = true; } if (cluster->dimensions) { xstrfmtcat(vals, ", dimensions=%u", cluster->dimensions); clust_reg = true; } if (cluster->plugin_id_select) { xstrfmtcat(vals, ", plugin_id_select=%u", cluster->plugin_id_select); clust_reg = true; } if (cluster->flags != NO_VAL) { xstrfmtcat(vals, ", flags=%u", cluster->flags); clust_reg = true; } if (cluster->classification) { xstrfmtcat(vals, ", classification=%u", cluster->classification); } if(!vals) { xfree(cond); errno = SLURM_NO_CHANGE_IN_DATA; error("as/pg: modify_clusters: nothing to change"); return NULL; } else if(clust_reg && (set != 3)) { xfree(vals); xfree(cond); errno = EFAULT; error("as/pg: modify_clusters: need control host, port and " "rpc version to register a cluster"); return NULL; } query = xstrdup_printf( "SELECT name, control_port FROM %s WHERE deleted=0 %s;", cluster_table, cond ?: ""); xfree(cond); result = DEF_QUERY_RET; if (!result) { xfree(vals); error("as/pg: modify_clusters: no result given"); return NULL; } rc = 0; ret_list = list_create(slurm_destroy_char); FOR_EACH_ROW { object = xstrdup(ROW(0)); list_append(ret_list, object); if(!rc) { xstrfmtcat(name_char, "name='%s'", object); rc = 1; } else { xstrfmtcat(name_char, " OR name='%s'", object); } } END_EACH_ROW; PQclear(result); if(!list_count(ret_list)) { errno = SLURM_NO_CHANGE_IN_DATA; debug3("as/pg: modify_cluster: nothing effected"); xfree(vals); return ret_list; } if(vals) { send_char = xstrdup_printf("(%s)", name_char); user_name = uid_to_string((uid_t) uid); rc = pgsql_modify_common(pg_conn, DBD_MODIFY_CLUSTERS, now, "", user_name, cluster_table, send_char, vals); xfree(user_name); xfree(send_char); if (rc != SLURM_SUCCESS) { error("Couldn't modify cluster 1"); list_destroy(ret_list); ret_list = NULL; goto end_it; } } end_it: xfree(name_char); xfree(vals); return ret_list; }
/* * as_pg_add_clusters - add clusters * * IN pg_conn: database connection * IN uid: user performing the add operation * IN cluster_list: clusters to add * RET: error code */ extern int as_pg_add_clusters(pgsql_conn_t *pg_conn, uint32_t uid, List cluster_list) { ListIterator itr = NULL; int rc = SLURM_SUCCESS, added = 0; slurmdb_cluster_rec_t *object = NULL; time_t now = time(NULL); List assoc_list = NULL; slurmdb_association_rec_t *assoc = NULL; char *txn_info = NULL, *query = NULL, *user_name = NULL; if (check_db_connection(pg_conn) != SLURM_SUCCESS) return ESLURM_DB_CONNECTION; assoc_list = list_create(slurmdb_destroy_association_rec); user_name = uid_to_string((uid_t) uid); itr = list_iterator_create(cluster_list); while((object = list_next(itr))) { if(!object->name) { error("as/pg: add_clusters: We need a cluster " "name to add."); rc = SLURM_ERROR; continue; } if (strchr(object->name, '.')) { error("as/pg: add_clusters: invalid cluster name %s", object->name); rc = SLURM_ERROR; continue; } if (cluster_in_db(pg_conn, object->name)) { error("cluster %s already added", object->name); rc = SLURM_ERROR; continue; } query = xstrdup_printf( "SELECT public.add_cluster(" "(%ld, %ld, 0, '%s', '', 0, 0, %u, 1, 0, 0));", (long)now, (long)now, object->name, object->classification); rc = DEF_QUERY_RET_RC; if(rc != SLURM_SUCCESS) { error("Couldn't add cluster %s", object->name); added = 0; /* rollback modification to DB */ break; } rc = _create_cluster_tables(pg_conn, object->name); if (rc != SLURM_SUCCESS) { error("Failed creating cluster tables for %s", object->name); added = 0; break; } /* add root account assoc: <'cluster', 'root', '', ''> */ if (add_cluster_root_assoc(pg_conn, now, object, &txn_info) != SLURM_SUCCESS) { added = 0; break; } if (add_txn(pg_conn, now, "", DBD_ADD_CLUSTERS, object->name, user_name, txn_info) != SLURM_SUCCESS) { error("as/pg: add_cluster: couldn't add txn"); } else { added ++; } xfree(txn_info); /* Add user root by default to run from the root * association. This gets popped off so we need to * read it every time here. */ assoc = xmalloc(sizeof(slurmdb_association_rec_t)); slurmdb_init_association_rec(assoc, 0); list_append(assoc_list, assoc); assoc->cluster = xstrdup(object->name); assoc->user = xstrdup("root"); assoc->acct = xstrdup("root"); if(acct_storage_p_add_associations(pg_conn, uid, assoc_list) == SLURM_ERROR) { error("Problem adding root user association"); rc = SLURM_ERROR; } list_flush(assoc_list); /* do not add it again, in case not popped */ } list_iterator_destroy(itr); xfree(user_name); list_destroy(assoc_list); if (!added) { reset_pgsql_conn(pg_conn); } else { /* when loading sacctmgr cfg file, get_assoc will be called before commit */ pg_conn->cluster_changed = 1; } return rc; }
/* * js_pg_job_start - load into the storage the start of a job * * IN pg_conn: database connection * IN cluster_name: cluster of the job * IN job_ptr: job just started * RET: error code */ extern int js_pg_job_start(pgsql_conn_t *pg_conn, struct job_record *job_ptr) { int rc=SLURM_SUCCESS, track_steps = 0, reinit = 0; char *jname = NULL, *nodes = NULL, *node_inx = NULL; char *block_id = NULL, *rec = NULL, *query = NULL; time_t begin_time, check_time, start_time, submit_time; int job_state, node_cnt = 0; uint32_t wckeyid = 0; if ((!job_ptr->details || !job_ptr->details->submit_time) && !job_ptr->resize_time) { error("as/pg: job_start: Not inputing this job, " "it has no submit time."); return SLURM_ERROR; } if (check_db_connection(pg_conn) != SLURM_SUCCESS) return ESLURM_DB_CONNECTION; if (! cluster_in_db(pg_conn, pg_conn->cluster_name) ) { error("cluster %s not in db", pg_conn->cluster_name); return SLURM_ERROR; } debug3("as/pg: job_start() called"); job_state = job_ptr->job_state; /* Since we need a new db_inx make sure the old db_inx * removed. This is most likely the only time we are going to * be notified of the change also so make the state without * the resize. */ if (IS_JOB_RESIZING(job_ptr)) { /* If we have a db_index lets end the previous record. */ if (job_ptr->db_index) js_pg_job_complete(pg_conn, job_ptr); else error("We don't have a db_index for job %u, " "this should never happen.", job_ptr->job_id); job_state &= (~JOB_RESIZING); job_ptr->db_index = 0; } job_state &= JOB_STATE_BASE; if (job_ptr->resize_time) { begin_time = job_ptr->resize_time; submit_time = job_ptr->resize_time; start_time = job_ptr->resize_time; } else { begin_time = job_ptr->details->begin_time; submit_time = job_ptr->details->submit_time; start_time = job_ptr->start_time; } /* See what we are hearing about here if no start time. If * this job latest time is before the last roll up we will * need to reset it to look at this job. */ if (start_time) check_time = start_time; else if (begin_time) check_time = begin_time; else check_time = submit_time; slurm_mutex_lock(&usage_rollup_lock); if (check_time < global_last_rollup) { PGresult *result = NULL; /* check to see if we are hearing about this time for the * first time. */ query = xstrdup_printf( "SELECT job_db_inx FROM %s.%s WHERE id_job=%u AND " "time_submit=%ld AND time_eligible=%ld AND time_start=%ld", pg_conn->cluster_name, job_table, job_ptr->job_id, submit_time, begin_time, start_time); result = DEF_QUERY_RET; if (!result) { slurm_mutex_unlock(&usage_rollup_lock); return SLURM_ERROR; } if (PQntuples(result) != 0) { PQclear(result); debug4("revieved an update for a " "job (%u) already known about", job_ptr->job_id); slurm_mutex_unlock(&usage_rollup_lock); goto no_rollup_change; } PQclear(result); if (job_ptr->start_time) debug("Need to reroll usage from %s Job %u " "from %s started then and we are just " "now hearing about it.", ctime(&check_time), job_ptr->job_id, pg_conn->cluster_name); else if (begin_time) debug("Need to reroll usage from %s Job %u " "from %s became eligible then and we are just " "now hearing about it.", ctime(&check_time), job_ptr->job_id, pg_conn->cluster_name); else debug("Need to reroll usage from %s Job %u " "from %s was submitted then and we are just " "now hearing about it.", ctime(&check_time), job_ptr->job_id, pg_conn->cluster_name); global_last_rollup = check_time; slurm_mutex_unlock(&usage_rollup_lock); query = xstrdup_printf("UPDATE %s.%s SET hourly_rollup=%ld, " "daily_rollup=%ld, monthly_rollup=%ld", pg_conn->cluster_name, last_ran_table, check_time, check_time, check_time); rc = DEF_QUERY_RET_RC; } else slurm_mutex_unlock(&usage_rollup_lock); no_rollup_change: if (job_ptr->name && job_ptr->name[0]) jname = xstrdup(job_ptr->name); else { jname = xstrdup("allocation"); track_steps = 1; } if (job_ptr->nodes && job_ptr->nodes[0]) nodes = job_ptr->nodes; else nodes = "None assigned"; if (job_ptr->batch_flag) track_steps = 1; if (slurmdbd_conf) { block_id = xstrdup(job_ptr->comment); node_cnt = job_ptr->total_nodes; node_inx = job_ptr->network; } else { char temp_bit[BUF_SIZE]; if (job_ptr->node_bitmap) { node_inx = bit_fmt(temp_bit, sizeof(temp_bit), job_ptr->node_bitmap); } #ifdef HAVE_BG select_g_select_jobinfo_get(job_ptr->select_jobinfo, SELECT_JOBDATA_BLOCK_ID, &block_id); select_g_select_jobinfo_get(job_ptr->select_jobinfo, SELECT_JOBDATA_NODE_CNT, &node_cnt); #else node_cnt = job_ptr->total_nodes; #endif } /* If there is a start_time get the wckeyid. If the job is * cancelled before the job starts we also want to grab it. */ if (job_ptr->assoc_id && (job_ptr->start_time || IS_JOB_CANCELLED(job_ptr))) wckeyid = get_wckeyid(pg_conn, &job_ptr->wckey, job_ptr->user_id, pg_conn->cluster_name, job_ptr->assoc_id); if (!job_ptr->db_index) { if (!begin_time) begin_time = submit_time; rec = xstrdup_printf( "(0, 0, '%s', '%s', %d, %d, 0, '%s', " "%d, '%s', %d, %d, %d, %d, %d, %d, 0, " "%d, %ld, %ld, %ld, 0, 0, " "%d, '%s', '%s', %d, %d, '%s', %d)", /* job_db_inx=0, not used */ /* deleted=0 */ job_ptr->account ?: "", /* account */ job_ptr->partition ?: "", /* partition */ (int)job_ptr->details->min_cpus, /* cpus_req */ (int)job_ptr->total_cpus, /* cpus_alloc */ /* exit_code=0 */ jname, /* job_name */ (int)job_ptr->assoc_id, /* id_assoc */ block_id ?: "", /* id_block */ (int)job_ptr->job_id, /* id_job */ (int)job_ptr->qos_id, /* id_qos */ (int)job_ptr->resv_id, /* id_resv */ (int)wckeyid, /* id_wckey */ (int)job_ptr->user_id, /* uid */ (int)job_ptr->group_id, /* gid */ /* kill_requid=0 */ (int)job_ptr->time_limit, /* timelimit */ submit_time, /* time_submit */ begin_time, /* time_eligible */ start_time, /* time_start */ /* time_end=0 */ /* time_suspended=0 */ (int)node_cnt, /* nodes_alloc */ nodes ?: "", /* nodelist */ node_inx ?: "", /* node_inx */ (int)job_ptr->priority, /* priority */ (int)job_state, /* state */ job_ptr->wckey ?: "", /* wckey */ (int)track_steps); query = xstrdup_printf("SELECT %s.add_job_start(%s);", pg_conn->cluster_name, rec); xfree(rec); try_again: DEBUG_QUERY; job_ptr->db_index = pgsql_query_ret_id(pg_conn->db_conn, query); if (!job_ptr->db_index) { if (!reinit) { error("It looks like the storage has gone " "away trying to reconnect"); check_db_connection(pg_conn); reinit = 1; goto try_again; } else rc = SLURM_ERROR; } xfree(query); } else {