2 Bacula® - The Network Backup Solution
4 Copyright (C) 2001-2010 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 three of the GNU Affero 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 Affero 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
41 char *job_name, *level_name, *jid, *store_name, *pool_name;
42 char *where, *fileset_name, *client_name, *bootstrap, *regexwhere;
43 char *restore_client_name;
45 char *when, *verify_job_name, *catalog_name;
46 char *previous_job_name;
49 const char *verify_list;
66 run_ctx() { memset(this, 0, sizeof(run_ctx));
67 store = new USTORE; };
68 ~run_ctx() { delete store; };
71 /* Forward referenced subroutines */
72 static void select_job_level(UAContext *ua, JCR *jcr);
73 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job,
74 const char *verify_list, char *jid, const char *replace,
76 static void select_where_regexp(UAContext *ua, JCR *jcr);
77 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc);
78 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc);
79 static int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc);
81 /* Imported variables */
82 extern struct s_kw ReplaceOptions[];
85 * For Backup and Verify Jobs
86 * run [job=]<job-name> level=<level-name>
95 int run_cmd(UAContext *ua, const char *cmd)
101 if (!open_client_db(ua)) {
105 if (!scan_command_line_arguments(ua, rc)) {
109 if (find_arg(ua, NT_("fdcalled")) > 0) {
110 jcr->file_bsock = dup_bsock(ua->UA_sock);
115 * Create JCR to run job. NOTE!!! after this point, free_jcr()
119 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
120 set_jcr_defaults(jcr, rc.job);
121 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
122 ua->jcr->unlink_bsr = false;
126 if (!reset_restore_context(ua, jcr, rc)) {
131 /* Run without prompting? */
132 if (ua->batch || find_arg(ua, NT_("yes")) > 0) {
137 * Prompt User to see if all run job parameters are correct, and
138 * allow him to modify them.
140 if (!display_job_parameters(ua, jcr, rc.job, rc.verify_list, rc.jid, rc.replace,
145 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
149 if (strncasecmp(ua->cmd, ".mod ", 5) == 0 ||
150 (strncasecmp(ua->cmd, "mod ", 4) == 0 && strlen(ua->cmd) > 6)) {
153 if (!scan_command_line_arguments(ua, rc)) {
159 /* Allow the user to modify the settings */
160 status = modify_job_parameters(ua, jcr, rc);
171 if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
173 Dmsg1(800, "Calling run_job job=%x\n", jcr->job);
176 Dmsg3(100, "JobId=%u using pool %s priority=%d\n", (int)jcr->JobId,
177 jcr->pool->name(), jcr->JobPriority);
178 Dmsg1(900, "Running a job; its spool_data = %d\n", jcr->spool_data);
179 JobId = run_job(jcr);
180 Dmsg4(100, "JobId=%u NewJobId=%d using pool %s priority=%d\n", (int)jcr->JobId,
181 JobId, jcr->pool->name(), jcr->JobPriority);
182 free_jcr(jcr); /* release jcr */
184 ua->error_msg(_("Job failed.\n"));
187 ua->send_msg(_("Job queued. JobId=%s\n"), edit_int64(JobId, ed1));
193 ua->send_msg(_("Job not run.\n"));
195 return 0; /* do not run */
198 int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc)
202 * At user request modify parameters of job to be run.
204 if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
207 start_prompt(ua, _("Parameters to modify:\n"));
208 add_prompt(ua, _("Level")); /* 0 */
209 add_prompt(ua, _("Storage")); /* 1 */
210 add_prompt(ua, _("Job")); /* 2 */
211 add_prompt(ua, _("FileSet")); /* 3 */
212 if (jcr->getJobType() == JT_RESTORE) {
213 add_prompt(ua, _("Restore Client")); /* 4 */
215 add_prompt(ua, _("Client")); /* 4 */
217 add_prompt(ua, _("When")); /* 5 */
218 add_prompt(ua, _("Priority")); /* 6 */
219 if (jcr->getJobType() == JT_BACKUP ||
220 jcr->getJobType() == JT_COPY ||
221 jcr->getJobType() == JT_MIGRATE ||
222 jcr->getJobType() == JT_VERIFY) {
223 add_prompt(ua, _("Pool")); /* 7 */
224 if (jcr->getJobType() == JT_VERIFY) {
225 add_prompt(ua, _("Verify Job")); /* 8 */
227 } else if (jcr->getJobType() == JT_RESTORE) {
228 add_prompt(ua, _("Bootstrap")); /* 7 */
229 add_prompt(ua, _("Where")); /* 8 */
230 add_prompt(ua, _("File Relocation"));/* 9 */
231 add_prompt(ua, _("Replace")); /* 10 */
232 add_prompt(ua, _("JobId")); /* 11 */
234 if (jcr->getJobType() == JT_BACKUP || jcr->getJobType() == JT_RESTORE) {
235 add_prompt(ua, _("Plugin Options")); /* 12 */
237 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
240 select_job_level(ua, jcr);
244 rc.store->store = select_storage_resource(ua);
245 if (rc.store->store) {
246 pm_strcpy(rc.store->store_source, _("user selection"));
247 set_rwstorage(jcr, rc.store);
253 rc.job = select_job_resource(ua);
256 set_jcr_defaults(jcr, rc.job);
262 rc.fileset = select_fileset_resource(ua);
264 jcr->fileset = rc.fileset;
270 rc.client = select_client_resource(ua);
272 jcr->client = rc.client;
278 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
281 if (ua->cmd[0] == 0) {
282 jcr->sched_time = time(NULL);
284 jcr->sched_time = str_to_utime(ua->cmd);
285 if (jcr->sched_time == 0) {
286 ua->send_msg(_("Invalid time, using current time.\n"));
287 jcr->sched_time = time(NULL);
293 if (!get_pint(ua, _("Enter new Priority: "))) {
296 if (ua->pint32_val == 0) {
297 ua->send_msg(_("Priority must be a positive integer.\n"));
299 jcr->JobPriority = ua->pint32_val;
303 /* Pool or Bootstrap depending on JobType */
304 if (jcr->getJobType() == JT_BACKUP ||
305 jcr->getJobType() == JT_COPY ||
306 jcr->getJobType() == JT_MIGRATE ||
307 jcr->getJobType() == JT_VERIFY) { /* Pool */
308 rc.pool = select_pool_resource(ua);
311 Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
318 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
321 if (jcr->RestoreBootstrap) {
322 free(jcr->RestoreBootstrap);
323 jcr->RestoreBootstrap = NULL;
325 if (ua->cmd[0] != 0) {
326 jcr->RestoreBootstrap = bstrdup(ua->cmd);
327 fd = fopen(jcr->RestoreBootstrap, "rb");
330 ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
331 jcr->RestoreBootstrap, be.bstrerror());
332 free(jcr->RestoreBootstrap);
333 jcr->RestoreBootstrap = NULL;
341 if (jcr->getJobType() == JT_VERIFY) {
342 rc.verify_job = select_job_resource(ua);
344 jcr->verify_job = rc.verify_job;
349 if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
352 if (jcr->RegexWhere) { /* cannot use regexwhere and where */
353 free(jcr->RegexWhere);
354 jcr->RegexWhere = NULL;
360 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
363 jcr->where = bstrdup(ua->cmd);
366 /* File relocation */
367 select_where_regexp(ua, jcr);
371 start_prompt(ua, _("Replace:\n"));
372 for (i=0; ReplaceOptions[i].name; i++) {
373 add_prompt(ua, ReplaceOptions[i].name);
375 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
377 rc.replace = ReplaceOptions[opt].name;
378 jcr->replace = ReplaceOptions[opt].token;
383 rc.jid = NULL; /* force reprompt */
384 jcr->RestoreJobId = 0;
385 if (jcr->RestoreBootstrap) {
386 ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
391 if (!get_cmd(ua, _("Please Plugin Options string: "))) {
394 if (jcr->plugin_options) {
395 free(jcr->plugin_options);
396 jcr->plugin_options = NULL;
398 jcr->plugin_options = bstrdup(ua->cmd);
400 case -1: /* error or cancel */
417 * Reset the restore context.
418 * This subroutine can be called multiple times, so it
419 * must keep any prior settings.
421 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc)
425 jcr->verify_job = rc.verify_job;
426 jcr->previous_job = rc.previous_job;
428 if (jcr->pool != jcr->job->pool) {
429 pm_strcpy(jcr->pool_source, _("User input"));
431 set_rwstorage(jcr, rc.store);
432 jcr->client = rc.client;
433 pm_strcpy(jcr->client_name, rc.client->name());
434 jcr->fileset = rc.fileset;
435 jcr->ExpectedFiles = rc.files;
437 jcr->catalog = rc.catalog;
438 pm_strcpy(jcr->catalog_source, _("User input"));
444 jcr->where = bstrdup(rc.where);
449 if (jcr->RegexWhere) {
450 free(jcr->RegexWhere);
452 jcr->RegexWhere = bstrdup(rc.regexwhere);
453 rc.regexwhere = NULL;
457 jcr->sched_time = str_to_utime(rc.when);
458 if (jcr->sched_time == 0) {
459 ua->send_msg(_("Invalid time, using current time.\n"));
460 jcr->sched_time = time(NULL);
466 if (jcr->RestoreBootstrap) {
467 free(jcr->RestoreBootstrap);
469 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
473 if (rc.plugin_options) {
474 if (jcr->plugin_options) {
475 free(jcr->plugin_options);
477 jcr->plugin_options = bstrdup(rc.plugin_options);
478 rc.plugin_options = NULL;
484 for (i=0; ReplaceOptions[i].name; i++) {
485 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
486 jcr->replace = ReplaceOptions[i].token;
490 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
493 } else if (rc.job->replace) {
494 jcr->replace = rc.job->replace;
496 jcr->replace = REPLACE_ALWAYS;
501 jcr->JobPriority = rc.Priority;
507 jcr->stime = get_pool_memory(PM_MESSAGE);
509 pm_strcpy(jcr->stime, rc.since);
514 jcr->cloned = rc.cloned;
519 /* If pool changed, update migration write storage */
520 if (jcr->getJobType() == JT_MIGRATE || jcr->getJobType() == JT_COPY ||
521 (jcr->getJobType() == JT_BACKUP && jcr->getJobLevel() == L_VIRTUAL_FULL)) {
522 if (!set_migration_wstorage(jcr, rc.pool)) {
526 rc.replace = ReplaceOptions[0].name;
527 for (i=0; ReplaceOptions[i].name; i++) {
528 if (ReplaceOptions[i].token == jcr->replace) {
529 rc.replace = ReplaceOptions[i].name;
533 if (!get_level_from_name(jcr, rc.level_name)) {
534 ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
537 rc.level_name = NULL;
540 /* Note, this is also MigrateJobId */
541 jcr->RestoreJobId = str_to_int64(rc.jid);
547 static void select_where_regexp(UAContext *ua, JCR *jcr)
550 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
551 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
554 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
555 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
557 start_prompt(ua, _("This will replace your current Where value\n"));
558 add_prompt(ua, _("Strip prefix")); /* 0 */
559 add_prompt(ua, _("Add prefix")); /* 1 */
560 add_prompt(ua, _("Add file suffix")); /* 2 */
561 add_prompt(ua, _("Enter a regexp")); /* 3 */
562 add_prompt(ua, _("Test filename manipulation")); /* 4 */
563 add_prompt(ua, _("Use this ?")); /* 5 */
565 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
568 if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
569 if (strip_prefix) bfree(strip_prefix);
570 strip_prefix = bstrdup(ua->cmd);
576 if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
577 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
581 if (add_prefix) bfree(add_prefix);
582 add_prefix = bstrdup(ua->cmd);
587 if (get_cmd(ua, _("Please enter file suffix to add: "))) {
588 if (add_suffix) bfree(add_suffix);
589 add_suffix = bstrdup(ua->cmd);
594 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
595 if (rwhere) bfree(rwhere);
596 rwhere = bstrdup(ua->cmd);
605 if (rwhere && rwhere[0] != '\0') {
606 regs = get_bregexps(rwhere);
607 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
609 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
610 regexp = (char *) bmalloc (len * sizeof(char));
611 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
612 regs = get_bregexps(regexp);
613 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
614 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
620 ua->send_msg(_("Cannot use your regexp\n"));
623 ua->send_msg(_("Enter a period (.) to stop this test\n"));
624 while (get_cmd(ua, _("Please enter filename to test: "))) {
625 apply_bregexps(ua->cmd, regs, &result);
626 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
635 case -1: /* error or cancel */
641 /* replace the existing where */
647 /* replace the existing regexwhere */
648 if (jcr->RegexWhere) {
649 bfree(jcr->RegexWhere);
650 jcr->RegexWhere = NULL;
654 jcr->RegexWhere = bstrdup(rwhere);
655 } else if (strip_prefix || add_prefix || add_suffix) {
656 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
657 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
658 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
661 regs = get_bregexps(jcr->RegexWhere);
666 if (jcr->RegexWhere) {
667 bfree(jcr->RegexWhere);
668 jcr->RegexWhere = NULL;
670 ua->send_msg(_("Cannot use your regexp.\n"));
674 if (strip_prefix) bfree(strip_prefix);
675 if (add_prefix) bfree(add_prefix);
676 if (add_suffix) bfree(add_suffix);
677 if (rwhere) bfree(rwhere);
680 static void select_job_level(UAContext *ua, JCR *jcr)
682 if (jcr->getJobType() == JT_BACKUP) {
683 start_prompt(ua, _("Levels:\n"));
684 // add_prompt(ua, _("Base"));
685 add_prompt(ua, _("Full"));
686 add_prompt(ua, _("Incremental"));
687 add_prompt(ua, _("Differential"));
688 add_prompt(ua, _("Since"));
689 add_prompt(ua, _("VirtualFull"));
690 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
692 // jcr->JobLevel = L_BASE;
695 jcr->set_JobLevel(L_FULL);
698 jcr->set_JobLevel(L_INCREMENTAL);
701 jcr->set_JobLevel(L_DIFFERENTIAL);
704 jcr->set_JobLevel(L_SINCE);
707 jcr->set_JobLevel(L_VIRTUAL_FULL);
712 } else if (jcr->getJobType() == JT_VERIFY) {
713 start_prompt(ua, _("Levels:\n"));
714 add_prompt(ua, _("Initialize Catalog"));
715 add_prompt(ua, _("Verify Catalog"));
716 add_prompt(ua, _("Verify Volume to Catalog"));
717 add_prompt(ua, _("Verify Disk to Catalog"));
718 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
719 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
721 jcr->set_JobLevel(L_VERIFY_INIT);
724 jcr->set_JobLevel(L_VERIFY_CATALOG);
727 jcr->set_JobLevel(L_VERIFY_VOLUME_TO_CATALOG);
730 jcr->set_JobLevel(L_VERIFY_DISK_TO_CATALOG);
733 jcr->set_JobLevel(L_VERIFY_DATA);
739 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
744 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
745 char *jid, const char *replace, char *client_name)
747 Dmsg1(800, "JobType=%c\n", jcr->getJobType());
748 switch (jcr->getJobType()) {
750 char dt[MAX_TIME_LENGTH];
753 ua->signal(BNET_RUN_CMD);
754 ua->send_msg("Type: Admin\n"
755 "Title: Run Admin Job\n"
763 jcr->fileset->name(),
764 NPRT(jcr->client->name()),
765 jcr->wstore?jcr->wstore->name():"*None*",
766 bstrutime(dt, sizeof(dt), jcr->sched_time),
769 ua->send_msg(_("Run %s job\n"
778 jcr->fileset->name(),
779 NPRT(jcr->client->name()),
780 jcr->wstore?jcr->wstore->name():"*None*",
781 bstrutime(dt, sizeof(dt), jcr->sched_time),
784 jcr->set_JobLevel(L_FULL);
788 if (jcr->getJobType() == JT_BACKUP) {
790 ua->signal(BNET_RUN_CMD);
791 ua->send_msg("Type: Backup\n"
792 "Title: Run Backup Job\n"
803 level_to_str(jcr->getJobLevel()),
805 jcr->fileset->name(),
806 NPRT(jcr->pool->name()),
807 jcr->wstore?jcr->wstore->name():"*None*",
808 bstrutime(dt, sizeof(dt), jcr->sched_time),
810 jcr->plugin_options?"Plugin Options: ":"",
811 jcr->plugin_options?jcr->plugin_options:"",
812 jcr->plugin_options?"\n":"");
814 ua->send_msg(_("Run %s job\n"
819 "Pool: %s (From %s)\n"
820 "Storage: %s (From %s)\n"
825 level_to_str(jcr->getJobLevel()),
827 jcr->fileset->name(),
828 NPRT(jcr->pool->name()), jcr->pool_source,
829 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
830 bstrutime(dt, sizeof(dt), jcr->sched_time),
832 jcr->plugin_options?"Plugin Options: ":"",
833 jcr->plugin_options?jcr->plugin_options:"",
834 jcr->plugin_options?"\n":"");
836 } else { /* JT_VERIFY */
838 if (jcr->verify_job) {
839 Name = jcr->verify_job->name();
844 verify_list = job->WriteVerifyList;
850 ua->signal(BNET_RUN_CMD);
851 ua->send_msg("Type: Verify\n"
852 "Title: Run Verify Job\n"
857 "Pool: %s (From %s)\n"
858 "Storage: %s (From %s)\n"
864 level_to_str(jcr->getJobLevel()),
866 jcr->fileset->name(),
867 NPRT(jcr->pool->name()), jcr->pool_source,
868 jcr->rstore->name(), jcr->rstore_source,
871 bstrutime(dt, sizeof(dt), jcr->sched_time),
874 ua->send_msg(_("Run %s job\n"
879 "Pool: %s (From %s)\n"
880 "Storage: %s (From %s)\n"
887 level_to_str(jcr->getJobLevel()),
889 jcr->fileset->name(),
890 NPRT(jcr->pool->name()), jcr->pool_source,
891 jcr->rstore->name(), jcr->rstore_source,
894 bstrutime(dt, sizeof(dt), jcr->sched_time),
900 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
902 jcr->RestoreJobId = str_to_int64(jid);
904 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
907 jcr->RestoreJobId = ua->int64_val;
910 jcr->set_JobLevel(L_FULL); /* default level */
911 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
912 if (jcr->RestoreJobId == 0) {
913 /* RegexWhere is take before RestoreWhere */
914 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
916 ua->signal(BNET_RUN_CMD);
917 ua->send_msg("Type: Restore\n"
918 "Title: Run Restore Job\n"
924 "Backup Client: %s\n"
925 "Restore Client: %s\n"
930 "Plugin Options: %s\n",
932 NPRT(jcr->RestoreBootstrap),
933 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
935 jcr->fileset->name(),
939 bstrutime(dt, sizeof(dt), jcr->sched_time),
940 jcr->catalog->name(),
942 NPRT(jcr->plugin_options));
944 ua->send_msg(_("Run Restore job\n"
950 "Backup Client: %s\n"
951 "Restore Client: %s\n"
956 "Plugin Options: %s\n"),
958 NPRT(jcr->RestoreBootstrap),
959 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
961 jcr->fileset->name(),
965 bstrutime(dt, sizeof(dt), jcr->sched_time),
966 jcr->catalog->name(),
968 NPRT(jcr->plugin_options));
972 ua->signal(BNET_RUN_CMD);
973 ua->send_msg("Type: Restore\n"
974 "Title: Run Restore job\n"
980 "Backup Client: %s\n"
981 "Restore Client: %s\n"
986 "Plugin Options: %s\n",
988 NPRT(jcr->RestoreBootstrap),
989 jcr->where?jcr->where:NPRT(job->RestoreWhere),
991 jcr->fileset->name(),
995 bstrutime(dt, sizeof(dt), jcr->sched_time),
996 jcr->catalog->name(),
998 NPRT(jcr->plugin_options));
1000 ua->send_msg(_("Run Restore job\n"
1006 "Backup Client: %s\n"
1007 "Restore Client: %s\n"
1012 "Plugin Options: %s\n"),
1014 NPRT(jcr->RestoreBootstrap),
1015 jcr->where?jcr->where:NPRT(job->RestoreWhere),
1017 jcr->fileset->name(),
1019 jcr->client->name(),
1020 jcr->rstore->name(),
1021 bstrutime(dt, sizeof(dt), jcr->sched_time),
1022 jcr->catalog->name(),
1024 NPRT(jcr->plugin_options));
1029 /* ***FIXME*** This needs to be fixed for bat */
1030 if (ua->api) ua->signal(BNET_RUN_CMD);
1031 ua->send_msg(_("Run Restore job\n"
1035 NPRT(jcr->RestoreBootstrap));
1037 /* RegexWhere is take before RestoreWhere */
1038 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
1039 ua->send_msg(_("RegexWhere: %s\n"),
1040 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
1042 ua->send_msg(_("Where: %s\n"),
1043 jcr->where?jcr->where:NPRT(job->RestoreWhere));
1046 ua->send_msg(_("Replace: %s\n"
1053 "Plugin Options: %s\n"),
1055 jcr->client->name(),
1056 jcr->rstore->name(),
1057 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
1058 bstrutime(dt, sizeof(dt), jcr->sched_time),
1059 jcr->catalog->name(),
1061 NPRT(jcr->plugin_options));
1067 jcr->set_JobLevel(L_FULL); /* default level */
1069 ua->signal(BNET_RUN_CMD);
1070 if (jcr->getJobType() == JT_COPY) {
1071 prt_type = (char *)"Type: Copy\nTitle: Run Copy Job\n";
1073 prt_type = (char *)"Type: Migration\nTitle: Run Migration Job\n";
1081 "Read Storage: %s\n"
1082 "Write Storage: %s\n"
1089 NPRT(jcr->RestoreBootstrap),
1090 jcr->client->name(),
1091 jcr->fileset->name(),
1092 NPRT(jcr->pool->name()),
1093 jcr->rstore->name(),
1094 jcr->wstore?jcr->wstore->name():"*None*",
1095 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1096 bstrutime(dt, sizeof(dt), jcr->sched_time),
1097 jcr->catalog->name(),
1100 if (jcr->getJobType() == JT_COPY) {
1101 prt_type = _("Run Copy job\n");
1103 prt_type = _("Run Migration job\n");
1110 "Pool: %s (From %s)\n"
1111 "Read Storage: %s (From %s)\n"
1112 "Write Storage: %s (From %s)\n"
1119 NPRT(jcr->RestoreBootstrap),
1120 jcr->client->name(),
1121 jcr->fileset->name(),
1122 NPRT(jcr->pool->name()), jcr->pool_source,
1123 jcr->rstore->name(), jcr->rstore_source,
1124 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
1125 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1126 bstrutime(dt, sizeof(dt), jcr->sched_time),
1127 jcr->catalog->name(),
1132 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType());
1139 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
1143 static const char *kw[] = { /* command line arguments */
1144 "job", /* Used in a switch() */
1152 "regexwhere", /* 8 where string as a bregexp */
1154 "bootstrap", /* 10 */
1157 "priority", /* 13 */
1158 "yes", /* 14 -- if you change this change YES_POS too */
1159 "verifyjob", /* 15 */
1160 "files", /* 16 number of files to restore */
1161 "catalog", /* 17 override catalog */
1162 "since", /* 18 since */
1163 "cloned", /* 19 cloned */
1164 "verifylist", /* 20 verify output list */
1165 "migrationjob", /* 21 migration job name */
1167 "backupclient", /* 23 */
1168 "restoreclient", /* 24 */
1169 "pluginoptions", /* 25 */
1170 "spooldata", /* 26 */
1175 rc.catalog_name = NULL;
1177 rc.pool_name = NULL;
1178 rc.store_name = NULL;
1179 rc.client_name = NULL;
1180 rc.restore_client_name = NULL;
1181 rc.fileset_name = NULL;
1182 rc.verify_job_name = NULL;
1183 rc.previous_job_name = NULL;
1184 rc.spool_data_set = 0;
1187 for (i=1; i<ua->argc; i++) {
1188 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1190 /* Keep looking until we find a good keyword */
1191 for (j=0; !kw_ok && kw[j]; j++) {
1192 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1193 /* Note, yes and run have no value, so do not fail */
1194 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1195 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1198 Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
1202 ua->send_msg(_("Job name specified twice.\n"));
1205 rc.job_name = ua->argv[i];
1209 if (rc.jid && !rc.mod) {
1210 ua->send_msg(_("JobId specified twice.\n"));
1213 rc.jid = ua->argv[i];
1216 case 2: /* client */
1218 if (rc.client_name) {
1219 ua->send_msg(_("Client specified twice.\n"));
1222 rc.client_name = ua->argv[i];
1225 case 4: /* fileset */
1226 if (rc.fileset_name) {
1227 ua->send_msg(_("FileSet specified twice.\n"));
1230 rc.fileset_name = ua->argv[i];
1234 if (rc.level_name) {
1235 ua->send_msg(_("Level specified twice.\n"));
1238 rc.level_name = ua->argv[i];
1241 case 6: /* storage */
1243 if (rc.store_name) {
1244 ua->send_msg(_("Storage specified twice.\n"));
1247 rc.store_name = ua->argv[i];
1250 case 8: /* regexwhere */
1251 if ((rc.regexwhere || rc.where) && !rc.mod) {
1252 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1255 rc.regexwhere = ua->argv[i];
1256 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1257 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1263 if ((rc.where || rc.regexwhere) && !rc.mod) {
1264 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1267 rc.where = ua->argv[i];
1268 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1269 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1274 case 10: /* bootstrap */
1275 if (rc.bootstrap && !rc.mod) {
1276 ua->send_msg(_("Bootstrap specified twice.\n"));
1279 rc.bootstrap = ua->argv[i];
1282 case 11: /* replace */
1283 if (rc.replace && !rc.mod) {
1284 ua->send_msg(_("Replace specified twice.\n"));
1287 rc.replace = ua->argv[i];
1291 if (rc.when && !rc.mod) {
1292 ua->send_msg(_("When specified twice.\n"));
1295 rc.when = ua->argv[i];
1298 case 13: /* Priority */
1299 if (rc.Priority && !rc.mod) {
1300 ua->send_msg(_("Priority specified twice.\n"));
1303 rc.Priority = atoi(ua->argv[i]);
1304 if (rc.Priority <= 0) {
1305 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1313 case 15: /* Verify Job */
1314 if (rc.verify_job_name) {
1315 ua->send_msg(_("Verify Job specified twice.\n"));
1318 rc.verify_job_name = ua->argv[i];
1321 case 16: /* files */
1322 rc.files = atoi(ua->argv[i]);
1326 case 17: /* catalog */
1327 rc.catalog_name = ua->argv[i];
1331 case 18: /* since */
1332 rc.since = ua->argv[i];
1336 case 19: /* cloned */
1341 case 20: /* write verify list output */
1342 rc.verify_list = ua->argv[i];
1345 case 21: /* Migration Job */
1346 if (rc.previous_job_name) {
1347 ua->send_msg(_("Migration Job specified twice.\n"));
1350 rc.previous_job_name = ua->argv[i];
1355 ua->send_msg(_("Pool specified twice.\n"));
1358 rc.pool_name = ua->argv[i];
1361 case 23: /* backupclient */
1362 if (rc.client_name) {
1363 ua->send_msg(_("Client specified twice.\n"));
1366 rc.client_name = ua->argv[i];
1369 case 24: /* restoreclient */
1370 if (rc.restore_client_name && !rc.mod) {
1371 ua->send_msg(_("Restore Client specified twice.\n"));
1374 rc.restore_client_name = ua->argv[i];
1377 case 25: /* pluginoptions */
1378 ua->send_msg(_("Plugin Options not yet implemented.\n"));
1380 if (rc.plugin_options) {
1381 ua->send_msg(_("Plugin Options specified twice.\n"));
1384 rc.plugin_options = ua->argv[i];
1385 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1386 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1391 case 26: /* spooldata */
1392 if (rc.spool_data_set) {
1393 ua->send_msg(_("Spool flag specified twice.\n"));
1396 if (is_yesno(ua->argv[i], &rc.spool_data)) {
1397 rc.spool_data_set = 1;
1400 ua->send_msg(_("Invalid spooldata flag.\n"));
1406 } /* end strcase compare */
1407 } /* end keyword loop */
1409 * End of keyword for loop -- if not found, we got a bogus keyword
1412 Dmsg1(800, "%s not found\n", ua->argk[i]);
1414 * Special case for Job Name, it can be the first
1415 * keyword that has no value.
1417 if (!rc.job_name && !ua->argv[i]) {
1418 rc.job_name = ua->argk[i]; /* use keyword as job name */
1419 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1421 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1425 } /* end argc loop */
1427 Dmsg0(800, "Done scan.\n");
1429 if (rc.catalog_name) {
1430 rc.catalog = GetCatalogResWithName(rc.catalog_name);
1431 if (rc.catalog == NULL) {
1432 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1435 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1436 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1440 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1444 rc.job = GetJobResWithName(rc.job_name);
1446 if (*rc.job_name != 0) {
1447 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1449 rc.job = select_job_resource(ua);
1451 Dmsg1(800, "Found job=%s\n", rc.job_name);
1453 } else if (!rc.job) {
1454 ua->send_msg(_("A job name must be specified.\n"));
1455 rc.job = select_job_resource(ua);
1459 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1460 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1465 rc.pool = GetPoolResWithName(rc.pool_name);
1467 if (*rc.pool_name != 0) {
1468 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1470 rc.pool = select_pool_resource(ua);
1472 } else if (!rc.pool) {
1473 rc.pool = rc.job->pool; /* use default */
1477 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1478 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1481 Dmsg1(100, "Using pool %s\n", rc.pool->name());
1483 if (rc.spool_data_set) {
1484 rc.job->spool_data = rc.spool_data;
1486 Dmsg1(900, "Spooling data: %s\n", (rc.job->spool_data ? "Yes" : "No"));
1488 if (rc.store_name) {
1489 rc.store->store = GetStoreResWithName(rc.store_name);
1490 pm_strcpy(rc.store->store_source, _("command line"));
1491 if (!rc.store->store) {
1492 if (*rc.store_name != 0) {
1493 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1495 rc.store->store = select_storage_resource(ua);
1496 pm_strcpy(rc.store->store_source, _("user selection"));
1498 } else if (!rc.store->store) {
1499 get_job_storage(rc.store, rc.job, NULL); /* use default */
1501 if (!rc.store->store) {
1502 ua->error_msg(_("No storage specified.\n"));
1504 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1505 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1506 rc.store->store->name());
1509 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1511 if (rc.client_name) {
1512 rc.client = GetClientResWithName(rc.client_name);
1514 if (*rc.client_name != 0) {
1515 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1517 rc.client = select_client_resource(ua);
1519 } else if (!rc.client) {
1520 rc.client = rc.job->client; /* use default */
1524 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1525 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1529 Dmsg1(800, "Using client=%s\n", rc.client->name());
1531 if (rc.restore_client_name) {
1532 rc.client = GetClientResWithName(rc.restore_client_name);
1534 if (*rc.restore_client_name != 0) {
1535 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1537 rc.client = select_client_resource(ua);
1539 } else if (!rc.client) {
1540 rc.client = rc.job->client; /* use default */
1544 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1545 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1549 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1552 if (rc.fileset_name) {
1553 rc.fileset = GetFileSetResWithName(rc.fileset_name);
1555 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1556 rc.fileset = select_fileset_resource(ua);
1558 } else if (!rc.fileset) {
1559 rc.fileset = rc.job->fileset; /* use default */
1563 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1564 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1565 rc.fileset->name());
1569 if (rc.verify_job_name) {
1570 rc.verify_job = GetJobResWithName(rc.verify_job_name);
1571 if (!rc.verify_job) {
1572 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1573 rc.verify_job = select_job_resource(ua);
1575 } else if (!rc.verify_job) {
1576 rc.verify_job = rc.job->verify_job;
1579 if (rc.previous_job_name) {
1580 rc.previous_job = GetJobResWithName(rc.previous_job_name);
1581 if (!rc.previous_job) {
1582 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1583 rc.previous_job = select_job_resource(ua);
1586 rc.previous_job = rc.job->verify_job;