]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/dird.c
26May06
[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
559          /* Transfer default items from JobDefs Resource */
560          for (i=0; job_items[i].name; i++) {
561             char **def_svalue, **svalue;  /* string value */
562             int *def_ivalue, *ivalue;     /* integer value */
563             bool *def_bvalue, *bvalue;    /* bool value */
564             int64_t *def_lvalue, *lvalue; /* 64 bit values */
565             uint32_t offset;
566
567             Dmsg4(1400, "Job \"%s\", field \"%s\" bit=%d def=%d\n",
568                 job->hdr.name, job_items[i].name,
569                 bit_is_set(i, job->hdr.item_present),
570                 bit_is_set(i, job->jobdefs->hdr.item_present));
571
572             if (!bit_is_set(i, job->hdr.item_present) &&
573                  bit_is_set(i, job->jobdefs->hdr.item_present)) {
574                Dmsg2(400, "Job \"%s\", field \"%s\": getting default.\n",
575                  job->hdr.name, job_items[i].name);
576                offset = (char *)(job_items[i].value) - (char *)&res_all;
577                /*
578                 * Handle strings and directory strings
579                 */
580                if (job_items[i].handler == store_str ||
581                    job_items[i].handler == store_dir) {
582                   def_svalue = (char **)((char *)(job->jobdefs) + offset);
583                   Dmsg5(400, "Job \"%s\", field \"%s\" def_svalue=%s item %d offset=%u\n",
584                        job->hdr.name, job_items[i].name, *def_svalue, i, offset);
585                   svalue = (char **)((char *)job + offset);
586                   if (*svalue) {
587                      Pmsg1(000, _("Hey something is wrong. p=0x%lu\n"), *svalue);
588                   }
589                   *svalue = bstrdup(*def_svalue);
590                   set_bit(i, job->hdr.item_present);
591                /*
592                 * Handle resources
593                 */
594                } else if (job_items[i].handler == store_res) {
595                   def_svalue = (char **)((char *)(job->jobdefs) + offset);
596                   Dmsg4(400, "Job \"%s\", field \"%s\" item %d offset=%u\n",
597                        job->hdr.name, job_items[i].name, 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 = *def_svalue;
603                   set_bit(i, job->hdr.item_present);
604                /*
605                 * Handle alist resources
606                 */
607                } else if (job_items[i].handler == store_alist_res) {
608                   if (bit_is_set(i, job->jobdefs->hdr.item_present)) {
609                      set_bit(i, job->hdr.item_present);
610                   }
611                /*
612                 * Handle integer fields
613                 *    Note, our store_bit does not handle bitmaped fields
614                 */
615                } else if (job_items[i].handler == store_bit     ||
616                           job_items[i].handler == store_pint    ||
617                           job_items[i].handler == store_jobtype ||
618                           job_items[i].handler == store_level   ||
619                           job_items[i].handler == store_pint    ||
620                           job_items[i].handler == store_replace) {
621                   def_ivalue = (int *)((char *)(job->jobdefs) + offset);
622                   Dmsg5(400, "Job \"%s\", field \"%s\" def_ivalue=%d item %d offset=%u\n",
623                        job->hdr.name, job_items[i].name, *def_ivalue, i, offset);
624                   ivalue = (int *)((char *)job + offset);
625                   *ivalue = *def_ivalue;
626                   set_bit(i, job->hdr.item_present);
627                /*
628                 * Handle 64 bit integer fields
629                 */
630                } else if (job_items[i].handler == store_time   ||
631                           job_items[i].handler == store_size   ||
632                           job_items[i].handler == store_int64) {
633                   def_lvalue = (int64_t *)((char *)(job->jobdefs) + offset);
634                   Dmsg5(400, "Job \"%s\", field \"%s\" def_lvalue=%" lld " item %d offset=%u\n",
635                        job->hdr.name, job_items[i].name, *def_lvalue, i, offset);
636                   lvalue = (int64_t *)((char *)job + offset);
637                   *lvalue = *def_lvalue;
638                   set_bit(i, job->hdr.item_present);
639                /*
640                 * Handle bool fields
641                 */
642                } else if (job_items[i].handler == store_bool) {
643                   def_bvalue = (bool *)((char *)(job->jobdefs) + offset);
644                   Dmsg5(400, "Job \"%s\", field \"%s\" def_bvalue=%d item %d offset=%u\n",
645                        job->hdr.name, job_items[i].name, *def_bvalue, i, offset);
646                   bvalue = (bool *)((char *)job + offset);
647                   *bvalue = *def_bvalue;
648                   set_bit(i, job->hdr.item_present);
649                }
650             }
651          }
652       }
653       /*
654        * Ensure that all required items are present
655        */
656       for (i=0; job_items[i].name; i++) {
657          if (job_items[i].flags & ITEM_REQUIRED) {
658                if (!bit_is_set(i, job->hdr.item_present)) {
659                   Jmsg(NULL, M_FATAL, 0, _("\"%s\" directive in Job \"%s\" resource is required, but not found.\n"),
660                     job_items[i].name, job->hdr.name);
661                   OK = false;
662                 }
663          }
664          /* If this triggers, take a look at lib/parse_conf.h */
665          if (i >= MAX_RES_ITEMS) {
666             Emsg0(M_ERROR_TERM, 0, _("Too many items in Job resource\n"));
667          }
668       }
669    } /* End loop over Job res */
670
671    /* Loop over databases */
672    CAT *catalog;
673    foreach_res(catalog, R_CATALOG) {
674       B_DB *db;
675       /*
676        * Make sure we can open catalog, otherwise print a warning
677        * message because the server is probably not running.
678        */
679       db = db_init_database(NULL, catalog->db_name, catalog->db_user,
680                          catalog->db_password, catalog->db_address,
681                          catalog->db_port, catalog->db_socket,
682                          catalog->mult_db_connections);
683       if (!db || !db_open_database(NULL, db)) {
684          Jmsg(NULL, M_FATAL, 0, _("Could not open Catalog \"%s\", database \"%s\".\n"),
685               catalog->hdr.name, catalog->db_name);
686          if (db) {
687             Jmsg(NULL, M_FATAL, 0, _("%s"), db_strerror(db));
688          }
689          OK = false;
690          continue;
691       }
692
693       /* Loop over all pools, defining/updating them in each database */
694       POOL *pool;
695       foreach_res(pool, R_POOL) {
696          create_pool(NULL, db, pool, POOL_OP_UPDATE);  /* update request */
697       }
698
699       STORE *store;
700       foreach_res(store, R_STORAGE) {
701          STORAGE_DBR sr;
702          MEDIATYPE_DBR mr;
703          if (store->media_type) {
704             bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
705             mr.ReadOnly = 0;
706             db_create_mediatype_record(NULL, db, &mr);
707          } else {
708             mr.MediaTypeId = 0;
709          }
710          bstrncpy(sr.Name, store->name(), sizeof(sr.Name));
711          sr.AutoChanger = store->autochanger;
712          db_create_storage_record(NULL, db, &sr);
713          store->StorageId = sr.StorageId;   /* set storage Id */
714          if (!sr.created) {                 /* if not created, update it */
715             db_update_storage_record(NULL, db, &sr);
716          }
717
718          /* tls_require implies tls_enable */
719          if (store->tls_require) {
720             if (have_tls) {
721                store->tls_enable = true;
722             } else {
723                Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
724                OK = false;
725             }
726          } 
727
728          if ((!store->tls_ca_certfile && !store->tls_ca_certdir) && store->tls_enable) {
729             Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
730                  " or \"TLS CA Certificate Dir\" are defined for Storage \"%s\" in %s.\n"),
731                  store->hdr.name, configfile);
732             OK = false;
733          }
734
735          /* If everything is well, attempt to initialize our per-resource TLS context */
736          if (OK && (store->tls_enable || store->tls_require)) {
737            /* Initialize TLS context:
738             * Args: CA certfile, CA certdir, Certfile, Keyfile,
739             * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
740             store->tls_ctx = new_tls_context(store->tls_ca_certfile,
741                store->tls_ca_certdir, store->tls_certfile,
742                store->tls_keyfile, NULL, NULL, NULL, true);
743          
744             if (!store->tls_ctx) {
745                Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Storage \"%s\" in %s.\n"),
746                     store->hdr.name, configfile);
747                OK = false;
748             }
749          }
750       }
751
752       /* Loop over all counters, defining them in each database */
753       /* Set default value in all counters */
754       COUNTER *counter;
755       foreach_res(counter, R_COUNTER) {
756          /* Write to catalog? */
757          if (!counter->created && counter->Catalog == catalog) {
758             COUNTER_DBR cr;
759             bstrncpy(cr.Counter, counter->hdr.name, sizeof(cr.Counter));
760             cr.MinValue = counter->MinValue;
761             cr.MaxValue = counter->MaxValue;
762             cr.CurrentValue = counter->MinValue;
763             if (counter->WrapCounter) {
764                bstrncpy(cr.WrapCounter, counter->WrapCounter->hdr.name, sizeof(cr.WrapCounter));
765             } else {
766                cr.WrapCounter[0] = 0;  /* empty string */
767             }
768             if (db_create_counter_record(NULL, db, &cr)) {
769                counter->CurrentValue = cr.CurrentValue;
770                counter->created = true;
771                Dmsg2(100, "Create counter %s val=%d\n", counter->hdr.name, counter->CurrentValue);
772             }
773          }
774          if (!counter->created) {
775             counter->CurrentValue = counter->MinValue;  /* default value */
776          }
777       }
778       db_close_database(NULL, db);
779    }
780
781    /* Loop over Consoles */
782    CONRES *cons;
783    foreach_res(cons, R_CONSOLE) {
784       /* tls_require implies tls_enable */
785       if (cons->tls_require) {
786          if (have_tls) {
787             cons->tls_enable = true;
788          } else {
789             Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
790             OK = false;
791             continue;
792          }
793       }
794
795       if (!cons->tls_certfile && cons->tls_enable) {
796          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Console \"%s\" in %s.\n"),
797             cons->hdr.name, configfile);
798          OK = false;
799       }
800
801       if (!cons->tls_keyfile && cons->tls_enable) {
802          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Console \"%s\" in %s.\n"),
803             cons->hdr.name, configfile);
804          OK = false;
805       }
806
807       if ((!cons->tls_ca_certfile && !cons->tls_ca_certdir) && cons->tls_enable && cons->tls_verify_peer) {
808          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA"
809             " Certificate Dir\" are defined for Console \"%s\" in %s."
810             " At least one CA certificate store is required"
811             " when using \"TLS Verify Peer\".\n"),
812             cons->hdr.name, configfile);
813          OK = false;
814       }
815       /* If everything is well, attempt to initialize our per-resource TLS context */
816       if (OK && (cons->tls_enable || cons->tls_require)) {
817          /* Initialize TLS context:
818           * Args: CA certfile, CA certdir, Certfile, Keyfile,
819           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
820          cons->tls_ctx = new_tls_context(cons->tls_ca_certfile,
821             cons->tls_ca_certdir, cons->tls_certfile,
822             cons->tls_keyfile, NULL, NULL, cons->tls_dhfile, cons->tls_verify_peer);
823          
824          if (!cons->tls_ctx) {
825             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
826                cons->hdr.name, configfile);
827             OK = false;
828          }
829       }
830
831    }
832
833    /* Loop over Clients */
834    CLIENT *client;
835    foreach_res(client, R_CLIENT) {
836       /* tls_require implies tls_enable */
837       if (client->tls_require) {
838          if (have_tls) {
839             client->tls_enable = true;
840          } else {
841             Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
842             OK = false;
843             continue;
844          }
845       }
846
847       if ((!client->tls_ca_certfile && !client->tls_ca_certdir) && client->tls_enable) {
848          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
849             " or \"TLS CA Certificate Dir\" are defined for File daemon \"%s\" in %s.\n"),
850             client->hdr.name, configfile);
851          OK = false;
852       }
853
854       /* If everything is well, attempt to initialize our per-resource TLS context */
855       if (OK && (client->tls_enable || client->tls_require)) {
856          /* Initialize TLS context:
857           * Args: CA certfile, CA certdir, Certfile, Keyfile,
858           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
859          client->tls_ctx = new_tls_context(client->tls_ca_certfile,
860             client->tls_ca_certdir, client->tls_certfile,
861             client->tls_keyfile, NULL, NULL, NULL,
862             true);
863          
864          if (!client->tls_ctx) {
865             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
866                client->hdr.name, configfile);
867             OK = false;
868          }
869       }
870    }
871
872    UnlockRes();
873    if (OK) {
874       close_msg(NULL);                /* close temp message handler */
875       init_msg(NULL, director->messages); /* open daemon message handler */
876    }
877    return OK;
878 }