1 /*****************************************************************************\
2  *  layouts_mgr.h - layouts manager data structures and main functions
3  *****************************************************************************
4  *  Initially written by Francois Chevallier <chevallierfrancois@free.fr>
5  *  at Bull for slurm-2.6.
6  *  Adapted by Matthieu Hautreux <matthieu.hautreux@cea.fr> for slurm-14.11.
7  *  Enhanced by Matthieu Hautreux <matthieu.hautreux@cea.fr> for slurm-15.x.
8  *
9  *  This file is part of Slurm, a resource management program.
10  *  For details, see <https://slurm.schedmd.com/>.
11  *  Please also read the included file: DISCLAIMER.
12  *
13  *  Slurm is free software; you can redistribute it and/or modify it under
14  *  the terms of the GNU General Public License as published by the Free
15  *  Software Foundation; either version 2 of the License, or (at your option)
16  *  any later version.
17  *
18  *  In addition, as a special exception, the copyright holders give permission
19  *  to link the code of portions of this program with the OpenSSL library under
20  *  certain conditions as described in each individual source file, and
21  *  distribute linked combinations including the two. You must obey the GNU
22  *  General Public License in all respects for all of the code used other than
23  *  OpenSSL. If you modify file(s) with this exception, you may extend this
24  *  exception to your version of the file(s), but you are not obligated to do
25  *  so. If you do not wish to do so, delete this exception statement from your
26  *  version.  If you delete this exception statement from all source files in
27  *  the program, then also delete it here.
28  *
29  *  Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
30  *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
31  *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
32  *  details.
33  *
34  *  You should have received a copy of the GNU General Public License along
35  *  with Slurm; if not, write to the Free Software Foundation, Inc.,
36  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
37 \*****************************************************************************/
38 
39 #ifndef __LAYOUTS_MGR_1NRINRSD__INC__
40 #define __LAYOUTS_MGR_1NRINRSD__INC__
41 
42 #include "src/common/list.h"
43 #include "src/common/xhash.h"
44 #include "src/common/xtree.h"
45 #include "src/common/pack.h"
46 #include "src/common/parse_config.h"
47 
48 #include "src/common/layout.h"
49 #include "src/common/entity.h"
50 
51 /*
52  * Layouts are managed through a "layouts manager" of type layouts_mgr_t.
53  *
54  * The layouts_mgr_t manages the layouts and entities loaded through the list
55  * of layouts specified in the Slurm configuration file (slurm.conf)
56  *
57  * At startup, Slurm initialize one layouts_mgr_t using layouts_init()
58  * and then load the required layouts defined in the configuration using
59  * layouts_load_config().
60  *
61  * The different layouts and entities can then be queried using either
62  * layouts_get_layout() and layouts_get_entity().
63  *
64  * Note that each entity contains a list of nodes appearing inside the
65  * associated layouts.
66  */
67 
68 /*
69  * Potential enhancement to complete: agregate specified plugin etypes in a
70  *      xhash in the mgr, avoiding same string to be duplicated again and again.
71  *      (in short: apply the same logic for etypes as for entity data keys.)
72  */
73 
74 typedef enum layouts_keydef_types_en {
75 	L_T_ERROR = 0,
76 	L_T_STRING,
77 	L_T_LONG,
78 	L_T_UINT16,
79 	L_T_UINT32,
80 	L_T_BOOLEAN,
81 	L_T_FLOAT,
82 	L_T_DOUBLE,
83 	L_T_LONG_DOUBLE,
84 	L_T_CUSTOM,
85 } layouts_keydef_types_t;
86 
87 /* keyspec flags */
88 #define KEYSPEC_RDONLY        0x00000001
89 
90 #define KEYSPEC_UPDATE_CHILDREN_SUM   0x00010000
91 #define KEYSPEC_UPDATE_CHILDREN_AVG   0x00020000
92 #define KEYSPEC_UPDATE_CHILDREN_MIN   0x00040000
93 #define KEYSPEC_UPDATE_CHILDREN_MAX   0x00080000
94 #define KEYSPEC_UPDATE_CHILDREN_COUNT 0x00110000
95 #define KEYSPEC_UPDATE_CHILDREN_MASK  0x00FF0000
96 
97 #define KEYSPEC_UPDATE_PARENTS_SUM    0x01000000
98 #define KEYSPEC_UPDATE_PARENTS_AVG    0x02000000
99 #define KEYSPEC_UPDATE_PARENTS_MIN    0x04000000
100 #define KEYSPEC_UPDATE_PARENTS_MAX    0x08000000
101 #define KEYSPEC_UPDATE_PARENTS_FSHARE 0x11000000
102 #define KEYSPEC_UPDATE_PARENTS_MASK   0xFF000000
103 
104 typedef struct layouts_keyspec_st {
105 	char*			key;
106 	layouts_keydef_types_t	type;
107 	uint32_t                flags;
108 	char*			ref_key; /* reference key to use for update
109 					  * NULL means use the same key in my
110 					  * neighborhood */
111 	void			(*custom_destroy)(void*);
112 	char*			(*custom_dump)(void*);
113 } layouts_keyspec_t;
114 
115 typedef struct layouts_plugin_spec_st {
116 	const s_p_options_t*		options;
117 	const layouts_keyspec_t*	keyspec;
118 	int				struct_type;
119 	const char**			etypes;
120 	bool				automerge;
121 	bool				autoupdate;
122 } layouts_plugin_spec_t;
123 
124 /*****************************************************************************\
125  *                             PLUGIN FUNCTIONS                              *
126 \*****************************************************************************/
127 
128 /*
129  * layouts_init - intialize the layouts mgr, load the required plugins
130  *        and initialize the internal hash tables for entities, keydefs and
131  *        layouts.
132  *
133  * Return SLURM_SUCCESS or SLURM_ERROR if all the required layouts were not
134  * loaded correctly.
135  *
136  * Notes: this call do not try to read and parse the layouts configuration
137  * files. It only loads the layouts plugins, dlsym the layout API and conf
138  * elements to prepare the reading and parsing performed in the adhoc call
139  * layouts_load_config()
140  *
141  */
142 int layouts_init(void);
143 
144 /*
145  * layouts_fini - uninitialize the layouts mgr and free the internal
146  *        hash tables.
147  */
148 int layouts_fini(void);
149 
150 /*
151  * layouts_load_config - use the layouts plugins details loaded during
152  *        layouts_init() and read+parse the different layouts
153  *        configuration files, creating the entities and the relational
154  *        structures associated the eaf of them.
155  *
156  * IN recover - update entities information with the latest available
157  *              information depending upon value
158  *              0 = use no saved state information, rebuild everything from
159  *		    layouts conf files contents
160  *              1 = recover saved entities information
161  *              2 = recover saved entities information
162  *
163  * Return SLURM_SUCCESS or SLURM_ERROR if all the required layouts were not
164  * loaded correctly.
165  */
166 int layouts_load_config(int recover);
167 
168 /*
169  * layouts_get_layout - return the layout from a given type
170  *
171  * Return a pointer to the layout_t struct of the layout or NULL if not found
172  */
173 layout_t* layouts_get_layout(const char* type);
174 
175 /*
176  * layouts_get_entity - return the entity from a given name
177  *
178  * Return a pointer to the entity_t struct of the entity or NULL if not found
179  */
180 entity_t* layouts_get_entity(const char* name);
181 
182 /*
183  * layouts_pack_layout - pack the layout of the target type into the provided
184  *        buffer.
185  *
186  * The buffer will be appended with multiple strings representing an expanded
187  * form of its configuration element, terminated by a "\0" string.
188  *
189  * Return SLURM_SUCCES or SLURM_ERROR in case of failure
190  */
191 int layouts_pack_layout(char *l_type, char *entities, char *type,
192 			uint32_t flags, Buf buffer);
193 
194 /*
195  * layouts_update_layout - update a particular layout loading the information
196  *        provided in the input buffer.
197  *
198  * The buffer must contain multiple strings corresponding to the different
199  * configuration lines similar to those that can be put in a configuration
200  * file that will be parsed and integrated.
201  *
202  * Note that the entities key/value entries will be updated only.
203  *
204  * Return SLURM_SUCCES or SLURM_ERROR in case of failure
205  */
206 int layouts_update_layout(char *l_type, Buf buffer);
207 
208 /*
209  * layouts_state_save_layout - save the state of a particular layout
210  *        in the adhoc file in slurm state save location.
211  *
212  * The file produced will be an ASCII file created from the configuration
213  * strings packed using layouts_pack_layout(). Thus it will be the expanded
214  * form of the current configuration of the layout that could be used as
215  * a perfect updated replacement of the layout configuration file.
216  *
217  * Return SLURM_SUCCES or SLURM_ERROR in case of failure
218  */
219 int layouts_state_save_layout(char* l_type);
220 
221 /*
222  * layouts_state_save - save the state of all the loaded layouts iterating
223  *        over each one of them and applying layouts_state_save_layout().
224  *
225  * Return SLURM_SUCCES or SLURM_ERROR in case of failure
226  */
227 int layouts_state_save(void);
228 
229 /*
230  * layouts_entity_get_kv_type - get the type of the value associated with a key
231  *        of an entity in a particular layout.
232  *
233  * The returned type is a member of the layouts_keydef_types_t enum :
234  * L_T_ERROR, L_T_STRING, L_T_LONG, L_T_UINT16, ...
235  *
236  * Return the requested type or SLURM_ERROR in case of failure
237  */
238 int layouts_entity_get_kv_type(char* layout, char* entity,
239 			       char* key);
240 
241 /*
242  * layouts_entity_get_kv_flags - get the keyspec flags associated with the
243  *        targeted key/value pair of an entity in a particular layout.
244  *
245  * Return the associated flags or SLURM_ERROR in case of failure
246  */
247 int layouts_entity_get_kv_flags(char* layout, char* entity,
248 				char* key);
249 
250 /*
251  * layouts_entity_push_kv - update the layout internal states to take into
252  *        account the current state of the targeted key/value pair.
253  *
254  * This ensures that the child and/or parents of the targeted entity in the
255  * targeted layout are synchronized with the current value associated with
256  * the key.
257  *
258  * Note: this call only makes sense when the targeted k/v is a k/v that helps
259  *       to dynamically compute its parents and/or children. It is a
260  *       no-op otherwise that just returns SLURM_SUCCESS.
261  *
262  * Return SLURM_SUCCES or SLURM_ERROR in case of failure
263  */
264 int layouts_entity_push_kv(char* layout, char* entity,
265 			   char* key);
266 
267 /*
268  * layouts_entity_pull_kv - synchronize the targeted key/value pair based on
269  *        the states of their neighborhood in the targeted layout.
270  *
271  * This ensures that the K/V is up-to-date and correspond to the values that
272  *        its neighborhood in the layout think it should have.
273  *
274  * Note: this call only makes sense when the targeted k/v is a k/v that is
275  *       dynamically computed based on its parents and/or children. It is a
276  *       no-op otherwise that just returns SLURM_SUCCESS.
277  *
278  * Return SLURM_SUCCES or SLURM_ERROR in case of failure
279  */
280 int layouts_entity_pull_kv(char* layout, char* entity,
281 			   char* key);
282 
283 /*
284  * layouts_entity_set_kv - update an entity with a new value for a particular
285  *        key in the targeted layout.
286  *
287  * The input key_type will force the call to check types consistency between
288  * the requester and the underlying keyspec associated with the key. To skip
289  * that check the caller will have to pass a 0 value.
290  *
291  * Note : in case the key/value is already set for the entity, the content of
292  * the provided buffer will override the current content. In case the key/value
293  * already exists, it will be xfree and a new memory allocation will be
294  * performed and the content of the provided buffer dumped into it.
295  *
296  * Return SLURM_SUCCES or SLURM_ERROR in case of failure
297  */
298 int layouts_entity_set_kv(char* layout, char* entity,
299 			  char* key, void* value,
300 			  layouts_keydef_types_t key_type);
301 
302 /*
303  * layouts_entity_set_kv_ref - replace an entity key value with a new memory
304  *        area for a particular key in the targeted layout
305  *
306  * The input key_type will force the call to check types consistency between
307  * the requester and the underlying keyspec associated with the key. To skip
308  * that check the caller will have to pass a 0 value.
309  *
310  * Note : in case the key/value is already set for the entity, the older value
311  * will be free and the provided buffer will be associated to the new value.
312  * Once done, the caller must not free the provided buffer has it will then
313  * be owned by the layout logic and will be free automatically when the layout
314  * framework will be unloaded or at a next call to that function.
315  *
316  * Return SLURM_SUCCES or SLURM_ERROR in case of failure
317  */
318 int layouts_entity_set_kv_ref(char* layout, char* entity,
319 			      char* key, void* value,
320 			      layouts_keydef_types_t key_type);
321 
322 /*
323  * layouts_entity_setpush_kv - combination of layouts_entity_set_kv and
324  *        layouts_entity_push_kv to update an entity with a new value and force
325  *        the synchronization of its neighborhood in the layout.
326  *
327  * The input key_type will force the call to check types consistency between
328  * the requester and the underlying keyspec associated with the key. To skip
329  * that check the caller will have to pass a 0 value.
330  *
331  * Note: see layouts_entity_push_kv.
332  *
333  * Return SLURM_SUCCES or SLURM_ERROR in case of failure
334  */
335 int layouts_entity_setpush_kv(char* layout, char* entity,
336 			      char* key, void* value,
337 			      layouts_keydef_types_t key_type);
338 
339 /*
340  * layouts_entity_setpush_kv - combination of layouts_entity_set_kv_ref and
341  *        layouts_entity_push_kv to replace an entity key value with a new
342  *        memory area and force the synchronization of its neighborhood in
343  *        the layout.
344  *
345  * The input key_type will force the call to check types consistency between
346  * the requester and the underlying keyspec associated with the key. To skip
347  * that check the caller will have to pass a 0 value.
348  *
349  * Note: see layouts_entity_push_kv.
350  *
351  * Return SLURM_SUCCES or SLURM_ERROR in case of failure
352  */
353 int layouts_entity_setpush_kv_ref(char* layout, char* entity,
354 				  char* key, void* value,
355 				  layouts_keydef_types_t key_type);
356 
357 /*
358  * layouts_entity_get_kv - get the value associated with a key of an entity
359  *        in a particular layout.
360  *
361  * The input key_type will force the call to check types consistency between
362  * the requester and the underlying keyspec associated with the key. To skip
363  * that check the caller will have to pass a 0 value.
364  *
365  * Note : the destination buffer will be filled with the content of the
366  * value associated with the requested key in the entity except for these
367  * types for which :
368  *   L_T_STRING  : value must be the address of the char* that will be
369  *                 xstrduped with the key value. The char* will have to be
370  *                 xfree() after that.
371  *   L_T_CUSTOM : value must be the address of the char* that will result
372  *                of the custom_dump function. The char* will have to be
373  *                xfree() after that.
374  *   L_T_ERROR : will return SLURM_ERROR in all cases.
375  *
376  * Return SLURM_SUCCES or SLURM_ERROR in case of failure
377  */
378 int layouts_entity_get_kv(char* layout, char* entity,
379 			  char* key, void* value,
380 			  layouts_keydef_types_t key_type);
381 
382 /*
383  * layouts_entity_get_kv_ref - get a pointer to the value associated with a key
384  *        of an entity in a particular layout.
385  *
386  * The input key_type will force the call to check types consistency between
387  * the requester and the underlying keyspec associated with the key. To skip
388  * that check the caller will have to pass a 0 value.
389  *
390  * Note : this call must be used with caution as the pointer could be free
391  * sooner or later by the underlying layout engine in reply to the execution
392  * of the layouts_entity_set_kv_ref().
393  *
394  * Return SLURM_SUCCES or SLURM_ERROR in case of failure
395  */
396 int layouts_entity_get_kv_ref(char* layout, char* entity,
397 			      char* key, void** pvalue,
398 			      layouts_keydef_types_t key_type);
399 
400 /*
401  * layouts_entity_pullget_kv - combination of layouts_entity_pull_kv and
402  *        layouts_entity_get_kv to retrieve the up-to-date value of a particular
403  *        entity key in the targeted layout.
404  *
405  * The input key_type will force the call to check types consistency between
406  * the requester and the underlying keyspec associated with the key. To skip
407  * that check the caller will have to pass a 0 value.
408  *
409  * Note: see layouts_entity_pull_kv.
410  *
411  * Return SLURM_SUCCES or SLURM_ERROR in case of failure
412  */
413 int layouts_entity_pullget_kv(char* layout, char* entity,
414 			      char* key, void* value,
415 			      layouts_keydef_types_t key_type);
416 
417 /*
418  * layouts_entity_pullget_kv - combination of layouts_entity_pull_kv_ref and
419  *        layouts_entity_get_kv to retrieve a reference to the up-to-date value
420  *        of a particular entity key in the targeted layout.
421  *
422  * The input key_type will force the call to check types consistency between
423  * the requester and the underlying keyspec associated with the key. To skip
424  * that check the caller will have to pass a 0 value.
425  *
426  * Note: see layouts_entity_pull_kv_ref.
427  *
428  * Return SLURM_SUCCES or SLURM_ERROR in case of failure
429  */
430 int layouts_entity_pullget_kv_ref(char* layout, char* entity,
431 				  char* key, void** value,
432 				  layouts_keydef_types_t key_type);
433 
434 /*
435  * layouts_entity_get_mkv - get the values associated with a set of keys of an
436  *        entity in a particular layout.
437  *
438  * The input key_type will force the call to check types consistency between
439  * the requester and the underlying keyspec associated with the key. To skip
440  * that check the caller will have to pass a 0 value. This is mandatory for
441  * cases where the keyspecs of the requested keys do not share the same type.
442  *
443  * Note : the destination buffer will be sequentially filled with the content of
444  * the values associated with the requested keys in the entity.
445  * If the length of the buffer is too small, the remaining references will not
446  * be added and the counter of missed keys incremented as necessary.
447  * The first encountered error terminates the logic and the missing elements
448  * counter will reflect all the unprocessed elements including the faulty one.
449 
450  * Special care must be taken for the following types of key :
451  *   L_T_STRING  : a char* will be added to the buffer. It will be xstrduped
452  *                 with the associated key value. The char* will have to be
453  *                 xfree() after that.
454  *   L_T_CUSTOM : a char* will be added to the buffer. It will be xstrduped
455  *                with the result of the custom_dump function. It will have to
456  *                be xfree() after that.
457  *   L_T_ERROR : will generate an error that will force the function to return
458  *               the count of missing elements (at least 1, depending on where
459  *               this type first appeared in the ordered list of keys to get.
460  *
461  * Note: keys correspond to a list of keys that can be represented as
462  * an hostlist expression (i.e. keys[1-10]).
463  *
464  * Return SLURM_SUCCES or the count of missed keys/references
465  */
466 int layouts_entity_get_mkv(char* layout, char* entity,
467 			   char* keys, void* value, size_t length,
468 			   layouts_keydef_types_t key_type);
469 
470 /*
471  * layouts_entity_get_mkv_ref - get a set of pointers to the values associated
472  *        with a set of keys of an entity in a particular layout.
473  *
474  * The input key_type will force the call to check types consistency between
475  * the requester and the underlying keyspecs associated with the keys. To skip
476  * that check the caller will have to pass a 0 value. This is mandatory for cases
477  * where the keyspecs of the requested keys do not share the same type.
478  *
479  * The output buffer will be filled with the different references.
480  * If the length of the buffer is too small, the remaining references will not
481  * be added and the counter of missed keys incremented as necessary.
482  * The first encountered error terminates the logic and the missing elements
483  * counter will reflect all the unprocessed elements including the faulty one.
484  *
485  * Note: this call must be used with caution as the pointers could be free
486  * sooner or later by the underlying layout engine in reply to the execution
487  * of the layouts_entity_set_kv_ref().
488  *
489  * Note: keys correspond to a list of keys that can be represented as
490  * an hostlist expression (i.e. keys[1-10]).
491  *
492  * Return SLURM_SUCCES or the count of missed keys/references
493  */
494 int layouts_entity_get_mkv_ref(char* layout, char* entity,
495 			       char* keys, void* buffer, size_t length,
496 			       layouts_keydef_types_t key_type);
497 
498 #endif /* end of include guard: __LAYOUTS_MGR_1NRINRSD__INC__ */
499