3 * Bacula Director -- Run Command
5 * Kern Sibbald, December MMI
11 Copyright (C) 2001-2004 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, const char *cmd)
50 char *job_name, *level_name, *jid, *store_name, *pool_name;
51 char *where, *fileset_name, *client_name, *bootstrap;
53 char *when, *verify_job_name;
55 int i, j, opt, files = 0;
58 JOB *verify_job = NULL;
60 CLIENT *client = NULL;
61 FILESET *fileset = NULL;
63 static const char *kw[] = { /* command line arguments */
64 N_("job"), /* Used in a switch() */
68 N_("fileset"), /* 4 */
70 N_("storage"), /* 6 */
74 N_("bootstrap"), /* 10 */
75 N_("replace"), /* 11 */
77 N_("priority"), /* 13 */
78 N_("yes"), /* 14 -- if you change this change YES_POS too */
79 N_("verifyjob"), /* 15 */
80 N_("files"), /* 16 number of files to restore */
100 verify_job_name = NULL;
102 for (i=1; i<ua->argc; i++) {
103 Dmsg2(200, "Doing arg %d = %s\n", i, ua->argk[i]);
105 /* Keep looking until we find a good keyword */
106 for (j=0; !kw_ok && kw[j]; j++) {
107 if (strcasecmp(ua->argk[i], _(kw[j])) == 0) {
108 /* Note, yes and run have no value, so do not err */
109 if (!ua->argv[i] && j != YES_POS /*yes*/) {
110 bsendmsg(ua, _("Value missing for keyword %s\n"), ua->argk[i]);
113 Dmsg1(200, "Got keyword=%s\n", kw[j]);
117 bsendmsg(ua, _("Job name specified twice.\n"));
120 job_name = ua->argv[i];
125 bsendmsg(ua, _("JobId specified twice.\n"));
134 bsendmsg(ua, _("Client specified twice.\n"));
137 client_name = ua->argv[i];
140 case 4: /* fileset */
142 bsendmsg(ua, _("FileSet specified twice.\n"));
145 fileset_name = ua->argv[i];
150 bsendmsg(ua, _("Level specified twice.\n"));
153 level_name = ua->argv[i];
156 case 6: /* storage */
159 bsendmsg(ua, _("Storage specified twice.\n"));
162 store_name = ua->argv[i];
167 bsendmsg(ua, _("Pool specified twice.\n"));
170 pool_name = ua->argv[i];
175 bsendmsg(ua, _("Where specified twice.\n"));
181 case 10: /* bootstrap */
183 bsendmsg(ua, _("Bootstrap specified twice.\n"));
186 bootstrap = ua->argv[i];
189 case 11: /* replace */
191 bsendmsg(ua, _("Replace specified twice.\n"));
194 replace = ua->argv[i];
199 bsendmsg(ua, _("When specified twice.\n"));
205 case 13: /* Priority */
207 bsendmsg(ua, _("Priority specified twice.\n"));
210 Priority = atoi(ua->argv[i]);
212 bsendmsg(ua, _("Priority must be positive nonzero setting it to 10.\n"));
220 case 15: /* Verify Job */
221 if (verify_job_name) {
222 bsendmsg(ua, _("Verify Job specified twice.\n"));
225 verify_job_name = ua->argv[i];
229 files = atoi(ua->argv[i]);
236 } /* end strcase compare */
237 } /* end keyword loop */
239 * End of keyword for loop -- if not found, we got a bogus keyword
242 Dmsg1(200, "%s not found\n", ua->argk[i]);
244 * Special case for Job Name, it can be the first
245 * keyword that has no value.
247 if (!job_name && !ua->argv[i]) {
248 job_name = ua->argk[i]; /* use keyword as job name */
249 Dmsg1(200, "Set jobname=%s\n", job_name);
251 bsendmsg(ua, _("Invalid keyword: %s\n"), ua->argk[i]);
255 } /* end argc loop */
257 Dmsg0(200, "Done scan.\n");
261 job = (JOB *)GetResWithName(R_JOB, job_name);
263 if (*job_name != 0) {
264 bsendmsg(ua, _("Job \"%s\" not found\n"), job_name);
266 job = select_job_resource(ua);
268 Dmsg1(200, "Found job=%s\n", job_name);
271 bsendmsg(ua, _("A job name must be specified.\n"));
272 job = select_job_resource(ua);
279 store = (STORE *)GetResWithName(R_STORAGE, store_name);
281 if (*store_name != 0) {
282 bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name);
284 store = select_storage_resource(ua);
287 store = job->storage; /* use default */
295 pool = (POOL *)GetResWithName(R_POOL, pool_name);
297 if (*pool_name != 0) {
298 bsendmsg(ua, _("Pool \"%s\" not found.\n"), pool_name);
300 pool = select_pool_resource(ua);
303 pool = job->pool; /* use default */
310 client = (CLIENT *)GetResWithName(R_CLIENT, client_name);
312 if (*client_name != 0) {
313 bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name);
315 client = select_client_resource(ua);
318 client = job->client; /* use default */
325 fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name);
327 bsendmsg(ua, _("FileSet \"%s\" not found.\n"), fileset_name);
328 fileset = select_fileset_resource(ua);
331 fileset = job->fileset; /* use default */
337 if (verify_job_name) {
338 verify_job = (JOB *)GetResWithName(R_JOB, verify_job_name);
340 bsendmsg(ua, _("Verify Job \"%s\" not found.\n"), verify_job_name);
341 verify_job = select_job_resource(ua);
344 verify_job = job->verify_job;
348 * Create JCR to run job. NOTE!!! after this point, free_jcr()
351 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
352 set_jcr_defaults(jcr, job);
355 jcr->client = client;
356 jcr->fileset = fileset;
358 jcr->ExpectedFiles = files;
363 jcr->where = bstrdup(where);
367 jcr->sched_time = str_to_utime(when);
368 if (jcr->sched_time == 0) {
369 bsendmsg(ua, _("Invalid time, using current time.\n"));
370 jcr->sched_time = time(NULL);
375 if (jcr->RestoreBootstrap) {
376 free(jcr->RestoreBootstrap);
378 jcr->RestoreBootstrap = bstrdup(bootstrap);
383 for (i=0; ReplaceOptions[i].name; i++) {
384 if (strcasecmp(replace, ReplaceOptions[i].name) == 0) {
385 jcr->replace = ReplaceOptions[i].token;
389 bsendmsg(ua, _("Invalid replace option: %s\n"), replace);
392 } else if (job->replace) {
393 jcr->replace = job->replace;
395 jcr->replace = REPLACE_ALWAYS;
399 jcr->JobPriority = Priority;
403 replace = ReplaceOptions[0].name;
404 for (i=0; ReplaceOptions[i].name; i++) {
405 if (ReplaceOptions[i].token == jcr->replace) {
406 replace = ReplaceOptions[i].name;
410 /* Look up level name and pull code */
412 for (i=0; joblevels[i].level_name; i++) {
413 if (strcasecmp(level_name, _(joblevels[i].level_name)) == 0) {
414 jcr->JobLevel = joblevels[i].level;
420 bsendmsg(ua, _("Level %s not valid.\n"), level_name);
426 jcr->RestoreJobId = atoi(jid);
429 /* Run without prompting? */
430 if (find_arg(ua, _("yes")) > 0) {
431 Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
433 free_jcr(jcr); /* release jcr */
434 bsendmsg(ua, _("Run command submitted.\n"));
439 * Prompt User to see if all run job parameters are correct, and
440 * allow him to modify them.
442 Dmsg1(20, "JobType=%c\n", jcr->JobType);
443 switch (jcr->JobType) {
445 char dt[MAX_TIME_LENGTH];
447 bsendmsg(ua, _("Run %s job\n\
456 jcr->fileset->hdr.name,
457 NPRT(jcr->client->hdr.name),
458 NPRT(jcr->store->hdr.name),
459 bstrutime(dt, sizeof(dt), jcr->sched_time),
461 jcr->JobLevel = L_FULL;
465 if (jcr->JobType == JT_BACKUP) {
466 bsendmsg(ua, _("Run %s job\n\
477 jcr->fileset->hdr.name,
478 level_to_str(jcr->JobLevel),
479 jcr->client->hdr.name,
480 jcr->store->hdr.name,
481 NPRT(jcr->pool->hdr.name),
482 bstrutime(dt, sizeof(dt), jcr->sched_time),
484 } else { /* JT_VERIFY */
486 if (jcr->job->verify_job) {
487 Name = jcr->job->verify_job->hdr.name;
491 bsendmsg(ua, _("Run %s job\n\
503 jcr->fileset->hdr.name,
504 level_to_str(jcr->JobLevel),
505 jcr->client->hdr.name,
506 jcr->store->hdr.name,
507 NPRT(jcr->pool->hdr.name),
509 bstrutime(dt, sizeof(dt), jcr->sched_time),
514 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
516 jcr->RestoreJobId = atoi(jid);
518 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
521 jcr->RestoreJobId = ua->pint32_val;
524 jcr->JobLevel = L_FULL; /* default level */
525 Dmsg1(20, "JobId to restore=%d\n", jcr->RestoreJobId);
526 if (jcr->RestoreJobId == 0) {
527 bsendmsg(ua, _("Run Restore job\n\
538 NPRT(jcr->RestoreBootstrap),
539 jcr->where?jcr->where:NPRT(job->RestoreWhere),
541 jcr->fileset->hdr.name,
542 jcr->client->hdr.name,
543 jcr->store->hdr.name,
544 bstrutime(dt, sizeof(dt), jcr->sched_time),
547 bsendmsg(ua, _("Run Restore job\n\
559 NPRT(jcr->RestoreBootstrap),
560 jcr->where?jcr->where:NPRT(job->RestoreWhere),
562 jcr->fileset->hdr.name,
563 jcr->client->hdr.name,
564 jcr->store->hdr.name,
565 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
566 bstrutime(dt, sizeof(dt), jcr->sched_time),
571 bsendmsg(ua, _("Unknown Job Type=%d\n"), jcr->JobType);
576 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
580 * At user request modify parameters of job to be run.
582 if (ua->cmd[0] == 0) {
585 if (strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
588 start_prompt(ua, _("Parameters to modify:\n"));
589 add_prompt(ua, _("Level")); /* 0 */
590 add_prompt(ua, _("Storage")); /* 1 */
591 add_prompt(ua, _("Job")); /* 2 */
592 add_prompt(ua, _("FileSet")); /* 3 */
593 add_prompt(ua, _("Client")); /* 4 */
594 add_prompt(ua, _("When")); /* 5 */
595 add_prompt(ua, _("Priority")); /* 6 */
596 if (jcr->JobType == JT_BACKUP ||
597 jcr->JobType == JT_VERIFY) {
598 add_prompt(ua, _("Pool")); /* 7 */
599 if (jcr->JobType == JT_VERIFY) {
600 add_prompt(ua, _("Verify Job")); /* 8 */
602 } else if (jcr->JobType == JT_RESTORE) {
603 add_prompt(ua, _("Bootstrap")); /* 7 */
604 add_prompt(ua, _("Where")); /* 8 */
605 add_prompt(ua, _("Replace")); /* 9 */
606 add_prompt(ua, _("JobId")); /* 10 */
608 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
611 if (jcr->JobType == JT_BACKUP) {
612 start_prompt(ua, _("Levels:\n"));
613 add_prompt(ua, _("Base"));
614 add_prompt(ua, _("Full"));
615 add_prompt(ua, _("Incremental"));
616 add_prompt(ua, _("Differential"));
617 add_prompt(ua, _("Since"));
618 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
620 jcr->JobLevel = L_BASE;
623 jcr->JobLevel = L_FULL;
626 jcr->JobLevel = L_INCREMENTAL;
629 jcr->JobLevel = L_DIFFERENTIAL;
632 jcr->JobLevel = L_SINCE;
638 } else if (jcr->JobType == JT_VERIFY) {
639 start_prompt(ua, _("Levels:\n"));
640 add_prompt(ua, _("Initialize Catalog"));
641 add_prompt(ua, _("Verify Catalog"));
642 add_prompt(ua, _("Verify Volume to Catalog"));
643 add_prompt(ua, _("Verify Disk to Catalog"));
644 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
645 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
647 jcr->JobLevel = L_VERIFY_INIT;
650 jcr->JobLevel = L_VERIFY_CATALOG;
653 jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
656 jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
659 jcr->JobLevel = L_VERIFY_DATA;
666 bsendmsg(ua, _("Level not appropriate for this Job. Cannot be changed.\n"));
671 store = select_storage_resource(ua);
679 job = select_job_resource(ua);
682 set_jcr_defaults(jcr, job);
688 fileset = select_fileset_resource(ua);
690 jcr->fileset = fileset;
696 client = select_client_resource(ua);
698 jcr->client = client;
704 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
707 if (ua->cmd[0] == 0) {
708 jcr->sched_time = time(NULL);
710 jcr->sched_time = str_to_utime(ua->cmd);
711 if (jcr->sched_time == 0) {
712 bsendmsg(ua, _("Invalid time, using current time.\n"));
713 jcr->sched_time = time(NULL);
719 if (!get_pint(ua, _("Enter new Priority: "))) {
722 if (ua->pint32_val == 0) {
723 bsendmsg(ua, _("Priority must be a positive integer.\n"));
725 jcr->JobPriority = ua->pint32_val;
729 /* Pool or Bootstrap depending on JobType */
730 if (jcr->JobType == JT_BACKUP ||
731 jcr->JobType == JT_VERIFY) { /* Pool */
732 pool = select_pool_resource(ua);
741 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
744 if (jcr->RestoreBootstrap) {
745 free(jcr->RestoreBootstrap);
746 jcr->RestoreBootstrap = NULL;
748 if (ua->cmd[0] != 0) {
749 jcr->RestoreBootstrap = bstrdup(ua->cmd);
750 fd = fopen(jcr->RestoreBootstrap, "r");
752 bsendmsg(ua, _("Warning cannot open %s: ERR=%s\n"),
753 jcr->RestoreBootstrap, strerror(errno));
754 free(jcr->RestoreBootstrap);
755 jcr->RestoreBootstrap = NULL;
763 if (jcr->JobType == JT_VERIFY) {
764 JOB *job = select_job_resource(ua);
766 jcr->job->verify_job = job;
768 jcr->job->verify_job = NULL;
773 if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
780 if (ua->cmd[0] == '/' && ua->cmd[1] == 0) {
783 jcr->where = bstrdup(ua->cmd);
787 start_prompt(ua, _("Replace:\n"));
788 for (i=0; ReplaceOptions[i].name; i++) {
789 add_prompt(ua, ReplaceOptions[i].name);
791 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
793 jcr->replace = ReplaceOptions[opt].token;
798 jid = NULL; /* force reprompt */
799 jcr->RestoreJobId = 0;
800 if (jcr->RestoreBootstrap) {
801 bsendmsg(ua, _("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
810 if (strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
811 Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
813 free_jcr(jcr); /* release jcr */
814 bsendmsg(ua, _("Run command submitted.\n"));
819 bsendmsg(ua, _("Job not run.\n"));
821 return 0; /* do not run */