]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/restore.c
ebl add Error status in update volume=xxx status=yyyy
[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;
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    msg_type = M_INFO;                 /* by default INFO message */
240    switch (TermCode) {
241    case JS_Terminated:
242       if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
243          term_msg = _("Restore OK -- warning file count mismatch");
244       } else {
245          term_msg = _("Restore OK");
246       }
247       break;
248    case JS_FatalError:
249    case JS_ErrorTerminated:
250       term_msg = _("*** Restore Error ***");
251       msg_type = M_ERROR;          /* Generate error message */
252       if (jcr->store_bsock) {
253          bnet_sig(jcr->store_bsock, BNET_TERMINATE);
254          if (jcr->SD_msg_chan) {
255             pthread_cancel(jcr->SD_msg_chan);
256          }
257       }
258       break;
259    case JS_Canceled:
260       term_msg = _("Restore Canceled");
261       if (jcr->store_bsock) {
262          bnet_sig(jcr->store_bsock, BNET_TERMINATE);
263          if (jcr->SD_msg_chan) {
264             pthread_cancel(jcr->SD_msg_chan);
265          }
266       }
267       break;
268    default:
269       term_msg = term_code;
270       sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
271       break;
272    }
273    bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
274    bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
275    if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
276       kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
277    } else {
278       kbps = 0;
279    }
280    if (kbps < 0.05) {
281       kbps = 0;
282    }
283
284    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
285    jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
286
287    Jmsg(jcr, msg_type, 0, _("Bacula %s (%s): %s\n"
288 "  JobId:                  %d\n"
289 "  Job:                    %s\n"
290 "  Client:                 %s\n"
291 "  Start time:             %s\n"
292 "  End time:               %s\n"
293 "  Files Expected:         %s\n"
294 "  Files Restored:         %s\n"
295 "  Bytes Restored:         %s\n"
296 "  Rate:                   %.1f KB/s\n"
297 "  FD Errors:              %d\n"
298 "  FD termination status:  %s\n"
299 "  SD termination status:  %s\n"
300 "  Termination:            %s\n\n"),
301         VERSION,
302         LSMDATE,
303         edt,
304         jcr->jr.JobId,
305         jcr->jr.Job,
306         jcr->client->hdr.name,
307         sdt,
308         edt,
309         edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
310         edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
311         edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
312         (float)kbps,
313         jcr->Errors,
314         fd_term_msg,
315         sd_term_msg,
316         term_msg);
317
318    Dmsg0(20, "Leaving restore_cleanup\n");
319 }