]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/restore.c
Fix #4996 about MaxRunTime canceling the job too early
[bacula/bacula] / bacula / src / dird / restore.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2011 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 three of the GNU Affero 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 Affero 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       jcr->setJobStatus(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 fail 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_WARNING, 0,
185            _("Could not get storage resource '%s'.\n"), new_one);
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
270    if (!strcmp(jcr->rstore->name(), info.storage)) {
271       return true;                 /* same SD nothing to change */
272    }
273
274    if (!(ustore.store = (STORE *)GetResWithName(R_STORAGE,info.storage))) {
275       Jmsg(jcr, M_FATAL, 0,
276            _("Could not get storage resource '%s'.\n"), info.storage);
277       jcr->setJobStatus(JS_ErrorTerminated);
278       return false;
279    }
280    
281    /*
282     * What does this do???????????  KES
283     */
284    if (jcr->store_bsock) {
285       jcr->store_bsock->destroy();
286       jcr->store_bsock = NULL;
287    }
288    
289    /*
290     * release current read storage and get a new one 
291     */
292    dec_read_store(jcr);
293    free_rstorage(jcr);
294    set_rstorage(jcr, &ustore);
295    jcr->setJobStatus(JS_WaitSD);
296    /*
297     * Wait for up to 6 hours to increment read stoage counter 
298     */
299    for (i=0; i < MAX_TRIES; i++) {
300       /* try to get read storage counter incremented */
301       if (inc_read_store(jcr)) {
302          jcr->setJobStatus(JS_Running);
303          return true;
304       }
305       bmicrosleep(10, 0);       /* sleep 10 secs */
306       if (job_canceled(jcr)) {
307          free_rstorage(jcr);
308          return false;
309       }
310    }
311    /* Failed to inc_read_store() */
312    free_rstorage(jcr);
313    Jmsg(jcr, M_FATAL, 0, 
314       _("Could not acquire read storage lock for \"%s\""), info.storage);
315    return false;
316 }
317
318 /* 
319  * Clean the bootstrap_info struct
320  */
321 static void close_bootstrap_file(bootstrap_info &info)
322 {
323    if (info.bs) {
324       fclose(info.bs);
325    }
326    if (info.ua) {
327       free_ua_context(info.ua);
328    }
329 }
330
331 /**
332  * The bootstrap is stored in a file, so open the file, and loop
333  *   through it processing each storage device in turn. If the
334  *   storage is different from the prior one, we open a new connection
335  *   to the new storage and do a restore for that part.
336  * This permits handling multiple storage daemons for a single
337  *   restore.  E.g. your Full is stored on tape, and Incrementals
338  *   on disk.
339  */
340 bool restore_bootstrap(JCR *jcr)
341 {
342    BSOCK *fd = NULL;
343    BSOCK *sd;
344    bool first_time = true;
345    bootstrap_info info;
346    POOL_MEM restore_cmd(PM_MESSAGE);
347    bool ret = false;
348
349    /* this command is used for each part */
350    build_restore_command(jcr, restore_cmd);
351    
352    /* Open the bootstrap file */
353    if (!open_bootstrap_file(jcr, info)) {
354       goto bail_out;
355    }
356    /* Read the bootstrap file */
357    while (!feof(info.bs)) {
358       
359       if (!select_rstore(jcr, info)) {
360          goto bail_out;
361       }
362
363       /**
364        * Open a message channel connection with the Storage
365        * daemon. This is to let him know that our client
366        * will be contacting him for a backup  session.
367        *
368        */
369       Dmsg0(10, "Open connection with storage daemon\n");
370       jcr->setJobStatus(JS_WaitSD);
371       /*
372        * Start conversation with Storage daemon
373        */
374       if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
375          goto bail_out;
376       }
377       sd = jcr->store_bsock;
378       /*
379        * Now start a job with the Storage daemon
380        */
381       if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
382          goto bail_out;
383       }
384
385       if (first_time) {
386          /*
387           * Start conversation with File daemon
388           */
389          jcr->setJobStatus(JS_WaitFD);
390          jcr->keep_sd_auth_key = true; /* don't clear the sd_auth_key now */
391          if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
392             goto bail_out;
393          }
394          fd = jcr->file_bsock;
395       }
396
397       jcr->setJobStatus(JS_Running);
398
399       /*
400        * Send the bootstrap file -- what Volumes/files to restore
401        */
402       if (!send_bootstrap_file(jcr, sd, info) ||
403           !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
404          goto bail_out;
405       }
406
407       if (!sd->fsend("run")) {
408          goto bail_out;
409       }
410       /*
411        * Now start a Storage daemon message thread
412        */
413       if (!start_storage_daemon_message_thread(jcr)) {
414          goto bail_out;
415       }
416       Dmsg0(50, "Storage daemon connection OK\n");
417
418       /*
419        * send Storage daemon address to the File daemon,
420        *   then wait for File daemon to make connection
421        *   with Storage daemon.
422        */
423       if (jcr->rstore->SDDport == 0) {
424          jcr->rstore->SDDport = jcr->rstore->SDport;
425       }
426       fd->fsend(storaddr, jcr->rstore->address, jcr->rstore->SDDport,
427                 jcr->sd_auth_key);
428       memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
429
430       Dmsg1(6, "dird>filed: %s\n", fd->msg);
431       if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
432          goto bail_out;
433       }
434
435       /* Declare the job started to start the MaxRunTime check */
436       jcr->setJobStarted();
437
438       /* Only pass "global" commands to the FD once */
439       if (first_time) {
440          first_time = false;
441          if (!send_runscripts_commands(jcr)) {
442             goto bail_out;
443          }
444          if (!send_restore_objects(jcr)) {
445             Dmsg0(000, "FAIL: Send restore objects\n");
446             goto bail_out;
447          }
448       }
449
450       fd->fsend("%s", restore_cmd.c_str());
451
452       if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
453          goto bail_out;
454       }
455
456       if (jcr->FDVersion < 2) { /* Old FD */
457          break;                 /* we do only one loop */
458       } else {
459          if (!response(jcr, fd, OKstoreend, "Store end", DISPLAY_ERROR)) {
460             goto bail_out;
461          }
462          wait_for_storage_daemon_termination(jcr);
463       }
464    } /* the whole boostrap has been send */
465
466    if (fd && jcr->FDVersion >= 2) {
467       fd->fsend("endrestore");
468    }
469
470    ret = true;
471
472 bail_out:
473    close_bootstrap_file(info);
474    return ret;
475 }
476
477 /**
478  * Do a restore of the specified files
479  *
480  *  Returns:  0 on failure
481  *            1 on success
482  */
483 bool do_restore(JCR *jcr)
484 {
485    JOB_DBR rjr;                       /* restore job record */
486    int stat;
487
488    free_wstorage(jcr);                /* we don't write */
489
490    if (!allow_duplicate_job(jcr)) {
491       goto bail_out;
492    }
493
494    memset(&rjr, 0, sizeof(rjr));
495    jcr->jr.JobLevel = L_FULL;         /* Full restore */
496    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
497       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
498       goto bail_out;
499    }
500    Dmsg0(20, "Updated job start record\n");
501
502    Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
503
504    if (!jcr->RestoreBootstrap) {
505       Jmsg(jcr, M_FATAL, 0, _("Cannot restore without a bootstrap file.\n"
506           "You probably ran a restore job directly. All restore jobs must\n"
507           "be run using the restore command.\n"));
508       goto bail_out;
509    }
510
511
512    /* Print Job Start message */
513    Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
514
515    /* Read the bootstrap file and do the restore */
516    if (!restore_bootstrap(jcr)) {
517       goto bail_out;
518    }
519
520    /* Wait for Job Termination */
521    stat = wait_for_job_termination(jcr);
522    restore_cleanup(jcr, stat);
523    return true;
524
525 bail_out:
526    restore_cleanup(jcr, JS_ErrorTerminated);
527    return false;
528 }
529
530 bool do_restore_init(JCR *jcr) 
531 {
532    free_wstorage(jcr);
533    return true;
534 }
535
536 /**
537  * Release resources allocated during restore.
538  *
539  */
540 void restore_cleanup(JCR *jcr, int TermCode)
541 {
542    char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
543    char ec1[30], ec2[30], ec3[30];
544    char term_code[100], fd_term_msg[100], sd_term_msg[100];
545    const char *term_msg;
546    int msg_type = M_INFO;
547    double kbps;
548
549    Dmsg0(20, "In restore_cleanup\n");
550    update_job_end(jcr, TermCode);
551
552    if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
553       unlink(jcr->RestoreBootstrap);
554       jcr->unlink_bsr = false;
555    }
556
557    if (job_canceled(jcr)) {
558       cancel_storage_daemon_job(jcr);
559    }  
560
561    switch (TermCode) {
562    case JS_Terminated:
563       if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
564          term_msg = _("Restore OK -- warning file count mismatch");
565       } else {
566          term_msg = _("Restore OK");
567       }
568       break;
569    case JS_Warnings:
570          term_msg = _("Restore OK -- with warnings");
571          break;
572    case JS_FatalError:
573    case JS_ErrorTerminated:
574       term_msg = _("*** Restore Error ***");
575       msg_type = M_ERROR;          /* Generate error message */
576       if (jcr->store_bsock) {
577          jcr->store_bsock->signal(BNET_TERMINATE);
578          if (jcr->SD_msg_chan) {
579             pthread_cancel(jcr->SD_msg_chan);
580          }
581       }
582       break;
583    case JS_Canceled:
584       term_msg = _("Restore Canceled");
585       if (jcr->store_bsock) {
586          jcr->store_bsock->signal(BNET_TERMINATE);
587          if (jcr->SD_msg_chan) {
588             pthread_cancel(jcr->SD_msg_chan);
589          }
590       }
591       break;
592    default:
593       term_msg = term_code;
594       sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
595       break;
596    }
597    bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
598    bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
599    if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
600       kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
601    } else {
602       kbps = 0;
603    }
604    if (kbps < 0.05) {
605       kbps = 0;
606    }
607
608    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
609    jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
610
611    Jmsg(jcr, msg_type, 0, _("%s %s %s (%s):\n"
612 "  Build OS:               %s %s %s\n"
613 "  JobId:                  %d\n"
614 "  Job:                    %s\n"
615 "  Restore Client:         %s\n"
616 "  Start time:             %s\n"
617 "  End time:               %s\n"
618 "  Files Expected:         %s\n"
619 "  Files Restored:         %s\n"
620 "  Bytes Restored:         %s\n"
621 "  Rate:                   %.1f KB/s\n"
622 "  FD Errors:              %d\n"
623 "  FD termination status:  %s\n"
624 "  SD termination status:  %s\n"
625 "  Termination:            %s\n\n"),
626         BACULA, my_name, VERSION, LSMDATE,
627         HOST_OS, DISTNAME, DISTVER,
628         jcr->jr.JobId,
629         jcr->jr.Job,
630         jcr->client->name(),
631         sdt,
632         edt,
633         edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
634         edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
635         edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
636         (float)kbps,
637         jcr->JobErrors,
638         fd_term_msg,
639         sd_term_msg,
640         term_msg);
641
642    Dmsg0(20, "Leaving restore_cleanup\n");
643 }