]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/dird.c
1.20 update -- kes18May02
[bacula/bacula] / bacula / src / dird / dird.c
1 /*
2  *
3  *   Bacula Director daemon -- this is the main program
4  *
5  *     Kern Sibbald, March MM
6  */
7 /*
8    Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2 of
13    the License, or (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public
21    License along with this program; if not, write to the Free
22    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23    MA 02111-1307, USA.
24
25  */
26
27 #include "bacula.h"
28 #include "dird.h"
29
30 /* Forward referenced subroutines */
31 static void terminate_dird(int sig);
32 static int check_resources();
33 static void reload_config(int sig);
34
35 /* Exported subroutines */
36
37
38 /* Imported subroutines */
39 extern JCR *wait_for_next_job(char *runjob);
40 extern void term_scheduler();
41 extern void term_ua_server();
42 extern int do_backup(JCR *jcr);
43 extern void backup_cleanup(void);
44 extern void start_UA_server(int port);
45 extern void run_job(JCR *jcr);
46 extern void init_job_server(int max_workers);
47
48 static char *configfile = NULL;
49 static char *runjob = NULL;
50
51 static int background = 1;
52
53 /* Globals Exported */
54 DIRRES *director;                     /* Director resource */
55 int FDConnectTimeout;
56 int SDConnectTimeout;
57
58 #define CONFIG_FILE "./bacula-dir.conf" /* default configuration file */
59
60 static void usage()
61 {
62    fprintf(stderr, _(
63 "\nVersion: " VERSION " (" DATE ")\n\n"
64 "Usage: dird [-f -s] [-c config_file] [-d debug_level] [config_file]\n"
65 "       -c <file>   set configuration file to file\n"
66 "       -dnn        set debug level to nn\n"
67 "       -f          run in foreground (for debugging)\n"
68 "       -r <job>    run <job> now\n"
69 "       -s          no signals\n"
70 "       -t          test - read configuration and exit\n"
71 "       -?          print this message.\n"  
72 "\n"));
73
74    exit(1);
75 }
76
77
78 /*********************************************************************
79  *
80  *         Main Bacula Server program
81  *
82  */
83 int main (int argc, char *argv[])
84 {
85    int ch;
86    JCR *jcr;
87    int no_signals = FALSE;
88    int test_config = FALSE;
89
90    init_stack_dump();
91    my_name_is(argc, argv, "bacula-dir");
92    init_msg(NULL, NULL);              /* initialize message handler */
93    daemon_start_time = time(NULL);
94    memset(&last_job, 0, sizeof(last_job));
95
96    while ((ch = getopt(argc, argv, "c:d:fr:st?")) != -1) {
97       switch (ch) {
98          case 'c':                    /* specify config file */
99             if (configfile != NULL) {
100                free(configfile);
101             }
102             configfile = bstrdup(optarg);
103             break;
104
105          case 'd':                    /* set debug level */
106             debug_level = atoi(optarg);
107             if (debug_level <= 0) {
108                debug_level = 1; 
109             }
110             Dmsg1(0, "Debug level = %d\n", debug_level);
111             break;
112
113          case 'f':                    /* run in foreground */
114             background = FALSE;
115             break;
116
117          case 'r':                    /* run job */
118             if (runjob != NULL) {
119                free(runjob);
120             }
121             if (optarg) {
122                runjob = bstrdup(optarg);
123             }
124             break;
125
126          case 's':                    /* turn off signals */
127             no_signals = TRUE;
128             break;
129
130          case 't':                    /* test config */
131             test_config = TRUE;
132             break;
133
134          case '?':
135          default:
136             usage();
137
138       }  
139    }
140    argc -= optind;
141    argv += optind;
142
143    if (!no_signals) {
144       init_signals(terminate_dird);
145    }
146    signal(SIGCHLD, SIG_IGN);
147
148    if (argc) {
149       if (configfile != NULL) {
150          free(configfile);
151       }
152       configfile = bstrdup(*argv);
153       argc--; 
154       argv++;
155    }
156    if (argc) {
157       usage();
158    }
159
160    if (configfile == NULL) {
161       configfile = bstrdup(CONFIG_FILE);
162    }
163
164    parse_config(configfile);
165
166    if (!check_resources()) {
167       Emsg1(M_ABORT, 0, "Please correct configuration file: %s\n", configfile);
168    }
169
170    if (test_config) {
171       terminate_dird(0);
172    }
173
174    my_name_is(0, NULL, director->hdr.name);    /* set user defined name */
175
176    FDConnectTimeout = director->FDConnectTimeout;
177    SDConnectTimeout = director->SDConnectTimeout;
178
179    if (background) {
180       daemon_start();
181       init_stack_dump();              /* grab new pid */
182    }
183
184    /* Create pid must come after we are a daemon -- so we have our final pid */
185    create_pid_file(director->pid_directory, "bacula-dir", director->DIRport);
186
187    signal(SIGHUP, reload_config);
188
189    init_console_msg(working_directory);
190
191    Dmsg0(200, "Start UA server\n");
192    start_UA_server(director->DIRport);
193
194    start_watchdog();                  /* start network watchdog thread */
195
196    init_job_server(director->MaxConcurrentJobs);
197   
198    Dmsg0(200, "wait for next job\n");
199    /* Main loop -- call scheduler to get next job to run */
200    while ((jcr = wait_for_next_job(runjob))) {
201       run_job(jcr);                   /* run job */
202       if (runjob)                     /* command line, run a single job? */
203          break;                       /* yes, terminate */
204    }
205
206    terminate_dird(0);
207 }
208
209 /* Cleanup and then exit */
210 static void terminate_dird(int sig)
211 {
212    static int already_here = FALSE;
213
214    if (already_here) {                /* avoid recursive temination problems */
215       exit(1);
216    }
217    already_here = TRUE;
218    delete_pid_file(director->pid_directory, "bacula-dir",  
219                    director->DIRport);
220    stop_watchdog();
221    signal(SIGCHLD, SIG_IGN);          /* don't worry about children now */
222    term_scheduler();
223    if (runjob) {
224       free(runjob);
225    }
226    if (configfile != NULL) {
227       free(configfile);
228    }
229    if (debug_level > 5) {
230       print_memory_pool_stats(); 
231    }
232    free_config_resources();
233    term_ua_server();
234    term_msg();                        /* terminate message handler */
235    close_memory_pool();               /* release free memory in pool */
236    sm_dump(False);
237    exit(sig != 0);
238 }
239
240 /*
241  * If we get here, we have received a SIGHUP, which means to
242  * reread our configuration file. 
243  *
244  *  ***FIXME***  Check that there are no jobs running before
245  *               doing this. 
246  */
247 static void reload_config(int sig)
248 {
249    static int already_here = FALSE;
250    sigset_t set;        
251
252    if (already_here) {
253       abort();                        /* Oops, recursion -> die */
254    }
255    already_here = TRUE;
256    sigfillset(&set);
257    sigprocmask(SIG_BLOCK, &set, NULL);
258
259    free_config_resources();
260
261    parse_config(configfile);
262
263    Dmsg0(200, "check_resources()\n");
264    if (!check_resources()) {
265       Emsg1(M_ABORT, 0, _("Please correct configuration file: %s\n"), configfile);
266    }
267
268    /* Reset globals */
269    working_directory = director->working_directory;
270    FDConnectTimeout = director->FDConnectTimeout;
271    SDConnectTimeout = director->SDConnectTimeout;
272  
273    sigprocmask(SIG_UNBLOCK, &set, NULL);
274    signal(SIGHUP, reload_config);
275    already_here = FALSE;
276    Dmsg0(0, "Director's configuration file reread.\n");
277 }
278
279 /*
280  * Make a quick check to see that we have all the
281  * resources needed.
282  *
283  *  **** FIXME **** this routine could be a lot more
284  *   intelligent and comprehensive.
285  */
286 static int check_resources()
287 {
288    int OK = TRUE;
289    JOB *job;
290
291    LockRes();
292
293    job  = (JOB *)GetNextRes(R_JOB, NULL);
294    director = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
295    if (!director) {
296       Emsg1(M_FATAL, 0, _("No Director resource defined in %s\n\
297 Without that I don't know who I am :-(\n"), configfile);
298       OK = FALSE;
299    } else {
300       if (!director->working_directory) {
301          Emsg0(M_FATAL, 0, _("No working directory specified. Cannot continue.\n"));
302          OK = FALSE;
303       }       
304       working_directory = director->working_directory;
305       if (!director->messages) {       /* If message resource not specified */
306          director->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
307          if (!director->messages) {
308             Emsg1(M_FATAL, 0, _("No Messages resource defined in %s\n"), configfile);
309             OK = FALSE;
310          }
311       }
312       if (GetNextRes(R_DIRECTOR, (RES *)director) != NULL) {
313          Emsg1(M_FATAL, 0, _("Only one Director resource permitted in %s\n"),
314             configfile);
315          OK = FALSE;
316       } 
317    }
318
319    if (!job) {
320       Emsg1(M_FATAL, 0, _("No Job records defined in %s\n"), configfile);
321       OK = FALSE;
322    }
323    for (job=NULL; (job = (JOB *)GetNextRes(R_JOB, (RES *)job)); ) {
324       if (!job->client) {
325          Emsg1(M_FATAL, 0, _("No Client record defined for job %s\n"), job->hdr.name);
326          OK = FALSE;
327       }
328       if (!job->fs) {
329          Emsg1(M_FATAL, 0, _("No FileSet record defined for job %s\n"), job->hdr.name);
330          OK = FALSE;
331       }
332       if (!job->storage && job->JobType != JT_VERIFY) {
333          Emsg1(M_FATAL, 0, _("No Storage resource defined for job %s\n"), job->hdr.name);
334          OK = FALSE;
335       }
336       if (!job->pool) {
337          Emsg1(M_FATAL, 0, _("No Pool resource defined for job %s\n"), job->hdr.name);
338          OK = FALSE;
339       }
340       if (job->client->catalog) {
341          CAT *catalog = job->client->catalog;
342          B_DB *db;
343
344          /*
345           * Make sure we can open catalog, otherwise print a warning
346           * message because the server is probably not running.
347           */
348          db = db_init_database(catalog->db_name, catalog->db_user,
349                             catalog->db_password);
350          if (!db_open_database(db)) {
351             Emsg1(M_FATAL,  0, "%s", db_strerror(db));
352          }
353          db_close_database(db);
354       } else {
355          Emsg1(M_FATAL, 0, _("No Catalog resource defined for client %s\n"), 
356                job->client->hdr.name);
357          OK = FALSE;
358       }
359    }
360
361    UnlockRes();
362    if (OK) {
363       close_msg(NULL);                /* close temp message handler */
364       init_msg(NULL, director->messages); /* open daemon message handler */
365    }
366    return OK;
367 }