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