1 /****************************************************************************\
2 * update_config.c - request that slurmctld update its configuration
3 *****************************************************************************
4 * Copyright (C) 2002-2007 The Regents of the University of California.
5 * Copyright (C) 2008-2010 Lawrence Livermore National Security.
6 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
7 * Written by Morris Jette <jette1@llnl.gov> and Kevin Tew <tew1@llnl.gov>.
8 * CODE-OCEC-09-009. All rights reserved.
9 *
10 * This file is part of Slurm, a resource management program.
11 * For details, see <https://slurm.schedmd.com/>.
12 * Please also read the included file: DISCLAIMER.
13 *
14 * Slurm is free software; you can redistribute it and/or modify it under
15 * the terms of the GNU General Public License as published by the Free
16 * Software Foundation; either version 2 of the License, or (at your option)
17 * any later version.
18 *
19 * In addition, as a special exception, the copyright holders give permission
20 * to link the code of portions of this program with the OpenSSL library under
21 * certain conditions as described in each individual source file, and
22 * distribute linked combinations including the two. You must obey the GNU
23 * General Public License in all respects for all of the code used other than
24 * OpenSSL. If you modify file(s) with this exception, you may extend this
25 * exception to your version of the file(s), but you are not obligated to do
26 * so. If you do not wish to do so, delete this exception statement from your
27 * version. If you delete this exception statement from all source files in
28 * the program, then also delete it here.
29 *
30 * Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
31 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
32 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
33 * details.
34 *
35 * You should have received a copy of the GNU General Public License along
36 * with Slurm; if not, write to the Free Software Foundation, Inc.,
37 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
38 \*****************************************************************************/
39
40 #include <errno.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include "slurm/slurm.h"
46
47 #include "src/common/slurm_protocol_api.h"
48
49 static int _slurm_update (void * data, slurm_msg_type_t msg_type);
50
51 /*
52 * slurm_update_front_end - issue RPC to a front_end node's configuration per
53 * request, only usable by user root
54 * IN front_end_msg - description of front_end node updates
55 * RET SLURM_SUCCESS on success, otherwise return SLURM_ERROR with errno set
56 */
57 int
slurm_update_front_end(update_front_end_msg_t * front_end_msg)58 slurm_update_front_end (update_front_end_msg_t * front_end_msg)
59 {
60 return _slurm_update ((void *) front_end_msg, REQUEST_UPDATE_FRONT_END);
61 }
62
63 /*
64 * slurm_update_job - issue RPC to a job's configuration per request,
65 * only usable by user root or (for some parameters) the job's owner
66 * IN job_msg - description of job updates
67 * RET SLURM_SUCCESS on success, otherwise return SLURM_ERROR with errno set
68 */
69 int
slurm_update_job(job_desc_msg_t * job_msg)70 slurm_update_job (job_desc_msg_t * job_msg)
71 {
72 if (job_msg->job_id_str) {
73 error("Use slurm_update_job2() rather than slurm_update_job() "
74 "with job_msg->job_id_str to get multiple error codes "
75 "for various job array task and avoid memory leaks");
76 }
77 return _slurm_update ((void *) job_msg, REQUEST_UPDATE_JOB);
78 }
79
80 /*
81 * slurm_update_job2 - issue RPC to a job's configuration per request,
82 * only usable by user root or (for some parameters) the job's owner
83 * IN job_msg - description of job updates
84 * OUT resp - per task response to the request,
85 * free using slurm_free_job_array_resp()
86 * RET SLURM_SUCCESS on success, otherwise return SLURM_ERROR with errno set
87 */
88 extern int
slurm_update_job2(job_desc_msg_t * job_msg,job_array_resp_msg_t ** resp)89 slurm_update_job2 (job_desc_msg_t * job_msg, job_array_resp_msg_t **resp)
90 {
91 int rc = SLURM_SUCCESS;
92 slurm_msg_t req_msg, resp_msg;
93 slurmdb_cluster_rec_t *save_working_cluster_rec = working_cluster_rec;
94
95 slurm_msg_t_init(&req_msg);
96 req_msg.msg_type = REQUEST_UPDATE_JOB;
97 req_msg.data = job_msg;
98
99 tryagain:
100 slurm_msg_t_init(&resp_msg);
101
102 rc = slurm_send_recv_controller_msg(&req_msg, &resp_msg,
103 working_cluster_rec);
104 switch (resp_msg.msg_type) {
105 case RESPONSE_SLURM_REROUTE_MSG:
106 {
107 reroute_msg_t *rr_msg = (reroute_msg_t *)resp_msg.data;
108
109 /* Don't expect mutliple hops but in the case it does
110 * happen, free the previous rr cluster_rec. */
111 if (working_cluster_rec &&
112 working_cluster_rec != save_working_cluster_rec)
113 slurmdb_destroy_cluster_rec(
114 working_cluster_rec);
115
116 working_cluster_rec = rr_msg->working_cluster_rec;
117 slurmdb_setup_cluster_rec(working_cluster_rec);
118 rr_msg->working_cluster_rec = NULL;
119 goto tryagain;
120 }
121 case RESPONSE_JOB_ARRAY_ERRORS:
122 *resp = (job_array_resp_msg_t *) resp_msg.data;
123 break;
124 case RESPONSE_SLURM_RC:
125 rc = ((return_code_msg_t *) resp_msg.data)->return_code;
126 if (rc)
127 slurm_seterrno(rc);
128 break;
129 default:
130 slurm_seterrno(SLURM_UNEXPECTED_MSG_ERROR);
131 }
132
133 if (working_cluster_rec != save_working_cluster_rec) {
134 slurmdb_destroy_cluster_rec(working_cluster_rec);
135 working_cluster_rec = save_working_cluster_rec;
136 }
137
138 return rc;
139 }
140
141 /*
142 * slurm_update_node - issue RPC to a node's configuration per request,
143 * only usable by user root
144 * IN node_msg - description of node updates
145 * RET SLURM_SUCCESS on success, otherwise return SLURM_ERROR with errno set
146 */
147 int
slurm_update_node(update_node_msg_t * node_msg)148 slurm_update_node ( update_node_msg_t * node_msg)
149 {
150 return _slurm_update ((void *) node_msg, REQUEST_UPDATE_NODE);
151 }
152 /*
153 * slurm_update_layout - issue RPC to a layout's configuration per request,
154 * only usable by user root
155 * IN layout_msg - command line (same format as conf)
156 * RET SLURM_SUCCESS on success, otherwise return SLURM_ERROR with errno set
157 */
158 int
slurm_update_layout(update_layout_msg_t * layout_msg)159 slurm_update_layout ( update_layout_msg_t * layout_msg)
160 {
161 return _slurm_update ((void *) layout_msg, REQUEST_UPDATE_LAYOUT);
162 }
163
164 /*
165 * slurm_create_partition - create a new partition, only usable by user root
166 * IN part_msg - description of partition configuration
167 * RET SLURM_SUCCESS on success, otherwise return SLURM_ERROR with errno set
168 */
169 int
slurm_create_partition(update_part_msg_t * part_msg)170 slurm_create_partition ( update_part_msg_t * part_msg)
171 {
172 return _slurm_update ((void *) part_msg, REQUEST_CREATE_PARTITION);
173 }
174
175 /*
176 * slurm_update_partition - issue RPC to a partition's configuration per
177 * request, only usable by user root
178 * IN part_msg - description of partition updates
179 * RET SLURM_SUCCESS on success, otherwise return SLURM_ERROR with errno set
180 */
181 int
slurm_update_partition(update_part_msg_t * part_msg)182 slurm_update_partition ( update_part_msg_t * part_msg )
183 {
184 return _slurm_update ((void *) part_msg, REQUEST_UPDATE_PARTITION);
185 }
186
187 /*
188 * slurm_delete_partition - issue RPC to delete a partition, only usable
189 * by user root
190 * IN part_msg - description of partition to delete
191 * RET SLURM_SUCCESS on success, otherwise return SLURM_ERROR with errno set
192 */
193 int
slurm_delete_partition(delete_part_msg_t * part_msg)194 slurm_delete_partition ( delete_part_msg_t * part_msg )
195 {
196 return _slurm_update ((void *) part_msg, REQUEST_DELETE_PARTITION);
197 }
198
199 /*
200 * slurm_update_powercap - issue RPC to update powercapping cap
201 * IN powercap_msg - description of powercapping updates
202 * RET SLURM_SUCCESS on success, otherwise return SLURM_ERROR with errno set
203 */
204 int
slurm_update_powercap(update_powercap_msg_t * powercap_msg)205 slurm_update_powercap ( update_powercap_msg_t * powercap_msg )
206 {
207 return _slurm_update ((void *) powercap_msg, REQUEST_UPDATE_POWERCAP);
208 }
209
210 /*
211 * slurm_create_reservation - create a new reservation, only usable by user root
212 * IN resv_msg - description of reservation
213 * RET name of reservation on success (caller must free the memory),
214 * otherwise return NULL and set errno to indicate the error
215 */
216 char *
slurm_create_reservation(resv_desc_msg_t * resv_msg)217 slurm_create_reservation (resv_desc_msg_t * resv_msg)
218 {
219 int rc;
220 char *resv_name = NULL;
221 slurm_msg_t req_msg;
222 slurm_msg_t resp_msg;
223 reservation_name_msg_t *resp;
224
225 slurm_msg_t_init(&req_msg);
226 slurm_msg_t_init(&resp_msg);
227
228 req_msg.msg_type = REQUEST_CREATE_RESERVATION;
229 req_msg.data = resv_msg;
230
231 rc = slurm_send_recv_controller_msg(&req_msg, &resp_msg,
232 working_cluster_rec);
233 if (rc)
234 slurm_seterrno(rc);
235 switch (resp_msg.msg_type) {
236 case RESPONSE_CREATE_RESERVATION:
237 resp = (reservation_name_msg_t *) resp_msg.data;
238 resv_name = strdup(resp->name);
239 break;
240 case RESPONSE_SLURM_RC:
241 rc = ((return_code_msg_t *) resp_msg.data)->return_code;
242 if (rc)
243 slurm_seterrno(rc);
244 break;
245 default:
246 slurm_seterrno(SLURM_UNEXPECTED_MSG_ERROR);
247 }
248 slurm_free_msg_data(resp_msg.msg_type, resp_msg.data);
249 return resv_name;
250 }
251
252 /*
253 * slurm_update_reservation - modify an existing reservation, only usable by
254 * user root
255 * IN resv_msg - description of reservation
256 * RET SLURM_SUCCESS on success, otherwise return SLURM_ERROR with errno set
257 */
slurm_update_reservation(resv_desc_msg_t * resv_msg)258 extern int slurm_update_reservation (resv_desc_msg_t * resv_msg)
259 {
260 return _slurm_update ((void *) resv_msg, REQUEST_UPDATE_RESERVATION);
261 }
262
263 /*
264 * slurm_delete_reservation - issue RPC to delete a reservation, only usable
265 * by user root
266 * IN resv_msg - description of reservation to delete
267 * RET SLURM_SUCCESS on success, otherwise return SLURM_ERROR with errno set
268 */
269 int
slurm_delete_reservation(reservation_name_msg_t * resv_msg)270 slurm_delete_reservation (reservation_name_msg_t * resv_msg)
271 {
272 return _slurm_update ((void *) resv_msg, REQUEST_DELETE_RESERVATION);
273 }
274
275 /* Update the time limit of a job step,
276 * step_id == NO_VAL updates all job steps of the specified job_id
277 * RET 0 or -1 on error */
278 int
slurm_update_step(step_update_request_msg_t * step_msg)279 slurm_update_step (step_update_request_msg_t * step_msg)
280 {
281 return _slurm_update ((void *) step_msg, REQUEST_UPDATE_JOB_STEP);
282 }
283
284 /*
285 * Move the specified job ID to the top of the queue for a given user ID,
286 * partition, account, and QOS.
287 * IN job_id_str - a job id
288 * RET 0 or -1 on error */
289 extern int
slurm_top_job(char * job_id_str)290 slurm_top_job(char *job_id_str)
291 {
292 int rc = SLURM_SUCCESS;
293 top_job_msg_t top_job_req;
294 slurm_msg_t req_msg;
295
296 slurm_msg_t_init(&req_msg);
297 memset(&top_job_req, 0, sizeof(top_job_req));
298 top_job_req.job_id_str = job_id_str;
299 req_msg.msg_type = REQUEST_TOP_JOB;
300 req_msg.data = &top_job_req;
301
302 if (slurm_send_recv_controller_rc_msg(&req_msg, &rc,
303 working_cluster_rec) < 0)
304 return SLURM_ERROR;
305
306 slurm_seterrno(rc);
307 return rc;
308 }
309
310 /* _slurm_update - issue RPC for all update requests */
311 static int
_slurm_update(void * data,slurm_msg_type_t msg_type)312 _slurm_update (void *data, slurm_msg_type_t msg_type)
313 {
314 int rc;
315 slurm_msg_t req_msg;
316
317 slurm_msg_t_init(&req_msg);
318 req_msg.msg_type = msg_type;
319 req_msg.data = data;
320
321 if (slurm_send_recv_controller_rc_msg(&req_msg, &rc,
322 working_cluster_rec) < 0)
323 return SLURM_ERROR;
324
325 if (rc != SLURM_SUCCESS)
326 slurm_seterrno_ret(rc);
327
328 return SLURM_SUCCESS;
329 }
330