]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/restore.c
Rename cats_pgsql to cats_postgresql and cats_sqlite to cats_sqlite3. This makes...
[bacula/bacula] / bacula / src / dird / restore.c
1 /*
2  *   Bacula Director -- restore.c -- responsible for restoring files
3  *
4  *     Kern Sibbald, November MM
5  *
6  *    This routine is run as a separate thread.
7  *
8  * Current implementation is Catalog verification only (i.e. no
9  *  verification versus tape).
10  *
11  *  Basic tasks done here:
12  *     Open DB
13  *     Open Message Channel with Storage daemon to tell him a job will be starting.
14  *     Open connection with File daemon and pass him commands
15  *       to do the restore.
16  *     Update the DB according to what files where restored????
17  *
18  *   Version $Id$
19  */
20 /*
21    Bacula® - The Network Backup Solution
22
23    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
24
25    The main author of Bacula is Kern Sibbald, with contributions from
26    many others, a complete list can be found in the file AUTHORS.
27    This program is Free Software; you can redistribute it and/or
28    modify it under the terms of version two of the GNU General Public
29    License as published by the Free Software Foundation plus additions
30    that are listed in the file LICENSE.
31
32    This program is distributed in the hope that it will be useful, but
33    WITHOUT ANY WARRANTY; without even the implied warranty of
34    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35    General Public License for more details.
36
37    You should have received a copy of the GNU General Public License
38    along with this program; if not, write to the Free Software
39    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
40    02110-1301, USA.
41
42    Bacula® is a registered trademark of John Walker.
43    The licensor of Bacula is the Free Software Foundation Europe
44    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
45    Switzerland, email:ftf@fsfeurope.org.
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 storaddr[]     = "storage address=%s port=%d ssl=0\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 OKbootstrap[] = "2000 OK bootstrap\n";
60
61 /*
62  * Do a restore of the specified files
63  *
64  *  Returns:  0 on failure
65  *            1 on success
66  */
67 bool do_restore(JCR *jcr)
68 {
69    BSOCK   *fd;
70    JOB_DBR rjr;                       /* restore job record */
71
72    free_wstorage(jcr);                /* we don't write */
73
74    memset(&rjr, 0, sizeof(rjr));
75    jcr->jr.JobLevel = L_FULL;         /* Full restore */
76    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
77       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
78       restore_cleanup(jcr, JS_ErrorTerminated);
79       return false;
80    }
81    Dmsg0(20, "Updated job start record\n");
82
83    Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
84
85    if (!jcr->RestoreBootstrap) {
86       Jmsg0(jcr, M_FATAL, 0, _("Cannot restore without a bootstrap file.\n"
87           "You probably ran a restore job directly. All restore jobs must\n"
88           "be run using the restore command.\n"));
89       restore_cleanup(jcr, JS_ErrorTerminated);
90       return false;
91    }
92
93
94    /* Print Job Start message */
95    Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
96
97    /*
98     * Open a message channel connection with the Storage
99     * daemon. This is to let him know that our client
100     * will be contacting him for a backup  session.
101     *
102     */
103    Dmsg0(10, "Open connection with storage daemon\n");
104    set_jcr_job_status(jcr, JS_WaitSD);
105    /*
106     * Start conversation with Storage daemon
107     */
108    if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
109       restore_cleanup(jcr, JS_ErrorTerminated);
110       return false;
111    }
112    /*
113     * Now start a job with the Storage daemon
114     */
115    if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
116       restore_cleanup(jcr, JS_ErrorTerminated);
117       return false;
118    }
119    if (!bnet_fsend(jcr->store_bsock, "run")) {
120       return false;
121    }
122    /*
123     * Now start a Storage daemon message thread
124     */
125    if (!start_storage_daemon_message_thread(jcr)) {
126       restore_cleanup(jcr, JS_ErrorTerminated);
127       return false;
128    }
129    Dmsg0(50, "Storage daemon connection OK\n");
130
131
132    /*
133     * Start conversation with File daemon
134     */
135    set_jcr_job_status(jcr, JS_WaitFD);
136    if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
137       restore_cleanup(jcr, JS_ErrorTerminated);
138       return false;
139    }
140
141    fd = jcr->file_bsock;
142    set_jcr_job_status(jcr, JS_Running);
143
144    /*
145     * send Storage daemon address to the File daemon,
146     *   then wait for File daemon to make connection
147     *   with Storage daemon.
148     */
149    if (jcr->rstore->SDDport == 0) {
150       jcr->rstore->SDDport = jcr->rstore->SDport;
151    }
152    bnet_fsend(fd, storaddr, jcr->rstore->address, jcr->rstore->SDDport);
153    Dmsg1(6, "dird>filed: %s\n", fd->msg);
154    if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
155       restore_cleanup(jcr, JS_ErrorTerminated);
156       return false;
157    }
158
159    /*
160     * Send the bootstrap file -- what Volumes/files to restore
161     */
162    if (!send_bootstrap_file(jcr, fd) ||
163        !response(jcr, fd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
164       restore_cleanup(jcr, JS_ErrorTerminated);
165       return false;
166    }
167
168
169    if (!send_runscripts_commands(jcr)) {
170       restore_cleanup(jcr, JS_ErrorTerminated);
171       return false;
172    }
173
174    /* Send restore command */
175    char replace, *where;
176    char empty = '\0';
177
178    if (jcr->replace != 0) {
179       replace = jcr->replace;
180    } else if (jcr->job->replace != 0) {
181       replace = jcr->job->replace;
182    } else {
183       replace = REPLACE_ALWAYS;       /* always replace */
184    }
185    if (jcr->where) {
186       where = jcr->where;             /* override */
187    } else if (jcr->job->RestoreWhere) {
188       where = jcr->job->RestoreWhere; /* no override take from job */
189    } else {
190       where = ∅                 /* None */
191    }
192    jcr->prefix_links = jcr->job->PrefixLinks;
193    bash_spaces(where);
194    bnet_fsend(fd, restorecmd, replace, jcr->prefix_links, where);
195    unbash_spaces(where);
196
197    if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
198       restore_cleanup(jcr, JS_ErrorTerminated);
199       return false;
200    }
201
202    /* Wait for Job Termination */
203    int stat = wait_for_job_termination(jcr);
204    restore_cleanup(jcr, stat);
205
206    return true;
207 }
208
209 bool do_restore_init(JCR *jcr) 
210 {
211    free_wstorage(jcr);
212    return true;
213 }
214
215 /*
216  * Release resources allocated during restore.
217  *
218  */
219 void restore_cleanup(JCR *jcr, int TermCode)
220 {
221    char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
222    char ec1[30], ec2[30], ec3[30];
223    char term_code[100], fd_term_msg[100], sd_term_msg[100];
224    const char *term_msg;
225    int msg_type = M_INFO;
226    double kbps;
227
228    Dmsg0(20, "In restore_cleanup\n");
229    dequeue_messages(jcr);             /* display any queued messages */
230    set_jcr_job_status(jcr, TermCode);
231
232    if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
233       unlink(jcr->RestoreBootstrap);
234       jcr->unlink_bsr = false;
235    }
236
237    update_job_end_record(jcr);
238
239    switch (TermCode) {
240    case JS_Terminated:
241       if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
242          term_msg = _("Restore OK -- warning file count mismatch");
243       } else {
244          term_msg = _("Restore OK");
245       }
246       break;
247    case JS_FatalError:
248    case JS_ErrorTerminated:
249       term_msg = _("*** Restore Error ***");
250       msg_type = M_ERROR;          /* Generate error message */
251       if (jcr->store_bsock) {
252          bnet_sig(jcr->store_bsock, BNET_TERMINATE);
253          if (jcr->SD_msg_chan) {
254             pthread_cancel(jcr->SD_msg_chan);
255          }
256       }
257       break;
258    case JS_Canceled:
259       term_msg = _("Restore Canceled");
260       if (jcr->store_bsock) {
261          bnet_sig(jcr->store_bsock, BNET_TERMINATE);
262          if (jcr->SD_msg_chan) {
263             pthread_cancel(jcr->SD_msg_chan);
264          }
265       }
266       break;
267    default:
268       term_msg = term_code;
269       sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
270       break;
271    }
272    bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
273    bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
274    if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
275       kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
276    } else {
277       kbps = 0;
278    }
279    if (kbps < 0.05) {
280       kbps = 0;
281    }
282
283    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
284    jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
285
286    Jmsg(jcr, msg_type, 0, _("Bacula %s (%s): %s\n"
287 "  JobId:                  %d\n"
288 "  Job:                    %s\n"
289 "  Client:                 %s\n"
290 "  Start time:             %s\n"
291 "  End time:               %s\n"
292 "  Files Expected:         %s\n"
293 "  Files Restored:         %s\n"
294 "  Bytes Restored:         %s\n"
295 "  Rate:                   %.1f KB/s\n"
296 "  FD Errors:              %d\n"
297 "  FD termination status:  %s\n"
298 "  SD termination status:  %s\n"
299 "  Termination:            %s\n\n"),
300         VERSION,
301         LSMDATE,
302         edt,
303         jcr->jr.JobId,
304         jcr->jr.Job,
305         jcr->client->hdr.name,
306         sdt,
307         edt,
308         edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
309         edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
310         edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
311         (float)kbps,
312         jcr->Errors,
313         fd_term_msg,
314         sd_term_msg,
315         term_msg);
316
317    Dmsg0(20, "Leaving restore_cleanup\n");
318 }