]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_run.c
Add new files
[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-2003 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
33 /* Imported subroutines */
34 extern void run_job(JCR *jcr);
35
36 /* Imported variables */
37 extern struct s_jl joblevels[];
38 extern struct s_kw ReplaceOptions[];
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, *pool_name;
52    char *where, *fileset_name, *client_name, *bootstrap, *replace;
53    char *when;
54    int i, j, found, opt;
55    JOB *job = NULL;
56    STORE *store = NULL;
57    CLIENT *client = NULL;
58    FILESET *fileset = NULL;
59    POOL *pool = NULL;
60    static char *kw[] = {
61       N_("job"),
62       N_("jobid"),
63       N_("client"),
64       N_("fileset"),
65       N_("level"),
66       N_("storage"),
67       N_("pool"), 
68       N_("where"),
69       N_("bootstrap"),
70       N_("replace"),
71       N_("when"),
72       NULL};
73
74    if (!open_db(ua)) {
75       return 1;
76    }
77
78    job_name = NULL;
79    level_name = NULL;
80    jid = NULL;
81    store_name = NULL;
82    pool_name = NULL;
83    where = NULL;
84    when = NULL;
85    client_name = NULL;
86    fileset_name = NULL;
87    bootstrap = NULL;
88    replace = NULL;
89
90    for (i=1; i<ua->argc; i++) {
91       found = False;
92       Dmsg2(200, "Doing arg %d = %s\n", i, ua->argk[i]);
93       for (j=0; !found && kw[j]; j++) {
94          if (strcasecmp(ua->argk[i], _(kw[j])) == 0) {
95             if (!ua->argv[i]) {
96                bsendmsg(ua, _("Value missing for keyword %s\n"), ua->argk[i]);
97                return 1;
98             }
99             Dmsg1(200, "Got keyword=%s\n", kw[j]);
100             switch (j) {
101                case 0: /* job */
102                   if (job_name) {
103                      bsendmsg(ua, _("Job name specified twice.\n"));
104                      return 1;
105                   }
106                   job_name = ua->argv[i];
107                   found = True;
108                   break;
109                case 1: /* JobId */
110                   if (jid) {
111                      bsendmsg(ua, _("JobId specified twice.\n"));
112                      return 1;
113                   }
114                   jid = ua->argv[i];
115                   found = True;
116                   break;
117                case 2: /* client */
118                   if (client_name) {
119                      bsendmsg(ua, _("Client specified twice.\n"));
120                      return 1;
121                   }
122                   client_name = ua->argv[i];
123                   found = True;
124                   break;
125                case 3: /* fileset */
126                   if (fileset_name) {
127                      bsendmsg(ua, _("FileSet specified twice.\n"));
128                      return 1;
129                   }
130                   fileset_name = ua->argv[i];
131                   found = True;
132                   break;
133                case 4: /* level */
134                   if (level_name) {
135                      bsendmsg(ua, _("Level specified twice.\n"));
136                      return 1;
137                   }
138                   level_name = ua->argv[i];
139                   found = True;
140                   break;
141                case 5: /* storage */
142                   if (store_name) {
143                      bsendmsg(ua, _("Storage specified twice.\n"));
144                      return 1;
145                   }
146                   store_name = ua->argv[i];
147                   found = True;
148                   break;
149                case 6: /* pool */
150                   if (pool_name) {
151                      bsendmsg(ua, _("Pool specified twice.\n"));
152                      return 1;
153                   }
154                   pool_name = ua->argv[i];
155                   found = True;
156                   break;
157                case 7: /* where */
158                   if (where) {
159                      bsendmsg(ua, _("Where specified twice.\n"));
160                      return 1;
161                   }
162                   where = ua->argv[i];
163                   found = True;
164                   break;
165                case 8: /* bootstrap */
166                   if (bootstrap) {
167                      bsendmsg(ua, _("Bootstrap specified twice.\n"));
168                      return 1;
169                   }
170                   bootstrap = ua->argv[i];
171                   found = True;
172                   break;
173                case 9: /* replace */
174                   if (replace) {
175                      bsendmsg(ua, _("Replace specified twice.\n"));
176                      return 1;
177                   }
178                   replace = ua->argv[i];
179                   found = True;
180                   break;
181                case 10: /* When */
182                   if (when) {
183                      bsendmsg(ua, _("When specified twice.\n"));
184                      return 1;
185                   }
186                   when = ua->argv[i];
187                   found = True;
188                   break;
189                default:
190                   break;
191             }
192          } /* end strcase compare */
193       } /* end keyword loop */
194       if (!found) {
195          Dmsg1(200, "%s not found\n", ua->argk[i]);
196          /*
197           * Special case for Job Name, it can be the first
198           * keyword that has no value.
199           */
200          if (!job_name && !ua->argv[i]) {
201             job_name = ua->argk[i];   /* use keyword as job name */
202             Dmsg1(200, "Set jobname=%s\n", job_name);
203          } else {
204             bsendmsg(ua, _("Invalid keyword: %s\n"), ua->argk[i]);
205             return 1;
206          }
207       }
208    } /* end argc loop */
209              
210    Dmsg0(200, "Done scan.\n");
211
212
213
214    if (job_name) {
215       /* Find Job */
216       job = (JOB *)GetResWithName(R_JOB, job_name);
217       if (!job) {
218          bsendmsg(ua, _("Job \"%s\" not found\n"), job_name);
219          job = select_job_resource(ua);
220       } else {
221          Dmsg1(200, "Found job=%s\n", job_name);
222       }
223    } else {
224       bsendmsg(ua, _("A job name must be specified.\n"));
225       job = select_job_resource(ua);
226    }
227    if (!job) {
228       return 1;
229    }
230
231    if (store_name) {
232       store = (STORE *)GetResWithName(R_STORAGE, store_name);
233       if (!store) {
234          bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name);
235          store = select_storage_resource(ua);
236       }
237    } else {
238       store = job->storage;           /* use default */
239    }
240    if (!store) {
241       return 1;
242    }
243
244
245    if (pool_name) {
246       pool = (POOL *)GetResWithName(R_POOL, pool_name);
247       if (!pool) {
248          bsendmsg(ua, _("Pool \"%s\" not found.\n"), pool_name);
249          pool = get_pool_resource(ua);
250       }
251    } else {
252       pool = job->pool;             /* use default */
253    }
254
255    if (client_name) {
256       client = (CLIENT *)GetResWithName(R_CLIENT, client_name);
257       if (!client) {
258          bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name);
259          client = select_client_resource(ua);
260       }
261    } else {
262       client = job->client;           /* use default */
263    }
264    if (!client) {
265       return 1;
266    }
267
268    if (fileset_name) {
269       fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name);
270       if (!fileset) {
271          bsendmsg(ua, _("FileSet \"%s\" not found.\n"), fileset_name);
272          fileset = select_fileset_resource(ua);
273       }
274    } else {
275       fileset = job->fileset;           /* use default */
276    }
277    if (!fileset) {
278       return 1;
279    }
280
281
282    /* Create JCR to run job */
283    jcr = new_jcr(sizeof(JCR), dird_free_jcr);
284    set_jcr_defaults(jcr, job);
285
286    jcr->store = store;
287    jcr->client = client;
288    jcr->fileset = fileset;
289    jcr->pool = pool;
290    if (where) {
291       if (jcr->where) {
292          free(jcr->where);
293       }
294       jcr->where = bstrdup(where);
295    }
296
297    if (when) {
298       jcr->sched_time = str_to_utime(when);
299       if (jcr->sched_time == 0) {
300          bsendmsg(ua, _("Invalid time, using current time.\n"));
301          jcr->sched_time = time(NULL);
302       }
303    }
304          
305    if (bootstrap) {
306       if (jcr->RestoreBootstrap) {
307          free(jcr->RestoreBootstrap);
308       }
309       jcr->RestoreBootstrap = bstrdup(bootstrap);
310    }
311
312    if (replace) {
313       jcr->replace = 0;
314       for (i=0; ReplaceOptions[i].name; i++) {
315          if (strcasecmp(replace, ReplaceOptions[i].name) == 0) {
316             jcr->replace = ReplaceOptions[i].token;
317          }
318       }
319       if (!jcr->replace) {
320          bsendmsg(ua, _("Invalid replace option: %s\n"), replace);
321          return 0;
322       }
323    } else if (job->replace) {
324       jcr->replace = job->replace;
325    } else {
326       jcr->replace = REPLACE_ALWAYS;
327    }
328
329 try_again:
330    replace = ReplaceOptions[0].name;
331    for (i=0; ReplaceOptions[i].name; i++) {
332       if (ReplaceOptions[i].token == jcr->replace) {
333          replace = ReplaceOptions[i].name;
334       }
335    }
336    Dmsg1(20, "JobType=%c\n", jcr->JobType);
337    switch (jcr->JobType) {
338       char ec1[30];
339       char dt[MAX_TIME_LENGTH];
340       case JT_ADMIN:
341          bsendmsg(ua, _("Run %s job\n\
342 JobName:  %s\n\
343 FileSet:  %s\n\
344 Client:   %s\n\
345 Storage:  %s\n\
346 When:     %s\n"),
347                  _("Admin"),
348                  job->hdr.name,
349                  jcr->fileset->hdr.name,
350                  NPRT(jcr->client->hdr.name),
351                  NPRT(jcr->store->hdr.name), 
352                  bstrutime(dt, sizeof(dt), jcr->sched_time));
353          jcr->JobLevel = L_FULL;
354          break;
355       case JT_BACKUP:
356       case JT_VERIFY:
357          if (level_name) {
358             /* Look up level name and pull code */
359             found = 0;
360             for (i=0; joblevels[i].level_name; i++) {
361                if (strcasecmp(level_name, _(joblevels[i].level_name)) == 0) {
362                   jcr->JobLevel = joblevels[i].level;
363                   found = 1;
364                   break;
365                }
366             }
367             if (!found) { 
368                bsendmsg(ua, _("Level %s not valid.\n"), level_name);
369                free_jcr(jcr);
370                return 1;
371             }
372          }
373          level_name = NULL;
374          bsendmsg(ua, _("Run %s job\n\
375 JobName:  %s\n\
376 FileSet:  %s\n\
377 Level:    %s\n\
378 Client:   %s\n\
379 Storage:  %s\n\
380 Pool:     %s\n\
381 When:     %s\n"),
382                  jcr->JobType==JT_BACKUP?_("Backup"):_("Verify"),
383                  job->hdr.name,
384                  jcr->fileset->hdr.name,
385                  level_to_str(jcr->JobLevel),
386                  jcr->client->hdr.name,
387                  jcr->store->hdr.name,
388                  NPRT(jcr->pool->hdr.name), 
389                  bstrutime(dt, sizeof(dt), jcr->sched_time));
390          break;
391       case JT_RESTORE:
392          if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
393             if (jid) {
394                jcr->RestoreJobId = atoi(jid);
395             } else {
396                if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
397                   free_jcr(jcr);
398                   return 1;
399                }  
400                jcr->RestoreJobId = ua->pint32_val;
401             }
402          }
403          jcr->JobLevel = L_FULL;      /* default level */
404          Dmsg1(20, "JobId to restore=%d\n", jcr->RestoreJobId);
405          if (jcr->RestoreJobId == 0) {
406             bsendmsg(ua, _("Run Restore job\n\
407 JobName:    %s\n\
408 Bootstrap:  %s\n\
409 Where:      %s\n\
410 Replace:    %s\n\
411 FileSet:    %s\n\
412 Client:     %s\n\
413 Storage:    %s\n\
414 When:       %s\n"),
415                  job->hdr.name,
416                  NPRT(jcr->RestoreBootstrap),
417                  jcr->where?jcr->where:NPRT(job->RestoreWhere),
418                  replace,
419                  jcr->fileset->hdr.name,
420                  jcr->client->hdr.name,
421                  jcr->store->hdr.name, 
422                  bstrutime(dt, sizeof(dt), jcr->sched_time));
423          } else {
424             bsendmsg(ua, _("Run Restore job\n\
425 JobName:    %s\n\
426 Bootstrap:  %s\n\
427 Where:      %s\n\
428 Replace:    %s\n\
429 FileSet:    %s\n\
430 Client:     %s\n\
431 Storage:    %s\n\
432 JobId:      %s\n\
433 When:       %s\n"),
434                  job->hdr.name,
435                  NPRT(jcr->RestoreBootstrap),
436                  jcr->where?jcr->where:NPRT(job->RestoreWhere),
437                  replace,
438                  jcr->fileset->hdr.name,
439                  jcr->client->hdr.name,
440                  jcr->store->hdr.name, 
441                  jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1), 
442                  bstrutime(dt, sizeof(dt), jcr->sched_time));
443          }
444          break;
445       default:
446          bsendmsg(ua, _("Unknown Job Type=%d\n"), jcr->JobType);
447          free_jcr(jcr);
448          return 0;
449    }
450    if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
451       free_jcr(jcr);
452       return 0;                       /* do not run */
453    }
454    /*
455     * At user request modify parameters of job to be run.
456     */
457    if (ua->cmd[0] == 0) {
458       bsendmsg(ua, _("Job not run.\n"));
459       free_jcr(jcr);
460       return 0;                       /* do not run */
461    }
462    if (strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
463       FILE *fd;
464
465       start_prompt(ua, _("Parameters to modify:\n"));
466       add_prompt(ua, _("Level"));            /* 0 */
467       add_prompt(ua, _("Storage"));          /* 1 */
468       add_prompt(ua, _("Job"));              /* 2 */
469       add_prompt(ua, _("FileSet"));          /* 3 */
470       add_prompt(ua, _("Client"));           /* 4 */
471       add_prompt(ua, _("When"));             /* 5 */
472       if (jcr->JobType == JT_BACKUP ||
473           jcr->JobType == JT_VERIFY) {
474          add_prompt(ua, _("Pool"));          /* 6 */
475       } else if (jcr->JobType == JT_RESTORE) {
476          add_prompt(ua, _("Bootstrap"));     /* 6 */
477          add_prompt(ua, _("Where"));         /* 7 */
478          add_prompt(ua, _("Replace"));       /* 8 */
479          add_prompt(ua, _("JobId"));         /* 9 */
480       }
481       switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
482       case 0:
483          /* Level */
484          if (jcr->JobType == JT_BACKUP) {
485             start_prompt(ua, _("Levels:\n"));
486             add_prompt(ua, _("Base"));
487             add_prompt(ua, _("Full"));
488             add_prompt(ua, _("Incremental"));
489             add_prompt(ua, _("Differential"));
490             add_prompt(ua, _("Since"));
491             switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
492             case 0:
493                jcr->JobLevel = L_BASE;
494                break;
495             case 1:
496                jcr->JobLevel = L_FULL;
497                break;
498             case 2:
499                jcr->JobLevel = L_INCREMENTAL;
500                break;
501             case 3:
502                jcr->JobLevel = L_DIFFERENTIAL;
503                break;
504             case 4:
505                jcr->JobLevel = L_SINCE;
506                break;
507             default:
508                break;
509             }
510             goto try_again;
511          } else if (jcr->JobType == JT_VERIFY) {
512             start_prompt(ua, _("Levels:\n"));
513             add_prompt(ua, _("Initialize Catalog"));
514             add_prompt(ua, _("Verify Catalog"));
515             add_prompt(ua, _("Verify Volume to Catalog"));
516             add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
517             switch (do_prompt(ua, "",  _("Select level"), NULL, 0)) {
518             case 0:
519                jcr->JobLevel = L_VERIFY_INIT;
520                break;
521             case 1:
522                jcr->JobLevel = L_VERIFY_CATALOG;
523                break;
524             case 2:
525                jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
526                break;
527             case 3:
528                jcr->JobLevel = L_VERIFY_DATA;
529                break;
530             default:
531                break;
532             }
533             goto try_again;
534          } else {
535             bsendmsg(ua, _("Level not appropriate for this Job. Cannot be changed.\n"));
536          }
537          goto try_again;
538       case 1:
539          /* Storage */
540          store = select_storage_resource(ua);
541          if (store) {
542             jcr->store = store;
543             goto try_again;
544          }
545          break;
546       case 2:
547          /* Job */
548          job = select_job_resource(ua);
549          if (job) {
550             jcr->job = job;
551             set_jcr_defaults(jcr, job);
552             goto try_again;
553          }
554          break;
555       case 3:
556          /* FileSet */
557          fileset = select_fileset_resource(ua);
558          if (fileset) {
559             jcr->fileset = fileset;
560             goto try_again;
561          }      
562          break;
563       case 4:
564          /* Client */
565          client = select_client_resource(ua);
566          if (client) {
567             jcr->client = client;
568             goto try_again;
569          }
570          break;
571       case 5:
572          /* When */
573          if (!get_cmd(ua, _("Please enter scheduled start time (return for now): "))) {
574             break;
575          }
576          if (ua->cmd[0] == 0) {
577             jcr->sched_time = time(NULL);
578          } else {
579             jcr->sched_time = str_to_utime(ua->cmd);
580             if (jcr->sched_time == 0) {
581                bsendmsg(ua, _("Invalid time, using current time.\n"));
582                jcr->sched_time = time(NULL);
583             }
584          }
585          goto try_again;
586       case 6:
587          if (jcr->JobType == JT_BACKUP ||
588              jcr->JobType == JT_VERIFY) {      /* Pool */
589             pool = select_pool_resource(ua);
590             if (pool) {
591                jcr->pool = pool;
592                goto try_again;
593             }
594             break;
595          }
596
597          /* Bootstrap */
598          if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
599             break;
600          }
601          if (jcr->RestoreBootstrap) {
602             free(jcr->RestoreBootstrap);
603             jcr->RestoreBootstrap = NULL;
604          }
605          if (ua->cmd[0] != 0) {
606             jcr->RestoreBootstrap = bstrdup(ua->cmd);
607             fd = fopen(jcr->RestoreBootstrap, "r");
608             if (!fd) {
609                bsendmsg(ua, _("Warning cannot open %s: ERR=%s\n"),
610                   jcr->RestoreBootstrap, strerror(errno));
611                free(jcr->RestoreBootstrap);
612                jcr->RestoreBootstrap = NULL;
613             } else {
614                fclose(fd);
615             }
616          }
617          goto try_again;
618       case 7:
619          /* Where */
620          if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
621             break;
622          }
623          if (jcr->where) {
624             free(jcr->where);
625             jcr->where = NULL;
626          }
627          if (ua->cmd[0] == '/' && ua->cmd[1] == 0) {
628             ua->cmd[0] = 0;
629          }
630          jcr->where = bstrdup(ua->cmd);
631          goto try_again;
632       case 8:
633          /* Replace */
634          start_prompt(ua, _("Replace:\n"));
635          for (i=0; ReplaceOptions[i].name; i++) {
636             add_prompt(ua, ReplaceOptions[i].name);
637          }
638          opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
639          if (opt >=  0) {
640             jcr->replace = ReplaceOptions[opt].token;
641          }
642          goto try_again;
643       case 9:
644          /* JobId */
645          jid = NULL;                  /* force reprompt */
646          jcr->RestoreJobId = 0;
647          if (jcr->RestoreBootstrap) {
648             bsendmsg(ua, _("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
649          }
650          goto try_again;
651       default: 
652          goto try_again;
653       }
654       bsendmsg(ua, _("Job not run.\n"));
655       free_jcr(jcr);
656       return 0;                       /* error do no run Job */
657    }
658    if (strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
659       Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
660       run_job(jcr);
661       bsendmsg(ua, _("Run command submitted.\n"));
662       return 1;
663    }
664
665    bsendmsg(ua, _("Job not run.\n"));
666    free_jcr(jcr);
667    return 0;                       /* do not run */
668
669 }