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