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,
33 /* Imported subroutines */
35 /* Imported variables */
36 extern struct s_jl joblevels[];
37 extern struct s_kw ReplaceOptions[];
40 * For Backup and Verify Jobs
41 * run [job=]<job-name> level=<level-name>
44 * run <job-name> jobid=nn
47 int run_cmd(UAContext *ua, char *cmd)
50 char *job_name, *level_name, *jid, *store_name, *pool_name;
51 char *where, *fileset_name, *client_name, *bootstrap, *replace;
57 CLIENT *client = NULL;
58 FILESET *fileset = NULL;
60 static char *kw[] = { /* command line arguments */
73 N_("yes"), /* 12 -- if you change this change YES_POS too */
74 N_("run"), /* 13 -- if you change this change RUN_POS too */
96 for (i=1; i<ua->argc; i++) {
98 Dmsg2(200, "Doing arg %d = %s\n", i, ua->argk[i]);
99 for (j=0; !found && kw[j]; j++) {
100 if (strcasecmp(ua->argk[i], _(kw[j])) == 0) {
101 /* Note, yes and run have no value, so do not err */
102 if (!ua->argv[i] && (j != YES_POS /*yes*/ && j != RUN_POS)) {
103 bsendmsg(ua, _("Value missing for keyword %s\n"), ua->argk[i]);
106 Dmsg1(200, "Got keyword=%s\n", kw[j]);
110 bsendmsg(ua, _("Job name specified twice.\n"));
113 job_name = ua->argv[i];
118 bsendmsg(ua, _("JobId specified twice.\n"));
126 bsendmsg(ua, _("Client specified twice.\n"));
129 client_name = ua->argv[i];
132 case 3: /* fileset */
134 bsendmsg(ua, _("FileSet specified twice.\n"));
137 fileset_name = ua->argv[i];
142 bsendmsg(ua, _("Level specified twice.\n"));
145 level_name = ua->argv[i];
148 case 5: /* storage */
150 bsendmsg(ua, _("Storage specified twice.\n"));
153 store_name = ua->argv[i];
158 bsendmsg(ua, _("Pool specified twice.\n"));
161 pool_name = ua->argv[i];
166 bsendmsg(ua, _("Where specified twice.\n"));
172 case 8: /* bootstrap */
174 bsendmsg(ua, _("Bootstrap specified twice.\n"));
177 bootstrap = ua->argv[i];
180 case 9: /* replace */
182 bsendmsg(ua, _("Replace specified twice.\n"));
185 replace = ua->argv[i];
190 bsendmsg(ua, _("When specified twice.\n"));
196 case 11: /* Priority */
198 bsendmsg(ua, _("Priority specified twice.\n"));
201 Priority = atoi(ua->argv[i]);
203 bsendmsg(ua, _("Priority must be positive nonzero setting it to 10.\n"));
214 } /* end strcase compare */
215 } /* end keyword loop */
217 Dmsg1(200, "%s not found\n", ua->argk[i]);
219 * Special case for Job Name, it can be the first
220 * keyword that has no value.
222 if (!job_name && !ua->argv[i]) {
223 job_name = ua->argk[i]; /* use keyword as job name */
224 Dmsg1(200, "Set jobname=%s\n", job_name);
226 bsendmsg(ua, _("Invalid keyword: %s\n"), ua->argk[i]);
230 } /* end argc loop */
232 Dmsg0(200, "Done scan.\n");
238 job = (JOB *)GetResWithName(R_JOB, job_name);
240 bsendmsg(ua, _("Job \"%s\" not found\n"), job_name);
241 job = select_job_resource(ua);
243 Dmsg1(200, "Found job=%s\n", job_name);
246 bsendmsg(ua, _("A job name must be specified.\n"));
247 job = select_job_resource(ua);
254 store = (STORE *)GetResWithName(R_STORAGE, store_name);
256 bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name);
257 store = select_storage_resource(ua);
260 store = job->storage; /* use default */
268 pool = (POOL *)GetResWithName(R_POOL, pool_name);
270 bsendmsg(ua, _("Pool \"%s\" not found.\n"), pool_name);
271 pool = get_pool_resource(ua);
274 pool = job->pool; /* use default */
278 client = (CLIENT *)GetResWithName(R_CLIENT, client_name);
280 bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name);
281 client = select_client_resource(ua);
284 client = job->client; /* use default */
291 fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name);
293 bsendmsg(ua, _("FileSet \"%s\" not found.\n"), fileset_name);
294 fileset = select_fileset_resource(ua);
297 fileset = job->fileset; /* use default */
304 /* Create JCR to run job */
305 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
306 set_jcr_defaults(jcr, job);
309 jcr->client = client;
310 jcr->fileset = fileset;
316 jcr->where = bstrdup(where);
320 jcr->sched_time = str_to_utime(when);
321 if (jcr->sched_time == 0) {
322 bsendmsg(ua, _("Invalid time, using current time.\n"));
323 jcr->sched_time = time(NULL);
328 if (jcr->RestoreBootstrap) {
329 free(jcr->RestoreBootstrap);
331 jcr->RestoreBootstrap = bstrdup(bootstrap);
336 for (i=0; ReplaceOptions[i].name; i++) {
337 if (strcasecmp(replace, ReplaceOptions[i].name) == 0) {
338 jcr->replace = ReplaceOptions[i].token;
342 bsendmsg(ua, _("Invalid replace option: %s\n"), replace);
345 } else if (job->replace) {
346 jcr->replace = job->replace;
348 jcr->replace = REPLACE_ALWAYS;
352 jcr->JobPriority = Priority;
356 replace = ReplaceOptions[0].name;
357 for (i=0; ReplaceOptions[i].name; i++) {
358 if (ReplaceOptions[i].token == jcr->replace) {
359 replace = ReplaceOptions[i].name;
362 Dmsg1(20, "JobType=%c\n", jcr->JobType);
363 switch (jcr->JobType) {
365 char dt[MAX_TIME_LENGTH];
367 bsendmsg(ua, _("Run %s job\n\
376 jcr->fileset->hdr.name,
377 NPRT(jcr->client->hdr.name),
378 NPRT(jcr->store->hdr.name),
379 bstrutime(dt, sizeof(dt), jcr->sched_time),
381 jcr->JobLevel = L_FULL;
386 /* Look up level name and pull code */
388 for (i=0; joblevels[i].level_name; i++) {
389 if (strcasecmp(level_name, _(joblevels[i].level_name)) == 0) {
390 jcr->JobLevel = joblevels[i].level;
396 bsendmsg(ua, _("Level %s not valid.\n"), level_name);
402 bsendmsg(ua, _("Run %s job\n\
411 jcr->JobType==JT_BACKUP?_("Backup"):_("Verify"),
413 jcr->fileset->hdr.name,
414 level_to_str(jcr->JobLevel),
415 jcr->client->hdr.name,
416 jcr->store->hdr.name,
417 NPRT(jcr->pool->hdr.name),
418 bstrutime(dt, sizeof(dt), jcr->sched_time),
422 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
424 jcr->RestoreJobId = atoi(jid);
426 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
430 jcr->RestoreJobId = ua->pint32_val;
433 jcr->JobLevel = L_FULL; /* default level */
434 Dmsg1(20, "JobId to restore=%d\n", jcr->RestoreJobId);
435 if (jcr->RestoreJobId == 0) {
436 bsendmsg(ua, _("Run Restore job\n\
447 NPRT(jcr->RestoreBootstrap),
448 jcr->where?jcr->where:NPRT(job->RestoreWhere),
450 jcr->fileset->hdr.name,
451 jcr->client->hdr.name,
452 jcr->store->hdr.name,
453 bstrutime(dt, sizeof(dt), jcr->sched_time),
456 bsendmsg(ua, _("Run Restore job\n\
468 NPRT(jcr->RestoreBootstrap),
469 jcr->where?jcr->where:NPRT(job->RestoreWhere),
471 jcr->fileset->hdr.name,
472 jcr->client->hdr.name,
473 jcr->store->hdr.name,
474 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
475 bstrutime(dt, sizeof(dt), jcr->sched_time),
480 bsendmsg(ua, _("Unknown Job Type=%d\n"), jcr->JobType);
485 /* Run without prompting? */
486 if (find_arg(ua, _("yes")) > 0) {
487 Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
489 bsendmsg(ua, _("Run command submitted.\n"));
493 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
495 return 0; /* do not run */
498 * At user request modify parameters of job to be run.
500 if (ua->cmd[0] == 0) {
501 bsendmsg(ua, _("Job not run.\n"));
503 return 0; /* do not run */
505 if (strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
508 start_prompt(ua, _("Parameters to modify:\n"));
509 add_prompt(ua, _("Level")); /* 0 */
510 add_prompt(ua, _("Storage")); /* 1 */
511 add_prompt(ua, _("Job")); /* 2 */
512 add_prompt(ua, _("FileSet")); /* 3 */
513 add_prompt(ua, _("Client")); /* 4 */
514 add_prompt(ua, _("When")); /* 5 */
515 add_prompt(ua, _("Priority")); /* 6 */
516 if (jcr->JobType == JT_BACKUP ||
517 jcr->JobType == JT_VERIFY) {
518 add_prompt(ua, _("Pool")); /* 7 */
519 } else if (jcr->JobType == JT_RESTORE) {
520 add_prompt(ua, _("Bootstrap")); /* 7 */
521 add_prompt(ua, _("Where")); /* 8 */
522 add_prompt(ua, _("Replace")); /* 9 */
523 add_prompt(ua, _("JobId")); /* 10 */
525 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
528 if (jcr->JobType == JT_BACKUP) {
529 start_prompt(ua, _("Levels:\n"));
530 add_prompt(ua, _("Base"));
531 add_prompt(ua, _("Full"));
532 add_prompt(ua, _("Incremental"));
533 add_prompt(ua, _("Differential"));
534 add_prompt(ua, _("Since"));
535 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
537 jcr->JobLevel = L_BASE;
540 jcr->JobLevel = L_FULL;
543 jcr->JobLevel = L_INCREMENTAL;
546 jcr->JobLevel = L_DIFFERENTIAL;
549 jcr->JobLevel = L_SINCE;
555 } else if (jcr->JobType == JT_VERIFY) {
556 start_prompt(ua, _("Levels:\n"));
557 add_prompt(ua, _("Initialize Catalog"));
558 add_prompt(ua, _("Verify Catalog"));
559 add_prompt(ua, _("Verify Volume to Catalog"));
560 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
561 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
563 jcr->JobLevel = L_VERIFY_INIT;
566 jcr->JobLevel = L_VERIFY_CATALOG;
569 jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
572 jcr->JobLevel = L_VERIFY_DATA;
579 bsendmsg(ua, _("Level not appropriate for this Job. Cannot be changed.\n"));
584 store = select_storage_resource(ua);
592 job = select_job_resource(ua);
595 set_jcr_defaults(jcr, job);
601 fileset = select_fileset_resource(ua);
603 jcr->fileset = fileset;
609 client = select_client_resource(ua);
611 jcr->client = client;
617 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
620 if (ua->cmd[0] == 0) {
621 jcr->sched_time = time(NULL);
623 jcr->sched_time = str_to_utime(ua->cmd);
624 if (jcr->sched_time == 0) {
625 bsendmsg(ua, _("Invalid time, using current time.\n"));
626 jcr->sched_time = time(NULL);
632 if (!get_pint(ua, _("Enter new Priority: "))) {
635 if (ua->pint32_val == 0) {
636 bsendmsg(ua, _("Priority must be a positive integer.\n"));
638 jcr->JobPriority = ua->pint32_val;
642 if (jcr->JobType == JT_BACKUP ||
643 jcr->JobType == JT_VERIFY) { /* Pool */
644 pool = select_pool_resource(ua);
653 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
656 if (jcr->RestoreBootstrap) {
657 free(jcr->RestoreBootstrap);
658 jcr->RestoreBootstrap = NULL;
660 if (ua->cmd[0] != 0) {
661 jcr->RestoreBootstrap = bstrdup(ua->cmd);
662 fd = fopen(jcr->RestoreBootstrap, "r");
664 bsendmsg(ua, _("Warning cannot open %s: ERR=%s\n"),
665 jcr->RestoreBootstrap, strerror(errno));
666 free(jcr->RestoreBootstrap);
667 jcr->RestoreBootstrap = NULL;
675 if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
682 if (ua->cmd[0] == '/' && ua->cmd[1] == 0) {
685 jcr->where = bstrdup(ua->cmd);
689 start_prompt(ua, _("Replace:\n"));
690 for (i=0; ReplaceOptions[i].name; i++) {
691 add_prompt(ua, ReplaceOptions[i].name);
693 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
695 jcr->replace = ReplaceOptions[opt].token;
700 jid = NULL; /* force reprompt */
701 jcr->RestoreJobId = 0;
702 if (jcr->RestoreBootstrap) {
703 bsendmsg(ua, _("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
709 bsendmsg(ua, _("Job not run.\n"));
711 return 0; /* error do no run Job */
714 if (strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
715 Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
717 bsendmsg(ua, _("Run command submitted.\n"));
721 bsendmsg(ua, _("Job not run.\n"));
723 return 0; /* do not run */