]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_run.c
Important protocol change -- see kes29Oct02
[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    for (i=1; i<ua->argc; i++) {
83       found = False;
84       Dmsg2(200, "Doing arg %d = %s\n", i, ua->argk[i]);
85       for (j=0; !found && kw[j]; j++) {
86          if (strcasecmp(ua->argk[i], _(kw[j])) == 0) {
87             if (!ua->argv[i]) {
88                bsendmsg(ua, _("Value missing for keyword %s\n"), ua->argk[i]);
89                return 1;
90             }
91             Dmsg1(200, "Got keyword=%s\n", kw[j]);
92             switch (j) {
93                case 0: /* job */
94                   if (job_name) {
95                      bsendmsg(ua, _("Job name specified twice.\n"));
96                      return 1;
97                   }
98                   job_name = ua->argv[i];
99                   found = True;
100                   break;
101                case 1: /* JobId */
102                   if (jid) {
103                      bsendmsg(ua, _("JobId specified twice.\n"));
104                      return 1;
105                   }
106                   jid = ua->argv[i];
107                   found = True;
108                   break;
109                case 2: /* client */
110                   if (client_name) {
111                      bsendmsg(ua, _("Client specified twice.\n"));
112                      return 1;
113                   }
114                   client_name = ua->argv[i];
115                   found = True;
116                   break;
117                case 3: /* fileset */
118                   if (fileset_name) {
119                      bsendmsg(ua, _("FileSet specified twice.\n"));
120                      return 1;
121                   }
122                   fileset_name = ua->argv[i];
123                   found = True;
124                   break;
125                case 4: /* level */
126                   if (level_name) {
127                      bsendmsg(ua, _("Level specified twice.\n"));
128                      return 1;
129                   }
130                   level_name = ua->argv[i];
131                   found = True;
132                   break;
133                case 5: /* storage */
134                   if (store_name) {
135                      bsendmsg(ua, _("Storage specified twice.\n"));
136                      return 1;
137                   }
138                   store_name = ua->argv[i];
139                   found = True;
140                   break;
141                case 6: /* where */
142                   if (where) {
143                      bsendmsg(ua, _("Where specified twice.\n"));
144                      return 1;
145                   }
146                   where = ua->argv[i];
147                   found = True;
148                   break;
149                case 7: /* bootstrap */
150                   if (bootstrap) {
151                      bsendmsg(ua, _("Bootstrap specified twice.\n"));
152                      return 1;
153                   }
154                   bootstrap = ua->argv[i];
155                   found = True;
156                   break;
157                default:
158                   break;
159             }
160          } /* end strcase compare */
161       } /* end keyword loop */
162       if (!found) {
163          Dmsg1(200, "%s not found\n", ua->argk[i]);
164          /*
165           * Special case for Job Name, it can be the first
166           * keyword that has no value.
167           */
168          if (!job_name && !ua->argv[i]) {
169             job_name = ua->argk[i];   /* use keyword as job name */
170             Dmsg1(200, "Set jobname=%s\n", job_name);
171          } else {
172             bsendmsg(ua, _("Invalid keyword: %s\n"), ua->argk[i]);
173             return 1;
174          }
175       }
176    } /* end argc loop */
177              
178    Dmsg0(200, "Done scan.\n");
179
180
181
182    if (job_name) {
183       /* Find Job */
184       job = (JOB *)GetResWithName(R_JOB, job_name);
185       if (!job) {
186          bsendmsg(ua, _("Job \"%s\" not found\n"), job_name);
187          job = select_job_resource(ua);
188       } else {
189          Dmsg1(200, "Found job=%s\n", job_name);
190       }
191    } else {
192       bsendmsg(ua, _("A job name must be specified.\n"));
193       job = select_job_resource(ua);
194    }
195    if (!job) {
196       return 1;
197    }
198
199    if (store_name) {
200       store = (STORE *)GetResWithName(R_STORAGE, store_name);
201       if (!store) {
202          bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name);
203          store = select_storage_resource(ua);
204       }
205    } else {
206       store = job->storage;           /* use default */
207    }
208    if (!store) {
209       return 1;
210    }
211
212    if (client_name) {
213       client = (CLIENT *)GetResWithName(R_CLIENT, client_name);
214       if (!client) {
215          bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name);
216          client = select_client_resource(ua);
217       }
218    } else {
219       client = job->client;           /* use default */
220    }
221    if (!client) {
222       return 1;
223    }
224
225    if (fileset_name) {
226       fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name);
227       if (!fileset) {
228          bsendmsg(ua, _("FileSet \"%s\" not found.\n"), fileset_name);
229          fileset = select_fileset_resource(ua);
230       }
231    } else {
232       fileset = job->fileset;           /* use default */
233    }
234    if (!fileset) {
235       return 1;
236    }
237
238
239    /* Create JCR to run job */
240    jcr = new_jcr(sizeof(JCR), dird_free_jcr);
241    set_jcr_defaults(jcr, job);
242
243    jcr->store = store;
244    jcr->client = client;
245    jcr->fileset = fileset;
246    if (where) {
247       if (jcr->RestoreWhere) {
248          free(jcr->RestoreWhere);
249       }
250       jcr->RestoreWhere = bstrdup(where);
251    }
252    if (bootstrap) {
253       if (jcr->RestoreBootstrap) {
254          free(jcr->RestoreBootstrap);
255       }
256       jcr->RestoreBootstrap = bstrdup(bootstrap);
257    }
258
259
260
261
262 try_again:
263    Dmsg1(20, "JobType=%c\n", jcr->JobType);
264    switch (jcr->JobType) {
265       char ec1[30];
266       case JT_ADMIN:
267          bsendmsg(ua, _("Run %s job\n\
268 JobName:  %s\n\
269 FileSet:  %s\n\
270 Client:   %s\n\
271 Storage:  %s\n"),
272                  _("Admin"),
273                  job->hdr.name,
274                  jcr->fileset->hdr.name,
275                  NPRT(jcr->client->hdr.name),
276                  NPRT(jcr->store->hdr.name));
277          break;
278          break;
279       case JT_BACKUP:
280       case JT_VERIFY:
281          if (level_name) {
282             /* Look up level name and pull code */
283             found = 0;
284             for (i=0; joblevels[i].level_name; i++) {
285                if (strcasecmp(level_name, _(joblevels[i].level_name)) == 0) {
286                   jcr->JobLevel = joblevels[i].level;
287                   found = 1;
288                   break;
289                }
290             }
291             if (!found) { 
292                bsendmsg(ua, _("Level %s not valid.\n"), level_name);
293                free_jcr(jcr);
294                return 1;
295             }
296          }
297          level_name = NULL;
298          bsendmsg(ua, _("Run %s job\n\
299 JobName:  %s\n\
300 FileSet:  %s\n\
301 Level:    %s\n\
302 Client:   %s\n\
303 Storage:  %s\n"),
304                  jcr->JobType==JT_BACKUP?_("Backup"):_("Verify"),
305                  job->hdr.name,
306                  jcr->fileset->hdr.name,
307                  level_to_str(jcr->JobLevel),
308                  jcr->client->hdr.name,
309                  jcr->store->hdr.name);
310          break;
311       case JT_RESTORE:
312          if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
313             if (jid) {
314                jcr->RestoreJobId = atoi(jid);
315             } else {
316                if (!get_cmd(ua, _("Please enter a JobId for restore: "))) {
317                   free_jcr(jcr);
318                   return 1;
319                }  
320                jcr->RestoreJobId = atoi(ua->cmd);
321             }
322          }
323          jcr->JobLevel = 'F';         /* default level */
324          Dmsg1(20, "JobId to restore=%d\n", jcr->RestoreJobId);
325          bsendmsg(ua, _("Run Restore job\n\
326 JobName:    %s\n\
327 Bootstrap:  %s\n\
328 Where:      %s\n\
329 FileSet:    %s\n\
330 Client:     %s\n\
331 Storage:    %s\n\
332 JobId:      %s\n"),
333                  job->hdr.name,
334                  NPRT(jcr->RestoreBootstrap),
335                  jcr->RestoreWhere?jcr->RestoreWhere:NPRT(job->RestoreWhere),
336                  jcr->fileset->hdr.name,
337                  jcr->client->hdr.name,
338                  jcr->store->hdr.name, 
339                  jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1));
340          break;
341       default:
342          bsendmsg(ua, _("Unknown Job Type=%d\n"), jcr->JobType);
343          free_jcr(jcr);
344          return 0;
345    }
346    if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
347       free_jcr(jcr);
348       return 0;                       /* do not run */
349    }
350    /*
351     * At user request modify parameters of job to be run.
352     */
353    if (strlen(ua->cmd) == 0) {
354       bsendmsg(ua, _("Job not run.\n"));
355       free_jcr(jcr);
356       return 0;                       /* do not run */
357    }
358    if (strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
359       FILE *fd;
360
361       start_prompt(ua, _("Parameters to modify:\n"));
362       add_prompt(ua, _("Level"));            /* 0 */
363       add_prompt(ua, _("Storage"));          /* 1 */
364       add_prompt(ua, _("Job"));              /* 2 */
365       add_prompt(ua, _("FileSet"));          /* 3 */
366       add_prompt(ua, _("Client"));           /* 4 */
367       if (jcr->JobType == JT_RESTORE) {
368          add_prompt(ua, _("Bootstrap"));     /* 5 */
369          add_prompt(ua, _("Where"));         /* 6 */
370          add_prompt(ua, _("JobId"));         /* 7 */
371       }
372       switch (do_prompt(ua, _("Select parameter to modify"), NULL)) {
373       case 0:
374          /* Level */
375          if (jcr->JobType == JT_BACKUP) {
376             start_prompt(ua, _("Levels:\n"));
377             add_prompt(ua, _("Full"));
378             add_prompt(ua, _("Incremental"));
379             add_prompt(ua, _("Differential"));
380             add_prompt(ua, _("Level"));
381             add_prompt(ua, _("Since"));
382             switch (do_prompt(ua, _("Select level"), NULL)) {
383             case 0:
384                jcr->JobLevel = L_FULL;
385                break;
386             case 1:
387                jcr->JobLevel = L_INCREMENTAL;
388                break;
389             case 2:
390                jcr->JobLevel = L_DIFFERENTIAL;
391                break;
392             case 3:
393                jcr->JobLevel = L_LEVEL;
394                break;
395             case 4:
396                jcr->JobLevel = L_SINCE;
397                break;
398             default:
399                break;
400             }
401             goto try_again;
402          } else if (jcr->JobType == JT_VERIFY) {
403             start_prompt(ua, _("Levels:\n"));
404             add_prompt(ua, _("Initialize Catalog"));
405             add_prompt(ua, _("Verify Catalog"));
406             add_prompt(ua, _("Verify Volume"));
407             add_prompt(ua, _("Verify Volume Data"));
408             switch (do_prompt(ua, _("Select level"), NULL)) {
409             case 0:
410                jcr->JobLevel = L_VERIFY_INIT;
411                break;
412             case 1:
413                jcr->JobLevel = L_VERIFY_CATALOG;
414                break;
415             case 2:
416                jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
417                break;
418             case 3:
419                jcr->JobLevel = L_VERIFY_DATA;
420                break;
421             default:
422                break;
423             }
424             goto try_again;
425          } else {
426             bsendmsg(ua, _("Level not appropriate for this Job. Cannot be changed.\n"));
427          }
428          goto try_again;
429       case 1:
430          store = select_storage_resource(ua);
431          if (store) {
432             jcr->store = store;
433             goto try_again;
434          }
435          break;
436       case 2:
437          /* Job */
438          job = select_job_resource(ua);
439          if (job) {
440             jcr->job = job;
441             set_jcr_defaults(jcr, job);
442             goto try_again;
443          }
444          break;
445       case 3:
446          /* FileSet */
447          fileset = select_fileset_resource(ua);
448          if (fileset) {
449             jcr->fileset = fileset;
450             goto try_again;
451          }      
452          break;
453       case 4:
454          client = select_client_resource(ua);
455          if (client) {
456             jcr->client = client;
457             goto try_again;
458          }
459          break;
460       case 5:
461          /* Bootstrap */
462          if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
463             break;
464          }
465          if (jcr->RestoreBootstrap) {
466             free(jcr->RestoreBootstrap);
467             jcr->RestoreBootstrap = NULL;
468          }
469          if (ua->cmd[0] != 0) {
470             jcr->RestoreBootstrap = bstrdup(ua->cmd);
471             fd = fopen(jcr->RestoreBootstrap, "r");
472             if (!fd) {
473                bsendmsg(ua, _("Warning cannot open %s: ERR=%s\n"),
474                   jcr->RestoreBootstrap, strerror(errno));
475                free(jcr->RestoreBootstrap);
476                jcr->RestoreBootstrap = NULL;
477             } else {
478                fclose(fd);
479             }
480          }
481          goto try_again;
482       case 6:
483          /* Where */
484          if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
485             break;
486          }
487          if (jcr->RestoreWhere) {
488             free(jcr->RestoreWhere);
489             jcr->RestoreWhere = NULL;
490          }
491          if (ua->cmd[0] == '/' && ua->cmd[1] == 0) {
492             ua->cmd[0] = 0;
493          }
494          jcr->RestoreWhere = bstrdup(ua->cmd);
495          goto try_again;
496       case 7:
497          /* JobId */
498          jid = NULL;                  /* force reprompt */
499          jcr->RestoreJobId = 0;
500          if (jcr->RestoreBootstrap) {
501             bsendmsg(ua, _("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
502          }
503          goto try_again;
504       default: 
505          goto try_again;
506       }
507       bsendmsg(ua, _("Job not run.\n"));
508       free_jcr(jcr);
509       return 0;                       /* error do no run Job */
510    }
511    if (strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
512       Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
513       run_job(jcr);
514       return 1;
515    }
516
517    bsendmsg(ua, _("Job not run.\n"));
518    free_jcr(jcr);
519    return 0;                       /* do not run */
520
521 }