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