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