]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/dird.c
This commit was manufactured by cvs2svn to create tag
[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
33 extern "C" void reload_config(int sig);
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 = 10;
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);  /* 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       /*
426        * Hook all active jobs so that they release this table
427        */
428       foreach_jcr(jcr) {
429          if (jcr->JobType != JT_SYSTEM) {
430             reload_table[table].job_count++;
431             job_end_push(jcr, reload_job_end_cb, (void *)((long int)table));
432             njobs++;
433          }
434       }
435       endeach_jcr(jcr);
436    }
437
438    /* Reset globals */
439    set_working_directory(director->working_directory);
440    FDConnectTimeout = director->FDConnectTimeout;
441    SDConnectTimeout = director->SDConnectTimeout;
442    Dmsg0(0, "Director's configuration file reread.\n");
443
444    /* Now release saved resources, if no jobs using the resources */
445    if (njobs == 0) {
446       free_saved_resources(table);
447    }
448
449 bail_out:
450    UnlockRes();
451    unlock_jobs();
452    sigprocmask(SIG_UNBLOCK, &set, NULL);
453    signal(SIGHUP, reload_config);
454    already_here = false;
455 }
456
457 /*
458  * Make a quick check to see that we have all the
459  * resources needed.
460  *
461  *  **** FIXME **** this routine could be a lot more
462  *   intelligent and comprehensive.
463  */
464 static int check_resources()
465 {
466    bool OK = true;
467    JOB *job;
468
469    LockRes();
470
471    job = (JOB *)GetNextRes(R_JOB, NULL);
472    director = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
473    if (!director) {
474       Jmsg(NULL, M_FATAL, 0, _("No Director resource defined in %s\n"
475 "Without that I don't know who I am :-(\n"), configfile);
476       OK = false;
477    } else {
478       set_working_directory(director->working_directory);
479       if (!director->messages) {       /* If message resource not specified */
480          director->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
481          if (!director->messages) {
482             Jmsg(NULL, M_FATAL, 0, _("No Messages resource defined in %s\n"), configfile);
483             OK = false;
484          }
485       }
486       if (GetNextRes(R_DIRECTOR, (RES *)director) != NULL) {
487          Jmsg(NULL, M_FATAL, 0, _("Only one Director resource permitted in %s\n"),
488             configfile);
489          OK = false;
490       }
491       /* tls_require implies tls_enable */
492       if (director->tls_require) {
493          if (have_tls) {
494             director->tls_enable = true;
495          } else {
496             Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
497             OK = false;
498          }
499       }
500
501       if (!director->tls_certfile && director->tls_enable) {
502          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Director \"%s\" in %s.\n"),
503             director->hdr.name, configfile);
504          OK = false;
505       }
506
507       if (!director->tls_keyfile && director->tls_enable) {
508          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Director \"%s\" in %s.\n"),
509             director->hdr.name, configfile);
510          OK = false;
511       }
512
513       if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && director->tls_enable && director->tls_verify_peer) {
514          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA"
515               " Certificate Dir\" are defined for Director \"%s\" in %s."
516               " At least one CA certificate store is required"
517               " when using \"TLS Verify Peer\".\n"),
518               director->hdr.name, configfile);
519          OK = false;
520       }
521
522       /* If everything is well, attempt to initialize our per-resource TLS context */
523       if (OK && (director->tls_enable || director->tls_require)) {
524          /* Initialize TLS context:
525           * Args: CA certfile, CA certdir, Certfile, Keyfile,
526           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
527          director->tls_ctx = new_tls_context(director->tls_ca_certfile,
528             director->tls_ca_certdir, director->tls_certfile,
529             director->tls_keyfile, NULL, NULL, director->tls_dhfile,
530             director->tls_verify_peer);
531          
532          if (!director->tls_ctx) {
533             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Director \"%s\" in %s.\n"),
534                  director->hdr.name, configfile);
535             OK = false;
536          }
537       }
538    }
539
540    if (!job) {
541       Jmsg(NULL, M_FATAL, 0, _("No Job records defined in %s\n"), configfile);
542       OK = false;
543    }
544    foreach_res(job, R_JOB) {
545       int i;
546
547       if (job->jobdefs) {
548          /* Handle Storage alists specifically */
549          JOB *jobdefs = job->jobdefs;
550          if (jobdefs->storage && !job->storage) {
551             STORE *st;
552             job->storage = New(alist(10, not_owned_by_alist));
553             foreach_alist(st, jobdefs->storage) {
554                job->storage->append(st);
555             }
556          }
557
558          /* Transfer default items from JobDefs Resource */
559          for (i=0; job_items[i].name; i++) {
560             char **def_svalue, **svalue;  /* string value */
561             int *def_ivalue, *ivalue;     /* integer value */
562             int64_t *def_lvalue, *lvalue; /* 64 bit values */
563             uint32_t offset;
564
565             Dmsg4(1400, "Job \"%s\", field \"%s\" bit=%d def=%d\n",
566                 job->hdr.name, job_items[i].name,
567                 bit_is_set(i, job->hdr.item_present),
568                 bit_is_set(i, job->jobdefs->hdr.item_present));
569
570             if (!bit_is_set(i, job->hdr.item_present) &&
571                  bit_is_set(i, job->jobdefs->hdr.item_present)) {
572                Dmsg2(400, "Job \"%s\", field \"%s\": getting default.\n",
573                  job->hdr.name, job_items[i].name);
574                offset = (char *)(job_items[i].value) - (char *)&res_all;
575                /*
576                 * Handle strings and directory strings
577                 */
578                if (job_items[i].handler == store_str ||
579                    job_items[i].handler == store_dir) {
580                   def_svalue = (char **)((char *)(job->jobdefs) + offset);
581                   Dmsg5(400, "Job \"%s\", field \"%s\" def_svalue=%s item %d offset=%u\n",
582                        job->hdr.name, job_items[i].name, *def_svalue, i, offset);
583                   svalue = (char **)((char *)job + offset);
584                   if (*svalue) {
585                      Pmsg1(000, _("Hey something is wrong. p=0x%lu\n"), *svalue);
586                   }
587                   *svalue = bstrdup(*def_svalue);
588                   set_bit(i, job->hdr.item_present);
589                /*
590                 * Handle resources
591                 */
592                } else if (job_items[i].handler == store_res) {
593                   def_svalue = (char **)((char *)(job->jobdefs) + offset);
594                   Dmsg4(400, "Job \"%s\", field \"%s\" item %d offset=%u\n",
595                        job->hdr.name, job_items[i].name, i, offset);
596                   svalue = (char **)((char *)job + offset);
597                   if (*svalue) {
598                      Pmsg1(000, _("Hey something is wrong. p=0x%lu\n"), *svalue);
599                   }
600                   *svalue = *def_svalue;
601                   set_bit(i, job->hdr.item_present);
602                /*
603                 * Handle alist resources
604                 */
605                } else if (job_items[i].handler == store_alist_res) {
606                   if (bit_is_set(i, job->jobdefs->hdr.item_present)) {
607                      set_bit(i, job->hdr.item_present);
608                   }
609                /*
610                 * Handle integer fields
611                 *    Note, our store_yesno does not handle bitmaped fields
612                 */
613                } else if (job_items[i].handler == store_yesno   ||
614                           job_items[i].handler == store_pint    ||
615                           job_items[i].handler == store_jobtype ||
616                           job_items[i].handler == store_level   ||
617                           job_items[i].handler == store_pint    ||
618                           job_items[i].handler == store_replace) {
619                   def_ivalue = (int *)((char *)(job->jobdefs) + offset);
620                   Dmsg5(400, "Job \"%s\", field \"%s\" def_ivalue=%d item %d offset=%u\n",
621                        job->hdr.name, job_items[i].name, *def_ivalue, i, offset);
622                   ivalue = (int *)((char *)job + offset);
623                   *ivalue = *def_ivalue;
624                   set_bit(i, job->hdr.item_present);
625                /*
626                 * Handle 64 bit integer fields
627                 */
628                } else if (job_items[i].handler == store_time   ||
629                           job_items[i].handler == store_size   ||
630                           job_items[i].handler == store_int64) {
631                   def_lvalue = (int64_t *)((char *)(job->jobdefs) + offset);
632                   Dmsg5(400, "Job \"%s\", field \"%s\" def_lvalue=%" lld " item %d offset=%u\n",
633                        job->hdr.name, job_items[i].name, *def_lvalue, i, offset);
634                   lvalue = (int64_t *)((char *)job + offset);
635                   *lvalue = *def_lvalue;
636                   set_bit(i, job->hdr.item_present);
637                }
638             }
639          }
640       }
641       /*
642        * Ensure that all required items are present
643        */
644       for (i=0; job_items[i].name; i++) {
645          if (job_items[i].flags & ITEM_REQUIRED) {
646                if (!bit_is_set(i, job->hdr.item_present)) {
647                   Jmsg(NULL, M_FATAL, 0, _("\"%s\" directive in Job \"%s\" resource is required, but not found.\n"),
648                     job_items[i].name, job->hdr.name);
649                   OK = false;
650                 }
651          }
652          /* If this triggers, take a look at lib/parse_conf.h */
653          if (i >= MAX_RES_ITEMS) {
654             Emsg0(M_ERROR_TERM, 0, _("Too many items in Job resource\n"));
655          }
656       }
657    } /* End loop over Job res */
658
659    /* Loop over databases */
660    CAT *catalog;
661    foreach_res(catalog, R_CATALOG) {
662       B_DB *db;
663       /*
664        * Make sure we can open catalog, otherwise print a warning
665        * message because the server is probably not running.
666        */
667       db = db_init_database(NULL, catalog->db_name, catalog->db_user,
668                          catalog->db_password, catalog->db_address,
669                          catalog->db_port, catalog->db_socket,
670                          catalog->mult_db_connections);
671       if (!db || !db_open_database(NULL, db)) {
672          Jmsg(NULL, M_FATAL, 0, _("Could not open database \"%s\".\n"),
673               catalog->db_name);
674          if (db) {
675             Jmsg(NULL, M_FATAL, 0, _("%s"), db_strerror(db));
676          }
677          OK = false;
678          continue;
679       }
680
681       /* Loop over all pools, defining/updating them in each database */
682       POOL *pool;
683       foreach_res(pool, R_POOL) {
684          create_pool(NULL, db, pool, POOL_OP_UPDATE);  /* update request */
685       }
686
687       STORE *store;
688       foreach_res(store, R_STORAGE) {
689          STORAGE_DBR sr;
690          MEDIATYPE_DBR mr;
691          if (store->media_type) {
692             bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
693             mr.ReadOnly = 0;
694             db_create_mediatype_record(NULL, db, &mr);
695          } else {
696             mr.MediaTypeId = 0;
697          }
698          bstrncpy(sr.Name, store->name(), sizeof(sr.Name));
699          sr.AutoChanger = store->autochanger;
700          db_create_storage_record(NULL, db, &sr);
701          store->StorageId = sr.StorageId;   /* set storage Id */
702          if (!sr.created) {                 /* if not created, update it */
703             db_update_storage_record(NULL, db, &sr);
704          }
705
706          /* tls_require implies tls_enable */
707          if (store->tls_require) {
708             if (have_tls) {
709                store->tls_enable = true;
710             } else {
711                Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
712                OK = false;
713             }
714          } 
715
716          if ((!store->tls_ca_certfile && !store->tls_ca_certdir) && store->tls_enable) {
717             Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
718                  " or \"TLS CA Certificate Dir\" are defined for Storage \"%s\" in %s.\n"),
719                  store->hdr.name, configfile);
720             OK = false;
721          }
722
723          /* If everything is well, attempt to initialize our per-resource TLS context */
724          if (OK && (store->tls_enable || store->tls_require)) {
725            /* Initialize TLS context:
726             * Args: CA certfile, CA certdir, Certfile, Keyfile,
727             * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
728             store->tls_ctx = new_tls_context(store->tls_ca_certfile,
729                store->tls_ca_certdir, store->tls_certfile,
730                store->tls_keyfile, NULL, NULL, NULL, true);
731          
732             if (!store->tls_ctx) {
733                Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Storage \"%s\" in %s.\n"),
734                     store->hdr.name, configfile);
735                OK = false;
736             }
737          }
738       }
739
740       /* Loop over all counters, defining them in each database */
741       /* Set default value in all counters */
742       COUNTER *counter;
743       foreach_res(counter, R_COUNTER) {
744          /* Write to catalog? */
745          if (!counter->created && counter->Catalog == catalog) {
746             COUNTER_DBR cr;
747             bstrncpy(cr.Counter, counter->hdr.name, sizeof(cr.Counter));
748             cr.MinValue = counter->MinValue;
749             cr.MaxValue = counter->MaxValue;
750             cr.CurrentValue = counter->MinValue;
751             if (counter->WrapCounter) {
752                bstrncpy(cr.WrapCounter, counter->WrapCounter->hdr.name, sizeof(cr.WrapCounter));
753             } else {
754                cr.WrapCounter[0] = 0;  /* empty string */
755             }
756             if (db_create_counter_record(NULL, db, &cr)) {
757                counter->CurrentValue = cr.CurrentValue;
758                counter->created = true;
759                Dmsg2(100, "Create counter %s val=%d\n", counter->hdr.name, counter->CurrentValue);
760             }
761          }
762          if (!counter->created) {
763             counter->CurrentValue = counter->MinValue;  /* default value */
764          }
765       }
766       db_close_database(NULL, db);
767    }
768
769    /* Loop over Consoles */
770    CONRES *cons;
771    foreach_res(cons, R_CONSOLE) {
772       /* tls_require implies tls_enable */
773       if (cons->tls_require) {
774          if (have_tls) {
775             cons->tls_enable = true;
776          } else {
777             Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
778             OK = false;
779             continue;
780          }
781       }
782
783       if (!cons->tls_certfile && cons->tls_enable) {
784          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Console \"%s\" in %s.\n"),
785             cons->hdr.name, configfile);
786          OK = false;
787       }
788
789       if (!cons->tls_keyfile && cons->tls_enable) {
790          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Console \"%s\" in %s.\n"),
791             cons->hdr.name, configfile);
792          OK = false;
793       }
794
795       if ((!cons->tls_ca_certfile && !cons->tls_ca_certdir) && cons->tls_enable && cons->tls_verify_peer) {
796          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA"
797             " Certificate Dir\" are defined for Console \"%s\" in %s."
798             " At least one CA certificate store is required"
799             " when using \"TLS Verify Peer\".\n"),
800             cons->hdr.name, configfile);
801          OK = false;
802       }
803       /* If everything is well, attempt to initialize our per-resource TLS context */
804       if (OK && (cons->tls_enable || cons->tls_require)) {
805          /* Initialize TLS context:
806           * Args: CA certfile, CA certdir, Certfile, Keyfile,
807           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
808          cons->tls_ctx = new_tls_context(cons->tls_ca_certfile,
809             cons->tls_ca_certdir, cons->tls_certfile,
810             cons->tls_keyfile, NULL, NULL, cons->tls_dhfile, cons->tls_verify_peer);
811          
812          if (!cons->tls_ctx) {
813             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
814                cons->hdr.name, configfile);
815             OK = false;
816          }
817       }
818
819    }
820
821    /* Loop over Clients */
822    CLIENT *client;
823    foreach_res(client, R_CLIENT) {
824       /* tls_require implies tls_enable */
825       if (client->tls_require) {
826          if (have_tls) {
827             client->tls_enable = true;
828          } else {
829             Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
830             OK = false;
831             continue;
832          }
833       }
834
835       if ((!client->tls_ca_certfile && !client->tls_ca_certdir) && client->tls_enable) {
836          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
837             " or \"TLS CA Certificate Dir\" are defined for File daemon \"%s\" in %s.\n"),
838             client->hdr.name, configfile);
839          OK = false;
840       }
841
842       /* If everything is well, attempt to initialize our per-resource TLS context */
843       if (OK && (client->tls_enable || client->tls_require)) {
844          /* Initialize TLS context:
845           * Args: CA certfile, CA certdir, Certfile, Keyfile,
846           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
847          client->tls_ctx = new_tls_context(client->tls_ca_certfile,
848             client->tls_ca_certdir, client->tls_certfile,
849             client->tls_keyfile, NULL, NULL, NULL,
850             true);
851          
852          if (!client->tls_ctx) {
853             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
854                client->hdr.name, configfile);
855             OK = false;
856          }
857       }
858    }
859
860    UnlockRes();
861    if (OK) {
862       close_msg(NULL);                /* close temp message handler */
863       init_msg(NULL, director->messages); /* open daemon message handler */
864    }
865    return OK;
866 }