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
************************************************************************/
36
#include "sge_hostL.h"
38
#include "sge_qrefL.h"
40
#include "sge_userprjL.h"
41
#include "sge_userprj.h"
42
#include "sge_cqueueL.h"
43
#include "sge_qinstance.h"
44
#include "sge_qinstance_state.h"
45
#include "sge_qinstance_type.h"
46
#include "sge_select_queue.h"
47
#include "sge_cqueue_qstat.h"
48
#include "qstat_printing.h"
53
#include "sge_centry.h"
54
#include "valid_queue_user.h"
55
#include "sge_cqueue.h"
56
#include "sge_complex_schedd.h"
57
#include "sge_schedd_conf.h"
58
#include "sge_parse_num_par.h"
59
#include "sched/sge_resource_utilization.h"
60
#include "uti/sge_time.h"
62
#include "msg_clients_common.h"
65
bool cqueue_calculate_summary(const lListElem *cqueue,
66
const lList *exechost_list,
67
const lList *centry_list,
69
bool *is_load_available,
73
u_long32 *suspend_manual,
74
u_long32 *suspend_threshold,
75
u_long32 *suspend_on_subordinate,
76
u_long32 *suspend_calendar,
79
u_long32 *disabled_manual,
80
u_long32 *disabled_calendar,
85
u_long32 *temp_disabled,
86
u_long32 *manual_intervention)
91
DENTER(TOP_LAYER, "cqueue_calculate_summary");
93
lList *qinstance_list = lGetList(cqueue, CQ_qinstances);
94
lListElem *qinstance = NULL;
95
double host_load_avg = 0.0;
96
u_long32 load_slots = 0;
97
u_long32 used_available = 0;
98
u_long32 used_slots = 0;
99
u_long32 resv_slots = 0;
102
*is_load_available = false;
103
*used = *total = *resv = 0;
104
*available = *temp_disabled = *manual_intervention = 0;
105
*suspend_manual = *suspend_threshold = *suspend_on_subordinate = 0;
106
*suspend_calendar = *unknown = *load_alarm = 0;
107
*disabled_manual = *disabled_calendar = *ambiguous = 0;
108
*orphaned = *error = 0;
109
for_each(qinstance, qinstance_list) {
110
u_long32 slots = lGetUlong(qinstance, QU_job_slots);
111
bool has_value_from_object;
113
used_slots = qinstance_slots_used(qinstance);
114
resv_slots = qinstance_slots_reserved_now(qinstance);
115
(*used) += used_slots;
116
(*resv) += resv_slots;
119
if (!sge_get_double_qattr(&host_load_avg, LOAD_ATTR_NP_LOAD_AVG,
120
qinstance, exechost_list, centry_list,
121
&has_value_from_object)) {
122
if (has_value_from_object) {
123
*is_load_available = true;
125
*load += host_load_avg * slots;
130
* manual_intervention: cdsuE
131
* temp_disabled: aoACDS
133
if (qinstance_state_is_manual_suspended(qinstance) ||
134
qinstance_state_is_unknown(qinstance) ||
135
qinstance_state_is_manual_disabled(qinstance) ||
136
qinstance_state_is_ambiguous(qinstance) ||
137
qinstance_state_is_error(qinstance)) {
138
*manual_intervention += slots;
139
} else if (qinstance_state_is_alarm(qinstance) ||
140
qinstance_state_is_cal_disabled(qinstance) ||
141
qinstance_state_is_orphaned(qinstance) ||
142
qinstance_state_is_susp_on_sub(qinstance) ||
143
qinstance_state_is_cal_suspended(qinstance) ||
144
qinstance_state_is_suspend_alarm(qinstance)) {
145
*temp_disabled += slots;
148
used_available += used_slots;
150
if (qinstance_state_is_unknown(qinstance)) {
153
if (qinstance_state_is_alarm(qinstance)) {
154
*load_alarm += slots;
156
if (qinstance_state_is_manual_disabled(qinstance)) {
157
*disabled_manual += slots;
159
if (qinstance_state_is_cal_disabled(qinstance)) {
160
*disabled_calendar += slots;
162
if (qinstance_state_is_ambiguous(qinstance)) {
165
if (qinstance_state_is_orphaned(qinstance)) {
168
if (qinstance_state_is_manual_suspended(qinstance)) {
169
*suspend_manual += slots;
171
if (qinstance_state_is_susp_on_sub(qinstance)) {
172
*suspend_on_subordinate += slots;
174
if (qinstance_state_is_cal_suspended(qinstance)) {
175
*suspend_calendar += slots;
177
if (qinstance_state_is_suspend_alarm(qinstance)) {
178
*suspend_threshold += slots;
180
if (qinstance_state_is_error(qinstance)) {
185
*available -= used_available;
192
select_by_qref_list(lList *cqueue_list, const lList *hgrp_list, const lList *qref_list)
195
lList *queueref_list = NULL;
197
DENTER(TOP_LAYER, "select_by_qref_list");
200
* Resolve queue pattern
203
lList *tmp_list = NULL;
204
bool found_something = true;
205
queueref_list = lCopyList("", qref_list);
207
qref_list_resolve(queueref_list, NULL, &tmp_list,
208
&found_something, cqueue_list, hgrp_list, true, true);
209
if (!found_something) {
210
lFreeList(&queueref_list);
214
lFreeList(&queueref_list);
215
queueref_list = tmp_list;
220
if (cqueue_list != NULL && queueref_list != NULL) {
221
lListElem *cqueue = NULL;
222
lListElem *qref = NULL;
224
for_each(qref, queueref_list) {
225
dstring cqueue_buffer = DSTRING_INIT;
226
dstring hostname_buffer = DSTRING_INIT;
227
const char *full_name = NULL;
228
const char *cqueue_name = NULL;
229
const char *hostname = NULL;
230
bool has_hostname = false;
231
bool has_domain = false;
232
lListElem *cqueue = NULL;
233
lListElem *qinstance = NULL;
234
lList *qinstance_list = NULL;
237
full_name = lGetString(qref, QR_name);
238
cqueue_name_split(full_name, &cqueue_buffer, &hostname_buffer,
239
&has_hostname, &has_domain);
240
cqueue_name = sge_dstring_get_string(&cqueue_buffer);
241
hostname = sge_dstring_get_string(&hostname_buffer);
242
cqueue = lGetElemStr(cqueue_list, CQ_name, cqueue_name);
243
qinstance_list = lGetList(cqueue, CQ_qinstances);
244
qinstance = lGetElemHost(qinstance_list, QU_qhostname, hostname);
246
tag = lGetUlong(qinstance, QU_tag);
247
lSetUlong(qinstance, QU_tag, tag | TAG_SELECT_IT);
249
sge_dstring_free(&cqueue_buffer);
250
sge_dstring_free(&hostname_buffer);
253
for_each(cqueue, cqueue_list) {
254
lListElem *qinstance = NULL;
255
lList *qinstance_list = NULL;
257
qinstance_list = lGetList(cqueue, CQ_qinstances);
258
for_each(qinstance, qinstance_list) {
259
u_long32 tag = lGetUlong(qinstance, QU_tag);
260
bool selected = ((tag & TAG_SELECT_IT) != 0) ? true : false;
263
tag &= ~(TAG_SELECT_IT | TAG_SHOW_IT);
264
lSetUlong(qinstance, QU_tag, tag);
272
lFreeList(&queueref_list);
279
untag all queues not selected by a -pe
286
int select_by_pe_list(
288
lList *peref_list, /* ST_Type */
292
lList *pe_selected = NULL;
293
lListElem *pe, *qep, *cqueue;
295
DENTER(TOP_LAYER, "select_by_pe_list");
298
* iterate through peref_list and build up a new pe_list
299
* containing only those pe's referenced in peref_list
301
for_each(pe, peref_list) {
302
lListElem *ref_pe; /* PE_Type */
303
lListElem *copy_pe; /* PE_Type */
305
ref_pe = pe_list_locate(pe_list, lGetString(pe, ST_name));
306
copy_pe = lCopyElem(ref_pe);
307
if (pe_selected == NULL) {
308
const lDescr *descriptor = lGetElemDescr(ref_pe);
310
pe_selected = lCreateList("", descriptor);
312
lAppendElem(pe_selected, copy_pe);
314
if (lGetNumberOfElem(pe_selected)==0) {
315
fprintf(stderr, "%s\n", MSG_PE_NOSUCHPARALLELENVIRONMENT);
320
* untag all non-parallel queues and queues not referenced
321
* by a pe in the selected pe list entry of a queue
323
for_each(cqueue, queue_list) {
324
lList *qinstance_list = lGetList(cqueue, CQ_qinstances);
326
for_each(qep, qinstance_list) {
327
lListElem* found = NULL;
329
if (!qinstance_is_parallel_queue(qep)) {
330
lSetUlong(qep, QU_tag, 0);
333
for_each (pe, pe_selected) {
334
const char *pe_name = lGetString(pe, PE_name);
336
found = lGetSubStr(qep, ST_name, pe_name, QU_pe_list);
342
lSetUlong(qep, QU_tag, 0);
349
if (pe_selected != NULL) {
350
lFreeList(&pe_selected);
357
untag all queues not selected by a -pe
364
int select_by_queue_user_list(
365
lList *exechost_list,
367
lList *queue_user_list,
372
lListElem *qu = NULL;
373
lListElem *qep = NULL;
374
lListElem *cqueue = NULL;
375
lListElem *ehep = NULL;
377
lList *h_xacl = NULL;
378
lList *global_acl = NULL;
379
lList *global_xacl = NULL;
380
lList *config_acl = NULL;
381
lList *config_xacl = NULL;
385
lList *h_xprj = NULL;
386
lList *global_prj = NULL;
387
lList *global_xprj = NULL;
389
DENTER(TOP_LAYER, "select_by_queue_user_list");
391
/* untag all queues where no of the users has access */
393
ehep = host_list_locate(exechost_list, "global");
394
global_acl = lGetList(ehep, EH_acl);
395
global_xacl = lGetList(ehep, EH_xacl);
396
global_prj = lGetList(ehep, EH_prj);
397
global_xprj = lGetList(ehep, EH_xprj);
399
config_acl = mconf_get_user_lists();
400
config_xacl = mconf_get_xuser_lists();
402
for_each(cqueue, cqueue_list) {
403
lList *qinstance_list = lGetList(cqueue, CQ_qinstances);
405
for_each(qep, qinstance_list) {
407
const char *host_name = NULL;
409
prj = lGetList(qep, QU_projects);
410
xprj = lGetList(qep, QU_xprojects);
412
/* get exec host list element for current queue
413
and its access lists */
414
host_name = lGetHost(qep, QU_qhostname);
415
ehep = host_list_locate(exechost_list, host_name);
417
h_acl = lGetList(ehep, EH_acl);
418
h_xacl = lGetList(ehep, EH_xacl);
419
h_prj = lGetList(ehep, EH_prj);
420
h_xprj = lGetList(ehep, EH_xprj);
423
for_each (qu, queue_user_list) {
424
lListElem *pep = NULL;
430
const char *name = lGetString(qu, ST_name);
434
DPRINTF(("-----> checking queue user: %s\n", name ));
436
DPRINTF(("testing queue access lists\n"));
437
q_access = (name[0]=='@')?
438
sge_has_access(NULL, &name[1], qep, acl_list):
439
sge_has_access(name, NULL, qep, acl_list);
441
DPRINTF(("no access\n"));
445
if (project_list != NULL) {
446
DPRINTF(("testing queue projects lists\n"));
448
const char *prj_name;
450
if ((prj_name = lGetString(pep, PR_name))!=NULL) {
451
if ((prj = prj_list_locate(project_list, prj_name)) != NULL) {
452
q_access &= (name[0]=='@')?
453
sge_has_access_(NULL, &name[1], lGetList(prj, PR_acl), lGetList(prj, PR_xacl), acl_list):
454
sge_has_access_(name, NULL, lGetList(prj, PR_acl), lGetList(prj, PR_xacl), acl_list);
456
DPRINTF(("no reference object for project %s\n", prj_name));
460
for_each(pep, xprj) {
461
const char *prj_name;
463
if ((prj_name = lGetString(pep, PR_name))!=NULL) {
464
if ((prj = prj_list_locate(project_list, prj_name)) != NULL) {
465
q_access &= (name[0]=='@')?
466
!sge_has_access_(NULL, &name[1], lGetList(prj, PR_acl), lGetList(prj, PR_xacl), acl_list):
467
!sge_has_access_(name, NULL, lGetList(prj, PR_acl), lGetList(prj, PR_xacl), acl_list);
469
DPRINTF(("no reference object for project %s\n", prj_name));
474
DPRINTF(("no access\n"));
480
DPRINTF(("testing host access lists\n"));
481
h_access = (name[0]=='@')?
482
sge_has_access_(NULL, &name[1], h_acl, h_xacl , acl_list):
483
sge_has_access_(name, NULL, h_acl, h_xacl , acl_list);
485
DPRINTF(("no access\n"));
489
if (project_list != NULL) {
490
DPRINTF(("testing host projects lists\n"));
491
for_each(pep, h_prj) {
492
const char *prj_name;
494
if ((prj_name = lGetString(pep, PR_name))!=NULL) {
495
if ((prj = prj_list_locate(project_list, prj_name)) != NULL) {
496
q_access &= (name[0]=='@')?
497
sge_has_access_(NULL, &name[1], lGetList(prj, PR_acl), lGetList(prj, PR_xacl), acl_list):
498
sge_has_access_(name, NULL, lGetList(prj, PR_acl), lGetList(prj, PR_xacl), acl_list);
500
DPRINTF(("no reference object for project %s\n", prj_name));
504
for_each(pep, h_xprj) {
505
const char *prj_name;
507
if ((prj_name = lGetString(pep, PR_name))!=NULL) {
508
if ((prj = prj_list_locate(project_list, prj_name)) != NULL) {
509
q_access &= (name[0]=='@')?
510
!sge_has_access_(NULL, &name[1], lGetList(prj, PR_acl), lGetList(prj, PR_xacl), acl_list):
511
!sge_has_access_(name, NULL, lGetList(prj, PR_acl), lGetList(prj, PR_xacl), acl_list);
513
DPRINTF(("no reference object for project %s\n", prj_name));
518
DPRINTF(("no access\n"));
524
DPRINTF(("testing global host access lists\n"));
525
gh_access = (name[0]=='@')?
526
sge_has_access_(NULL, &name[1], global_acl , global_xacl , acl_list):
527
sge_has_access_(name, NULL,global_acl , global_xacl , acl_list);
529
DPRINTF(("no access\n"));
533
if (project_list != NULL) {
534
DPRINTF(("testing host projects lists\n"));
535
for_each(pep, global_prj) {
536
const char *prj_name;
538
if ((prj_name = lGetString(pep, PR_name))!=NULL) {
539
if ((prj = prj_list_locate(project_list, prj_name)) != NULL) {
540
q_access &= (name[0]=='@')?
541
sge_has_access_(NULL, &name[1], lGetList(prj, PR_acl), lGetList(prj, PR_xacl), acl_list):
542
sge_has_access_(name, NULL, lGetList(prj, PR_acl), lGetList(prj, PR_xacl), acl_list);
544
DPRINTF(("no reference object for project %s\n", prj_name));
548
for_each(pep, global_xprj) {
549
const char *prj_name;
551
if ((prj_name = lGetString(pep, PR_name))!=NULL) {
552
if ((prj = prj_list_locate(project_list, prj_name)) != NULL) {
553
q_access &= (name[0]=='@')?
554
!sge_has_access_(NULL, &name[1], lGetList(prj, PR_acl), lGetList(prj, PR_xacl), acl_list):
555
!sge_has_access_(name, NULL, lGetList(prj, PR_acl), lGetList(prj, PR_xacl), acl_list);
557
DPRINTF(("no reference object for project %s\n", prj_name));
562
DPRINTF(("no access\n"));
568
DPRINTF(("testing cluster config access lists\n"));
569
conf_access = (name[0]=='@')?
570
sge_has_access_(NULL, &name[1],config_acl , config_xacl , acl_list):
571
sge_has_access_(name, NULL, config_acl , config_xacl , acl_list);
573
DPRINTF(("no access\n"));
578
access = q_access && h_access && gh_access && conf_access;
584
DPRINTF(("no access for queue %s\n", lGetString(qep,QU_qname) ));
585
lSetUlong(qep, QU_tag, 0);
588
DPRINTF(("access for queue %s\n", lGetString(qep,QU_qname) ));
594
lFreeList(&config_acl);
595
lFreeList(&config_xacl);
601
untag all queues not in a specific state
608
int select_by_queue_state(
609
u_long32 queue_states,
610
lList *exechost_list,
614
bool has_value_from_object;
617
lListElem *cqueue = NULL;
620
DENTER(TOP_LAYER, "select_by_queue_state");
622
/* only show queues in the requested state */
623
/* make it possible to display any load value in qstat output */
624
if (!(load_avg_str=getenv("SGE_LOAD_AVG")) || !strlen(load_avg_str))
625
load_avg_str = LOAD_ATTR_LOAD_AVG;
627
for_each(cqueue, queue_list){
628
lList *qinstance_list = lGetList(cqueue, CQ_qinstances);
629
lListElem *qep = NULL;
630
for_each(qep, qinstance_list) {
632
/* compute the load and suspend alarm */
633
sge_get_double_qattr(&load_avg, load_avg_str, qep, exechost_list, centry_list, &has_value_from_object);
634
if (sge_load_alarm(NULL, qep, lGetList(qep, QU_load_thresholds), exechost_list, centry_list, NULL, true)) {
635
qinstance_state_set_alarm(qep, true);
637
parse_ulong_val(NULL, &interval, TYPE_TIM,
638
lGetString(qep, QU_suspend_interval), NULL, 0);
639
if (lGetUlong(qep, QU_nsuspend) != 0 &&
641
sge_load_alarm(NULL, qep, lGetList(qep, QU_suspend_thresholds), exechost_list, centry_list, NULL, false)) {
642
qinstance_state_set_suspend_alarm(qep, true);
646
if (!qinstance_has_state(qep, queue_states)) {
647
lSetUlong(qep, QU_tag, 0);
656
untag all queues not covered by -l
659
0 successfully untagged qinstances if necessary
663
int select_by_resource_list(
664
lList *resource_list,
665
lList *exechost_list,
670
lListElem *cqueue = NULL;
672
DENTER(TOP_LAYER, "select_by_resource_list");
674
if (centry_list_fill_request(resource_list, NULL, centry_list, true, true, false)) {
676
** error message gets written by centry_list_fill_request into
683
/* prepare request */
684
for_each(cqueue, queue_list) {
687
lList *qinstance_list = lGetList(cqueue, CQ_qinstances);
689
for_each(qep, qinstance_list) {
691
sconf_set_qs_state(QS_STATE_EMPTY);
693
selected = sge_select_queue(resource_list, qep, NULL, exechost_list, centry_list, true, -1, NULL, NULL, NULL);
695
sconf_set_qs_state(QS_STATE_FULL);
698
lSetUlong(qep, QU_tag, 0);
706
bool is_cqueue_selected(lList *queue_list)
709
bool a_qinstance_is_selected = false;
710
bool a_cqueue_is_selected = false;
712
DENTER(TOP_LAYER, "is_cqueue_selected");
714
for_each(cqueue, queue_list) {
716
lList *qinstance_list = lGetList(cqueue, CQ_qinstances);
717
bool tmp_a_qinstance_is_selected = false;
719
for_each(qep, qinstance_list) {
720
if (lGetUlong(qep, QU_tag) & TAG_SHOW_IT) {
721
tmp_a_qinstance_is_selected = true;
725
a_qinstance_is_selected |= tmp_a_qinstance_is_selected;
726
if (!tmp_a_qinstance_is_selected && (lGetNumberOfElem(lGetList(cqueue,CQ_qinstances)) > 0)) {
727
lSetUlong(cqueue, CQ_tag, TAG_DEFAULT);
729
a_cqueue_is_selected |= true;
734
return a_cqueue_is_selected;
737
/****** sge_cqueue_qstat/qinstance_slots_reserved_now() ************************
739
* qinstance_slots_reserved_now() -- get current reserved slots
742
* int qinstance_slots_reserved_now(const lListElem *this_elem)
745
* rturns the current amount of reserved slots
748
* const lListElem *this_elem - queue elem (QU_Type)
751
* int - number of currently reserved slots
754
* MT-NOTE: qinstance_slots_reserved_now() is MT safe
757
* qinstance_slots_reserved()
758
*******************************************************************************/
759
int qinstance_slots_reserved_now(const lListElem *this_elem)
763
u_long32 now = sge_get_gmt();
765
DENTER(TOP_LAYER, "qinstance_slots_reserved_now");
767
slots = lGetSubStr(this_elem, RUE_name, SGE_ATTR_SLOTS, QU_resource_utilization);
769
ret = utilization_max(slots, now, 0);