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 */
34 extern void run_job(JCR *jcr);
36 /* Imported variables */
37 extern struct s_jl joblevels[];
38 extern struct s_kw ReplaceOptions[];
41 * For Backup and Verify Jobs
42 * run [job=]<job-name> level=<level-name>
45 * run <job-name> jobid=nn
48 int runcmd(UAContext *ua, char *cmd)
51 char *job_name, *level_name, *jid, *store_name, *pool_name;
52 char *where, *fileset_name, *client_name, *bootstrap, *replace;
57 CLIENT *client = NULL;
58 FILESET *fileset = NULL;
90 for (i=1; i<ua->argc; i++) {
92 Dmsg2(200, "Doing arg %d = %s\n", i, ua->argk[i]);
93 for (j=0; !found && kw[j]; j++) {
94 if (strcasecmp(ua->argk[i], _(kw[j])) == 0) {
96 bsendmsg(ua, _("Value missing for keyword %s\n"), ua->argk[i]);
99 Dmsg1(200, "Got keyword=%s\n", kw[j]);
103 bsendmsg(ua, _("Job name specified twice.\n"));
106 job_name = ua->argv[i];
111 bsendmsg(ua, _("JobId specified twice.\n"));
119 bsendmsg(ua, _("Client specified twice.\n"));
122 client_name = ua->argv[i];
125 case 3: /* fileset */
127 bsendmsg(ua, _("FileSet specified twice.\n"));
130 fileset_name = ua->argv[i];
135 bsendmsg(ua, _("Level specified twice.\n"));
138 level_name = ua->argv[i];
141 case 5: /* storage */
143 bsendmsg(ua, _("Storage specified twice.\n"));
146 store_name = ua->argv[i];
151 bsendmsg(ua, _("Pool specified twice.\n"));
154 pool_name = ua->argv[i];
159 bsendmsg(ua, _("Where specified twice.\n"));
165 case 8: /* bootstrap */
167 bsendmsg(ua, _("Bootstrap specified twice.\n"));
170 bootstrap = ua->argv[i];
173 case 9: /* replace */
175 bsendmsg(ua, _("Replace specified twice.\n"));
178 replace = ua->argv[i];
183 bsendmsg(ua, _("When specified twice.\n"));
192 } /* end strcase compare */
193 } /* end keyword loop */
195 Dmsg1(200, "%s not found\n", ua->argk[i]);
197 * Special case for Job Name, it can be the first
198 * keyword that has no value.
200 if (!job_name && !ua->argv[i]) {
201 job_name = ua->argk[i]; /* use keyword as job name */
202 Dmsg1(200, "Set jobname=%s\n", job_name);
204 bsendmsg(ua, _("Invalid keyword: %s\n"), ua->argk[i]);
208 } /* end argc loop */
210 Dmsg0(200, "Done scan.\n");
216 job = (JOB *)GetResWithName(R_JOB, job_name);
218 bsendmsg(ua, _("Job \"%s\" not found\n"), job_name);
219 job = select_job_resource(ua);
221 Dmsg1(200, "Found job=%s\n", job_name);
224 bsendmsg(ua, _("A job name must be specified.\n"));
225 job = select_job_resource(ua);
232 store = (STORE *)GetResWithName(R_STORAGE, store_name);
234 bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name);
235 store = select_storage_resource(ua);
238 store = job->storage; /* use default */
246 pool = (POOL *)GetResWithName(R_POOL, pool_name);
248 bsendmsg(ua, _("Pool \"%s\" not found.\n"), pool_name);
249 pool = get_pool_resource(ua);
252 pool = job->pool; /* use default */
256 client = (CLIENT *)GetResWithName(R_CLIENT, client_name);
258 bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name);
259 client = select_client_resource(ua);
262 client = job->client; /* use default */
269 fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name);
271 bsendmsg(ua, _("FileSet \"%s\" not found.\n"), fileset_name);
272 fileset = select_fileset_resource(ua);
275 fileset = job->fileset; /* use default */
282 /* Create JCR to run job */
283 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
284 set_jcr_defaults(jcr, job);
287 jcr->client = client;
288 jcr->fileset = fileset;
291 if (jcr->RestoreWhere) {
292 free(jcr->RestoreWhere);
294 jcr->RestoreWhere = bstrdup(where);
298 jcr->sched_time = str_to_utime(when);
299 if (jcr->sched_time == 0) {
300 bsendmsg(ua, _("Invalid time, using current time.\n"));
301 jcr->sched_time = time(NULL);
306 if (jcr->RestoreBootstrap) {
307 free(jcr->RestoreBootstrap);
309 jcr->RestoreBootstrap = bstrdup(bootstrap);
314 for (i=0; ReplaceOptions[i].name; i++) {
315 if (strcasecmp(replace, ReplaceOptions[i].name) == 0) {
316 jcr->replace = ReplaceOptions[i].token;
320 bsendmsg(ua, _("Invalid replace option: %s\n"), replace);
323 } else if (job->replace) {
324 jcr->replace = job->replace;
326 jcr->replace = REPLACE_ALWAYS;
330 replace = ReplaceOptions[0].name;
331 for (i=0; ReplaceOptions[i].name; i++) {
332 if (ReplaceOptions[i].token == jcr->replace) {
333 replace = ReplaceOptions[i].name;
336 Dmsg1(20, "JobType=%c\n", jcr->JobType);
337 switch (jcr->JobType) {
339 char dt[MAX_TIME_LENGTH];
341 bsendmsg(ua, _("Run %s job\n\
349 jcr->fileset->hdr.name,
350 NPRT(jcr->client->hdr.name),
351 NPRT(jcr->store->hdr.name),
352 bstrutime(dt, sizeof(dt), jcr->sched_time));
353 jcr->JobLevel = L_FULL;
358 /* Look up level name and pull code */
360 for (i=0; joblevels[i].level_name; i++) {
361 if (strcasecmp(level_name, _(joblevels[i].level_name)) == 0) {
362 jcr->JobLevel = joblevels[i].level;
368 bsendmsg(ua, _("Level %s not valid.\n"), level_name);
374 bsendmsg(ua, _("Run %s job\n\
382 jcr->JobType==JT_BACKUP?_("Backup"):_("Verify"),
384 jcr->fileset->hdr.name,
385 level_to_str(jcr->JobLevel),
386 jcr->client->hdr.name,
387 jcr->store->hdr.name,
388 NPRT(jcr->pool->hdr.name),
389 bstrutime(dt, sizeof(dt), jcr->sched_time));
392 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
394 jcr->RestoreJobId = atoi(jid);
396 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
400 jcr->RestoreJobId = ua->pint32_val;
403 jcr->JobLevel = L_FULL; /* default level */
404 Dmsg1(20, "JobId to restore=%d\n", jcr->RestoreJobId);
405 if (jcr->RestoreJobId == 0) {
406 bsendmsg(ua, _("Run Restore job\n\
416 NPRT(jcr->RestoreBootstrap),
417 jcr->RestoreWhere?jcr->RestoreWhere:NPRT(job->RestoreWhere),
419 jcr->fileset->hdr.name,
420 jcr->client->hdr.name,
421 jcr->store->hdr.name,
422 bstrutime(dt, sizeof(dt), jcr->sched_time));
424 bsendmsg(ua, _("Run Restore job\n\
434 NPRT(jcr->RestoreBootstrap),
435 jcr->RestoreWhere?jcr->RestoreWhere:NPRT(job->RestoreWhere),
437 jcr->fileset->hdr.name,
438 jcr->client->hdr.name,
439 jcr->store->hdr.name,
440 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
441 bstrutime(dt, sizeof(dt), jcr->sched_time));
445 bsendmsg(ua, _("Unknown Job Type=%d\n"), jcr->JobType);
449 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
451 return 0; /* do not run */
454 * At user request modify parameters of job to be run.
456 if (ua->cmd[0] == 0) {
457 bsendmsg(ua, _("Job not run.\n"));
459 return 0; /* do not run */
461 if (strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
464 start_prompt(ua, _("Parameters to modify:\n"));
465 add_prompt(ua, _("Level")); /* 0 */
466 add_prompt(ua, _("Storage")); /* 1 */
467 add_prompt(ua, _("Job")); /* 2 */
468 add_prompt(ua, _("FileSet")); /* 3 */
469 add_prompt(ua, _("Client")); /* 4 */
470 add_prompt(ua, _("When")); /* 5 */
471 if (jcr->JobType == JT_BACKUP ||
472 jcr->JobType == JT_VERIFY) {
473 add_prompt(ua, _("Pool")); /* 6 */
474 } else if (jcr->JobType == JT_RESTORE) {
475 add_prompt(ua, _("Bootstrap")); /* 6 */
476 add_prompt(ua, _("Where")); /* 7 */
477 add_prompt(ua, _("Replace")); /* 8 */
478 add_prompt(ua, _("JobId")); /* 9 */
480 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
483 if (jcr->JobType == JT_BACKUP) {
484 start_prompt(ua, _("Levels:\n"));
485 add_prompt(ua, _("Base"));
486 add_prompt(ua, _("Full"));
487 add_prompt(ua, _("Incremental"));
488 add_prompt(ua, _("Differential"));
489 add_prompt(ua, _("Since"));
490 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
492 jcr->JobLevel = L_BASE;
495 jcr->JobLevel = L_FULL;
498 jcr->JobLevel = L_INCREMENTAL;
501 jcr->JobLevel = L_DIFFERENTIAL;
504 jcr->JobLevel = L_SINCE;
510 } else if (jcr->JobType == JT_VERIFY) {
511 start_prompt(ua, _("Levels:\n"));
512 add_prompt(ua, _("Initialize Catalog"));
513 add_prompt(ua, _("Verify Catalog"));
514 add_prompt(ua, _("Verify Volume"));
515 add_prompt(ua, _("Verify Volume Data"));
516 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
518 jcr->JobLevel = L_VERIFY_INIT;
521 jcr->JobLevel = L_VERIFY_CATALOG;
524 jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
527 jcr->JobLevel = L_VERIFY_DATA;
534 bsendmsg(ua, _("Level not appropriate for this Job. Cannot be changed.\n"));
539 store = select_storage_resource(ua);
547 job = select_job_resource(ua);
550 set_jcr_defaults(jcr, job);
556 fileset = select_fileset_resource(ua);
558 jcr->fileset = fileset;
564 client = select_client_resource(ua);
566 jcr->client = client;
572 if (!get_cmd(ua, _("Please enter scheduled start time (return for now): "))) {
575 if (ua->cmd[0] == 0) {
576 jcr->sched_time = time(NULL);
578 jcr->sched_time = str_to_utime(ua->cmd);
579 if (jcr->sched_time == 0) {
580 bsendmsg(ua, _("Invalid time, using current time.\n"));
581 jcr->sched_time = time(NULL);
586 if (jcr->JobType == JT_BACKUP ||
587 jcr->JobType == JT_VERIFY) { /* Pool */
588 pool = select_pool_resource(ua);
597 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
600 if (jcr->RestoreBootstrap) {
601 free(jcr->RestoreBootstrap);
602 jcr->RestoreBootstrap = NULL;
604 if (ua->cmd[0] != 0) {
605 jcr->RestoreBootstrap = bstrdup(ua->cmd);
606 fd = fopen(jcr->RestoreBootstrap, "r");
608 bsendmsg(ua, _("Warning cannot open %s: ERR=%s\n"),
609 jcr->RestoreBootstrap, strerror(errno));
610 free(jcr->RestoreBootstrap);
611 jcr->RestoreBootstrap = NULL;
619 if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
622 if (jcr->RestoreWhere) {
623 free(jcr->RestoreWhere);
624 jcr->RestoreWhere = NULL;
626 if (ua->cmd[0] == '/' && ua->cmd[1] == 0) {
629 jcr->RestoreWhere = bstrdup(ua->cmd);
633 start_prompt(ua, _("Replace:\n"));
634 for (i=0; ReplaceOptions[i].name; i++) {
635 add_prompt(ua, ReplaceOptions[i].name);
637 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
639 jcr->replace = ReplaceOptions[opt].token;
644 jid = NULL; /* force reprompt */
645 jcr->RestoreJobId = 0;
646 if (jcr->RestoreBootstrap) {
647 bsendmsg(ua, _("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
653 bsendmsg(ua, _("Job not run.\n"));
655 return 0; /* error do no run Job */
657 if (strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
658 Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
660 bsendmsg(ua, _("Run command submitted.\n"));
664 bsendmsg(ua, _("Job not run.\n"));
666 return 0; /* do not run */