2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2000-2015 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Bacula Director -- restore.c -- responsible for restoring files
23 * Written by Kern Sibbald, November MM
25 * This routine is run as a separate thread.
27 * Current implementation is Catalog verification only (i.e. no
28 * verification versus tape).
30 * Basic tasks done here:
32 * Open Message Channel with Storage daemon to tell him a job will be starting.
33 * Open connection with File daemon and pass him commands
35 * Update the DB according to what files where restored????
44 /* Commands sent to File daemon */
45 static char restorecmd[] = "restore %sreplace=%c prelinks=%d where=%s\n";
46 static char restorecmdR[] = "restore %sreplace=%c prelinks=%d regexwhere=%s\n";
47 static char storaddr[] = "storage address=%s port=%d ssl=%d Authorization=%s\n";
49 /* Responses received from File daemon */
50 static char OKrestore[] = "2000 OK restore\n";
51 static char OKstore[] = "2000 OK storage\n";
52 static char OKstoreend[] = "2000 OK storage end\n";
54 /* Responses received from the Storage daemon */
55 static char OKbootstrap[] = "3000 OK bootstrap\n";
57 static void build_restore_command(JCR *jcr, POOL_MEM &ret)
59 char replace, *where, *cmd;
63 /* Build the restore command */
65 if (jcr->replace != 0) {
66 replace = jcr->replace;
67 } else if (jcr->job->replace != 0) {
68 replace = jcr->job->replace;
70 replace = REPLACE_ALWAYS; /* always replace */
73 if (jcr->RegexWhere) {
74 where = jcr->RegexWhere; /* override */
76 } else if (jcr->job->RegexWhere) {
77 where = jcr->job->RegexWhere; /* no override take from job */
80 } else if (jcr->where) {
81 where = jcr->where; /* override */
83 } else if (jcr->job->RestoreWhere) {
84 where = jcr->job->RestoreWhere; /* no override take from job */
87 } else { /* nothing was specified */
88 where = ∅ /* use default */
92 jcr->prefix_links = jcr->job->PrefixLinks;
95 if (jcr->FDVersion < 7) {
96 Mmsg(ret, cmd, "", replace, jcr->prefix_links, where);
98 snprintf(files, sizeof(files), "files=%d ", jcr->ExpectedFiles);
99 Mmsg(ret, cmd, files, replace, jcr->prefix_links, where);
101 unbash_spaces(where);
104 struct bootstrap_info
108 char storage[MAX_NAME_LENGTH+1];
111 #define UA_CMD_SIZE 1000
114 * Open the bootstrap file and find the first Storage=
115 * Returns ok if able to open
116 * It fills the storage name (should be the first line)
117 * and the file descriptor to the bootstrap file,
118 * it should be used for next operations, and need to be closed
121 static bool open_bootstrap_file(JCR *jcr, bootstrap_info &info)
128 if (!jcr->RestoreBootstrap) {
131 strncpy(info.storage, jcr->rstore->name(), MAX_NAME_LENGTH);
133 bs = fopen(jcr->RestoreBootstrap, "rb");
136 Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
137 jcr->RestoreBootstrap, be.bstrerror());
138 jcr->setJobStatus(JS_ErrorTerminated);
142 ua = new_ua_context(jcr);
143 ua->cmd = check_pool_memory_size(ua->cmd, UA_CMD_SIZE+1);
144 while (!fgets(ua->cmd, UA_CMD_SIZE, bs)) {
149 if (!strcasecmp(ua->argk[0], "Storage")) {
150 strncpy(info.storage, ua->argv[0], MAX_NAME_LENGTH);
156 fseek(bs, 0, SEEK_SET); /* return to the top of the file */
161 * This function compare the given storage name with the
162 * the current one. We compare the name and the address:port.
163 * Returns true if we use the same storage.
165 static bool is_on_same_storage(JCR *jcr, char *new_one)
169 /* with old FD, we send the whole bootstrap to the storage */
170 if (jcr->FDVersion < 2) {
173 /* we are in init loop ? shoudn't fail here */
178 if (!strcmp(new_one, jcr->rstore->name())) {
181 new_store = (STORE *)GetResWithName(R_STORAGE, new_one);
183 Jmsg(jcr, M_WARNING, 0,
184 _("Could not get storage resource '%s'.\n"), new_one);
185 /* If not storage found, use last one */
188 /* if Port and Hostname/IP are same, we are talking to the same
191 if (jcr->rstore->SDport != new_store->SDport ||
192 strcmp(jcr->rstore->address, new_store->address))
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
204 * Returns true if we need to change the storage, and it set the new
205 * Storage resource name in "storage" arg.
207 static bool check_for_new_storage(JCR *jcr, bootstrap_info &info)
209 UAContext *ua = info.ua;
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])) {
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);
228 * Send bootstrap file to Storage daemon section by section.
230 static bool send_bootstrap_file(JCR *jcr, BSOCK *sock,
231 bootstrap_info &info)
234 const char *bootstrap = "bootstrap\n";
235 UAContext *ua = info.ua;
238 Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
239 if (!jcr->RestoreBootstrap) {
242 sock->fsend(bootstrap);
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.
249 fseeko(bs, pos, SEEK_SET);
252 sock->fsend("%s", ua->cmd);
255 sock->signal(BNET_EOD);
259 #define MAX_TRIES 6 * 360 /* 6 hours */
262 * Change the read storage resource for the current job.
264 static bool select_rstore(JCR *jcr, bootstrap_info &info)
270 if (!strcmp(jcr->rstore->name(), info.storage)) {
271 return true; /* same SD nothing to change */
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);
282 * This releases the store_bsock between calls to the SD.
285 free_bsock(jcr->store_bsock);
288 * release current read storage and get a new one
292 set_rstorage(jcr, &ustore);
293 jcr->setJobStatus(JS_WaitSD);
295 * Wait for up to 6 hours to increment read stoage counter
297 for (i=0; i < MAX_TRIES; i++) {
298 /* try to get read storage counter incremented */
299 if (inc_read_store(jcr)) {
300 jcr->setJobStatus(JS_Running);
303 bmicrosleep(10, 0); /* sleep 10 secs */
304 if (job_canceled(jcr)) {
309 /* Failed to inc_read_store() */
311 Jmsg(jcr, M_FATAL, 0,
312 _("Could not acquire read storage lock for \"%s\""), info.storage);
317 * Clean the bootstrap_info struct
319 static void close_bootstrap_file(bootstrap_info &info)
325 free_ua_context(info.ua);
330 * The bootstrap is stored in a file, so open the file, and loop
331 * through it processing each storage device in turn. If the
332 * storage is different from the prior one, we open a new connection
333 * to the new storage and do a restore for that part.
334 * This permits handling multiple storage daemons for a single
335 * restore. E.g. your Full is stored on tape, and Incrementals
338 bool restore_bootstrap(JCR *jcr)
340 int tls_need = BNET_TLS_NONE;
345 bool first_time = true;
347 POOL_MEM restore_cmd(PM_MESSAGE);
351 /* Open the bootstrap file */
352 if (!open_bootstrap_file(jcr, info)) {
355 /* Read the bootstrap file */
356 while (!feof(info.bs)) {
358 if (!select_rstore(jcr, info)) {
363 * Open a message channel connection with the Storage
364 * daemon. This is to let him know that our client
365 * will be contacting him for a backup session.
368 Dmsg0(10, "Open connection with storage daemon\n");
369 jcr->setJobStatus(JS_WaitSD);
371 * Start conversation with Storage daemon
373 if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
376 sd = jcr->store_bsock;
378 * Now start a job with the Storage daemon
380 if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
386 * Start conversation with File daemon
388 jcr->setJobStatus(JS_WaitFD);
389 jcr->keep_sd_auth_key = true; /* don't clear the sd_auth_key now */
390 if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
393 fd = jcr->file_bsock;
394 build_restore_command(jcr, restore_cmd);
397 jcr->setJobStatus(JS_Running);
400 * Send the bootstrap file -- what Volumes/files to restore
402 if (!send_bootstrap_file(jcr, sd, info) ||
403 !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
407 if (jcr->sd_calls_client) {
409 * SD must call "client" i.e. FD
411 if (jcr->FDVersion < 10) {
412 Jmsg(jcr, M_FATAL, 0, _("The File daemon does not support SDCallsClient.\n"));
415 if (!send_client_addr_to_sd(jcr)) {
418 if (!run_storage_and_start_message_thread(jcr, sd)) {
422 store_address = jcr->rstore->address; /* dummy */
423 store_port = 0; /* flag that SD calls FD */
427 * Default case where FD must call the SD
429 if (!run_storage_and_start_message_thread(jcr, sd)) {
434 * send Storage daemon address to the File daemon,
435 * then wait for File daemon to make connection
436 * with Storage daemon.
438 if (jcr->rstore->SDDport == 0) {
439 jcr->rstore->SDDport = jcr->rstore->SDport;
442 store_address = get_storage_address(jcr->client, jcr->rstore);
443 store_port = jcr->rstore->SDDport;
446 /* TLS Requirement */
447 if (jcr->rstore->tls_enable) {
448 if (jcr->rstore->tls_require) {
449 tls_need = BNET_TLS_REQUIRED;
451 tls_need = BNET_TLS_OK;
456 * Send storage address to FD
457 * if port==0 FD must wait for SD to call it.
459 fd->fsend(storaddr, store_address, store_port, tls_need, jcr->sd_auth_key);
460 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
461 Dmsg1(6, "dird>filed: %s\n", fd->msg);
462 if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
466 /* Declare the job started to start the MaxRunTime check */
467 jcr->setJobStarted();
469 /* Only pass "global" commands to the FD once */
472 if (!send_runscripts_commands(jcr)) {
475 if (!send_component_info(jcr)) {
476 Pmsg0(000, "FAIL: Send component info\n");
479 if (!send_restore_objects(jcr)) {
480 Pmsg0(000, "FAIL: Send restore objects\n");
485 fd->fsend("%s", restore_cmd.c_str());
486 if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
490 if (jcr->FDVersion < 2) { /* Old FD */
491 break; /* we do only one loop */
493 if (!response(jcr, fd, OKstoreend, "Store end", DISPLAY_ERROR)) {
496 wait_for_storage_daemon_termination(jcr);
498 } /* the whole boostrap has been send */
500 if (fd && jcr->FDVersion >= 2) {
501 fd->fsend("endrestore");
507 close_bootstrap_file(info);
512 * Do a restore of the specified files
514 * Returns: 0 on failure
517 bool do_restore(JCR *jcr)
519 JOB_DBR rjr; /* restore job record */
522 free_wstorage(jcr); /* we don't write */
524 if (!allow_duplicate_job(jcr)) {
528 memset(&rjr, 0, sizeof(rjr));
529 jcr->jr.JobLevel = L_FULL; /* Full restore */
530 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
531 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
534 Dmsg0(20, "Updated job start record\n");
536 Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
538 if (!jcr->RestoreBootstrap) {
539 Jmsg(jcr, M_FATAL, 0, _("Cannot restore without a bootstrap file.\n"
540 "You probably ran a restore job directly. All restore jobs must\n"
541 "be run using the restore command.\n"));
546 /* Print Job Start message */
547 Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
550 jcr->sd_calls_client = jcr->client->sd_calls_client;
553 /* Read the bootstrap file and do the restore */
554 if (!restore_bootstrap(jcr)) {
558 /* Wait for Job Termination */
559 stat = wait_for_job_termination(jcr);
560 restore_cleanup(jcr, stat);
564 restore_cleanup(jcr, JS_ErrorTerminated);
568 bool do_restore_init(JCR *jcr)
575 * Release resources allocated during restore.
578 void restore_cleanup(JCR *jcr, int TermCode)
580 char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
581 char ec1[30], ec2[30], ec3[30];
582 char term_code[100], fd_term_msg[100], sd_term_msg[100];
583 const char *term_msg;
584 int msg_type = M_INFO;
587 Dmsg0(20, "In restore_cleanup\n");
588 update_job_end(jcr, TermCode);
590 if (jcr->component_fd) {
591 fclose(jcr->component_fd);
592 jcr->component_fd = NULL;
594 if (jcr->component_fname && *jcr->component_fname) {
595 unlink(jcr->component_fname);
597 free_and_null_pool_memory(jcr->component_fname);
599 if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
600 unlink(jcr->RestoreBootstrap);
601 jcr->unlink_bsr = false;
604 if (job_canceled(jcr)) {
605 cancel_storage_daemon_job(jcr);
610 if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
611 term_msg = _("Restore OK -- warning file count mismatch");
613 term_msg = _("Restore OK");
617 term_msg = _("Restore OK -- with warnings");
620 case JS_ErrorTerminated:
621 term_msg = _("*** Restore Error ***");
622 msg_type = M_ERROR; /* Generate error message */
623 if (jcr->store_bsock) {
624 jcr->store_bsock->signal(BNET_TERMINATE);
625 if (jcr->SD_msg_chan_started) {
626 pthread_cancel(jcr->SD_msg_chan);
631 term_msg = _("Restore Canceled");
632 if (jcr->store_bsock) {
633 jcr->store_bsock->signal(BNET_TERMINATE);
634 if (jcr->SD_msg_chan_started) {
635 pthread_cancel(jcr->SD_msg_chan);
640 term_msg = term_code;
641 sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
644 bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
645 bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
646 if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
647 kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
655 jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
656 jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
658 Jmsg(jcr, msg_type, 0, _("%s %s %s (%s):\n"
659 " Build OS: %s %s %s\n"
662 " Restore Client: %s\n"
665 " Files Expected: %s\n"
666 " Files Restored: %s\n"
667 " Bytes Restored: %s\n"
670 " FD termination status: %s\n"
671 " SD termination status: %s\n"
672 " Termination: %s\n\n"),
673 BACULA, my_name, VERSION, LSMDATE,
674 HOST_OS, DISTNAME, DISTVER,
680 edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
681 edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
682 edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
689 Dmsg0(20, "Leaving restore_cleanup\n");