3 * Bacula Director -- Run Command
5 * Kern Sibbald, December MMI
11 Copyright (C) 2001-2003 Kern Sibbald and John Walker
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.
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.
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,
34 /* Imported subroutines */
35 extern void run_job(JCR *jcr);
37 /* Imported variables */
38 extern struct s_jl joblevels[];
39 extern struct s_kw ReplaceOptions[];
42 * For Backup and Verify Jobs
43 * run [job=]<job-name> level=<level-name>
46 * run <job-name> jobid=nn
49 int runcmd(UAContext *ua, char *cmd)
52 char *job_name, *level_name, *jid, *store_name, *pool_name;
53 char *where, *fileset_name, *client_name, *bootstrap, *replace;
57 CLIENT *client = NULL;
58 FILESET *fileset = NULL;
88 for (i=1; i<ua->argc; i++) {
90 Dmsg2(200, "Doing arg %d = %s\n", i, ua->argk[i]);
91 for (j=0; !found && kw[j]; j++) {
92 if (strcasecmp(ua->argk[i], _(kw[j])) == 0) {
94 bsendmsg(ua, _("Value missing for keyword %s\n"), ua->argk[i]);
97 Dmsg1(200, "Got keyword=%s\n", kw[j]);
101 bsendmsg(ua, _("Job name specified twice.\n"));
104 job_name = ua->argv[i];
109 bsendmsg(ua, _("JobId specified twice.\n"));
117 bsendmsg(ua, _("Client specified twice.\n"));
120 client_name = ua->argv[i];
123 case 3: /* fileset */
125 bsendmsg(ua, _("FileSet specified twice.\n"));
128 fileset_name = ua->argv[i];
133 bsendmsg(ua, _("Level specified twice.\n"));
136 level_name = ua->argv[i];
139 case 5: /* storage */
141 bsendmsg(ua, _("Storage specified twice.\n"));
144 store_name = ua->argv[i];
149 bsendmsg(ua, _("Pool specified twice.\n"));
152 pool_name = ua->argv[i];
157 bsendmsg(ua, _("Where specified twice.\n"));
163 case 8: /* bootstrap */
165 bsendmsg(ua, _("Bootstrap specified twice.\n"));
168 bootstrap = ua->argv[i];
171 case 9: /* replace */
173 bsendmsg(ua, _("Replace specified twice.\n"));
176 replace = ua->argv[i];
182 } /* end strcase compare */
183 } /* end keyword loop */
185 Dmsg1(200, "%s not found\n", ua->argk[i]);
187 * Special case for Job Name, it can be the first
188 * keyword that has no value.
190 if (!job_name && !ua->argv[i]) {
191 job_name = ua->argk[i]; /* use keyword as job name */
192 Dmsg1(200, "Set jobname=%s\n", job_name);
194 bsendmsg(ua, _("Invalid keyword: %s\n"), ua->argk[i]);
198 } /* end argc loop */
200 Dmsg0(200, "Done scan.\n");
206 job = (JOB *)GetResWithName(R_JOB, job_name);
208 bsendmsg(ua, _("Job \"%s\" not found\n"), job_name);
209 job = select_job_resource(ua);
211 Dmsg1(200, "Found job=%s\n", job_name);
214 bsendmsg(ua, _("A job name must be specified.\n"));
215 job = select_job_resource(ua);
222 store = (STORE *)GetResWithName(R_STORAGE, store_name);
224 bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name);
225 store = select_storage_resource(ua);
228 store = job->storage; /* use default */
236 pool = (POOL *)GetResWithName(R_POOL, pool_name);
238 bsendmsg(ua, _("Pool \"%s\" not found.\n"), pool_name);
239 pool = get_pool_resource(ua);
242 pool = job->pool; /* use default */
246 client = (CLIENT *)GetResWithName(R_CLIENT, client_name);
248 bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name);
249 client = select_client_resource(ua);
252 client = job->client; /* use default */
259 fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name);
261 bsendmsg(ua, _("FileSet \"%s\" not found.\n"), fileset_name);
262 fileset = select_fileset_resource(ua);
265 fileset = job->fileset; /* use default */
272 /* Create JCR to run job */
273 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
274 set_jcr_defaults(jcr, job);
277 jcr->client = client;
278 jcr->fileset = fileset;
281 if (jcr->RestoreWhere) {
282 free(jcr->RestoreWhere);
284 jcr->RestoreWhere = bstrdup(where);
287 if (jcr->RestoreBootstrap) {
288 free(jcr->RestoreBootstrap);
290 jcr->RestoreBootstrap = bstrdup(bootstrap);
295 for (i=0; ReplaceOptions[i].name; i++) {
296 if (strcasecmp(replace, ReplaceOptions[i].name) == 0) {
297 jcr->replace = ReplaceOptions[i].token;
301 bsendmsg(ua, _("Invalid replace option: %s\n"), replace);
304 } else if (job->replace) {
305 jcr->replace = job->replace;
307 jcr->replace = REPLACE_ALWAYS;
311 replace = ReplaceOptions[0].name;
312 for (i=0; ReplaceOptions[i].name; i++) {
313 if (ReplaceOptions[i].token == jcr->replace) {
314 replace = ReplaceOptions[i].name;
317 Dmsg1(20, "JobType=%c\n", jcr->JobType);
318 switch (jcr->JobType) {
321 bsendmsg(ua, _("Run %s job\n\
328 jcr->fileset->hdr.name,
329 NPRT(jcr->client->hdr.name),
330 NPRT(jcr->store->hdr.name));
336 /* Look up level name and pull code */
338 for (i=0; joblevels[i].level_name; i++) {
339 if (strcasecmp(level_name, _(joblevels[i].level_name)) == 0) {
340 jcr->JobLevel = joblevels[i].level;
346 bsendmsg(ua, _("Level %s not valid.\n"), level_name);
352 bsendmsg(ua, _("Run %s job\n\
359 jcr->JobType==JT_BACKUP?_("Backup"):_("Verify"),
361 jcr->fileset->hdr.name,
362 level_to_str(jcr->JobLevel),
363 jcr->client->hdr.name,
364 jcr->store->hdr.name,
365 NPRT(jcr->pool->hdr.name));
368 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
370 jcr->RestoreJobId = atoi(jid);
372 if (!get_cmd(ua, _("Please enter a JobId for restore: "))) {
376 jcr->RestoreJobId = atoi(ua->cmd);
379 jcr->JobLevel = 'F'; /* default level */
380 Dmsg1(20, "JobId to restore=%d\n", jcr->RestoreJobId);
381 bsendmsg(ua, _("Run Restore job\n\
391 NPRT(jcr->RestoreBootstrap),
392 jcr->RestoreWhere?jcr->RestoreWhere:NPRT(job->RestoreWhere),
394 jcr->fileset->hdr.name,
395 jcr->client->hdr.name,
396 jcr->store->hdr.name,
397 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1));
400 bsendmsg(ua, _("Unknown Job Type=%d\n"), jcr->JobType);
404 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
406 return 0; /* do not run */
409 * At user request modify parameters of job to be run.
411 if (strlen(ua->cmd) == 0) {
412 bsendmsg(ua, _("Job not run.\n"));
414 return 0; /* do not run */
416 if (strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
419 start_prompt(ua, _("Parameters to modify:\n"));
420 add_prompt(ua, _("Level")); /* 0 */
421 add_prompt(ua, _("Storage")); /* 1 */
422 add_prompt(ua, _("Job")); /* 2 */
423 add_prompt(ua, _("FileSet")); /* 3 */
424 add_prompt(ua, _("Client")); /* 4 */
425 if (jcr->JobType == JT_BACKUP ||
426 jcr->JobType == JT_VERIFY) {
427 add_prompt(ua, _("Pool")); /* 5 */
428 } else if (jcr->JobType == JT_RESTORE) {
429 add_prompt(ua, _("Bootstrap")); /* 5 */
430 add_prompt(ua, _("Where")); /* 6 */
431 add_prompt(ua, _("Replace")); /* 7 */
432 add_prompt(ua, _("JobId")); /* 8 */
434 switch (do_prompt(ua, _("Select parameter to modify"), NULL, 0)) {
437 if (jcr->JobType == JT_BACKUP) {
438 start_prompt(ua, _("Levels:\n"));
439 add_prompt(ua, _("Full"));
440 add_prompt(ua, _("Incremental"));
441 add_prompt(ua, _("Differential"));
442 add_prompt(ua, _("Since"));
443 switch (do_prompt(ua, _("Select level"), NULL, 0)) {
445 jcr->JobLevel = L_FULL;
448 jcr->JobLevel = L_INCREMENTAL;
451 jcr->JobLevel = L_DIFFERENTIAL;
454 jcr->JobLevel = L_SINCE;
460 } else if (jcr->JobType == JT_VERIFY) {
461 start_prompt(ua, _("Levels:\n"));
462 add_prompt(ua, _("Initialize Catalog"));
463 add_prompt(ua, _("Verify Catalog"));
464 add_prompt(ua, _("Verify Volume"));
465 add_prompt(ua, _("Verify Volume Data"));
466 switch (do_prompt(ua, _("Select level"), NULL, 0)) {
468 jcr->JobLevel = L_VERIFY_INIT;
471 jcr->JobLevel = L_VERIFY_CATALOG;
474 jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
477 jcr->JobLevel = L_VERIFY_DATA;
484 bsendmsg(ua, _("Level not appropriate for this Job. Cannot be changed.\n"));
488 store = select_storage_resource(ua);
496 job = select_job_resource(ua);
499 set_jcr_defaults(jcr, job);
505 fileset = select_fileset_resource(ua);
507 jcr->fileset = fileset;
512 client = select_client_resource(ua);
514 jcr->client = client;
519 if (jcr->JobType == JT_BACKUP ||
520 jcr->JobType == JT_VERIFY) { /* Pool */
521 pool = select_pool_resource(ua);
530 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
533 if (jcr->RestoreBootstrap) {
534 free(jcr->RestoreBootstrap);
535 jcr->RestoreBootstrap = NULL;
537 if (ua->cmd[0] != 0) {
538 jcr->RestoreBootstrap = bstrdup(ua->cmd);
539 fd = fopen(jcr->RestoreBootstrap, "r");
541 bsendmsg(ua, _("Warning cannot open %s: ERR=%s\n"),
542 jcr->RestoreBootstrap, strerror(errno));
543 free(jcr->RestoreBootstrap);
544 jcr->RestoreBootstrap = NULL;
552 if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
555 if (jcr->RestoreWhere) {
556 free(jcr->RestoreWhere);
557 jcr->RestoreWhere = NULL;
559 if (ua->cmd[0] == '/' && ua->cmd[1] == 0) {
562 jcr->RestoreWhere = bstrdup(ua->cmd);
566 start_prompt(ua, _("Replace:\n"));
567 for (i=0; ReplaceOptions[i].name; i++) {
568 add_prompt(ua, ReplaceOptions[i].name);
570 opt = do_prompt(ua, _("Select replace option"), NULL, 0);
572 jcr->replace = ReplaceOptions[opt].token;
577 jid = NULL; /* force reprompt */
578 jcr->RestoreJobId = 0;
579 if (jcr->RestoreBootstrap) {
580 bsendmsg(ua, _("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
586 bsendmsg(ua, _("Job not run.\n"));
588 return 0; /* error do no run Job */
590 if (strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
591 Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
596 bsendmsg(ua, _("Job not run.\n"));
598 return 0; /* do not run */