]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_run.c
Restore command fires off a Run command
[bacula/bacula] / bacula / src / dird / ua_run.c
1 /*
2  *
3  *   Bacula Director -- Run Command
4  *
5  *     Kern Sibbald, December MMI
6  *
7  *   Version $Id$
8  */
9
10 /*
11    Copyright (C) 2001, 2002 Kern Sibbald and John Walker
12
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of
16    the License, or (at your option) any later version.
17
18    This program is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21    General Public License for more details.
22
23    You should have received a copy of the GNU General Public
24    License along with this program; if not, write to the Free
25    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26    MA 02111-1307, USA.
27
28  */
29
30 #include "bacula.h"
31 #include "dird.h"
32 #include "ua.h"
33
34 /* Imported subroutines */
35 extern void run_job(JCR *jcr);
36
37 /* Imported variables */
38 extern struct s_jl joblevels[];
39
40 /*
41  * For Backup and Verify Jobs
42  *     run [job=]<job-name> level=<level-name>
43  *
44  * For Restore Jobs
45  *     run <job-name> jobid=nn
46  *
47  */
48 int runcmd(UAContext *ua, char *cmd)
49 {
50    JOB *job;
51    JCR *jcr;
52    char *job_name, *level_name, *jid, *store_name;
53    char *where, *fileset_name, *client_name, *bootstrap;
54    int i, j, found;
55    STORE *store;
56    CLIENT *client;
57    FILESET *fileset;
58    static char *kw[] = {
59       N_("job"),
60       N_("jobid"),
61       N_("client"),
62       N_("fileset"),
63       N_("level"),
64       N_("storage"),
65       N_("where"),
66       N_("bootstrap"),
67       NULL};
68
69    if (!open_db(ua)) {
70       return 1;
71    }
72
73    job_name = NULL;
74    level_name = NULL;
75    jid = NULL;
76    store_name = NULL;
77    where = NULL;
78    client_name = NULL;
79    fileset_name = NULL;
80    bootstrap = NULL;
81
82    Dmsg1(20, "run: %s\n", ua->UA_sock->msg);
83
84    for (i=1; i<ua->argc; i++) {
85       found = False;
86       Dmsg2(200, "Doing arg %d = %s\n", i, ua->argk[i]);
87       for (j=0; !found && kw[j]; j++) {
88          if (strcasecmp(ua->argk[i], _(kw[j])) == 0) {
89             if (!ua->argv[i]) {
90                bsendmsg(ua, _("Value missing for keyword %s\n"), ua->argk[i]);
91                return 1;
92             }
93             Dmsg1(200, "Got keyword=%s\n", kw[j]);
94             switch (j) {
95                case 0: /* job */
96                   if (job_name) {
97                      bsendmsg(ua, _("Job name specified twice.\n"));
98                      return 1;
99                   }
100                   job_name = ua->argv[i];
101                   found = True;
102                   break;
103                case 1: /* JobId */
104                   if (jid) {
105                      bsendmsg(ua, _("JobId specified twice.\n"));
106                      return 1;
107                   }
108                   jid = ua->argv[i];
109                   found = True;
110                   break;
111                case 2: /* client */
112                   if (client_name) {
113                      bsendmsg(ua, _("Client specified twice.\n"));
114                      return 1;
115                   }
116                   client_name = ua->argv[i];
117                   found = True;
118                   break;
119                case 3: /* fileset */
120                   if (fileset_name) {
121                      bsendmsg(ua, _("FileSet specified twice.\n"));
122                      return 1;
123                   }
124                   fileset_name = ua->argv[i];
125                   found = True;
126                   break;
127                case 4: /* level */
128                   if (level_name) {
129                      bsendmsg(ua, _("Level specified twice.\n"));
130                      return 1;
131                   }
132                   level_name = ua->argv[i];
133                   found = True;
134                   break;
135                case 5: /* storage */
136                   if (store_name) {
137                      bsendmsg(ua, _("Storage specified twice.\n"));
138                      return 1;
139                   }
140                   store_name = ua->argv[i];
141                   found = True;
142                   break;
143                case 6: /* where */
144                   if (where) {
145                      bsendmsg(ua, _("Where specified twice.\n"));
146                      return 1;
147                   }
148                   where = ua->argv[i];
149                   found = True;
150                   break;
151                case 7: /* bootstrap */
152                   if (bootstrap) {
153                      bsendmsg(ua, _("Bootstrap specified twice.\n"));
154                      return 1;
155                   }
156                   bootstrap = ua->argv[i];
157                   found = True;
158                   break;
159                default:
160                   break;
161             }
162          } /* end strcase compare */
163       } /* end keyword loop */
164       if (!found) {
165          Dmsg1(200, "%s not found\n", ua->argk[i]);
166          /*
167           * Special case for Job Name, it can be the first
168           * keyword that has no value.
169           */
170          if (!job_name && !ua->argv[i]) {
171             job_name = ua->argk[i];   /* use keyword as job name */
172             Dmsg1(200, "Set jobname=%s\n", job_name);
173          } else {
174             bsendmsg(ua, _("Invalid keyword: %s\n"), ua->argk[i]);
175             return 1;
176          }
177       }
178    } /* end argc loop */
179              
180    Dmsg0(20, "Done scan.\n");
181    if (job_name) {
182       /* Find Job */
183       job = (JOB *)GetResWithName(R_JOB, job_name);
184       if (!job) {
185          bsendmsg(ua, _("Job %s: not found\n"), job_name);
186          job = select_job_resource(ua);
187       } else {
188          Dmsg1(20, "Found job=%s\n", job_name);
189       }
190    } else {
191       bsendmsg(ua, _("A job name must be specified.\n"));
192       job = select_job_resource(ua);
193    }
194    if (!job) {
195       return 1;
196    }
197
198    if (store_name) {
199       store = (STORE *)GetResWithName(R_STORAGE, store_name);
200       if (!store) {
201          bsendmsg(ua, _("Storage %s not found.\n"), store_name);
202          store = select_storage_resource(ua);
203       }
204    } else {
205       store = job->storage;           /* use default */
206    }
207    if (!store) {
208       return 1;
209    }
210
211    jcr = new_jcr(sizeof(JCR), dird_free_jcr);
212    set_jcr_defaults(jcr, job);
213    jcr->store = store;                /* set possible new Storage */
214
215 try_again:
216    Dmsg1(20, "JobType=%c\n", jcr->JobType);
217    switch (jcr->JobType) {
218       char ec1[30];
219       case JT_ADMIN:
220          bsendmsg(ua, _("Run %s job\n\
221 JobName:  %s\n\
222 FileSet:  %s\n\
223 Client:   %s\n\
224 Storage:  %s\n"),
225                  _("Admin"),
226                  job->hdr.name,
227                  jcr->fileset->hdr.name,
228                  NPRT(jcr->client->hdr.name),
229                  NPRT(jcr->store->hdr.name));
230          break;
231          break;
232       case JT_BACKUP:
233       case JT_VERIFY:
234          if (level_name) {
235             /* Look up level name and pull code */
236             found = 0;
237             for (i=0; joblevels[i].level_name; i++) {
238                if (strcasecmp(level_name, _(joblevels[i].level_name)) == 0) {
239                   jcr->JobLevel = joblevels[i].level;
240                   found = 1;
241                   break;
242                }
243             }
244             if (!found) { 
245                bsendmsg(ua, _("Level %s not valid.\n"), level_name);
246                free_jcr(jcr);
247                return 1;
248             }
249          }
250          level_name = NULL;
251          bsendmsg(ua, _("Run %s job\n\
252 JobName:  %s\n\
253 FileSet:  %s\n\
254 Level:    %s\n\
255 Client:   %s\n\
256 Storage:  %s\n"),
257                  jcr->JobType==JT_BACKUP?_("Backup"):_("Verify"),
258                  job->hdr.name,
259                  jcr->fileset->hdr.name,
260                  level_to_str(jcr->JobLevel),
261                  jcr->client->hdr.name,
262                  jcr->store->hdr.name);
263          break;
264       case JT_RESTORE:
265          if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
266             if (jid) {
267                jcr->RestoreJobId = atoi(jid);
268             } else {
269                if (!get_cmd(ua, _("Please enter a JobId for restore: "))) {
270                   free_jcr(jcr);
271                   return 1;
272                }  
273                jcr->RestoreJobId = atoi(ua->cmd);
274             }
275          }
276          jcr->JobLevel = 'F';         /* default level */
277          Dmsg1(20, "JobId to restore=%d\n", jcr->RestoreJobId);
278          bsendmsg(ua, _("Run Restore job\n\
279 JobName:    %s\n\
280 Bootstrap:  %s\n\
281 Where:      %s\n\
282 FileSet:    %s\n\
283 Client:     %s\n\
284 Storage:    %s\n\
285 JobId:      %s\n"),
286                  job->hdr.name,
287                  NPRT(jcr->RestoreBootstrap),
288                  jcr->RestoreWhere?jcr->RestoreWhere:NPRT(job->RestoreWhere),
289                  jcr->fileset->hdr.name,
290                  jcr->client->hdr.name,
291                  jcr->store->hdr.name, 
292                  jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1));
293          break;
294       default:
295          bsendmsg(ua, _("Unknown Job Type=%d\n"), jcr->JobType);
296          free_jcr(jcr);
297          return 0;
298    }
299    if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
300       free_jcr(jcr);
301       return 0;                       /* do not run */
302    }
303    /*
304     * At user request modify parameters of job to be run.
305     */
306    if (strcasecmp(ua->cmd, _("mod")) == 0) {
307       FILE *fd;
308
309       start_prompt(ua, _("Parameters to modify:\n"));
310       add_prompt(ua, _("Level"));            /* 0 */
311       add_prompt(ua, _("Storage"));          /* 1 */
312       add_prompt(ua, _("Job"));              /* 2 */
313       add_prompt(ua, _("FileSet"));          /* 3 */
314       add_prompt(ua, _("Client"));           /* 4 */
315       if (jcr->JobType == JT_RESTORE) {
316          add_prompt(ua, _("Bootstrap"));     /* 5 */
317          add_prompt(ua, _("Where"));         /* 6 */
318          add_prompt(ua, _("JobId"));         /* 7 */
319       }
320       switch (do_prompt(ua, _("Select parameter to modify"), NULL)) {
321       case 0:
322          /* Level */
323          if (jcr->JobType == JT_BACKUP) {
324             start_prompt(ua, _("Levels:\n"));
325             add_prompt(ua, _("Full"));
326             add_prompt(ua, _("Incremental"));
327             add_prompt(ua, _("Differential"));
328             add_prompt(ua, _("Level"));
329             add_prompt(ua, _("Since"));
330             switch (do_prompt(ua, _("Select level"), NULL)) {
331             case 0:
332                jcr->JobLevel = L_FULL;
333                break;
334             case 1:
335                jcr->JobLevel = L_INCREMENTAL;
336                break;
337             case 2:
338                jcr->JobLevel = L_DIFFERENTIAL;
339                break;
340             case 3:
341                jcr->JobLevel = L_LEVEL;
342                break;
343             case 4:
344                jcr->JobLevel = L_SINCE;
345                break;
346             default:
347                break;
348             }
349             goto try_again;
350          } else if (jcr->JobType == JT_VERIFY) {
351             start_prompt(ua, _("Levels:\n"));
352             add_prompt(ua, _("Initialize Catalog"));
353             add_prompt(ua, _("Verify Catalog"));
354             add_prompt(ua, _("Verify Volume"));
355             add_prompt(ua, _("Verify Volume Data"));
356             switch (do_prompt(ua, _("Select level"), NULL)) {
357             case 0:
358                jcr->JobLevel = L_VERIFY_INIT;
359                break;
360             case 1:
361                jcr->JobLevel = L_VERIFY_CATALOG;
362                break;
363             case 2:
364                jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
365                break;
366             case 3:
367                jcr->JobLevel = L_VERIFY_DATA;
368                break;
369             default:
370                break;
371             }
372             goto try_again;
373          } else {
374             bsendmsg(ua, _("Level not appropriate for this Job. Cannot be changed.\n"));
375          }
376          goto try_again;
377       case 1:
378          store = select_storage_resource(ua);
379          if (store) {
380             jcr->store = store;
381             goto try_again;
382          }
383          break;
384       case 2:
385          /* Job */
386          job = select_job_resource(ua);
387          if (job) {
388             jcr->job = job;
389             set_jcr_defaults(jcr, job);
390             goto try_again;
391          }
392          break;
393       case 3:
394          /* FileSet */
395          fileset = select_fs_resource(ua);
396          if (fileset) {
397             jcr->fileset = fileset;
398             goto try_again;
399          }      
400          break;
401       case 4:
402          client = select_client_resource(ua);
403          if (client) {
404             jcr->client = client;
405             goto try_again;
406          }
407          break;
408       case 5:
409          /* Bootstrap */
410          if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
411             break;
412          }
413          if (jcr->RestoreBootstrap) {
414             free(jcr->RestoreBootstrap);
415             jcr->RestoreBootstrap = NULL;
416          }
417          if (ua->cmd[0] != 0) {
418             jcr->RestoreBootstrap = bstrdup(ua->cmd);
419             fd = fopen(jcr->RestoreBootstrap, "r");
420             if (!fd) {
421                bsendmsg(ua, _("Warning cannot open %s: ERR=%s\n"),
422                   jcr->RestoreBootstrap, strerror(errno));
423                free(jcr->RestoreBootstrap);
424                jcr->RestoreBootstrap = NULL;
425             } else {
426                fclose(fd);
427             }
428          }
429          goto try_again;
430       case 6:
431          /* Where */
432          if (!get_cmd(ua, _("Please enter path prefix (where) for restore: "))) {
433             break;
434          }
435          /* ***FIXME*** allow drive:/ for Windows */
436          if (ua->cmd[0] != '/') {
437             bsendmsg(ua, _("Prefix must begin with a /\n"));
438          } else {
439             if (jcr->RestoreWhere) {
440                free(jcr->RestoreWhere);
441             }
442             jcr->RestoreWhere = bstrdup(ua->cmd);
443          }  
444          goto try_again;
445       case 7:
446          /* JobId */
447          jid = NULL;                  /* force reprompt */
448          jcr->RestoreJobId = 0;
449          if (jcr->RestoreBootstrap) {
450             bsendmsg(ua, _("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
451          }
452          goto try_again;
453       default: 
454          goto try_again;
455       }
456       bsendmsg(ua, _("Job not run.\n"));
457       free_jcr(jcr);
458       return 0;                       /* error do no run Job */
459    }
460    if (strcasecmp(ua->cmd, _("yes")) != 0) {
461       bsendmsg(ua, _("Job not run.\n"));
462       free_jcr(jcr);
463       return 0;                       /* do not run */
464    }
465
466    Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
467    run_job(jcr);
468    return 1;
469 }