]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/stored.c
This commit was manufactured by cvs2svn to create tag
[bacula/bacula] / bacula / src / stored / stored.c
1 /*
2  * Second generation Storage daemon.
3  *
4  * It accepts a number of simple commands from the File daemon
5  * and acts on them. When a request to append data is made,
6  * it opens a data channel and accepts data from the
7  * File daemon.
8  *
9  *   Version $Id$
10  *
11  */
12 /*
13    Copyright (C) 2000-2006 Kern Sibbald
14
15    This program is free software; you can redistribute it and/or
16    modify it under the terms of the GNU General Public License
17    version 2 as amended with additional clauses defined in the
18    file LICENSE in the main source directory.
19
20    This program is distributed in the hope that it will be useful,
21    but WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
23    the file LICENSE for additional details.
24
25  */
26
27 #include "bacula.h"
28 #include "stored.h"
29
30 /* Imported functions */
31
32
33 /* Forward referenced functions */
34 void terminate_stored(int sig);
35 static int check_resources();
36 static void cleanup_old_files();
37
38 extern "C" void *device_initialization(void *arg);
39
40 #define CONFIG_FILE "bacula-sd.conf"  /* Default config file */
41
42 /* Global variables exported */
43 char OK_msg[]   = "3000 OK\n";
44 char TERM_msg[] = "3999 Terminate\n";
45 STORES *me = NULL;                    /* our Global resource */
46 bool forge_on = false;                /* proceed inspite of I/O errors */
47 pthread_mutex_t device_release_mutex = PTHREAD_MUTEX_INITIALIZER;
48 pthread_cond_t wait_device_release = PTHREAD_COND_INITIALIZER;
49
50
51 static uint32_t VolSessionId = 0;
52 uint32_t VolSessionTime;
53 char *configfile = NULL;
54 bool init_done = false;
55
56 /* Global static variables */
57 static int foreground = 0;
58 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
59 static workq_t dird_workq;            /* queue for processing connections */
60
61
62 static void usage()
63 {
64    fprintf(stderr, _(
65 "Copyright (C) 2000-2005 Kern Sibbald.\n"
66 "\nVersion: %s (%s)\n\n"
67 "Usage: stored [options] [-c config_file] [config_file]\n"
68 "        -c <file>   use <file> as configuration file\n"
69 "        -dnn        set debug level to nn\n"
70 "        -f          run in foreground (for debugging)\n"
71 "        -g <group>  set groupid to group\n"
72 "        -p          proceed despite I/O errors\n"
73 "        -s          no signals (for debugging)\n"
74 "        -t          test - read config and exit\n"
75 "        -u <user>   userid to <user>\n"
76 "        -v          verbose user messages\n"
77 "        -?          print this message.\n"
78 "\n"), VERSION, BDATE);
79    exit(1);
80 }
81
82 /*********************************************************************
83  *
84  *  Main Bacula Unix Storage Daemon
85  *
86  */
87 int main (int argc, char *argv[])
88 {
89    int ch;
90    int no_signals = FALSE;
91    int test_config = FALSE;
92    pthread_t thid;
93    char *uid = NULL;
94    char *gid = NULL;
95
96    setlocale(LC_ALL, "");
97    bindtextdomain("bacula", LOCALEDIR);
98    textdomain("bacula");
99
100    init_stack_dump();
101    my_name_is(argc, argv, "bacula-sd");
102    init_msg(NULL, NULL);
103    daemon_start_time = time(NULL);
104
105    /* Sanity checks */
106    if (TAPE_BSIZE % B_DEV_BSIZE != 0 || TAPE_BSIZE / B_DEV_BSIZE == 0) {
107       Emsg2(M_ABORT, 0, _("Tape block size (%d) not multiple of system size (%d)\n"),
108          TAPE_BSIZE, B_DEV_BSIZE);
109    }
110    if (TAPE_BSIZE != (1 << (ffs(TAPE_BSIZE)-1))) {
111       Emsg1(M_ABORT, 0, _("Tape block size (%d) is not a power of 2\n"), TAPE_BSIZE);
112    }
113
114    while ((ch = getopt(argc, argv, "c:d:fg:pstu:v?")) != -1) {
115       switch (ch) {
116       case 'c':                    /* configuration file */
117          if (configfile != NULL) {
118             free(configfile);
119          }
120          configfile = bstrdup(optarg);
121          break;
122
123       case 'd':                    /* debug level */
124          debug_level = atoi(optarg);
125          if (debug_level <= 0) {
126             debug_level = 1;
127          }
128          break;
129
130       case 'f':                    /* run in foreground */
131          foreground = TRUE;
132          break;
133
134       case 'g':                    /* set group id */
135          gid = optarg;
136          break;
137
138       case 'p':                    /* proceed in spite of I/O errors */
139          forge_on = true;
140          break;
141
142       case 's':                    /* no signals */
143          no_signals = TRUE;
144          break;
145
146       case 't':
147          test_config = TRUE;
148          break;
149
150       case 'u':                    /* set uid */
151          uid = optarg;
152          break;
153
154       case 'v':                    /* verbose */
155          verbose++;
156          break;
157
158       case '?':
159       default:
160          usage();
161          break;
162       }
163    }
164    argc -= optind;
165    argv += optind;
166
167    if (argc) {
168       if (configfile != NULL) {
169          free(configfile);
170       }
171       configfile = bstrdup(*argv);
172       argc--;
173       argv++;
174    }
175    if (argc)
176       usage();
177
178    if (!no_signals) {
179       init_signals(terminate_stored);
180    }
181
182    if (configfile == NULL) {
183       configfile = bstrdup(CONFIG_FILE);
184    }
185
186    parse_config(configfile);
187
188    if (init_crypto() != 0) {
189       Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Cryptography library initialization failed.\n"));
190    }
191
192    if (!check_resources()) {
193       Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile);
194    }
195
196    init_reservations_lock();
197
198    if (test_config) {
199       terminate_stored(0);
200    }
201
202    my_name_is(0, (char **)NULL, me->hdr.name);     /* Set our real name */
203
204    if (!foreground) {
205       daemon_start();                 /* become daemon */
206       init_stack_dump();              /* pick up new pid */
207    }
208
209    create_pid_file(me->pid_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
210    read_state_file(me->working_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
211
212    drop(uid, gid);
213
214    cleanup_old_files();
215
216
217    /* Ensure that Volume Session Time and Id are both
218     * set and are both non-zero.
219     */
220    VolSessionTime = (uint32_t)daemon_start_time;
221    if (VolSessionTime == 0) { /* paranoid */
222       Jmsg0(NULL, M_ABORT, 0, _("Volume Session Time is ZERO!\n"));
223    }
224
225    init_python_interpreter(me->hdr.name, me->scripts_directory, "SDStartUp");
226
227    /* Make sure on Solaris we can run concurrent, watch dog + servers + misc */
228    set_thread_concurrency(me->max_concurrent_jobs * 2 + 4);
229
230     /*
231      * Start the device allocation thread
232      */
233    create_volume_list();              /* do before device_init */
234    if (pthread_create(&thid, NULL, device_initialization, NULL) != 0) {
235       Emsg1(M_ABORT, 0, _("Unable to create thread. ERR=%s\n"), strerror(errno));
236    }
237
238    start_watchdog();                  /* start watchdog thread */
239    init_jcr_subsystem();              /* start JCR watchdogs etc. */
240
241    /* Single server used for Director and File daemon */
242    bnet_thread_server(me->sdaddrs, me->max_concurrent_jobs * 2 + 1,
243                       &dird_workq, handle_connection_request);
244    exit(1);                           /* to keep compiler quiet */
245 }
246
247 /* Return a new Session Id */
248 uint32_t newVolSessionId()
249 {
250    uint32_t Id;
251
252    P(mutex);
253    VolSessionId++;
254    Id = VolSessionId;
255    V(mutex);
256    return Id;
257 }
258
259 /* Check Configuration file for necessary info */
260 static int check_resources()
261 {
262    bool OK = true;
263
264
265    me = (STORES *)GetNextRes(R_STORAGE, NULL);
266    if (!me) {
267       Jmsg1(NULL, M_ERROR, 0, _("No Storage resource defined in %s. Cannot continue.\n"),
268          configfile);
269       OK = false;
270    }
271
272    if (GetNextRes(R_STORAGE, (RES *)me) != NULL) {
273       Jmsg1(NULL, M_ERROR, 0, _("Only one Storage resource permitted in %s\n"),
274          configfile);
275       OK = false;
276    }
277    if (GetNextRes(R_DIRECTOR, NULL) == NULL) {
278       Jmsg1(NULL, M_ERROR, 0, _("No Director resource defined in %s. Cannot continue.\n"),
279          configfile);
280       OK = false;
281    }
282    if (GetNextRes(R_DEVICE, NULL) == NULL){
283       Jmsg1(NULL, M_ERROR, 0, _("No Device resource defined in %s. Cannot continue.\n"),
284            configfile);
285       OK = false;
286    }
287
288    if (!me->messages) {
289       me->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
290       if (!me->messages) {
291          Jmsg1(NULL, M_ERROR, 0, _("No Messages resource defined in %s. Cannot continue.\n"),
292             configfile);
293          OK = false;
294       }
295    }
296
297    if (!me->working_directory) {
298       Jmsg1(NULL, M_ERROR, 0, _("No Working Directory defined in %s. Cannot continue.\n"),
299          configfile);
300       OK = false;
301    }
302
303    DIRRES *director;
304    STORES *store;
305    foreach_res(store, R_STORAGE) { 
306       /* tls_require implies tls_enable */
307       if (store->tls_require) {
308          if (have_tls) {
309             store->tls_enable = true;
310          } else {
311             Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
312             OK = false;
313             continue;
314          }
315       }
316
317       if (!store->tls_certfile && store->tls_enable) {
318          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Storage \"%s\" in %s.\n"),
319               store->hdr.name, configfile);
320          OK = false;
321       }
322
323       if (!store->tls_keyfile && store->tls_enable) {
324          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Storage \"%s\" in %s.\n"),
325               store->hdr.name, configfile);
326          OK = false;
327       }
328
329       if ((!store->tls_ca_certfile && !store->tls_ca_certdir) && store->tls_enable && store->tls_verify_peer) {
330          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
331               " or \"TLS CA Certificate Dir\" are defined for Storage \"%s\" in %s."
332               " At least one CA certificate store is required"
333               " when using \"TLS Verify Peer\".\n"),
334               store->hdr.name, configfile);
335          OK = false;
336       }
337
338       /* If everything is well, attempt to initialize our per-resource TLS context */
339       if (OK && (store->tls_enable || store->tls_require)) {
340          /* Initialize TLS context:
341           * Args: CA certfile, CA certdir, Certfile, Keyfile,
342           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
343          store->tls_ctx = new_tls_context(store->tls_ca_certfile,
344             store->tls_ca_certdir, store->tls_certfile,
345             store->tls_keyfile, NULL, NULL, store->tls_dhfile,
346             store->tls_verify_peer);
347
348          if (!store->tls_ctx) { 
349             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Storage \"%s\" in %s.\n"),
350                  store->hdr.name, configfile);
351             OK = false;
352          }
353       }
354    }
355
356    foreach_res(director, R_DIRECTOR) { 
357       /* tls_require implies tls_enable */
358       if (director->tls_require) {
359          director->tls_enable = true;
360       }
361
362       if (!director->tls_certfile && director->tls_enable) {
363          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Director \"%s\" in %s.\n"),
364               director->hdr.name, configfile);
365          OK = false;
366       }
367
368       if (!director->tls_keyfile && director->tls_enable) {
369          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Director \"%s\" in %s.\n"),
370               director->hdr.name, configfile);
371          OK = false;
372       }
373
374       if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && director->tls_enable && director->tls_verify_peer) {
375          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
376               " or \"TLS CA Certificate Dir\" are defined for Director \"%s\" in %s."
377               " At least one CA certificate store is required"
378               " when using \"TLS Verify Peer\".\n"),
379               director->hdr.name, configfile);
380          OK = false;
381       }
382
383       /* If everything is well, attempt to initialize our per-resource TLS context */
384       if (OK && (director->tls_enable || director->tls_require)) {
385          /* Initialize TLS context:
386           * Args: CA certfile, CA certdir, Certfile, Keyfile,
387           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
388          director->tls_ctx = new_tls_context(director->tls_ca_certfile,
389             director->tls_ca_certdir, director->tls_certfile,
390             director->tls_keyfile, NULL, NULL, director->tls_dhfile,
391             director->tls_verify_peer);
392
393          if (!director->tls_ctx) { 
394             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Director \"%s\" in %s.\n"),
395                  director->hdr.name, configfile);
396             OK = false;
397          }
398       }
399    }
400
401    OK = init_autochangers();
402
403    
404    if (OK) {
405       close_msg(NULL);                   /* close temp message handler */
406       init_msg(NULL, me->messages);      /* open daemon message handler */
407       set_working_directory(me->working_directory);
408    }
409
410    return OK;
411 }
412
413 static void cleanup_old_files()
414 {
415    POOLMEM *cleanup = get_pool_memory(PM_MESSAGE);
416    int len = strlen(me->working_directory);
417    pm_strcpy(cleanup, "/bin/rm -f ");
418    pm_strcat(cleanup, me->working_directory);
419    if (len > 0 && me->working_directory[len-1] != '/') {
420       pm_strcat(cleanup, "/");
421    }
422    pm_strcat(cleanup, my_name);
423    pm_strcat(cleanup, "*.spool");
424    run_program(cleanup, 0, NULL);
425    free_pool_memory(cleanup);
426 }      
427
428
429 /*
430  * Here we attempt to init and open each device. This is done
431  *  once at startup in a separate thread.
432  */
433 extern "C"
434 void *device_initialization(void *arg)
435 {
436    DEVRES *device;
437    DCR *dcr;
438    JCR *jcr;
439    DEVICE *dev;
440
441    LockRes();
442
443    pthread_detach(pthread_self());
444    jcr = new_jcr(sizeof(JCR), stored_free_jcr);
445    jcr->JobType = JT_SYSTEM;
446    /* Initialize FD start condition variable */
447    int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
448    if (errstat != 0) {
449       Jmsg1(jcr, M_ABORT, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat));
450    }
451
452    foreach_res(device, R_DEVICE) {
453       Dmsg1(90, "calling init_dev %s\n", device->device_name);
454       device->dev = dev = init_dev(NULL, device);
455       Dmsg1(10, "SD init done %s\n", device->device_name);
456       if (!dev) {
457          Jmsg1(NULL, M_ERROR, 0, _("Could not initialize %s\n"), device->device_name);
458          continue;
459       }
460
461       jcr->dcr = dcr = new_dcr(jcr, dev);
462       if (dev->is_autochanger()) {
463          /* If autochanger set slot in dev sturcture */
464          get_autochanger_loaded_slot(dcr);
465       }
466
467       if (device->cap_bits & CAP_ALWAYSOPEN) {
468          Dmsg1(20, "calling first_open_device %s\n", dev->print_name());
469          if (!first_open_device(dcr)) {
470             Jmsg1(NULL, M_ERROR, 0, _("Could not open device %s\n"), dev->print_name());
471             Dmsg1(20, "Could not open device %s\n", dev->print_name());
472             free_dcr(dcr);
473             jcr->dcr = NULL;
474             continue;
475          }
476       }
477       if (device->cap_bits & CAP_AUTOMOUNT && dev->is_open()) {
478          switch (read_dev_volume_label(dcr)) {
479          case VOL_OK:
480             memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
481             break;
482          default:
483             Jmsg1(NULL, M_WARNING, 0, _("Could not mount device %s\n"), dev->print_name());
484             break;
485          }
486       }
487       free_dcr(dcr);
488       jcr->dcr = NULL;
489    }
490    free_jcr(jcr); 
491    init_done = true;
492    UnlockRes();
493    return NULL;
494 }
495
496
497 /* Clean up and then exit */
498 void terminate_stored(int sig)
499 {
500    static bool in_here = false;
501    DEVRES *device;
502    JCR *jcr;
503
504    if (in_here) {                     /* prevent loops */
505       exit(1);
506    }
507    in_here = true;
508
509    if (sig == SIGTERM) {              /* normal shutdown request? */
510       /*
511        * This is a normal shutdown request. We wiffle through
512        *   all open jobs canceling them and trying to wake
513        *   them up so that they will report back the correct
514        *   volume status.
515        */
516       foreach_jcr(jcr) {
517          BSOCK *fd;
518          if (jcr->JobId == 0) {
519             free_jcr(jcr);
520             continue;                 /* ignore console */
521          }
522          set_jcr_job_status(jcr, JS_Canceled);
523          fd = jcr->file_bsock;
524          if (fd) {
525             fd->timed_out = true;
526             Dmsg1(100, "term_stored killing JobId=%d\n", jcr->JobId);
527             pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
528             /* ***FIXME*** wiffle through all dcrs */
529             if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->dev_blocked) {
530                pthread_cond_broadcast(&jcr->dcr->dev->wait_next_vol);
531                pthread_cond_broadcast(&wait_device_release);
532             }
533             if (jcr->read_dcr && jcr->read_dcr->dev && jcr->read_dcr->dev->dev_blocked) {
534                pthread_cond_broadcast(&jcr->read_dcr->dev->wait_next_vol);
535                pthread_cond_broadcast(&wait_device_release);
536             }
537             bmicrosleep(0, 50000);
538          }
539          free_jcr(jcr);
540       }
541       bmicrosleep(0, 500000);         /* give them 1/2 sec to clean up */
542    }
543
544    write_state_file(me->working_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
545    delete_pid_file(me->pid_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
546
547    Dmsg1(200, "In terminate_stored() sig=%d\n", sig);
548
549    foreach_res(device, R_DEVICE) {
550       Dmsg1(10, "Term device %s\n", device->device_name);
551       if (device->dev) {
552          free_volume(device->dev);
553          term_dev(device->dev);
554       } else {
555          Dmsg1(10, "No dev structure %s\n", device->device_name);
556       }
557    }
558
559    if (configfile) {
560       free(configfile);
561       configfile = NULL;
562    }
563    free_config_resources();
564
565    if (debug_level > 10) {
566       print_memory_pool_stats();
567    }
568    term_reservations_lock();
569    term_msg();
570    stop_watchdog();
571    cleanup_crypto();
572    free_volume_list();
573    close_memory_pool();
574
575    sm_dump(false);                    /* dump orphaned buffers */
576    exit(sig);
577 }