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, *comment;
45 char *when, *verify_job_name, *catalog_name;
46 char *previous_job_name;
49 const char *verify_list;
65 bool allow_duplicates_set;
68 run_ctx() { memset(this, 0, sizeof(run_ctx));
69 store = new USTORE; };
70 ~run_ctx() { delete store; };
73 /* Forward referenced subroutines */
74 static void select_job_level(UAContext *ua, JCR *jcr);
75 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job,
76 const char *verify_list, char *jid, const char *replace,
78 static void select_where_regexp(UAContext *ua, JCR *jcr);
79 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc);
80 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc);
81 static int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc);
83 /* Imported variables */
84 extern struct s_kw ReplaceOptions[];
87 * For Backup and Verify Jobs
88 * run [job=]<job-name> level=<level-name>
97 int run_cmd(UAContext *ua, const char *cmd)
103 if (!open_client_db(ua)) {
107 if (!scan_command_line_arguments(ua, rc)) {
111 if (find_arg(ua, NT_("fdcalled")) > 0) {
112 jcr->file_bsock = dup_bsock(ua->UA_sock);
117 * Create JCR to run job. NOTE!!! after this point, free_jcr()
121 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
122 set_jcr_defaults(jcr, rc.job);
123 jcr->unlink_bsr = ua->jcr->unlink_bsr; /* copy unlink flag from caller */
124 ua->jcr->unlink_bsr = false;
126 /* Transfer JobIds to new restore Job */
127 if (ua->jcr->JobIds) {
128 jcr->JobIds = ua->jcr->JobIds;
129 ua->jcr->JobIds = NULL;
133 if (!reset_restore_context(ua, jcr, rc)) {
138 /* Run without prompting? */
139 if (ua->batch || find_arg(ua, NT_("yes")) > 0) {
144 * Prompt User to see if all run job parameters are correct, and
145 * allow him to modify them.
147 if (!display_job_parameters(ua, jcr, rc.job, rc.verify_list, rc.jid, rc.replace,
152 if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
156 if (strncasecmp(ua->cmd, ".mod ", 5) == 0 ||
157 (strncasecmp(ua->cmd, "mod ", 4) == 0 && strlen(ua->cmd) > 6)) {
160 if (!scan_command_line_arguments(ua, rc)) {
166 /* Allow the user to modify the settings */
167 status = modify_job_parameters(ua, jcr, rc);
178 if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
180 Dmsg1(800, "Calling run_job job=%x\n", jcr->job);
183 Dmsg3(100, "JobId=%u using pool %s priority=%d\n", (int)jcr->JobId,
184 jcr->pool->name(), jcr->JobPriority);
185 Dmsg1(900, "Running a job; its spool_data = %d\n", jcr->spool_data);
186 JobId = run_job(jcr);
187 Dmsg4(100, "JobId=%u NewJobId=%d using pool %s priority=%d\n", (int)jcr->JobId,
188 JobId, jcr->pool->name(), jcr->JobPriority);
189 free_jcr(jcr); /* release jcr */
191 ua->error_msg(_("Job failed.\n"));
194 ua->send_msg(_("Job queued. JobId=%s\n"), edit_int64(JobId, ed1));
200 ua->send_msg(_("Job not run.\n"));
202 return 0; /* do not run */
205 int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc)
209 * At user request modify parameters of job to be run.
211 if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
214 start_prompt(ua, _("Parameters to modify:\n"));
215 add_prompt(ua, _("Level")); /* 0 */
216 add_prompt(ua, _("Storage")); /* 1 */
217 add_prompt(ua, _("Job")); /* 2 */
218 add_prompt(ua, _("FileSet")); /* 3 */
219 if (jcr->getJobType() == JT_RESTORE) {
220 add_prompt(ua, _("Restore Client")); /* 4 */
222 add_prompt(ua, _("Client")); /* 4 */
224 add_prompt(ua, _("When")); /* 5 */
225 add_prompt(ua, _("Priority")); /* 6 */
226 if (jcr->getJobType() == JT_BACKUP ||
227 jcr->getJobType() == JT_COPY ||
228 jcr->getJobType() == JT_MIGRATE ||
229 jcr->getJobType() == JT_VERIFY) {
230 add_prompt(ua, _("Pool")); /* 7 */
231 if (jcr->getJobType() == JT_VERIFY) {
232 add_prompt(ua, _("Verify Job")); /* 8 */
234 } else if (jcr->getJobType() == JT_RESTORE) {
235 add_prompt(ua, _("Bootstrap")); /* 7 */
236 add_prompt(ua, _("Where")); /* 8 */
237 add_prompt(ua, _("File Relocation"));/* 9 */
238 add_prompt(ua, _("Replace")); /* 10 */
239 add_prompt(ua, _("JobId")); /* 11 */
241 if (jcr->getJobType() == JT_BACKUP || jcr->getJobType() == JT_RESTORE) {
242 add_prompt(ua, _("Plugin Options")); /* 12 */
244 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
247 select_job_level(ua, jcr);
251 rc.store->store = select_storage_resource(ua);
252 if (rc.store->store) {
253 pm_strcpy(rc.store->store_source, _("user selection"));
254 set_rwstorage(jcr, rc.store);
260 rc.job = select_job_resource(ua);
263 set_jcr_defaults(jcr, rc.job);
269 rc.fileset = select_fileset_resource(ua);
271 jcr->fileset = rc.fileset;
277 rc.client = select_client_resource(ua);
279 jcr->client = rc.client;
285 if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
288 if (ua->cmd[0] == 0) {
289 jcr->sched_time = time(NULL);
291 jcr->sched_time = str_to_utime(ua->cmd);
292 if (jcr->sched_time == 0) {
293 ua->send_msg(_("Invalid time, using current time.\n"));
294 jcr->sched_time = time(NULL);
300 if (!get_pint(ua, _("Enter new Priority: "))) {
303 if (ua->pint32_val == 0) {
304 ua->send_msg(_("Priority must be a positive integer.\n"));
306 jcr->JobPriority = ua->pint32_val;
310 /* Pool or Bootstrap depending on JobType */
311 if (jcr->getJobType() == JT_BACKUP ||
312 jcr->getJobType() == JT_COPY ||
313 jcr->getJobType() == JT_MIGRATE ||
314 jcr->getJobType() == JT_VERIFY) { /* Pool */
315 rc.pool = select_pool_resource(ua);
318 Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
325 if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
328 if (jcr->RestoreBootstrap) {
329 free(jcr->RestoreBootstrap);
330 jcr->RestoreBootstrap = NULL;
332 if (ua->cmd[0] != 0) {
333 jcr->RestoreBootstrap = bstrdup(ua->cmd);
334 fd = fopen(jcr->RestoreBootstrap, "rb");
337 ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
338 jcr->RestoreBootstrap, be.bstrerror());
339 free(jcr->RestoreBootstrap);
340 jcr->RestoreBootstrap = NULL;
348 if (jcr->getJobType() == JT_VERIFY) {
349 rc.verify_job = select_job_resource(ua);
351 jcr->verify_job = rc.verify_job;
356 if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
359 if (jcr->RegexWhere) { /* cannot use regexwhere and where */
360 free(jcr->RegexWhere);
361 jcr->RegexWhere = NULL;
367 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
370 jcr->where = bstrdup(ua->cmd);
373 /* File relocation */
374 select_where_regexp(ua, jcr);
378 start_prompt(ua, _("Replace:\n"));
379 for (i=0; ReplaceOptions[i].name; i++) {
380 add_prompt(ua, ReplaceOptions[i].name);
382 opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
384 rc.replace = ReplaceOptions[opt].name;
385 jcr->replace = ReplaceOptions[opt].token;
390 rc.jid = NULL; /* force reprompt */
391 jcr->RestoreJobId = 0;
392 if (jcr->RestoreBootstrap) {
393 ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
398 if (!get_cmd(ua, _("Please Plugin Options string: "))) {
401 if (jcr->plugin_options) {
402 free(jcr->plugin_options);
403 jcr->plugin_options = NULL;
405 jcr->plugin_options = bstrdup(ua->cmd);
407 case -1: /* error or cancel */
424 * Reset the restore context.
425 * This subroutine can be called multiple times, so it
426 * must keep any prior settings.
428 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc)
432 jcr->verify_job = rc.verify_job;
433 jcr->previous_job = rc.previous_job;
435 if (jcr->pool != jcr->job->pool) {
436 pm_strcpy(jcr->pool_source, _("User input"));
438 set_rwstorage(jcr, rc.store);
439 jcr->client = rc.client;
440 pm_strcpy(jcr->client_name, rc.client->name());
441 jcr->fileset = rc.fileset;
442 jcr->ExpectedFiles = rc.files;
444 jcr->catalog = rc.catalog;
445 pm_strcpy(jcr->catalog_source, _("User input"));
448 pm_strcpy(jcr->comment, rc.comment);
454 jcr->where = bstrdup(rc.where);
459 if (jcr->RegexWhere) {
460 free(jcr->RegexWhere);
462 jcr->RegexWhere = bstrdup(rc.regexwhere);
463 rc.regexwhere = NULL;
467 jcr->sched_time = str_to_utime(rc.when);
468 if (jcr->sched_time == 0) {
469 ua->send_msg(_("Invalid time, using current time.\n"));
470 jcr->sched_time = time(NULL);
476 if (jcr->RestoreBootstrap) {
477 free(jcr->RestoreBootstrap);
479 jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
483 if (rc.plugin_options) {
484 if (jcr->plugin_options) {
485 free(jcr->plugin_options);
487 jcr->plugin_options = bstrdup(rc.plugin_options);
488 rc.plugin_options = NULL;
493 for (i=0; ReplaceOptions[i].name; i++) {
494 if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
495 jcr->replace = ReplaceOptions[i].token;
499 ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
502 } else if (rc.job->replace) {
503 jcr->replace = rc.job->replace;
505 jcr->replace = REPLACE_ALWAYS;
510 jcr->JobPriority = rc.Priority;
516 jcr->stime = get_pool_memory(PM_MESSAGE);
518 pm_strcpy(jcr->stime, rc.since);
523 jcr->cloned = rc.cloned;
527 /* If pool changed, update migration write storage */
528 if (jcr->is_JobType(JT_MIGRATE) || jcr->is_JobType(JT_COPY) ||
529 (jcr->is_JobType(JT_BACKUP) && jcr->is_JobLevel(L_VIRTUAL_FULL))) {
530 if (!set_migration_wstorage(jcr, rc.pool)) {
534 rc.replace = ReplaceOptions[0].name;
535 for (i=0; ReplaceOptions[i].name; i++) {
536 if (ReplaceOptions[i].token == jcr->replace) {
537 rc.replace = ReplaceOptions[i].name;
541 if (!get_level_from_name(jcr, rc.level_name)) {
542 ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
545 rc.level_name = NULL;
548 /* Note, this is also MigrateJobId and a VerifyJobId */
549 jcr->RestoreJobId = str_to_int64(rc.jid);
555 static void select_where_regexp(UAContext *ua, JCR *jcr)
558 char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
559 strip_prefix = add_suffix = rwhere = add_prefix = NULL;
562 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
563 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
565 start_prompt(ua, _("This will replace your current Where value\n"));
566 add_prompt(ua, _("Strip prefix")); /* 0 */
567 add_prompt(ua, _("Add prefix")); /* 1 */
568 add_prompt(ua, _("Add file suffix")); /* 2 */
569 add_prompt(ua, _("Enter a regexp")); /* 3 */
570 add_prompt(ua, _("Test filename manipulation")); /* 4 */
571 add_prompt(ua, _("Use this ?")); /* 5 */
573 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
576 if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
577 if (strip_prefix) bfree(strip_prefix);
578 strip_prefix = bstrdup(ua->cmd);
584 if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
585 if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
589 if (add_prefix) bfree(add_prefix);
590 add_prefix = bstrdup(ua->cmd);
595 if (get_cmd(ua, _("Please enter file suffix to add: "))) {
596 if (add_suffix) bfree(add_suffix);
597 add_suffix = bstrdup(ua->cmd);
602 if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
603 if (rwhere) bfree(rwhere);
604 rwhere = bstrdup(ua->cmd);
613 if (rwhere && rwhere[0] != '\0') {
614 regs = get_bregexps(rwhere);
615 ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
617 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
618 regexp = (char *) bmalloc (len * sizeof(char));
619 bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
620 regs = get_bregexps(regexp);
621 ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
622 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
628 ua->send_msg(_("Cannot use your regexp\n"));
631 ua->send_msg(_("Enter a period (.) to stop this test\n"));
632 while (get_cmd(ua, _("Please enter filename to test: "))) {
633 apply_bregexps(ua->cmd, regs, &result);
634 ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
643 case -1: /* error or cancel */
649 /* replace the existing where */
655 /* replace the existing regexwhere */
656 if (jcr->RegexWhere) {
657 bfree(jcr->RegexWhere);
658 jcr->RegexWhere = NULL;
662 jcr->RegexWhere = bstrdup(rwhere);
663 } else if (strip_prefix || add_prefix || add_suffix) {
664 int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
665 jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
666 bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
669 regs = get_bregexps(jcr->RegexWhere);
674 if (jcr->RegexWhere) {
675 bfree(jcr->RegexWhere);
676 jcr->RegexWhere = NULL;
678 ua->send_msg(_("Cannot use your regexp.\n"));
682 if (strip_prefix) bfree(strip_prefix);
683 if (add_prefix) bfree(add_prefix);
684 if (add_suffix) bfree(add_suffix);
685 if (rwhere) bfree(rwhere);
688 static void select_job_level(UAContext *ua, JCR *jcr)
690 if (jcr->getJobType() == JT_BACKUP) {
691 start_prompt(ua, _("Levels:\n"));
692 // add_prompt(ua, _("Base"));
693 add_prompt(ua, _("Full"));
694 add_prompt(ua, _("Incremental"));
695 add_prompt(ua, _("Differential"));
696 add_prompt(ua, _("Since"));
697 add_prompt(ua, _("VirtualFull"));
698 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
700 // jcr->JobLevel = L_BASE;
703 jcr->setJobLevel(L_FULL);
706 jcr->setJobLevel(L_INCREMENTAL);
709 jcr->setJobLevel(L_DIFFERENTIAL);
712 jcr->setJobLevel(L_SINCE);
715 jcr->setJobLevel(L_VIRTUAL_FULL);
720 } else if (jcr->getJobType() == JT_VERIFY) {
721 start_prompt(ua, _("Levels:\n"));
722 add_prompt(ua, _("Initialize Catalog"));
723 add_prompt(ua, _("Verify Catalog"));
724 add_prompt(ua, _("Verify Volume to Catalog"));
725 add_prompt(ua, _("Verify Disk to Catalog"));
726 add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
727 switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
729 jcr->setJobLevel(L_VERIFY_INIT);
732 jcr->setJobLevel(L_VERIFY_CATALOG);
735 jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
738 jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
741 jcr->setJobLevel(L_VERIFY_DATA);
747 ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
752 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
753 char *jid, const char *replace, char *client_name)
756 char dt[MAX_TIME_LENGTH];
758 Dmsg1(800, "JobType=%c\n", jcr->getJobType());
759 switch (jcr->getJobType()) {
762 ua->signal(BNET_RUN_CMD);
763 ua->send_msg("Type: Admin\n"
764 "Title: Run Admin Job\n"
772 jcr->fileset->name(),
773 NPRT(jcr->client->name()),
774 jcr->wstore?jcr->wstore->name():"*None*",
775 bstrutime(dt, sizeof(dt), jcr->sched_time),
778 ua->send_msg(_("Run Admin Job\n"
786 jcr->fileset->name(),
787 NPRT(jcr->client->name()),
788 jcr->wstore?jcr->wstore->name():"*None*",
789 bstrutime(dt, sizeof(dt), jcr->sched_time),
792 jcr->setJobLevel(L_FULL);
796 if (jcr->getJobType() == JT_BACKUP) {
798 ua->signal(BNET_RUN_CMD);
799 ua->send_msg("Type: Backup\n"
800 "Title: Run Backup Job\n"
811 level_to_str(jcr->getJobLevel()),
813 jcr->fileset->name(),
814 NPRT(jcr->pool->name()),
815 jcr->wstore?jcr->wstore->name():"*None*",
816 bstrutime(dt, sizeof(dt), jcr->sched_time),
818 jcr->plugin_options?"Plugin Options: ":"",
819 jcr->plugin_options?jcr->plugin_options:"",
820 jcr->plugin_options?"\n":"");
822 ua->send_msg(_("Run Backup job\n"
827 "Pool: %s (From %s)\n"
828 "Storage: %s (From %s)\n"
833 level_to_str(jcr->getJobLevel()),
835 jcr->fileset->name(),
836 NPRT(jcr->pool->name()), jcr->pool_source,
837 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
838 bstrutime(dt, sizeof(dt), jcr->sched_time),
840 jcr->plugin_options?"Plugin Options: ":"",
841 jcr->plugin_options?jcr->plugin_options:"",
842 jcr->plugin_options?"\n":"");
844 } else { /* JT_VERIFY */
847 if (jcr->verify_job) {
848 Name = jcr->verify_job->name();
849 } else if (jcr->RestoreJobId) { /* Display job name if jobid requested */
850 memset(&jr, 0, sizeof(jr));
851 jr.JobId = jcr->RestoreJobId;
852 if (!db_get_job_record(jcr, ua->db, &jr)) {
853 ua->error_msg(_("Could not get job record for selected JobId. ERR=%s"),
854 db_strerror(ua->db));
862 verify_list = job->WriteVerifyList;
868 ua->signal(BNET_RUN_CMD);
869 ua->send_msg("Type: Verify\n"
870 "Title: Run Verify Job\n"
875 "Pool: %s (From %s)\n"
876 "Storage: %s (From %s)\n"
882 level_to_str(jcr->getJobLevel()),
884 jcr->fileset->name(),
885 NPRT(jcr->pool->name()), jcr->pool_source,
886 jcr->rstore->name(), jcr->rstore_source,
889 bstrutime(dt, sizeof(dt), jcr->sched_time),
892 ua->send_msg(_("Run Verify Job\n"
897 "Pool: %s (From %s)\n"
898 "Storage: %s (From %s)\n"
904 level_to_str(jcr->getJobLevel()),
906 jcr->fileset->name(),
907 NPRT(jcr->pool->name()), jcr->pool_source,
908 jcr->rstore->name(), jcr->rstore_source,
911 bstrutime(dt, sizeof(dt), jcr->sched_time),
917 if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
919 jcr->RestoreJobId = str_to_int64(jid);
921 if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
924 jcr->RestoreJobId = ua->int64_val;
927 jcr->setJobLevel(L_FULL); /* default level */
928 Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
929 if (jcr->RestoreJobId == 0) {
930 /* RegexWhere is take before RestoreWhere */
931 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
933 ua->signal(BNET_RUN_CMD);
934 ua->send_msg("Type: Restore\n"
935 "Title: Run Restore Job\n"
941 "Backup Client: %s\n"
942 "Restore Client: %s\n"
947 "Plugin Options: %s\n",
949 NPRT(jcr->RestoreBootstrap),
950 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
952 jcr->fileset->name(),
956 bstrutime(dt, sizeof(dt), jcr->sched_time),
957 jcr->catalog->name(),
959 NPRT(jcr->plugin_options));
961 ua->send_msg(_("Run Restore job\n"
967 "Backup Client: %s\n"
968 "Restore Client: %s\n"
973 "Plugin Options: %s\n"),
975 NPRT(jcr->RestoreBootstrap),
976 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
978 jcr->fileset->name(),
982 bstrutime(dt, sizeof(dt), jcr->sched_time),
983 jcr->catalog->name(),
985 NPRT(jcr->plugin_options));
989 ua->signal(BNET_RUN_CMD);
990 ua->send_msg("Type: Restore\n"
991 "Title: Run Restore job\n"
997 "Backup Client: %s\n"
998 "Restore Client: %s\n"
1003 "Plugin Options: %s\n",
1005 NPRT(jcr->RestoreBootstrap),
1006 jcr->where?jcr->where:NPRT(job->RestoreWhere),
1008 jcr->fileset->name(),
1010 jcr->client->name(),
1011 jcr->rstore->name(),
1012 bstrutime(dt, sizeof(dt), jcr->sched_time),
1013 jcr->catalog->name(),
1015 NPRT(jcr->plugin_options));
1017 ua->send_msg(_("Run Restore job\n"
1023 "Backup Client: %s\n"
1024 "Restore Client: %s\n"
1029 "Plugin Options: %s\n"),
1031 NPRT(jcr->RestoreBootstrap),
1032 jcr->where?jcr->where:NPRT(job->RestoreWhere),
1034 jcr->fileset->name(),
1036 jcr->client->name(),
1037 jcr->rstore->name(),
1038 bstrutime(dt, sizeof(dt), jcr->sched_time),
1039 jcr->catalog->name(),
1041 NPRT(jcr->plugin_options));
1046 /* ***FIXME*** This needs to be fixed for bat */
1047 if (ua->api) ua->signal(BNET_RUN_CMD);
1048 ua->send_msg(_("Run Restore job\n"
1052 NPRT(jcr->RestoreBootstrap));
1054 /* RegexWhere is take before RestoreWhere */
1055 if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
1056 ua->send_msg(_("RegexWhere: %s\n"),
1057 jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
1059 ua->send_msg(_("Where: %s\n"),
1060 jcr->where?jcr->where:NPRT(job->RestoreWhere));
1063 ua->send_msg(_("Replace: %s\n"
1070 "Plugin Options: %s\n"),
1072 jcr->client->name(),
1073 jcr->rstore->name(),
1074 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
1075 bstrutime(dt, sizeof(dt), jcr->sched_time),
1076 jcr->catalog->name(),
1078 NPRT(jcr->plugin_options));
1084 jcr->setJobLevel(L_FULL); /* default level */
1086 ua->signal(BNET_RUN_CMD);
1087 if (jcr->getJobType() == JT_COPY) {
1088 prt_type = (char *)"Type: Copy\nTitle: Run Copy Job\n";
1090 prt_type = (char *)"Type: Migration\nTitle: Run Migration Job\n";
1098 "Read Storage: %s\n"
1099 "Write Storage: %s\n"
1106 NPRT(jcr->RestoreBootstrap),
1107 jcr->client->name(),
1108 jcr->fileset->name(),
1109 NPRT(jcr->pool->name()),
1110 jcr->rstore->name(),
1111 jcr->wstore?jcr->wstore->name():"*None*",
1112 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1113 bstrutime(dt, sizeof(dt), jcr->sched_time),
1114 jcr->catalog->name(),
1117 if (jcr->getJobType() == JT_COPY) {
1118 prt_type = _("Run Copy job\n");
1120 prt_type = _("Run Migration job\n");
1127 "Pool: %s (From %s)\n"
1128 "Read Storage: %s (From %s)\n"
1129 "Write Storage: %s (From %s)\n"
1136 NPRT(jcr->RestoreBootstrap),
1137 jcr->client->name(),
1138 jcr->fileset->name(),
1139 NPRT(jcr->pool->name()), jcr->pool_source,
1140 jcr->rstore->name(), jcr->rstore_source,
1141 jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
1142 jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1143 bstrutime(dt, sizeof(dt), jcr->sched_time),
1144 jcr->catalog->name(),
1149 ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType());
1156 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
1160 static const char *kw[] = { /* command line arguments */
1161 "job", /* Used in a switch() */
1169 "regexwhere", /* 8 where string as a bregexp */
1171 "bootstrap", /* 10 */
1174 "priority", /* 13 */
1175 "yes", /* 14 -- if you change this change YES_POS too */
1176 "verifyjob", /* 15 */
1177 "files", /* 16 number of files to restore */
1178 "catalog", /* 17 override catalog */
1179 "since", /* 18 since */
1180 "cloned", /* 19 cloned */
1181 "verifylist", /* 20 verify output list */
1182 "migrationjob", /* 21 migration job name */
1184 "backupclient", /* 23 */
1185 "restoreclient", /* 24 */
1186 "pluginoptions", /* 25 */
1187 "spooldata", /* 26 */
1189 "allowduplicates", /* 28 */
1195 rc.catalog_name = NULL;
1197 rc.pool_name = NULL;
1198 rc.store_name = NULL;
1199 rc.client_name = NULL;
1200 rc.restore_client_name = NULL;
1201 rc.fileset_name = NULL;
1202 rc.verify_job_name = NULL;
1203 rc.previous_job_name = NULL;
1204 rc.spool_data_set = false;
1205 rc.allow_duplicates_set = false;
1208 for (i=1; i<ua->argc; i++) {
1209 Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1211 /* Keep looking until we find a good keyword */
1212 for (j=0; !kw_ok && kw[j]; j++) {
1213 if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1214 /* Note, yes and run have no value, so do not fail */
1215 if (!ua->argv[i] && j != YES_POS /*yes*/) {
1216 ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1219 Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
1223 ua->send_msg(_("Job name specified twice.\n"));
1226 rc.job_name = ua->argv[i];
1230 if (rc.jid && !rc.mod) {
1231 ua->send_msg(_("JobId specified twice.\n"));
1234 rc.jid = ua->argv[i];
1237 case 2: /* client */
1239 if (rc.client_name) {
1240 ua->send_msg(_("Client specified twice.\n"));
1243 rc.client_name = ua->argv[i];
1246 case 4: /* fileset */
1247 if (rc.fileset_name) {
1248 ua->send_msg(_("FileSet specified twice.\n"));
1251 rc.fileset_name = ua->argv[i];
1255 if (rc.level_name) {
1256 ua->send_msg(_("Level specified twice.\n"));
1259 rc.level_name = ua->argv[i];
1262 case 6: /* storage */
1264 if (rc.store_name) {
1265 ua->send_msg(_("Storage specified twice.\n"));
1268 rc.store_name = ua->argv[i];
1271 case 8: /* regexwhere */
1272 if ((rc.regexwhere || rc.where) && !rc.mod) {
1273 ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1276 rc.regexwhere = ua->argv[i];
1277 if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1278 ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1284 if ((rc.where || rc.regexwhere) && !rc.mod) {
1285 ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1288 rc.where = ua->argv[i];
1289 if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1290 ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1295 case 10: /* bootstrap */
1296 if (rc.bootstrap && !rc.mod) {
1297 ua->send_msg(_("Bootstrap specified twice.\n"));
1300 rc.bootstrap = ua->argv[i];
1303 case 11: /* replace */
1304 if (rc.replace && !rc.mod) {
1305 ua->send_msg(_("Replace specified twice.\n"));
1308 rc.replace = ua->argv[i];
1312 if (rc.when && !rc.mod) {
1313 ua->send_msg(_("When specified twice.\n"));
1316 rc.when = ua->argv[i];
1319 case 13: /* Priority */
1320 if (rc.Priority && !rc.mod) {
1321 ua->send_msg(_("Priority specified twice.\n"));
1324 rc.Priority = atoi(ua->argv[i]);
1325 if (rc.Priority <= 0) {
1326 ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1334 case 15: /* Verify Job */
1335 if (rc.verify_job_name) {
1336 ua->send_msg(_("Verify Job specified twice.\n"));
1339 rc.verify_job_name = ua->argv[i];
1342 case 16: /* files */
1343 rc.files = atoi(ua->argv[i]);
1346 case 17: /* catalog */
1347 rc.catalog_name = ua->argv[i];
1350 case 18: /* since */
1351 rc.since = ua->argv[i];
1354 case 19: /* cloned */
1358 case 20: /* write verify list output */
1359 rc.verify_list = ua->argv[i];
1362 case 21: /* Migration Job */
1363 if (rc.previous_job_name) {
1364 ua->send_msg(_("Migration Job specified twice.\n"));
1367 rc.previous_job_name = ua->argv[i];
1372 ua->send_msg(_("Pool specified twice.\n"));
1375 rc.pool_name = ua->argv[i];
1378 case 23: /* backupclient */
1379 if (rc.client_name) {
1380 ua->send_msg(_("Client specified twice.\n"));
1383 rc.client_name = ua->argv[i];
1386 case 24: /* restoreclient */
1387 if (rc.restore_client_name && !rc.mod) {
1388 ua->send_msg(_("Restore Client specified twice.\n"));
1391 rc.restore_client_name = ua->argv[i];
1394 case 25: /* pluginoptions */
1395 ua->send_msg(_("Plugin Options not yet implemented.\n"));
1397 if (rc.plugin_options) {
1398 ua->send_msg(_("Plugin Options specified twice.\n"));
1401 rc.plugin_options = ua->argv[i];
1402 if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1403 ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1408 case 26: /* spooldata */
1409 if (rc.spool_data_set) {
1410 ua->send_msg(_("Spool flag specified twice.\n"));
1413 if (is_yesno(ua->argv[i], &rc.spool_data)) {
1414 rc.spool_data_set = true;
1417 ua->send_msg(_("Invalid spooldata flag.\n"));
1420 case 27: /* comment */
1421 rc.comment = ua->argv[i];
1424 case 28: /* allowduplicates */
1425 if (rc.allow_duplicates_set) {
1426 ua->send_msg(_("AllowDuplicates flag specified twice.\n"));
1429 if (is_yesno(ua->argv[i], &rc.allow_duplicates)) {
1430 rc.allow_duplicates_set = true;
1433 ua->send_msg(_("Invalid allowduplicates flag.\n"));
1439 } /* end strcase compare */
1440 } /* end keyword loop */
1442 * End of keyword for loop -- if not found, we got a bogus keyword
1445 Dmsg1(800, "%s not found\n", ua->argk[i]);
1447 * Special case for Job Name, it can be the first
1448 * keyword that has no value.
1450 if (!rc.job_name && !ua->argv[i]) {
1451 rc.job_name = ua->argk[i]; /* use keyword as job name */
1452 Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1454 ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1458 } /* end argc loop */
1460 Dmsg0(800, "Done scan.\n");
1462 if (!is_comment_legal(ua, rc.comment)) {
1466 if (rc.catalog_name) {
1467 rc.catalog = GetCatalogResWithName(rc.catalog_name);
1468 if (rc.catalog == NULL) {
1469 ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1472 if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1473 ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1477 Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1481 rc.job = GetJobResWithName(rc.job_name);
1483 if (*rc.job_name != 0) {
1484 ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1486 rc.job = select_job_resource(ua);
1488 Dmsg1(800, "Found job=%s\n", rc.job_name);
1490 } else if (!rc.job) {
1491 ua->send_msg(_("A job name must be specified.\n"));
1492 rc.job = select_job_resource(ua);
1496 } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1497 ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1502 rc.pool = GetPoolResWithName(rc.pool_name);
1504 if (*rc.pool_name != 0) {
1505 ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1507 rc.pool = select_pool_resource(ua);
1509 } else if (!rc.pool) {
1510 rc.pool = rc.job->pool; /* use default */
1514 } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1515 ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1518 Dmsg1(100, "Using pool %s\n", rc.pool->name());
1520 if (rc.spool_data_set) {
1521 rc.job->spool_data = rc.spool_data;
1523 Dmsg1(900, "Spooling data: %s\n", (rc.job->spool_data ? "Yes" : "No"));
1525 if (rc.allow_duplicates_set) {
1526 rc.job->AllowDuplicateJobs = rc.allow_duplicates;
1528 Dmsg1(900, "Allow Duplicate Jobs: %s\n", (rc.job->AllowDuplicateJobs ? "Yes" : "No"));
1530 if (rc.store_name) {
1531 rc.store->store = GetStoreResWithName(rc.store_name);
1532 pm_strcpy(rc.store->store_source, _("command line"));
1533 if (!rc.store->store) {
1534 if (*rc.store_name != 0) {
1535 ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1537 rc.store->store = select_storage_resource(ua);
1538 pm_strcpy(rc.store->store_source, _("user selection"));
1540 } else if (!rc.store->store) {
1541 get_job_storage(rc.store, rc.job, NULL); /* use default */
1543 if (!rc.store->store) {
1544 ua->error_msg(_("No storage specified.\n"));
1546 } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1547 ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1548 rc.store->store->name());
1551 Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1553 if (rc.client_name) {
1554 rc.client = GetClientResWithName(rc.client_name);
1556 if (*rc.client_name != 0) {
1557 ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1559 rc.client = select_client_resource(ua);
1561 } else if (!rc.client) {
1562 rc.client = rc.job->client; /* use default */
1566 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1567 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1571 Dmsg1(800, "Using client=%s\n", rc.client->name());
1573 if (rc.restore_client_name) {
1574 rc.client = GetClientResWithName(rc.restore_client_name);
1576 if (*rc.restore_client_name != 0) {
1577 ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1579 rc.client = select_client_resource(ua);
1581 } else if (!rc.client) {
1582 rc.client = rc.job->client; /* use default */
1586 } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1587 ua->error_msg(_("No authorization. Client \"%s\".\n"),
1591 Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1593 if (rc.fileset_name) {
1594 rc.fileset = GetFileSetResWithName(rc.fileset_name);
1596 ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1597 rc.fileset = select_fileset_resource(ua);
1599 } else if (!rc.fileset) {
1600 rc.fileset = rc.job->fileset; /* use default */
1604 } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1605 ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1606 rc.fileset->name());
1610 if (rc.verify_job_name) {
1611 rc.verify_job = GetJobResWithName(rc.verify_job_name);
1612 if (!rc.verify_job) {
1613 ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1614 rc.verify_job = select_job_resource(ua);
1616 } else if (!rc.verify_job) {
1617 rc.verify_job = rc.job->verify_job;
1620 if (rc.previous_job_name) {
1621 rc.previous_job = GetJobResWithName(rc.previous_job_name);
1622 if (!rc.previous_job) {
1623 ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1624 rc.previous_job = select_job_resource(ua);
1627 rc.previous_job = rc.job->verify_job;