2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation plus additions
11 that are listed in the file LICENSE.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
30 * Bacula Director daemon -- this is the main program
32 * Kern Sibbald, March MM
40 /* Forward referenced subroutines */
41 void terminate_dird(int sig);
42 static bool check_resources();
43 static bool check_catalog();
44 static void dir_sql_query(JCR *jcr, const char *cmd);
46 /* Exported subroutines */
47 extern "C" void reload_config(int sig);
48 extern void invalidate_schedules();
51 /* Imported subroutines */
52 JCR *wait_for_next_job(char *runjob);
53 void term_scheduler();
54 void term_ua_server();
55 void start_UA_server(dlist *addrs);
56 void init_job_server(int max_workers);
57 void term_job_server();
58 void store_jobtype(LEX *lc, RES_ITEM *item, int index, int pass);
59 void store_level(LEX *lc, RES_ITEM *item, int index, int pass);
60 void store_replace(LEX *lc, RES_ITEM *item, int index, int pass);
61 void init_device_resources();
63 static char *runjob = NULL;
64 static int background = 1;
65 static void init_reload(void);
67 /* Globals Exported */
68 DIRRES *director; /* Director resource */
71 char *configfile = NULL;
73 /* Globals Imported */
74 extern int r_first, r_last; /* first and last resources */
75 extern RES_TABLE resources[];
76 extern RES **res_head;
77 extern RES_ITEM job_items[];
80 extern "C" { // work around visual compiler mangling variables
87 #define CONFIG_FILE "bacula-dir.conf" /* default configuration file */
93 "\nVersion: %s (%s)\n\n"
94 "Usage: dird [-f -s] [-c config_file] [-d debug_level] [config_file]\n"
95 " -c <file> set configuration file to file\n"
96 " -dnn set debug level to nn\n"
97 " -f run in foreground (for debugging)\n"
99 " -r <job> run <job> now\n"
101 " -t test - read configuration and exit\n"
103 " -v verbose user messages\n"
104 " -? print this message.\n"
105 "\n"), 2000, VERSION, BDATE);
111 /*********************************************************************
113 * Main Bacula Server program
116 #if defined(HAVE_WIN32)
117 /* For Win32 main() is in src/win32 code ... */
118 #define main BaculaMain
121 int main (int argc, char *argv[])
125 int no_signals = FALSE;
126 int test_config = FALSE;
130 setlocale(LC_ALL, "");
131 bindtextdomain("bacula", LOCALEDIR);
132 textdomain("bacula");
135 my_name_is(argc, argv, "bacula-dir");
136 init_msg(NULL, NULL); /* initialize message handler */
138 daemon_start_time = time(NULL);
140 while ((ch = getopt(argc, argv, "c:d:fg:r:stu:v?")) != -1) {
142 case 'c': /* specify config file */
143 if (configfile != NULL) {
146 configfile = bstrdup(optarg);
149 case 'd': /* set debug level */
150 debug_level = atoi(optarg);
151 if (debug_level <= 0) {
154 Dmsg1(0, "Debug level = %d\n", debug_level);
157 case 'f': /* run in foreground */
161 case 'g': /* set group id */
165 case 'r': /* run job */
166 if (runjob != NULL) {
170 runjob = bstrdup(optarg);
174 case 's': /* turn off signals */
178 case 't': /* test config */
182 case 'u': /* set uid */
186 case 'v': /* verbose */
200 init_signals(terminate_dird);
204 if (configfile != NULL) {
207 configfile = bstrdup(*argv);
215 if (configfile == NULL) {
216 configfile = bstrdup(CONFIG_FILE);
219 parse_config(configfile);
221 if (init_crypto() != 0) {
222 Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Cryptography library initialization failed.\n"));
225 if (!check_resources()) {
226 Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile);
233 my_name_is(0, NULL, director->name()); /* set user defined name */
235 /* Plug database interface for library routines */
236 p_sql_query = (sql_query)dir_sql_query;
237 p_sql_escape = (sql_escape)db_escape_string;
239 FDConnectTimeout = (int)director->FDConnectTimeout;
240 SDConnectTimeout = (int)director->SDConnectTimeout;
244 init_stack_dump(); /* grab new pid */
247 /* Create pid must come after we are a daemon -- so we have our final pid */
248 create_pid_file(director->pid_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
249 read_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
251 drop(uid, gid); /* reduce privileges if requested */
253 if (!check_catalog()) {
254 Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile);
257 #if !defined(HAVE_WIN32)
258 signal(SIGHUP, reload_config);
261 init_console_msg(working_directory);
263 init_python_interpreter(director->name(), director->scripts_directory,
266 set_thread_concurrency(director->MaxConcurrentJobs * 2 +
267 4 /* UA */ + 4 /* sched+watchdog+jobsvr+misc */);
269 Dmsg0(200, "Start UA server\n");
270 start_UA_server(director->DIRaddrs);
272 start_watchdog(); /* start network watchdog thread */
274 init_jcr_subsystem(); /* start JCR watchdogs etc. */
276 init_job_server(director->MaxConcurrentJobs);
278 // init_device_resources();
280 Dmsg0(200, "wait for next job\n");
281 /* Main loop -- call scheduler to get next job to run */
282 while ( (jcr = wait_for_next_job(runjob)) ) {
283 run_job(jcr); /* run job */
284 free_jcr(jcr); /* release jcr */
285 if (runjob) { /* command line, run a single job? */
286 break; /* yes, terminate */
295 static void dir_sql_query(JCR *jcr, const char *cmd)
297 if (!jcr || !jcr->db) {
300 db_sql_query(jcr->db, cmd, NULL, NULL);
303 /* Cleanup and then exit */
304 void terminate_dird(int sig)
306 static bool already_here = false;
308 if (already_here) { /* avoid recursive temination problems */
313 generate_daemon_event(NULL, "Exit");
314 write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
315 delete_pid_file(director->pid_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
316 // signal(SIGCHLD, SIG_IGN); /* don't worry about children now */
322 if (configfile != NULL) {
325 if (debug_level > 5) {
326 print_memory_pool_stats();
328 free_config_resources();
330 term_msg(); /* terminate message handler */
332 close_memory_pool(); /* release free memory in pool */
337 struct RELOAD_TABLE {
342 static const int max_reloads = 32;
343 static RELOAD_TABLE reload_table[max_reloads];
345 static void init_reload(void)
347 for (int i=0; i < max_reloads; i++) {
348 reload_table[i].job_count = 0;
349 reload_table[i].res_table = NULL;
353 static void free_saved_resources(int table)
355 int num = r_last - r_first + 1;
356 RES **res_tab = reload_table[table].res_table;
358 Dmsg1(100, "res_tab for table %d already released.\n", table);
361 Dmsg1(100, "Freeing resources for table %d\n", table);
362 for (int j=0; j<num; j++) {
363 free_resource(res_tab[j], r_first + j);
366 reload_table[table].job_count = 0;
367 reload_table[table].res_table = NULL;
371 * Called here at the end of every job that was
372 * hooked decrementing the active job_count. When
373 * it goes to zero, no one is using the associated
374 * resource table, so free it.
376 static void reload_job_end_cb(JCR *jcr, void *ctx)
378 int reload_id = (int)((long int)ctx);
379 Dmsg3(100, "reload job_end JobId=%d table=%d cnt=%d\n", jcr->JobId,
380 reload_id, reload_table[reload_id].job_count);
383 if (--reload_table[reload_id].job_count <= 0) {
384 free_saved_resources(reload_id);
390 static int find_free_reload_table_entry()
393 for (int i=0; i < max_reloads; i++) {
394 if (reload_table[i].res_table == NULL) {
403 * If we get here, we have received a SIGHUP, which means to
404 * reread our configuration file.
406 * The algorithm used is as follows: we count how many jobs are
407 * running and mark the running jobs to make a callback on
408 * exiting. The old config is saved with the reload table
409 * id in a reload table. The new config file is read. Now, as
410 * each job exits, it calls back to the reload_job_end_cb(), which
411 * decrements the count of open jobs for the given reload table.
412 * When the count goes to zero, we release those resources.
413 * This allows us to have pointers into the resource table (from
414 * jobs), and once they exit and all the pointers are released, we
415 * release the old table. Note, if no new jobs are running since the
416 * last reload, then the old resources will be immediately release.
417 * A console is considered a job because it may have pointers to
418 * resources, but a SYSTEM job is not since it *should* not have any
419 * permanent pointers to jobs.
422 void reload_config(int sig)
424 static bool already_here = false;
425 #if !defined(HAVE_WIN32)
429 int njobs = 0; /* number of running jobs */
434 abort(); /* Oops, recursion -> die */
438 #if !defined(HAVE_WIN32)
440 sigaddset(&set, SIGHUP);
441 sigprocmask(SIG_BLOCK, &set, NULL);
447 table = find_free_reload_table_entry();
449 Jmsg(NULL, M_ERROR, 0, _("Too many open reload requests. Request ignored.\n"));
453 Dmsg1(100, "Reload_config njobs=%d\n", njobs);
454 reload_table[table].res_table = save_config_resources();
455 Dmsg1(100, "Saved old config in table %d\n", table);
457 ok = parse_config(configfile, 0, M_ERROR); /* no exit on error */
459 Dmsg0(100, "Reloaded config file\n");
460 if (!ok || !check_resources()) {
461 rtable = find_free_reload_table_entry(); /* save new, bad table */
463 Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
464 Jmsg(NULL, M_ERROR_TERM, 0, _("Out of reload table entries. Giving up.\n"));
466 Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
467 Jmsg(NULL, M_ERROR, 0, _("Resetting previous configuration.\n"));
469 reload_table[rtable].res_table = save_config_resources();
470 /* Now restore old resoure values */
471 int num = r_last - r_first + 1;
472 RES **res_tab = reload_table[table].res_table;
473 for (int i=0; i<num; i++) {
474 res_head[i] = res_tab[i];
476 table = rtable; /* release new, bad, saved table below */
478 invalidate_schedules();
480 * Hook all active jobs so that they release this table
483 if (jcr->JobType != JT_SYSTEM) {
484 reload_table[table].job_count++;
485 job_end_push(jcr, reload_job_end_cb, (void *)((long int)table));
493 set_working_directory(director->working_directory);
494 FDConnectTimeout = director->FDConnectTimeout;
495 SDConnectTimeout = director->SDConnectTimeout;
496 Dmsg0(0, "Director's configuration file reread.\n");
498 /* Now release saved resources, if no jobs using the resources */
500 free_saved_resources(table);
506 #if !defined(HAVE_WIN32)
507 sigprocmask(SIG_UNBLOCK, &set, NULL);
508 signal(SIGHUP, reload_config);
510 already_here = false;
514 * Make a quick check to see that we have all the
517 * **** FIXME **** this routine could be a lot more
518 * intelligent and comprehensive.
520 static bool check_resources()
527 job = (JOB *)GetNextRes(R_JOB, NULL);
528 director = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
530 Jmsg(NULL, M_FATAL, 0, _("No Director resource defined in %s\n"
531 "Without that I don't know who I am :-(\n"), configfile);
534 set_working_directory(director->working_directory);
535 if (!director->messages) { /* If message resource not specified */
536 director->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
537 if (!director->messages) {
538 Jmsg(NULL, M_FATAL, 0, _("No Messages resource defined in %s\n"), configfile);
542 if (GetNextRes(R_DIRECTOR, (RES *)director) != NULL) {
543 Jmsg(NULL, M_FATAL, 0, _("Only one Director resource permitted in %s\n"),
547 /* tls_require implies tls_enable */
548 if (director->tls_require) {
550 director->tls_enable = true;
552 Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
557 if (!director->tls_certfile && director->tls_enable) {
558 Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Director \"%s\" in %s.\n"),
559 director->name(), configfile);
563 if (!director->tls_keyfile && director->tls_enable) {
564 Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Director \"%s\" in %s.\n"),
565 director->name(), configfile);
569 if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && director->tls_enable && director->tls_verify_peer) {
570 Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA"
571 " Certificate Dir\" are defined for Director \"%s\" in %s."
572 " At least one CA certificate store is required"
573 " when using \"TLS Verify Peer\".\n"),
574 director->name(), configfile);
578 /* If everything is well, attempt to initialize our per-resource TLS context */
579 if (OK && (director->tls_enable || director->tls_require)) {
580 /* Initialize TLS context:
581 * Args: CA certfile, CA certdir, Certfile, Keyfile,
582 * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
583 director->tls_ctx = new_tls_context(director->tls_ca_certfile,
584 director->tls_ca_certdir, director->tls_certfile,
585 director->tls_keyfile, NULL, NULL, director->tls_dhfile,
586 director->tls_verify_peer);
588 if (!director->tls_ctx) {
589 Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Director \"%s\" in %s.\n"),
590 director->name(), configfile);
597 Jmsg(NULL, M_FATAL, 0, _("No Job records defined in %s\n"), configfile);
600 foreach_res(job, R_JOB) {
604 /* Handle Storage alists specifically */
605 JOB *jobdefs = job->jobdefs;
606 if (jobdefs->storage && !job->storage) {
608 job->storage = New(alist(10, not_owned_by_alist));
609 foreach_alist(st, jobdefs->storage) {
610 job->storage->append(st);
613 /* Handle RunScripts alists specifically */
614 if (jobdefs->RunScripts) {
617 if (!job->RunScripts) {
618 job->RunScripts = New(alist(10, not_owned_by_alist));
621 foreach_alist(rs, jobdefs->RunScripts) {
622 elt = copy_runscript(rs);
623 job->RunScripts->append(elt); /* we have to free it */
627 /* Transfer default items from JobDefs Resource */
628 for (i=0; job_items[i].name; i++) {
629 char **def_svalue, **svalue; /* string value */
630 int *def_ivalue, *ivalue; /* integer value */
631 bool *def_bvalue, *bvalue; /* bool value */
632 int64_t *def_lvalue, *lvalue; /* 64 bit values */
635 Dmsg4(1400, "Job \"%s\", field \"%s\" bit=%d def=%d\n",
636 job->name(), job_items[i].name,
637 bit_is_set(i, job->hdr.item_present),
638 bit_is_set(i, job->jobdefs->hdr.item_present));
640 if (!bit_is_set(i, job->hdr.item_present) &&
641 bit_is_set(i, job->jobdefs->hdr.item_present)) {
642 Dmsg2(400, "Job \"%s\", field \"%s\": getting default.\n",
643 job->name(), job_items[i].name);
644 offset = (char *)(job_items[i].value) - (char *)&res_all;
646 * Handle strings and directory strings
648 if (job_items[i].handler == store_str ||
649 job_items[i].handler == store_dir) {
650 def_svalue = (char **)((char *)(job->jobdefs) + offset);
651 Dmsg5(400, "Job \"%s\", field \"%s\" def_svalue=%s item %d offset=%u\n",
652 job->name(), job_items[i].name, *def_svalue, i, offset);
653 svalue = (char **)((char *)job + offset);
655 Pmsg1(000, _("Hey something is wrong. p=0x%lu\n"), *svalue);
657 *svalue = bstrdup(*def_svalue);
658 set_bit(i, job->hdr.item_present);
662 } else if (job_items[i].handler == store_res) {
663 def_svalue = (char **)((char *)(job->jobdefs) + offset);
664 Dmsg4(400, "Job \"%s\", field \"%s\" item %d offset=%u\n",
665 job->name(), job_items[i].name, i, offset);
666 svalue = (char **)((char *)job + offset);
668 Pmsg1(000, _("Hey something is wrong. p=0x%lu\n"), *svalue);
670 *svalue = *def_svalue;
671 set_bit(i, job->hdr.item_present);
673 * Handle alist resources
675 } else if (job_items[i].handler == store_alist_res) {
676 if (bit_is_set(i, job->jobdefs->hdr.item_present)) {
677 set_bit(i, job->hdr.item_present);
680 * Handle integer fields
681 * Note, our store_bit does not handle bitmaped fields
683 } else if (job_items[i].handler == store_bit ||
684 job_items[i].handler == store_pint ||
685 job_items[i].handler == store_jobtype ||
686 job_items[i].handler == store_level ||
687 job_items[i].handler == store_pint ||
688 job_items[i].handler == store_replace) {
689 def_ivalue = (int *)((char *)(job->jobdefs) + offset);
690 Dmsg5(400, "Job \"%s\", field \"%s\" def_ivalue=%d item %d offset=%u\n",
691 job->name(), job_items[i].name, *def_ivalue, i, offset);
692 ivalue = (int *)((char *)job + offset);
693 *ivalue = *def_ivalue;
694 set_bit(i, job->hdr.item_present);
696 * Handle 64 bit integer fields
698 } else if (job_items[i].handler == store_time ||
699 job_items[i].handler == store_size ||
700 job_items[i].handler == store_int64) {
701 def_lvalue = (int64_t *)((char *)(job->jobdefs) + offset);
702 Dmsg5(400, "Job \"%s\", field \"%s\" def_lvalue=%" lld " item %d offset=%u\n",
703 job->name(), job_items[i].name, *def_lvalue, i, offset);
704 lvalue = (int64_t *)((char *)job + offset);
705 *lvalue = *def_lvalue;
706 set_bit(i, job->hdr.item_present);
710 } else if (job_items[i].handler == store_bool) {
711 def_bvalue = (bool *)((char *)(job->jobdefs) + offset);
712 Dmsg5(400, "Job \"%s\", field \"%s\" def_bvalue=%d item %d offset=%u\n",
713 job->name(), job_items[i].name, *def_bvalue, i, offset);
714 bvalue = (bool *)((char *)job + offset);
715 *bvalue = *def_bvalue;
716 set_bit(i, job->hdr.item_present);
722 * Ensure that all required items are present
724 for (i=0; job_items[i].name; i++) {
725 if (job_items[i].flags & ITEM_REQUIRED) {
726 if (!bit_is_set(i, job->hdr.item_present)) {
727 Jmsg(NULL, M_FATAL, 0, _("\"%s\" directive in Job \"%s\" resource is required, but not found.\n"),
728 job_items[i].name, job->name());
732 /* If this triggers, take a look at lib/parse_conf.h */
733 if (i >= MAX_RES_ITEMS) {
734 Emsg0(M_ERROR_TERM, 0, _("Too many items in Job resource\n"));
737 if (!job->storage && !job->pool->storage) {
738 Jmsg(NULL, M_FATAL, 0, _("No storage specified in Job \"%s\" nor in Pool.\n"),
742 } /* End loop over Job res */
745 /* Loop over Consoles */
747 foreach_res(cons, R_CONSOLE) {
748 /* tls_require implies tls_enable */
749 if (cons->tls_require) {
751 cons->tls_enable = true;
753 Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
759 if (!cons->tls_certfile && cons->tls_enable) {
760 Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Console \"%s\" in %s.\n"),
761 cons->name(), configfile);
765 if (!cons->tls_keyfile && cons->tls_enable) {
766 Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Console \"%s\" in %s.\n"),
767 cons->name(), configfile);
771 if ((!cons->tls_ca_certfile && !cons->tls_ca_certdir) && cons->tls_enable && cons->tls_verify_peer) {
772 Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA"
773 " Certificate Dir\" are defined for Console \"%s\" in %s."
774 " At least one CA certificate store is required"
775 " when using \"TLS Verify Peer\".\n"),
776 cons->name(), configfile);
779 /* If everything is well, attempt to initialize our per-resource TLS context */
780 if (OK && (cons->tls_enable || cons->tls_require)) {
781 /* Initialize TLS context:
782 * Args: CA certfile, CA certdir, Certfile, Keyfile,
783 * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
784 cons->tls_ctx = new_tls_context(cons->tls_ca_certfile,
785 cons->tls_ca_certdir, cons->tls_certfile,
786 cons->tls_keyfile, NULL, NULL, cons->tls_dhfile, cons->tls_verify_peer);
788 if (!cons->tls_ctx) {
789 Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
790 cons->name(), configfile);
797 /* Loop over Clients */
799 foreach_res(client, R_CLIENT) {
800 /* tls_require implies tls_enable */
801 if (client->tls_require) {
803 client->tls_enable = true;
805 Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
811 if ((!client->tls_ca_certfile && !client->tls_ca_certdir) && client->tls_enable) {
812 Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
813 " or \"TLS CA Certificate Dir\" are defined for File daemon \"%s\" in %s.\n"),
814 client->name(), configfile);
818 /* If everything is well, attempt to initialize our per-resource TLS context */
819 if (OK && (client->tls_enable || client->tls_require)) {
820 /* Initialize TLS context:
821 * Args: CA certfile, CA certdir, Certfile, Keyfile,
822 * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
823 client->tls_ctx = new_tls_context(client->tls_ca_certfile,
824 client->tls_ca_certdir, client->tls_certfile,
825 client->tls_keyfile, NULL, NULL, NULL,
828 if (!client->tls_ctx) {
829 Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
830 client->name(), configfile);
838 close_msg(NULL); /* close temp message handler */
839 init_msg(NULL, director->messages); /* open daemon message handler */
844 static bool check_catalog()
848 /* Loop over databases */
850 foreach_res(catalog, R_CATALOG) {
853 * Make sure we can open catalog, otherwise print a warning
854 * message because the server is probably not running.
856 db = db_init_database(NULL, catalog->db_name, catalog->db_user,
857 catalog->db_password, catalog->db_address,
858 catalog->db_port, catalog->db_socket,
859 catalog->mult_db_connections);
860 if (!db || !db_open_database(NULL, db)) {
861 Jmsg(NULL, M_FATAL, 0, _("Could not open Catalog \"%s\", database \"%s\".\n"),
862 catalog->name(), catalog->db_name);
864 Jmsg(NULL, M_FATAL, 0, _("%s"), db_strerror(db));
870 /* Loop over all pools, defining/updating them in each database */
872 foreach_res(pool, R_POOL) {
873 create_pool(NULL, db, pool, POOL_OP_UPDATE); /* update request */
876 /* Loop over all pools for updating RecyclePool */
877 foreach_res(pool, R_POOL) {
878 update_pool_recyclepool(NULL, db, pool);
882 foreach_res(store, R_STORAGE) {
885 if (store->media_type) {
886 bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
888 db_create_mediatype_record(NULL, db, &mr);
892 bstrncpy(sr.Name, store->name(), sizeof(sr.Name));
893 sr.AutoChanger = store->autochanger;
894 db_create_storage_record(NULL, db, &sr);
895 store->StorageId = sr.StorageId; /* set storage Id */
896 if (!sr.created) { /* if not created, update it */
897 db_update_storage_record(NULL, db, &sr);
900 /* tls_require implies tls_enable */
901 if (store->tls_require) {
903 store->tls_enable = true;
905 Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
910 if ((!store->tls_ca_certfile && !store->tls_ca_certdir) && store->tls_enable) {
911 Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
912 " or \"TLS CA Certificate Dir\" are defined for Storage \"%s\" in %s.\n"),
913 store->name(), configfile);
917 /* If everything is well, attempt to initialize our per-resource TLS context */
918 if (OK && (store->tls_enable || store->tls_require)) {
919 /* Initialize TLS context:
920 * Args: CA certfile, CA certdir, Certfile, Keyfile,
921 * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
922 store->tls_ctx = new_tls_context(store->tls_ca_certfile,
923 store->tls_ca_certdir, store->tls_certfile,
924 store->tls_keyfile, NULL, NULL, NULL, true);
926 if (!store->tls_ctx) {
927 Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Storage \"%s\" in %s.\n"),
928 store->name(), configfile);
934 /* Loop over all counters, defining them in each database */
935 /* Set default value in all counters */
937 foreach_res(counter, R_COUNTER) {
938 /* Write to catalog? */
939 if (!counter->created && counter->Catalog == catalog) {
941 bstrncpy(cr.Counter, counter->name(), sizeof(cr.Counter));
942 cr.MinValue = counter->MinValue;
943 cr.MaxValue = counter->MaxValue;
944 cr.CurrentValue = counter->MinValue;
945 if (counter->WrapCounter) {
946 bstrncpy(cr.WrapCounter, counter->WrapCounter->name(), sizeof(cr.WrapCounter));
948 cr.WrapCounter[0] = 0; /* empty string */
950 if (db_create_counter_record(NULL, db, &cr)) {
951 counter->CurrentValue = cr.CurrentValue;
952 counter->created = true;
953 Dmsg2(100, "Create counter %s val=%d\n", counter->name(), counter->CurrentValue);
956 if (!counter->created) {
957 counter->CurrentValue = counter->MinValue; /* default value */
960 db_close_database(NULL, db);