]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_run.c
fac2652a4caa6523798ffa59fd7a443662a4402d
[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    JCR *jcr;
51    char *job_name, *level_name, *jid, *store_name;
52    char *where, *fileset_name, *client_name, *bootstrap;
53    int i, j, found;
54    JOB *job = NULL;
55    STORE *store = NULL;
56    CLIENT *client = NULL;
57    FILESET *fileset = NULL;
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(000, "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(200, "Done scan.\n");
181
182
183
184    if (job_name) {
185       /* Find Job */
186       job = (JOB *)GetResWithName(R_JOB, job_name);
187       if (!job) {
188          bsendmsg(ua, _("Job %s: not found\n"), job_name);
189          job = select_job_resource(ua);
190       } else {
191          Dmsg1(200, "Found job=%s\n", job_name);
192       }
193    } else {
194       bsendmsg(ua, _("A job name must be specified.\n"));
195       job = select_job_resource(ua);
196    }
197    if (!job) {
198       return 1;
199    }
200
201    if (store_name) {
202       store = (STORE *)GetResWithName(R_STORAGE, store_name);
203       if (!store) {
204          bsendmsg(ua, _("Storage %s not found.\n"), store_name);
205          store = select_storage_resource(ua);
206       }
207    } else {
208       store = job->storage;           /* use default */
209    }
210    if (!store) {
211       return 1;
212    }
213
214    if (client_name) {
215       client = (CLIENT *)GetResWithName(R_CLIENT, client_name);
216       if (!client) {
217          bsendmsg(ua, _("Client %s not found.\n"), client_name);
218          client = select_client_resource(ua);
219       }
220    } else {
221       client = job->client;           /* use default */
222    }
223    if (!client) {
224       return 1;
225    }
226
227    if (fileset_name) {
228       fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name);
229       if (!fileset) {
230          bsendmsg(ua, _("FileSet %s not found.\n"), fileset_name);
231          fileset = select_fileset_resource(ua);
232       }
233    } else {
234       fileset = job->fileset;           /* use default */
235    }
236    if (!fileset) {
237       return 1;
238    }
239
240
241    /* Create JCR to run job */
242    jcr = new_jcr(sizeof(JCR), dird_free_jcr);
243    set_jcr_defaults(jcr, job);
244    init_msg(jcr, jcr->msgs);          /* start message handler */
245
246    jcr->store = store;
247    jcr->client = client;
248    jcr->fileset = fileset;
249    if (where) {
250       if (jcr->RestoreWhere) {
251          free(jcr->RestoreWhere);
252       }
253       jcr->RestoreWhere = bstrdup(where);
254    }
255    if (bootstrap) {
256       if (jcr->RestoreBootstrap) {
257          free(jcr->RestoreBootstrap);
258       }
259       jcr->RestoreBootstrap = bstrdup(bootstrap);
260    }
261
262
263
264
265 try_again:
266    Dmsg1(20, "JobType=%c\n", jcr->JobType);
267    switch (jcr->JobType) {
268       char ec1[30];
269       case JT_ADMIN:
270          bsendmsg(ua, _("Run %s job\n\
271 JobName:  %s\n\
272 FileSet:  %s\n\
273 Client:   %s\n\
274 Storage:  %s\n"),
275                  _("Admin"),
276                  job->hdr.name,
277                  jcr->fileset->hdr.name,
278                  NPRT(jcr->client->hdr.name),
279                  NPRT(jcr->store->hdr.name));
280          break;
281          break;
282       case JT_BACKUP:
283       case JT_VERIFY:
284          if (level_name) {
285             /* Look up level name and pull code */
286             found = 0;
287             for (i=0; joblevels[i].level_name; i++) {
288                if (strcasecmp(level_name, _(joblevels[i].level_name)) == 0) {
289                   jcr->JobLevel = joblevels[i].level;
290                   found = 1;
291                   break;
292                }
293             }
294             if (!found) { 
295                bsendmsg(ua, _("Level %s not valid.\n"), level_name);
296                free_jcr(jcr);
297                return 1;
298             }
299          }
300          level_name = NULL;
301          bsendmsg(ua, _("Run %s job\n\
302 JobName:  %s\n\
303 FileSet:  %s\n\
304 Level:    %s\n\
305 Client:   %s\n\
306 Storage:  %s\n"),
307                  jcr->JobType==JT_BACKUP?_("Backup"):_("Verify"),
308                  job->hdr.name,
309                  jcr->fileset->hdr.name,
310                  level_to_str(jcr->JobLevel),
311                  jcr->client->hdr.name,
312                  jcr->store->hdr.name);
313          break;
314       case JT_RESTORE:
315          if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
316             if (jid) {
317                jcr->RestoreJobId = atoi(jid);
318             } else {
319                if (!get_cmd(ua, _("Please enter a JobId for restore: "))) {
320                   free_jcr(jcr);
321                   return 1;
322                }  
323                jcr->RestoreJobId = atoi(ua->cmd);
324             }
325          }
326          jcr->JobLevel = 'F';         /* default level */
327          Dmsg1(20, "JobId to restore=%d\n", jcr->RestoreJobId);
328          bsendmsg(ua, _("Run Restore job\n\
329 JobName:    %s\n\
330 Bootstrap:  %s\n\
331 Where:      %s\n\
332 FileSet:    %s\n\
333 Client:     %s\n\
334 Storage:    %s\n\
335 JobId:      %s\n"),
336                  job->hdr.name,
337                  NPRT(jcr->RestoreBootstrap),
338                  jcr->RestoreWhere?jcr->RestoreWhere:NPRT(job->RestoreWhere),
339                  jcr->fileset->hdr.name,
340                  jcr->client->hdr.name,
341                  jcr->store->hdr.name, 
342                  jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1));
343          break;
344       default:
345          bsendmsg(ua, _("Unknown Job Type=%d\n"), jcr->JobType);
346          free_jcr(jcr);
347          return 0;
348    }
349    if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
350       free_jcr(jcr);
351       return 0;                       /* do not run */
352    }
353    /*
354     * At user request modify parameters of job to be run.
355     */
356    if (strcasecmp(ua->cmd, _("mod")) == 0) {
357       FILE *fd;
358
359       start_prompt(ua, _("Parameters to modify:\n"));
360       add_prompt(ua, _("Level"));            /* 0 */
361       add_prompt(ua, _("Storage"));          /* 1 */
362       add_prompt(ua, _("Job"));              /* 2 */
363       add_prompt(ua, _("FileSet"));          /* 3 */
364       add_prompt(ua, _("Client"));           /* 4 */
365       if (jcr->JobType == JT_RESTORE) {
366          add_prompt(ua, _("Bootstrap"));     /* 5 */
367          add_prompt(ua, _("Where"));         /* 6 */
368          add_prompt(ua, _("JobId"));         /* 7 */
369       }
370       switch (do_prompt(ua, _("Select parameter to modify"), NULL)) {
371       case 0:
372          /* Level */
373          if (jcr->JobType == JT_BACKUP) {
374             start_prompt(ua, _("Levels:\n"));
375             add_prompt(ua, _("Full"));
376             add_prompt(ua, _("Incremental"));
377             add_prompt(ua, _("Differential"));
378             add_prompt(ua, _("Level"));
379             add_prompt(ua, _("Since"));
380             switch (do_prompt(ua, _("Select level"), NULL)) {
381             case 0:
382                jcr->JobLevel = L_FULL;
383                break;
384             case 1:
385                jcr->JobLevel = L_INCREMENTAL;
386                break;
387             case 2:
388                jcr->JobLevel = L_DIFFERENTIAL;
389                break;
390             case 3:
391                jcr->JobLevel = L_LEVEL;
392                break;
393             case 4:
394                jcr->JobLevel = L_SINCE;
395                break;
396             default:
397                break;
398             }
399             goto try_again;
400          } else if (jcr->JobType == JT_VERIFY) {
401             start_prompt(ua, _("Levels:\n"));
402             add_prompt(ua, _("Initialize Catalog"));
403             add_prompt(ua, _("Verify Catalog"));
404             add_prompt(ua, _("Verify Volume"));
405             add_prompt(ua, _("Verify Volume Data"));
406             switch (do_prompt(ua, _("Select level"), NULL)) {
407             case 0:
408                jcr->JobLevel = L_VERIFY_INIT;
409                break;
410             case 1:
411                jcr->JobLevel = L_VERIFY_CATALOG;
412                break;
413             case 2:
414                jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
415                break;
416             case 3:
417                jcr->JobLevel = L_VERIFY_DATA;
418                break;
419             default:
420                break;
421             }
422             goto try_again;
423          } else {
424             bsendmsg(ua, _("Level not appropriate for this Job. Cannot be changed.\n"));
425          }
426          goto try_again;
427       case 1:
428          store = select_storage_resource(ua);
429          if (store) {
430             jcr->store = store;
431             goto try_again;
432          }
433          break;
434       case 2:
435          /* Job */
436          job = select_job_resource(ua);
437          if (job) {
438             jcr->job = job;
439             set_jcr_defaults(jcr, job);
440             goto try_again;
441          }
442          break;
443       case 3:
444          /* FileSet */
445          fileset = select_fileset_resource(ua);
446          if (fileset) {
447             jcr->fileset = fileset;
448             goto try_again;
449          }      
450          break;
451       case 4:
452          client = select_client_resource(ua);
453          if (client) {
454             jcr->client = client;
455             goto try_again;
456          }
457          break;
458       case 5:
459          /* Bootstrap */
460          if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
461             break;
462          }
463          if (jcr->RestoreBootstrap) {
464             free(jcr->RestoreBootstrap);
465             jcr->RestoreBootstrap = NULL;
466          }
467          if (ua->cmd[0] != 0) {
468             jcr->RestoreBootstrap = bstrdup(ua->cmd);
469             fd = fopen(jcr->RestoreBootstrap, "r");
470             if (!fd) {
471                bsendmsg(ua, _("Warning cannot open %s: ERR=%s\n"),
472                   jcr->RestoreBootstrap, strerror(errno));
473                free(jcr->RestoreBootstrap);
474                jcr->RestoreBootstrap = NULL;
475             } else {
476                fclose(fd);
477             }
478          }
479          goto try_again;
480       case 6:
481          /* Where */
482          if (!get_cmd(ua, _("Please enter path prefix (where) for restore: "))) {
483             break;
484          }
485          /* ***FIXME*** allow drive:/ for Windows */
486          if (ua->cmd[0] != '/') {
487             bsendmsg(ua, _("Prefix must begin with a /\n"));
488          } else {
489             if (jcr->RestoreWhere) {
490                free(jcr->RestoreWhere);
491             }
492             jcr->RestoreWhere = bstrdup(ua->cmd);
493          }  
494          goto try_again;
495       case 7:
496          /* JobId */
497          jid = NULL;                  /* force reprompt */
498          jcr->RestoreJobId = 0;
499          if (jcr->RestoreBootstrap) {
500             bsendmsg(ua, _("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
501          }
502          goto try_again;
503       default: 
504          goto try_again;
505       }
506       bsendmsg(ua, _("Job not run.\n"));
507       free_jcr(jcr);
508       return 0;                       /* error do no run Job */
509    }
510    if (strcasecmp(ua->cmd, _("yes")) != 0) {
511       bsendmsg(ua, _("Job not run.\n"));
512       free_jcr(jcr);
513       return 0;                       /* do not run */
514    }
515
516    Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
517    run_job(jcr);
518    return 1;
519 }