int main (int argc, char *argv[]) { int ch; bool no_signals = false; bool test_config = false; bool export_config = false; bool export_config_schema = false; pthread_t thid; char *uid = NULL; char *gid = NULL; start_heap = sbrk(0); setlocale(LC_ALL, ""); bindtextdomain("bareos", LOCALEDIR); textdomain("bareos"); init_stack_dump(); my_name_is(argc, argv, "bareos-sd"); init_msg(NULL, NULL); daemon_start_time = time(NULL); /* * Sanity checks */ if (TAPE_BSIZE % B_DEV_BSIZE != 0 || TAPE_BSIZE / B_DEV_BSIZE == 0) { Emsg2(M_ABORT, 0, _("Tape block size (%d) not multiple of system size (%d)\n"), TAPE_BSIZE, B_DEV_BSIZE); } if (TAPE_BSIZE != (1 << (ffs(TAPE_BSIZE)-1))) { Emsg1(M_ABORT, 0, _("Tape block size (%d) is not a power of 2\n"), TAPE_BSIZE); } while ((ch = getopt(argc, argv, "c:d:fg:mpstu:vx:?")) != -1) { switch (ch) { case 'c': /* configuration file */ if (configfile != NULL) { free(configfile); } configfile = bstrdup(optarg); break; case 'd': /* debug level */ if (*optarg == 't') { dbg_timestamp = true; } else { debug_level = atoi(optarg); if (debug_level <= 0) { debug_level = 1; } } break; case 'f': /* run in foreground */ foreground = true; break; case 'g': /* set group id */ gid = optarg; break; case 'm': /* print kaboom output */ prt_kaboom = true; break; case 'p': /* proceed in spite of I/O errors */ forge_on = true; break; case 's': /* no signals */ no_signals = true; break; case 't': test_config = true; break; case 'u': /* set uid */ uid = optarg; break; case 'v': /* verbose */ verbose++; break; case 'x': /* export configuration/schema and exit */ if (*optarg == 's') { export_config_schema = true; } else if (*optarg == 'c') { export_config = true; } else { usage(); } break; case '?': default: usage(); break; } } argc -= optind; argv += optind; if (argc) { if (configfile != NULL) { free(configfile); } configfile = bstrdup(*argv); argc--; argv++; } if (argc) { usage(); } /* * See if we want to drop privs. */ if (geteuid() == 0) { drop(uid, gid, false); } if (!no_signals) { init_signals(terminate_stored); } if (export_config_schema) { POOL_MEM buffer; my_config = new_config_parser(); init_sd_config(my_config, configfile, M_ERROR_TERM); print_config_schema_json(buffer); printf("%s\n", buffer.c_str()); goto bail_out; } my_config = new_config_parser(); parse_sd_config(my_config, configfile, M_ERROR_TERM); if (export_config) { my_config->dump_resources(prtmsg, NULL); goto bail_out; } if (!foreground && !test_config) { daemon_start(); /* become daemon */ init_stack_dump(); /* pick up new pid */ } if (init_crypto() != 0) { Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Cryptography library initialization failed.\n")); } if (!check_resources()) { Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), my_config->get_base_config_path()); } init_reservations_lock(); if (test_config) { terminate_stored(0); } my_name_is(0, (char **)NULL, me->name()); /* Set our real name */ create_pid_file(me->pid_directory, "bareos-sd", get_first_port_host_order(me->SDaddrs)); read_state_file(me->working_directory, "bareos-sd", get_first_port_host_order(me->SDaddrs)); read_crypto_cache(me->working_directory, "bareos-sd", get_first_port_host_order(me->SDaddrs)); set_jcr_in_tsd(INVALID_JCR); /* * Make sure on Solaris we can run concurrent, watch dog + servers + misc */ set_thread_concurrency(me->MaxConcurrentJobs * 2 + 4); lmgr_init_thread(); /* initialize the lockmanager stack */ load_sd_plugins(me->plugin_directory, me->plugin_names); cleanup_old_files(); /* Ensure that Volume Session Time and Id are both * set and are both non-zero. */ VolSessionTime = (uint32_t)daemon_start_time; if (VolSessionTime == 0) { /* paranoid */ Jmsg0(NULL, M_ABORT, 0, _("Volume Session Time is ZERO!\n")); } /* * Start the device allocation thread */ create_volume_lists(); /* do before device_init */ if (pthread_create(&thid, NULL, device_initialization, NULL) != 0) { berrno be; Emsg1(M_ABORT, 0, _("Unable to create thread. ERR=%s\n"), be.bstrerror()); } start_watchdog(); /* start watchdog thread */ if (me->jcr_watchdog_time) { init_jcr_subsystem(me->jcr_watchdog_time); /* start JCR watchdogs etc. */ } start_statistics_thread(); #if HAVE_NDMP /* * Seperate thread that handles NDMP connections */ if (me->ndmp_enable) { start_ndmp_thread_server(me->NDMPaddrs, me->MaxConnections); } #endif /* * Single server used for Director/Storage and File daemon */ start_socket_server(me->SDaddrs); /* to keep compiler quiet */ terminate_stored(0); bail_out: return 0; }
int main() { int res, try, retries; char *query_string, *abf_api_url, *api_token; char *log_level = getenv("LOG_LEVEL"); if (init_logger(log_level == NULL ? "INFO" : log_level) < 0) { return 2; } register_thread("Main"); log_printf(LOG_INFO, "Starting DNS check...\n"); res = check_dns(); if (res < 0) { log_printf(LOG_FATAL, "Check DNS failed, can't resolve github.com. Exiting...\n"); return 6; } else { log_printf(LOG_INFO, "Successfuly resolved github. Continuing.\n"); } usergroup omv_mock = get_omv_uid_mock_gid(); if(omv_mock.omv_uid == 0) { log_printf(LOG_FATAL, "User omv doesn't exist. Exiting...\n"); return 7; } if(omv_mock.mock_gid == 0) { log_printf(LOG_FATAL, "Group mock doesn't exist. Exiting...\n"); return 8; } res = process_config(&abf_api_url, &api_token, &query_string); if (res < 0) { log_printf(LOG_FATAL, "Failed to process config, exiting.\n"); return 1; } init_strings(api_token); init_api(abf_api_url, api_token); if(start_statistics_thread(query_string)) { log_printf(LOG_FATAL, "Failed to initialize statistics thread. Exiting...\n"); return 5; } while(1) { char *job; if(api_jobs_shift(&job, query_string)) { sleep(10); continue; } char *build_id, *distrib_type; char **env; int ttl; res = parse_job_description(job, &build_id, &ttl, &distrib_type, &env); free(job); if(res < 0) { sleep(10); continue; } log_printf(LOG_INFO, "Starting build with build_id %s.\n", build_id); log_printf(LOG_INFO, "Sending build start notification to ABF.\n"); retries = 5; try = 0; set_busy_status(1, build_id); int build_start_success = 0; while(retries) { log_printf(LOG_INFO, "Try #%d: Sending data to ABF.\n", try + 1); if(!api_jobs_feedback(build_id, BUILD_STARTED, hostname_payload)) { log_printf(LOG_INFO, "Try #%d: Data sent.\n", try + 1); build_start_success = 1; break; } else { log_printf(LOG_ERROR, "Try #%d: Failed to send data to ABF. Sleeping for %d seconds and retrying...\n", try + 1, 1 << try); } retries--; sleep(1 << try); try++; } if (!build_start_success) { log_printf(LOG_ERROR, "Failed to send build start to ABF, aborting build.\n"); free(build_id); free(distrib_type); for(int i = 0; i < res; i++) { free(env[i]); } free(env); set_busy_status(0, NULL); continue; } child script = exec_build(distrib_type, (char * const *)env, omv_mock); int live_inspector_started = 1; log_printf(LOG_INFO, "Starting live inspector, build's time to live is %d seconds.\n", ttl); if(start_live_inspector(ttl, script.pid, build_id) < 0) { live_inspector_started = 0; log_printf(LOG_WARN, "Live inspector failed to start. Job canceling and timeout will be unavailable.\n"); } int live_logger_started = 1; log_printf(LOG_INFO, "Starting live logger.\n"); if(start_live_logger(build_id, script.read_fd) < 0) { live_logger_started = 0; log_printf(LOG_WARN, "Live logger failed to start. Live log will be unavailable.\n"); } int status, build_status = BUILD_COMPLETED; waitpid(script.pid, &status, 0); int canceled = 0; if (live_inspector_started) { canceled = stop_live_inspector(); } if (live_logger_started) { stop_live_logger(); } int exit_code = 0; if (canceled) { build_status = BUILD_CANCELED; } else if(WIFEXITED(status)) { exit_code = WEXITSTATUS(status); switch(exit_code) { case 0: build_status = BUILD_COMPLETED; break; case 5: build_status = TESTS_FAILED; break; default: build_status = BUILD_FAILED; } } else if(WIFSIGNALED(status)) { exit_code = 255; build_status = BUILD_FAILED; } for(int i = 0; i < res; i++) { free(env[i]); } free(env); free(distrib_type); log_printf(LOG_INFO, "Build is over with status %s.\n", build_statuses_str[build_status]); mkdir(home_output, 0666); system(move_output_cmd); system(upload_cmd); char *container_data = read_file(container_data_path); char *results = read_file("/tmp/results.json"); char *commit_hash = read_file(commit_hash_path); if(commit_hash != NULL) { commit_hash[40] = '\0'; } char *fail_reason = NULL; if (build_status == BUILD_FAILED) { fail_reason = read_file(fail_reason_path); if (fail_reason != NULL) { for (unsigned int i = 0; i < strlen(fail_reason); i++) { if (!isprint(fail_reason[i]) || fail_reason[i] == '"') { fail_reason[i] = ' '; } } } } char *args = xmalloc((container_data ? strlen(container_data) : 0) + (results ? strlen(results) : 0) + 2048); sprintf(args, build_completed_args_fmt, (results ? results : "[]"), \ (container_data ? container_data : "{}"), exit_code, (commit_hash ? commit_hash : ""), (fail_reason ? fail_reason : "")); retries = 5; try = 0; while(retries) { log_printf(LOG_INFO, "Try #%d: Sending data to ABF\n", try + 1); if(!api_jobs_feedback(build_id, build_status, args)) { log_printf(LOG_INFO, "Data sent.\n"); break; } else { log_printf(LOG_ERROR, "Failed to send data to ABF. Sleeping for %d seconds and retrying...\n", 1 << try); } retries--; sleep(1 << try); try++; } set_busy_status(0, NULL); free(args); free(build_id); if(commit_hash) { free(commit_hash); } if(results) { free(results); } if(container_data) { free(container_data); } if(fail_reason) { free(fail_reason); } } return 0; }