2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Bacula Director -- restore.c -- responsible for restoring files
22 * Written by Kern Sibbald, November MM
24 * This routine is run as a separate thread.
26 * Current implementation is Catalog verification only (i.e. no
27 * verification versus tape).
29 * Basic tasks done here:
31 * Open Message Channel with Storage daemon to tell him a job will be starting.
32 * Open connection with File daemon and pass him commands
34 * Update the DB according to what files where restored????
43 /* Commands sent to File daemon */
44 static char restorecmd[] = "restore %sreplace=%c prelinks=%d where=%s\n";
45 static char restorecmdR[] = "restore %sreplace=%c prelinks=%d regexwhere=%s\n";
46 static char storaddr[] = "storage address=%s port=%d ssl=%d Authorization=%s\n";
48 /* Responses received from File daemon */
49 static char OKrestore[] = "2000 OK restore\n";
50 static char OKstore[] = "2000 OK storage\n";
51 static char OKstoreend[] = "2000 OK storage end\n";
53 /* Responses received from the Storage daemon */
54 static char OKbootstrap[] = "3000 OK bootstrap\n";
56 static void build_restore_command(JCR *jcr, POOL_MEM &ret)
58 char replace, *where, *cmd;
62 /* Build the restore command */
64 if (jcr->replace != 0) {
65 replace = jcr->replace;
66 } else if (jcr->job->replace != 0) {
67 replace = jcr->job->replace;
69 replace = REPLACE_ALWAYS; /* always replace */
72 if (jcr->RegexWhere) {
73 where = jcr->RegexWhere; /* override */
75 } else if (jcr->job->RegexWhere) {
76 where = jcr->job->RegexWhere; /* no override take from job */
79 } else if (jcr->where) {
80 where = jcr->where; /* override */
82 } else if (jcr->job->RestoreWhere) {
83 where = jcr->job->RestoreWhere; /* no override take from job */
86 } else { /* nothing was specified */
87 where = ∅ /* use default */
91 jcr->prefix_links = jcr->job->PrefixLinks;
94 if (jcr->FDVersion < 7) {
95 Mmsg(ret, cmd, "", replace, jcr->prefix_links, where);
97 snprintf(files, sizeof(files), "files=%d ", jcr->ExpectedFiles);
98 Mmsg(ret, cmd, files, replace, jcr->prefix_links, where);
100 unbash_spaces(where);
103 struct bootstrap_info
107 char storage[MAX_NAME_LENGTH+1];
110 #define UA_CMD_SIZE 1000
113 * Open the bootstrap file and find the first Storage=
114 * Returns ok if able to open
115 * It fills the storage name (should be the first line)
116 * and the file descriptor to the bootstrap file,
117 * it should be used for next operations, and need to be closed
120 static bool open_bootstrap_file(JCR *jcr, bootstrap_info &info)
127 if (!jcr->RestoreBootstrap) {
130 strncpy(info.storage, jcr->rstore->name(), MAX_NAME_LENGTH);
132 bs = bfopen(jcr->RestoreBootstrap, "rb");
135 Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
136 jcr->RestoreBootstrap, be.bstrerror());
137 jcr->setJobStatus(JS_ErrorTerminated);
141 ua = new_ua_context(jcr);
142 ua->cmd = check_pool_memory_size(ua->cmd, UA_CMD_SIZE+1);
143 while (!fgets(ua->cmd, UA_CMD_SIZE, bs)) {
148 if (!strcasecmp(ua->argk[0], "Storage")) {
149 strncpy(info.storage, ua->argv[0], MAX_NAME_LENGTH);
155 fseek(bs, 0, SEEK_SET); /* return to the top of the file */
160 * This function compare the given storage name with the
161 * the current one. We compare the name and the address:port.
162 * Returns true if we use the same storage.
164 static bool is_on_same_storage(JCR *jcr, char *new_one)
168 /* with old FD, we send the whole bootstrap to the storage */
169 if (jcr->FDVersion < 2) {
172 /* we are in init loop ? shoudn't fail here */
177 if (!strcmp(new_one, jcr->rstore->name())) {
180 new_store = (STORE *)GetResWithName(R_STORAGE, new_one);
182 Jmsg(jcr, M_WARNING, 0,
183 _("Could not get storage resource '%s'.\n"), new_one);
184 /* If not storage found, use last one */
187 /* if Port and Hostname/IP are same, we are talking to the same
190 if (jcr->rstore->SDport != new_store->SDport ||
191 strcmp(jcr->rstore->address, new_store->address))
199 * Check if the current line contains Storage="xxx", and compare the
200 * result to the current storage. We use UAContext to analyse the bsr
203 * Returns true if we need to change the storage, and it set the new
204 * Storage resource name in "storage" arg.
206 static bool check_for_new_storage(JCR *jcr, bootstrap_info &info)
208 UAContext *ua = info.ua;
213 if (!strcasecmp(ua->argk[0], "Storage")) {
214 /* Continue if this is a volume from the same storage. */
215 if (is_on_same_storage(jcr, ua->argv[0])) {
218 /* note the next storage name */
219 strncpy(info.storage, ua->argv[0], MAX_NAME_LENGTH);
220 Dmsg1(5, "Change storage to %s\n", info.storage);
227 * Send bootstrap file to Storage daemon section by section.
229 static bool send_bootstrap_file(JCR *jcr, BSOCK *sock,
230 bootstrap_info &info)
233 const char *bootstrap = "bootstrap\n";
234 UAContext *ua = info.ua;
237 Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
238 if (!jcr->RestoreBootstrap) {
241 sock->fsend(bootstrap);
243 while(fgets(ua->cmd, UA_CMD_SIZE, bs)) {
244 if (check_for_new_storage(jcr, info)) {
245 /* Otherwise, we need to contact another storage daemon.
246 * Reset bs to the beginning of the current segment.
248 fseeko(bs, pos, SEEK_SET);
251 sock->fsend("%s", ua->cmd);
254 sock->signal(BNET_EOD);
258 #define MAX_TRIES 6 * 360 /* 6 hours */
261 * Change the read storage resource for the current job.
263 static bool select_rstore(JCR *jcr, bootstrap_info &info)
269 if (!strcmp(jcr->rstore->name(), info.storage)) {
270 return true; /* same SD nothing to change */
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 jcr->setJobStatus(JS_ErrorTerminated);
281 * This releases the store_bsock between calls to the SD.
284 free_bsock(jcr->store_bsock);
287 * release current read storage and get a new one
291 set_rstorage(jcr, &ustore);
292 jcr->setJobStatus(JS_WaitSD);
294 * Wait for up to 6 hours to increment read stoage counter
296 for (i=0; i < MAX_TRIES; i++) {
297 /* try to get read storage counter incremented */
298 if (inc_read_store(jcr)) {
299 jcr->setJobStatus(JS_Running);
302 bmicrosleep(10, 0); /* sleep 10 secs */
303 if (job_canceled(jcr)) {
308 /* Failed to inc_read_store() */
310 Jmsg(jcr, M_FATAL, 0,
311 _("Could not acquire read storage lock for \"%s\""), info.storage);
316 * Clean the bootstrap_info struct
318 static void close_bootstrap_file(bootstrap_info &info)
324 free_ua_context(info.ua);
329 * The bootstrap is stored in a file, so open the file, and loop
330 * through it processing each storage device in turn. If the
331 * storage is different from the prior one, we open a new connection
332 * to the new storage and do a restore for that part.
333 * This permits handling multiple storage daemons for a single
334 * restore. E.g. your Full is stored on tape, and Incrementals
337 bool restore_bootstrap(JCR *jcr)
339 int tls_need = BNET_TLS_NONE;
344 bool first_time = true;
346 POOL_MEM restore_cmd(PM_MESSAGE);
350 /* Open the bootstrap file */
351 if (!open_bootstrap_file(jcr, info)) {
354 /* Read the bootstrap file */
355 while (!feof(info.bs)) {
357 if (!select_rstore(jcr, info)) {
362 * Open a message channel connection with the Storage
363 * daemon. This is to let him know that our client
364 * will be contacting him for a backup session.
367 Dmsg0(10, "Open connection with storage daemon\n");
368 jcr->setJobStatus(JS_WaitSD);
370 * Start conversation with Storage daemon
372 if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
375 sd = jcr->store_bsock;
377 * Now start a job with the Storage daemon
379 if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
385 * Start conversation with File daemon
387 jcr->setJobStatus(JS_WaitFD);
388 jcr->keep_sd_auth_key = true; /* don't clear the sd_auth_key now */
389 if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
392 fd = jcr->file_bsock;
393 build_restore_command(jcr, restore_cmd);
396 jcr->setJobStatus(JS_Running);
399 * Send the bootstrap file -- what Volumes/files to restore
401 if (!send_bootstrap_file(jcr, sd, info) ||
402 !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
406 if (jcr->sd_calls_client) {
408 * SD must call "client" i.e. FD
410 if (jcr->FDVersion < 10) {
411 Jmsg(jcr, M_FATAL, 0, _("The File daemon does not support SDCallsClient.\n"));
414 if (!send_client_addr_to_sd(jcr)) {
417 if (!run_storage_and_start_message_thread(jcr, sd)) {
421 store_address = jcr->rstore->address; /* dummy */
422 store_port = 0; /* flag that SD calls FD */
426 * Default case where FD must call the SD
428 if (!run_storage_and_start_message_thread(jcr, sd)) {
433 * send Storage daemon address to the File daemon,
434 * then wait for File daemon to make connection
435 * with Storage daemon.
437 if (jcr->rstore->SDDport == 0) {
438 jcr->rstore->SDDport = jcr->rstore->SDport;
441 store_address = get_storage_address(jcr->client, jcr->rstore);
442 store_port = jcr->rstore->SDDport;
445 /* TLS Requirement */
446 if (jcr->rstore->tls_enable) {
447 if (jcr->rstore->tls_require) {
448 tls_need = BNET_TLS_REQUIRED;
450 tls_need = BNET_TLS_OK;
455 * Send storage address to FD
456 * if port==0 FD must wait for SD to call it.
458 fd->fsend(storaddr, store_address, store_port, tls_need, jcr->sd_auth_key);
459 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
460 Dmsg1(6, "dird>filed: %s\n", fd->msg);
461 if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
465 /* Declare the job started to start the MaxRunTime check */
466 jcr->setJobStarted();
468 /* Only pass "global" commands to the FD once */
471 if (!send_runscripts_commands(jcr)) {
474 if (!send_component_info(jcr)) {
475 Pmsg0(000, "FAIL: Send component info\n");
478 if (!send_restore_objects(jcr)) {
479 Pmsg0(000, "FAIL: Send restore objects\n");
484 fd->fsend("%s", restore_cmd.c_str());
485 if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
489 if (jcr->FDVersion < 2) { /* Old FD */
490 break; /* we do only one loop */
492 if (!response(jcr, fd, OKstoreend, "Store end", DISPLAY_ERROR)) {
495 wait_for_storage_daemon_termination(jcr);
497 } /* the whole boostrap has been send */
499 if (fd && jcr->FDVersion >= 2) {
500 fd->fsend("endrestore");
506 close_bootstrap_file(info);
511 * Do a restore of the specified files
513 * Returns: 0 on failure
516 bool do_restore(JCR *jcr)
518 JOB_DBR rjr; /* restore job record */
521 free_wstorage(jcr); /* we don't write */
523 if (!allow_duplicate_job(jcr)) {
527 memset(&rjr, 0, sizeof(rjr));
528 jcr->jr.JobLevel = L_FULL; /* Full restore */
529 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
530 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
533 Dmsg0(20, "Updated job start record\n");
535 Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
537 if (!jcr->RestoreBootstrap) {
538 Jmsg(jcr, M_FATAL, 0, _("Cannot restore without a bootstrap file.\n"
539 "You probably ran a restore job directly. All restore jobs must\n"
540 "be run using the restore command.\n"));
545 /* Print Job Start message */
546 Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
549 jcr->sd_calls_client = jcr->client->sd_calls_client;
552 /* Read the bootstrap file and do the restore */
553 if (!restore_bootstrap(jcr)) {
557 /* Wait for Job Termination */
558 stat = wait_for_job_termination(jcr);
559 restore_cleanup(jcr, stat);
563 restore_cleanup(jcr, JS_ErrorTerminated);
567 /* Create a Plugin Config RestoreObject, will be sent
568 * at restore time to the Plugin
570 static void plugin_create_restoreobject(JCR *jcr, plugin_config_item *elt)
573 memset(&ro, 0, sizeof(ro));
575 ro.JobId = jcr->JobId;
576 ro.FileType = FT_PLUGIN_CONFIG_FILLED;
578 ro.object_full_len = ro.object_len = strlen(elt->content);
579 ro.object_compression = 0;
580 ro.plugin_name = elt->plugin_name;
581 ro.object_name = (char*)INI_RESTORE_OBJECT_NAME;
582 ro.object = elt->content;
583 db_create_restore_object_record(jcr, jcr->db, &ro);
584 Dmsg1(50, "Creating restore object for %s\n", elt->plugin_name);
587 bool do_restore_init(JCR *jcr)
589 /* Will add RestoreObject used for the Plugin configuration */
590 if (jcr->plugin_config) {
592 plugin_config_item *elt;
593 foreach_alist(elt, jcr->plugin_config) {
594 plugin_create_restoreobject(jcr, elt);
595 free_plugin_config_item(elt);
598 delete jcr->plugin_config;
599 jcr->plugin_config = NULL;
606 * Release resources allocated during restore.
609 void restore_cleanup(JCR *jcr, int TermCode)
611 char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
612 char ec1[30], ec2[30], ec3[30], ec4[30], elapsed[50];
613 char term_code[100], fd_term_msg[100], sd_term_msg[100];
614 const char *term_msg;
615 int msg_type = M_INFO;
619 Dmsg0(20, "In restore_cleanup\n");
620 update_job_end(jcr, TermCode);
622 if (jcr->component_fd) {
623 fclose(jcr->component_fd);
624 jcr->component_fd = NULL;
626 if (jcr->component_fname && *jcr->component_fname) {
627 unlink(jcr->component_fname);
629 free_and_null_pool_memory(jcr->component_fname);
631 if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
632 unlink(jcr->RestoreBootstrap);
633 jcr->unlink_bsr = false;
636 if (job_canceled(jcr)) {
637 cancel_storage_daemon_job(jcr);
642 if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
643 term_msg = _("Restore OK -- warning file count mismatch");
645 } else if (jcr->JobErrors > 0 || jcr->SDErrors > 0) {
646 term_msg = _("Restore OK -- with errors");
649 term_msg = _("Restore OK");
653 term_msg = _("Restore OK -- with warnings");
656 case JS_ErrorTerminated:
657 term_msg = _("*** Restore Error ***");
658 msg_type = M_ERROR; /* Generate error message */
659 if (jcr->store_bsock) {
660 jcr->store_bsock->signal(BNET_TERMINATE);
661 if (jcr->SD_msg_chan_started) {
662 pthread_cancel(jcr->SD_msg_chan);
667 term_msg = _("Restore Canceled");
668 if (jcr->store_bsock) {
669 jcr->store_bsock->signal(BNET_TERMINATE);
670 if (jcr->SD_msg_chan_started) {
671 pthread_cancel(jcr->SD_msg_chan);
676 term_msg = term_code;
677 sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
680 bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
681 bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
683 RunTime = jcr->jr.EndTime - jcr->jr.StartTime;
687 kbps = (double)jcr->jr.JobBytes / (1000.0 * (double)RunTime);
692 jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
693 jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
695 Jmsg(jcr, msg_type, 0, _("%s %s %s (%s):\n"
696 " Build OS: %s %s %s\n"
699 " Restore Client: %s\n"
702 " Elapsed time: %s\n"
703 " Files Expected: %s\n"
704 " Files Restored: %s\n"
705 " Bytes Restored: %s (%sB)\n"
708 " FD termination status: %s\n"
709 " SD termination status: %s\n"
710 " Termination: %s\n\n"),
711 BACULA, my_name, VERSION, LSMDATE,
712 HOST_OS, DISTNAME, DISTVER,
718 edit_utime(RunTime, elapsed, sizeof(elapsed)),
719 edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
720 edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
721 edit_uint64_with_commas(jcr->jr.JobBytes, ec3), edit_uint64_with_suffix(jcr->jr.JobBytes, ec4),
728 Dmsg0(20, "Leaving restore_cleanup\n");