예제 #1
0
파일: stored.c 프로젝트: dl5rcw/bareos
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;
}
예제 #2
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;
}