]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/dird.c
Done with item 9 = Implement new {Client}Run{Before|After}Job feature.
[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  *   Version $Id$
8  */
9 /*
10    Copyright (C) 2000-2006 Kern Sibbald
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License
14    version 2 as amended with additional clauses defined in the
15    file LICENSE in the main source directory.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
20    the file LICENSE for additional details.
21
22  */
23
24 #include "bacula.h"
25 #include "dird.h"
26
27 /* Forward referenced subroutines */
28 static void terminate_dird(int sig);
29 static int check_resources();
30
31 /* Exported subroutines */
32 extern "C" void reload_config(int sig);
33 extern void invalidate_schedules();
34
35
36 /* Imported subroutines */
37 JCR *wait_for_next_job(char *runjob);
38 void term_scheduler();
39 void term_ua_server();
40 void start_UA_server(dlist *addrs);
41 void init_job_server(int max_workers);
42 void term_job_server();
43 void store_jobtype(LEX *lc, RES_ITEM *item, int index, int pass);
44 void store_level(LEX *lc, RES_ITEM *item, int index, int pass);
45 void store_replace(LEX *lc, RES_ITEM *item, int index, int pass);
46 void init_device_resources();
47
48 static char *runjob = NULL;
49 static int background = 1;
50 static void init_reload(void);
51
52 /* Globals Exported */
53 DIRRES *director;                     /* Director resource */
54 int FDConnectTimeout;
55 int SDConnectTimeout;
56 char *configfile = NULL;
57
58 /* Globals Imported */
59 extern int r_first, r_last;           /* first and last resources */
60 extern RES_TABLE resources[];
61 extern RES **res_head;
62 extern RES_ITEM job_items[];
63 extern URES res_all;
64
65
66 #define CONFIG_FILE "./bacula-dir.conf" /* default configuration file */
67
68 static void usage()
69 {
70    fprintf(stderr, _(
71 "Copyright (C) 2000-2005 Kern Sibbald.\n"
72 "\nVersion: %s (%s)\n\n"
73 "Usage: dird [-f -s] [-c config_file] [-d debug_level] [config_file]\n"
74 "       -c <file>   set configuration file to file\n"
75 "       -dnn        set debug level to nn\n"
76 "       -f          run in foreground (for debugging)\n"
77 "       -g          groupid\n"
78 "       -r <job>    run <job> now\n"
79 "       -s          no signals\n"
80 "       -t          test - read configuration and exit\n"
81 "       -u          userid\n"
82 "       -v          verbose user messages\n"
83 "       -?          print this message.\n"
84 "\n"), VERSION, BDATE);
85
86    exit(1);
87 }
88
89
90 /*********************************************************************
91  *
92  *         Main Bacula Server program
93  *
94  */
95 int main (int argc, char *argv[])
96 {
97    int ch;
98    JCR *jcr;
99    int no_signals = FALSE;
100    int test_config = FALSE;
101    char *uid = NULL;
102    char *gid = NULL;
103
104    setlocale(LC_ALL, "");
105    bindtextdomain("bacula", LOCALEDIR);
106    textdomain("bacula");
107
108    init_stack_dump();
109    my_name_is(argc, argv, "bacula-dir");
110    init_msg(NULL, NULL);              /* initialize message handler */
111    init_reload();
112    daemon_start_time = time(NULL);
113
114    while ((ch = getopt(argc, argv, "c:d:fg:r:stu:v?")) != -1) {
115       switch (ch) {
116       case 'c':                    /* specify config file */
117          if (configfile != NULL) {
118             free(configfile);
119          }
120          configfile = bstrdup(optarg);
121          break;
122
123       case 'd':                    /* set debug level */
124          debug_level = atoi(optarg);
125          if (debug_level <= 0) {
126             debug_level = 1;
127          }
128          Dmsg1(0, "Debug level = %d\n", debug_level);
129          break;
130
131       case 'f':                    /* run in foreground */
132          background = FALSE;
133          break;
134
135       case 'g':                    /* set group id */
136          gid = optarg;
137          break;
138
139       case 'r':                    /* run job */
140          if (runjob != NULL) {
141             free(runjob);
142          }
143          if (optarg) {
144             runjob = bstrdup(optarg);
145          }
146          break;
147
148       case 's':                    /* turn off signals */
149          no_signals = TRUE;
150          break;
151
152       case 't':                    /* test config */
153          test_config = TRUE;
154          break;
155
156       case 'u':                    /* set uid */
157          uid = optarg;
158          break;
159
160       case 'v':                    /* verbose */
161          verbose++;
162          break;
163
164       case '?':
165       default:
166          usage();
167
168       }
169    }
170    argc -= optind;
171    argv += optind;
172
173    if (!no_signals) {
174       init_signals(terminate_dird);
175    }
176
177    if (argc) {
178       if (configfile != NULL) {
179          free(configfile);
180       }
181       configfile = bstrdup(*argv);
182       argc--;
183       argv++;
184    }
185    if (argc) {
186       usage();
187    }
188
189    if (configfile == NULL) {
190       configfile = bstrdup(CONFIG_FILE);
191    }
192
193    parse_config(configfile);
194
195    if (init_crypto() != 0) {
196       Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Cryptography library initialization failed.\n"));
197    }
198
199    if (!check_resources()) {
200       Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile);
201    }
202
203    if (test_config) {
204       terminate_dird(0);
205    }
206
207    my_name_is(0, NULL, director->hdr.name);    /* set user defined name */
208
209    FDConnectTimeout = (int)director->FDConnectTimeout;
210    SDConnectTimeout = (int)director->SDConnectTimeout;
211
212    if (background) {
213       daemon_start();
214       init_stack_dump();              /* grab new pid */
215    }
216
217    /* Create pid must come after we are a daemon -- so we have our final pid */
218    create_pid_file(director->pid_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
219    read_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
220
221    drop(uid, gid);                    /* reduce priveleges if requested */
222
223    signal(SIGHUP, reload_config);
224
225    init_console_msg(working_directory);
226
227    init_python_interpreter(director->hdr.name, director->scripts_directory, 
228        "DirStartUp");
229
230    set_thread_concurrency(director->MaxConcurrentJobs * 2 +
231       4 /* UA */ + 4 /* sched+watchdog+jobsvr+misc */);
232
233    Dmsg0(200, "Start UA server\n");
234    start_UA_server(director->DIRaddrs);
235
236    start_watchdog();                  /* start network watchdog thread */
237
238    init_jcr_subsystem();              /* start JCR watchdogs etc. */
239
240    init_job_server(director->MaxConcurrentJobs);
241
242    Dmsg0(200, "wait for next job\n");
243    /* Main loop -- call scheduler to get next job to run */
244    while ( (jcr = wait_for_next_job(runjob)) ) {
245       run_job(jcr);                   /* run job */
246       free_jcr(jcr);                  /* release jcr */
247       if (runjob) {                   /* command line, run a single job? */
248          break;                       /* yes, terminate */
249       }
250    }
251
252    terminate_dird(0);
253 }
254
255 /* Cleanup and then exit */
256 static void terminate_dird(int sig)
257 {
258    static bool already_here = false;
259
260    if (already_here) {                /* avoid recursive temination problems */
261       exit(1);
262    }
263    already_here = true;
264    generate_daemon_event(NULL, "Exit");
265    write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
266    delete_pid_file(director->pid_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
267 // signal(SIGCHLD, SIG_IGN);          /* don't worry about children now */
268    term_scheduler();
269    term_job_server();
270    if (runjob) {
271       free(runjob);
272    }
273    if (configfile != NULL) {
274       free(configfile);
275    }
276    if (debug_level > 5) {
277       print_memory_pool_stats();
278    }
279    free_config_resources();
280    term_ua_server();
281    term_msg();                        /* terminate message handler */
282    stop_watchdog();
283    cleanup_crypto();
284    close_memory_pool();               /* release free memory in pool */
285    sm_dump(false);
286    exit(sig);
287 }
288
289 struct RELOAD_TABLE {
290    int job_count;
291    RES **res_table;
292 };
293
294 static const int max_reloads = 32;
295 static RELOAD_TABLE reload_table[max_reloads];
296
297 static void init_reload(void)
298 {
299    for (int i=0; i < max_reloads; i++) {
300       reload_table[i].job_count = 0;
301       reload_table[i].res_table = NULL;
302    }
303 }
304
305 static void free_saved_resources(int table)
306 {
307    int num = r_last - r_first + 1;
308    RES **res_tab = reload_table[table].res_table;
309    if (!res_tab) {
310       Dmsg1(100, "res_tab for table %d already released.\n", table);
311       return;
312    }
313    Dmsg1(100, "Freeing resources for table %d\n", table);
314    for (int j=0; j<num; j++) {
315       free_resource(res_tab[j], r_first + j);
316    }
317    free(res_tab);
318    reload_table[table].job_count = 0;
319    reload_table[table].res_table = NULL;
320 }
321
322 /*
323  * Called here at the end of every job that was
324  * hooked decrementing the active job_count. When
325  * it goes to zero, no one is using the associated
326  * resource table, so free it.
327  */
328 static void reload_job_end_cb(JCR *jcr, void *ctx)
329 {
330    int reload_id = (int)((long int)ctx);
331    Dmsg3(100, "reload job_end JobId=%d table=%d cnt=%d\n", jcr->JobId,
332       reload_id, reload_table[reload_id].job_count);
333    lock_jobs();
334    LockRes();
335    if (--reload_table[reload_id].job_count <= 0) {
336       free_saved_resources(reload_id);
337    }
338    UnlockRes();
339    unlock_jobs();
340 }
341
342 static int find_free_reload_table_entry()
343 {
344    int table = -1;
345    for (int i=0; i < max_reloads; i++) {
346       if (reload_table[i].res_table == NULL) {
347          table = i;
348          break;
349       }
350    }
351    return table;
352 }
353
354 /*
355  * If we get here, we have received a SIGHUP, which means to
356  *    reread our configuration file.
357  *
358  * The algorithm used is as follows: we count how many jobs are
359  *   running and mark the running jobs to make a callback on
360  *   exiting. The old config is saved with the reload table
361  *   id in a reload table. The new config file is read. Now, as
362  *   each job exits, it calls back to the reload_job_end_cb(), which
363  *   decrements the count of open jobs for the given reload table.
364  *   When the count goes to zero, we release those resources.
365  *   This allows us to have pointers into the resource table (from
366  *   jobs), and once they exit and all the pointers are released, we
367  *   release the old table. Note, if no new jobs are running since the
368  *   last reload, then the old resources will be immediately release.
369  *   A console is considered a job because it may have pointers to
370  *   resources, but a SYSTEM job is not since it *should* not have any
371  *   permanent pointers to jobs.
372  */
373 extern "C"
374 void reload_config(int sig)
375 {
376    static bool already_here = false;
377    sigset_t set;
378    JCR *jcr;
379    int njobs = 0;                     /* number of running jobs */
380    int table, rtable;
381    bool ok;       
382
383    if (already_here) {
384       abort();                        /* Oops, recursion -> die */
385    }
386    already_here = true;
387    sigemptyset(&set);
388    sigaddset(&set, SIGHUP);
389    sigprocmask(SIG_BLOCK, &set, NULL);
390
391    lock_jobs();
392    LockRes();
393
394    table = find_free_reload_table_entry();
395    if (table < 0) {
396       Jmsg(NULL, M_ERROR, 0, _("Too many open reload requests. Request ignored.\n"));
397       goto bail_out;
398    }
399
400    Dmsg1(100, "Reload_config njobs=%d\n", njobs);
401    reload_table[table].res_table = save_config_resources();
402    Dmsg1(100, "Saved old config in table %d\n", table);
403
404    ok = parse_config(configfile, 0, M_ERROR);  /* no exit on error */
405
406    Dmsg0(100, "Reloaded config file\n");
407    if (!ok || !check_resources()) {
408       rtable = find_free_reload_table_entry();    /* save new, bad table */
409       if (rtable < 0) {
410          Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
411          Jmsg(NULL, M_ERROR_TERM, 0, _("Out of reload table entries. Giving up.\n"));
412       } else {
413          Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
414          Jmsg(NULL, M_ERROR, 0, _("Resetting previous configuration.\n"));
415       }
416       reload_table[rtable].res_table = save_config_resources();
417       /* Now restore old resoure values */
418       int num = r_last - r_first + 1;
419       RES **res_tab = reload_table[table].res_table;
420       for (int i=0; i<num; i++) {
421          res_head[i] = res_tab[i];
422       }
423       table = rtable;                 /* release new, bad, saved table below */
424    } else {
425       invalidate_schedules();
426       /*
427        * Hook all active jobs so that they release this table
428        */
429       foreach_jcr(jcr) {
430          if (jcr->JobType != JT_SYSTEM) {
431             reload_table[table].job_count++;
432             job_end_push(jcr, reload_job_end_cb, (void *)((long int)table));
433             njobs++;
434          }
435       }
436       endeach_jcr(jcr);
437    }
438
439    /* Reset globals */
440    set_working_directory(director->working_directory);
441    FDConnectTimeout = director->FDConnectTimeout;
442    SDConnectTimeout = director->SDConnectTimeout;
443    Dmsg0(0, "Director's configuration file reread.\n");
444
445    /* Now release saved resources, if no jobs using the resources */
446    if (njobs == 0) {
447       free_saved_resources(table);
448    }
449
450 bail_out:
451    UnlockRes();
452    unlock_jobs();
453    sigprocmask(SIG_UNBLOCK, &set, NULL);
454    signal(SIGHUP, reload_config);
455    already_here = false;
456 }
457
458 /*
459  * Make a quick check to see that we have all the
460  * resources needed.
461  *
462  *  **** FIXME **** this routine could be a lot more
463  *   intelligent and comprehensive.
464  */
465 static int check_resources()
466 {
467    bool OK = true;
468    JOB *job;
469
470    LockRes();
471
472    job = (JOB *)GetNextRes(R_JOB, NULL);
473    director = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
474    if (!director) {
475       Jmsg(NULL, M_FATAL, 0, _("No Director resource defined in %s\n"
476 "Without that I don't know who I am :-(\n"), configfile);
477       OK = false;
478    } else {
479       set_working_directory(director->working_directory);
480       if (!director->messages) {       /* If message resource not specified */
481          director->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
482          if (!director->messages) {
483             Jmsg(NULL, M_FATAL, 0, _("No Messages resource defined in %s\n"), configfile);
484             OK = false;
485          }
486       }
487       if (GetNextRes(R_DIRECTOR, (RES *)director) != NULL) {
488          Jmsg(NULL, M_FATAL, 0, _("Only one Director resource permitted in %s\n"),
489             configfile);
490          OK = false;
491       }
492       /* tls_require implies tls_enable */
493       if (director->tls_require) {
494          if (have_tls) {
495             director->tls_enable = true;
496          } else {
497             Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
498             OK = false;
499          }
500       }
501
502       if (!director->tls_certfile && director->tls_enable) {
503          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Director \"%s\" in %s.\n"),
504             director->hdr.name, configfile);
505          OK = false;
506       }
507
508       if (!director->tls_keyfile && director->tls_enable) {
509          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Director \"%s\" in %s.\n"),
510             director->hdr.name, configfile);
511          OK = false;
512       }
513
514       if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && director->tls_enable && director->tls_verify_peer) {
515          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA"
516               " Certificate Dir\" are defined for Director \"%s\" in %s."
517               " At least one CA certificate store is required"
518               " when using \"TLS Verify Peer\".\n"),
519               director->hdr.name, configfile);
520          OK = false;
521       }
522
523       /* If everything is well, attempt to initialize our per-resource TLS context */
524       if (OK && (director->tls_enable || director->tls_require)) {
525          /* Initialize TLS context:
526           * Args: CA certfile, CA certdir, Certfile, Keyfile,
527           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
528          director->tls_ctx = new_tls_context(director->tls_ca_certfile,
529             director->tls_ca_certdir, director->tls_certfile,
530             director->tls_keyfile, NULL, NULL, director->tls_dhfile,
531             director->tls_verify_peer);
532          
533          if (!director->tls_ctx) {
534             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Director \"%s\" in %s.\n"),
535                  director->hdr.name, configfile);
536             OK = false;
537          }
538       }
539    }
540
541    if (!job) {
542       Jmsg(NULL, M_FATAL, 0, _("No Job records defined in %s\n"), configfile);
543       OK = false;
544    }
545    foreach_res(job, R_JOB) {
546       int i;
547
548       if (job->jobdefs) {
549          /* Handle Storage alists specifically */
550          JOB *jobdefs = job->jobdefs;
551          if (jobdefs->storage && !job->storage) {
552             STORE *st;
553             job->storage = New(alist(10, not_owned_by_alist));
554             foreach_alist(st, jobdefs->storage) {
555                job->storage->append(st);
556             }
557          }
558          /* Handle RunScripts alists specifically */
559          if (jobdefs->RunScripts) {
560             RUNSCRIPT *rs, *elt;
561             
562             if (!job->RunScripts) {
563                job->RunScripts = New(alist(10, not_owned_by_alist));
564             }
565            
566             foreach_alist(rs, jobdefs->RunScripts) {
567                elt = copy_runscript(rs);
568                job->RunScripts->append(elt); /* we have to free it */
569             }
570          }
571
572          /* Transfer default items from JobDefs Resource */
573          for (i=0; job_items[i].name; i++) {
574             char **def_svalue, **svalue;  /* string value */
575             int *def_ivalue, *ivalue;     /* integer value */
576             bool *def_bvalue, *bvalue;    /* bool value */
577             int64_t *def_lvalue, *lvalue; /* 64 bit values */
578             uint32_t offset;
579
580             Dmsg4(1400, "Job \"%s\", field \"%s\" bit=%d def=%d\n",
581                 job->hdr.name, job_items[i].name,
582                 bit_is_set(i, job->hdr.item_present),
583                 bit_is_set(i, job->jobdefs->hdr.item_present));
584
585             if (!bit_is_set(i, job->hdr.item_present) &&
586                  bit_is_set(i, job->jobdefs->hdr.item_present)) {
587                Dmsg2(400, "Job \"%s\", field \"%s\": getting default.\n",
588                  job->hdr.name, job_items[i].name);
589                offset = (char *)(job_items[i].value) - (char *)&res_all;
590                /*
591                 * Handle strings and directory strings
592                 */
593                if (job_items[i].handler == store_str ||
594                    job_items[i].handler == store_dir) {
595                   def_svalue = (char **)((char *)(job->jobdefs) + offset);
596                   Dmsg5(400, "Job \"%s\", field \"%s\" def_svalue=%s item %d offset=%u\n",
597                        job->hdr.name, job_items[i].name, *def_svalue, i, offset);
598                   svalue = (char **)((char *)job + offset);
599                   if (*svalue) {
600                      Pmsg1(000, _("Hey something is wrong. p=0x%lu\n"), *svalue);
601                   }
602                   *svalue = bstrdup(*def_svalue);
603                   set_bit(i, job->hdr.item_present);
604                /*
605                 * Handle resources
606                 */
607                } else if (job_items[i].handler == store_res) {
608                   def_svalue = (char **)((char *)(job->jobdefs) + offset);
609                   Dmsg4(400, "Job \"%s\", field \"%s\" item %d offset=%u\n",
610                        job->hdr.name, job_items[i].name, i, offset);
611                   svalue = (char **)((char *)job + offset);
612                   if (*svalue) {
613                      Pmsg1(000, _("Hey something is wrong. p=0x%lu\n"), *svalue);
614                   }
615                   *svalue = *def_svalue;
616                   set_bit(i, job->hdr.item_present);
617                /*
618                 * Handle alist resources
619                 */
620                } else if (job_items[i].handler == store_alist_res) {
621                   if (bit_is_set(i, job->jobdefs->hdr.item_present)) {
622                      set_bit(i, job->hdr.item_present);
623                   }
624                /*
625                 * Handle integer fields
626                 *    Note, our store_bit does not handle bitmaped fields
627                 */
628                } else if (job_items[i].handler == store_bit     ||
629                           job_items[i].handler == store_pint    ||
630                           job_items[i].handler == store_jobtype ||
631                           job_items[i].handler == store_level   ||
632                           job_items[i].handler == store_pint    ||
633                           job_items[i].handler == store_replace) {
634                   def_ivalue = (int *)((char *)(job->jobdefs) + offset);
635                   Dmsg5(400, "Job \"%s\", field \"%s\" def_ivalue=%d item %d offset=%u\n",
636                        job->hdr.name, job_items[i].name, *def_ivalue, i, offset);
637                   ivalue = (int *)((char *)job + offset);
638                   *ivalue = *def_ivalue;
639                   set_bit(i, job->hdr.item_present);
640                /*
641                 * Handle 64 bit integer fields
642                 */
643                } else if (job_items[i].handler == store_time   ||
644                           job_items[i].handler == store_size   ||
645                           job_items[i].handler == store_int64) {
646                   def_lvalue = (int64_t *)((char *)(job->jobdefs) + offset);
647                   Dmsg5(400, "Job \"%s\", field \"%s\" def_lvalue=%" lld " item %d offset=%u\n",
648                        job->hdr.name, job_items[i].name, *def_lvalue, i, offset);
649                   lvalue = (int64_t *)((char *)job + offset);
650                   *lvalue = *def_lvalue;
651                   set_bit(i, job->hdr.item_present);
652                /*
653                 * Handle bool fields
654                 */
655                } else if (job_items[i].handler == store_bool) {
656                   def_bvalue = (bool *)((char *)(job->jobdefs) + offset);
657                   Dmsg5(400, "Job \"%s\", field \"%s\" def_bvalue=%d item %d offset=%u\n",
658                        job->hdr.name, job_items[i].name, *def_bvalue, i, offset);
659                   bvalue = (bool *)((char *)job + offset);
660                   *bvalue = *def_bvalue;
661                   set_bit(i, job->hdr.item_present);
662                }
663             }
664          }
665       }
666       /*
667        * Ensure that all required items are present
668        */
669       for (i=0; job_items[i].name; i++) {
670          if (job_items[i].flags & ITEM_REQUIRED) {
671                if (!bit_is_set(i, job->hdr.item_present)) {
672                   Jmsg(NULL, M_FATAL, 0, _("\"%s\" directive in Job \"%s\" resource is required, but not found.\n"),
673                     job_items[i].name, job->hdr.name);
674                   OK = false;
675                 }
676          }
677          /* If this triggers, take a look at lib/parse_conf.h */
678          if (i >= MAX_RES_ITEMS) {
679             Emsg0(M_ERROR_TERM, 0, _("Too many items in Job resource\n"));
680          }
681       }
682    } /* End loop over Job res */
683
684    /* Loop over databases */
685    CAT *catalog;
686    foreach_res(catalog, R_CATALOG) {
687       B_DB *db;
688       /*
689        * Make sure we can open catalog, otherwise print a warning
690        * message because the server is probably not running.
691        */
692       db = db_init_database(NULL, catalog->db_name, catalog->db_user,
693                          catalog->db_password, catalog->db_address,
694                          catalog->db_port, catalog->db_socket,
695                          catalog->mult_db_connections);
696       if (!db || !db_open_database(NULL, db)) {
697          Jmsg(NULL, M_FATAL, 0, _("Could not open Catalog \"%s\", database \"%s\".\n"),
698               catalog->hdr.name, catalog->db_name);
699          if (db) {
700             Jmsg(NULL, M_FATAL, 0, _("%s"), db_strerror(db));
701          }
702          OK = false;
703          continue;
704       }
705
706       /* Loop over all pools, defining/updating them in each database */
707       POOL *pool;
708       foreach_res(pool, R_POOL) {
709          create_pool(NULL, db, pool, POOL_OP_UPDATE);  /* update request */
710       }
711
712       STORE *store;
713       foreach_res(store, R_STORAGE) {
714          STORAGE_DBR sr;
715          MEDIATYPE_DBR mr;
716          if (store->media_type) {
717             bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
718             mr.ReadOnly = 0;
719             db_create_mediatype_record(NULL, db, &mr);
720          } else {
721             mr.MediaTypeId = 0;
722          }
723          bstrncpy(sr.Name, store->name(), sizeof(sr.Name));
724          sr.AutoChanger = store->autochanger;
725          db_create_storage_record(NULL, db, &sr);
726          store->StorageId = sr.StorageId;   /* set storage Id */
727          if (!sr.created) {                 /* if not created, update it */
728             db_update_storage_record(NULL, db, &sr);
729          }
730
731          /* tls_require implies tls_enable */
732          if (store->tls_require) {
733             if (have_tls) {
734                store->tls_enable = true;
735             } else {
736                Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
737                OK = false;
738             }
739          } 
740
741          if ((!store->tls_ca_certfile && !store->tls_ca_certdir) && store->tls_enable) {
742             Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
743                  " or \"TLS CA Certificate Dir\" are defined for Storage \"%s\" in %s.\n"),
744                  store->hdr.name, configfile);
745             OK = false;
746          }
747
748          /* If everything is well, attempt to initialize our per-resource TLS context */
749          if (OK && (store->tls_enable || store->tls_require)) {
750            /* Initialize TLS context:
751             * Args: CA certfile, CA certdir, Certfile, Keyfile,
752             * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
753             store->tls_ctx = new_tls_context(store->tls_ca_certfile,
754                store->tls_ca_certdir, store->tls_certfile,
755                store->tls_keyfile, NULL, NULL, NULL, true);
756          
757             if (!store->tls_ctx) {
758                Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Storage \"%s\" in %s.\n"),
759                     store->hdr.name, configfile);
760                OK = false;
761             }
762          }
763       }
764
765       /* Loop over all counters, defining them in each database */
766       /* Set default value in all counters */
767       COUNTER *counter;
768       foreach_res(counter, R_COUNTER) {
769          /* Write to catalog? */
770          if (!counter->created && counter->Catalog == catalog) {
771             COUNTER_DBR cr;
772             bstrncpy(cr.Counter, counter->hdr.name, sizeof(cr.Counter));
773             cr.MinValue = counter->MinValue;
774             cr.MaxValue = counter->MaxValue;
775             cr.CurrentValue = counter->MinValue;
776             if (counter->WrapCounter) {
777                bstrncpy(cr.WrapCounter, counter->WrapCounter->hdr.name, sizeof(cr.WrapCounter));
778             } else {
779                cr.WrapCounter[0] = 0;  /* empty string */
780             }
781             if (db_create_counter_record(NULL, db, &cr)) {
782                counter->CurrentValue = cr.CurrentValue;
783                counter->created = true;
784                Dmsg2(100, "Create counter %s val=%d\n", counter->hdr.name, counter->CurrentValue);
785             }
786          }
787          if (!counter->created) {
788             counter->CurrentValue = counter->MinValue;  /* default value */
789          }
790       }
791       db_close_database(NULL, db);
792    }
793
794    /* Loop over Consoles */
795    CONRES *cons;
796    foreach_res(cons, R_CONSOLE) {
797       /* tls_require implies tls_enable */
798       if (cons->tls_require) {
799          if (have_tls) {
800             cons->tls_enable = true;
801          } else {
802             Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
803             OK = false;
804             continue;
805          }
806       }
807
808       if (!cons->tls_certfile && cons->tls_enable) {
809          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Console \"%s\" in %s.\n"),
810             cons->hdr.name, configfile);
811          OK = false;
812       }
813
814       if (!cons->tls_keyfile && cons->tls_enable) {
815          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Console \"%s\" in %s.\n"),
816             cons->hdr.name, configfile);
817          OK = false;
818       }
819
820       if ((!cons->tls_ca_certfile && !cons->tls_ca_certdir) && cons->tls_enable && cons->tls_verify_peer) {
821          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA"
822             " Certificate Dir\" are defined for Console \"%s\" in %s."
823             " At least one CA certificate store is required"
824             " when using \"TLS Verify Peer\".\n"),
825             cons->hdr.name, configfile);
826          OK = false;
827       }
828       /* If everything is well, attempt to initialize our per-resource TLS context */
829       if (OK && (cons->tls_enable || cons->tls_require)) {
830          /* Initialize TLS context:
831           * Args: CA certfile, CA certdir, Certfile, Keyfile,
832           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
833          cons->tls_ctx = new_tls_context(cons->tls_ca_certfile,
834             cons->tls_ca_certdir, cons->tls_certfile,
835             cons->tls_keyfile, NULL, NULL, cons->tls_dhfile, cons->tls_verify_peer);
836          
837          if (!cons->tls_ctx) {
838             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
839                cons->hdr.name, configfile);
840             OK = false;
841          }
842       }
843
844    }
845
846    /* Loop over Clients */
847    CLIENT *client;
848    foreach_res(client, R_CLIENT) {
849       /* tls_require implies tls_enable */
850       if (client->tls_require) {
851          if (have_tls) {
852             client->tls_enable = true;
853          } else {
854             Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
855             OK = false;
856             continue;
857          }
858       }
859
860       if ((!client->tls_ca_certfile && !client->tls_ca_certdir) && client->tls_enable) {
861          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
862             " or \"TLS CA Certificate Dir\" are defined for File daemon \"%s\" in %s.\n"),
863             client->hdr.name, configfile);
864          OK = false;
865       }
866
867       /* If everything is well, attempt to initialize our per-resource TLS context */
868       if (OK && (client->tls_enable || client->tls_require)) {
869          /* Initialize TLS context:
870           * Args: CA certfile, CA certdir, Certfile, Keyfile,
871           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
872          client->tls_ctx = new_tls_context(client->tls_ca_certfile,
873             client->tls_ca_certdir, client->tls_certfile,
874             client->tls_keyfile, NULL, NULL, NULL,
875             true);
876          
877          if (!client->tls_ctx) {
878             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
879                client->hdr.name, configfile);
880             OK = false;
881          }
882       }
883    }
884
885    UnlockRes();
886    if (OK) {
887       close_msg(NULL);                /* close temp message handler */
888       init_msg(NULL, director->messages); /* open daemon message handler */
889    }
890    return OK;
891 }