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