/* * 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_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; }