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