1
/*___INFO__MARK_BEGIN__*/
2
/*************************************************************************
4
* The Contents of this file are made available subject to the terms of
5
* the Sun Industry Standards Source License Version 1.2
7
* Sun Microsystems Inc., March, 2001
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
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.
24
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
26
* Copyright: 2001 by Sun Microsystems, Inc.
28
* All Rights Reserved.
30
************************************************************************/
31
/*___INFO__MARK_END__*/
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"
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);
62
/****** sge_resource_quota/rqs_parse_filter_from_string() *************************
64
* rqs_parse_filter_from_string() -- parse a RQRF Object from string
67
* bool rqs_parse_filter_from_string(lListElem **filter, const char* buffer,
71
* Converts a spooled RQRF Object to a CULL Element
74
* lListElem **filter - resulting RQRF object
75
* const char* buffer - string to be converted
76
* lList **alp - answer_list
79
* bool - true on success
83
* MT-NOTE: rqs_parse_filter_from_string() is MT safe
85
*******************************************************************************/
86
bool rqs_parse_filter_from_string(lListElem **filter, const char* buffer, lList **alp) {
87
lListElem *tmp_filter = NULL;
88
lListElem *scope = NULL;
90
lList *scope_list = NULL;
91
lList *xscope_list = NULL;
92
char delims[] = "\t \v\r,{}";
94
DENTER(TOP_LAYER, "rqs_parse_filter_from_string");
100
tmp_filter = lCreateElem(RQRF_Type);
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);
111
lSetBool(tmp_filter, RQRF_expand, false);
114
lString2List(buffer, &lp, ST_Type, ST_name, delims);
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);
121
lAddElemStr(&scope_list, ST_name, name, ST_Type);
127
lSetList(tmp_filter, RQRF_scope, scope_list);
128
lSetList(tmp_filter, RQRF_xscope, xscope_list);
130
*filter = tmp_filter;
135
/****** sge_resource_quota/rqs_append_filter_to_dstring() *************************
137
* rqs_append_filter_to_dstringRQRF_object_append_to_dstring() -- RQRF Element to string
140
* bool rqs_append_filter_to_dstring(lListElem *filter, dstring *buffer,
144
* Converts a RQRF element to string for spooling
147
* lListElem *filter - Element to be converted
148
* dstring *buffer - buffer for the element string
149
* lList **alp - answer_list
152
* bool - true on success
156
* MT-NOTE: rqs_append_filter_to_dstring() is MT safe
158
*******************************************************************************/
159
bool rqs_append_filter_to_dstring(const lListElem *filter, dstring *buffer, lList **alp){
161
lListElem *scope = NULL;
166
if (filter == NULL) {
170
expand = lGetBool(filter, RQRF_expand) ? true : false;
173
sge_dstring_append_char(buffer, '{');
176
tlp = lGetList(filter, RQRF_scope);
177
for_each(scope, tlp) {
180
sge_dstring_append_char(buffer, ',');
184
sge_dstring_append(buffer, lGetString(scope, ST_name));
187
tlp = lGetList(filter, RQRF_xscope);
188
for_each(scope, tlp) {
191
sge_dstring_append_char(buffer, ',');
195
sge_dstring_append_char(buffer, '!');
196
sge_dstring_append(buffer, lGetString(scope, ST_name));
200
sge_dstring_append_char(buffer, '}');
206
/****** sge_resource_quota/rqs_set_defaults() *******************************
208
* rqs_set_defaults() -- set default values to given rqs
211
* lListElem* rqs_set_defaults(lListElem* rqs)
214
* This function sets the default values to a resource quota set.
215
* The default rule set is:
217
* name = <must be already set>
223
* lListElem* rqs - Already created object to be modified.
226
* lListElem* - modified Object
229
* MT-NOTE: rqs_set_defaults() is MT safe
230
*******************************************************************************/
231
lListElem* rqs_set_defaults(lListElem* rqs)
233
DENTER(TOP_LAYER, "rqs_set_defaults");
236
lList *limit_list = NULL;
237
lList *rule_list = NULL;
238
lListElem *rule = NULL;
239
lListElem *limit = NULL;
242
rule_list = lGetList(rqs, RQS_rule);
243
lFreeList(&rule_list);
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);
256
/* Set RQS_enabled */
257
lSetBool(rqs, RQS_enabled, false);
260
lSetList(rqs, RQS_rule, rule_list);
265
/****** sge_resource_quota/rqs_verify_attributes() **********************
267
* rqs_verify_attributes() -- verify the attributes of a rqs Object
270
* bool rqs_verify_attributes(lListElem *rqs, lList
271
* **answer_list, bool in_master)
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.
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
285
* bool - true on success
289
* MT-NOTE: rqs_verify_attributes() is not MT safe
290
*******************************************************************************/
291
bool rqs_verify_attributes(lListElem *rqs, lList **answer_list, bool in_master)
296
DENTER(TOP_LAYER, "rqs_verify_attributes");
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);
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);
311
if (ret && in_master) {
312
lList *master_centry_list = (*centry_list_get_master_list());
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);
322
/* set rule level. Needed by schedd */
324
if ((filter = lGetObject(rule, RQR_filter_hosts))) {
325
lListElem *host = NULL;
326
host_expand = lGetBool(filter, RQRF_expand) ? true : false;
328
for_each(host, lGetList(filter, RQRF_xscope)) {
329
sge_resolve_host(host, ST_name);
331
for_each(host, lGetList(filter, RQRF_scope)) {
332
sge_resolve_host(host, ST_name);
336
if ((filter = lGetObject(rule, RQR_filter_queues))) {
337
queue_expand = lGetBool(filter, RQRF_expand) ? true : false;
340
if (host_expand == false && queue_expand == false) {
341
lSetUlong(rule, RQR_level, RQR_GLOBAL);
342
} else if (host_expand == true && queue_expand == false) {
344
lSetUlong(rule, RQR_level, RQR_HOST);
345
} else if (host_expand == false && queue_expand == true) {
347
lSetUlong(rule, RQR_level, RQR_CQUEUE);
349
lSetUlong(rule, RQR_level, RQR_QUEUEI);
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);
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);
364
lSetString(limit, RQRL_name, lGetString(centry, CE_name));
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)) {
375
lSetUlong(limit, RQRL_type, lGetUlong(centry, CE_valtype));
376
lSetBool(limit, RQRL_dynamic, true);
378
answer_list_add_sprintf(answer_list, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR, MSG_RESOURCEQUOTA_DYNAMICLIMITNOTSUPPORTED);
382
/* The evaluation of the value needs to be done at scheduling time. Per default it's zero */
384
lListElem *tmp_ce = lCopyElem(centry);
385
/* fix limit, fill up missing attributes */
386
lSetBool(limit, RQRL_dynamic, false);
388
lSetString(tmp_ce, CE_stringval, strval);
389
if (centry_fill_and_check(tmp_ce, answer_list, false, false)) {
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));
410
/****** sge_resource_quota/rqs_list_verify_attributes() *********************
412
* rqs_list_verify_attributes() -- verifies the attributes of a rqs list
415
* bool rqs_list_verify_attributes(lList *rqs_list, lList
416
* **answer_list, bool in_master)
419
* This function iterates over a rqs list and checks for every rqs the attributes
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
427
* bool - true on success
430
* MT-NOTE: rqs_list_verify_attributes() is MT safe
433
* sge_resource_quota/rqs_verify_attributes()
434
*******************************************************************************/
435
bool rqs_list_verify_attributes(lList *rqs_list, lList **answer_list, bool in_master)
439
DENTER(TOP_LAYER, "rqs_list_verify_attributes");
440
if (rqs_list != NULL) {
441
lListElem *rqs = NULL;
443
for_each(rqs, rqs_list) {
444
ret = rqs_verify_attributes(rqs, answer_list, in_master);
453
/****** sge_resource_quota/rqs_list_locate() ****************************
455
* rqs_list_locate() -- locate a specific resource quota set by name
458
* lListElem* rqs_list_locate(lList *lp, const char *name)
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.
465
* lList *lp - rule set list to be searched in
466
* const char *name - rule set name of interest
469
* lListElem* - if found the reference to the resource quota set, else NULL
472
* MT-NOTE: rqs_list_locate() is MT safe
473
*******************************************************************************/
474
lListElem *rqs_list_locate(lList *lp, const char *name)
476
lListElem *ep = NULL;
478
DENTER(TOP_LAYER, "rqs_list_locate");
480
ep = lGetElemStr(lp, RQS_name, name);
485
/****** sge_resource_quota/rqs_rule_locate() *************************************
487
* rqs_rule_locate() -- locate a specific rule by name
490
* lListElem* rqs_rule_locate(lList *lp, const char *name)
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.
500
* lList *lp - list to be searched in
501
* const char *name - rule name of interest
504
* lListElem* - reference to found rule
505
* NULL if rule was not found
508
* MT-NOTE: rqs_rule_locate() is MT safe
509
*******************************************************************************/
510
lListElem* rqs_rule_locate(lList *lp, const char *name)
512
lListElem *ep = NULL;
516
DENTER(TOP_LAYER, "rqs_rule_locate");
522
get_pos = atoi(name);
525
const char *rule_name = lGetString(ep, RQR_name);
526
if (get_pos != -1 && act_pos == get_pos) {
528
} else if (rule_name != NULL && !strcasecmp(name, lGetString(ep, RQR_name))) {
537
/****** sge_resource_quota/rqs_xattr_pre_gdi() *************************************
539
* rqs_xattr_pre_gdi() -- qconf xattr list preformat
542
* bool rqs_xattr_pre_gdi(lList *this_list, lList **answer_list)
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
552
* lList *this_list - list to be modified
553
* lList **answer_list - answer list
556
* bool - true on success
560
* MT-NOTE: rqs_xattr_pre_gdi() is MT safe
561
*******************************************************************************/
562
bool rqs_xattr_pre_gdi(lList *this_list, lList **answer_list)
567
DENTER(TOP_LAYER, "rqs_xattr_pre_gdi");
568
if (this_list != NULL) {
569
lListElem *rqs = NULL;
571
for_each(rqs, this_list) {
573
const char *name = lGetString(rqs, RQS_name);
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);
582
lSetString(rqs, RQS_name, lGetString(ep, ST_name));
584
for_each(rule, rules) {
585
lSetString(rule, RQR_name, lGetString(ep, ST_name));
594
/****** sge_resource_quota/rqs_get_rue_string() *****************************
596
* rqs_get_rue_string() -- creates a rue name
599
* bool rqs_get_rue_string(dstring *name, lListElem *rule, const char
600
* *user, const char *project, const char *host, const char *queue, const
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,
607
* Filters that count for a sum
608
* of hosts are saved as a empty string because they don't need to be matched.
610
* For example the rule
611
* limit users `*` queues `all.q,my.q` to slots=10
612
* may result in the rue name
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
628
* MT-NOTE: rqs_get_rue_string() is MT safe
630
*******************************************************************************/
632
rqs_get_rue_string(dstring *name, const lListElem *rule, const char *user,
633
const char *project, const char *host, const char *queue,
636
lListElem *filter = NULL;
638
DENTER(BASIS_LAYER, "rqs_get_rue_string");
644
sge_dstring_clear(name);
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);
651
sge_dstring_append(name, "/");
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);
658
sge_dstring_append(name, "/");
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);
665
sge_dstring_append(name, "/");
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);
672
sge_dstring_append(name, "/");
674
if ((filter = lGetObject(rule, RQR_filter_hosts)) != NULL) {
675
if (filter != NULL && host != NULL && lGetBool(filter, RQRF_expand) == true) {
677
sge_hostcpy(buffer, host);
678
sge_dstring_append(name, buffer);
681
sge_dstring_append(name, "/");
683
DPRINTF(("rue_name: %s\n", sge_dstring_get_string(name)));
688
/****** sge_resource_quota/rqs_debit_consumable() *********************************
690
* rqs_debit_consumable() -- debit slots in all relevant rule sets
693
* int rqs_debit_consumable(lListElem *rqs, lListElem *job, lListElem
694
* *granted, lListElem *pe, lList *centry_list, int slots)
697
* iterater over all rules in the given rule set and debit the amount of slots
698
* in the relevant rule
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
709
* int - amount of modified rule
712
* MT-NOTE: rqs_debit_consumable() is not MT safe
714
*******************************************************************************/
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)
719
lListElem *rule = NULL;
721
const char* hostname = lGetHost(granted, JG_qhostname);
722
const char* username = lGetString(job, JB_owner);
723
const char* groupname = lGetString(job, JB_group);
725
const char *queue_instance = lGetString(granted, JG_qname);
726
const char* project = lGetString(job, JB_project);
728
DENTER(TOP_LAYER, "rqs_debit_consumable");
730
if (!lGetBool(rqs, RQS_enabled)) {
734
/* remove the host name part of the queue instance name */
735
qname = cqueue_get_name_from_qinstance(queue_instance);
737
rule = rqs_get_matching_rule(rqs, username, groupname, project, pename, hostname, qname, acl_list, hgrp_list, NULL);
741
dstring rue_name = DSTRING_INIT;
743
rqs_get_rue_string(&rue_name, rule, username, project,
744
hostname, qname, pename);
746
mods = rqs_debit_rule_usage(job, rule, &rue_name, slots, centry_list, lGetString(rqs, RQS_name));
748
sge_dstring_free(&rue_name);
756
/****** sge_resource_quota/rqs_get_matching_rule() ********************************
758
* rqs_get_matching_rule() -- found relevant rule for job request
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)
766
* This function searches in a resource quota set the relevant rule.
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
780
* lListElem* - pointer to matching rule
783
* MT-NOTE: rqs_get_matching_rule() is MT safe
785
*******************************************************************************/
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)
791
lListElem *rule = NULL;
792
lList *rule_list = lGetList(rqs, RQS_rule);
795
DENTER(BASIS_LAYER, "rqs_get_matching_rule");
797
for_each (rule, rule_list) {
800
if (!rqs_is_matching_rule(rule, user, group, project, pe, host, queue, userset_list, hgroup_list)) {
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));
807
DPRINTF(("Using resource quota %d\n", i));
808
sge_dstring_sprintf(rule_name, "%s/%d", lGetString(rqs, RQS_name), i);
810
/* if all filter object matches this is our rule */
816
/****** sge_resource_quota/rqs_debit_rule_usage() *********************************
818
* rqs_debit_rule_usage() -- debit usage in a resource quota rule
821
* int rqs_debit_rule_usage(lListElem *job, lListElem *rule, dstring
822
* *rue_name, int slots, lList *centry_list, const char *obj_name)
825
* Debit an amount of slots in all limits of one resource quota rule
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
836
* int - amount of debited limits
839
* MT-NOTE: rqs_debit_rule_usage() is MT safe
840
*******************************************************************************/
842
rqs_debit_rule_usage(lListElem *job, lListElem *rule, dstring *rue_name, int slots, lList *centry_list, const char *obj_name)
846
const char *centry_name;
849
DENTER(TOP_LAYER, "rqs_debit_rule_usage");
851
limit_list = lGetList(rule, RQR_limit);
853
for_each(limit, limit_list) {
854
lListElem *raw_centry;
858
centry_name = lGetString(limit, RQRL_name);
860
if (!(raw_centry = centry_list_locate(centry_list, centry_name))) {
861
/* ignoring not defined centry */
865
if (!lGetBool(raw_centry, CE_consumable)) {
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 */
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);
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);
893
/****** sge_resource_quota/rqs_match_user_host_scope() ****************************
895
* rqs_match_user_host_scope() -- match user or host scope
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)
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
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)
915
* static bool - true, if value was found in scope
916
* false, if value was not found in scope
919
* MT-NOTE: rqs_match_user_host_scope() is MT safe
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) {
929
DENTER(TOP_LAYER, "rqs_match_user_host_scope");
931
if (!sge_is_pattern(value)) {
932
/* used in scheduler/qmaster and qquota */
933
if (lGetElemStr(scope, ST_name, value) != NULL) {
936
for_each(ep, scope) {
938
const char *cp = lGetString(ep, ST_name);
939
const char *group_name = NULL;
940
const char *query = NULL;
942
if (fnmatch(cp, value, 0) == 0) {
947
if (!is_hgroup_name(value) && is_hgroup_name(cp)) {
950
} else if (is_hgroup_name(value) && !is_hgroup_name(cp)) {
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 */
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) {
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) {
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);
990
} else if (sge_is_pattern(query)) {
992
for_each(host_ep, host_list) {
993
if (fnmatch(query, lGetHost(host_ep, HR_name), 0) == 0) {
994
lFreeList(&host_list);
1003
lFreeList(&host_list);
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);
1013
} else if (sge_is_pattern(query)) {
1015
for_each(host_ep, host_list) {
1016
if (fnmatch(query, lGetHost(host_ep, HR_name), 0) == 0) {
1017
lFreeList(&host_list);
1022
if (found == true) {
1026
lFreeList(&host_list);
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;
1041
if (fnmatch(value, cp, 0) == 0) {
1046
if (strcmp(value, cp) == 0) {
1047
/* amount of sets is equal */
1051
/* amount of sets does not overlap. We can not reject in
1052
xscope context and have to wave through */
1058
if (sge_is_pattern(cp) && (fnmatch(cp, value, 0) == 0)) {
1062
if (!is_hgroup_name(value) && is_hgroup_name(cp)) {
1065
} else if (is_hgroup_name(value) && !is_hgroup_name(cp)) {
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 */
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) {
1084
if (found == true) {
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) {
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) {
1099
lFreeList(&host_list);
1100
if (found == true) {
1105
if (found == true) {
1115
/****** sge_resource_quota/rqs_is_matching_rule() *********************************
1117
* rqs_is_matching_rule() -- matches a rule with the filter touples
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)
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
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)
1140
* bool - true if the rule does match
1141
* false if the rule does not match
1144
* MT-NOTE: rqs_is_matching_rule() is MT safe
1146
*******************************************************************************/
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)
1150
DENTER(TOP_LAYER, "rqs_is_matching_rule");
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"));
1156
if (!rqs_filter_match(lGetObject(rule, RQR_filter_projects), FILTER_PROJECTS, project, NULL, NULL, NULL)) {
1157
DPRINTF(("project doesn't match\n"));
1160
if (!rqs_filter_match(lGetObject(rule, RQR_filter_pes), FILTER_PES, pe, NULL, NULL, NULL)) {
1161
DPRINTF(("pe doesn't match\n"));
1164
if (!rqs_filter_match(lGetObject(rule, RQR_filter_queues), FILTER_QUEUES, queue, NULL, NULL, NULL)) {
1165
DPRINTF(("queue doesn't match\n"));
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"));
1178
/****** sge_resource_quota/rqs_match_host_scope() ******************************
1180
* rqs_match_host_scope() -- Match name with host scope
1183
* static bool rqs_match_host_scope(lList *scope, const char *name, lList
1184
* *master_hgroup_list)
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.
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)
1198
* bool - Returns true if 'name' matches
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)
1207
DENTER(TOP_LAYER, "rqs_match_host_scope");
1209
if (lGetElemStr(scope, ST_name, "*")) {
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));
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)) {
1228
/****** sge_resource_quota/rqs_filter_match() *******************************
1230
* rqs_filter_match() -- compares value with configured filter
1233
* bool rqs_filter_match(lListElem *filter, int filter_type, const
1234
* char *value, lList *master_userset_list, lList *master_hgroup_list)
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
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)
1249
* bool - true if the value does match
1250
* false if the value does not match
1253
* MT-NOTE: rqs_filter_match() is MT safe
1255
*******************************************************************************/
1257
rqs_filter_match(lListElem *filter, int filter_type, const char *value, lList *master_userset_list, lList *master_hgroup_list, const char *group) {
1261
DENTER(BASIS_LAYER, "rqs_filter_match");
1263
if (filter != NULL) {
1264
lList* scope = lGetList(filter, RQRF_scope);
1265
lList* xscope = lGetList(filter, RQRF_xscope);
1267
switch (filter_type) {
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)) {
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)) {
1291
case FILTER_PROJECTS:
1294
DPRINTF(("matching projects, pes or queues with %s\n", value? value: "NULL"));
1295
if (lGetElemStr(xscope, ST_name, value) != NULL) {
1298
for_each(ep, xscope) {
1299
const char *cp = lGetString(ep, ST_name);
1300
if (value == NULL || (strcmp(value, "*") == 0)) {
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"));
1309
DPRINTF(("no match\n"));
1314
if (lGetElemStr(scope, ST_name, value) != NULL) {
1317
for_each(ep, scope) {
1318
const char *cp = lGetString(ep, ST_name);
1320
if (value == NULL) {
1323
DPRINTF(("scope: strcmp(%s,%s)\n", cp, value));
1324
if ((strcmp(cp, "*") == 0) || (fnmatch(cp, value, 0) == 0) || (fnmatch(value,cp, 0) == 0)) {
1330
if (scope != NULL && found == false) {
1341
/****** sge_resource_quota/sge_centry_referenced_in_rqs() *************************
1343
* sge_centry_referenced_in_rqs() -- search for a centry reference in
1344
* a resource quota set
1347
* bool sge_centry_referenced_in_rqs(const lListElem *rqs, const lListElem
1351
* This function search a centry reference in a resource quota set
1354
* const lListElem *rqs - resource quota set
1355
* const lListElem *centry - complex entry
1358
* bool - true if found
1359
* false if not found
1362
* MT-NOTE: sge_centry_referenced_in_rqs() is MT safe
1364
*******************************************************************************/
1365
bool sge_centry_referenced_in_rqs(const lListElem *rqs, const lListElem *centry)
1368
const char *centry_name = lGetString(centry, CE_name);
1371
DENTER(TOP_LAYER, "sge_centry_referenced_in_rqs");
1373
for_each(rule, lGetList(rqs, RQS_rule)) {
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)) {
1386
if (strcmp(limit_name, centry_name) == 0) {
1400
/****** sge_resource_quota/rqs_replace_request_verify() ************************
1402
* rqs_replace_request_verify() -- verify a rqs replace request
1405
* bool rqs_replace_request_verify(lList **answer_list, const lList
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.
1413
* lList **answer_list - answer list to report errors
1414
* const lList *request - the request to check
1417
* bool - true, if it is ok, false on error
1420
* MT-NOTE: rqs_replace_request_verify() is MT safe
1421
*******************************************************************************/
1422
bool rqs_replace_request_verify(lList **answer_list, const lList *request)
1426
DENTER(TOP_LAYER, "rqs_replace_request_verify");
1428
/* search for duplicate rqs names in the request */
1429
for_each(ep, request) {
1430
const char *name = lGetString(ep, RQS_name);
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);
1440
second = lNext(second);