~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/libs/sgeobj/sge_resource_quota.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*___INFO__MARK_BEGIN__*/
 
2
/*************************************************************************
 
3
 * 
 
4
 *  The Contents of this file are made available subject to the terms of
 
5
 *  the Sun Industry Standards Source License Version 1.2
 
6
 * 
 
7
 *  Sun Microsystems Inc., March, 2001
 
8
 * 
 
9
 * 
 
10
 *  Sun Industry Standards Source License Version 1.2
 
11
 *  =================================================
 
12
 *  The contents of this file are subject to the Sun Industry Standards
 
13
 *  Source License Version 1.2 (the "License"); You may not use this file
 
14
 *  except in compliance with the License. You may obtain a copy of the
 
15
 *  License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html
 
16
 * 
 
17
 *  Software provided under this License is provided on an "AS IS" basis,
 
18
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 
19
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 
20
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 
21
 *  See the License for the specific provisions governing your rights and
 
22
 *  obligations concerning the Software.
 
23
 * 
 
24
 *   The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 
25
 * 
 
26
 *   Copyright: 2001 by Sun Microsystems, Inc.
 
27
 * 
 
28
 *   All Rights Reserved.
 
29
 * 
 
30
 ************************************************************************/
 
31
/*___INFO__MARK_END__*/
 
32
 
 
33
#include <string.h>
 
34
#include <fnmatch.h>
 
35
 
 
36
#include "sge.h"
 
37
 
 
38
#include "sgeobj/sge_resource_quota.h"
 
39
#include "sgeobj/sge_strL.h"
 
40
#include "sgeobj/msg_sgeobjlib.h"
 
41
#include "sgeobj/sge_answer.h"
 
42
#include "sgeobj/sge_object.h"
 
43
#include "sgeobj/sge_centry.h"
 
44
#include "sgeobj/sge_qref.h"
 
45
#include "msg_common.h"
 
46
#include "uti/sge_log.h"
 
47
#include "uti/sge_parse_num_par.h"
 
48
#include "rmon/sgermon.h"
 
49
#include "sgeobj/sge_job.h"
 
50
#include "sgeobj/sge_ja_task.h"
 
51
#include "sgeobj/sge_pe.h"
 
52
#include "sched/sge_resource_utilization.h"
 
53
#include "sgeobj/sge_hgroup.h"
 
54
#include "sgeobj/sge_userset.h"
 
55
#include "sgeobj/sge_href.h"
 
56
#include "sgeobj/sge_host.h"
 
57
#include "sgeobj/sge_cqueue.h"
 
58
#include "uti/sge_string.h"
 
59
 
 
60
static bool rqs_match_user_host_scope(lList *scope, int filter_type, const char *value, lList *master_userset_list, lList *master_hgroup_list, const char *group, bool is_xscope);
 
61
 
 
62
/****** sge_resource_quota/rqs_parse_filter_from_string() *************************
 
63
*  NAME
 
64
*     rqs_parse_filter_from_string() -- parse a RQRF Object from string
 
65
*
 
66
*  SYNOPSIS
 
67
*     bool rqs_parse_filter_from_string(lListElem **filter, const char* buffer, 
 
68
*     lList **alp) 
 
69
*
 
70
*  FUNCTION
 
71
*     Converts a spooled RQRF Object to a CULL Element
 
72
*
 
73
*  INPUTS
 
74
*     lListElem **filter - resulting RQRF object
 
75
*     const char* buffer - string to be converted
 
76
*     lList **alp        - answer_list
 
77
*
 
78
*  RESULT
 
79
*     bool - true on success
 
80
*            false on error
 
81
*
 
82
*  NOTES
 
83
*     MT-NOTE: rqs_parse_filter_from_string() is MT safe 
 
84
*
 
85
*******************************************************************************/
 
86
bool rqs_parse_filter_from_string(lListElem **filter, const char* buffer, lList **alp) {
 
87
   lListElem *tmp_filter = NULL;
 
88
   lListElem *scope = NULL;
 
89
   lList *lp = NULL;
 
90
   lList *scope_list = NULL;
 
91
   lList *xscope_list = NULL;
 
92
   char delims[] = "\t \v\r,{}"; 
 
93
 
 
94
   DENTER(TOP_LAYER, "rqs_parse_filter_from_string");
 
95
 
 
96
   if (buffer == NULL) {
 
97
     DRETURN(false);
 
98
   }
 
99
 
 
100
   tmp_filter = lCreateElem(RQRF_Type);
 
101
 
 
102
   if ( buffer[0] == '{' ) {
 
103
      /* We have a expanded list */
 
104
      lSetBool(tmp_filter, RQRF_expand, true);
 
105
      if (buffer[strlen(buffer)-1] != '}') {
 
106
         ERROR((SGE_EVENT, MSG_RESOURCEQUOTA_NOVALIDEXPANDEDLIST));
 
107
         answer_list_add(alp, SGE_EVENT, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR);
 
108
         DRETURN(false);
 
109
      }
 
110
   } else {
 
111
      lSetBool(tmp_filter, RQRF_expand, false);
 
112
   }
 
113
 
 
114
   lString2List(buffer, &lp, ST_Type, ST_name, delims); 
 
115
 
 
116
   for_each(scope, lp) {
 
117
      const char *name = lGetString(scope, ST_name);
 
118
      if ( name[0] == '!' ) {
 
119
         lAddElemStr(&xscope_list, ST_name, name+1, ST_Type);
 
120
      } else {
 
121
         lAddElemStr(&scope_list, ST_name, name, ST_Type);
 
122
      }
 
123
   }
 
124
 
 
125
   lFreeList(&lp);
 
126
 
 
127
   lSetList(tmp_filter, RQRF_scope, scope_list);
 
128
   lSetList(tmp_filter, RQRF_xscope, xscope_list);
 
129
 
 
130
   *filter = tmp_filter;
 
131
   
 
132
   DRETURN(true);
 
133
}
 
134
 
 
135
/****** sge_resource_quota/rqs_append_filter_to_dstring() *************************
 
136
*  NAME
 
137
*    rqs_append_filter_to_dstringRQRF_object_append_to_dstring() -- RQRF Element to string
 
138
*
 
139
*  SYNOPSIS
 
140
*     bool rqs_append_filter_to_dstring(lListElem *filter, dstring *buffer, 
 
141
*     lList **alp) 
 
142
*
 
143
*  FUNCTION
 
144
*     Converts a RQRF element to string for spooling 
 
145
*
 
146
*  INPUTS
 
147
*     lListElem *filter - Element to be converted
 
148
*     dstring *buffer   - buffer for the element string
 
149
*     lList **alp       - answer_list
 
150
*
 
151
*  RESULT
 
152
*     bool - true on success
 
153
*            false on error
 
154
*
 
155
*  NOTES
 
156
*     MT-NOTE: rqs_append_filter_to_dstring() is MT safe 
 
157
*
 
158
*******************************************************************************/
 
159
bool rqs_append_filter_to_dstring(const lListElem *filter, dstring *buffer, lList **alp){
 
160
   lList *tlp = NULL;
 
161
   lListElem *scope = NULL;
 
162
   bool first = true;
 
163
   bool expand = false;
 
164
   bool ret = false;
 
165
 
 
166
   if (filter == NULL) {
 
167
      return ret;
 
168
   }
 
169
 
 
170
   expand = lGetBool(filter, RQRF_expand) ? true : false;
 
171
 
 
172
   if (expand) {
 
173
      sge_dstring_append_char(buffer, '{');
 
174
   }
 
175
 
 
176
   tlp = lGetList(filter, RQRF_scope);
 
177
   for_each(scope, tlp) {
 
178
      ret = true;
 
179
      if (!first) {
 
180
         sge_dstring_append_char(buffer, ',');
 
181
      } else {
 
182
         first = false;
 
183
      }
 
184
      sge_dstring_append(buffer, lGetString(scope, ST_name));
 
185
   }
 
186
 
 
187
   tlp = lGetList(filter, RQRF_xscope);
 
188
   for_each(scope, tlp) {
 
189
      ret = true;
 
190
      if (!first) {
 
191
         sge_dstring_append_char(buffer, ',');
 
192
      } else {
 
193
         first = false;
 
194
      }
 
195
      sge_dstring_append_char(buffer, '!');
 
196
      sge_dstring_append(buffer, lGetString(scope, ST_name));
 
197
   }
 
198
 
 
199
   if (expand) {
 
200
      sge_dstring_append_char(buffer, '}');
 
201
   }
 
202
 
 
203
   return ret; 
 
204
}
 
205
 
 
206
/****** sge_resource_quota/rqs_set_defaults() *******************************
 
207
*  NAME
 
208
*     rqs_set_defaults() -- set default values to given rqs
 
209
*
 
210
*  SYNOPSIS
 
211
*     lListElem* rqs_set_defaults(lListElem* rqs) 
 
212
*
 
213
*  FUNCTION
 
214
*     This function sets the default values to a resource quota set.
 
215
*     The default rule set is:
 
216
*     {
 
217
*       name = <must be already set>
 
218
*       enabled = true
 
219
*       limit to slots=0
 
220
*     }
 
221
*
 
222
*  INPUTS
 
223
*     lListElem* rqs - Already created object to be modified.
 
224
*
 
225
*  RESULT
 
226
*     lListElem* - modified Object
 
227
*
 
228
*  NOTES
 
229
*     MT-NOTE: rqs_set_defaults() is MT safe 
 
230
*******************************************************************************/
 
231
lListElem* rqs_set_defaults(lListElem* rqs)
 
232
{
 
233
   DENTER(TOP_LAYER, "rqs_set_defaults");
 
234
 
 
235
   if (rqs != NULL) {
 
236
      lList *limit_list = NULL;
 
237
      lList *rule_list = NULL;
 
238
      lListElem *rule = NULL;
 
239
      lListElem *limit = NULL;
 
240
 
 
241
      /* Free RQS_rule */
 
242
      rule_list = lGetList(rqs, RQS_rule);
 
243
      lFreeList(&rule_list);
 
244
 
 
245
      /* Create Rule List */
 
246
      rule_list = lCreateList("Rule_List", RQR_Type);
 
247
      rule = lCreateElem(RQR_Type);
 
248
      limit_list = lCreateList("Limit_List", RQRL_Type);
 
249
      limit = lCreateElem(RQRL_Type);
 
250
      lSetString(limit, RQRL_name, "slots");
 
251
      lSetString(limit, RQRL_value, "0");
 
252
      lAppendElem(limit_list, limit);
 
253
      lSetList(rule, RQR_limit, limit_list);
 
254
      lAppendElem(rule_list, rule);
 
255
 
 
256
      /* Set RQS_enabled */
 
257
      lSetBool(rqs, RQS_enabled, false);
 
258
 
 
259
      /* Set RQS_rule */
 
260
      lSetList(rqs, RQS_rule, rule_list);
 
261
   }
 
262
   DRETURN(rqs);
 
263
}
 
264
 
 
265
/****** sge_resource_quota/rqs_verify_attributes() **********************
 
266
*  NAME
 
267
*     rqs_verify_attributes() -- verify the attributes of a rqs Object 
 
268
*
 
269
*  SYNOPSIS
 
270
*     bool rqs_verify_attributes(lListElem *rqs, lList 
 
271
*     **answer_list, bool in_master) 
 
272
*
 
273
*  FUNCTION
 
274
*     This function verifies the attributes of a given rqs object. A valid rqs
 
275
*     object has a name and at least one rule set. After verification it sets the
 
276
*     double limit value.
 
277
*     Addition checks are done if in_master is true.
 
278
*
 
279
*  INPUTS
 
280
*     lListElem *rqs     - Object that should be verified
 
281
*     lList **answer_list - answer list in case of errors
 
282
*     bool in_master      - flag if called by qmaster or by qconf
 
283
*
 
284
*  RESULT
 
285
*     bool - true on success
 
286
*            false on error
 
287
*
 
288
*  NOTES
 
289
*     MT-NOTE: rqs_verify_attributes() is not MT safe 
 
290
*******************************************************************************/
 
291
bool rqs_verify_attributes(lListElem *rqs, lList **answer_list, bool in_master)
 
292
{
 
293
   bool ret = true;
 
294
   lList *rules = NULL;
 
295
 
 
296
   DENTER(TOP_LAYER, "rqs_verify_attributes");
 
297
 
 
298
   /* every rule set needs a RQS_name */
 
299
   if (lGetString(rqs, RQS_name) == NULL) {
 
300
      answer_list_add_sprintf(answer_list, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR, MSG_RESOURCEQUOTA_NONAME);
 
301
      ret = false;
 
302
   }
 
303
 
 
304
   /* every rule set needs at least one rule */
 
305
   rules = lGetList(rqs, RQS_rule);
 
306
   if (ret && (rules == NULL || lGetNumberOfElem(rules) < 1)) {
 
307
      answer_list_add_sprintf(answer_list, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR, MSG_RESOURCEQUOTA_NORULES);
 
308
      ret = false;
 
309
   }
 
310
  
 
311
   if (ret && in_master) {
 
312
      lList *master_centry_list = (*centry_list_get_master_list());
 
313
 
 
314
      lListElem *rule = NULL;
 
315
      for_each(rule, rules) {
 
316
         bool host_expand = false;
 
317
         bool queue_expand = false;
 
318
         lListElem *limit = NULL;
 
319
         lListElem *filter = NULL;
 
320
         lList *limit_list = lGetList(rule, RQR_limit);
 
321
 
 
322
         /* set rule level. Needed by schedd */
 
323
 
 
324
         if ((filter = lGetObject(rule, RQR_filter_hosts))) {
 
325
            lListElem *host = NULL;
 
326
            host_expand = lGetBool(filter, RQRF_expand) ? true : false;
 
327
 
 
328
            for_each(host, lGetList(filter, RQRF_xscope)) {
 
329
               sge_resolve_host(host, ST_name);
 
330
            }
 
331
            for_each(host, lGetList(filter, RQRF_scope)) {
 
332
               sge_resolve_host(host, ST_name);
 
333
            }
 
334
            
 
335
         }
 
336
         if ((filter = lGetObject(rule, RQR_filter_queues))) {
 
337
            queue_expand = lGetBool(filter, RQRF_expand) ? true : false;
 
338
         }
 
339
 
 
340
         if (host_expand == false && queue_expand == false) {
 
341
            lSetUlong(rule, RQR_level, RQR_GLOBAL);
 
342
         } else if (host_expand == true && queue_expand == false) {
 
343
            /* per host */
 
344
            lSetUlong(rule, RQR_level, RQR_HOST);
 
345
         } else if (host_expand == false && queue_expand == true) {
 
346
            /* per queue */
 
347
            lSetUlong(rule, RQR_level, RQR_CQUEUE);
 
348
         } else {
 
349
            lSetUlong(rule, RQR_level, RQR_QUEUEI);
 
350
         }
 
351
 
 
352
         for_each(limit, limit_list) {
 
353
            const char *name = lGetString(limit, RQRL_name);
 
354
            const char *strval = lGetString(limit, RQRL_value);
 
355
            lListElem *centry = centry_list_locate(master_centry_list, name);
 
356
 
 
357
            if (centry == NULL) {
 
358
               sprintf(SGE_EVENT, MSG_NOTEXISTING_ATTRIBUTE_SS, SGE_RQS_NAME, name);
 
359
               answer_list_add(answer_list, SGE_EVENT, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR);
 
360
               ret = false;
 
361
               break;
 
362
            }
 
363
 
 
364
            lSetString(limit, RQRL_name, lGetString(centry, CE_name));
 
365
 
 
366
            if (strchr(strval, '$') != NULL) {
 
367
               if (lGetUlong(rule, RQR_level) == RQR_HOST || lGetUlong(rule, RQR_level) == RQR_QUEUEI) {
 
368
                  /* the value is a dynamical limit */
 
369
                  if (!validate_load_formula(lGetString(limit, RQRL_value), answer_list, 
 
370
                                            master_centry_list, SGE_ATTR_DYNAMICAL_LIMIT)) {
 
371
                     ret = false;
 
372
                     break;
 
373
                  }
 
374
 
 
375
                  lSetUlong(limit, RQRL_type, lGetUlong(centry, CE_valtype));
 
376
                  lSetBool(limit, RQRL_dynamic, true);
 
377
               } else {
 
378
                  answer_list_add_sprintf(answer_list, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR, MSG_RESOURCEQUOTA_DYNAMICLIMITNOTSUPPORTED);
 
379
                  ret = false;
 
380
                  break;
 
381
               }  
 
382
               /* The evaluation of the value needs to be done at scheduling time. Per default it's zero */
 
383
            } else {
 
384
               lListElem *tmp_ce = lCopyElem(centry);
 
385
               /* fix limit, fill up missing attributes */
 
386
               lSetBool(limit, RQRL_dynamic, false);
 
387
  
 
388
               lSetString(tmp_ce, CE_stringval, strval);
 
389
               if (centry_fill_and_check(tmp_ce, answer_list, false, false)) {
 
390
                  ret = false;
 
391
                  lFreeElem(&tmp_ce);
 
392
                  break;
 
393
               }
 
394
              
 
395
               lSetString(limit, RQRL_value, lGetString(tmp_ce, CE_stringval));
 
396
               lSetDouble(limit, RQRL_dvalue, lGetDouble(tmp_ce, CE_doubleval));
 
397
               lSetUlong(limit, RQRL_type, lGetUlong(tmp_ce, CE_valtype));
 
398
               lFreeElem(&tmp_ce);
 
399
            }
 
400
         }
 
401
         if (ret == false) {
 
402
            break;
 
403
         }
 
404
      }
 
405
   }
 
406
 
 
407
   DRETURN(ret);
 
408
}
 
409
 
 
410
/****** sge_resource_quota/rqs_list_verify_attributes() *********************
 
411
*  NAME
 
412
*     rqs_list_verify_attributes() -- verifies the attributes of a rqs list
 
413
*
 
414
*  SYNOPSIS
 
415
*     bool rqs_list_verify_attributes(lList *rqs_list, lList 
 
416
*     **answer_list, bool in_master) 
 
417
*
 
418
*  FUNCTION
 
419
*     This function iterates over a rqs list and checks for every rqs the attributes
 
420
*
 
421
*  INPUTS
 
422
*     lList *rqs_list    - List that should be verified
 
423
*     lList **answer_list - answer list 
 
424
*     bool in_master      - flag if called by qmaster or qconf
 
425
*
 
426
*  RESULT
 
427
*     bool - true on success
 
428
*            false on error
 
429
*  NOTES
 
430
*     MT-NOTE: rqs_list_verify_attributes() is MT safe 
 
431
*
 
432
*  SEE ALSO
 
433
*     sge_resource_quota/rqs_verify_attributes()
 
434
*******************************************************************************/
 
435
bool rqs_list_verify_attributes(lList *rqs_list, lList **answer_list, bool in_master)
 
436
{
 
437
   bool ret = true;
 
438
   
 
439
   DENTER(TOP_LAYER, "rqs_list_verify_attributes");
 
440
   if (rqs_list != NULL) {
 
441
      lListElem *rqs = NULL;
 
442
 
 
443
      for_each(rqs, rqs_list) {
 
444
         ret = rqs_verify_attributes(rqs, answer_list, in_master);
 
445
         if (!ret) {
 
446
            break;
 
447
         }
 
448
      }
 
449
   }
 
450
   DRETURN(ret);
 
451
}
 
452
 
 
453
/****** sge_resource_quota/rqs_list_locate() ****************************
 
454
*  NAME
 
455
*     rqs_list_locate() -- locate a specific resource quota set by name
 
456
*
 
457
*  SYNOPSIS
 
458
*     lListElem* rqs_list_locate(lList *lp, const char *name) 
 
459
*
 
460
*  FUNCTION
 
461
*     This function searches the rule set list for a specific resource quota
 
462
*     set. The search criteria is the name of the resource quota set.
 
463
*
 
464
*  INPUTS
 
465
*     lList *lp        - rule set list to be searched in
 
466
*     const char *name - rule set name of interest
 
467
*
 
468
*  RESULT
 
469
*     lListElem* - if found the reference to the resource quota set, else NULL
 
470
*
 
471
*  NOTES
 
472
*     MT-NOTE: rqs_list_locate() is MT safe 
 
473
*******************************************************************************/
 
474
lListElem *rqs_list_locate(lList *lp, const char *name)
 
475
{
 
476
   lListElem *ep = NULL;
 
477
 
 
478
   DENTER(TOP_LAYER, "rqs_list_locate");
 
479
 
 
480
   ep = lGetElemStr(lp, RQS_name, name);
 
481
 
 
482
   DRETURN(ep);
 
483
}
 
484
 
 
485
/****** sge_resource_quota/rqs_rule_locate() *************************************
 
486
*  NAME
 
487
*     rqs_rule_locate() -- locate a specific rule by name 
 
488
*
 
489
*  SYNOPSIS
 
490
*     lListElem* rqs_rule_locate(lList *lp, const char *name) 
 
491
*
 
492
*  FUNCTION
 
493
*     This function searches a rule list for a specific rule. The search criteria
 
494
*     is the name or the index of the rule.
 
495
*     The index is used if the name was successfully converted to an integer by
 
496
*     the atoi() function. If atoi() was not able to convert the name the rule is
 
497
*     searched by a sting compare.
 
498
*
 
499
*  INPUTS
 
500
*     lList *lp        - list to be searched in
 
501
*     const char *name - rule name of interest
 
502
*
 
503
*  RESULT
 
504
*     lListElem* - reference to found rule
 
505
*                  NULL if rule was not found
 
506
*
 
507
*  NOTES
 
508
*     MT-NOTE: rqs_rule_locate() is MT safe 
 
509
*******************************************************************************/
 
510
lListElem* rqs_rule_locate(lList *lp, const char *name)
 
511
{
 
512
   lListElem *ep = NULL;
 
513
   int get_pos = 0;
 
514
   int act_pos = 1;
 
515
 
 
516
   DENTER(TOP_LAYER, "rqs_rule_locate");
 
517
 
 
518
   if (name == NULL) {
 
519
      DRETURN(NULL);
 
520
   }
 
521
 
 
522
   get_pos = atoi(name);
 
523
 
 
524
   for_each(ep, lp) {
 
525
      const char *rule_name = lGetString(ep, RQR_name);
 
526
      if (get_pos != -1 && act_pos == get_pos) {
 
527
         break;
 
528
      } else if (rule_name != NULL && !strcasecmp(name, lGetString(ep, RQR_name))) {
 
529
         break;
 
530
      }
 
531
      act_pos++;
 
532
   }
 
533
 
 
534
   DRETURN(ep);
 
535
}
 
536
 
 
537
/****** sge_resource_quota/rqs_xattr_pre_gdi() *************************************
 
538
*  NAME
 
539
*     rqs_xattr_pre_gdi() -- qconf xattr list preformat
 
540
*
 
541
*  SYNOPSIS
 
542
*     bool rqs_xattr_pre_gdi(lList *this_list, lList **answer_list) 
 
543
*
 
544
*  FUNCTION
 
545
*     This function preformates the given list created by xattr. The xattr switch
 
546
*     allows to address single rules by using the special rule set name "rule_set_name/rule_name".
 
547
*     The rule name can be the name for named rules or the index of the rule.
 
548
*     This function splits such a name into the single rule set name and set the correct
 
549
*     rule name.
 
550
*
 
551
*  INPUTS
 
552
*     lList *this_list    - list to be modified
 
553
*     lList **answer_list - answer list
 
554
*
 
555
*  RESULT
 
556
*     bool - true on success
 
557
*            false on error
 
558
*
 
559
*  NOTES
 
560
*     MT-NOTE: rqs_xattr_pre_gdi() is MT safe 
 
561
*******************************************************************************/
 
562
bool rqs_xattr_pre_gdi(lList *this_list, lList **answer_list) 
 
563
{
 
564
   bool ret = true;
 
565
   char delim[] = "/";
 
566
 
 
567
   DENTER(TOP_LAYER, "rqs_xattr_pre_gdi");
 
568
   if (this_list != NULL) {
 
569
      lListElem *rqs = NULL;
 
570
 
 
571
      for_each(rqs, this_list) {
 
572
         lList *lp = NULL;
 
573
         const char *name = lGetString(rqs, RQS_name);
 
574
         
 
575
         lString2List(name, &lp, ST_Type, ST_name, delim);
 
576
         if (lGetNumberOfElem(lp) == 2) {
 
577
            lListElem *ep = NULL;
 
578
            lListElem *rule = NULL;
 
579
            lList *rules = lGetList(rqs, RQS_rule);
 
580
 
 
581
            ep = lFirst(lp);
 
582
            lSetString(rqs, RQS_name, lGetString(ep, ST_name));
 
583
            ep = lNext(ep);
 
584
            for_each(rule, rules) {
 
585
               lSetString(rule, RQR_name, lGetString(ep, ST_name));
 
586
            }
 
587
         }
 
588
         lFreeList(&lp);
 
589
      }
 
590
   }
 
591
   DRETURN(ret);
 
592
}
 
593
 
 
594
/****** sge_resource_quota/rqs_get_rue_string() *****************************
 
595
*  NAME
 
596
*     rqs_get_rue_string() -- creates a rue name
 
597
*
 
598
*  SYNOPSIS
 
599
*     bool rqs_get_rue_string(dstring *name, lListElem *rule, const char 
 
600
*     *user, const char *project, const char *host, const char *queue, const 
 
601
*     char* pe) 
 
602
*
 
603
*  FUNCTION
 
604
*     Creates the rue name used for debiting a specific job request. The name 
 
605
*     consists of the five touples devided by a /. The order is user, project,
 
606
*     pe, queue, host.
 
607
*     Filters that count for a sum
 
608
*     of hosts are saved as a empty string because they don't need to be matched.
 
609
*
 
610
*     For example the rule
 
611
*       limit users `*` queues `all.q,my.q` to slots=10
 
612
*     may result in the rue name
 
613
*       user1///all.q//
 
614
*
 
615
*  INPUTS
 
616
*     dstring *name       - out: rue_name
 
617
*     lListElem *rule     - resource quota rule (RQR_Type)
 
618
*     const char *user    - user name
 
619
*     const char *project - project name
 
620
*     const char *host    - host name
 
621
*     const char *queue   - queue name
 
622
*     const char* pe      - pe name
 
623
*
 
624
*  RESULT
 
625
*     bool - always true
 
626
*
 
627
*  NOTES
 
628
*     MT-NOTE: rqs_get_rue_string() is MT safe 
 
629
*
 
630
*******************************************************************************/
 
631
bool
 
632
rqs_get_rue_string(dstring *name, const lListElem *rule, const char *user, 
 
633
                              const char *project, const char *host, const char *queue,
 
634
                              const char* pe)
 
635
{
 
636
   lListElem *filter = NULL;
 
637
 
 
638
   DENTER(BASIS_LAYER, "rqs_get_rue_string");
 
639
 
 
640
   if (rule == NULL) {
 
641
      DRETURN(false);
 
642
   }
 
643
 
 
644
   sge_dstring_clear(name);
 
645
 
 
646
   if ((filter = lGetObject(rule, RQR_filter_users)) != NULL) {
 
647
      if (filter != NULL && user != NULL && lGetBool(filter, RQRF_expand) == true) {
 
648
         sge_dstring_append(name, user); 
 
649
      }
 
650
   }
 
651
   sge_dstring_append(name, "/");
 
652
 
 
653
   if ((filter = lGetObject(rule, RQR_filter_projects)) != NULL) {
 
654
      if (filter != NULL && project != NULL && lGetBool(filter, RQRF_expand) == true) {
 
655
         sge_dstring_append(name, project); 
 
656
      }
 
657
   }
 
658
   sge_dstring_append(name, "/");
 
659
 
 
660
   if ((filter = lGetObject(rule, RQR_filter_pes)) != NULL) {
 
661
      if (filter != NULL && pe != NULL && lGetBool(filter, RQRF_expand) == true) {
 
662
         sge_dstring_append(name, pe); 
 
663
      }
 
664
   }
 
665
   sge_dstring_append(name, "/");
 
666
 
 
667
   if ((filter = lGetObject(rule, RQR_filter_queues)) != NULL) {
 
668
      if (filter != NULL && queue != NULL && lGetBool(filter, RQRF_expand) == true) {
 
669
         sge_dstring_append(name, queue); 
 
670
      }
 
671
   }
 
672
   sge_dstring_append(name, "/");
 
673
 
 
674
   if ((filter = lGetObject(rule, RQR_filter_hosts)) != NULL) {
 
675
      if (filter != NULL && host != NULL && lGetBool(filter, RQRF_expand) == true) {
 
676
         char buffer[10240];
 
677
         sge_hostcpy(buffer, host);
 
678
         sge_dstring_append(name, buffer); 
 
679
      }
 
680
   }
 
681
   sge_dstring_append(name, "/");
 
682
 
 
683
   DPRINTF(("rue_name: %s\n", sge_dstring_get_string(name)));
 
684
 
 
685
   DRETURN(true);
 
686
}
 
687
 
 
688
/****** sge_resource_quota/rqs_debit_consumable() *********************************
 
689
*  NAME
 
690
*     rqs_debit_consumable() -- debit slots in all relevant rule sets
 
691
*
 
692
*  SYNOPSIS
 
693
*     int rqs_debit_consumable(lListElem *rqs, lListElem *job, lListElem 
 
694
*     *granted, lListElem *pe, lList *centry_list, int slots) 
 
695
*
 
696
*  FUNCTION
 
697
*     iterater over all rules in the given rule set and debit the amount of slots
 
698
*     in the relevant rule
 
699
*
 
700
*  INPUTS
 
701
*     lListElem *rqs     - resource quota set (RQS_Type)
 
702
*     lListElem *job     - job request (JB_Type)
 
703
*     lListElem *granted - granted destination identifier (JG_Type)
 
704
*     lListElem *pe      - granted pe (PE_Type)
 
705
*     lList *centry_list - consumable resouces list (CE_Type)
 
706
*     int slots          - slot amount
 
707
*
 
708
*  RESULT
 
709
*     int - amount of modified rule
 
710
*
 
711
*  NOTES
 
712
*     MT-NOTE: rqs_debit_consumable() is not MT safe 
 
713
*
 
714
*******************************************************************************/
 
715
int
 
716
rqs_debit_consumable(lListElem *rqs, lListElem *job, lListElem *granted, const char *pename, lList *centry_list, 
 
717
                      lList *acl_list, lList *hgrp_list, int slots)
 
718
{
 
719
   lListElem *rule = NULL;
 
720
   int mods = 0;
 
721
   const char* hostname = lGetHost(granted, JG_qhostname);
 
722
   const char* username = lGetString(job, JB_owner);
 
723
   const char* groupname = lGetString(job, JB_group);
 
724
   char *qname = NULL;
 
725
   const char *queue_instance = lGetString(granted, JG_qname);
 
726
   const char* project = lGetString(job, JB_project);
 
727
 
 
728
   DENTER(TOP_LAYER, "rqs_debit_consumable");
 
729
 
 
730
   if (!lGetBool(rqs, RQS_enabled)) {
 
731
      DRETURN(0);
 
732
   }
 
733
 
 
734
   /* remove the host name part of the queue instance name */
 
735
   qname = cqueue_get_name_from_qinstance(queue_instance);
 
736
 
 
737
   rule = rqs_get_matching_rule(rqs, username, groupname, project, pename, hostname, qname, acl_list, hgrp_list, NULL);
 
738
 
 
739
   if (rule != NULL) {
 
740
      /* debit usage */
 
741
      dstring rue_name = DSTRING_INIT;
 
742
 
 
743
      rqs_get_rue_string(&rue_name, rule, username, project,
 
744
                                hostname, qname, pename);
 
745
 
 
746
      mods = rqs_debit_rule_usage(job, rule, &rue_name, slots, centry_list, lGetString(rqs, RQS_name));
 
747
 
 
748
      sge_dstring_free(&rue_name);
 
749
   }
 
750
   
 
751
   FREE(qname);
 
752
 
 
753
   DRETURN(mods); 
 
754
}
 
755
 
 
756
/****** sge_resource_quota/rqs_get_matching_rule() ********************************
 
757
*  NAME
 
758
*     rqs_get_matching_rule() -- found relevant rule for job request
 
759
*
 
760
*  SYNOPSIS
 
761
*     lListElem* rqs_get_matching_rule(lListElem *rqs, const char *user, 
 
762
*     const char *project, const char* pe, const char *host, const char *queue, 
 
763
*     lList *userset_list, lList* hgroup_list, dstring *rule_name) 
 
764
*
 
765
*  FUNCTION
 
766
*     This function searches in a resource quota set the relevant rule.
 
767
*
 
768
*  INPUTS
 
769
*     lListElem *rqs     - rule set (RQS_Type)
 
770
*     const char *user    - user name
 
771
*     const char *project - project name
 
772
*     const char* pe      - pe name
 
773
*     const char *host    - host name
 
774
*     const char *queue   - queue name
 
775
*     lList *userset_list - master user set list (US_Type)
 
776
*     lList* hgroup_list  - master host group list (HG_Type);
 
777
*     dstring *rule_name  - out: name or matching rule
 
778
*
 
779
*  RESULT
 
780
*     lListElem* - pointer to matching rule
 
781
*
 
782
*  NOTES
 
783
*     MT-NOTE: rqs_get_matching_rule() is MT safe 
 
784
*
 
785
*******************************************************************************/
 
786
lListElem *
 
787
rqs_get_matching_rule(const lListElem *rqs, const char *user, const char *group, const char *project,
 
788
                                  const char* pe, const char *host, const char *queue,
 
789
                                  lList *userset_list, lList* hgroup_list, dstring *rule_name)
 
790
{
 
791
   lListElem *rule = NULL;
 
792
   lList *rule_list = lGetList(rqs, RQS_rule);
 
793
   int i = 0;
 
794
 
 
795
   DENTER(BASIS_LAYER, "rqs_get_matching_rule");
 
796
 
 
797
   for_each (rule, rule_list) {
 
798
      i++;
 
799
 
 
800
      if (!rqs_is_matching_rule(rule, user, group, project, pe, host, queue, userset_list, hgroup_list)) {
 
801
         continue;
 
802
      }
 
803
      if (lGetString(rule, RQR_name)) {
 
804
         DPRINTF(("Using resource quota %s\n", lGetString(rule, RQR_name)));
 
805
         sge_dstring_sprintf(rule_name, "%s/%s", lGetString(rqs, RQS_name), lGetString(rule, RQR_name));
 
806
      } else {
 
807
         DPRINTF(("Using resource quota %d\n", i));
 
808
         sge_dstring_sprintf(rule_name, "%s/%d", lGetString(rqs, RQS_name), i);
 
809
      }
 
810
      /* if all filter object matches this is our rule */
 
811
      break;
 
812
   }
 
813
   DRETURN(rule);
 
814
}
 
815
 
 
816
/****** sge_resource_quota/rqs_debit_rule_usage() *********************************
 
817
*  NAME
 
818
*     rqs_debit_rule_usage() -- debit usage in a resource quota rule 
 
819
*
 
820
*  SYNOPSIS
 
821
*     int rqs_debit_rule_usage(lListElem *job, lListElem *rule, dstring 
 
822
*     *rue_name, int slots, lList *centry_list, const char *obj_name) 
 
823
*
 
824
*  FUNCTION
 
825
*     Debit an amount of slots in all limits of one resource quota rule
 
826
*
 
827
*  INPUTS
 
828
*     lListElem *job       - job request (JG_Type)
 
829
*     lListElem *rule      - resource quota rule (RQR_Type)
 
830
*     dstring *rue_name    - rue name that counts
 
831
*     int slots            - amount of slots to debit
 
832
*     lList *centry_list   - consumable resource list (CE_Type)
 
833
*     const char *obj_name - name of the limit
 
834
*
 
835
*  RESULT
 
836
*     int - amount of debited limits
 
837
*
 
838
*  NOTES
 
839
*     MT-NOTE: rqs_debit_rule_usage() is MT safe 
 
840
*******************************************************************************/
 
841
int
 
842
rqs_debit_rule_usage(lListElem *job, lListElem *rule, dstring *rue_name, int slots, lList *centry_list, const char *obj_name) 
 
843
{
 
844
   lList *limit_list;
 
845
   lListElem *limit;
 
846
   const char *centry_name;
 
847
   int mods = 0;
 
848
 
 
849
   DENTER(TOP_LAYER, "rqs_debit_rule_usage");
 
850
 
 
851
   limit_list = lGetList(rule, RQR_limit);
 
852
 
 
853
   for_each(limit, limit_list) {
 
854
      lListElem *raw_centry;
 
855
      lListElem *rue_elem;
 
856
      double dval;
 
857
 
 
858
      centry_name = lGetString(limit, RQRL_name);
 
859
      
 
860
      if (!(raw_centry = centry_list_locate(centry_list, centry_name))) {
 
861
         /* ignoring not defined centry */
 
862
         continue;
 
863
      }
 
864
 
 
865
      if (!lGetBool(raw_centry, CE_consumable)) {
 
866
         continue;
 
867
      }
 
868
 
 
869
      rue_elem = lGetSubStr(limit, RUE_name, sge_dstring_get_string(rue_name), RQRL_usage);
 
870
      if(rue_elem == NULL) {
 
871
         rue_elem = lAddSubStr(limit, RUE_name, sge_dstring_get_string(rue_name), RQRL_usage, RUE_Type);
 
872
         /* RUE_utilized_now is implicitly set to zero */
 
873
      }
 
874
 
 
875
      if (job) {
 
876
         bool tmp_ret = job_get_contribution(job, NULL, centry_name, &dval, raw_centry);
 
877
         if (tmp_ret && dval != 0.0) {
 
878
            DPRINTF(("debiting %f of %s on rqs %s for %s %d slots\n", dval, centry_name,
 
879
                     obj_name, sge_dstring_get_string(rue_name), slots));
 
880
            lAddDouble(rue_elem, RUE_utilized_now, slots * dval);
 
881
            mods++;
 
882
         }
 
883
         if ((lGetDouble(rue_elem, RUE_utilized_now) == 0) && !lGetList(rue_elem, RUE_utilized)) {
 
884
            rue_elem = lDechainElem(lGetList(limit, RQRL_usage), rue_elem);
 
885
            lFreeElem(&rue_elem);
 
886
         }
 
887
      }
 
888
   }
 
889
 
 
890
   DRETURN(mods);
 
891
}
 
892
 
 
893
/****** sge_resource_quota/rqs_match_user_host_scope() ****************************
 
894
*  NAME
 
895
*     rqs_match_user_host_scope() -- match user or host scope
 
896
*
 
897
*  SYNOPSIS
 
898
*     static bool rqs_match_user_host_scope(lList *scope, int filter_type, 
 
899
*     const char *value, lList *master_userset_list, lList *master_hgroup_list) 
 
900
*
 
901
*  FUNCTION
 
902
*     This function verifies a user or host scope. The function allows for every
 
903
*     scope entry and for the value a wildcard definition. Hostgroups and Usergroups
 
904
*     are resolved and matched against the value
 
905
*     
 
906
*
 
907
*  INPUTS
 
908
*     lList *scope               - Scope to match (ST_Type)
 
909
*     int filter_type            - filter type (FILTER_USERS or FILTER_HOSTS)
 
910
*     const char *value          - value to match
 
911
*     lList *master_userset_list - master userset list (US_Type)
 
912
*     lList *master_hgroup_list  - master hostgroup list (HG_Type)
 
913
*
 
914
*  RESULT
 
915
*     static bool - true, if value was found in scope 
 
916
*                   false, if value was not found in scope
 
917
*
 
918
*  NOTES
 
919
*     MT-NOTE: rqs_match_user_host_scope() is MT safe 
 
920
*
 
921
*  SEE ALSO
 
922
*     sge_resource_quota/rqs_match_user_host_scope()
 
923
*******************************************************************************/
 
924
static bool rqs_match_user_host_scope(lList *scope, int filter_type, const char *value, lList *master_userset_list, lList *master_hgroup_list, const char *group, bool is_xscope) {
 
925
 
 
926
   bool found = false;
 
927
   lListElem *ep;
 
928
 
 
929
   DENTER(TOP_LAYER, "rqs_match_user_host_scope");
 
930
 
 
931
   if (!sge_is_pattern(value)) {
 
932
      /* used in scheduler/qmaster and qquota */
 
933
      if (lGetElemStr(scope, ST_name, value) != NULL) {
 
934
         found = true;
 
935
      } else {
 
936
         for_each(ep, scope) {
 
937
            lListElem *group_ep;
 
938
            const char *cp = lGetString(ep, ST_name);
 
939
            const char *group_name = NULL;
 
940
            const char *query = NULL;
 
941
 
 
942
            if (fnmatch(cp, value, 0) == 0) {
 
943
               found = true;
 
944
               break;
 
945
            }
 
946
 
 
947
            if (!is_hgroup_name(value) && is_hgroup_name(cp)) {
 
948
               group_name = cp;
 
949
               query = value;
 
950
            } else if (is_hgroup_name(value) && !is_hgroup_name(cp)) {
 
951
               group_name = value;
 
952
               query = cp;
 
953
            }
 
954
 
 
955
            if (group_name != NULL && query != NULL) {
 
956
               DPRINTF(("group_name=%s, query=%s\n", group_name, query));
 
957
               if (filter_type == FILTER_USERS) {
 
958
                  /* the userset name does not contain the preattached \@ sign */
 
959
                  group_name++; 
 
960
                  if (!sge_is_pattern(group_name)) {
 
961
                     if ((group_ep = userset_list_locate(master_userset_list, group_name)) != NULL) {
 
962
                        if (sge_contained_in_access_list(query, group, group_ep, NULL) == 1) {
 
963
                           found = true;
 
964
                           break;
 
965
                        }
 
966
                     }
 
967
                  } else {
 
968
                     for_each(group_ep, master_userset_list) {
 
969
                        if (fnmatch(group_name, lGetString(group_ep, US_name), 0) == 0) {
 
970
                           if (sge_contained_in_access_list(query, group, group_ep, NULL) == 1) {
 
971
                              found = true;
 
972
                              break;
 
973
                           }
 
974
                        }
 
975
                     }
 
976
                     if (found == true) {
 
977
                        break;
 
978
                     }
 
979
                  }
 
980
               } else { /* FILTER_HOSTS */
 
981
                  lListElem *hgroup = NULL;
 
982
                  lList *host_list = NULL;
 
983
                  if (!sge_is_pattern(group_name)) {
 
984
                     if ((hgroup = hgroup_list_locate(master_hgroup_list, group_name))) { 
 
985
                        hgroup_find_all_references(hgroup, NULL, master_hgroup_list, &host_list, NULL);
 
986
                        if (host_list != NULL && lGetElemHost(host_list, HR_name, query) != NULL) {
 
987
                           lFreeList(&host_list);
 
988
                           found = true;
 
989
                           break;
 
990
                        } else if (sge_is_pattern(query)) {
 
991
                           lListElem *host_ep;
 
992
                           for_each(host_ep, host_list) {
 
993
                              if (fnmatch(query, lGetHost(host_ep, HR_name), 0) == 0) {
 
994
                                 lFreeList(&host_list);
 
995
                                 found = true;
 
996
                                 break;
 
997
                              }
 
998
                           }
 
999
                           if (found == true) {
 
1000
                              break;
 
1001
                           }
 
1002
                        }
 
1003
                        lFreeList(&host_list);
 
1004
                     }
 
1005
                  } else {
 
1006
                     for_each(group_ep, master_hgroup_list) {
 
1007
                        if (fnmatch(group_name, lGetHost(group_ep, HGRP_name), 0) == 0) {
 
1008
                           hgroup_find_all_references(group_ep, NULL, master_hgroup_list, &host_list, NULL);
 
1009
                           if (host_list != NULL && lGetElemHost(host_list, HR_name, query) != NULL) {
 
1010
                              lFreeList(&host_list);
 
1011
                              found = true;
 
1012
                              break;
 
1013
                           } else if (sge_is_pattern(query)) {
 
1014
                              lListElem *host_ep;
 
1015
                              for_each(host_ep, host_list) {
 
1016
                                 if (fnmatch(query, lGetHost(host_ep, HR_name), 0) == 0) {
 
1017
                                    lFreeList(&host_list);
 
1018
                                    found = true;
 
1019
                                    break;
 
1020
                                 }
 
1021
                              }
 
1022
                              if (found == true) {
 
1023
                                 break;
 
1024
                              }
 
1025
                           }
 
1026
                           lFreeList(&host_list);
 
1027
                        }
 
1028
                     }
 
1029
                  }
 
1030
               }
 
1031
            }
 
1032
         }
 
1033
      }
 
1034
   } else {
 
1035
      /* only used in qquota */ 
 
1036
      for_each(ep, scope) {
 
1037
         const char *cp = lGetString(ep, ST_name);
 
1038
         const char *group_name = NULL;
 
1039
         const char *query = NULL;
 
1040
 
 
1041
         if (fnmatch(value, cp, 0) == 0) {
 
1042
            if (!is_xscope) {
 
1043
               found = true;
 
1044
               break;
 
1045
            } else {
 
1046
               if (strcmp(value, cp) == 0) {
 
1047
                  /* amount of sets is equal */
 
1048
                  found = true;
 
1049
                  break;
 
1050
               } else {
 
1051
                  /* amount of sets does not overlap. We can not reject in
 
1052
                     xscope context and have to wave through */
 
1053
                  found = false;
 
1054
                  break;
 
1055
               }
 
1056
            }
 
1057
         }
 
1058
         if (sge_is_pattern(cp) && (fnmatch(cp, value, 0) == 0)) {
 
1059
            found = true;
 
1060
            break;
 
1061
         }
 
1062
         if (!is_hgroup_name(value) && is_hgroup_name(cp)) {
 
1063
            group_name = cp;
 
1064
            query = value;
 
1065
         } else if (is_hgroup_name(value) && !is_hgroup_name(cp)) {
 
1066
            group_name = value;
 
1067
            query = cp;
 
1068
         }
 
1069
 
 
1070
         if (group_name != NULL && query != NULL) {
 
1071
            lListElem *group_ep;
 
1072
            DPRINTF(("group_name=%s, query=%s\n", group_name, query));
 
1073
            if (filter_type == FILTER_USERS) {
 
1074
               /* the userset name does not contain the preattached \@ sign */
 
1075
               group_name++;
 
1076
               for_each(group_ep, master_userset_list) {
 
1077
                  if (fnmatch(group_name, lGetString(group_ep, US_name), 0) == 0) {
 
1078
                     if (sge_contained_in_access_list(query, group, group_ep, NULL) == 1) {
 
1079
                        found = true;
 
1080
                        break;
 
1081
                     }
 
1082
                  }
 
1083
               }
 
1084
               if (found == true) {
 
1085
                  break;
 
1086
               }
 
1087
            } else {
 
1088
               lList *host_list = NULL;
 
1089
               for_each(group_ep, master_hgroup_list) {
 
1090
                  if (fnmatch(group_name, lGetHost(group_ep, HGRP_name), 0) == 0) {
 
1091
                     lListElem *host_ep;
 
1092
                     hgroup_find_all_references(group_ep, NULL, master_hgroup_list, &host_list, NULL);
 
1093
                     for_each(host_ep, host_list) {
 
1094
                        if (fnmatch(query, lGetHost(host_ep, HR_name), 0) == 0) {
 
1095
                           found = true;
 
1096
                           break;
 
1097
                        }
 
1098
                     }
 
1099
                     lFreeList(&host_list);
 
1100
                     if (found == true) {
 
1101
                        break;
 
1102
                     }
 
1103
                  }
 
1104
               }
 
1105
               if (found == true) {
 
1106
                  break;
 
1107
               }
 
1108
            }
 
1109
         }
 
1110
      }
 
1111
   }
 
1112
   DRETURN(found);
 
1113
}
 
1114
 
 
1115
/****** sge_resource_quota/rqs_is_matching_rule() *********************************
 
1116
*  NAME
 
1117
*     rqs_is_matching_rule() -- matches a rule with the filter touples
 
1118
*
 
1119
*  SYNOPSIS
 
1120
*     bool rqs_is_matching_rule(lListElem *rule, const char *user, const char 
 
1121
*     *project, const char *pe, const char *host, const char *queue, lList 
 
1122
*     *master_userset_list, lList *master_hgroup_list) 
 
1123
*
 
1124
*  FUNCTION
 
1125
*     The function verifies for every filter touple if the request matches
 
1126
*     the configured resource quota rule. If only one touple does not match
 
1127
*     the whole rule will not match
 
1128
*
 
1129
*  INPUTS
 
1130
*     lListElem *rule            - resource quota rule (RQR_Type)
 
1131
*     const char *user           - user name
 
1132
*     const char *project        - project name
 
1133
*     const char *pe             - pe name
 
1134
*     const char *host           - host name
 
1135
*     const char *queue          - queue name
 
1136
*     lList *master_userset_list - master user set list (US_Type)
 
1137
*     lList *master_hgroup_list  - master hostgroup list (HG_Type)
 
1138
*
 
1139
*  RESULT
 
1140
*     bool - true if the rule does match
 
1141
*            false if the rule does not match
 
1142
*
 
1143
*  NOTES
 
1144
*     MT-NOTE: rqs_is_matching_rule() is MT safe 
 
1145
*
 
1146
*******************************************************************************/
 
1147
bool
 
1148
rqs_is_matching_rule(lListElem *rule, const char *user, const char *group, const char *project, const char *pe, const char *host, const char *queue, lList *master_userset_list, lList *master_hgroup_list)
 
1149
{
 
1150
      DENTER(TOP_LAYER, "rqs_is_matching_rule");
 
1151
 
 
1152
      if (!rqs_filter_match(lGetObject(rule, RQR_filter_users), FILTER_USERS, user, master_userset_list, NULL, group)) {
 
1153
         DPRINTF(("user doesn't match\n"));
 
1154
         DRETURN(false);
 
1155
      }
 
1156
      if (!rqs_filter_match(lGetObject(rule, RQR_filter_projects), FILTER_PROJECTS, project, NULL, NULL, NULL)) {
 
1157
         DPRINTF(("project doesn't match\n"));
 
1158
         DRETURN(false);
 
1159
      }
 
1160
      if (!rqs_filter_match(lGetObject(rule, RQR_filter_pes), FILTER_PES, pe, NULL, NULL, NULL)) {
 
1161
         DPRINTF(("pe doesn't match\n"));
 
1162
         DRETURN(false);
 
1163
      }
 
1164
      if (!rqs_filter_match(lGetObject(rule, RQR_filter_queues), FILTER_QUEUES, queue, NULL, NULL, NULL)) {
 
1165
         DPRINTF(("queue doesn't match\n"));
 
1166
         DRETURN(false);
 
1167
      }
 
1168
      if (!rqs_filter_match(lGetObject(rule, RQR_filter_hosts), FILTER_HOSTS, host, NULL, master_hgroup_list, NULL)) {
 
1169
         DPRINTF(("host doesn't match\n"));
 
1170
         DRETURN(false);
 
1171
      }
 
1172
 
 
1173
      DRETURN(true);
 
1174
}
 
1175
 
 
1176
 
 
1177
 
 
1178
/****** sge_resource_quota/rqs_match_host_scope() ******************************
 
1179
*  NAME
 
1180
*     rqs_match_host_scope() -- Match name with host scope
 
1181
*
 
1182
*  SYNOPSIS
 
1183
*     static bool rqs_match_host_scope(lList *scope, const char *name, lList 
 
1184
*     *master_hgroup_list) 
 
1185
*
 
1186
*  FUNCTION
 
1187
*     The function matches the passed name with the host scope. Name
 
1188
*     may not only be a hostname, but also host group name or a wildcard
 
1189
*     expression. For performance reasons qref_list_host_rejected() is
 
1190
*     used for matching, if we got no pattern and no hostgroup.
 
1191
*
 
1192
*  INPUTS
 
1193
*     lList *scope              - A scope list (ST_Type)
 
1194
*     const char *name          - hostname/hostgroup name/wildcard expression
 
1195
*     lList *master_hgroup_list - the host group list (HGRP_Type)
 
1196
*
 
1197
*  RESULT
 
1198
*     bool - Returns true if 'name' matches
 
1199
*
 
1200
*  NOTES
 
1201
*     MT-NOTE: rqs_match_host_scope() is MT safe 
 
1202
*******************************************************************************/
 
1203
static bool rqs_match_host_scope(lList *scope, const char *name, lList *master_hgroup_list, bool is_xscope) 
 
1204
{
 
1205
   lListElem *ep;
 
1206
 
 
1207
   DENTER(TOP_LAYER, "rqs_match_host_scope");
 
1208
 
 
1209
   if (lGetElemStr(scope, ST_name, "*")) {
 
1210
      DRETURN(true);
 
1211
   }
 
1212
   
 
1213
   if (sge_is_pattern(name) || is_hgroup_name(name)) {
 
1214
      DRETURN(rqs_match_user_host_scope(scope, FILTER_HOSTS, name, NULL, master_hgroup_list, NULL, is_xscope));
 
1215
   }
 
1216
 
 
1217
   /* at this stage we know 'name' is a simple hostname */
 
1218
   for_each(ep, scope) {
 
1219
      if (!qref_list_host_rejected(lGetString(ep, ST_name), name, master_hgroup_list)) {
 
1220
         DRETURN(true);
 
1221
      }
 
1222
   }
 
1223
   DRETURN(false);
 
1224
}
 
1225
 
 
1226
 
 
1227
 
 
1228
/****** sge_resource_quota/rqs_filter_match() *******************************
 
1229
*  NAME
 
1230
*     rqs_filter_match() -- compares value with configured filter
 
1231
*
 
1232
*  SYNOPSIS
 
1233
*     bool rqs_filter_match(lListElem *filter, int filter_type, const 
 
1234
*     char *value, lList *master_userset_list, lList *master_hgroup_list) 
 
1235
*
 
1236
*  FUNCTION
 
1237
*     This function compares for the given filter if the value does match
 
1238
*     the configured one. Wildcards are allowed for the filter as well as for
 
1239
*     the value.
 
1240
*
 
1241
*  INPUTS
 
1242
*     lListElem *filter          - filter element (RQRF_Type)
 
1243
*     int filter_type            - filter type
 
1244
*     const char *value          - value to match
 
1245
*     lList *master_userset_list - master userset list (US_Type)
 
1246
*     lList *master_hgroup_list  - master hostgroup list (HG_Type)
 
1247
*
 
1248
*  RESULT
 
1249
*     bool - true if the value does match
 
1250
*            false if the value does not match
 
1251
*
 
1252
*  NOTES
 
1253
*     MT-NOTE: rqs_filter_match() is MT safe 
 
1254
*
 
1255
*******************************************************************************/
 
1256
bool 
 
1257
rqs_filter_match(lListElem *filter, int filter_type, const char *value, lList *master_userset_list, lList *master_hgroup_list, const char *group) {
 
1258
   bool ret = true;
 
1259
   lListElem* ep; 
 
1260
 
 
1261
   DENTER(BASIS_LAYER, "rqs_filter_match");
 
1262
 
 
1263
   if (filter != NULL) {
 
1264
      lList* scope = lGetList(filter, RQRF_scope);
 
1265
      lList* xscope = lGetList(filter, RQRF_xscope);
 
1266
 
 
1267
      switch (filter_type) {
 
1268
         case FILTER_HOSTS:
 
1269
            DPRINTF(("matching hosts with %s\n", value));
 
1270
            /* inverse logic because of xscope */
 
1271
            ret = rqs_match_host_scope(xscope, value, master_hgroup_list, true) ? false: true;
 
1272
            if (ret == true && scope != NULL) { 
 
1273
               if (!rqs_match_host_scope(scope, value, master_hgroup_list, false)) {
 
1274
                  ret = false;
 
1275
               }
 
1276
            }
 
1277
            break;
 
1278
 
 
1279
         case FILTER_USERS:
 
1280
         {  
 
1281
            DPRINTF(("matching users or hosts with %s\n", value));
 
1282
            /* inverse logic because of xscope */
 
1283
            ret = rqs_match_user_host_scope(xscope, filter_type, value, master_userset_list, NULL, group, true) ? false: true;
 
1284
            if (ret == true && scope != NULL) { 
 
1285
               if (!rqs_match_user_host_scope(scope, filter_type, value, master_userset_list, NULL, group, false)) {
 
1286
                  ret = false;
 
1287
               }
 
1288
            }
 
1289
            break;
 
1290
         }
 
1291
         case FILTER_PROJECTS:
 
1292
         case FILTER_PES:
 
1293
         case FILTER_QUEUES:
 
1294
            DPRINTF(("matching projects, pes or queues with %s\n", value? value: "NULL"));
 
1295
            if (lGetElemStr(xscope, ST_name, value) != NULL) {
 
1296
               ret = false;
 
1297
            } else {
 
1298
               for_each(ep, xscope) {
 
1299
                  const char *cp = lGetString(ep, ST_name);
 
1300
                  if (value == NULL || (strcmp(value, "*") == 0)) {
 
1301
                     break;
 
1302
                  }
 
1303
                  DPRINTF(("xscope: strcmp(%s,%s)\n", cp, value));
 
1304
                  if ((strcmp(cp, "*") == 0) || (fnmatch(cp, value, 0) == 0) || (fnmatch(value,cp, 0) == 0)) {
 
1305
                     DPRINTF(("match\n"));
 
1306
                     ret = false;
 
1307
                     break;
 
1308
                  }
 
1309
                  DPRINTF(("no match\n"));
 
1310
               }
 
1311
            }
 
1312
            if (ret != false) { 
 
1313
               bool found = false;
 
1314
               if (lGetElemStr(scope, ST_name, value) != NULL) {
 
1315
                  found = true;
 
1316
               } else {
 
1317
                  for_each(ep, scope) {
 
1318
                     const char *cp = lGetString(ep, ST_name);
 
1319
 
 
1320
                     if (value == NULL) {
 
1321
                        break;
 
1322
                     }
 
1323
                     DPRINTF(("scope: strcmp(%s,%s)\n", cp, value));
 
1324
                     if ((strcmp(cp, "*") == 0) || (fnmatch(cp, value, 0) == 0) || (fnmatch(value,cp, 0) == 0)) {
 
1325
                        found = true;
 
1326
                        break;
 
1327
                     }
 
1328
                  }
 
1329
               }
 
1330
               if (scope != NULL && found == false) {
 
1331
                  ret = false;
 
1332
               }
 
1333
            }
 
1334
            break;
 
1335
      }
 
1336
   }
 
1337
 
 
1338
   DRETURN(ret);
 
1339
}
 
1340
 
 
1341
/****** sge_resource_quota/sge_centry_referenced_in_rqs() *************************
 
1342
*  NAME
 
1343
*     sge_centry_referenced_in_rqs() -- search for a centry reference in
 
1344
*                                        a resource quota set
 
1345
*
 
1346
*  SYNOPSIS
 
1347
*     bool sge_centry_referenced_in_rqs(const lListElem *rqs, const lListElem 
 
1348
*     *centry) 
 
1349
*
 
1350
*  FUNCTION
 
1351
*     This function search a centry reference in a resource quota set
 
1352
*
 
1353
*  INPUTS
 
1354
*     const lListElem *rqs   - resource quota set
 
1355
*     const lListElem *centry - complex entry
 
1356
*
 
1357
*  RESULT
 
1358
*     bool - true if found
 
1359
*            false if not found
 
1360
*
 
1361
*  NOTES
 
1362
*     MT-NOTE: sge_centry_referenced_in_rqs() is MT safe 
 
1363
*
 
1364
*******************************************************************************/
 
1365
bool sge_centry_referenced_in_rqs(const lListElem *rqs, const lListElem *centry)
 
1366
{
 
1367
   bool ret = false;
 
1368
   const char *centry_name = lGetString(centry, CE_name);
 
1369
   lListElem *rule;
 
1370
 
 
1371
   DENTER(TOP_LAYER, "sge_centry_referenced_in_rqs");
 
1372
 
 
1373
   for_each(rule, lGetList(rqs, RQS_rule)) {
 
1374
      lListElem *limit;
 
1375
      for_each(limit, lGetList(rule, RQR_limit)) {
 
1376
         const char *limit_name = lGetString(limit, RQRL_value);
 
1377
         DPRINTF(("limit name %s\n", limit_name));
 
1378
         if (strchr(limit_name, '$') != NULL) {
 
1379
            /* dynamical limit */
 
1380
            if (load_formula_is_centry_referenced(limit_name, centry)) {
 
1381
               ret = true;
 
1382
               break;
 
1383
            }
 
1384
         } else {
 
1385
            /* static limit */
 
1386
            if (strcmp(limit_name, centry_name) == 0) {
 
1387
               ret = true;
 
1388
               break;
 
1389
            }
 
1390
         }
 
1391
      }
 
1392
      if (ret) {
 
1393
         break;
 
1394
      }
 
1395
   }
 
1396
 
 
1397
   DRETURN(ret);
 
1398
}
 
1399
 
 
1400
/****** sge_resource_quota/rqs_replace_request_verify() ************************
 
1401
*  NAME
 
1402
*     rqs_replace_request_verify() -- verify a rqs replace request
 
1403
*
 
1404
*  SYNOPSIS
 
1405
*     bool rqs_replace_request_verify(lList **answer_list, const lList 
 
1406
*     *request) 
 
1407
*
 
1408
*  FUNCTION
 
1409
*     Verify a rqs replace request (e.g. coming from a qconf -mrqs).
 
1410
*     We make sure, that no duplicate names appear in the request.
 
1411
*
 
1412
*  INPUTS
 
1413
*     lList **answer_list  - answer list to report errors
 
1414
*     const lList *request - the request to check
 
1415
*
 
1416
*  RESULT
 
1417
*     bool - true, if it is ok, false on error
 
1418
*
 
1419
*  NOTES
 
1420
*     MT-NOTE: rqs_replace_request_verify() is MT safe 
 
1421
*******************************************************************************/
 
1422
bool rqs_replace_request_verify(lList **answer_list, const lList *request)
 
1423
{
 
1424
   lListElem *ep;
 
1425
 
 
1426
   DENTER(TOP_LAYER, "rqs_replace_request_verify");
 
1427
 
 
1428
   /* search for duplicate rqs names in the request */
 
1429
   for_each(ep, request) {
 
1430
      const char *name = lGetString(ep, RQS_name);
 
1431
 
 
1432
      lListElem *second = lNext(ep);
 
1433
      while (second != NULL) {
 
1434
         const char *second_name = lGetString(second, RQS_name);
 
1435
         if (strcmp(name, second_name) == 0) {
 
1436
            answer_list_add_sprintf(answer_list, STATUS_EUNKNOWN, ANSWER_QUALITY_ERROR, 
 
1437
                                    MSG_RQS_REQUEST_DUPLICATE_NAME_S, name);
 
1438
            DRETURN(false);
 
1439
         }
 
1440
         second = lNext(second);
 
1441
      }
 
1442
   }
 
1443
 
 
1444
   DRETURN(true);
 
1445
}