2 Bacula® - The Network Backup Solution
4 Copyright (C) 2001-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
30 * Bacula Director -- Run Command
32 * Kern Sibbald, December MMI
42 char *job_name, *level_name, *jid, *store_name, *pool_name;
43 char *where, *fileset_name, *client_name, *bootstrap, *regexwhere;
44 char *restore_client_name;
46 char *when, *verify_job_name, *catalog_name;
47 char *previous_job_name;
50 const char *verify_list;
65 run_ctx() { memset(this, 0, sizeof(run_ctx));
66 store = new USTORE; };
67 ~run_ctx() { delete store; };
70 /* Forward referenced subroutines */
71 static void select_job_level(UAContext *ua, JCR *jcr);
72 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job,
73 const char *verify_list, char *jid, const char *replace,
75 static void select_where_regexp(UAContext *ua, JCR *jcr);
76 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc);
77 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc);
78 static int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc);
80 /* Imported variables */
81 extern struct s_kw ReplaceOptions[];
84 * For Backup and Verify Jobs
85 * run [job=]<job-name> level=<level-name>
94 int run_cmd(UAContext *ua, const char *cmd)
100 if (!open_client_db(ua)) {
104 if (!scan_command_line_arguments(ua, rc)) {
108 if (find_arg(ua, NT_("fdcalled")) > 0) {
109 jcr->file_bsock = dup_bsock(ua->UA_sock);
114 * Create JCR to run job. NOTE!!! after this point, free_jcr()
118 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
119 set_jcr_defaults(jcr, rc.job);
120 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
121 ua->jcr->unlink_bsr = false;
125 if (!reset_restore_context(ua, jcr, rc)) {
130 /* Run without prompting? */
131 if (ua->batch || find_arg(ua, NT_("yes")) > 0) {
136 * Prompt User to see if all run job parameters are correct, and
137 * allow him to modify them.
139 if (!display_job_parameters(ua, jcr, rc.job, rc.verify_list, rc.jid, rc.replace,
144 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
148 if (strncasecmp(ua->cmd, ".mod ", 5) == 0 ||
149 (strncasecmp(ua->cmd, "mod ", 4) == 0 && strlen(ua->cmd) > 6)) {
152 if (!scan_command_line_arguments(ua, rc)) {
158 /* Allow the user to modify the settings */
159 status = modify_job_parameters(ua, jcr, rc);
170 if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
172 Dmsg1(800, "Calling run_job job=%x\n", jcr->job);
175 Dmsg3(100, "JobId=%u using pool %s priority=%d\n", (int)jcr->JobId,
176 jcr->pool->name(), jcr->JobPriority);
177 JobId = run_job(jcr);
178 Dmsg4(100, "JobId=%u NewJobId=%d using pool %s priority=%d\n", (int)jcr->JobId,
179 JobId, jcr->pool->name(), jcr->JobPriority);
180 free_jcr(jcr); /* release jcr */
182 ua->error_msg(_("Job failed.\n"));
185 ua->send_msg(_("Job queued. JobId=%s\n"), edit_int64(JobId, ed1));
191 ua->send_msg(_("Job not run.\n"));
193 return 0; /* do not run */
196 int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc)
200 * At user request modify parameters of job to be run.
202 if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
205 start_prompt(ua, _("Parameters to modify:\n"));
206 add_prompt(ua, _("Level")); /* 0 */
207 add_prompt(ua, _("Storage")); /* 1 */
208 add_prompt(ua, _("Job")); /* 2 */
209 add_prompt(ua, _("FileSet")); /* 3 */
210 if (jcr->get_JobType() == JT_RESTORE) {
211 add_prompt(ua, _("Restore Client")); /* 4 */
213 add_prompt(ua, _("Client")); /* 4 */
215 add_prompt(ua, _("When")); /* 5 */
216 add_prompt(ua, _("Priority")); /* 6 */
217 if (jcr->get_JobType() == JT_BACKUP ||
218 jcr->get_JobType() == JT_COPY ||
219 jcr->get_JobType() == JT_MIGRATE ||
220 jcr->get_JobType() == JT_VERIFY) {
221 add_prompt(ua, _("Pool")); /* 7 */
222 if (jcr->get_JobType() == JT_VERIFY) {
223 add_prompt(ua, _("Verify Job")); /* 8 */
225 } else if (jcr->get_JobType() == JT_RESTORE) {
226 add_prompt(ua, _("Bootstrap")); /* 7 */
227 add_prompt(ua, _("Where")); /* 8 */
228 add_prompt(ua, _("File Relocation"));/* 9 */
229 add_prompt(ua, _("Replace")); /* 10 */
230 add_prompt(ua, _("JobId")); /* 11 */
232 if (jcr->get_JobType() == JT_BACKUP || jcr->get_JobType() == JT_RESTORE) {
233 add_prompt(ua, _("Plugin Options")); /* 12 */
235 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
238 select_job_level(ua, jcr);
242 rc.store->store = select_storage_resource(ua);
243 if (rc.store->store) {
244 pm_strcpy(rc.store->store_source, _("user selection"));
245 set_rwstorage(jcr, rc.store);
251 rc.job = select_job_resource(ua);
254 set_jcr_defaults(jcr, rc.job);
260 rc.fileset = select_fileset_resource(ua);
262 jcr->fileset = rc.fileset;
268 rc.client = select_client_resource(ua);
270 jcr->client = rc.client;
276 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
279 if (ua->cmd[0] == 0) {
280 jcr->sched_time = time(NULL);
282 jcr->sched_time = str_to_utime(ua->cmd);
283 if (jcr->sched_time == 0) {
284 ua->send_msg(_("Invalid time, using current time.\n"));
285 jcr->sched_time = time(NULL);
291 if (!get_pint(ua, _("Enter new Priority: "))) {
294 if (ua->pint32_val == 0) {
295 ua->send_msg(_("Priority must be a positive integer.\n"));
297 jcr->JobPriority = ua->pint32_val;
301 /* Pool or Bootstrap depending on JobType */
302 if (jcr->get_JobType() == JT_BACKUP ||
303 jcr->get_JobType() == JT_COPY ||
304 jcr->get_JobType() == JT_MIGRATE ||
305 jcr->get_JobType() == JT_VERIFY) { /* Pool */
306 rc.pool = select_pool_resource(ua);
309 Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
316 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
319 if (jcr->RestoreBootstrap) {
320 free(jcr->RestoreBootstrap);
321 jcr->RestoreBootstrap = NULL;
323 if (ua->cmd[0] != 0) {
324 jcr->RestoreBootstrap = bstrdup(ua->cmd);
325 fd = fopen(jcr->RestoreBootstrap, "rb");
328 ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
329 jcr->RestoreBootstrap, be.bstrerror());
330 free(jcr->RestoreBootstrap);
331 jcr->RestoreBootstrap = NULL;
339 if (jcr->get_JobType() == JT_VERIFY) {
340 rc.verify_job = select_job_resource(ua);
342 jcr->verify_job = rc.verify_job;
347 if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
350 if (jcr->RegexWhere) { /* cannot use regexwhere and where */
351 free(jcr->RegexWhere);
352 jcr->RegexWhere = NULL;
358 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
361 jcr->where = bstrdup(ua->cmd);
364 /* File relocation */
365 select_where_regexp(ua, jcr);
369 start_prompt(ua, _("Replace:\n"));
370 for (i=0; ReplaceOptions[i].name; i++) {
371 add_prompt(ua, ReplaceOptions[i].name);
373 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
375 rc.replace = ReplaceOptions[opt].name;
376 jcr->replace = ReplaceOptions[opt].token;
381 rc.jid = NULL; /* force reprompt */
382 jcr->RestoreJobId = 0;
383 if (jcr->RestoreBootstrap) {
384 ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
389 if (!get_cmd(ua, _("Please Plugin Options string: "))) {
392 if (jcr->plugin_options) {
393 free(jcr->plugin_options);
394 jcr->plugin_options = NULL;
396 jcr->plugin_options = bstrdup(ua->cmd);
398 case -1: /* error or cancel */
415 * Reset the restore context.
416 * This subroutine can be called multiple times, so it
417 * must keep any prior settings.
419 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc)
423 jcr->verify_job = rc.verify_job;
424 jcr->previous_job = rc.previous_job;
426 if (jcr->pool != jcr->job->pool) {
427 pm_strcpy(jcr->pool_source, _("User input"));
429 set_rwstorage(jcr, rc.store);
430 jcr->client = rc.client;
431 pm_strcpy(jcr->client_name, rc.client->name());
432 jcr->fileset = rc.fileset;
433 jcr->ExpectedFiles = rc.files;
435 jcr->catalog = rc.catalog;
436 pm_strcpy(jcr->catalog_source, _("User input"));
442 jcr->where = bstrdup(rc.where);
447 if (jcr->RegexWhere) {
448 free(jcr->RegexWhere);
450 jcr->RegexWhere = bstrdup(rc.regexwhere);
451 rc.regexwhere = NULL;
455 jcr->sched_time = str_to_utime(rc.when);
456 if (jcr->sched_time == 0) {
457 ua->send_msg(_("Invalid time, using current time.\n"));
458 jcr->sched_time = time(NULL);
464 if (jcr->RestoreBootstrap) {
465 free(jcr->RestoreBootstrap);
467 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
471 if (rc.plugin_options) {
472 if (jcr->plugin_options) {
473 free(jcr->plugin_options);
475 jcr->plugin_options = bstrdup(rc.plugin_options);
476 rc.plugin_options = NULL;
482 for (i=0; ReplaceOptions[i].name; i++) {
483 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
484 jcr->replace = ReplaceOptions[i].token;
488 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
491 } else if (rc.job->replace) {
492 jcr->replace = rc.job->replace;
494 jcr->replace = REPLACE_ALWAYS;
499 jcr->JobPriority = rc.Priority;
505 jcr->stime = get_pool_memory(PM_MESSAGE);
507 pm_strcpy(jcr->stime, rc.since);
512 jcr->cloned = rc.cloned;
517 /* If pool changed, update migration write storage */
518 if (jcr->get_JobType() == JT_MIGRATE || jcr->get_JobType() == JT_COPY ||
519 (jcr->get_JobType() == JT_BACKUP && jcr->get_JobLevel() == L_VIRTUAL_FULL)) {
520 if (!set_migration_wstorage(jcr, rc.pool)) {
524 rc.replace = ReplaceOptions[0].name;
525 for (i=0; ReplaceOptions[i].name; i++) {
526 if (ReplaceOptions[i].token == jcr->replace) {
527 rc.replace = ReplaceOptions[i].name;
531 if (!get_level_from_name(jcr, rc.level_name)) {
532 ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
535 rc.level_name = NULL;
538 /* Note, this is also MigrateJobId */
539 jcr->RestoreJobId = str_to_int64(rc.jid);
545 static void select_where_regexp(UAContext *ua, JCR *jcr)
548 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
549 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
552 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
553 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
555 start_prompt(ua, _("This will replace your current Where value\n"));
556 add_prompt(ua, _("Strip prefix")); /* 0 */
557 add_prompt(ua, _("Add prefix")); /* 1 */
558 add_prompt(ua, _("Add file suffix")); /* 2 */
559 add_prompt(ua, _("Enter a regexp")); /* 3 */
560 add_prompt(ua, _("Test filename manipulation")); /* 4 */
561 add_prompt(ua, _("Use this ?")); /* 5 */
563 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
566 if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
567 if (strip_prefix) bfree(strip_prefix);
568 strip_prefix = bstrdup(ua->cmd);
574 if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
575 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
579 if (add_prefix) bfree(add_prefix);
580 add_prefix = bstrdup(ua->cmd);
585 if (get_cmd(ua, _("Please enter file suffix to add: "))) {
586 if (add_suffix) bfree(add_suffix);
587 add_suffix = bstrdup(ua->cmd);
592 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
593 if (rwhere) bfree(rwhere);
594 rwhere = bstrdup(ua->cmd);
603 if (rwhere && rwhere[0] != '\0') {
604 regs = get_bregexps(rwhere);
605 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
607 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
608 regexp = (char *) bmalloc (len * sizeof(char));
609 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
610 regs = get_bregexps(regexp);
611 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
612 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
618 ua->send_msg(_("Cannot use your regexp\n"));
622 while (get_cmd(ua, _("Please enter filename to test: "))) {
623 apply_bregexps(ua->cmd, regs, &result);
624 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
633 case -1: /* error or cancel */
639 /* replace the existing where */
645 /* replace the existing regexwhere */
646 if (jcr->RegexWhere) {
647 bfree(jcr->RegexWhere);
648 jcr->RegexWhere = NULL;
652 jcr->RegexWhere = bstrdup(rwhere);
653 } else if (strip_prefix || add_prefix || add_suffix) {
654 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
655 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
656 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
659 regs = get_bregexps(jcr->RegexWhere);
664 if (jcr->RegexWhere) {
665 bfree(jcr->RegexWhere);
666 jcr->RegexWhere = NULL;
668 ua->send_msg(_("Cannot use your regexp.\n"));
672 if (strip_prefix) bfree(strip_prefix);
673 if (add_prefix) bfree(add_prefix);
674 if (add_suffix) bfree(add_suffix);
675 if (rwhere) bfree(rwhere);
678 static void select_job_level(UAContext *ua, JCR *jcr)
680 if (jcr->get_JobType() == JT_BACKUP) {
681 start_prompt(ua, _("Levels:\n"));
682 // add_prompt(ua, _("Base"));
683 add_prompt(ua, _("Full"));
684 add_prompt(ua, _("Incremental"));
685 add_prompt(ua, _("Differential"));
686 add_prompt(ua, _("Since"));
687 add_prompt(ua, _("VirtualFull"));
688 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
690 // jcr->JobLevel = L_BASE;
693 jcr->set_JobLevel(L_FULL);
696 jcr->set_JobLevel(L_INCREMENTAL);
699 jcr->set_JobLevel(L_DIFFERENTIAL);
702 jcr->set_JobLevel(L_SINCE);
705 jcr->set_JobLevel(L_VIRTUAL_FULL);
710 } else if (jcr->get_JobType() == JT_VERIFY) {
711 start_prompt(ua, _("Levels:\n"));
712 add_prompt(ua, _("Initialize Catalog"));
713 add_prompt(ua, _("Verify Catalog"));
714 add_prompt(ua, _("Verify Volume to Catalog"));
715 add_prompt(ua, _("Verify Disk to Catalog"));
716 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
717 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
719 jcr->set_JobLevel(L_VERIFY_INIT);
722 jcr->set_JobLevel(L_VERIFY_CATALOG);
725 jcr->set_JobLevel(L_VERIFY_VOLUME_TO_CATALOG);
728 jcr->set_JobLevel(L_VERIFY_DISK_TO_CATALOG);
731 jcr->set_JobLevel(L_VERIFY_DATA);
737 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
742 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
743 char *jid, const char *replace, char *client_name)
745 Dmsg1(800, "JobType=%c\n", jcr->get_JobType());
746 switch (jcr->get_JobType()) {
748 char dt[MAX_TIME_LENGTH];
750 if (ua->api) ua->signal(BNET_RUN_CMD);
751 ua->send_msg(_("Run %s job\n"
760 jcr->fileset->name(),
761 NPRT(jcr->client->name()),
762 jcr->wstore?jcr->wstore->name():"*None*",
763 bstrutime(dt, sizeof(dt), jcr->sched_time),
765 jcr->set_JobLevel(L_FULL);
769 if (jcr->get_JobType() == JT_BACKUP) {
770 if (ua->api) ua->signal(BNET_RUN_CMD);
771 ua->send_msg(_("Run %s job\n"
776 "Pool: %s (From %s)\n"
777 "Storage: %s (From %s)\n"
783 level_to_str(jcr->get_JobLevel()),
785 jcr->fileset->name(),
786 NPRT(jcr->pool->name()), jcr->pool_source,
787 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
788 bstrutime(dt, sizeof(dt), jcr->sched_time),
790 jcr->plugin_options?"Plugin Options: ":"",
791 jcr->plugin_options?jcr->plugin_options:"",
792 jcr->plugin_options?"\n":"");
793 } else { /* JT_VERIFY */
795 if (jcr->verify_job) {
796 Name = jcr->verify_job->name();
801 verify_list = job->WriteVerifyList;
806 if (ua->api) ua->signal(BNET_RUN_CMD);
807 ua->send_msg(_("Run %s job\n"
812 "Pool: %s (From %s)\n"
813 "Storage: %s (From %s)\n"
820 level_to_str(jcr->get_JobLevel()),
822 jcr->fileset->name(),
823 NPRT(jcr->pool->name()), jcr->pool_source,
824 jcr->rstore->name(), jcr->rstore_source,
827 bstrutime(dt, sizeof(dt), jcr->sched_time),
832 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
834 jcr->RestoreJobId = str_to_int64(jid);
836 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
839 jcr->RestoreJobId = ua->int64_val;
842 jcr->set_JobLevel(L_FULL); /* default level */
843 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
844 if (jcr->RestoreJobId == 0) {
845 if (ua->api) ua->signal(BNET_RUN_CMD);
846 /* RegexWhere is take before RestoreWhere */
847 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
848 ua->send_msg(_("Run Restore job\n"
854 "Backup Client: %s\n"
855 "Restore Client: %s\n"
860 "Plugin Options: %s\n"),
862 NPRT(jcr->RestoreBootstrap),
863 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
865 jcr->fileset->name(),
869 bstrutime(dt, sizeof(dt), jcr->sched_time),
870 jcr->catalog->name(),
872 NPRT(jcr->plugin_options));
875 ua->send_msg(_("Run Restore job\n"
881 "Backup Client: %s\n"
882 "Restore Client: %s\n"
887 "Plugin Options: %s\n"),
889 NPRT(jcr->RestoreBootstrap),
890 jcr->where?jcr->where:NPRT(job->RestoreWhere),
892 jcr->fileset->name(),
896 bstrutime(dt, sizeof(dt), jcr->sched_time),
897 jcr->catalog->name(),
899 NPRT(jcr->plugin_options));
903 if (ua->api) ua->signal(BNET_RUN_CMD);
904 ua->send_msg(_("Run Restore job\n"
908 NPRT(jcr->RestoreBootstrap));
910 /* RegexWhere is take before RestoreWhere */
911 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
912 ua->send_msg(_("RegexWhere: %s\n"),
913 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
915 ua->send_msg(_("Where: %s\n"),
916 jcr->where?jcr->where:NPRT(job->RestoreWhere));
919 ua->send_msg(_("Replace: %s\n"
926 "Plugin Options: %s\n"),
930 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
931 bstrutime(dt, sizeof(dt), jcr->sched_time),
932 jcr->catalog->name(),
934 NPRT(jcr->plugin_options));
940 if (jcr->get_JobType() == JT_COPY) {
941 prt_type = _("Run Copy job\n");
943 prt_type = _("Run Migration job\n");
945 jcr->set_JobLevel(L_FULL); /* default level */
946 if (ua->api) ua->signal(BNET_RUN_CMD);
952 "Pool: %s (From %s)\n"
953 "Read Storage: %s (From %s)\n"
954 "Write Storage: %s (From %s)\n"
961 NPRT(jcr->RestoreBootstrap),
963 jcr->fileset->name(),
964 NPRT(jcr->pool->name()), jcr->pool_source,
965 jcr->rstore->name(), jcr->rstore_source,
966 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
967 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
968 bstrutime(dt, sizeof(dt), jcr->sched_time),
969 jcr->catalog->name(),
973 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->get_JobType());
980 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
984 static const char *kw[] = { /* command line arguments */
985 "job", /* Used in a switch() */
993 "regexwhere", /* 8 where string as a bregexp */
995 "bootstrap", /* 10 */
999 "yes", /* 14 -- if you change this change YES_POS too */
1000 "verifyjob", /* 15 */
1001 "files", /* 16 number of files to restore */
1002 "catalog", /* 17 override catalog */
1003 "since", /* 18 since */
1004 "cloned", /* 19 cloned */
1005 "verifylist", /* 20 verify output list */
1006 "migrationjob", /* 21 migration job name */
1008 "backupclient", /* 23 */
1009 "restoreclient", /* 24 */
1010 "pluginoptions", /* 25 */
1015 rc.catalog_name = NULL;
1017 rc.pool_name = NULL;
1018 rc.store_name = NULL;
1019 rc.client_name = NULL;
1020 rc.restore_client_name = NULL;
1021 rc.fileset_name = NULL;
1022 rc.verify_job_name = NULL;
1023 rc.previous_job_name = NULL;
1026 for (i=1; i<ua->argc; i++) {
1027 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1029 /* Keep looking until we find a good keyword */
1030 for (j=0; !kw_ok && kw[j]; j++) {
1031 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1032 /* Note, yes and run have no value, so do not fail */
1033 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1034 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1037 Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
1041 ua->send_msg(_("Job name specified twice.\n"));
1044 rc.job_name = ua->argv[i];
1048 if (rc.jid && !rc.mod) {
1049 ua->send_msg(_("JobId specified twice.\n"));
1052 rc.jid = ua->argv[i];
1055 case 2: /* client */
1057 if (rc.client_name) {
1058 ua->send_msg(_("Client specified twice.\n"));
1061 rc.client_name = ua->argv[i];
1064 case 4: /* fileset */
1065 if (rc.fileset_name) {
1066 ua->send_msg(_("FileSet specified twice.\n"));
1069 rc.fileset_name = ua->argv[i];
1073 if (rc.level_name) {
1074 ua->send_msg(_("Level specified twice.\n"));
1077 rc.level_name = ua->argv[i];
1080 case 6: /* storage */
1082 if (rc.store_name) {
1083 ua->send_msg(_("Storage specified twice.\n"));
1086 rc.store_name = ua->argv[i];
1089 case 8: /* regexwhere */
1090 if ((rc.regexwhere || rc.where) && !rc.mod) {
1091 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1094 rc.regexwhere = ua->argv[i];
1095 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1096 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1102 if ((rc.where || rc.regexwhere) && !rc.mod) {
1103 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1106 rc.where = ua->argv[i];
1107 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1108 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1113 case 10: /* bootstrap */
1114 if (rc.bootstrap && !rc.mod) {
1115 ua->send_msg(_("Bootstrap specified twice.\n"));
1118 rc.bootstrap = ua->argv[i];
1121 case 11: /* replace */
1122 if (rc.replace && !rc.mod) {
1123 ua->send_msg(_("Replace specified twice.\n"));
1126 rc.replace = ua->argv[i];
1130 if (rc.when && !rc.mod) {
1131 ua->send_msg(_("When specified twice.\n"));
1134 rc.when = ua->argv[i];
1137 case 13: /* Priority */
1138 if (rc.Priority && !rc.mod) {
1139 ua->send_msg(_("Priority specified twice.\n"));
1142 rc.Priority = atoi(ua->argv[i]);
1143 if (rc.Priority <= 0) {
1144 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1152 case 15: /* Verify Job */
1153 if (rc.verify_job_name) {
1154 ua->send_msg(_("Verify Job specified twice.\n"));
1157 rc.verify_job_name = ua->argv[i];
1160 case 16: /* files */
1161 rc.files = atoi(ua->argv[i]);
1165 case 17: /* catalog */
1166 rc.catalog_name = ua->argv[i];
1170 case 18: /* since */
1171 rc.since = ua->argv[i];
1175 case 19: /* cloned */
1180 case 20: /* write verify list output */
1181 rc.verify_list = ua->argv[i];
1184 case 21: /* Migration Job */
1185 if (rc.previous_job_name) {
1186 ua->send_msg(_("Migration Job specified twice.\n"));
1189 rc.previous_job_name = ua->argv[i];
1194 ua->send_msg(_("Pool specified twice.\n"));
1197 rc.pool_name = ua->argv[i];
1200 case 23: /* backupclient */
1201 if (rc.client_name) {
1202 ua->send_msg(_("Client specified twice.\n"));
1205 rc.client_name = ua->argv[i];
1208 case 24: /* restoreclient */
1209 if (rc.restore_client_name && !rc.mod) {
1210 ua->send_msg(_("Restore Client specified twice.\n"));
1213 rc.restore_client_name = ua->argv[i];
1216 case 25: /* pluginoptions */
1217 if (rc.plugin_options) {
1218 ua->send_msg(_("Plugin Options specified twice.\n"));
1221 rc.plugin_options = ua->argv[i];
1222 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1223 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1231 } /* end strcase compare */
1232 } /* end keyword loop */
1234 * End of keyword for loop -- if not found, we got a bogus keyword
1237 Dmsg1(800, "%s not found\n", ua->argk[i]);
1239 * Special case for Job Name, it can be the first
1240 * keyword that has no value.
1242 if (!rc.job_name && !ua->argv[i]) {
1243 rc.job_name = ua->argk[i]; /* use keyword as job name */
1244 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1246 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1250 } /* end argc loop */
1252 Dmsg0(800, "Done scan.\n");
1254 if (rc.catalog_name) {
1255 rc.catalog = GetCatalogResWithName(rc.catalog_name);
1256 if (rc.catalog == NULL) {
1257 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1260 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1261 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1265 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1269 rc.job = GetJobResWithName(rc.job_name);
1271 if (*rc.job_name != 0) {
1272 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1274 rc.job = select_job_resource(ua);
1276 Dmsg1(800, "Found job=%s\n", rc.job_name);
1278 } else if (!rc.job) {
1279 ua->send_msg(_("A job name must be specified.\n"));
1280 rc.job = select_job_resource(ua);
1284 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1285 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1290 rc.pool = GetPoolResWithName(rc.pool_name);
1292 if (*rc.pool_name != 0) {
1293 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1295 rc.pool = select_pool_resource(ua);
1297 } else if (!rc.pool) {
1298 rc.pool = rc.job->pool; /* use default */
1302 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1303 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1306 Dmsg1(100, "Using pool %s\n", rc.pool->name());
1308 if (rc.store_name) {
1309 rc.store->store = GetStoreResWithName(rc.store_name);
1310 pm_strcpy(rc.store->store_source, _("command line"));
1311 if (!rc.store->store) {
1312 if (*rc.store_name != 0) {
1313 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1315 rc.store->store = select_storage_resource(ua);
1316 pm_strcpy(rc.store->store_source, _("user selection"));
1318 } else if (!rc.store->store) {
1319 get_job_storage(rc.store, rc.job, NULL); /* use default */
1321 if (!rc.store->store) {
1322 ua->error_msg(_("No storage specified.\n"));
1324 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1325 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1326 rc.store->store->name());
1329 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1331 if (rc.client_name) {
1332 rc.client = GetClientResWithName(rc.client_name);
1334 if (*rc.client_name != 0) {
1335 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1337 rc.client = select_client_resource(ua);
1339 } else if (!rc.client) {
1340 rc.client = rc.job->client; /* use default */
1344 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1345 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1349 Dmsg1(800, "Using client=%s\n", rc.client->name());
1351 if (rc.restore_client_name) {
1352 rc.client = GetClientResWithName(rc.restore_client_name);
1354 if (*rc.restore_client_name != 0) {
1355 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1357 rc.client = select_client_resource(ua);
1359 } else if (!rc.client) {
1360 rc.client = rc.job->client; /* use default */
1364 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1365 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1369 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1372 if (rc.fileset_name) {
1373 rc.fileset = GetFileSetResWithName(rc.fileset_name);
1375 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1376 rc.fileset = select_fileset_resource(ua);
1378 } else if (!rc.fileset) {
1379 rc.fileset = rc.job->fileset; /* use default */
1383 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1384 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1385 rc.fileset->name());
1389 if (rc.verify_job_name) {
1390 rc.verify_job = GetJobResWithName(rc.verify_job_name);
1391 if (!rc.verify_job) {
1392 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1393 rc.verify_job = select_job_resource(ua);
1395 } else if (!rc.verify_job) {
1396 rc.verify_job = rc.job->verify_job;
1399 if (rc.previous_job_name) {
1400 rc.previous_job = GetJobResWithName(rc.previous_job_name);
1401 if (!rc.previous_job) {
1402 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1403 rc.previous_job = select_job_resource(ua);
1406 rc.previous_job = rc.job->verify_job;