2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
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
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.
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
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.
29 * Bacula Director -- restore.c -- responsible for restoring files
31 * Kern Sibbald, November MM
33 * This routine is run as a separate thread.
35 * Current implementation is Catalog verification only (i.e. no
36 * verification versus tape).
38 * Basic tasks done here:
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
43 * Update the DB according to what files where restored????
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";
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";
61 /* Responses received from the Storage daemon */
62 static char OKbootstrap[] = "3000 OK bootstrap\n";
64 static void build_restore_command(JCR *jcr, POOL_MEM &ret)
66 char replace, *where, *cmd;
69 /* Build the restore command */
71 if (jcr->replace != 0) {
72 replace = jcr->replace;
73 } else if (jcr->job->replace != 0) {
74 replace = jcr->job->replace;
76 replace = REPLACE_ALWAYS; /* always replace */
79 if (jcr->RegexWhere) {
80 where = jcr->RegexWhere; /* override */
82 } else if (jcr->job->RegexWhere) {
83 where = jcr->job->RegexWhere; /* no override take from job */
86 } else if (jcr->where) {
87 where = jcr->where; /* override */
89 } else if (jcr->job->RestoreWhere) {
90 where = jcr->job->RestoreWhere; /* no override take from job */
93 } else { /* nothing was specified */
94 where = ∅ /* use default */
98 jcr->prefix_links = jcr->job->PrefixLinks;
101 Mmsg(ret, cmd, replace, jcr->prefix_links, where);
102 unbash_spaces(where);
105 struct bootstrap_info
109 char storage[MAX_NAME_LENGTH+1];
112 #define UA_CMD_SIZE 1000
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
122 static bool open_bootstrap_file(JCR *jcr, struct bootstrap_info &info)
129 if (!jcr->RestoreBootstrap) {
132 strncpy(info.storage, jcr->rstore->name(), MAX_NAME_LENGTH);
134 bs = fopen(jcr->RestoreBootstrap, "rb");
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);
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)) {
150 if (!strcasecmp(ua->argk[0], "Storage")) {
151 strncpy(info.storage, ua->argv[0], MAX_NAME_LENGTH);
157 fseek(bs, 0, SEEK_SET); /* return to the top of the file */
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.
166 static bool is_on_same_storage(JCR *jcr, char *new_one)
170 /* with old FD, we send the whole bootstrap to the storage */
171 if (jcr->FDVersion < 2) {
174 /* we are in init loop ? shoudn't fall here */
179 if (!strcmp(new_one, jcr->rstore->name())) {
182 new_store = (STORE *)GetResWithName(R_STORAGE, new_one);
184 Jmsg(jcr, M_FATAL, 0,
185 _("Could not get storage resource '%s'.\n"), new_one);
186 set_jcr_job_status(jcr, JS_ErrorTerminated);
189 /* if Port and Hostname/IP are same, we are talking to the same
192 if (jcr->rstore->SDport != new_store->SDport ||
193 strcmp(jcr->rstore->address, new_store->address))
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
205 * Returns true if we need to change the storage, and it set the new
206 * Storage resource name in "storage" arg.
208 static bool check_for_new_storage(JCR *jcr, struct bootstrap_info &info)
210 UAContext *ua = info.ua;
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])) {
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);
229 * Send bootstrap file to Storage daemon section by section.
231 static bool send_bootstrap_file(JCR *jcr, BSOCK *sock,
232 struct bootstrap_info &info)
235 const char *bootstrap = "bootstrap\n";
236 UAContext *ua = info.ua;
239 Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
240 if (!jcr->RestoreBootstrap) {
243 sock->fsend(bootstrap);
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.
250 fseeko(bs, pos, SEEK_SET);
253 sock->fsend("%s", ua->cmd);
256 sock->signal(BNET_EOD);
261 * Change the read storage resource for the current job.
263 static void select_rstore(JCR *jcr, struct bootstrap_info &info)
267 if (!strcmp(jcr->rstore->name(), info.storage)) {
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);
278 if (jcr->store_bsock) {
279 jcr->store_bsock->destroy();
280 jcr->store_bsock = NULL;
284 set_rstorage(jcr, &ustore);
288 * Clean the struct bootstrap_info struct
290 static void close_bootstrap_file(struct bootstrap_info &info)
296 free_ua_context(info.ua);
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
309 bool restore_bootstrap(JCR *jcr)
313 bool first_time = true;
314 struct bootstrap_info info;
315 POOL_MEM restore_cmd(PM_MESSAGE);
318 /* this command is used for each part */
319 build_restore_command(jcr, restore_cmd);
321 /* Open the bootstrap file */
322 if (!open_bootstrap_file(jcr, info)) {
325 /* Read the bootstrap file */
326 while (!feof(info.bs)) {
328 select_rstore(jcr, info);
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.
336 Dmsg0(10, "Open connection with storage daemon\n");
337 set_jcr_job_status(jcr, JS_WaitSD);
339 * Start conversation with Storage daemon
341 if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
344 sd = jcr->store_bsock;
346 * Now start a job with the Storage daemon
348 if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
354 * Start conversation with File daemon
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)) {
361 fd = jcr->file_bsock;
364 set_jcr_job_status(jcr, JS_WaitSD);
367 * Send the bootstrap file -- what Volumes/files to restore
369 if (!send_bootstrap_file(jcr, sd, info) ||
370 !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
374 if (!sd->fsend("run")) {
378 * Now start a Storage daemon message thread
380 if (!start_storage_daemon_message_thread(jcr)) {
383 Dmsg0(50, "Storage daemon connection OK\n");
386 * send Storage daemon address to the File daemon,
387 * then wait for File daemon to make connection
388 * with Storage daemon.
390 if (jcr->rstore->SDDport == 0) {
391 jcr->rstore->SDDport = jcr->rstore->SDport;
393 fd->fsend(storaddr, jcr->rstore->address, jcr->rstore->SDDport,
395 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
397 Dmsg1(6, "dird>filed: %s\n", fd->msg);
398 if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
402 /* Only pass "global" commands to the FD once */
405 if (!send_runscripts_commands(jcr)) {
408 if (!send_restore_objects(jcr)) {
409 Dmsg0(000, "FAIL: Send restore objects\n");
414 fd->fsend("%s", restore_cmd.c_str());
416 if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
420 if (jcr->FDVersion < 2) { /* Old FD */
421 break; /* we do only one loop */
423 if (!response(jcr, fd, OKstoreend, "Store end", DISPLAY_ERROR)) {
426 wait_for_storage_daemon_termination(jcr);
428 } /* the whole boostrap has been send */
430 if (fd && jcr->FDVersion >= 2) {
431 fd->fsend("endrestore");
437 close_bootstrap_file(info);
442 * Do a restore of the specified files
444 * Returns: 0 on failure
447 bool do_restore(JCR *jcr)
449 JOB_DBR rjr; /* restore job record */
452 free_wstorage(jcr); /* we don't write */
454 if (!allow_duplicate_job(jcr)) {
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));
464 Dmsg0(20, "Updated job start record\n");
466 Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
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"));
476 /* Print Job Start message */
477 Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
479 /* Read the bootstrap file and do the restore */
480 if (!restore_bootstrap(jcr)) {
484 /* Wait for Job Termination */
485 stat = wait_for_job_termination(jcr);
486 restore_cleanup(jcr, stat);
490 restore_cleanup(jcr, JS_ErrorTerminated);
494 bool do_restore_init(JCR *jcr)
501 * Release resources allocated during restore.
504 void restore_cleanup(JCR *jcr, int TermCode)
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;
513 Dmsg0(20, "In restore_cleanup\n");
514 update_job_end(jcr, TermCode);
516 if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
517 unlink(jcr->RestoreBootstrap);
518 jcr->unlink_bsr = false;
521 if (job_canceled(jcr)) {
522 cancel_storage_daemon_job(jcr);
527 if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
528 term_msg = _("Restore OK -- warning file count mismatch");
530 term_msg = _("Restore OK");
534 term_msg = _("Restore OK -- with warnings");
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);
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);
557 term_msg = term_code;
558 sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
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));
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));
575 Jmsg(jcr, msg_type, 0, _("%s %s %s (%s): %s\n"
576 " Build OS: %s %s %s\n"
579 " Restore Client: %s\n"
582 " Files Expected: %s\n"
583 " Files Restored: %s\n"
584 " Bytes Restored: %s\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,
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),
606 Dmsg0(20, "Leaving restore_cleanup\n");