/* * Returns: false on failure * true on success */ bool do_admin(JCR *jcr) { jcr->jr.JobId = jcr->JobId; jcr->fname = (char *)get_pool_memory(PM_FNAME); /* Print Job Start message */ Jmsg(jcr, M_INFO, 0, _("Start Admin JobId %d, Job=%s\n"), jcr->JobId, jcr->Job); jcr->setJobStatus(JS_Running); admin_cleanup(jcr, JS_Terminated); return true; }
bool setup_job(JCR *jcr) { int errstat; jcr->lock(); Dsm_check(100); init_msg(jcr, jcr->res.messages, job_code_callback_director); /* * Initialize termination condition variable */ if ((errstat = pthread_cond_init(&jcr->term_wait, NULL)) != 0) { berrno be; Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.bstrerror(errstat)); jcr->unlock(); goto bail_out; } jcr->term_wait_inited = true; /* * Initialize nextrun ready condition variable */ if ((errstat = pthread_cond_init(&jcr->nextrun_ready, NULL)) != 0) { berrno be; Jmsg1(jcr, M_FATAL, 0, _("Unable to init job nextrun cond variable: ERR=%s\n"), be.bstrerror(errstat)); jcr->unlock(); goto bail_out; } jcr->nextrun_ready_inited = true; create_unique_job_name(jcr, jcr->res.job->name()); jcr->setJobStatus(JS_Created); jcr->unlock(); /* * Open database */ Dmsg0(100, "Open database\n"); jcr->db = db_sql_get_pooled_connection(jcr, jcr->res.catalog->db_driver, jcr->res.catalog->db_name, jcr->res.catalog->db_user, jcr->res.catalog->db_password, jcr->res.catalog->db_address, jcr->res.catalog->db_port, jcr->res.catalog->db_socket, jcr->res.catalog->mult_db_connections, jcr->res.catalog->disable_batch_insert); if (jcr->db == NULL) { Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"), jcr->res.catalog->db_name); goto bail_out; } Dmsg0(150, "DB opened\n"); if (!jcr->fname) { jcr->fname = get_pool_memory(PM_FNAME); } if (!jcr->res.pool_source) { jcr->res.pool_source = get_pool_memory(PM_MESSAGE); pm_strcpy(jcr->res.pool_source, _("unknown source")); } if (!jcr->res.npool_source) { jcr->res.npool_source = get_pool_memory(PM_MESSAGE); pm_strcpy(jcr->res.npool_source, _("unknown source")); } if (jcr->JobReads()) { if (!jcr->res.rpool_source) { jcr->res.rpool_source = get_pool_memory(PM_MESSAGE); pm_strcpy(jcr->res.rpool_source, _("unknown source")); } } /* * Create Job record */ init_jcr_job_record(jcr); if (!get_or_create_client_record(jcr)) { goto bail_out; } if (!db_create_job_record(jcr, jcr->db, &jcr->jr)) { Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db)); goto bail_out; } jcr->JobId = jcr->jr.JobId; Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n", jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel); new_plugins(jcr); /* instantiate plugins for this jcr */ generate_plugin_event(jcr, bDirEventJobStart); if (job_canceled(jcr)) { goto bail_out; } if (jcr->JobReads() && !jcr->rstorage) { if (jcr->res.job->storage) { copy_rwstorage(jcr, jcr->res.job->storage, _("Job resource")); } else { copy_rwstorage(jcr, jcr->res.job->pool->storage, _("Pool resource")); } } if (!jcr->JobReads()) { free_rstorage(jcr); } /* * Now, do pre-run stuff, like setting job level (Inc/diff, ...) * this allows us to setup a proper job start record for restarting * in case of later errors. */ switch (jcr->getJobType()) { case JT_BACKUP: switch (jcr->getJobProtocol()) { case PT_NDMP: if (!do_ndmp_backup_init(jcr)) { ndmp_backup_cleanup(jcr, JS_ErrorTerminated); goto bail_out; } break; default: if (jcr->is_JobLevel(L_VIRTUAL_FULL)) { if (!do_native_vbackup_init(jcr)) { native_vbackup_cleanup(jcr, JS_ErrorTerminated); goto bail_out; } } else { if (!do_native_backup_init(jcr)) { native_backup_cleanup(jcr, JS_ErrorTerminated); goto bail_out; } } break; } break; case JT_VERIFY: if (!do_verify_init(jcr)) { verify_cleanup(jcr, JS_ErrorTerminated); goto bail_out; } break; case JT_RESTORE: switch (jcr->getJobProtocol()) { case PT_NDMP: if (!do_ndmp_restore_init(jcr)) { ndmp_restore_cleanup(jcr, JS_ErrorTerminated); goto bail_out; } break; default: /* * Any non NDMP restore is not interested at the items * that were selected for restore so drop them now. */ if (jcr->restore_tree_root) { free_tree(jcr->restore_tree_root); jcr->restore_tree_root = NULL; } if (!do_native_restore_init(jcr)) { native_restore_cleanup(jcr, JS_ErrorTerminated); goto bail_out; } break; } break; case JT_ADMIN: if (!do_admin_init(jcr)) { admin_cleanup(jcr, JS_ErrorTerminated); goto bail_out; } break; case JT_COPY: case JT_MIGRATE: if (!do_migration_init(jcr)) { migration_cleanup(jcr, JS_ErrorTerminated); goto bail_out; } break; default: Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->getJobType()); jcr->setJobStatus(JS_ErrorTerminated); goto bail_out; } generate_plugin_event(jcr, bDirEventJobInit); Dsm_check(100); return true; bail_out: return false; }
/* * This is the engine called by jobq.c:jobq_add() when we were pulled * from the work queue. * At this point, we are running in our own thread and all * necessary resources are allocated -- see jobq.c */ static void *job_thread(void *arg) { JCR *jcr = (JCR *)arg; pthread_detach(pthread_self()); Dsm_check(100); Dmsg0(200, "=====Start Job=========\n"); jcr->setJobStatus(JS_Running); /* this will be set only if no error */ jcr->start_time = time(NULL); /* set the real start time */ jcr->jr.StartTime = jcr->start_time; if (jcr->res.job->MaxStartDelay != 0 && jcr->res.job->MaxStartDelay < (utime_t)(jcr->start_time - jcr->sched_time)) { jcr->setJobStatus(JS_Canceled); Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n")); } if (job_check_maxrunschedtime(jcr)) { jcr->setJobStatus(JS_Canceled); Jmsg(jcr, M_FATAL, 0, _("Job canceled because max run sched time exceeded.\n")); } /* TODO : check if it is used somewhere */ if (jcr->res.job->RunScripts == NULL) { Dmsg0(200, "Warning, job->RunScripts is empty\n"); jcr->res.job->RunScripts = New(alist(10, not_owned_by_alist)); } if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) { Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db)); } /* Run any script BeforeJob on dird */ run_scripts(jcr, jcr->res.job->RunScripts, "BeforeJob"); /* * We re-update the job start record so that the start * time is set after the run before job. This avoids * that any files created by the run before job will * be saved twice. They will be backed up in the current * job, but not in the next one unless they are changed. * Without this, they will be backed up in this job and * in the next job run because in that case, their date * is after the start of this run. */ jcr->start_time = time(NULL); jcr->jr.StartTime = jcr->start_time; if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) { Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db)); } generate_plugin_event(jcr, bDirEventJobRun); switch (jcr->getJobType()) { case JT_BACKUP: switch (jcr->getJobProtocol()) { case PT_NDMP: if (!job_canceled(jcr)) { if (do_ndmp_backup(jcr)) { do_autoprune(jcr); } else { ndmp_backup_cleanup(jcr, JS_ErrorTerminated); } } else { ndmp_backup_cleanup(jcr, JS_Canceled); } break; default: if (!job_canceled(jcr)) { if (jcr->is_JobLevel(L_VIRTUAL_FULL)) { if (do_native_vbackup(jcr)) { do_autoprune(jcr); } else { native_vbackup_cleanup(jcr, JS_ErrorTerminated); } } else { if (do_native_backup(jcr)) { do_autoprune(jcr); } else { native_backup_cleanup(jcr, JS_ErrorTerminated); } } } else { if (jcr->is_JobLevel(L_VIRTUAL_FULL)) { native_vbackup_cleanup(jcr, JS_Canceled); } else { native_backup_cleanup(jcr, JS_Canceled); } } break; } break; case JT_VERIFY: if (!job_canceled(jcr)) { if (do_verify(jcr)) { do_autoprune(jcr); } else { verify_cleanup(jcr, JS_ErrorTerminated); } } else { verify_cleanup(jcr, JS_Canceled); } break; case JT_RESTORE: switch (jcr->getJobProtocol()) { case PT_NDMP: if (!job_canceled(jcr)) { if (do_ndmp_restore(jcr)) { do_autoprune(jcr); } else { ndmp_restore_cleanup(jcr, JS_ErrorTerminated); } } else { ndmp_restore_cleanup(jcr, JS_Canceled); } break; default: if (!job_canceled(jcr)) { if (do_native_restore(jcr)) { do_autoprune(jcr); } else { native_restore_cleanup(jcr, JS_ErrorTerminated); } } else { native_restore_cleanup(jcr, JS_Canceled); } break; } break; case JT_ADMIN: if (!job_canceled(jcr)) { if (do_admin(jcr)) { do_autoprune(jcr); } else { admin_cleanup(jcr, JS_ErrorTerminated); } } else { admin_cleanup(jcr, JS_Canceled); } break; case JT_COPY: case JT_MIGRATE: if (!job_canceled(jcr)) { if (do_migration(jcr)) { do_autoprune(jcr); } else { migration_cleanup(jcr, JS_ErrorTerminated); } } else { migration_cleanup(jcr, JS_Canceled); } break; default: Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->getJobType()); break; } run_scripts(jcr, jcr->res.job->RunScripts, "AfterJob"); /* Send off any queued messages */ if (jcr->msg_queue && jcr->msg_queue->size() > 0) { dequeue_messages(jcr); } generate_plugin_event(jcr, bDirEventJobEnd); Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus); Dsm_check(100); return NULL; }
int main(int argc, char **argv) { void *dest_addr; struct cmd_struct *cmd; struct admin_opts opts; int i, ret, addr_type, status = 0; int cmd_num = ARRAY_SIZE(admin_cmds); int rsock; ret = parse_opts(argc, argv, &status); if (ret) exit(status); for (i = 0; i < cmd_num; i++) { cmd = admin_cmds + i; if (!strncmp(argv[optind], cmd->cmd, strlen(cmd->cmd))) break; } if (i == cmd_num) { fprintf(stderr, "Non-existing command specified\n"); show_usage(); exit(-1); } if (!strncmp(cmd->cmd, "help", 4)) { if (argc - optind <= 1) { fprintf(stderr, "No command was specified\n"); exit(-1); } for (i = 0; i < cmd_num; i++) { cmd = admin_cmds + i; if (!strncmp(argv[optind + 1], cmd->cmd, strlen(cmd->cmd))) break; } if (i == cmd_num) { fprintf(stderr, "Non-existing command specified\n"); show_usage(); exit(-1); } if (cmd) show_cmd_usage(cmd->cmd, admin_cmd_help(cmd->id), admin_get_cmd_opts(cmd->id)); exit(0); } if (dest_lid) { dest_addr = &dest_lid; addr_type = ADMIN_ADDR_TYPE_LID; } else { if (!dest_gid) dest_gid = "::1"; /* local host GID */ dest_addr = dest_gid; addr_type = ADMIN_ADDR_TYPE_GID; } if (admin_init(short_option, long_option) < 0) { fprintf(stderr, "ERROR - unable to init admin client\n"); exit(-1); } opts.dev = ca_name; opts.src_port = src_port; opts.admin_port = admin_port; opts.pkey = pkey; opts.timeout = timeout; rsock = admin_connect(dest_addr, addr_type, &opts); if (rsock < 0) { fprintf(stderr, "ERROR - unable to connect\n"); exit(-1); } optind = 1; ret = admin_exec_recursive(rsock, cmd->id, recursive, argc, argv); if (ret) { fprintf(stderr, "Failed executing '%s' command (%s)\n", cmd->cmd, admin_cmd_help(cmd->id)->desc); exit(-1); } admin_disconnect(rsock); admin_cleanup(); return 0; }