3 * Bacula Director -- Run Command
5 * Kern Sibbald, December MMI
11 Copyright (C) 2001-2005 Kern Sibbald
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_kw ReplaceOptions[];
39 * For Backup and Verify Jobs
40 * run [job=]<job-name> level=<level-name>
43 * run <job-name> jobid=nn
49 int run_cmd(UAContext *ua, const char *cmd)
52 char *job_name, *level_name, *jid, *store_name, *pool_name;
53 char *where, *fileset_name, *client_name, *bootstrap;
55 char *when, *verify_job_name, *catalog_name;
59 int i, j, opt, files = 0;
62 JOB *verify_job = NULL;
64 CLIENT *client = NULL;
65 FILESET *fileset = NULL;
67 static const char *kw[] = { /* command line arguments */
68 "job", /* Used in a switch() */
82 "yes", /* 14 -- if you change this change YES_POS too */
84 "files", /* 16 number of files to restore */
85 "catalog", /* 17 override catalog */
86 "since", /* 18 since */
87 "cloned", /* 19 cloned */
107 verify_job_name = NULL;
110 for (i=1; i<ua->argc; i++) {
111 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
113 /* Keep looking until we find a good keyword */
114 for (j=0; !kw_ok && kw[j]; j++) {
115 if (strcasecmp(ua->argk[i], _(kw[j])) == 0) {
116 /* Note, yes and run have no value, so do not err */
117 if (!ua->argv[i] && j != YES_POS /*yes*/) {
118 bsendmsg(ua, _("Value missing for keyword %s\n"), ua->argk[i]);
121 Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
125 bsendmsg(ua, _("Job name specified twice.\n"));
128 job_name = ua->argv[i];
133 bsendmsg(ua, _("JobId specified twice.\n"));
142 bsendmsg(ua, _("Client specified twice.\n"));
145 client_name = ua->argv[i];
148 case 4: /* fileset */
150 bsendmsg(ua, _("FileSet specified twice.\n"));
153 fileset_name = ua->argv[i];
158 bsendmsg(ua, _("Level specified twice.\n"));
161 level_name = ua->argv[i];
164 case 6: /* storage */
167 bsendmsg(ua, _("Storage specified twice.\n"));
170 store_name = ua->argv[i];
175 bsendmsg(ua, _("Pool specified twice.\n"));
178 pool_name = ua->argv[i];
183 bsendmsg(ua, _("Where specified twice.\n"));
189 case 10: /* bootstrap */
191 bsendmsg(ua, _("Bootstrap specified twice.\n"));
194 bootstrap = ua->argv[i];
197 case 11: /* replace */
199 bsendmsg(ua, _("Replace specified twice.\n"));
202 replace = ua->argv[i];
207 bsendmsg(ua, _("When specified twice.\n"));
213 case 13: /* Priority */
215 bsendmsg(ua, _("Priority specified twice.\n"));
218 Priority = atoi(ua->argv[i]);
220 bsendmsg(ua, _("Priority must be positive nonzero setting it to 10.\n"));
228 case 15: /* Verify Job */
229 if (verify_job_name) {
230 bsendmsg(ua, _("Verify Job specified twice.\n"));
233 verify_job_name = ua->argv[i];
237 files = atoi(ua->argv[i]);
241 case 17: /* catalog */
242 catalog_name = ua->argv[i];
251 case 19: /* cloned */
259 } /* end strcase compare */
260 } /* end keyword loop */
262 * End of keyword for loop -- if not found, we got a bogus keyword
265 Dmsg1(800, "%s not found\n", ua->argk[i]);
267 * Special case for Job Name, it can be the first
268 * keyword that has no value.
270 if (!job_name && !ua->argv[i]) {
271 job_name = ua->argk[i]; /* use keyword as job name */
272 Dmsg1(800, "Set jobname=%s\n", job_name);
274 bsendmsg(ua, _("Invalid keyword: %s\n"), ua->argk[i]);
278 } /* end argc loop */
280 Dmsg0(800, "Done scan.\n");
283 if (catalog_name != NULL) {
284 catalog = (CAT *)GetResWithName(R_CATALOG, catalog_name);
285 if (catalog == NULL) {
286 bsendmsg(ua, _("Catalog \"%s\" not found\n"), catalog_name);
290 Dmsg1(800, "Using catalog=%s\n", NPRT(catalog_name));
294 job = (JOB *)GetResWithName(R_JOB, job_name);
296 if (*job_name != 0) {
297 bsendmsg(ua, _("Job \"%s\" not found\n"), job_name);
299 job = select_job_resource(ua);
301 Dmsg1(800, "Found job=%s\n", job_name);
304 bsendmsg(ua, _("A job name must be specified.\n"));
305 job = select_job_resource(ua);
309 } else if (!acl_access_ok(ua, Job_ACL, job->hdr.name)) {
310 bsendmsg(ua, _("No authorization. Job \"%s\".\n"),
316 store = (STORE *)GetResWithName(R_STORAGE, store_name);
318 if (*store_name != 0) {
319 bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name);
321 store = select_storage_resource(ua);
324 store = (STORE *)job->storage->first(); /* use default */
328 } else if (!acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
329 bsendmsg(ua, _("No authorization. Storage \"%s\".\n"),
333 Dmsg1(800, "Using storage=%s\n", store->hdr.name);
336 pool = (POOL *)GetResWithName(R_POOL, pool_name);
338 if (*pool_name != 0) {
339 bsendmsg(ua, _("Pool \"%s\" not found.\n"), pool_name);
341 pool = select_pool_resource(ua);
344 pool = job->pool; /* use default */
348 } else if (!acl_access_ok(ua, Pool_ACL, pool->hdr.name)) {
349 bsendmsg(ua, _("No authorization. Pool \"%s\".\n"),
353 Dmsg1(800, "Using pool\n", pool->hdr.name);
356 client = (CLIENT *)GetResWithName(R_CLIENT, client_name);
358 if (*client_name != 0) {
359 bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name);
361 client = select_client_resource(ua);
364 client = job->client; /* use default */
368 } else if (!acl_access_ok(ua, Client_ACL, client->hdr.name)) {
369 bsendmsg(ua, _("No authorization. Client \"%s\".\n"),
373 Dmsg1(800, "Using client=%s\n", client->hdr.name);
376 fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name);
378 bsendmsg(ua, _("FileSet \"%s\" not found.\n"), fileset_name);
379 fileset = select_fileset_resource(ua);
382 fileset = job->fileset; /* use default */
386 } else if (!acl_access_ok(ua, FileSet_ACL, fileset->hdr.name)) {
387 bsendmsg(ua, _("No authorization. FileSet \"%s\".\n"),
392 if (verify_job_name) {
393 verify_job = (JOB *)GetResWithName(R_JOB, verify_job_name);
395 bsendmsg(ua, _("Verify Job \"%s\" not found.\n"), verify_job_name);
396 verify_job = select_job_resource(ua);
399 verify_job = job->verify_job;
403 * Create JCR to run job. NOTE!!! after this point, free_jcr()
406 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
407 set_jcr_defaults(jcr, job);
409 jcr->verify_job = verify_job;
410 set_storage(jcr, store);
411 jcr->client = client;
412 jcr->fileset = fileset;
414 jcr->ExpectedFiles = files;
415 if (catalog != NULL) {
416 jcr->catalog = catalog;
422 jcr->where = bstrdup(where);
426 jcr->sched_time = str_to_utime(when);
427 if (jcr->sched_time == 0) {
428 bsendmsg(ua, _("Invalid time, using current time.\n"));
429 jcr->sched_time = time(NULL);
434 if (jcr->RestoreBootstrap) {
435 free(jcr->RestoreBootstrap);
437 jcr->RestoreBootstrap = bstrdup(bootstrap);
442 for (i=0; ReplaceOptions[i].name; i++) {
443 if (strcasecmp(replace, ReplaceOptions[i].name) == 0) {
444 jcr->replace = ReplaceOptions[i].token;
448 bsendmsg(ua, _("Invalid replace option: %s\n"), replace);
451 } else if (job->replace) {
452 jcr->replace = job->replace;
454 jcr->replace = REPLACE_ALWAYS;
458 jcr->JobPriority = Priority;
463 jcr->stime = get_pool_memory(PM_MESSAGE);
465 pm_strcpy(jcr->stime, since);
468 jcr->cloned = cloned;
470 if (find_arg(ua, _("fdcalled")) > 0) {
471 jcr->file_bsock = dup_bsock(ua->UA_sock);
476 replace = ReplaceOptions[0].name;
477 for (i=0; ReplaceOptions[i].name; i++) {
478 if (ReplaceOptions[i].token == jcr->replace) {
479 replace = ReplaceOptions[i].name;
483 if (!get_level_from_name(jcr, level_name)) {
484 bsendmsg(ua, _("Level %s not valid.\n"), level_name);
489 jcr->RestoreJobId = str_to_int64(jid);
492 /* Run without prompting? */
493 if (ua->batch || find_arg(ua, _("yes")) > 0) {
498 * Prompt User to see if all run job parameters are correct, and
499 * allow him to modify them.
501 Dmsg1(800, "JobType=%c\n", jcr->JobType);
502 switch (jcr->JobType) {
504 char dt[MAX_TIME_LENGTH];
506 bsendmsg(ua, _("Run %s job\n"
515 jcr->fileset->hdr.name,
516 NPRT(jcr->client->hdr.name),
517 NPRT(jcr->store->hdr.name),
518 bstrutime(dt, sizeof(dt), jcr->sched_time),
520 jcr->JobLevel = L_FULL;
524 if (jcr->JobType == JT_BACKUP) {
525 bsendmsg(ua, _("Run %s job\n"
536 jcr->fileset->hdr.name,
537 level_to_str(jcr->JobLevel),
538 jcr->client->hdr.name,
539 jcr->store->hdr.name,
540 NPRT(jcr->pool->hdr.name),
541 bstrutime(dt, sizeof(dt), jcr->sched_time),
543 } else { /* JT_VERIFY */
545 if (jcr->verify_job) {
546 Name = jcr->verify_job->hdr.name;
550 bsendmsg(ua, _("Run %s job\n"
562 jcr->fileset->hdr.name,
563 level_to_str(jcr->JobLevel),
564 jcr->client->hdr.name,
565 jcr->store->hdr.name,
566 NPRT(jcr->pool->hdr.name),
568 bstrutime(dt, sizeof(dt), jcr->sched_time),
573 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
575 jcr->RestoreJobId = str_to_int64(jid);
577 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
580 jcr->RestoreJobId = ua->int64_val;
583 jcr->JobLevel = L_FULL; /* default level */
584 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
585 if (jcr->RestoreJobId == 0) {
586 bsendmsg(ua, _("Run Restore job\n"
598 NPRT(jcr->RestoreBootstrap),
599 jcr->where?jcr->where:NPRT(job->RestoreWhere),
601 jcr->fileset->hdr.name,
602 jcr->client->hdr.name,
603 jcr->store->hdr.name,
604 bstrutime(dt, sizeof(dt), jcr->sched_time),
605 jcr->catalog->hdr.name,
608 bsendmsg(ua, _("Run Restore job\n"
620 NPRT(jcr->RestoreBootstrap),
621 jcr->where?jcr->where:NPRT(job->RestoreWhere),
623 jcr->client->hdr.name,
624 jcr->store->hdr.name,
625 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
626 bstrutime(dt, sizeof(dt), jcr->sched_time),
627 jcr->catalog->hdr.name,
632 bsendmsg(ua, _("Unknown Job Type=%d\n"), jcr->JobType);
637 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
641 * At user request modify parameters of job to be run.
643 if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
646 start_prompt(ua, _("Parameters to modify:\n"));
647 add_prompt(ua, _("Level")); /* 0 */
648 add_prompt(ua, _("Storage")); /* 1 */
649 add_prompt(ua, _("Job")); /* 2 */
650 add_prompt(ua, _("FileSet")); /* 3 */
651 add_prompt(ua, _("Client")); /* 4 */
652 add_prompt(ua, _("When")); /* 5 */
653 add_prompt(ua, _("Priority")); /* 6 */
654 if (jcr->JobType == JT_BACKUP ||
655 jcr->JobType == JT_VERIFY) {
656 add_prompt(ua, _("Pool")); /* 7 */
657 if (jcr->JobType == JT_VERIFY) {
658 add_prompt(ua, _("Verify Job")); /* 8 */
660 } else if (jcr->JobType == JT_RESTORE) {
661 add_prompt(ua, _("Bootstrap")); /* 7 */
662 add_prompt(ua, _("Where")); /* 8 */
663 add_prompt(ua, _("Replace")); /* 9 */
664 add_prompt(ua, _("JobId")); /* 10 */
666 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
669 if (jcr->JobType == JT_BACKUP) {
670 start_prompt(ua, _("Levels:\n"));
671 add_prompt(ua, _("Base"));
672 add_prompt(ua, _("Full"));
673 add_prompt(ua, _("Incremental"));
674 add_prompt(ua, _("Differential"));
675 add_prompt(ua, _("Since"));
676 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
678 jcr->JobLevel = L_BASE;
681 jcr->JobLevel = L_FULL;
684 jcr->JobLevel = L_INCREMENTAL;
687 jcr->JobLevel = L_DIFFERENTIAL;
690 jcr->JobLevel = L_SINCE;
696 } else if (jcr->JobType == JT_VERIFY) {
697 start_prompt(ua, _("Levels:\n"));
698 add_prompt(ua, _("Initialize Catalog"));
699 add_prompt(ua, _("Verify Catalog"));
700 add_prompt(ua, _("Verify Volume to Catalog"));
701 add_prompt(ua, _("Verify Disk to Catalog"));
702 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
703 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
705 jcr->JobLevel = L_VERIFY_INIT;
708 jcr->JobLevel = L_VERIFY_CATALOG;
711 jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
714 jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
717 jcr->JobLevel = L_VERIFY_DATA;
724 bsendmsg(ua, _("Level not appropriate for this Job. Cannot be changed.\n"));
729 store = select_storage_resource(ua);
731 set_storage(jcr, store);
737 job = select_job_resource(ua);
740 set_jcr_defaults(jcr, job);
746 fileset = select_fileset_resource(ua);
748 jcr->fileset = fileset;
754 client = select_client_resource(ua);
756 jcr->client = client;
762 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
765 if (ua->cmd[0] == 0) {
766 jcr->sched_time = time(NULL);
768 jcr->sched_time = str_to_utime(ua->cmd);
769 if (jcr->sched_time == 0) {
770 bsendmsg(ua, _("Invalid time, using current time.\n"));
771 jcr->sched_time = time(NULL);
777 if (!get_pint(ua, _("Enter new Priority: "))) {
780 if (ua->pint32_val == 0) {
781 bsendmsg(ua, _("Priority must be a positive integer.\n"));
783 jcr->JobPriority = ua->pint32_val;
787 /* Pool or Bootstrap depending on JobType */
788 if (jcr->JobType == JT_BACKUP ||
789 jcr->JobType == JT_VERIFY) { /* Pool */
790 pool = select_pool_resource(ua);
799 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
802 if (jcr->RestoreBootstrap) {
803 free(jcr->RestoreBootstrap);
804 jcr->RestoreBootstrap = NULL;
806 if (ua->cmd[0] != 0) {
807 jcr->RestoreBootstrap = bstrdup(ua->cmd);
808 fd = fopen(jcr->RestoreBootstrap, "r");
810 bsendmsg(ua, _("Warning cannot open %s: ERR=%s\n"),
811 jcr->RestoreBootstrap, strerror(errno));
812 free(jcr->RestoreBootstrap);
813 jcr->RestoreBootstrap = NULL;
821 if (jcr->JobType == JT_VERIFY) {
822 verify_job = select_job_resource(ua);
824 jcr->verify_job = verify_job;
829 if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
836 if (ua->cmd[0] == '/' && ua->cmd[1] == 0) {
839 jcr->where = bstrdup(ua->cmd);
843 start_prompt(ua, _("Replace:\n"));
844 for (i=0; ReplaceOptions[i].name; i++) {
845 add_prompt(ua, ReplaceOptions[i].name);
847 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
849 jcr->replace = ReplaceOptions[opt].token;
854 jid = NULL; /* force reprompt */
855 jcr->RestoreJobId = 0;
856 if (jcr->RestoreBootstrap) {
857 bsendmsg(ua, _("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
866 if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
868 Dmsg1(800, "Calling run_job job=%x\n", jcr->job);
870 JobId = run_job(jcr);
871 free_jcr(jcr); /* release jcr */
873 bsendmsg(ua, _("Job failed.\n"));
876 bsendmsg(ua, _("Job started. JobId=%s\n"), edit_int64(JobId,ed1));
882 bsendmsg(ua, _("Job not run.\n"));
884 return 0; /* do not run */