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