]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/restore.c
Merge branch 'master' into basejobv3
[bacula/bacula] / bacula / src / dird / restore.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2009 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  *   Version $Id$
46  */
47
48
49 #include "bacula.h"
50 #include "dird.h"
51
52 /* Commands sent to File daemon */
53 static char restorecmd[]  = "restore replace=%c prelinks=%d where=%s\n";
54 static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=%s\n";
55 static char storaddr[]    = "storage address=%s port=%d ssl=0 Authorization=%s\n";
56
57 /* Responses received from File daemon */
58 static char OKrestore[]   = "2000 OK restore\n";
59 static char OKstore[]     = "2000 OK storage\n";
60 static char OKstoreend[]  = "2000 OK storage end\n";
61
62 /* Responses received from the Storage daemon */
63 static char OKbootstrap[] = "3000 OK bootstrap\n";
64
65 static void build_restore_command(JCR *jcr, POOL_MEM &ret)
66 {
67    char replace, *where, *cmd;
68    char empty = '\0';
69
70    /* Build the restore command */
71
72    if (jcr->replace != 0) {
73       replace = jcr->replace;
74    } else if (jcr->job->replace != 0) {
75       replace = jcr->job->replace;
76    } else {
77       replace = REPLACE_ALWAYS;       /* always replace */
78    }
79    
80    if (jcr->RegexWhere) {
81       where = jcr->RegexWhere;             /* override */
82       cmd = restorecmdR;
83    } else if (jcr->job->RegexWhere) {
84       where = jcr->job->RegexWhere;   /* no override take from job */
85       cmd = restorecmdR;
86
87    } else if (jcr->where) {
88       where = jcr->where;             /* override */
89       cmd = restorecmd;
90    } else if (jcr->job->RestoreWhere) {
91       where = jcr->job->RestoreWhere; /* no override take from job */
92       cmd = restorecmd;
93
94    } else {                           /* nothing was specified */
95       where = ∅                 /* use default */
96       cmd   = restorecmd;                    
97    }
98    
99    jcr->prefix_links = jcr->job->PrefixLinks;
100
101    bash_spaces(where);
102    Mmsg(ret, cmd, replace, jcr->prefix_links, where);
103    unbash_spaces(where);
104 }
105
106 struct bootstrap_info
107 {
108    FILE *bs;
109    UAContext *ua;
110    char storage[MAX_NAME_LENGTH+1];
111 };
112
113 #define UA_CMD_SIZE 1000
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, struct 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, struct 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                                 struct 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 /* 
261  * Change the read storage resource for the current job.
262  */
263 static void select_rstore(JCR *jcr, struct bootstrap_info &info)
264 {
265    USTORE ustore;
266    if (!strcmp(jcr->rstore->name(), info.storage)) {
267       return;
268    }
269
270    if (!(ustore.store = (STORE *)GetResWithName(R_STORAGE,info.storage))) {
271       Jmsg(jcr, M_FATAL, 0,
272            _("Could not get storage resource '%s'.\n"), info.storage);
273       set_jcr_job_status(jcr, JS_ErrorTerminated);
274       return;
275    }
276    
277    if (jcr->store_bsock) {
278       jcr->store_bsock->destroy();
279       jcr->store_bsock = NULL;
280    }
281    
282    free_rstorage(jcr);
283    set_rstorage(jcr, &ustore);
284 }
285
286 /* 
287  * Clean the struct bootstrap_info struct
288  */
289 static void close_bootstrap_file(struct bootstrap_info &info)
290 {
291    if (info.bs) {
292       fclose(info.bs);
293    }
294    if (info.ua) {
295       free_ua_context(info.ua);
296    }
297 }
298
299 /* 
300  * Take a bootstrap and for each different storage, we change the storage
301  * resource and start a new restore session between the client and the storage
302  *
303  */
304 bool restore_bootstrap(JCR *jcr)
305 {
306    BSOCK *fd=NULL, *sd;
307    bool end_loop=false;
308    bool first_time=true;
309    struct bootstrap_info info;
310    POOL_MEM restore_cmd(PM_MESSAGE);
311    bool ret=false;
312
313    /* this command is used for each part */
314    build_restore_command(jcr, restore_cmd);
315    
316    if (!open_bootstrap_file(jcr, info)) {
317       goto bail_out;
318    }
319    while (!end_loop && !feof(info.bs)) {
320       
321       select_rstore(jcr, info);
322
323       /*
324        * Open a message channel connection with the Storage
325        * daemon. This is to let him know that our client
326        * will be contacting him for a backup  session.
327        *
328        */
329       Dmsg0(10, "Open connection with storage daemon\n");
330       set_jcr_job_status(jcr, JS_WaitSD);
331       /*
332        * Start conversation with Storage daemon
333        */
334       if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
335          goto bail_out;
336       }
337       sd = jcr->store_bsock;
338       /*
339        * Now start a job with the Storage daemon
340        */
341       if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
342          goto bail_out;
343       }
344
345       if (first_time) {
346          /*
347           * Start conversation with File daemon
348           */
349          set_jcr_job_status(jcr, JS_WaitFD);
350          jcr->keep_sd_auth_key = true; /* don't clear the sd_auth_key now */
351          if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
352             goto bail_out;
353          }
354
355          fd = jcr->file_bsock;
356       }
357
358       set_jcr_job_status(jcr, JS_WaitSD);
359
360       /*
361        * Send the bootstrap file -- what Volumes/files to restore
362        */
363       if (!send_bootstrap_file(jcr, sd, info) ||
364           !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
365          goto bail_out;
366       }
367
368       if (!sd->fsend("run")) {
369          goto bail_out;
370       }
371       /*
372        * Now start a Storage daemon message thread
373        */
374       if (!start_storage_daemon_message_thread(jcr)) {
375          goto bail_out;
376       }
377       Dmsg0(50, "Storage daemon connection OK\n");
378
379       /*
380        * send Storage daemon address to the File daemon,
381        *   then wait for File daemon to make connection
382        *   with Storage daemon.
383        */
384       if (jcr->rstore->SDDport == 0) {
385          jcr->rstore->SDDport = jcr->rstore->SDport;
386       }
387       fd->fsend(storaddr, jcr->rstore->address, jcr->rstore->SDDport,
388                 jcr->sd_auth_key);
389       memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
390
391       Dmsg1(6, "dird>filed: %s\n", fd->msg);
392       if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
393          goto bail_out;
394       }
395
396       if (first_time) {
397          if (!send_runscripts_commands(jcr)) {
398             goto bail_out;
399          }
400          first_time=false;
401       }
402
403       fd->fsend("%s", restore_cmd.c_str());
404
405       if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
406          goto bail_out;
407       }
408
409       if (jcr->FDVersion < 2) { /* Old FD */
410          end_loop=true;         /* we do only one loop */
411
412       } else {
413          if (!response(jcr, fd, OKstoreend, "Store end", DISPLAY_ERROR)) {
414             goto bail_out;
415          }
416          wait_for_storage_daemon_termination(jcr);
417       }
418    } /* the whole boostrap has been send */
419
420    if (fd && jcr->FDVersion >= 2) {
421       fd->fsend("endrestore");
422    }
423
424    ret = true;
425
426 bail_out:
427    close_bootstrap_file(info);
428    return ret;
429 }
430
431 /*
432  * Do a restore of the specified files
433  *
434  *  Returns:  0 on failure
435  *            1 on success
436  */
437 bool do_restore(JCR *jcr)
438 {
439    JOB_DBR rjr;                       /* restore job record */
440    int stat;
441
442    free_wstorage(jcr);                /* we don't write */
443
444    if (!allow_duplicate_job(jcr)) {
445       goto bail_out;
446    }
447
448    memset(&rjr, 0, sizeof(rjr));
449    jcr->jr.JobLevel = L_FULL;         /* Full restore */
450    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
451       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
452       goto bail_out;
453    }
454    Dmsg0(20, "Updated job start record\n");
455
456    Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
457
458    if (!jcr->RestoreBootstrap) {
459       Jmsg(jcr, M_FATAL, 0, _("Cannot restore without a bootstrap file.\n"
460           "You probably ran a restore job directly. All restore jobs must\n"
461           "be run using the restore command.\n"));
462       goto bail_out;
463    }
464
465
466    /* Print Job Start message */
467    Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
468
469    if (!restore_bootstrap(jcr)) {
470       goto bail_out;
471    }
472
473    /* Wait for Job Termination */
474    stat = wait_for_job_termination(jcr);
475    restore_cleanup(jcr, stat);
476    return true;
477
478 bail_out:
479    restore_cleanup(jcr, JS_ErrorTerminated);
480    return false;
481 }
482
483 bool do_restore_init(JCR *jcr) 
484 {
485    free_wstorage(jcr);
486    return true;
487 }
488
489 /*
490  * Release resources allocated during restore.
491  *
492  */
493 void restore_cleanup(JCR *jcr, int TermCode)
494 {
495    char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
496    char ec1[30], ec2[30], ec3[30];
497    char term_code[100], fd_term_msg[100], sd_term_msg[100];
498    const char *term_msg;
499    int msg_type = M_INFO;
500    double kbps;
501
502    Dmsg0(20, "In restore_cleanup\n");
503    update_job_end(jcr, TermCode);
504
505    if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
506       unlink(jcr->RestoreBootstrap);
507       jcr->unlink_bsr = false;
508    }
509
510    if (job_canceled(jcr)) {
511       cancel_storage_daemon_job(jcr);
512    }  
513
514    switch (TermCode) {
515    case JS_Terminated:
516       if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
517          term_msg = _("Restore OK -- warning file count mismatch");
518       } else {
519          term_msg = _("Restore OK");
520       }
521       break;
522    case JS_Warnings:
523          term_msg = _("Restore OK -- with warnings");
524          break;
525    case JS_FatalError:
526    case JS_ErrorTerminated:
527       term_msg = _("*** Restore Error ***");
528       msg_type = M_ERROR;          /* Generate error message */
529       if (jcr->store_bsock) {
530          jcr->store_bsock->signal(BNET_TERMINATE);
531          if (jcr->SD_msg_chan) {
532             pthread_cancel(jcr->SD_msg_chan);
533          }
534       }
535       break;
536    case JS_Canceled:
537       term_msg = _("Restore Canceled");
538       if (jcr->store_bsock) {
539          jcr->store_bsock->signal(BNET_TERMINATE);
540          if (jcr->SD_msg_chan) {
541             pthread_cancel(jcr->SD_msg_chan);
542          }
543       }
544       break;
545    default:
546       term_msg = term_code;
547       sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
548       break;
549    }
550    bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
551    bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
552    if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
553       kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
554    } else {
555       kbps = 0;
556    }
557    if (kbps < 0.05) {
558       kbps = 0;
559    }
560
561    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
562    jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
563
564    Jmsg(jcr, msg_type, 0, _("%s %s %s (%s): %s\n"
565 "  Build OS:               %s %s %s\n"
566 "  JobId:                  %d\n"
567 "  Job:                    %s\n"
568 "  Restore Client:         %s\n"
569 "  Start time:             %s\n"
570 "  End time:               %s\n"
571 "  Files Expected:         %s\n"
572 "  Files Restored:         %s\n"
573 "  Bytes Restored:         %s\n"
574 "  Rate:                   %.1f KB/s\n"
575 "  FD Errors:              %d\n"
576 "  FD termination status:  %s\n"
577 "  SD termination status:  %s\n"
578 "  Termination:            %s\n\n"),
579         BACULA, my_name, VERSION, LSMDATE, edt,
580         HOST_OS, DISTNAME, DISTVER,
581         jcr->jr.JobId,
582         jcr->jr.Job,
583         jcr->client->name(),
584         sdt,
585         edt,
586         edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
587         edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
588         edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
589         (float)kbps,
590         jcr->JobErrors,
591         fd_term_msg,
592         sd_term_msg,
593         term_msg);
594
595    Dmsg0(20, "Leaving restore_cleanup\n");
596 }