]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/restore.c
Fix bug #1582 Restore from multiple storage daemons breaks subsequent backups
[bacula/bacula] / bacula / src / dird / restore.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
5
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 and included
11    in the file LICENSE.
12
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.
17
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
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
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.
27 */
28 /**
29  *   Bacula Director -- restore.c -- responsible for restoring files
30  *
31  *     Kern Sibbald, November MM
32  *
33  *    This routine is run as a separate thread.
34  *
35  * Current implementation is Catalog verification only (i.e. no
36  *  verification versus tape).
37  *
38  *  Basic tasks done here:
39  *     Open DB
40  *     Open Message Channel with Storage daemon to tell him a job will be starting.
41  *     Open connection with File daemon and pass him commands
42  *       to do the restore.
43  *     Update the DB according to what files where restored????
44  *
45  */
46
47
48 #include "bacula.h"
49 #include "dird.h"
50
51 /* Commands sent to File daemon */
52 static char restorecmd[]  = "restore replace=%c prelinks=%d where=%s\n";
53 static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=%s\n";
54 static char storaddr[]    = "storage address=%s port=%d ssl=0 Authorization=%s\n";
55
56 /* Responses received from File daemon */
57 static char OKrestore[]   = "2000 OK restore\n";
58 static char OKstore[]     = "2000 OK storage\n";
59 static char OKstoreend[]  = "2000 OK storage end\n";
60
61 /* Responses received from the Storage daemon */
62 static char OKbootstrap[] = "3000 OK bootstrap\n";
63
64 static void build_restore_command(JCR *jcr, POOL_MEM &ret)
65 {
66    char replace, *where, *cmd;
67    char empty = '\0';
68
69    /* Build the restore command */
70
71    if (jcr->replace != 0) {
72       replace = jcr->replace;
73    } else if (jcr->job->replace != 0) {
74       replace = jcr->job->replace;
75    } else {
76       replace = REPLACE_ALWAYS;       /* always replace */
77    }
78    
79    if (jcr->RegexWhere) {
80       where = jcr->RegexWhere;             /* override */
81       cmd = restorecmdR;
82    } else if (jcr->job->RegexWhere) {
83       where = jcr->job->RegexWhere;   /* no override take from job */
84       cmd = restorecmdR;
85
86    } else if (jcr->where) {
87       where = jcr->where;             /* override */
88       cmd = restorecmd;
89    } else if (jcr->job->RestoreWhere) {
90       where = jcr->job->RestoreWhere; /* no override take from job */
91       cmd = restorecmd;
92
93    } else {                           /* nothing was specified */
94       where = ∅                 /* use default */
95       cmd   = restorecmd;                    
96    }
97    
98    jcr->prefix_links = jcr->job->PrefixLinks;
99
100    bash_spaces(where);
101    Mmsg(ret, cmd, replace, jcr->prefix_links, where);
102    unbash_spaces(where);
103 }
104
105 struct bootstrap_info
106 {
107    FILE *bs;
108    UAContext *ua;
109    char storage[MAX_NAME_LENGTH+1];
110 };
111
112 #define UA_CMD_SIZE 1000
113
114 /**
115  * Open the bootstrap file and find the first Storage=
116  * Returns ok if able to open
117  * It fills the storage name (should be the first line) 
118  * and the file descriptor to the bootstrap file, 
119  * it should be used for next operations, and need to be closed
120  * at the end.
121  */
122 static bool open_bootstrap_file(JCR *jcr, bootstrap_info &info)
123 {
124    FILE *bs;
125    UAContext *ua;
126    info.bs = NULL;
127    info.ua = NULL;
128
129    if (!jcr->RestoreBootstrap) {
130       return false;
131    }
132    strncpy(info.storage, jcr->rstore->name(), MAX_NAME_LENGTH);
133
134    bs = fopen(jcr->RestoreBootstrap, "rb");
135    if (!bs) {
136       berrno be;
137       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
138          jcr->RestoreBootstrap, be.bstrerror());
139       set_jcr_job_status(jcr, JS_ErrorTerminated);
140       return false;
141    }
142
143    ua = new_ua_context(jcr);
144    ua->cmd = check_pool_memory_size(ua->cmd, UA_CMD_SIZE+1);
145    while (!fgets(ua->cmd, UA_CMD_SIZE, bs)) {
146       parse_ua_args(ua);
147       if (ua->argc != 1) {
148          continue;
149       }
150       if (!strcasecmp(ua->argk[0], "Storage")) {
151          strncpy(info.storage, ua->argv[0], MAX_NAME_LENGTH);
152          break;
153       }
154    }
155    info.bs = bs;
156    info.ua = ua;
157    fseek(bs, 0, SEEK_SET);      /* return to the top of the file */
158    return true;
159 }
160
161 /**
162  * This function compare the given storage name with the
163  * the current one. We compare the name and the address:port.
164  * Returns true if we use the same storage.
165  */
166 static bool is_on_same_storage(JCR *jcr, char *new_one)
167 {
168    STORE *new_store;
169
170    /* with old FD, we send the whole bootstrap to the storage */
171    if (jcr->FDVersion < 2) {
172       return true;
173    }
174    /* we are in init loop ? shoudn't fall here */
175    if (!*new_one) {
176       return true;
177    }
178    /* same name */
179    if (!strcmp(new_one, jcr->rstore->name())) {
180       return true;
181    }
182    new_store = (STORE *)GetResWithName(R_STORAGE, new_one);
183    if (!new_store) {
184       Jmsg(jcr, M_FATAL, 0,
185            _("Could not get storage resource '%s'.\n"), new_one);
186       set_jcr_job_status(jcr, JS_ErrorTerminated);
187       return false;
188    }
189    /* if Port and Hostname/IP are same, we are talking to the same
190     * Storage Daemon
191     */
192    if (jcr->rstore->SDport != new_store->SDport ||
193        strcmp(jcr->rstore->address, new_store->address))
194    {
195       return false;
196    }
197    return true;
198 }
199
200 /**
201  * Check if the current line contains Storage="xxx", and compare the
202  * result to the current storage. We use UAContext to analyse the bsr 
203  * string.
204  *
205  * Returns true if we need to change the storage, and it set the new
206  * Storage resource name in "storage" arg. 
207  */
208 static bool check_for_new_storage(JCR *jcr, bootstrap_info &info)
209 {
210    UAContext *ua = info.ua;
211    parse_ua_args(ua);
212    if (ua->argc != 1) {
213       return false;
214    }
215    if (!strcasecmp(ua->argk[0], "Storage")) {
216       /* Continue if this is a volume from the same storage. */
217       if (is_on_same_storage(jcr, ua->argv[0])) {
218          return false;
219       }
220       /* note the next storage name */
221       strncpy(info.storage, ua->argv[0], MAX_NAME_LENGTH);
222       Dmsg1(5, "Change storage to %s\n", info.storage);
223       return true;
224    }
225    return false;
226 }
227
228 /**
229  * Send bootstrap file to Storage daemon section by section.
230  */
231 static bool send_bootstrap_file(JCR *jcr, BSOCK *sock,
232                                 bootstrap_info &info)
233 {
234    boffset_t pos;
235    const char *bootstrap = "bootstrap\n";
236    UAContext *ua = info.ua;
237    FILE *bs = info.bs;
238
239    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
240    if (!jcr->RestoreBootstrap) {
241       return false;
242    }
243    sock->fsend(bootstrap);
244    pos = ftello(bs);
245    while(fgets(ua->cmd, UA_CMD_SIZE, bs)) {
246       if (check_for_new_storage(jcr, info)) {
247          /* Otherwise, we need to contact another storage daemon.
248           * Reset bs to the beginning of the current segment. 
249           */
250          fseeko(bs, pos, SEEK_SET);
251          break;
252       }
253       sock->fsend("%s", ua->cmd);
254       pos = ftello(bs);
255    }
256    sock->signal(BNET_EOD);
257    return true;
258 }
259
260 #define MAX_TRIES 6 * 360   /* 6 hours */
261
262 /**
263  * Change the read storage resource for the current job.
264  */
265 static bool select_rstore(JCR *jcr, bootstrap_info &info)
266 {
267    USTORE ustore;
268    int i;
269
270
271    if (!strcmp(jcr->rstore->name(), info.storage)) {
272       return true;                 /* same SD nothing to change */
273    }
274
275    if (!(ustore.store = (STORE *)GetResWithName(R_STORAGE,info.storage))) {
276       Jmsg(jcr, M_FATAL, 0,
277            _("Could not get storage resource '%s'.\n"), info.storage);
278       set_jcr_job_status(jcr, JS_ErrorTerminated);
279       return false;
280    }
281    
282    /*
283     * What does this do???????????  KES
284     */
285    if (jcr->store_bsock) {
286       jcr->store_bsock->destroy();
287       jcr->store_bsock = NULL;
288    }
289    
290    /*
291     * release current read storage and get a new one 
292     */
293    dec_read_store(jcr);
294    free_rstorage(jcr);
295    set_rstorage(jcr, &ustore);
296    set_jcr_job_status(jcr, JS_WaitSD);
297    /*
298     * Wait for up to 6 hours to increment read stoage counter 
299     */
300    for (i=0; i < MAX_TRIES; i++) {
301       /* try to get read storage counter incremented */
302       if (inc_read_store(jcr)) {
303          set_jcr_job_status(jcr, JS_Running);
304          return true;
305       }
306       bmicrosleep(10, 0);       /* sleep 10 secs */
307       if (job_canceled(jcr)) {
308          free_rstorage(jcr);
309          return false;
310       }
311    }
312    /* Failed to inc_read_store() */
313    free_rstorage(jcr);
314    Jmsg(jcr, M_FATAL, 0, 
315       _("Could not acquire read storage lock for \"%s\""), info.storage);
316    return false;
317 }
318
319 /* 
320  * Clean the bootstrap_info struct
321  */
322 static void close_bootstrap_file(bootstrap_info &info)
323 {
324    if (info.bs) {
325       fclose(info.bs);
326    }
327    if (info.ua) {
328       free_ua_context(info.ua);
329    }
330 }
331
332 /**
333  * The bootstrap is stored in a file, so open the file, and loop
334  *   through it processing each storage device in turn. If the
335  *   storage is different from the prior one, we open a new connection
336  *   to the new storage and do a restore for that part.
337  * This permits handling multiple storage daemons for a single
338  *   restore.  E.g. your Full is stored on tape, and Incrementals
339  *   on disk.
340  */
341 bool restore_bootstrap(JCR *jcr)
342 {
343    BSOCK *fd = NULL;
344    BSOCK *sd;
345    bool first_time = true;
346    bootstrap_info info;
347    POOL_MEM restore_cmd(PM_MESSAGE);
348    bool ret = false;
349
350    /* this command is used for each part */
351    build_restore_command(jcr, restore_cmd);
352    
353    /* Open the bootstrap file */
354    if (!open_bootstrap_file(jcr, info)) {
355       goto bail_out;
356    }
357    /* Read the bootstrap file */
358    while (!feof(info.bs)) {
359       
360       if (!select_rstore(jcr, info)) {
361          goto bail_out;
362       }
363
364       /**
365        * Open a message channel connection with the Storage
366        * daemon. This is to let him know that our client
367        * will be contacting him for a backup  session.
368        *
369        */
370       Dmsg0(10, "Open connection with storage daemon\n");
371       set_jcr_job_status(jcr, JS_WaitSD);
372       /*
373        * Start conversation with Storage daemon
374        */
375       if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
376          goto bail_out;
377       }
378       sd = jcr->store_bsock;
379       /*
380        * Now start a job with the Storage daemon
381        */
382       if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
383          goto bail_out;
384       }
385
386       if (first_time) {
387          /*
388           * Start conversation with File daemon
389           */
390          set_jcr_job_status(jcr, JS_WaitFD);
391          jcr->keep_sd_auth_key = true; /* don't clear the sd_auth_key now */
392          if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
393             goto bail_out;
394          }
395          fd = jcr->file_bsock;
396       }
397
398       set_jcr_job_status(jcr, JS_WaitSD);
399
400       /*
401        * Send the bootstrap file -- what Volumes/files to restore
402        */
403       if (!send_bootstrap_file(jcr, sd, info) ||
404           !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
405          goto bail_out;
406       }
407
408       if (!sd->fsend("run")) {
409          goto bail_out;
410       }
411       /*
412        * Now start a Storage daemon message thread
413        */
414       if (!start_storage_daemon_message_thread(jcr)) {
415          goto bail_out;
416       }
417       Dmsg0(50, "Storage daemon connection OK\n");
418
419       /*
420        * send Storage daemon address to the File daemon,
421        *   then wait for File daemon to make connection
422        *   with Storage daemon.
423        */
424       if (jcr->rstore->SDDport == 0) {
425          jcr->rstore->SDDport = jcr->rstore->SDport;
426       }
427       fd->fsend(storaddr, jcr->rstore->address, jcr->rstore->SDDport,
428                 jcr->sd_auth_key);
429       memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
430
431       Dmsg1(6, "dird>filed: %s\n", fd->msg);
432       if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
433          goto bail_out;
434       }
435
436       /* Only pass "global" commands to the FD once */
437       if (first_time) {
438          first_time = false;
439          if (!send_runscripts_commands(jcr)) {
440             goto bail_out;
441          }
442          if (!send_restore_objects(jcr)) {
443             Dmsg0(000, "FAIL: Send restore objects\n");
444             goto bail_out;
445          }
446       }
447
448       fd->fsend("%s", restore_cmd.c_str());
449
450       if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
451          goto bail_out;
452       }
453
454       if (jcr->FDVersion < 2) { /* Old FD */
455          break;                 /* we do only one loop */
456       } else {
457          if (!response(jcr, fd, OKstoreend, "Store end", DISPLAY_ERROR)) {
458             goto bail_out;
459          }
460          wait_for_storage_daemon_termination(jcr);
461       }
462    } /* the whole boostrap has been send */
463
464    if (fd && jcr->FDVersion >= 2) {
465       fd->fsend("endrestore");
466    }
467
468    ret = true;
469
470 bail_out:
471    close_bootstrap_file(info);
472    return ret;
473 }
474
475 /**
476  * Do a restore of the specified files
477  *
478  *  Returns:  0 on failure
479  *            1 on success
480  */
481 bool do_restore(JCR *jcr)
482 {
483    JOB_DBR rjr;                       /* restore job record */
484    int stat;
485
486    free_wstorage(jcr);                /* we don't write */
487
488    if (!allow_duplicate_job(jcr)) {
489       goto bail_out;
490    }
491
492    memset(&rjr, 0, sizeof(rjr));
493    jcr->jr.JobLevel = L_FULL;         /* Full restore */
494    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
495       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
496       goto bail_out;
497    }
498    Dmsg0(20, "Updated job start record\n");
499
500    Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
501
502    if (!jcr->RestoreBootstrap) {
503       Jmsg(jcr, M_FATAL, 0, _("Cannot restore without a bootstrap file.\n"
504           "You probably ran a restore job directly. All restore jobs must\n"
505           "be run using the restore command.\n"));
506       goto bail_out;
507    }
508
509
510    /* Print Job Start message */
511    Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
512
513    /* Read the bootstrap file and do the restore */
514    if (!restore_bootstrap(jcr)) {
515       goto bail_out;
516    }
517
518    /* Wait for Job Termination */
519    stat = wait_for_job_termination(jcr);
520    restore_cleanup(jcr, stat);
521    return true;
522
523 bail_out:
524    restore_cleanup(jcr, JS_ErrorTerminated);
525    return false;
526 }
527
528 bool do_restore_init(JCR *jcr) 
529 {
530    free_wstorage(jcr);
531    return true;
532 }
533
534 /**
535  * Release resources allocated during restore.
536  *
537  */
538 void restore_cleanup(JCR *jcr, int TermCode)
539 {
540    char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
541    char ec1[30], ec2[30], ec3[30];
542    char term_code[100], fd_term_msg[100], sd_term_msg[100];
543    const char *term_msg;
544    int msg_type = M_INFO;
545    double kbps;
546
547    Dmsg0(20, "In restore_cleanup\n");
548    update_job_end(jcr, TermCode);
549
550    if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
551       unlink(jcr->RestoreBootstrap);
552       jcr->unlink_bsr = false;
553    }
554
555    if (job_canceled(jcr)) {
556       cancel_storage_daemon_job(jcr);
557    }  
558
559    switch (TermCode) {
560    case JS_Terminated:
561       if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
562          term_msg = _("Restore OK -- warning file count mismatch");
563       } else {
564          term_msg = _("Restore OK");
565       }
566       break;
567    case JS_Warnings:
568          term_msg = _("Restore OK -- with warnings");
569          break;
570    case JS_FatalError:
571    case JS_ErrorTerminated:
572       term_msg = _("*** Restore Error ***");
573       msg_type = M_ERROR;          /* Generate error message */
574       if (jcr->store_bsock) {
575          jcr->store_bsock->signal(BNET_TERMINATE);
576          if (jcr->SD_msg_chan) {
577             pthread_cancel(jcr->SD_msg_chan);
578          }
579       }
580       break;
581    case JS_Canceled:
582       term_msg = _("Restore Canceled");
583       if (jcr->store_bsock) {
584          jcr->store_bsock->signal(BNET_TERMINATE);
585          if (jcr->SD_msg_chan) {
586             pthread_cancel(jcr->SD_msg_chan);
587          }
588       }
589       break;
590    default:
591       term_msg = term_code;
592       sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
593       break;
594    }
595    bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
596    bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
597    if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
598       kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
599    } else {
600       kbps = 0;
601    }
602    if (kbps < 0.05) {
603       kbps = 0;
604    }
605
606    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
607    jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
608
609    Jmsg(jcr, msg_type, 0, _("%s %s %s (%s): %s\n"
610 "  Build OS:               %s %s %s\n"
611 "  JobId:                  %d\n"
612 "  Job:                    %s\n"
613 "  Restore Client:         %s\n"
614 "  Start time:             %s\n"
615 "  End time:               %s\n"
616 "  Files Expected:         %s\n"
617 "  Files Restored:         %s\n"
618 "  Bytes Restored:         %s\n"
619 "  Rate:                   %.1f KB/s\n"
620 "  FD Errors:              %d\n"
621 "  FD termination status:  %s\n"
622 "  SD termination status:  %s\n"
623 "  Termination:            %s\n\n"),
624         BACULA, my_name, VERSION, LSMDATE, edt,
625         HOST_OS, DISTNAME, DISTVER,
626         jcr->jr.JobId,
627         jcr->jr.Job,
628         jcr->client->name(),
629         sdt,
630         edt,
631         edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
632         edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
633         edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
634         (float)kbps,
635         jcr->JobErrors,
636         fd_term_msg,
637         sd_term_msg,
638         term_msg);
639
640    Dmsg0(20, "Leaving restore_cleanup\n");
641 }