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

« back to all changes in this revision

Viewing changes to source/daemons/common/admin_mail.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
#include <stdlib.h>
 
33
#include <string.h>
 
34
#include <errno.h>
 
35
 
 
36
#include "sge.h"
 
37
#include "sge_conf.h"
 
38
#include "sge_usageL.h"
 
39
#include "sge_time.h"
 
40
#include "execution_states.h"
 
41
#include "sge_mailrec.h"
 
42
#include "admin_mail.h"
 
43
#include "mail.h"
 
44
#include "sgermon.h"
 
45
#include "sge_log.h"
 
46
#include "sge_feature.h"
 
47
#include "sge_report.h"
 
48
 
 
49
#include "uti/sge_unistd.h"
 
50
#include "uti/sge_stdio.h"
 
51
 
 
52
#include "msg_common.h"
 
53
#include "msg_daemons_common.h"
 
54
 
 
55
int admail_states[MAX_SSTATE + 1] = {
 
56
                                      0,
 
57
                                      0,
 
58
/* 2  SSTATE_FAILURE_BEFORE_JOB  */   0,
 
59
/* 3  ESSTATE_NO_SHEPHERD        */   0,
 
60
/* 4  ESSTATE_NO_CONFIG          */   0,
 
61
/* 5  ESSTATE_NO_PID             */   0,
 
62
/* 6  SSTATE_READ_CONFIG         */   0,
 
63
/* 7  SSTATE_BEFORE_PROLOG       */   BIT_ADM_NEW_CONF | BIT_ADM_QCHANGE,
 
64
/* 8  SSTATE_PROLOG_FAILED       */   0,
 
65
/* 9  SSTATE_BEFORE_PESTART      */   0,
 
66
/* 10 SSTATE_PESTART_FAILED      */   0,
 
67
/* 11 SSTATE_BEFORE_JOB          */   0,
 
68
/* 12 SSTATE_BEFORE_PESTOP       */   0,
 
69
/* 13 SSTATE_PESTOP_FAILED       */   0,
 
70
/* 14 SSTATE_BEFORE_EPILOG       */   BIT_ADM_NEW_CONF | BIT_ADM_QCHANGE,
 
71
/* 15 SSTATE_EPILOG_FAILED       */   0,
 
72
/* 16 SSTATE_EPILOG_FAILED       */   0,
 
73
/* 17 ESSTATE_DIED_THRU_SIGNAL   */   0,
 
74
/* 18 ESSTATE_SHEPHERD_EXIT      */   0,
 
75
/* 19 ESSTATE_NO_EXITSTATUS      */   0,
 
76
/* 20 ESSTATE_UNEXP_ERRORFILE    */   0,
 
77
/* 21 ESSTATE_UNKNOWN_JOB        */   0,
 
78
/* 22 ESSTATE_EXECD_LOST_RUNNING */   0,
 
79
/* 23 ESSTATE_PTF_CANT_GET_PIDS  */   0,
 
80
/* 24 SSTATE_MIGRATE             */   BIT_ADM_NEVER,
 
81
/* 25 SSTATE_AGAIN               */   BIT_ADM_NEVER,
 
82
/* 26 SSTATE_OPEN_OUTPUT         */   0,
 
83
/* 27 SSTATE_NO_SHELL            */   0,
 
84
/* 28 SSTATE_NO_CWD              */   0,
 
85
/* 29 SSTATE_AFS_PROBLEM         */   0,
 
86
/* 30 SSTATE_APPERROR            */   0,
 
87
/* 31 SSTATE_PASSWD_FILE_ERROR   */   0,
 
88
/* 32 SSTATE_PASSWD_MISSING      */   0,
 
89
/* 33 SSTATE_PASSWD_WRONG        */   0,
 
90
/* 34 SSTATE_HELPER_SERVICE_ERROR */  0,
 
91
/* 35 SSTATE_HELPER_SERVICE_BEFORE_JOB */ 0,
 
92
/* 36 SSTATE_CHECK_DAEMON_CONFIG */   0 };
 
93
 
 
94
u_long32 admail_times[MAX_SSTATE + 1];
 
95
 
 
96
/*
 
97
** this functions reports job failures to the admin
 
98
** it might not be apt to report on errors that
 
99
** have nothing to do with a particular job
 
100
*/
 
101
void job_related_adminmail(u_long32 progid, lListElem *jr, int is_array, const char *job_owner)
 
102
{
 
103
   static int first = 1;
 
104
   char sge_mail_subj[1024];
 
105
   char sge_mail_body[2048];
 
106
   char sge_mail_start[128];
 
107
   char sge_mail_end[128];
 
108
   char str_general[512] = "";
 
109
   u_long32 jobid, jataskid, failed, general;
 
110
   const char *q;
 
111
   lListElem *ep;
 
112
   lList *lp_mail = NULL;
 
113
   u_long32 now;
 
114
   int ret;
 
115
   char *shepherd_filenames[] = { "trace", "error", "pe_hostfile" };
 
116
   int num_files = 3;
 
117
   struct {
 
118
      int exists;
 
119
      SGE_STRUCT_STAT statbuf;
 
120
      char filepath[SGE_PATH_MAX];
 
121
   } shepherd_files[3];
 
122
   int i;
 
123
   char *sge_mail_body_total = NULL;
 
124
   int sge_mail_body_total_size = 0;
 
125
   FILE *fp;
 
126
   int start = 0;
 
127
   dstring ds;
 
128
   char buffer[128];
 
129
   char* administrator_mail = NULL;
 
130
 
 
131
   DENTER(TOP_LAYER, "job_related_adminmail");
 
132
 
 
133
   sge_dstring_init(&ds, buffer, sizeof(buffer));
 
134
 
 
135
   DPRINTF(("sizeof(admail_times) : %d\n", sizeof(admail_times)));
 
136
   if (first) {
 
137
      memset(admail_times, sizeof(admail_times), 0);
 
138
      first = 0;
 
139
   }
 
140
 
 
141
   administrator_mail = mconf_get_administrator_mail();
 
142
 
 
143
   if (administrator_mail == NULL) {
 
144
      DEXIT;
 
145
      return;
 
146
   }
 
147
 
 
148
   if (!strcasecmp(administrator_mail, "none")) {
 
149
      FREE(administrator_mail);
 
150
      DEXIT;
 
151
      return;
 
152
   }
 
153
 
 
154
   if (!(q=lGetString(jr, JR_queue_name)))
 
155
      q = MSG_MAIL_UNKNOWN_NAME;
 
156
   if ((ep=lGetSubStr(jr, UA_name, "start_time", JR_usage)))
 
157
      strcpy(sge_mail_start, sge_ctime((time_t)lGetDouble(ep, UA_value), &ds));
 
158
   else   
 
159
      strcpy(sge_mail_start, MSG_MAIL_UNKNOWN_NAME);
 
160
   if ((ep=lGetSubStr(jr, UA_name, "end_time", JR_usage)))
 
161
      strcpy(sge_mail_end, sge_ctime((time_t)lGetDouble(ep, UA_value), &ds));
 
162
   else   
 
163
      strcpy(sge_mail_end, MSG_MAIL_UNKNOWN_NAME);
 
164
 
 
165
   jobid = lGetUlong(jr, JR_job_number);
 
166
   jataskid = lGetUlong(jr, JR_ja_task_number);
 
167
 
 
168
   failed = lGetUlong(jr, JR_failed);
 
169
   general = lGetUlong(jr, JR_general_failure);
 
170
   now = sge_get_gmt();
 
171
   
 
172
   if (failed) {
 
173
      const char *err_str;
 
174
      dstring ds;
 
175
      char buffer[256];
 
176
      sge_dstring_init(&ds, buffer, sizeof(buffer));
 
177
 
 
178
      if (failed <= MAX_SSTATE) {
 
179
         /*
 
180
         ** a state might have more than one bit set
 
181
         */
 
182
         if ((admail_states[failed] & BIT_ADM_NEVER)) {
 
183
            DPRINTF(("NEVER SENDING ADMIN MAIL for state %d\n", failed));
 
184
            FREE(administrator_mail);
 
185
            DEXIT;
 
186
            return;
 
187
         }
 
188
         if ((admail_states[failed] & BIT_ADM_NEW_CONF)) {
 
189
            if (admail_times[failed]) {
 
190
               DPRINTF(("NOT SENDING ADMIN MAIL AGAIN for state %d, again on conf\n", failed));
 
191
               FREE(administrator_mail);
 
192
               DEXIT;
 
193
               return;
 
194
            }
 
195
         }
 
196
         if ((admail_states[failed] & BIT_ADM_QCHANGE)) {
 
197
            if (admail_times[failed]) {
 
198
               DPRINTF(("NOT SENDING ADMIN MAIL AGAIN for state %d, again on qchange\n", failed));
 
199
               FREE(administrator_mail);
 
200
               DEXIT;
 
201
               return;
 
202
            }
 
203
         }
 
204
         if ((admail_states[failed] & BIT_ADM_HOUR)) {
 
205
            if ((now - admail_times[failed] < 3600))
 
206
               DPRINTF(("NOT SENDING ADMIN MAIL AGAIN for state %d, again next hour\n", failed));
 
207
               FREE(administrator_mail);
 
208
               DEXIT;
 
209
               return;
 
210
         }
 
211
         admail_times[failed] = now;
 
212
      }
 
213
      if (!(err_str=lGetString(jr, JR_err_str)))
 
214
         err_str = MSG_MAIL_UNKNOWN_REASON;
 
215
 
 
216
      ret = mailrec_parse(&lp_mail, administrator_mail);
 
217
      if (ret) {
 
218
         ERROR((SGE_EVENT, MSG_MAIL_PARSE_S,
 
219
            (administrator_mail ? administrator_mail : MSG_NULL)));
 
220
         FREE(administrator_mail);
 
221
         DEXIT;
 
222
         return;
 
223
      }
 
224
 
 
225
      if (lGetString(jr, JR_pe_task_id_str) == NULL) {
 
226
          /* This is a regular job */
 
227
          if (general == GFSTATE_QUEUE) {
 
228
             sprintf(str_general, MSG_GFSTATE_QUEUE_S, q);
 
229
          }
 
230
          else if (general == GFSTATE_HOST) {
 
231
             const char *s = strchr(q, '@');
 
232
             if (s != NULL) {
 
233
               s++;
 
234
               sprintf(str_general, MSG_GFSTATE_HOST_S, s);
 
235
             } else {
 
236
               sprintf(str_general, MSG_GFSTATE_HOST_S, MSG_MAIL_UNKNOWN_NAME);
 
237
             }
 
238
          }
 
239
          else if (general == GFSTATE_JOB) {
 
240
             if (is_array)
 
241
                sprintf(str_general, MSG_GFSTATE_JOB_UU, sge_u32c(jobid), sge_u32c(jataskid));
 
242
             else
 
243
                sprintf(str_general, MSG_GFSTATE_JOB_U, sge_u32c(jobid));
 
244
          }
 
245
          else {
 
246
             sprintf(str_general, MSG_NONE);
 
247
          }
 
248
      } else {
 
249
          /* This is a pe task */
 
250
          sprintf(str_general, MSG_GFSTATE_PEJOB_U, sge_u32c(jobid));
 
251
      }
 
252
 
 
253
      if (is_array)
 
254
         sprintf(sge_mail_subj, MSG_MAIL_SUBJECT_SUU, 
 
255
                 feature_get_product_name(FS_SHORT_VERSION, &ds), sge_u32c(jobid), sge_u32c(jataskid));
 
256
      else
 
257
         sprintf(sge_mail_subj, MSG_MAIL_SUBJECT_SU, 
 
258
                 feature_get_product_name(FS_SHORT_VERSION, &ds), sge_u32c(jobid));
 
259
      sprintf(sge_mail_body,
 
260
              MSG_MAIL_BODY_USSSSSSS,
 
261
              sge_u32c(jobid),
 
262
              str_general,
 
263
              job_owner, q, sge_mail_start, sge_mail_end,
 
264
              get_sstate_description(failed),
 
265
              err_str);
 
266
      /*
 
267
      ** attach the trace and error file to admin mail if it is present
 
268
      */
 
269
      sge_mail_body_total_size = strlen(sge_mail_body) + 1000;
 
270
 
 
271
      for (i=0; i<num_files; i++) {
 
272
         shepherd_files[i].exists = 0;
 
273
      }
 
274
      for (i=0; i<num_files; i++) {
 
275
         /* JG: TODO (254): use function creating path */
 
276
         sprintf(shepherd_files[i].filepath, "%s/" sge_u32"."sge_u32"/%s", ACTIVE_DIR, 
 
277
                     jobid, jataskid, shepherd_filenames[i]);
 
278
         if (!SGE_STAT(shepherd_files[i].filepath, &shepherd_files[i].statbuf) 
 
279
             && (shepherd_files[i].statbuf.st_size > 0)) {
 
280
            sge_mail_body_total_size += shepherd_files[i].statbuf.st_size;
 
281
            shepherd_files[i].exists = 1;
 
282
         }
 
283
      }
 
284
      /*
 
285
      ** allocate enough space for trace and error file
 
286
      */
 
287
      sge_mail_body_total = (char*) malloc(sizeof(char) * 
 
288
                                           sge_mail_body_total_size); 
 
289
      
 
290
      strcpy(sge_mail_body_total, sge_mail_body);
 
291
 
 
292
      
 
293
      for (i=0; i<num_files; i++) {
 
294
         if (shepherd_files[i].exists) {
 
295
            sprintf(sge_mail_body_total, "%s\nShepherd %s:\n", 
 
296
                      sge_mail_body_total, shepherd_filenames[i]);
 
297
            start = strlen(sge_mail_body_total);
 
298
            if ((fp = fopen(shepherd_files[i].filepath, "r"))) {
 
299
               int n;
 
300
 
 
301
               n=fread(sge_mail_body_total+start, 1, 
 
302
                        sge_mail_body_total_size - start, fp);
 
303
               FCLOSE(fp);
 
304
               sge_mail_body_total[start + n] = '\0';
 
305
            }
 
306
         }
 
307
      }
 
308
 
 
309
      cull_mail(progid, lp_mail, sge_mail_subj, sge_mail_body_total, 
 
310
                MSG_MAIL_TYPE_ADMIN);
 
311
 
 
312
      if (sge_mail_body_total)
 
313
         free((char*)sge_mail_body_total);
 
314
   }
 
315
   lFreeList(&lp_mail);
 
316
   FREE(administrator_mail); 
 
317
   DEXIT;
 
318
   return;
 
319
FCLOSE_ERROR:
 
320
   DPRINTF((MSG_FILE_ERRORCLOSEINGXY_SS, shepherd_files[i].filepath, strerror(errno)));
 
321
   DEXIT;
 
322
   return;
 
323
}
 
324
 
 
325
int adm_mail_reset(
 
326
int state 
 
327
) {
 
328
   int i;
 
329
 
 
330
   DENTER(TOP_LAYER, "adm_mail_reset");
 
331
 
 
332
   /*
 
333
   ** let 0 be a reset all
 
334
   */
 
335
   if (!state) {
 
336
      memset(admail_times, sizeof(admail_times), 0);
 
337
      return 0;
 
338
   }
 
339
 
 
340
   DPRINTF(("resetting admin mail for state %d\n", state));
 
341
   for (i = 0; i < MAX_SSTATE + 1; i++) {
 
342
      if ((admail_states[i] & state)) {
 
343
         admail_times[i] = 0;
 
344
      }
 
345
   }
 
346
   
 
347
   DEXIT;
 
348
   return 0;
 
349
}