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__*/
47
#include "sge_c_gdi.h"
48
#include "sge_string.h"
49
#include "sge_answer.h"
50
#include "sge_utility.h"
51
#include "sge_utility_qmaster.h"
52
#include "sge_unistd.h"
53
#include "sge_hgroup.h"
54
#include "sge_cqueue.h"
56
#include "sge_ja_task.h"
57
#include "sge_qinstance.h"
58
#include "sge_qinstance_state.h"
59
#include "sge_userset.h"
63
#include "sge_event_master.h"
64
#include "sge_persistence_qmaster.h"
66
#include "sge_userprj.h"
67
#include "sge_feature.h"
68
#include "sge_cqueue_qmaster.h"
69
#include "sge_qinstance_qmaster.h"
70
#include "sge_host_qmaster.h"
71
#include "sge_qmod_qmaster.h"
72
#include "sched/sge_select_queue.h"
73
#include "sched/valid_queue_user.h"
74
#include "sge_queue_event_master.h"
75
#include "sge_signal.h"
76
#include "sge_mtutil.h"
77
#include "sgeobj/sge_load.h"
78
#include "sgeobj/sge_advance_reservation.h"
80
#include "sge_userprj_qmaster.h"
81
#include "sge_userset_qmaster.h"
83
#include "spool/sge_spooling.h"
85
#include "msg_common.h"
86
#include "msg_qmaster.h"
87
#include "msg_sgeobjlib.h"
91
cqueue_mod_hostlist(lListElem *cqueue, lList **answer_list,
92
lListElem *reduced_elem, int sub_command,
93
lList **add_hosts, lList **rem_hosts);
96
cqueue_mod_attributes(lListElem *cqueue, lList **answer_list,
97
lListElem *reduced_elem, int sub_command);
100
cqueue_mark_qinstances(lListElem *cqueue, lList **answer_list,
104
cqueue_add_qinstances(sge_gdi_ctx_class_t *ctx, lListElem *cqueue, lList **answer_list, lList *add_hosts, monitoring_t *monitor);
107
qinstance_create(sge_gdi_ctx_class_t *ctx,
108
const lListElem *cqueue, lList **answer_list,
109
const char *hostname, bool *is_ambiguous, monitoring_t *monitor);
112
cqueue_update_categories(const lListElem *new_cq, const lListElem *old_cq);
115
qinstance_check_unknown_state(lListElem *this_elem, lList *master_exechost_list);
118
qinstance_create(sge_gdi_ctx_class_t *ctx,
119
const lListElem *cqueue, lList **answer_list,
120
const char *hostname, bool *is_ambiguous, monitoring_t *monitor)
122
dstring buffer = DSTRING_INIT;
123
const char *cqueue_name = lGetString(cqueue, CQ_name);
124
lList *centry_list = *(object_type_get_master_list(SGE_TYPE_CENTRY));
125
lListElem *ret = NULL;
128
DENTER(TOP_LAYER, "qinstance_create");
130
ret = lCreateElem(QU_Type);
133
* Pre-initialize some fields: hostname, full_name
135
lSetHost(ret, QU_qhostname, hostname);
136
lSetString(ret, QU_qname, cqueue_name);
137
sge_dstring_sprintf(&buffer, "%s@%s", cqueue_name, hostname);
138
lSetString(ret, QU_full_name, sge_dstring_get_string(&buffer));
139
sge_dstring_free(&buffer);
142
* Initialize configuration attributes from CQ
144
*is_ambiguous = false;
146
while (cqueue_attribute_array[index].cqueue_attr != NoName) {
147
bool tmp_is_ambiguous = false;
148
bool tmp_has_changed_conf_attr = false;
149
bool tmp_has_changed_state_attr = false;
150
const char *matching_host_or_group = NULL;
151
const char *matching_group = NULL;
153
qinstance_modify_attribute(ctx,
154
ret, answer_list, cqueue,
155
cqueue_attribute_array[index].qinstance_attr,
156
cqueue_attribute_array[index].cqueue_attr,
157
cqueue_attribute_array[index].href_attr,
158
cqueue_attribute_array[index].value_attr,
159
cqueue_attribute_array[index].primary_key_attr,
160
&matching_host_or_group,
163
&tmp_has_changed_conf_attr,
164
&tmp_has_changed_state_attr,
165
true, NULL, monitor);
167
*is_ambiguous |= tmp_is_ambiguous;
172
qinstance_set_conf_slots_used(ret);
173
qinstance_debit_consumable(ret, NULL, centry_list, 0);
176
* Change qinstance state
178
sge_qmaster_qinstance_state_set_ambiguous(ret, *is_ambiguous);
180
DPRINTF(("Qinstance "SFN"@"SFN" has ambiguous configuration\n",
181
cqueue_name, hostname));
183
DPRINTF(("Qinstance "SFN"@"SFN" has non-ambiguous configuration\n",
184
cqueue_name, hostname));
188
* For new qinstances we have to set some internal fields which
189
* will be spooled later on:
190
* - state (modification according to initial state)
193
sge_qmaster_qinstance_state_set_unknown(ret, true);
194
qinstance_check_unknown_state(ret, *object_type_get_master_list(SGE_TYPE_EXECHOST));
195
sge_qmaster_qinstance_set_initial_state(ret, false);
196
qinstance_increase_qversion(ret);
202
cqueue_add_qinstances(sge_gdi_ctx_class_t *ctx, lListElem *cqueue, lList **answer_list, lList *add_hosts, monitoring_t *monitor)
206
DENTER(TOP_LAYER, "cqueue_add_qinstances");
207
if (cqueue != NULL && add_hosts != NULL) {
208
lListElem *href = NULL;
210
for_each(href, add_hosts) {
211
const char *hostname = lGetHost(href, HR_name);
212
lList *list = lGetList(cqueue, CQ_qinstances);
213
lListElem* qinstance = lGetElemHost(list, QU_qhostname, hostname);
215
if (qinstance != NULL) {
216
if (qinstance_state_is_orphaned(qinstance)) {
217
sge_qmaster_qinstance_state_set_orphaned(qinstance, false);
218
lSetUlong(qinstance, QU_tag, SGE_QI_TAG_MOD);
221
* We might already have this QI if it is in orphaned state.
222
* If this is not true, than there is a bug!
224
ERROR((SGE_EVENT, MSG_QINSTANCE_QIALREADYHERE_S, hostname));
225
answer_list_add(answer_list, SGE_EVENT, STATUS_ESYNTAX,
226
ANSWER_QUALITY_ERROR);
229
bool is_ambiguous = false;
232
list = lCreateList("", QU_Type);
233
lSetList(cqueue, CQ_qinstances, list);
235
qinstance = qinstance_create(ctx,
237
hostname, &is_ambiguous, monitor);
239
DPRINTF(("qinstance %s has ambiguous conf\n", hostname));
241
lSetUlong(qinstance, QU_tag, SGE_QI_TAG_ADD);
242
lAppendElem(list, qinstance);
251
cqueue_mark_qinstances(lListElem *cqueue, lList **answer_list, lList *del_hosts)
255
DENTER(TOP_LAYER, "cqueue_mark_qinstances");
256
if (cqueue != NULL) {
257
lList *qinstance_list = lGetList(cqueue, CQ_qinstances);
258
lListElem *qinstance = NULL;
260
for_each(qinstance, qinstance_list) {
261
const char *hostname = lGetHost(qinstance, QU_qhostname);
262
lListElem *href = lGetElemHost(del_hosts, HR_name, hostname);
265
if (qinstance_slots_used(qinstance) > 0 || qinstance_slots_reserved(qinstance) > 0) {
267
* Jobs are currently running in this queue. Therefore
268
* it is not possible to delete the queue but we
269
* will set it into the "orphaned" state
271
sge_qmaster_qinstance_state_set_orphaned(qinstance, true);
272
lSetUlong(qinstance, QU_tag, SGE_QI_TAG_MOD);
274
lSetUlong(qinstance, QU_tag, SGE_QI_TAG_DEL);
277
lSetUlong(qinstance, QU_tag, SGE_QI_TAG_DEFAULT);
285
cqueue_mod_attributes(lListElem *cqueue, lList **answer_list,
286
lListElem *reduced_elem, int sub_command)
290
DENTER(TOP_LAYER, "cqueue_mod_attributes");
291
if (cqueue != NULL && reduced_elem != NULL) {
292
const char *cqueue_name = lGetString(cqueue, CQ_name);
295
while (cqueue_attribute_array[index].cqueue_attr != NoName && ret) {
296
int pos = lGetPosViaElem(reduced_elem,
297
cqueue_attribute_array[index].cqueue_attr, SGE_NO_ABORT);
300
ret &= cqueue_mod_sublist(cqueue, answer_list, reduced_elem,
302
cqueue_attribute_array[index].cqueue_attr,
303
cqueue_attribute_array[index].href_attr,
304
cqueue_attribute_array[index].value_attr,
305
cqueue_attribute_array[index].primary_key_attr,
306
cqueue_attribute_array[index].name,
316
cqueue_mod_hostlist(lListElem *cqueue, lList **answer_list,
317
lListElem *reduced_elem, int sub_command,
318
lList **add_hosts, lList **rem_hosts)
322
DENTER(TOP_LAYER, "cqueue_mod_hostlist");
323
if (cqueue != NULL && reduced_elem != NULL) {
324
int pos = lGetPosViaElem(reduced_elem, CQ_hostlist, SGE_NO_ABORT);
327
const char *cqueue_name = lGetString(cqueue, CQ_name);
328
lList *list = lGetPosList(reduced_elem, pos);
329
lList *old_href_list = lCopyList("", lGetList(cqueue, CQ_hostlist));
330
lList *master_list = *(hgroup_list_get_master_list());
331
lList *href_list = NULL;
332
lList *add_groups = NULL;
333
lList *rem_groups = NULL;
336
ret &= href_list_resolve_hostnames(list, answer_list, true);
339
ret = attr_mod_sub_list(answer_list, cqueue, CQ_hostlist, HR_name,
340
reduced_elem, sub_command,
343
href_list = lGetList(cqueue, CQ_hostlist);
346
ret &= href_list_find_diff(href_list, answer_list, old_href_list,
347
add_hosts, rem_hosts, &add_groups,
350
if (ret && add_groups != NULL) {
351
ret &= hgroup_list_exists(master_list, answer_list, add_groups);
354
ret &= href_list_find_effective_diff(answer_list, add_groups,
355
rem_groups, master_list,
356
add_hosts, rem_hosts);
359
ret &= href_list_resolve_hostnames(*add_hosts, answer_list, false);
364
* - added hosts where not already part the old hostlist
365
* - removed hosts are not part of the new hostlist
368
lList *tmp_hosts = NULL;
370
ret &= href_list_find_all_references(old_href_list, answer_list,
371
master_list, &tmp_hosts, NULL);
372
ret &= href_list_remove_existing(add_hosts, answer_list, tmp_hosts);
373
lFreeList(&tmp_hosts);
375
ret &= href_list_find_all_references(href_list, answer_list,
376
master_list, &tmp_hosts, NULL);
377
ret &= href_list_remove_existing(rem_hosts, answer_list, tmp_hosts);
378
lFreeList(&tmp_hosts);
381
#if 0 /* EB: DEBUG */
383
href_list_debug_print(*add_hosts, "add_hosts: ");
384
href_list_debug_print(*rem_hosts, "rem_hosts: ");
388
lFreeList(&old_href_list);
389
lFreeList(&add_groups);
390
lFreeList(&rem_groups);
398
cqueue_mod_qinstances(sge_gdi_ctx_class_t *ctx,
399
lListElem *cqueue, lList **answer_list,
400
lListElem *reduced_elem, bool refresh_all_values, bool is_startup, monitoring_t *monitor)
402
dstring buffer = DSTRING_INIT;
405
DENTER(TOP_LAYER, "cqueue_mod_qinstances");
407
if (cqueue != NULL && reduced_elem != NULL) {
408
lList *qinstance_list = lGetList(cqueue, CQ_qinstances);
409
lListElem *qinstance = NULL;
412
* Try to find changes for all qinstances ...
414
for_each(qinstance, qinstance_list) {
415
const char *qinstance_name = qinstance_get_name(qinstance, &buffer);
416
bool is_ambiguous = qinstance_state_is_ambiguous(qinstance);
417
bool is_del = (lGetUlong(qinstance, QU_tag) == SGE_QI_TAG_DEL) ? true : false;
418
bool will_be_ambiguous = false;
419
bool state_changed = false;
420
bool conf_changed = false;
422
bool need_reinitialize = false;
425
* Set full name of QI if it is not set
427
if (refresh_all_values &&
428
lGetString(qinstance, QU_full_name) == NULL) {
429
qinstance_set_full_name(qinstance);
433
* Clear all messages which explain ambiguous state
435
qinstance_message_trash_all_of_type_X(qinstance, QI_AMBIGUOUS);
438
* Handle each cqueue attribute as long as there was no error
439
* and only if the qinstance won't be deleted afterward.
442
while (ret && !is_del &&
443
cqueue_attribute_array[index].cqueue_attr != NoName) {
444
const char *matching_host_or_group = NULL;
445
const char *matching_group = NULL;
447
int pos = lGetPosViaElem(reduced_elem,
448
cqueue_attribute_array[index].cqueue_attr, SGE_NO_ABORT);
452
* We try to find changes only for attributes which were
453
* sent by the client. Only for those attributes 'pos' will
456
* There are two situations which make it absolutely necessary
457
* to have a look on ALL attributes:
459
* 1) refresh_all_values == true
460
* The hostlist of "cqueue" changed. As a result it
461
* might be possible that a value for an attribute is
464
* 2) is_ambiguous == true
465
* The qinstance is currently in the ambiguous state.
466
* It is not enough to test only modified attributes if
467
* they are nonambigous. It is also necesssary to check
468
* if all attributes which are not changed now are
469
* nonambigous to clear the ambigous-state from qinstance.
471
if (pos >= 0 || refresh_all_values || is_ambiguous) {
472
bool tmp_is_ambiguous = false;
473
bool tmp_has_changed_conf_attr = false;
474
bool tmp_has_changed_state_attr = false;
476
ret &= qinstance_modify_attribute(ctx,
479
cqueue_attribute_array[index].qinstance_attr,
480
cqueue_attribute_array[index].cqueue_attr,
481
cqueue_attribute_array[index].href_attr,
482
cqueue_attribute_array[index].value_attr,
483
cqueue_attribute_array[index].primary_key_attr,
484
&matching_host_or_group,
487
&tmp_has_changed_conf_attr,
488
&tmp_has_changed_state_attr,
493
if (tmp_is_ambiguous) {
495
* Add a message which explains the reason for
498
sprintf(SGE_EVENT, MSG_ATTR_HASAMBVAL_SSS,
499
cqueue_attribute_array[index].name,
500
matching_host_or_group, matching_group);
501
qinstance_message_add(qinstance, QI_AMBIGUOUS, SGE_EVENT);
504
will_be_ambiguous |= tmp_is_ambiguous;
505
state_changed |= tmp_has_changed_state_attr;
506
conf_changed |= tmp_has_changed_conf_attr;
512
if (need_reinitialize) {
513
qinstance_reinit_consumable_actual_list(qinstance, answer_list);
517
* Change qinstance state
519
sge_qmaster_qinstance_state_set_ambiguous(qinstance, will_be_ambiguous);
520
if (will_be_ambiguous && !is_ambiguous) {
521
state_changed = true;
522
DPRINTF(("Qinstance "SFQ" has ambiguous configuration\n",
524
} else if (!will_be_ambiguous && is_ambiguous) {
525
state_changed = true;
526
DPRINTF(("Qinstance "SFQ" has non-ambiguous configuration\n",
531
* Tag the qinstance as modified if the internal state changed.
532
* This will result in spooling the qinstance. Also mod-events wiil
533
* be sent. If only the configuration changed than it is only
534
* necessary to send mod-events.
537
DPRINTF(("Internal state of qinstance "SFQ" has been changed\n",
539
lSetUlong(qinstance, QU_tag, SGE_QI_TAG_MOD);
540
qinstance_increase_qversion(qinstance);
541
} else if (conf_changed) {
542
DPRINTF(("Only config value of qinstance "SFQ" has been changed\n",
544
lSetUlong(qinstance, QU_tag, SGE_QI_TAG_MOD_ONLY_CONFIG);
545
qinstance_increase_qversion(qinstance);
548
if (ret && !is_startup) {
550
lList *master_userset_list = *(object_type_get_master_list(SGE_TYPE_USERSET));
552
for_each(ar, *(object_type_get_master_list(SGE_TYPE_AR))) {
553
if (lGetElemStr(lGetList(ar, AR_granted_slots), JG_qname, qinstance_name)) {
554
if (!sge_ar_have_users_access(NULL, ar, lGetString(qinstance, QU_full_name),
555
lGetList(qinstance, QU_acl),
556
lGetList(qinstance, QU_xacl),
557
master_userset_list)) {
558
ERROR((SGE_EVENT, MSG_PARSE_MOD3_REJECTED_DUE_TO_AR_SU,
559
SGE_ATTR_USER_LISTS, sge_u32c(lGetUlong(ar, AR_id))));
560
answer_list_add(answer_list, SGE_EVENT,
561
STATUS_ESYNTAX, ANSWER_QUALITY_ERROR);
571
* Skip remaining qinstances if an error occured.
577
sge_dstring_free(&buffer);
583
cqueue_handle_qinstances(sge_gdi_ctx_class_t *ctx,
584
lListElem *cqueue, lList **answer_list,
585
lListElem *reduced_elem, lList *add_hosts,
586
lList *rem_hosts, bool refresh_all_values,
587
monitoring_t *monitor)
591
DENTER(TOP_LAYER, "cqueue_handle_qinstances");
594
ret = cqueue_mark_qinstances(cqueue, answer_list, rem_hosts);
597
ret = cqueue_mod_qinstances(ctx, cqueue, answer_list, reduced_elem,
598
refresh_all_values, false, monitor);
601
ret = cqueue_add_qinstances(ctx, cqueue, answer_list, add_hosts, monitor);
606
int cqueue_mod(sge_gdi_ctx_class_t *ctx,
607
lList **answer_list, lListElem *cqueue, lListElem *reduced_elem,
608
int add, const char *remote_user, const char *remote_host,
609
gdi_object_t *object, int sub_command, monitoring_t *monitor)
612
lList *add_hosts = NULL;
613
lList *rem_hosts = NULL;
616
DENTER(TOP_LAYER, "cqueue_mod");
619
int pos = lGetPosViaElem(reduced_elem, CQ_name, SGE_NO_ABORT);
622
const char *name = lGetPosString(reduced_elem, pos);
626
answer_list, name, MAX_VERIFY_STRING, "cqueue", KEY_TABLE) == STATUS_OK) {
628
lSetString(cqueue, CQ_name, name);
630
ERROR((SGE_EVENT, MSG_CQUEUE_NAMENOTGUILTY_S, name));
631
answer_list_add(answer_list, SGE_EVENT, STATUS_ESYNTAX,
632
ANSWER_QUALITY_ERROR);
636
const char *old_name = lGetString(cqueue, CQ_name);
638
if (strcmp(old_name, name)) {
639
ERROR((SGE_EVENT, MSG_CQUEUE_NONAMECHANGE));
640
answer_list_add(answer_list, SGE_EVENT, STATUS_ESYNTAX,
641
ANSWER_QUALITY_ERROR);
646
ERROR((SGE_EVENT, MSG_SGETEXT_MISSINGCULLFIELD_SS,
647
lNm2Str(CQ_name), SGE_FUNC));
648
answer_list_add(answer_list, SGE_EVENT, STATUS_EUNKNOWN,
649
ANSWER_QUALITY_ERROR);
655
* Find differences of hostlist configuration
658
ret &= cqueue_mod_hostlist(cqueue, answer_list, reduced_elem,
659
sub_command, &add_hosts, &rem_hosts);
663
* Its time to do the cqueue modifications:
664
* - change the attribute lists in the cqueue object
665
* - verify the attribute lists
668
ret &= cqueue_mod_attributes(cqueue, answer_list,
669
reduced_elem, sub_command);
672
ret &= cqueue_verify_attributes(cqueue, answer_list,
677
* Now we have to add/mod/del all qinstances
680
bool refresh_all_values = ((add_hosts != NULL) || (rem_hosts != NULL)) ? true : false;
682
ret &= cqueue_handle_qinstances(ctx,
683
cqueue, answer_list, reduced_elem,
684
add_hosts, rem_hosts, refresh_all_values, monitor);
688
* Client and scheduler code expects existing EH_Type elements
689
* for all hosts used in CQ_hostlist. Therefore it is neccessary
690
* to create all not existing EH_Type elements.
693
lList *list = *(object_type_get_master_list(SGE_TYPE_EXECHOST));
695
ret &= host_list_add_missing_href(ctx, list, answer_list, add_hosts, monitor);
701
lFreeList(&add_hosts);
702
lFreeList(&rem_hosts);
707
DRETURN(STATUS_EUNKNOWN);
711
int cqueue_success(sge_gdi_ctx_class_t *ctx,
712
lListElem *cqueue, lListElem *old_cqueue,
713
gdi_object_t *object, lList **ppList, monitoring_t *monitor)
716
lListElem *qinstance;
717
DENTER(TOP_LAYER, "cqueue_success");
719
cqueue_update_categories(cqueue, old_cqueue);
722
* CQ modify or add event
724
sge_add_event(0, old_cqueue?sgeE_CQUEUE_MOD:sgeE_CQUEUE_ADD, 0, 0,
725
lGetString(cqueue, CQ_name), NULL, NULL, cqueue);
728
* QI modify, add or delete event. Finalize operation.
730
cqueue_commit(ctx, cqueue);
733
* Handle jobs which were supended due to suspend threshold
735
qinstances = lGetList(cqueue, CQ_qinstances);
737
for_each(qinstance, qinstances) {
738
if (lGetUlong(qinstance, QU_gdi_do_later) == GDI_DO_LATER) {
739
bool is_qinstance_mod = false;
740
const char *full_name = lGetString(qinstance, QU_full_name);
741
lList *master_job_list = *(object_type_get_master_list(SGE_TYPE_JOB));
744
lSetUlong(qinstance, QU_gdi_do_later, 0);
746
/* in case the thresholds are set to none, we have to unsuspend all jobs because
747
the scheduler is not able to do that. If the suspend threshold is still set;
748
just changed, the scheduler can easily deal with it.*/
749
if (lGetList(qinstance, QU_suspend_thresholds) == NULL) {
750
for_each(job, master_job_list) {
751
lList *ja_tasks = lGetList(job, JB_ja_tasks);
754
for_each(ja_task, ja_tasks) {
755
u_long32 state = lGetUlong(ja_task, JAT_state);
757
if (ISSET(state, JSUSPENDED_ON_THRESHOLD)) {
758
/* this does most likely not work with pe jobs, which run in different queues.
760
const char *queue_name = lGetString(lFirst(lGetList(ja_task,
761
JAT_granted_destin_identifier_list)), JG_qname);
763
if (!strcmp(queue_name, full_name)) {
765
if (!ISSET(state, JSUSPENDED)) {
766
sge_signal_queue(ctx, SGE_SIGCONT, qinstance, job, ja_task, monitor);
767
SETBIT(JRUNNING, state);
768
is_qinstance_mod = true;
771
CLEARBIT(JSUSPENDED_ON_THRESHOLD, state);
773
lSetUlong(ja_task, JAT_state, state);
775
sge_event_spool(ctx, NULL, 0, sgeE_JATASK_MOD,
776
lGetUlong(job,JB_job_number),
777
lGetUlong(ja_task, JAT_task_number), NULL, NULL, NULL,
778
job, ja_task, NULL, true, true);
786
if (is_qinstance_mod) {
787
const char *hostname = lGetHost(qinstance, QU_qhostname);
788
const char *cqueue_name = lGetString(qinstance, QU_qname);
789
sge_event_spool(ctx, NULL, 0, sgeE_QINSTANCE_MOD,
790
0, 0, cqueue_name, hostname, NULL,
791
qinstance, NULL, NULL, true, true);
799
void cqueue_commit(sge_gdi_ctx_class_t *ctx, lListElem *cqueue)
801
lList *qinstances = lGetList(cqueue, CQ_qinstances);
802
lListElem *next_qinstance = NULL;
803
lListElem *qinstance = NULL;
805
DENTER(TOP_LAYER, "cqueue_commit");
808
* QI modify, add or delete event
810
next_qinstance = lFirst(qinstances);
811
while ((qinstance = next_qinstance)) {
812
u_long32 tag = lGetUlong(qinstance, QU_tag);
813
const char *name = lGetString(qinstance, QU_qname);
814
const char *hostname = lGetHost(qinstance, QU_qhostname);
816
next_qinstance = lNext(qinstance);
821
lSetUlong(qinstance, QU_tag, SGE_QI_TAG_DEFAULT);
823
if (tag == SGE_QI_TAG_ADD) {
824
sge_add_event( 0, sgeE_QINSTANCE_ADD, 0, 0,
825
name, hostname, NULL, qinstance);
826
} else if (tag == SGE_QI_TAG_MOD ||
827
tag == SGE_QI_TAG_MOD_ONLY_CONFIG) {
828
sge_add_event( 0, sgeE_QINSTANCE_MOD, 0, 0,
829
name, hostname, NULL, qinstance);
830
} else if (tag == SGE_QI_TAG_DEL) {
831
sge_event_spool(ctx, NULL, 0, sgeE_QINSTANCE_DEL,
832
0, 0, name, hostname,
833
NULL, NULL, NULL, NULL, true, true);
836
* Now we can remove the qinstance.
838
lRemoveElem(qinstances, &qinstance);
841
if (lGetNumberOfElem(qinstances) == 0) {
842
lSetList(cqueue, CQ_qinstances, NULL);
847
int cqueue_spool(sge_gdi_ctx_class_t *ctx, lList **answer_list, lListElem *cqueue, gdi_object_t *object)
850
const char *name = lGetString(cqueue, CQ_name);
851
lListElem *qinstance;
852
dstring key_dstring = DSTRING_INIT;
854
lList *spool_answer_list = NULL;
855
bool job_spooling = ctx->get_job_spooling(ctx);
857
DENTER(TOP_LAYER, "cqueue_spool");
858
dbret = spool_write_object(&spool_answer_list, spool_get_default_context(),
859
cqueue, name, SGE_TYPE_CQUEUE,
861
answer_list_output(&spool_answer_list);
864
answer_list_add_sprintf(answer_list, STATUS_EUNKNOWN,
865
ANSWER_QUALITY_ERROR,
866
MSG_PERSISTENCE_WRITE_FAILED_S,
871
for_each(qinstance, lGetList(cqueue, CQ_qinstances)) {
872
u_long32 tag = lGetUlong(qinstance, QU_tag);
874
if (tag == SGE_QI_TAG_ADD || tag == SGE_QI_TAG_MOD) {
876
sge_dstring_sprintf(&key_dstring, "%s/%s", name,
877
lGetHost(qinstance, QU_qhostname));
878
dbret = spool_write_object(&spool_answer_list,
879
spool_get_default_context(), qinstance,
880
key, SGE_TYPE_QINSTANCE,
882
answer_list_output(&spool_answer_list);
885
answer_list_add_sprintf(answer_list, STATUS_EUNKNOWN,
886
ANSWER_QUALITY_ERROR,
887
MSG_PERSISTENCE_WRITE_FAILED_S,
894
sge_dstring_free(&key_dstring);
900
int cqueue_del(sge_gdi_ctx_class_t *ctx, lListElem *this_elem, lList **answer_list,
901
char *remote_user, char *remote_host)
905
DENTER(TOP_LAYER, "cqueue_del");
907
if (this_elem != NULL && remote_user != NULL && remote_host != NULL) {
908
const char* name = lGetString(this_elem, CQ_name);
911
lList *master_list = *(object_type_get_master_list(SGE_TYPE_CQUEUE));
912
lListElem *cqueue = cqueue_list_locate(master_list, name);
914
if (cqueue != NULL) {
915
lList *qinstances = lGetList(cqueue, CQ_qinstances);
916
lListElem *qinstance = NULL;
917
const char *cq_name = lGetString(cqueue, CQ_name);
918
dstring dir = DSTRING_INIT;
923
* test if the CQ can be removed
925
for_each(qinstance, qinstances) {
926
if (qinstance_slots_used(qinstance) > 0 || qinstance_slots_reserved(qinstance) > 0) {
927
ERROR((SGE_EVENT, MSG_QINSTANCE_STILLJOBS));
928
answer_list_add(answer_list, SGE_EVENT, STATUS_EEXIST,
929
ANSWER_QUALITY_ERROR);
936
* check for references of this cqueue in other cqueues subordinate
940
lListElem *tmp_cqueue;
942
for_each(tmp_cqueue, master_list) {
944
if (cqueue_is_used_in_subordinate(name, tmp_cqueue)) {
945
ERROR((SGE_EVENT, MSG_CQUEUE_DEL_ISREFASSUBORDINATE_SS,
946
name, lGetString(tmp_cqueue, CQ_name)));
947
answer_list_add(answer_list, SGE_EVENT, STATUS_EUNKNOWN,
948
ANSWER_QUALITY_ERROR);
959
dstring key = DSTRING_INIT;
960
sge_dstring_sprintf(&dir, "%s/%s", QINSTANCES_DIR, cq_name);
962
for_each(qinstance, qinstances) {
963
const char *qi_name = lGetHost(qinstance, QU_qhostname);
965
sge_dstring_sprintf(&key, "%s/%s", cq_name, qi_name);
966
if (sge_event_spool(ctx, answer_list, 0, sgeE_QINSTANCE_DEL,
967
0, 0, cq_name, qi_name,
968
NULL, NULL, NULL, NULL, true, true)) {
972
sge_dstring_free(&key);
973
sge_rmdir(sge_dstring_get_string(&dir), NULL);
974
sge_dstring_free(&dir);
979
if (sge_event_spool(ctx, answer_list, 0, sgeE_CQUEUE_DEL,
980
0, 0, name, NULL, NULL,
981
NULL, NULL, NULL, true, true)) {
982
cqueue_update_categories(NULL, cqueue);
983
lRemoveElem(*(object_type_get_master_list(SGE_TYPE_CQUEUE)), &cqueue);
985
INFO((SGE_EVENT, MSG_SGETEXT_REMOVEDFROMLIST_SSSS,
986
remote_user, remote_host, name , "cluster queue"));
987
answer_list_add(answer_list, SGE_EVENT, STATUS_OK,
988
ANSWER_QUALITY_INFO);
990
ERROR((SGE_EVENT, MSG_CANTSPOOL_SS, "cluster queue",
992
answer_list_add(answer_list, SGE_EVENT, STATUS_EEXIST,
993
ANSWER_QUALITY_ERROR);
1000
ERROR((SGE_EVENT, MSG_SGETEXT_DOESNOTEXIST_SS,
1001
"cluster queue", name));
1002
answer_list_add(answer_list, SGE_EVENT, STATUS_EEXIST,
1003
ANSWER_QUALITY_ERROR);
1007
ERROR((SGE_EVENT, MSG_SGETEXT_MISSINGCULLFIELD_SS,
1008
lNm2Str(CQ_name), SGE_FUNC));
1009
answer_list_add(answer_list, SGE_EVENT, STATUS_EUNKNOWN,
1010
ANSWER_QUALITY_ERROR);
1014
CRITICAL((SGE_EVENT, MSG_SGETEXT_NULLPTRPASSED_S, SGE_FUNC));
1015
answer_list_add(answer_list, SGE_EVENT, STATUS_EUNKNOWN,
1016
ANSWER_QUALITY_ERROR);
1024
return STATUS_EUNKNOWN;
1029
cqueue_del_all_orphaned(sge_gdi_ctx_class_t *ctx, lListElem *this_elem, lList **answer_list, const char *ehname)
1033
DENTER(TOP_LAYER, "cqueue_del_all_orphaned");
1035
if (this_elem != NULL) {
1036
dstring dir = DSTRING_INIT;
1037
const char* cq_name = lGetString(this_elem, CQ_name);
1038
lList *qinstance_list = lGetList(this_elem, CQ_qinstances);
1039
lListElem *qinstance = NULL;
1042
if ((qinstance = lGetElemHost(qinstance_list, QU_qhostname, ehname)) &&
1043
qinstance_state_is_orphaned(qinstance) &&
1044
qinstance_slots_used(qinstance) == 0 &&
1045
qinstance_slots_reserved(qinstance) == 0) {
1046
const char *qi_name = lGetHost(qinstance, QU_qhostname);
1049
* This qinstance should be deleted. There are not jobs anymore.
1051
sge_dstring_sprintf(&dir, "%s/%s", QINSTANCES_DIR, cq_name);
1052
if (sge_event_spool(ctx, answer_list, 0, sgeE_QINSTANCE_DEL,
1053
0, 0, cq_name, qi_name,
1054
NULL, NULL, NULL, NULL, true, true)) {
1055
lRemoveElem(qinstance_list, &qinstance);
1056
if (lGetNumberOfElem(qinstance_list) == 0) {
1057
sge_rmdir(sge_dstring_get_string(&dir), NULL);
1062
lListElem *next_qinstance = NULL;
1064
next_qinstance = lFirst(qinstance_list);
1065
while ((qinstance = next_qinstance) != NULL) {
1066
next_qinstance = lNext(qinstance);
1068
if (qinstance_state_is_orphaned(qinstance) &&
1069
qinstance_slots_used(qinstance) == 0 &&
1070
qinstance_slots_reserved(qinstance) == 0) {
1071
const char *qi_name = lGetHost(qinstance, QU_qhostname);
1074
* This qinstance should be deleted. There are not jobs anymore.
1076
sge_dstring_sprintf(&dir, "%s/%s", QINSTANCES_DIR, cq_name);
1077
if (sge_event_spool(ctx, answer_list, 0, sgeE_QINSTANCE_DEL,
1078
0, 0, cq_name, qi_name,
1079
NULL, NULL, NULL, NULL, true, true)) {
1080
lRemoveElem(qinstance_list, &qinstance);
1081
if (lGetNumberOfElem(qinstance_list) == 0) {
1082
sge_rmdir(sge_dstring_get_string(&dir), NULL);
1088
sge_dstring_free(&dir);
1096
cqueue_list_del_all_orphaned(sge_gdi_ctx_class_t *ctx, lList *this_list, lList **answer_list, const char *cqname, const char *ehname)
1101
DENTER(TOP_LAYER, "cqueue_list_del_all_orphaned");
1104
cqueue = lGetElemStr(this_list, CQ_name, cqname);
1105
ret &= cqueue_del_all_orphaned(ctx, cqueue, answer_list, ehname);
1107
for_each(cqueue, this_list) {
1108
ret &= cqueue_del_all_orphaned(ctx, cqueue, answer_list, ehname);
1120
cqueue_list_set_unknown_state(lList *this_list, const char *hostname,
1121
bool send_events, bool is_unknown)
1123
lListElem *cqueue = NULL;
1125
for_each(cqueue, this_list) {
1126
if (hostname != NULL) {
1127
lList *qinstance_list = lGetList(cqueue, CQ_qinstances);
1128
lListElem *qinstance = lGetElemHost(qinstance_list, QU_qhostname,
1130
if (qinstance != NULL &&
1131
qinstance_state_is_unknown(qinstance) != is_unknown) {
1132
sge_qmaster_qinstance_state_set_unknown(qinstance, is_unknown);
1134
qinstance_add_event(qinstance, sgeE_QINSTANCE_MOD);
1138
lListElem *qinstance = NULL;
1139
for_each (qinstance, lGetList(cqueue, CQ_qinstances)) {
1140
if (qinstance_state_is_unknown(qinstance) != is_unknown) {
1141
sge_qmaster_qinstance_state_set_unknown(qinstance, is_unknown);
1143
qinstance_add_event(qinstance, sgeE_QINSTANCE_MOD);
1152
/****** sge_cqueue_qmaster/cqueue_diff_sublist() *******************************
1154
* cqueue_diff_sublist() -- Diff cluster queue sublists
1157
* static void cqueue_diff_sublist(const lListElem *new, const lListElem
1158
* *old, int snm1, int snm2, int sublist_nm, int key_nm, const lDescr *dp,
1159
* lList **new_sublist, lList **old_sublist)
1162
* Determine new/old refereneces in a cluster queue configuration sublist.
1165
* const lListElem *new - New cluster queue (CQ_Type)
1166
* const lListElem *old - Old cluster queue (CQ_Type)
1167
* int snm1 - First cluster queue sublist field
1168
* int snm2 - Second cluster queue sublist field
1169
* int sublist_nm - Subsub list field
1170
* int key_nm - Field with key in subsublist
1171
* const lDescr *dp - Type for outgoing sublist arguments
1172
* lList **new_sublist - List of new references
1173
* lList **old_sublist - List of old references
1176
* MT-NOTE: cqueue_diff_sublist() is MT safe
1177
*******************************************************************************/
1178
static void cqueue_diff_sublist(const lListElem *new, const lListElem *old,
1179
int snm1, int snm2, int sublist_nm, int key_nm, const lDescr *dp,
1180
lList **new_sublist, lList **old_sublist)
1182
const lListElem *qc, *ep;
1185
DENTER(TOP_LAYER, "cqueue_diff_sublist");
1187
/* collect 'old' entries in 'old_sublist' */
1188
if (old && old_sublist) {
1189
for_each (qc, lGetList(old, snm1)) {
1190
for_each (ep, lGetList(qc, sublist_nm)) {
1191
p = lGetString(ep, key_nm);
1192
if (!lGetElemStr(*old_sublist, key_nm, p))
1193
lAddElemStr(old_sublist, key_nm, p, dp);
1196
for_each (qc, lGetList(old, snm2)) {
1197
for_each (ep, lGetList(qc, sublist_nm)) {
1198
p = lGetString(ep, key_nm);
1199
if (!lGetElemStr(*old_sublist, key_nm, p))
1200
lAddElemStr(old_sublist, key_nm, p, dp);
1205
/* collect 'new' entries in 'new_sublist' */
1206
if (new && new_sublist) {
1207
for_each (qc, lGetList(new, snm1)) {
1208
for_each (ep, lGetList(qc, sublist_nm)) {
1209
p = lGetString(ep, key_nm);
1210
if (!lGetElemStr(*new_sublist, key_nm, p))
1211
lAddElemStr(new_sublist, key_nm, p, dp);
1214
for_each (qc, lGetList(new, snm2)) {
1215
for_each (ep, lGetList(qc, sublist_nm)) {
1216
p = lGetString(ep, key_nm);
1217
if (!lGetElemStr(*new_sublist, key_nm, p))
1218
lAddElemStr(new_sublist, key_nm, p, dp);
1227
/****** sge_cqueue_qmaster/cqueue_diff_projects() ******************************
1229
* cqueue_diff_projects() -- Diff old/new cluster queue projects
1232
* void cqueue_diff_projects(const lListElem *new, const lListElem *old,
1233
* lList **new_prj, lList **old_prj)
1236
* A diff new/old is made regarding cluster queue projects/xprojects.
1237
* Project references are returned in new_prj/old_prj.
1240
* const lListElem *new - New cluster queue (CQ_Type)
1241
* const lListElem *old - Old cluster queue (CQ_Type)
1242
* lList **new_prj - New project references (PR_Type)
1243
* lList **old_prj - Old project references (PR_Type)
1246
* MT-NOTE: cqueue_diff_projects() is MT safe
1247
*******************************************************************************/
1248
void cqueue_diff_projects(const lListElem *new,
1249
const lListElem *old, lList **new_prj, lList **old_prj)
1251
cqueue_diff_sublist(new, old, CQ_projects, CQ_xprojects,
1252
APRJLIST_value, PR_name, PR_Type, new_prj, old_prj);
1253
lDiffListStr(PR_name, new_prj, old_prj);
1256
/****** sge_cqueue_qmaster/cqueue_diff_usersets() ******************************
1258
* cqueue_diff_projects() -- Diff old/new cluster queue usersets
1261
* void cqueue_diff_projects(const lListElem *new, const lListElem *old,
1262
* lList **new_prj, lList **old_prj)
1265
* A diff new/old is made regarding cluster queue acl/xacl.
1266
* Userset references are returned in new_acl/old_acl.
1269
* const lListElem *new - New cluster queue (CQ_Type)
1270
* const lListElem *old - Old cluster queue (CQ_Type)
1271
* lList **new_acl - New userset references (US_Type)
1272
* lList **old_acl - Old userset references (US_Type)
1275
* MT-NOTE: cqueue_diff_usersets() is MT safe
1276
*******************************************************************************/
1277
void cqueue_diff_usersets(const lListElem *new,
1278
const lListElem *old, lList **new_acl, lList **old_acl)
1280
cqueue_diff_sublist(new, old, CQ_acl, CQ_xacl,
1281
AUSRLIST_value, US_name, US_Type, new_acl, old_acl);
1282
lDiffListStr(US_name, new_acl, old_acl);
1286
/****** sge_cqueue_qmaster/cqueue_update_categories() **************************
1288
* cqueue_update_categories() -- Update categories wrts userset/project
1291
* static void cqueue_update_categories(const lListElem *new_cq, const
1292
* lListElem *old_cq)
1295
* The userset/project information wrts categories is updated based
1296
* on new/old cluster queue configuration and events are sent upon
1300
* const lListElem *new_cq - New cluster queue (CQ_Type)
1301
* const lListElem *old_cq - Old cluster queue (CQ_Type)
1304
* MT-NOTE: cqueue_update_categories() is not MT safe
1305
*******************************************************************************/
1306
static void cqueue_update_categories(const lListElem *new_cq, const lListElem *old_cq)
1308
lList *old = NULL, *new = NULL;
1310
cqueue_diff_projects(new_cq, old_cq, &new, &old);
1311
project_update_categories(new, old);
1315
cqueue_diff_usersets(new_cq, old_cq, &new, &old);
1316
userset_update_categories(new, old);
1321
/****** sgeobj/qinstance/qinstance_check_unknown_state() **********************
1323
* qinstance_check_unknown_state() -- Modifies the number of used slots
1327
* qinstance_check_unknown_state(lListElem *this_elem)
1330
* Checks if there are nonstatic load values available for the
1331
* qinstance. If this is the case, then then the "unknown" state
1332
* of that machine will be released.
1335
* lListElem *this_elem - QU_Type
1341
* MT-NOTE: qinstance_check_unknown_state() is MT safe
1342
*******************************************************************************/
1344
qinstance_check_unknown_state(lListElem *this_elem, lList *master_exechost_list)
1346
const char *hostname = NULL;
1347
lListElem *host = NULL;
1349
DENTER(TOP_LAYER, "qinstance_check_unknown_state");
1350
hostname = lGetHost(this_elem, QU_qhostname);
1351
host = host_list_locate(master_exechost_list, hostname);
1353
u_long32 last_heard = lGetUlong(host, EH_lt_heard_from);
1355
if (last_heard != 0) {
1356
sge_qmaster_qinstance_state_set_unknown(this_elem, false);