]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/restore.c
es Fix error message that was clobbered when Dir tells SD it does not
[bacula/bacula] / bacula / src / dird / restore.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 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 John Walker.
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  *   Version $Id$
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 restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=%s\n";
55 static char storaddr[]   = "storage address=%s port=%d ssl=0\n";
56
57 /* Responses received from File daemon */
58 static char OKrestore[]   = "2000 OK restore\n";
59 static char OKstore[]     = "2000 OK storage\n";
60 static char OKbootstrap[] = "2000 OK bootstrap\n";
61
62 /*
63  * Do a restore of the specified files
64  *
65  *  Returns:  0 on failure
66  *            1 on success
67  */
68 bool do_restore(JCR *jcr)
69 {
70    BSOCK   *fd;
71    JOB_DBR rjr;                       /* restore job record */
72
73    free_wstorage(jcr);                /* we don't write */
74
75    memset(&rjr, 0, sizeof(rjr));
76    jcr->jr.JobLevel = L_FULL;         /* Full restore */
77    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
78       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
79       restore_cleanup(jcr, JS_ErrorTerminated);
80       return false;
81    }
82    Dmsg0(20, "Updated job start record\n");
83
84    Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
85
86    if (!jcr->RestoreBootstrap) {
87       Jmsg0(jcr, M_FATAL, 0, _("Cannot restore without a bootstrap file.\n"
88           "You probably ran a restore job directly. All restore jobs must\n"
89           "be run using the restore command.\n"));
90       restore_cleanup(jcr, JS_ErrorTerminated);
91       return false;
92    }
93
94
95    /* Print Job Start message */
96    Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
97
98    /*
99     * Open a message channel connection with the Storage
100     * daemon. This is to let him know that our client
101     * will be contacting him for a backup  session.
102     *
103     */
104    Dmsg0(10, "Open connection with storage daemon\n");
105    set_jcr_job_status(jcr, JS_WaitSD);
106    /*
107     * Start conversation with Storage daemon
108     */
109    if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
110       restore_cleanup(jcr, JS_ErrorTerminated);
111       return false;
112    }
113    /*
114     * Now start a job with the Storage daemon
115     */
116    if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
117       restore_cleanup(jcr, JS_ErrorTerminated);
118       return false;
119    }
120    if (!bnet_fsend(jcr->store_bsock, "run")) {
121       return false;
122    }
123    /*
124     * Now start a Storage daemon message thread
125     */
126    if (!start_storage_daemon_message_thread(jcr)) {
127       restore_cleanup(jcr, JS_ErrorTerminated);
128       return false;
129    }
130    Dmsg0(50, "Storage daemon connection OK\n");
131
132
133    /*
134     * Start conversation with File daemon
135     */
136    set_jcr_job_status(jcr, JS_WaitFD);
137    if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
138       cancel_storage_daemon_job(jcr);
139       restore_cleanup(jcr, JS_ErrorTerminated);
140       return false;
141    }
142
143    fd = jcr->file_bsock;
144    set_jcr_job_status(jcr, JS_Running);
145
146    /*
147     * send Storage daemon address to the File daemon,
148     *   then wait for File daemon to make connection
149     *   with Storage daemon.
150     */
151    if (jcr->rstore->SDDport == 0) {
152       jcr->rstore->SDDport = jcr->rstore->SDport;
153    }
154    bnet_fsend(fd, storaddr, jcr->rstore->address, jcr->rstore->SDDport);
155    Dmsg1(6, "dird>filed: %s\n", fd->msg);
156    if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
157       restore_cleanup(jcr, JS_ErrorTerminated);
158       return false;
159    }
160
161    /*
162     * Send the bootstrap file -- what Volumes/files to restore
163     */
164    if (!send_bootstrap_file(jcr, fd) ||
165        !response(jcr, fd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
166       restore_cleanup(jcr, JS_ErrorTerminated);
167       return false;
168    }
169
170
171    if (!send_runscripts_commands(jcr)) {
172       restore_cleanup(jcr, JS_ErrorTerminated);
173       return false;
174    }
175
176    /* Send restore command */
177    char replace, *where, *cmd=NULL;
178    char empty = '\0';
179
180    if (jcr->replace != 0) {
181       replace = jcr->replace;
182    } else if (jcr->job->replace != 0) {
183       replace = jcr->job->replace;
184    } else {
185       replace = REPLACE_ALWAYS;       /* always replace */
186    }
187    
188    where = ∅                    /* default */
189
190    if (jcr->RegexWhere) {
191       where = jcr->RegexWhere;             /* override */
192       cmd = restorecmdR;
193    } else if (jcr->job->RegexWhere) {
194       where = jcr->job->RegexWhere; /* no override take from job */
195       cmd = restorecmdR;
196
197    } else if (jcr->where) {
198       where = jcr->where;             /* override */
199       cmd = restorecmd;
200    } else if (jcr->job->RestoreWhere) {
201       where = jcr->job->RestoreWhere; /* no override take from job */
202       cmd = restorecmd;
203    } 
204    
205    jcr->prefix_links = jcr->job->PrefixLinks;
206
207    bash_spaces(where);
208    bnet_fsend(fd, cmd, replace, jcr->prefix_links, where);
209    unbash_spaces(where);
210
211    if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
212       restore_cleanup(jcr, JS_ErrorTerminated);
213       return false;
214    }
215
216    /* Wait for Job Termination */
217    int stat = wait_for_job_termination(jcr);
218    restore_cleanup(jcr, stat);
219
220    return true;
221 }
222
223 bool do_restore_init(JCR *jcr) 
224 {
225    free_wstorage(jcr);
226    return true;
227 }
228
229 /*
230  * Release resources allocated during restore.
231  *
232  */
233 void restore_cleanup(JCR *jcr, int TermCode)
234 {
235    char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
236    char ec1[30], ec2[30], ec3[30];
237    char term_code[100], fd_term_msg[100], sd_term_msg[100];
238    const char *term_msg;
239    int msg_type = M_INFO;
240    double kbps;
241
242    Dmsg0(20, "In restore_cleanup\n");
243    update_job_end(jcr, TermCode);
244
245    if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
246       unlink(jcr->RestoreBootstrap);
247       jcr->unlink_bsr = false;
248    }
249
250    switch (TermCode) {
251    case JS_Terminated:
252       if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
253          term_msg = _("Restore OK -- warning file count mismatch");
254       } else {
255          term_msg = _("Restore OK");
256       }
257       break;
258    case JS_FatalError:
259    case JS_ErrorTerminated:
260       term_msg = _("*** Restore Error ***");
261       msg_type = M_ERROR;          /* Generate error message */
262       if (jcr->store_bsock) {
263          bnet_sig(jcr->store_bsock, BNET_TERMINATE);
264          if (jcr->SD_msg_chan) {
265             pthread_cancel(jcr->SD_msg_chan);
266          }
267       }
268       break;
269    case JS_Canceled:
270       term_msg = _("Restore Canceled");
271       if (jcr->store_bsock) {
272          bnet_sig(jcr->store_bsock, BNET_TERMINATE);
273          if (jcr->SD_msg_chan) {
274             pthread_cancel(jcr->SD_msg_chan);
275          }
276       }
277       break;
278    default:
279       term_msg = term_code;
280       sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
281       break;
282    }
283    bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
284    bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
285    if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
286       kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
287    } else {
288       kbps = 0;
289    }
290    if (kbps < 0.05) {
291       kbps = 0;
292    }
293
294    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
295    jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
296
297    Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n"
298 "  Build OS:               %s %s %s\n"
299 "  JobId:                  %d\n"
300 "  Job:                    %s\n"
301 "  Restore Client:         %s\n"
302 "  Start time:             %s\n"
303 "  End time:               %s\n"
304 "  Files Expected:         %s\n"
305 "  Files Restored:         %s\n"
306 "  Bytes Restored:         %s\n"
307 "  Rate:                   %.1f KB/s\n"
308 "  FD Errors:              %d\n"
309 "  FD termination status:  %s\n"
310 "  SD termination status:  %s\n"
311 "  Termination:            %s\n\n"),
312         my_name, VERSION, LSMDATE, edt,
313         HOST_OS, DISTNAME, DISTVER,
314         jcr->jr.JobId,
315         jcr->jr.Job,
316         jcr->client->name(),
317         sdt,
318         edt,
319         edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
320         edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
321         edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
322         (float)kbps,
323         jcr->Errors,
324         fd_term_msg,
325         sd_term_msg,
326         term_msg);
327
328    Dmsg0(20, "Leaving restore_cleanup\n");
329 }