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 Admin Job\n"
777 jcr->fileset->name(),
778 NPRT(jcr->client->name()),
779 jcr->wstore?jcr->wstore->name():"*None*",
780 bstrutime(dt, sizeof(dt), jcr->sched_time),
783 jcr->set_JobLevel(L_FULL);
787 if (jcr->getJobType() == JT_BACKUP) {
789 ua->signal(BNET_RUN_CMD);
790 ua->send_msg("Type: Backup\n"
791 "Title: Run Backup Job\n"
802 level_to_str(jcr->getJobLevel()),
804 jcr->fileset->name(),
805 NPRT(jcr->pool->name()),
806 jcr->wstore?jcr->wstore->name():"*None*",
807 bstrutime(dt, sizeof(dt), jcr->sched_time),
809 jcr->plugin_options?"Plugin Options: ":"",
810 jcr->plugin_options?jcr->plugin_options:"",
811 jcr->plugin_options?"\n":"");
813 ua->send_msg(_("Run Backup job\n"
818 "Pool: %s (From %s)\n"
819 "Storage: %s (From %s)\n"
824 level_to_str(jcr->getJobLevel()),
826 jcr->fileset->name(),
827 NPRT(jcr->pool->name()), jcr->pool_source,
828 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
829 bstrutime(dt, sizeof(dt), jcr->sched_time),
831 jcr->plugin_options?"Plugin Options: ":"",
832 jcr->plugin_options?jcr->plugin_options:"",
833 jcr->plugin_options?"\n":"");
835 } else { /* JT_VERIFY */
837 if (jcr->verify_job) {
838 Name = jcr->verify_job->name();
843 verify_list = job->WriteVerifyList;
849 ua->signal(BNET_RUN_CMD);
850 ua->send_msg("Type: Verify\n"
851 "Title: Run Verify Job\n"
856 "Pool: %s (From %s)\n"
857 "Storage: %s (From %s)\n"
863 level_to_str(jcr->getJobLevel()),
865 jcr->fileset->name(),
866 NPRT(jcr->pool->name()), jcr->pool_source,
867 jcr->rstore->name(), jcr->rstore_source,
870 bstrutime(dt, sizeof(dt), jcr->sched_time),
873 ua->send_msg(_("Run Verify Job\n"
878 "Pool: %s (From %s)\n"
879 "Storage: %s (From %s)\n"
885 level_to_str(jcr->getJobLevel()),
887 jcr->fileset->name(),
888 NPRT(jcr->pool->name()), jcr->pool_source,
889 jcr->rstore->name(), jcr->rstore_source,
892 bstrutime(dt, sizeof(dt), jcr->sched_time),
898 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
900 jcr->RestoreJobId = str_to_int64(jid);
902 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
905 jcr->RestoreJobId = ua->int64_val;
908 jcr->set_JobLevel(L_FULL); /* default level */
909 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
910 if (jcr->RestoreJobId == 0) {
911 /* RegexWhere is take before RestoreWhere */
912 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
914 ua->signal(BNET_RUN_CMD);
915 ua->send_msg("Type: Restore\n"
916 "Title: Run Restore Job\n"
922 "Backup Client: %s\n"
923 "Restore Client: %s\n"
928 "Plugin Options: %s\n",
930 NPRT(jcr->RestoreBootstrap),
931 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
933 jcr->fileset->name(),
937 bstrutime(dt, sizeof(dt), jcr->sched_time),
938 jcr->catalog->name(),
940 NPRT(jcr->plugin_options));
942 ua->send_msg(_("Run Restore job\n"
948 "Backup Client: %s\n"
949 "Restore Client: %s\n"
954 "Plugin Options: %s\n"),
956 NPRT(jcr->RestoreBootstrap),
957 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
959 jcr->fileset->name(),
963 bstrutime(dt, sizeof(dt), jcr->sched_time),
964 jcr->catalog->name(),
966 NPRT(jcr->plugin_options));
970 ua->signal(BNET_RUN_CMD);
971 ua->send_msg("Type: Restore\n"
972 "Title: Run Restore job\n"
978 "Backup Client: %s\n"
979 "Restore Client: %s\n"
984 "Plugin Options: %s\n",
986 NPRT(jcr->RestoreBootstrap),
987 jcr->where?jcr->where:NPRT(job->RestoreWhere),
989 jcr->fileset->name(),
993 bstrutime(dt, sizeof(dt), jcr->sched_time),
994 jcr->catalog->name(),
996 NPRT(jcr->plugin_options));
998 ua->send_msg(_("Run Restore job\n"
1004 "Backup Client: %s\n"
1005 "Restore Client: %s\n"
1010 "Plugin Options: %s\n"),
1012 NPRT(jcr->RestoreBootstrap),
1013 jcr->where?jcr->where:NPRT(job->RestoreWhere),
1015 jcr->fileset->name(),
1017 jcr->client->name(),
1018 jcr->rstore->name(),
1019 bstrutime(dt, sizeof(dt), jcr->sched_time),
1020 jcr->catalog->name(),
1022 NPRT(jcr->plugin_options));
1027 /* ***FIXME*** This needs to be fixed for bat */
1028 if (ua->api) ua->signal(BNET_RUN_CMD);
1029 ua->send_msg(_("Run Restore job\n"
1033 NPRT(jcr->RestoreBootstrap));
1035 /* RegexWhere is take before RestoreWhere */
1036 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
1037 ua->send_msg(_("RegexWhere: %s\n"),
1038 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
1040 ua->send_msg(_("Where: %s\n"),
1041 jcr->where?jcr->where:NPRT(job->RestoreWhere));
1044 ua->send_msg(_("Replace: %s\n"
1051 "Plugin Options: %s\n"),
1053 jcr->client->name(),
1054 jcr->rstore->name(),
1055 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
1056 bstrutime(dt, sizeof(dt), jcr->sched_time),
1057 jcr->catalog->name(),
1059 NPRT(jcr->plugin_options));
1065 jcr->set_JobLevel(L_FULL); /* default level */
1067 ua->signal(BNET_RUN_CMD);
1068 if (jcr->getJobType() == JT_COPY) {
1069 prt_type = (char *)"Type: Copy\nTitle: Run Copy Job\n";
1071 prt_type = (char *)"Type: Migration\nTitle: Run Migration Job\n";
1079 "Read Storage: %s\n"
1080 "Write Storage: %s\n"
1087 NPRT(jcr->RestoreBootstrap),
1088 jcr->client->name(),
1089 jcr->fileset->name(),
1090 NPRT(jcr->pool->name()),
1091 jcr->rstore->name(),
1092 jcr->wstore?jcr->wstore->name():"*None*",
1093 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1094 bstrutime(dt, sizeof(dt), jcr->sched_time),
1095 jcr->catalog->name(),
1098 if (jcr->getJobType() == JT_COPY) {
1099 prt_type = _("Run Copy job\n");
1101 prt_type = _("Run Migration job\n");
1108 "Pool: %s (From %s)\n"
1109 "Read Storage: %s (From %s)\n"
1110 "Write Storage: %s (From %s)\n"
1117 NPRT(jcr->RestoreBootstrap),
1118 jcr->client->name(),
1119 jcr->fileset->name(),
1120 NPRT(jcr->pool->name()), jcr->pool_source,
1121 jcr->rstore->name(), jcr->rstore_source,
1122 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
1123 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1124 bstrutime(dt, sizeof(dt), jcr->sched_time),
1125 jcr->catalog->name(),
1130 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType());
1137 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
1141 static const char *kw[] = { /* command line arguments */
1142 "job", /* Used in a switch() */
1150 "regexwhere", /* 8 where string as a bregexp */
1152 "bootstrap", /* 10 */
1155 "priority", /* 13 */
1156 "yes", /* 14 -- if you change this change YES_POS too */
1157 "verifyjob", /* 15 */
1158 "files", /* 16 number of files to restore */
1159 "catalog", /* 17 override catalog */
1160 "since", /* 18 since */
1161 "cloned", /* 19 cloned */
1162 "verifylist", /* 20 verify output list */
1163 "migrationjob", /* 21 migration job name */
1165 "backupclient", /* 23 */
1166 "restoreclient", /* 24 */
1167 "pluginoptions", /* 25 */
1168 "spooldata", /* 26 */
1173 rc.catalog_name = NULL;
1175 rc.pool_name = NULL;
1176 rc.store_name = NULL;
1177 rc.client_name = NULL;
1178 rc.restore_client_name = NULL;
1179 rc.fileset_name = NULL;
1180 rc.verify_job_name = NULL;
1181 rc.previous_job_name = NULL;
1182 rc.spool_data_set = 0;
1185 for (i=1; i<ua->argc; i++) {
1186 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1188 /* Keep looking until we find a good keyword */
1189 for (j=0; !kw_ok && kw[j]; j++) {
1190 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1191 /* Note, yes and run have no value, so do not fail */
1192 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1193 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1196 Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
1200 ua->send_msg(_("Job name specified twice.\n"));
1203 rc.job_name = ua->argv[i];
1207 if (rc.jid && !rc.mod) {
1208 ua->send_msg(_("JobId specified twice.\n"));
1211 rc.jid = ua->argv[i];
1214 case 2: /* client */
1216 if (rc.client_name) {
1217 ua->send_msg(_("Client specified twice.\n"));
1220 rc.client_name = ua->argv[i];
1223 case 4: /* fileset */
1224 if (rc.fileset_name) {
1225 ua->send_msg(_("FileSet specified twice.\n"));
1228 rc.fileset_name = ua->argv[i];
1232 if (rc.level_name) {
1233 ua->send_msg(_("Level specified twice.\n"));
1236 rc.level_name = ua->argv[i];
1239 case 6: /* storage */
1241 if (rc.store_name) {
1242 ua->send_msg(_("Storage specified twice.\n"));
1245 rc.store_name = ua->argv[i];
1248 case 8: /* regexwhere */
1249 if ((rc.regexwhere || rc.where) && !rc.mod) {
1250 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1253 rc.regexwhere = ua->argv[i];
1254 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1255 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1261 if ((rc.where || rc.regexwhere) && !rc.mod) {
1262 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1265 rc.where = ua->argv[i];
1266 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1267 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1272 case 10: /* bootstrap */
1273 if (rc.bootstrap && !rc.mod) {
1274 ua->send_msg(_("Bootstrap specified twice.\n"));
1277 rc.bootstrap = ua->argv[i];
1280 case 11: /* replace */
1281 if (rc.replace && !rc.mod) {
1282 ua->send_msg(_("Replace specified twice.\n"));
1285 rc.replace = ua->argv[i];
1289 if (rc.when && !rc.mod) {
1290 ua->send_msg(_("When specified twice.\n"));
1293 rc.when = ua->argv[i];
1296 case 13: /* Priority */
1297 if (rc.Priority && !rc.mod) {
1298 ua->send_msg(_("Priority specified twice.\n"));
1301 rc.Priority = atoi(ua->argv[i]);
1302 if (rc.Priority <= 0) {
1303 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1311 case 15: /* Verify Job */
1312 if (rc.verify_job_name) {
1313 ua->send_msg(_("Verify Job specified twice.\n"));
1316 rc.verify_job_name = ua->argv[i];
1319 case 16: /* files */
1320 rc.files = atoi(ua->argv[i]);
1324 case 17: /* catalog */
1325 rc.catalog_name = ua->argv[i];
1329 case 18: /* since */
1330 rc.since = ua->argv[i];
1334 case 19: /* cloned */
1339 case 20: /* write verify list output */
1340 rc.verify_list = ua->argv[i];
1343 case 21: /* Migration Job */
1344 if (rc.previous_job_name) {
1345 ua->send_msg(_("Migration Job specified twice.\n"));
1348 rc.previous_job_name = ua->argv[i];
1353 ua->send_msg(_("Pool specified twice.\n"));
1356 rc.pool_name = ua->argv[i];
1359 case 23: /* backupclient */
1360 if (rc.client_name) {
1361 ua->send_msg(_("Client specified twice.\n"));
1364 rc.client_name = ua->argv[i];
1367 case 24: /* restoreclient */
1368 if (rc.restore_client_name && !rc.mod) {
1369 ua->send_msg(_("Restore Client specified twice.\n"));
1372 rc.restore_client_name = ua->argv[i];
1375 case 25: /* pluginoptions */
1376 ua->send_msg(_("Plugin Options not yet implemented.\n"));
1378 if (rc.plugin_options) {
1379 ua->send_msg(_("Plugin Options specified twice.\n"));
1382 rc.plugin_options = ua->argv[i];
1383 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1384 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1389 case 26: /* spooldata */
1390 if (rc.spool_data_set) {
1391 ua->send_msg(_("Spool flag specified twice.\n"));
1394 if (is_yesno(ua->argv[i], &rc.spool_data)) {
1395 rc.spool_data_set = 1;
1398 ua->send_msg(_("Invalid spooldata flag.\n"));
1404 } /* end strcase compare */
1405 } /* end keyword loop */
1407 * End of keyword for loop -- if not found, we got a bogus keyword
1410 Dmsg1(800, "%s not found\n", ua->argk[i]);
1412 * Special case for Job Name, it can be the first
1413 * keyword that has no value.
1415 if (!rc.job_name && !ua->argv[i]) {
1416 rc.job_name = ua->argk[i]; /* use keyword as job name */
1417 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1419 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1423 } /* end argc loop */
1425 Dmsg0(800, "Done scan.\n");
1427 if (rc.catalog_name) {
1428 rc.catalog = GetCatalogResWithName(rc.catalog_name);
1429 if (rc.catalog == NULL) {
1430 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1433 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1434 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1438 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1442 rc.job = GetJobResWithName(rc.job_name);
1444 if (*rc.job_name != 0) {
1445 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1447 rc.job = select_job_resource(ua);
1449 Dmsg1(800, "Found job=%s\n", rc.job_name);
1451 } else if (!rc.job) {
1452 ua->send_msg(_("A job name must be specified.\n"));
1453 rc.job = select_job_resource(ua);
1457 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1458 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1463 rc.pool = GetPoolResWithName(rc.pool_name);
1465 if (*rc.pool_name != 0) {
1466 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1468 rc.pool = select_pool_resource(ua);
1470 } else if (!rc.pool) {
1471 rc.pool = rc.job->pool; /* use default */
1475 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1476 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1479 Dmsg1(100, "Using pool %s\n", rc.pool->name());
1481 if (rc.spool_data_set) {
1482 rc.job->spool_data = rc.spool_data;
1484 Dmsg1(900, "Spooling data: %s\n", (rc.job->spool_data ? "Yes" : "No"));
1486 if (rc.store_name) {
1487 rc.store->store = GetStoreResWithName(rc.store_name);
1488 pm_strcpy(rc.store->store_source, _("command line"));
1489 if (!rc.store->store) {
1490 if (*rc.store_name != 0) {
1491 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1493 rc.store->store = select_storage_resource(ua);
1494 pm_strcpy(rc.store->store_source, _("user selection"));
1496 } else if (!rc.store->store) {
1497 get_job_storage(rc.store, rc.job, NULL); /* use default */
1499 if (!rc.store->store) {
1500 ua->error_msg(_("No storage specified.\n"));
1502 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1503 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1504 rc.store->store->name());
1507 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1509 if (rc.client_name) {
1510 rc.client = GetClientResWithName(rc.client_name);
1512 if (*rc.client_name != 0) {
1513 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1515 rc.client = select_client_resource(ua);
1517 } else if (!rc.client) {
1518 rc.client = rc.job->client; /* use default */
1522 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1523 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1527 Dmsg1(800, "Using client=%s\n", rc.client->name());
1529 if (rc.restore_client_name) {
1530 rc.client = GetClientResWithName(rc.restore_client_name);
1532 if (*rc.restore_client_name != 0) {
1533 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1535 rc.client = select_client_resource(ua);
1537 } else if (!rc.client) {
1538 rc.client = rc.job->client; /* use default */
1542 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1543 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1547 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1550 if (rc.fileset_name) {
1551 rc.fileset = GetFileSetResWithName(rc.fileset_name);
1553 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1554 rc.fileset = select_fileset_resource(ua);
1556 } else if (!rc.fileset) {
1557 rc.fileset = rc.job->fileset; /* use default */
1561 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1562 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1563 rc.fileset->name());
1567 if (rc.verify_job_name) {
1568 rc.verify_job = GetJobResWithName(rc.verify_job_name);
1569 if (!rc.verify_job) {
1570 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1571 rc.verify_job = select_job_resource(ua);
1573 } else if (!rc.verify_job) {
1574 rc.verify_job = rc.job->verify_job;
1577 if (rc.previous_job_name) {
1578 rc.previous_job = GetJobResWithName(rc.previous_job_name);
1579 if (!rc.previous_job) {
1580 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1581 rc.previous_job = select_job_resource(ua);
1584 rc.previous_job = rc.job->verify_job;